Commit 03600d91 authored by sebastien's avatar sebastien

k_order_perturbation DLL:

* no longer use mexPrintf()/mexErrMsgTxt() outside mexFunction(): use exceptions to report errors, in order to be able to integrate the code in a standalone executable
* fixed a few memory leaks (other still remain)
* fixed a buffer overflow issue in the filename of the dynamic MEX (using C++ string object)
* various cosmetic cleanups


git-svn-id: https://www.dynare.org/svn/dynare/trunk@3177 ac1d8469-bf42-47a9-8791-bf33cf982152
parent 9a23cee3
include ../mex.am
include ../../k_order_perturbation.am
CPPFLAGS += -DMEXEXT=$(MEXEXT)
include ../mex.am
include ../../k_order_perturbation.am
CPPFLAGS += -DMEXEXT=mex
......@@ -17,63 +17,45 @@
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include "k_ord_dynare.h"
#include "dynamic_dll.h"
#include "math.h"
#include <cstring>
#include <sstream>
/***********************************
* Members of DynamicModelDLL for handling loading and calling
* <model>_dynamic () function
**************************************/
DynamicModelDLL::DynamicModelDLL(const char *modName, const int y_length, const int j_cols,
const int n_max_lag, const int n_exog, const char *sExt)
DynamicModelDLL::DynamicModelDLL(const string &modName, const int y_length, const int j_cols,
const int n_max_lag, const int n_exog, const string &sExt) throw (DynareException)
: length(y_length), jcols(j_cols), nMax_lag(n_max_lag), nExog(n_exog)
{
char fName[MAX_MODEL_NAME];
#if defined _WIN32
strcpy(fName, modName);
#else
strcpy(fName, "./");
strcat(fName, modName);
#endif
using namespace std;
strcat(fName, "_dynamic");
#ifdef DEBUG
mexPrintf("MexPrintf: Call Load run DLL %s .\n", fName);
string fName;
#ifndef _WIN32
fName = "./";
#endif
fName += modName + "_dynamic" + sExt;
try
{
#define QUOTEME(x) #x
if (sExt == NULL)
sExt = QUOTEME(MEXEXT);
#ifdef _WIN32
HINSTANCE dynamicHinstance;
// dynamicHinstance=::LoadLibraryEx(strcat(fNname,"_.dll"),NULL,DONT_RESOLVE_DLL_REFERENCES);//sExt); //"_.dll");
dynamicHinstance = ::LoadLibrary(strcat(fName, sExt)); //.dll); //"_.dll");
dynamicHinstance = ::LoadLibrary(fName.c_str());
if (dynamicHinstance == NULL)
throw 1; //alt: return;
// (DynamicFn*) typedef void * (__stdcall *DynamicFn)();
# ifdef DEBUG
mexPrintf("MexPrintf: Call GetProcAddress %s .\n", fName);
# endif
throw 1;
Dynamic = (DynamicFn *) ::GetProcAddress(dynamicHinstance, "Dynamic");
#else // __linux__
dynamicHinstance = dlopen(strcat(fName, sExt), RTLD_NOW);
#else // Linux or Mac
dynamicHinstance = dlopen(fName.c_str(), RTLD_NOW);
if ((dynamicHinstance == NULL) || dlerror())
{
cerr << dlerror() << endl;
// mexPrintf("MexPrintf:Error loading DLL");
throw 1;
}
Dynamic = (DynamicFn) dlsym(dynamicHinstance, "Dynamic");
if ((Dynamic == NULL) || dlerror())
{
cerr << dlerror() << endl;
// mexPrintf("MexPrintf:Error finding DLL function");
throw 2;
}
#endif
......@@ -81,58 +63,41 @@ DynamicModelDLL::DynamicModelDLL(const char *modName, const int y_length, const
}
catch (int i)
{
// mexPrintf("MexPrintf: error in Load and run DLL %s , %d.\n", fName, i);
// mexErrMsgTxt("Err: An error in Load and run DLL .\n");
return;
ostringstream msg;
msg << "Can't load " << fName << " (error code: " << i;
throw DynareException(__FILE__, __LINE__, msg.str());
}
catch (...)
{
// mexPrintf("MexPrintf: Unknown error in Call MATLAB function %s.\n", fName);
// mexErrMsgTxt("Err: Unknown error in Load and run DLL .\n");
return;
throw DynareException(__FILE__, __LINE__, string("Can't load ") + fName);
}
}
// close DLL: If the referenced object was successfully closed,
// close() returns 0, non 0 otherwise
int
DynamicModelDLL::close()
DynamicModelDLL::~DynamicModelDLL()
{
#ifdef _WIN32
// MS FreeLibrary returns non 0 if OK, 0 if fails.
bool rb = FreeLibrary(dynamicHinstance);
if (rb)
return 0;
else
return 1;
#else // linux
//If OK, dlclose() returns 0, non 0 otherwise
return dlclose(dynamicHinstance);
FreeLibrary(dynamicHinstance);
#else
dlclose(dynamicHinstance);
#endif
};
}
void
DynamicModelDLL::eval(const Vector &y, const TwoDMatrix &x, const Vector *modParams,
int it_, Vector &residual, TwoDMatrix *g1, TwoDMatrix *g2, TwoDMatrix *g3)
DynamicModelDLL::eval(double *y, double *x, int nb_row_x, double *params,
int it_, double *residual, double *g1, double *g2, double *g3)
{
Dynamic(y, x, nb_row_x, params, it_, residual, g1, g2, g3);
}
void
DynamicModelDLL::eval(const Vector &y, const TwoDMatrix &x, const Vector *modParams,
int it_, Vector &residual, TwoDMatrix *g1, TwoDMatrix *g2, TwoDMatrix *g3) throw (DynareException)
{
double *dresidual, *dg1 = NULL, *dg2 = NULL, *dg3 = NULL;
//int length=y.length(); // not!
//mexPrintf("y.length() = %d\n",y.length());
if ((jcols-nExog) != y.length())
{
// throw DLL Error
// mexPrintf(" DLL Error: (jcols-nExog)!=ys.length() \n");
return;
}
if (residual.length() < length) // dummy or insufficient
{
Vector *tempv = new Vector(length);
residual = *tempv;
delete tempv;
residual.zeros();
}
throw DynareException(__FILE__, __LINE__, "DLL Error: (jcols-nExog)!=ys.length()");
if (g1 != NULL)
{
if (g1->nrows() != length) // dummy
......@@ -144,56 +109,29 @@ DynamicModelDLL::eval(const Vector &y, const TwoDMatrix &x, const Vector *modPa
dg1 = const_cast<double *>(g1->base());
}
if (g2 != NULL)
{
dg2 = const_cast<double *>(g2->base());
}
dresidual = const_cast<double *>(residual.base());
if (g3 != NULL)
{
dg3 = const_cast<double *>(g3->base());
}
dresidual = const_cast<double *>(residual.base());
double *dy = const_cast<double *>(y.base());
double *dx = const_cast<double *>(x.base());
double *dbParams = const_cast<double *>(modParams->base());
#ifdef DEBUG
mexPrintf(" try eval Dynamic with ne g1: cols=%d , rows=%d\n",
g1->ncols(), g1->nrows());
for (int i = 0; i < modParams->length(); i++)
{
mexPrintf("k_ord_perturbation: Params[%d]= %g.\n", i, (*modParams)[i]);
}
for (int i = 0; i < jcols-nExog; i++)
{
mexPrintf("k_ord_perturbation: Ys[%d]= %g.\n", i, dy[i]);
}
mexPrintf("k_order_perturbation: call <model> Dynamic dParams= %g , , dy = %g dx = %f .\n",
dbParams[0], dy[0], dx[0]);
#endif
try
{
Dynamic(dy, dx, nExog, dbParams, it_, dresidual, dg1, dg2, dg3);
}
catch (...)
{
// mexPrintf("MexPrintf: error in run Dynamic DLL \n");
}
};
}
void
DynamicModelDLL::eval(const Vector &y, const TwoDMatrix &x, const Vector *modParams,
Vector &residual, TwoDMatrix *g1, TwoDMatrix *g2, TwoDMatrix *g3)
Vector &residual, TwoDMatrix *g1, TwoDMatrix *g2, TwoDMatrix *g3) throw (DynareException)
{
eval(y, x, modParams, nMax_lag, residual, g1, g2, g3);
};
}
void
DynamicModelDLL::eval(const Vector &y, const Vector &x, const Vector *modParams,
Vector &residual, TwoDMatrix *g1, TwoDMatrix *g2, TwoDMatrix *g3)
Vector &residual, TwoDMatrix *g1, TwoDMatrix *g2, TwoDMatrix *g3) throw (DynareException)
{
/** ignore given exogens and create new 2D x matrix since
* when calling <model>_dynamic(z,x,params,it_) x must be equal to
* zeros(M_.maximum_lag+1,M_.exo_nbr)
......@@ -202,6 +140,4 @@ DynamicModelDLL::eval(const Vector &y, const Vector &x, const Vector *modParams,
mx.zeros(); // initialise shocks to 0s
eval(y, mx, modParams, nMax_lag, residual, g1, g2, g3);
};
}
......@@ -36,21 +36,19 @@
#include <string>
#include <dynmex.h>
#include "dynare_exception.h"
// <model>_Dynamic DLL pointer
#ifdef _WIN32
typedef void *(DynamicFn)
#else // linux
#else // Linux or Mac
typedef void (*DynamicFn)
#endif
(double *y, double *x, int nb_row_x, double *params,
int it_, double *residual, double *g1, double *g2, double *g3);
//DynamicFn Dynamic;
typedef void *(mexFunctionPtr)(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
const int MAX_MODEL_NAME = 100;
/**
* creates pointer to Dynamic function inside <model>_dynamic.dll
* and handles calls to it.
......@@ -67,41 +65,25 @@ private:
const int jcols; // tot num var t-1, t and t+1 instances + exogs = Num of Jacobian columns
const int nMax_lag; // no of lags
const int nExog; // no of exogenous
// const char * sExt; // dynamic file extension: dll, mexw32, ...
#ifdef _WIN32
HINSTANCE dynamicHinstance; // DLL instance pointer in Windows
#else // linux
void *dynamicHinstance; // and in Linux
#else
void *dynamicHinstance; // and in Linux or Mac
#endif
public:
// construct and load Dynamic model DLL
DynamicModelDLL(const char *fname, const int length, const int jcols,
const int nMax_lag, const int nExog, const char *sExt);
virtual ~DynamicModelDLL()
{
close();
};
DynamicModelDLL(const string &fname, const int length, const int jcols,
const int nMax_lag, const int nExog, const string &sExt) throw (DynareException);
virtual ~DynamicModelDLL();
// evaluate Dynamic model DLL
void
eval(double *y, double *x, int nb_row_x, double *params,
int it_, double *residual, double *g1, double *g2, double *g3)
{
Dynamic(y, x, nb_row_x, params, it_, residual, g1, g2, g3);
};
void eval(double *y, double *x, int nb_row_x, double *params,
int it_, double *residual, double *g1, double *g2, double *g3);
void eval(const Vector &y, const Vector &x, const Vector *params,
Vector &residual, TwoDMatrix *g1, TwoDMatrix *g2, TwoDMatrix *g3);
Vector &residual, TwoDMatrix *g1, TwoDMatrix *g2, TwoDMatrix *g3) throw (DynareException);
void eval(const Vector &y, const TwoDMatrix &x, const Vector *params,
int it_, Vector &residual, TwoDMatrix *g1, TwoDMatrix *g2, TwoDMatrix *g3);
int it_, Vector &residual, TwoDMatrix *g1, TwoDMatrix *g2, TwoDMatrix *g3) throw (DynareException);
void eval(const Vector &y, const TwoDMatrix &x, const Vector *params,
Vector &residual, TwoDMatrix *g1, TwoDMatrix *g2, TwoDMatrix *g3);
// close DLL: If the referenced object was successfully closed,
// close() returns 0, non 0 otherwise
int close();
Vector &residual, TwoDMatrix *g1, TwoDMatrix *g2, TwoDMatrix *g3) throw (DynareException);
};
// convert Matlab endo and exo names array to C type array of strings
const char **DynareMxArrayToString(const mxArray *mxFldp, const int len, const int width);
const char **DynareMxArrayToString(const char *cArray, const int len, const int width);
......@@ -62,7 +62,7 @@ public:
/** This for each string of the input vector calculates its index
* in the names. And returns the resulting vector of indices. If
* the name cannot be found, then an exception is raised. */
vector<int> selectIndices(const vector<const char *> &ns) const;
vector<int> selectIndices(const vector<const char *> &ns) const throw (DynareException);
};
class DynareExogNameList : public NameList
......@@ -104,7 +104,7 @@ public:
// The following only implements DynamicModel with help of ogdyn::DynareModel
// instantiation of pure abstract DynamicModel decl. in dynamic_model.h
class DynamicModelDLL;
class KordpJacobian;
class KordpDynare : public DynamicModel
{
friend class DynareNameList;
......@@ -112,7 +112,7 @@ class KordpDynare : public DynamicModel
friend class DynareStateNameList;
friend class KordpDynareJacobian;
friend class DynamicModelDLL;
//////////
const int nStat;
const int nBoth;
const int nPred;
......@@ -123,13 +123,11 @@ class KordpDynare : public DynamicModel
const int nYss; // nyss ={ nboth + nforw ; }
const int nY; // = num_endo={ nstat + npred + nboth + nforw ; }
const int nJcols; // no of jacobian columns= nExog+nEndo+nsPred+nsForw
const Vector *NNZD; //the total number of non-zero derivative elements
// where hessian is 2nd : NZZD(order=2)
const Vector *NNZD; /* the total number of non-zero derivative elements
where hessian is 2nd : NZZD(order=2) */
const int nSteps;
const int nOrder;
Journal &journal;
/// DynamicModel* model;
///const char* modName;
Vector *ySteady;
Vector *params;
TwoDMatrix *vCov;
......@@ -144,13 +142,13 @@ class KordpDynare : public DynamicModel
vector<int> *JacobianIndices;
public:
KordpDynare(const char **endo, int num_endo,
const char **exo, int num_exo, int num_par, //const char** par,
const char **exo, int num_exo, int num_par,
Vector *ySteady, TwoDMatrix *vCov, Vector *params, int nstat, int nPred,
int nforw, int nboth, const int nJcols, const Vector *NNZD,
const int nSteps, const int ord, //const char* modName,
const int nSteps, const int ord,
Journal &jr, DynamicModelDLL &dynamicDLL, double sstol,
const vector<int> *varOrder, const TwoDMatrix *ll_Incidence,
double qz_criterium);
double qz_criterium) throw (TLException);
/** Makes a deep copy of the object. */
KordpDynare(const KordpDynare &dyn);
......@@ -247,38 +245,26 @@ public:
return *ySteady;
}
// here is true public interface
void solveDeterministicSteady(Vector &steady);
void
solveDeterministicSteady()
{
solveDeterministicSteady(*ySteady);
}
void evaluateSystem(Vector &out, const Vector &yy, const Vector &xx);
void solveDeterministicSteady();
void evaluateSystem(Vector &out, const Vector &yy, const Vector &xx) throw (DynareException);
void evaluateSystem(Vector &out, const Vector &yym, const Vector &yy,
const Vector &yyp, const Vector &xx);
void calcDerivatives(const Vector &yy, const Vector &xx);
//void calcDerivatives(const Vector& yy, TwoDMatrix& jj);
void calcDerivatives(const Vector &yy, ogu::Jacobian &jacob);
void calcDerivativesAtSteady();
const Vector &yyp, const Vector &xx) throw (DynareException);
void calcDerivatives(const Vector &yy, const Vector &xx) throw (DynareException);
void calcDerivativesAtSteady() throw (DynareException);
DynamicModelDLL &dynamicDLL;
/// void writeMat4(FILE* fd, const char* prefix) const;
/// void writeDump(const std::string& basename) const;
DynamicModel *
clone() const
{
return new KordpDynare(*this);
}
void ReorderCols(TwoDMatrix *tdx, const int *varOrder);
void ReorderCols(TwoDMatrix *tdx, const vector<int> *varOrder);
Vector *LLxSteady(const Vector &yS); // returns ySteady extended with leads and lags
void ReorderCols(TwoDMatrix *tdx, const int *varOrder) throw (TLException);
void ReorderCols(TwoDMatrix *tdx, const vector<int> *varOrder) throw (DynareException, TLException);
Vector *LLxSteady(const Vector &yS) throw (DynareException, TLException); // returns ySteady extended with leads and lags
private:
void writeModelInfo(Journal &jr) const;
int *ReorderDynareJacobianIndices(const int *varOrder);
vector<int> *ReorderDynareJacobianIndices(const vector<int> *varOrder);
void ReorderBlocks(TwoDMatrix *tdx, const int *varOrder);
void ReorderBlocks(TwoDMatrix *tdx, const vector<int> *vOrder);
vector<int> *ReorderDynareJacobianIndices(const vector<int> *varOrder) throw (TLException);
void ReorderBlocks(TwoDMatrix *tdx, const vector<int> *vOrder) throw (DynareException, TLException);
void populateDerivativesContainer(TwoDMatrix *g, int ord, const vector<int> *vOrder);
};
......@@ -286,10 +272,9 @@ private:
* ModelDerivativeContainer manages derivatives container
************************************/
class ModelDerivativeContainer //: public ogp::FormulaDerEvalLoader
class ModelDerivativeContainer
{
protected:
// const ogp::FineAtoms& atoms;
TensorContainer<FSSparseTensor> &md;
public:
ModelDerivativeContainer(const KordpDynare &model, TensorContainer<FSSparseTensor> &mod_ders,
......@@ -297,24 +282,6 @@ public:
void load(int i, int iord, const int *vars, double res);
};
/****************************
* K-Order Perturbation instance of Jacobian:
************************************/
class KordpJacobian : public ogu::Jacobian ///, public ogp::FormulaDerEvalLoader
{
protected:
KordpDynare &dyn;
public:
KordpJacobian(KordpDynare &dyn);
virtual ~KordpJacobian()
{
}
// Load <mod>_dynamic.DLL
// void load(const char** modName);
void eval(const Vector &in);
};
/****************************
* K-Order Perturbation instance of VectorFunction:
************************************/
......@@ -341,8 +308,7 @@ public:
{
return d.ny();
}
void eval(const ConstVector &in, Vector &out);
void eval(const ConstVector &in, Vector &out) throw (DynareException);
};
#endif
......@@ -35,7 +35,7 @@ main(int argc, char *argv[])
double qz_criterium = 1+1e-6;
const int check_flag = 0;
const char *fName = "./fs2000k"; //mxArrayToString(mFname);
const char *dfExt = NULL; //Dyanamic file extension, e.g.".dll";
const char *dfExt = ".mexa64"; //Dynamic file extension, e.g.".dll";
#ifdef DEBUG
mexPrintf("k_order_perturbation: check_flag = %d , fName = %s .\n", check_flag, fName);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment