dynare/dynare++/sylv/cc/SylvMemory.cpp

222 lines
5.0 KiB
C++

/* $Header: /var/lib/cvs/dynare_cpp/sylv/cc/SylvMemory.cpp,v 1.1.1.1 2004/06/04 13:00:49 kamenik Exp $ */
/* Tag $Name: $ */
#include "SylvMemory.h"
#include "SylvException.h"
#include "KronVector.h"
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
# include <dynmex.h>
#endif
#include <cmath>
#include <cstdio>
#include <cstdlib>
/**********************************************************/
/* SylvMemoryPool */
/**********************************************************/
SylvMemoryPool memory_pool;
SylvMemoryPool::SylvMemoryPool()
: base(0), length(0), allocated(0), stack_mode(false)
{
}
void SylvMemoryPool::init(size_t size)
{
#ifdef USE_MEMORY_POOL
length = size;
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
if (base)
throw SYLV_MES_EXCEPTION("Attempt to use matlab memory pool twice.");
base = (char*) mxMalloc(length);
#else
base = (char*) malloc(length);
#endif
#else
throw SYLV_MES_EXCEPTION("SylvMemoryPool::init() called for non memory pool code.");
#endif
}
void* SylvMemoryPool::allocate(size_t size)
{
#ifdef USE_MEMORY_POOL
if (allocated + size < length) {
char* res = base + allocated;
allocated += size;
return res;
} else {
throw SYLV_MES_EXCEPTION("Run out of memory space");
}
#else
throw SYLV_MES_EXCEPTION("SylvMemoryPool::allocate() called for non memory pool code.");
#endif
}
void SylvMemoryPool::free(void* p)
{
#ifdef USE_MEMORY_POOL
int offset = ((char*)p) - base;
#ifdef DEBUG
if (offset < 0)
throw SYLV_MES_EXCEPTION("SylvMemoryPool::free() frees wrong address < begin.");
if (offset >= (int)length)
throw SYLV_MES_EXCEPTION("SylvMemoryPool::free() frees wrong address > end.");
#endif
if (stack_mode && offset >= 0 && offset < (int)allocated)
allocated = offset;
#else
throw SYLV_MES_EXCEPTION("SylvMemoryPool::free() called for non memory pool code.");
#endif
}
void SylvMemoryPool::setStackMode(bool mode)
{
stack_mode = mode;
}
SylvMemoryPool::~SylvMemoryPool()
{
reset();
}
void SylvMemoryPool::reset()
{
#if !defined(MATLAB_MEX_FILE) && !defined(OCTAVE_MEX_FILE)
delete [] base;
base = 0;
allocated = 0;
length = 0;
stack_mode = false;
#endif
}
/**********************************************************/
/* global new and delete */
/**********************************************************/
#ifdef USE_MEMORY_POOL
void* operator new(size_t size)
{
return memory_pool.allocate(size);
}
void* operator new[](size_t size)
{
return memory_pool.allocate(size);
}
void operator delete(void* p)
{
memory_pool.free(p);
}
void operator delete[](void* p)
{
memory_pool.free(p);
}
#endif
/**********************************************************/
/* saved version of global new and delete */
/**********************************************************/
#ifdef USE_MEMORY_POOL
void* MallocAllocator::operator new(size_t size)
{
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
throw SYLV_MES_EXCEPTION("Attempt to call wrong memory allocator.");
#else
void* res = malloc(size);
if (!res)
throw SYLV_MES_EXCEPTION("Malloc unable to allocate memory.");
return res;
#endif
}
void* MallocAllocator::operator new[](size_t size)
{
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
throw SYLV_MES_EXCEPTION("Attempt to call wrong memory allocator.");
#else
void* res = malloc(size);
if (!res)
throw SYLV_MES_EXCEPTION("Malloc unable allocate memory.");
return res;
#endif
}
void MallocAllocator::operator delete(void* p)
{
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
throw SYLV_MES_EXCEPTION("Attempt to call wrong memory destructor.");
#else
free(p);
#endif
}
void MallocAllocator::operator delete[](void* p)
{
#if defined(MATLAB_MEX_FILE) || defined(OCTAVE_MEX_FILE)
throw SYLV_MES_EXCEPTION("Attempt to call wrong memory destructor.");
#else
free(p);
#endif
}
#endif
/**********************************************************/
/* SylvMemoryDriver */
/**********************************************************/
void SylvMemoryDriver::allocate(int num_d, int m, int n, int order)
{
#ifdef USE_MEMORY_POOL
int x_cols = power(m,order);
int total = num_d*x_cols*n; // storage for big matrices
total += x_cols; // storage for one extra row of a big matrix
int dig_vectors = (int)ceil(((double)(power(m,order)-1))/(m-1));
total += 8*n*dig_vectors; // storage for kron vectors instantiated during solv
total += 50*(m*m+n*n); // some storage for small square matrices
total *= sizeof(double); // everything in doubles
memory_pool.init(total);
#endif
}
SylvMemoryDriver::SylvMemoryDriver(int num_d, int m, int n, int order)
{
allocate(num_d, m, n, order);
}
SylvMemoryDriver::SylvMemoryDriver(const SylvParams& pars, int num_d,
int m, int n, int order)
{
if (*(pars.method) == SylvParams::iter)
num_d++;
if (*(pars.want_check))
num_d++;
allocate(num_d, m, n, order);
}
SylvMemoryDriver::~SylvMemoryDriver()
{
memory_pool.reset();
}
void SylvMemoryDriver::setStackMode(bool mode) {
memory_pool.setStackMode(mode);
}