Refactor bytecode output around a new BytecodeWriter class and operator<< overloads

master
Sébastien Villemot 2022-06-23 14:28:13 +02:00
parent 13dc0a1144
commit 9bd2973034
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
11 changed files with 680 additions and 970 deletions

105
src/Bytecode.cc Normal file
View File

@ -0,0 +1,105 @@
/*
* Copyright © 2022 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <ios>
#include <cstdlib>
#include "Bytecode.hh"
BytecodeWriter::BytecodeWriter(const string &filename)
{
open(filename, ios::out | ios::binary);
if (!is_open())
{
cerr << R"(Error : Can't open file ")" << filename << R"(" for writing)" << endl;
exit(EXIT_FAILURE);
}
}
template<>
BytecodeWriter &
operator<<(BytecodeWriter &code_file, const FCALL_ &instr)
{
code_file.instructions_positions.push_back(code_file.tellp());
code_file.write(reinterpret_cast<const char *>(&instr.op_code), sizeof instr.op_code);
code_file.write(reinterpret_cast<const char *>(&instr.nb_output_arguments), sizeof instr.nb_output_arguments);
code_file.write(reinterpret_cast<const char *>(&instr.nb_input_arguments), sizeof instr.nb_input_arguments);
code_file.write(reinterpret_cast<const char *>(&instr.indx), sizeof instr.indx);
code_file.write(reinterpret_cast<const char *>(&instr.add_input_arguments), sizeof instr.add_input_arguments);
code_file.write(reinterpret_cast<const char *>(&instr.row), sizeof instr.row);
code_file.write(reinterpret_cast<const char *>(&instr.col), sizeof instr.col);
code_file.write(reinterpret_cast<const char *>(&instr.function_type), sizeof instr.function_type);
int size = static_cast<int>(instr.func_name.size());
code_file.write(reinterpret_cast<char *>(&size), sizeof size);
const char *name = instr.func_name.c_str();
code_file.write(name, size);
size = static_cast<int>(instr.arg_func_name.size());
code_file.write(reinterpret_cast<char *>(&size), sizeof size);
name = instr.arg_func_name.c_str();
code_file.write(name, size);
return code_file;
}
template<>
BytecodeWriter &
operator<<(BytecodeWriter &code_file, const FBEGINBLOCK_ &instr)
{
code_file.instructions_positions.push_back(code_file.tellp());
code_file.write(reinterpret_cast<const char *>(&instr.op_code), sizeof instr.op_code);
code_file.write(reinterpret_cast<const char *>(&instr.size), sizeof instr.size);
code_file.write(reinterpret_cast<const char *>(&instr.type), sizeof instr.type);
for (int i = 0; i < instr.size; i++)
{
code_file.write(reinterpret_cast<const char *>(&instr.variable[i]), sizeof instr.variable[i]);
code_file.write(reinterpret_cast<const char *>(&instr.equation[i]), sizeof instr.equation[i]);
}
if (instr.type == BlockSimulationType::solveTwoBoundariesSimple
|| instr.type == BlockSimulationType::solveTwoBoundariesComplete
|| instr.type == BlockSimulationType::solveBackwardComplete
|| instr.type == BlockSimulationType::solveForwardComplete)
{
code_file.write(reinterpret_cast<const char *>(&instr.is_linear), sizeof instr.is_linear);
code_file.write(reinterpret_cast<const char *>(&instr.endo_nbr), sizeof instr.endo_nbr);
code_file.write(reinterpret_cast<const char *>(&instr.Max_Lag), sizeof instr.Max_Lag);
code_file.write(reinterpret_cast<const char *>(&instr.Max_Lead), sizeof instr.Max_Lead);
code_file.write(reinterpret_cast<const char *>(&instr.u_count_int), sizeof instr.u_count_int);
}
code_file.write(reinterpret_cast<const char *>(&instr.nb_col_jacob), sizeof instr.nb_col_jacob);
code_file.write(reinterpret_cast<const char *>(&instr.det_exo_size), sizeof instr.det_exo_size);
code_file.write(reinterpret_cast<const char *>(&instr.nb_col_det_exo_jacob), sizeof instr.nb_col_det_exo_jacob);
code_file.write(reinterpret_cast<const char *>(&instr.exo_size), sizeof instr.exo_size);
code_file.write(reinterpret_cast<const char *>(&instr.nb_col_exo_jacob), sizeof instr.nb_col_exo_jacob);
code_file.write(reinterpret_cast<const char *>(&instr.other_endo_size), sizeof instr.other_endo_size);
code_file.write(reinterpret_cast<const char *>(&instr.nb_col_other_endo_jacob), sizeof instr.nb_col_other_endo_jacob);
for (int i{0}; i < instr.det_exo_size; i++)
code_file.write(reinterpret_cast<const char *>(&instr.det_exogenous[i]), sizeof instr.det_exogenous[i]);
for (int i{0}; i < instr.exo_size; i++)
code_file.write(reinterpret_cast<const char *>(&instr.exogenous[i]), sizeof instr.exogenous[i]);
for (int i{0}; i < instr.other_endo_size; i++)
code_file.write(reinterpret_cast<const char *>(&instr.other_endogenous[i]), sizeof instr.other_endogenous[i]);
return code_file;
}

View File

@ -23,11 +23,13 @@
#include <fstream> #include <fstream>
#include <vector> #include <vector>
#include <utility> #include <utility>
#include <ios>
#include "CommonEnums.hh"
#ifdef BYTECODE_MEX #ifdef BYTECODE_MEX
# include <dynmex.h> # include <dynmex.h>
# include <cstring> # include <cstring>
# include "CommonEnums.hh"
#endif #endif
using namespace std; using namespace std;
@ -103,20 +105,18 @@ struct Block_contain_type
int Equation, Variable, Own_Derivative; int Equation, Variable, Own_Derivative;
}; };
class BytecodeWriter;
class BytecodeInstruction class BytecodeInstruction
{ {
template<typename B>
friend BytecodeWriter &operator<<(BytecodeWriter &code_file, const B &instr);
protected: protected:
Tags op_code; Tags op_code;
public: public:
explicit BytecodeInstruction(Tags op_code_arg) : op_code{op_code_arg} explicit BytecodeInstruction(Tags op_code_arg) : op_code{op_code_arg}
{ {
}; };
void
write(ostream &CompileCode, unsigned int &instruction_number)
{
CompileCode.write(reinterpret_cast<char *>(this), sizeof(*this));
instruction_number++;
};
}; };
template<typename T1> template<typename T1>
@ -129,12 +129,6 @@ public:
arg1{arg_arg1} arg1{arg_arg1}
{ {
}; };
void
write(ostream &CompileCode, unsigned int &instruction_number)
{
CompileCode.write(reinterpret_cast<char *>(this), sizeof(*this));
instruction_number++;
};
}; };
template<typename T1, typename T2> template<typename T1, typename T2>
@ -148,12 +142,6 @@ public:
BytecodeInstruction{op_code_arg}, arg1{arg_arg1}, arg2{arg_arg2} BytecodeInstruction{op_code_arg}, arg1{arg_arg1}, arg2{arg_arg2}
{ {
}; };
void
write(ostream &CompileCode, unsigned int &instruction_number)
{
CompileCode.write(reinterpret_cast<char *>(this), sizeof(*this));
instruction_number++;
};
}; };
template<typename T1, typename T2, typename T3> template<typename T1, typename T2, typename T3>
@ -168,12 +156,6 @@ public:
BytecodeInstruction{op_code_arg}, arg1{arg_arg1}, arg2{arg_arg2}, arg3{arg_arg3} BytecodeInstruction{op_code_arg}, arg1{arg_arg1}, arg2{arg_arg2}, arg3{arg_arg3}
{ {
}; };
void
write(ostream &CompileCode, unsigned int &instruction_number)
{
CompileCode.write(reinterpret_cast<char *>(this), sizeof(*this));
instruction_number++;
};
}; };
template<typename T1, typename T2, typename T3, typename T4> template<typename T1, typename T2, typename T3, typename T4>
@ -190,12 +172,6 @@ public:
arg3{move(arg_arg3)}, arg4{arg_arg4} arg3{move(arg_arg3)}, arg4{arg_arg4}
{ {
}; };
void
write(ostream &CompileCode, unsigned int &instruction_number)
{
CompileCode.write(reinterpret_cast<char *>(this), sizeof(*this));
instruction_number++;
};
}; };
class FLDZ_ : public BytecodeInstruction class FLDZ_ : public BytecodeInstruction
@ -750,6 +726,9 @@ public:
class FCALL_ : public BytecodeInstruction class FCALL_ : public BytecodeInstruction
{ {
template<typename B>
friend BytecodeWriter &operator<<(BytecodeWriter &code_file, const B &instr);
private:
int nb_output_arguments, nb_input_arguments, indx; int nb_output_arguments, nb_input_arguments, indx;
string func_name; string func_name;
string arg_func_name; string arg_func_name;
@ -838,27 +817,6 @@ public:
{ {
return function_type; return function_type;
} }
void
write(ostream &CompileCode, unsigned int &instruction_number)
{
CompileCode.write(reinterpret_cast<char *>(&op_code), sizeof(op_code));
CompileCode.write(reinterpret_cast<char *>(&nb_output_arguments), sizeof(nb_output_arguments));
CompileCode.write(reinterpret_cast<char *>(&nb_input_arguments), sizeof(nb_input_arguments));
CompileCode.write(reinterpret_cast<char *>(&indx), sizeof(indx));
CompileCode.write(reinterpret_cast<char *>(&add_input_arguments), sizeof(add_input_arguments));
CompileCode.write(reinterpret_cast<char *>(&row), sizeof(row));
CompileCode.write(reinterpret_cast<char *>(&col), sizeof(col));
CompileCode.write(reinterpret_cast<char *>(&function_type), sizeof(function_type));
size_t size = func_name.size();
CompileCode.write(reinterpret_cast<char *>(&size), sizeof(int));
const char *name = func_name.c_str();
CompileCode.write(reinterpret_cast<const char *>(name), func_name.size());
size = arg_func_name.size();
CompileCode.write(reinterpret_cast<char *>(&size), sizeof(int));
name = arg_func_name.c_str();
CompileCode.write(reinterpret_cast<const char *>(name), arg_func_name.size());
instruction_number++;
};
#ifdef BYTECODE_MEX #ifdef BYTECODE_MEX
char * char *
@ -940,16 +898,12 @@ public:
{ {
return lag1; return lag1;
}; };
void
write(ostream &CompileCode, unsigned int &instruction_number)
{
CompileCode.write(reinterpret_cast<char *>(this), sizeof(*this));
instruction_number++;
};
}; };
class FBEGINBLOCK_ : public BytecodeInstruction class FBEGINBLOCK_ : public BytecodeInstruction
{ {
template<typename B>
friend BytecodeWriter &operator<<(BytecodeWriter &code_file, const B &instr);
private: private:
int size{0}; int size{0};
BlockSimulationType type; BlockSimulationType type;
@ -1106,44 +1060,6 @@ public:
{ {
return exogenous; return exogenous;
} }
void
write(ostream &CompileCode, unsigned int &instruction_number)
{
CompileCode.write(reinterpret_cast<char *>(&op_code), sizeof(op_code));
CompileCode.write(reinterpret_cast<char *>(&size), sizeof(size));
CompileCode.write(reinterpret_cast<char *>(&type), sizeof(type));
for (int i = 0; i < size; i++)
{
CompileCode.write(reinterpret_cast<char *>(&variable[i]), sizeof(variable[0]));
CompileCode.write(reinterpret_cast<char *>(&equation[i]), sizeof(equation[0]));
}
if (type == BlockSimulationType::solveTwoBoundariesSimple
|| type == BlockSimulationType::solveTwoBoundariesComplete
|| type == BlockSimulationType::solveBackwardComplete
|| type == BlockSimulationType::solveForwardComplete)
{
CompileCode.write(reinterpret_cast<char *>(&is_linear), sizeof(is_linear));
CompileCode.write(reinterpret_cast<char *>(&endo_nbr), sizeof(endo_nbr));
CompileCode.write(reinterpret_cast<char *>(&Max_Lag), sizeof(Max_Lag));
CompileCode.write(reinterpret_cast<char *>(&Max_Lead), sizeof(Max_Lead));
CompileCode.write(reinterpret_cast<char *>(&u_count_int), sizeof(u_count_int));
}
CompileCode.write(reinterpret_cast<char *>(&nb_col_jacob), sizeof(nb_col_jacob));
CompileCode.write(reinterpret_cast<char *>(&det_exo_size), sizeof(det_exo_size));
CompileCode.write(reinterpret_cast<char *>(&nb_col_det_exo_jacob), sizeof(nb_col_det_exo_jacob));
CompileCode.write(reinterpret_cast<char *>(&exo_size), sizeof(exo_size));
CompileCode.write(reinterpret_cast<char *>(&nb_col_exo_jacob), sizeof(nb_col_exo_jacob));
CompileCode.write(reinterpret_cast<char *>(&other_endo_size), sizeof(other_endo_size));
CompileCode.write(reinterpret_cast<char *>(&nb_col_other_endo_jacob), sizeof(nb_col_other_endo_jacob));
for (int i{0}; i < det_exo_size; i++)
CompileCode.write(reinterpret_cast<char *>(&det_exogenous[i]), sizeof(det_exogenous[0]));
for (int i{0}; i < exo_size; i++)
CompileCode.write(reinterpret_cast<char *>(&exogenous[i]), sizeof(exogenous[0]));
for (int i{0}; i < other_endo_size; i++)
CompileCode.write(reinterpret_cast<char *>(&other_endogenous[i]), sizeof(other_endogenous[0]));
instruction_number++;
};
#ifdef BYTECODE_MEX #ifdef BYTECODE_MEX
char * char *
@ -1201,6 +1117,54 @@ public:
#endif #endif
}; };
// Superclass of std::ofstream for writing a sequence of bytecode instructions
class BytecodeWriter : private ofstream
{
template<typename B>
friend BytecodeWriter &operator<<(BytecodeWriter &code_file, const B &instr);
private:
// Stores the positions of all instructions in the byte stream
vector<pos_type> instructions_positions;
public:
BytecodeWriter(const string &filename);
// Returns the number of the next instruction to be written
int
getInstructionCounter() const
{
return static_cast<int>(instructions_positions.size());
}
/* Overwrites an existing instruction, given its number.
It is the responsibility of the caller to ensure that the new instruction
occupies exactly as many bytes as the former one. */
template<typename B>
void
overwriteInstruction(int instruction_number, const B &new_instruction)
{
seekp(instructions_positions.at(instruction_number));
*this << new_instruction;
instructions_positions.pop_back();
seekp(0, ios_base::end);
}
};
// Overloads of operator<< for writing bytecode instructions
template<typename B>
BytecodeWriter &
operator<<(BytecodeWriter &code_file, const B &instr)
{
code_file.instructions_positions.push_back(code_file.tellp());
code_file.write(reinterpret_cast<const char *>(&instr), sizeof(B));
return code_file;
}
template<>
BytecodeWriter &operator<<(BytecodeWriter &code_file, const FCALL_ &instr);
template<>
BytecodeWriter &operator<<(BytecodeWriter &code_file, const FBEGINBLOCK_ &instr);
#ifdef BYTECODE_MEX #ifdef BYTECODE_MEX
using tags_liste_t = vector<pair<Tags, void * >>; using tags_liste_t = vector<pair<Tags, void * >>;
class CodeLoad class CodeLoad

View File

@ -28,7 +28,6 @@
#include "DynamicModel.hh" #include "DynamicModel.hh"
#include "ParsingDriver.hh" #include "ParsingDriver.hh"
#include "Bytecode.hh"
void void
DynamicModel::copyHelper(const DynamicModel &m) DynamicModel::copyHelper(const DynamicModel &m)
@ -169,29 +168,23 @@ DynamicModel::operator=(const DynamicModel &m)
} }
void void
DynamicModel::compileDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int symb_id, int lag, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const DynamicModel::writeBytecodeDerivative(BytecodeWriter &code_file, int eq, int symb_id, int lag, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const
{ {
if (auto it = derivatives[1].find({ eq, getDerivID(symbol_table.getID(SymbolType::endogenous, symb_id), lag) }); if (auto it = derivatives[1].find({ eq, getDerivID(symbol_table.getID(SymbolType::endogenous, symb_id), lag) });
it != derivatives[1].end()) it != derivatives[1].end())
it->second->compile(code_file, instruction_number, false, temporary_terms, temporary_terms_idxs, true, false, tef_terms); it->second->writeBytecodeOutput(code_file, false, temporary_terms, temporary_terms_idxs, true, false, tef_terms);
else else
{ code_file << FLDZ_{};
FLDZ_ fldz;
fldz.write(code_file, instruction_number);
}
} }
void void
DynamicModel::compileChainRuleDerivative(ofstream &code_file, unsigned int &instruction_number, int blk, int eq, int var, int lag, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const DynamicModel::writeBytecodeChainRuleDerivative(BytecodeWriter &code_file, int blk, int eq, int var, int lag, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const
{ {
if (auto it = blocks_derivatives[blk].find({ eq, var, lag }); if (auto it = blocks_derivatives[blk].find({ eq, var, lag });
it != blocks_derivatives[blk].end()) it != blocks_derivatives[blk].end())
it->second->compile(code_file, instruction_number, false, temporary_terms, temporary_terms_idxs, true, false, tef_terms); it->second->writeBytecodeOutput(code_file, false, temporary_terms, temporary_terms_idxs, true, false, tef_terms);
else else
{ code_file << FLDZ_{};
FLDZ_ fldz;
fldz.write(code_file, instruction_number);
}
} }
void void
@ -776,18 +769,9 @@ void
DynamicModel::writeDynamicBytecode(const string &basename) const DynamicModel::writeDynamicBytecode(const string &basename) const
{ {
ostringstream tmp_output; ostringstream tmp_output;
ofstream code_file; BytecodeWriter code_file{basename + "/model/bytecode/dynamic.cod"};
unsigned int instruction_number = 0;
bool file_open = false; bool file_open = false;
string main_name = basename + "/model/bytecode/dynamic.cod";
code_file.open(main_name, ios::out | ios::binary | ios::ate);
if (!code_file.is_open())
{
cerr << R"(Error : Can't open file ")" << main_name << R"(" for writing)" << endl;
exit(EXIT_FAILURE);
}
int count_u; int count_u;
int u_count_int = 0; int u_count_int = 0;
BlockSimulationType simulation_type; BlockSimulationType simulation_type;
@ -802,8 +786,7 @@ DynamicModel::writeDynamicBytecode(const string &basename) const
file_open = true; file_open = true;
//Temporary variables declaration //Temporary variables declaration
FDIMT_ fdimt{static_cast<int>(temporary_terms_idxs.size())}; code_file << FDIMT_{static_cast<int>(temporary_terms_idxs.size())};
fdimt.write(code_file, instruction_number);
vector<int> exo, exo_det, other_endo; vector<int> exo, exo_det, other_endo;
@ -863,44 +846,40 @@ DynamicModel::writeDynamicBytecode(const string &basename) const
} }
} }
FBEGINBLOCK_ fbeginblock(symbol_table.endo_nbr(), code_file << FBEGINBLOCK_{symbol_table.endo_nbr(),
simulation_type, simulation_type,
0, 0,
symbol_table.endo_nbr(), symbol_table.endo_nbr(),
endo_idx_block2orig, endo_idx_block2orig,
eq_idx_block2orig, eq_idx_block2orig,
false, false,
symbol_table.endo_nbr(), symbol_table.endo_nbr(),
max_endo_lag, max_endo_lag,
max_endo_lead, max_endo_lead,
u_count_int, u_count_int,
count_col_endo, count_col_endo,
symbol_table.exo_det_nbr(), symbol_table.exo_det_nbr(),
count_col_det_exo, count_col_det_exo,
symbol_table.exo_nbr(), symbol_table.exo_nbr(),
count_col_exo, count_col_exo,
0, 0,
0, 0,
exo_det, exo_det,
exo, exo,
other_endo); other_endo};
fbeginblock.write(code_file, instruction_number);
temporary_terms_t temporary_terms_union; temporary_terms_t temporary_terms_union;
deriv_node_temp_terms_t tef_terms; deriv_node_temp_terms_t tef_terms;
compileTemporaryTerms(code_file, instruction_number, true, false, temporary_terms_union, temporary_terms_idxs, tef_terms); writeBytecodeTemporaryTerms(code_file, true, false, temporary_terms_union, temporary_terms_idxs, tef_terms);
compileModelEquations(code_file, instruction_number, true, false, temporary_terms_union, temporary_terms_idxs, tef_terms); writeBytecodeModelEquations(code_file, true, false, temporary_terms_union, temporary_terms_idxs, tef_terms);
FENDEQU_ fendequ; code_file << FENDEQU_{};
fendequ.write(code_file, instruction_number);
// Get the current code_file position and jump if eval = true // Get the current code_file position and jump if evaluating
streampos pos1 = code_file.tellp(); int pos_jmpifeval = code_file.getInstructionCounter();
FJMPIFEVAL_ fjmp_if_eval(0); code_file << FJMPIFEVAL_{0}; // Use 0 as jump offset for the time being
fjmp_if_eval.write(code_file, instruction_number);
int prev_instruction_number = instruction_number;
vector<vector<tuple<int, int, int>>> my_derivatives(symbol_table.endo_nbr());; vector<vector<tuple<int, int, int>>> my_derivatives(symbol_table.endo_nbr());;
count_u = symbol_table.endo_nbr(); count_u = symbol_table.endo_nbr();
@ -913,56 +892,39 @@ DynamicModel::writeDynamicBytecode(const string &basename) const
int symb = getSymbIDByDerivID(deriv_id); int symb = getSymbIDByDerivID(deriv_id);
int var = symbol_table.getTypeSpecificID(symb); int var = symbol_table.getTypeSpecificID(symb);
int lag = getLagByDerivID(deriv_id); int lag = getLagByDerivID(deriv_id);
FNUMEXPR_ fnumexpr(ExpressionType::FirstEndoDerivative, eq, var, lag); code_file << FNUMEXPR_{ExpressionType::FirstEndoDerivative, eq, var, lag};
fnumexpr.write(code_file, instruction_number);
if (!my_derivatives[eq].size()) if (!my_derivatives[eq].size())
my_derivatives[eq].clear(); my_derivatives[eq].clear();
my_derivatives[eq].emplace_back(var, lag, count_u); my_derivatives[eq].emplace_back(var, lag, count_u);
d1->compile(code_file, instruction_number, false, temporary_terms_union, temporary_terms_idxs, true, false, tef_terms); d1->writeBytecodeOutput(code_file, false, temporary_terms_union, temporary_terms_idxs, true, false, tef_terms);
FSTPU_ fstpu(count_u); code_file << FSTPU_{count_u};
fstpu.write(code_file, instruction_number);
count_u++; count_u++;
} }
} }
for (int i = 0; i < symbol_table.endo_nbr(); i++) for (int i = 0; i < symbol_table.endo_nbr(); i++)
{ {
FLDR_ fldr(i); code_file << FLDR_{i};
fldr.write(code_file, instruction_number);
if (my_derivatives[i].size()) if (my_derivatives[i].size())
{ {
for (auto it = my_derivatives[i].begin(); it != my_derivatives[i].end(); ++it) for (auto it = my_derivatives[i].begin(); it != my_derivatives[i].end(); ++it)
{ {
FLDU_ fldu(get<2>(*it)); code_file << FLDU_{get<2>(*it)}
fldu.write(code_file, instruction_number); << FLDV_{SymbolType::endogenous, get<0>(*it), get<1>(*it)}
FLDV_ fldv{SymbolType::endogenous, get<0>(*it), get<1>(*it)}; << FBINARY_{BinaryOpcode::times};
fldv.write(code_file, instruction_number);
FBINARY_ fbinary{BinaryOpcode::times};
fbinary.write(code_file, instruction_number);
if (it != my_derivatives[i].begin()) if (it != my_derivatives[i].begin())
{ code_file << FBINARY_{BinaryOpcode::plus};
FBINARY_ fbinary{BinaryOpcode::plus};
fbinary.write(code_file, instruction_number);
}
} }
FBINARY_ fbinary{BinaryOpcode::minus}; code_file << FBINARY_{BinaryOpcode::minus};
fbinary.write(code_file, instruction_number);
} }
FSTPU_ fstpu(i); code_file << FSTPU_{i};
fstpu.write(code_file, instruction_number);
} }
// Get the current code_file position and jump = true // Jump unconditionally after the block
streampos pos2 = code_file.tellp(); int pos_jmp = code_file.getInstructionCounter();
FJMP_ fjmp(0); code_file << FJMP_{0}; // Use 0 as jump offset for the time being
fjmp.write(code_file, instruction_number); // Update jump offset for previous JMPIFEVAL
// Set code_file position to previous JMPIFEVAL_ and set the number of instructions to jump code_file.overwriteInstruction(pos_jmpifeval, FJMPIFEVAL_{pos_jmp-pos_jmpifeval});
streampos pos3 = code_file.tellp();
code_file.seekp(pos1);
FJMPIFEVAL_ fjmp_if_eval1(instruction_number - prev_instruction_number);
fjmp_if_eval1.write(code_file, instruction_number);
code_file.seekp(pos3);
prev_instruction_number = instruction_number;
// The Jacobian // The Jacobian
prev_var = -1; prev_var = -1;
@ -972,17 +934,15 @@ DynamicModel::writeDynamicBytecode(const string &basename) const
{ {
auto [lag, var, eq] = it.first; auto [lag, var, eq] = it.first;
expr_t d1 = it.second; expr_t d1 = it.second;
FNUMEXPR_ fnumexpr(ExpressionType::FirstEndoDerivative, eq, var, lag); code_file << FNUMEXPR_{ExpressionType::FirstEndoDerivative, eq, var, lag};
fnumexpr.write(code_file, instruction_number);
if (prev_var != var || prev_lag != lag) if (prev_var != var || prev_lag != lag)
{ {
prev_var = var; prev_var = var;
prev_lag = lag; prev_lag = lag;
count_col_endo++; count_col_endo++;
} }
d1->compile(code_file, instruction_number, false, temporary_terms_union, temporary_terms_idxs, true, false, tef_terms); d1->writeBytecodeOutput(code_file, false, temporary_terms_union, temporary_terms_idxs, true, false, tef_terms);
FSTPG3_ fstpg3(eq, var, lag, count_col_endo-1); code_file << FSTPG3_{eq, var, lag, count_col_endo-1};
fstpg3.write(code_file, instruction_number);
} }
prev_var = -1; prev_var = -1;
prev_lag = -999999999; prev_lag = -999999999;
@ -991,30 +951,21 @@ DynamicModel::writeDynamicBytecode(const string &basename) const
{ {
auto [lag, ignore, var, eq] = it.first; auto [lag, ignore, var, eq] = it.first;
expr_t d1 = it.second; expr_t d1 = it.second;
FNUMEXPR_ fnumexpr(ExpressionType::FirstExoDerivative, eq, var, lag); code_file << FNUMEXPR_{ExpressionType::FirstExoDerivative, eq, var, lag};
fnumexpr.write(code_file, instruction_number);
if (prev_var != var || prev_lag != lag) if (prev_var != var || prev_lag != lag)
{ {
prev_var = var; prev_var = var;
prev_lag = lag; prev_lag = lag;
count_col_exo++; count_col_exo++;
} }
d1->compile(code_file, instruction_number, false, temporary_terms_union, temporary_terms_idxs, true, false, tef_terms); d1->writeBytecodeOutput(code_file, false, temporary_terms_union, temporary_terms_idxs, true, false, tef_terms);
FSTPG3_ fstpg3(eq, var, lag, count_col_exo-1); code_file << FSTPG3_{eq, var, lag, count_col_exo-1};
fstpg3.write(code_file, instruction_number);
} }
// Set codefile position to previous JMP_ and set the number of instructions to jump // Update jump offset for previous JMP
pos1 = code_file.tellp(); int pos_end_block = code_file.getInstructionCounter();
code_file.seekp(pos2); code_file.overwriteInstruction(pos_jmp, FJMP_{pos_end_block-pos_jmp-1});
FJMP_ fjmp1(instruction_number - prev_instruction_number);
fjmp1.write(code_file, instruction_number);
code_file.seekp(pos1);
FENDBLOCK_ fendblock; code_file << FENDBLOCK_{} << FEND_{};
fendblock.write(code_file, instruction_number);
FEND_ fend;
fend.write(code_file, instruction_number);
code_file.close();
} }
void void
@ -1034,34 +985,23 @@ DynamicModel::writeDynamicBlockBytecode(const string &basename) const
int i, v; int i, v;
string tmp_s; string tmp_s;
ostringstream tmp_output; ostringstream tmp_output;
ofstream code_file;
unsigned int instruction_number = 0;
expr_t lhs = nullptr, rhs = nullptr; expr_t lhs = nullptr, rhs = nullptr;
BinaryOpNode *eq_node; BinaryOpNode *eq_node;
Uff Uf[symbol_table.endo_nbr()]; Uff Uf[symbol_table.endo_nbr()];
map<expr_t, int> reference_count; map<expr_t, int> reference_count;
vector<int> feedback_variables; vector<int> feedback_variables;
bool file_open = false; bool file_open = false;
string main_name = basename + "/model/bytecode/dynamic.cod"; BytecodeWriter code_file{basename + "/model/bytecode/dynamic.cod"};
code_file.open(main_name, ios::out | ios::binary | ios::ate);
if (!code_file.is_open())
{
cerr << R"(Error : Can't open file ")" << main_name << R"(" for writing)" << endl;
exit(EXIT_FAILURE);
}
//Temporary variables declaration //Temporary variables declaration
FDIMT_ fdimt{static_cast<int>(blocks_temporary_terms_idxs.size())}; code_file << FDIMT_{static_cast<int>(blocks_temporary_terms_idxs.size())};
fdimt.write(code_file, instruction_number);
for (int block = 0; block < static_cast<int>(blocks.size()); block++) for (int block = 0; block < static_cast<int>(blocks.size()); block++)
{ {
feedback_variables.clear(); feedback_variables.clear();
if (block > 0) if (block > 0)
{ code_file << FENDBLOCK_{};
FENDBLOCK_ fendblock;
fendblock.write(code_file, instruction_number);
}
int count_u; int count_u;
int u_count_int = 0; int u_count_int = 0;
BlockSimulationType simulation_type = blocks[block].simulation_type; BlockSimulationType simulation_type = blocks[block].simulation_type;
@ -1081,28 +1021,27 @@ DynamicModel::writeDynamicBlockBytecode(const string &basename) const
file_open = true; file_open = true;
} }
FBEGINBLOCK_ fbeginblock(block_mfs, code_file << FBEGINBLOCK_{block_mfs,
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,
symbol_table.endo_nbr(), symbol_table.endo_nbr(),
block_max_lag, block_max_lag,
block_max_lead, block_max_lead,
u_count_int, u_count_int,
blocks_jacob_cols_endo[block].size(), static_cast<int>(blocks_jacob_cols_endo[block].size()),
blocks_exo_det[block].size(), static_cast<int>(blocks_exo_det[block].size()),
blocks_jacob_cols_exo_det[block].size(), static_cast<int>(blocks_jacob_cols_exo_det[block].size()),
blocks_exo[block].size(), static_cast<int>(blocks_exo[block].size()),
blocks_jacob_cols_exo[block].size(), static_cast<int>(blocks_jacob_cols_exo[block].size()),
blocks_other_endo[block].size(), static_cast<int>(blocks_other_endo[block].size()),
blocks_jacob_cols_other_endo[block].size(), static_cast<int>(blocks_jacob_cols_other_endo[block].size()),
vector<int>(blocks_exo_det[block].begin(), blocks_exo_det[block].end()), vector<int>(blocks_exo_det[block].begin(), blocks_exo_det[block].end()),
vector<int>(blocks_exo[block].begin(), blocks_exo[block].end()), vector<int>(blocks_exo[block].begin(), blocks_exo[block].end()),
vector<int>(blocks_other_endo[block].begin(), blocks_other_endo[block].end())); vector<int>(blocks_other_endo[block].begin(), blocks_other_endo[block].end())};
fbeginblock.write(code_file, instruction_number);
temporary_terms_t temporary_terms_union; temporary_terms_t temporary_terms_union;
@ -1114,13 +1053,11 @@ DynamicModel::writeDynamicBlockBytecode(const string &basename) const
for (auto it : blocks_temporary_terms[block][eq]) for (auto it : blocks_temporary_terms[block][eq])
{ {
if (dynamic_cast<AbstractExternalFunctionNode *>(it)) if (dynamic_cast<AbstractExternalFunctionNode *>(it))
it->compileExternalFunctionOutput(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms); it->writeBytecodeExternalFunctionOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms);
FNUMEXPR_ fnumexpr{ExpressionType::TemporaryTerm, blocks_temporary_terms_idxs.at(it)}; code_file << FNUMEXPR_{ExpressionType::TemporaryTerm, blocks_temporary_terms_idxs.at(it)};
fnumexpr.write(code_file, instruction_number); it->writeBytecodeOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms);
it->compile(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms); code_file << FSTPT_{blocks_temporary_terms_idxs.at(it)};
FSTPT_ fstpt{blocks_temporary_terms_idxs.at(it)};
fstpt.write(code_file, instruction_number);
temporary_terms_union.insert(it); temporary_terms_union.insert(it);
} }
}; };
@ -1139,25 +1076,22 @@ DynamicModel::writeDynamicBlockBytecode(const string &basename) const
case BlockSimulationType::evaluateBackward: case BlockSimulationType::evaluateBackward:
case BlockSimulationType::evaluateForward: case BlockSimulationType::evaluateForward:
equ_type = getBlockEquationType(block, i); equ_type = getBlockEquationType(block, i);
{ code_file << FNUMEXPR_{ExpressionType::ModelEquation, getBlockEquationID(block, i)};
FNUMEXPR_ fnumexpr(ExpressionType::ModelEquation, getBlockEquationID(block, i));
fnumexpr.write(code_file, instruction_number);
}
if (equ_type == EquationType::evaluate) if (equ_type == EquationType::evaluate)
{ {
eq_node = getBlockEquationExpr(block, i); eq_node = getBlockEquationExpr(block, i);
lhs = eq_node->arg1; lhs = eq_node->arg1;
rhs = eq_node->arg2; rhs = eq_node->arg2;
rhs->compile(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms); rhs->writeBytecodeOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms);
lhs->compile(code_file, instruction_number, true, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms); lhs->writeBytecodeOutput(code_file, true, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms);
} }
else if (equ_type == EquationType::evaluateRenormalized) else if (equ_type == EquationType::evaluateRenormalized)
{ {
eq_node = getBlockEquationRenormalizedExpr(block, i); eq_node = getBlockEquationRenormalizedExpr(block, i);
lhs = eq_node->arg1; lhs = eq_node->arg1;
rhs = eq_node->arg2; rhs = eq_node->arg2;
rhs->compile(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms); rhs->writeBytecodeOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms);
lhs->compile(code_file, instruction_number, true, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms); lhs->writeBytecodeOutput(code_file, true, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms);
} }
break; break;
case BlockSimulationType::solveBackwardComplete: case BlockSimulationType::solveBackwardComplete:
@ -1173,22 +1107,17 @@ DynamicModel::writeDynamicBlockBytecode(const string &basename) const
goto end; goto end;
default: default:
end: end:
FNUMEXPR_ fnumexpr(ExpressionType::ModelEquation, getBlockEquationID(block, i)); code_file << FNUMEXPR_{ExpressionType::ModelEquation, getBlockEquationID(block, i)};
fnumexpr.write(code_file, instruction_number);
eq_node = getBlockEquationExpr(block, i); eq_node = getBlockEquationExpr(block, i);
lhs = eq_node->arg1; lhs = eq_node->arg1;
rhs = eq_node->arg2; rhs = eq_node->arg2;
lhs->compile(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms); lhs->writeBytecodeOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms);
rhs->compile(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms); rhs->writeBytecodeOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms);
FBINARY_ fbinary{BinaryOpcode::minus}; code_file << FBINARY_{BinaryOpcode::minus} << FSTPR_{i - block_recursive};
fbinary.write(code_file, instruction_number);
FSTPR_ fstpr(i - block_recursive);
fstpr.write(code_file, instruction_number);
} }
} }
FENDEQU_ fendequ; code_file << FENDEQU_{};
fendequ.write(code_file, instruction_number);
/* If the block is not of type “evaluate backward/forward”, then we write /* If the block is not of type “evaluate backward/forward”, then we write
the temporary terms for derivatives at this point, i.e. before the the temporary terms for derivatives at this point, i.e. before the
@ -1198,11 +1127,9 @@ DynamicModel::writeDynamicBlockBytecode(const string &basename) const
&& simulation_type != BlockSimulationType::evaluateForward) && simulation_type != BlockSimulationType::evaluateForward)
write_eq_tt(blocks[block].size); write_eq_tt(blocks[block].size);
// Get the current code_file position and jump if eval = true // Get the current code_file position and jump if evaluating
streampos pos1 = code_file.tellp(); int pos_jmpifeval = code_file.getInstructionCounter();
FJMPIFEVAL_ fjmp_if_eval(0); code_file << FJMPIFEVAL_{0}; // Use 0 as jump offset for the time being
fjmp_if_eval.write(code_file, instruction_number);
int prev_instruction_number = instruction_number;
/* 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) */
@ -1213,15 +1140,9 @@ DynamicModel::writeDynamicBlockBytecode(const string &basename) const
{ {
case BlockSimulationType::solveBackwardSimple: case BlockSimulationType::solveBackwardSimple:
case BlockSimulationType::solveForwardSimple: case BlockSimulationType::solveForwardSimple:
{ code_file << FNUMEXPR_{ExpressionType::FirstEndoDerivative, getBlockEquationID(block, 0), getBlockVariableID(block, 0), 0};
FNUMEXPR_ fnumexpr(ExpressionType::FirstEndoDerivative, getBlockEquationID(block, 0), getBlockVariableID(block, 0), 0); writeBytecodeDerivative(code_file, getBlockEquationID(block, 0), getBlockVariableID(block, 0), 0, temporary_terms_union, blocks_temporary_terms_idxs, tef_terms);
fnumexpr.write(code_file, instruction_number); code_file << FSTPG_{0};
}
compileDerivative(code_file, instruction_number, getBlockEquationID(block, 0), getBlockVariableID(block, 0), 0, temporary_terms_union, blocks_temporary_terms_idxs, tef_terms);
{
FSTPG_ fstpg(0);
fstpg.write(code_file, instruction_number);
}
break; break;
case BlockSimulationType::solveBackwardComplete: case BlockSimulationType::solveBackwardComplete:
@ -1254,11 +1175,9 @@ DynamicModel::writeDynamicBlockBytecode(const string &basename) const
Uf[eqr].Ufl->u = count_u; Uf[eqr].Ufl->u = count_u;
Uf[eqr].Ufl->var = varr; Uf[eqr].Ufl->var = varr;
Uf[eqr].Ufl->lag = lag; Uf[eqr].Ufl->lag = lag;
FNUMEXPR_ fnumexpr(ExpressionType::FirstEndoDerivative, eqr, varr, lag); code_file << FNUMEXPR_{ExpressionType::FirstEndoDerivative, eqr, varr, lag};
fnumexpr.write(code_file, instruction_number); writeBytecodeChainRuleDerivative(code_file, block, eq, var, lag, temporary_terms_union, blocks_temporary_terms_idxs, tef_terms);
compileChainRuleDerivative(code_file, instruction_number, block, eq, var, lag, temporary_terms_union, blocks_temporary_terms_idxs, tef_terms); code_file << FSTPU_{count_u};
FSTPU_ fstpu(count_u);
fstpu.write(code_file, instruction_number);
count_u++; count_u++;
} }
} }
@ -1266,26 +1185,14 @@ DynamicModel::writeDynamicBlockBytecode(const string &basename) const
{ {
if (i >= block_recursive) if (i >= block_recursive)
{ {
FLDR_ fldr(i-block_recursive); code_file << FLDR_{i-block_recursive} << FLDZ_{};
fldr.write(code_file, instruction_number);
FLDZ_ fldz;
fldz.write(code_file, instruction_number);
v = getBlockEquationID(block, i); v = getBlockEquationID(block, i);
for (Uf[v].Ufl = Uf[v].Ufl_First; Uf[v].Ufl; Uf[v].Ufl = Uf[v].Ufl->pNext) for (Uf[v].Ufl = Uf[v].Ufl_First; Uf[v].Ufl; Uf[v].Ufl = Uf[v].Ufl->pNext)
{ code_file << FLDU_{Uf[v].Ufl->u}
FLDU_ fldu(Uf[v].Ufl->u); << FLDV_{SymbolType::endogenous, Uf[v].Ufl->var, Uf[v].Ufl->lag}
fldu.write(code_file, instruction_number); << FBINARY_{BinaryOpcode::times}
FLDV_ fldv{SymbolType::endogenous, Uf[v].Ufl->var, Uf[v].Ufl->lag}; << FCUML_{};
fldv.write(code_file, instruction_number);
FBINARY_ fbinary{BinaryOpcode::times};
fbinary.write(code_file, instruction_number);
FCUML_ fcuml;
fcuml.write(code_file, instruction_number);
}
Uf[v].Ufl = Uf[v].Ufl_First; Uf[v].Ufl = Uf[v].Ufl_First;
while (Uf[v].Ufl) while (Uf[v].Ufl)
{ {
@ -1293,11 +1200,8 @@ DynamicModel::writeDynamicBlockBytecode(const string &basename) const
free(Uf[v].Ufl); free(Uf[v].Ufl);
Uf[v].Ufl = Uf[v].Ufl_First; Uf[v].Ufl = Uf[v].Ufl_First;
} }
FBINARY_ fbinary{BinaryOpcode::minus}; code_file << FBINARY_{BinaryOpcode::minus}
fbinary.write(code_file, instruction_number); << FSTPU_{i - block_recursive};
FSTPU_ fstpu(i - block_recursive);
fstpu.write(code_file, instruction_number);
} }
} }
break; break;
@ -1306,17 +1210,11 @@ DynamicModel::writeDynamicBlockBytecode(const string &basename) const
} }
} }
// Get the current code_file position and jump = true // Jump unconditionally after the block
streampos pos2 = code_file.tellp(); int pos_jmp = code_file.getInstructionCounter();
FJMP_ fjmp(0); code_file << FJMP_{0}; // Use 0 as jump offset for the time being
fjmp.write(code_file, instruction_number); // Update jump offset for previous JMPIFEVAL
// Set code_file position to previous JMPIFEVAL_ and set the number of instructions to jump code_file.overwriteInstruction(pos_jmpifeval, FJMPIFEVAL_{pos_jmp-pos_jmpifeval});
streampos pos3 = code_file.tellp();
code_file.seekp(pos1);
FJMPIFEVAL_ fjmp_if_eval1(instruction_number - prev_instruction_number);
fjmp_if_eval1.write(code_file, instruction_number);
code_file.seekp(pos3);
prev_instruction_number = instruction_number;
/* If the block is of type “evaluate backward/forward”, then write the /* If the block is of type “evaluate backward/forward”, then write the
temporary terms for derivatives at this point, because they have not temporary terms for derivatives at this point, because they have not
@ -1331,58 +1229,43 @@ DynamicModel::writeDynamicBlockBytecode(const string &basename) const
auto [eq, var, lag] = indices; 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);
FNUMEXPR_ fnumexpr(ExpressionType::FirstEndoDerivative, eqr, varr, lag); code_file << FNUMEXPR_{ExpressionType::FirstEndoDerivative, eqr, varr, lag};
fnumexpr.write(code_file, instruction_number); writeBytecodeDerivative(code_file, eqr, varr, lag, temporary_terms_union, blocks_temporary_terms_idxs, tef_terms);
compileDerivative(code_file, instruction_number, eqr, varr, lag, temporary_terms_union, blocks_temporary_terms_idxs, tef_terms); code_file << FSTPG3_{eq, var, lag, blocks_jacob_cols_endo[block].at({ var, lag })};
FSTPG3_ fstpg3(eq, var, lag, blocks_jacob_cols_endo[block].at({ var, lag }));
fstpg3.write(code_file, instruction_number);
} }
for (const auto &[indices, d] : blocks_derivatives_exo[block]) for (const auto &[indices, d] : blocks_derivatives_exo[block])
{ {
auto [eqr, var, lag] = indices; auto [eqr, var, lag] = indices;
int eq = getBlockEquationID(block, eqr); int eq = getBlockEquationID(block, eqr);
int varr = 0; // Dummy value, actually unused by the bytecode MEX int varr = 0; // Dummy value, actually unused by the bytecode MEX
FNUMEXPR_ fnumexpr(ExpressionType::FirstExoDerivative, eqr, varr, lag); code_file << FNUMEXPR_{ExpressionType::FirstExoDerivative, eqr, varr, lag};
fnumexpr.write(code_file, instruction_number); d->writeBytecodeOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms);
d->compile(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms); code_file << FSTPG3_{eq, var, lag, blocks_jacob_cols_exo[block].at({ var, lag })};
FSTPG3_ fstpg3(eq, var, lag, blocks_jacob_cols_exo[block].at({ var, lag }));
fstpg3.write(code_file, instruction_number);
} }
for (const auto &[indices, d] : blocks_derivatives_exo_det[block]) for (const auto &[indices, d] : blocks_derivatives_exo_det[block])
{ {
auto [eqr, var, lag] = indices; auto [eqr, var, lag] = indices;
int eq = getBlockEquationID(block, eqr); int eq = getBlockEquationID(block, eqr);
int varr = 0; // Dummy value, actually unused by the bytecode MEX int varr = 0; // Dummy value, actually unused by the bytecode MEX
FNUMEXPR_ fnumexpr(ExpressionType::FirstExodetDerivative, eqr, varr, lag); code_file << FNUMEXPR_{ExpressionType::FirstExodetDerivative, eqr, varr, lag};
fnumexpr.write(code_file, instruction_number); d->writeBytecodeOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms);
d->compile(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms); code_file << FSTPG3_{eq, var, lag, blocks_jacob_cols_exo_det[block].at({ var, lag })};
FSTPG3_ fstpg3(eq, var, lag, blocks_jacob_cols_exo_det[block].at({ var, lag }));
fstpg3.write(code_file, instruction_number);
} }
for (const auto &[indices, d] : blocks_derivatives_other_endo[block]) for (const auto &[indices, d] : blocks_derivatives_other_endo[block])
{ {
auto [eqr, var, lag] = indices; auto [eqr, var, lag] = indices;
int eq = getBlockEquationID(block, eqr); int eq = getBlockEquationID(block, eqr);
int varr = 0; // Dummy value, actually unused by the bytecode MEX int varr = 0; // Dummy value, actually unused by the bytecode MEX
FNUMEXPR_ fnumexpr(ExpressionType::FirstOtherEndoDerivative, eqr, varr, lag); code_file << FNUMEXPR_{ExpressionType::FirstOtherEndoDerivative, eqr, varr, lag};
fnumexpr.write(code_file, instruction_number); d->writeBytecodeOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms);
d->compile(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, true, false, tef_terms); code_file << FSTPG3_{eq, var, lag, blocks_jacob_cols_other_endo[block].at({ var, lag })};
FSTPG3_ fstpg3(eq, var, lag, blocks_jacob_cols_other_endo[block].at({ var, lag }));
fstpg3.write(code_file, instruction_number);
} }
// Set codefile position to previous JMP_ and set the number of instructions to jump // Update jump offset for previous JMP
pos1 = code_file.tellp(); int pos_end_block = code_file.getInstructionCounter();
code_file.seekp(pos2); code_file.overwriteInstruction(pos_jmp, FJMP_{pos_end_block-pos_jmp-1});
FJMP_ fjmp1(instruction_number - prev_instruction_number);
fjmp1.write(code_file, instruction_number);
code_file.seekp(pos1);
} }
FENDBLOCK_ fendblock; code_file << FENDBLOCK_{} << FEND_{};
fendblock.write(code_file, instruction_number);
FEND_ fend;
fend.write(code_file, instruction_number);
code_file.close();
} }
void void

View File

@ -24,6 +24,7 @@
#include <filesystem> #include <filesystem>
#include "StaticModel.hh" #include "StaticModel.hh"
#include "Bytecode.hh"
using namespace std; using namespace std;
@ -182,10 +183,10 @@ private:
vector<vector<temporary_terms_t>> &blocks_temporary_terms, vector<vector<temporary_terms_t>> &blocks_temporary_terms,
map<expr_t, tuple<int, int, int>> &reference_count) const override; map<expr_t, tuple<int, int, int>> &reference_count) const override;
//! Write derivative code of an equation w.r. to a variable //! Write derivative bytecode of an equation w.r. to a variable
void compileDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int symb_id, int lag, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const; void writeBytecodeDerivative(BytecodeWriter &code_file, int eq, int symb_id, int lag, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
//! Write chain rule derivative code of an equation w.r. to a variable //! Write chain rule derivative bytecode of an equation w.r. to a variable
void compileChainRuleDerivative(ofstream &code_file, unsigned int &instruction_number, int blk, int eq, int var, int lag, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const; void writeBytecodeChainRuleDerivative(BytecodeWriter &code_file, int blk, int eq, int var, int lag, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
//! Get the type corresponding to a derivation ID //! Get the type corresponding to a derivation ID
SymbolType getTypeByDerivID(int deriv_id) const noexcept(false) override; SymbolType getTypeByDerivID(int deriv_id) const noexcept(false) override;

View File

@ -27,7 +27,6 @@
#include "ExprNode.hh" #include "ExprNode.hh"
#include "DataTree.hh" #include "DataTree.hh"
#include "ModFile.hh" #include "ModFile.hh"
#include "Bytecode.hh"
ExprNode::ExprNode(DataTree &datatree_arg, int idx_arg) : datatree{datatree_arg}, idx{idx_arg} ExprNode::ExprNode(DataTree &datatree_arg, int idx_arg) : datatree{datatree_arg}, idx{idx_arg}
{ {
@ -107,6 +106,28 @@ ExprNode::checkIfTemporaryTermThenWrite(ostream &output, ExprNodeOutputType outp
return true; return true;
} }
bool
ExprNode::checkIfTemporaryTermThenWriteBytecode(BytecodeWriter &code_file,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs,
bool dynamic) const
{
if (!temporary_terms.contains(const_cast<ExprNode *>(this)))
return false;
auto it2 = temporary_terms_idxs.find(const_cast<ExprNode *>(this));
// It is the responsibility of the caller to ensure that all temporary terms have their index
assert(it2 != temporary_terms_idxs.end());
if (dynamic)
code_file << FLDT_{it2->second};
else
code_file << FLDST_{it2->second};
return true;
}
pair<expr_t, int> pair<expr_t, int>
ExprNode::getLagEquivalenceClass() const ExprNode::getLagEquivalenceClass() const
{ {
@ -189,10 +210,10 @@ ExprNode::writeJsonExternalFunctionOutput(vector<string> &efout,
} }
void void
ExprNode::compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, ExprNode::writeBytecodeExternalFunctionOutput(BytecodeWriter &code_file, bool lhs_rhs,
bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
deriv_node_temp_terms_t &tef_terms) const deriv_node_temp_terms_t &tef_terms) const
{ {
// Nothing to do // Nothing to do
} }
@ -456,13 +477,12 @@ NumConstNode::eval(const eval_context_t &eval_context) const noexcept(false)
} }
void void
NumConstNode::compile(ostream &CompileCode, unsigned int &instruction_number, NumConstNode::writeBytecodeOutput(BytecodeWriter &code_file, bool lhs_rhs,
bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
const deriv_node_temp_terms_t &tef_terms) const const deriv_node_temp_terms_t &tef_terms) const
{ {
FLDC_ fldc(datatree.num_constants.getDouble(id)); code_file << FLDC_{datatree.num_constants.getDouble(id)};
fldc.write(CompileCode, instruction_number);
} }
void void
@ -1225,14 +1245,14 @@ VariableNode::eval(const eval_context_t &eval_context) const noexcept(false)
} }
void void
VariableNode::compile(ostream &CompileCode, unsigned int &instruction_number, VariableNode::writeBytecodeOutput(BytecodeWriter &code_file, bool lhs_rhs,
bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
const deriv_node_temp_terms_t &tef_terms) const const deriv_node_temp_terms_t &tef_terms) const
{ {
auto type = get_type(); auto type = get_type();
if (type == SymbolType::modelLocalVariable || type == SymbolType::modFileLocalVariable) if (type == SymbolType::modelLocalVariable || type == SymbolType::modFileLocalVariable)
datatree.getLocalVariable(symb_id)->compile(CompileCode, instruction_number, lhs_rhs, temporary_terms, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms); datatree.getLocalVariable(symb_id)->writeBytecodeOutput(code_file, lhs_rhs, temporary_terms, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
else else
{ {
int tsid = datatree.symbol_table.getTypeSpecificID(symb_id); int tsid = datatree.symbol_table.getTypeSpecificID(symb_id);
@ -1243,29 +1263,17 @@ VariableNode::compile(ostream &CompileCode, unsigned int &instruction_number,
if (dynamic) if (dynamic)
{ {
if (steady_dynamic) // steady state values in a dynamic model if (steady_dynamic) // steady state values in a dynamic model
{ code_file << FLDVS_{type, tsid};
FLDVS_ fldvs{type, tsid};
fldvs.write(CompileCode, instruction_number);
}
else else
{ {
if (type == SymbolType::parameter) if (type == SymbolType::parameter)
{ code_file << FLDV_{type, tsid};
FLDV_ fldv{type, tsid};
fldv.write(CompileCode, instruction_number);
}
else else
{ code_file << FLDV_{type, tsid, lag};
FLDV_ fldv{type, tsid, lag};
fldv.write(CompileCode, instruction_number);
}
} }
} }
else else
{ code_file << FLDSV_{type, tsid};
FLDSV_ fldsv{type, tsid};
fldsv.write(CompileCode, instruction_number);
}
} }
else else
{ {
@ -1279,22 +1287,13 @@ VariableNode::compile(ostream &CompileCode, unsigned int &instruction_number,
else else
{ {
if (type == SymbolType::parameter) if (type == SymbolType::parameter)
{ code_file << FSTPV_{type, tsid};
FSTPV_ fstpv{type, tsid};
fstpv.write(CompileCode, instruction_number);
}
else else
{ code_file << FSTPV_{type, tsid, lag};
FSTPV_ fstpv{type, tsid, lag};
fstpv.write(CompileCode, instruction_number);
}
} }
} }
else else
{ code_file << FSTPSV_{type, tsid};
FSTPSV_ fstpsv{type, tsid};
fstpsv.write(CompileCode, instruction_number);
}
} }
} }
} }
@ -2923,13 +2922,13 @@ UnaryOpNode::writeJsonExternalFunctionOutput(vector<string> &efout,
} }
void void
UnaryOpNode::compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, UnaryOpNode::writeBytecodeExternalFunctionOutput(BytecodeWriter &code_file, bool lhs_rhs,
bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
deriv_node_temp_terms_t &tef_terms) const deriv_node_temp_terms_t &tef_terms) const
{ {
arg->compileExternalFunctionOutput(CompileCode, instruction_number, lhs_rhs, temporary_terms, arg->writeBytecodeExternalFunctionOutput(code_file, lhs_rhs, temporary_terms,
temporary_terms_idxs, dynamic, steady_dynamic, tef_terms); temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
} }
double double
@ -3011,33 +3010,20 @@ UnaryOpNode::eval(const eval_context_t &eval_context) const noexcept(false)
} }
void void
UnaryOpNode::compile(ostream &CompileCode, unsigned int &instruction_number, UnaryOpNode::writeBytecodeOutput(BytecodeWriter &code_file, bool lhs_rhs,
bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
const deriv_node_temp_terms_t &tef_terms) const const deriv_node_temp_terms_t &tef_terms) const
{ {
if (auto this2 = const_cast<UnaryOpNode *>(this); if (checkIfTemporaryTermThenWriteBytecode(code_file, temporary_terms, temporary_terms_idxs, dynamic))
temporary_terms.contains(this2)) return;
{
if (dynamic)
{
FLDT_ fldt(temporary_terms_idxs.at(this2));
fldt.write(CompileCode, instruction_number);
}
else
{
FLDST_ fldst(temporary_terms_idxs.at(this2));
fldst.write(CompileCode, instruction_number);
}
return;
}
if (op_code == UnaryOpcode::steadyState) if (op_code == UnaryOpcode::steadyState)
arg->compile(CompileCode, instruction_number, lhs_rhs, temporary_terms, temporary_terms_idxs, dynamic, true, tef_terms); arg->writeBytecodeOutput(code_file, lhs_rhs, temporary_terms, temporary_terms_idxs, dynamic, true, tef_terms);
else else
{ {
arg->compile(CompileCode, instruction_number, lhs_rhs, temporary_terms, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms); arg->writeBytecodeOutput(code_file, lhs_rhs, temporary_terms, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
FUNARY_ funary{op_code}; code_file << FUNARY_{op_code};
funary.write(CompileCode, instruction_number);
} }
} }
@ -4271,36 +4257,19 @@ BinaryOpNode::eval(const eval_context_t &eval_context) const noexcept(false)
} }
void void
BinaryOpNode::compile(ostream &CompileCode, unsigned int &instruction_number, BinaryOpNode::writeBytecodeOutput(BytecodeWriter &code_file, bool lhs_rhs,
bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
const deriv_node_temp_terms_t &tef_terms) const const deriv_node_temp_terms_t &tef_terms) const
{ {
// If current node is a temporary term if (checkIfTemporaryTermThenWriteBytecode(code_file, temporary_terms, temporary_terms_idxs, dynamic))
if (auto this2 = const_cast<BinaryOpNode *>(this); return;
temporary_terms.contains(this2))
{
if (dynamic)
{
FLDT_ fldt(temporary_terms_idxs.at(this2));
fldt.write(CompileCode, instruction_number);
}
else
{
FLDST_ fldst(temporary_terms_idxs.at(this2));
fldst.write(CompileCode, instruction_number);
}
return;
}
if (op_code == BinaryOpcode::powerDeriv) if (op_code == BinaryOpcode::powerDeriv)
{ code_file << FLDC_{static_cast<double>(powerDerivOrder)};
FLDC_ fldc(powerDerivOrder); arg1->writeBytecodeOutput(code_file, lhs_rhs, temporary_terms, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
fldc.write(CompileCode, instruction_number); arg2->writeBytecodeOutput(code_file, lhs_rhs, temporary_terms, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
} code_file << FBINARY_{op_code};
arg1->compile(CompileCode, instruction_number, lhs_rhs, temporary_terms, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
arg2->compile(CompileCode, instruction_number, lhs_rhs, temporary_terms, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
FBINARY_ fbinary{op_code};
fbinary.write(CompileCode, instruction_number);
} }
bool bool
@ -4738,15 +4707,15 @@ BinaryOpNode::writeJsonExternalFunctionOutput(vector<string> &efout,
} }
void void
BinaryOpNode::compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, BinaryOpNode::writeBytecodeExternalFunctionOutput(BytecodeWriter &code_file, bool lhs_rhs,
bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
deriv_node_temp_terms_t &tef_terms) const deriv_node_temp_terms_t &tef_terms) const
{ {
arg1->compileExternalFunctionOutput(CompileCode, instruction_number, lhs_rhs, temporary_terms, arg1->writeBytecodeExternalFunctionOutput(code_file, lhs_rhs, temporary_terms,
temporary_terms_idxs, dynamic, steady_dynamic, tef_terms); temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
arg2->compileExternalFunctionOutput(CompileCode, instruction_number, lhs_rhs, temporary_terms, arg2->writeBytecodeExternalFunctionOutput(code_file, lhs_rhs, temporary_terms,
temporary_terms_idxs, dynamic, steady_dynamic, tef_terms); temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
} }
int int
@ -5971,32 +5940,18 @@ TrinaryOpNode::eval(const eval_context_t &eval_context) const noexcept(false)
} }
void void
TrinaryOpNode::compile(ostream &CompileCode, unsigned int &instruction_number, TrinaryOpNode::writeBytecodeOutput(BytecodeWriter &code_file, bool lhs_rhs,
bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
const deriv_node_temp_terms_t &tef_terms) const const deriv_node_temp_terms_t &tef_terms) const
{ {
// If current node is a temporary term if (checkIfTemporaryTermThenWriteBytecode(code_file, temporary_terms, temporary_terms_idxs, dynamic))
if (auto this2 = const_cast<TrinaryOpNode *>(this); return;
temporary_terms.contains(this2))
{ arg1->writeBytecodeOutput(code_file, lhs_rhs, temporary_terms, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
if (dynamic) arg2->writeBytecodeOutput(code_file, lhs_rhs, temporary_terms, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
{ arg3->writeBytecodeOutput(code_file, lhs_rhs, temporary_terms, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
FLDT_ fldt(temporary_terms_idxs.at(this2)); code_file << FTRINARY_{op_code};
fldt.write(CompileCode, instruction_number);
}
else
{
FLDST_ fldst(temporary_terms_idxs.at(this2));
fldst.write(CompileCode, instruction_number);
}
return;
}
arg1->compile(CompileCode, instruction_number, lhs_rhs, temporary_terms, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
arg2->compile(CompileCode, instruction_number, lhs_rhs, temporary_terms, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
arg3->compile(CompileCode, instruction_number, lhs_rhs, temporary_terms, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
FTRINARY_ ftrinary{op_code};
ftrinary.write(CompileCode, instruction_number);
} }
bool bool
@ -6174,17 +6129,17 @@ TrinaryOpNode::writeJsonExternalFunctionOutput(vector<string> &efout,
} }
void void
TrinaryOpNode::compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, TrinaryOpNode::writeBytecodeExternalFunctionOutput(BytecodeWriter &code_file, bool lhs_rhs,
bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
deriv_node_temp_terms_t &tef_terms) const deriv_node_temp_terms_t &tef_terms) const
{ {
arg1->compileExternalFunctionOutput(CompileCode, instruction_number, lhs_rhs, temporary_terms, arg1->writeBytecodeExternalFunctionOutput(code_file, lhs_rhs, temporary_terms,
temporary_terms_idxs, dynamic, steady_dynamic, tef_terms); temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
arg2->compileExternalFunctionOutput(CompileCode, instruction_number, lhs_rhs, temporary_terms, arg2->writeBytecodeExternalFunctionOutput(code_file, lhs_rhs, temporary_terms,
temporary_terms_idxs, dynamic, steady_dynamic, tef_terms); temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
arg3->compileExternalFunctionOutput(CompileCode, instruction_number, lhs_rhs, temporary_terms, arg3->writeBytecodeExternalFunctionOutput(code_file, lhs_rhs, temporary_terms,
temporary_terms_idxs, dynamic, steady_dynamic, tef_terms); temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
} }
void void
@ -6655,14 +6610,14 @@ AbstractExternalFunctionNode::getChainRuleDerivative(int deriv_id, const map<int
} }
int int
AbstractExternalFunctionNode::compileExternalFunctionArguments(ostream &CompileCode, unsigned int &instruction_number, AbstractExternalFunctionNode::writeBytecodeExternalFunctionArguments(BytecodeWriter &code_file, bool lhs_rhs,
bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
const deriv_node_temp_terms_t &tef_terms) const const deriv_node_temp_terms_t &tef_terms) const
{ {
for (auto argument : arguments) for (auto argument : arguments)
argument->compile(CompileCode, instruction_number, lhs_rhs, temporary_terms, argument->writeBytecodeOutput(code_file, lhs_rhs, temporary_terms,
temporary_terms_idxs, dynamic, steady_dynamic, tef_terms); temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
return static_cast<int>(arguments.size()); return static_cast<int>(arguments.size());
} }
@ -7206,51 +7161,32 @@ ExternalFunctionNode::composeDerivatives(const vector<expr_t> &dargs)
} }
void void
ExternalFunctionNode::compile(ostream &CompileCode, unsigned int &instruction_number, ExternalFunctionNode::writeBytecodeOutput(BytecodeWriter &code_file, bool lhs_rhs,
bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
const deriv_node_temp_terms_t &tef_terms) const const deriv_node_temp_terms_t &tef_terms) const
{ {
if (auto this2 = const_cast<ExternalFunctionNode *>(this); if (checkIfTemporaryTermThenWriteBytecode(code_file, temporary_terms, temporary_terms_idxs, dynamic))
temporary_terms.contains(this2)) return;
{
if (dynamic)
{
FLDT_ fldt(temporary_terms_idxs.at(this2));
fldt.write(CompileCode, instruction_number);
}
else
{
FLDST_ fldst(temporary_terms_idxs.at(this2));
fldst.write(CompileCode, instruction_number);
}
return;
}
if (!lhs_rhs) if (!lhs_rhs)
{ code_file << FLDTEF_{getIndxInTefTerms(symb_id, tef_terms)};
FLDTEF_ fldtef(getIndxInTefTerms(symb_id, tef_terms));
fldtef.write(CompileCode, instruction_number);
}
else else
{ code_file << FSTPTEF_{getIndxInTefTerms(symb_id, tef_terms)};
FSTPTEF_ fstptef(getIndxInTefTerms(symb_id, tef_terms));
fstptef.write(CompileCode, instruction_number);
}
} }
void void
ExternalFunctionNode::compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, ExternalFunctionNode::writeBytecodeExternalFunctionOutput(BytecodeWriter &code_file, bool lhs_rhs,
bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
deriv_node_temp_terms_t &tef_terms) const deriv_node_temp_terms_t &tef_terms) const
{ {
int first_deriv_symb_id = datatree.external_functions_table.getFirstDerivSymbID(symb_id); int first_deriv_symb_id = datatree.external_functions_table.getFirstDerivSymbID(symb_id);
assert(first_deriv_symb_id != ExternalFunctionsTable::IDSetButNoNameProvided); assert(first_deriv_symb_id != ExternalFunctionsTable::IDSetButNoNameProvided);
for (auto argument : arguments) for (auto argument : arguments)
argument->compileExternalFunctionOutput(CompileCode, instruction_number, lhs_rhs, temporary_terms, argument->writeBytecodeExternalFunctionOutput(code_file, lhs_rhs, temporary_terms,
temporary_terms_idxs, dynamic, steady_dynamic, tef_terms); temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
if (!alreadyWrittenAsTefTerm(symb_id, tef_terms)) if (!alreadyWrittenAsTefTerm(symb_id, tef_terms))
{ {
@ -7267,10 +7203,10 @@ ExternalFunctionNode::compileExternalFunctionOutput(ostream &CompileCode, unsign
nb_output_arguments = 2; nb_output_arguments = 2;
else else
nb_output_arguments = 1; nb_output_arguments = 1;
int nb_input_arguments{compileExternalFunctionArguments(CompileCode, instruction_number, lhs_rhs, temporary_terms, int nb_input_arguments{writeBytecodeExternalFunctionArguments(code_file, lhs_rhs, temporary_terms,
temporary_terms_idxs, dynamic, steady_dynamic, tef_terms)}; temporary_terms_idxs, dynamic, steady_dynamic, tef_terms)};
FCALL_ fcall(nb_output_arguments, nb_input_arguments, datatree.symbol_table.getName(symb_id), indx); FCALL_ fcall{nb_output_arguments, nb_input_arguments, datatree.symbol_table.getName(symb_id), indx};
switch (nb_output_arguments) switch (nb_output_arguments)
{ {
case 1: case 1:
@ -7283,9 +7219,7 @@ ExternalFunctionNode::compileExternalFunctionOutput(ostream &CompileCode, unsign
fcall.set_function_type(ExternalFunctionType::withFirstAndSecondDerivative); fcall.set_function_type(ExternalFunctionType::withFirstAndSecondDerivative);
break; break;
} }
fcall.write(CompileCode, instruction_number); code_file << fcall << FSTPTEF_{indx};
FSTPTEF_ fstptef(indx);
fstptef.write(CompileCode, instruction_number);
} }
} }
@ -7599,39 +7533,21 @@ FirstDerivExternalFunctionNode::writeOutput(ostream &output, ExprNodeOutputType
} }
void void
FirstDerivExternalFunctionNode::compile(ostream &CompileCode, unsigned int &instruction_number, FirstDerivExternalFunctionNode::writeBytecodeOutput(BytecodeWriter &code_file, bool lhs_rhs,
bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
const deriv_node_temp_terms_t &tef_terms) const const deriv_node_temp_terms_t &tef_terms) const
{ {
if (auto this2 = const_cast<FirstDerivExternalFunctionNode *>(this); if (checkIfTemporaryTermThenWriteBytecode(code_file, temporary_terms, temporary_terms_idxs, dynamic))
temporary_terms.contains(this2)) return;
{
if (dynamic)
{
FLDT_ fldt(temporary_terms_idxs.at(this2));
fldt.write(CompileCode, instruction_number);
}
else
{
FLDST_ fldst(temporary_terms_idxs.at(this2));
fldst.write(CompileCode, instruction_number);
}
return;
}
int first_deriv_symb_id = datatree.external_functions_table.getFirstDerivSymbID(symb_id); int first_deriv_symb_id = datatree.external_functions_table.getFirstDerivSymbID(symb_id);
assert(first_deriv_symb_id != ExternalFunctionsTable::IDSetButNoNameProvided); assert(first_deriv_symb_id != ExternalFunctionsTable::IDSetButNoNameProvided);
if (!lhs_rhs) if (!lhs_rhs)
{ code_file << FLDTEFD_{getIndxInTefTerms(symb_id, tef_terms), inputIndex};
FLDTEFD_ fldtefd(getIndxInTefTerms(symb_id, tef_terms), inputIndex);
fldtefd.write(CompileCode, instruction_number);
}
else else
{ code_file << FSTPTEFD_{getIndxInTefTerms(symb_id, tef_terms), inputIndex};
FSTPTEFD_ fstptefd(getIndxInTefTerms(symb_id, tef_terms), inputIndex);
fstptefd.write(CompileCode, instruction_number);
}
} }
void void
@ -7760,10 +7676,10 @@ FirstDerivExternalFunctionNode::writeJsonExternalFunctionOutput(vector<string> &
} }
void void
FirstDerivExternalFunctionNode::compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, FirstDerivExternalFunctionNode::writeBytecodeExternalFunctionOutput(BytecodeWriter &code_file, bool lhs_rhs,
bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
deriv_node_temp_terms_t &tef_terms) const deriv_node_temp_terms_t &tef_terms) const
{ {
int first_deriv_symb_id = datatree.external_functions_table.getFirstDerivSymbID(symb_id); int first_deriv_symb_id = datatree.external_functions_table.getFirstDerivSymbID(symb_id);
assert(first_deriv_symb_id != ExternalFunctionsTable::IDSetButNoNameProvided); assert(first_deriv_symb_id != ExternalFunctionsTable::IDSetButNoNameProvided);
@ -7773,30 +7689,28 @@ FirstDerivExternalFunctionNode::compileExternalFunctionOutput(ostream &CompileCo
if (first_deriv_symb_id == symb_id) if (first_deriv_symb_id == symb_id)
{ {
expr_t parent = datatree.AddExternalFunction(symb_id, arguments); expr_t parent = datatree.AddExternalFunction(symb_id, arguments);
parent->compileExternalFunctionOutput(CompileCode, instruction_number, lhs_rhs, parent->writeBytecodeExternalFunctionOutput(code_file, lhs_rhs,
temporary_terms, temporary_terms_idxs, temporary_terms, temporary_terms_idxs,
dynamic, steady_dynamic, tef_terms); dynamic, steady_dynamic, tef_terms);
return; return;
} }
if (alreadyWrittenAsTefTerm(first_deriv_symb_id, tef_terms)) if (alreadyWrittenAsTefTerm(first_deriv_symb_id, tef_terms))
return; return;
int nb_add_input_arguments{compileExternalFunctionArguments(CompileCode, instruction_number, lhs_rhs, temporary_terms, int nb_add_input_arguments{writeBytecodeExternalFunctionArguments(code_file, lhs_rhs, temporary_terms,
temporary_terms_idxs, dynamic, steady_dynamic, tef_terms)}; temporary_terms_idxs, dynamic, steady_dynamic, tef_terms)};
if (first_deriv_symb_id == ExternalFunctionsTable::IDNotSet) if (first_deriv_symb_id == ExternalFunctionsTable::IDNotSet)
{ {
int nb_input_arguments{0}; int nb_input_arguments{0};
int nb_output_arguments{1}; int nb_output_arguments{1};
int indx = getIndxInTefTerms(symb_id, tef_terms); int indx = getIndxInTefTerms(symb_id, tef_terms);
FCALL_ fcall(nb_output_arguments, nb_input_arguments, "jacob_element", indx); FCALL_ fcall{nb_output_arguments, nb_input_arguments, "jacob_element", indx};
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(nb_add_input_arguments); fcall.set_nb_add_input_arguments(nb_add_input_arguments);
fcall.set_function_type(ExternalFunctionType::numericalFirstDerivative); fcall.set_function_type(ExternalFunctionType::numericalFirstDerivative);
fcall.write(CompileCode, instruction_number); code_file << fcall << FSTPTEFD_{indx, inputIndex};
FSTPTEFD_ fstptefd(indx, inputIndex);
fstptefd.write(CompileCode, instruction_number);
} }
else else
{ {
@ -7807,11 +7721,9 @@ FirstDerivExternalFunctionNode::compileExternalFunctionOutput(ostream &CompileCo
int nb_output_arguments{1}; int nb_output_arguments{1};
FCALL_ fcall(nb_output_arguments, nb_add_input_arguments, datatree.symbol_table.getName(first_deriv_symb_id), indx); FCALL_ fcall{nb_output_arguments, nb_add_input_arguments, datatree.symbol_table.getName(first_deriv_symb_id), indx};
fcall.set_function_type(ExternalFunctionType::firstDerivative); fcall.set_function_type(ExternalFunctionType::firstDerivative);
fcall.write(CompileCode, instruction_number); code_file << fcall << FSTPTEFD_{indx, inputIndex};
FSTPTEFD_ fstptefd(indx, inputIndex);
fstptefd.write(CompileCode, instruction_number);
} }
} }
@ -8138,47 +8050,28 @@ SecondDerivExternalFunctionNode::computeXrefs(EquationInfo &ei) const
} }
void void
SecondDerivExternalFunctionNode::compile(ostream &CompileCode, unsigned int &instruction_number, SecondDerivExternalFunctionNode::writeBytecodeOutput(BytecodeWriter &code_file, bool lhs_rhs,
bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
const deriv_node_temp_terms_t &tef_terms) const const deriv_node_temp_terms_t &tef_terms) const
{ {
if (auto this2 = const_cast<SecondDerivExternalFunctionNode *>(this); if (checkIfTemporaryTermThenWriteBytecode(code_file, temporary_terms, temporary_terms_idxs, dynamic))
temporary_terms.contains(this2)) return;
{
if (dynamic)
{
FLDT_ fldt(temporary_terms_idxs.at(this2));
fldt.write(CompileCode, instruction_number);
}
else
{
FLDST_ fldst(temporary_terms_idxs.at(this2));
fldst.write(CompileCode, instruction_number);
}
return;
}
int second_deriv_symb_id = datatree.external_functions_table.getSecondDerivSymbID(symb_id); int second_deriv_symb_id = datatree.external_functions_table.getSecondDerivSymbID(symb_id);
assert(second_deriv_symb_id != ExternalFunctionsTable::IDSetButNoNameProvided); assert(second_deriv_symb_id != ExternalFunctionsTable::IDSetButNoNameProvided);
if (!lhs_rhs) if (!lhs_rhs)
{ code_file << FLDTEFDD_{getIndxInTefTerms(symb_id, tef_terms), inputIndex1, inputIndex2};
FLDTEFDD_ fldtefdd(getIndxInTefTerms(symb_id, tef_terms), inputIndex1, inputIndex2);
fldtefdd.write(CompileCode, instruction_number);
}
else else
{ code_file << FSTPTEFDD_{getIndxInTefTerms(symb_id, tef_terms), inputIndex1, inputIndex2};
FSTPTEFDD_ fstptefdd(getIndxInTefTerms(symb_id, tef_terms), inputIndex1, inputIndex2);
fstptefdd.write(CompileCode, instruction_number);
}
} }
void void
SecondDerivExternalFunctionNode::compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, SecondDerivExternalFunctionNode::writeBytecodeExternalFunctionOutput(BytecodeWriter &code_file, bool lhs_rhs,
bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
deriv_node_temp_terms_t &tef_terms) const deriv_node_temp_terms_t &tef_terms) const
{ {
int second_deriv_symb_id = datatree.external_functions_table.getSecondDerivSymbID(symb_id); int second_deriv_symb_id = datatree.external_functions_table.getSecondDerivSymbID(symb_id);
assert(second_deriv_symb_id != ExternalFunctionsTable::IDSetButNoNameProvided); assert(second_deriv_symb_id != ExternalFunctionsTable::IDSetButNoNameProvided);
@ -8188,31 +8081,29 @@ SecondDerivExternalFunctionNode::compileExternalFunctionOutput(ostream &CompileC
if (second_deriv_symb_id == symb_id) if (second_deriv_symb_id == symb_id)
{ {
expr_t parent = datatree.AddExternalFunction(symb_id, arguments); expr_t parent = datatree.AddExternalFunction(symb_id, arguments);
parent->compileExternalFunctionOutput(CompileCode, instruction_number, lhs_rhs, parent->writeBytecodeExternalFunctionOutput(code_file, lhs_rhs,
temporary_terms, temporary_terms_idxs, temporary_terms, temporary_terms_idxs,
dynamic, steady_dynamic, tef_terms); dynamic, steady_dynamic, tef_terms);
return; return;
} }
if (alreadyWrittenAsTefTerm(second_deriv_symb_id, tef_terms)) if (alreadyWrittenAsTefTerm(second_deriv_symb_id, tef_terms))
return; return;
int nb_add_input_arguments{compileExternalFunctionArguments(CompileCode, instruction_number, lhs_rhs, temporary_terms, int nb_add_input_arguments{writeBytecodeExternalFunctionArguments(code_file, lhs_rhs, temporary_terms,
temporary_terms_idxs, dynamic, steady_dynamic, tef_terms)}; temporary_terms_idxs, dynamic, steady_dynamic, tef_terms)};
if (second_deriv_symb_id == ExternalFunctionsTable::IDNotSet) if (second_deriv_symb_id == ExternalFunctionsTable::IDNotSet)
{ {
int nb_input_arguments{0}; int nb_input_arguments{0};
int nb_output_arguments{1}; int nb_output_arguments{1};
int indx = getIndxInTefTerms(symb_id, tef_terms); int indx = getIndxInTefTerms(symb_id, tef_terms);
FCALL_ fcall(nb_output_arguments, nb_input_arguments, "hess_element", indx); FCALL_ fcall{nb_output_arguments, nb_input_arguments, "hess_element", indx};
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(nb_add_input_arguments); fcall.set_nb_add_input_arguments(nb_add_input_arguments);
fcall.set_function_type(ExternalFunctionType::numericalSecondDerivative); fcall.set_function_type(ExternalFunctionType::numericalSecondDerivative);
fcall.write(CompileCode, instruction_number); code_file << fcall << FSTPTEFDD_{indx, inputIndex1, inputIndex2};
FSTPTEFDD_ fstptefdd(indx, inputIndex1, inputIndex2);
fstptefdd.write(CompileCode, instruction_number);
} }
else else
{ {
@ -8221,11 +8112,9 @@ SecondDerivExternalFunctionNode::compileExternalFunctionOutput(ostream &CompileC
int nb_output_arguments{1}; int nb_output_arguments{1};
FCALL_ fcall(nb_output_arguments, nb_add_input_arguments, datatree.symbol_table.getName(second_deriv_symb_id), indx); FCALL_ fcall{nb_output_arguments, nb_add_input_arguments, datatree.symbol_table.getName(second_deriv_symb_id), indx};
fcall.set_function_type(ExternalFunctionType::secondDerivative); fcall.set_function_type(ExternalFunctionType::secondDerivative);
fcall.write(CompileCode, instruction_number); code_file << fcall << FSTPTEFDD_{indx, inputIndex1, inputIndex2};
FSTPTEFDD_ fstptefdd(indx, inputIndex1, inputIndex2);
fstptefdd.write(CompileCode, instruction_number);
} }
} }
@ -8428,10 +8317,10 @@ SubModelNode::collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &
} }
void void
SubModelNode::compile(ostream &CompileCode, unsigned int &instruction_number, SubModelNode::writeBytecodeOutput(BytecodeWriter &code_file, bool lhs_rhs,
bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
const deriv_node_temp_terms_t &tef_terms) const const deriv_node_temp_terms_t &tef_terms) const
{ {
cerr << "SubModelNode::compile not implemented." << endl; cerr << "SubModelNode::compile not implemented." << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);

View File

@ -31,6 +31,7 @@ using namespace std;
#include "CommonEnums.hh" #include "CommonEnums.hh"
#include "ExternalFunctionsTable.hh" #include "ExternalFunctionsTable.hh"
#include "Bytecode.hh"
class DataTree; class DataTree;
class NumConstNode; class NumConstNode;
@ -240,6 +241,12 @@ protected:
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;
// Same as above, for the bytecode case
bool checkIfTemporaryTermThenWriteBytecode(BytecodeWriter &code_file,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs,
bool dynamic) const;
// Internal helper for matchVariableTimesConstantTimesParam() // Internal helper for matchVariableTimesConstantTimesParam()
virtual void matchVTCTPHelper(optional<int> &var_id, int &lag, optional<int> &param_id, double &constant, bool at_denominator) const; virtual void matchVTCTPHelper(optional<int> &var_id, int &lag, optional<int> &param_id, double &constant, bool at_denominator) const;
@ -360,10 +367,10 @@ public:
deriv_node_temp_terms_t &tef_terms, deriv_node_temp_terms_t &tef_terms,
bool isdynamic = true) const; bool isdynamic = true) const;
virtual void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, virtual void writeBytecodeExternalFunctionOutput(BytecodeWriter &code_file,
bool lhs_rhs, const temporary_terms_t &temporary_terms, bool lhs_rhs, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
deriv_node_temp_terms_t &tef_terms) const; deriv_node_temp_terms_t &tef_terms) const;
//! Computes the set of all variables of a given symbol type in the expression (with information on lags) //! Computes the set of all variables of a given symbol type in the expression (with information on lags)
/*! /*!
@ -406,7 +413,7 @@ public:
}; };
virtual double eval(const eval_context_t &eval_context) const noexcept(false) = 0; virtual double eval(const eval_context_t &eval_context) const noexcept(false) = 0;
virtual void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const = 0; virtual void writeBytecodeOutput(BytecodeWriter &code_file, bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const = 0;
//! Creates a static version of this node //! Creates a static version of this node
/*! /*!
@ -788,7 +795,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;
double eval(const eval_context_t &eval_context) const noexcept(false) override; double eval(const eval_context_t &eval_context) const noexcept(false) override;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override; void writeBytecodeOutput(BytecodeWriter &code_file, bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override;
expr_t toStatic(DataTree &static_datatree) const override; expr_t toStatic(DataTree &static_datatree) const override;
void computeXrefs(EquationInfo &ei) const override; void computeXrefs(EquationInfo &ei) const override;
void computeSubExprContainingVariable(int symb_id, int lag, set<expr_t> &contain_var) const override; void computeSubExprContainingVariable(int symb_id, int lag, set<expr_t> &contain_var) const override;
@ -860,7 +867,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;
double eval(const eval_context_t &eval_context) const noexcept(false) override; double eval(const eval_context_t &eval_context) const noexcept(false) override;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override; void writeBytecodeOutput(BytecodeWriter &code_file, bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override;
expr_t toStatic(DataTree &static_datatree) const override; expr_t toStatic(DataTree &static_datatree) const override;
void computeXrefs(EquationInfo &ei) const override; void computeXrefs(EquationInfo &ei) const override;
SymbolType get_type() const; SymbolType get_type() const;
@ -955,7 +962,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 compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, void writeBytecodeExternalFunctionOutput(BytecodeWriter &code_file,
bool lhs_rhs, const temporary_terms_t &temporary_terms, bool lhs_rhs, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
deriv_node_temp_terms_t &tef_terms) const override; deriv_node_temp_terms_t &tef_terms) const override;
@ -963,7 +970,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);
double eval(const eval_context_t &eval_context) const noexcept(false) override; double eval(const eval_context_t &eval_context) const noexcept(false) override;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override; void writeBytecodeOutput(BytecodeWriter &code_file, bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override;
expr_t toStatic(DataTree &static_datatree) const override; expr_t toStatic(DataTree &static_datatree) const override;
void computeXrefs(EquationInfo &ei) const override; void computeXrefs(EquationInfo &ei) const override;
void computeSubExprContainingVariable(int symb_id, int lag, set<expr_t> &contain_var) const override; void computeSubExprContainingVariable(int symb_id, int lag, set<expr_t> &contain_var) const override;
@ -1058,15 +1065,15 @@ 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 compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, void writeBytecodeExternalFunctionOutput(BytecodeWriter &code_file,
bool lhs_rhs, const temporary_terms_t &temporary_terms, bool lhs_rhs, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
deriv_node_temp_terms_t &tef_terms) const override; deriv_node_temp_terms_t &tef_terms) const override;
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;
static double eval_opcode(double v1, BinaryOpcode op_code, double v2, int derivOrder) noexcept(false); static double eval_opcode(double v1, BinaryOpcode op_code, double v2, int derivOrder) noexcept(false);
double eval(const eval_context_t &eval_context) const noexcept(false) override; double eval(const eval_context_t &eval_context) const noexcept(false) override;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override; void writeBytecodeOutput(BytecodeWriter &code_file, bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override;
expr_t Compute_RHS(expr_t arg1, expr_t arg2, int op, int op_type) const; expr_t Compute_RHS(expr_t arg1, expr_t arg2, int op, int op_type) const;
expr_t toStatic(DataTree &static_datatree) const override; expr_t toStatic(DataTree &static_datatree) const override;
void computeXrefs(EquationInfo &ei) const override; void computeXrefs(EquationInfo &ei) const override;
@ -1199,15 +1206,15 @@ 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 compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, void writeBytecodeExternalFunctionOutput(BytecodeWriter &code_file,
bool lhs_rhs, const temporary_terms_t &temporary_terms, bool lhs_rhs, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
deriv_node_temp_terms_t &tef_terms) const override; deriv_node_temp_terms_t &tef_terms) const override;
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;
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);
double eval(const eval_context_t &eval_context) const noexcept(false) override; double eval(const eval_context_t &eval_context) const noexcept(false) override;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override; void writeBytecodeOutput(BytecodeWriter &code_file, bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override;
expr_t toStatic(DataTree &static_datatree) const override; expr_t toStatic(DataTree &static_datatree) const override;
void computeXrefs(EquationInfo &ei) const override; void computeXrefs(EquationInfo &ei) const override;
void computeSubExprContainingVariable(int symb_id, int lag, set<expr_t> &contain_var) const override; void computeSubExprContainingVariable(int symb_id, int lag, set<expr_t> &contain_var) const override;
@ -1281,6 +1288,10 @@ protected:
void writeExternalFunctionArguments(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const; void writeExternalFunctionArguments(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
void writeJsonASTExternalFunctionArguments(ostream &output) const; void writeJsonASTExternalFunctionArguments(ostream &output) const;
void writeJsonExternalFunctionArguments(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const; void writeJsonExternalFunctionArguments(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const;
int writeBytecodeExternalFunctionArguments(BytecodeWriter &code_file,
bool lhs_rhs, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
const deriv_node_temp_terms_t &tef_terms) const;
/*! Returns a predicate that tests whether an other ExprNode is an external /*! Returns a predicate that tests whether an other ExprNode is an external
function which is computed by the same external function call (i.e. it has function which is computed by the same external function call (i.e. it has
the same so-called "Tef" index) */ the same so-called "Tef" index) */
@ -1307,19 +1318,14 @@ 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 = true) const override = 0; bool isdynamic = true) const override = 0;
void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, void writeBytecodeExternalFunctionOutput(BytecodeWriter &code_file,
bool lhs_rhs, const temporary_terms_t &temporary_terms, bool lhs_rhs, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
deriv_node_temp_terms_t &tef_terms) const override = 0; deriv_node_temp_terms_t &tef_terms) const override = 0;
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;
double eval(const eval_context_t &eval_context) const noexcept(false) override; double eval(const eval_context_t &eval_context) const noexcept(false) override;
int compileExternalFunctionArguments(ostream &CompileCode, unsigned int &instruction_number, void writeBytecodeOutput(BytecodeWriter &code_file, bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override = 0;
bool lhs_rhs, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
const deriv_node_temp_terms_t &tef_terms) const;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override = 0;
expr_t toStatic(DataTree &static_datatree) const override = 0; expr_t toStatic(DataTree &static_datatree) const override = 0;
void computeXrefs(EquationInfo &ei) const override = 0; void computeXrefs(EquationInfo &ei) const override = 0;
void computeSubExprContainingVariable(int symb_id, int lag, set<expr_t> &contain_var) const override; void computeSubExprContainingVariable(int symb_id, int lag, set<expr_t> &contain_var) const override;
@ -1393,11 +1399,11 @@ 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 compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, void writeBytecodeExternalFunctionOutput(BytecodeWriter &code_file,
bool lhs_rhs, const temporary_terms_t &temporary_terms, bool lhs_rhs, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
deriv_node_temp_terms_t &tef_terms) const override; deriv_node_temp_terms_t &tef_terms) const override;
void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override; void writeBytecodeOutput(BytecodeWriter &code_file, bool lhs_rhs, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const deriv_node_temp_terms_t &tef_terms) const override;
expr_t toStatic(DataTree &static_datatree) const override; expr_t toStatic(DataTree &static_datatree) const override;
void computeXrefs(EquationInfo &ei) const override; void computeXrefs(EquationInfo &ei) const override;
expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const override; expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const override;
@ -1420,10 +1426,10 @@ public:
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override; void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeJsonAST(ostream &output) const override; void writeJsonAST(ostream &output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override; void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override;
void compile(ostream &CompileCode, unsigned int &instruction_number, void writeBytecodeOutput(BytecodeWriter &code_file,
bool lhs_rhs, const temporary_terms_t &temporary_terms, bool lhs_rhs, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
const deriv_node_temp_terms_t &tef_terms) const override; const deriv_node_temp_terms_t &tef_terms) const override;
void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type, void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType 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,
@ -1432,10 +1438,10 @@ 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 compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, void writeBytecodeExternalFunctionOutput(BytecodeWriter &code_file,
bool lhs_rhs, const temporary_terms_t &temporary_terms, bool lhs_rhs, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
deriv_node_temp_terms_t &tef_terms) const override; deriv_node_temp_terms_t &tef_terms) const override;
expr_t toStatic(DataTree &static_datatree) const override; expr_t toStatic(DataTree &static_datatree) const override;
void computeXrefs(EquationInfo &ei) const override; void computeXrefs(EquationInfo &ei) const override;
expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const override; expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const override;
@ -1460,10 +1466,10 @@ public:
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override; void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
void writeJsonAST(ostream &output) const override; void writeJsonAST(ostream &output) const override;
void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override; void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override;
void compile(ostream &CompileCode, unsigned int &instruction_number, void writeBytecodeOutput(BytecodeWriter &code_file,
bool lhs_rhs, const temporary_terms_t &temporary_terms, bool lhs_rhs, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
const deriv_node_temp_terms_t &tef_terms) const override; const deriv_node_temp_terms_t &tef_terms) const override;
void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type, void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType 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,
@ -1472,10 +1478,10 @@ 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 compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number, void writeBytecodeExternalFunctionOutput(BytecodeWriter &code_file,
bool lhs_rhs, const temporary_terms_t &temporary_terms, bool lhs_rhs, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
deriv_node_temp_terms_t &tef_terms) const override; deriv_node_temp_terms_t &tef_terms) const override;
expr_t toStatic(DataTree &static_datatree) const override; expr_t toStatic(DataTree &static_datatree) const override;
void computeXrefs(EquationInfo &ei) const override; void computeXrefs(EquationInfo &ei) const override;
expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const override; expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const override;
@ -1528,10 +1534,10 @@ public:
expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override; expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
void computeSubExprContainingVariable(int symb_id, int lag, set<expr_t> &contain_var) const override; void computeSubExprContainingVariable(int symb_id, int lag, set<expr_t> &contain_var) 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 compile(ostream &CompileCode, unsigned int &instruction_number, void writeBytecodeOutput(BytecodeWriter &code_file,
bool lhs_rhs, const temporary_terms_t &temporary_terms, bool lhs_rhs, const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic, const temporary_terms_idxs_t &temporary_terms_idxs, bool dynamic, bool steady_dynamic,
const deriv_node_temp_terms_t &tef_terms) const override; const deriv_node_temp_terms_t &tef_terms) const override;
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;
bool isNumConstNodeEqualTo(double value) const override; bool isNumConstNodeEqualTo(double value) const override;

View File

@ -46,6 +46,7 @@ dynare_preprocessor_SOURCES = \
VariableDependencyGraph.hh \ VariableDependencyGraph.hh \
DynareMain.cc \ DynareMain.cc \
MacroExpandModFile.cc \ MacroExpandModFile.cc \
Bytecode.cc \
Bytecode.hh \ Bytecode.hh \
ExternalFunctionsTable.cc \ ExternalFunctionsTable.cc \
ExternalFunctionsTable.hh \ ExternalFunctionsTable.hh \

View File

@ -19,7 +19,6 @@
#include "ModelTree.hh" #include "ModelTree.hh"
#include "VariableDependencyGraph.hh" #include "VariableDependencyGraph.hh"
#include "Bytecode.hh"
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wold-style-cast"
@ -1256,27 +1255,20 @@ ModelTree::testNestedParenthesis(const string &str) const
} }
void void
ModelTree::compileTemporaryTerms(ostream &code_file, unsigned int &instruction_number, bool dynamic, bool steady_dynamic, temporary_terms_t &temporary_terms_union, const temporary_terms_idxs_t &temporary_terms_idxs, deriv_node_temp_terms_t &tef_terms) const ModelTree::writeBytecodeTemporaryTerms(BytecodeWriter &code_file, bool dynamic, bool steady_dynamic, temporary_terms_t &temporary_terms_union, const temporary_terms_idxs_t &temporary_terms_idxs, deriv_node_temp_terms_t &tef_terms) const
{ {
// To store the functions that have already been written in the form TEF* = ext_fun(); // To store the functions that have already been written in the form TEF* = ext_fun();
for (auto [tt, idx] : temporary_terms_idxs) for (auto [tt, idx] : temporary_terms_idxs)
{ {
if (dynamic_cast<AbstractExternalFunctionNode *>(tt)) if (dynamic_cast<AbstractExternalFunctionNode *>(tt))
tt->compileExternalFunctionOutput(code_file, instruction_number, false, temporary_terms_union, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms); tt->writeBytecodeExternalFunctionOutput(code_file, false, temporary_terms_union, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
FNUMEXPR_ fnumexpr(ExpressionType::TemporaryTerm, idx); code_file << FNUMEXPR_{ExpressionType::TemporaryTerm, idx};
fnumexpr.write(code_file, instruction_number); tt->writeBytecodeOutput(code_file, false, temporary_terms_union, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
tt->compile(code_file, instruction_number, false, temporary_terms_union, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
if (dynamic) if (dynamic)
{ code_file << FSTPT_{idx};
FSTPT_ fstpt(idx);
fstpt.write(code_file, instruction_number);
}
else else
{ code_file << FSTPST_{idx};
FSTPST_ fstpst(idx);
fstpst.write(code_file, instruction_number);
}
} }
} }
@ -1392,15 +1384,14 @@ ModelTree::writeModelEquations(ostream &output, ExprNodeOutputType output_type,
} }
void void
ModelTree::compileModelEquations(ostream &code_file, unsigned int &instruction_number, bool dynamic, bool steady_dynamic, const temporary_terms_t &temporary_terms_union, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const ModelTree::writeBytecodeModelEquations(BytecodeWriter &code_file, bool dynamic, bool steady_dynamic, const temporary_terms_t &temporary_terms_union, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const
{ {
for (int eq = 0; eq < static_cast<int>(equations.size()); eq++) for (int eq = 0; eq < static_cast<int>(equations.size()); eq++)
{ {
BinaryOpNode *eq_node = equations[eq]; BinaryOpNode *eq_node = equations[eq];
expr_t lhs = eq_node->arg1; expr_t lhs = eq_node->arg1;
expr_t rhs = eq_node->arg2; expr_t rhs = eq_node->arg2;
FNUMEXPR_ fnumexpr(ExpressionType::ModelEquation, eq); code_file << FNUMEXPR_{ExpressionType::ModelEquation, eq};
fnumexpr.write(code_file, instruction_number);
// 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
@ -1413,20 +1404,15 @@ ModelTree::compileModelEquations(ostream &code_file, unsigned int &instruction_n
if (vrhs != 0) // The right hand side of the equation is not empty ==> residual=lhs-rhs; if (vrhs != 0) // The right hand side of the equation is not empty ==> residual=lhs-rhs;
{ {
lhs->compile(code_file, instruction_number, false, temporary_terms_union, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms); lhs->writeBytecodeOutput(code_file, false, temporary_terms_union, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
rhs->compile(code_file, instruction_number, false, temporary_terms_union, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms); rhs->writeBytecodeOutput(code_file, false, temporary_terms_union, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
FBINARY_ fbinary{BinaryOpcode::minus}; code_file << FBINARY_{BinaryOpcode::minus} << FSTPR_{eq};
fbinary.write(code_file, instruction_number);
FSTPR_ fstpr(eq);
fstpr.write(code_file, instruction_number);
} }
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->compile(code_file, instruction_number, false, temporary_terms_union, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms); lhs->writeBytecodeOutput(code_file, false, temporary_terms_union, temporary_terms_idxs, dynamic, steady_dynamic, tef_terms);
FSTPR_ fstpr(eq); code_file << FSTPR_{eq};
fstpr.write(code_file, instruction_number);
} }
} }
} }

View File

@ -32,6 +32,7 @@
#include "DataTree.hh" #include "DataTree.hh"
#include "EquationTags.hh" #include "EquationTags.hh"
#include "ExtendedPreprocessorTypes.hh" #include "ExtendedPreprocessorTypes.hh"
#include "Bytecode.hh"
using namespace std; using namespace std;
@ -236,8 +237,8 @@ protected:
//! Writes temporary terms //! Writes temporary terms
void writeTemporaryTerms(const temporary_terms_t &tt, temporary_terms_t &temp_term_union, const temporary_terms_idxs_t &tt_idxs, ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const; void writeTemporaryTerms(const temporary_terms_t &tt, temporary_terms_t &temp_term_union, const temporary_terms_idxs_t &tt_idxs, ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const;
void writeJsonTemporaryTerms(const temporary_terms_t &tt, temporary_terms_t &temp_term_union, ostream &output, deriv_node_temp_terms_t &tef_terms, const string &concat) const; void writeJsonTemporaryTerms(const temporary_terms_t &tt, temporary_terms_t &temp_term_union, ostream &output, deriv_node_temp_terms_t &tef_terms, const string &concat) const;
//! Compiles temporary terms //! Writes temporary terms in bytecode
void compileTemporaryTerms(ostream &code_file, unsigned int &instruction_number, bool dynamic, bool steady_dynamic, temporary_terms_t &temporary_terms_union, const temporary_terms_idxs_t &temporary_terms_idxs, deriv_node_temp_terms_t &tef_terms) const; void writeBytecodeTemporaryTerms(BytecodeWriter &code_file, bool dynamic, bool steady_dynamic, temporary_terms_t &temporary_terms_union, const temporary_terms_idxs_t &temporary_terms_idxs, deriv_node_temp_terms_t &tef_terms) const;
//! Adds information for (non-block) bytecode simulation in a separate .bin file //! Adds information for (non-block) bytecode simulation in a separate .bin file
void writeBytecodeBinFile(const string &filename, int &u_count_int, bool &file_open, bool is_two_boundaries) const; void writeBytecodeBinFile(const string &filename, int &u_count_int, bool &file_open, bool is_two_boundaries) const;
//! Fixes output when there are more than 32 nested parens, Issue #1201 //! Fixes output when there are more than 32 nested parens, Issue #1201
@ -259,8 +260,8 @@ protected:
/* Writes JSON model local variables. /* Writes JSON model local variables.
Optionally put the external function variable calls into TEF terms */ Optionally put the external function variable calls into TEF terms */
void writeJsonModelLocalVariables(ostream &output, bool write_tef_terms, deriv_node_temp_terms_t &tef_terms) const; void writeJsonModelLocalVariables(ostream &output, bool write_tef_terms, deriv_node_temp_terms_t &tef_terms) const;
//! Compiles model equations //! Writes model equations in bytecode
void compileModelEquations(ostream &code_file, unsigned int &instruction_number, bool dynamic, bool steady_dynamic, const temporary_terms_t &temporary_terms_union, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const; void writeBytecodeModelEquations(BytecodeWriter &code_file, bool dynamic, bool steady_dynamic, const temporary_terms_t &temporary_terms_union, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
//! Writes LaTeX model file //! Writes LaTeX model file
void writeLatexModelFile(const string &mod_basename, const string &latex_basename, ExprNodeOutputType output_type, bool write_equation_tags) const; void writeLatexModelFile(const string &mod_basename, const string &latex_basename, ExprNodeOutputType output_type, bool write_equation_tags) const;

View File

@ -26,7 +26,6 @@
#include "StaticModel.hh" #include "StaticModel.hh"
#include "DynamicModel.hh" #include "DynamicModel.hh"
#include "Bytecode.hh"
void void
StaticModel::copyHelper(const StaticModel &m) StaticModel::copyHelper(const StaticModel &m)
@ -104,29 +103,23 @@ StaticModel::StaticModel(const DynamicModel &m) :
} }
void void
StaticModel::compileDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int symb_id, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const StaticModel::writeBytecodeDerivative(BytecodeWriter &code_file, int eq, int symb_id, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const
{ {
if (auto it = derivatives[1].find({ eq, getDerivID(symbol_table.getID(SymbolType::endogenous, symb_id), 0) }); if (auto it = derivatives[1].find({ eq, getDerivID(symbol_table.getID(SymbolType::endogenous, symb_id), 0) });
it != derivatives[1].end()) it != derivatives[1].end())
it->second->compile(code_file, instruction_number, false, temporary_terms, temporary_terms_idxs, false, false, tef_terms); it->second->writeBytecodeOutput(code_file, false, temporary_terms, temporary_terms_idxs, false, false, tef_terms);
else else
{ code_file << FLDZ_{};
FLDZ_ fldz;
fldz.write(code_file, instruction_number);
}
} }
void void
StaticModel::compileChainRuleDerivative(ofstream &code_file, unsigned int &instruction_number, int blk, int eq, int var, int lag, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const StaticModel::writeBytecodeChainRuleDerivative(BytecodeWriter &code_file, int blk, int eq, int var, int lag, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const
{ {
if (auto it = blocks_derivatives[blk].find({ eq, var, lag }); if (auto it = blocks_derivatives[blk].find({ eq, var, lag });
it != blocks_derivatives[blk].end()) it != blocks_derivatives[blk].end())
it->second->compile(code_file, instruction_number, false, temporary_terms, temporary_terms_idxs, false, false, tef_terms); it->second->writeBytecodeOutput(code_file, false, temporary_terms, temporary_terms_idxs, false, false, tef_terms);
else else
{ code_file << FLDZ_{};
FLDZ_ fldz;
fldz.write(code_file, instruction_number);
}
} }
void void
@ -381,17 +374,9 @@ void
StaticModel::writeStaticBytecode(const string &basename) const StaticModel::writeStaticBytecode(const string &basename) const
{ {
ostringstream tmp_output; ostringstream tmp_output;
ofstream code_file;
unsigned int instruction_number = 0;
bool file_open = false; bool file_open = false;
string main_name = basename + "/model/bytecode/static.cod"; BytecodeWriter code_file{basename + "/model/bytecode/static.cod"};
code_file.open(main_name, ios::out | ios::binary | ios::ate);
if (!code_file.is_open())
{
cerr << R"(Error : Can't open file ")" << main_name << R"(" for writing)" << endl;
exit(EXIT_FAILURE);
}
int count_u; int count_u;
int u_count_int = 0; int u_count_int = 0;
@ -403,37 +388,32 @@ StaticModel::writeStaticBytecode(const string &basename) const
temporary_terms.insert(temporary_terms_derivatives[1].begin(), temporary_terms_derivatives[1].end()); temporary_terms.insert(temporary_terms_derivatives[1].begin(), temporary_terms_derivatives[1].end());
//Temporary variables declaration //Temporary variables declaration
FDIMST_ fdimst{static_cast<int>(temporary_terms.size())}; code_file << FDIMST_{static_cast<int>(temporary_terms.size())}
fdimst.write(code_file, instruction_number); << FBEGINBLOCK_{symbol_table.endo_nbr(),
FBEGINBLOCK_ fbeginblock(symbol_table.endo_nbr(), BlockSimulationType::solveForwardComplete,
BlockSimulationType::solveForwardComplete, 0,
0, symbol_table.endo_nbr(),
symbol_table.endo_nbr(), endo_idx_block2orig,
endo_idx_block2orig, eq_idx_block2orig,
eq_idx_block2orig, false,
false, symbol_table.endo_nbr(),
symbol_table.endo_nbr(), 0,
0, 0,
0, u_count_int,
u_count_int, symbol_table.endo_nbr()};
symbol_table.endo_nbr());
fbeginblock.write(code_file, instruction_number);
temporary_terms_t temporary_terms_union; temporary_terms_t temporary_terms_union;
deriv_node_temp_terms_t tef_terms; deriv_node_temp_terms_t tef_terms;
compileTemporaryTerms(code_file, instruction_number, false, false, temporary_terms_union, temporary_terms_idxs, tef_terms); writeBytecodeTemporaryTerms(code_file, false, false, temporary_terms_union, temporary_terms_idxs, tef_terms);
compileModelEquations(code_file, instruction_number, false, false, temporary_terms_union, temporary_terms_idxs, tef_terms); writeBytecodeModelEquations(code_file, false, false, temporary_terms_union, temporary_terms_idxs, tef_terms);
FENDEQU_ fendequ; code_file << FENDEQU_{};
fendequ.write(code_file, instruction_number);
// Get the current code_file position and jump if eval = true // Get the current code_file position and jump if evaluating
streampos pos1 = code_file.tellp(); int pos_jmpifeval = code_file.getInstructionCounter();
FJMPIFEVAL_ fjmp_if_eval(0); code_file << FJMPIFEVAL_{0}; // Use 0 as jump offset for the time being
fjmp_if_eval.write(code_file, instruction_number);
int prev_instruction_number = instruction_number;
vector<vector<pair<int, int>>> my_derivatives(symbol_table.endo_nbr()); vector<vector<pair<int, int>>> my_derivatives(symbol_table.endo_nbr());
count_u = symbol_table.endo_nbr(); count_u = symbol_table.endo_nbr();
@ -445,57 +425,41 @@ StaticModel::writeStaticBytecode(const string &basename) const
int eq = indices[0]; int eq = indices[0];
int symb = getSymbIDByDerivID(deriv_id); int symb = getSymbIDByDerivID(deriv_id);
int var = symbol_table.getTypeSpecificID(symb); int var = symbol_table.getTypeSpecificID(symb);
FNUMEXPR_ fnumexpr(ExpressionType::FirstEndoDerivative, eq, var); code_file << FNUMEXPR_{ExpressionType::FirstEndoDerivative, eq, var};
fnumexpr.write(code_file, instruction_number);
if (!my_derivatives[eq].size()) if (!my_derivatives[eq].size())
my_derivatives[eq].clear(); my_derivatives[eq].clear();
my_derivatives[eq].emplace_back(var, count_u); my_derivatives[eq].emplace_back(var, count_u);
d1->compile(code_file, instruction_number, false, temporary_terms_union, temporary_terms_idxs, false, false, tef_terms); d1->writeBytecodeOutput(code_file, false, temporary_terms_union, temporary_terms_idxs, false, false, tef_terms);
FSTPSU_ fstpsu(count_u); code_file << FSTPSU_{count_u};
fstpsu.write(code_file, instruction_number);
count_u++; count_u++;
} }
} }
for (int i = 0; i < symbol_table.endo_nbr(); i++) for (int i = 0; i < symbol_table.endo_nbr(); i++)
{ {
FLDR_ fldr(i); code_file << FLDR_{i};
fldr.write(code_file, instruction_number);
if (my_derivatives[i].size()) if (my_derivatives[i].size())
{ {
for (bool printed_something{false}; for (bool printed_something{false};
const auto &it : my_derivatives[i]) const auto &it : my_derivatives[i])
{ {
FLDSU_ fldsu(it.second); code_file << FLDSU_{it.second}
fldsu.write(code_file, instruction_number); << FLDSV_{SymbolType::endogenous, it.first}
FLDSV_ fldsv{SymbolType::endogenous, it.first}; << FBINARY_{BinaryOpcode::times};
fldsv.write(code_file, instruction_number);
FBINARY_ fbinary{BinaryOpcode::times};
fbinary.write(code_file, instruction_number);
if (exchange(printed_something, true)) if (exchange(printed_something, true))
{ code_file << FBINARY_{BinaryOpcode::plus};
FBINARY_ fbinary{BinaryOpcode::plus};
fbinary.write(code_file, instruction_number);
}
} }
FBINARY_ fbinary{BinaryOpcode::minus}; code_file << FBINARY_{BinaryOpcode::minus};
fbinary.write(code_file, instruction_number);
} }
FSTPSU_ fstpsu(i); code_file << FSTPSU_{i};
fstpsu.write(code_file, instruction_number);
} }
// Get the current code_file position and jump = true
streampos pos2 = code_file.tellp(); // Jump unconditionally after the block
FJMP_ fjmp(0); int pos_jmp = code_file.getInstructionCounter();
fjmp.write(code_file, instruction_number); code_file << FJMP_{0}; // Use 0 as jump offset for the time being
// Set code_file position to previous JMPIFEVAL_ and set the number of instructions to jump // Update jump offset for previous JMPIFEVAL
streampos pos3 = code_file.tellp(); code_file.overwriteInstruction(pos_jmpifeval, FJMPIFEVAL_{pos_jmp-pos_jmpifeval});
code_file.seekp(pos1);
FJMPIFEVAL_ fjmp_if_eval1(instruction_number - prev_instruction_number);
fjmp_if_eval1.write(code_file, instruction_number);
code_file.seekp(pos3);
prev_instruction_number = instruction_number;
temporary_terms_t tt2, tt3; temporary_terms_t tt2, tt3;
@ -508,30 +472,21 @@ StaticModel::writeStaticBytecode(const string &basename) const
int eq = indices[0]; int eq = indices[0];
int symb = getSymbIDByDerivID(deriv_id); int symb = getSymbIDByDerivID(deriv_id);
int var = symbol_table.getTypeSpecificID(symb); int var = symbol_table.getTypeSpecificID(symb);
FNUMEXPR_ fnumexpr(ExpressionType::FirstEndoDerivative, eq, var); code_file << FNUMEXPR_{ExpressionType::FirstEndoDerivative, eq, var};
fnumexpr.write(code_file, instruction_number);
if (!my_derivatives[eq].size()) if (!my_derivatives[eq].size())
my_derivatives[eq].clear(); my_derivatives[eq].clear();
my_derivatives[eq].emplace_back(var, count_u); my_derivatives[eq].emplace_back(var, count_u);
d1->compile(code_file, instruction_number, false, temporary_terms_union, temporary_terms_idxs, false, false, tef_terms); d1->writeBytecodeOutput(code_file, false, temporary_terms_union, temporary_terms_idxs, false, false, tef_terms);
FSTPG2_ fstpg2(eq, var); code_file << FSTPG2_{eq, var};
fstpg2.write(code_file, instruction_number);
} }
} }
// Set codefile position to previous JMP_ and set the number of instructions to jump // Update jump offset for previous JMP
pos1 = code_file.tellp(); int pos_end_block = code_file.getInstructionCounter();
code_file.seekp(pos2); code_file.overwriteInstruction(pos_jmp, FJMP_{pos_end_block-pos_jmp-1});
FJMP_ fjmp1(instruction_number - prev_instruction_number);
fjmp1.write(code_file, instruction_number);
code_file.seekp(pos1);
FENDBLOCK_ fendblock; code_file << FENDBLOCK_{} << FEND_{};
fendblock.write(code_file, instruction_number);
FEND_ fend;
fend.write(code_file, instruction_number);
code_file.close();
} }
void void
@ -551,8 +506,6 @@ StaticModel::writeStaticBlockBytecode(const string &basename) const
int i, v; int i, v;
string tmp_s; string tmp_s;
ostringstream tmp_output; ostringstream tmp_output;
ofstream code_file;
unsigned int instruction_number = 0;
expr_t lhs = nullptr, rhs = nullptr; expr_t lhs = nullptr, rhs = nullptr;
BinaryOpNode *eq_node; BinaryOpNode *eq_node;
Uff Uf[symbol_table.endo_nbr()]; Uff Uf[symbol_table.endo_nbr()];
@ -560,17 +513,10 @@ StaticModel::writeStaticBlockBytecode(const string &basename) const
vector<int> feedback_variables; vector<int> feedback_variables;
bool file_open = false; bool file_open = false;
string main_name = basename + "/model/bytecode/static.cod"; BytecodeWriter code_file{basename + "/model/bytecode/static.cod"};
code_file.open(main_name, ios::out | ios::binary | ios::ate);
if (!code_file.is_open())
{
cerr << R"(Error : Can't open file ")" << main_name << R"(" for writing)" << endl;
exit(EXIT_FAILURE);
}
//Temporary variables declaration
FDIMST_ fdimst{static_cast<int>(blocks_temporary_terms_idxs.size())}; //Temporary variables declaration
fdimst.write(code_file, instruction_number); code_file << FDIMST_{static_cast<int>(blocks_temporary_terms_idxs.size())};
temporary_terms_t temporary_terms_union; temporary_terms_t temporary_terms_union;
@ -578,10 +524,7 @@ StaticModel::writeStaticBlockBytecode(const string &basename) const
{ {
feedback_variables.clear(); feedback_variables.clear();
if (block > 0) if (block > 0)
{ code_file << FENDBLOCK_{};
FENDBLOCK_ fendblock;
fendblock.write(code_file, instruction_number);
}
int count_u; int count_u;
int u_count_int = 0; int u_count_int = 0;
BlockSimulationType simulation_type = blocks[block].simulation_type; BlockSimulationType simulation_type = blocks[block].simulation_type;
@ -598,26 +541,22 @@ StaticModel::writeStaticBlockBytecode(const string &basename) const
file_open = true; file_open = true;
} }
FBEGINBLOCK_ fbeginblock(block_mfs, code_file << FBEGINBLOCK_{block_mfs,
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,
symbol_table.endo_nbr(), symbol_table.endo_nbr(),
0, 0,
0, 0,
u_count_int, u_count_int,
block_size); block_size};
fbeginblock.write(code_file, instruction_number); // Get the current code_file position and jump if evaluating
int pos_jmpifeval = code_file.getInstructionCounter();
// Get the current code_file position and jump if eval = true code_file << FJMPIFEVAL_{0}; // Use 0 as jump offset for the time being
streampos pos1 = code_file.tellp();
FJMPIFEVAL_ fjmp_if_eval(0);
fjmp_if_eval.write(code_file, instruction_number);
int prev_instruction_number = instruction_number;
//The Temporary terms //The Temporary terms
deriv_node_temp_terms_t tef_terms; deriv_node_temp_terms_t tef_terms;
@ -630,13 +569,11 @@ StaticModel::writeStaticBlockBytecode(const string &basename) const
for (auto it : blocks_temporary_terms[block][eq]) for (auto it : blocks_temporary_terms[block][eq])
{ {
if (dynamic_cast<AbstractExternalFunctionNode *>(it)) if (dynamic_cast<AbstractExternalFunctionNode *>(it))
it->compileExternalFunctionOutput(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms); it->writeBytecodeExternalFunctionOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms);
FNUMEXPR_ fnumexpr{ExpressionType::TemporaryTerm, blocks_temporary_terms_idxs.at(it)}; code_file << FNUMEXPR_{ExpressionType::TemporaryTerm, blocks_temporary_terms_idxs.at(it)};
fnumexpr.write(code_file, instruction_number); it->writeBytecodeOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms);
it->compile(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms); code_file << FSTPST_{blocks_temporary_terms_idxs.at(it)};
FSTPST_ fstpst{blocks_temporary_terms_idxs.at(it)};
fstpst.write(code_file, instruction_number);
temporary_terms_union.insert(it); temporary_terms_union.insert(it);
} }
}; };
@ -654,25 +591,22 @@ StaticModel::writeStaticBlockBytecode(const string &basename) const
case BlockSimulationType::evaluateBackward: case BlockSimulationType::evaluateBackward:
case BlockSimulationType::evaluateForward: case BlockSimulationType::evaluateForward:
equ_type = getBlockEquationType(block, i); equ_type = getBlockEquationType(block, i);
{ code_file << FNUMEXPR_{ExpressionType::ModelEquation, getBlockEquationID(block, i)};
FNUMEXPR_ fnumexpr(ExpressionType::ModelEquation, getBlockEquationID(block, i));
fnumexpr.write(code_file, instruction_number);
}
if (equ_type == EquationType::evaluate) if (equ_type == EquationType::evaluate)
{ {
eq_node = getBlockEquationExpr(block, i); eq_node = getBlockEquationExpr(block, i);
lhs = eq_node->arg1; lhs = eq_node->arg1;
rhs = eq_node->arg2; rhs = eq_node->arg2;
rhs->compile(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms); rhs->writeBytecodeOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms);
lhs->compile(code_file, instruction_number, true, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms); lhs->writeBytecodeOutput(code_file, true, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms);
} }
else if (equ_type == EquationType::evaluateRenormalized) else if (equ_type == EquationType::evaluateRenormalized)
{ {
eq_node = getBlockEquationRenormalizedExpr(block, i); eq_node = getBlockEquationRenormalizedExpr(block, i);
lhs = eq_node->arg1; lhs = eq_node->arg1;
rhs = eq_node->arg2; rhs = eq_node->arg2;
rhs->compile(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms); rhs->writeBytecodeOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms);
lhs->compile(code_file, instruction_number, true, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms); lhs->writeBytecodeOutput(code_file, true, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms);
} }
break; break;
case BlockSimulationType::solveBackwardComplete: case BlockSimulationType::solveBackwardComplete:
@ -686,23 +620,17 @@ StaticModel::writeStaticBlockBytecode(const string &basename) const
goto end; goto end;
default: default:
end: end:
FNUMEXPR_ fnumexpr(ExpressionType::ModelEquation, getBlockEquationID(block, i)); code_file << FNUMEXPR_{ExpressionType::ModelEquation, getBlockEquationID(block, i)};
fnumexpr.write(code_file, instruction_number);
eq_node = getBlockEquationExpr(block, i); eq_node = getBlockEquationExpr(block, i);
lhs = eq_node->arg1; lhs = eq_node->arg1;
rhs = eq_node->arg2; rhs = eq_node->arg2;
lhs->compile(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms); lhs->writeBytecodeOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms);
rhs->compile(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms); rhs->writeBytecodeOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms);
FBINARY_ fbinary{BinaryOpcode::minus}; code_file << FBINARY_{BinaryOpcode::minus} << FSTPR_{i - block_recursive};
fbinary.write(code_file, instruction_number);
FSTPR_ fstpr(i - block_recursive);
fstpr.write(code_file, instruction_number);
} }
} }
FENDEQU_ fendequ; code_file << FENDEQU_{};
fendequ.write(code_file, instruction_number);
// The Jacobian if we have to solve the block // The Jacobian if we have to solve the block
if (simulation_type != BlockSimulationType::evaluateBackward if (simulation_type != BlockSimulationType::evaluateBackward
@ -715,15 +643,9 @@ StaticModel::writeStaticBlockBytecode(const string &basename) const
{ {
case BlockSimulationType::solveBackwardSimple: case BlockSimulationType::solveBackwardSimple:
case BlockSimulationType::solveForwardSimple: case BlockSimulationType::solveForwardSimple:
{ code_file << FNUMEXPR_{ExpressionType::FirstEndoDerivative, 0, 0};
FNUMEXPR_ fnumexpr(ExpressionType::FirstEndoDerivative, 0, 0); writeBytecodeDerivative(code_file, getBlockEquationID(block, 0), getBlockVariableID(block, 0), temporary_terms_union, blocks_temporary_terms_idxs, tef_terms);
fnumexpr.write(code_file, instruction_number); code_file << FSTPG_{0};
}
compileDerivative(code_file, instruction_number, getBlockEquationID(block, 0), getBlockVariableID(block, 0), temporary_terms_union, blocks_temporary_terms_idxs, tef_terms);
{
FSTPG_ fstpg(0);
fstpg.write(code_file, instruction_number);
}
break; break;
case BlockSimulationType::solveBackwardComplete: case BlockSimulationType::solveBackwardComplete:
@ -749,37 +671,23 @@ StaticModel::writeStaticBlockBytecode(const string &basename) const
Uf[eqr].Ufl->pNext = nullptr; Uf[eqr].Ufl->pNext = nullptr;
Uf[eqr].Ufl->u = count_u; Uf[eqr].Ufl->u = count_u;
Uf[eqr].Ufl->var = varr; Uf[eqr].Ufl->var = varr;
FNUMEXPR_ fnumexpr(ExpressionType::FirstEndoDerivative, eqr, varr); code_file << FNUMEXPR_{ExpressionType::FirstEndoDerivative, eqr, varr};
fnumexpr.write(code_file, instruction_number); writeBytecodeChainRuleDerivative(code_file, block, eq, var, 0, temporary_terms_union, blocks_temporary_terms_idxs, tef_terms);
compileChainRuleDerivative(code_file, instruction_number, block, eq, var, 0, temporary_terms_union, blocks_temporary_terms_idxs, tef_terms); code_file << FSTPSU_{count_u};
FSTPSU_ fstpsu(count_u);
fstpsu.write(code_file, instruction_number);
count_u++; count_u++;
} }
} }
for (i = 0; i < block_size; i++) for (i = 0; i < block_size; i++)
if (i >= block_recursive) if (i >= block_recursive)
{ {
FLDR_ fldr(i-block_recursive); code_file << FLDR_{i-block_recursive} << FLDZ_{};
fldr.write(code_file, instruction_number);
FLDZ_ fldz;
fldz.write(code_file, instruction_number);
v = getBlockEquationID(block, i); v = getBlockEquationID(block, i);
for (Uf[v].Ufl = Uf[v].Ufl_First; Uf[v].Ufl; Uf[v].Ufl = Uf[v].Ufl->pNext) for (Uf[v].Ufl = Uf[v].Ufl_First; Uf[v].Ufl; Uf[v].Ufl = Uf[v].Ufl->pNext)
{ code_file << FLDSU_{Uf[v].Ufl->u}
FLDSU_ fldsu(Uf[v].Ufl->u); << FLDSV_{SymbolType::endogenous, Uf[v].Ufl->var}
fldsu.write(code_file, instruction_number); << FBINARY_{BinaryOpcode::times}
FLDSV_ fldsv{SymbolType::endogenous, Uf[v].Ufl->var}; << FCUML_{};
fldsv.write(code_file, instruction_number);
FBINARY_ fbinary{BinaryOpcode::times};
fbinary.write(code_file, instruction_number);
FCUML_ fcuml;
fcuml.write(code_file, instruction_number);
}
Uf[v].Ufl = Uf[v].Ufl_First; Uf[v].Ufl = Uf[v].Ufl_First;
while (Uf[v].Ufl) while (Uf[v].Ufl)
{ {
@ -787,12 +695,8 @@ StaticModel::writeStaticBlockBytecode(const string &basename) const
free(Uf[v].Ufl); free(Uf[v].Ufl);
Uf[v].Ufl = Uf[v].Ufl_First; Uf[v].Ufl = Uf[v].Ufl_First;
} }
FBINARY_ fbinary{BinaryOpcode::minus}; code_file << FBINARY_{BinaryOpcode::minus}
fbinary.write(code_file, instruction_number); << FSTPSU_{i - block_recursive};
FSTPSU_ fstpsu(i - block_recursive);
fstpsu.write(code_file, instruction_number);
} }
break; break;
default: default:
@ -800,17 +704,11 @@ StaticModel::writeStaticBlockBytecode(const string &basename) const
} }
} }
// Get the current code_file position and jump = true // Jump unconditionally after the block
streampos pos2 = code_file.tellp(); int pos_jmp = code_file.getInstructionCounter();
FJMP_ fjmp(0); code_file << FJMP_{0}; // Use 0 as jump offset for the time being
fjmp.write(code_file, instruction_number); // Update jump offset for previous JMPIFEVAL
// Set code_file position to previous JMPIFEVAL_ and set the number of instructions to jump code_file.overwriteInstruction(pos_jmpifeval, FJMPIFEVAL_{pos_jmp-pos_jmpifeval});
streampos pos3 = code_file.tellp();
code_file.seekp(pos1);
FJMPIFEVAL_ fjmp_if_eval1(instruction_number - prev_instruction_number);
fjmp_if_eval1.write(code_file, instruction_number);
code_file.seekp(pos3);
prev_instruction_number = instruction_number;
tef_terms.clear(); tef_terms.clear();
temporary_terms_union = ttu_old; temporary_terms_union = ttu_old;
@ -828,25 +726,22 @@ StaticModel::writeStaticBlockBytecode(const string &basename) const
case BlockSimulationType::evaluateBackward: case BlockSimulationType::evaluateBackward:
case BlockSimulationType::evaluateForward: case BlockSimulationType::evaluateForward:
equ_type = getBlockEquationType(block, i); equ_type = getBlockEquationType(block, i);
{ code_file << FNUMEXPR_{ExpressionType::ModelEquation, getBlockEquationID(block, i)};
FNUMEXPR_ fnumexpr(ExpressionType::ModelEquation, getBlockEquationID(block, i));
fnumexpr.write(code_file, instruction_number);
}
if (equ_type == EquationType::evaluate) if (equ_type == EquationType::evaluate)
{ {
eq_node = getBlockEquationExpr(block, i); eq_node = getBlockEquationExpr(block, i);
lhs = eq_node->arg1; lhs = eq_node->arg1;
rhs = eq_node->arg2; rhs = eq_node->arg2;
rhs->compile(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms); rhs->writeBytecodeOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms);
lhs->compile(code_file, instruction_number, true, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms); lhs->writeBytecodeOutput(code_file, true, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms);
} }
else if (equ_type == EquationType::evaluateRenormalized) else if (equ_type == EquationType::evaluateRenormalized)
{ {
eq_node = getBlockEquationRenormalizedExpr(block, i); eq_node = getBlockEquationRenormalizedExpr(block, i);
lhs = eq_node->arg1; lhs = eq_node->arg1;
rhs = eq_node->arg2; rhs = eq_node->arg2;
rhs->compile(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms); rhs->writeBytecodeOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms);
lhs->compile(code_file, instruction_number, true, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms); lhs->writeBytecodeOutput(code_file, true, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms);
} }
break; break;
case BlockSimulationType::solveBackwardComplete: case BlockSimulationType::solveBackwardComplete:
@ -860,23 +755,17 @@ StaticModel::writeStaticBlockBytecode(const string &basename) const
goto end_l; goto end_l;
default: default:
end_l: end_l:
FNUMEXPR_ fnumexpr(ExpressionType::ModelEquation, getBlockEquationID(block, i)); code_file << FNUMEXPR_{ExpressionType::ModelEquation, getBlockEquationID(block, i)};
fnumexpr.write(code_file, instruction_number);
eq_node = getBlockEquationExpr(block, i); eq_node = getBlockEquationExpr(block, i);
lhs = eq_node->arg1; lhs = eq_node->arg1;
rhs = eq_node->arg2; rhs = eq_node->arg2;
lhs->compile(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms); lhs->writeBytecodeOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms);
rhs->compile(code_file, instruction_number, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms); rhs->writeBytecodeOutput(code_file, false, temporary_terms_union, blocks_temporary_terms_idxs, false, false, tef_terms);
FBINARY_ fbinary{BinaryOpcode::minus}; code_file << FBINARY_{BinaryOpcode::minus} << FSTPR_{i - block_recursive};
fbinary.write(code_file, instruction_number);
FSTPR_ fstpr(i - block_recursive);
fstpr.write(code_file, instruction_number);
} }
} }
FENDEQU_ fendequ_l; code_file << FENDEQU_{};
fendequ_l.write(code_file, instruction_number);
// The Jacobian if we have to solve the block determinsitic bloc // The Jacobian if we have to solve the block determinsitic bloc
@ -887,15 +776,9 @@ StaticModel::writeStaticBlockBytecode(const string &basename) const
{ {
case BlockSimulationType::solveBackwardSimple: case BlockSimulationType::solveBackwardSimple:
case BlockSimulationType::solveForwardSimple: case BlockSimulationType::solveForwardSimple:
{ code_file << FNUMEXPR_{ExpressionType::FirstEndoDerivative, 0, 0};
FNUMEXPR_ fnumexpr(ExpressionType::FirstEndoDerivative, 0, 0); writeBytecodeDerivative(code_file, getBlockEquationID(block, 0), getBlockVariableID(block, 0), temporary_terms_union, blocks_temporary_terms_idxs, tef_terms);
fnumexpr.write(code_file, instruction_number); code_file << FSTPG2_{0, 0};
}
compileDerivative(code_file, instruction_number, getBlockEquationID(block, 0), getBlockVariableID(block, 0), temporary_terms_union, blocks_temporary_terms_idxs, tef_terms);
{
FSTPG2_ fstpg2(0, 0);
fstpg2.write(code_file, instruction_number);
}
break; break;
case BlockSimulationType::evaluateBackward: case BlockSimulationType::evaluateBackward:
case BlockSimulationType::evaluateForward: case BlockSimulationType::evaluateForward:
@ -907,30 +790,20 @@ StaticModel::writeStaticBlockBytecode(const string &basename) const
auto &[eq, var, ignore] = indices; auto &[eq, var, ignore] = indices;
int eqr = getBlockEquationID(block, eq); int eqr = getBlockEquationID(block, eq);
int varr = getBlockVariableID(block, var); int varr = getBlockVariableID(block, var);
FNUMEXPR_ fnumexpr(ExpressionType::FirstEndoDerivative, eqr, varr, 0); code_file << FNUMEXPR_{ExpressionType::FirstEndoDerivative, eqr, varr, 0};
fnumexpr.write(code_file, instruction_number); writeBytecodeChainRuleDerivative(code_file, block, eq, var, 0, temporary_terms_union, blocks_temporary_terms_idxs, tef_terms);
code_file << FSTPG2_{eq, var};
compileChainRuleDerivative(code_file, instruction_number, block, eq, var, 0, temporary_terms_union, blocks_temporary_terms_idxs, tef_terms);
FSTPG2_ fstpg2(eq, var);
fstpg2.write(code_file, instruction_number);
} }
break; break;
default: default:
break; break;
} }
// Set codefile position to previous JMP_ and set the number of instructions to jump // Set codefile position to previous JMP_ and set the number of instructions to jump
pos1 = code_file.tellp(); // Update jump offset for previous JMP
code_file.seekp(pos2); int pos_end_block = code_file.getInstructionCounter();
FJMP_ fjmp1(instruction_number - prev_instruction_number); code_file.overwriteInstruction(pos_jmp, FJMP_{pos_end_block-pos_jmp-1});
fjmp1.write(code_file, instruction_number);
code_file.seekp(pos1);
} }
FENDBLOCK_ fendblock; code_file << FENDBLOCK_{} << FEND_{};
fendblock.write(code_file, instruction_number);
FEND_ fend;
fend.write(code_file, instruction_number);
code_file.close();
} }
void void

View File

@ -24,6 +24,7 @@
#include <filesystem> #include <filesystem>
#include "ModelTree.hh" #include "ModelTree.hh"
#include "Bytecode.hh"
using namespace std; using namespace std;
@ -77,10 +78,10 @@ private:
*/ */
void evaluateJacobian(const eval_context_t &eval_context, jacob_map_t *j_m, bool dynamic); void evaluateJacobian(const eval_context_t &eval_context, jacob_map_t *j_m, bool dynamic);
//! Write derivative code of an equation w.r. to a variable //! Write derivative bytecode of an equation w.r. to a variable
void compileDerivative(ofstream &code_file, unsigned int &instruction_number, int eq, int symb_id, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const; void writeBytecodeDerivative(BytecodeWriter &code_file, int eq, int symb_id, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
//! Write chain rule derivative code of an equation w.r. to a variable //! Write chain rule derivative bytecode of an equation w.r. to a variable
void compileChainRuleDerivative(ofstream &code_file, unsigned int &instruction_number, int blk, int eq, int var, int lag, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const; void writeBytecodeChainRuleDerivative(BytecodeWriter &code_file, int blk, int eq, int var, int lag, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
//! Get the type corresponding to a derivation ID //! Get the type corresponding to a derivation ID
SymbolType getTypeByDerivID(int deriv_id) const noexcept(false) override; SymbolType getTypeByDerivID(int deriv_id) const noexcept(false) override;