diff --git a/CodeInterpreter.hh b/CodeInterpreter.hh index 8d6e600e..f730cbbc 100644 --- a/CodeInterpreter.hh +++ b/CodeInterpreter.hh @@ -188,6 +188,8 @@ enum UnaryOpcode oAsinh, oAtanh, oSqrt, + oAbs, + oSign, oSteadyState, oSteadyStateParamDeriv, // for the derivative of the STEADY_STATE operator w.r.t. to a parameter oSteadyStateParam2ndDeriv, // for the 2nd derivative of the STEADY_STATE operator w.r.t. to a parameter diff --git a/DataTree.cc b/DataTree.cc index 267a97e6..24f97f98 100644 --- a/DataTree.cc +++ b/DataTree.cc @@ -401,6 +401,28 @@ DataTree::AddSqrt(expr_t iArg1) return Zero; } +expr_t +DataTree::AddAbs(expr_t iArg1) +{ + if (iArg1 == Zero) + return Zero; + if (iArg1 == One) + return One; + else + return AddUnaryOp(oAbs, iArg1); +} + +expr_t +DataTree::AddSign(expr_t iArg1) +{ + if (iArg1 == Zero) + return Zero; + if (iArg1 == One) + return One; + else + return AddUnaryOp(oSign, iArg1); +} + expr_t DataTree::AddErf(expr_t iArg1) { diff --git a/DataTree.hh b/DataTree.hh index 1456e9c8..0cb2ab7c 100644 --- a/DataTree.hh +++ b/DataTree.hh @@ -176,6 +176,10 @@ public: expr_t AddAtanh(expr_t iArg1); //! Adds "sqrt(arg)" to model tree expr_t AddSqrt(expr_t iArg1); + //! Adds "abs(arg)" to model tree + expr_t AddAbs(expr_t iArg1); + //! Adds "sign(arg)" to model tree + expr_t AddSign(expr_t iArg1); //! Adds "erf(arg)" to model tree expr_t AddErf(expr_t iArg1); //! Adds "max(arg1,arg2)" to model tree diff --git a/DynareBison.yy b/DynareBison.yy index 09c45b7c..bdd3f2de 100644 --- a/DynareBison.yy +++ b/DynareBison.yy @@ -108,7 +108,7 @@ class ParsingDriver; %token LABELS LAPLACE LIK_ALGO LIK_INIT LINEAR LOAD_IDENT_FILES LOAD_MH_FILE LOAD_PARAMS_AND_STEADY_STATE LOGLINEAR %token MARKOWITZ MARGINAL_DENSITY MAX %token MFS MH_DROP MH_INIT_SCALE MH_JSCALE MH_MODE MH_NBLOCKS MH_REPLIC MH_RECOVER MIN MINIMAL_SOLVING_PERIODS -%token MODE_CHECK MODE_COMPUTE MODE_FILE MODEL MODEL_COMPARISON MODEL_INFO MSHOCKS +%token MODE_CHECK MODE_COMPUTE MODE_FILE MODEL MODEL_COMPARISON MODEL_INFO MSHOCKS ABS SIGN %token MODIFIEDHARMONICMEAN MOMENTS_VARENDO DIFFUSE_FILTER %token NAME %token NAN_CONSTANT NO_STATIC NOBS NOCONSTANT NOCORR NODIAGNOSTIC NOFUNCTIONS @@ -459,6 +459,10 @@ expression : '(' expression ')' { $$ = driver.add_atan($3); } | SQRT '(' expression ')' { $$ = driver.add_sqrt($3); } + | ABS '(' expression ')' + { $$ = driver.add_abs($3); } + | SIGN '(' expression ')' + { $$ = driver.add_sign($3); } | MAX '(' expression COMMA expression ')' { $$ = driver.add_max($3, $5); } | MIN '(' expression COMMA expression ')' @@ -613,6 +617,10 @@ hand_side : '(' hand_side ')' { $$ = driver.add_atan($3); } | SQRT '(' hand_side ')' { $$ = driver.add_sqrt($3); } + | ABS '(' hand_side ')' + { $$ = driver.add_abs($3); } + | SIGN '(' hand_side ')' + { $$ = driver.add_sign($3); } | MAX '(' hand_side COMMA hand_side ')' { $$ = driver.add_max($3, $5); } | MIN '(' hand_side COMMA hand_side ')' diff --git a/DynareFlex.ll b/DynareFlex.ll index eec53364..6d8b51e4 100644 --- a/DynareFlex.ll +++ b/DynareFlex.ll @@ -511,6 +511,8 @@ string eofbuff; sqrt {return token::SQRT;} max {return token::MAX;} min {return token::MIN;} +abs {return token::ABS;} +sign {return token::SIGN;} normcdf {return token::NORMCDF;} normpdf {return token::NORMPDF;} erf {return token::ERF;} diff --git a/ExprNode.cc b/ExprNode.cc index 3974cbbf..386f2870 100644 --- a/ExprNode.cc +++ b/ExprNode.cc @@ -1323,6 +1323,11 @@ UnaryOpNode::composeDerivatives(expr_t darg, int deriv_id) case oSqrt: t11 = datatree.AddPlus(this, this); return datatree.AddDivide(darg, t11); + case oAbs: + t11 = datatree.AddSign(arg); + return datatree.AddTimes(t11, darg); + case oSign: + return datatree.Zero; case oSteadyState: if (datatree.isDynamic()) { @@ -1406,6 +1411,7 @@ UnaryOpNode::cost(const temporary_terms_t &temporary_terms, bool is_matlab) cons switch (op_code) { case oUminus: + case oSign: return cost + 70; case oExp: return cost + 160; @@ -1437,6 +1443,7 @@ UnaryOpNode::cost(const temporary_terms_t &temporary_terms, bool is_matlab) cons case oAtanh: return cost + 350; case oSqrt: + case oAbs: return cost + 570; case oSteadyState: case oSteadyStateParamDeriv: @@ -1449,6 +1456,7 @@ UnaryOpNode::cost(const temporary_terms_t &temporary_terms, bool is_matlab) cons switch (op_code) { case oUminus: + case oSign: return cost + 3; case oExp: case oAcosh: @@ -1477,6 +1485,7 @@ UnaryOpNode::cost(const temporary_terms_t &temporary_terms, bool is_matlab) cons case oAtanh: return cost + 150; case oSqrt: + case oAbs: return cost + 90; case oSteadyState: case oSteadyStateParamDeriv: @@ -1622,6 +1631,15 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, case oSqrt: output << "sqrt"; break; + case oAbs: + output << "abs"; + break; + case oSign: + if (output_type == oCDynamicModel) + output << "copysign"; + else + output << "sign"; + break; case oSteadyState: ExprNodeOutputType new_output_type; switch (output_type) @@ -1692,6 +1710,8 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, && arg->precedence(output_type, temporary_terms) < precedence(output_type, temporary_terms))) { output << LEFT_PAR(output_type); + if (op_code == oSign && output_type == oCDynamicModel) + output << "1.0,"; close_parenthesis = true; } @@ -1763,6 +1783,10 @@ UnaryOpNode::eval_opcode(UnaryOpcode op_code, double v) throw (EvalException, Ev return (atanh(v)); case oSqrt: return (sqrt(v)); + case oAbs: + return (abs(v)); + case oSign: + return (v > 0) ? 1 : ((v < 0) ? -1 : 0); case oSteadyState: return (v); case oSteadyStateParamDeriv: @@ -1901,6 +1925,10 @@ UnaryOpNode::normalizeEquation(int var_endo, vectorAddSqrt(arg1); } +expr_t +ParsingDriver::add_abs(expr_t arg1) +{ + return data_tree->AddAbs(arg1); +} + +expr_t +ParsingDriver::add_sign(expr_t arg1) +{ + return data_tree->AddSign(arg1); +} + expr_t ParsingDriver::add_max(expr_t arg1, expr_t arg2) { diff --git a/ParsingDriver.hh b/ParsingDriver.hh index c60a18c1..74ddc41d 100644 --- a/ParsingDriver.hh +++ b/ParsingDriver.hh @@ -485,6 +485,10 @@ public: expr_t add_atanh(expr_t arg1); //! Writes token "sqrt(arg1)" to model tree expr_t add_sqrt(expr_t arg1); + //! Writes token "abs(arg1)" to model tree + expr_t add_abs(expr_t arg1); + //! Writes token "sign(arg1)" to model tree + expr_t add_sign(expr_t arg1); //! Writes token "max(arg1,arg2)" to model tree expr_t add_max(expr_t arg1, expr_t arg2); //! Writes token "min(arg1,arg2)" to model tree