From 44c864f9f7dc0ee2685b9b6c3ab9b821bfe89c3c Mon Sep 17 00:00:00 2001 From: sebastien Date: Thu, 30 Apr 2009 13:14:33 +0000 Subject: [PATCH] trunk preprocessor: added new statements "write_latex_dynamic_model" and "write_latex_static_model" which list model equations in LaTeX code git-svn-id: https://www.dynare.org/svn/dynare/trunk@2654 ac1d8469-bf42-47a9-8791-bf33cf982152 --- preprocessor/ComputingTasks.cc | 22 +++++ preprocessor/ComputingTasks.hh | 19 ++++ preprocessor/DynamicModel.cc | 6 ++ preprocessor/DynamicModel.hh | 4 + preprocessor/DynareBison.yy | 21 +++-- preprocessor/DynareFlex.ll | 2 + preprocessor/ExprNode.cc | 154 +++++++++++++++++++++++---------- preprocessor/ExprNode.hh | 40 ++++++--- preprocessor/ModelTree.cc | 63 ++++++++++++-- preprocessor/ModelTree.hh | 3 + preprocessor/ParsingDriver.cc | 20 ++++- preprocessor/ParsingDriver.hh | 12 ++- preprocessor/StaticModel.cc | 6 ++ preprocessor/StaticModel.hh | 3 + preprocessor/SymbolTable.cc | 14 +++ preprocessor/SymbolTable.hh | 4 +- 16 files changed, 309 insertions(+), 84 deletions(-) diff --git a/preprocessor/ComputingTasks.cc b/preprocessor/ComputingTasks.cc index a96bbe6fe..428592c9d 100644 --- a/preprocessor/ComputingTasks.cc +++ b/preprocessor/ComputingTasks.cc @@ -965,3 +965,25 @@ void IdentificationStatement::writeOutput(ostream &output, const string &basename) const { } + +WriteLatexDynamicModelStatement::WriteLatexDynamicModelStatement(const DynamicModel &dynamic_model_arg) : + dynamic_model(dynamic_model_arg) +{ +} + +void +WriteLatexDynamicModelStatement::writeOutput(ostream &output, const string &basename) const +{ + dynamic_model.writeLatexFile(basename); +} + +WriteLatexStaticModelStatement::WriteLatexStaticModelStatement(const StaticModel &static_model_arg) : + static_model(static_model_arg) +{ +} + +void +WriteLatexStaticModelStatement::writeOutput(ostream &output, const string &basename) const +{ + static_model.writeLatexFile(basename); +} diff --git a/preprocessor/ComputingTasks.hh b/preprocessor/ComputingTasks.hh index cd39b4bc8..7f52eaa87 100644 --- a/preprocessor/ComputingTasks.hh +++ b/preprocessor/ComputingTasks.hh @@ -26,6 +26,7 @@ #include "SymbolTable.hh" #include "Statement.hh" #include "StaticModel.hh" +#include "DynamicModel.hh" class SteadyStatement : public Statement { @@ -438,4 +439,22 @@ public: virtual void writeOutput(ostream &output, const string &basename) const; }; +class WriteLatexDynamicModelStatement : public Statement +{ +private: + const DynamicModel &dynamic_model; +public: + WriteLatexDynamicModelStatement(const DynamicModel &dynamic_model_arg); + virtual void writeOutput(ostream &output, const string &basename) const; +}; + +class WriteLatexStaticModelStatement : public Statement +{ +private: + const StaticModel &static_model; +public: + WriteLatexStaticModelStatement(const StaticModel &static_model_arg); + virtual void writeOutput(ostream &output, const string &basename) const; +}; + #endif diff --git a/preprocessor/DynamicModel.cc b/preprocessor/DynamicModel.cc index d15e78077..6e8fcdfeb 100644 --- a/preprocessor/DynamicModel.cc +++ b/preprocessor/DynamicModel.cc @@ -2500,3 +2500,9 @@ DynamicModel::writeParamsDerivativesFile(const string &basename) const paramsDerivsFile.close(); } + +void +DynamicModel::writeLatexFile(const string &basename) const +{ + writeLatexModelFile(basename + "_dynamic.tex", oLatexDynamicModel); +} diff --git a/preprocessor/DynamicModel.hh b/preprocessor/DynamicModel.hh index c80592c76..fd0d16ff8 100644 --- a/preprocessor/DynamicModel.hh +++ b/preprocessor/DynamicModel.hh @@ -146,6 +146,10 @@ public: //! Converts to static model (only the equations) /*! It assumes that the static model given in argument has just been allocated */ void toStatic(StaticModel &static_model) const; + + //! Writes LaTeX file with the equations of the dynamic model + void writeLatexFile(const string &basename) const; + virtual int getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException); virtual int getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDException); }; diff --git a/preprocessor/DynareBison.yy b/preprocessor/DynareBison.yy index c892520be..1f45870ac 100644 --- a/preprocessor/DynareBison.yy +++ b/preprocessor/DynareBison.yy @@ -99,7 +99,7 @@ class ParsingDriver; %token FLOAT_NUMBER %token FORECAST %token GAMMA_PDF GAUSSIAN_ELIMINATION GMRES GRAPH -%token HISTVAL HP_FILTER HP_NGRID +%token HISTVAL HOMOTOPY_SETUP HOMOTOPY_MODE HOMOTOPY_STEPS HP_FILTER HP_NGRID %token IDENTIFICATION INF_CONSTANT INITVAL INITVAL_FILE %token INT_NUMBER %token INV_GAMMA_PDF INV_GAMMA1_PDF INV_GAMMA2_PDF IRF @@ -113,7 +113,7 @@ class ParsingDriver; %token NAN_CONSTANT NOBS NOCONSTANT NOCORR NODIAGNOSTIC NOFUNCTIONS %token NOGRAPH NOMOMENTS NOPRINT NORMAL_PDF %token OBSERVATION_TRENDS OPTIM OPTIM_WEIGHTS ORDER OSR OSR_PARAMS -%token PARAMETERS PERIODS PLANNER_OBJECTIVE PREFILTER PRESAMPLE +%token PARAMETERS PERIODS PLANNER_OBJECTIVE PLOT_PRIORS PREFILTER PRESAMPLE %token PRINT PRIOR_TRUNC PRIOR_ANALYSIS POSTERIOR_ANALYSIS %token QUOTED_STRING %token QZ_CRITERIUM @@ -124,9 +124,8 @@ class ParsingDriver; %token TEX_NAME %token UNIFORM_PDF UNIT_ROOT_VARS USE_DLL %token VALUES VAR VAREXO VAREXO_DET VAROBS -%token XLS_SHEET XLS_RANGE PLOT_PRIORS -%token NORMCDF -%token HOMOTOPY_SETUP HOMOTOPY_MODE HOMOTOPY_STEPS +%token WRITE_LATEX_DYNAMIC_MODEL WRITE_LATEX_STATIC_MODEL +%token XLS_SHEET XLS_RANGE %left COMMA %left EQUAL_EQUAL EXCLAMATION_EQUAL %left LESS GREATER LESS_EQUAL GREATER_EQUAL @@ -134,7 +133,7 @@ class ParsingDriver; %left TIMES DIVIDE %left UMINUS UPLUS %nonassoc POWER -%token EXP LOG LN LOG10 SIN COS TAN ASIN ACOS ATAN SINH COSH TANH ASINH ACOSH ATANH SQRT +%token EXP LOG LN LOG10 SIN COS TAN ASIN ACOS ATAN SINH COSH TANH ASINH ACOSH ATANH SQRT NORMCDF /* GSA analysis */ %token DYNARE_SENSITIVITY MORRIS STAB REDFORM PPRIOR PRIOR_RANGE PPOST ILPTAU GLUE MORRIS_NLIV %token MORRIS_NTRA NSAM LOAD_REDFORM LOAD_RMSE LOAD_STAB ALPHA2_STAB KSSTAT LOGTRANS_REDFORM THRESHOLD_REDFORM @@ -211,6 +210,8 @@ statement : parameters | load_params_and_steady_state | save_params_and_steady_state | identification + | write_latex_dynamic_model + | write_latex_static_model ; dsample : DSAMPLE INT_NUMBER ';' @@ -1159,6 +1160,14 @@ ramsey_policy_options : stoch_simul_options | o_planner_discount ; +write_latex_dynamic_model : WRITE_LATEX_DYNAMIC_MODEL ';' + { driver.write_latex_dynamic_model(); } + ; + +write_latex_static_model : WRITE_LATEX_STATIC_MODEL ';' + { driver.write_latex_static_model(); } + ; + bvar_prior_option : o_bvar_prior_tau | o_bvar_prior_decay | o_bvar_prior_lambda diff --git a/preprocessor/DynareFlex.ll b/preprocessor/DynareFlex.ll index e04af03ee..5b0611b69 100644 --- a/preprocessor/DynareFlex.ll +++ b/preprocessor/DynareFlex.ll @@ -116,6 +116,8 @@ int sigma_e = 0; change_type {BEGIN DYNARE_STATEMENT; return token::CHANGE_TYPE;} load_params_and_steady_state {BEGIN DYNARE_STATEMENT; return token::LOAD_PARAMS_AND_STEADY_STATE;} save_params_and_steady_state {BEGIN DYNARE_STATEMENT; return token::SAVE_PARAMS_AND_STEADY_STATE;} +write_latex_dynamic_model {BEGIN DYNARE_STATEMENT; return token::WRITE_LATEX_DYNAMIC_MODEL;} +write_latex_static_model {BEGIN DYNARE_STATEMENT; return token::WRITE_LATEX_STATIC_MODEL;} steady {BEGIN DYNARE_STATEMENT; return token::STEADY;} check {BEGIN DYNARE_STATEMENT; return token::CHECK;} diff --git a/preprocessor/ExprNode.cc b/preprocessor/ExprNode.cc index a82f1dcab..a890f766a 100644 --- a/preprocessor/ExprNode.cc +++ b/preprocessor/ExprNode.cc @@ -263,6 +263,23 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, return; } + if (IS_LATEX(output_type)) + { + output << datatree.symbol_table.getTeXName(symb_id); + if (output_type == oLatexDynamicModel) + { + output << "_{t"; + if (lag != 0) + { + if (lag > 0) + output << "+"; + output << lag; + } + output << "}"; + } + return; + } + int i; int tsid = datatree.symbol_table.getTypeSpecificID(symb_id); switch(type) @@ -271,7 +288,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, if (output_type == oMatlabOutsideModel) output << "M_.params" << "(" << tsid + 1 << ")"; else - output << "params" << LPAR(output_type) << tsid + OFFSET(output_type) << RPAR(output_type); + output << "params" << LEFT_ARRAY_SUBSCRIPT(output_type) << tsid + ARRAY_SUBSCRIPT_OFFSET(output_type) << RIGHT_ARRAY_SUBSCRIPT(output_type); break; case eModelLocalVariable: @@ -291,32 +308,34 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, { case oMatlabDynamicModel: case oCDynamicModel: - i = datatree.getDynJacobianCol(deriv_id) + OFFSET(output_type); - output << "y" << LPAR(output_type) << i << RPAR(output_type); + i = datatree.getDynJacobianCol(deriv_id) + ARRAY_SUBSCRIPT_OFFSET(output_type); + output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << RIGHT_ARRAY_SUBSCRIPT(output_type); break; case oMatlabStaticModel: case oMatlabStaticModelSparse: case oCStaticModel: - i = tsid + OFFSET(output_type); - output << "y" << LPAR(output_type) << i << RPAR(output_type); + i = tsid + ARRAY_SUBSCRIPT_OFFSET(output_type); + output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << RIGHT_ARRAY_SUBSCRIPT(output_type); break; case oMatlabDynamicModelSparse: - i = tsid + OFFSET(output_type); + i = tsid + ARRAY_SUBSCRIPT_OFFSET(output_type); if (lag > 0) - output << "y" << LPAR(output_type) << "it_+" << lag << ", " << i << RPAR(output_type); + output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << "it_+" << lag << ", " << i << RIGHT_ARRAY_SUBSCRIPT(output_type); else if (lag < 0) - output << "y" << LPAR(output_type) << "it_" << lag << ", " << i << RPAR(output_type); + output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << "it_" << lag << ", " << i << RIGHT_ARRAY_SUBSCRIPT(output_type); else - output << "y" << LPAR(output_type) << "it_, " << i << RPAR(output_type); + output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << "it_, " << i << RIGHT_ARRAY_SUBSCRIPT(output_type); break; case oMatlabOutsideModel: output << "oo_.steady_state" << "(" << tsid + 1 << ")"; break; + default: + assert(false); } break; case eExogenous: - i = tsid + OFFSET(output_type); + i = tsid + ARRAY_SUBSCRIPT_OFFSET(output_type); switch(output_type) { case oMatlabDynamicModel: @@ -339,17 +358,19 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, case oMatlabStaticModel: case oMatlabStaticModelSparse: case oCStaticModel: - output << "x" << LPAR(output_type) << i << RPAR(output_type); + output << "x" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << RIGHT_ARRAY_SUBSCRIPT(output_type); break; case oMatlabOutsideModel: assert(lag == 0); output << "oo_.exo_steady_state" << "(" << i << ")"; break; + default: + assert(false); } break; case eExogenousDet: - i = tsid + datatree.symbol_table.exo_nbr() + OFFSET(output_type); + i = tsid + datatree.symbol_table.exo_nbr() + ARRAY_SUBSCRIPT_OFFSET(output_type); switch(output_type) { case oMatlabDynamicModel: @@ -372,12 +393,14 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, case oMatlabStaticModel: case oMatlabStaticModelSparse: case oCStaticModel: - output << "x" << LPAR(output_type) << i << RPAR(output_type); + output << "x" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << RIGHT_ARRAY_SUBSCRIPT(output_type); break; case oMatlabOutsideModel: assert(lag == 0); output << "oo_.exo_det_steady_state" << "(" << tsid + 1 << ")"; break; + default: + assert(false); } break; @@ -729,7 +752,7 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, // Always put parenthesis around uminus nodes if (op_code == oUminus) - output << "("; + output << LEFT_PAR(output_type); switch(op_code) { @@ -743,7 +766,10 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, output << "log"; break; case oLog10: - output << "log10"; + if (IS_LATEX(output_type)) + output << "log_{10}"; + else + output << "log10"; break; case oCos: output << "cos"; @@ -796,7 +822,7 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, || (op_code == oUminus && arg->precedence(output_type, temporary_terms) < precedence(output_type, temporary_terms))) { - output << "("; + output << LEFT_PAR(output_type); close_parenthesis = true; } @@ -804,11 +830,11 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, arg->writeOutput(output, output_type, temporary_terms); if (close_parenthesis) - output << ")"; + output << RIGHT_PAR(output_type); // Close parenthesis for uminus if (op_code == oUminus) - output << ")"; + output << RIGHT_PAR(output_type); } double @@ -1055,7 +1081,7 @@ BinaryOpNode::precedence(ExprNodeOutputType output_type, const temporary_terms_t case oDivide: return 4; case oPower: - if (!OFFSET(output_type)) + if (IS_C(output_type)) // In C, power operator is of the form pow(a, b) return 100; else @@ -1289,7 +1315,7 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, } // Treat special case of power operator in C, and case of max and min operators - if ((op_code == oPower && !OFFSET(output_type)) || op_code == oMax || op_code == oMin ) + if ((op_code == oPower && IS_C(output_type)) || op_code == oMax || op_code == oMin ) { switch (op_code) { @@ -1316,20 +1342,29 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, bool close_parenthesis = false; - // If left argument has a lower precedence, or if current and left argument are both power operators, add parenthesis around left argument - BinaryOpNode *barg1 = dynamic_cast(arg1); - if (arg1->precedence(output_type, temporary_terms) < prec - || (op_code == oPower && barg1 != NULL && barg1->op_code == oPower)) + if (IS_LATEX(output_type) && op_code == oDivide) + output << "\\frac{"; + else { - output << "("; - close_parenthesis = true; + // If left argument has a lower precedence, or if current and left argument are both power operators, add parenthesis around left argument + BinaryOpNode *barg1 = dynamic_cast(arg1); + if (arg1->precedence(output_type, temporary_terms) < prec + || (op_code == oPower && barg1 != NULL && barg1->op_code == oPower)) + { + output << LEFT_PAR(output_type); + close_parenthesis = true; + } } // Write left argument arg1->writeOutput(output, output_type, temporary_terms); if (close_parenthesis) - output << ")"; + output << RIGHT_PAR(output_type); + + if (IS_LATEX(output_type) && op_code == oDivide) + output << "}"; + // Write current operator symbol switch(op_code) @@ -1341,10 +1376,14 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, output << "-"; break; case oTimes: - output << "*"; + if (IS_LATEX(output_type)) + output << "\\cdot "; + else + output << "*"; break; case oDivide: - output << "/"; + if (!IS_LATEX(output_type)) + output << "/"; break; case oPower: output << "^"; @@ -1356,19 +1395,30 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, output << ">"; break; case oLessEqual: - output << "<="; + if (IS_LATEX(output_type)) + output << "\\leq "; + else + output << "<="; break; case oGreaterEqual: - output << ">="; + if (IS_LATEX(output_type)) + output << "\\geq "; + else + output << ">="; break; case oEqualEqual: output << "=="; break; case oDifferent: - if (OFFSET(output_type)) + if (IS_MATLAB(output_type)) output << "~="; else - output << "!="; + { + if (IS_C(output_type)) + output << "!="; + else + output << "\\neq "; + } break; case oEqual: output << "="; @@ -1379,27 +1429,35 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, close_parenthesis = false; - /* Add parenthesis around right argument if: - - its precedence is lower than those of the current node - - it is a power operator and current operator is also a power operator - - it is a minus operator with same precedence than current operator - - it is a divide operator with same precedence than current operator */ - BinaryOpNode *barg2 = dynamic_cast(arg2); - int arg2_prec = arg2->precedence(output_type, temporary_terms); - if (arg2_prec < prec - || (op_code == oPower && barg2 != NULL && barg2->op_code == oPower) - || (op_code == oMinus && arg2_prec == prec) - || (op_code == oDivide && arg2_prec == prec)) + if (IS_LATEX(output_type) && (op_code == oPower || op_code == oDivide)) + output << "{"; + else { - output << "("; - close_parenthesis = true; + /* Add parenthesis around right argument if: + - its precedence is lower than those of the current node + - it is a power operator and current operator is also a power operator + - it is a minus operator with same precedence than current operator + - it is a divide operator with same precedence than current operator */ + BinaryOpNode *barg2 = dynamic_cast(arg2); + int arg2_prec = arg2->precedence(output_type, temporary_terms); + if (arg2_prec < prec + || (op_code == oPower && barg2 != NULL && barg2->op_code == oPower && !IS_LATEX(output_type)) + || (op_code == oMinus && arg2_prec == prec) + || (op_code == oDivide && arg2_prec == prec && !IS_LATEX(output_type))) + { + output << LEFT_PAR(output_type); + close_parenthesis = true; + } } // Write right argument arg2->writeOutput(output, output_type, temporary_terms); + if (IS_LATEX(output_type) && (op_code == oPower || op_code == oDivide)) + output << "}"; + if (close_parenthesis) - output << ")"; + output << RIGHT_PAR(output_type); } void @@ -1698,7 +1756,7 @@ TrinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_type &temporary_terms) const { // TrinaryOpNode not implemented for C output - assert(OFFSET(output_type)); + assert(!IS_C(output_type)); // If current node is a temporary term temporary_terms_type::const_iterator it = temporary_terms.find(const_cast(this)); diff --git a/preprocessor/ExprNode.hh b/preprocessor/ExprNode.hh index a44b89325..b21642bc2 100644 --- a/preprocessor/ExprNode.hh +++ b/preprocessor/ExprNode.hh @@ -46,6 +46,10 @@ typedef set temporary_terms_type; typedef map map_idx_type; typedef set temporary_terms_inuse_type; +//! Type for evaluation contexts +/*! The key is a symbol id. Lags are assumed to be null */ +typedef map eval_context_type; + //! Possible types of output when writing ExprNode(s) enum ExprNodeOutputType { @@ -55,26 +59,34 @@ enum ExprNodeOutputType oMatlabDynamicModelSparse,//!< Matlab code, dynamic block decomposed mode declaration oCStaticModel, //!< C code, static model declarations oCDynamicModel, //!< C code, dynamic model declarations - oMatlabOutsideModel //!< Matlab code, outside model block (for example in initval) + oMatlabOutsideModel, //!< Matlab code, outside model block (for example in initval) + oLatexStaticModel, //!< LaTeX code, static model declarations + oLatexDynamicModel //!< LaTeX code, dynamic model declarations }; -//! Type for evaluation contexts -/*! The key is a symbol id. Lags are assumed to be null */ -typedef map eval_context_type; +#define IS_MATLAB(output_type) ((output_type) == oMatlabStaticModel \ + || (output_type) == oMatlabDynamicModel \ + || (output_type) == oMatlabOutsideModel \ + || (output_type) == oMatlabStaticModelSparse \ + || (output_type) == oMatlabDynamicModelSparse) -/* Equal to 1 for Matlab langage, or to 0 for C language +#define IS_C(output_type) ((output_type) == oCStaticModel \ + || (output_type) == oCDynamicModel) + +#define IS_LATEX(output_type) ((output_type) == oLatexStaticModel \ + || (output_type) == oLatexDynamicModel) + +/* Equal to 1 for Matlab langage, or to 0 for C language. Not defined for LaTeX. In Matlab, array indexes begin at 1, while they begin at 0 in C */ -#define OFFSET(output_type) ((output_type == oMatlabStaticModel) \ - || (output_type == oMatlabDynamicModel) \ - || (output_type == oMatlabOutsideModel) \ - || (output_type == oMatlabStaticModelSparse) \ - || (output_type == oMatlabDynamicModelSparse)) +#define ARRAY_SUBSCRIPT_OFFSET(output_type) ((int) IS_MATLAB(output_type)) -// Left parenthesis: '(' for Matlab, '[' for C -#define LPAR(output_type) (OFFSET(output_type) ? '(' : '[') +// Left and right array subscript delimiters: '(' and ')' for Matlab, '[' and ']' for C +#define LEFT_ARRAY_SUBSCRIPT(output_type) (IS_MATLAB(output_type) ? '(' : '[') +#define RIGHT_ARRAY_SUBSCRIPT(output_type) (IS_MATLAB(output_type) ? ')' : ']') -// Right parenthesis: ')' for Matlab, ']' for C -#define RPAR(output_type) (OFFSET(output_type) ? ')' : ']') +// Left and right parentheses +#define LEFT_PAR(output_type) (IS_LATEX(output_type) ? "\\left(" : "(") +#define RIGHT_PAR(output_type) (IS_LATEX(output_type) ? "\\right)" : ")") // Computing cost above which a node can be declared a temporary term #define MIN_COST_MATLAB (40*90) diff --git a/preprocessor/ModelTree.cc b/preprocessor/ModelTree.cc index 708ac4f5b..ed7f578c1 100644 --- a/preprocessor/ModelTree.cc +++ b/preprocessor/ModelTree.cc @@ -17,6 +17,7 @@ * along with Dynare. If not, see . */ +#include #include #include @@ -149,13 +150,13 @@ ModelTree::writeTemporaryTerms(const temporary_terms_type &tt, ostream &output, // Local var used to keep track of temp nodes already written temporary_terms_type tt2; - if (tt.size() > 0 && (!OFFSET(output_type))) + if (tt.size() > 0 && (IS_C(output_type))) output << "double" << endl; for (temporary_terms_type::const_iterator it = tt.begin(); it != tt.end(); it++) { - if (!OFFSET(output_type) && it != tt.begin()) + if (IS_C(output_type) && it != tt.begin()) output << "," << endl; (*it)->writeOutput(output, output_type, tt); @@ -166,10 +167,10 @@ ModelTree::writeTemporaryTerms(const temporary_terms_type &tt, ostream &output, // Insert current node into tt2 tt2.insert(*it); - if (OFFSET(output_type)) + if (IS_MATLAB(output_type)) output << ";" << endl; } - if (!OFFSET(output_type)) + if (IS_C(output_type)) output << ";" << endl; } @@ -182,7 +183,7 @@ ModelTree::writeModelLocalVariables(ostream &output, ExprNodeOutputType output_t int id = it->first; NodeID value = it->second; - if (!OFFSET(output_type)) + if (IS_C(output_type)) output << "double "; output << symbol_table.getName(id) << " = "; @@ -209,10 +210,54 @@ ModelTree::writeModelEquations(ostream &output, ExprNodeOutputType output_type) rhs->writeOutput(output, output_type, temporary_terms); output << ";" << endl; - output << "residual" << LPAR(output_type) << eq + OFFSET(output_type) << RPAR(output_type) << "= lhs-rhs;" << endl; + output << "residual" << LEFT_ARRAY_SUBSCRIPT(output_type) << eq + ARRAY_SUBSCRIPT_OFFSET(output_type) << RIGHT_ARRAY_SUBSCRIPT(output_type) << "= lhs-rhs;" << endl; } } +void +ModelTree::writeLatexModelFile(const string &filename, ExprNodeOutputType output_type) const +{ + ofstream output; + output.open(filename.c_str(), ios::out | ios::binary); + if (!output.is_open()) + { + cerr << "ERROR: Can't open file " << filename << " for writing" << endl; + exit(EXIT_FAILURE); + } + + output << "\\documentclass[10pt,a4paper]{article}" << endl + << "\\usepackage[landscape]{geometry}" << endl + << "\\usepackage{fullpage}" << endl + << "\\begin{document}" << endl + << "\\footnotesize" << endl; + + // Write model local variables + for (map::const_iterator it = local_variables_table.begin(); + it != local_variables_table.end(); it++) + { + int id = it->first; + NodeID value = it->second; + + output << "\\begin{equation*}" << endl + << symbol_table.getName(id) << " = "; + // Use an empty set for the temporary terms + value->writeOutput(output, output_type, temporary_terms_type()); + output << endl << "\\end{equation*}" << endl; + } + + for (int eq = 0; eq < (int) equations.size(); eq++) + { + output << "\\begin{equation}" << endl + << "% Equation " << eq+1 << endl; + equations[eq]->writeOutput(output, output_type, temporary_terms_type()); + output << endl << "\\end{equation}" << endl; + } + + output << "\\end{document}" << endl; + + output.close(); +} + void ModelTree::addEquation(NodeID eq) { @@ -225,10 +270,10 @@ ModelTree::addEquation(NodeID eq) void ModelTree::matrixHelper(ostream &output, int eq_nb, int col_nb, ExprNodeOutputType output_type) const { - output << LPAR(output_type); - if (OFFSET(output_type)) + output << LEFT_ARRAY_SUBSCRIPT(output_type); + if (IS_MATLAB(output_type)) output << eq_nb + 1 << ", " << col_nb + 1; else output << eq_nb + col_nb * equations.size(); - output << RPAR(output_type); + output << RIGHT_ARRAY_SUBSCRIPT(output_type); } diff --git a/preprocessor/ModelTree.hh b/preprocessor/ModelTree.hh index df156d526..8c61f21d9 100644 --- a/preprocessor/ModelTree.hh +++ b/preprocessor/ModelTree.hh @@ -99,6 +99,9 @@ protected: //! Writes either (i+1,j+1) or [i+j*n_i] whether we are in Matlab or C mode void matrixHelper(ostream &output, int eq_nb, int col_nb, ExprNodeOutputType output_type) const; + //! Writes LaTeX model file + void writeLatexModelFile(const string &filename, ExprNodeOutputType output_type) const; + public: ModelTree(SymbolTable &symbol_table_arg, NumericalConstants &num_constants); //! Mode in which the ModelTree is supposed to work (Matlab, DLL or SparseDLL) diff --git a/preprocessor/ParsingDriver.cc b/preprocessor/ParsingDriver.cc index 9d823945d..61a340a43 100644 --- a/preprocessor/ParsingDriver.cc +++ b/preprocessor/ParsingDriver.cc @@ -101,7 +101,10 @@ ParsingDriver::declare_symbol(string *name, SymbolType type, string *tex_name) { try { - mod_file->symbol_table.addSymbol(*name, type, *tex_name); + if (tex_name == NULL) + mod_file->symbol_table.addSymbol(*name, type); + else + mod_file->symbol_table.addSymbol(*name, type, *tex_name); } catch(SymbolTable::AlreadyDeclaredException &e) { @@ -112,7 +115,8 @@ ParsingDriver::declare_symbol(string *name, SymbolType type, string *tex_name) } delete name; - delete tex_name; + if (tex_name != NULL) + delete tex_name; } void @@ -1042,6 +1046,18 @@ ParsingDriver::ramsey_policy() options_list.clear(); } +void +ParsingDriver::write_latex_dynamic_model() +{ + mod_file->addStatement(new WriteLatexDynamicModelStatement(mod_file->dynamic_model)); +} + +void +ParsingDriver::write_latex_static_model() +{ + mod_file->addStatement(new WriteLatexStaticModelStatement(mod_file->static_model)); +} + void ParsingDriver::bvar_density(string *maxnlags) { diff --git a/preprocessor/ParsingDriver.hh b/preprocessor/ParsingDriver.hh index a272e9c0e..1e935cb11 100644 --- a/preprocessor/ParsingDriver.hh +++ b/preprocessor/ParsingDriver.hh @@ -178,13 +178,13 @@ public: //! Sets the FILENAME for the initial value in initval void initval_file(string *filename); //! Declares an endogenous variable - void declare_endogenous(string *name, string *tex_name = new string); + void declare_endogenous(string *name, string *tex_name = NULL); //! Declares an exogenous variable - void declare_exogenous(string *name, string *tex_name = new string); + void declare_exogenous(string *name, string *tex_name = NULL); //! Declares an exogenous deterministic variable - void declare_exogenous_det(string *name, string *tex_name = new string); + void declare_exogenous_det(string *name, string *tex_name = NULL); //! Declares a parameter - void declare_parameter(string *name, string *tex_name = new string); + void declare_parameter(string *name, string *tex_name = NULL); //! Declares and initializes a local parameter void declare_and_init_model_local_variable(string *name, NodeID rhs); //! Changes type of a symbol @@ -338,6 +338,10 @@ public: void end_planner_objective(NodeID expr); //! ramsey policy statement void ramsey_policy(); + //! Adds a write_latex_dynamic_model statement + void write_latex_dynamic_model(); + //! Adds a write_latex_static_model statement + void write_latex_static_model(); //! BVAR marginal density void bvar_density(string *maxnlags); //! BVAR forecast diff --git a/preprocessor/StaticModel.cc b/preprocessor/StaticModel.cc index 550398ddf..cad546aef 100644 --- a/preprocessor/StaticModel.cc +++ b/preprocessor/StaticModel.cc @@ -415,3 +415,9 @@ StaticModel::computeNormalizedEquations(multimap &endo_to_eqs) const cout << "Endogenous " << symbol_table.getName(symb_id) << " normalized in equation " << (i+1) << endl; } } + +void +StaticModel::writeLatexFile(const string &basename) const +{ + writeLatexModelFile(basename + "_static.tex", oLatexStaticModel); +} diff --git a/preprocessor/StaticModel.hh b/preprocessor/StaticModel.hh index 6bab4556f..30302159b 100644 --- a/preprocessor/StaticModel.hh +++ b/preprocessor/StaticModel.hh @@ -55,6 +55,9 @@ public: //! Writes static model file void writeStaticFile(const string &basename) const; + //! Writes LaTeX file with the equations of the static model + void writeLatexFile(const string &basename) const; + virtual int getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException); }; diff --git a/preprocessor/SymbolTable.cc b/preprocessor/SymbolTable.cc index 35fbb17bb..e73b3771e 100644 --- a/preprocessor/SymbolTable.cc +++ b/preprocessor/SymbolTable.cc @@ -48,6 +48,20 @@ SymbolTable::addSymbol(const string &name, SymbolType type, const string &tex_na tex_name_table.push_back(tex_name); } +void +SymbolTable::addSymbol(const string &name, SymbolType type) throw (AlreadyDeclaredException, FrozenException) +{ + // Construct "tex_name" by prepending an antislash to all underscores in "name" + string tex_name = name; + size_t pos = 0; + while((pos = tex_name.find('_', pos)) != string::npos) + { + tex_name.insert(pos, "\\"); + pos += 2; + } + addSymbol(name, type, tex_name); +} + void SymbolTable::freeze() throw (FrozenException) { diff --git a/preprocessor/SymbolTable.hh b/preprocessor/SymbolTable.hh index f33e07f95..11a8ba22e 100644 --- a/preprocessor/SymbolTable.hh +++ b/preprocessor/SymbolTable.hh @@ -115,7 +115,9 @@ public: { }; //! Add a symbol - void addSymbol(const string &name, SymbolType type, const string &tex_name = "") throw (AlreadyDeclaredException, FrozenException); + void addSymbol(const string &name, SymbolType type, const string &tex_name) throw (AlreadyDeclaredException, FrozenException); + //! Add a symbol without its TeX name (will be equal to its name) + void addSymbol(const string &name, SymbolType type) throw (AlreadyDeclaredException, FrozenException); //! Tests if symbol already exists inline bool exists(const string &name) const; //! Get symbol name (by ID)