Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 4.6
  • 5.x
  • 6.x
  • aux_vars_fix
  • julia
  • llvm-15
  • master
  • python-codegen
  • rework_pac
  • uop
  • julia-6.2.0
  • julia-6.3.0
  • julia-6.4.0
  • julia-7.0.0
14 results

Target

Select target project
  • normann/preprocessor
  • Dynare/preprocessor
  • FerhatMihoubi/preprocessor
  • MichelJuillard/preprocessor
  • sebastien/preprocessor
  • lnsongxf/preprocessor
  • albop/preprocessor
  • DoraK/preprocessor
  • amg/preprocessor
  • wmutschl/preprocessor
  • JohannesPfeifer/preprocessor
11 results
Select Git revision
  • julia-6.3.0
  • julia-6.4.0
  • master
  • created_preprocessor_repo
4 results
Show changes
...@@ -49,7 +49,12 @@ NativeStatement::writeOutput(ostream& output, [[maybe_unused]] const string& bas ...@@ -49,7 +49,12 @@ NativeStatement::writeOutput(ostream& output, [[maybe_unused]] const string& bas
otherwise 2023M12 will be matched as 2023M1 (see dynare#1918). Technically, it seems that otherwise 2023M12 will be matched as 2023M1 (see dynare#1918). Technically, it seems that
boost::xpressive does not look for the longest match in an alternation, but stops at the first boost::xpressive does not look for the longest match in an alternation, but stops at the first
match from left to right. */ match from left to right. */
string date_regex = R"((-?\d+([YyAa]|[Mm](1[0-2]|[1-9])|[Qq][1-4]|[SsHh][1-2])))"; string date_regex = R"((-?\d+([YyAa]|[Mm](1[0-2]|[1-9])|[Qq][1-4]|[SsHh][12])))";
/* NB: the following dance around the dollar sign (exclude it from lookbehind, then use it in a
temporary string after the first replace, then remove it in the second replace) has a purpose:
it allows the user to disable the substitution mechanism. For example, if the user writes
“$2024Q4” in a native statement, it will be transformed into “2024Q4” and not
“$dates('2024Q4')”. */
sregex regex_lookbehind = sregex::compile(R"((?<!\$|\d|[a-zA-Z_]|-|'))" + date_regex); sregex regex_lookbehind = sregex::compile(R"((?<!\$|\d|[a-zA-Z_]|-|'))" + date_regex);
sregex regex_dollar = sregex::compile(R"((\$))" + date_regex); sregex regex_dollar = sregex::compile(R"((\$))" + date_regex);
......
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
#include "SymbolList.hh" #include "SymbolList.hh"
#include "WarningConsolidation.hh" #include "WarningConsolidation.hh"
// Helper constant for visitors
template<class>
inline constexpr bool always_false_v {false};
struct ModFileStructure struct ModFileStructure
{ {
//! Whether check is present //! Whether check is present
...@@ -169,8 +173,6 @@ struct ModFileStructure ...@@ -169,8 +173,6 @@ struct ModFileStructure
bool endval_learnt_in_present {false}; bool endval_learnt_in_present {false};
// Whether an occbin_constraints block appears // Whether an occbin_constraints block appears
bool occbin_constraints_present {false}; bool occbin_constraints_present {false};
// Whether a ramsey_constraints block appears
bool ramsey_constraints_present {false};
}; };
class Statement class Statement
...@@ -317,7 +319,8 @@ public: ...@@ -317,7 +319,8 @@ public:
/* Applies a variant visitor to the value of the option with that name. /* Applies a variant visitor to the value of the option with that name.
Throws UnknownOptionException if there is no option with that name. */ Throws UnknownOptionException if there is no option with that name. */
template<class Visitor> template<class Visitor>
requires invocable<Visitor, OptionValue> decltype(auto) requires invocable<Visitor, OptionValue>
decltype(auto)
visit(const string& name, Visitor&& vis) const visit(const string& name, Visitor&& vis) const
{ {
auto it = options.find(name); auto it = options.find(name);
...@@ -334,9 +337,6 @@ public: ...@@ -334,9 +337,6 @@ public:
private: private:
map<string, OptionValue> options; map<string, OptionValue> options;
void writeOutputCommon(ostream& output, const string& option_group) const; void writeOutputCommon(ostream& output, const string& option_group) const;
// Helper constant for visitors
template<class>
static constexpr bool always_false_v {false};
}; };
#endif #endif
/* /*
* Copyright © 2003-2024 Dynare Team * Copyright © 2003-2025 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <cstdlib> #include <cstdlib>
#include <iostream> #include <iostream>
#include <numeric> #include <numeric>
#include <ranges>
#include <sstream> #include <sstream>
#include <unordered_map> #include <unordered_map>
...@@ -30,8 +31,10 @@ ...@@ -30,8 +31,10 @@
#include "StaticModel.hh" #include "StaticModel.hh"
StaticModel::StaticModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg, StaticModel::StaticModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants_arg,
ExternalFunctionsTable& external_functions_table_arg) : ExternalFunctionsTable& external_functions_table_arg,
ModelTree {symbol_table_arg, num_constants_arg, external_functions_table_arg} HeterogeneityTable& heterogeneity_table_arg) :
ModelTree {symbol_table_arg, num_constants_arg, external_functions_table_arg,
heterogeneity_table_arg}
{ {
} }
...@@ -71,7 +74,7 @@ StaticModel::operator=(const StaticModel& m) ...@@ -71,7 +74,7 @@ StaticModel::operator=(const StaticModel& m)
} }
StaticModel::StaticModel(const DynamicModel& m) : StaticModel::StaticModel(const DynamicModel& m) :
ModelTree {m.symbol_table, m.num_constants, m.external_functions_table} ModelTree {m.symbol_table, m.num_constants, m.external_functions_table, m.heterogeneity_table}
{ {
// Convert model local variables (need to be done first) // Convert model local variables (need to be done first)
for (int it : m.local_variables_vector) for (int it : m.local_variables_vector)
...@@ -87,17 +90,18 @@ StaticModel::StaticModel(const DynamicModel& m) : ...@@ -87,17 +90,18 @@ StaticModel::StaticModel(const DynamicModel& m) :
if (dynamic_equations.contains(i)) if (dynamic_equations.contains(i))
{ {
auto [static_only_equations, static_only_equations_lineno, auto [static_only_equations, static_only_equations_lineno,
static_only_equations_equation_tags] static_only_complementarity_conditions, static_only_equations_equation_tags]
= m.getStaticOnlyEquationsInfo(); = m.getStaticOnlyEquationsInfo();
addEquation(static_only_equations[static_only_index]->toStatic(*this), addEquation(static_only_equations[static_only_index]->toStatic(*this),
static_only_equations_lineno[static_only_index], static_only_equations_lineno[static_only_index],
static_only_complementarity_conditions[static_only_index],
static_only_equations_equation_tags.getTagsByEqn(static_only_index)); static_only_equations_equation_tags.getTagsByEqn(static_only_index));
static_only_index++; static_only_index++;
} }
else else
addEquation(m.equations[i]->toStatic(*this), m.equations_lineno[i], addEquation(m.equations[i]->toStatic(*this), m.equations_lineno[i],
m.equation_tags.getTagsByEqn(i)); m.complementarity_conditions[i], m.equation_tags.getTagsByEqn(i));
} }
catch (DataTree::DivisionByZeroException) catch (DataTree::DivisionByZeroException)
{ {
...@@ -132,10 +136,8 @@ StaticModel::writeStaticBytecode(const string& basename) const ...@@ -132,10 +136,8 @@ StaticModel::writeStaticBytecode(const string& basename) const
int u_count_int {writeBytecodeBinFile(basename + "/model/bytecode/static.bin", false)}; int u_count_int {writeBytecodeBinFile(basename + "/model/bytecode/static.bin", false)};
Bytecode::Writer code_file {basename + "/model/bytecode/static.cod"}; Bytecode::Writer code_file {basename + "/model/bytecode/static.cod"};
vector<int> eq_idx(equations.size()); auto eq_idx = views::iota(0, static_cast<int>(equations.size()));
iota(eq_idx.begin(), eq_idx.end(), 0); auto endo_idx = views::iota(0, symbol_table.endo_nbr());
vector<int> endo_idx(symbol_table.endo_nbr());
iota(endo_idx.begin(), endo_idx.end(), 0);
// Declare temporary terms and the (single) block // Declare temporary terms and the (single) block
code_file << Bytecode::FDIMST {static_cast<int>(temporary_terms_derivatives[0].size() code_file << Bytecode::FDIMST {static_cast<int>(temporary_terms_derivatives[0].size()
...@@ -144,8 +146,8 @@ StaticModel::writeStaticBytecode(const string& basename) const ...@@ -144,8 +146,8 @@ StaticModel::writeStaticBytecode(const string& basename) const
BlockSimulationType::solveForwardComplete, BlockSimulationType::solveForwardComplete,
0, 0,
symbol_table.endo_nbr(), symbol_table.endo_nbr(),
endo_idx, {endo_idx.begin(), endo_idx.end()},
eq_idx, {eq_idx.begin(), eq_idx.end()},
false, false,
u_count_int, u_count_int,
symbol_table.endo_nbr()}; symbol_table.endo_nbr()};
...@@ -250,6 +252,8 @@ StaticModel::computingPass(int derivsOrder, int paramsDerivsOrder, ...@@ -250,6 +252,8 @@ StaticModel::computingPass(int derivsOrder, int paramsDerivsOrder,
<< endl; << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
computeMCPEquationsReordering();
} }
void void
...@@ -283,10 +287,6 @@ StaticModel::writeStaticFile(const string& basename, bool use_dll, const string& ...@@ -283,10 +287,6 @@ StaticModel::writeStaticFile(const string& basename, bool use_dll, const string&
} }
create_directories(model_dir / "bytecode" / "block"); create_directories(model_dir / "bytecode" / "block");
// Legacy representation
if (use_dll)
writeModelCFile<false>(basename, mexext, matlabroot);
/* PlannerObjective subclass or discretionary optimal policy models don’t /* PlannerObjective subclass or discretionary optimal policy models don’t
have as many variables as equations; bytecode does not support that have as many variables as equations; bytecode does not support that
case */ case */
...@@ -305,10 +305,13 @@ StaticModel::writeStaticFile(const string& basename, bool use_dll, const string& ...@@ -305,10 +305,13 @@ StaticModel::writeStaticFile(const string& basename, bool use_dll, const string&
writeSetAuxiliaryVariablesFile<false>(basename, julia); writeSetAuxiliaryVariablesFile<false>(basename, julia);
// Support for model debugging
if (!julia) if (!julia)
{
writeComplementarityConditionsFile<false>(basename);
// Support for model debugging
writeDebugModelMFiles<false>(basename); writeDebugModelMFiles<false>(basename);
} }
}
bool bool
StaticModel::exoPresentInEqs() const StaticModel::exoPresentInEqs() const
...@@ -330,7 +333,12 @@ StaticModel::writeDriverOutput(ostream& output) const ...@@ -330,7 +333,12 @@ StaticModel::writeDriverOutput(ostream& output) const
if (block_decomposed) if (block_decomposed)
writeBlockDriverOutput(output); writeBlockDriverOutput(output);
writeDriverSparseIndicesHelper<false, false>(output); writeDriverSparseIndicesHelper("static", output);
output << "M_.static_mcp_equations_reordering = [";
for (auto i : mcp_equations_reordering)
output << i + 1 << "; ";
output << "];" << endl;
} }
void void
...@@ -634,7 +642,7 @@ StaticModel::computeRamseyMultipliersDerivatives(int ramsey_orig_endo_nbr, bool ...@@ -634,7 +642,7 @@ StaticModel::computeRamseyMultipliersDerivatives(int ramsey_orig_endo_nbr, bool
Lagrange multiplier. We use the guarantee given by SymbolTable that Lagrange multiplier. We use the guarantee given by SymbolTable that
symbol IDs are increasing. */ symbol IDs are increasing. */
if (varexpr->symb_id > *mult_symb_ids.crbegin()) if (varexpr->symb_id > *mult_symb_ids.crbegin())
recursive_variables.emplace(getDerivID(varexpr->symb_id, 0), aux_eq); recursive_variables.emplace(varexpr->getDerivID(), aux_eq);
} }
// Compute the chain rule derivatives w.r.t. multipliers // Compute the chain rule derivatives w.r.t. multipliers
...@@ -658,7 +666,7 @@ StaticModel::computeRamseyMultipliersDerivatives(int ramsey_orig_endo_nbr, bool ...@@ -658,7 +666,7 @@ StaticModel::computeRamseyMultipliersDerivatives(int ramsey_orig_endo_nbr, bool
if (no_tmp_terms) if (no_tmp_terms)
for (auto& it : temp_terms_map) for (auto& it : temp_terms_map)
erase_if(it.second, [](expr_t e) { return !dynamic_cast<AbstractExternalFunctionNode*>(e); }); erase_if(it.second, [](expr_t e) { return !dynamic_cast<AbstractExternalFunctionNode*>(e); });
copy(temp_terms_map[{1, 0}].begin(), temp_terms_map[{1, 0}].end(), ranges::copy(temp_terms_map[{1, 0}],
inserter(ramsey_multipliers_derivatives_temporary_terms, inserter(ramsey_multipliers_derivatives_temporary_terms,
ramsey_multipliers_derivatives_temporary_terms.begin())); ramsey_multipliers_derivatives_temporary_terms.begin()));
for (int idx {0}; auto it : ramsey_multipliers_derivatives_temporary_terms) for (int idx {0}; auto it : ramsey_multipliers_derivatives_temporary_terms)
...@@ -704,12 +712,7 @@ StaticModel::writeRamseyMultipliersDerivativesMFile(const string& basename, ...@@ -704,12 +712,7 @@ StaticModel::writeRamseyMultipliersDerivativesMFile(const string& basename,
writeRamseyMultipliersDerivativesHelper<output_type>(output_file); writeRamseyMultipliersDerivativesHelper<output_type>(output_file);
// On MATLAB < R2020a, sparse() does not accept int32 indices output_file << "g1m = sparse(sparse_rowval, sparse_colval, g1m_v, " << ramsey_orig_endo_nbr
output_file << "if ~isoctave && matlab_ver_less_than('9.8')" << endl
<< " sparse_rowval = double(sparse_rowval);" << endl
<< " sparse_colval = double(sparse_colval);" << endl
<< "end" << endl
<< "g1m = sparse(sparse_rowval, sparse_colval, g1m_v, " << ramsey_orig_endo_nbr
<< ", " << symbol_table.getLagrangeMultipliers().size() << ");" << endl << ", " << symbol_table.getLagrangeMultipliers().size() << ");" << endl
<< "end" << endl; << "end" << endl;
output_file.close(); output_file.close();
......
...@@ -121,7 +121,8 @@ protected: ...@@ -121,7 +121,8 @@ protected:
public: public:
StaticModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants, StaticModel(SymbolTable& symbol_table_arg, NumericalConstants& num_constants,
ExternalFunctionsTable& external_functions_table_arg); ExternalFunctionsTable& external_functions_table_arg,
HeterogeneityTable& heterogeneity_table_arg);
StaticModel(const StaticModel& m); StaticModel(const StaticModel& m);
StaticModel& operator=(const StaticModel& m); StaticModel& operator=(const StaticModel& m);
......
/* /*
* Copyright © 2018-2023 Dynare Team * Copyright © 2018-2025 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -58,8 +58,7 @@ TrendComponentModelTable::setVals(map<string, vector<int>> eqnums_arg, ...@@ -58,8 +58,7 @@ TrendComponentModelTable::setVals(map<string, vector<int>> eqnums_arg,
{ {
vector<int> nontrend_vec; vector<int> nontrend_vec;
for (auto eq : it.second) for (auto eq : it.second)
if (find(target_eqnums[it.first].begin(), target_eqnums[it.first].end(), eq) if (ranges::find(target_eqnums[it.first], eq) == target_eqnums[it.first].end())
== target_eqnums[it.first].end())
nontrend_vec.push_back(eq); nontrend_vec.push_back(eq);
nontarget_eqnums[it.first] = nontrend_vec; nontarget_eqnums[it.first] = nontrend_vec;
} }
...@@ -71,12 +70,12 @@ TrendComponentModelTable::setVals(map<string, vector<int>> eqnums_arg, ...@@ -71,12 +70,12 @@ TrendComponentModelTable::setVals(map<string, vector<int>> eqnums_arg,
vector<int> eqnumsv = getEqNums(name); vector<int> eqnumsv = getEqNums(name);
for (int nontrend_it : getNonTargetEqNums(name)) for (int nontrend_it : getNonTargetEqNums(name))
nontarget_lhs_vec.push_back( nontarget_lhs_vec.push_back(
lhsv.at(distance(eqnumsv.begin(), find(eqnumsv.begin(), eqnumsv.end(), nontrend_it)))); lhsv.at(ranges::distance(eqnumsv.begin(), ranges::find(eqnumsv, nontrend_it))));
nontarget_lhs[name] = nontarget_lhs_vec; nontarget_lhs[name] = nontarget_lhs_vec;
for (int trend_it : getTargetEqNums(name)) for (int trend_it : getTargetEqNums(name))
target_lhs_vec.push_back( target_lhs_vec.push_back(
lhsv.at(distance(eqnumsv.begin(), find(eqnumsv.begin(), eqnumsv.end(), trend_it)))); lhsv.at(ranges::distance(eqnumsv.begin(), ranges::find(eqnumsv, trend_it))));
target_lhs[name] = target_lhs_vec; target_lhs[name] = target_lhs_vec;
} }
} }
...@@ -274,8 +273,7 @@ TrendComponentModelTable::writeOutput(const string& basename, ostream& output) c ...@@ -274,8 +273,7 @@ TrendComponentModelTable::writeOutput(const string& basename, ostream& output) c
output << it + 1 << " "; output << it + 1 << " ";
output << "];" << endl << "M_.trend_component." << name << ".targets = ["; output << "];" << endl << "M_.trend_component." << name << ".targets = [";
for (auto it : eqnums.at(name)) for (auto it : eqnums.at(name))
if (find(target_eqnums.at(name).begin(), target_eqnums.at(name).end(), it) if (ranges::find(target_eqnums.at(name), it) == target_eqnums.at(name).end())
== target_eqnums.at(name).end())
output << "false "; output << "false ";
else else
output << "true "; output << "true ";
...@@ -322,8 +320,7 @@ TrendComponentModelTable::writeOutput(const string& basename, ostream& output) c ...@@ -322,8 +320,7 @@ TrendComponentModelTable::writeOutput(const string& basename, ostream& output) c
vector<string> eqtags_vec = eqtags.at(name); vector<string> eqtags_vec = eqtags.at(name);
output << "M_.trend_component." << name << ".target_eqn = ["; output << "M_.trend_component." << name << ".target_eqn = [";
for (const auto& it : target_eqtags_vec) for (const auto& it : target_eqtags_vec)
output << distance(eqtags_vec.begin(), find(eqtags_vec.begin(), eqtags_vec.end(), it)) + 1 output << ranges::distance(eqtags_vec.begin(), ranges::find(eqtags_vec, it)) + 1 << " ";
<< " ";
output << "];" << endl; output << "];" << endl;
vector<int> target_lhs_vec = getTargetLhs(name); vector<int> target_lhs_vec = getTargetLhs(name);
...@@ -336,9 +333,8 @@ TrendComponentModelTable::writeOutput(const string& basename, ostream& output) c ...@@ -336,9 +333,8 @@ TrendComponentModelTable::writeOutput(const string& basename, ostream& output) c
for (const auto& [key, expr] : AR.at(name)) for (const auto& [key, expr] : AR.at(name))
{ {
auto [eqn, lag, lhs_symb_id] = key; auto [eqn, lag, lhs_symb_id] = key;
int colidx = static_cast<int>( int colidx = static_cast<int>(ranges::distance(
distance(nontarget_lhs_vec.begin(), nontarget_lhs_vec.begin(), ranges::find(nontarget_lhs_vec, lhs_symb_id)));
find(nontarget_lhs_vec.begin(), nontarget_lhs_vec.end(), lhs_symb_id)));
ar_ec_output << " AR(" << eqn + 1 << ", " << colidx + 1 << ", " << lag << ") = "; ar_ec_output << " AR(" << eqn + 1 << ", " << colidx + 1 << ", " << lag << ") = ";
expr->writeOutput(ar_ec_output, ExprNodeOutputType::matlabDynamicModel); expr->writeOutput(ar_ec_output, ExprNodeOutputType::matlabDynamicModel);
ar_ec_output << ";" << endl; ar_ec_output << ";" << endl;
...@@ -488,7 +484,7 @@ VarModelTable::writeOutput(const string& basename, ostream& output) const ...@@ -488,7 +484,7 @@ VarModelTable::writeOutput(const string& basename, ostream& output) const
{ {
auto [eqn, lag, lhs_symb_id] = key; auto [eqn, lag, lhs_symb_id] = key;
int colidx int colidx
= static_cast<int>(distance(lhs.begin(), find(lhs.begin(), lhs.end(), lhs_symb_id))); = static_cast<int>(ranges::distance(lhs.begin(), ranges::find(lhs, lhs_symb_id)));
ar_output << " ar(" << eqn + 1 << "," << colidx + 1 << "," << lag << ") = "; ar_output << " ar(" << eqn + 1 << "," << colidx + 1 << "," << lag << ") = ";
expr->writeOutput(ar_output, ExprNodeOutputType::matlabDynamicModel); expr->writeOutput(ar_output, ExprNodeOutputType::matlabDynamicModel);
ar_output << ";" << endl; ar_output << ";" << endl;
...@@ -498,7 +494,7 @@ VarModelTable::writeOutput(const string& basename, ostream& output) const ...@@ -498,7 +494,7 @@ VarModelTable::writeOutput(const string& basename, ostream& output) const
{ {
auto [eqn, lhs_symb_id] = key; auto [eqn, lhs_symb_id] = key;
int colidx int colidx
= static_cast<int>(distance(lhs.begin(), find(lhs.begin(), lhs.end(), lhs_symb_id))); = static_cast<int>(ranges::distance(lhs.begin(), ranges::find(lhs, lhs_symb_id)));
if (eqn != colidx) if (eqn != colidx)
{ {
ar_output << " a0(" << eqn + 1 << "," << colidx + 1 << ") = "; ar_output << " a0(" << eqn + 1 << "," << colidx + 1 << ") = ";
...@@ -803,9 +799,8 @@ VarExpectationModelTable::writeOutput(ostream& output) const ...@@ -803,9 +799,8 @@ VarExpectationModelTable::writeOutput(ostream& output) const
<< mstruct << ".expr.constants = [ " << constants_list.str() << " ];" << endl; << mstruct << ".expr.constants = [ " << constants_list.str() << " ];" << endl;
if (auto disc_var = dynamic_cast<const VariableNode*>(discount.at(name)); disc_var) if (auto disc_var = dynamic_cast<const VariableNode*>(discount.at(name)); disc_var)
output << mstruct output << mstruct << ".discount_index = " << disc_var->getTypeSpecificID() + 1 << ';'
<< ".discount_index = " << symbol_table.getTypeSpecificID(disc_var->symb_id) + 1 << endl;
<< ';' << endl;
else else
{ {
output << mstruct << ".discount_value = "; output << mstruct << ".discount_value = ";
...@@ -1285,8 +1280,8 @@ PacModelTable::transformPass(const lag_equivalence_table_t& unary_ops_nodes, ...@@ -1285,8 +1280,8 @@ PacModelTable::transformPass(const lag_equivalence_table_t& unary_ops_nodes,
// Associate the coefficients of the linear combination with the right components // Associate the coefficients of the linear combination with the right components
for (auto [var, coeff] : terms) for (auto [var, coeff] : terms)
if (auto it = find_if( if (auto it = ranges::find_if(
components.begin(), components.end(), components,
[&](const auto& v) { return get<0>(v) == dynamic_model.AddVariable(var); }); [&](const auto& v) { return get<0>(v) == dynamic_model.AddVariable(var); });
it != components.end()) it != components.end())
get<4>(*it) = coeff; get<4>(*it) = coeff;
...@@ -1384,11 +1379,11 @@ PacModelTable::transformPass(const lag_equivalence_table_t& unary_ops_nodes, ...@@ -1384,11 +1379,11 @@ PacModelTable::transformPass(const lag_equivalence_table_t& unary_ops_nodes,
{ {
if (target_info.contains(name)) if (target_info.contains(name))
{ {
cerr << "ERROR: the block 'pac_target_info(" << name assert(growth_correction_term == dynamic_model.Zero);
<< ")' is not supported in the context of a PAC model with model-consistent " dynamic_model.computePacModelConsistentExpectationSubstitutionWithComponents(
"expectations (MCE)." name, symbol_table.getID(discount[name]), pacEquationMaxLag(name),
<< endl; diff_subst_table, aux_param_symb_ids, get<2>(target_info[name]),
exit(EXIT_FAILURE); pac_expectation_substitution);
} }
else else
dynamic_model.computePacModelConsistentExpectationSubstitution( dynamic_model.computePacModelConsistentExpectationSubstitution(
...@@ -1507,7 +1502,7 @@ PacModelTable::writeOutput(ostream& output) const ...@@ -1507,7 +1502,7 @@ PacModelTable::writeOutput(ostream& output) const
// Write the auxiliary variable IDs created for the pac_expectation operator // Write the auxiliary variable IDs created for the pac_expectation operator
for (auto& [name, id] : aux_var_symb_ids) for (auto& [name, id] : aux_var_symb_ids)
output << "M_.pac." << name << "." << (aux_model_name.at(name).empty() ? "mce.z1" : "aux_id") output << "M_.pac." << name << "." << (aux_model_name.at(name).empty() ? "mce.z" : "aux_id")
<< " = " << symbol_table.getTypeSpecificID(id) + 1 << ";" << endl; << " = " << symbol_table.getTypeSpecificID(id) + 1 << ";" << endl;
// Write PAC equation name info // Write PAC equation name info
...@@ -1687,9 +1682,8 @@ PacModelTable::writeOutput(ostream& output) const ...@@ -1687,9 +1682,8 @@ PacModelTable::writeOutput(ostream& output) const
string fieldname = "M_.pac." + name + ".components(" + to_string(component_idx) + ")"; string fieldname = "M_.pac." + name + ".components(" + to_string(component_idx) + ")";
output << fieldname << ".aux_id = " << symbol_table.getTypeSpecificID(auxname) + 1 << ";" output << fieldname << ".aux_id = " << symbol_table.getTypeSpecificID(auxname) + 1 << ";"
<< endl << endl
<< fieldname << ".endo_var = " << fieldname
<< symbol_table.getTypeSpecificID(dynamic_cast<VariableNode*>(component)->symb_id) << ".endo_var = " << dynamic_cast<VariableNode*>(component)->getTypeSpecificID() + 1
+ 1
<< ";" << endl << ";" << endl
<< fieldname << ".kind = '" << kindToString(kind) << "';" << endl << fieldname << ".kind = '" << kindToString(kind) << "';" << endl
<< fieldname << ".h_param_indices = ["; << fieldname << ".h_param_indices = [";
...@@ -1709,6 +1703,21 @@ PacModelTable::writeOutput(ostream& output) const ...@@ -1709,6 +1703,21 @@ PacModelTable::writeOutput(ostream& output) const
} }
component_idx++; component_idx++;
} }
for (auto& [name, val] : target_info)
if (aux_model_name.at(name).empty())
{
string pac_model_name = "M_.pac." + name + ".mce.";
output << pac_model_name << "z = NaN(" << get<2>(val).size() << ",1);" << endl;
for (int component_idx {1};
auto& [component, growth_component, auxname, kind, coeff, growth_neutrality_param,
h_indices, original_growth_component, growth_component_info] : get<2>(val))
{
output << pac_model_name << "z(" << component_idx
<< ") = " << symbol_table.getTypeSpecificID(auxname) + 1 << ";" << endl;
component_idx++;
}
}
} }
void void
......
/* /*
* Copyright © 2003-2022 Dynare Team * Copyright © 2003-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -57,7 +57,7 @@ SymbolList::checkPass(WarningConsolidation& warnings, const vector<SymbolType>& ...@@ -57,7 +57,7 @@ SymbolList::checkPass(WarningConsolidation& warnings, const vector<SymbolType>&
throw SymbolListException {"Variable " + symbol + " was not declared."}; throw SymbolListException {"Variable " + symbol + " was not declared."};
} }
if (none_of(types.begin(), types.end(), if (ranges::none_of(types,
[&](SymbolType type) { return symbol_table.getType(symbol) == type; })) [&](SymbolType type) { return symbol_table.getType(symbol) == type; }))
{ {
string valid_types; string valid_types;
...@@ -103,6 +103,15 @@ SymbolList::checkPass(WarningConsolidation& warnings, const vector<SymbolType>& ...@@ -103,6 +103,15 @@ SymbolList::checkPass(WarningConsolidation& warnings, const vector<SymbolType>&
case SymbolType::excludedVariable: case SymbolType::excludedVariable:
valid_types += "excludedVariable, "; valid_types += "excludedVariable, ";
break; break;
case SymbolType::heterogeneousEndogenous:
valid_types += "heterogeneousEndogenous, ";
break;
case SymbolType::heterogeneousExogenous:
valid_types += "heterogeneousExogenous, ";
break;
case SymbolType::heterogeneousParameter:
valid_types += "heterogeneousParameter, ";
break;
} }
valid_types = valid_types.erase(valid_types.size() - 2, 2); valid_types = valid_types.erase(valid_types.size() - 2, 2);
throw SymbolListException {"Variable " + symbol + " is not one of {" + valid_types + "}"}; throw SymbolListException {"Variable " + symbol + " is not one of {" + valid_types + "}"};
......
...@@ -63,7 +63,7 @@ public: ...@@ -63,7 +63,7 @@ public:
empty() const empty() const
{ {
return symbols.empty(); return symbols.empty();
}; }
//! Return the list of symbols //! Return the list of symbols
[[nodiscard]] vector<string> getSymbols() const; [[nodiscard]] vector<string> getSymbols() const;
}; };
......
/* /*
* Copyright © 2003-2023 Dynare Team * Copyright © 2003-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -31,7 +31,8 @@ ...@@ -31,7 +31,8 @@
int int
SymbolTable::addSymbol(const string& name, SymbolType type, const string& tex_name, SymbolTable::addSymbol(const string& name, SymbolType type, const string& tex_name,
const vector<pair<string, string>>& partition_value) noexcept(false) const vector<pair<string, string>>& partition_value,
const optional<int>& heterogeneity_dimension) noexcept(false)
{ {
if (frozen) if (frozen)
throw FrozenException(); throw FrozenException();
...@@ -78,13 +79,20 @@ SymbolTable::addSymbol(const string& name, SymbolType type, const string& tex_na ...@@ -78,13 +79,20 @@ SymbolTable::addSymbol(const string& name, SymbolType type, const string& tex_na
pmv[it.first] = it.second; pmv[it.first] = it.second;
partition_value_map[id] = pmv; partition_value_map[id] = pmv;
} }
assert(!isHeterogeneous(type)
|| (heterogeneity_dimension.has_value() && *heterogeneity_dimension >= 0
&& *heterogeneity_dimension < heterogeneity_table.size()));
if (isHeterogeneous(type))
heterogeneity_dimensions.emplace(id, *heterogeneity_dimension);
return id; return id;
} }
int int
SymbolTable::addSymbol(const string& name, SymbolType type) noexcept(false) SymbolTable::addSymbol(const string& name, SymbolType type) noexcept(false)
{ {
return addSymbol(name, type, "", {}); return addSymbol(name, type, "", {}, {});
} }
void void
...@@ -95,6 +103,10 @@ SymbolTable::freeze() noexcept(false) ...@@ -95,6 +103,10 @@ SymbolTable::freeze() noexcept(false)
frozen = true; frozen = true;
het_endo_ids.resize(heterogeneity_table.size());
het_exo_ids.resize(heterogeneity_table.size());
het_param_ids.resize(heterogeneity_table.size());
for (int i = 0; i < static_cast<int>(symbol_table.size()); i++) for (int i = 0; i < static_cast<int>(symbol_table.size()); i++)
{ {
int tsi; int tsi;
...@@ -116,6 +128,18 @@ SymbolTable::freeze() noexcept(false) ...@@ -116,6 +128,18 @@ SymbolTable::freeze() noexcept(false)
tsi = param_ids.size(); tsi = param_ids.size();
param_ids.push_back(i); param_ids.push_back(i);
break; break;
case SymbolType::heterogeneousEndogenous:
tsi = het_endo_ids.at(heterogeneity_dimensions.at(i)).size();
het_endo_ids.at(heterogeneity_dimensions.at(i)).push_back(i);
break;
case SymbolType::heterogeneousExogenous:
tsi = het_exo_ids.at(heterogeneity_dimensions.at(i)).size();
het_exo_ids.at(heterogeneity_dimensions.at(i)).push_back(i);
break;
case SymbolType::heterogeneousParameter:
tsi = het_param_ids.at(heterogeneity_dimensions.at(i)).size();
het_param_ids.at(heterogeneity_dimensions.at(i)).push_back(i);
break;
default: default:
continue; continue;
} }
...@@ -131,12 +155,18 @@ SymbolTable::unfreeze() ...@@ -131,12 +155,18 @@ SymbolTable::unfreeze()
exo_ids.clear(); exo_ids.clear();
exo_det_ids.clear(); exo_det_ids.clear();
param_ids.clear(); param_ids.clear();
het_endo_ids.clear();
het_exo_ids.clear();
het_param_ids.clear();
type_specific_ids.clear(); type_specific_ids.clear();
} }
void void
SymbolTable::changeType(int id, SymbolType newtype) noexcept(false) SymbolTable::changeType(int id, SymbolType newtype) noexcept(false)
{ {
// FIXME: implement switch to heterogeneous variable; dimension will have to be provided
assert(!isHeterogeneous(newtype));
if (frozen) if (frozen)
throw FrozenException(); throw FrozenException();
...@@ -146,7 +176,8 @@ SymbolTable::changeType(int id, SymbolType newtype) noexcept(false) ...@@ -146,7 +176,8 @@ SymbolTable::changeType(int id, SymbolType newtype) noexcept(false)
} }
int int
SymbolTable::getID(SymbolType type, int tsid) const noexcept(false) SymbolTable::getID(SymbolType type, int tsid, const optional<int>& heterogeneity_dimension) const
noexcept(false)
{ {
if (!frozen) if (!frozen)
throw NotYetFrozenException(); throw NotYetFrozenException();
...@@ -155,26 +186,44 @@ SymbolTable::getID(SymbolType type, int tsid) const noexcept(false) ...@@ -155,26 +186,44 @@ SymbolTable::getID(SymbolType type, int tsid) const noexcept(false)
{ {
case SymbolType::endogenous: case SymbolType::endogenous:
if (tsid < 0 || tsid >= static_cast<int>(endo_ids.size())) if (tsid < 0 || tsid >= static_cast<int>(endo_ids.size()))
throw UnknownTypeSpecificIDException {tsid, type}; throw UnknownTypeSpecificIDException {tsid, type, {}};
else else
return endo_ids[tsid]; return endo_ids[tsid];
case SymbolType::exogenous: case SymbolType::exogenous:
if (tsid < 0 || tsid >= static_cast<int>(exo_ids.size())) if (tsid < 0 || tsid >= static_cast<int>(exo_ids.size()))
throw UnknownTypeSpecificIDException {tsid, type}; throw UnknownTypeSpecificIDException {tsid, type, {}};
else else
return exo_ids[tsid]; return exo_ids[tsid];
case SymbolType::exogenousDet: case SymbolType::exogenousDet:
if (tsid < 0 || tsid >= static_cast<int>(exo_det_ids.size())) if (tsid < 0 || tsid >= static_cast<int>(exo_det_ids.size()))
throw UnknownTypeSpecificIDException {tsid, type}; throw UnknownTypeSpecificIDException {tsid, type, {}};
else else
return exo_det_ids[tsid]; return exo_det_ids[tsid];
case SymbolType::parameter: case SymbolType::parameter:
if (tsid < 0 || tsid >= static_cast<int>(param_ids.size())) if (tsid < 0 || tsid >= static_cast<int>(param_ids.size()))
throw UnknownTypeSpecificIDException {tsid, type}; throw UnknownTypeSpecificIDException {tsid, type, {}};
else else
return param_ids[tsid]; return param_ids[tsid];
case SymbolType::heterogeneousEndogenous:
assert(heterogeneity_dimension.has_value());
if (tsid < 0 || tsid >= static_cast<int>(het_endo_ids.at(*heterogeneity_dimension).size()))
throw UnknownTypeSpecificIDException {tsid, type, *heterogeneity_dimension};
else
return het_endo_ids.at(*heterogeneity_dimension).at(tsid);
case SymbolType::heterogeneousExogenous:
assert(heterogeneity_dimension.has_value());
if (tsid < 0 || tsid >= static_cast<int>(het_exo_ids.at(*heterogeneity_dimension).size()))
throw UnknownTypeSpecificIDException {tsid, type, *heterogeneity_dimension};
else
return het_exo_ids.at(*heterogeneity_dimension).at(tsid);
case SymbolType::heterogeneousParameter:
assert(heterogeneity_dimension.has_value());
if (tsid < 0 || tsid >= static_cast<int>(het_param_ids.at(*heterogeneity_dimension).size()))
throw UnknownTypeSpecificIDException {tsid, type, *heterogeneity_dimension};
else
return het_param_ids.at(*heterogeneity_dimension).at(tsid);
default: default:
throw UnknownTypeSpecificIDException {tsid, type}; throw UnknownTypeSpecificIDException {tsid, type, {}};
} }
} }
...@@ -348,6 +397,8 @@ SymbolTable::writeOutput(ostream& output) const noexcept(false) ...@@ -348,6 +397,8 @@ SymbolTable::writeOutput(ostream& output) const noexcept(false)
case AuxVarType::expectation: case AuxVarType::expectation:
case AuxVarType::pacExpectation: case AuxVarType::pacExpectation:
case AuxVarType::pacTargetNonstationary: case AuxVarType::pacTargetNonstationary:
case AuxVarType::aggregationOp:
case AuxVarType::heterogeneousMultiplier:
break; break;
case AuxVarType::endoLag: case AuxVarType::endoLag:
case AuxVarType::exoLag: case AuxVarType::exoLag:
...@@ -419,6 +470,54 @@ SymbolTable::writeOutput(ostream& output) const noexcept(false) ...@@ -419,6 +470,54 @@ SymbolTable::writeOutput(ostream& output) const noexcept(false)
output << getTypeSpecificID(varexob) + 1 << " "; output << getTypeSpecificID(varexob) + 1 << " ";
output << " ];" << endl; output << " ];" << endl;
} }
// Heterogeneous symbols
// FIXME: the following helper could be used to simplify non-heterogenous variables
auto print_symb_names = [this, &output](const string& field, const auto& symb_ids) {
auto helper = [this, &output, &symb_ids](auto nameMethod) {
for (bool first_printed {false}; int symb_id : symb_ids)
{
if (exchange(first_printed, true))
output << "; ";
output << "'" << (this->*nameMethod)(symb_id) << "'";
}
};
output << field << " = {";
helper(&SymbolTable::getName);
output << "};" << endl << field << "_tex = {";
helper(&SymbolTable::getTeXName);
output << "};" << endl << field << "_long = {";
helper(&SymbolTable::getLongName);
output << "};" << endl;
};
for (int het_dim {0}; het_dim < heterogeneity_table.size(); het_dim++)
{
const string basefield {"M_.heterogeneity(" + to_string(het_dim + 1) + ")."};
output << basefield << "endo_nbr = " << het_endo_nbr(het_dim) << ";" << endl;
print_symb_names(basefield + "endo_names", het_endo_ids.at(het_dim));
output << basefield << "orig_endo_nbr = " << het_orig_endo_nbr(het_dim) << ";" << endl;
output << basefield << "exo_nbr = " << het_exo_nbr(het_dim) << ";" << endl;
print_symb_names(basefield + "exo_names", het_exo_ids.at(het_dim));
output << basefield << "param_nbr = " << het_param_nbr(het_dim) << ";" << endl;
print_symb_names(basefield + "param_names", het_param_ids.at(het_dim));
const vector<AuxVarInfo>& hav = het_aux_vars[het_dim];
if (hav.size() == 0)
output << basefield << "aux_vars = [];";
else
for (int i = 0; i < static_cast<int>(hav.size()); i++)
{
output << basefield << "aux_vars(" << i + 1
<< ").endo_index = " << getTypeSpecificID(hav[i].symb_id) + 1 << ";" << endl
<< basefield << "aux_vars(" << i + 1 << ").type = " << hav[i].get_type_id()
<< ";" << basefield << "aux_vars(" << i + 1
<< ").eq_nbr = " << hav[i].equation_number_for_multiplier + 1 << ";" << endl;
}
}
} }
int int
...@@ -630,6 +729,27 @@ SymbolTable::addUnaryOpAuxiliaryVar(int index, expr_t expr_arg, string unary_op, ...@@ -630,6 +729,27 @@ SymbolTable::addUnaryOpAuxiliaryVar(int index, expr_t expr_arg, string unary_op,
return symb_id; return symb_id;
} }
int
SymbolTable::addHeterogeneousMultiplierAuxiliaryVar(int het_dim, int index,
const string& varname) noexcept(false)
{
int symb_id;
try
{
symb_id = addSymbol(varname, SymbolType::heterogeneousEndogenous, "", {}, het_dim);
}
catch (AlreadyDeclaredException& e)
{
cerr << "ERROR: you should rename your variable called " << varname
<< ", this name is internally used by Dynare" << endl;
exit(EXIT_FAILURE);
}
het_aux_vars[het_dim].emplace_back(symb_id, AuxVarType::heterogeneousMultiplier, 0, 0, index, 0,
nullptr, "");
return symb_id;
}
int int
SymbolTable::addMultiplierAuxiliaryVar(int index) noexcept(false) SymbolTable::addMultiplierAuxiliaryVar(int index) noexcept(false)
{ {
...@@ -714,6 +834,28 @@ SymbolTable::addPacTargetNonstationaryAuxiliaryVar(const string& name, expr_t ex ...@@ -714,6 +834,28 @@ SymbolTable::addPacTargetNonstationaryAuxiliaryVar(const string& name, expr_t ex
return symb_id; return symb_id;
} }
int
SymbolTable::addAggregationOpAuxiliaryVar(const string& name, expr_t expr_arg)
{
int symb_id {[&] {
try
{
return addSymbol(name, SymbolType::endogenous);
}
catch (AlreadyDeclaredException&)
{
cerr << "ERROR: the variable/parameter '" << name
<< "' conflicts with a variable that will be generated for an aggregation operator. "
"Please rename it."
<< endl;
exit(EXIT_FAILURE);
}
}()};
aux_vars.emplace_back(symb_id, AuxVarType::aggregationOp, 0, 0, 0, 0, expr_arg, "");
return symb_id;
}
int int
SymbolTable::searchAuxiliaryVars(int orig_symb_id, int orig_lead_lag) const noexcept(false) SymbolTable::searchAuxiliaryVars(int orig_symb_id, int orig_lead_lag) const noexcept(false)
{ {
...@@ -812,13 +954,13 @@ SymbolTable::observedVariablesNbr() const ...@@ -812,13 +954,13 @@ SymbolTable::observedVariablesNbr() const
bool bool
SymbolTable::isObservedVariable(int symb_id) const SymbolTable::isObservedVariable(int symb_id) const
{ {
return find(varobs.begin(), varobs.end(), symb_id) != varobs.end(); return ranges::find(varobs, symb_id) != varobs.end();
} }
int int
SymbolTable::getObservedVariableIndex(int symb_id) const SymbolTable::getObservedVariableIndex(int symb_id) const
{ {
auto it = find(varobs.begin(), varobs.end(), symb_id); auto it = ranges::find(varobs, symb_id);
assert(it != varobs.end()); assert(it != varobs.end());
return static_cast<int>(it - varobs.begin()); return static_cast<int>(it - varobs.begin());
} }
...@@ -827,7 +969,7 @@ void ...@@ -827,7 +969,7 @@ void
SymbolTable::addObservedExogenousVariable(int symb_id) noexcept(false) SymbolTable::addObservedExogenousVariable(int symb_id) noexcept(false)
{ {
validateSymbID(symb_id); validateSymbID(symb_id);
assert(getType(symb_id) != SymbolType::endogenous); assert(getType(symb_id) == SymbolType::exogenous);
varexobs.push_back(symb_id); varexobs.push_back(symb_id);
} }
...@@ -840,13 +982,13 @@ SymbolTable::observedExogenousVariablesNbr() const ...@@ -840,13 +982,13 @@ SymbolTable::observedExogenousVariablesNbr() const
bool bool
SymbolTable::isObservedExogenousVariable(int symb_id) const SymbolTable::isObservedExogenousVariable(int symb_id) const
{ {
return find(varexobs.begin(), varexobs.end(), symb_id) != varexobs.end(); return ranges::find(varexobs, symb_id) != varexobs.end();
} }
int int
SymbolTable::getObservedExogenousVariableIndex(int symb_id) const SymbolTable::getObservedExogenousVariableIndex(int symb_id) const
{ {
auto it = find(varexobs.begin(), varexobs.end(), symb_id); auto it = ranges::find(varexobs, symb_id);
assert(it != varexobs.end()); assert(it != varexobs.end());
return static_cast<int>(it - varexobs.begin()); return static_cast<int>(it - varexobs.begin());
} }
...@@ -895,14 +1037,13 @@ SymbolTable::getEndogenous() const ...@@ -895,14 +1037,13 @@ SymbolTable::getEndogenous() const
bool bool
SymbolTable::isAuxiliaryVariable(int symb_id) const SymbolTable::isAuxiliaryVariable(int symb_id) const
{ {
return any_of(aux_vars.begin(), aux_vars.end(), return ranges::any_of(aux_vars, [=](const auto& av) { return av.symb_id == symb_id; });
[=](const auto& av) { return av.symb_id == symb_id; });
} }
bool bool
SymbolTable::isDiffAuxiliaryVariable(int symb_id) const SymbolTable::isDiffAuxiliaryVariable(int symb_id) const
{ {
return any_of(aux_vars.begin(), aux_vars.end(), [=](const auto& av) { return ranges::any_of(aux_vars, [=](const auto& av) {
return av.symb_id == symb_id return av.symb_id == symb_id
&& (av.type == AuxVarType::diff || av.type == AuxVarType::diffLag && (av.type == AuxVarType::diff || av.type == AuxVarType::diffLag
|| av.type == AuxVarType::diffLead); || av.type == AuxVarType::diffLead);
...@@ -995,6 +1136,8 @@ SymbolTable::writeJsonOutput(ostream& output) const ...@@ -995,6 +1136,8 @@ SymbolTable::writeJsonOutput(ostream& output) const
case AuxVarType::expectation: case AuxVarType::expectation:
case AuxVarType::pacExpectation: case AuxVarType::pacExpectation:
case AuxVarType::pacTargetNonstationary: case AuxVarType::pacTargetNonstationary:
case AuxVarType::aggregationOp:
case AuxVarType::heterogeneousMultiplier:
break; break;
case AuxVarType::endoLag: case AuxVarType::endoLag:
case AuxVarType::exoLag: case AuxVarType::exoLag:
...@@ -1029,6 +1172,25 @@ SymbolTable::writeJsonOutput(ostream& output) const ...@@ -1029,6 +1172,25 @@ SymbolTable::writeJsonOutput(ostream& output) const
} }
output << "]" << endl; output << "]" << endl;
} }
if (!heterogeneity_table.empty())
{
output << R"(, "heterogeneous_symbols": [)";
for (int i {0}; i < heterogeneity_table.size(); i++)
{
if (i != 0)
output << ", ";
output << R"({ "dimension": ")" << heterogeneity_table.getName(i)
<< R"(", "endogenous": )";
writeJsonVarVector(output, het_endo_ids.at(i));
output << R"(, "exogenous": )";
writeJsonVarVector(output, het_exo_ids.at(i));
output << R"(, "parameters": )";
writeJsonVarVector(output, het_param_ids.at(i));
output << "}";
}
output << "]" << endl;
}
} }
void void
...@@ -1088,3 +1250,14 @@ SymbolTable::getLagrangeMultipliers() const ...@@ -1088,3 +1250,14 @@ SymbolTable::getLagrangeMultipliers() const
r.insert(aux_var.symb_id); r.insert(aux_var.symb_id);
return r; return r;
} }
int
SymbolTable::getHeterogeneityDimension(int symb_id) const
{
validateSymbID(symb_id);
auto it = heterogeneity_dimensions.find(symb_id);
if (it != heterogeneity_dimensions.end())
return it->second;
else
throw NonHeteregeneousSymbolException {symb_id};
}
/* /*
* Copyright © 2003-2023 Dynare Team * Copyright © 2003-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "CommonEnums.hh" #include "CommonEnums.hh"
#include "ExprNode.hh" #include "ExprNode.hh"
#include "HeterogeneityTable.hh"
using namespace std; using namespace std;
...@@ -53,7 +54,11 @@ enum class AuxVarType ...@@ -53,7 +54,11 @@ enum class AuxVarType
diffLead = 11, //!< Variable for timing between Diff operators (lead) diffLead = 11, //!< Variable for timing between Diff operators (lead)
pacExpectation = 12, //!< Variable created for the substitution of the pac_expectation operator pacExpectation = 12, //!< Variable created for the substitution of the pac_expectation operator
pacTargetNonstationary pacTargetNonstationary
= 13 //!< Variable created for the substitution of the pac_target_nonstationary operator = 13, //!< Variable created for the substitution of the pac_target_nonstationary operator
aggregationOp
= 14, // Substitute for an aggregation operator in a heterogeneous setup, such as SUM()
heterogeneousMultiplier = 15 /* Multiplier for bound conditions of complementarity conditions in
the heterogeneous equations */
}; };
//! Information on some auxiliary variables //! Information on some auxiliary variables
...@@ -106,6 +111,8 @@ struct AuxVarInfo ...@@ -106,6 +111,8 @@ struct AuxVarInfo
class SymbolTable class SymbolTable
{ {
private: private:
HeterogeneityTable& heterogeneity_table;
//! Has method freeze() been called? //! Has method freeze() been called?
bool frozen {false}; bool frozen {false};
...@@ -123,6 +130,8 @@ private: ...@@ -123,6 +130,8 @@ private:
map<int, map<string, string>> partition_value_map; map<int, map<string, string>> partition_value_map;
//! Maps IDs to types //! Maps IDs to types
vector<SymbolType> type_table; vector<SymbolType> type_table;
// Maps IDs of heterogenous symbols to heterogeneity dimension IDs
map<int, int> heterogeneity_dimensions;
//! Maps symbol IDs to type specific IDs //! Maps symbol IDs to type specific IDs
map<int, int> type_specific_ids; map<int, int> type_specific_ids;
...@@ -135,9 +144,22 @@ private: ...@@ -135,9 +144,22 @@ private:
vector<int> exo_det_ids; vector<int> exo_det_ids;
//! Maps type specific IDs of parameters to symbol IDs //! Maps type specific IDs of parameters to symbol IDs
vector<int> param_ids; vector<int> param_ids;
/* Maps type specific IDs of heterogeneous endogenous to symbol IDs (outer vector is for
heterogeneity dimensions) */
vector<vector<int>> het_endo_ids;
/* Maps type specific IDs of heterogeneous exogenous to symbol IDs (outer vector is for
heterogeneity dimensions) */
vector<vector<int>> het_exo_ids;
/* Maps type specific IDs of heterogeneous parameters to symbol IDs (outer vector is for
heterogeneity dimensions) */
vector<vector<int>> het_param_ids;
//! Information about auxiliary variables //! Information about auxiliary variables
vector<AuxVarInfo> aux_vars; vector<AuxVarInfo> aux_vars;
//! Information about heterogeneous auxiliary variables
vector<vector<AuxVarInfo>> het_aux_vars;
//! Stores the predetermined variables (by symbol IDs) //! Stores the predetermined variables (by symbol IDs)
set<int> predetermined_variables; set<int> predetermined_variables;
...@@ -168,6 +190,7 @@ public: ...@@ -168,6 +190,7 @@ public:
{ {
const int tsid; const int tsid;
const SymbolType type; const SymbolType type;
const optional<int> heterogeneity_dimension;
}; };
/* Thrown when requesting the type specific ID of a symbol which doesn’t /* Thrown when requesting the type specific ID of a symbol which doesn’t
have one */ have one */
...@@ -202,6 +225,12 @@ public: ...@@ -202,6 +225,12 @@ public:
} }
}; };
// Thrown by getHeterogeneityDimension() on non-heterogeneous symbols
struct NonHeteregeneousSymbolException
{
const int id;
};
private: private:
//! Factorized code for adding aux lag variables //! Factorized code for adding aux lag variables
int addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_lead_lag, int addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_lead_lag,
...@@ -214,11 +243,19 @@ private: ...@@ -214,11 +243,19 @@ private:
inline void validateSymbID(int symb_id) const noexcept(false); inline void validateSymbID(int symb_id) const noexcept(false);
public: public:
SymbolTable(HeterogeneityTable& heterogeneity_table_arg) :
heterogeneity_table {heterogeneity_table_arg}
{
}
//! Add a symbol //! Add a symbol
/*! Returns the symbol ID */ /* Returns the symbol ID.
heterogeneity_dimension must be defined if this is a heterogeneous symbol (otherwise it is
ignored) */
int addSymbol(const string& name, SymbolType type, const string& tex_name, int addSymbol(const string& name, SymbolType type, const string& tex_name,
const vector<pair<string, string>>& partition_value) noexcept(false); const vector<pair<string, string>>& partition_value,
//! Add a symbol without its TeX name (will be equal to its name) const optional<int>& heterogeneity_dimension) noexcept(false);
//! Add a (non-heterogenous) symbol without its TeX name (will be equal to its name)
/*! Returns the symbol ID */ /*! Returns the symbol ID */
int addSymbol(const string& name, SymbolType type) noexcept(false); int addSymbol(const string& name, SymbolType type) noexcept(false);
//! Adds an auxiliary variable for endogenous with lead >= 2 //! Adds an auxiliary variable for endogenous with lead >= 2
...@@ -250,6 +287,14 @@ public: ...@@ -250,6 +287,14 @@ public:
\return the symbol ID of the new symbol \return the symbol ID of the new symbol
*/ */
int addExpectationAuxiliaryVar(int information_set, int index, expr_t arg) noexcept(false); int addExpectationAuxiliaryVar(int information_set, int index, expr_t arg) noexcept(false);
/* Adds an auxiliary variable for the bound-specific multiplier of the MCPs and returns its
symbolID.
– het_dim is the heterogeneity dimension of the model
– index is the equation's index
– varname is the multiplier name
*/
int addHeterogeneousMultiplierAuxiliaryVar(int het_dim, int index,
const string& varname) noexcept(false);
//! Adds an auxiliary variable for the multiplier for the FOCs of the Ramsey Problem //! Adds an auxiliary variable for the multiplier for the FOCs of the Ramsey Problem
/*! /*!
\param[in] index Used to construct the variable name \param[in] index Used to construct the variable name
...@@ -313,12 +358,16 @@ public: ...@@ -313,12 +358,16 @@ public:
int addPacExpectationAuxiliaryVar(const string& name, expr_t expr_arg); int addPacExpectationAuxiliaryVar(const string& name, expr_t expr_arg);
//! An auxiliary variable for a pac_target_nonstationary operator //! An auxiliary variable for a pac_target_nonstationary operator
int addPacTargetNonstationaryAuxiliaryVar(const string& name, expr_t expr_arg); int addPacTargetNonstationaryAuxiliaryVar(const string& name, expr_t expr_arg);
// An auxiliary variable for an aggregation operator (e.g. SUM(yh) where yh is heterogeneous)
int addAggregationOpAuxiliaryVar(const string& name, expr_t expr_arg);
//! Set the size of het_aux_vars
inline void resizeHetAuxVars();
//! Returns the number of auxiliary variables //! Returns the number of auxiliary variables
[[nodiscard]] int [[nodiscard]] int
AuxVarsSize() const AuxVarsSize() const
{ {
return aux_vars.size(); return aux_vars.size();
}; }
//! Tests if symbol already exists //! Tests if symbol already exists
[[nodiscard]] inline bool exists(const string& name) const; [[nodiscard]] inline bool exists(const string& name) const;
//! Get symbol name (by ID) //! Get symbol name (by ID)
...@@ -340,7 +389,9 @@ public: ...@@ -340,7 +389,9 @@ public:
//! Get ID (by name) //! Get ID (by name)
[[nodiscard]] inline int getID(const string& name) const noexcept(false); [[nodiscard]] inline int getID(const string& name) const noexcept(false);
//! Get ID (by type specific ID) //! Get ID (by type specific ID)
[[nodiscard]] int getID(SymbolType type, int tsid) const noexcept(false); [[nodiscard]] int getID(SymbolType type, int tsid,
const optional<int>& heterogeneity_dimension = nullopt) const
noexcept(false);
//! Freeze symbol table //! Freeze symbol table
void freeze() noexcept(false); void freeze() noexcept(false);
//! unreeze symbol table //! unreeze symbol table
...@@ -360,6 +411,15 @@ public: ...@@ -360,6 +411,15 @@ public:
[[nodiscard]] inline int exo_det_nbr() const noexcept(false); [[nodiscard]] inline int exo_det_nbr() const noexcept(false);
//! Get number of parameters //! Get number of parameters
[[nodiscard]] inline int param_nbr() const noexcept(false); [[nodiscard]] inline int param_nbr() const noexcept(false);
//! Get number of heterogeneous endogenous variables along a given dimension
[[nodiscard]] inline int het_endo_nbr(int het_dim) const noexcept(false);
//! Get number of user-declared heterogeneous endogenous variables (without
//! the auxiliary variables)
[[nodiscard]] inline int het_orig_endo_nbr(int het_dim) const noexcept(false);
//! Get number of heterogeneous exogenous variables along a given dimension
[[nodiscard]] inline int het_exo_nbr(int het_dim) const noexcept(false);
//! Get number of heterogeneous parameters along a given dimension
[[nodiscard]] inline int het_param_nbr(int het_dim) const noexcept(false);
//! Returns the greatest symbol ID (the smallest is zero) //! Returns the greatest symbol ID (the smallest is zero)
[[nodiscard]] inline int maxID() const; [[nodiscard]] inline int maxID() const;
//! Get number of user-declared endogenous variables (without the auxiliary variables) //! Get number of user-declared endogenous variables (without the auxiliary variables)
...@@ -423,6 +483,9 @@ public: ...@@ -423,6 +483,9 @@ public:
[[nodiscard]] const set<int>& getVariablesWithLogTransform() const; [[nodiscard]] const set<int>& getVariablesWithLogTransform() const;
// Returns all Lagrange multipliers // Returns all Lagrange multipliers
[[nodiscard]] set<int> getLagrangeMultipliers() const; [[nodiscard]] set<int> getLagrangeMultipliers() const;
/* Get heterogeneity dimension of a given symbol. Throws NonHeterogeneousSymbolException
if there is no such dimension. */
[[nodiscard]] int getHeterogeneityDimension(int symb_id) const;
}; };
inline void inline void
...@@ -432,6 +495,12 @@ SymbolTable::validateSymbID(int symb_id) const noexcept(false) ...@@ -432,6 +495,12 @@ SymbolTable::validateSymbID(int symb_id) const noexcept(false)
throw UnknownSymbolIDException {symb_id}; throw UnknownSymbolIDException {symb_id};
} }
inline void
SymbolTable::resizeHetAuxVars()
{
het_aux_vars.resize(heterogeneity_table.size());
}
inline bool inline bool
SymbolTable::exists(const string& name) const SymbolTable::exists(const string& name) const
{ {
...@@ -537,6 +606,42 @@ SymbolTable::param_nbr() const noexcept(false) ...@@ -537,6 +606,42 @@ SymbolTable::param_nbr() const noexcept(false)
return param_ids.size(); return param_ids.size();
} }
inline int
SymbolTable::het_endo_nbr(int het_dim) const noexcept(false)
{
if (!frozen)
throw NotYetFrozenException();
return het_endo_ids.at(het_dim).size();
}
inline int
SymbolTable::het_orig_endo_nbr(int het_dim) const noexcept(false)
{
if (!frozen)
throw NotYetFrozenException();
return het_endo_ids.at(het_dim).size() - het_aux_vars.at(het_dim).size();
}
inline int
SymbolTable::het_exo_nbr(int het_dim) const noexcept(false)
{
if (!frozen)
throw NotYetFrozenException();
return het_exo_ids.at(het_dim).size();
}
inline int
SymbolTable::het_param_nbr(int het_dim) const noexcept(false)
{
if (!frozen)
throw NotYetFrozenException();
return het_param_ids.at(het_dim).size();
}
inline int inline int
SymbolTable::maxID() const SymbolTable::maxID() const
{ {
......
/* /*
* Copyright © 2012-2022 Dynare Team * Copyright © 2012-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -18,39 +18,33 @@ ...@@ -18,39 +18,33 @@
*/ */
#include "WarningConsolidation.hh" #include "WarningConsolidation.hh"
#include <ostream>
WarningConsolidation& ostream&
operator<<(WarningConsolidation& wcc, const string& warning) operator<<(ostream& stream, const Dynare::location& l)
{ {
if (wcc.no_warn) stream << *l.begin.filename << ": line " << l.begin.line;
return wcc; if (l.begin.line == l.end.line)
if (l.begin.column == l.end.column - 1)
stream << ", col " << l.begin.column;
else
stream << ", cols " << l.begin.column << "-" << l.end.column - 1;
else
stream << ", col " << l.begin.column << " -"
<< " line " << l.end.line << ", col " << l.end.column - 1;
cerr << warning; return stream;
wcc.addWarning(warning); }
return wcc;
};
WarningConsolidation& void
operator<<(WarningConsolidation& wcc, const Dynare::location& loc) WarningConsolidation::incrementWarnings(const string& msg)
{ {
if (wcc.no_warn) size_t p {0};
return wcc; while ((p = msg.find('\n', p)) != string::npos)
{
stringstream ostr; p++;
Dynare::position last = loc.end - 1; num_warnings++;
ostr << loc.begin; }
if (last.filename && (!loc.begin.filename || *loc.begin.filename != *last.filename)) }
ostr << '-' << last;
else if (loc.begin.line != last.line)
ostr << '-' << last.line << '.' << last.column;
else if (loc.begin.column != last.column)
ostr << '-' << last.column;
cerr << ostr.str();
wcc.addWarning(ostr.str());
return wcc;
};
WarningConsolidation& WarningConsolidation&
operator<<(WarningConsolidation& wcc, ostream& (*pf)(ostream&)) operator<<(WarningConsolidation& wcc, ostream& (*pf)(ostream&))
...@@ -58,49 +52,12 @@ operator<<(WarningConsolidation& wcc, ostream& (*pf)(ostream&)) ...@@ -58,49 +52,12 @@ operator<<(WarningConsolidation& wcc, ostream& (*pf)(ostream&))
if (wcc.no_warn) if (wcc.no_warn)
return wcc; return wcc;
cerr << pf; ostringstream ostr;
wcc.addWarning(pf); ostr << pf;
return wcc;
}
void cerr << ostr.str();
WarningConsolidation::writeOutput(ostream& output) const
{
if (warnings.str().empty())
return;
output << "disp([char(10) 'Dynare Preprocessor Warning(s) Encountered:']);" << endl;
bool writedisp = true; wcc.incrementWarnings(ostr.str());
string warningsstr = warnings.str();
for (size_t i = 0; i < warningsstr.length(); i++)
{
if (writedisp)
{
output << "disp(' ";
writedisp = false;
}
if (warningsstr[i] != '\n') return wcc;
output << warningsstr[i];
else
{
output << "');" << endl;
if (i + 1 < warningsstr.length())
writedisp = true;
}
}
}
int
WarningConsolidation::countWarnings() const
{
size_t p = 0;
int n = 0;
while ((p = warnings.str().find('\n', p)) != string::npos)
{
p++;
n++;
}
return n;
} }
/* /*
* Copyright © 2012-2023 Dynare Team * Copyright © 2012-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -21,45 +21,64 @@ ...@@ -21,45 +21,64 @@
#define WARNING_CONSOLIDATION_HH #define WARNING_CONSOLIDATION_HH
#include "DynareBisonLocation.hh" #include "DynareBisonLocation.hh"
#include <iostream>
#include <ostream>
#include <sstream> #include <sstream>
#include <string> #include <string>
using namespace std; using namespace std;
//! Stores Warnings issued by the Preprocessor /* Provide our implementation of operator<< with locations in DynareBison.hh. Note that the
following is a template specialization of the version provided in DynareBisonLocation.hh.
Ideally it should go into DynareBisonLocation.hh, but there does not seem to be a way to achieve
that. */
ostream& operator<<(ostream& stream, const Dynare::location& l);
class WarningConsolidation class WarningConsolidation
{ {
private: private:
stringstream warnings; const bool no_warn;
bool no_warn; int num_warnings {0};
// Increases the warning counter by as many newlines as there are in the message
void incrementWarnings(const string& msg);
public: public:
explicit WarningConsolidation(bool no_warn_arg) : no_warn {no_warn_arg} explicit WarningConsolidation(bool no_warn_arg) : no_warn {no_warn_arg}
{ {
} }
//! Add A Warning to the StringStream // Generic function to print something to the warning stream
friend WarningConsolidation& operator<<(WarningConsolidation& wcc, const string& warning); friend WarningConsolidation& operator<<(WarningConsolidation& wcc, auto&& warning);
friend WarningConsolidation& operator<<(WarningConsolidation& wcc, const Dynare::location& loc);
/* Print std::endl to the warning stream. Unfortunately, since std::endl is a template of
functions, it cannot be bound to the universal reference of the generic function, hence the
need for this specialization. */
friend WarningConsolidation& operator<<(WarningConsolidation& wcc, ostream& (*pf)(ostream&)); friend WarningConsolidation& operator<<(WarningConsolidation& wcc, ostream& (*pf)(ostream&));
void int
addWarning(const string& w) numWarnings() const
{ {
warnings << w; return num_warnings;
}
}; };
void
addWarning(ostream& (*pf)(ostream&)) WarningConsolidation&
operator<<(WarningConsolidation& wcc, auto&& warning)
{ {
warnings << pf; if (wcc.no_warn)
}; return wcc;
//! Write Warnings to m file ostringstream ostr;
void writeOutput(ostream& output) const; ostr << warning;
//! Count warnings
/*! This is done in a very lousy way, by counting newlines in the cerr << ostr.str();
stringstream... */
int countWarnings() const; wcc.incrementWarnings(ostr.str());
};
return wcc;
}
#endif #endif
...@@ -189,10 +189,7 @@ void ...@@ -189,10 +189,7 @@ void
EchoMacroVars::interpret(ostream& output, Environment& env, EchoMacroVars::interpret(ostream& output, Environment& env,
[[maybe_unused]] vector<filesystem::path>& paths) [[maybe_unused]] vector<filesystem::path>& paths)
{ {
if (save) env.print(save ? output : cout, vars, location.begin.line, save);
env.print(output, vars, location.begin.line, true);
else
env.print(cout, vars);
printEndLineInfo(output); printEndLineInfo(output);
} }
......
/* /*
* Copyright © 2019-2023 Dynare Team * Copyright © 2019-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -17,7 +17,9 @@ ...@@ -17,7 +17,9 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <algorithm>
#include <cassert> #include <cassert>
#include <ranges>
#include "Environment.hh" #include "Environment.hh"
#include "Expressions.hh" #include "Expressions.hh"
...@@ -54,7 +56,7 @@ Environment::getVariable(const string& name) const ...@@ -54,7 +56,7 @@ Environment::getVariable(const string& name) const
return getGlobalEnv()->getVariable(name); return getGlobalEnv()->getVariable(name);
} }
tuple<FunctionPtr, ExpressionPtr> pair<FunctionPtr, ExpressionPtr>
Environment::getFunction(const string& name) const Environment::getFunction(const string& name) const
{ {
if (auto it = functions.find(name); it != functions.end()) if (auto it = functions.find(name); it != functions.end())
...@@ -101,41 +103,54 @@ Environment::isFunctionDefined(const string& name) const noexcept ...@@ -101,41 +103,54 @@ Environment::isFunctionDefined(const string& name) const noexcept
} }
void void
Environment::print(ostream& output, const vector<string>& vars, const optional<int>& line, Environment::print(ostream& output, const vector<string>& vars, int line, bool save) const
bool save) const
{ {
if (!save && !variables.empty()) if (!save && !variables.empty())
output << "Macro Variables:" << endl; output << "Macro Variables (at line " << line << "):" << endl;
// For sorting the symbols in a case-insensitive way, see #128
auto case_insensitive_string_less = [](const string& a, const string& b) {
return ranges::lexicographical_compare(
a, b, [](char c1, char c2) { return tolower(c1) < tolower(c2); });
};
if (vars.empty()) if (vars.empty())
for (const auto& it : variables) {
printVariable(output, it.first, line, save); vector<string> variables_sorted;
ranges::copy(views::keys(variables), back_inserter(variables_sorted));
ranges::sort(variables_sorted, case_insensitive_string_less);
for (const auto& it : variables_sorted)
printVariable(output, it, line, save);
}
else else
for (const auto& it : vars) for (const auto& it : vars)
if (isVariableDefined(it)) if (isVariableDefined(it))
printVariable(output, it, line, save); printVariable(output, it, line, save);
if (!save && !functions.empty()) if (!save && !functions.empty())
output << "Macro Functions:" << endl; output << "Macro Functions (at line " << line << "):" << endl;
if (vars.empty()) if (vars.empty())
for (const auto& it : functions) {
printFunction(output, it.second, line, save); vector<string> functions_sorted;
ranges::copy(views::keys(functions), back_inserter(functions_sorted));
ranges::sort(functions_sorted, case_insensitive_string_less);
for (const auto& it : functions_sorted)
printFunction(output, it, line, save);
}
else else
for (const auto& it : vars) for (const auto& it : vars)
if (isFunctionDefined(it)) if (isFunctionDefined(it))
printFunction(output, functions.at(it), line, save); printFunction(output, it, line, save);
if (parent) if (parent)
parent->print(output, vars, line, save); parent->print(output, vars, line, save);
} }
void void
Environment::printVariable(ostream& output, const string& name, const optional<int>& line, Environment::printVariable(ostream& output, const string& name, int line, bool save) const
bool save) const
{ {
assert(!save || line); output << (save ? "options_.macrovars_line_" + to_string(line) + "." : " ") << name << " = ";
output << (save ? "options_.macrovars_line_" + to_string(*line) + "." : " ") << name << " = ";
getVariable(name)->eval(const_cast<Environment&>(*this))->print(output, save); getVariable(name)->eval(const_cast<Environment&>(*this))->print(output, save);
if (save) if (save)
output << ";"; output << ";";
...@@ -143,20 +158,19 @@ Environment::printVariable(ostream& output, const string& name, const optional<i ...@@ -143,20 +158,19 @@ Environment::printVariable(ostream& output, const string& name, const optional<i
} }
void void
Environment::printFunction(ostream& output, const tuple<FunctionPtr, ExpressionPtr>& function, Environment::printFunction(ostream& output, const string& name, int line, bool save) const
const optional<int>& line, bool save) const
{ {
assert(!save || line); auto [func_signature, func_body] = getFunction(name);
output << (save ? "options_.macrovars_line_" + to_string(*line) + ".function." : " "); output << (save ? "options_.macrovars_line_" + to_string(line) + ".function." : " ");
if (save) if (save)
{ {
get<0>(function)->printName(output); func_signature->printName(output);
output << " = '"; output << " = '";
} }
get<0>(function)->print(output); func_signature->print(output);
output << " = "; output << " = ";
get<1>(function)->print(output); func_body->print(output);
if (save) if (save)
output << "';"; output << "';";
......
/* /*
* Copyright © 2019-2023 Dynare Team * Copyright © 2019-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -33,7 +33,7 @@ class Environment ...@@ -33,7 +33,7 @@ class Environment
private: private:
const Environment* parent {nullptr}; const Environment* parent {nullptr};
map<string, ExpressionPtr> variables; map<string, ExpressionPtr> variables;
map<string, tuple<FunctionPtr, ExpressionPtr>> functions; map<string, pair<FunctionPtr, ExpressionPtr>> functions;
public: public:
Environment() = default; Environment() = default;
...@@ -45,7 +45,7 @@ public: ...@@ -45,7 +45,7 @@ public:
/* The following two functions are not marked [[nodiscard]], because they are used without output /* The following two functions are not marked [[nodiscard]], because they are used without output
to check whether they return an exception or not. */ to check whether they return an exception or not. */
ExpressionPtr getVariable(const string& name) const; // NOLINT(modernize-use-nodiscard) ExpressionPtr getVariable(const string& name) const; // NOLINT(modernize-use-nodiscard)
tuple<FunctionPtr, ExpressionPtr> // NOLINT(modernize-use-nodiscard) pair<FunctionPtr, ExpressionPtr> // NOLINT(modernize-use-nodiscard)
getFunction(const string& name) const; getFunction(const string& name) const;
[[nodiscard]] codes::BaseType getType(const string& name) const; [[nodiscard]] codes::BaseType getType(const string& name) const;
[[nodiscard]] bool isVariableDefined(const string& name) const noexcept; [[nodiscard]] bool isVariableDefined(const string& name) const noexcept;
...@@ -55,12 +55,9 @@ public: ...@@ -55,12 +55,9 @@ public:
{ {
return isVariableDefined(name) || isFunctionDefined(name); return isVariableDefined(name) || isFunctionDefined(name);
} }
void print(ostream& output, const vector<string>& vars, const optional<int>& line = nullopt, void print(ostream& output, const vector<string>& vars, int line, bool save) const;
bool save = false) const; void printVariable(ostream& output, const string& name, int line, bool save) const;
void printVariable(ostream& output, const string& name, const optional<int>& line, void printFunction(ostream& output, const string& name, int line, bool save) const;
bool save) const;
void printFunction(ostream& output, const tuple<FunctionPtr, ExpressionPtr>& function,
const optional<int>& line, bool save) const;
[[nodiscard]] size_t [[nodiscard]] size_t
size() const noexcept size() const noexcept
{ {
......
/* /*
* Copyright © 2019-2023 Dynare Team * Copyright © 2019-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -241,9 +241,9 @@ Real::normpdf(const BaseTypePtr& btp1, const BaseTypePtr& btp2) const ...@@ -241,9 +241,9 @@ Real::normpdf(const BaseTypePtr& btp1, const BaseTypePtr& btp2) const
auto btp22 = dynamic_pointer_cast<Real>(btp2); auto btp22 = dynamic_pointer_cast<Real>(btp2);
if (!btp12 || !btp22) if (!btp12 || !btp22)
throw StackTrace("Type mismatch for operands of `normpdf` operator"); throw StackTrace("Type mismatch for operands of `normpdf` operator");
return make_shared<Real>((1 return make_shared<Real>(1
/ (btp22->value * std::sqrt(2 * numbers::pi) / (btp22->value * std::sqrt(2 * numbers::pi)
* std::exp(pow((value - btp12->value) / btp22->value, 2) / 2)))); * std::exp(pow((value - btp12->value) / btp22->value, 2) / 2)));
} }
RealPtr RealPtr
...@@ -254,7 +254,7 @@ Real::normcdf(const BaseTypePtr& btp1, const BaseTypePtr& btp2) const ...@@ -254,7 +254,7 @@ Real::normcdf(const BaseTypePtr& btp1, const BaseTypePtr& btp2) const
if (!btp12 || !btp22) if (!btp12 || !btp22)
throw StackTrace("Type mismatch for operands of `normpdf` operator"); throw StackTrace("Type mismatch for operands of `normpdf` operator");
return make_shared<Real>( return make_shared<Real>(
(0.5 * (1 + std::erf((value - btp12->value) / btp22->value / numbers::sqrt2)))); 0.5 * (1 + std::erf((value - btp12->value) / btp22->value / numbers::sqrt2)));
} }
BaseTypePtr BaseTypePtr
...@@ -314,12 +314,12 @@ String::is_equal(const BaseTypePtr& btp) const ...@@ -314,12 +314,12 @@ String::is_equal(const BaseTypePtr& btp) const
BoolPtr BoolPtr
String::cast_bool([[maybe_unused]] Environment& env) const String::cast_bool([[maybe_unused]] Environment& env) const
{ {
auto f = [](const char& a, const char& b) { return (tolower(a) == tolower(b)); }; auto f = [](const char& a, const char& b) { return tolower(a) == tolower(b); };
if (string tf = "true"; equal(value.begin(), value.end(), tf.begin(), tf.end(), f)) if (ranges::equal(value, "true"s, f))
return make_shared<Bool>(true); return make_shared<Bool>(true);
if (string tf = "false"; equal(value.begin(), value.end(), tf.begin(), tf.end(), f)) if (ranges::equal(value, "false"s, f))
return make_shared<Bool>(false); return make_shared<Bool>(false);
try try
......
// -*- C++ -*- // -*- C++ -*-
/* /*
* Copyright © 2019-2023 Dynare Team * Copyright © 2019-2024 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
...@@ -28,10 +28,6 @@ ...@@ -28,10 +28,6 @@
%define parse.error verbose %define parse.error verbose
%define parse.trace %define parse.trace
%code requires {
namespace macro { class Driver; }
}
%param { macro::Driver& driver } %param { macro::Driver& driver }
%locations %locations
...@@ -43,6 +39,9 @@ namespace macro { class Driver; } ...@@ -43,6 +39,9 @@ namespace macro { class Driver; }
%code requires { %code requires {
#include "Directives.hh" #include "Directives.hh"
namespace macro { class Driver; }
using namespace macro; using namespace macro;
} }
......
...@@ -53,6 +53,8 @@ preprocessor_src = [ 'ComputingTasks.cc', ...@@ -53,6 +53,8 @@ preprocessor_src = [ 'ComputingTasks.cc',
'ModelEquationBlock.cc', 'ModelEquationBlock.cc',
'WarningConsolidation.cc', 'WarningConsolidation.cc',
'SubModel.cc', 'SubModel.cc',
'HeterogeneityTable.cc',
'HeterogeneousModel.cc',
'macro/Driver.cc', 'macro/Driver.cc',
'macro/Environment.cc', 'macro/Environment.cc',
'macro/Expressions.cc', 'macro/Expressions.cc',
......