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),
variable_table(symbol_table_arg)
{
Zero = AddNumConstant("0.0");
One = AddNumConstant("1.0");
Zero = AddNumConstant("0");
One = AddNumConstant("1");
MinusOne = AddUMinus(One);
}

View File

@ -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:

View File

@ -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

View File

@ -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<NodeID, int> &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

View File

@ -1,51 +1,47 @@
/*! \file
\version 1.0
\date 04/09/2004
\par This file implements the NumericalConstants class methodes.
*/
//------------------------------------------------------------------------------
#include <iostream>
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<string, int, less<string> >::iterator iter = numConstantsIndex.find(iConst);
map<string, int>::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()));
}

View File

@ -6,6 +6,7 @@ using namespace std;
#include <string>
#include <map>
#include <list>
#include <sstream>
#include "SymbolTable.hh"
#include "NumericalConstants.hh"
@ -44,6 +45,7 @@ protected:
typedef map<pair<pair<NodeID, NodeID>, 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<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
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<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
@ -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

View File

@ -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);
};

View File

@ -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 <string>
#include <vector>
#include <map>
//------------------------------------------------------------------------------
/*!
\class NumericalConstants
\brief Handles numerical constants
*/
//! Handles numerical constants
class NumericalConstants
{
private :
/*! Vector of numerical constants */
std::vector<std::string> mNumericalConstants;
private:
//! Vector of numerical constants
vector<string> mNumericalConstants;
//! Map matching constants to their id
std::map<std::string, int, std::less<std::string> > numConstantsIndex;
public :
/*! Construcor */
map<string, int> 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