Add support for external functions
parent
b652c563ba
commit
9abc7563c1
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Dynare Team
|
||||
* Copyright (C) 2007-2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -139,7 +139,7 @@ enum SymbolType
|
|||
eParameter = 4, //!< Parameter
|
||||
eModelLocalVariable = 10, //!< Local variable whose scope is model (pound expression)
|
||||
eModFileLocalVariable = 11, //!< Local variable whose scope is mod file (model excluded)
|
||||
eUnknownFunction = 12 //!< Function unknown to the preprocessor
|
||||
eExternalFunction = 12 //!< External (user-defined) function
|
||||
};
|
||||
|
||||
enum ExpressionType
|
||||
|
|
32
DataTree.cc
32
DataTree.cc
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2009 Dynare Team
|
||||
* Copyright (C) 2003-2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -23,9 +23,12 @@
|
|||
|
||||
#include "DataTree.hh"
|
||||
|
||||
DataTree::DataTree(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg) :
|
||||
DataTree::DataTree(SymbolTable &symbol_table_arg,
|
||||
NumericalConstants &num_constants_arg,
|
||||
ExternalFunctionsTable &external_functions_table_arg) :
|
||||
symbol_table(symbol_table_arg),
|
||||
num_constants(num_constants_arg),
|
||||
external_functions_table(external_functions_table_arg),
|
||||
node_counter(0)
|
||||
{
|
||||
Zero = AddNumConstant("0");
|
||||
|
@ -454,13 +457,30 @@ DataTree::AddLocalVariable(const string &name, NodeID value) throw (LocalVariabl
|
|||
}
|
||||
|
||||
NodeID
|
||||
DataTree::AddUnknownFunction(const string &function_name, const vector<NodeID> &arguments)
|
||||
DataTree::AddExternalFunction(const string &function_name, const vector<NodeID> &arguments)
|
||||
{
|
||||
int id = symbol_table.getID(function_name);
|
||||
return AddExternalFunction(symbol_table.getID(function_name), arguments);
|
||||
}
|
||||
|
||||
assert(symbol_table.getType(id) == eUnknownFunction);
|
||||
NodeID
|
||||
DataTree::AddExternalFunction(int symb_id, const vector<NodeID> &arguments)
|
||||
{
|
||||
assert(symbol_table.getType(symb_id) == eExternalFunction);
|
||||
return new ExternalFunctionNode(*this, symb_id, arguments);
|
||||
}
|
||||
|
||||
return new UnknownFunctionNode(*this, id, arguments);
|
||||
NodeID
|
||||
DataTree::AddFirstDerivExternalFunctionNode(int top_level_symb_id, const vector<NodeID> &arguments, int input_index)
|
||||
{
|
||||
assert(symbol_table.getType(top_level_symb_id) == eExternalFunction);
|
||||
return new FirstDerivExternalFunctionNode(*this, top_level_symb_id, arguments, input_index);
|
||||
}
|
||||
|
||||
NodeID
|
||||
DataTree::AddSecondDerivExternalFunctionNode(int top_level_symb_id, const vector<NodeID> &arguments, int input_index1, int input_index2)
|
||||
{
|
||||
assert(symbol_table.getType(top_level_symb_id) == eExternalFunction);
|
||||
return new SecondDerivExternalFunctionNode(*this, top_level_symb_id, arguments, input_index1, input_index2);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
20
DataTree.hh
20
DataTree.hh
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2009 Dynare Team
|
||||
* Copyright (C) 2003-2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -30,6 +30,7 @@ using namespace std;
|
|||
|
||||
#include "SymbolTable.hh"
|
||||
#include "NumericalConstants.hh"
|
||||
#include "ExternalFunctionsTable.hh"
|
||||
#include "ExprNode.hh"
|
||||
|
||||
#define CONSTANTS_PRECISION 16
|
||||
|
@ -42,12 +43,16 @@ class DataTree
|
|||
friend class UnaryOpNode;
|
||||
friend class BinaryOpNode;
|
||||
friend class TrinaryOpNode;
|
||||
friend class UnknownFunctionNode;
|
||||
friend class ExternalFunctionNode;
|
||||
friend class FirstDerivExternalFunctionNode;
|
||||
friend class SecondDerivExternalFunctionNode;
|
||||
protected:
|
||||
//! A reference to the symbol table
|
||||
SymbolTable &symbol_table;
|
||||
//! Reference to numerical constants table
|
||||
NumericalConstants &num_constants;
|
||||
//! A reference to the external functions table
|
||||
ExternalFunctionsTable &external_functions_table;
|
||||
|
||||
typedef map<int, NumConstNode *> num_const_node_map_type;
|
||||
num_const_node_map_type num_const_node_map;
|
||||
|
@ -80,7 +85,7 @@ private:
|
|||
inline NodeID AddTrinaryOp(NodeID arg1, TrinaryOpcode op_code, NodeID arg2, NodeID arg3);
|
||||
|
||||
public:
|
||||
DataTree(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg);
|
||||
DataTree(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg);
|
||||
virtual ~DataTree();
|
||||
|
||||
//! Some predefined constants
|
||||
|
@ -175,9 +180,14 @@ public:
|
|||
NodeID AddEqual(NodeID iArg1, NodeID iArg2);
|
||||
//! Adds a model local variable with its value
|
||||
void AddLocalVariable(const string &name, NodeID value) throw (LocalVariableException);
|
||||
//! Adds an unknown function node
|
||||
//! Adds an external function node
|
||||
/*! \todo Use a map to share identical nodes */
|
||||
NodeID AddUnknownFunction(const string &function_name, const vector<NodeID> &arguments);
|
||||
NodeID AddExternalFunction(const string &function_name, const vector<NodeID> &arguments);
|
||||
NodeID AddExternalFunction(int symb_id, const vector<NodeID> &arguments);
|
||||
//! Adds an external function node for the first derivative of an external function
|
||||
NodeID AddFirstDerivExternalFunctionNode(int top_level_symb_id, const vector<NodeID> &arguments, int input_index);
|
||||
//! Adds an external function node for the second derivative of an external function
|
||||
NodeID AddSecondDerivExternalFunctionNode(int top_level_symb_id, const vector<NodeID> &arguments, int input_index1, int input_index2);
|
||||
//! Checks if a given symbol is used somewhere in the data tree
|
||||
bool isSymbolUsed(int symb_id) const;
|
||||
//! Checks if a given unary op is used somewhere in the data tree
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2009 Dynare Team
|
||||
* Copyright (C) 2003-2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -36,8 +36,9 @@
|
|||
#endif
|
||||
|
||||
DynamicModel::DynamicModel(SymbolTable &symbol_table_arg,
|
||||
NumericalConstants &num_constants_arg) :
|
||||
ModelTree(symbol_table_arg, num_constants_arg),
|
||||
NumericalConstants &num_constants_arg,
|
||||
ExternalFunctionsTable &external_functions_table_arg) :
|
||||
ModelTree(symbol_table_arg, num_constants_arg, external_functions_table_arg),
|
||||
max_lag(0), max_lead(0),
|
||||
max_endo_lag(0), max_endo_lead(0),
|
||||
max_exo_lag(0), max_exo_lead(0),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2009 Dynare Team
|
||||
* Copyright (C) 2003-2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -199,7 +199,7 @@ private:
|
|||
vector<pair<int, int> > endo_max_leadlag_block, other_endo_max_leadlag_block, exo_max_leadlag_block, exo_det_max_leadlag_block, max_leadlag_block;
|
||||
|
||||
public:
|
||||
DynamicModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants);
|
||||
DynamicModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_argx);
|
||||
//! Adds a variable node
|
||||
/*! This implementation allows for non-zero lag */
|
||||
virtual VariableNode *AddVariable(int symb_id, int lag = 0);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2009 Dynare Team
|
||||
* Copyright (C) 2003-2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -158,9 +158,10 @@ class ParsingDriver;
|
|||
%token SVAR_IDENTIFICATION EQUATION EXCLUSION LAG UPPER_CHOLESKY LOWER_CHOLESKY
|
||||
%token MARKOV_SWITCHING CHAIN STATE DURATION NUMBER_OF_STATES
|
||||
%token SVAR COEFFICIENTS VARIANCES CONSTANTS EQUATIONS
|
||||
%token EXTERNAL_FUNCTION EXT_FUNC_NAME EXT_FUNC_NARGS FIRST_DERIV_PROVIDED SECOND_DERIV_PROVIDED
|
||||
|
||||
%type <node_val> expression expression_or_empty
|
||||
%type <node_val> equation hand_side model_var
|
||||
%type <node_val> equation hand_side
|
||||
%type <string_val> signed_float signed_integer prior
|
||||
%type <string_val> filename symbol expectation_input
|
||||
%type <string_val> value value1
|
||||
|
@ -239,6 +240,7 @@ statement : parameters
|
|||
| svar_identification
|
||||
| markov_switching
|
||||
| svar
|
||||
| external_function
|
||||
;
|
||||
|
||||
dsample : DSAMPLE INT_NUMBER ';'
|
||||
|
@ -413,8 +415,8 @@ expression : '(' expression ')'
|
|||
{ $$ = driver.add_max($3, $5); }
|
||||
| MIN '(' expression COMMA expression ')'
|
||||
{ $$ = driver.add_min($3, $5); }
|
||||
| symbol '(' comma_expression ')'
|
||||
{ $$ = driver.add_unknown_function($1); }
|
||||
| symbol { driver.push_external_function_arg_vector_onto_stack(); } '(' comma_expression ')'
|
||||
{ $$ = driver.add_model_var_or_external_function($1); }
|
||||
| NORMCDF '(' expression COMMA expression COMMA expression ')'
|
||||
{ $$ = driver.add_normcdf($3, $5, $7); }
|
||||
| NORMCDF '(' expression ')'
|
||||
|
@ -426,14 +428,14 @@ expression : '(' expression ')'
|
|||
;
|
||||
|
||||
comma_expression : expression
|
||||
{ driver.add_unknown_function_arg($1); }
|
||||
| comma_expression COMMA expression
|
||||
{ driver.add_unknown_function_arg($3); }
|
||||
{ driver.add_external_function_arg($1); }
|
||||
| comma_expression COMMA expression
|
||||
{ driver.add_external_function_arg($3); }
|
||||
;
|
||||
|
||||
expression_or_empty : {$$ = driver.add_nan_constant();}
|
||||
| expression
|
||||
;
|
||||
| expression
|
||||
;
|
||||
|
||||
initval : INITVAL ';' initval_list END
|
||||
{ driver.end_initval(); }
|
||||
|
@ -503,7 +505,8 @@ tag_pair : NAME EQUAL QUOTED_STRING
|
|||
|
||||
hand_side : '(' hand_side ')'
|
||||
{ $$ = $2;}
|
||||
| model_var
|
||||
| symbol
|
||||
{ $$ = driver.add_model_variable($1); }
|
||||
| FLOAT_NUMBER
|
||||
{ $$ = driver.add_constant($1); }
|
||||
| INT_NUMBER
|
||||
|
@ -562,6 +565,8 @@ hand_side : '(' hand_side ')'
|
|||
{ $$ = driver.add_max($3, $5); }
|
||||
| MIN '(' hand_side COMMA hand_side ')'
|
||||
{ $$ = driver.add_min($3, $5); }
|
||||
| symbol { driver.push_external_function_arg_vector_onto_stack(); } '(' comma_hand_side ')'
|
||||
{ $$ = driver.add_model_var_or_external_function($1); }
|
||||
| NORMCDF '(' hand_side COMMA hand_side COMMA hand_side ')'
|
||||
{ $$ = driver.add_normcdf($3, $5, $7); }
|
||||
| NORMCDF '(' hand_side ')'
|
||||
|
@ -570,6 +575,11 @@ hand_side : '(' hand_side ')'
|
|||
{ $$ = driver.add_steady_state($3); }
|
||||
;
|
||||
|
||||
comma_hand_side : hand_side
|
||||
{ driver.add_external_function_arg($1); }
|
||||
| comma_hand_side COMMA hand_side
|
||||
{ driver.add_external_function_arg($3); }
|
||||
|
||||
expectation_input : signed_integer
|
||||
| VAROBS { string *varobs = new string("varobs"); $$ = varobs; }
|
||||
| FULL { string *full = new string("full"); $$ = full; }
|
||||
|
@ -578,12 +588,6 @@ expectation_input : signed_integer
|
|||
pound_expression: '#' symbol EQUAL hand_side ';'
|
||||
{ driver.declare_and_init_model_local_variable($2, $4); };
|
||||
|
||||
model_var : symbol
|
||||
{ $$ = driver.add_model_variable($1); }
|
||||
| symbol '(' signed_integer ')'
|
||||
{ $$ = driver.add_model_variable($1, $3); }
|
||||
;
|
||||
|
||||
shocks : SHOCKS ';' shock_list END { driver.end_shocks(); };
|
||||
|
||||
shock_list : shock_list shock_elem
|
||||
|
@ -772,6 +776,20 @@ simul_options : o_periods
|
|||
| o_minimal_solving_periods
|
||||
;
|
||||
|
||||
external_function : EXTERNAL_FUNCTION '(' external_function_options_list ')' ';'
|
||||
{ driver.external_function(); }
|
||||
;
|
||||
|
||||
external_function_options_list : external_function_options_list COMMA external_function_options
|
||||
| external_function_options
|
||||
;
|
||||
|
||||
external_function_options : o_ext_func_name
|
||||
| o_ext_func_nargs
|
||||
| o_first_deriv_provided
|
||||
| o_second_deriv_provided
|
||||
;
|
||||
|
||||
stoch_simul : STOCH_SIMUL ';'
|
||||
{ driver.stoch_simul(); }
|
||||
| STOCH_SIMUL '(' stoch_simul_options_list ')' ';'
|
||||
|
@ -1888,6 +1906,19 @@ o_equations : EQUATIONS EQUAL vec_int
|
|||
|
||||
o_instruments : INSTRUMENTS EQUAL '(' symbol_list ')' {driver.option_symbol_list("instruments"); };
|
||||
|
||||
o_ext_func_name : EXT_FUNC_NAME EQUAL filename { driver.external_function_option("name", $3); };
|
||||
o_ext_func_nargs : EXT_FUNC_NARGS EQUAL INT_NUMBER { driver.external_function_option("nargs",$3); };
|
||||
o_first_deriv_provided : FIRST_DERIV_PROVIDED EQUAL filename
|
||||
{ driver.external_function_option("first_deriv_provided", $3); }
|
||||
| FIRST_DERIV_PROVIDED
|
||||
{ driver.external_function_option("first_deriv_provided", ""); }
|
||||
;
|
||||
o_second_deriv_provided : SECOND_DERIV_PROVIDED EQUAL filename
|
||||
{ driver.external_function_option("second_deriv_provided", $3); }
|
||||
| SECOND_DERIV_PROVIDED
|
||||
{ driver.external_function_option("second_deriv_provided", ""); }
|
||||
;
|
||||
|
||||
range : symbol ':' symbol
|
||||
{
|
||||
$1->append(":");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2009 Dynare Team
|
||||
* Copyright (C) 2003-2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -144,6 +144,7 @@ int sigma_e = 0;
|
|||
|
||||
<INITIAL>markov_switching {BEGIN DYNARE_STATEMENT; return token::MARKOV_SWITCHING;}
|
||||
<INITIAL>svar {BEGIN DYNARE_STATEMENT; return token::SVAR;}
|
||||
<INITIAL>external_function {BEGIN DYNARE_STATEMENT; return token::EXTERNAL_FUNCTION;}
|
||||
/* End of a Dynare statement */
|
||||
|
||||
<DYNARE_STATEMENT>; {
|
||||
|
@ -229,6 +230,10 @@ int sigma_e = 0;
|
|||
<DYNARE_STATEMENT>aim_solver {return token::AIM_SOLVER;}
|
||||
<DYNARE_STATEMENT>partial_information {return token::PARTIAL_INFORMATION;}
|
||||
<DYNARE_STATEMENT>conditional_variance_decomposition {return token::CONDITIONAL_VARIANCE_DECOMPOSITION;}
|
||||
<DYNARE_STATEMENT>name {return token::EXT_FUNC_NAME;}
|
||||
<DYNARE_STATEMENT>nargs {return token::EXT_FUNC_NARGS;}
|
||||
<DYNARE_STATEMENT>first_deriv_provided {return token::FIRST_DERIV_PROVIDED;}
|
||||
<DYNARE_STATEMENT>second_deriv_provided {return token::SECOND_DERIV_PROVIDED;}
|
||||
|
||||
<DYNARE_STATEMENT>freq {return token::FREQ;}
|
||||
<DYNARE_STATEMENT>initial_year {return token::INITIAL_YEAR;}
|
||||
|
@ -531,16 +536,16 @@ int sigma_e = 0;
|
|||
}
|
||||
|
||||
/* An instruction starting with a recognized symbol (which is not a modfile local
|
||||
or an unknown function) is passed as NAME, otherwise it is a native statement
|
||||
or an external function) is passed as NAME, otherwise it is a native statement
|
||||
until the end of the line.
|
||||
We exclude modfile local vars because the user may want to modify their value
|
||||
using a Matlab assignment statement.
|
||||
We also exclude unknown functions because the user may have used a Matlab matrix
|
||||
element in initval (in which case Dynare recognizes the matrix name as an unknown
|
||||
We also exclude external functions because the user may have used a Matlab matrix
|
||||
element in initval (in which case Dynare recognizes the matrix name as an external
|
||||
function symbol), and may want to modify the matrix later with Matlab statements.
|
||||
*/
|
||||
<INITIAL>[A-Za-z_][A-Za-z0-9_]* {
|
||||
if (driver.symbol_exists_and_is_not_modfile_local_or_unknown_function(yytext))
|
||||
if (driver.symbol_exists_and_is_not_modfile_local_or_external_function(yytext))
|
||||
{
|
||||
BEGIN DYNARE_STATEMENT;
|
||||
yylval->string_val = new string(yytext);
|
||||
|
|
271
ExprNode.cc
271
ExprNode.cc
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Dynare Team
|
||||
* Copyright (C) 2007-2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -359,7 +359,7 @@ VariableNode::VariableNode(DataTree &datatree_arg, int symb_id_arg, int lag_arg)
|
|||
datatree.variable_node_map[make_pair(symb_id, lag)] = this;
|
||||
|
||||
// It makes sense to allow a lead/lag on parameters: during steady state calibration, endogenous and parameters can be swapped
|
||||
assert(type != eUnknownFunction
|
||||
assert(type != eExternalFunction
|
||||
&& (lag == 0 || (type != eModelLocalVariable && type != eModFileLocalVariable)));
|
||||
}
|
||||
|
||||
|
@ -389,7 +389,7 @@ VariableNode::prepareForDerivation()
|
|||
case eModFileLocalVariable:
|
||||
// Such a variable is never derived
|
||||
break;
|
||||
case eUnknownFunction:
|
||||
case eExternalFunction:
|
||||
cerr << "VariableNode::prepareForDerivation: impossible case" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
@ -413,7 +413,7 @@ VariableNode::computeDerivative(int deriv_id)
|
|||
case eModFileLocalVariable:
|
||||
cerr << "ModFileLocalVariable is not derivable" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
case eUnknownFunction:
|
||||
case eExternalFunction:
|
||||
cerr << "Impossible case!" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
@ -601,7 +601,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
|
|||
}
|
||||
break;
|
||||
|
||||
case eUnknownFunction:
|
||||
case eExternalFunction:
|
||||
cerr << "Impossible case" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
@ -767,7 +767,7 @@ VariableNode::getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recur
|
|||
case eModFileLocalVariable:
|
||||
cerr << "ModFileLocalVariable is not derivable" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
case eUnknownFunction:
|
||||
case eExternalFunction:
|
||||
cerr << "Impossible case!" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
@ -3174,7 +3174,7 @@ TrinaryOpNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOp
|
|||
return buildSimilarTrinaryOpNode(arg1subst, arg2subst, arg3subst, datatree);
|
||||
}
|
||||
|
||||
UnknownFunctionNode::UnknownFunctionNode(DataTree &datatree_arg,
|
||||
ExternalFunctionNode::ExternalFunctionNode(DataTree &datatree_arg,
|
||||
int symb_id_arg,
|
||||
const vector<NodeID> &arguments_arg) :
|
||||
ExprNode(datatree_arg),
|
||||
|
@ -3184,37 +3184,65 @@ UnknownFunctionNode::UnknownFunctionNode(DataTree &datatree_arg,
|
|||
}
|
||||
|
||||
void
|
||||
UnknownFunctionNode::prepareForDerivation()
|
||||
ExternalFunctionNode::prepareForDerivation()
|
||||
{
|
||||
cerr << "UnknownFunctionNode::prepareForDerivation: operation impossible!" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
if (preparedForDerivation)
|
||||
return;
|
||||
|
||||
for (vector<NodeID>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
|
||||
(*it)->prepareForDerivation();
|
||||
|
||||
non_null_derivatives = arguments.at(0)->non_null_derivatives;
|
||||
for (int i = 1; i < (int)arguments.size(); i++)
|
||||
set_union(non_null_derivatives.begin(),
|
||||
non_null_derivatives.end(),
|
||||
arguments.at(i)->non_null_derivatives.begin(),
|
||||
arguments.at(i)->non_null_derivatives.end(),
|
||||
inserter(non_null_derivatives, non_null_derivatives.begin()));
|
||||
|
||||
preparedForDerivation = true;
|
||||
}
|
||||
|
||||
NodeID
|
||||
UnknownFunctionNode::computeDerivative(int deriv_id)
|
||||
ExternalFunctionNode::computeDerivative(int deriv_id)
|
||||
{
|
||||
cerr << "UnknownFunctionNode::computeDerivative: operation impossible!" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
vector<NodeID> dargs;
|
||||
for (vector<NodeID>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
|
||||
dargs.push_back((*it)->getDerivative(deriv_id));
|
||||
return composeDerivatives(dargs);
|
||||
}
|
||||
|
||||
NodeID
|
||||
UnknownFunctionNode::getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables)
|
||||
ExternalFunctionNode::composeDerivatives(const vector<NodeID> &dargs)
|
||||
{
|
||||
cerr << "UnknownFunctionNode::getChainRuleDerivative: operation impossible!" << endl;
|
||||
vector<NodeID> dNodes;
|
||||
for (int i = 0; i < (int)dargs.size(); i++)
|
||||
if (dargs.at(i) != 0)
|
||||
dNodes.push_back(datatree.AddTimes(dargs.at(i),
|
||||
datatree.AddFirstDerivExternalFunctionNode(symb_id, arguments, i+1)));
|
||||
|
||||
NodeID theDeriv = datatree.Zero;
|
||||
for (vector<NodeID>::const_iterator it = dNodes.begin(); it != dNodes.end(); it++)
|
||||
theDeriv = datatree.AddPlus(theDeriv, *it);
|
||||
return theDeriv;
|
||||
}
|
||||
|
||||
NodeID
|
||||
ExternalFunctionNode::getChainRuleDerivative(int deriv_id, const map<int, NodeID> &recursive_variables)
|
||||
{
|
||||
cerr << "ExternalFunctionNode::getChainRuleDerivative: operation impossible!" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void
|
||||
UnknownFunctionNode::computeTemporaryTerms(map<NodeID, int> &reference_count,
|
||||
ExternalFunctionNode::computeTemporaryTerms(map<NodeID, int> &reference_count,
|
||||
temporary_terms_type &temporary_terms,
|
||||
bool is_matlab) const
|
||||
{
|
||||
cerr << "UnknownFunctionNode::computeTemporaryTerms: operation impossible!" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void
|
||||
UnknownFunctionNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
|
||||
ExternalFunctionNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
|
||||
const temporary_terms_type &temporary_terms) const
|
||||
{
|
||||
output << datatree.symbol_table.getName(symb_id) << "(";
|
||||
|
@ -3230,19 +3258,19 @@ UnknownFunctionNode::writeOutput(ostream &output, ExprNodeOutputType output_type
|
|||
}
|
||||
|
||||
void
|
||||
UnknownFunctionNode::computeTemporaryTerms(map<NodeID, int> &reference_count,
|
||||
ExternalFunctionNode::computeTemporaryTerms(map<NodeID, int> &reference_count,
|
||||
temporary_terms_type &temporary_terms,
|
||||
map<NodeID, pair<int, int> > &first_occurence,
|
||||
int Curr_block,
|
||||
vector< vector<temporary_terms_type> > &v_temporary_terms,
|
||||
int equation) const
|
||||
{
|
||||
cerr << "UnknownFunctionNode::computeTemporaryTerms: not implemented" << endl;
|
||||
cerr << "ExternalFunctionNode::computeTemporaryTerms: not implemented" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void
|
||||
UnknownFunctionNode::collectVariables(SymbolType type_arg, set<pair<int, int> > &result) const
|
||||
ExternalFunctionNode::collectVariables(SymbolType type_arg, set<pair<int, int> > &result) const
|
||||
{
|
||||
for (vector<NodeID>::const_iterator it = arguments.begin();
|
||||
it != arguments.end(); it++)
|
||||
|
@ -3250,9 +3278,9 @@ UnknownFunctionNode::collectVariables(SymbolType type_arg, set<pair<int, int> >
|
|||
}
|
||||
|
||||
void
|
||||
UnknownFunctionNode::collectTemporary_terms(const temporary_terms_type &temporary_terms, temporary_terms_inuse_type &temporary_terms_inuse, int Curr_Block) const
|
||||
ExternalFunctionNode::collectTemporary_terms(const temporary_terms_type &temporary_terms, temporary_terms_inuse_type &temporary_terms_inuse, int Curr_Block) const
|
||||
{
|
||||
temporary_terms_type::const_iterator it = temporary_terms.find(const_cast<UnknownFunctionNode *>(this));
|
||||
temporary_terms_type::const_iterator it = temporary_terms.find(const_cast<ExternalFunctionNode *>(this));
|
||||
if (it != temporary_terms.end())
|
||||
temporary_terms_inuse.insert(idx);
|
||||
else
|
||||
|
@ -3262,20 +3290,20 @@ UnknownFunctionNode::collectTemporary_terms(const temporary_terms_type &temporar
|
|||
}
|
||||
|
||||
double
|
||||
UnknownFunctionNode::eval(const eval_context_type &eval_context) const throw (EvalException)
|
||||
ExternalFunctionNode::eval(const eval_context_type &eval_context) const throw (EvalException)
|
||||
{
|
||||
throw EvalException();
|
||||
}
|
||||
|
||||
void
|
||||
UnknownFunctionNode::compile(ostream &CompileCode, bool lhs_rhs, const temporary_terms_type &temporary_terms, const map_idx_type &map_idx, bool dynamic, bool steady_dynamic) const
|
||||
ExternalFunctionNode::compile(ostream &CompileCode, bool lhs_rhs, const temporary_terms_type &temporary_terms, const map_idx_type &map_idx, bool dynamic, bool steady_dynamic) const
|
||||
{
|
||||
cerr << "UnknownFunctionNode::compile: operation impossible!" << endl;
|
||||
cerr << "ExternalFunctionNode::compile: operation impossible!" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pair<int, NodeID>
|
||||
UnknownFunctionNode::normalizeEquation(int var_endo, vector<pair<int, pair<NodeID, NodeID> > > &List_of_Op_RHS) const
|
||||
ExternalFunctionNode::normalizeEquation(int var_endo, vector<pair<int, pair<NodeID, NodeID> > > &List_of_Op_RHS) const
|
||||
{
|
||||
vector<pair<bool, NodeID> > V_arguments;
|
||||
vector<NodeID> V_NodeID;
|
||||
|
@ -3288,23 +3316,23 @@ UnknownFunctionNode::normalizeEquation(int var_endo, vector<pair<int, pair<NodeI
|
|||
V_NodeID.push_back(V_arguments[V_arguments.size()-1].second);
|
||||
}
|
||||
if (!present)
|
||||
return (make_pair(0, datatree.AddUnknownFunction(datatree.symbol_table.getName(symb_id), V_NodeID)));
|
||||
return (make_pair(0, datatree.AddExternalFunction(datatree.symbol_table.getName(symb_id), V_NodeID)));
|
||||
else
|
||||
return (make_pair(1, (NodeID) NULL));
|
||||
}
|
||||
|
||||
NodeID
|
||||
UnknownFunctionNode::toStatic(DataTree &static_datatree) const
|
||||
ExternalFunctionNode::toStatic(DataTree &static_datatree) const
|
||||
{
|
||||
vector<NodeID> static_arguments;
|
||||
for (vector<NodeID>::const_iterator it = arguments.begin();
|
||||
it != arguments.end(); it++)
|
||||
static_arguments.push_back((*it)->toStatic(static_datatree));
|
||||
return static_datatree.AddUnknownFunction(datatree.symbol_table.getName(symb_id), static_arguments);
|
||||
return static_datatree.AddExternalFunction(datatree.symbol_table.getName(symb_id), static_arguments);
|
||||
}
|
||||
|
||||
int
|
||||
UnknownFunctionNode::maxEndoLead() const
|
||||
ExternalFunctionNode::maxEndoLead() const
|
||||
{
|
||||
int val = 0;
|
||||
for (vector<NodeID>::const_iterator it = arguments.begin();
|
||||
|
@ -3314,7 +3342,7 @@ UnknownFunctionNode::maxEndoLead() const
|
|||
}
|
||||
|
||||
int
|
||||
UnknownFunctionNode::maxExoLead() const
|
||||
ExternalFunctionNode::maxExoLead() const
|
||||
{
|
||||
int val = 0;
|
||||
for (vector<NodeID>::const_iterator it = arguments.begin();
|
||||
|
@ -3324,50 +3352,187 @@ UnknownFunctionNode::maxExoLead() const
|
|||
}
|
||||
|
||||
NodeID
|
||||
UnknownFunctionNode::decreaseLeadsLags(int n) const
|
||||
ExternalFunctionNode::decreaseLeadsLags(int n) const
|
||||
{
|
||||
cerr << "UnknownFunctionNode::decreaseLeadsLags: not implemented!" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
vector<NodeID> arguments_subst;
|
||||
for (vector<NodeID>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
|
||||
arguments_subst.push_back((*it)->decreaseLeadsLags(n));
|
||||
return buildSimilarExternalFunctionNode(arguments_subst, datatree);
|
||||
}
|
||||
|
||||
NodeID
|
||||
UnknownFunctionNode::decreaseLeadsLagsPredeterminedVariables() const
|
||||
ExternalFunctionNode::decreaseLeadsLagsPredeterminedVariables() const
|
||||
{
|
||||
cerr << "UnknownFunctionNode::decreaseLeadsLagsPredeterminedVariables: not implemented!" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
vector<NodeID> arguments_subst;
|
||||
for (vector<NodeID>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
|
||||
arguments_subst.push_back((*it)->decreaseLeadsLagsPredeterminedVariables());
|
||||
return buildSimilarExternalFunctionNode(arguments_subst, datatree);
|
||||
}
|
||||
|
||||
NodeID
|
||||
UnknownFunctionNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
|
||||
ExternalFunctionNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
|
||||
{
|
||||
cerr << "UnknownFunctionNode::substituteEndoLeadGreaterThanTwo: not implemented!" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
vector<NodeID> arguments_subst;
|
||||
for (vector<NodeID>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
|
||||
arguments_subst.push_back((*it)->substituteEndoLeadGreaterThanTwo(subst_table, neweqs));
|
||||
return buildSimilarExternalFunctionNode(arguments_subst, datatree);
|
||||
}
|
||||
|
||||
NodeID
|
||||
UnknownFunctionNode::substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
|
||||
ExternalFunctionNode::substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
|
||||
{
|
||||
cerr << "UnknownFunctionNode::substituteEndoLagGreaterThanTwo: not implemented!" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
vector<NodeID> arguments_subst;
|
||||
for (vector<NodeID>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
|
||||
arguments_subst.push_back((*it)->substituteEndoLagGreaterThanTwo(subst_table, neweqs));
|
||||
return buildSimilarExternalFunctionNode(arguments_subst, datatree);
|
||||
}
|
||||
|
||||
NodeID
|
||||
UnknownFunctionNode::substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
|
||||
ExternalFunctionNode::substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
|
||||
{
|
||||
cerr << "UnknownFunctionNode::substituteExoLead: not implemented!" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
vector<NodeID> arguments_subst;
|
||||
for (vector<NodeID>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
|
||||
arguments_subst.push_back((*it)->substituteExoLead(subst_table, neweqs));
|
||||
return buildSimilarExternalFunctionNode(arguments_subst, datatree);
|
||||
}
|
||||
|
||||
NodeID
|
||||
UnknownFunctionNode::substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
|
||||
ExternalFunctionNode::substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
|
||||
{
|
||||
cerr << "UnknownFunctionNode::substituteExoLag: not implemented!" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
vector<NodeID> arguments_subst;
|
||||
for (vector<NodeID>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
|
||||
arguments_subst.push_back((*it)->substituteExoLag(subst_table, neweqs));
|
||||
return buildSimilarExternalFunctionNode(arguments_subst, datatree);
|
||||
}
|
||||
|
||||
NodeID
|
||||
UnknownFunctionNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const
|
||||
ExternalFunctionNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const
|
||||
{
|
||||
cerr << "UnknownFunctionNode::substituteExpectation: not implemented!" << endl;
|
||||
vector<NodeID> arguments_subst;
|
||||
for (vector<NodeID>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
|
||||
arguments_subst.push_back((*it)->substituteExpectation(subst_table, neweqs, partial_information_model));
|
||||
return buildSimilarExternalFunctionNode(arguments_subst, datatree);
|
||||
}
|
||||
|
||||
NodeID
|
||||
ExternalFunctionNode::buildSimilarExternalFunctionNode(vector<NodeID> &alt_args, DataTree &alt_datatree) const
|
||||
{
|
||||
return alt_datatree.AddExternalFunction(symb_id, alt_args);
|
||||
}
|
||||
|
||||
FirstDerivExternalFunctionNode::FirstDerivExternalFunctionNode(DataTree &datatree_arg,
|
||||
int top_level_symb_id_arg,
|
||||
const vector<NodeID> &arguments_arg,
|
||||
int inputIndex_arg) :
|
||||
ExternalFunctionNode(datatree_arg, top_level_symb_id_arg, arguments_arg),
|
||||
inputIndex(inputIndex_arg)
|
||||
{
|
||||
}
|
||||
|
||||
NodeID
|
||||
FirstDerivExternalFunctionNode::composeDerivatives(const vector<NodeID> &dargs)
|
||||
{
|
||||
vector<NodeID> dNodes;
|
||||
for (int i = 0; i < (int)dargs.size(); i++)
|
||||
if (dargs.at(i) != 0)
|
||||
dNodes.push_back(datatree.AddTimes(dargs.at(i),
|
||||
datatree.AddSecondDerivExternalFunctionNode(symb_id, arguments, inputIndex, i+1)));
|
||||
|
||||
NodeID theDeriv = datatree.Zero;
|
||||
for (vector<NodeID>::const_iterator it = dNodes.begin(); it != dNodes.end(); it++)
|
||||
theDeriv = datatree.AddPlus(theDeriv, *it);
|
||||
return theDeriv;
|
||||
}
|
||||
|
||||
void
|
||||
FirstDerivExternalFunctionNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
|
||||
const temporary_terms_type &temporary_terms) const
|
||||
{
|
||||
int first_deriv_symb_id = datatree.external_functions_table.getFirstDerivSymbID(symb_id);
|
||||
switch (first_deriv_symb_id)
|
||||
{
|
||||
case eExtFunSetButNoNameProvided:
|
||||
cerr << "ERROR in: FirstDerivExternalFunctionNode::writeOutput(). Please inform Dynare Team." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
case eExtFunNotSet:
|
||||
output << "jacob_element(@" << datatree.symbol_table.getName(symb_id) << ","
|
||||
<< inputIndex << ",{";
|
||||
break;
|
||||
default:
|
||||
int numOutArgs;
|
||||
if (first_deriv_symb_id==symb_id)
|
||||
numOutArgs = 2; // means that the external function also returns at least the first derivative
|
||||
else
|
||||
numOutArgs = 1; // means that there is a function that returns only the second derivative
|
||||
output << "subscript_get(" << numOutArgs << ",@" << datatree.symbol_table.getName(first_deriv_symb_id) << ",{";
|
||||
}
|
||||
|
||||
for (vector<NodeID>::const_iterator it = arguments.begin();
|
||||
it != arguments.end(); it++)
|
||||
{
|
||||
if (it != arguments.begin())
|
||||
output << ",";
|
||||
|
||||
(*it)->writeOutput(output, output_type, temporary_terms);
|
||||
}
|
||||
|
||||
output << "}";
|
||||
if (first_deriv_symb_id!=eExtFunNotSet)
|
||||
output << "," << inputIndex;
|
||||
output << ")";
|
||||
}
|
||||
|
||||
SecondDerivExternalFunctionNode::SecondDerivExternalFunctionNode(DataTree &datatree_arg,
|
||||
int top_level_symb_id_arg,
|
||||
const vector<NodeID> &arguments_arg,
|
||||
int inputIndex1_arg,
|
||||
int inputIndex2_arg) :
|
||||
ExternalFunctionNode(datatree_arg, top_level_symb_id_arg, arguments_arg),
|
||||
inputIndex1(inputIndex1_arg),
|
||||
inputIndex2(inputIndex2_arg)
|
||||
{
|
||||
}
|
||||
|
||||
NodeID
|
||||
SecondDerivExternalFunctionNode::computeDerivative(int deriv_id)
|
||||
{
|
||||
cerr << "ERROR: SecondDerivExternalFunctionNode::computeDerivative(). Not implemented" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void
|
||||
SecondDerivExternalFunctionNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
|
||||
const temporary_terms_type &temporary_terms) const
|
||||
{
|
||||
int second_deriv_symb_id = datatree.external_functions_table.getSecondDerivSymbID(symb_id);
|
||||
switch (second_deriv_symb_id)
|
||||
{
|
||||
case eExtFunSetButNoNameProvided:
|
||||
cerr << "ERROR in: FirstDerivExternalFunctionNode::writeOutput(). Please inform Dynare Team." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
case eExtFunNotSet:
|
||||
output << "hess_element(@" << datatree.symbol_table.getName(symb_id) << ","
|
||||
<< inputIndex1 << "," << inputIndex2 << ",{";
|
||||
break;
|
||||
default:
|
||||
int numOutArgs;
|
||||
if (second_deriv_symb_id==symb_id)
|
||||
numOutArgs = 3; // means that the external function also returns the first and second derivatives
|
||||
else
|
||||
numOutArgs = 1; // means that there is a function that returns only the second derivative
|
||||
output << "subscript_get(" << numOutArgs << ",@" << datatree.symbol_table.getName(second_deriv_symb_id) << ",{";
|
||||
}
|
||||
|
||||
for (vector<NodeID>::const_iterator it = arguments.begin();
|
||||
it != arguments.end(); it++)
|
||||
{
|
||||
if (it != arguments.begin())
|
||||
output << ",";
|
||||
(*it)->writeOutput(output, output_type, temporary_terms);
|
||||
}
|
||||
|
||||
output << "}";
|
||||
if (second_deriv_symb_id!=eExtFunNotSet)
|
||||
output << "," << inputIndex1 << "," << inputIndex2;
|
||||
output << ")";
|
||||
}
|
||||
|
|
44
ExprNode.hh
44
ExprNode.hh
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 Dynare Team
|
||||
* Copyright (C) 2007-2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -29,6 +29,7 @@ using namespace std;
|
|||
|
||||
#include "SymbolTable.hh"
|
||||
#include "CodeInterpreter.hh"
|
||||
#include "ExternalFunctionsTable.hh"
|
||||
|
||||
class DataTree;
|
||||
class VariableNode;
|
||||
|
@ -115,7 +116,7 @@ class ExprNode
|
|||
friend class UnaryOpNode;
|
||||
friend class BinaryOpNode;
|
||||
friend class TrinaryOpNode;
|
||||
|
||||
friend class ExternalFunctionNode;
|
||||
private:
|
||||
//! Computes derivative w.r. to a derivation ID (but doesn't store it in derivatives map)
|
||||
/*! You shoud use getDerivative() to get the benefit of symbolic a priori and of caching */
|
||||
|
@ -568,15 +569,17 @@ public:
|
|||
virtual NodeID decreaseLeadsLagsPredeterminedVariables() const;
|
||||
};
|
||||
|
||||
//! Unknown function node
|
||||
class UnknownFunctionNode : public ExprNode
|
||||
//! External function node
|
||||
class ExternalFunctionNode : public ExprNode
|
||||
{
|
||||
private:
|
||||
virtual NodeID computeDerivative(int deriv_id);
|
||||
virtual NodeID composeDerivatives(const vector<NodeID> &dargs);
|
||||
protected:
|
||||
const int symb_id;
|
||||
const vector<NodeID> arguments;
|
||||
virtual NodeID computeDerivative(int deriv_id);
|
||||
public:
|
||||
UnknownFunctionNode(DataTree &datatree_arg, int symb_id_arg,
|
||||
ExternalFunctionNode(DataTree &datatree_arg, int symb_id_arg,
|
||||
const vector<NodeID> &arguments_arg);
|
||||
virtual void prepareForDerivation();
|
||||
virtual void computeTemporaryTerms(map<NodeID, int> &reference_count, temporary_terms_type &temporary_terms, bool is_matlab) const;
|
||||
|
@ -602,7 +605,36 @@ public:
|
|||
virtual NodeID substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
|
||||
virtual NodeID substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
|
||||
virtual NodeID substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const;
|
||||
virtual NodeID buildSimilarExternalFunctionNode(vector<NodeID> &alt_args, DataTree &alt_datatree) const;
|
||||
virtual NodeID decreaseLeadsLagsPredeterminedVariables() const;
|
||||
};
|
||||
|
||||
class FirstDerivExternalFunctionNode : public ExternalFunctionNode
|
||||
{
|
||||
private:
|
||||
const int inputIndex;
|
||||
virtual NodeID composeDerivatives(const vector<NodeID> &dargs);
|
||||
public:
|
||||
FirstDerivExternalFunctionNode(DataTree &datatree_arg,
|
||||
int top_level_symb_id_arg,
|
||||
const vector<NodeID> &arguments_arg,
|
||||
int inputIndex_arg);
|
||||
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_type &temporary_terms) const;
|
||||
};
|
||||
|
||||
class SecondDerivExternalFunctionNode : public ExternalFunctionNode
|
||||
{
|
||||
private:
|
||||
const int inputIndex1;
|
||||
const int inputIndex2;
|
||||
virtual NodeID computeDerivative(int deriv_id);
|
||||
public:
|
||||
SecondDerivExternalFunctionNode(DataTree &datatree_arg,
|
||||
int top_level_symb_id_arg,
|
||||
const vector<NodeID> &arguments_arg,
|
||||
int inputIndex1_arg,
|
||||
int inputIndex2_arg);
|
||||
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_type &temporary_terms) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <cerrno>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
#include "ExternalFunctionsTable.hh"
|
||||
#include "SymbolTable.hh"
|
||||
|
||||
ExternalFunctionsTable::ExternalFunctionsTable()
|
||||
{
|
||||
};
|
||||
|
||||
void
|
||||
ExternalFunctionsTable::addExternalFunction(const int symb_id, const external_function_options external_function_options_arg)
|
||||
{
|
||||
assert(symb_id >= 0);
|
||||
|
||||
if (external_function_options_arg.secondDerivSymbID > eExtFunNotSet &&
|
||||
external_function_options_arg.firstDerivSymbID == eExtFunNotSet)
|
||||
{
|
||||
cerr << "If the second derivative is provided to the external_function() command,"
|
||||
<< "the first derivative must also be provided." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (external_function_options_arg.nargs <= 0)
|
||||
{
|
||||
cerr << "The number of arguments passed to an external function must be > 0." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
external_function_options external_function_options_chng = external_function_options_arg;
|
||||
if (external_function_options_arg.firstDerivSymbID == eExtFunSetButNoNameProvided)
|
||||
external_function_options_chng.firstDerivSymbID = symb_id;
|
||||
|
||||
if (external_function_options_arg.secondDerivSymbID == eExtFunSetButNoNameProvided)
|
||||
external_function_options_chng.secondDerivSymbID = symb_id;
|
||||
|
||||
externalFunctionTable[symb_id] = external_function_options_chng;
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
* Dynare is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Dynare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _EXTERNALFUNCTIONSTABLE_HH
|
||||
#define _EXTERNALFUNCTIONSTABLE_HH
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
enum ExternalFunctionSetOrNot
|
||||
{
|
||||
eExtFunSetButNoNameProvided = -2, //! Signifies that the derivative is obtained from the top-level function
|
||||
eExtFunNotSet = -1, //! Signifies that no external function exists that calculates the derivative
|
||||
eExtFunSetDefaultNargs = 1 //! This is the default number of arguments when nargs is not specified
|
||||
};
|
||||
|
||||
//! Handles external functions
|
||||
class ExternalFunctionsTable
|
||||
{
|
||||
public:
|
||||
//! Thrown when trying to access an unknown symbol (by id)
|
||||
class UnknownExternalFunctionSymbolIDException
|
||||
{
|
||||
public:
|
||||
//! Symbol ID
|
||||
int id;
|
||||
UnknownExternalFunctionSymbolIDException(int id_arg) : id(id_arg)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/* For all arguments, -2 means not set
|
||||
* For firstDerivSymbID and secondDerivSymbID, -1 means that the derivatives are
|
||||
* provided in the main function given in the by the "name" option to the
|
||||
* external_function() statement.
|
||||
*/
|
||||
struct external_function_options
|
||||
{
|
||||
int nargs, firstDerivSymbID, secondDerivSymbID;
|
||||
};
|
||||
typedef map<int, external_function_options> external_function_table_type;
|
||||
private:
|
||||
//! Map containing options provided to external_functions()
|
||||
external_function_table_type externalFunctionTable;
|
||||
public:
|
||||
ExternalFunctionsTable();
|
||||
//! Adds an external function to the table as well as its derivative functions
|
||||
void addExternalFunction(const int symb_id, const external_function_options external_function_options_arg);
|
||||
//! See if the function exists in the External Functions Table
|
||||
inline bool exists(const int symb_id) const;
|
||||
//! Get the number of arguments for a given external function
|
||||
inline int getNargs(const int symb_id) const throw (UnknownExternalFunctionSymbolIDException);
|
||||
//! Get the symbol_id of the first derivative function
|
||||
inline int getFirstDerivSymbID(const int symb_id) const throw (UnknownExternalFunctionSymbolIDException);
|
||||
//! Get the symbol_id of the second derivative function
|
||||
inline int getSecondDerivSymbID(const int symb_id) const throw (UnknownExternalFunctionSymbolIDException);
|
||||
//! Returns the total number of unique external functions declared or used in the .mod file
|
||||
inline int get_total_number_of_unique_external_functions();
|
||||
};
|
||||
|
||||
inline bool
|
||||
ExternalFunctionsTable::exists(const int symb_id) const
|
||||
{
|
||||
external_function_table_type::const_iterator iter = externalFunctionTable.find(symb_id);
|
||||
return (iter != externalFunctionTable.end());
|
||||
}
|
||||
|
||||
inline int
|
||||
ExternalFunctionsTable::getNargs(const int symb_id) const throw (UnknownExternalFunctionSymbolIDException)
|
||||
{
|
||||
if (exists(symb_id))
|
||||
return externalFunctionTable.find(symb_id)->second.nargs;
|
||||
else
|
||||
{
|
||||
cout << "In get_nargs(): id: " << symb_id << endl;
|
||||
throw UnknownExternalFunctionSymbolIDException(symb_id);
|
||||
}
|
||||
}
|
||||
|
||||
inline int
|
||||
ExternalFunctionsTable::getFirstDerivSymbID(const int symb_id) const throw (UnknownExternalFunctionSymbolIDException)
|
||||
{
|
||||
if (exists(symb_id))
|
||||
return externalFunctionTable.find(symb_id)->second.firstDerivSymbID;
|
||||
else
|
||||
{
|
||||
cout << "In getFirstDerivSymbID(): id: " << symb_id << endl;
|
||||
throw UnknownExternalFunctionSymbolIDException(symb_id);
|
||||
}
|
||||
}
|
||||
|
||||
inline int
|
||||
ExternalFunctionsTable::getSecondDerivSymbID(const int symb_id) const throw (UnknownExternalFunctionSymbolIDException)
|
||||
{
|
||||
if (exists(symb_id))
|
||||
return externalFunctionTable.find(symb_id)->second.secondDerivSymbID;
|
||||
else
|
||||
{
|
||||
cout << "In getSecondDerivSymbID(): id: " << symb_id << endl;
|
||||
throw UnknownExternalFunctionSymbolIDException(symb_id);
|
||||
}
|
||||
}
|
||||
|
||||
inline int
|
||||
ExternalFunctionsTable::get_total_number_of_unique_external_functions()
|
||||
{
|
||||
return externalFunctionTable.size();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -45,7 +45,9 @@ dynare_m_SOURCES = \
|
|||
DynareMain.cc \
|
||||
DynareMain2.cc \
|
||||
CodeInterpreter.hh \
|
||||
FlexLexer.h
|
||||
FlexLexer.h \
|
||||
ExternalFunctionsTable.cc \
|
||||
ExternalFunctionsTable.hh
|
||||
|
||||
# The -I. is for <FlexLexer.h>
|
||||
dynare_m_CPPFLAGS = $(BOOST_CPPFLAGS) -I.
|
||||
|
|
14
ModFile.cc
14
ModFile.cc
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2009 Dynare Team
|
||||
* Copyright (C) 2006-2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -23,9 +23,9 @@
|
|||
#include <typeinfo>
|
||||
#include "ModFile.hh"
|
||||
|
||||
ModFile::ModFile() : expressions_tree(symbol_table, num_constants),
|
||||
static_model(symbol_table, num_constants),
|
||||
dynamic_model(symbol_table, num_constants),
|
||||
ModFile::ModFile() : expressions_tree(symbol_table, num_constants, external_functions_table),
|
||||
static_model(symbol_table, num_constants, external_functions_table),
|
||||
dynamic_model(symbol_table, num_constants, external_functions_table),
|
||||
linear(false), block(false), byte_code(false),
|
||||
use_dll(false), no_static(false)
|
||||
{
|
||||
|
@ -134,6 +134,12 @@ ModFile::checkPass()
|
|||
cerr << "no_static option is incompatible with stochastic simulation, estimation, optimal policy, steady or check command" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if ((use_dll || byte_code) && external_functions_table.get_total_number_of_unique_external_functions())
|
||||
{
|
||||
cerr << "ERROR: In 'model' block, use of external functions is not compatible with 'use_dll' or 'bytecode'" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2006-2009 Dynare Team
|
||||
* Copyright (C) 2006-2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -31,6 +31,7 @@ using namespace std;
|
|||
#include "StaticModel.hh"
|
||||
#include "DynamicModel.hh"
|
||||
#include "Statement.hh"
|
||||
#include "ExternalFunctionsTable.hh"
|
||||
|
||||
//! The abstract representation of a "mod" file
|
||||
class ModFile
|
||||
|
@ -40,6 +41,8 @@ public:
|
|||
~ModFile();
|
||||
//! Symbol table
|
||||
SymbolTable symbol_table;
|
||||
//! External Functions table
|
||||
ExternalFunctionsTable external_functions_table;
|
||||
//! Numerical constants table
|
||||
NumericalConstants num_constants;
|
||||
//! Expressions outside model block
|
||||
|
|
|
@ -855,8 +855,9 @@ ModelTree::BlockLinear(t_blocks_derivatives &blocks_derivatives, vector<int> &va
|
|||
}
|
||||
|
||||
ModelTree::ModelTree(SymbolTable &symbol_table_arg,
|
||||
NumericalConstants &num_constants_arg) :
|
||||
DataTree(symbol_table_arg, num_constants_arg)
|
||||
NumericalConstants &num_constants_arg,
|
||||
ExternalFunctionsTable &external_functions_table_arg) :
|
||||
DataTree(symbol_table_arg, num_constants_arg, external_functions_table_arg)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
NNZDerivatives[i] = 0;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2009 Dynare Team
|
||||
* Copyright (C) 2003-2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -213,7 +213,7 @@ protected:
|
|||
virtual int getBlockInitialVariableID(int block_number, int variable_number) const = 0;
|
||||
|
||||
public:
|
||||
ModelTree(SymbolTable &symbol_table_arg, NumericalConstants &num_constants);
|
||||
ModelTree(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg);
|
||||
//! Declare a node as an equation of the model
|
||||
void addEquation(NodeID eq);
|
||||
//! Adds tags to equation number i
|
||||
|
|
202
ParsingDriver.cc
202
ParsingDriver.cc
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2009 Dynare Team
|
||||
* Copyright (C) 2003-2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -20,19 +20,21 @@
|
|||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
#include "ParsingDriver.hh"
|
||||
#include "Statement.hh"
|
||||
#include <ExprNode.hh>
|
||||
|
||||
bool
|
||||
ParsingDriver::symbol_exists_and_is_not_modfile_local_or_unknown_function(const char *s)
|
||||
ParsingDriver::symbol_exists_and_is_not_modfile_local_or_external_function(const char *s)
|
||||
{
|
||||
if (!mod_file->symbol_table.exists(s))
|
||||
return false;
|
||||
|
||||
SymbolType type = mod_file->symbol_table.getType(s);
|
||||
|
||||
return (type != eModFileLocalVariable && type != eUnknownFunction);
|
||||
return (type != eModFileLocalVariable && type != eExternalFunction);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -56,6 +58,15 @@ ParsingDriver::reset_data_tree()
|
|||
set_current_data_tree(&mod_file->expressions_tree);
|
||||
}
|
||||
|
||||
void
|
||||
ParsingDriver::reset_current_external_function_options()
|
||||
{
|
||||
current_external_function_options.nargs = eExtFunSetDefaultNargs;
|
||||
current_external_function_options.firstDerivSymbID = eExtFunNotSet;
|
||||
current_external_function_options.secondDerivSymbID = eExtFunNotSet;
|
||||
current_external_function_name.clear();
|
||||
}
|
||||
|
||||
ModFile *
|
||||
ParsingDriver::parse(istream &in, bool debug)
|
||||
{
|
||||
|
@ -65,6 +76,7 @@ ParsingDriver::parse(istream &in, bool debug)
|
|||
|
||||
reset_data_tree();
|
||||
estim_params.init(*data_tree);
|
||||
reset_current_external_function_options();
|
||||
|
||||
lexer = new DynareFlex(&in);
|
||||
lexer->set_debug(debug);
|
||||
|
@ -98,7 +110,7 @@ ParsingDriver::warning(const string &m)
|
|||
}
|
||||
|
||||
void
|
||||
ParsingDriver::declare_symbol(string *name, SymbolType type, string *tex_name)
|
||||
ParsingDriver::declare_symbol(const string *name, const SymbolType type, const string *tex_name)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -114,34 +126,42 @@ ParsingDriver::declare_symbol(string *name, SymbolType type, string *tex_name)
|
|||
else
|
||||
error("Symbol " + *name + " declared twice with different types!");
|
||||
}
|
||||
|
||||
delete name;
|
||||
if (tex_name != NULL)
|
||||
delete tex_name;
|
||||
}
|
||||
|
||||
void
|
||||
ParsingDriver::declare_endogenous(string *name, string *tex_name)
|
||||
{
|
||||
declare_symbol(name, eEndogenous, tex_name);
|
||||
delete name;
|
||||
if (tex_name != NULL)
|
||||
delete tex_name;
|
||||
}
|
||||
|
||||
void
|
||||
ParsingDriver::declare_exogenous(string *name, string *tex_name)
|
||||
{
|
||||
declare_symbol(name, eExogenous, tex_name);
|
||||
delete name;
|
||||
if (tex_name != NULL)
|
||||
delete tex_name;
|
||||
}
|
||||
|
||||
void
|
||||
ParsingDriver::declare_exogenous_det(string *name, string *tex_name)
|
||||
{
|
||||
declare_symbol(name, eExogenousDet, tex_name);
|
||||
delete name;
|
||||
if (tex_name != NULL)
|
||||
delete tex_name;
|
||||
}
|
||||
|
||||
void
|
||||
ParsingDriver::declare_parameter(string *name, string *tex_name)
|
||||
{
|
||||
declare_symbol(name, eParameter, tex_name);
|
||||
delete name;
|
||||
if (tex_name != NULL)
|
||||
delete tex_name;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -194,32 +214,29 @@ ParsingDriver::add_inf_constant()
|
|||
NodeID
|
||||
ParsingDriver::add_model_variable(string *name)
|
||||
{
|
||||
return add_model_variable(name, new string("0"));
|
||||
check_symbol_existence(*name);
|
||||
int symb_id = mod_file->symbol_table.getID(*name);
|
||||
delete name;
|
||||
return add_model_variable(symb_id, 0);
|
||||
}
|
||||
|
||||
NodeID
|
||||
ParsingDriver::add_model_variable(string *name, string *olag)
|
||||
ParsingDriver::add_model_variable(int symb_id, int lag)
|
||||
{
|
||||
check_symbol_existence(*name);
|
||||
SymbolType type = mod_file->symbol_table.getType(*name);
|
||||
int lag = atoi(olag->c_str());
|
||||
assert(symb_id >= 0);
|
||||
SymbolType type = mod_file->symbol_table.getType(symb_id);
|
||||
|
||||
if (type == eModFileLocalVariable)
|
||||
error("Variable " + *name + " not allowed inside model declaration. Its scope is only outside model.");
|
||||
error("Variable " + mod_file->symbol_table.getName(symb_id) + " not allowed inside model declaration. Its scope is only outside model.");
|
||||
|
||||
if (type == eUnknownFunction)
|
||||
error("Symbol " + *name + " is a function name unknown to Dynare. It cannot be used inside model.");
|
||||
if (type == eExternalFunction)
|
||||
error("Symbol " + mod_file->symbol_table.getName(symb_id) + " is a function name external to Dynare. It cannot be used inside model.");
|
||||
|
||||
if (type == eModelLocalVariable && lag != 0)
|
||||
error("Model local variable " + *name + " cannot be given a lead or a lag.");
|
||||
error("Model local variable " + mod_file->symbol_table.getName(symb_id) + " cannot be given a lead or a lag.");
|
||||
|
||||
// It makes sense to allow a lead/lag on parameters: during steady state calibration, endogenous and parameters can be swapped
|
||||
|
||||
NodeID id = model_tree->AddVariable(*name, lag);
|
||||
|
||||
delete name;
|
||||
delete olag;
|
||||
return id;
|
||||
return model_tree->AddVariable(symb_id, lag);
|
||||
}
|
||||
|
||||
NodeID
|
||||
|
@ -1151,7 +1168,7 @@ ParsingDriver::run_model_comparison()
|
|||
void
|
||||
ParsingDriver::begin_planner_objective()
|
||||
{
|
||||
set_current_data_tree(new StaticModel(mod_file->symbol_table, mod_file->num_constants));
|
||||
set_current_data_tree(new StaticModel(mod_file->symbol_table, mod_file->num_constants, mod_file->external_functions_table));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1608,24 +1625,145 @@ ParsingDriver::add_steady_state(NodeID arg1)
|
|||
}
|
||||
|
||||
void
|
||||
ParsingDriver::add_unknown_function_arg(NodeID arg)
|
||||
ParsingDriver::external_function_option(const string &name_option, string *opt)
|
||||
{
|
||||
unknown_function_args.push_back(arg);
|
||||
external_function_option(name_option, *opt);
|
||||
}
|
||||
|
||||
void
|
||||
ParsingDriver::external_function_option(const string &name_option, const string &opt)
|
||||
{
|
||||
if (name_option == "name")
|
||||
{
|
||||
if (opt.empty())
|
||||
error("An argument must be passed to the 'name' option of the external_function() statement.");
|
||||
declare_symbol(&opt, eExternalFunction, NULL);
|
||||
current_external_function_name = opt;
|
||||
}
|
||||
else if (name_option == "first_deriv_provided")
|
||||
{
|
||||
if (opt.empty())
|
||||
current_external_function_options.firstDerivSymbID = eExtFunSetButNoNameProvided;
|
||||
else
|
||||
{
|
||||
declare_symbol(&opt, eExternalFunction, NULL);
|
||||
current_external_function_options.firstDerivSymbID = mod_file->symbol_table.getID(opt);
|
||||
}
|
||||
}
|
||||
else if (name_option == "second_deriv_provided")
|
||||
{
|
||||
if (opt.empty())
|
||||
current_external_function_options.secondDerivSymbID = eExtFunSetButNoNameProvided;
|
||||
else
|
||||
{
|
||||
declare_symbol(&opt, eExternalFunction, NULL);
|
||||
current_external_function_options.secondDerivSymbID = mod_file->symbol_table.getID(opt);
|
||||
}
|
||||
}
|
||||
else if (name_option == "nargs")
|
||||
current_external_function_options.nargs = atoi(opt.c_str());
|
||||
else
|
||||
error("Unexpected error in ParsingDriver::external_function_option(): Please inform Dynare Team.");
|
||||
}
|
||||
|
||||
void
|
||||
ParsingDriver::external_function()
|
||||
{
|
||||
if (current_external_function_name.empty())
|
||||
error("The 'name' option must be passed to external_function().");
|
||||
int function_symb_id = mod_file->symbol_table.getID(current_external_function_name);
|
||||
|
||||
if (current_external_function_options.secondDerivSymbID > eExtFunNotSet &&
|
||||
current_external_function_options.firstDerivSymbID == eExtFunNotSet)
|
||||
error("If the second derivative is provided to the external_function command, the first derivative must also be provided.");
|
||||
|
||||
mod_file->external_functions_table.addExternalFunction(function_symb_id, current_external_function_options);
|
||||
reset_current_external_function_options();
|
||||
}
|
||||
|
||||
void
|
||||
ParsingDriver::push_external_function_arg_vector_onto_stack()
|
||||
{
|
||||
vector<NodeID> emptyvec;
|
||||
stack_external_function_args.push(emptyvec);
|
||||
}
|
||||
|
||||
void
|
||||
ParsingDriver::add_external_function_arg(NodeID arg)
|
||||
{
|
||||
stack_external_function_args.top().push_back(arg);
|
||||
}
|
||||
|
||||
NodeID
|
||||
ParsingDriver::add_unknown_function(string *function_name)
|
||||
ParsingDriver::add_model_var_or_external_function(string *function_name)
|
||||
{
|
||||
if (mod_file->symbol_table.exists(*function_name))
|
||||
{
|
||||
if (mod_file->symbol_table.getType(*function_name) != eUnknownFunction)
|
||||
error("Symbol " + *function_name + " is not a function name.");
|
||||
if (mod_file->symbol_table.getType(*function_name) != eExternalFunction)
|
||||
{ // e.g. model_var(lag) => ADD MODEL VARIABLE WITH LEAD (NumConstNode)/LAG (UnaryOpNode)
|
||||
if ((int)stack_external_function_args.top().size() == 1)
|
||||
{
|
||||
NumConstNode *numNode = dynamic_cast<NumConstNode *>(stack_external_function_args.top().front());
|
||||
UnaryOpNode *unaryNode = dynamic_cast<UnaryOpNode *>(stack_external_function_args.top().front());
|
||||
|
||||
if (numNode == NULL && unaryNode == NULL)
|
||||
error("A model variable is being treated as if it were a function (i.e., takes an argument that is not an integer).");
|
||||
|
||||
eval_context_type ectmp;
|
||||
int model_var_arg;
|
||||
double model_var_arg_dbl;
|
||||
if (unaryNode == NULL)
|
||||
{
|
||||
model_var_arg = (int)numNode->eval(ectmp);
|
||||
model_var_arg_dbl = numNode->eval(ectmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unaryNode->get_op_code() != oUminus)
|
||||
error("A model variable is being treated as if it were a function (i.e., takes an argument that is not an integer).");
|
||||
else
|
||||
{
|
||||
model_var_arg = (int)unaryNode->eval(ectmp);
|
||||
model_var_arg_dbl = unaryNode->eval(ectmp);
|
||||
}
|
||||
}
|
||||
|
||||
if ((double) model_var_arg != model_var_arg_dbl) //make 100% sure int cast didn't lose info
|
||||
error("A model variable is being treated as if it were a function (i.e., takes an argument that is not an integer).");
|
||||
|
||||
NodeID nid = add_model_variable(mod_file->symbol_table.getID(*function_name), model_var_arg);
|
||||
stack_external_function_args.pop();
|
||||
delete function_name;
|
||||
return nid;
|
||||
}
|
||||
else
|
||||
error("A model variable is being treated as if it were a function (i.e., has received more than one argument).");
|
||||
}
|
||||
else
|
||||
{ // e.g. this function has already been referenced (either ad hoc or through the external_function() statement
|
||||
// => check that the information matches previously declared info
|
||||
int symb_id = mod_file->symbol_table.getID(*function_name);
|
||||
if (!mod_file->external_functions_table.exists(symb_id))
|
||||
error("In ParsingDriver::add_external_function()(1) Please report to Dynare Team.");
|
||||
|
||||
if ((int)(stack_external_function_args.top().size()) != mod_file->external_functions_table.getNargs(symb_id))
|
||||
error("The number of arguments passed to " + *function_name +
|
||||
" does not match those of a previous call or declaration of this function.");
|
||||
}
|
||||
}
|
||||
else
|
||||
mod_file->symbol_table.addSymbol(*function_name, eUnknownFunction);
|
||||
{ //First time encountering this external function i.e., not previously declared or encountered
|
||||
declare_symbol(function_name, eExternalFunction, NULL);
|
||||
current_external_function_options.nargs = stack_external_function_args.top().size();
|
||||
mod_file->external_functions_table.addExternalFunction(mod_file->symbol_table.getID(*function_name),
|
||||
current_external_function_options);
|
||||
reset_current_external_function_options();
|
||||
}
|
||||
|
||||
NodeID id = data_tree->AddUnknownFunction(*function_name, unknown_function_args);
|
||||
unknown_function_args.clear();
|
||||
//By this point, we're sure that this function exists in the External Functions Table and is not a mod var
|
||||
NodeID id = data_tree->AddExternalFunction(*function_name, stack_external_function_args.top());
|
||||
stack_external_function_args.pop();
|
||||
delete function_name;
|
||||
return id;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2009 Dynare Team
|
||||
* Copyright (C) 2003-2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -27,6 +27,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <istream>
|
||||
#include <stack>
|
||||
|
||||
#include "ModFile.hh"
|
||||
#include "SymbolList.hh"
|
||||
|
@ -78,7 +79,7 @@ private:
|
|||
void check_symbol_existence(const string &name);
|
||||
|
||||
//! Helper to add a symbol declaration
|
||||
void declare_symbol(string *name, SymbolType type, string *tex_name);
|
||||
void declare_symbol(const string *name, const SymbolType type, const string *tex_name);
|
||||
|
||||
//! Creates option "optim_opt" in OptionsList if it doesn't exist, else add a comma, and adds the option name
|
||||
void optim_options_helper(const string &name);
|
||||
|
@ -153,12 +154,17 @@ private:
|
|||
//! Temporary storage for lower cholesky within an svar_identification bock
|
||||
bool svar_lower_cholesky;
|
||||
|
||||
//! Temporary storage for argument list of unknown function
|
||||
vector<NodeID> unknown_function_args;
|
||||
//! Temporary storage for argument list of external function
|
||||
stack<vector<NodeID> > stack_external_function_args;
|
||||
//! Temporary storage for the symb_id associated with the "name" symbol of the current external_function statement
|
||||
string current_external_function_name;
|
||||
//! Temporary storage for option list provided to external_function()
|
||||
ExternalFunctionsTable::external_function_options current_external_function_options;
|
||||
//! reset the values for temporary storage
|
||||
void reset_current_external_function_options();
|
||||
|
||||
//! The mod file representation constructed by this ParsingDriver
|
||||
ModFile *mod_file;
|
||||
|
||||
public:
|
||||
//! Starts parsing, and constructs the MOD file representation
|
||||
/*! The returned pointer should be deleted after use */
|
||||
|
@ -181,7 +187,7 @@ public:
|
|||
void warning(const string &m);
|
||||
|
||||
//! Check if a given symbol exists in the parsing context, and is not a mod file local variable
|
||||
bool symbol_exists_and_is_not_modfile_local_or_unknown_function(const char *s);
|
||||
bool symbol_exists_and_is_not_modfile_local_or_external_function(const char *s);
|
||||
//! Sets mode of ModelTree class to use C output
|
||||
void use_dll();
|
||||
//! the modelis block decomposed
|
||||
|
@ -221,7 +227,7 @@ public:
|
|||
//! Adds a model variable to ModelTree and VariableTable
|
||||
NodeID add_model_variable(string *name);
|
||||
//! Adds a model lagged variable to ModelTree and VariableTable
|
||||
NodeID add_model_variable(string *name, string *olag);
|
||||
NodeID add_model_variable(int symb_id, int lag);
|
||||
//! Adds an Expression's variable
|
||||
NodeID add_expression_variable(string *name);
|
||||
//! Adds a "periods" statement
|
||||
|
@ -315,6 +321,12 @@ public:
|
|||
void estimated_params_init();
|
||||
//! Writes estimated params bound command
|
||||
void estimated_params_bounds();
|
||||
//! Adds a declaration for a user-defined external function
|
||||
void external_function();
|
||||
//! Sets an external_function option to a string value
|
||||
void external_function_option(const string &name_option, string *opt);
|
||||
//! Sets an external_function option to a string value
|
||||
void external_function_option(const string &name_option, const string &opt);
|
||||
//! Add a line in an estimated params block
|
||||
void add_estimated_params_element();
|
||||
//! Runs estimation process
|
||||
|
@ -467,10 +479,12 @@ public:
|
|||
NodeID add_normcdf(NodeID arg);
|
||||
//! Writes token "steadyState(arg1)" to model tree
|
||||
NodeID add_steady_state(NodeID arg1);
|
||||
//! Adds an unknwon function argument
|
||||
void add_unknown_function_arg(NodeID arg);
|
||||
//! Adds an unknown function call node
|
||||
NodeID add_unknown_function(string *function_name);
|
||||
//! Pushes empty vector onto stack when a symbol is encountered (mod_var or ext_fun)
|
||||
void push_external_function_arg_vector_onto_stack();
|
||||
//! Adds an external function argument
|
||||
void add_external_function_arg(NodeID arg);
|
||||
//! Adds an external function call node
|
||||
NodeID add_model_var_or_external_function(string *function_name);
|
||||
//! Adds a native statement
|
||||
void add_native(const char *s);
|
||||
//! Resets data_tree and model_tree pointers to default (i.e. mod_file->expressions_tree)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2009 Dynare Team
|
||||
* Copyright (C) 2003-2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -36,8 +36,9 @@
|
|||
#endif
|
||||
|
||||
StaticModel::StaticModel(SymbolTable &symbol_table_arg,
|
||||
NumericalConstants &num_constants_arg) :
|
||||
ModelTree(symbol_table_arg, num_constants_arg),
|
||||
NumericalConstants &num_constants_arg,
|
||||
ExternalFunctionsTable &external_functions_table_arg) :
|
||||
ModelTree(symbol_table_arg, num_constants_arg, external_functions_table_arg),
|
||||
global_temporary_terms(true),
|
||||
cutoff(1e-15),
|
||||
mfs(0)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2009 Dynare Team
|
||||
* Copyright (C) 2003-2010 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -151,7 +151,7 @@ protected:
|
|||
vector<pair<int, int> > endo_max_leadlag_block, other_endo_max_leadlag_block, exo_max_leadlag_block, exo_det_max_leadlag_block, max_leadlag_block;
|
||||
|
||||
public:
|
||||
StaticModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants);
|
||||
StaticModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants, ExternalFunctionsTable &external_functions_table_arg);
|
||||
|
||||
//! Writes information on block decomposition when relevant
|
||||
void writeOutput(ostream &output, bool block) const;
|
||||
|
|
Loading…
Reference in New Issue