Compare commits

...

34 Commits

Author SHA1 Message Date
Sébastien Villemot e32025a76f
Bump major version number 2023-12-21 15:57:59 +01:00
Sébastien Villemot 5fa91a08f6
CI: bump MSYS2 Boost dependency 2023-12-21 11:14:45 +01:00
Sébastien Villemot 520876560d
New matched_irfs and matched_irfs_weights blocks
Closes: #124
2023-12-19 16:10:19 +01:00
Sébastien Villemot f8b2de715c
Drop unused options_.minimal_workspace 2023-12-18 16:24:22 +01:00
Sébastien Villemot 638c49d96e Merge branch 'EP' into 'master'
Remove globals from extended path

See merge request Dynare/preprocessor!99
2023-12-18 10:47:51 +00:00
Sébastien Villemot b6875ebb9d Merge branch 'mj_steadystatemodel' into 'master'
Add steady_state_model_present field to modfile.json

See merge request Dynare/preprocessor!100
2023-12-18 09:57:06 +00:00
MichelJuillard c96d96cfb3 Add steady_state_model_present field to modfile.json 2023-12-18 09:57:06 +00:00
Johannes Pfeifer 1cfce804a6 Perfect foresight: remove globals 2023-12-15 22:24:07 +01:00
Johannes Pfeifer 5a2c099871 EP: output results explicitly as opposed to assignin-statement 2023-12-14 19:53:07 +01:00
Sébastien Villemot 0f397f40af
Rename “dynare_sensitivity” command to “sensitivity”
The old name is still accepted, but will trigger a deprecation warning.
2023-12-14 18:37:10 +01:00
Sébastien Villemot 8d0e8cca5c
Merge branch 'gsa_namespace' of git.dynare.org:JohannesPfeifer/preprocessor
Ref. !96
2023-12-14 18:27:19 +01:00
Sébastien Villemot ba3ab3a234
Merge branch 'sylvester' of git.dynare.org:JohannesPfeifer/preprocessor
Ref. !97
2023-12-14 17:59:54 +01:00
Sébastien Villemot 3dadac8f19
Merge branch 'cond_forecast' of git.dynare.org:JohannesPfeifer/preprocessor
Ref. !98
2023-12-14 17:34:27 +01:00
Sébastien Villemot cf45c77343
Bytecode: simplify various instruction classes 2023-12-14 17:07:06 +01:00
Sébastien Villemot f55019c41e
Bytecode: rename several classes and class members, for consistency and clarity 2023-12-14 16:17:22 +01:00
Sébastien Villemot 22709f8225
Move bytecode stuff into a dedicated namespace, for better code separation 2023-12-14 15:48:22 +01:00
Johannes Pfeifer 1734491b76 conditional_forecast: remove global variables and move to namespace 2023-12-14 11:42:41 +01:00
Johannes Pfeifer cf1c11676b Remove obsolete Sylvester options
dr_block has been removed
2023-12-14 11:36:59 +01:00
Johannes Pfeifer 090945d8a8 Use namespace for identification and sensitivity 2023-12-13 17:51:49 +01:00
Sébastien Villemot 1c10a3acbf
Enable performance-* checks in clang-tidy 2023-12-13 16:30:40 +01:00
Sébastien Villemot cbfad751c8
Remove some unnecessary temporary std::string allocation
Automatically detected by clang-tidy using
performance-inefficient-string-concatenation check.

Several of the detected cases are left unattended, because the syntax is more
elegant as it is, and they are not performance-critical.
2023-12-13 16:29:46 +01:00
Sébastien Villemot b31de3d9a6
Pre-allocate std::vector instances filled from loops
Automatically detected by clang-tidy using
performance-inefficient-vector-operation check.
2023-12-13 16:19:51 +01:00
Sébastien Villemot 22675728aa
No longer call std::move on trivially-copyable types
Automatically detected by clang-tidy with performance-move-const-arg check.

Do not make the modification for Tokenizer::location type, since we have no
guarantee that the type will remain trivially-copyable in the future.
2023-12-13 15:37:07 +01:00
Sébastien Villemot 7cfe226e58
When possible, use a more efficient overload of std::string::find()
Automatically detected by clang-tidy using the performance-faster-string-find
check.
2023-12-13 14:21:11 +01:00
Sébastien Villemot d635aac04a
Turn some loop variables into const references when possible
Automatically detected by clang-tidy using performance-for-range-copy check.
2023-12-13 14:21:09 +01:00
Sébastien Villemot 3d94f1956c
Remove some unneeded object copies
Automatically detected by clang-tidy using performance-unnecessary-value-param
check.
2023-12-13 10:28:54 +01:00
Sébastien Villemot cd86b1895d
Configuration file: new default value for GlobalInitFile option
If the user did not specify the GlobalInitFile option, use global_init.m in configuration
directory if it exists.
2023-12-12 16:01:54 +01:00
Sébastien Villemot 1de83b7b12
Configuration file: simplify handling of GlobalInitFile option
There was some overengineering related to the Hook class.
2023-12-12 15:54:57 +01:00
Sébastien Villemot 328e8eef78
Change default location for configuration file
– under Linux and macOS, use the “dynare” subdirectory of the configuration
  directory specified by the XDG specification
– under Windows, use the “dynare” subdirectory of the Application Data folder

The old location is kept for backward compatibility, with a warning.
2023-12-12 12:28:33 +01:00
Sébastien Villemot 7c83b81623
Turn some configuration-related classes into nested classes 2023-12-11 17:32:30 +01:00
Sébastien Villemot 4389e5320d
Rename files, classes and variables in relation to the configuration file
In particular, makes clearer the distinction between configuration and
configuration file. The former includes information that is not in the
latter (command-line options.)
2023-12-11 17:17:57 +01:00
Sébastien Villemot 7dd125e43a
Remove duplicate definition of expr_t 2023-12-11 14:29:43 +01:00
Sébastien Villemot e4b23fecb0
Update comments in relation to implicit conversion from std::filesystem::path to std::string
There is actually no bug in MinGW. The different behaviour under Windows is
expected, because the implicit conversion there is only to std::wstring.
2023-12-08 18:39:27 +01:00
Sébastien Villemot 4790fa00d8
Remove workaround for bug in MinGW compiler
It would mishandle trailing slashes or backslashes in std::filesystem::path, see
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88881

The bug is now fixed in the version of MinGW in Debian “bookworm” 12.

Ref. Madysson/estimation-codes#11
2023-12-08 18:36:25 +01:00
37 changed files with 1085 additions and 1129 deletions

View File

@ -1,9 +1,8 @@
# TODO: add the following check families: # TODO: add the following check families:
# - performance-*
# - bugprone-* # - bugprone-*
# - cppcoreguidelines- # - cppcoreguidelines-
# NB: as of clang-tidy 16, we get several false positives inside boost, notably this one: # NB: as of clang-tidy 16, we get several false positives inside boost, notably this one:
# https://github.com/llvm/llvm-project/issues/40486 # https://github.com/llvm/llvm-project/issues/40486
Checks: 'modernize-*,-modernize-use-trailing-return-type,-clang-diagnostic-unqualified-std-cast-call' Checks: 'performance-*,modernize-*,-modernize-use-trailing-return-type,-clang-diagnostic-unqualified-std-cast-call'

View File

@ -1,7 +1,7 @@
variables: variables:
TERM: linux TERM: linux
MINGW32_BOOST_VERSION: 1.81.0-7 MINGW32_BOOST_VERSION: 1.84.0-1
MINGW64_BOOST_VERSION: 1.81.0-7 MINGW64_BOOST_VERSION: 1.84.0-1
WGET_OPTIONS: '--no-verbose --no-use-server-timestamps --retry-connrefused --retry-on-host-error' WGET_OPTIONS: '--no-verbose --no-use-server-timestamps --retry-connrefused --retry-on-host-error'
# To ensure that "false && true" fails, see https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25394#note_412609647 # To ensure that "false && true" fails, see https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25394#note_412609647
FF_ENABLE_BASH_EXIT_CODE_CHECK: 'true' FF_ENABLE_BASH_EXIT_CODE_CHECK: 'true'

View File

@ -2,7 +2,7 @@
# It is not used when building Dynare as a whole. # It is not used when building Dynare as a whole.
project('dynare-preprocessor', 'cpp', project('dynare-preprocessor', 'cpp',
version : '6-unstable', version : '7-unstable',
# NB: update C++ standard in .clang-format whenever the following is modified # NB: update C++ standard in .clang-format whenever the following is modified
default_options : [ 'cpp_std=gnu++20', 'warning_level=2' ], default_options : [ 'cpp_std=gnu++20', 'warning_level=2' ],
meson_version : '>=0.64.0') meson_version : '>=0.64.0')

View File

@ -24,7 +24,10 @@
#include "Bytecode.hh" #include "Bytecode.hh"
BytecodeWriter::BytecodeWriter(const filesystem::path& filename) namespace Bytecode
{
Writer::Writer(const filesystem::path& filename)
{ {
open(filename, ios::out | ios::binary); open(filename, ios::out | ios::binary);
if (!is_open()) if (!is_open())
@ -35,8 +38,8 @@ BytecodeWriter::BytecodeWriter(const filesystem::path& filename)
} }
template<> template<>
BytecodeWriter& Writer&
operator<<(BytecodeWriter& code_file, const FCALL_& instr) operator<<(Writer& code_file, const FCALL& instr)
{ {
code_file.instructions_positions.push_back(code_file.tellp()); code_file.instructions_positions.push_back(code_file.tellp());
@ -44,7 +47,7 @@ operator<<(BytecodeWriter& code_file, const FCALL_& instr)
code_file.write(reinterpret_cast<const char*>(&member), sizeof member); code_file.write(reinterpret_cast<const char*>(&member), sizeof member);
}; };
write_member(instr.op_code); write_member(instr.tag);
write_member(instr.nb_output_arguments); write_member(instr.nb_output_arguments);
write_member(instr.nb_input_arguments); write_member(instr.nb_input_arguments);
write_member(instr.indx); write_member(instr.indx);
@ -65,8 +68,8 @@ operator<<(BytecodeWriter& code_file, const FCALL_& instr)
} }
template<> template<>
BytecodeWriter& Writer&
operator<<(BytecodeWriter& code_file, const FBEGINBLOCK_& instr) operator<<(Writer& code_file, const FBEGINBLOCK& instr)
{ {
code_file.instructions_positions.push_back(code_file.tellp()); code_file.instructions_positions.push_back(code_file.tellp());
@ -74,7 +77,7 @@ operator<<(BytecodeWriter& code_file, const FBEGINBLOCK_& instr)
code_file.write(reinterpret_cast<const char*>(&member), sizeof member); code_file.write(reinterpret_cast<const char*>(&member), sizeof member);
}; };
write_member(instr.op_code); write_member(instr.tag);
write_member(instr.size); write_member(instr.size);
write_member(instr.type); write_member(instr.type);
for (int i = 0; i < instr.size; i++) for (int i = 0; i < instr.size; i++)
@ -99,3 +102,5 @@ operator<<(BytecodeWriter& code_file, const FBEGINBLOCK_& instr)
return code_file; return code_file;
} }
}

File diff suppressed because it is too large Load Diff

View File

@ -153,7 +153,8 @@ SimulStatement::writeOutput(ostream& output, [[maybe_unused]] const string& base
options_list_new.erase("datafile"); options_list_new.erase("datafile");
} }
options_list_new.writeOutput(output); options_list_new.writeOutput(output);
output << "perfect_foresight_setup;" << endl << "perfect_foresight_solver;" << endl; output << "oo_ = perfect_foresight_setup(M_, options_, oo_);" << endl
<< "[oo_, Simulated_time_series] = perfect_foresight_solver(M_, options_, oo_);" << endl;
} }
void void
@ -188,7 +189,7 @@ PerfectForesightSetupStatement::writeOutput(ostream& output,
options_list_new.erase("datafile"); options_list_new.erase("datafile");
} }
options_list_new.writeOutput(output); options_list_new.writeOutput(output);
output << "perfect_foresight_setup;" << endl; output << "oo_ = perfect_foresight_setup(M_, options_, oo_);" << endl;
} }
void void
@ -221,7 +222,7 @@ PerfectForesightSolverStatement::writeOutput(ostream& output,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
options_list.writeOutput(output); options_list.writeOutput(output);
output << "perfect_foresight_solver;" << endl; output << "[oo_, Simulated_time_series] = perfect_foresight_solver(M_, options_, oo_);" << endl;
} }
void void
@ -248,7 +249,7 @@ PerfectForesightWithExpectationErrorsSetupStatement::writeOutput(
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
options_list.writeOutput(output); options_list.writeOutput(output);
output << "perfect_foresight_with_expectation_errors_setup;" << endl; output << "oo_ = perfect_foresight_with_expectation_errors_setup(M_, options_, oo_);" << endl;
} }
void void
@ -282,7 +283,7 @@ PerfectForesightWithExpectationErrorsSolverStatement::writeOutput(
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
options_list.writeOutput(output); options_list.writeOutput(output);
output << "perfect_foresight_with_expectation_errors_solver;" << endl; output << "oo_ = perfect_foresight_with_expectation_errors_solver(M_, options_, oo_);" << endl;
} }
void void
@ -1070,14 +1071,14 @@ EstimationStatement::writeJsonOutput(ostream& output) const
output << "}"; output << "}";
} }
DynareSensitivityStatement::DynareSensitivityStatement(OptionsList options_list_arg) : SensitivityStatement::SensitivityStatement(OptionsList options_list_arg) :
options_list {move(options_list_arg)} options_list {move(options_list_arg)}
{ {
} }
void void
DynareSensitivityStatement::checkPass(ModFileStructure& mod_file_struct, SensitivityStatement::checkPass(ModFileStructure& mod_file_struct,
[[maybe_unused]] WarningConsolidation& warnings) [[maybe_unused]] WarningConsolidation& warnings)
{ {
if (auto opt = options_list.get_if<OptionsList::NumVal>("identification"); opt && *opt == "1") if (auto opt = options_list.get_if<OptionsList::NumVal>("identification"); opt && *opt == "1")
{ {
@ -1089,8 +1090,8 @@ DynareSensitivityStatement::checkPass(ModFileStructure& mod_file_struct,
} }
void void
DynareSensitivityStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename, SensitivityStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
options_list.writeOutput(output, "options_gsa"); options_list.writeOutput(output, "options_gsa");
@ -1106,13 +1107,13 @@ DynareSensitivityStatement::writeOutput(ostream& output, [[maybe_unused]] const
if (auto opt = options_list.get_if<OptionsList::SymbolListVal>("graph_format")) if (auto opt = options_list.get_if<OptionsList::SymbolListVal>("graph_format"))
opt->writeOutput("options_.graph_format", output); opt->writeOutput("options_.graph_format", output);
output << "dynare_sensitivity(M_,oo_,options_,bayestopt_,estim_params_,options_gsa);" << endl; output << "gsa.run(M_,oo_,options_,bayestopt_,estim_params_,options_gsa);" << endl;
} }
void void
DynareSensitivityStatement::writeJsonOutput(ostream& output) const SensitivityStatement::writeJsonOutput(ostream& output) const
{ {
output << R"({"statementName": "dynare_sensitivity")"; output << R"({"statementName": "sensitivity")";
if (!options_list.empty()) if (!options_list.empty())
{ {
output << ", "; output << ", ";
@ -2941,7 +2942,7 @@ IdentificationStatement::writeOutput(ostream& output, [[maybe_unused]] const str
if (auto opt = options_list.get_if<OptionsList::SymbolListVal>("graph_format")) if (auto opt = options_list.get_if<OptionsList::SymbolListVal>("graph_format"))
opt->writeOutput("options_.graph_format", output); opt->writeOutput("options_.graph_format", output);
output << "dynare_identification(M_,oo_,options_,bayestopt_,estim_params_," output << "identification.run(M_,oo_,options_,bayestopt_,estim_params_,"
<< "options_ident);" << endl; << "options_ident);" << endl;
} }
@ -3331,7 +3332,9 @@ ConditionalForecastStatement::writeOutput(ostream& output, [[maybe_unused]] cons
[[maybe_unused]] bool minimal_workspace) const [[maybe_unused]] bool minimal_workspace) const
{ {
options_list.writeOutput(output, "options_cond_fcst_"); options_list.writeOutput(output, "options_cond_fcst_");
output << "imcforecast(constrained_paths_, constrained_vars_, options_cond_fcst_);" << endl; output << "oo_.conditional_forecast=conditional_forecasts.run(M_,options_,"
<< "oo_,bayestopt_,estim_params_,constrained_paths_, constrained_vars_,"
<< "options_cond_fcst_);" << endl;
} }
void void
@ -3347,10 +3350,9 @@ ConditionalForecastStatement::writeJsonOutput(ostream& output) const
} }
PlotConditionalForecastStatement::PlotConditionalForecastStatement( PlotConditionalForecastStatement::PlotConditionalForecastStatement(
optional<int> periods_arg, SymbolList symbol_list_arg, const SymbolTable& symbol_table_arg) : const optional<int>& periods_arg, SymbolList symbol_list_arg,
periods {move(periods_arg)}, const SymbolTable& symbol_table_arg) :
symbol_list {move(symbol_list_arg)}, periods {periods_arg}, symbol_list {move(symbol_list_arg)}, symbol_table {symbol_table_arg}
symbol_table {symbol_table_arg}
{ {
} }
@ -3376,9 +3378,9 @@ PlotConditionalForecastStatement::writeOutput(ostream& output,
{ {
symbol_list.writeOutput("var_list_", output); symbol_list.writeOutput("var_list_", output);
if (periods) if (periods)
output << "plot_icforecast(var_list_, " << *periods << ",options_,oo_);" << endl; output << "conditional_forecasts.plot(var_list_, " << *periods << ",options_,oo_);" << endl;
else else
output << "plot_icforecast(var_list_,[],options_,oo_);" << endl; output << "conditional_forecasts.plot(var_list_,[],options_,oo_);" << endl;
} }
void void
@ -5058,7 +5060,8 @@ ExtendedPathStatement::writeOutput(ostream& output, [[maybe_unused]] const strin
options_list_new.erase("periods"); options_list_new.erase("periods");
options_list_new.writeOutput(output); options_list_new.writeOutput(output);
output << "extended_path([], " << periods << ", [], options_, M_, oo_);" << endl; output << "[Simulated_time_series, oo_] = extended_path([], " << periods
<< ", [], options_, M_, oo_);" << endl;
} }
void void
@ -5480,3 +5483,103 @@ ResidStatement::writeJsonOutput(ostream& output) const
} }
output << "}"; output << "}";
} }
MatchedIrfsStatement::MatchedIrfsStatement(matched_irfs_t values_weights_arg, bool overwrite_arg) :
values_weights {move(values_weights_arg)}, overwrite {overwrite_arg}
{
}
void
MatchedIrfsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
if (overwrite)
output << "M_.matched_irfs = {};" << endl;
for (const auto& [key, vec] : values_weights)
{
const auto& [endo, exo] = key;
output << "M_.matched_irfs = [M_.matched_irfs; {'" << endo << "', '" << exo << "', {";
for (const auto& [p1, p2, value, weight] : vec)
{
output << p1 << ":" << p2 << ", ";
value->writeOutput(output);
output << ", ";
weight->writeOutput(output);
output << "; ";
}
output << "}}];" << endl;
}
}
void
MatchedIrfsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "matched_irfs")"
<< R"(, "overwrite": )" << boolalpha << overwrite << R"(, "contents": [)";
for (bool printed_something {false}; const auto& [key, vec] : values_weights)
{
if (exchange(printed_something, true))
output << ", ";
const auto& [endo, exo] = key;
output << R"({"var": ")" << endo << R"(", "varexo": ")" << exo
<< R"(", "periods_values_weights": [)";
for (bool printed_something2 {false}; const auto& [p1, p2, value, weight] : vec)
{
if (exchange(printed_something2, true))
output << ", ";
output << R"({"period1": )" << p1 << ", "
<< R"("period2": })" << p2 << ", "
<< R"("value": ")";
value->writeJsonOutput(output, {}, {});
output << R"(", "weight": ")";
weight->writeJsonOutput(output, {}, {});
output << R"("})";
}
output << "]}";
}
output << "]}";
}
MatchedIrfsWeightsStatement::MatchedIrfsWeightsStatement(matched_irfs_weights_t weights_arg,
bool overwrite_arg) :
weights {move(weights_arg)}, overwrite {overwrite_arg}
{
}
void
MatchedIrfsWeightsStatement::writeOutput(ostream& output, [[maybe_unused]] const string& basename,
[[maybe_unused]] bool minimal_workspace) const
{
if (overwrite)
output << "M_.matched_irfs_weights = {};" << endl;
for (const auto& [key, val] : weights)
{
const auto& [endo1, periods1, exo1, endo2, periods2, exo2] = key;
output << "M_.matched_irfs_weights = [M_.matched_irfs_weights; {'" << endo1 << "', "
<< periods1 << ", '" << exo1 << "', '" << endo2 << "', " << periods2 << ", '" << exo2
<< "', ";
val->writeOutput(output);
output << "}];" << endl;
}
}
void
MatchedIrfsWeightsStatement::writeJsonOutput(ostream& output) const
{
output << R"({"statementName": "matched_irfs_weights")"
<< R"(, "overwrite": )" << boolalpha << overwrite << R"(, "contents": [)";
for (bool printed_something {false}; const auto& [key, val] : weights)
{
const auto& [endo1, periods1, exo1, endo2, periods2, exo2] = key;
if (exchange(printed_something, true))
output << ", ";
output << R"({"endo1": ")" << endo1 << R"(", "periods1": ")" << periods1 << R"(", "exo1": )"
<< exo1 << R"(", "endo2": ")" << endo2 << R"(", "periods2": ")" << periods2
<< R"(", "exo2": )" << exo2 << R"(", "weight": ")";
val->writeJsonOutput(output, {}, {});
output << R"("})";
}
output << "]}";
}

View File

@ -334,13 +334,13 @@ public:
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
}; };
class DynareSensitivityStatement : public Statement class SensitivityStatement : public Statement
{ {
private: private:
const OptionsList options_list; const OptionsList options_list;
public: public:
explicit DynareSensitivityStatement(OptionsList options_list_arg); explicit SensitivityStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
@ -929,7 +929,7 @@ private:
const SymbolTable& symbol_table; const SymbolTable& symbol_table;
public: public:
PlotConditionalForecastStatement(optional<int> periods_arg, SymbolList symbol_list_arg, PlotConditionalForecastStatement(const optional<int>& periods_arg, SymbolList symbol_list_arg,
const SymbolTable& symbol_table_arg); const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override; void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override; void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
@ -1332,4 +1332,33 @@ public:
void writeJsonOutput(ostream& output) const override; void writeJsonOutput(ostream& output) const override;
}; };
class MatchedIrfsStatement : public Statement
{
public:
// (endo name, exo name) → vector of (period start, period end, value, weight)
using matched_irfs_t = map<pair<string, string>, vector<tuple<int, int, expr_t, expr_t>>>;
MatchedIrfsStatement(matched_irfs_t values_weights_arg, bool overwrite_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
private:
const matched_irfs_t values_weights;
const bool overwrite;
};
class MatchedIrfsWeightsStatement : public Statement
{
public:
/* (endo1 name, period index or range for endo1, exo1 name, endo2 name, period index or range for
endo2, exo2 name) weight */
using matched_irfs_weights_t = map<tuple<string, string, string, string, string, string>, expr_t>;
MatchedIrfsWeightsStatement(matched_irfs_weights_t weights_arg, bool overwrite_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
private:
const matched_irfs_weights_t weights;
const bool overwrite;
};
#endif #endif

View File

@ -20,9 +20,13 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <utility> #include <utility>
#include <vector>
#include "ConfigFile.hh" #ifdef _WIN32
# include <shlobj.h>
#endif
#include "Configuration.hh"
#include "DataTree.hh" // For strsplit()
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wold-style-cast"
@ -31,19 +35,7 @@
#include <boost/tokenizer.hpp> #include <boost/tokenizer.hpp>
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
using namespace std; Configuration::Path::Path(vector<string> includepath_arg)
Hook::Hook(string global_init_file_arg)
{
if (global_init_file_arg.empty())
{
cerr << "ERROR: The Hook must have a Global Initialization File argument." << endl;
exit(EXIT_FAILURE);
}
hooks["global_init_file"] = move(global_init_file_arg);
}
Path::Path(vector<string> includepath_arg)
{ {
if (includepath_arg.empty()) if (includepath_arg.empty())
{ {
@ -53,12 +45,13 @@ Path::Path(vector<string> includepath_arg)
paths["include"] = move(includepath_arg); paths["include"] = move(includepath_arg);
} }
FollowerNode::FollowerNode(string computerName_arg, string port_arg, int minCpuNbr_arg, Configuration::FollowerNode::FollowerNode(string computerName_arg, string port_arg,
int maxCpuNbr_arg, string userName_arg, string password_arg, int minCpuNbr_arg, int maxCpuNbr_arg, string userName_arg,
string remoteDrive_arg, string remoteDirectory_arg, string password_arg, string remoteDrive_arg,
string programPath_arg, string programConfig_arg, string remoteDirectory_arg, string programPath_arg,
string matlabOctavePath_arg, bool singleCompThread_arg, string programConfig_arg, string matlabOctavePath_arg,
int numberOfThreadsPerJob_arg, string operatingSystem_arg) : bool singleCompThread_arg, int numberOfThreadsPerJob_arg,
string operatingSystem_arg) :
computerName {move(computerName_arg)}, computerName {move(computerName_arg)},
port {move(port_arg)}, port {move(port_arg)},
minCpuNbr {minCpuNbr_arg}, minCpuNbr {minCpuNbr_arg},
@ -89,7 +82,8 @@ FollowerNode::FollowerNode(string computerName_arg, string port_arg, int minCpuN
} }
} }
Cluster::Cluster(member_nodes_t member_nodes_arg) : member_nodes {move(member_nodes_arg)} Configuration::Cluster::Cluster(member_nodes_t member_nodes_arg) :
member_nodes {move(member_nodes_arg)}
{ {
if (member_nodes.empty()) if (member_nodes.empty())
{ {
@ -98,9 +92,9 @@ Cluster::Cluster(member_nodes_t member_nodes_arg) : member_nodes {move(member_no
} }
} }
ConfigFile::ConfigFile(bool parallel_arg, bool parallel_test_arg, Configuration::Configuration(bool parallel_arg, bool parallel_test_arg,
bool parallel_follower_open_mode_arg, bool parallel_use_psexec_arg, bool parallel_follower_open_mode_arg, bool parallel_use_psexec_arg,
string cluster_name_arg) : string cluster_name_arg) :
parallel {parallel_arg}, parallel {parallel_arg},
parallel_test {parallel_test_arg}, parallel_test {parallel_test_arg},
parallel_follower_open_mode {parallel_follower_open_mode_arg}, parallel_follower_open_mode {parallel_follower_open_mode_arg},
@ -110,68 +104,63 @@ ConfigFile::ConfigFile(bool parallel_arg, bool parallel_test_arg,
} }
void void
ConfigFile::getConfigFileInfo(const filesystem::path& config_file) Configuration::getConfigFileInfo(const filesystem::path& conffile_option,
WarningConsolidation& warnings)
{ {
using namespace boost; using namespace boost;
ifstream configFile;
filesystem::path config_file {conffile_option};
if (config_file.empty()) if (config_file.empty())
{ {
filesystem::path defaultConfigFile; config_file = findConfigFile("dynare.ini");
// Test OS and try to open default file
#if defined(_WIN32) || defined(__CYGWIN32__)
if (auto appdata = getenv("APPDATA"); appdata)
defaultConfigFile = filesystem::path {appdata} / "dynare.ini";
else
{
if (parallel || parallel_test)
cerr << "ERROR: ";
else
cerr << "WARNING: ";
cerr << "APPDATA environment variable not found." << endl;
if (parallel || parallel_test) if (config_file.empty()) // Try old default location (Dynare ⩽ 5) for backward compatibility
exit(EXIT_FAILURE); {
} filesystem::path old_default_config_file;
#ifdef _WIN32
array<wchar_t, MAX_PATH + 1> appdata;
if (SHGetFolderPathW(nullptr, CSIDL_APPDATA | CSIDL_FLAG_DONT_VERIFY, nullptr,
SHGFP_TYPE_CURRENT, appdata.data())
== S_OK)
old_default_config_file = filesystem::path {appdata.data()} / "dynare.ini";
#else #else
if (auto home = getenv("HOME"); home) if (auto home = getenv("HOME"); home)
defaultConfigFile = filesystem::path {home} / ".dynare"; old_default_config_file = filesystem::path {home} / ".dynare";
else
{
if (parallel || parallel_test)
cerr << "ERROR: ";
else
cerr << "WARNING: ";
cerr << "HOME environment variable not found." << endl;
if (parallel || parallel_test)
exit(EXIT_FAILURE);
}
#endif #endif
configFile.open(defaultConfigFile, fstream::in); if (!old_default_config_file.empty() && exists(old_default_config_file))
if (!configFile.is_open())
{
if (parallel || parallel_test)
{ {
cerr << "ERROR: Could not open the default config file (" warnings << "WARNING: the location " << old_default_config_file.string()
<< defaultConfigFile.string() << ")" << endl; << " for the configuration file is obsolete; please see the reference"
exit(EXIT_FAILURE); << " manual for the new location." << endl;
config_file = old_default_config_file;
} }
else
return;
} }
} }
else
if (config_file.empty())
{ {
configFile.open(config_file, fstream::in); if (parallel || parallel_test)
if (!configFile.is_open())
{ {
cerr << "ERROR: Couldn't open file " << config_file.string() << endl; cerr << "ERROR: the parallel or parallel_test option was passed but no configuration "
<< "file was found" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
else
return;
}
ifstream configFile;
configFile.open(config_file, fstream::in);
if (!configFile.is_open())
{
cerr << "ERROR: Couldn't open configuration file " << config_file.string() << endl;
exit(EXIT_FAILURE);
} }
string name, computerName, port, userName, password, remoteDrive, remoteDirectory, programPath, string name, computerName, port, userName, password, remoteDrive, remoteDirectory, programPath,
programConfig, matlabOctavePath, operatingSystem, global_init_file; programConfig, matlabOctavePath, operatingSystem;
vector<string> includepath; vector<string> includepath;
int minCpuNbr {0}, maxCpuNbr {0}; int minCpuNbr {0}, maxCpuNbr {0};
int numberOfThreadsPerJob {1}; int numberOfThreadsPerJob {1};
@ -190,10 +179,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path& config_file)
if (line == "[node]" || line == "[cluster]" || line == "[hooks]" || line == "[paths]") if (line == "[node]" || line == "[cluster]" || line == "[hooks]" || line == "[paths]")
{ {
if (!global_init_file.empty()) if (!includepath.empty())
// we were just in [hooks]
addHooksConfFileElement(global_init_file);
else if (!includepath.empty())
// we were just in [paths] // we were just in [paths]
addPathsConfFileElement(includepath); addPathsConfFileElement(includepath);
else else
@ -234,8 +220,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path& config_file)
} }
name = userName = computerName = port = password = remoteDrive = remoteDirectory name = userName = computerName = port = password = remoteDrive = remoteDirectory
= programPath = programConfig = matlabOctavePath = operatingSystem = global_init_file = programPath = programConfig = matlabOctavePath = operatingSystem = "";
= "";
includepath.clear(); includepath.clear();
minCpuNbr = maxCpuNbr = 0; minCpuNbr = maxCpuNbr = 0;
numberOfThreadsPerJob = 1; numberOfThreadsPerJob = 1;
@ -455,9 +440,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path& config_file)
} }
} }
if (!global_init_file.empty()) if (!includepath.empty())
addHooksConfFileElement(global_init_file);
else if (!includepath.empty())
addPathsConfFileElement(includepath); addPathsConfFileElement(includepath);
else else
addParallelConfFileElement(inNode, inCluster, member_nodes, name, computerName, port, minCpuNbr, addParallelConfFileElement(inNode, inCluster, member_nodes, name, computerName, port, minCpuNbr,
@ -469,20 +452,7 @@ ConfigFile::getConfigFileInfo(const filesystem::path& config_file)
} }
void void
ConfigFile::addHooksConfFileElement(string global_init_file) Configuration::addPathsConfFileElement(vector<string> includepath)
{
if (global_init_file.empty())
{
cerr << "ERROR: The global initialization file must be passed to the GlobalInitFile option."
<< endl;
exit(EXIT_FAILURE);
}
else
hooks.emplace_back(move(global_init_file));
}
void
ConfigFile::addPathsConfFileElement(vector<string> includepath)
{ {
if (includepath.empty()) if (includepath.empty())
{ {
@ -494,15 +464,15 @@ ConfigFile::addPathsConfFileElement(vector<string> includepath)
} }
void void
ConfigFile::addParallelConfFileElement(bool inNode, bool inCluster, Configuration::addParallelConfFileElement(bool inNode, bool inCluster,
const member_nodes_t& member_nodes, const string& name, const member_nodes_t& member_nodes, const string& name,
const string& computerName, const string& port, const string& computerName, const string& port,
int minCpuNbr, int maxCpuNbr, const string& userName, int minCpuNbr, int maxCpuNbr, const string& userName,
const string& password, const string& remoteDrive, const string& password, const string& remoteDrive,
const string& remoteDirectory, const string& programPath, const string& remoteDirectory, const string& programPath,
const string& programConfig, const string& matlabOctavePath, const string& programConfig,
bool singleCompThread, int numberOfThreadsPerJob, const string& matlabOctavePath, bool singleCompThread,
const string& operatingSystem) int numberOfThreadsPerJob, const string& operatingSystem)
{ {
//! ADD NODE //! ADD NODE
if (inNode) if (inNode)
@ -546,17 +516,8 @@ ConfigFile::addParallelConfFileElement(bool inNode, bool inCluster,
} }
void void
ConfigFile::checkPass([[maybe_unused]] WarningConsolidation& warnings) const Configuration::checkPass([[maybe_unused]] WarningConsolidation& warnings) const
{ {
for (bool global_init_file_declared {false}; const auto& hook : hooks)
for (const auto& mapit : hook.get_hooks())
if (mapit.first == "global_init_file")
if (exchange(global_init_file_declared, true))
{
cerr << "ERROR: Only one global initialization file may be provided." << endl;
exit(EXIT_FAILURE);
}
if (!parallel && !parallel_test) if (!parallel && !parallel_test)
return; return;
@ -684,8 +645,14 @@ ConfigFile::checkPass([[maybe_unused]] WarningConsolidation& warnings) const
} }
void void
ConfigFile::transformPass() Configuration::transformPass()
{ {
/* If the user did not specify the GlobalInitFile option, use global_init.m in configuration
directory if it exists */
if (auto default_global_init_file = findConfigFile("global_init.m");
global_init_file.empty() && !default_global_init_file.empty())
global_init_file = default_global_init_file.string();
if (!parallel && !parallel_test) if (!parallel && !parallel_test)
return; return;
@ -711,10 +678,10 @@ ConfigFile::transformPass()
} }
vector<filesystem::path> vector<filesystem::path>
ConfigFile::getIncludePaths() const Configuration::getIncludePaths() const
{ {
vector<filesystem::path> include_paths; vector<filesystem::path> include_paths;
for (auto path : paths) for (const auto& path : paths)
for (const auto& mapit : path.get_paths()) for (const auto& mapit : path.get_paths())
for (const auto& vecit : mapit.second) for (const auto& vecit : mapit.second)
include_paths.emplace_back(vecit); include_paths.emplace_back(vecit);
@ -722,15 +689,14 @@ ConfigFile::getIncludePaths() const
} }
void void
ConfigFile::writeHooks(ostream& output) const Configuration::writeHooks(ostream& output) const
{ {
for (auto hook : hooks) if (!global_init_file.empty())
for (const auto& mapit : hook.get_hooks()) output << "options_.global_init_file = '" << global_init_file << "';" << endl;
output << "options_." << mapit.first << " = '" << mapit.second << "';" << endl;
} }
void void
ConfigFile::writeCluster(ostream& output) const Configuration::writeCluster(ostream& output) const
{ {
if (!parallel && !parallel_test) if (!parallel && !parallel_test)
return; return;
@ -804,7 +770,7 @@ ConfigFile::writeCluster(ostream& output) const
} }
void void
ConfigFile::writeEndParallel(ostream& output) const Configuration::writeEndParallel(ostream& output) const
{ {
if ((!parallel && !parallel_test) || !parallel_follower_open_mode) if ((!parallel && !parallel_test) || !parallel_follower_open_mode)
return; return;
@ -813,3 +779,46 @@ ConfigFile::writeEndParallel(ostream& output) const
<< " closeSlave(options_.parallel,options_.parallel_info.RemoteTmpFolder);" << endl << " closeSlave(options_.parallel,options_.parallel_info.RemoteTmpFolder);" << endl
<< "end" << endl; << "end" << endl;
} }
filesystem::path
Configuration::findConfigFile(const string& filename)
{
#ifdef _WIN32
array<wchar_t, MAX_PATH + 1> appdata;
if (SHGetFolderPathW(nullptr, CSIDL_APPDATA | CSIDL_FLAG_DONT_VERIFY, nullptr, SHGFP_TYPE_CURRENT,
appdata.data())
== S_OK)
{
filesystem::path candidate {filesystem::path {appdata.data()} / "dynare" / filename};
if (exists(candidate))
return candidate;
}
#else
filesystem::path xdg_config_home;
if (auto xdg_config_home_env = getenv("XDG_CONFIG_HOME"); xdg_config_home_env)
xdg_config_home = xdg_config_home_env;
if (auto home = getenv("HOME"); xdg_config_home.empty() && home)
xdg_config_home = filesystem::path {home} / ".config";
if (!xdg_config_home.empty())
{
filesystem::path candidate {xdg_config_home / "dynare" / filename};
if (exists(candidate))
return candidate;
}
string xdg_config_dirs;
if (auto xdg_config_dirs_env = getenv("XDG_CONFIG_DIRS"); xdg_config_dirs_env)
xdg_config_dirs = xdg_config_dirs_env;
if (xdg_config_dirs.empty())
xdg_config_dirs = "/etc/xdg";
for (const auto& dir : DataTree::strsplit(xdg_config_dirs, ':'))
{
filesystem::path candidate {filesystem::path {dir} / "dynare" / filename};
if (exists(candidate))
return candidate;
}
#endif
return {};
}

View File

@ -17,8 +17,8 @@
* along with Dynare. If not, see <https://www.gnu.org/licenses/>. * along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef CONFIG_FILE_HH #ifndef CONFIGURATION_HH
#define CONFIG_FILE_HH #define CONFIGURATION_HH
#include <filesystem> #include <filesystem>
#include <map> #include <map>
@ -28,94 +28,65 @@
using namespace std; using namespace std;
using member_nodes_t = map<string, double>; /* The abstract representation of the configuration.
Merges information from the command-line and from the configuration file. */
class Hook class Configuration
{ {
public: public:
explicit Hook(string global_init_file_arg); Configuration(bool parallel_arg, bool parallel_test_arg, bool parallel_follower_open_mode_arg,
bool parallel_use_psexec_arg, string cluster_name);
private: private:
map<string, string> hooks; using member_nodes_t = map<string, double>;
public: class Path
[[nodiscard]] map<string, string>
get_hooks() const
{ {
return hooks; public:
explicit Path(vector<string> includepath_arg);
[[nodiscard]] map<string, vector<string>>
get_paths() const
{
return paths;
};
private:
map<string, vector<string>> paths;
}; };
};
class Path struct FollowerNode
{
public:
explicit Path(vector<string> includepath_arg);
private:
map<string, vector<string>> paths;
public:
[[nodiscard]] map<string, vector<string>>
get_paths() const
{ {
return paths; FollowerNode(string computerName_arg, string port_arg, int minCpuNbr_arg, int maxCpuNbr_arg,
string userName_arg, string password_arg, string remoteDrive_arg,
string remoteDirectory_arg, string programPath_arg, string programConfig_arg,
string matlabOctavePath_arg, bool singleCompThread_arg,
int numberOfThreadsPerJob_arg, string operatingSystem_arg);
const string computerName, port;
int minCpuNbr, maxCpuNbr;
const string userName, password;
const string remoteDrive, remoteDirectory;
const string programPath, programConfig, matlabOctavePath;
const bool singleCompThread;
const int numberOfThreadsPerJob;
const string operatingSystem;
}; };
};
class FollowerNode struct Cluster
{ {
friend class ConfigFile; explicit Cluster(member_nodes_t member_nodes_arg);
member_nodes_t member_nodes;
};
public:
FollowerNode(string computerName_arg, string port_arg, int minCpuNbr_arg, int maxCpuNbr_arg,
string userName_arg, string password_arg, string remoteDrive_arg,
string remoteDirectory_arg, string programPath_arg, string programConfig_arg,
string matlabOctavePath_arg, bool singleCompThread_arg,
int numberOfThreadsPerJob_arg, string operatingSystem_arg);
protected:
const string computerName, port;
int minCpuNbr, maxCpuNbr;
const string userName, password;
const string remoteDrive, remoteDirectory;
const string programPath, programConfig, matlabOctavePath;
const bool singleCompThread;
const int numberOfThreadsPerJob;
const string operatingSystem;
};
class Cluster
{
friend class ConfigFile;
public:
explicit Cluster(member_nodes_t member_nodes_arg);
protected:
member_nodes_t member_nodes;
};
//! The abstract representation of a "config" file
class ConfigFile
{
public:
ConfigFile(bool parallel_arg, bool parallel_test_arg, bool parallel_follower_open_mode_arg,
bool parallel_use_psexec_arg, string cluster_name);
private:
const bool parallel, parallel_test, parallel_follower_open_mode, parallel_use_psexec; const bool parallel, parallel_test, parallel_follower_open_mode, parallel_use_psexec;
const string cluster_name; const string cluster_name;
string firstClusterName; string firstClusterName;
//! Hooks //! Hooks
vector<Hook> hooks; string global_init_file;
//! Paths //! Paths
vector<Path> paths; vector<Path> paths;
//! Cluster Table //! Cluster Table
map<string, Cluster> clusters; map<string, Cluster> clusters;
//! Node Map //! Node Map
map<string, FollowerNode> follower_nodes; map<string, FollowerNode> follower_nodes;
//! Add Hooks
void addHooksConfFileElement(string global_init_file);
//! Add Paths //! Add Paths
void addPathsConfFileElement(vector<string> includepath); void addPathsConfFileElement(vector<string> includepath);
//! Add a FollowerNode or a Cluster object //! Add a FollowerNode or a Cluster object
@ -127,10 +98,17 @@ private:
const string& programPath, const string& programConfig, const string& programPath, const string& programConfig,
const string& matlabOctavePath, bool singleCompThread, const string& matlabOctavePath, bool singleCompThread,
int numberOfThreadsPerJob, const string& operatingSystem); int numberOfThreadsPerJob, const string& operatingSystem);
/* Given a filename (e.g. dynare.ini), looks for it in the configuration directory:
if under Linux or macOS, look into the dynare subdirectory of the XDG
configuration directories (following the default values and the precedence order specified in
the XDG specification)
if under Windows, look into %APPDATA%\dynare\
The returned path will be empty if the file is not found. */
[[nodiscard]] static filesystem::path findConfigFile(const string& filename);
public: public:
//! Parse config file //! Parse config file
void getConfigFileInfo(const filesystem::path& parallel_config_file); void getConfigFileInfo(const filesystem::path& conffile_option, WarningConsolidation& warnings);
//! Check Pass //! Check Pass
void checkPass(WarningConsolidation& warnings) const; void checkPass(WarningConsolidation& warnings) const;
//! Check Pass //! Check Pass

View File

@ -946,10 +946,10 @@ DataTree::strsplit(string_view str, char delim)
} }
filesystem::path filesystem::path
DataTree::packageDir(string_view package) DataTree::packageDir(const string_view& package)
{ {
filesystem::path d; filesystem::path d;
for (const auto& it : strsplit(move(package), '.')) for (const auto& it : strsplit(package, '.'))
d /= "+" + it; d /= "+" + it;
return d; return d;
} }

View File

@ -384,7 +384,7 @@ public:
and returns the path to the corresponding filesystem directory. and returns the path to the corresponding filesystem directory.
In practice the package nesting is used for the planner_objective (stored In practice the package nesting is used for the planner_objective (stored
inside +objective subdir). */ inside +objective subdir). */
static filesystem::path packageDir(string_view package); static filesystem::path packageDir(const string_view& package);
}; };
inline expr_t inline expr_t

View File

@ -164,11 +164,11 @@ DynamicModel::writeDynamicBytecode(const string& basename) const
writeBytecodeBinFile(basename + "/model/bytecode/dynamic.bin", writeBytecodeBinFile(basename + "/model/bytecode/dynamic.bin",
simulation_type == BlockSimulationType::solveTwoBoundariesComplete)}; simulation_type == BlockSimulationType::solveTwoBoundariesComplete)};
BytecodeWriter code_file {basename + "/model/bytecode/dynamic.cod"}; Bytecode::Writer code_file {basename + "/model/bytecode/dynamic.cod"};
// Declare temporary terms // Declare temporary terms
code_file << FDIMT_ {static_cast<int>(temporary_terms_derivatives[0].size() code_file << Bytecode::FDIMT {static_cast<int>(temporary_terms_derivatives[0].size()
+ temporary_terms_derivatives[1].size())}; + temporary_terms_derivatives[1].size())};
// Declare the (single) block // Declare the (single) block
vector<int> exo(symbol_table.exo_nbr()), exo_det(symbol_table.exo_det_nbr()); vector<int> exo(symbol_table.exo_nbr()), exo_det(symbol_table.exo_det_nbr());
@ -183,19 +183,19 @@ DynamicModel::writeDynamicBytecode(const string& basename) const
vector<int> endo_idx(symbol_table.endo_nbr()); vector<int> endo_idx(symbol_table.endo_nbr());
iota(endo_idx.begin(), endo_idx.end(), 0); iota(endo_idx.begin(), endo_idx.end(), 0);
code_file << FBEGINBLOCK_ {symbol_table.endo_nbr(), code_file << Bytecode::FBEGINBLOCK {symbol_table.endo_nbr(),
simulation_type, simulation_type,
0, 0,
symbol_table.endo_nbr(), symbol_table.endo_nbr(),
endo_idx, endo_idx,
eq_idx, eq_idx,
false, false,
u_count_int, u_count_int,
jacobian_ncols_endo, jacobian_ncols_endo,
symbol_table.exo_det_nbr(), symbol_table.exo_det_nbr(),
symbol_table.exo_nbr(), symbol_table.exo_nbr(),
exo_det, exo_det,
exo}; exo};
writeBytecodeHelper<true>(code_file); writeBytecodeHelper<true>(code_file);
} }
@ -203,7 +203,7 @@ DynamicModel::writeDynamicBytecode(const string& basename) const
void void
DynamicModel::writeDynamicBlockBytecode(const string& basename) const DynamicModel::writeDynamicBlockBytecode(const string& basename) const
{ {
BytecodeWriter code_file {basename + "/model/bytecode/block/dynamic.cod"}; Bytecode::Writer code_file {basename + "/model/bytecode/block/dynamic.cod"};
const filesystem::path bin_filename {basename + "/model/bytecode/block/dynamic.bin"}; const filesystem::path bin_filename {basename + "/model/bytecode/block/dynamic.bin"};
ofstream bin_file {bin_filename, ios::out | ios::binary}; ofstream bin_file {bin_filename, ios::out | ios::binary};
@ -214,7 +214,7 @@ DynamicModel::writeDynamicBlockBytecode(const string& basename) const
} }
// Temporary variables declaration // Temporary variables declaration
code_file << FDIMT_ {static_cast<int>(blocks_temporary_terms_idxs.size())}; code_file << Bytecode::FDIMT {static_cast<int>(blocks_temporary_terms_idxs.size())};
temporary_terms_t temporary_terms_written; temporary_terms_t temporary_terms_written;
@ -231,19 +231,19 @@ DynamicModel::writeDynamicBlockBytecode(const string& basename) const
? writeBlockBytecodeBinFile(bin_file, block) ? writeBlockBytecodeBinFile(bin_file, block)
: 0}; : 0};
code_file << FBEGINBLOCK_ {blocks[block].mfs_size, code_file << Bytecode::FBEGINBLOCK {blocks[block].mfs_size,
simulation_type, simulation_type,
blocks[block].first_equation, blocks[block].first_equation,
blocks[block].size, blocks[block].size,
endo_idx_block2orig, endo_idx_block2orig,
eq_idx_block2orig, eq_idx_block2orig,
blocks[block].linear, blocks[block].linear,
u_count, u_count,
static_cast<int>(blocks_jacob_cols_endo[block].size())}; static_cast<int>(blocks_jacob_cols_endo[block].size())};
writeBlockBytecodeHelper<true>(code_file, block, temporary_terms_written); writeBlockBytecodeHelper<true>(code_file, block, temporary_terms_written);
} }
code_file << FEND_ {}; code_file << Bytecode::FEND {};
} }
void void
@ -302,7 +302,7 @@ string
DynamicModel::reform(const string& name1) const DynamicModel::reform(const string& name1) const
{ {
string name = name1; string name = name1;
int pos = name.find(R"(\)", 0); int pos = name.find('\\', 0);
while (pos >= 0) while (pos >= 0)
{ {
if (name.substr(pos + 1, 1) != R"(\)") if (name.substr(pos + 1, 1) != R"(\)")
@ -311,7 +311,7 @@ DynamicModel::reform(const string& name1) const
pos++; pos++;
} }
pos++; pos++;
pos = name.find(R"(\)", pos); pos = name.find('\\', pos);
} }
return name; return name;
} }
@ -573,12 +573,12 @@ DynamicModel::parseIncludeExcludeEquations(const string& inc_exc_option_value, b
removeLeadingTrailingWhitespace(line); removeLeadingTrailingWhitespace(line);
if (!line.empty()) if (!line.empty())
{ {
if (tags.empty() && line.find("=") != string::npos) if (tags.empty() && line.find('=') != string::npos)
{ {
tagname_on_first_line = true; tagname_on_first_line = true;
tags += line + "("; tags += line + "(";
} }
else if (line.find("'") != string::npos) else if (line.find('\'') != string::npos)
tags += line + ","; tags += line + ",";
else else
tags += "'" + line + "',"; tags += "'" + line + "',";
@ -1212,7 +1212,7 @@ DynamicModel::updateVarAndTrendModel() const
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
trend_var.push_back(move(trend_var_symb_id)); trend_var.push_back(trend_var_symb_id);
} }
} }
@ -1906,7 +1906,7 @@ DynamicModel::analyzePacEquationStructure(const string& name, map<string, string
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
pac_equation_info[name] = {lhs, pac_equation_info[name] = {lhs,
move(optim_share_index), optim_share_index,
move(ar_params_and_vars), move(ar_params_and_vars),
move(ec_params_and_vars), move(ec_params_and_vars),
move(non_optim_vars_params_and_constants), move(non_optim_vars_params_and_constants),
@ -3575,14 +3575,15 @@ DynamicModel::fillEvalContext(eval_context_t& eval_context) const
} }
void void
DynamicModel::addStaticOnlyEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags) DynamicModel::addStaticOnlyEquation(expr_t eq, const optional<int>& lineno,
map<string, string> eq_tags)
{ {
auto beq = dynamic_cast<BinaryOpNode*>(eq); auto beq = dynamic_cast<BinaryOpNode*>(eq);
assert(beq && beq->op_code == BinaryOpcode::equal); assert(beq && beq->op_code == BinaryOpcode::equal);
static_only_equations_equation_tags.add(static_only_equations.size(), move(eq_tags)); static_only_equations_equation_tags.add(static_only_equations.size(), move(eq_tags));
static_only_equations.push_back(beq); static_only_equations.push_back(beq);
static_only_equations_lineno.push_back(move(lineno)); static_only_equations_lineno.push_back(lineno);
} }
size_t size_t
@ -3598,7 +3599,7 @@ DynamicModel::dynamicOnlyEquationsNbr() const
} }
void void
DynamicModel::addOccbinEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags, DynamicModel::addOccbinEquation(expr_t eq, const optional<int>& lineno, map<string, string> eq_tags,
const vector<string>& regimes_bind, const vector<string>& regimes_bind,
const vector<string>& regimes_relax) const vector<string>& regimes_relax)
{ {

View File

@ -428,7 +428,7 @@ public:
void replaceMyEquations(DynamicModel& dynamic_model) const; void replaceMyEquations(DynamicModel& dynamic_model) const;
//! Adds an equation marked as [static] //! Adds an equation marked as [static]
void addStaticOnlyEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags); void addStaticOnlyEquation(expr_t eq, const optional<int>& lineno, map<string, string> eq_tags);
//! Returns number of static only equations //! Returns number of static only equations
size_t staticOnlyEquationsNbr() const; size_t staticOnlyEquationsNbr() const;
@ -441,7 +441,7 @@ public:
auxiliary parameters have already been added to the symbol table. auxiliary parameters have already been added to the symbol table.
It also assumes that the bind and relax tags have been cleared from It also assumes that the bind and relax tags have been cleared from
eq_tags. */ eq_tags. */
void addOccbinEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags, void addOccbinEquation(expr_t eq, const optional<int>& lineno, map<string, string> eq_tags,
const vector<string>& regimes_bind, const vector<string>& regimes_relax); const vector<string>& regimes_bind, const vector<string>& regimes_relax);
//! Writes LaTeX file with the equations of the dynamic model //! Writes LaTeX file with the equations of the dynamic model

View File

@ -138,7 +138,7 @@ str_tolower(string s)
%token RELATIVE_IRF REPLIC SIMUL_REPLIC RPLOT SAVE_PARAMS_AND_STEADY_STATE PARAMETER_UNCERTAINTY TARGETS %token RELATIVE_IRF REPLIC SIMUL_REPLIC RPLOT SAVE_PARAMS_AND_STEADY_STATE PARAMETER_UNCERTAINTY TARGETS
%token SHOCKS HETEROSKEDASTIC_SHOCKS SHOCK_DECOMPOSITION SHOCK_GROUPS USE_SHOCK_GROUPS SIMUL SIMUL_ALGO SIMUL_SEED ENDOGENOUS_TERMINAL_PERIOD %token SHOCKS HETEROSKEDASTIC_SHOCKS SHOCK_DECOMPOSITION SHOCK_GROUPS USE_SHOCK_GROUPS SIMUL SIMUL_ALGO SIMUL_SEED ENDOGENOUS_TERMINAL_PERIOD
%token SMOOTHER SMOOTHER2HISTVAL SQUARE_ROOT_SOLVER STACK_SOLVE_ALGO STEADY_STATE_MODEL SOLVE_ALGO SOLVER_PERIODS ROBUST_LIN_SOLVE %token SMOOTHER SMOOTHER2HISTVAL SQUARE_ROOT_SOLVER STACK_SOLVE_ALGO STEADY_STATE_MODEL SOLVE_ALGO SOLVER_PERIODS ROBUST_LIN_SOLVE
%token STDERR STEADY STOCH_SIMUL SYLVESTER SYLVESTER_FIXED_POINT_TOL REGIMES REGIME REALTIME_SHOCK_DECOMPOSITION CONDITIONAL UNCONDITIONAL %token STDERR STEADY STOCH_SIMUL REGIMES REGIME REALTIME_SHOCK_DECOMPOSITION CONDITIONAL UNCONDITIONAL
%token TEX RAMSEY_MODEL RAMSEY_POLICY RAMSEY_CONSTRAINTS PLANNER_DISCOUNT PLANNER_DISCOUNT_LATEX_NAME %token TEX RAMSEY_MODEL RAMSEY_POLICY RAMSEY_CONSTRAINTS PLANNER_DISCOUNT PLANNER_DISCOUNT_LATEX_NAME
%token DISCRETIONARY_POLICY DISCRETIONARY_TOL EVALUATE_PLANNER_OBJECTIVE %token DISCRETIONARY_POLICY DISCRETIONARY_TOL EVALUATE_PLANNER_OBJECTIVE
%token OCCBIN_SETUP OCCBIN_SOLVER OCCBIN_WRITE_REGIMES OCCBIN_GRAPH SIMUL_MAXIT LIKELIHOOD_MAXIT SMOOTHER_MAXIT SIMUL_PERIODS LIKELIHOOD_PERIODS SMOOTHER_PERIODS %token OCCBIN_SETUP OCCBIN_SOLVER OCCBIN_WRITE_REGIMES OCCBIN_GRAPH SIMUL_MAXIT LIKELIHOOD_MAXIT SMOOTHER_MAXIT SIMUL_PERIODS LIKELIHOOD_PERIODS SMOOTHER_PERIODS
@ -161,7 +161,7 @@ str_tolower(string s)
%token EXP LOG LN LOG10 SIN COS TAN ASIN ACOS ATAN SINH COSH TANH ASINH ACOSH ATANH ERF ERFC DIFF ADL AUXILIARY_MODEL_NAME %token EXP LOG LN LOG10 SIN COS TAN ASIN ACOS ATAN SINH COSH TANH ASINH ACOSH ATANH ERF ERFC DIFF ADL AUXILIARY_MODEL_NAME
%token SQRT CBRT NORMCDF NORMPDF STEADY_STATE EXPECTATION %token SQRT CBRT NORMCDF NORMPDF STEADY_STATE EXPECTATION
/* GSA analysis */ /* GSA analysis */
%token DYNARE_SENSITIVITY MORRIS STAB REDFORM PPRIOR PRIOR_RANGE PPOST ILPTAU MORRIS_NLIV %token SENSITIVITY DYNARE_SENSITIVITY MORRIS STAB REDFORM PPRIOR PRIOR_RANGE PPOST ILPTAU MORRIS_NLIV
%token MORRIS_NTRA NSAM LOAD_REDFORM LOAD_RMSE LOAD_STAB ALPHA2_STAB LOGTRANS_REDFORM THRESHOLD_REDFORM %token MORRIS_NTRA NSAM LOAD_REDFORM LOAD_RMSE LOAD_STAB ALPHA2_STAB LOGTRANS_REDFORM THRESHOLD_REDFORM
%token KSSTAT_REDFORM ALPHA2_REDFORM NAMENDO NAMLAGENDO NAMEXO RMSE LIK_ONLY VAR_RMSE PFILT_RMSE ISTART_RMSE %token KSSTAT_REDFORM ALPHA2_REDFORM NAMENDO NAMLAGENDO NAMEXO RMSE LIK_ONLY VAR_RMSE PFILT_RMSE ISTART_RMSE
%token ALPHA_RMSE ALPHA2_RMSE %token ALPHA_RMSE ALPHA2_RMSE
@ -215,7 +215,7 @@ str_tolower(string s)
%token ENDVAL_STEADY STEADY_SOLVE_ALGO STEADY_MAXIT STEADY_TOLF STEADY_TOLX STEADY_MARKOWITZ %token ENDVAL_STEADY STEADY_SOLVE_ALGO STEADY_MAXIT STEADY_TOLF STEADY_TOLX STEADY_MARKOWITZ
%token HOMOTOPY_MAX_COMPLETION_SHARE HOMOTOPY_MIN_STEP_SIZE HOMOTOPY_INITIAL_STEP_SIZE HOMOTOPY_STEP_SIZE_INCREASE_SUCCESS_COUNT %token HOMOTOPY_MAX_COMPLETION_SHARE HOMOTOPY_MIN_STEP_SIZE HOMOTOPY_INITIAL_STEP_SIZE HOMOTOPY_STEP_SIZE_INCREASE_SUCCESS_COUNT
%token HOMOTOPY_LINEARIZATION_FALLBACK HOMOTOPY_MARGINAL_LINEARIZATION_FALLBACK FROM_INITVAL_TO_ENDVAL %token HOMOTOPY_LINEARIZATION_FALLBACK HOMOTOPY_MARGINAL_LINEARIZATION_FALLBACK FROM_INITVAL_TO_ENDVAL
%token STATIC_MFS RELATIVE_TO_INITVAL %token STATIC_MFS RELATIVE_TO_INITVAL MATCHED_IRFS MATCHED_IRFS_WEIGHTS WEIGHTS
%token <vector<string>> SYMBOL_VEC %token <vector<string>> SYMBOL_VEC
@ -236,7 +236,7 @@ str_tolower(string s)
%type <vector<int>> vec_int_elem vec_int_1 vec_int vec_int_number %type <vector<int>> vec_int_elem vec_int_1 vec_int vec_int_number
%type <PriorDistributions> prior_pdf prior_distribution %type <PriorDistributions> prior_pdf prior_distribution
%type <pair<expr_t,expr_t>> calibration_range %type <pair<expr_t,expr_t>> calibration_range
%type <pair<string,string>> partition_elem subsamples_eq_opt integer_range_w_inf tag_pair %type <pair<string,string>> partition_elem subsamples_eq_opt integer_range_w_inf tag_pair matched_irfs_elem_var_varexo
%type <vector<pair<string,string>>> partition partition_1 symbol_list_with_tex %type <vector<pair<string,string>>> partition partition_1 symbol_list_with_tex
%type <vector<map<string, string>>> tag_pair_list_for_selection %type <vector<map<string, string>>> tag_pair_list_for_selection
%type <map<string, string>> tag_pair_list %type <map<string, string>> tag_pair_list
@ -251,6 +251,12 @@ str_tolower(string s)
%type <vector<tuple<string, string, vector<pair<string, string>>>>> symbol_list_with_tex_and_partition %type <vector<tuple<string, string, vector<pair<string, string>>>>> symbol_list_with_tex_and_partition
%type <map<string, variant<bool, string>>> mshocks_options_list %type <map<string, variant<bool, string>>> mshocks_options_list
%type <pair<string, variant<bool, string>>> mshocks_option %type <pair<string, variant<bool, string>>> mshocks_option
%type <pair<vector<expr_t>, vector<expr_t>>> matched_irfs_elem_values_weights
%type <pair<pair<string, string>, vector<tuple<int, int, expr_t, expr_t>>>> matched_irfs_elem
%type <map<pair<string, string>, vector<tuple<int, int, expr_t, expr_t>>>> matched_irfs_list
%type <tuple<string, string, string>> matched_irfs_weights_elem_var_varexo
%type <pair<tuple<string, string, string, string, string, string>, expr_t>> matched_irfs_weights_elem
%type <map<tuple<string, string, string, string, string, string>, expr_t>> matched_irfs_weights_list
%% %%
%start statement_list; %start statement_list;
@ -326,7 +332,7 @@ statement : parameters
| bvar_forecast | bvar_forecast
| bvar_irf | bvar_irf
| sbvar | sbvar
| dynare_sensitivity | sensitivity
| homotopy_setup | homotopy_setup
| forecast | forecast
| load_params_and_steady_state | load_params_and_steady_state
@ -386,6 +392,8 @@ statement : parameters
| var_remove | var_remove
| pac_target_info | pac_target_info
| resid | resid
| matched_irfs
| matched_irfs_weights
; ;
dsample : DSAMPLE INT_NUMBER ';' dsample : DSAMPLE INT_NUMBER ';'
@ -1654,8 +1662,6 @@ method_of_moments_option : o_add_tiny_number_to_cholesky
| o_simulation_method | o_simulation_method
| o_simulation_multiple | o_simulation_multiple
| o_sub_draws | o_sub_draws
| o_sylvester
| o_sylvester_fixed_point_tol
| o_taper_steps | o_taper_steps
| o_tex | o_tex
| o_use_penalized_objective_for_hessian | o_use_penalized_objective_for_hessian
@ -1762,8 +1768,6 @@ stoch_simul_primary_options : o_solve_algo
| o_conditional_variance_decomposition | o_conditional_variance_decomposition
| o_k_order_solver | o_k_order_solver
| o_pruning | o_pruning
| o_sylvester
| o_sylvester_fixed_point_tol
| o_dr | o_dr
| o_dr_cycle_reduction_tol | o_dr_cycle_reduction_tol
| o_dr_logarithmic_reduction_tol | o_dr_logarithmic_reduction_tol
@ -2297,8 +2301,6 @@ estimation_options : o_datafile
| o_cova_compute | o_cova_compute
| o_irf_shocks | o_irf_shocks
| o_sub_draws | o_sub_draws
| o_sylvester
| o_sylvester_fixed_point_tol
| o_lyapunov | o_lyapunov
| o_lyapunov_fixed_point_tol | o_lyapunov_fixed_point_tol
| o_lyapunov_doubling_tol | o_lyapunov_doubling_tol
@ -3125,70 +3127,80 @@ ms_estimation : MS_ESTIMATION ';'
{ driver.ms_estimation(); } { driver.ms_estimation(); }
; ;
dynare_sensitivity : DYNARE_SENSITIVITY ';' sensitivity : SENSITIVITY ';'
{ driver.dynare_sensitivity(); } { driver.sensitivity(); }
| DYNARE_SENSITIVITY '(' dynare_sensitivity_options_list ')' ';' | SENSITIVITY '(' sensitivity_options_list ')' ';'
{ driver.dynare_sensitivity(); } { driver.sensitivity(); }
| DYNARE_SENSITIVITY ';'
{
driver.warning("The 'dynare_sensitivity' command is deprecated. It has been renamed 'sensitivity'.");
driver.sensitivity();
}
| DYNARE_SENSITIVITY '(' sensitivity_options_list ')' ';'
{
driver.warning("The 'dynare_sensitivity' command is deprecated. It has been renamed 'sensitivity'.");
driver.sensitivity();
}
;
sensitivity_options_list : sensitivity_option COMMA sensitivity_options_list
| sensitivity_option
;
sensitivity_option : o_gsa_identification
| o_gsa_morris
| o_gsa_stab
| o_gsa_redform
| o_gsa_pprior
| o_gsa_prior_range
| o_gsa_ppost
| o_gsa_ilptau
| o_gsa_morris_nliv
| o_gsa_morris_ntra
| o_gsa_nsam
| o_gsa_load_redform
| o_gsa_load_rmse
| o_gsa_load_stab
| o_gsa_alpha2_stab
| o_gsa_logtrans_redform
| o_gsa_ksstat_redform
| o_gsa_alpha2_redform
| o_gsa_rmse
| o_gsa_lik_only
| o_gsa_pfilt_rmse
| o_gsa_istart_rmse
| o_gsa_alpha_rmse
| o_gsa_alpha2_rmse
| o_gsa_threshold_redform
| o_gsa_namendo
| o_gsa_namexo
| o_gsa_namlagendo
| o_gsa_var_rmse
| o_gsa_neighborhood_width
| o_gsa_pvalue_ks
| o_gsa_pvalue_corr
| o_datafile
| o_nobs
| o_first_obs
| o_prefilter
| o_presample
| o_nograph
| o_nodisplay
| o_graph_format
| o_forecasts_conf_sig
| o_mh_conf_sig
| o_loglinear
| o_mode_file
| o_load_ident_files
| o_useautocorr
| o_ar
| o_kalman_algo
| o_lik_init
| o_diffuse_filter
| o_analytic_derivation
| o_analytic_derivation_mode
; ;
dynare_sensitivity_options_list : dynare_sensitivity_option COMMA dynare_sensitivity_options_list
| dynare_sensitivity_option
;
dynare_sensitivity_option : o_gsa_identification
| o_gsa_morris
| o_gsa_stab
| o_gsa_redform
| o_gsa_pprior
| o_gsa_prior_range
| o_gsa_ppost
| o_gsa_ilptau
| o_gsa_morris_nliv
| o_gsa_morris_ntra
| o_gsa_nsam
| o_gsa_load_redform
| o_gsa_load_rmse
| o_gsa_load_stab
| o_gsa_alpha2_stab
| o_gsa_logtrans_redform
| o_gsa_ksstat_redform
| o_gsa_alpha2_redform
| o_gsa_rmse
| o_gsa_lik_only
| o_gsa_pfilt_rmse
| o_gsa_istart_rmse
| o_gsa_alpha_rmse
| o_gsa_alpha2_rmse
| o_gsa_threshold_redform
| o_gsa_namendo
| o_gsa_namexo
| o_gsa_namlagendo
| o_gsa_var_rmse
| o_gsa_neighborhood_width
| o_gsa_pvalue_ks
| o_gsa_pvalue_corr
| o_datafile
| o_nobs
| o_first_obs
| o_prefilter
| o_presample
| o_nograph
| o_nodisplay
| o_graph_format
| o_forecasts_conf_sig
| o_mh_conf_sig
| o_loglinear
| o_mode_file
| o_load_ident_files
| o_useautocorr
| o_ar
| o_kalman_algo
| o_lik_init
| o_diffuse_filter
| o_analytic_derivation
| o_analytic_derivation_mode
;
shock_decomposition_options_list : shock_decomposition_option COMMA shock_decomposition_options_list shock_decomposition_options_list : shock_decomposition_option COMMA shock_decomposition_options_list
| shock_decomposition_option | shock_decomposition_option
; ;
@ -3544,6 +3556,108 @@ init2shocks_element : symbol symbol ';' { driver.add_init2shocks($1, $2); }
| symbol COMMA symbol ';' { driver.add_init2shocks($1, $3); } | symbol COMMA symbol ';' { driver.add_init2shocks($1, $3); }
; ;
matched_irfs : MATCHED_IRFS ';' matched_irfs_list END ';'
{ driver.matched_irfs($3, false); }
| MATCHED_IRFS '(' OVERWRITE ')' ';' matched_irfs_list END ';'
{ driver.matched_irfs($6, true); }
;
matched_irfs_list : matched_irfs_elem
{ $$ = {$1}; }
| matched_irfs_list matched_irfs_elem
{
$$ = $1;
auto [it, success] = $$.insert($2);
if (!success)
driver.error("matched_irfs: the pair endogenous " + $2.first.first + " with exogenous " + $2.first.second + " appears two times");
}
;
matched_irfs_elem : matched_irfs_elem_var_varexo
PERIODS period_list ';'
matched_irfs_elem_values_weights
{
if ($3.size() != $5.first.size())
driver.error("matched_irfs: the 'periods' and 'values' keywords are not followed by the same number of elements");
if ($3.size() != $5.second.size())
driver.error("matched_irfs: the 'periods' and 'values' keywords are not followed by the same number of elements");
vector<tuple<int, int, expr_t, expr_t>> v;
v.reserve($3.size());
for (size_t i {0}; i < $3.size(); i++)
v.emplace_back($3[i].first, $3[i].second, $5.first[i], $5.second[i]);
$$ = {$1, v};
}
;
matched_irfs_elem_var_varexo : VAR symbol ';' VAREXO symbol ';'
{
driver.check_symbol_is_endogenous($2);
driver.check_symbol_is_exogenous($5, false);
$$ = {$2, $5};
}
| VAREXO symbol ';' VAR symbol ';'
{
driver.check_symbol_is_endogenous($5);
driver.check_symbol_is_exogenous($2, false);
$$ = {$5, $2};
}
;
matched_irfs_elem_values_weights : VALUES value_list ';'
{
$$ = {$2, vector($2.size(),
driver.add_non_negative_constant("1"))};
}
| VALUES value_list ';' WEIGHTS value_list ';'
{ $$ = {$2, $5}; }
| WEIGHTS value_list ';' VALUES value_list ';'
{ $$ = {$5, $2}; }
;
matched_irfs_weights : MATCHED_IRFS_WEIGHTS ';' matched_irfs_weights_list END ';'
{ driver.matched_irfs_weights($3, false); }
| MATCHED_IRFS_WEIGHTS '(' OVERWRITE ')' ';' matched_irfs_weights_list END ';'
{ driver.matched_irfs_weights($6, true); }
;
matched_irfs_weights_list : matched_irfs_weights_elem
{ $$ = {$1}; }
| matched_irfs_weights_list matched_irfs_weights_elem
{
$$ = $1;
auto [it, success] = $$.insert($2);
if (!success)
driver.error("matched_irfs: the tuple (" + get<0>($2.first)
+ "(" + get<1>($2.first) + ")," + get<2>($2.first)
+ "," + get<3>($2.first) + "(" + get<4>($2.first) + "),"
+ get<5>($2.first) + ") appears two times");
}
;
matched_irfs_weights_elem : matched_irfs_weights_elem_var_varexo COMMA
matched_irfs_weights_elem_var_varexo COMMA
expression ';'
{
$$ = {{get<0>($1), get<1>($1), get<2>($1),
get<0>($3), get<1>($3), get<2>($3)},
$5};
}
;
matched_irfs_weights_elem_var_varexo : symbol '(' INT_NUMBER ')' COMMA symbol
{
driver.check_symbol_is_endogenous($1);
driver.check_symbol_is_exogenous($6, false);
$$ = {$1, $3, $6};
}
| symbol '(' integer_range ')' COMMA symbol
{
driver.check_symbol_is_endogenous($1);
driver.check_symbol_is_exogenous($6, false);
$$ = {$1, $3, $6};
}
;
o_solve_algo : SOLVE_ALGO EQUAL INT_NUMBER { driver.option_num("solve_algo", $3); }; o_solve_algo : SOLVE_ALGO EQUAL INT_NUMBER { driver.option_num("solve_algo", $3); };
o_stack_solve_algo : STACK_SOLVE_ALGO EQUAL INT_NUMBER { driver.option_num("stack_solve_algo", $3); }; o_stack_solve_algo : STACK_SOLVE_ALGO EQUAL INT_NUMBER { driver.option_num("stack_solve_algo", $3); };
o_robust_lin_solve : ROBUST_LIN_SOLVE { driver.option_num("simul.robust_lin_solve", "true"); }; o_robust_lin_solve : ROBUST_LIN_SOLVE { driver.option_num("simul.robust_lin_solve", "true"); };
@ -3818,9 +3932,6 @@ o_partial_information : PARTIAL_INFORMATION { driver.option_num("partial_informa
o_sub_draws: SUB_DRAWS EQUAL INT_NUMBER { driver.option_num("sub_draws", $3); }; o_sub_draws: SUB_DRAWS EQUAL INT_NUMBER { driver.option_num("sub_draws", $3); };
o_planner_discount : PLANNER_DISCOUNT EQUAL expression { driver.set_planner_discount($3); }; o_planner_discount : PLANNER_DISCOUNT EQUAL expression { driver.set_planner_discount($3); };
o_planner_discount_latex_name : PLANNER_DISCOUNT_LATEX_NAME EQUAL TEX_NAME { driver.set_planner_discount_latex_name($3); }; o_planner_discount_latex_name : PLANNER_DISCOUNT_LATEX_NAME EQUAL TEX_NAME { driver.set_planner_discount_latex_name($3); };
o_sylvester : SYLVESTER EQUAL FIXED_POINT { driver.option_num("sylvester_fp", "true"); }
| SYLVESTER EQUAL DEFAULT { driver.option_num("sylvester_fp", "false"); };
o_sylvester_fixed_point_tol : SYLVESTER_FIXED_POINT_TOL EQUAL non_negative_number { driver.option_num("sylvester_fixed_point_tol", $3); };
o_lyapunov : LYAPUNOV EQUAL FIXED_POINT { driver.option_num("lyapunov_fp", "true"); } o_lyapunov : LYAPUNOV EQUAL FIXED_POINT { driver.option_num("lyapunov_fp", "true"); }
| LYAPUNOV EQUAL DOUBLING { driver.option_num("lyapunov_db", "true"); } | LYAPUNOV EQUAL DOUBLING { driver.option_num("lyapunov_db", "true"); }
| LYAPUNOV EQUAL SQUARE_ROOT_SOLVER { driver.option_num("lyapunov_srs", "true"); } | LYAPUNOV EQUAL SQUARE_ROOT_SOLVER { driver.option_num("lyapunov_srs", "true"); }

View File

@ -155,7 +155,8 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<INITIAL>bvar_density {BEGIN DYNARE_STATEMENT; return token::BVAR_DENSITY; } <INITIAL>bvar_density {BEGIN DYNARE_STATEMENT; return token::BVAR_DENSITY; }
<INITIAL>bvar_forecast {BEGIN DYNARE_STATEMENT; return token::BVAR_FORECAST; } <INITIAL>bvar_forecast {BEGIN DYNARE_STATEMENT; return token::BVAR_FORECAST; }
<INITIAL>bvar_irf {BEGIN DYNARE_STATEMENT; return token::BVAR_IRF; } <INITIAL>bvar_irf {BEGIN DYNARE_STATEMENT; return token::BVAR_IRF; }
<INITIAL>dynare_sensitivity {BEGIN DYNARE_STATEMENT; return token::DYNARE_SENSITIVITY;} <INITIAL>sensitivity {BEGIN DYNARE_STATEMENT; return token::SENSITIVITY;}
<INITIAL>dynare_sensitivity {BEGIN DYNARE_STATEMENT; return token::DYNARE_SENSITIVITY;} // Deprecated
<INITIAL>initval_file {BEGIN DYNARE_STATEMENT; return token::INITVAL_FILE;} <INITIAL>initval_file {BEGIN DYNARE_STATEMENT; return token::INITVAL_FILE;}
<INITIAL>histval_file {BEGIN DYNARE_STATEMENT; return token::HISTVAL_FILE;} <INITIAL>histval_file {BEGIN DYNARE_STATEMENT; return token::HISTVAL_FILE;}
<INITIAL>forecast {BEGIN DYNARE_STATEMENT; return token::FORECAST;} <INITIAL>forecast {BEGIN DYNARE_STATEMENT; return token::FORECAST;}
@ -232,6 +233,8 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<INITIAL>occbin_constraints {BEGIN DYNARE_BLOCK; return token::OCCBIN_CONSTRAINTS;} <INITIAL>occbin_constraints {BEGIN DYNARE_BLOCK; return token::OCCBIN_CONSTRAINTS;}
<INITIAL>model_replace {BEGIN DYNARE_BLOCK; return token::MODEL_REPLACE;} <INITIAL>model_replace {BEGIN DYNARE_BLOCK; return token::MODEL_REPLACE;}
<INITIAL>pac_target_info {BEGIN DYNARE_BLOCK; return token::PAC_TARGET_INFO;} <INITIAL>pac_target_info {BEGIN DYNARE_BLOCK; return token::PAC_TARGET_INFO;}
<INITIAL>matched_irfs {BEGIN DYNARE_BLOCK; return token::MATCHED_IRFS;}
<INITIAL>matched_irfs_weights {BEGIN DYNARE_BLOCK; return token::MATCHED_IRFS_WEIGHTS;}
/* For the semicolon after an "end" keyword */ /* For the semicolon after an "end" keyword */
<INITIAL>; {return Dynare::parser::token_type (yytext[0]);} <INITIAL>; {return Dynare::parser::token_type (yytext[0]);}
@ -786,6 +789,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
/* Inside a Dynare block */ /* Inside a Dynare block */
<DYNARE_BLOCK>var {return token::VAR;} <DYNARE_BLOCK>var {return token::VAR;}
<DYNARE_BLOCK>varexo {return token::VAREXO;}
<DYNARE_BLOCK>stderr {return token::STDERR;} <DYNARE_BLOCK>stderr {return token::STDERR;}
<DYNARE_BLOCK>values {return token::VALUES;} <DYNARE_BLOCK>values {return token::VALUES;}
<DYNARE_BLOCK>corr {return token::CORR;} <DYNARE_BLOCK>corr {return token::CORR;}
@ -855,7 +859,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
yylval->build<string>(yytext); yylval->build<string>(yytext);
return token::DD; return token::DD;
} }
<DYNARE_BLOCK>weights {return token::WEIGHTS;}
/* Inside Dynare statement */ /* Inside Dynare statement */
<DYNARE_STATEMENT>solve_algo {return token::SOLVE_ALGO;} <DYNARE_STATEMENT>solve_algo {return token::SOLVE_ALGO;}
@ -865,13 +869,11 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
<DYNARE_STATEMENT>robust_lin_solve {return token::ROBUST_LIN_SOLVE;} <DYNARE_STATEMENT>robust_lin_solve {return token::ROBUST_LIN_SOLVE;}
<DYNARE_STATEMENT>drop {return token::DROP;} <DYNARE_STATEMENT>drop {return token::DROP;}
<DYNARE_STATEMENT>order {return token::ORDER;} <DYNARE_STATEMENT>order {return token::ORDER;}
<DYNARE_STATEMENT>sylvester {return token::SYLVESTER;}
<DYNARE_STATEMENT>lyapunov {return token::LYAPUNOV;} <DYNARE_STATEMENT>lyapunov {return token::LYAPUNOV;}
<DYNARE_STATEMENT>dr { <DYNARE_STATEMENT>dr {
yylval->build<string>(yytext); yylval->build<string>(yytext);
return token::DR; return token::DR;
} }
<DYNARE_STATEMENT>sylvester_fixed_point_tol {return token::SYLVESTER_FIXED_POINT_TOL;}
<DYNARE_STATEMENT>lyapunov_complex_threshold {return token::LYAPUNOV_COMPLEX_THRESHOLD;} <DYNARE_STATEMENT>lyapunov_complex_threshold {return token::LYAPUNOV_COMPLEX_THRESHOLD;}
<DYNARE_STATEMENT>lyapunov_fixed_point_tol {return token::LYAPUNOV_FIXED_POINT_TOL;} <DYNARE_STATEMENT>lyapunov_fixed_point_tol {return token::LYAPUNOV_FIXED_POINT_TOL;}
<DYNARE_STATEMENT>lyapunov_doubling_tol {return token::LYAPUNOV_DOUBLING_TOL;} <DYNARE_STATEMENT>lyapunov_doubling_tol {return token::LYAPUNOV_DOUBLING_TOL;}

View File

@ -31,7 +31,7 @@
#include <unistd.h> #include <unistd.h>
#include "ConfigFile.hh" #include "Configuration.hh"
#include "ExtendedPreprocessorTypes.hh" #include "ExtendedPreprocessorTypes.hh"
#include "ModFile.hh" #include "ModFile.hh"
#include "ParsingDriver.hh" #include "ParsingDriver.hh"
@ -53,7 +53,7 @@ usage()
cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] " cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] "
"[savemacro[=macro_file]] [onlymacro] [linemacro] [notmpterms] [nolog] [warn_uninit]" "[savemacro[=macro_file]] [onlymacro] [linemacro] [notmpterms] [nolog] [warn_uninit]"
<< " [console] [nograph] [nointeractive] [parallel[=cluster_name]] " << " [console] [nograph] [nointeractive] [parallel[=cluster_name]] "
"[conffile=parallel_config_path_and_filename] [parallel_follower_open_mode] " "[conffile=path_to_config_file] [parallel_follower_open_mode] "
"[parallel_test] [parallel_use_psexec=true|false]" "[parallel_test] [parallel_use_psexec=true|false]"
<< " [-D<variable>[=<value>]] [-I/path] [nostrict] [stochastic] [fast] [minimal_workspace] " << " [-D<variable>[=<value>]] [-I/path] [nostrict] [stochastic] [fast] [minimal_workspace] "
"[compute_xrefs] [output=second|third] [language=matlab|julia]" "[compute_xrefs] [output=second|third] [language=matlab|julia]"
@ -142,7 +142,7 @@ main(int argc, char** argv)
bool console = false; bool console = false;
bool nograph = false; bool nograph = false;
bool nointeractive = false; bool nointeractive = false;
filesystem::path parallel_config_file; filesystem::path conffile;
bool parallel = false; bool parallel = false;
string cluster_name; string cluster_name;
bool parallel_follower_open_mode bool parallel_follower_open_mode
@ -234,7 +234,7 @@ main(int argc, char** argv)
cerr << "Incorrect syntax for conffile option" << endl; cerr << "Incorrect syntax for conffile option" << endl;
usage(); usage();
} }
parallel_config_file = s.substr(9); conffile = s.substr(9);
} }
else if (s == "parallel_follower_open_mode" else if (s == "parallel_follower_open_mode"
|| s == "parallel_slave_open_mode") // Kept for backward compatibility, see #86 || s == "parallel_slave_open_mode") // Kept for backward compatibility, see #86
@ -444,9 +444,9 @@ main(int argc, char** argv)
dynareroot = dynareroot.parent_path(); dynareroot = dynareroot.parent_path();
// Construct basename (i.e. remove file extension if there is one) // Construct basename (i.e. remove file extension if there is one)
/* Calling `string()` method on filename because of bug in GCC/MinGW 10.2 /* Calling string() method on filename.stem(): not necessary on GNU/Linux and macOS because there
(shipped in Debian Bullseye 11), that fails to accept implicit is an implicit conversion from filesystem:path to string (i.e. basic_string<char>), but needed
conversion to string from filename::path. */ on Windows because the implicit conversion is only to wstring (i.e. basic_string<wchar_t>). */
const string basename {filename.stem().string()}; const string basename {filename.stem().string()};
// Forbid some basenames, since they will cause trouble (see preprocessor#62) // Forbid some basenames, since they will cause trouble (see preprocessor#62)
@ -461,15 +461,15 @@ main(int argc, char** argv)
WarningConsolidation warnings(no_warn); WarningConsolidation warnings(no_warn);
// Process config file // Process config file
ConfigFile config_file(parallel, parallel_test, parallel_follower_open_mode, parallel_use_psexec, Configuration config {parallel, parallel_test, parallel_follower_open_mode, parallel_use_psexec,
cluster_name); cluster_name};
config_file.getConfigFileInfo(parallel_config_file); config.getConfigFileInfo(conffile, warnings);
config_file.checkPass(warnings); config.checkPass(warnings);
config_file.transformPass(); config.transformPass();
// If Include option was passed to the [paths] block of the config file, add // If Include option was passed to the [paths] block of the config file, add
// it to paths before macroprocessing // it to paths before macroprocessing
for (const auto& it : config_file.getIncludePaths()) for (const auto& it : config.getIncludePaths())
paths.emplace_back(it); paths.emplace_back(it);
/* /*
@ -540,7 +540,7 @@ main(int argc, char** argv)
mod_file->writeJuliaOutput(basename); mod_file->writeJuliaOutput(basename);
else else
mod_file->writeMOutput(basename, clear_all, clear_global, no_warn, console, nograph, mod_file->writeMOutput(basename, clear_all, clear_global, no_warn, console, nograph,
nointeractive, config_file, check_model_changes, minimal_workspace, nointeractive, config, check_model_changes, minimal_workspace,
compute_xrefs, mexext, matlabroot, onlymodel, gui, notime); compute_xrefs, mexext, matlabroot, onlymodel, gui, notime);
/* Ensures that workers are not destroyed before they finish compiling. /* Ensures that workers are not destroyed before they finish compiling.

View File

@ -144,7 +144,7 @@ ExprNode::checkIfTemporaryTermThenWrite(ostream& output, ExprNodeOutputType outp
bool bool
ExprNode::checkIfTemporaryTermThenWriteBytecode( ExprNode::checkIfTemporaryTermThenWriteBytecode(
BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs) const const temporary_terms_idxs_t& temporary_terms_idxs) const
{ {
@ -163,10 +163,10 @@ ExprNode::checkIfTemporaryTermThenWriteBytecode(
was initially not called with steady_dynamic=true). */ was initially not called with steady_dynamic=true). */
return false; return false;
case ExprNodeBytecodeOutputType::dynamicModel: case ExprNodeBytecodeOutputType::dynamicModel:
code_file << FLDT_ {it2->second}; code_file << Bytecode::FLDT {it2->second};
break; break;
case ExprNodeBytecodeOutputType::staticModel: case ExprNodeBytecodeOutputType::staticModel:
code_file << FLDST_ {it2->second}; code_file << Bytecode::FLDST {it2->second};
break; break;
case ExprNodeBytecodeOutputType::dynamicAssignmentLHS: case ExprNodeBytecodeOutputType::dynamicAssignmentLHS:
case ExprNodeBytecodeOutputType::staticAssignmentLHS: case ExprNodeBytecodeOutputType::staticAssignmentLHS:
@ -267,7 +267,7 @@ ExprNode::writeJsonExternalFunctionOutput([[maybe_unused]] vector<string>& efout
void void
ExprNode::writeBytecodeExternalFunctionOutput( ExprNode::writeBytecodeExternalFunctionOutput(
[[maybe_unused]] BytecodeWriter& code_file, [[maybe_unused]] Bytecode::Writer& code_file,
[[maybe_unused]] ExprNodeBytecodeOutputType output_type, [[maybe_unused]] ExprNodeBytecodeOutputType output_type,
[[maybe_unused]] const temporary_terms_t& temporary_terms, [[maybe_unused]] const temporary_terms_t& temporary_terms,
[[maybe_unused]] const temporary_terms_idxs_t& temporary_terms_idxs, [[maybe_unused]] const temporary_terms_idxs_t& temporary_terms_idxs,
@ -556,7 +556,8 @@ NumConstNode::eval([[maybe_unused]] const eval_context_t& eval_context) const no
} }
void void
NumConstNode::writeBytecodeOutput(BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, NumConstNode::writeBytecodeOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
[[maybe_unused]] const deriv_node_temp_terms_t& tef_terms) const [[maybe_unused]] const deriv_node_temp_terms_t& tef_terms) const
@ -564,7 +565,7 @@ NumConstNode::writeBytecodeOutput(BytecodeWriter& code_file, ExprNodeBytecodeOut
assert(!isAssignmentLHSBytecodeOutput(output_type)); assert(!isAssignmentLHSBytecodeOutput(output_type));
if (!checkIfTemporaryTermThenWriteBytecode(code_file, output_type, temporary_terms, if (!checkIfTemporaryTermThenWriteBytecode(code_file, output_type, temporary_terms,
temporary_terms_idxs)) temporary_terms_idxs))
code_file << FLDC_ {datatree.num_constants.getDouble(id)}; code_file << Bytecode::FLDC {datatree.num_constants.getDouble(id)};
} }
void void
@ -1431,7 +1432,8 @@ VariableNode::eval(const eval_context_t& eval_context) const noexcept(false)
} }
void void
VariableNode::writeBytecodeOutput(BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, VariableNode::writeBytecodeOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const const deriv_node_temp_terms_t& tef_terms) const
@ -1450,19 +1452,19 @@ VariableNode::writeBytecodeOutput(BytecodeWriter& code_file, ExprNodeBytecodeOut
switch (output_type) switch (output_type)
{ {
case ExprNodeBytecodeOutputType::dynamicModel: case ExprNodeBytecodeOutputType::dynamicModel:
code_file << FLDV_ {type, tsid, lag}; code_file << Bytecode::FLDV {type, tsid, lag};
break; break;
case ExprNodeBytecodeOutputType::staticModel: case ExprNodeBytecodeOutputType::staticModel:
code_file << FLDSV_ {type, tsid}; code_file << Bytecode::FLDSV {type, tsid};
break; break;
case ExprNodeBytecodeOutputType::dynamicSteadyStateOperator: case ExprNodeBytecodeOutputType::dynamicSteadyStateOperator:
code_file << FLDVS_ {type, tsid}; code_file << Bytecode::FLDVS {type, tsid};
break; break;
case ExprNodeBytecodeOutputType::dynamicAssignmentLHS: case ExprNodeBytecodeOutputType::dynamicAssignmentLHS:
code_file << FSTPV_ {type, tsid, lag}; code_file << Bytecode::FSTPV {type, tsid, lag};
break; break;
case ExprNodeBytecodeOutputType::staticAssignmentLHS: case ExprNodeBytecodeOutputType::staticAssignmentLHS:
code_file << FSTPSV_ {type, tsid}; code_file << Bytecode::FSTPSV {type, tsid};
break; break;
} }
} }
@ -3160,7 +3162,7 @@ UnaryOpNode::writeJsonExternalFunctionOutput(vector<string>& efout,
} }
void void
UnaryOpNode::writeBytecodeExternalFunctionOutput(BytecodeWriter& code_file, UnaryOpNode::writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
@ -3250,7 +3252,8 @@ UnaryOpNode::eval(const eval_context_t& eval_context) const noexcept(false)
} }
void void
UnaryOpNode::writeBytecodeOutput(BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, UnaryOpNode::writeBytecodeOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const const deriv_node_temp_terms_t& tef_terms) const
@ -3283,7 +3286,7 @@ UnaryOpNode::writeBytecodeOutput(BytecodeWriter& code_file, ExprNodeBytecodeOutp
{ {
arg->writeBytecodeOutput(code_file, output_type, temporary_terms, temporary_terms_idxs, arg->writeBytecodeOutput(code_file, output_type, temporary_terms, temporary_terms_idxs,
tef_terms); tef_terms);
code_file << FUNARY_ {op_code}; code_file << Bytecode::FUNARY {op_code};
} }
} }
@ -4547,7 +4550,8 @@ BinaryOpNode::eval(const eval_context_t& eval_context) const noexcept(false)
} }
void void
BinaryOpNode::writeBytecodeOutput(BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, BinaryOpNode::writeBytecodeOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const const deriv_node_temp_terms_t& tef_terms) const
@ -4558,12 +4562,12 @@ BinaryOpNode::writeBytecodeOutput(BytecodeWriter& code_file, ExprNodeBytecodeOut
return; return;
if (op_code == BinaryOpcode::powerDeriv) if (op_code == BinaryOpcode::powerDeriv)
code_file << FLDC_ {static_cast<double>(powerDerivOrder)}; code_file << Bytecode::FLDC {static_cast<double>(powerDerivOrder)};
arg1->writeBytecodeOutput(code_file, output_type, temporary_terms, temporary_terms_idxs, arg1->writeBytecodeOutput(code_file, output_type, temporary_terms, temporary_terms_idxs,
tef_terms); tef_terms);
arg2->writeBytecodeOutput(code_file, output_type, temporary_terms, temporary_terms_idxs, arg2->writeBytecodeOutput(code_file, output_type, temporary_terms, temporary_terms_idxs,
tef_terms); tef_terms);
code_file << FBINARY_ {op_code}; code_file << Bytecode::FBINARY {op_code};
} }
bool bool
@ -5009,7 +5013,7 @@ BinaryOpNode::writeJsonExternalFunctionOutput(vector<string>& efout,
void void
BinaryOpNode::writeBytecodeExternalFunctionOutput( BinaryOpNode::writeBytecodeExternalFunctionOutput(
BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const deriv_node_temp_terms_t& tef_terms) const
{ {
@ -5697,7 +5701,7 @@ BinaryOpNode::getPacAREC(
{ {
// NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage)
auto [vid, lag, pid, constant] = term->matchVariableTimesConstantTimesParam(true); auto [vid, lag, pid, constant] = term->matchVariableTimesConstantTimesParam(true);
linear_combination.emplace_back(vid.value(), lag, move(pid), constant); linear_combination.emplace_back(vid.value(), lag, pid, constant);
} }
catch (MatchFailureException& e) catch (MatchFailureException& e)
{ {
@ -6288,7 +6292,7 @@ TrinaryOpNode::eval(const eval_context_t& eval_context) const noexcept(false)
} }
void void
TrinaryOpNode::writeBytecodeOutput(BytecodeWriter& code_file, TrinaryOpNode::writeBytecodeOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
@ -6305,7 +6309,7 @@ TrinaryOpNode::writeBytecodeOutput(BytecodeWriter& code_file,
tef_terms); tef_terms);
arg3->writeBytecodeOutput(code_file, output_type, temporary_terms, temporary_terms_idxs, arg3->writeBytecodeOutput(code_file, output_type, temporary_terms, temporary_terms_idxs,
tef_terms); tef_terms);
code_file << FTRINARY_ {op_code}; code_file << Bytecode::FTRINARY {op_code};
} }
bool bool
@ -6484,7 +6488,7 @@ TrinaryOpNode::writeJsonExternalFunctionOutput(vector<string>& efout,
void void
TrinaryOpNode::writeBytecodeExternalFunctionOutput( TrinaryOpNode::writeBytecodeExternalFunctionOutput(
BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const deriv_node_temp_terms_t& tef_terms) const
{ {
@ -6917,6 +6921,7 @@ AbstractExternalFunctionNode::computeDerivative(int deriv_id)
{ {
assert(datatree.external_functions_table.getNargs(symb_id) > 0); assert(datatree.external_functions_table.getNargs(symb_id) > 0);
vector<expr_t> dargs; vector<expr_t> dargs;
dargs.reserve(arguments.size());
for (auto argument : arguments) for (auto argument : arguments)
dargs.push_back(argument->getDerivative(deriv_id)); dargs.push_back(argument->getDerivative(deriv_id));
return composeDerivatives(dargs); return composeDerivatives(dargs);
@ -6930,6 +6935,7 @@ AbstractExternalFunctionNode::computeChainRuleDerivative(
{ {
assert(datatree.external_functions_table.getNargs(symb_id) > 0); assert(datatree.external_functions_table.getNargs(symb_id) > 0);
vector<expr_t> dargs; vector<expr_t> dargs;
dargs.reserve(arguments.size());
for (auto argument : arguments) for (auto argument : arguments)
dargs.push_back(argument->getChainRuleDerivative(deriv_id, recursive_variables, dargs.push_back(argument->getChainRuleDerivative(deriv_id, recursive_variables,
non_null_chain_rule_derivatives, cache)); non_null_chain_rule_derivatives, cache));
@ -6938,7 +6944,7 @@ AbstractExternalFunctionNode::computeChainRuleDerivative(
void void
AbstractExternalFunctionNode::writeBytecodeExternalFunctionArguments( AbstractExternalFunctionNode::writeBytecodeExternalFunctionArguments(
BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const const deriv_node_temp_terms_t& tef_terms) const
{ {
@ -7405,6 +7411,7 @@ expr_t
AbstractExternalFunctionNode::toStatic(DataTree& static_datatree) const AbstractExternalFunctionNode::toStatic(DataTree& static_datatree) const
{ {
vector<expr_t> static_arguments; vector<expr_t> static_arguments;
static_arguments.reserve(arguments.size());
for (auto argument : arguments) for (auto argument : arguments)
static_arguments.push_back(argument->toStatic(static_datatree)); static_arguments.push_back(argument->toStatic(static_datatree));
return buildSimilarExternalFunctionNode(static_arguments, static_datatree); return buildSimilarExternalFunctionNode(static_arguments, static_datatree);
@ -7414,6 +7421,7 @@ expr_t
AbstractExternalFunctionNode::clone(DataTree& alt_datatree) const AbstractExternalFunctionNode::clone(DataTree& alt_datatree) const
{ {
vector<expr_t> dynamic_arguments; vector<expr_t> dynamic_arguments;
dynamic_arguments.reserve(arguments.size());
for (auto argument : arguments) for (auto argument : arguments)
dynamic_arguments.push_back(argument->clone(alt_datatree)); dynamic_arguments.push_back(argument->clone(alt_datatree));
return buildSimilarExternalFunctionNode(dynamic_arguments, alt_datatree); return buildSimilarExternalFunctionNode(dynamic_arguments, alt_datatree);
@ -7423,6 +7431,7 @@ expr_t
ExternalFunctionNode::composeDerivatives(const vector<expr_t>& dargs) ExternalFunctionNode::composeDerivatives(const vector<expr_t>& dargs)
{ {
vector<expr_t> dNodes; vector<expr_t> dNodes;
dNodes.reserve(dargs.size());
for (int i = 0; i < static_cast<int>(dargs.size()); i++) for (int i = 0; i < static_cast<int>(dargs.size()); i++)
dNodes.push_back(datatree.AddTimes( dNodes.push_back(datatree.AddTimes(
dargs.at(i), datatree.AddFirstDerivExternalFunction(symb_id, arguments, i + 1))); dargs.at(i), datatree.AddFirstDerivExternalFunction(symb_id, arguments, i + 1)));
@ -7432,7 +7441,7 @@ ExternalFunctionNode::composeDerivatives(const vector<expr_t>& dargs)
} }
void void
ExternalFunctionNode::writeBytecodeOutput(BytecodeWriter& code_file, ExternalFunctionNode::writeBytecodeOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
@ -7451,14 +7460,14 @@ ExternalFunctionNode::writeBytecodeOutput(BytecodeWriter& code_file,
return; return;
if (!isAssignmentLHSBytecodeOutput(output_type)) if (!isAssignmentLHSBytecodeOutput(output_type))
code_file << FLDTEF_ {getIndxInTefTerms(symb_id, tef_terms)}; code_file << Bytecode::FLDTEF {getIndxInTefTerms(symb_id, tef_terms)};
else else
code_file << FSTPTEF_ {getIndxInTefTerms(symb_id, tef_terms)}; code_file << Bytecode::FSTPTEF {getIndxInTefTerms(symb_id, tef_terms)};
} }
void void
ExternalFunctionNode::writeBytecodeExternalFunctionOutput( ExternalFunctionNode::writeBytecodeExternalFunctionOutput(
BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const deriv_node_temp_terms_t& tef_terms) const
{ {
@ -7480,26 +7489,26 @@ ExternalFunctionNode::writeBytecodeExternalFunctionOutput(
temporary_terms_idxs, tef_terms); temporary_terms_idxs, tef_terms);
int nb_output_arguments; int nb_output_arguments;
ExternalFunctionCallType call_type; Bytecode::ExternalFunctionCallType call_type;
if (symb_id == first_deriv_symb_id && symb_id == second_deriv_symb_id) if (symb_id == first_deriv_symb_id && symb_id == second_deriv_symb_id)
{ {
nb_output_arguments = 3; nb_output_arguments = 3;
call_type = ExternalFunctionCallType::levelWithFirstAndSecondDerivative; call_type = Bytecode::ExternalFunctionCallType::levelWithFirstAndSecondDerivative;
} }
else if (symb_id == first_deriv_symb_id) else if (symb_id == first_deriv_symb_id)
{ {
nb_output_arguments = 2; nb_output_arguments = 2;
call_type = ExternalFunctionCallType::levelWithFirstDerivative; call_type = Bytecode::ExternalFunctionCallType::levelWithFirstDerivative;
} }
else else
{ {
nb_output_arguments = 1; nb_output_arguments = 1;
call_type = ExternalFunctionCallType::levelWithoutDerivative; call_type = Bytecode::ExternalFunctionCallType::levelWithoutDerivative;
} }
code_file << FCALL_ {nb_output_arguments, static_cast<int>(arguments.size()), code_file << Bytecode::FCALL {nb_output_arguments, static_cast<int>(arguments.size()),
datatree.symbol_table.getName(symb_id), indx, call_type} datatree.symbol_table.getName(symb_id), indx, call_type}
<< FSTPTEF_ {indx}; << Bytecode::FSTPTEF {indx};
} }
} }
@ -7715,6 +7724,7 @@ expr_t
FirstDerivExternalFunctionNode::composeDerivatives(const vector<expr_t>& dargs) FirstDerivExternalFunctionNode::composeDerivatives(const vector<expr_t>& dargs)
{ {
vector<expr_t> dNodes; vector<expr_t> dNodes;
dNodes.reserve(dargs.size());
for (int i = 0; i < static_cast<int>(dargs.size()); i++) for (int i = 0; i < static_cast<int>(dargs.size()); i++)
dNodes.push_back(datatree.AddTimes(dargs.at(i), datatree.AddSecondDerivExternalFunction( dNodes.push_back(datatree.AddTimes(dargs.at(i), datatree.AddSecondDerivExternalFunction(
symb_id, arguments, inputIndex, i + 1))); symb_id, arguments, inputIndex, i + 1)));
@ -7809,7 +7819,7 @@ FirstDerivExternalFunctionNode::writeOutput(ostream& output, ExprNodeOutputType
void void
FirstDerivExternalFunctionNode::writeBytecodeOutput( FirstDerivExternalFunctionNode::writeBytecodeOutput(
BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const const deriv_node_temp_terms_t& tef_terms) const
{ {
@ -7829,9 +7839,9 @@ FirstDerivExternalFunctionNode::writeBytecodeOutput(
assert(first_deriv_symb_id != ExternalFunctionsTable::IDSetButNoNameProvided); assert(first_deriv_symb_id != ExternalFunctionsTable::IDSetButNoNameProvided);
if (!isAssignmentLHSBytecodeOutput(output_type)) if (!isAssignmentLHSBytecodeOutput(output_type))
code_file << FLDTEFD_ {getIndxInTefTerms(symb_id, tef_terms), inputIndex}; code_file << Bytecode::FLDTEFD {getIndxInTefTerms(symb_id, tef_terms), inputIndex};
else else
code_file << FSTPTEFD_ {getIndxInTefTerms(symb_id, tef_terms), inputIndex}; code_file << Bytecode::FSTPTEFD {getIndxInTefTerms(symb_id, tef_terms), inputIndex};
} }
void void
@ -7966,7 +7976,7 @@ FirstDerivExternalFunctionNode::writeJsonExternalFunctionOutput(
void void
FirstDerivExternalFunctionNode::writeBytecodeExternalFunctionOutput( FirstDerivExternalFunctionNode::writeBytecodeExternalFunctionOutput(
BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const deriv_node_temp_terms_t& tef_terms) const
{ {
@ -7994,12 +8004,12 @@ FirstDerivExternalFunctionNode::writeBytecodeExternalFunctionOutput(
{ {
int nb_input_arguments {0}; int nb_input_arguments {0};
int nb_output_arguments {1}; int nb_output_arguments {1};
FCALL_ fcall {nb_output_arguments, nb_input_arguments, "jacob_element", indx, Bytecode::FCALL fcall {nb_output_arguments, nb_input_arguments, "jacob_element", indx,
ExternalFunctionCallType::numericalFirstDerivative}; Bytecode::ExternalFunctionCallType::numericalFirstDerivative};
fcall.set_arg_func_name(datatree.symbol_table.getName(symb_id)); fcall.set_arg_func_name(datatree.symbol_table.getName(symb_id));
fcall.set_row(inputIndex); fcall.set_row(inputIndex);
fcall.set_nb_add_input_arguments(static_cast<int>(arguments.size())); fcall.set_nb_add_input_arguments(static_cast<int>(arguments.size()));
code_file << fcall << FSTPTEFD_ {indx, inputIndex}; code_file << fcall << Bytecode::FSTPTEFD {indx, inputIndex};
} }
else else
{ {
@ -8009,10 +8019,11 @@ FirstDerivExternalFunctionNode::writeBytecodeExternalFunctionOutput(
int nb_output_arguments {1}; int nb_output_arguments {1};
code_file << FCALL_ {nb_output_arguments, static_cast<int>(arguments.size()), code_file
datatree.symbol_table.getName(first_deriv_symb_id), indx, << Bytecode::FCALL {nb_output_arguments, static_cast<int>(arguments.size()),
ExternalFunctionCallType::separatelyProvidedFirstDerivative} datatree.symbol_table.getName(first_deriv_symb_id), indx,
<< FSTPTEFD_ {indx, inputIndex}; Bytecode::ExternalFunctionCallType::separatelyProvidedFirstDerivative}
<< Bytecode::FSTPTEFD {indx, inputIndex};
} }
} }
@ -8313,7 +8324,7 @@ SecondDerivExternalFunctionNode::computeXrefs(EquationInfo& ei) const
void void
SecondDerivExternalFunctionNode::writeBytecodeOutput( SecondDerivExternalFunctionNode::writeBytecodeOutput(
BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const const deriv_node_temp_terms_t& tef_terms) const
{ {
@ -8333,14 +8344,16 @@ SecondDerivExternalFunctionNode::writeBytecodeOutput(
assert(second_deriv_symb_id != ExternalFunctionsTable::IDSetButNoNameProvided); assert(second_deriv_symb_id != ExternalFunctionsTable::IDSetButNoNameProvided);
if (!isAssignmentLHSBytecodeOutput(output_type)) if (!isAssignmentLHSBytecodeOutput(output_type))
code_file << FLDTEFDD_ {getIndxInTefTerms(symb_id, tef_terms), inputIndex1, inputIndex2}; code_file << Bytecode::FLDTEFDD {getIndxInTefTerms(symb_id, tef_terms), inputIndex1,
inputIndex2};
else else
code_file << FSTPTEFDD_ {getIndxInTefTerms(symb_id, tef_terms), inputIndex1, inputIndex2}; code_file << Bytecode::FSTPTEFDD {getIndxInTefTerms(symb_id, tef_terms), inputIndex1,
inputIndex2};
} }
void void
SecondDerivExternalFunctionNode::writeBytecodeExternalFunctionOutput( SecondDerivExternalFunctionNode::writeBytecodeExternalFunctionOutput(
BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const deriv_node_temp_terms_t& tef_terms) const
{ {
@ -8366,22 +8379,23 @@ SecondDerivExternalFunctionNode::writeBytecodeExternalFunctionOutput(
if (int indx = getIndxInTefTerms(symb_id, tef_terms); if (int indx = getIndxInTefTerms(symb_id, tef_terms);
second_deriv_symb_id == ExternalFunctionsTable::IDNotSet) second_deriv_symb_id == ExternalFunctionsTable::IDNotSet)
{ {
FCALL_ fcall {1, 0, "hess_element", indx, Bytecode::FCALL fcall {1, 0, "hess_element", indx,
ExternalFunctionCallType::numericalSecondDerivative}; Bytecode::ExternalFunctionCallType::numericalSecondDerivative};
fcall.set_arg_func_name(datatree.symbol_table.getName(symb_id)); fcall.set_arg_func_name(datatree.symbol_table.getName(symb_id));
fcall.set_row(inputIndex1); fcall.set_row(inputIndex1);
fcall.set_col(inputIndex2); fcall.set_col(inputIndex2);
fcall.set_nb_add_input_arguments(static_cast<int>(arguments.size())); fcall.set_nb_add_input_arguments(static_cast<int>(arguments.size()));
code_file << fcall << FSTPTEFDD_ {indx, inputIndex1, inputIndex2}; code_file << fcall << Bytecode::FSTPTEFDD {indx, inputIndex1, inputIndex2};
} }
else else
{ {
tef_terms[{second_deriv_symb_id, arguments}] = static_cast<int>(tef_terms.size()); tef_terms[{second_deriv_symb_id, arguments}] = static_cast<int>(tef_terms.size());
code_file << FCALL_ {1, static_cast<int>(arguments.size()), code_file << Bytecode::
datatree.symbol_table.getName(second_deriv_symb_id), indx, FCALL {1, static_cast<int>(arguments.size()),
ExternalFunctionCallType::separatelyProvidedSecondDerivative} datatree.symbol_table.getName(second_deriv_symb_id), indx,
<< FSTPTEFDD_ {indx, inputIndex1, inputIndex2}; Bytecode::ExternalFunctionCallType::separatelyProvidedSecondDerivative}
<< Bytecode::FSTPTEFDD {indx, inputIndex1, inputIndex2};
} }
} }
@ -8604,7 +8618,7 @@ SubModelNode::collectDynamicVariables([[maybe_unused]] SymbolType type_arg,
void void
SubModelNode::writeBytecodeOutput( SubModelNode::writeBytecodeOutput(
[[maybe_unused]] BytecodeWriter& code_file, [[maybe_unused]] Bytecode::Writer& code_file,
[[maybe_unused]] ExprNodeBytecodeOutputType output_type, [[maybe_unused]] ExprNodeBytecodeOutputType output_type,
[[maybe_unused]] const temporary_terms_t& temporary_terms, [[maybe_unused]] const temporary_terms_t& temporary_terms,
[[maybe_unused]] const temporary_terms_idxs_t& temporary_terms_idxs, [[maybe_unused]] const temporary_terms_idxs_t& temporary_terms_idxs,
@ -9102,7 +9116,7 @@ ExprNode::matchVariableTimesConstantTimesParam(bool variable_obligatory) const
matchVTCTPHelper(variable_id, lag, param_id, constant, false); matchVTCTPHelper(variable_id, lag, param_id, constant, false);
if (variable_obligatory && !variable_id) if (variable_obligatory && !variable_id)
throw MatchFailureException {"No variable in this expression"}; throw MatchFailureException {"No variable in this expression"};
return {move(variable_id), lag, move(param_id), constant}; return {variable_id, lag, param_id, constant};
} }
void void
@ -9194,7 +9208,7 @@ ExprNode::matchLinearCombinationOfVariables() const
auto [variable_id, lag, param_id, constant] auto [variable_id, lag, param_id, constant]
= term->matchVariableTimesConstantTimesParam(true); = term->matchVariableTimesConstantTimesParam(true);
constant *= sign; constant *= sign;
result.emplace_back(variable_id.value(), lag, move(param_id), constant); result.emplace_back(variable_id.value(), lag, param_id, constant);
} }
return result; return result;
} }

View File

@ -321,7 +321,7 @@ protected:
// Same as above, for the bytecode case // Same as above, for the bytecode case
bool bool
checkIfTemporaryTermThenWriteBytecode(BytecodeWriter& code_file, checkIfTemporaryTermThenWriteBytecode(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs) const; const temporary_terms_idxs_t& temporary_terms_idxs) const;
@ -488,7 +488,7 @@ public:
bool isdynamic = true) const; bool isdynamic = true) const;
virtual void writeBytecodeExternalFunctionOutput( virtual void writeBytecodeExternalFunctionOutput(
BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_t& temporary_terms, const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const; deriv_node_temp_terms_t& tef_terms) const;
@ -537,7 +537,7 @@ public:
[[nodiscard]] virtual double eval(const eval_context_t& eval_context) const noexcept(false) = 0; [[nodiscard]] virtual double eval(const eval_context_t& eval_context) const noexcept(false) = 0;
// Write output to bytecode file // Write output to bytecode file
virtual void writeBytecodeOutput(BytecodeWriter& code_file, virtual void writeBytecodeOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
@ -995,7 +995,7 @@ public:
void collectVARLHSVariable(set<expr_t>& result) const override; void collectVARLHSVariable(set<expr_t>& result) const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override; void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override; [[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
void writeBytecodeOutput(BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override; const deriv_node_temp_terms_t& tef_terms) const override;
@ -1095,7 +1095,7 @@ public:
void collectVARLHSVariable(set<expr_t>& result) const override; void collectVARLHSVariable(set<expr_t>& result) const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override; void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override; [[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
void writeBytecodeOutput(BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override; const deriv_node_temp_terms_t& tef_terms) const override;
@ -1231,7 +1231,7 @@ public:
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms, deriv_node_temp_terms_t& tef_terms,
bool isdynamic) const override; bool isdynamic) const override;
void writeBytecodeExternalFunctionOutput(BytecodeWriter& code_file, void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
@ -1240,7 +1240,7 @@ public:
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override; void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
static double eval_opcode(UnaryOpcode op_code, double v) noexcept(false); static double eval_opcode(UnaryOpcode op_code, double v) noexcept(false);
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override; [[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
void writeBytecodeOutput(BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override; const deriv_node_temp_terms_t& tef_terms) const override;
@ -1376,7 +1376,7 @@ public:
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms, deriv_node_temp_terms_t& tef_terms,
bool isdynamic) const override; bool isdynamic) const override;
void writeBytecodeExternalFunctionOutput(BytecodeWriter& code_file, void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
@ -1386,7 +1386,7 @@ public:
static double eval_opcode(double v1, BinaryOpcode op_code, double v2, static double eval_opcode(double v1, BinaryOpcode op_code, double v2,
int derivOrder) noexcept(false); int derivOrder) noexcept(false);
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override; [[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
void writeBytecodeOutput(BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override; const deriv_node_temp_terms_t& tef_terms) const override;
@ -1569,7 +1569,7 @@ public:
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms, deriv_node_temp_terms_t& tef_terms,
bool isdynamic) const override; bool isdynamic) const override;
void writeBytecodeExternalFunctionOutput(BytecodeWriter& code_file, void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
@ -1578,7 +1578,7 @@ public:
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override; void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
static double eval_opcode(double v1, TrinaryOpcode op_code, double v2, double v3) noexcept(false); static double eval_opcode(double v1, TrinaryOpcode op_code, double v2, double v3) noexcept(false);
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override; [[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
void writeBytecodeOutput(BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override; const deriv_node_temp_terms_t& tef_terms) const override;
@ -1694,7 +1694,7 @@ protected:
void writeJsonExternalFunctionArguments(ostream& output, const temporary_terms_t& temporary_terms, void writeJsonExternalFunctionArguments(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, const deriv_node_temp_terms_t& tef_terms,
bool isdynamic) const; bool isdynamic) const;
void writeBytecodeExternalFunctionArguments(BytecodeWriter& code_file, void writeBytecodeExternalFunctionArguments(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
@ -1737,7 +1737,7 @@ public:
deriv_node_temp_terms_t& tef_terms, deriv_node_temp_terms_t& tef_terms,
bool isdynamic = true) const override bool isdynamic = true) const override
= 0; = 0;
void writeBytecodeExternalFunctionOutput(BytecodeWriter& code_file, void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
@ -1746,7 +1746,7 @@ public:
void collectVARLHSVariable(set<expr_t>& result) const override; void collectVARLHSVariable(set<expr_t>& result) const override;
void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override; void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>>& result) const override;
[[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override; [[nodiscard]] double eval(const eval_context_t& eval_context) const noexcept(false) override;
void writeBytecodeOutput(BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override const deriv_node_temp_terms_t& tef_terms) const override
@ -1842,12 +1842,12 @@ public:
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms, deriv_node_temp_terms_t& tef_terms,
bool isdynamic) const override; bool isdynamic) const override;
void writeBytecodeExternalFunctionOutput(BytecodeWriter& code_file, void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
deriv_node_temp_terms_t& tef_terms) const override; deriv_node_temp_terms_t& tef_terms) const override;
void writeBytecodeOutput(BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override; const deriv_node_temp_terms_t& tef_terms) const override;
@ -1877,7 +1877,7 @@ public:
void writeJsonAST(ostream& output) const override; void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms, void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override; const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
void writeBytecodeOutput(BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override; const deriv_node_temp_terms_t& tef_terms) const override;
@ -1889,7 +1889,7 @@ public:
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms, deriv_node_temp_terms_t& tef_terms,
bool isdynamic) const override; bool isdynamic) const override;
void writeBytecodeExternalFunctionOutput(BytecodeWriter& code_file, void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
@ -1922,7 +1922,7 @@ public:
void writeJsonAST(ostream& output) const override; void writeJsonAST(ostream& output) const override;
void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms, void writeJsonOutput(ostream& output, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override; const deriv_node_temp_terms_t& tef_terms, bool isdynamic) const override;
void writeBytecodeOutput(BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override; const deriv_node_temp_terms_t& tef_terms) const override;
@ -1934,7 +1934,7 @@ public:
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
deriv_node_temp_terms_t& tef_terms, deriv_node_temp_terms_t& tef_terms,
bool isdynamic) const override; bool isdynamic) const override;
void writeBytecodeExternalFunctionOutput(BytecodeWriter& code_file, void writeBytecodeExternalFunctionOutput(Bytecode::Writer& code_file,
ExprNodeBytecodeOutputType output_type, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
@ -1994,7 +1994,7 @@ public:
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table, expr_t substituteUnaryOpNodes(const lag_equivalence_table_t& nodes, subst_table_t& subst_table,
vector<BinaryOpNode*>& neweqs) const override; vector<BinaryOpNode*>& neweqs) const override;
BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override; BinaryOpNode* normalizeEquationHelper(const set<expr_t>& contain_var, expr_t rhs) const override;
void writeBytecodeOutput(BytecodeWriter& code_file, ExprNodeBytecodeOutputType output_type, void writeBytecodeOutput(Bytecode::Writer& code_file, ExprNodeBytecodeOutputType output_type,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const temporary_terms_idxs_t& temporary_terms_idxs, const temporary_terms_idxs_t& temporary_terms_idxs,
const deriv_node_temp_terms_t& tef_terms) const override; const deriv_node_temp_terms_t& tef_terms) const override;

View File

@ -34,9 +34,9 @@ macroExpandModFile(const filesystem::path& filename, const istream& modfile, boo
stringstream macro_output; stringstream macro_output;
macro::Environment env = macro::Environment(); macro::Environment env = macro::Environment();
macro::Driver m; macro::Driver m;
/* Calling `string()` method on filename because of bug in GCC/MinGW 10.2 /* Calling string() method on filename: not necessary on GNU/Linux and macOS because there is an
(shipped in Debian Bullseye 11), that fails to accept implicit implicit conversion from filesystem:path to string (i.e. basic_string<char>), but needed on
conversion to string from filename::path. */ Windows because the implicit conversion is only to wstring (i.e. basic_string<wchar_t>). */
m.parse(filename.string(), modfile, debug, defines, env, paths, macro_output); m.parse(filename.string(), modfile, debug, defines, env, paths, macro_output);
if (save_macro) if (save_macro)
{ {

View File

@ -27,7 +27,6 @@
#include <filesystem> #include <filesystem>
#include "ComputingTasks.hh" #include "ComputingTasks.hh"
#include "ConfigFile.hh"
#include "ModFile.hh" #include "ModFile.hh"
#include "Shocks.hh" #include "Shocks.hh"
@ -843,7 +842,7 @@ ModFile::remove_directory_with_matlab_lock(const filesystem::path& dir)
void void
ModFile::writeMOutput(const string& basename, bool clear_all, bool clear_global, bool no_warn, ModFile::writeMOutput(const string& basename, bool clear_all, bool clear_global, bool no_warn,
bool console, bool nograph, bool nointeractive, const ConfigFile& config_file, bool console, bool nograph, bool nointeractive, const Configuration& config,
bool check_model_changes, bool minimal_workspace, bool compute_xrefs, bool check_model_changes, bool minimal_workspace, bool compute_xrefs,
const string& mexext, const filesystem::path& matlabroot, bool onlymodel, const string& mexext, const filesystem::path& matlabroot, bool onlymodel,
bool gui, bool notime) const bool gui, bool notime) const
@ -916,12 +915,9 @@ ModFile::writeMOutput(const string& basename, bool clear_all, bool clear_global,
<< "% Some global variables initialization" << endl << "% Some global variables initialization" << endl
<< "%" << endl; << "%" << endl;
if (!onlymodel) if (!onlymodel)
config_file.writeHooks(mOutputFile); config.writeHooks(mOutputFile);
mOutputFile << "global_initialization;" << endl; mOutputFile << "global_initialization;" << endl;
if (minimal_workspace)
mOutputFile << "options_.minimal_workspace = true;" << endl;
if (console) if (console)
mOutputFile << "options_.console_mode = true;" << endl << "options_.nodisplay = true;" << endl; mOutputFile << "options_.console_mode = true;" << endl << "options_.nodisplay = true;" << endl;
if (nograph) if (nograph)
@ -957,14 +953,16 @@ ModFile::writeMOutput(const string& basename, bool clear_all, bool clear_global,
// May be later modified by a shocks block // May be later modified by a shocks block
mOutputFile << "M_.sigma_e_is_diagonal = true;" << endl; mOutputFile << "M_.sigma_e_is_diagonal = true;" << endl;
// Initialize M_.det_shocks, M_.surprise_shocks, M_.learnt_shocks, M_.learnt_endval and /* Initialize the structures created for several blocks, as part of the implementation of the
// M_.heteroskedastic_shocks overwrite option */
mOutputFile << "M_.det_shocks = [];" << endl mOutputFile << "M_.det_shocks = [];" << endl
<< "M_.surprise_shocks = [];" << endl << "M_.surprise_shocks = [];" << endl
<< "M_.learnt_shocks = [];" << endl << "M_.learnt_shocks = [];" << endl
<< "M_.learnt_endval = [];" << endl << "M_.learnt_endval = [];" << endl
<< "M_.heteroskedastic_shocks.Qvalue_orig = [];" << endl << "M_.heteroskedastic_shocks.Qvalue_orig = [];" << endl
<< "M_.heteroskedastic_shocks.Qscale_orig = [];" << endl; << "M_.heteroskedastic_shocks.Qscale_orig = [];" << endl
<< "M_.matched_irfs = {};" << endl
<< "M_.matched_irfs_weights = {};" << endl;
// NB: options_.{ramsey,discretionary}_policy should rather be fields of M_ // NB: options_.{ramsey,discretionary}_policy should rather be fields of M_
mOutputFile << boolalpha << "options_.linear = " << linear << ";" << endl mOutputFile << boolalpha << "options_.linear = " << linear << ";" << endl
@ -1002,7 +1000,7 @@ ModFile::writeMOutput(const string& basename, bool clear_all, bool clear_global,
} }
if (!onlymodel) if (!onlymodel)
config_file.writeCluster(mOutputFile); config.writeCluster(mOutputFile);
if (bytecode) if (bytecode)
mOutputFile << "if exist('bytecode') ~= 3" << endl mOutputFile << "if exist('bytecode') ~= 3" << endl
@ -1131,7 +1129,7 @@ ModFile::writeMOutput(const string& basename, bool clear_all, bool clear_global,
<< "_results.mat'], 'options_mom_', '-append');" << endl << "_results.mat'], 'options_mom_', '-append');" << endl
<< "end" << endl; << "end" << endl;
config_file.writeEndParallel(mOutputFile); config.writeEndParallel(mOutputFile);
if (!no_warn) if (!no_warn)
{ {
@ -1301,6 +1299,9 @@ ModFile::writeJsonOutputParsingCheck(const string& basename, JsonFileOutputType
output << ","; output << ",";
dynamic_model.writeJsonDynamicModelInfo(output); dynamic_model.writeJsonDynamicModelInfo(output);
} }
output << R"(, "steady_state_model": )" << mod_file_struct.steady_state_model_present << endl;
output << "}" << endl; output << "}" << endl;
ostringstream original_model_output; ostringstream original_model_output;

View File

@ -26,7 +26,7 @@
#include <ostream> #include <ostream>
#include <sstream> #include <sstream>
#include "ConfigFile.hh" #include "Configuration.hh"
#include "DynamicModel.hh" #include "DynamicModel.hh"
#include "ExtendedPreprocessorTypes.hh" #include "ExtendedPreprocessorTypes.hh"
#include "ExternalFunctionsTable.hh" #include "ExternalFunctionsTable.hh"
@ -176,7 +176,7 @@ public:
\param compute_xrefs if true, equation cross references will be computed \param compute_xrefs if true, equation cross references will be computed
*/ */
void writeMOutput(const string& basename, bool clear_all, bool clear_global, bool no_warn, void writeMOutput(const string& basename, bool clear_all, bool clear_global, bool no_warn,
bool console, bool nograph, bool nointeractive, const ConfigFile& config_file, bool console, bool nograph, bool nointeractive, const Configuration& config,
bool check_model_changes, bool minimal_workspace, bool compute_xrefs, bool check_model_changes, bool minimal_workspace, bool compute_xrefs,
const string& mexext, const filesystem::path& matlabroot, bool onlymodel, const string& mexext, const filesystem::path& matlabroot, bool onlymodel,
bool gui, bool notime) const; bool gui, bool notime) const;

View File

@ -529,6 +529,7 @@ Epilogue::writeOutput(ostream& output) const
expr->collectVariables(SymbolType::endogenous, endogs); expr->collectVariables(SymbolType::endogenous, endogs);
vector<string> symbol_list; vector<string> symbol_list;
symbol_list.reserve(endogs.size());
for (auto symb_id : endogs) for (auto symb_id : endogs)
symbol_list.push_back(symbol_table.getName(symb_id)); symbol_list.push_back(symbol_table.getName(symb_id));
SymbolList {move(symbol_list)}.writeOutput("M_.epilogue_var_list_", output); SymbolList {move(symbol_list)}.writeOutput("M_.epilogue_var_list_", output);

View File

@ -109,7 +109,7 @@ ModelTree::copyHelper(const ModelTree& m)
blocks_derivatives.push_back(v); blocks_derivatives.push_back(v);
} }
auto convert_vector_tt = [f](vector<temporary_terms_t> vtt) { auto convert_vector_tt = [f](const vector<temporary_terms_t>& vtt) {
vector<temporary_terms_t> vtt2; vector<temporary_terms_t> vtt2;
for (const auto& tt : vtt) for (const auto& tt : vtt)
{ {
@ -1169,7 +1169,7 @@ ModelTree::fixNestedParenthesis(ostringstream& output, map<string, string>& tmp_
if (auto it = tmp_paren_vars.find(val); it == tmp_paren_vars.end()) if (auto it = tmp_paren_vars.find(val); it == tmp_paren_vars.end())
{ {
varname = "paren32_tmp_var_" + to_string(i1++); varname = "paren32_tmp_var_" + to_string(i1++);
repstr = repstr + varname + " = " + val + ";\n"; repstr += varname + " = " + val + ";\n";
tmp_paren_vars[val] = varname; tmp_paren_vars[val] = varname;
} }
else else
@ -1182,12 +1182,12 @@ ModelTree::fixNestedParenthesis(ostringstream& output, map<string, string>& tmp_
if (auto it = tmp_paren_vars.find(str1); it == tmp_paren_vars.end()) if (auto it = tmp_paren_vars.find(str1); it == tmp_paren_vars.end())
{ {
varname = "paren32_tmp_var_" + to_string(i1++); varname = "paren32_tmp_var_" + to_string(i1++);
repstr = repstr + varname + " = " + str1 + ";\n"; repstr += varname + " = " + str1 + ";\n";
} }
else else
varname = it->second; varname = it->second;
str.replace(first_open_paren, matching_paren - first_open_paren + 1, varname); str.replace(first_open_paren, matching_paren - first_open_paren + 1, varname);
size_t insertLoc = str.find_last_of("\n", first_open_paren); size_t insertLoc = str.find_last_of('\n', first_open_paren);
str.insert(insertLoc + 1, repstr); str.insert(insertLoc + 1, repstr);
hit_limit = false; hit_limit = false;
i = -1; i = -1;
@ -1394,13 +1394,13 @@ ModelTree::writeLatexModelFile(const string& mod_basename, const string& latex_b
} }
void void
ModelTree::addEquation(expr_t eq, optional<int> lineno) ModelTree::addEquation(expr_t eq, const optional<int>& lineno)
{ {
auto beq = dynamic_cast<BinaryOpNode*>(eq); auto beq = dynamic_cast<BinaryOpNode*>(eq);
assert(beq && beq->op_code == BinaryOpcode::equal); assert(beq && beq->op_code == BinaryOpcode::equal);
equations.push_back(beq); equations.push_back(beq);
equations_lineno.push_back(move(lineno)); equations_lineno.push_back(lineno);
} }
void void
@ -1412,10 +1412,10 @@ ModelTree::findConstantEquationsWithoutMcpTag(map<VariableNode*, NumConstNode*>&
} }
void void
ModelTree::addEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags) ModelTree::addEquation(expr_t eq, const optional<int>& lineno, map<string, string> eq_tags)
{ {
equation_tags.add(equations.size(), move(eq_tags)); equation_tags.add(equations.size(), move(eq_tags));
addEquation(eq, move(lineno)); addEquation(eq, lineno);
} }
void void
@ -1927,7 +1927,13 @@ ModelTree::initializeMEXCompilationWorkers(int numworkers, const filesystem::pat
cout << "Spawning " << numworkers << " threads for compiling MEX files." << endl; cout << "Spawning " << numworkers << " threads for compiling MEX files." << endl;
for (int i {0}; i < numworkers; i++) for (int i {0}; i < numworkers; i++)
mex_compilation_workers.emplace_back([](stop_token stoken) { /* Passing the stop_token by const reference is ok (and makes clang-tidy happier),
since the std::jthread constructor calls the lambda with the return argument of the
get_stop_token() method, which returns a stop_token by value; hence there is no lifetime
issue. See:
https://stackoverflow.com/questions/72990607/const-stdstop-token-or-just-stdstop-token-as-parameter-for-thread-funct
*/
mex_compilation_workers.emplace_back([](const stop_token& stoken) {
unique_lock<mutex> lk {mex_compilation_mut}; unique_lock<mutex> lk {mex_compilation_mut};
filesystem::path output; filesystem::path output;
string cmd; string cmd;

View File

@ -294,9 +294,10 @@ protected:
const string& concat) const; const string& concat) const;
//! Writes temporary terms in bytecode //! Writes temporary terms in bytecode
template<ExprNodeBytecodeOutputType output_type> template<ExprNodeBytecodeOutputType output_type>
void void writeBytecodeTemporaryTerms(const temporary_terms_t& tt,
writeBytecodeTemporaryTerms(const temporary_terms_t& tt, temporary_terms_t& temporary_terms_union, temporary_terms_t& temporary_terms_union,
BytecodeWriter& code_file, deriv_node_temp_terms_t& tef_terms) const; Bytecode::Writer& code_file,
deriv_node_temp_terms_t& tef_terms) const;
/* Adds information for (non-block) bytecode simulation in a separate .bin /* Adds information for (non-block) bytecode simulation in a separate .bin
file. file.
Returns the number of first derivatives w.r.t. endogenous variables */ Returns the number of first derivatives w.r.t. endogenous variables */
@ -343,11 +344,11 @@ protected:
// Helper for writing bytecode (without block decomposition) // Helper for writing bytecode (without block decomposition)
template<bool dynamic> template<bool dynamic>
void writeBytecodeHelper(BytecodeWriter& code_file) const; void writeBytecodeHelper(Bytecode::Writer& code_file) const;
// Helper for writing blocks in bytecode // Helper for writing blocks in bytecode
template<bool dynamic> template<bool dynamic>
void writeBlockBytecodeHelper(BytecodeWriter& code_file, int block, void writeBlockBytecodeHelper(Bytecode::Writer& code_file, int block,
temporary_terms_t& temporary_terms_union) const; temporary_terms_t& temporary_terms_union) const;
// Helper for writing sparse derivatives indices in MATLAB/Octave driver file // Helper for writing sparse derivatives indices in MATLAB/Octave driver file
@ -387,7 +388,7 @@ protected:
//! Writes model equations in bytecode //! Writes model equations in bytecode
template<ExprNodeBytecodeOutputType output_type> template<ExprNodeBytecodeOutputType output_type>
void writeBytecodeModelEquations(BytecodeWriter& code_file, void writeBytecodeModelEquations(Bytecode::Writer& code_file,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms) const; const deriv_node_temp_terms_t& tef_terms) const;
@ -650,9 +651,9 @@ public:
//! Absolute value under which a number is considered to be zero //! Absolute value under which a number is considered to be zero
double cutoff {1e-15}; double cutoff {1e-15};
//! Declare a node as an equation of the model; also give its line number //! Declare a node as an equation of the model; also give its line number
void addEquation(expr_t eq, optional<int> lineno); void addEquation(expr_t eq, const optional<int>& lineno);
//! Declare a node as an equation of the model, also giving its tags //! Declare a node as an equation of the model, also giving its tags
void addEquation(expr_t eq, optional<int> lineno, map<string, string> eq_tags); void addEquation(expr_t eq, const optional<int>& lineno, map<string, string> eq_tags);
//! Declare a node as an auxiliary equation of the model, adding it at the end of the list of //! Declare a node as an auxiliary equation of the model, adding it at the end of the list of
//! auxiliary equations //! auxiliary equations
void addAuxEquation(expr_t eq); void addAuxEquation(expr_t eq);
@ -1518,7 +1519,7 @@ template<ExprNodeBytecodeOutputType output_type>
void void
ModelTree::writeBytecodeTemporaryTerms(const temporary_terms_t& tt, ModelTree::writeBytecodeTemporaryTerms(const temporary_terms_t& tt,
temporary_terms_t& temporary_terms_union, temporary_terms_t& temporary_terms_union,
BytecodeWriter& code_file, Bytecode::Writer& code_file,
deriv_node_temp_terms_t& tef_terms) const deriv_node_temp_terms_t& tef_terms) const
{ {
for (auto it : tt) for (auto it : tt)
@ -1528,16 +1529,16 @@ ModelTree::writeBytecodeTemporaryTerms(const temporary_terms_t& tt,
temporary_terms_idxs, tef_terms); temporary_terms_idxs, tef_terms);
int idx {temporary_terms_idxs.at(it)}; int idx {temporary_terms_idxs.at(it)};
code_file << FNUMEXPR_ {ExpressionType::TemporaryTerm, idx}; code_file << Bytecode::FNUMEXPR {Bytecode::ExpressionType::TemporaryTerm, idx};
it->writeBytecodeOutput(code_file, output_type, temporary_terms_union, temporary_terms_idxs, it->writeBytecodeOutput(code_file, output_type, temporary_terms_union, temporary_terms_idxs,
tef_terms); tef_terms);
static_assert(output_type == ExprNodeBytecodeOutputType::dynamicModel static_assert(output_type == ExprNodeBytecodeOutputType::dynamicModel
|| output_type == ExprNodeBytecodeOutputType::staticModel); || output_type == ExprNodeBytecodeOutputType::staticModel);
if constexpr (output_type == ExprNodeBytecodeOutputType::dynamicModel) if constexpr (output_type == ExprNodeBytecodeOutputType::dynamicModel)
code_file << FSTPT_ {idx}; code_file << Bytecode::FSTPT {idx};
else else
code_file << FSTPST_ {idx}; code_file << Bytecode::FSTPST {idx};
temporary_terms_union.insert(it); temporary_terms_union.insert(it);
} }
@ -1545,7 +1546,7 @@ ModelTree::writeBytecodeTemporaryTerms(const temporary_terms_t& tt,
template<ExprNodeBytecodeOutputType output_type> template<ExprNodeBytecodeOutputType output_type>
void void
ModelTree::writeBytecodeModelEquations(BytecodeWriter& code_file, ModelTree::writeBytecodeModelEquations(Bytecode::Writer& code_file,
const temporary_terms_t& temporary_terms, const temporary_terms_t& temporary_terms,
const deriv_node_temp_terms_t& tef_terms) const const deriv_node_temp_terms_t& tef_terms) const
{ {
@ -1553,7 +1554,7 @@ ModelTree::writeBytecodeModelEquations(BytecodeWriter& code_file,
{ {
BinaryOpNode* eq_node {equations[eq]}; BinaryOpNode* eq_node {equations[eq]};
expr_t lhs {eq_node->arg1}, rhs {eq_node->arg2}; expr_t lhs {eq_node->arg1}, rhs {eq_node->arg2};
code_file << FNUMEXPR_ {ExpressionType::ModelEquation, eq}; code_file << Bytecode::FNUMEXPR {Bytecode::ExpressionType::ModelEquation, eq};
// Test if the right hand side of the equation is empty. // Test if the right hand side of the equation is empty.
double vrhs {1.0}; double vrhs {1.0};
try try
@ -1571,20 +1572,20 @@ ModelTree::writeBytecodeModelEquations(BytecodeWriter& code_file,
rhs->writeBytecodeOutput(code_file, output_type, temporary_terms, temporary_terms_idxs, rhs->writeBytecodeOutput(code_file, output_type, temporary_terms, temporary_terms_idxs,
tef_terms); tef_terms);
code_file << FBINARY_ {BinaryOpcode::minus} << FSTPR_ {eq}; code_file << Bytecode::FBINARY {BinaryOpcode::minus} << Bytecode::FSTPR {eq};
} }
else // The right hand side of the equation is empty ⇒ residual=lhs else // The right hand side of the equation is empty ⇒ residual=lhs
{ {
lhs->writeBytecodeOutput(code_file, output_type, temporary_terms, temporary_terms_idxs, lhs->writeBytecodeOutput(code_file, output_type, temporary_terms, temporary_terms_idxs,
tef_terms); tef_terms);
code_file << FSTPR_ {eq}; code_file << Bytecode::FSTPR {eq};
} }
} }
} }
template<bool dynamic> template<bool dynamic>
void void
ModelTree::writeBytecodeHelper(BytecodeWriter& code_file) const ModelTree::writeBytecodeHelper(Bytecode::Writer& code_file) const
{ {
constexpr ExprNodeBytecodeOutputType output_type { constexpr ExprNodeBytecodeOutputType output_type {
dynamic ? ExprNodeBytecodeOutputType::dynamicModel : ExprNodeBytecodeOutputType::staticModel}; dynamic ? ExprNodeBytecodeOutputType::dynamicModel : ExprNodeBytecodeOutputType::staticModel};
@ -1596,7 +1597,7 @@ ModelTree::writeBytecodeHelper(BytecodeWriter& code_file) const
code_file, tef_terms); code_file, tef_terms);
writeBytecodeModelEquations<output_type>(code_file, temporary_terms_union, tef_terms); writeBytecodeModelEquations<output_type>(code_file, temporary_terms_union, tef_terms);
code_file << FENDEQU_ {}; code_file << Bytecode::FENDEQU {};
// Temporary terms for the Jacobian // Temporary terms for the Jacobian
writeBytecodeTemporaryTerms<output_type>(temporary_terms_derivatives[1], temporary_terms_union, writeBytecodeTemporaryTerms<output_type>(temporary_terms_derivatives[1], temporary_terms_union,
@ -1604,7 +1605,7 @@ ModelTree::writeBytecodeHelper(BytecodeWriter& code_file) const
// Get the current code_file position and jump if “evaluate” mode // Get the current code_file position and jump if “evaluate” mode
int pos_jmpifeval {code_file.getInstructionCounter()}; int pos_jmpifeval {code_file.getInstructionCounter()};
code_file << FJMPIFEVAL_ {0}; // Use 0 as jump offset for the time being code_file << Bytecode::FJMPIFEVAL {0}; // Use 0 as jump offset for the time being
// The Jacobian in “simulate” mode // The Jacobian in “simulate” mode
vector<vector<tuple<int, int, int>>> my_derivatives(symbol_table.endo_nbr()); vector<vector<tuple<int, int, int>>> my_derivatives(symbol_table.endo_nbr());
@ -1618,49 +1619,53 @@ ModelTree::writeBytecodeHelper(BytecodeWriter& code_file) const
int tsid {getTypeSpecificIDByDerivID(deriv_id)}; int tsid {getTypeSpecificIDByDerivID(deriv_id)};
int lag {getLagByDerivID(deriv_id)}; int lag {getLagByDerivID(deriv_id)};
if constexpr (dynamic) if constexpr (dynamic)
code_file << FNUMEXPR_ {ExpressionType::FirstEndoDerivative, eq, tsid, lag}; code_file << Bytecode::FNUMEXPR {Bytecode::ExpressionType::FirstEndoDerivative, eq,
tsid, lag};
else else
code_file << FNUMEXPR_ {ExpressionType::FirstEndoDerivative, eq, tsid}; code_file << Bytecode::FNUMEXPR {Bytecode::ExpressionType::FirstEndoDerivative, eq,
tsid};
if (!my_derivatives[eq].size()) if (!my_derivatives[eq].size())
my_derivatives[eq].clear(); my_derivatives[eq].clear();
my_derivatives[eq].emplace_back(tsid, lag, count_u); my_derivatives[eq].emplace_back(tsid, lag, count_u);
d1->writeBytecodeOutput(code_file, output_type, temporary_terms_union, d1->writeBytecodeOutput(code_file, output_type, temporary_terms_union,
temporary_terms_idxs, tef_terms); temporary_terms_idxs, tef_terms);
if constexpr (dynamic) if constexpr (dynamic)
code_file << FSTPU_ {count_u}; code_file << Bytecode::FSTPU {count_u};
else else
code_file << FSTPSU_ {count_u}; code_file << Bytecode::FSTPSU {count_u};
count_u++; count_u++;
} }
} }
for (int i {0}; i < symbol_table.endo_nbr(); i++) for (int i {0}; i < symbol_table.endo_nbr(); i++)
{ {
code_file << FLDR_ {i}; code_file << Bytecode::FLDR {i};
if (my_derivatives[i].size()) if (my_derivatives[i].size())
{ {
for (bool first_term {true}; const auto& [tsid, lag, uidx] : my_derivatives[i]) for (bool first_term {true}; const auto& [tsid, lag, uidx] : my_derivatives[i])
{ {
if constexpr (dynamic) if constexpr (dynamic)
code_file << FLDU_ {uidx} << FLDV_ {SymbolType::endogenous, tsid, lag}; code_file << Bytecode::FLDU {uidx}
<< Bytecode::FLDV {SymbolType::endogenous, tsid, lag};
else else
code_file << FLDSU_ {uidx} << FLDSV_ {SymbolType::endogenous, tsid}; code_file << Bytecode::FLDSU {uidx}
code_file << FBINARY_ {BinaryOpcode::times}; << Bytecode::FLDSV {SymbolType::endogenous, tsid};
code_file << Bytecode::FBINARY {BinaryOpcode::times};
if (!exchange(first_term, false)) if (!exchange(first_term, false))
code_file << FBINARY_ {BinaryOpcode::plus}; code_file << Bytecode::FBINARY {BinaryOpcode::plus};
} }
code_file << FBINARY_ {BinaryOpcode::minus}; code_file << Bytecode::FBINARY {BinaryOpcode::minus};
} }
if constexpr (dynamic) if constexpr (dynamic)
code_file << FSTPU_ {i}; code_file << Bytecode::FSTPU {i};
else else
code_file << FSTPSU_ {i}; code_file << Bytecode::FSTPSU {i};
} }
// Jump unconditionally after the block // Jump unconditionally after the block
int pos_jmp {code_file.getInstructionCounter()}; int pos_jmp {code_file.getInstructionCounter()};
code_file << FJMP_ {0}; // Use 0 as jump offset for the time being code_file << Bytecode::FJMP {0}; // Use 0 as jump offset for the time being
// Update jump offset for previous JMPIFEVAL // Update jump offset for previous JMPIFEVAL
code_file.overwriteInstruction(pos_jmpifeval, FJMPIFEVAL_ {pos_jmp - pos_jmpifeval}); code_file.overwriteInstruction(pos_jmpifeval, Bytecode::FJMPIFEVAL {pos_jmp - pos_jmpifeval});
// The Jacobian in “evaluate” mode // The Jacobian in “evaluate” mode
for (const auto& [indices, d1] : derivatives[1]) for (const auto& [indices, d1] : derivatives[1])
@ -1672,28 +1677,28 @@ ModelTree::writeBytecodeHelper(BytecodeWriter& code_file) const
if constexpr (dynamic) if constexpr (dynamic)
{ {
ExpressionType expr_type; Bytecode::ExpressionType expr_type;
switch (type) switch (type)
{ {
case SymbolType::endogenous: case SymbolType::endogenous:
expr_type = ExpressionType::FirstEndoDerivative; expr_type = Bytecode::ExpressionType::FirstEndoDerivative;
break; break;
case SymbolType::exogenous: case SymbolType::exogenous:
expr_type = ExpressionType::FirstExoDerivative; expr_type = Bytecode::ExpressionType::FirstExoDerivative;
break; break;
case SymbolType::exogenousDet: case SymbolType::exogenousDet:
expr_type = ExpressionType::FirstExodetDerivative; expr_type = Bytecode::ExpressionType::FirstExodetDerivative;
break; break;
default: default:
assert(false); assert(false);
break; break;
} }
code_file << FNUMEXPR_ {expr_type, eq, tsid, lag}; code_file << Bytecode::FNUMEXPR {expr_type, eq, tsid, lag};
} }
else else
{ {
assert(type == SymbolType::endogenous); assert(type == SymbolType::endogenous);
code_file << FNUMEXPR_ {ExpressionType::FirstEndoDerivative, eq, tsid}; code_file << Bytecode::FNUMEXPR {Bytecode::ExpressionType::FirstEndoDerivative, eq, tsid};
} }
d1->writeBytecodeOutput(code_file, output_type, temporary_terms_union, temporary_terms_idxs, d1->writeBytecodeOutput(code_file, output_type, temporary_terms_union, temporary_terms_idxs,
@ -1702,22 +1707,22 @@ ModelTree::writeBytecodeHelper(BytecodeWriter& code_file) const
{ {
// Bytecode MEX uses a separate matrix for exogenous and exodet Jacobians // Bytecode MEX uses a separate matrix for exogenous and exodet Jacobians
int jacob_col {type == SymbolType::endogenous ? getJacobianCol(deriv_id, false) : tsid}; int jacob_col {type == SymbolType::endogenous ? getJacobianCol(deriv_id, false) : tsid};
code_file << FSTPG3_ {eq, tsid, lag, jacob_col}; code_file << Bytecode::FSTPG3 {eq, tsid, lag, jacob_col};
} }
else else
code_file << FSTPG2_ {eq, tsid}; code_file << Bytecode::FSTPG2 {eq, tsid};
} }
// Update jump offset for previous JMP // Update jump offset for previous JMP
int pos_end_block {code_file.getInstructionCounter()}; int pos_end_block {code_file.getInstructionCounter()};
code_file.overwriteInstruction(pos_jmp, FJMP_ {pos_end_block - pos_jmp - 1}); code_file.overwriteInstruction(pos_jmp, Bytecode::FJMP {pos_end_block - pos_jmp - 1});
code_file << FENDBLOCK_ {} << FEND_ {}; code_file << Bytecode::FENDBLOCK {} << Bytecode::FEND {};
} }
template<bool dynamic> template<bool dynamic>
void void
ModelTree::writeBlockBytecodeHelper(BytecodeWriter& code_file, int block, ModelTree::writeBlockBytecodeHelper(Bytecode::Writer& code_file, int block,
temporary_terms_t& temporary_terms_union) const temporary_terms_t& temporary_terms_union) const
{ {
constexpr ExprNodeBytecodeOutputType output_type { constexpr ExprNodeBytecodeOutputType output_type {
@ -1740,13 +1745,14 @@ ModelTree::writeBlockBytecodeHelper(BytecodeWriter& code_file, int block,
it->writeBytecodeExternalFunctionOutput(code_file, output_type, temporary_terms_union, it->writeBytecodeExternalFunctionOutput(code_file, output_type, temporary_terms_union,
blocks_temporary_terms_idxs, tef_terms); blocks_temporary_terms_idxs, tef_terms);
code_file << FNUMEXPR_ {ExpressionType::TemporaryTerm, blocks_temporary_terms_idxs.at(it)}; code_file << Bytecode::FNUMEXPR {Bytecode::ExpressionType::TemporaryTerm,
blocks_temporary_terms_idxs.at(it)};
it->writeBytecodeOutput(code_file, output_type, temporary_terms_union, it->writeBytecodeOutput(code_file, output_type, temporary_terms_union,
blocks_temporary_terms_idxs, tef_terms); blocks_temporary_terms_idxs, tef_terms);
if constexpr (dynamic) if constexpr (dynamic)
code_file << FSTPT_ {blocks_temporary_terms_idxs.at(it)}; code_file << Bytecode::FSTPT {blocks_temporary_terms_idxs.at(it)};
else else
code_file << FSTPST_ {blocks_temporary_terms_idxs.at(it)}; code_file << Bytecode::FSTPST {blocks_temporary_terms_idxs.at(it)};
temporary_terms_union.insert(it); temporary_terms_union.insert(it);
} }
}; };
@ -1772,7 +1778,8 @@ ModelTree::writeBlockBytecodeHelper(BytecodeWriter& code_file, int block,
} }
else else
assert(equ_type == EquationType::evaluate); assert(equ_type == EquationType::evaluate);
code_file << FNUMEXPR_ {ExpressionType::ModelEquation, getBlockEquationID(block, i)}; code_file << Bytecode::FNUMEXPR {Bytecode::ExpressionType::ModelEquation,
getBlockEquationID(block, i)};
rhs->writeBytecodeOutput(code_file, output_type, temporary_terms_union, rhs->writeBytecodeOutput(code_file, output_type, temporary_terms_union,
blocks_temporary_terms_idxs, tef_terms); blocks_temporary_terms_idxs, tef_terms);
lhs->writeBytecodeOutput(code_file, assignment_lhs_output_type, temporary_terms_union, lhs->writeBytecodeOutput(code_file, assignment_lhs_output_type, temporary_terms_union,
@ -1787,12 +1794,14 @@ ModelTree::writeBlockBytecodeHelper(BytecodeWriter& code_file, int block,
[[fallthrough]]; [[fallthrough]];
case BlockSimulationType::solveBackwardSimple: case BlockSimulationType::solveBackwardSimple:
case BlockSimulationType::solveForwardSimple: case BlockSimulationType::solveForwardSimple:
code_file << FNUMEXPR_ {ExpressionType::ModelEquation, getBlockEquationID(block, i)}; code_file << Bytecode::FNUMEXPR {Bytecode::ExpressionType::ModelEquation,
getBlockEquationID(block, i)};
lhs->writeBytecodeOutput(code_file, output_type, temporary_terms_union, lhs->writeBytecodeOutput(code_file, output_type, temporary_terms_union,
blocks_temporary_terms_idxs, tef_terms); blocks_temporary_terms_idxs, tef_terms);
rhs->writeBytecodeOutput(code_file, output_type, temporary_terms_union, rhs->writeBytecodeOutput(code_file, output_type, temporary_terms_union,
blocks_temporary_terms_idxs, tef_terms); blocks_temporary_terms_idxs, tef_terms);
code_file << FBINARY_ {BinaryOpcode::minus} << FSTPR_ {i - block_recursive}; code_file << Bytecode::FBINARY {BinaryOpcode::minus}
<< Bytecode::FSTPR {i - block_recursive};
break; break;
} }
} }
@ -1807,11 +1816,11 @@ ModelTree::writeBlockBytecodeHelper(BytecodeWriter& code_file, int block,
be needed in subsequent blocks. */ be needed in subsequent blocks. */
write_eq_tt(blocks[block].size); write_eq_tt(blocks[block].size);
code_file << FENDEQU_ {}; code_file << Bytecode::FENDEQU {};
// Get the current code_file position and jump if evaluating // Get the current code_file position and jump if evaluating
int pos_jmpifeval {code_file.getInstructionCounter()}; int pos_jmpifeval {code_file.getInstructionCounter()};
code_file << FJMPIFEVAL_ {0}; // Use 0 as jump offset for the time being code_file << Bytecode::FJMPIFEVAL {0}; // Use 0 as jump offset for the time being
/* Write the derivatives for the “simulate” mode (not needed if the block /* Write the derivatives for the “simulate” mode (not needed if the block
is of type evaluate backward/forward) */ is of type evaluate backward/forward) */
@ -1825,15 +1834,16 @@ ModelTree::writeBlockBytecodeHelper(BytecodeWriter& code_file, int block,
{ {
int eqr {getBlockEquationID(block, 0)}; int eqr {getBlockEquationID(block, 0)};
int varr {getBlockVariableID(block, 0)}; int varr {getBlockVariableID(block, 0)};
code_file << FNUMEXPR_ {ExpressionType::FirstEndoDerivative, eqr, varr, 0}; code_file << Bytecode::FNUMEXPR {Bytecode::ExpressionType::FirstEndoDerivative, eqr,
varr, 0};
// Get contemporaneous derivative of the single variable in the block // Get contemporaneous derivative of the single variable in the block
if (auto it {blocks_derivatives[block].find({0, 0, 0})}; if (auto it {blocks_derivatives[block].find({0, 0, 0})};
it != blocks_derivatives[block].end()) it != blocks_derivatives[block].end())
it->second->writeBytecodeOutput(code_file, output_type, temporary_terms_union, it->second->writeBytecodeOutput(code_file, output_type, temporary_terms_union,
blocks_temporary_terms_idxs, tef_terms); blocks_temporary_terms_idxs, tef_terms);
else else
code_file << FLDZ_ {}; code_file << Bytecode::FLDZ {};
code_file << FSTPG_ {0}; code_file << Bytecode::FSTPG {0};
} }
break; break;
@ -1858,13 +1868,14 @@ ModelTree::writeBlockBytecodeHelper(BytecodeWriter& code_file, int block,
&& (simulation_type == BlockSimulationType::solveForwardComplete && (simulation_type == BlockSimulationType::solveForwardComplete
|| simulation_type == BlockSimulationType::solveBackwardComplete)) || simulation_type == BlockSimulationType::solveBackwardComplete))
continue; continue;
code_file << FNUMEXPR_ {ExpressionType::FirstEndoDerivative, eqr, varr, lag}; code_file << Bytecode::FNUMEXPR {Bytecode::ExpressionType::FirstEndoDerivative,
eqr, varr, lag};
d1->writeBytecodeOutput(code_file, output_type, temporary_terms_union, d1->writeBytecodeOutput(code_file, output_type, temporary_terms_union,
blocks_temporary_terms_idxs, tef_terms); blocks_temporary_terms_idxs, tef_terms);
if constexpr (dynamic) if constexpr (dynamic)
code_file << FSTPU_ {count_u}; code_file << Bytecode::FSTPU {count_u};
else else
code_file << FSTPSU_ {count_u}; code_file << Bytecode::FSTPSU {count_u};
Uf[eqr].emplace_back(count_u, varr, lag); Uf[eqr].emplace_back(count_u, varr, lag);
count_u++; count_u++;
} }
@ -1872,22 +1883,25 @@ ModelTree::writeBlockBytecodeHelper(BytecodeWriter& code_file, int block,
for (int i {0}; i < block_size; i++) for (int i {0}; i < block_size; i++)
if (i >= block_recursive) if (i >= block_recursive)
{ {
code_file << FLDR_ {i - block_recursive} << FLDZ_ {}; code_file << Bytecode::FLDR {i - block_recursive} << Bytecode::FLDZ {};
int eqr {getBlockEquationID(block, i)}; int eqr {getBlockEquationID(block, i)};
for (const auto& [index_u, var, lag] : Uf[eqr]) for (const auto& [index_u, var, lag] : Uf[eqr])
{ {
if constexpr (dynamic) if constexpr (dynamic)
code_file << FLDU_ {index_u} << FLDV_ {SymbolType::endogenous, var, lag}; code_file << Bytecode::FLDU {index_u}
<< Bytecode::FLDV {SymbolType::endogenous, var, lag};
else else
code_file << FLDSU_ {index_u} << FLDSV_ {SymbolType::endogenous, var}; code_file << Bytecode::FLDSU {index_u}
code_file << FBINARY_ {BinaryOpcode::times} << FBINARY_ {BinaryOpcode::plus}; << Bytecode::FLDSV {SymbolType::endogenous, var};
code_file << Bytecode::FBINARY {BinaryOpcode::times}
<< Bytecode::FBINARY {BinaryOpcode::plus};
} }
code_file << FBINARY_ {BinaryOpcode::minus}; code_file << Bytecode::FBINARY {BinaryOpcode::minus};
if constexpr (dynamic) if constexpr (dynamic)
code_file << FSTPU_ {i - block_recursive}; code_file << Bytecode::FSTPU {i - block_recursive};
else else
code_file << FSTPSU_ {i - block_recursive}; code_file << Bytecode::FSTPSU {i - block_recursive};
} }
} }
break; break;
@ -1898,9 +1912,9 @@ ModelTree::writeBlockBytecodeHelper(BytecodeWriter& code_file, int block,
// Jump unconditionally after the block // Jump unconditionally after the block
int pos_jmp {code_file.getInstructionCounter()}; int pos_jmp {code_file.getInstructionCounter()};
code_file << FJMP_ {0}; // Use 0 as jump offset for the time being code_file << Bytecode::FJMP {0}; // Use 0 as jump offset for the time being
// Update jump offset for previous JMPIFEVAL // Update jump offset for previous JMPIFEVAL
code_file.overwriteInstruction(pos_jmpifeval, FJMPIFEVAL_ {pos_jmp - pos_jmpifeval}); code_file.overwriteInstruction(pos_jmpifeval, Bytecode::FJMPIFEVAL {pos_jmp - pos_jmpifeval});
// Write the derivatives for the “evaluate” mode // Write the derivatives for the “evaluate” mode
for (const auto& [indices, d] : blocks_derivatives[block]) for (const auto& [indices, d] : blocks_derivatives[block])
@ -1908,22 +1922,24 @@ ModelTree::writeBlockBytecodeHelper(BytecodeWriter& code_file, int block,
const auto& [eq, var, lag] {indices}; const auto& [eq, var, lag] {indices};
int eqr {getBlockEquationID(block, eq)}; int eqr {getBlockEquationID(block, eq)};
int varr {getBlockVariableID(block, var)}; int varr {getBlockVariableID(block, var)};
code_file << FNUMEXPR_ {ExpressionType::FirstEndoDerivative, eqr, varr, lag}; code_file << Bytecode::FNUMEXPR {Bytecode::ExpressionType::FirstEndoDerivative, eqr, varr,
lag};
d->writeBytecodeOutput(code_file, output_type, temporary_terms_union, d->writeBytecodeOutput(code_file, output_type, temporary_terms_union,
blocks_temporary_terms_idxs, tef_terms); blocks_temporary_terms_idxs, tef_terms);
assert(eq >= block_recursive); assert(eq >= block_recursive);
if constexpr (dynamic) if constexpr (dynamic)
code_file << FSTPG3_ {eq - block_recursive, var, lag, code_file << Bytecode::FSTPG3 {eq - block_recursive, var, lag,
getBlockJacobianEndoCol(block, var, lag)}; getBlockJacobianEndoCol(block, var, lag)};
else else
code_file << FSTPG2_ {eq - block_recursive, getBlockJacobianEndoCol(block, var, lag)}; code_file << Bytecode::FSTPG2 {eq - block_recursive,
getBlockJacobianEndoCol(block, var, lag)};
} }
// Update jump offset for previous JMP // Update jump offset for previous JMP
int pos_end_block {code_file.getInstructionCounter()}; int pos_end_block {code_file.getInstructionCounter()};
code_file.overwriteInstruction(pos_jmp, FJMP_ {pos_end_block - pos_jmp - 1}); code_file.overwriteInstruction(pos_jmp, Bytecode::FJMP {pos_end_block - pos_jmp - 1});
code_file << FENDBLOCK_ {}; code_file << Bytecode::FENDBLOCK {};
} }
template<bool dynamic> template<bool dynamic>

View File

@ -341,7 +341,7 @@ ParsingDriver::add_inf_constant()
expr_t expr_t
ParsingDriver::add_model_variable(const string& name) ParsingDriver::add_model_variable(const string& name)
{ {
if (name.find(".") != string::npos) if (name.find('.') != string::npos)
error(name + " treated as a variable, but it contains a '.'"); error(name + " treated as a variable, but it contains a '.'");
check_symbol_existence_in_model_block(name); check_symbol_existence_in_model_block(name);
@ -456,7 +456,7 @@ ParsingDriver::add_model_variable(int symb_id, int lag)
expr_t expr_t
ParsingDriver::add_expression_variable(const string& name) ParsingDriver::add_expression_variable(const string& name)
{ {
if (name.find(".") != string::npos) if (name.find('.') != string::npos)
error(name + " treated as a variable, but it contains a '.'"); error(name + " treated as a variable, but it contains a '.'");
if (parsing_epilogue && !mod_file->symbol_table.exists(name)) if (parsing_epilogue && !mod_file->symbol_table.exists(name))
@ -2024,9 +2024,9 @@ ParsingDriver::run_estimation(vector<string> symbol_list)
} }
void void
ParsingDriver::dynare_sensitivity() ParsingDriver::sensitivity()
{ {
mod_file->addStatement(make_unique<DynareSensitivityStatement>(move(options_list))); mod_file->addStatement(make_unique<SensitivityStatement>(move(options_list)));
options_list.clear(); options_list.clear();
} }
@ -2127,7 +2127,7 @@ ParsingDriver::set_optim_weights(string name, expr_t value)
check_symbol_is_endogenous(name); check_symbol_is_endogenous(name);
if (var_weights.contains(name)) if (var_weights.contains(name))
error("optim_weights: " + name + " declared twice"); error("optim_weights: " + name + " declared twice");
var_weights[move(name)] = move(value); var_weights[move(name)] = value;
} }
void void
@ -2594,8 +2594,8 @@ ParsingDriver::plot_conditional_forecast(const optional<string>& periods,
optional<int> iperiods; optional<int> iperiods;
if (periods) if (periods)
iperiods = stoi(*periods); iperiods = stoi(*periods);
mod_file->addStatement(make_unique<PlotConditionalForecastStatement>( mod_file->addStatement(make_unique<PlotConditionalForecastStatement>(iperiods, move(symbol_list),
move(iperiods), move(symbol_list), mod_file->symbol_table)); mod_file->symbol_table));
} }
void void
@ -3875,3 +3875,16 @@ ParsingDriver::resid()
mod_file->addStatement(make_unique<ResidStatement>(move(options_list))); mod_file->addStatement(make_unique<ResidStatement>(move(options_list)));
options_list.clear(); options_list.clear();
} }
void
ParsingDriver::matched_irfs(MatchedIrfsStatement::matched_irfs_t values_weights, bool overwrite)
{
mod_file->addStatement(make_unique<MatchedIrfsStatement>(move(values_weights), overwrite));
}
void
ParsingDriver::matched_irfs_weights(MatchedIrfsWeightsStatement::matched_irfs_weights_t weights,
bool overwrite)
{
mod_file->addStatement(make_unique<MatchedIrfsWeightsStatement>(move(weights), overwrite));
}

View File

@ -98,6 +98,7 @@ private:
//! message if it isn't //! message if it isn't
void check_symbol_is_endogenous_or_exogenous(const string& name, bool allow_exo_det); void check_symbol_is_endogenous_or_exogenous(const string& name, bool allow_exo_det);
public:
//! Checks that a given symbol exists and is a endogenous, and stops with an error message if it //! Checks that a given symbol exists and is a endogenous, and stops with an error message if it
//! isn't //! isn't
void check_symbol_is_endogenous(const string& name); void check_symbol_is_endogenous(const string& name);
@ -106,6 +107,7 @@ private:
//! isn't //! isn't
void check_symbol_is_exogenous(const string& name, bool allow_exo_det); void check_symbol_is_exogenous(const string& name, bool allow_exo_det);
private:
//! Checks for symbol existence in model block. If it doesn't exist, an error message is stored to //! Checks for symbol existence in model block. If it doesn't exist, an error message is stored to
//! be printed at the end of the model block //! be printed at the end of the model block
void check_symbol_existence_in_model_block(const string& name); void check_symbol_existence_in_model_block(const string& name);
@ -592,8 +594,8 @@ public:
void set_corr_options(string name1, string name2, string subsample_name); void set_corr_options(string name1, string name2, string subsample_name);
//! Runs estimation process //! Runs estimation process
void run_estimation(vector<string> symbol_list); void run_estimation(vector<string> symbol_list);
//! Runs dynare_sensitivy() //! Runs sensitivity
void dynare_sensitivity(); void sensitivity();
//! Check that no observed variable has yet be defined //! Check that no observed variable has yet be defined
void check_varobs(); void check_varobs();
//! Add a new observed variable //! Add a new observed variable
@ -954,6 +956,11 @@ public:
void set_pac_target_info_component_kind(PacTargetKind kind); void set_pac_target_info_component_kind(PacTargetKind kind);
// Add a resid statement // Add a resid statement
void resid(); void resid();
// Add a matched_irfs block
void matched_irfs(MatchedIrfsStatement::matched_irfs_t values_weights, bool overwrite);
// Add a matched_irfs_weights block
void matched_irfs_weights(MatchedIrfsWeightsStatement::matched_irfs_weights_t weights,
bool overwrite);
// Returns true iff the string is a legal symbol identifier (see NAME token in lexer) // Returns true iff the string is a legal symbol identifier (see NAME token in lexer)
static bool isSymbolIdentifier(const string& str); static bool isSymbolIdentifier(const string& str);
// Given an Occbin regime name, returns the corresponding auxiliary parameter // Given an Occbin regime name, returns the corresponding auxiliary parameter

View File

@ -1,5 +1,5 @@
/* /*
* Copyright © 2006-2022 Dynare Team * Copyright © 2006-2023 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
@ -168,7 +168,7 @@ void
OptionsList::writeOutput(ostream& output, const string& option_group) const OptionsList::writeOutput(ostream& output, const string& option_group) const
{ {
// Initialize option_group as an empty struct iff the field does not exist! // Initialize option_group as an empty struct iff the field does not exist!
if (size_t idx = option_group.find_last_of("."); idx != string::npos) if (size_t idx = option_group.find_last_of('.'); idx != string::npos)
{ {
output << "if ~isfield(" << option_group.substr(0, idx) << ",'" output << "if ~isfield(" << option_group.substr(0, idx) << ",'"
<< option_group.substr(idx + 1) << "')" << endl; << option_group.substr(idx + 1) << "')" << endl;

View File

@ -131,24 +131,24 @@ StaticModel::writeStaticBytecode(const string& basename) const
// First write the .bin file // First write the .bin file
int u_count_int {writeBytecodeBinFile(basename + "/model/bytecode/static.bin", false)}; int u_count_int {writeBytecodeBinFile(basename + "/model/bytecode/static.bin", false)};
BytecodeWriter code_file {basename + "/model/bytecode/static.cod"}; Bytecode::Writer code_file {basename + "/model/bytecode/static.cod"};
vector<int> eq_idx(equations.size()); vector<int> eq_idx(equations.size());
iota(eq_idx.begin(), eq_idx.end(), 0); iota(eq_idx.begin(), eq_idx.end(), 0);
vector<int> endo_idx(symbol_table.endo_nbr()); vector<int> endo_idx(symbol_table.endo_nbr());
iota(endo_idx.begin(), endo_idx.end(), 0); iota(endo_idx.begin(), endo_idx.end(), 0);
// Declare temporary terms and the (single) block // Declare temporary terms and the (single) block
code_file << FDIMST_ {static_cast<int>(temporary_terms_derivatives[0].size() code_file << Bytecode::FDIMST {static_cast<int>(temporary_terms_derivatives[0].size()
+ temporary_terms_derivatives[1].size())} + temporary_terms_derivatives[1].size())}
<< FBEGINBLOCK_ {symbol_table.endo_nbr(), << Bytecode::FBEGINBLOCK {symbol_table.endo_nbr(),
BlockSimulationType::solveForwardComplete, BlockSimulationType::solveForwardComplete,
0, 0,
symbol_table.endo_nbr(), symbol_table.endo_nbr(),
endo_idx, endo_idx,
eq_idx, eq_idx,
false, false,
u_count_int, u_count_int,
symbol_table.endo_nbr()}; symbol_table.endo_nbr()};
writeBytecodeHelper<false>(code_file); writeBytecodeHelper<false>(code_file);
} }
@ -156,7 +156,7 @@ StaticModel::writeStaticBytecode(const string& basename) const
void void
StaticModel::writeStaticBlockBytecode(const string& basename) const StaticModel::writeStaticBlockBytecode(const string& basename) const
{ {
BytecodeWriter code_file {basename + "/model/bytecode/block/static.cod"}; Bytecode::Writer code_file {basename + "/model/bytecode/block/static.cod"};
const filesystem::path bin_filename {basename + "/model/bytecode/block/static.bin"}; const filesystem::path bin_filename {basename + "/model/bytecode/block/static.bin"};
ofstream bin_file {bin_filename, ios::out | ios::binary}; ofstream bin_file {bin_filename, ios::out | ios::binary};
@ -167,7 +167,7 @@ StaticModel::writeStaticBlockBytecode(const string& basename) const
} }
// Temporary variables declaration // Temporary variables declaration
code_file << FDIMST_ {static_cast<int>(blocks_temporary_terms_idxs.size())}; code_file << Bytecode::FDIMST {static_cast<int>(blocks_temporary_terms_idxs.size())};
temporary_terms_t temporary_terms_written; temporary_terms_t temporary_terms_written;
@ -181,19 +181,19 @@ StaticModel::writeStaticBlockBytecode(const string& basename) const
? writeBlockBytecodeBinFile(bin_file, block) ? writeBlockBytecodeBinFile(bin_file, block)
: 0}; : 0};
code_file << FBEGINBLOCK_ {blocks[block].mfs_size, code_file << Bytecode::FBEGINBLOCK {blocks[block].mfs_size,
simulation_type, simulation_type,
blocks[block].first_equation, blocks[block].first_equation,
block_size, block_size,
endo_idx_block2orig, endo_idx_block2orig,
eq_idx_block2orig, eq_idx_block2orig,
blocks[block].linear, blocks[block].linear,
u_count, u_count,
block_size}; block_size};
writeBlockBytecodeHelper<false>(code_file, block, temporary_terms_written); writeBlockBytecodeHelper<false>(code_file, block, temporary_terms_written);
} }
code_file << FEND_ {}; code_file << Bytecode::FEND {};
} }
void void
@ -854,6 +854,7 @@ StaticModel::computeRamseyMultipliersDerivatives(int ramsey_orig_endo_nbr, bool
// Compute derivation IDs of Lagrange multipliers // Compute derivation IDs of Lagrange multipliers
set<int> mult_symb_ids {symbol_table.getLagrangeMultipliers()}; set<int> mult_symb_ids {symbol_table.getLagrangeMultipliers()};
vector<int> mult_deriv_ids; vector<int> mult_deriv_ids;
mult_deriv_ids.reserve(mult_symb_ids.size());
for (int symb_id : mult_symb_ids) for (int symb_id : mult_symb_ids)
mult_deriv_ids.push_back(getDerivID(symb_id, 0)); mult_deriv_ids.push_back(getDerivID(symb_id, 0));

View File

@ -315,13 +315,13 @@ TrendComponentModelTable::writeOutput(const string& basename, ostream& output) c
vector<string> target_eqtags_vec = target_eqtags.at(name); vector<string> target_eqtags_vec = target_eqtags.at(name);
output << "M_.trend_component." << name << ".target_eqtags = {"; output << "M_.trend_component." << name << ".target_eqtags = {";
for (auto it : target_eqtags_vec) for (const auto& it : target_eqtags_vec)
output << "'" << it << "';"; output << "'" << it << "';";
output << "};" << endl; output << "};" << endl;
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 (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 << distance(eqtags_vec.begin(), find(eqtags_vec.begin(), eqtags_vec.end(), it)) + 1
<< " "; << " ";
output << "];" << endl; output << "];" << endl;
@ -595,7 +595,7 @@ void
VarModelTable::setLhs(map<string, vector<int>> lhs_arg) VarModelTable::setLhs(map<string, vector<int>> lhs_arg)
{ {
lhs = move(lhs_arg); lhs = move(lhs_arg);
for (auto it : lhs) for (const auto& it : lhs)
{ {
vector<int> lhsvec; vector<int> lhsvec;
for (auto ids : it.second) for (auto ids : it.second)

View File

@ -585,8 +585,8 @@ SymbolTable::addDiffLeadAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_i
} }
int int
SymbolTable::addDiffAuxiliaryVar(int index, expr_t expr_arg, optional<int> orig_symb_id, SymbolTable::addDiffAuxiliaryVar(int index, expr_t expr_arg, const optional<int>& orig_symb_id,
optional<int> orig_lag) noexcept(false) const optional<int>& orig_lag) noexcept(false)
{ {
string varname {"AUX_DIFF_" + to_string(index)}; string varname {"AUX_DIFF_" + to_string(index)};
int symb_id; int symb_id;
@ -601,16 +601,15 @@ SymbolTable::addDiffAuxiliaryVar(int index, expr_t expr_arg, optional<int> orig_
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
aux_vars.emplace_back(symb_id, AuxVarType::diff, move(orig_symb_id), move(orig_lag), 0, 0, aux_vars.emplace_back(symb_id, AuxVarType::diff, orig_symb_id, orig_lag, 0, 0, expr_arg, "");
expr_arg, "");
return symb_id; return symb_id;
} }
int int
SymbolTable::addUnaryOpAuxiliaryVar(int index, expr_t expr_arg, string unary_op, SymbolTable::addUnaryOpAuxiliaryVar(int index, expr_t expr_arg, string unary_op,
optional<int> orig_symb_id, const optional<int>& orig_symb_id,
optional<int> orig_lag) noexcept(false) const optional<int>& orig_lag) noexcept(false)
{ {
string varname {"AUX_UOP_" + to_string(index)}; string varname {"AUX_UOP_" + to_string(index)};
int symb_id; int symb_id;
@ -625,8 +624,8 @@ SymbolTable::addUnaryOpAuxiliaryVar(int index, expr_t expr_arg, string unary_op,
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
aux_vars.emplace_back(symb_id, AuxVarType::unaryOp, move(orig_symb_id), move(orig_lag), 0, 0, aux_vars.emplace_back(symb_id, AuxVarType::unaryOp, orig_symb_id, orig_lag, 0, 0, expr_arg,
expr_arg, unary_op); move(unary_op));
return symb_id; return symb_id;
} }

View File

@ -33,8 +33,6 @@
using namespace std; using namespace std;
using expr_t = class ExprNode*;
//! Types of auxiliary variables //! Types of auxiliary variables
enum class AuxVarType enum class AuxVarType
{ {
@ -299,8 +297,8 @@ public:
diffLead increases it). */ diffLead increases it). */
[[nodiscard]] pair<int, int> unrollDiffLeadLagChain(int symb_id, int lag) const noexcept(false); [[nodiscard]] pair<int, int> unrollDiffLeadLagChain(int symb_id, int lag) const noexcept(false);
//! Adds an auxiliary variable when the diff operator is encountered //! Adds an auxiliary variable when the diff operator is encountered
int addDiffAuxiliaryVar(int index, expr_t expr_arg, optional<int> orig_symb_id = nullopt, int addDiffAuxiliaryVar(int index, expr_t expr_arg, const optional<int>& orig_symb_id = nullopt,
optional<int> orig_lag = nullopt) noexcept(false); const optional<int>& orig_lag = nullopt) noexcept(false);
//! Takes care of timing between diff statements //! Takes care of timing between diff statements
int addDiffLagAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id, int addDiffLagAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id,
int orig_lag) noexcept(false); int orig_lag) noexcept(false);
@ -309,8 +307,8 @@ public:
int orig_lead) noexcept(false); int orig_lead) noexcept(false);
//! An Auxiliary variable for a unary op //! An Auxiliary variable for a unary op
int addUnaryOpAuxiliaryVar(int index, expr_t expr_arg, string unary_op, int addUnaryOpAuxiliaryVar(int index, expr_t expr_arg, string unary_op,
optional<int> orig_symb_id = nullopt, const optional<int>& orig_symb_id = nullopt,
optional<int> orig_lag = nullopt) noexcept(false); const optional<int>& orig_lag = nullopt) noexcept(false);
//! An auxiliary variable for a pac_expectation operator //! An auxiliary variable for a pac_expectation operator
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

View File

@ -75,10 +75,10 @@ Include::interpret(ostream& output, Environment& env, vector<filesystem::path>&
} }
} }
Driver m; Driver m;
/* Calling `string()` method on filename and filename.stem() because of /* Calling string() method on filename: not necessary on GNU/Linux and macOS because there is
bug in GCC/MinGW 10.2 (shipped in Debian Bullseye 11), that fails an implicit conversion from from filesystem:path to string (i.e. basic_string<char>), but
to accept implicit conversion to string from filename::path. See needed on Windows because the implicit conversion is only to wstring (i.e.
https://en.cppreference.com/w/cpp/filesystem/path/native. */ basic_string<wchar_t>). */
m.parse(filename.string(), incfile, false, {}, env, paths, output); m.parse(filename.string(), incfile, false, {}, env, paths, output);
} }
catch (StackTrace& ex) catch (StackTrace& ex)
@ -103,20 +103,7 @@ IncludePath::interpret([[maybe_unused]] ostream& output, Environment& env,
StringPtr msp = dynamic_pointer_cast<String>(expr->eval(env)); StringPtr msp = dynamic_pointer_cast<String>(expr->eval(env));
if (!msp) if (!msp)
throw StackTrace("File name does not evaluate to a string"); throw StackTrace("File name does not evaluate to a string");
#ifdef _WIN32
/* Trim trailing slashes and backslashes in the path. This is a
workaround for a GCC/MinGW bug present in version 10.2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88881, that affects
gcc-mingw-w64 in Debian Bullseye 11. It is fixed in GCC 10.3, and
thus should be fixed in Debian Bookworm 12.
See Madysson/estimation-codes#11. */
string ipstr = static_cast<string>(*msp);
while (ipstr.size() > 1 && (ipstr.back() == '/' || ipstr.back() == '\\'))
ipstr.pop_back();
path ip {ipstr};
#else
path ip = static_cast<string>(*msp); path ip = static_cast<string>(*msp);
#endif
if (!is_directory(ip)) if (!is_directory(ip))
throw StackTrace(ip.string() + " does not evaluate to a valid directory"); throw StackTrace(ip.string() + " does not evaluate to a valid directory");
if (!exists(ip)) if (!exists(ip))

View File

@ -1,5 +1,5 @@
/* /*
* Copyright © 2019-2022 Dynare Team * Copyright © 2019-2023 Dynare Team
* *
* This file is part of Dynare. * This file is part of Dynare.
* *
@ -25,7 +25,7 @@
using namespace macro; using namespace macro;
void void
Environment::define(VariablePtr var, ExpressionPtr value) Environment::define(const VariablePtr& var, const ExpressionPtr& value)
{ {
string name = var->getName(); string name = var->getName();
if (functions.contains(name)) if (functions.contains(name))

View File

@ -40,7 +40,7 @@ public:
Environment(const Environment* parent_arg) : parent {parent_arg} Environment(const Environment* parent_arg) : parent {parent_arg}
{ {
} }
void define(VariablePtr var, ExpressionPtr value); void define(const VariablePtr& var, const ExpressionPtr& value);
void define(FunctionPtr func, ExpressionPtr value); void define(FunctionPtr func, ExpressionPtr value);
/* 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. */

View File

@ -640,6 +640,7 @@ BaseTypePtr
Array::eval(Environment& env) const Array::eval(Environment& env) const
{ {
vector<ExpressionPtr> retval; vector<ExpressionPtr> retval;
retval.reserve(arr.size());
for (const auto& it : arr) for (const auto& it : arr)
retval.emplace_back(it->eval(env)); retval.emplace_back(it->eval(env));
return make_shared<Array>(retval); return make_shared<Array>(retval);
@ -649,6 +650,7 @@ BaseTypePtr
Tuple::eval(Environment& env) const Tuple::eval(Environment& env) const
{ {
vector<ExpressionPtr> retval; vector<ExpressionPtr> retval;
retval.reserve(tup.size());
for (const auto& it : tup) for (const auto& it : tup)
retval.emplace_back(it->eval(env)); retval.emplace_back(it->eval(env));
return make_shared<Tuple>(retval); return make_shared<Tuple>(retval);
@ -1282,7 +1284,7 @@ void
Array::print(ostream& output, bool matlab_output) const noexcept Array::print(ostream& output, bool matlab_output) const noexcept
{ {
output << (matlab_output ? "{" : "["); output << (matlab_output ? "{" : "[");
for (bool printed_something {false}; auto e : arr) for (bool printed_something {false}; const auto& e : arr)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
@ -1295,7 +1297,7 @@ void
Tuple::print(ostream& output, bool matlab_output) const noexcept Tuple::print(ostream& output, bool matlab_output) const noexcept
{ {
output << (matlab_output ? "{" : "("); output << (matlab_output ? "{" : "(");
for (bool printed_something {false}; auto e : tup) for (bool printed_something {false}; const auto& e : tup)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";
@ -1308,7 +1310,7 @@ void
Function::printArgs(ostream& output) const noexcept Function::printArgs(ostream& output) const noexcept
{ {
output << "("; output << "(";
for (bool printed_something {false}; auto e : args) for (bool printed_something {false}; const auto& e : args)
{ {
if (exchange(printed_something, true)) if (exchange(printed_something, true))
output << ", "; output << ", ";

View File

@ -1135,7 +1135,7 @@ private:
public: public:
UnaryOp(codes::UnaryOp op_code_arg, ExpressionPtr arg_arg, Tokenizer::location location_arg) : UnaryOp(codes::UnaryOp op_code_arg, ExpressionPtr arg_arg, Tokenizer::location location_arg) :
Expression(move(location_arg)), op_code {move(op_code_arg)}, arg {move(arg_arg)} Expression(move(location_arg)), op_code {op_code_arg}, arg {move(arg_arg)}
{ {
} }
[[nodiscard]] string to_string() const noexcept override; [[nodiscard]] string to_string() const noexcept override;

View File

@ -42,7 +42,7 @@ preprocessor_src = [ 'ComputingTasks.cc',
'ParsingDriver.cc', 'ParsingDriver.cc',
'DataTree.cc', 'DataTree.cc',
'ModFile.cc', 'ModFile.cc',
'ConfigFile.cc', 'Configuration.cc',
'Statement.cc', 'Statement.cc',
'ExprNode.cc', 'ExprNode.cc',
'VariableDependencyGraph.cc', 'VariableDependencyGraph.cc',