Commit f13b95cb authored by ferhat's avatar ferhat
Browse files

"bytecode" option can be used without "block" option

git-svn-id: https://www.dynare.org/svn/dynare/trunk@3373 ac1d8469-bf42-47a9-8791-bf33cf982152
parent e616667f
......@@ -82,6 +82,7 @@ enum Tags
FSTPR, //!< Loads a residual from the stack - 12
FSTPG, //!< Loads a derivative from the stack - 13
FSTPG2, //!< Loads a derivative matrix from the stack - 13
FUNARY, //!< A Unary operator - 14
FBINARY, //!< A binary operator - 15
......@@ -533,6 +534,28 @@ public:
};
};
class FSTPG2_ : public TagWithTwoArguments<unsigned int, unsigned int>
{
public:
inline FSTPG2_() : TagWithTwoArguments<unsigned int, unsigned int>::TagWithTwoArguments(FSTPG2, 0, 0)
{
};
inline FSTPG2_(const unsigned int pos_arg1, const unsigned int pos_arg2) : TagWithTwoArguments<unsigned int, unsigned int>::TagWithTwoArguments(FSTPG2, pos_arg1, pos_arg2)
{
};
inline unsigned int
get_row()
{
return arg1;
};
inline unsigned int
get_col()
{
return arg2;
};
};
class FUNARY_ : public TagWithOneArgument<uint8_t>
{
public:
......@@ -728,7 +751,7 @@ public:
op_code = FBEGINBLOCK; size = 0; type = UNKNOWN; /*variable = NULL; equation = NULL;*/
is_linear = false; endo_nbr = 0; Max_Lag = 0; Max_Lead = 0; u_count_int = 0;
};
inline FBEGINBLOCK_(unsigned int &size_arg, BlockSimulationType &type_arg, int unsigned first_element, int unsigned &block_size,
inline FBEGINBLOCK_(unsigned int size_arg, BlockSimulationType type_arg, int unsigned first_element, int unsigned block_size,
const vector<int> &variable_arg, const vector<int> &equation_arg,
bool is_linear_arg, int endo_nbr_arg, int Max_Lag_arg, int Max_Lead_arg, int &u_count_int_arg)
{
......
......@@ -878,7 +878,7 @@ PlannerObjectiveStatement::checkPass(ModFileStructure &mod_file_struct)
void
PlannerObjectiveStatement::computingPass()
{
model_tree->computingPass(eval_context_type(), false, true, false);
model_tree->computingPass(eval_context_type(), false, true, false, false);
}
void
......
......@@ -81,6 +81,18 @@ DynamicModel::compileChainRuleDerivative(ofstream &code_file, int eqr, int varr,
}
}
void
DynamicModel::initializeVariablesAndEquations()
{
for(int j=0; j<equation_number(); j++)
{
equation_reordered.push_back(j);
variable_reordered.push_back(j);
}
}
void
DynamicModel::computeTemporaryTermsOrdered()
{
......@@ -190,14 +202,21 @@ DynamicModel::computeTemporaryTermsOrdered()
it->second->collectTemporary_terms(temporary_terms, temporary_terms_in_use, block);
v_temporary_terms_inuse[block] = temporary_terms_in_use;
}
// Add a mapping form node ID to temporary terms order
int j = 0;
for (temporary_terms_type::const_iterator it = temporary_terms.begin();
it != temporary_terms.end(); it++)
map_idx[(*it)->idx] = j++;
computeTemporaryTermsMapping();
}
}
void
DynamicModel::computeTemporaryTermsMapping()
{
// Add a mapping form node ID to temporary terms order
int j = 0;
for (temporary_terms_type::const_iterator it = temporary_terms.begin();
it != temporary_terms.end(); it++)
map_idx[(*it)->idx] = j++;
}
void
DynamicModel::writeModelEquationsOrdered_M(const string &dynamic_basename) const
{
......@@ -710,7 +729,118 @@ DynamicModel::writeModelEquationsOrdered_M(const string &dynamic_basename) const
}
void
DynamicModel::writeModelEquationsCodeOrdered(const string file_name, const string bin_basename, map_idx_type map_idx) const
DynamicModel::writeModelEquationsCode(const string file_name, const string bin_basename, map_idx_type map_idx) const
{
ostringstream tmp_output;
ofstream code_file;
bool file_open = false;
string main_name = file_name;
main_name += ".cod";
code_file.open(main_name.c_str(), ios::out | ios::binary | ios::ate);
if (!code_file.is_open())
{
cout << "Error : Can't open file \"" << main_name << "\" for writing\n";
exit(EXIT_FAILURE);
}
int count_u;
int u_count_int = 0;
BlockSimulationType simulation_type;
if ((max_endo_lag > 0) && (max_endo_lead > 0))
simulation_type = SOLVE_TWO_BOUNDARIES_COMPLETE;
else if ((max_endo_lag >= 0) && (max_endo_lead == 0))
simulation_type = SOLVE_FORWARD_COMPLETE;
else
simulation_type = SOLVE_BACKWARD_COMPLETE;
Write_Inf_To_Bin_File(file_name, u_count_int, file_open, simulation_type == SOLVE_TWO_BOUNDARIES_COMPLETE, symbol_table.endo_nbr() );
file_open = true;
//Temporary variables declaration
FDIMT_ fdimt(temporary_terms.size());
fdimt.write(code_file);
FBEGINBLOCK_ fbeginblock(symbol_table.endo_nbr(),
simulation_type,
0,
symbol_table.endo_nbr(),
variable_reordered,
equation_reordered,
false,
symbol_table.endo_nbr(),
0,
0,
u_count_int
);
fbeginblock.write(code_file);
compileTemporaryTerms(code_file, temporary_terms, map_idx, true, false);
compileModelEquations(code_file, temporary_terms, map_idx, true, false);
FENDEQU_ fendequ;
fendequ.write(code_file);
vector<vector<pair<pair<int, int>, int > > > derivatives;
derivatives.resize(symbol_table.endo_nbr());
count_u = symbol_table.endo_nbr();
for (first_derivatives_type::const_iterator it = first_derivatives.begin();
it != first_derivatives.end(); it++)
{
int deriv_id = it->first.second;
if (getTypeByDerivID(deriv_id) == eEndogenous)
{
NodeID d1 = it->second;
unsigned int eq = it->first.first;
int symb = getSymbIDByDerivID(deriv_id);
unsigned int var = symbol_table.getTypeSpecificID(symb);
int lag = getLagByDerivID(deriv_id);
if (!derivatives[eq].size())
derivatives[eq].clear();
derivatives[eq].push_back(make_pair(make_pair(var, lag), count_u));
d1->compile(code_file, false, temporary_terms, map_idx, true, false);
FSTPU_ fstpu(count_u);
fstpu.write(code_file);
count_u++;
}
}
for (int i = 0; i < symbol_table.endo_nbr(); i++)
{
FLDR_ fldr(i);
fldr.write(code_file);
for(vector<pair<pair<int, int>, int> >::const_iterator it = derivatives[i].begin();
it != derivatives[i].end(); it++)
{
FLDU_ fldu(it->second);
fldu.write(code_file);
FLDV_ fldv(eEndogenous, it->first.first, it->first.second);
fldv.write(code_file);
FBINARY_ fbinary(oTimes);
fbinary.write(code_file);
if (it != derivatives[i].begin())
{
FBINARY_ fbinary(oPlus);
fbinary.write(code_file);
}
}
FBINARY_ fbinary(oMinus);
fbinary.write(code_file);
FSTPU_ fstpu(i);
fstpu.write(code_file);
}
FENDBLOCK_ fendblock;
fendblock.write(code_file);
FEND_ fend;
fend.write(code_file);
code_file.close();
}
void
DynamicModel::writeModelEquationsCode_Block(const string file_name, const string bin_basename, map_idx_type map_idx) const
{
struct Uff_l
{
......@@ -766,7 +896,7 @@ DynamicModel::writeModelEquationsCodeOrdered(const string file_name, const strin
if (simulation_type == SOLVE_TWO_BOUNDARIES_SIMPLE || simulation_type == SOLVE_TWO_BOUNDARIES_COMPLETE
|| simulation_type == SOLVE_BACKWARD_COMPLETE || simulation_type == SOLVE_FORWARD_COMPLETE)
{
Write_Inf_To_Bin_File(file_name, bin_basename, block, u_count_int, file_open,
Write_Inf_To_Bin_File_Block(file_name, bin_basename, block, u_count_int, file_open,
simulation_type == SOLVE_TWO_BOUNDARIES_COMPLETE || simulation_type == SOLVE_TWO_BOUNDARIES_SIMPLE);
file_open = true;
}
......@@ -1109,7 +1239,7 @@ DynamicModel::reform(const string name1) const
}
void
DynamicModel::Write_Inf_To_Bin_File(const string &dynamic_basename, const string &bin_basename, const int &num,
DynamicModel::Write_Inf_To_Bin_File_Block(const string &dynamic_basename, const string &bin_basename, const int &num,
int &u_count_int, bool &file_open, bool is_two_boundaries) const
{
int j;
......@@ -1940,7 +2070,7 @@ DynamicModel::collect_first_order_derivatives_endogenous()
void
DynamicModel::computingPass(bool jacobianExo, bool hessian, bool thirdDerivatives, bool paramsDerivatives,
const eval_context_type &eval_context, bool no_tmp_terms, bool block, bool use_dll)
const eval_context_type &eval_context, bool no_tmp_terms, bool block, bool use_dll, bool bytecode)
{
assert(jacobianExo || !(hessian || thirdDerivatives || paramsDerivatives));
......@@ -2025,7 +2155,11 @@ DynamicModel::computingPass(bool jacobianExo, bool hessian, bool thirdDerivative
}
else
if (!no_tmp_terms)
computeTemporaryTerms(!use_dll);
{
computeTemporaryTerms(!use_dll);
if (bytecode)
computeTemporaryTermsMapping();
}
}
map<pair<pair<int, pair<int, int> >, pair<int, int> >, int>
......@@ -2274,7 +2408,9 @@ DynamicModel::writeDynamicFile(const string &basename, bool block, bool bytecode
{
int r;
if (block && bytecode)
writeModelEquationsCodeOrdered(basename + "_dynamic", basename, map_idx);
writeModelEquationsCode_Block(basename + "_dynamic", basename, map_idx);
else if (!block && bytecode)
writeModelEquationsCode(basename + "_dynamic", basename, map_idx);
else if (block && !bytecode)
{
#ifdef _WIN32
......
......@@ -96,7 +96,10 @@ private:
//! Writes the Block reordred structure of the model in M output
void writeModelEquationsOrdered_M(const string &dynamic_basename) const;
//! Writes the code of the Block reordred structure of the model in virtual machine bytecode
void writeModelEquationsCodeOrdered(const string file_name, const string bin_basename, map_idx_type map_idx) const;
void writeModelEquationsCode_Block(const string file_name, const string bin_basename, map_idx_type map_idx) const;
//! Writes the code of the model in virtual machine bytecode
void writeModelEquationsCode(const string file_name, const string bin_basename, map_idx_type map_idx) const;
//! Computes jacobian and prepares for equation normalization
/*! Using values from initval/endval blocks and parameter initializations:
- computes the jacobian for the model w.r. to contemporaneous variables
......@@ -112,7 +115,11 @@ private:
string reform(string name) const;
map_idx_type map_idx;
//! sorts the temporary terms in the blocks order
void computeTemporaryTermsOrdered();
//! creates a mapping from the index of temporary terms to a natural index
void computeTemporaryTermsMapping();
//! Write derivative code of an equation w.r. to a variable
void compileDerivative(ofstream &code_file, int eq, int symb_id, int lag, map_idx_type &map_idx) const;
//! Write chain rule derivative code of an equation w.r. to a variable
......@@ -217,12 +224,12 @@ public:
\param no_tmp_terms if true, no temporary terms will be computed in the dynamic files
*/
void computingPass(bool jacobianExo, bool hessian, bool thirdDerivatives, bool paramsDerivatives,
const eval_context_type &eval_context, bool no_tmp_terms, bool block, bool use_dll);
const eval_context_type &eval_context, bool no_tmp_terms, bool block, bool use_dll, bool bytecode);
//! Writes model initialization and lead/lag incidence matrix to output
void writeOutput(ostream &output, const string &basename, bool block, bool byte_code, bool use_dll) const;
//! Adds informations for simulation in a binary file
void Write_Inf_To_Bin_File(const string &dynamic_basename, const string &bin_basename,
void Write_Inf_To_Bin_File_Block(const string &dynamic_basename, const string &bin_basename,
const int &num, int &u_count_int, bool &file_open, bool is_two_boundaries) const;
//! Writes dynamic model file
void writeDynamicFile(const string &basename, bool block, bool bytecode, bool use_dll) const;
......@@ -235,6 +242,9 @@ public:
//! Writes LaTeX file with the equations of the dynamic model
void writeLatexFile(const string &basename) const;
//! Initialize equation_reordered & variable_reordered
void initializeVariablesAndEquations();
virtual int getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException);
virtual int getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDException);
......
......@@ -108,6 +108,7 @@ class ExprNode
friend class DataTree;
friend class DynamicModel;
friend class StaticModel;
friend class ModelTree;
friend class ExprNodeLess;
friend class NumConstNode;
friend class VariableNode;
......
......@@ -129,11 +129,6 @@ ModFile::checkPass()
exit(EXIT_FAILURE);
}
if (byte_code && !block)
{
cerr << "ERROR: In 'model' block, can't use option 'bytecode' without option 'block'" << endl;
exit(EXIT_FAILURE);
}
if ( (stochastic_statement_present || mod_file_struct.check_present || mod_file_struct.steady_present) && no_static)
{
cerr << "no_static option is incompatible with stochastic simulation, estimation, optimal policy, steady or check command" << endl;
......@@ -193,12 +188,18 @@ ModFile::computingPass(bool no_tmp_terms)
// Compute static model and its derivatives
dynamic_model.toStatic(static_model);
if(!no_static)
static_model.computingPass(global_eval_context, no_tmp_terms, false, block);
{
static_model.initializeVariablesAndEquations();
static_model.computingPass(global_eval_context, no_tmp_terms, false, block, byte_code);
}
// Set things to compute for dynamic model
if (dynamic_model_needed)
{
if (mod_file_struct.simul_present)
dynamic_model.computingPass(false, false, false, false, global_eval_context, no_tmp_terms, block, use_dll);
{
dynamic_model.initializeVariablesAndEquations();
dynamic_model.computingPass(false, false, false, false, global_eval_context, no_tmp_terms, block, use_dll, byte_code);
}
else
{
if (mod_file_struct.order_option < 1 || mod_file_struct.order_option > 3)
......@@ -209,11 +210,11 @@ ModFile::computingPass(bool no_tmp_terms)
bool hessian = mod_file_struct.order_option >= 2 || mod_file_struct.identification_present;
bool thirdDerivatives = mod_file_struct.order_option == 3;
bool paramsDerivatives = mod_file_struct.identification_present;
dynamic_model.computingPass(true, hessian, thirdDerivatives, paramsDerivatives, global_eval_context, no_tmp_terms, false, use_dll);
dynamic_model.computingPass(true, hessian, thirdDerivatives, paramsDerivatives, global_eval_context, no_tmp_terms, false, use_dll, byte_code);
}
}
else
dynamic_model.computingPass(true, true, false, false, global_eval_context, no_tmp_terms, false, false);
dynamic_model.computingPass(true, true, false, false, global_eval_context, no_tmp_terms, false, false, byte_code);
}
for (vector<Statement *>::iterator it = statements.begin();
......
......@@ -1014,6 +1014,32 @@ ModelTree::writeTemporaryTerms(const temporary_terms_type &tt, ostream &output,
output << ";" << endl;
}
void
ModelTree::compileTemporaryTerms(ostream &code_file, const temporary_terms_type &tt, map_idx_type map_idx, bool dynamic, bool steady_dynamic) const
{
// Local var used to keep track of temp nodes already written
temporary_terms_type tt2;
for (temporary_terms_type::const_iterator it = tt.begin();
it != tt.end(); it++)
{
(*it)->compile(code_file, false, tt2, map_idx, dynamic, steady_dynamic);
if (dynamic)
{
FSTPT_ fstpt((int)(map_idx.find((*it)->idx)->second));
fstpt.write(code_file);
}
else
{
FSTPST_ fstpst((int)(map_idx.find((*it)->idx)->second));
fstpst.write(code_file);
}
// Insert current node into tt2
tt2.insert(*it);
}
}
void
ModelTree::writeModelLocalVariables(ostream &output, ExprNodeOutputType output_type) const
{
......@@ -1079,6 +1105,89 @@ ModelTree::writeModelEquations(ostream &output, ExprNodeOutputType output_type)
}
}
void
ModelTree::compileModelEquations(ostream &code_file, const temporary_terms_type &tt, map_idx_type &map_idx, bool dynamic, bool steady_dynamic) const
{
for (int eq = 0; eq < (int) equations.size(); eq++)
{
BinaryOpNode *eq_node = equations[eq];
NodeID lhs = eq_node->get_arg1();
NodeID rhs = eq_node->get_arg2();
// Test if the right hand side of the equation is empty.
double vrhs = 1.0;
try
{
vrhs = rhs->eval(eval_context_type());
}
catch (ExprNode::EvalException &e)
{
}
if (vrhs != 0) // The right hand side of the equation is not empty ==> residual=lhs-rhs;
{
lhs->compile(code_file, false, temporary_terms, map_idx, dynamic, steady_dynamic);
rhs->compile(code_file, false, temporary_terms, map_idx, dynamic, steady_dynamic);
FBINARY_ fbinary(oMinus);
fbinary.write(code_file);
FSTPR_ fstpr(eq);
fstpr.write(code_file);
}
else // The right hand side of the equation is empty ==> residual=lhs;
{
lhs->compile(code_file, false, temporary_terms, map_idx, dynamic, steady_dynamic);
FSTPR_ fstpr(eq);
fstpr.write(code_file);
}
}
}
void
ModelTree::Write_Inf_To_Bin_File(const string &basename,
int &u_count_int, bool &file_open, bool is_two_boundaries, int block_mfs) const
{
int j;
std::ofstream SaveCode;
const string bin_basename = basename + ".bin";
if (file_open)
SaveCode.open(bin_basename.c_str(), ios::out | ios::in | ios::binary | ios::ate);
else
SaveCode.open(bin_basename.c_str(), ios::out | ios::binary);
if (!SaveCode.is_open())
{
cout << "Error : Can't open file \"" << bin_basename << "\" for writing\n";
exit(EXIT_FAILURE);
}
u_count_int = 0;
for (first_derivatives_type::const_iterator it = first_derivatives.begin();it != first_derivatives.end(); it++)
{
int deriv_id = it->first.second;
if (getTypeByDerivID(deriv_id) == eEndogenous)
{
int eq = it->first.first;
int symb = getSymbIDByDerivID(deriv_id);
int var = symbol_table.getTypeSpecificID(symb);
int lag = getLagByDerivID(deriv_id);
SaveCode.write(reinterpret_cast<char *>(&eq), sizeof(eq));
int varr = var + lag * block_mfs;
SaveCode.write(reinterpret_cast<char *>(&varr), sizeof(varr));
SaveCode.write(reinterpret_cast<char *>(&lag), sizeof(lag));
int u = u_count_int + block_mfs;
SaveCode.write(reinterpret_cast<char *>(&u), sizeof(u));
u_count_int++;
}
}
if (is_two_boundaries)
u_count_int += symbol_table.endo_nbr();
for (j = 0; j < (int) symbol_table.endo_nbr(); j++)
SaveCode.write(reinterpret_cast<char *>(&j), sizeof(j));
for (j = 0; j < (int) symbol_table.endo_nbr(); j++)
SaveCode.write(reinterpret_cast<char *>(&j), sizeof(j));
SaveCode.close();
}
void
ModelTree::writeLatexModelFile(const string &filename, ExprNodeOutputType output_type) const
{
......
......@@ -109,11 +109,18 @@ protected:
void computeTemporaryTerms(bool is_matlab);
//! Writes temporary terms
void writeTemporaryTerms(const temporary_terms_type &tt, ostream &output, ExprNodeOutputType output_type) const;
//! Compiles temporary terms
void compileTemporaryTerms(ostream &code_file, const temporary_terms_type &tt, map_idx_type map_idx, bool dynamic, bool steady_dynamic) const;
//! Adds informations for simulation in a binary file
void Write_Inf_To_Bin_File(const string &basename, int &u_count_int, bool &file_open, bool is_two_boundaries, int block_mfs) const;
//! Writes model local variables
/*! No temporary term is used in the output, so that local parameters declarations can be safely put before temporary terms declaration in the output files */
void writeModelLocalVariables(ostream &output, ExprNodeOutputType output_type) const;
//! Writes model equations
void writeModelEquations(ostream &output, ExprNodeOutputType output_type) const;
//! Compiles model equations
void compileModelEquations(ostream &code_file, const temporary_terms_type &tt, map_idx_type &map_idx, bool dynamic, bool steady_dynamic) const;
//! Writes LaTeX model file
void writeLatexModelFile(const string &filename, ExprNodeOutputType output_type) const;
......
......@@ -70,6 +70,16 @@ StaticModel::compileChainRuleDerivative(ofstream &code_file, int eqr, int varr,
}
}
void
StaticModel::initializeVariablesAndEquations()
{
for(int j = 0; j < equation_number(); j++)
{
equation_reordered.push_back(j);
variable_reordered.push_back(j);
}
}
void
StaticModel::computeTemporaryTermsOrdered()
{
......@@ -173,11 +183,17 @@ StaticModel::computeTemporaryTermsOrdered()
(*it)->collectTemporary_terms(temporary_terms, temporary_terms_in_use, block);
v_temporary_terms_inuse[block] = temporary_terms_in_use;
}
computeTemporaryTermsMapping();
}
}
void
StaticModel::computeTemporaryTermsMapping()
{
// Add a mapping form node ID to temporary terms order
int j = 0;
for (temporary_terms_type::const_iterator it = temporary_terms.begin();
it != temporary_terms.end(); it++)
it != temporary_terms.end(); it++)
map_idx[(*it)->idx] = j++;
}
......@@ -388,7 +404,115 @@ StaticModel::writeModelEquationsOrdered_M(const string &static_basename) const
}
void
StaticModel::writeModelEquationsCodeOrdered(const string file_name, const string bin_basename, map_idx_type map_idx) const
StaticModel::writeModelEquationsCode(const string file_name, const string bin_basename, map_idx_type map_idx) const
{
ostringstream tmp_output;
ofstream code_file;
bool file_open = false;
string main_name = file_name;
main_name += ".cod";
code_file.open(main_name.c_str(), ios::out | ios::binary | ios::ate);
if (!code_file.is_open())
{
cout << "Error : Can't open file \"" << main_name << "\" for writing\n";
exit(EXIT_FAILURE);
}
int count_u;
int u_count_int = 0;
Write_Inf_To_Bin_File(file_name, u_count_int, file_open, false, symbol_table.endo_nbr());
file_open = true;
//Temporary variables declaration
FDIMT_ fdimt(temporary_terms.size());
fdimt.write(code_file);
FBEGINBLOCK_ fbeginblock(symbol_table.endo_nbr(),
SOLVE_FORWARD_COMPLETE,
0,
symbol_table.endo_nbr(),
variable_reordered,
equation_reordered,
false,
symbol_table.endo_nbr(),
0,
0,
u_count_int
);
fbeginblock.write(code_file);
// Add a mapping form node ID to temporary terms order
int j = 0;
for (temporary_terms_type::const_iterator it = temporary_terms.begin();
it != temporary_terms.end(); it++)
map_idx[(*it)->idx] = j++;
compileTemporaryTerms(code_file, temporary_terms, map_idx, false, false);
compileModelEquations(code_file, temporary_terms, map_idx, false, false);
FENDEQU_ fendequ;
fendequ.write(code_file);
vector<vector<pair<int, int> > > derivatives;
derivatives.resize(symbol_table.endo_nbr());
count_u = symbol_table.endo_nbr();