From 6f65d48376484e5c18caafc35087f18d91f87271 Mon Sep 17 00:00:00 2001 From: Michel Juillard Date: Sat, 15 Mar 2014 21:07:09 +0100 Subject: [PATCH 1/2] extended-preprocessor: starting a C interface (not finished) --- DynamicModel.cc | 105 +++++++++++++++++++++++++++++++++++++++--- DynamicModel.hh | 8 ++-- ModFile.cc | 108 +++++++++++++++++++++++++++++++++++++------- ModFile.hh | 2 +- SteadyStateModel.cc | 4 +- SteadyStateModel.hh | 2 +- SymbolTable.cc | 99 +++++++++++++++++++++++++++++++++++++++- SymbolTable.hh | 2 + 8 files changed, 300 insertions(+), 30 deletions(-) diff --git a/DynamicModel.cc b/DynamicModel.cc index bd2adaed..0c6e801b 100644 --- a/DynamicModel.cc +++ b/DynamicModel.cc @@ -2958,6 +2958,99 @@ DynamicModel::writeOutput(ostream &output, const string &basename, bool block_de void DynamicModel::writeCOutput(ostream &output, const string &basename, bool block_decomposition, bool byte_code, bool use_dll, int order, bool estimation_present) const +{ + int lag_presence[3]; + // Loop on endogenous variables + vector zeta_back, zeta_mixed, zeta_fwrd, zeta_static; + for (int endoID = 0; endoID < symbol_table.endo_nbr(); endoID++) + { + int varID; + // Loop on periods + for (int lag = 0; lag <= 2; lag++) + { + lag_presence[lag] = 1; + try + { + varID = getDerivID(symbol_table.getID(eEndogenous, endoID), lag-1); + } + catch (UnknownDerivIDException &e) + { + lag_presence[lag] = 0; + } + } + if (lag_presence[0] == 1) + if (lag_presence[2] == 1) + zeta_mixed.push_back(endoID); + else + zeta_back.push_back(endoID); + else if (lag_presence[2] == 1) + zeta_fwrd.push_back(endoID); + else + zeta_static.push_back(endoID); + + } + output << "nstatic = " << zeta_static.size() << ";" << endl + << "nfwrd = " << zeta_fwrd.size() << ";" << endl + << "nback = " << zeta_back.size() << ";" << endl + << "nmixed = " << zeta_mixed.size() << ";" << endl; + output << "zeta_static[" << zeta_static.size() << "] = {"; + for (vector::iterator i = zeta_static.begin(); i != zeta_static.end(); ++i) + { + if ( i != zeta_static.begin() ) + output << ","; + output << *i; + } + output << "};" << endl; + + output << "zeta_back[" << zeta_back.size() << "] = {"; + for (vector::iterator i = zeta_back.begin(); i != zeta_back.end(); ++i) + { + if ( i != zeta_back.begin() ) + output << ","; + output << *i; + } + output << "};" << endl; + + output << "zeta_fwrd[" << zeta_fwrd.size() << "] = {"; + for (vector::iterator i = zeta_fwrd.begin(); i != zeta_fwrd.end(); ++i) + { + if ( i != zeta_fwrd.begin() ) + output << ","; + output << *i; + } + output << "};" << endl; + + output << "zeta_mixed[" << zeta_mixed.size() << "] = {"; + for (vector::iterator i = zeta_mixed.begin(); i != zeta_mixed.end(); ++i) + { + if ( i != zeta_mixed.begin() ) + output << ","; + output << *i; + } + output << "};" << endl; + + // Write number of non-zero derivatives + // Use -1 if the derivatives have not been computed + output << "int *NNZDerivatives[3] = {"; + switch (order) + { + case 0: + output << NNZDerivativs[0] << ",-1,-1};" << endl; + break; + case 1: + output << NNZDerivativs[0] << "," << NNZDerivatives[1] << ",-1};" << endl; + break; + case 2: + output << NNZDerivativs[0] << "," << NNZDerivatives[1] << "," << NNZDerivatives[2] << "};" << endl; + break; + default: + cerr << "Order larger than 3 not implemented" << endl; + exit(EXIT_FAILURE); + } +} + +void +DynamicModel::writeCCOutput(ostream &output, const string &basename, bool block_decomposition, bool byte_code, bool use_dll, int order, bool estimation_present) const { int lag_presence[3]; // Loop on endogenous variables @@ -4339,9 +4432,9 @@ DynamicModel::dynamicOnlyEquationsNbr() const } void -DynamicModel::writeFirstDerivativesCC(const string &basename, bool cuda) const +DynamicModel::writeFirstDerivativesC(const string &basename, bool cuda) const { - string filename = basename + "_first_derivatives.cc"; + string filename = basename + "_first_derivatives.c"; ofstream mDynamicModelFile, mDynamicMexFile; mDynamicModelFile.open(filename.c_str(), ios::out | ios::binary); @@ -4396,10 +4489,10 @@ DynamicModel::writeFirstDerivativesCC(const string &basename, bool cuda) const // using compressed sparse row format (CSR) void -DynamicModel::writeSecondDerivativesCC_csr(const string &basename, bool cuda) const +DynamicModel::writeSecondDerivativesC_csr(const string &basename, bool cuda) const { - string filename = basename + "_second_derivatives.cc"; + string filename = basename + "_second_derivatives.c"; ofstream mDynamicModelFile, mDynamicMexFile; mDynamicModelFile.open(filename.c_str(), ios::out | ios::binary); @@ -4490,9 +4583,9 @@ DynamicModel::writeSecondDerivativesCC_csr(const string &basename, bool cuda) co } void -DynamicModel::writeThirdDerivativesCC_csr(const string &basename, bool cuda) const +DynamicModel::writeThirdDerivativesC_csr(const string &basename, bool cuda) const { - string filename = basename + "_third_derivatives.cc"; + string filename = basename + "_third_derivatives.c"; ofstream mDynamicModelFile, mDynamicMexFile; mDynamicModelFile.open(filename.c_str(), ios::out | ios::binary); diff --git a/DynamicModel.hh b/DynamicModel.hh index 8de6bd39..e1ee490b 100644 --- a/DynamicModel.hh +++ b/DynamicModel.hh @@ -215,6 +215,8 @@ public: void writeOutput(ostream &output, const string &basename, bool block, bool byte_code, bool use_dll, int order, bool estimation_present) const; //! Writes model initialization and lead/lag incidence matrix to C output void writeCOutput(ostream &output, const string &basename, bool block, bool byte_code, bool use_dll, int order, bool estimation_present) const; + //! Writes model initialization and lead/lag incidence matrix to Cpp output + void writeCCOutput(ostream &output, const string &basename, bool block, bool byte_code, bool use_dll, int order, bool estimation_present) const; //! Adds informations for simulation in a binary file void Write_Inf_To_Bin_File_Block(const string &dynamic_basename, const string &bin_basename, @@ -224,11 +226,11 @@ public: //! Writes file containing parameters derivatives void writeParamsDerivativesFile(const string &basename) const; //! Writes CC file containing first order derivatives of model evaluated at steady state - void writeFirstDerivativesCC(const string &basename, bool cuda) const; + void writeFirstDerivativesC(const string &basename, bool cuda) const; //! Writes CC file containing second order derivatives of model evaluated at steady state (compressed sparse column) - void writeSecondDerivativesCC_csr(const string &basename, bool cuda) const; + void writeSecondDerivativesC_csr(const string &basename, bool cuda) const; //! Writes CC file containing third order derivatives of model evaluated at steady state (compressed sparse column) - void writeThirdDerivativesCC_csr(const string &basename, bool cuda) const; + void writeThirdDerivativesC_csr(const string &basename, bool cuda) const; //! Converts to static model (only the equations) /*! It assumes that the static model given in argument has just been allocated */ void toStatic(StaticModel &static_model) const; diff --git a/ModFile.cc b/ModFile.cc index 98ee8d7d..ece9a709 100644 --- a/ModFile.cc +++ b/ModFile.cc @@ -805,9 +805,9 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool no_log, b } void -ModFile::writeModelCC(const string &basename, bool cuda) const +ModFile::writeModelC(const string &basename, bool cuda) const { - string filename = basename + ".cc"; + string filename = basename + ".c"; ofstream mDriverCFile; mDriverCFile.open(filename.c_str(), ios::out | ios::binary); @@ -818,15 +818,15 @@ ModFile::writeModelCC(const string &basename, bool cuda) const } mDriverCFile << "/*" << endl - << " * " << filename << " : Driver file for MS-DSGE code" << endl + << " * " << filename << " : Driver file for Dynare C code" << endl << " *" << endl << " * Warning : this file is generated automatically by Dynare" << endl << " * from model file (.mod)" << endl << " */" << endl << endl - << "#include \"dynare_cpp_driver.hh\"" << endl + << "#include \"dynare_driver.h\"" << endl << endl - << "DynareInfo::DynareInfo(void)" << endl + << "struct" << endl << "{" << endl; // Write basic info @@ -846,7 +846,7 @@ ModFile::writeModelCC(const string &basename, bool cuda) const it != statements.end(); it++) (*it)->writeCOutput(mDriverCFile, basename); - mDriverCFile << "}" << endl; + mDriverCFile << "} DynareInfo;" << endl; mDriverCFile.close(); // Write informational m file @@ -876,6 +876,82 @@ ModFile::writeModelCC(const string &basename, bool cuda) const << "% Warning : this file is generated automatically by Dynare" << endl << "% from model file (.mod)" << endl << endl << "disp('The following C file was successfully created:');" << endl + << "ls preprocessorOutput.c" << endl << endl; + mOutputFile.close(); +} + +void +ModFile::writeModelCC(const string &basename, bool cuda) const +{ + string filename = basename + ".cc"; + + ofstream mDriverCFile; + mDriverCFile.open(filename.c_str(), ios::out | ios::binary); + if (!mDriverCFile.is_open()) + { + cerr << "Error: Can't open file " << filename << " for writing" << endl; + exit(EXIT_FAILURE); + } + + mDriverCFile << "/*" << endl + << " * " << filename << " : Driver file for Dynare C++ code" << endl + << " *" << endl + << " * Warning : this file is generated automatically by Dynare" << endl + << " * from model file (.mod)" << endl + << " */" << endl + << endl + << "#include \"dynare_cpp_driver.hh\"" << endl + << endl + << "DynareInfo::DynareInfo(void)" << endl + << "{" << endl; + + // Write basic info + symbol_table.writeCCOutput(mDriverCFile); + + mDriverCFile << endl << "params.resize(param_nbr);" << endl; + + if (dynamic_model.equation_number() > 0) + { + dynamic_model.writeCOutput(mDriverCFile, basename, block, byte_code, use_dll, mod_file_struct.order_option, mod_file_struct.estimation_present); + // if (!no_static) + // static_model.writeCOutput(mOutputFile, block); + } + + // Print statements + for (vector::const_iterator it = statements.begin(); + it != statements.end(); it++) + (*it)->writeCOutput(mDriverCFile, basename); + + mDriverCFile << "};" << endl; + mDriverCFile.close(); + + // Write informational m file + ofstream mOutputFile; + + if (basename.size()) + { + string fname(basename); + fname += ".m"; + mOutputFile.open(fname.c_str(), ios::out | ios::binary); + if (!mOutputFile.is_open()) + { + cerr << "ERROR: Can't open file " << fname + << " for writing" << endl; + exit(EXIT_FAILURE); + } + } + else + { + cerr << "ERROR: Missing file name" << endl; + exit(EXIT_FAILURE); + } + + mOutputFile << "%" << endl + << "% Status : informational m file" << endl + << "%" << endl + << "% Warning : this file is generated automatically by Dynare" << endl + << "% from model file (.mod)" << endl << endl + << "disp('The following C++ file was successfully created:');" << endl << "ls preprocessorOutput.cc" << endl << endl; mOutputFile.close(); } @@ -883,8 +959,8 @@ ModFile::writeModelCC(const string &basename, bool cuda) const void ModFile::writeExternalFiles(const string &basename, FileOutputType output, bool cuda) const { - writeModelCC(basename, cuda); - steady_state_model.writeSteadyStateFileCC(basename, mod_file_struct.ramsey_model_present, cuda); + writeModelC(basename, cuda); + steady_state_model.writeSteadyStateFileC(basename, mod_file_struct.ramsey_model_present, cuda); dynamic_model.writeDynamicFile(basename, block, byte_code, use_dll, mod_file_struct.order_option); @@ -893,18 +969,18 @@ ModFile::writeExternalFiles(const string &basename, FileOutputType output, bool // static_model.writeStaticCFile(basename, block, byte_code, use_dll); - // static_model.writeParamsDerivativesFileCC(basename, cuda); - // static_model.writeAuxVarInitvalCC(mOutputFile, oMatlabOutsideModel, cuda); + // static_model.writeParamsDerivativesFileC(basename, cuda); + // static_model.writeAuxVarInitvalC(mOutputFile, oMatlabOutsideModel, cuda); - // dynamic_model.writeResidualsCC(basename, cuda); - // dynamic_model.writeParamsDerivativesFileCC(basename, cuda); - dynamic_model.writeFirstDerivativesCC(basename, cuda); + // dynamic_model.writeResidualsC(basename, cuda); + // dynamic_model.writeParamsDerivativesFileC(basename, cuda); + dynamic_model.writeFirstDerivativesC(basename, cuda); if (output == second) - dynamic_model.writeSecondDerivativesCC_csr(basename, cuda); + dynamic_model.writeSecondDerivativesC_csr(basename, cuda); else if (output == third) { - dynamic_model.writeSecondDerivativesCC_csr(basename, cuda); - dynamic_model.writeThirdDerivativesCC_csr(basename, cuda); + dynamic_model.writeSecondDerivativesC_csr(basename, cuda); + dynamic_model.writeThirdDerivativesC_csr(basename, cuda); } } diff --git a/ModFile.hh b/ModFile.hh index aca8ef9d..9885c6e6 100644 --- a/ModFile.hh +++ b/ModFile.hh @@ -140,7 +140,7 @@ public: ) const; //! Writes C output files only => No further Matlab processing void writeCOutputFiles(const string &basename) const; - void writeModelCC(const string &basename, bool cuda) const; + void writeModelC(const string &basename, bool cuda) const; void writeExternalFiles(const string &basename, FileOutputType output, bool cuda) const; }; diff --git a/SteadyStateModel.cc b/SteadyStateModel.cc index f1069642..1c590a98 100644 --- a/SteadyStateModel.cc +++ b/SteadyStateModel.cc @@ -153,9 +153,9 @@ SteadyStateModel::writeSteadyStateFile(const string &basename, bool ramsey_model } void -SteadyStateModel::writeSteadyStateFileCC(const string &basename, bool ramsey_model, bool cuda) const +SteadyStateModel::writeSteadyStateFileC(const string &basename, bool ramsey_model, bool cuda) const { - string filename = basename + "_steadystate.cc"; + string filename = basename + "_steadystate.c"; ofstream output; output.open(filename.c_str(), ios::out | ios::binary); diff --git a/SteadyStateModel.hh b/SteadyStateModel.hh index 817f84f5..f8bb051f 100644 --- a/SteadyStateModel.hh +++ b/SteadyStateModel.hh @@ -49,7 +49,7 @@ public: \param[in] ramsey_model Is there a Ramsey model in the MOD file? If yes, then use the "ys" in argument of the steady state file as initial values */ void writeSteadyStateFile(const string &basename, bool ramsey_model) const; - void writeSteadyStateFileCC(const string &basename, bool ramsey_model, bool cuda) const; + void writeSteadyStateFileC(const string &basename, bool ramsey_model, bool cuda) const; }; #endif diff --git a/SymbolTable.cc b/SymbolTable.cc index 00152684..4e207cfe 100644 --- a/SymbolTable.cc +++ b/SymbolTable.cc @@ -288,6 +288,103 @@ SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException) void SymbolTable::writeCOutput(ostream &output) const throw (NotYetFrozenException) +{ + if (!frozen) + throw NotYetFrozenException(); + + output << endl + << "int exo_nbr = " << exo_nbr() << ";" << endl; + if (exo_nbr() > 0) + { + output << "char *exo_names[" << exo_nbr() << "];" << endl; + for (int id = 0; id < exo_nbr(); id++) + output << "exo_names[" << id << "] = \"" << getName(exo_ids[id]) << "\";" << endl; + } + + output << endl + << "int exo_det_nbr = " << exo_det_nbr() << ";" << endl; + if (exo_det_nbr() > 0) + { + output << "char *exo_det_names[" << exo_det_nbr() << "];" << endl; + for (int id = 0; id < exo_det_nbr(); id++) + output << "exo_det_names[" << id << "] = \"" << getName(exo_det_ids[id]) << "\";" << endl; + } + + output << endl + << "int endo_nbr = " << endo_nbr() << ";" << endl; + if (endo_nbr() > 0) + { + output << "char *endo_names[" << endo_nbr() << "];" << endl; + for (int id = 0; id < endo_nbr(); id++) + output << "endo_names[" << id << "] = \"" << getName(endo_ids[id]) << "\";" << endl; + } + + output << endl + << "int param_nbr = " << param_nbr() << ";" << endl; + if (param_nbr() > 0) + { + output << "char *param_names[" << param_nbr() << "];" << endl; + for (int id = 0; id < param_nbr(); id++) + output << "param_names[" << id << "] = \"" << getName(param_ids[id]) << "\";" << endl; + } + + // Write the auxiliary variable table + output << "int aux_var_nbr = " << aux_vars.size() << ";" << endl; + if (aux_vars.size() > 0) + { + output << "struct aux_vars_t *av[" << aux_vars.size() << "];" << endl; + for (int i = 0; i < (int) aux_vars.size(); i++) + { + output << "av[" << i << "].endo_index = " << getTypeSpecificID(aux_vars[i].get_symb_id()) << ";" << endl + << "av[" << i << "].type = " << aux_vars[i].get_type() << ";" << endl; + switch (aux_vars[i].get_type()) + { + case avEndoLead: + case avExoLead: + case avExpectation: + case avMultiplier: + case avDiffForward: + break; + case avEndoLag: + case avExoLag: + output << "av[" << i << "].orig_index = " << getTypeSpecificID(aux_vars[i].get_orig_symb_id()) << ";" << endl + << "av[" << i << "].orig_lead_lag = " << aux_vars[i].get_orig_lead_lag() << ";" << endl; + break; + } + } + } + + output << "int predeterminedNbr = " << predeterminedNbr() << ";" << endl; + if (predeterminedNbr() > 0) + { + output << "int predetermined_variables[" << predeterminedNbr() << "] = {"; + for (set::const_iterator it = predetermined_variables.begin(); + it != predetermined_variables.end(); it++) + { + if ( it != predetermined_variables.begin() ) + output << ","; + output << getTypeSpecificID(*it); + } + output << "};" << endl; + } + + output << "int observedVariablesNbr = " << observedVariablesNbr() << ";" << endl; + if (observedVariablesNbr() > 0) + { + output << "int varobs[" << observedVariablesNbr() << "] = {"; + for (vector::const_iterator it = varobs.begin(); + it != varobs.end(); it++) + { + if ( it != varobs.begin() ) + output << ","; + output << getTypeSpecificID(*it); + } + output << "};" << endl; + } +} + +void +SymbolTable::writeCCOutput(ostream &output) const throw (NotYetFrozenException) { if (!frozen) throw NotYetFrozenException(); @@ -596,7 +693,7 @@ SymbolTable::getEndogenous() const bool SymbolTable::isAuxiliaryVariable(int symb_id) const { - for (int i = 0; i < aux_vars.size(); i++) + for (int i = 0; i < (int) aux_vars.size(); i++) if (aux_vars[i].get_symb_id() == symb_id) return true; return false; diff --git a/SymbolTable.hh b/SymbolTable.hh index 8e0903e5..3e4c47e1 100644 --- a/SymbolTable.hh +++ b/SymbolTable.hh @@ -278,6 +278,8 @@ public: void writeOutput(ostream &output) const throw (NotYetFrozenException); //! Write C output of this class void writeCOutput(ostream &output) const throw (NotYetFrozenException); + //! Write CC output of this class + void writeCCOutput(ostream &output) const throw (NotYetFrozenException); //! Mark a symbol as predetermined variable void markPredetermined(int symb_id) throw (UnknownSymbolIDException, FrozenException); //! Test if a given symbol is a predetermined variable From 63706abf2b0d8eeb126a278996a7b6db35ac85e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= Date: Tue, 13 May 2014 11:46:19 +0200 Subject: [PATCH 2/2] Forbid model local variables in planner_objective. Otherwise the preprocessor crashes. --- ParsingDriver.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ParsingDriver.cc b/ParsingDriver.cc index 70ebe871..517b0d88 100644 --- a/ParsingDriver.cc +++ b/ParsingDriver.cc @@ -323,6 +323,9 @@ ParsingDriver::add_model_variable(int symb_id, int lag) if (dynamic_cast(model_tree) != NULL && lag != 0) error("Leads and lags on variables are forbidden in 'planner_objective'."); + if (dynamic_cast(model_tree) != NULL && type == eModelLocalVariable) + error("Model local variable " + mod_file->symbol_table.getName(symb_id) + " cannot be used in 'planner_objective'."); + // It makes sense to allow a lead/lag on parameters: during steady state calibration, endogenous and parameters can be swapped return model_tree->AddVariable(symb_id, lag); }