Commit 181bda48 authored by sebastien's avatar sebastien
Browse files

trunk preprocessor: added new statements "write_latex_dynamic_model" and...

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
parent 5437ff05
...@@ -965,3 +965,25 @@ void ...@@ -965,3 +965,25 @@ void
IdentificationStatement::writeOutput(ostream &output, const string &basename) const 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);
}
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "SymbolTable.hh" #include "SymbolTable.hh"
#include "Statement.hh" #include "Statement.hh"
#include "StaticModel.hh" #include "StaticModel.hh"
#include "DynamicModel.hh"
class SteadyStatement : public Statement class SteadyStatement : public Statement
{ {
...@@ -438,4 +439,22 @@ public: ...@@ -438,4 +439,22 @@ public:
virtual void writeOutput(ostream &output, const string &basename) const; 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 #endif
...@@ -2500,3 +2500,9 @@ DynamicModel::writeParamsDerivativesFile(const string &basename) const ...@@ -2500,3 +2500,9 @@ DynamicModel::writeParamsDerivativesFile(const string &basename) const
paramsDerivsFile.close(); paramsDerivsFile.close();
} }
void
DynamicModel::writeLatexFile(const string &basename) const
{
writeLatexModelFile(basename + "_dynamic.tex", oLatexDynamicModel);
}
...@@ -146,6 +146,10 @@ public: ...@@ -146,6 +146,10 @@ public:
//! Converts to static model (only the equations) //! Converts to static model (only the equations)
/*! It assumes that the static model given in argument has just been allocated */ /*! It assumes that the static model given in argument has just been allocated */
void toStatic(StaticModel &static_model) const; 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 getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException);
virtual int getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDException); virtual int getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDException);
}; };
......
...@@ -99,7 +99,7 @@ class ParsingDriver; ...@@ -99,7 +99,7 @@ class ParsingDriver;
%token <string_val> FLOAT_NUMBER %token <string_val> FLOAT_NUMBER
%token FORECAST %token FORECAST
%token GAMMA_PDF GAUSSIAN_ELIMINATION GMRES GRAPH %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 IDENTIFICATION INF_CONSTANT INITVAL INITVAL_FILE
%token <string_val> INT_NUMBER %token <string_val> INT_NUMBER
%token INV_GAMMA_PDF INV_GAMMA1_PDF INV_GAMMA2_PDF IRF %token INV_GAMMA_PDF INV_GAMMA1_PDF INV_GAMMA2_PDF IRF
...@@ -113,7 +113,7 @@ class ParsingDriver; ...@@ -113,7 +113,7 @@ class ParsingDriver;
%token NAN_CONSTANT NOBS NOCONSTANT NOCORR NODIAGNOSTIC NOFUNCTIONS %token NAN_CONSTANT NOBS NOCONSTANT NOCORR NODIAGNOSTIC NOFUNCTIONS
%token NOGRAPH NOMOMENTS NOPRINT NORMAL_PDF %token NOGRAPH NOMOMENTS NOPRINT NORMAL_PDF
%token OBSERVATION_TRENDS OPTIM OPTIM_WEIGHTS ORDER OSR OSR_PARAMS %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 PRINT PRIOR_TRUNC PRIOR_ANALYSIS POSTERIOR_ANALYSIS
%token <string_val> QUOTED_STRING %token <string_val> QUOTED_STRING
%token QZ_CRITERIUM %token QZ_CRITERIUM
...@@ -124,9 +124,8 @@ class ParsingDriver; ...@@ -124,9 +124,8 @@ class ParsingDriver;
%token <string_val> TEX_NAME %token <string_val> TEX_NAME
%token UNIFORM_PDF UNIT_ROOT_VARS USE_DLL %token UNIFORM_PDF UNIT_ROOT_VARS USE_DLL
%token VALUES VAR VAREXO VAREXO_DET VAROBS %token VALUES VAR VAREXO VAREXO_DET VAROBS
%token XLS_SHEET XLS_RANGE PLOT_PRIORS %token WRITE_LATEX_DYNAMIC_MODEL WRITE_LATEX_STATIC_MODEL
%token NORMCDF %token XLS_SHEET XLS_RANGE
%token HOMOTOPY_SETUP HOMOTOPY_MODE HOMOTOPY_STEPS
%left COMMA %left COMMA
%left EQUAL_EQUAL EXCLAMATION_EQUAL %left EQUAL_EQUAL EXCLAMATION_EQUAL
%left LESS GREATER LESS_EQUAL GREATER_EQUAL %left LESS GREATER LESS_EQUAL GREATER_EQUAL
...@@ -134,7 +133,7 @@ class ParsingDriver; ...@@ -134,7 +133,7 @@ class ParsingDriver;
%left TIMES DIVIDE %left TIMES DIVIDE
%left UMINUS UPLUS %left UMINUS UPLUS
%nonassoc POWER %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 */ /* GSA analysis */
%token DYNARE_SENSITIVITY MORRIS STAB REDFORM PPRIOR PRIOR_RANGE PPOST ILPTAU GLUE MORRIS_NLIV %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 %token MORRIS_NTRA NSAM LOAD_REDFORM LOAD_RMSE LOAD_STAB ALPHA2_STAB KSSTAT LOGTRANS_REDFORM THRESHOLD_REDFORM
...@@ -211,6 +210,8 @@ statement : parameters ...@@ -211,6 +210,8 @@ statement : parameters
| load_params_and_steady_state | load_params_and_steady_state
| save_params_and_steady_state | save_params_and_steady_state
| identification | identification
| write_latex_dynamic_model
| write_latex_static_model
; ;
dsample : DSAMPLE INT_NUMBER ';' dsample : DSAMPLE INT_NUMBER ';'
...@@ -1159,6 +1160,14 @@ ramsey_policy_options : stoch_simul_options ...@@ -1159,6 +1160,14 @@ ramsey_policy_options : stoch_simul_options
| o_planner_discount | 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 bvar_prior_option : o_bvar_prior_tau
| o_bvar_prior_decay | o_bvar_prior_decay
| o_bvar_prior_lambda | o_bvar_prior_lambda
......
...@@ -116,6 +116,8 @@ int sigma_e = 0; ...@@ -116,6 +116,8 @@ int sigma_e = 0;
<INITIAL>change_type {BEGIN DYNARE_STATEMENT; return token::CHANGE_TYPE;} <INITIAL>change_type {BEGIN DYNARE_STATEMENT; return token::CHANGE_TYPE;}
<INITIAL>load_params_and_steady_state {BEGIN DYNARE_STATEMENT; return token::LOAD_PARAMS_AND_STEADY_STATE;} <INITIAL>load_params_and_steady_state {BEGIN DYNARE_STATEMENT; return token::LOAD_PARAMS_AND_STEADY_STATE;}
<INITIAL>save_params_and_steady_state {BEGIN DYNARE_STATEMENT; return token::SAVE_PARAMS_AND_STEADY_STATE;} <INITIAL>save_params_and_steady_state {BEGIN DYNARE_STATEMENT; return token::SAVE_PARAMS_AND_STEADY_STATE;}
<INITIAL>write_latex_dynamic_model {BEGIN DYNARE_STATEMENT; return token::WRITE_LATEX_DYNAMIC_MODEL;}
<INITIAL>write_latex_static_model {BEGIN DYNARE_STATEMENT; return token::WRITE_LATEX_STATIC_MODEL;}
<INITIAL>steady {BEGIN DYNARE_STATEMENT; return token::STEADY;} <INITIAL>steady {BEGIN DYNARE_STATEMENT; return token::STEADY;}
<INITIAL>check {BEGIN DYNARE_STATEMENT; return token::CHECK;} <INITIAL>check {BEGIN DYNARE_STATEMENT; return token::CHECK;}
......
...@@ -263,6 +263,23 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, ...@@ -263,6 +263,23 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
return; 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 i;
int tsid = datatree.symbol_table.getTypeSpecificID(symb_id); int tsid = datatree.symbol_table.getTypeSpecificID(symb_id);
switch(type) switch(type)
...@@ -271,7 +288,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, ...@@ -271,7 +288,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
if (output_type == oMatlabOutsideModel) if (output_type == oMatlabOutsideModel)
output << "M_.params" << "(" << tsid + 1 << ")"; output << "M_.params" << "(" << tsid + 1 << ")";
else 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; break;
case eModelLocalVariable: case eModelLocalVariable:
...@@ -291,32 +308,34 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, ...@@ -291,32 +308,34 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
{ {
case oMatlabDynamicModel: case oMatlabDynamicModel:
case oCDynamicModel: case oCDynamicModel:
i = datatree.getDynJacobianCol(deriv_id) + OFFSET(output_type); i = datatree.getDynJacobianCol(deriv_id) + ARRAY_SUBSCRIPT_OFFSET(output_type);
output << "y" << LPAR(output_type) << i << RPAR(output_type); output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << RIGHT_ARRAY_SUBSCRIPT(output_type);
break; break;
case oMatlabStaticModel: case oMatlabStaticModel:
case oMatlabStaticModelSparse: case oMatlabStaticModelSparse:
case oCStaticModel: case oCStaticModel:
i = tsid + OFFSET(output_type); i = tsid + ARRAY_SUBSCRIPT_OFFSET(output_type);
output << "y" << LPAR(output_type) << i << RPAR(output_type); output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << RIGHT_ARRAY_SUBSCRIPT(output_type);
break; break;
case oMatlabDynamicModelSparse: case oMatlabDynamicModelSparse:
i = tsid + OFFSET(output_type); i = tsid + ARRAY_SUBSCRIPT_OFFSET(output_type);
if (lag > 0) 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) 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 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; break;
case oMatlabOutsideModel: case oMatlabOutsideModel:
output << "oo_.steady_state" << "(" << tsid + 1 << ")"; output << "oo_.steady_state" << "(" << tsid + 1 << ")";
break; break;
default:
assert(false);
} }
break; break;
case eExogenous: case eExogenous:
i = tsid + OFFSET(output_type); i = tsid + ARRAY_SUBSCRIPT_OFFSET(output_type);
switch(output_type) switch(output_type)
{ {
case oMatlabDynamicModel: case oMatlabDynamicModel:
...@@ -339,17 +358,19 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, ...@@ -339,17 +358,19 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
case oMatlabStaticModel: case oMatlabStaticModel:
case oMatlabStaticModelSparse: case oMatlabStaticModelSparse:
case oCStaticModel: 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; break;
case oMatlabOutsideModel: case oMatlabOutsideModel:
assert(lag == 0); assert(lag == 0);
output << "oo_.exo_steady_state" << "(" << i << ")"; output << "oo_.exo_steady_state" << "(" << i << ")";
break; break;
default:
assert(false);
} }
break; break;
case eExogenousDet: 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) switch(output_type)
{ {
case oMatlabDynamicModel: case oMatlabDynamicModel:
...@@ -372,12 +393,14 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, ...@@ -372,12 +393,14 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
case oMatlabStaticModel: case oMatlabStaticModel:
case oMatlabStaticModelSparse: case oMatlabStaticModelSparse:
case oCStaticModel: 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; break;
case oMatlabOutsideModel: case oMatlabOutsideModel:
assert(lag == 0); assert(lag == 0);
output << "oo_.exo_det_steady_state" << "(" << tsid + 1 << ")"; output << "oo_.exo_det_steady_state" << "(" << tsid + 1 << ")";
break; break;
default:
assert(false);
} }
break; break;
...@@ -729,7 +752,7 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, ...@@ -729,7 +752,7 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
// Always put parenthesis around uminus nodes // Always put parenthesis around uminus nodes
if (op_code == oUminus) if (op_code == oUminus)
output << "("; output << LEFT_PAR(output_type);
switch(op_code) switch(op_code)
{ {
...@@ -743,7 +766,10 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, ...@@ -743,7 +766,10 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
output << "log"; output << "log";
break; break;
case oLog10: case oLog10:
output << "log10"; if (IS_LATEX(output_type))
output << "log_{10}";
else
output << "log10";
break; break;
case oCos: case oCos:
output << "cos"; output << "cos";
...@@ -796,7 +822,7 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, ...@@ -796,7 +822,7 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
|| (op_code == oUminus || (op_code == oUminus
&& arg->precedence(output_type, temporary_terms) < precedence(output_type, temporary_terms))) && arg->precedence(output_type, temporary_terms) < precedence(output_type, temporary_terms)))
{ {
output << "("; output << LEFT_PAR(output_type);
close_parenthesis = true; close_parenthesis = true;
} }
...@@ -804,11 +830,11 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, ...@@ -804,11 +830,11 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
arg->writeOutput(output, output_type, temporary_terms); arg->writeOutput(output, output_type, temporary_terms);
if (close_parenthesis) if (close_parenthesis)
output << ")"; output << RIGHT_PAR(output_type);
// Close parenthesis for uminus // Close parenthesis for uminus
if (op_code == oUminus) if (op_code == oUminus)
output << ")"; output << RIGHT_PAR(output_type);
} }
double double
...@@ -1055,7 +1081,7 @@ BinaryOpNode::precedence(ExprNodeOutputType output_type, const temporary_terms_t ...@@ -1055,7 +1081,7 @@ BinaryOpNode::precedence(ExprNodeOutputType output_type, const temporary_terms_t
case oDivide: case oDivide:
return 4; return 4;
case oPower: case oPower:
if (!OFFSET(output_type)) if (IS_C(output_type))
// In C, power operator is of the form pow(a, b) // In C, power operator is of the form pow(a, b)
return 100; return 100;
else else
...@@ -1289,7 +1315,7 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, ...@@ -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 // 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) switch (op_code)
{ {
...@@ -1316,20 +1342,29 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, ...@@ -1316,20 +1342,29 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
bool close_parenthesis = false; 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 if (IS_LATEX(output_type) && op_code == oDivide)
BinaryOpNode *barg1 = dynamic_cast<BinaryOpNode *>(arg1); output << "\\frac{";
if (arg1->precedence(output_type, temporary_terms) < prec else
|| (op_code == oPower && barg1 != NULL && barg1->op_code == oPower))
{ {
output << "("; // If left argument has a lower precedence, or if current and left argument are both power operators, add parenthesis around left argument
close_parenthesis = true; BinaryOpNode *barg1 = dynamic_cast<BinaryOpNode *>(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 // Write left argument
arg1->writeOutput(output, output_type, temporary_terms); arg1->writeOutput(output, output_type, temporary_terms);
if (close_parenthesis) if (close_parenthesis)
output << ")"; output << RIGHT_PAR(output_type);
if (IS_LATEX(output_type) && op_code == oDivide)
output << "}";
// Write current operator symbol // Write current operator symbol
switch(op_code) switch(op_code)
...@@ -1341,10 +1376,14 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, ...@@ -1341,10 +1376,14 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
output << "-"; output << "-";
break; break;
case oTimes: case oTimes:
output << "*"; if (IS_LATEX(output_type))
output << "\\cdot ";
else
output << "*";
break; break;
case oDivide: case oDivide:
output << "/"; if (!IS_LATEX(output_type))
output << "/";
break; break;
case oPower: case oPower:
output << "^"; output << "^";
...@@ -1356,19 +1395,30 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, ...@@ -1356,19 +1395,30 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
output << ">"; output << ">";
break; break;
case oLessEqual: case oLessEqual:
output << "<="; if (IS_LATEX(output_type))
output << "\\leq ";
else
output << "<=";
break; break;
case oGreaterEqual: case oGreaterEqual:
output << ">="; if (IS_LATEX(output_type))
output << "\\geq ";
else
output << ">=";
break; break;
case oEqualEqual: case oEqualEqual:
output << "=="; output << "==";
break; break;
case oDifferent: case oDifferent:
if (OFFSET(output_type)) if (IS_MATLAB(output_type))
output << "~="; output << "~=";
else else
output << "!="; {
if (IS_C(output_type))
output << "!=";
else
output << "\\neq ";
}
break; break;
case oEqual: case oEqual:
output << "="; output << "=";
...@@ -1379,27 +1429,35 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, ...@@ -1379,27 +1429,35 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
close_parenthesis = false; close_parenthesis = false;
/* Add parenthesis around right argument if: if (IS_LATEX(output_type) && (op_code == oPower || op_code == oDivide))
- its precedence is lower than those of the current node output << "{";
- it is a power operator and current operator is also a power operator else
- 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<BinaryOpNode *>(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))
{ {
output << "("; /* Add parenthesis around right argument if:
close_parenthesis = true; - 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<BinaryOpNode *>(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 // Write right argument
arg2->writeOutput(output, output_type, temporary_terms); arg2->writeOutput(output, output_type, temporary_terms);
if (IS_LATEX(output_type) && (op_code == oPower || op_code == oDivide))
output << "}";
if (close_parenthesis) if (close_parenthesis)
output << ")"