From 8fb8b0ff9933dab1cc3cdfe8bc7685f0af6ae903 Mon Sep 17 00:00:00 2001 From: sebastien Date: Tue, 8 May 2007 19:16:35 +0000 Subject: [PATCH] v4 parser: * added pre-computing of numerical constants (i.e. 1+1 is replaced by 2) * removed appending of ".0" for integer constants * refactoring of NumericalConstants git-svn-id: https://www.dynare.org/svn/dynare/dynare_v4@1255 ac1d8469-bf42-47a9-8791-bf33cf982152 --- parser.src/DataTree.cc | 4 +- parser.src/DynareBison.cc | 2 +- parser.src/DynareBison.yy | 2 +- parser.src/ExprNode.cc | 28 +++++++---- parser.src/NumericalConstants.cc | 50 +++++++++----------- parser.src/include/DataTree.hh | 59 ++++++++++++++++++++++-- parser.src/include/ExprNode.hh | 3 ++ parser.src/include/NumericalConstants.hh | 42 +++++++---------- 8 files changed, 122 insertions(+), 68 deletions(-) diff --git a/parser.src/DataTree.cc b/parser.src/DataTree.cc index d887eb974..57623393a 100644 --- a/parser.src/DataTree.cc +++ b/parser.src/DataTree.cc @@ -8,8 +8,8 @@ DataTree::DataTree(SymbolTable &symbol_table_arg, NumericalConstants &num_consta node_counter(0), variable_table(symbol_table_arg) { - Zero = AddNumConstant("0.0"); - One = AddNumConstant("1.0"); + Zero = AddNumConstant("0"); + One = AddNumConstant("1"); MinusOne = AddUMinus(One); } diff --git a/parser.src/DynareBison.cc b/parser.src/DynareBison.cc index f7275d4a9..932c59888 100644 --- a/parser.src/DynareBison.cc +++ b/parser.src/DynareBison.cc @@ -799,7 +799,7 @@ namespace yy case 141: #line 383 "DynareBison.yy" - {(yysemantic_stack_[(1) - (1)].string_val)->append(".0"); (yyval.node_val) = driver.add_constant((yysemantic_stack_[(1) - (1)].string_val));;} + {(yyval.node_val) = driver.add_constant((yysemantic_stack_[(1) - (1)].string_val));;} break; case 142: diff --git a/parser.src/DynareBison.yy b/parser.src/DynareBison.yy index bb561d86f..2697c22a0 100644 --- a/parser.src/DynareBison.yy +++ b/parser.src/DynareBison.yy @@ -380,7 +380,7 @@ cutoff | FLOAT_NUMBER {$$ = driver.add_constant($1);} | INT_NUMBER - {$1->append(".0"); $$ = driver.add_constant($1);} + {$$ = driver.add_constant($1);} | hand_side PLUS hand_side {$$ = driver.add_plus($1, $3);} | hand_side MINUS hand_side diff --git a/parser.src/ExprNode.cc b/parser.src/ExprNode.cc index 9b808e657..278d6c5d2 100644 --- a/parser.src/ExprNode.cc +++ b/parser.src/ExprNode.cc @@ -123,7 +123,7 @@ NumConstNode::writeOutput(ostream &output, ExprNodeOutputType output_type, double NumConstNode::eval(const eval_context_type &eval_context) const throw (EvalException) { - return(atof(datatree.num_constants.get(id).c_str())); + return(datatree.num_constants.getDouble(id)); } void @@ -666,10 +666,8 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, } double -UnaryOpNode::eval(const eval_context_type &eval_context) const throw (EvalException) +UnaryOpNode::eval_opcode(UnaryOpcode op_code, double v) throw (EvalException) { - double v = arg->eval(eval_context); - switch(op_code) { case oUminus: @@ -711,6 +709,14 @@ UnaryOpNode::eval(const eval_context_type &eval_context) const throw (EvalExcept throw EvalException(); } +double +UnaryOpNode::eval(const eval_context_type &eval_context) const throw (EvalException) +{ + double v = arg->eval(eval_context); + + return eval_opcode(op_code, v); +} + void UnaryOpNode::collectEndogenous(NodeID &Id) { @@ -914,11 +920,8 @@ BinaryOpNode::computeTemporaryTerms(map &reference_count, } double -BinaryOpNode::eval(const eval_context_type &eval_context) const throw (EvalException) +BinaryOpNode::eval_opcode(double v1, BinaryOpcode op_code, double v2) throw (EvalException) { - double v1 = arg1->eval(eval_context); - double v2 = arg2->eval(eval_context); - switch(op_code) { case oPlus: @@ -937,6 +940,15 @@ BinaryOpNode::eval(const eval_context_type &eval_context) const throw (EvalExcep } } +double +BinaryOpNode::eval(const eval_context_type &eval_context) const throw (EvalException) +{ + double v1 = arg1->eval(eval_context); + double v2 = arg2->eval(eval_context); + + return eval_opcode(v1, op_code, v2); +} + void BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_type &temporary_terms) const diff --git a/parser.src/NumericalConstants.cc b/parser.src/NumericalConstants.cc index 921fa6156..2661957d9 100644 --- a/parser.src/NumericalConstants.cc +++ b/parser.src/NumericalConstants.cc @@ -1,51 +1,47 @@ -/*! \file - \version 1.0 - \date 04/09/2004 - \par This file implements the NumericalConstants class methodes. -*/ -//------------------------------------------------------------------------------ #include -using namespace std; -//------------------------------------------------------------------------------ + #include "NumericalConstants.hh" NumericalConstants::NumericalConstants() { - AddConstant("0.0"); - AddConstant("1.0"); + AddConstant("0"); + AddConstant("1"); } -//------------------------------------------------------------------------------ -NumericalConstants::~NumericalConstants() +int +NumericalConstants::AddConstant(const string &iConst) { - // Empty -} - -//------------------------------------------------------------------------------ -int NumericalConstants::AddConstant(string iConst) -{ - map >::iterator iter = numConstantsIndex.find(iConst); + map::iterator iter = numConstantsIndex.find(iConst); if (iter != numConstantsIndex.end()) return iter->second; + if (atof(iConst.c_str()) < 0) + { + cerr << "Can't handle a negative constant..!" << endl; + exit(-1); + } + int id = (int) mNumericalConstants.size(); mNumericalConstants.push_back(iConst); numConstantsIndex[iConst] = id; return id; } -//------------------------------------------------------------------------------ -string NumericalConstants::get(int ID) const +string +NumericalConstants::get(int ID) const { - if (ID < (int)mNumericalConstants.size()) - { - return mNumericalConstants[ID]; - } + if (ID < (int) mNumericalConstants.size()) + return mNumericalConstants[ID]; else { - return ""; + cerr << "Unknown constant" << endl; + exit(-1); } } -//------------------------------------------------------------------------------ +double +NumericalConstants::getDouble(int iID) const +{ + return(atof(get(iID).c_str())); +} diff --git a/parser.src/include/DataTree.hh b/parser.src/include/DataTree.hh index 79ccab7d9..b415fa5b3 100644 --- a/parser.src/include/DataTree.hh +++ b/parser.src/include/DataTree.hh @@ -6,6 +6,7 @@ using namespace std; #include #include #include +#include #include "SymbolTable.hh" #include "NumericalConstants.hh" @@ -44,6 +45,7 @@ protected: typedef map, int>, NodeID> binary_op_node_map_type; binary_op_node_map_type binary_op_node_map; + inline NodeID AddPossiblyNegativeConstant(double val); inline NodeID AddUnaryOp(UnaryOpcode op_code, NodeID arg); inline NodeID AddBinaryOp(NodeID arg1, BinaryOpcode op_code, NodeID arg2); public: @@ -115,14 +117,51 @@ public: NodeID AddUnknownFunction(const string &function_name, const vector &arguments); }; +inline NodeID +DataTree::AddPossiblyNegativeConstant(double v) +{ + bool neg = false; + if (v < 0) + { + v = -v; + neg = true; + } + ostringstream ost; + ost << v; + + NodeID cnode = AddNumConstant(ost.str()); + + if (neg) + return AddUMinus(cnode); + else + return cnode; +} + inline NodeID DataTree::AddUnaryOp(UnaryOpcode op_code, NodeID arg) { + // If the node already exists in tree, share it unary_op_node_map_type::iterator it = unary_op_node_map.find(make_pair(arg, op_code)); if (it != unary_op_node_map.end()) return it->second; - else - return new UnaryOpNode(*this, op_code, arg); + + // Try to reduce to a constant + // Case where arg is a constant and op_code == oUminus (i.e. we're adding a negative constant) is skipped + NumConstNode *carg = dynamic_cast(arg); + if (op_code != oUminus || carg == NULL) + { + try + { + double argval = arg->eval(eval_context_type()); + double val = UnaryOpNode::eval_opcode(op_code, argval); + return AddPossiblyNegativeConstant(val); + } + catch(ExprNode::EvalException &e) + { + } + } + + return new UnaryOpNode(*this, op_code, arg); } inline NodeID @@ -131,8 +170,20 @@ DataTree::AddBinaryOp(NodeID arg1, BinaryOpcode op_code, NodeID arg2) binary_op_node_map_type::iterator it = binary_op_node_map.find(make_pair(make_pair(arg1, arg2), op_code)); if (it != binary_op_node_map.end()) return it->second; - else - return new BinaryOpNode(*this, arg1, op_code, arg2); + + // Try to reduce to a constant + try + { + double argval1 = arg1->eval(eval_context_type()); + double argval2 = arg2->eval(eval_context_type()); + double val = BinaryOpNode::eval_opcode(argval1, op_code, argval2); + return AddPossiblyNegativeConstant(val); + } + catch(ExprNode::EvalException &e) + { + } + + return new BinaryOpNode(*this, arg1, op_code, arg2); } #endif diff --git a/parser.src/include/ExprNode.hh b/parser.src/include/ExprNode.hh index 2c186fab9..d5118ef7f 100644 --- a/parser.src/include/ExprNode.hh +++ b/parser.src/include/ExprNode.hh @@ -141,6 +141,7 @@ struct ExprNodeLess }; //! Numerical constant node +/*! The constant is necessarily non-negative (this is enforced at the NumericalConstants class level) */ class NumConstNode : public ExprNode { private: @@ -213,6 +214,7 @@ public: int Curr_block, Model_Block *ModelBlock) const; virtual void collectEndogenous(NodeID &Id); + static double eval_opcode(UnaryOpcode op_code, double v) throw (EvalException); virtual double eval(const eval_context_type &eval_context) const throw (EvalException); }; @@ -247,6 +249,7 @@ public: int Curr_block, Model_Block *ModelBlock) const; virtual void collectEndogenous(NodeID &Id); + static double eval_opcode(double v1, BinaryOpcode op_code, double v2) throw (EvalException); virtual double eval(const eval_context_type &eval_context) const throw (EvalException); }; diff --git a/parser.src/include/NumericalConstants.hh b/parser.src/include/NumericalConstants.hh index 4610f7ef6..66ac63269 100644 --- a/parser.src/include/NumericalConstants.hh +++ b/parser.src/include/NumericalConstants.hh @@ -1,36 +1,28 @@ #ifndef _NUMERICALCONSTANTS_HH #define _NUMERICALCONSTANTS_HH -//------------------------------------------------------------------------------ -/** \file - * \version 1.0 - * \date 12/01/2003 - * \par This file defines NumericalConstants class. - */ -//------------------------------------------------------------------------------ + +using namespace std; + #include #include #include -//------------------------------------------------------------------------------ -/*! - \class NumericalConstants - \brief Handles numerical constants -*/ + +//! Handles numerical constants class NumericalConstants { -private : - /*! Vector of numerical constants */ - std::vector mNumericalConstants; +private: + //! Vector of numerical constants + vector mNumericalConstants; //! Map matching constants to their id - std::map > numConstantsIndex; -public : - /*! Construcor */ + map numConstantsIndex; +public: NumericalConstants(); - /*! Destructor */ - ~NumericalConstants(); - /*! Adds a constant to mNumericalConstants */ - int AddConstant(std::string iConst); - /*! Gets a constant form mNumericalConstants */ - std::string get(int iID) const; + //! Adds a constant and returns its ID + int AddConstant(const string &iConst); + //! Get a constant in string form + string get(int iID) const; + //! Get a constant in double form + double getDouble(int iID) const; }; -//------------------------------------------------------------------------------ + #endif