diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc index 2a1094ddc8e8936ff0290b4ab21cd4046d45d13a..376dfbba1e44fb85d432a9570445aed624c4dda8 100644 --- a/src/DynamicModel.cc +++ b/src/DynamicModel.cc @@ -2508,16 +2508,13 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput, deriv_node_temp_terms_t tef_terms; temporary_terms_t temp_term_union; - for (auto it : temporary_terms_mlv) - temp_term_union.insert(it.first); - writeModelLocalVariableTemporaryTerms(temp_term_union, temporary_terms_mlv, + writeModelLocalVariableTemporaryTerms(temp_term_union, model_tt_output, output_type, tef_terms); writeTemporaryTerms(temporary_terms_derivatives[0], temp_term_union, temporary_terms_idxs, model_tt_output, output_type, tef_terms); - temp_term_union.insert(temporary_terms_derivatives[0].begin(), temporary_terms_derivatives[0].end()); writeModelEquations(model_output, output_type, temp_term_union); @@ -2531,7 +2528,6 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput, temp_term_union, temporary_terms_idxs, jacobian_tt_output, output_type, tef_terms); - temp_term_union.insert(temporary_terms_derivatives[1].begin(), temporary_terms_derivatives[1].end()); for (const auto & first_derivative : derivatives[1]) { @@ -2554,7 +2550,6 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput, temp_term_union, temporary_terms_idxs, hessian_tt_output, output_type, tef_terms); - temp_term_union.insert(temporary_terms_derivatives[2].begin(), temporary_terms_derivatives[2].end()); int k = 0; // Keep the line of a 2nd derivative in v2 for (const auto & second_derivative : derivatives[2]) @@ -2623,7 +2618,6 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput, temp_term_union, temporary_terms_idxs, third_derivatives_tt_output, output_type, tef_terms); - temp_term_union.insert(temporary_terms_derivatives[3].begin(), temporary_terms_derivatives[3].end()); int k = 0; // Keep the line of a 3rd derivative in v3 for (const auto & third_derivative : derivatives[3]) @@ -5389,9 +5383,10 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con ostringstream third_derivs_output; // Used for storing third order derivatives equations ostringstream third_derivs1_output; // Used for storing third order derivatives equations + temporary_terms_t temp_term_union; deriv_node_temp_terms_t tef_terms; - writeTemporaryTerms(params_derivs_temporary_terms, {}, params_derivs_temporary_terms_idxs, model_output, output_type, tef_terms); + writeTemporaryTerms(params_derivs_temporary_terms, temp_term_union, params_derivs_temporary_terms_idxs, model_output, output_type, tef_terms); for (const auto & residuals_params_derivative : params_derivatives.find({ 0, 1 })->second) { diff --git a/src/ModelTree.cc b/src/ModelTree.cc index 76d878eb55fc6dd0fbb3b0861f1ff157602baa48..111c046c1d6b4d9fe1c211c703db75fcfe5a59dd 100644 --- a/src/ModelTree.cc +++ b/src/ModelTree.cc @@ -1361,17 +1361,18 @@ ModelTree::computeTemporaryTerms(bool is_matlab, bool no_tmp_terms) temporary_terms_derivatives.clear(); temporary_terms_derivatives.resize(4); - // Collect all model local variables appearing in equations. See #101 - // All used model local variables are automatically set as temporary variables + /* Collect all model local variables appearing in equations (and only those, + because printing unused model local variables can lead to a crash, + see Dynare/dynare#101). + Then store them in a dedicated structure (temporary_terms_mlv), that will + be treated as the rest of temporary terms. */ set<int> used_local_vars; for (auto & equation : equations) equation->collectVariables(SymbolType::modelLocalVariable, used_local_vars); - for (int used_local_var : used_local_vars) { VariableNode *v = AddVariable(used_local_var); temporary_terms_mlv[v] = local_variables_table.find(used_local_var)->second; - reference_count[v] = { ExprNode::min_cost(is_matlab)+1, NodeTreeReference::residuals }; } map<NodeTreeReference, temporary_terms_t> temp_terms_map; @@ -1413,9 +1414,8 @@ ModelTree::computeTemporaryTerms(bool is_matlab, bool no_tmp_terms) temporary_terms_derivatives[3] = temp_terms_map[NodeTreeReference::thirdDeriv]; int idx = 0; - for (map<expr_t, expr_t, ExprNodeLess>::const_iterator it = temporary_terms_mlv.begin(); - it != temporary_terms_mlv.end(); it++) - temporary_terms_idxs[it->first] = idx++; + for (auto &it : temporary_terms_mlv) + temporary_terms_idxs[it.first] = idx++; for (auto it : temporary_terms_derivatives[0]) temporary_terms_idxs[it] = idx++; @@ -1431,56 +1431,57 @@ ModelTree::computeTemporaryTerms(bool is_matlab, bool no_tmp_terms) } void -ModelTree::writeModelLocalVariableTemporaryTerms(const temporary_terms_t &tto, const map<expr_t, expr_t, ExprNodeLess> &tt, +ModelTree::writeModelLocalVariableTemporaryTerms(temporary_terms_t &temp_term_union, ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const { - temporary_terms_t tt2; - for (auto it : tt) + temporary_terms_t tto; + for (auto it : temporary_terms_mlv) + tto.insert(it.first); + + for (auto &it : temporary_terms_mlv) { if (isJuliaOutput(output_type)) output << " @inbounds const "; it.first->writeOutput(output, output_type, tto, temporary_terms_idxs, tef_terms); output << " = "; - it.second->writeOutput(output, output_type, tt2, temporary_terms_idxs, tef_terms); + it.second->writeOutput(output, output_type, temp_term_union, temporary_terms_idxs, tef_terms); if (isCOutput(output_type) || isMatlabOutput(output_type)) output << ";"; output << endl; - // Insert current node into tt2 - tt2.insert(it.first); + /* We put in temp_term_union the VariableNode corresponding to the MLV, + not its definition, so that when equations use the MLV, + T(XXX) is printed instead of the MLV name */ + temp_term_union.insert(it.first); } } void ModelTree::writeTemporaryTerms(const temporary_terms_t &tt, - const temporary_terms_t &ttm1, + temporary_terms_t &temp_term_union, const temporary_terms_idxs_t &tt_idxs, ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const { - // Local var used to keep track of temp nodes already written - temporary_terms_t tt2 = ttm1; - for (auto it = tt.begin(); - it != tt.end(); it++) + for (auto it : tt) { - if (dynamic_cast<AbstractExternalFunctionNode *>(*it) != nullptr) - (*it)->writeExternalFunctionOutput(output, output_type, tt2, tt_idxs, tef_terms); + if (dynamic_cast<AbstractExternalFunctionNode *>(it) != nullptr) + it->writeExternalFunctionOutput(output, output_type, temp_term_union, tt_idxs, tef_terms); if (isJuliaOutput(output_type)) output << " @inbounds "; - (*it)->writeOutput(output, output_type, tt, tt_idxs, tef_terms); + it->writeOutput(output, output_type, tt, tt_idxs, tef_terms); output << " = "; - (*it)->writeOutput(output, output_type, tt2, tt_idxs, tef_terms); + it->writeOutput(output, output_type, temp_term_union, tt_idxs, tef_terms); if (isCOutput(output_type) || isMatlabOutput(output_type)) output << ";"; output << endl; - // Insert current node into tt2 - tt2.insert(*it); + temp_term_union.insert(it); } } diff --git a/src/ModelTree.hh b/src/ModelTree.hh index 1b21f300bdd1a080ca18567954ed67957e21d3e1..33e0b79fb6e369aa07381fe361b3c61c8dba44e6 100644 --- a/src/ModelTree.hh +++ b/src/ModelTree.hh @@ -107,10 +107,11 @@ protected: the derivation IDs of endogenous, then the IDs of parameters */ map<pair<int,int>, map<vector<int>, expr_t>> params_derivatives; - //! Temporary terms for the static/dynamic file (those which will be noted T[x]) + //! Storage for temporary terms in block/bytecode mode temporary_terms_t temporary_terms; - //! Temporary terms for model local variables + //! Used model local variables, that will be treated as temporary terms + /*! See the comments in ModelTree::computeTemporaryTerms() */ map<expr_t, expr_t, ExprNodeLess> temporary_terms_mlv; //! Temporary terms for residuals and derivatives @@ -164,7 +165,7 @@ protected: //! Computes temporary terms for the file containing parameters derivatives void computeParamsDerivativesTemporaryTerms(); //! Writes temporary terms - void writeTemporaryTerms(const temporary_terms_t &tt, const temporary_terms_t &ttm1, const temporary_terms_idxs_t &tt_idxs, ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const; + void writeTemporaryTerms(const temporary_terms_t &tt, temporary_terms_t &temp_term_union, const temporary_terms_idxs_t &tt_idxs, ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const; void writeJsonTemporaryTerms(const temporary_terms_t &tt, const temporary_terms_t &ttm1, ostream &output, deriv_node_temp_terms_t &tef_terms, string &concat) const; //! Compiles temporary terms void compileTemporaryTerms(ostream &code_file, unsigned int &instruction_number, const temporary_terms_t &tt, map_idx_t map_idx, bool dynamic, bool steady_dynamic) const; @@ -174,7 +175,7 @@ protected: void fixNestedParenthesis(ostringstream &output, map<string, string> &tmp_paren_vars, bool &message_printed) const; //! Tests if string contains more than 32 nested parens, Issue #1201 bool testNestedParenthesis(const string &str) const; - void writeModelLocalVariableTemporaryTerms(const temporary_terms_t &tto, const map<expr_t, expr_t, ExprNodeLess> &tt, + void writeModelLocalVariableTemporaryTerms(temporary_terms_t &temp_term_union, ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const; //! Writes model equations diff --git a/src/StaticModel.cc b/src/StaticModel.cc index 9d6d52e00978a4ebd3ca2c13dfe16bebf0569e1e..20ab698210b0970b4b2bb5103f7f894fde42c159 100644 --- a/src/StaticModel.cc +++ b/src/StaticModel.cc @@ -1519,16 +1519,13 @@ StaticModel::writeStaticModel(const string &basename, deriv_node_temp_terms_t tef_terms; temporary_terms_t temp_term_union; - for (auto it : temporary_terms_mlv) - temp_term_union.insert(it.first); - writeModelLocalVariableTemporaryTerms(temp_term_union, temporary_terms_mlv, + writeModelLocalVariableTemporaryTerms(temp_term_union, model_tt_output, output_type, tef_terms); writeTemporaryTerms(temporary_terms_derivatives[0], temp_term_union, temporary_terms_idxs, model_tt_output, output_type, tef_terms); - temp_term_union.insert(temporary_terms_derivatives[0].begin(), temporary_terms_derivatives[0].end()); writeModelEquations(model_output, output_type, temp_term_union); @@ -1543,20 +1540,20 @@ StaticModel::writeStaticModel(const string &basename, temp_term_union, temporary_terms_idxs, jacobian_tt_output, output_type, tef_terms); - temp_term_union.insert(temporary_terms_derivatives[1].begin(), temporary_terms_derivatives[1].end()); - } - for (const auto & first_derivative : derivatives[1]) - { - int eq, var; - tie(eq, var) = vectorToTuple<2>(first_derivative.first); - expr_t d1 = first_derivative.second; - int symb_id = getSymbIDByDerivID(var); - jacobianHelper(jacobian_output, eq, symbol_table.getTypeSpecificID(symb_id), output_type); - jacobian_output << "="; - d1->writeOutput(jacobian_output, output_type, - temp_term_union, temporary_terms_idxs, tef_terms); - jacobian_output << ";" << endl; + for (const auto & first_derivative : derivatives[1]) + { + int eq, var; + tie(eq, var) = vectorToTuple<2>(first_derivative.first); + expr_t d1 = first_derivative.second; + int symb_id = getSymbIDByDerivID(var); + + jacobianHelper(jacobian_output, eq, symbol_table.getTypeSpecificID(symb_id), output_type); + jacobian_output << "="; + d1->writeOutput(jacobian_output, output_type, + temp_term_union, temporary_terms_idxs, tef_terms); + jacobian_output << ";" << endl; + } } int g2ncols = symbol_table.endo_nbr() * symbol_table.endo_nbr(); @@ -1567,7 +1564,6 @@ StaticModel::writeStaticModel(const string &basename, temp_term_union, temporary_terms_idxs, hessian_tt_output, output_type, tef_terms); - temp_term_union.insert(temporary_terms_derivatives[2].begin(), temporary_terms_derivatives[2].end()); int k = 0; // Keep the line of a 2nd derivative in v2 for (const auto & second_derivative : derivatives[2]) @@ -1638,7 +1634,6 @@ StaticModel::writeStaticModel(const string &basename, temp_term_union, temporary_terms_idxs, third_derivatives_tt_output, output_type, tef_terms); - temp_term_union.insert(temporary_terms_derivatives[3].begin(), temporary_terms_derivatives[3].end()); int k = 0; // Keep the line of a 3rd derivative in v3 for (const auto & third_derivative : derivatives[3]) @@ -2653,9 +2648,10 @@ StaticModel::writeParamsDerivativesFile(const string &basename, bool julia) cons ostringstream third_derivs_output; // Used for storing third order derivatives equations ostringstream third_derivs1_output; // Used for storing third order derivatives equations + temporary_terms_t temp_term_union; deriv_node_temp_terms_t tef_terms; - writeTemporaryTerms(params_derivs_temporary_terms, {}, params_derivs_temporary_terms_idxs, model_output, output_type, tef_terms); + writeTemporaryTerms(params_derivs_temporary_terms, temp_term_union, params_derivs_temporary_terms_idxs, tt_output, output_type, tef_terms); for (const auto & residuals_params_derivative : params_derivatives.find({ 0, 1 })->second) {