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
time-shift
sebastien 2007-05-08 19:16:35 +00:00
parent 3f6a51bfd4
commit 8fb8b0ff99
8 changed files with 122 additions and 68 deletions

View File

@ -8,8 +8,8 @@ DataTree::DataTree(SymbolTable &symbol_table_arg, NumericalConstants &num_consta
node_counter(0), node_counter(0),
variable_table(symbol_table_arg) variable_table(symbol_table_arg)
{ {
Zero = AddNumConstant("0.0"); Zero = AddNumConstant("0");
One = AddNumConstant("1.0"); One = AddNumConstant("1");
MinusOne = AddUMinus(One); MinusOne = AddUMinus(One);
} }

View File

@ -799,7 +799,7 @@ namespace yy
case 141: case 141:
#line 383 "DynareBison.yy" #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; break;
case 142: case 142:

View File

@ -380,7 +380,7 @@ cutoff
| FLOAT_NUMBER | FLOAT_NUMBER
{$$ = driver.add_constant($1);} {$$ = driver.add_constant($1);}
| INT_NUMBER | INT_NUMBER
{$1->append(".0"); $$ = driver.add_constant($1);} {$$ = driver.add_constant($1);}
| hand_side PLUS hand_side | hand_side PLUS hand_side
{$$ = driver.add_plus($1, $3);} {$$ = driver.add_plus($1, $3);}
| hand_side MINUS hand_side | hand_side MINUS hand_side

View File

@ -123,7 +123,7 @@ NumConstNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
double double
NumConstNode::eval(const eval_context_type &eval_context) const throw (EvalException) 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 void
@ -666,10 +666,8 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
} }
double 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) switch(op_code)
{ {
case oUminus: case oUminus:
@ -711,6 +709,14 @@ UnaryOpNode::eval(const eval_context_type &eval_context) const throw (EvalExcept
throw EvalException(); 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 void
UnaryOpNode::collectEndogenous(NodeID &Id) UnaryOpNode::collectEndogenous(NodeID &Id)
{ {
@ -914,11 +920,8 @@ BinaryOpNode::computeTemporaryTerms(map<NodeID, int> &reference_count,
} }
double 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) switch(op_code)
{ {
case oPlus: 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 void
BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_type &temporary_terms) const const temporary_terms_type &temporary_terms) const

View File

@ -1,51 +1,47 @@
/*! \file
\version 1.0
\date 04/09/2004
\par This file implements the NumericalConstants class methodes.
*/
//------------------------------------------------------------------------------
#include <iostream> #include <iostream>
using namespace std;
//------------------------------------------------------------------------------
#include "NumericalConstants.hh" #include "NumericalConstants.hh"
NumericalConstants::NumericalConstants() NumericalConstants::NumericalConstants()
{ {
AddConstant("0.0"); AddConstant("0");
AddConstant("1.0"); AddConstant("1");
} }
//------------------------------------------------------------------------------ int
NumericalConstants::~NumericalConstants() NumericalConstants::AddConstant(const string &iConst)
{ {
// Empty map<string, int>::iterator iter = numConstantsIndex.find(iConst);
}
//------------------------------------------------------------------------------
int NumericalConstants::AddConstant(string iConst)
{
map<string, int, less<string> >::iterator iter = numConstantsIndex.find(iConst);
if (iter != numConstantsIndex.end()) if (iter != numConstantsIndex.end())
return iter->second; return iter->second;
if (atof(iConst.c_str()) < 0)
{
cerr << "Can't handle a negative constant..!" << endl;
exit(-1);
}
int id = (int) mNumericalConstants.size(); int id = (int) mNumericalConstants.size();
mNumericalConstants.push_back(iConst); mNumericalConstants.push_back(iConst);
numConstantsIndex[iConst] = id; numConstantsIndex[iConst] = id;
return id; return id;
} }
//------------------------------------------------------------------------------ string
string NumericalConstants::get(int ID) const NumericalConstants::get(int ID) const
{ {
if (ID < (int)mNumericalConstants.size()) if (ID < (int) mNumericalConstants.size())
{ return mNumericalConstants[ID];
return mNumericalConstants[ID];
}
else else
{ {
return ""; cerr << "Unknown constant" << endl;
exit(-1);
} }
} }
//------------------------------------------------------------------------------ double
NumericalConstants::getDouble(int iID) const
{
return(atof(get(iID).c_str()));
}

View File

@ -6,6 +6,7 @@ using namespace std;
#include <string> #include <string>
#include <map> #include <map>
#include <list> #include <list>
#include <sstream>
#include "SymbolTable.hh" #include "SymbolTable.hh"
#include "NumericalConstants.hh" #include "NumericalConstants.hh"
@ -44,6 +45,7 @@ protected:
typedef map<pair<pair<NodeID, NodeID>, int>, NodeID> binary_op_node_map_type; typedef map<pair<pair<NodeID, NodeID>, int>, NodeID> binary_op_node_map_type;
binary_op_node_map_type binary_op_node_map; binary_op_node_map_type binary_op_node_map;
inline NodeID AddPossiblyNegativeConstant(double val);
inline NodeID AddUnaryOp(UnaryOpcode op_code, NodeID arg); inline NodeID AddUnaryOp(UnaryOpcode op_code, NodeID arg);
inline NodeID AddBinaryOp(NodeID arg1, BinaryOpcode op_code, NodeID arg2); inline NodeID AddBinaryOp(NodeID arg1, BinaryOpcode op_code, NodeID arg2);
public: public:
@ -115,14 +117,51 @@ public:
NodeID AddUnknownFunction(const string &function_name, const vector<NodeID> &arguments); NodeID AddUnknownFunction(const string &function_name, const vector<NodeID> &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 inline NodeID
DataTree::AddUnaryOp(UnaryOpcode op_code, NodeID arg) 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)); unary_op_node_map_type::iterator it = unary_op_node_map.find(make_pair(arg, op_code));
if (it != unary_op_node_map.end()) if (it != unary_op_node_map.end())
return it->second; 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<NumConstNode *>(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 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)); 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()) if (it != binary_op_node_map.end())
return it->second; 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 #endif

View File

@ -141,6 +141,7 @@ struct ExprNodeLess
}; };
//! Numerical constant node //! Numerical constant node
/*! The constant is necessarily non-negative (this is enforced at the NumericalConstants class level) */
class NumConstNode : public ExprNode class NumConstNode : public ExprNode
{ {
private: private:
@ -213,6 +214,7 @@ public:
int Curr_block, int Curr_block,
Model_Block *ModelBlock) const; Model_Block *ModelBlock) const;
virtual void collectEndogenous(NodeID &Id); 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); virtual double eval(const eval_context_type &eval_context) const throw (EvalException);
}; };
@ -247,6 +249,7 @@ public:
int Curr_block, int Curr_block,
Model_Block *ModelBlock) const; Model_Block *ModelBlock) const;
virtual void collectEndogenous(NodeID &Id); 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); virtual double eval(const eval_context_type &eval_context) const throw (EvalException);
}; };

View File

@ -1,36 +1,28 @@
#ifndef _NUMERICALCONSTANTS_HH #ifndef _NUMERICALCONSTANTS_HH
#define _NUMERICALCONSTANTS_HH #define _NUMERICALCONSTANTS_HH
//------------------------------------------------------------------------------
/** \file using namespace std;
* \version 1.0
* \date 12/01/2003
* \par This file defines NumericalConstants class.
*/
//------------------------------------------------------------------------------
#include <string> #include <string>
#include <vector> #include <vector>
#include <map> #include <map>
//------------------------------------------------------------------------------
/*! //! Handles numerical constants
\class NumericalConstants
\brief Handles numerical constants
*/
class NumericalConstants class NumericalConstants
{ {
private : private:
/*! Vector of numerical constants */ //! Vector of numerical constants
std::vector<std::string> mNumericalConstants; vector<string> mNumericalConstants;
//! Map matching constants to their id //! Map matching constants to their id
std::map<std::string, int, std::less<std::string> > numConstantsIndex; map<string, int> numConstantsIndex;
public : public:
/*! Construcor */
NumericalConstants(); NumericalConstants();
/*! Destructor */ //! Adds a constant and returns its ID
~NumericalConstants(); int AddConstant(const string &iConst);
/*! Adds a constant to mNumericalConstants */ //! Get a constant in string form
int AddConstant(std::string iConst); string get(int iID) const;
/*! Gets a constant form mNumericalConstants */ //! Get a constant in double form
std::string get(int iID) const; double getDouble(int iID) const;
}; };
//------------------------------------------------------------------------------
#endif #endif