diff --git a/matlab/utilities/general/dyn_mex.m b/matlab/utilities/general/dyn_mex.m
new file mode 100644
index 000000000..12e4c0b8d
--- /dev/null
+++ b/matlab/utilities/general/dyn_mex.m
@@ -0,0 +1,108 @@
+function dyn_mex(win_compiler,basename,force)
+
+% Compile Dynare model dlls when model option use_dll is used
+% if C file is fresher than mex file
+%
+% INPUTS
+% o win_compiler str compiler used under Windows (unused under Linux or OSX):
+% 'msvc' (MS Visual C)
+% 'cygwin'
+% o basename str filenames base
+% o force bool recompile if 1
+%
+% OUTPUTS
+% none
+%
+
+
+% Copyright (C) 2015 Dynare Team
+%
+% This file is part of Dynare.
+%
+% Dynare is free software: you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation, either version 3 of the License, or
+% (at your option) any later version.
+%
+% Dynare is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with Dynare. If not, see .
+
+Dc = dir([basename '_dynamic.c']);
+Dmex = dir([basename '_dynamic.' mexext]);
+
+% compile only if date of C file is greater than date of mex file
+% and force is not True
+if (Dmex.datenum > Dc.datenum) && ~force
+ disp('Mex files are newer than the source: not recompiled')
+ return
+end
+
+if ~exist('OCTAVE_VERSION')
+ % Some mex commands are enclosed in an eval(), because otherwise it will make Octave fail
+ if ispc
+ if msvc
+ % MATLAB/Windows + Microsoft Visual C++
+ eval(['mex -O LINKFLAGS="$LINKFLAGS /export:Dynamic" ' basename '_dynamic.c ' basename '_dynamic_mex.c'])
+ eval(['mex -O LINKFLAGS="$LINKFLAGS /export:Dynamic" ' basename '_static.c ' basename '_static_mex.c'])
+ elseif cygwin
+ % MATLAB/Windows + Cygwin g++
+ eval(['mex -O PRELINK_CMDS1="echo EXPORTS > mex.def & echo ' ...
+ 'mexFunction >> mex.def & echo Dynamic >> mex.def" ' ...
+ basename '_dynamic.c ' basename '_dynamic_mex.c'])
+ eval(['mex -O PRELINK_CMDS1="echo EXPORTS > mex.def & echo ' ...
+ 'mexFunction >> mex.def & echo Dynamic >> mex.def" ' ...
+ basename '_static.c ' basename '_static_mex.c'])
+ else
+ error(['When using the USE_DLL option, you must give either ' ...
+ '''cygwin'' or ''msvc'' option to the ''dynare'' command'])
+ end
+ elseif isunix
+ % MATLAB/Linux
+ if matlab_ver_less_than('8.3')
+ eval(['mex -O LDFLAGS=''-pthread -shared -Wl,--no-undefined'' ' ...
+ basename '_dynamic.c ' basename '_dynamic_mex.c'])
+ eval(['mex -O LDFLAGS=''-pthread -shared -Wl,--no-undefined'' ' ...
+ basename '_static.c ' basename '_static_mex.c'])
+ else
+ eval(['mex -O LINKEXPORT='''' ' basename '_dynamic.c ' basename '_dynamic_mex.c'])
+ eval(['mex -O LINKEXPORT='''' ' basename '_static.c ' basename '_static_mex.c'])
+ end
+ elseif ismac
+ % MATLAB/MacOS
+ if matlab_ver_less_than('8.3')
+ if matlab_ver_less_than('8.1')
+ eval(['mex -O LDFLAGS=''-Wl,-twolevel_namespace -undefined ' ...
+ 'error -arch $ARCHS -Wl,-syslibroot,$SDKROOT ' ...
+ '-mmacosx-version-min=$MACOSX_DEPLOYMENT_TARGET -bundle'' ' ...
+ basename '_dynamic.c ' basename '_dynamic_mex.c'])
+ eval(['mex -O LDFLAGS=''-Wl,-twolevel_namespace -undefined ' ...
+ 'error -arch $ARCHS -Wl,-syslibroot,$SDKROOT ' ...
+ '-mmacosx-version-min=$MACOSX_DEPLOYMENT_TARGET -bundle'' ' ...
+ basename '_static.c ' basename '_static_mex.c'])
+ else
+ eval(['mex -O LDFLAGS=''-Wl,-twolevel_namespace -undefined ' ...
+ 'error -arch $ARCHS -Wl,-syslibroot,$MW_SDKROOT ' ...
+ '-mmacosx-version-min=$MACOSX_DEPLOYMENT_TARGET -bundle'' ' ...
+ basename '_dynamic.c ' basename '_dynamic_mex.c'])
+ eval(['mex -O LDFLAGS=''-Wl,-twolevel_namespace -undefined ' ...
+ 'error -arch $ARCHS -Wl,-syslibroot,$MW_SDKROOT ' ...
+ '-mmacosx-version-min=$MACOSX_DEPLOYMENT_TARGET -bundle'' ' ...
+ basename '_static.c ' basename '_static_mex.c'])
+ end
+ else
+ eval(['mex -O LINKEXPORT='''' ' basename '_dynamic.c ' ...
+ basename '_dynamic_mex.c'])
+ eval(['mex -O LINKEXPORT='''' ' basename '_static.c ' basename ...
+ '_static_mex.c'])
+ end
+ end
+else
+ % Octave
+ eval(['mex ' basename '_dynamic.c ' basename '_dynamic_mex.c'])
+ eval(['mex ' basename '_static.c ' basename '_static_mex.c'])
+end
diff --git a/preprocessor/DynamicModel.cc b/preprocessor/DynamicModel.cc
index f4957557e..74d7a2c67 100644
--- a/preprocessor/DynamicModel.cc
+++ b/preprocessor/DynamicModel.cc
@@ -4221,5 +4221,99 @@ DynamicModel::dynamicOnlyEquationsNbr() const
return eqs.size();
}
+#ifndef PRIVATE_BUFFER_SIZE
+#define PRIVATE_BUFFER_SIZE 1024
+#endif
+bool
+DynamicModel::isChecksumMatching(const string &basename) const
+{
+ boost::crc_32_type result;
+ std::stringstream buffer;
+
+ // Write equation tags
+ for (size_t i = 0; i < equation_tags.size(); i++)
+ buffer << " " << equation_tags[i].first + 1
+ << equation_tags[i].second.first
+ << equation_tags[i].second.second;
+
+ ExprNodeOutputType buffer_type = oCDynamicModel;
+
+ for (int eq = 0; eq < (int) equations.size(); eq++)
+ {
+ BinaryOpNode *eq_node = equations[eq];
+ expr_t lhs = eq_node->get_arg1();
+ expr_t rhs = eq_node->get_arg2();
+
+ // Test if the right hand side of the equation is empty.
+ double vrhs = 1.0;
+ try
+ {
+ vrhs = rhs->eval(eval_context_t());
+ }
+ catch (ExprNode::EvalException &e)
+ {
+ }
+
+ if (vrhs != 0) // The right hand side of the equation is not empty ==> residual=lhs-rhs;
+ {
+ buffer << "lhs =";
+ lhs->writeOutput(buffer, buffer_type, temporary_terms);
+ buffer << ";" << endl;
+
+ buffer << "rhs =";
+ rhs->writeOutput(buffer, buffer_type, temporary_terms);
+ buffer << ";" << endl;
+
+ buffer << "residual" << LEFT_ARRAY_SUBSCRIPT(buffer_type)
+ << eq + ARRAY_SUBSCRIPT_OFFSET(buffer_type)
+ << RIGHT_ARRAY_SUBSCRIPT(buffer_type)
+ << "= lhs-rhs;" << endl;
+ }
+ else // The right hand side of the equation is empty ==> residual=lhs;
+ {
+ buffer << "residual" << LEFT_ARRAY_SUBSCRIPT(buffer_type)
+ << eq + ARRAY_SUBSCRIPT_OFFSET(buffer_type)
+ << RIGHT_ARRAY_SUBSCRIPT(buffer_type)
+ << " = ";
+ lhs->writeOutput(buffer, buffer_type, temporary_terms);
+ buffer << ";" << endl;
+ }
+ }
+
+ char private_buffer[PRIVATE_BUFFER_SIZE];
+ while(buffer)
+ {
+ buffer.get(private_buffer,PRIVATE_BUFFER_SIZE);
+ result.process_bytes(private_buffer,strlen(private_buffer));
+ }
+
+ fstream checksum_file;
+
+ string filename = basename + "/checksum";
+
+ // checksum_file.open(filename.c_str(), ios::in | ios::out | ios::binary);
+ checksum_file.open(filename.c_str(), ios::in | ios::binary);
+ unsigned int old_checksum = 0;
+ if (checksum_file.is_open())
+ {
+ checksum_file >> old_checksum;
+ std::cout << "old_checksum " << old_checksum << endl;
+ }
+ if ((!checksum_file.is_open()) || (old_checksum != result.checksum()))
+ {
+ checksum_file.close();
+ checksum_file.open(filename.c_str(), ios::out | ios::binary);
+ if (!checksum_file.is_open())
+ {
+ cerr << "ERROR: Can't open file " << filename << endl;
+ exit(EXIT_FAILURE);
+ }
+ checksum_file << result.checksum();
+ checksum_file.close();
+ return false;
+ }
+
+ return true;
+}
diff --git a/preprocessor/DynamicModel.hh b/preprocessor/DynamicModel.hh
index 8efbc5d3c..d96a7d504 100644
--- a/preprocessor/DynamicModel.hh
+++ b/preprocessor/DynamicModel.hh
@@ -24,6 +24,7 @@ using namespace std;
#define ZERO_BAND 1e-8
#include
+#include
#include "StaticModel.hh"
@@ -479,6 +480,8 @@ public:
void writeSecondDerivativesC_csr(const string &basename, bool cuda) const;
//! Writes C file containing third order derivatives of model evaluated at steady state (compressed sparse column)
void writeThirdDerivativesC_csr(const string &basename, bool cuda) const;
+
+ bool isChecksumMatching(const string &basename) const;
};
//! Classes to re-order derivatives for various sparse storage formats
diff --git a/preprocessor/ModFile.cc b/preprocessor/ModFile.cc
index 6d9eca0ec..9f8f73f56 100644
--- a/preprocessor/ModFile.cc
+++ b/preprocessor/ModFile.cc
@@ -469,55 +469,55 @@ ModFile::computingPass(bool no_tmp_terms, FileOutputType output)
// Compute static model and its derivatives
dynamic_model.toStatic(static_model);
if (!no_static)
- {
- if (mod_file_struct.stoch_simul_present
- || mod_file_struct.estimation_present || mod_file_struct.osr_present
- || mod_file_struct.ramsey_model_present || mod_file_struct.identification_present
- || mod_file_struct.calib_smoother_present)
- static_model.set_cutoff_to_zero();
+ {
+ if (mod_file_struct.stoch_simul_present
+ || mod_file_struct.estimation_present || mod_file_struct.osr_present
+ || mod_file_struct.ramsey_model_present || mod_file_struct.identification_present
+ || mod_file_struct.calib_smoother_present)
+ static_model.set_cutoff_to_zero();
- const bool static_hessian = mod_file_struct.identification_present
- || mod_file_struct.estimation_analytic_derivation;
- const bool paramsDerivatives = mod_file_struct.identification_present
- || mod_file_struct.estimation_analytic_derivation;
- static_model.computingPass(global_eval_context, no_tmp_terms, static_hessian,
- false, paramsDerivatives, block, byte_code);
- }
+ const bool static_hessian = mod_file_struct.identification_present
+ || mod_file_struct.estimation_analytic_derivation;
+ const bool paramsDerivatives = mod_file_struct.identification_present
+ || mod_file_struct.estimation_analytic_derivation;
+ static_model.computingPass(global_eval_context, no_tmp_terms, static_hessian,
+ false, paramsDerivatives, block, byte_code);
+ }
// Set things to compute for dynamic model
if (mod_file_struct.perfect_foresight_solver_present || mod_file_struct.check_present
- || mod_file_struct.stoch_simul_present
- || mod_file_struct.estimation_present || mod_file_struct.osr_present
- || mod_file_struct.ramsey_model_present || mod_file_struct.identification_present
- || mod_file_struct.calib_smoother_present)
- {
- if (mod_file_struct.perfect_foresight_solver_present)
- dynamic_model.computingPass(true, false, false, false, global_eval_context, no_tmp_terms, block, use_dll, byte_code);
- else
- {
- if (mod_file_struct.stoch_simul_present
- || mod_file_struct.estimation_present || mod_file_struct.osr_present
- || mod_file_struct.ramsey_model_present || mod_file_struct.identification_present
- || mod_file_struct.calib_smoother_present)
- dynamic_model.set_cutoff_to_zero();
- if (mod_file_struct.order_option < 1 || mod_file_struct.order_option > 3)
- {
- cerr << "ERROR: Incorrect order option..." << endl;
- exit(EXIT_FAILURE);
- }
- bool hessian = mod_file_struct.order_option >= 2
- || mod_file_struct.identification_present
- || mod_file_struct.estimation_analytic_derivation
- || output == second
- || output == third;
- bool thirdDerivatives = mod_file_struct.order_option == 3
- || mod_file_struct.estimation_analytic_derivation
- || output == third;
- bool paramsDerivatives = mod_file_struct.identification_present || mod_file_struct.estimation_analytic_derivation;
- dynamic_model.computingPass(true, hessian, thirdDerivatives, paramsDerivatives, global_eval_context, no_tmp_terms, block, use_dll, byte_code);
- }
- }
- else // No computing task requested, compute derivatives up to 2nd order by default
- dynamic_model.computingPass(true, true, false, false, global_eval_context, no_tmp_terms, block, use_dll, byte_code);
+ || mod_file_struct.stoch_simul_present
+ || mod_file_struct.estimation_present || mod_file_struct.osr_present
+ || mod_file_struct.ramsey_model_present || mod_file_struct.identification_present
+ || mod_file_struct.calib_smoother_present)
+ {
+ if (mod_file_struct.perfect_foresight_solver_present)
+ dynamic_model.computingPass(true, false, false, false, global_eval_context, no_tmp_terms, block, use_dll, byte_code);
+ else
+ {
+ if (mod_file_struct.stoch_simul_present
+ || mod_file_struct.estimation_present || mod_file_struct.osr_present
+ || mod_file_struct.ramsey_model_present || mod_file_struct.identification_present
+ || mod_file_struct.calib_smoother_present)
+ dynamic_model.set_cutoff_to_zero();
+ if (mod_file_struct.order_option < 1 || mod_file_struct.order_option > 3)
+ {
+ cerr << "ERROR: Incorrect order option..." << endl;
+ exit(EXIT_FAILURE);
+ }
+ bool hessian = mod_file_struct.order_option >= 2
+ || mod_file_struct.identification_present
+ || mod_file_struct.estimation_analytic_derivation
+ || output == second
+ || output == third;
+ bool thirdDerivatives = mod_file_struct.order_option == 3
+ || mod_file_struct.estimation_analytic_derivation
+ || output == third;
+ bool paramsDerivatives = mod_file_struct.identification_present || mod_file_struct.estimation_analytic_derivation;
+ dynamic_model.computingPass(true, hessian, thirdDerivatives, paramsDerivatives, global_eval_context, no_tmp_terms, block, use_dll, byte_code);
+ }
+ }
+ else // No computing task requested, compute derivatives up to 2nd order by default
+ dynamic_model.computingPass(true, true, false, false, global_eval_context, no_tmp_terms, block, use_dll, byte_code);
}
for (vector::iterator it = statements.begin();
@@ -649,18 +649,23 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
<< " error('DYNARE: Can''t find bytecode DLL. Please compile it or remove the ''bytecode'' option.')" << endl
<< "end" << endl;
- // Erase possible remnants of previous runs
- unlink((basename + "_dynamic.m").c_str());
- unlink((basename + "_dynamic.cod").c_str());
- unlink((basename + "_dynamic.bin").c_str());
+ bool hasModelChanged = !dynamic_model.isChecksumMatching(basename);
+
+ if (hasModelChanged)
+ {
+ // Erase possible remnants of previous runs
+ unlink((basename + "_dynamic.m").c_str());
+ unlink((basename + "_dynamic.cod").c_str());
+ unlink((basename + "_dynamic.bin").c_str());
- unlink((basename + "_static.m").c_str());
- unlink((basename + "_static.cod").c_str());
- unlink((basename + "_static.bin").c_str());
-
- unlink((basename + "_steadystate2.m").c_str());
- unlink((basename + "_set_auxiliary_variables.m").c_str());
+ unlink((basename + "_static.m").c_str());
+ unlink((basename + "_static.cod").c_str());
+ unlink((basename + "_static.bin").c_str());
+ unlink((basename + "_steadystate2.m").c_str());
+ unlink((basename + "_set_auxiliary_variables.m").c_str());
+ }
+
if (!use_dll)
{
mOutputFile << "erase_compiled_function('" + basename + "_static');" << endl;
@@ -697,53 +702,19 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
// Compile the dynamic MEX file for use_dll option
if (use_dll)
{
- mOutputFile << "if ~exist('OCTAVE_VERSION')" << endl;
- // Some mex commands are enclosed in an eval(), because otherwise it will make Octave fail
#if defined(_WIN32) || defined(__CYGWIN32__)
if (msvc)
// MATLAB/Windows + Microsoft Visual C++
- mOutputFile << " eval('mex -O LINKFLAGS=\"$LINKFLAGS /export:Dynamic\" " << basename << "_dynamic.c " << basename << "_dynamic_mex.c')" << endl
- << " eval('mex -O LINKFLAGS=\"$LINKFLAGS /export:Static\" " << basename << "_static.c "<< basename << "_static_mex.c')" << endl;
+ mOutputFile << "dyn_mex('msvc', '" << basename << ", 1)" << endl;
else if (cygwin)
// MATLAB/Windows + Cygwin g++
- mOutputFile << " eval('mex -O PRELINK_CMDS1=\"echo EXPORTS > mex.def & echo mexFunction >> mex.def & echo Dynamic >> mex.def\" " << basename << "_dynamic.c " << basename << "_dynamic_mex.c')" << endl
- << " eval('mex -O PRELINK_CMDS1=\"echo EXPORTS > mex.def & echo mexFunction >> mex.def & echo Static >> mex.def\" " << basename << "_static.c "<< basename << "_static_mex.c')" << endl;
+ mOutputFile << "dyn_mex('cygwin', '" << basename << "', 1)" << endl;
else
mOutputFile << " error('When using the USE_DLL option, you must give either ''cygwin'' or ''msvc'' option to the ''dynare'' command')" << endl;
#else
-# ifdef __linux__
- // MATLAB/Linux
- mOutputFile << " if matlab_ver_less_than('8.3')" << endl
- << " eval('mex -O LDFLAGS=''-pthread -shared -Wl,--no-undefined'' " << basename << "_dynamic.c " << basename << "_dynamic_mex.c')" << endl
- << " eval('mex -O LDFLAGS=''-pthread -shared -Wl,--no-undefined'' " << basename << "_static.c "<< basename << "_static_mex.c')" << endl
- << " else" << endl
- << " eval('mex -O LINKEXPORT='''' " << basename << "_dynamic.c " << basename << "_dynamic_mex.c')" << endl
- << " eval('mex -O LINKEXPORT='''' " << basename << "_static.c "<< basename << "_static_mex.c')" << endl
- << " end" << endl;
-# else // MacOS
- // MATLAB/MacOS
- mOutputFile << " if matlab_ver_less_than('8.3')" << endl
- << " if matlab_ver_less_than('8.1')" << endl
- << " eval('mex -O LDFLAGS=''-Wl,-twolevel_namespace -undefined error -arch \\$ARCHS -Wl,-syslibroot,\\$SDKROOT -mmacosx-version-min=\\$MACOSX_DEPLOYMENT_TARGET -bundle'' "
- << basename << "_dynamic.c " << basename << "_dynamic_mex.c')" << endl
- << " eval('mex -O LDFLAGS=''-Wl,-twolevel_namespace -undefined error -arch \\$ARCHS -Wl,-syslibroot,\\$SDKROOT -mmacosx-version-min=\\$MACOSX_DEPLOYMENT_TARGET -bundle'' "
- << basename << "_static.c " << basename << "_static_mex.c')" << endl
- << " else" << endl
- << " eval('mex -O LDFLAGS=''-Wl,-twolevel_namespace -undefined error -arch \\$ARCHS -Wl,-syslibroot,\\$MW_SDKROOT -mmacosx-version-min=\\$MACOSX_DEPLOYMENT_TARGET -bundle'' "
- << basename << "_dynamic.c " << basename << "_dynamic_mex.c')" << endl
- << " eval('mex -O LDFLAGS=''-Wl,-twolevel_namespace -undefined error -arch \\$ARCHS -Wl,-syslibroot,\\$MW_SDKROOT -mmacosx-version-min=\\$MACOSX_DEPLOYMENT_TARGET -bundle'' "
- << basename << "_static.c " << basename << "_static_mex.c')" << endl
- << " end" << endl
- << " else" << endl
- << " eval('mex -O LINKEXPORT='''' " << basename << "_dynamic.c " << basename << "_dynamic_mex.c')" << endl
- << " eval('mex -O LINKEXPORT='''' " << basename << "_static.c "<< basename << "_static_mex.c')" << endl
- << " end" << endl;
-# endif
+ // other configurations
+ mOutputFile << "dyn_mex('', '" << basename << "', 1)" << endl;
#endif
- mOutputFile << "else" << endl // Octave
- << " mex " << basename << "_dynamic.c " << basename << "_dynamic_mex.c" << endl
- << " mex " << basename << "_static.c " << basename << "_static_mex.c" << endl
- << "end" << endl;
}
// Add path for block option with M-files
@@ -824,22 +795,24 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
mOutputFile.close();
- // Create static and dynamic files
- if (dynamic_model.equation_number() > 0)
+ if (hasModelChanged)
{
- if (!no_static)
- {
- static_model.writeStaticFile(basename, block, byte_code, use_dll);
- static_model.writeParamsDerivativesFile(basename);
- }
+ // Create static and dynamic files
+ if (dynamic_model.equation_number() > 0)
+ {
+ if (!no_static)
+ {
+ static_model.writeStaticFile(basename, block, byte_code, use_dll);
+ static_model.writeParamsDerivativesFile(basename);
+ }
- dynamic_model.writeDynamicFile(basename, block, byte_code, use_dll, mod_file_struct.order_option);
- dynamic_model.writeParamsDerivativesFile(basename);
+ dynamic_model.writeDynamicFile(basename, block, byte_code, use_dll, mod_file_struct.order_option);
+ dynamic_model.writeParamsDerivativesFile(basename);
+ }
+
+ // Create steady state file
+ steady_state_model.writeSteadyStateFile(basename, mod_file_struct.ramsey_model_present);
}
-
- // Create steady state file
- steady_state_model.writeSteadyStateFile(basename, mod_file_struct.ramsey_model_present);
-
+
cout << "done" << endl;
}
-
diff --git a/preprocessor/ModFile.hh b/preprocessor/ModFile.hh
index 722ea5341..0a384931b 100644
--- a/preprocessor/ModFile.hh
+++ b/preprocessor/ModFile.hh
@@ -24,6 +24,8 @@ using namespace std;
#include
#include
+#include
+#include
#include "SymbolTable.hh"
#include "NumericalConstants.hh"
@@ -37,6 +39,11 @@ using namespace std;
#include "WarningConsolidation.hh"
#include "ExtendedPreprocessorTypes.hh"
+// for checksum computation
+#ifndef PRIVATE_BUFFER_SIZE
+#define PRIVATE_BUFFER_SIZE 1024
+#endif
+
//! The abstract representation of a "mod" file
class ModFile
{
@@ -153,6 +160,8 @@ public:
//! Writes Cpp output files only => No further Matlab processing
void writeCCOutputFiles(const string &basename) const;
void writeModelCC(const string &basename) const;
+
+ void computeChecksum();
};
#endif // ! MOD_FILE_HH