From 68aa1ace8f9414435ae92762ee3f73a1ffb64a7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= Date: Mon, 15 Apr 2019 16:46:39 +0200 Subject: [PATCH] k-order DLL: in use_dll mode, get model derivatives from preprocessor at an arbitrary order Ref #217 --- .../k_order_perturbation/dynamic_dll.cc | 92 +++++++++---------- .../k_order_perturbation/dynamic_dll.hh | 14 +-- .../k_order_perturbation.cc | 2 +- 3 files changed, 47 insertions(+), 61 deletions(-) diff --git a/mex/sources/k_order_perturbation/dynamic_dll.cc b/mex/sources/k_order_perturbation/dynamic_dll.cc index 287e87c73..51eee1b2c 100644 --- a/mex/sources/k_order_perturbation/dynamic_dll.cc +++ b/mex/sources/k_order_perturbation/dynamic_dll.cc @@ -22,8 +22,9 @@ #include "dynare_exception.hh" #include +#include -DynamicModelDLL::DynamicModelDLL(const std::string &modName, int ntt_arg) +DynamicModelDLL::DynamicModelDLL(const std::string &modName, int ntt_arg, int order) : DynamicModelAC(ntt_arg) { std::string fName; @@ -34,45 +35,43 @@ DynamicModelDLL::DynamicModelDLL(const std::string &modName, int ntt_arg) #if defined(__CYGWIN32__) || defined(_WIN32) dynamicHinstance = LoadLibrary(fName.c_str()); - if (!dynamicHinstance) - throw DynareException(__FILE__, __LINE__, "Error when loading " + fName + ": can't dynamically load the file"); - dynamic_resid_tt = reinterpret_cast(GetProcAddress(dynamicHinstance, "dynamic_resid_tt")); - dynamic_resid = reinterpret_cast(GetProcAddress(dynamicHinstance, "dynamic_resid")); - dynamic_g1_tt = reinterpret_cast(GetProcAddress(dynamicHinstance, "dynamic_g1_tt")); - dynamic_g1 = reinterpret_cast(GetProcAddress(dynamicHinstance, "dynamic_g1")); - dynamic_g2_tt = reinterpret_cast(GetProcAddress(dynamicHinstance, "dynamic_g2_tt")); - dynamic_g2 = reinterpret_cast(GetProcAddress(dynamicHinstance, "dynamic_g2")); - dynamic_g3_tt = reinterpret_cast(GetProcAddress(dynamicHinstance, "dynamic_g3_tt")); - dynamic_g3 = reinterpret_cast(GetProcAddress(dynamicHinstance, "dynamic_g3")); - if (!dynamic_resid_tt || !dynamic_resid - || !dynamic_g1_tt || !dynamic_g1 - || !dynamic_g2_tt || !dynamic_g2 - || !dynamic_g3_tt || !dynamic_g3) - { - FreeLibrary(dynamicHinstance); // Free the library - throw DynareException(__FILE__, __LINE__, "Error when loading " + fName + ": can't locate the relevant dynamic symbols within the MEX file"); - } -#else // Linux or Mac +#else // GNU/Linux or Mac dynamicHinstance = dlopen(fName.c_str(), RTLD_NOW); - if (!dynamicHinstance) - throw DynareException(__FILE__, __LINE__, "Error when loading " + fName + ": " + dlerror()); - dynamic_resid_tt = reinterpret_cast(dlsym(dynamicHinstance, "dynamic_resid_tt")); - dynamic_resid = reinterpret_cast(dlsym(dynamicHinstance, "dynamic_resid")); - dynamic_g1_tt = reinterpret_cast(dlsym(dynamicHinstance, "dynamic_g1_tt")); - dynamic_g1 = reinterpret_cast(dlsym(dynamicHinstance, "dynamic_g1")); - dynamic_g2_tt = reinterpret_cast(dlsym(dynamicHinstance, "dynamic_g2_tt")); - dynamic_g2 = reinterpret_cast(dlsym(dynamicHinstance, "dynamic_g2")); - dynamic_g3_tt = reinterpret_cast(dlsym(dynamicHinstance, "dynamic_g3_tt")); - dynamic_g3 = reinterpret_cast(dlsym(dynamicHinstance, "dynamic_g3")); - if (!dynamic_resid_tt || !dynamic_resid - || !dynamic_g1_tt || !dynamic_g1 - || !dynamic_g2_tt || !dynamic_g2 - || !dynamic_g3_tt || !dynamic_g3) - { - dlclose(dynamicHinstance); // Free the library - throw DynareException(__FILE__, __LINE__, "Error when loading " + fName + ": " + dlerror()); - } #endif + if (!dynamicHinstance) + throw DynareException(__FILE__, __LINE__, "Error when loading " + fName +#if !defined(__CYGWIN32__) && !defined(_WIN32) + + ": " + dlerror() +#endif + ); + + for (int i = 0; i <= order; i++) + { + std::string funcname = "dynamic_" + (i == 0 ? "resid" : "g" + std::to_string(i)); + void *deriv, *tt; +#if defined(__CYGWIN32__) || defined(_WIN32) + deriv = GetProcAddress(dynamicHinstance, funcname.c_str()); + tt = GetProcAddress(dynamicHinstance, (funcname + "_tt").c_str()); +#else + deriv = dlsym(dynamicHinstance, funcname.c_str()); + tt = dlsym(dynamicHinstance, (funcname + "_tt").c_str()); +#endif + if (!deriv || !tt) + { +#if defined(__CYGWIN32__) || defined(_WIN32) + FreeLibrary(dynamicHinstance); +#else + dlclose(dynamicHinstance); +#endif + throw DynareException(__FILE__, __LINE__, "Error when loading symbols from " + fName +#if !defined(__CYGWIN32__) && !defined(_WIN32) + + ": " + dlerror() +#endif + ); + } + dynamic_deriv.push_back(reinterpret_cast(deriv)); + dynamic_tt.push_back(reinterpret_cast(tt)); + } tt = std::make_unique(ntt); } @@ -95,18 +94,11 @@ void DynamicModelDLL::eval(const Vector &y, const Vector &x, const Vector &modParams, const Vector &ySteady, Vector &residual, std::vector &md) noexcept(false) { - dynamic_resid_tt(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get()); - dynamic_resid(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get(), residual.base()); - dynamic_g1_tt(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get()); - dynamic_g1(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get(), md[0].base()); - if (md.size() >= 2) + assert(md.size() == dynamic_deriv.size()-1); + + for (size_t i = 0; i < dynamic_deriv.size(); i++) { - dynamic_g2_tt(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get()); - dynamic_g2(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get(), md[1].base()); - } - if (md.size() >= 3) - { - dynamic_g3_tt(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get()); - dynamic_g3(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get(), md[2].base()); + dynamic_tt[i](y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get()); + dynamic_deriv[i](y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get(), i == 0 ? residual.base() : md[i-1].base()); } } diff --git a/mex/sources/k_order_perturbation/dynamic_dll.hh b/mex/sources/k_order_perturbation/dynamic_dll.hh index ec04c797c..a2cc556bc 100644 --- a/mex/sources/k_order_perturbation/dynamic_dll.hh +++ b/mex/sources/k_order_perturbation/dynamic_dll.hh @@ -35,10 +35,7 @@ #include "dynamic_abstract_class.hh" using dynamic_tt_fct = void (*)(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, double *T); -using dynamic_resid_fct = void (*) (const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, const double *T, double *residual); -using dynamic_g1_fct = void (*)(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, const double *T, double *g1); -using dynamic_g2_fct = void (*)(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, const double *T, double *v2); -using dynamic_g3_fct = void (*)(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, const double *T, double *v3); +using dynamic_deriv_fct = void (*) (const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, const double *T, double *deriv); /** * creates pointer to Dynamic function inside _dynamic.dll @@ -47,11 +44,8 @@ using dynamic_g3_fct = void (*)(const double *y, const double *x, int nb_row_x, class DynamicModelDLL : public DynamicModelAC { private: - dynamic_tt_fct dynamic_resid_tt, dynamic_g1_tt, dynamic_g2_tt, dynamic_g3_tt; - dynamic_resid_fct dynamic_resid; - dynamic_g1_fct dynamic_g1; - dynamic_g2_fct dynamic_g2; - dynamic_g3_fct dynamic_g3; + std::vector dynamic_tt; + std::vector dynamic_deriv; #if defined(_WIN32) || defined(__CYGWIN32__) HINSTANCE dynamicHinstance; // DLL instance pointer in Windows #else @@ -61,7 +55,7 @@ private: public: // construct and load Dynamic model DLL - explicit DynamicModelDLL(const std::string &fname, int ntt_arg); + explicit DynamicModelDLL(const std::string &fname, int ntt_arg, int order); virtual ~DynamicModelDLL(); void eval(const Vector &y, const Vector &x, const Vector ¶ms, const Vector &ySteady, diff --git a/mex/sources/k_order_perturbation/k_order_perturbation.cc b/mex/sources/k_order_perturbation/k_order_perturbation.cc index 66c50cefc..998402718 100644 --- a/mex/sources/k_order_perturbation/k_order_perturbation.cc +++ b/mex/sources/k_order_perturbation/k_order_perturbation.cc @@ -176,7 +176,7 @@ extern "C" { std::unique_ptr dynamicModelFile; if (use_dll) - dynamicModelFile = std::make_unique(fName, ntt); + dynamicModelFile = std::make_unique(fName, ntt, kOrder); else dynamicModelFile = std::make_unique(fName, ntt);