2008-02-03 11:28:36 +01:00
/*
2009-01-21 15:39:24 +01:00
* Copyright ( C ) 2007 - 2009 Dynare Team
2008-02-03 11:28:36 +01:00
*
* 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 <iostream>
# include <iterator>
# include <algorithm>
2009-07-13 11:13:42 +02:00
// For select1st()
# ifdef __GNUC__
# include <ext / functional>
using namespace __gnu_cxx ;
# endif
2009-07-10 18:42:08 +02:00
2009-04-28 18:21:39 +02:00
# include <cassert>
2008-02-19 15:35:59 +01:00
# include <cmath>
2008-02-03 11:28:36 +01:00
# include "ExprNode.hh"
# include "DataTree.hh"
2009-07-06 12:36:36 +02:00
# include "BlockTriangular.hh"
2008-02-03 11:28:36 +01:00
2009-09-30 17:10:31 +02:00
ExprNode : : ExprNode ( DataTree & datatree_arg ) : datatree ( datatree_arg ) , preparedForDerivation ( false )
2008-02-03 11:28:36 +01:00
{
// Add myself to datatree
datatree . node_list . push_back ( this ) ;
// Set my index and increment counter
idx = datatree . node_counter + + ;
}
ExprNode : : ~ ExprNode ( )
{
}
NodeID
2009-04-17 18:26:23 +02:00
ExprNode : : getDerivative ( int deriv_id )
2008-02-03 11:28:36 +01:00
{
2009-09-30 17:10:31 +02:00
if ( ! preparedForDerivation )
prepareForDerivation ( ) ;
2009-10-02 19:02:35 +02:00
2008-02-03 11:28:36 +01:00
// Return zero if derivative is necessarily null (using symbolic a priori)
2009-04-17 18:26:23 +02:00
set < int > : : const_iterator it = non_null_derivatives . find ( deriv_id ) ;
2008-02-03 11:28:36 +01:00
if ( it = = non_null_derivatives . end ( ) )
return datatree . Zero ;
2009-10-02 19:02:35 +02:00
2008-02-03 11:28:36 +01:00
// If derivative is stored in cache, use the cached value, otherwise compute it (and cache it)
2009-04-17 18:26:23 +02:00
map < int , NodeID > : : const_iterator it2 = derivatives . find ( deriv_id ) ;
2008-02-03 11:28:36 +01:00
if ( it2 ! = derivatives . end ( ) )
return it2 - > second ;
else
{
2009-04-17 18:26:23 +02:00
NodeID d = computeDerivative ( deriv_id ) ;
derivatives [ deriv_id ] = d ;
2008-02-03 11:28:36 +01:00
return d ;
}
}
2009-06-05 16:45:23 +02:00
int
ExprNode : : precedence ( ExprNodeOutputType output_type , const temporary_terms_type & temporary_terms ) const
{
// For a constant, a variable, or a unary op, the precedence is maximal
return 100 ;
}
2008-02-03 11:28:36 +01:00
int
ExprNode : : cost ( const temporary_terms_type & temporary_terms , bool is_matlab ) const
2009-06-05 16:45:23 +02:00
{
// For a terminal node, the cost is null
return 0 ;
}
2008-02-03 11:28:36 +01:00
2009-07-10 18:42:08 +02:00
void
ExprNode : : collectEndogenous ( set < pair < int , int > > & result ) const
{
set < pair < int , int > > symb_ids ;
collectVariables ( eEndogenous , symb_ids ) ;
for ( set < pair < int , int > > : : const_iterator it = symb_ids . begin ( ) ;
it ! = symb_ids . end ( ) ; it + + )
result . insert ( make_pair ( datatree . symbol_table . getTypeSpecificID ( it - > first ) , it - > second ) ) ;
}
void
ExprNode : : collectExogenous ( set < pair < int , int > > & result ) const
{
set < pair < int , int > > symb_ids ;
collectVariables ( eExogenous , symb_ids ) ;
for ( set < pair < int , int > > : : const_iterator it = symb_ids . begin ( ) ;
it ! = symb_ids . end ( ) ; it + + )
result . insert ( make_pair ( datatree . symbol_table . getTypeSpecificID ( it - > first ) , it - > second ) ) ;
}
void
ExprNode : : collectModelLocalVariables ( set < int > & result ) const
{
set < pair < int , int > > symb_ids ;
collectVariables ( eModelLocalVariable , symb_ids ) ;
transform ( symb_ids . begin ( ) , symb_ids . end ( ) , inserter ( result , result . begin ( ) ) ,
2009-07-13 11:13:42 +02:00
select1st < pair < int , int > > ( ) ) ;
2009-07-10 18:42:08 +02:00
}
2008-02-03 11:28:36 +01:00
void
ExprNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
temporary_terms_type & temporary_terms ,
bool is_matlab ) const
2009-06-05 16:45:23 +02:00
{
// Nothing to do for a terminal node
}
2008-02-03 11:28:36 +01:00
void
ExprNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
temporary_terms_type & temporary_terms ,
2009-01-02 14:00:43 +01:00
map < NodeID , pair < int , int > > & first_occurence ,
2008-02-03 11:28:36 +01:00
int Curr_block ,
Model_Block * ModelBlock ,
2009-01-02 14:00:43 +01:00
int equation ,
2008-02-03 11:28:36 +01:00
map_idx_type & map_idx ) const
2009-06-05 16:45:23 +02:00
{
// Nothing to do for a terminal node
}
2008-02-03 11:28:36 +01:00
2009-08-25 11:43:01 +02:00
pair < int , NodeID >
ExprNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < NodeID , NodeID > > > & List_of_Op_RHS ) const
{
return ( make_pair ( 0 , ( NodeID ) NULL ) ) ;
}
2008-02-03 11:28:36 +01:00
void
ExprNode : : writeOutput ( ostream & output )
{
writeOutput ( output , oMatlabOutsideModel , temporary_terms_type ( ) ) ;
}
2009-09-30 17:10:31 +02:00
VariableNode *
ExprNode : : createLeadAuxiliaryVarForMyself ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
int n = maxEndoLead ( ) ;
assert ( n > = 2 ) ;
subst_table_t : : const_iterator it = subst_table . find ( this ) ;
if ( it ! = subst_table . end ( ) )
return const_cast < VariableNode * > ( it - > second ) ;
NodeID substexpr = decreaseLeadsLags ( n - 1 ) ;
int lag = n - 2 ;
// Each iteration tries to create an auxvar such that auxvar(+1)=expr(-lag)
// At the beginning (resp. end) of each iteration, substexpr is an expression (possibly an auxvar) equivalent to expr(-lag-1) (resp. expr(-lag))
while ( lag > = 0 )
{
NodeID orig_expr = decreaseLeadsLags ( lag ) ;
it = subst_table . find ( orig_expr ) ;
if ( it = = subst_table . end ( ) )
{
int symb_id = datatree . symbol_table . addLeadAuxiliaryVar ( orig_expr - > idx ) ;
neweqs . push_back ( dynamic_cast < BinaryOpNode * > ( datatree . AddEqual ( datatree . AddVariable ( symb_id , 0 ) , substexpr ) ) ) ;
substexpr = datatree . AddVariable ( symb_id , + 1 ) ;
assert ( dynamic_cast < VariableNode * > ( substexpr ) ! = NULL ) ;
subst_table [ orig_expr ] = dynamic_cast < VariableNode * > ( substexpr ) ;
}
else
substexpr = const_cast < VariableNode * > ( it - > second ) ;
lag - - ;
}
return dynamic_cast < VariableNode * > ( substexpr ) ;
}
2009-04-14 16:39:53 +02:00
2008-02-03 11:28:36 +01:00
NumConstNode : : NumConstNode ( DataTree & datatree_arg , int id_arg ) :
2009-06-05 16:45:23 +02:00
ExprNode ( datatree_arg ) ,
id ( id_arg )
2008-02-03 11:28:36 +01:00
{
// Add myself to the num const map
datatree . num_const_node_map [ id ] = this ;
2009-09-30 17:10:31 +02:00
}
2008-02-03 11:28:36 +01:00
2009-09-30 17:10:31 +02:00
void
NumConstNode : : prepareForDerivation ( )
{
preparedForDerivation = true ;
2008-02-03 11:28:36 +01:00
// All derivatives are null, so non_null_derivatives is left empty
}
NodeID
2009-04-17 18:26:23 +02:00
NumConstNode : : computeDerivative ( int deriv_id )
2008-02-03 11:28:36 +01:00
{
return datatree . Zero ;
}
2008-12-24 16:49:01 +01:00
void
NumConstNode : : collectTemporary_terms ( const temporary_terms_type & temporary_terms , Model_Block * ModelBlock , int Curr_Block ) const
2009-06-05 16:45:23 +02:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < NumConstNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
ModelBlock - > Block_List [ Curr_Block ] . Temporary_InUse - > insert ( idx ) ;
}
2008-12-24 16:49:01 +01:00
2008-02-03 11:28:36 +01:00
void
NumConstNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_type & temporary_terms ) const
2009-06-05 16:45:23 +02:00
{
//cout << "writeOutput constante\n";
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < NumConstNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
if ( output_type = = oMatlabDynamicModelSparse )
output < < " T " < < idx < < " (it_) " ;
else
output < < " T " < < idx ;
2008-02-03 11:28:36 +01:00
else
2009-06-05 16:45:23 +02:00
output < < datatree . num_constants . get ( id ) ;
}
2008-02-03 11:28:36 +01:00
double
NumConstNode : : eval ( const eval_context_type & eval_context ) const throw ( EvalException )
{
return ( datatree . num_constants . getDouble ( id ) ) ;
}
void
2009-09-18 18:34:11 +02:00
NumConstNode : : compile ( ostream & CompileCode , bool lhs_rhs , const temporary_terms_type & temporary_terms , map_idx_type & map_idx , bool dynamic , bool steady_dynamic ) const
2009-06-05 16:45:23 +02:00
{
CompileCode . write ( & FLDC , sizeof ( FLDC ) ) ;
double vard = datatree . num_constants . getDouble ( id ) ;
CompileCode . write ( reinterpret_cast < char * > ( & vard ) , sizeof ( vard ) ) ;
}
2008-02-03 11:28:36 +01:00
void
2009-07-10 18:42:08 +02:00
NumConstNode : : collectVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
{
}
2009-06-05 16:45:23 +02:00
2009-08-25 11:43:01 +02:00
pair < int , NodeID >
NumConstNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < NodeID , NodeID > > > & List_of_Op_RHS ) const
2009-06-05 16:45:23 +02:00
{
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddNumConstant ( datatree . num_constants . get ( id ) ) ) ) ;
2009-06-05 16:45:23 +02:00
}
NodeID
2009-07-06 11:34:21 +02:00
NumConstNode : : getChainRuleDerivative ( int deriv_id , const map < int , NodeID > & recursive_variables )
2008-11-14 17:07:47 +01:00
{
2009-06-05 16:45:23 +02:00
return datatree . Zero ;
2008-11-14 17:07:47 +01:00
}
2009-04-14 16:39:53 +02:00
NodeID
NumConstNode : : toStatic ( DataTree & static_datatree ) const
2009-06-05 16:45:23 +02:00
{
return static_datatree . AddNumConstant ( datatree . num_constants . get ( id ) ) ;
}
2009-04-14 16:39:53 +02:00
2009-09-30 17:10:31 +02:00
int
NumConstNode : : maxEndoLead ( ) const
{
return 0 ;
}
2008-11-14 17:07:47 +01:00
2009-09-30 17:10:31 +02:00
NodeID
NumConstNode : : decreaseLeadsLags ( int n ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
NodeID
NumConstNode : : substituteLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
NodeID
NumConstNode : : substituteLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
VariableNode : : VariableNode ( DataTree & datatree_arg , int symb_id_arg , int lag_arg ) :
2009-06-05 16:45:23 +02:00
ExprNode ( datatree_arg ) ,
symb_id ( symb_id_arg ) ,
type ( datatree . symbol_table . getType ( symb_id_arg ) ) ,
2009-09-30 17:10:31 +02:00
lag ( lag_arg )
2008-02-03 11:28:36 +01:00
{
// Add myself to the variable map
2009-02-27 13:19:25 +01:00
datatree . variable_node_map [ make_pair ( symb_id , lag ) ] = this ;
2008-02-03 11:28:36 +01:00
2008-10-13 18:44:20 +02:00
// It makes sense to allow a lead/lag on parameters: during steady state calibration, endogenous and parameters can be swapped
2009-09-30 17:10:31 +02:00
assert ( type ! = eUnknownFunction
& & ( lag = = 0 | | ( type ! = eModelLocalVariable & & type ! = eModFileLocalVariable ) ) ) ;
}
void
VariableNode : : prepareForDerivation ( )
{
if ( preparedForDerivation )
return ;
2009-10-02 19:02:35 +02:00
2009-09-30 17:10:31 +02:00
preparedForDerivation = true ;
2008-10-13 18:44:20 +02:00
2008-02-03 11:28:36 +01:00
// Fill in non_null_derivatives
2009-06-05 16:45:23 +02:00
switch ( type )
2008-02-03 11:28:36 +01:00
{
case eEndogenous :
case eExogenous :
case eExogenousDet :
case eParameter :
2009-04-20 15:58:15 +02:00
// For a variable or a parameter, the only non-null derivative is with respect to itself
2009-10-02 19:02:35 +02:00
non_null_derivatives . insert ( datatree . getDerivID ( symb_id , lag ) ) ;
2008-02-03 11:28:36 +01:00
break ;
case eModelLocalVariable :
2009-09-30 17:10:31 +02:00
datatree . local_variables_table [ symb_id ] - > prepareForDerivation ( ) ;
2008-02-03 11:28:36 +01:00
// Non null derivatives are those of the value of the local parameter
non_null_derivatives = datatree . local_variables_table [ symb_id ] - > non_null_derivatives ;
break ;
case eModFileLocalVariable :
// Such a variable is never derived
break ;
case eUnknownFunction :
2009-09-30 17:10:31 +02:00
cerr < < " VariableNode::prepareForDerivation: impossible case " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
}
NodeID
2009-09-30 17:10:31 +02:00
VariableNode : : computeDerivative ( int deriv_id )
2008-02-03 11:28:36 +01:00
{
2009-06-05 16:45:23 +02:00
switch ( type )
2008-02-03 11:28:36 +01:00
{
case eEndogenous :
case eExogenous :
case eExogenousDet :
2009-04-20 15:58:15 +02:00
case eParameter :
2009-09-30 17:10:31 +02:00
if ( deriv_id = = datatree . getDerivID ( symb_id , lag ) )
2008-02-03 11:28:36 +01:00
return datatree . One ;
else
return datatree . Zero ;
case eModelLocalVariable :
2009-09-30 17:10:31 +02:00
return datatree . local_variables_table [ symb_id ] - > getDerivative ( deriv_id ) ;
2008-02-03 11:28:36 +01:00
case eModFileLocalVariable :
cerr < < " ModFileLocalVariable is not derivable " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
case eUnknownFunction :
cerr < < " Impossible case! " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2008-12-24 16:49:01 +01:00
void
VariableNode : : collectTemporary_terms ( const temporary_terms_type & temporary_terms , Model_Block * ModelBlock , int Curr_Block ) const
2009-06-05 16:45:23 +02:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < VariableNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
ModelBlock - > Block_List [ Curr_Block ] . Temporary_InUse - > insert ( idx ) ;
if ( type = = eModelLocalVariable )
datatree . local_variables_table [ symb_id ] - > collectTemporary_terms ( temporary_terms , ModelBlock , Curr_Block ) ;
}
2008-12-24 16:49:01 +01:00
2008-02-03 11:28:36 +01:00
void
VariableNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_type & temporary_terms ) const
2009-06-05 16:45:23 +02:00
{
// If node is a temporary term
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < VariableNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
{
if ( output_type = = oMatlabDynamicModelSparse )
output < < " T " < < idx < < " (it_) " ;
else
output < < " T " < < idx ;
return ;
}
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
if ( IS_LATEX ( output_type ) )
{
2009-09-11 11:16:52 +02:00
if ( output_type = = oLatexDynamicSteadyStateOperator )
output < < " \\ bar{ " ;
2009-06-05 16:45:23 +02:00
output < < datatree . symbol_table . getTeXName ( symb_id ) ;
2009-07-02 16:51:14 +02:00
if ( output_type = = oLatexDynamicModel
& & ( type = = eEndogenous | | type = = eExogenous | | type = = eExogenousDet | | type = = eModelLocalVariable ) )
2009-06-05 16:45:23 +02:00
{
output < < " _{t " ;
if ( lag ! = 0 )
{
if ( lag > 0 )
output < < " + " ;
output < < lag ;
}
output < < " } " ;
}
2009-09-11 11:16:52 +02:00
else if ( output_type = = oLatexDynamicSteadyStateOperator )
output < < " } " ;
2009-06-05 16:45:23 +02:00
return ;
}
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
int i ;
int tsid = datatree . symbol_table . getTypeSpecificID ( symb_id ) ;
switch ( type )
{
case eParameter :
if ( output_type = = oMatlabOutsideModel )
output < < " M_.params " < < " ( " < < tsid + 1 < < " ) " ;
else
output < < " params " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < tsid + ARRAY_SUBSCRIPT_OFFSET ( output_type ) < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
case eModelLocalVariable :
case eModFileLocalVariable :
if ( output_type = = oMatlabDynamicModelSparse | | output_type = = oMatlabStaticModelSparse )
{
output < < " ( " ;
datatree . local_variables_table [ symb_id ] - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " ) " ;
}
else
output < < datatree . symbol_table . getName ( symb_id ) ;
break ;
case eEndogenous :
switch ( output_type )
{
case oMatlabDynamicModel :
case oCDynamicModel :
2009-09-30 17:10:31 +02:00
i = datatree . getDynJacobianCol ( datatree . getDerivID ( symb_id , lag ) ) + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
2009-06-05 16:45:23 +02:00
output < < " y " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
case oMatlabStaticModel :
case oMatlabStaticModelSparse :
i = tsid + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
output < < " y " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
case oMatlabDynamicModelSparse :
i = tsid + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
if ( lag > 0 )
output < < " y " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < " it_+ " < < lag < < " , " < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
else if ( lag < 0 )
output < < " y " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < " it_ " < < lag < < " , " < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
else
output < < " y " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < " it_, " < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
case oMatlabOutsideModel :
2009-09-11 11:16:52 +02:00
output < < " oo_.steady_state( " < < tsid + 1 < < " ) " ;
2009-06-05 16:45:23 +02:00
break ;
2009-09-18 18:34:11 +02:00
case oMatlabDynamicSteadyStateOperator :
output < < " oo_.steady_state( " < < tsid + 1 < < " ) " ;
break ;
2009-06-05 16:45:23 +02:00
default :
assert ( false ) ;
}
break ;
case eExogenous :
i = tsid + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
switch ( output_type )
{
case oMatlabDynamicModel :
case oMatlabDynamicModelSparse :
if ( lag > 0 )
output < < " x(it_+ " < < lag < < " , " < < i < < " ) " ;
else if ( lag < 0 )
output < < " x(it_ " < < lag < < " , " < < i < < " ) " ;
else
output < < " x(it_, " < < i < < " ) " ;
break ;
case oCDynamicModel :
if ( lag = = 0 )
output < < " x[it_+ " < < i < < " *nb_row_x] " ;
else if ( lag > 0 )
output < < " x[it_+ " < < lag < < " + " < < i < < " *nb_row_x] " ;
else
output < < " x[it_ " < < lag < < " + " < < i < < " *nb_row_x] " ;
break ;
case oMatlabStaticModel :
case oMatlabStaticModelSparse :
output < < " x " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
case oMatlabOutsideModel :
assert ( lag = = 0 ) ;
2009-09-11 11:16:52 +02:00
output < < " oo_.exo_steady_state( " < < i < < " ) " ;
2009-06-05 16:45:23 +02:00
break ;
2009-09-18 18:34:11 +02:00
case oMatlabDynamicSteadyStateOperator :
output < < " oo_.exo_steady_state( " < < i < < " ) " ;
break ;
2009-06-05 16:45:23 +02:00
default :
assert ( false ) ;
}
break ;
case eExogenousDet :
i = tsid + datatree . symbol_table . exo_nbr ( ) + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
switch ( output_type )
{
case oMatlabDynamicModel :
case oMatlabDynamicModelSparse :
if ( lag > 0 )
output < < " x(it_+ " < < lag < < " , " < < i < < " ) " ;
else if ( lag < 0 )
output < < " x(it_ " < < lag < < " , " < < i < < " ) " ;
else
output < < " x(it_, " < < i < < " ) " ;
break ;
case oCDynamicModel :
if ( lag = = 0 )
output < < " x[it_+ " < < i < < " *nb_row_xd] " ;
else if ( lag > 0 )
output < < " x[it_+ " < < lag < < " + " < < i < < " *nb_row_xd] " ;
else
output < < " x[it_ " < < lag < < " + " < < i < < " *nb_row_xd] " ;
break ;
case oMatlabStaticModel :
case oMatlabStaticModelSparse :
output < < " x " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
case oMatlabOutsideModel :
assert ( lag = = 0 ) ;
2009-09-11 11:16:52 +02:00
output < < " oo_.exo_det_steady_state( " < < tsid + 1 < < " ) " ;
2009-06-05 16:45:23 +02:00
break ;
2009-09-10 22:09:16 +02:00
case oMatlabDynamicSteadyStateOperator :
2009-09-11 11:16:52 +02:00
output < < " oo_.exo_det_steady_state( " < < tsid + 1 < < " ) " ;
2009-09-10 22:09:16 +02:00
break ;
2009-06-05 16:45:23 +02:00
default :
assert ( false ) ;
}
break ;
case eUnknownFunction :
cerr < < " Impossible case " < < endl ;
exit ( EXIT_FAILURE ) ;
}
}
2008-02-03 11:28:36 +01:00
double
VariableNode : : eval ( const eval_context_type & eval_context ) const throw ( EvalException )
{
2009-02-27 13:19:25 +01:00
eval_context_type : : const_iterator it = eval_context . find ( symb_id ) ;
2008-02-03 11:28:36 +01:00
if ( it = = eval_context . end ( ) )
2009-02-27 13:19:25 +01:00
throw EvalException ( ) ;
2008-02-03 11:28:36 +01:00
return it - > second ;
}
void
2009-09-18 18:34:11 +02:00
VariableNode : : compile ( ostream & CompileCode , bool lhs_rhs , const temporary_terms_type & temporary_terms , map_idx_type & map_idx , bool dynamic , bool steady_dynamic ) const
2009-06-05 16:45:23 +02:00
{
int i , lagl ;
2009-10-07 11:31:58 +02:00
if ( type = = eModelLocalVariable | | type = = eModFileLocalVariable )
datatree . local_variables_table [ symb_id ] - > compile ( CompileCode , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic ) ;
2009-06-05 16:45:23 +02:00
if ( ! lhs_rhs )
{
2009-08-25 11:43:01 +02:00
if ( dynamic )
2009-09-18 18:34:11 +02:00
{
if ( steady_dynamic ) // steady state values in a dynamic model
CompileCode . write ( & FLDVS , sizeof ( FLDVS ) ) ;
else
CompileCode . write ( & FLDV , sizeof ( FLDV ) ) ;
}
2009-08-25 11:43:01 +02:00
else
CompileCode . write ( & FLDSV , sizeof ( FLDSV ) ) ;
2009-06-05 16:45:23 +02:00
}
else
{
2009-08-25 11:43:01 +02:00
if ( dynamic )
2009-09-18 18:34:11 +02:00
{
if ( steady_dynamic ) // steady state values in a dynamic model
{
/*CompileCode.write(&FLDVS, sizeof(FLDVS));*/
cerr < < " Impossible case: steady_state in rhs of equation " < < endl ;
exit ( EXIT_FAILURE ) ;
}
else
CompileCode . write ( & FSTPV , sizeof ( FSTPV ) ) ;
}
2009-08-25 11:43:01 +02:00
else
CompileCode . write ( & FSTPSV , sizeof ( FSTPSV ) ) ;
2009-06-05 16:45:23 +02:00
}
char typel = ( char ) type ;
CompileCode . write ( & typel , sizeof ( typel ) ) ;
int tsid = datatree . symbol_table . getTypeSpecificID ( symb_id ) ;
switch ( type )
{
case eParameter :
//cout << "Parameter=" << tsid << "\n";
i = tsid ;
CompileCode . write ( reinterpret_cast < char * > ( & i ) , sizeof ( i ) ) ;
break ;
case eEndogenous :
//cout << "Endogenous=" << symb_id << "\n";
i = tsid ; //symb_id;
CompileCode . write ( reinterpret_cast < char * > ( & i ) , sizeof ( i ) ) ;
2009-09-18 18:34:11 +02:00
if ( dynamic & & ! steady_dynamic )
2009-08-25 11:43:01 +02:00
{
lagl = lag ;
CompileCode . write ( reinterpret_cast < char * > ( & lagl ) , sizeof ( lagl ) ) ;
}
2009-06-05 16:45:23 +02:00
break ;
case eExogenous :
//cout << "Exogenous=" << tsid << "\n";
i = tsid ;
CompileCode . write ( reinterpret_cast < char * > ( & i ) , sizeof ( i ) ) ;
2009-09-18 18:34:11 +02:00
if ( dynamic & & ! steady_dynamic )
2009-08-25 11:43:01 +02:00
{
lagl = lag ;
CompileCode . write ( reinterpret_cast < char * > ( & lagl ) , sizeof ( lagl ) ) ;
}
2009-06-05 16:45:23 +02:00
break ;
case eExogenousDet :
i = tsid + datatree . symbol_table . exo_nbr ( ) ;
//cout << "ExogenousDet=" << i << "\n";
CompileCode . write ( reinterpret_cast < char * > ( & i ) , sizeof ( i ) ) ;
2009-09-18 18:34:11 +02:00
if ( dynamic & & ! steady_dynamic )
2009-08-25 11:43:01 +02:00
{
lagl = lag ;
CompileCode . write ( reinterpret_cast < char * > ( & lagl ) , sizeof ( lagl ) ) ;
}
2009-06-05 16:45:23 +02:00
break ;
case eModelLocalVariable :
case eModFileLocalVariable :
2009-10-02 19:02:35 +02:00
//cout << "eModelLocalVariable=" << symb_id << "\n";
2009-10-07 11:31:58 +02:00
2009-06-05 16:45:23 +02:00
break ;
case eUnknownFunction :
cerr < < " Impossible case: eUnknownFuncion " < < endl ;
exit ( EXIT_FAILURE ) ;
}
}
2008-02-03 11:28:36 +01:00
2009-01-02 14:00:43 +01:00
void
VariableNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
2009-01-23 11:59:37 +01:00
temporary_terms_type & temporary_terms ,
map < NodeID , pair < int , int > > & first_occurence ,
int Curr_block ,
Model_Block * ModelBlock ,
int equation ,
map_idx_type & map_idx ) const
2009-06-05 16:45:23 +02:00
{
if ( type = = eModelLocalVariable )
datatree . local_variables_table [ symb_id ] - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , ModelBlock , equation , map_idx ) ;
}
2009-01-02 14:00:43 +01:00
2008-02-03 11:28:36 +01:00
void
2009-07-10 18:42:08 +02:00
VariableNode : : collectVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
{
if ( type = = type_arg )
result . insert ( make_pair ( symb_id , lag ) ) ;
if ( type = = eModelLocalVariable )
datatree . local_variables_table [ symb_id ] - > collectVariables ( type_arg , result ) ;
}
2009-06-05 16:45:23 +02:00
2009-08-25 11:43:01 +02:00
pair < int , NodeID >
VariableNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < NodeID , NodeID > > > & List_of_Op_RHS ) const
2009-06-05 16:45:23 +02:00
{
if ( type = = eEndogenous )
{
2009-07-06 12:36:36 +02:00
if ( datatree . symbol_table . getTypeSpecificID ( symb_id ) = = var_endo & & lag = = 0 )
2009-08-25 11:43:01 +02:00
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-06-05 16:45:23 +02:00
else
2009-09-30 17:10:31 +02:00
return ( make_pair ( 0 , datatree . AddVariableInternal ( symb_id , lag ) ) ) ;
2009-06-05 16:45:23 +02:00
}
else
{
if ( type = = eParameter )
2009-09-30 17:10:31 +02:00
return ( make_pair ( 0 , datatree . AddVariableInternal ( symb_id , 0 ) ) ) ;
2009-06-05 16:45:23 +02:00
else
2009-09-30 17:10:31 +02:00
return ( make_pair ( 0 , datatree . AddVariableInternal ( symb_id , lag ) ) ) ;
2009-06-05 16:45:23 +02:00
}
}
2009-04-14 16:39:53 +02:00
NodeID
2009-09-30 17:10:31 +02:00
VariableNode : : getChainRuleDerivative ( int deriv_id , const map < int , NodeID > & recursive_variables )
2009-04-14 16:39:53 +02:00
{
2009-06-05 16:45:23 +02:00
switch ( type )
{
case eEndogenous :
case eExogenous :
case eExogenousDet :
case eParameter :
2009-09-30 17:10:31 +02:00
if ( deriv_id = = datatree . getDerivID ( symb_id , lag ) )
2009-06-05 16:45:23 +02:00
return datatree . One ;
else
{
//if there is in the equation a recursive variable we could use a chaine rule derivation
2009-09-30 17:10:31 +02:00
map < int , NodeID > : : const_iterator it = recursive_variables . find ( datatree . getDerivID ( symb_id , lag ) ) ;
2009-07-06 11:34:21 +02:00
if ( it ! = recursive_variables . end ( ) )
2009-06-05 16:45:23 +02:00
{
2009-09-30 17:10:31 +02:00
map < int , NodeID > : : const_iterator it2 = derivatives . find ( deriv_id ) ;
2009-08-25 11:43:01 +02:00
if ( it2 ! = derivatives . end ( ) )
return it2 - > second ;
else
{
map < int , NodeID > recursive_vars2 ( recursive_variables ) ;
recursive_vars2 . erase ( it - > first ) ;
//NodeID c = datatree.AddNumConstant("1");
2009-09-30 17:10:31 +02:00
NodeID d = datatree . AddUMinus ( it - > second - > getChainRuleDerivative ( deriv_id , recursive_vars2 ) ) ;
2009-08-25 11:43:01 +02:00
//d = datatree.AddTimes(c, d);
2009-09-30 17:10:31 +02:00
derivatives [ deriv_id ] = d ;
2009-08-25 11:43:01 +02:00
return d ;
}
2009-06-05 16:45:23 +02:00
}
else
return datatree . Zero ;
}
case eModelLocalVariable :
2009-09-30 17:10:31 +02:00
return datatree . local_variables_table [ symb_id ] - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
2009-06-05 16:45:23 +02:00
case eModFileLocalVariable :
cerr < < " ModFileLocalVariable is not derivable " < < endl ;
exit ( EXIT_FAILURE ) ;
case eUnknownFunction :
cerr < < " Impossible case! " < < endl ;
exit ( EXIT_FAILURE ) ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
2009-04-14 16:39:53 +02:00
}
2008-11-14 17:07:47 +01:00
2009-06-05 16:45:23 +02:00
NodeID
VariableNode : : toStatic ( DataTree & static_datatree ) const
{
return static_datatree . AddVariable ( datatree . symbol_table . getName ( symb_id ) ) ;
}
2009-09-30 17:10:31 +02:00
int
VariableNode : : maxEndoLead ( ) const
{
switch ( type )
{
case eEndogenous :
return max ( lag , 0 ) ;
case eModelLocalVariable :
return datatree . local_variables_table [ symb_id ] - > maxEndoLead ( ) ;
default :
return 0 ;
}
}
NodeID
VariableNode : : decreaseLeadsLags ( int n ) const
{
switch ( type )
{
case eEndogenous :
case eExogenous :
case eExogenousDet :
return datatree . AddVariable ( symb_id , lag - n ) ;
case eModelLocalVariable :
return datatree . local_variables_table [ symb_id ] - > decreaseLeadsLags ( n ) ;
default :
return const_cast < VariableNode * > ( this ) ;
}
}
NodeID
VariableNode : : substituteLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
NodeID value ;
switch ( type )
{
case eEndogenous :
if ( lag < = 1 )
return const_cast < VariableNode * > ( this ) ;
else
return createLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
case eModelLocalVariable :
value = datatree . local_variables_table [ symb_id ] ;
if ( value - > maxEndoLead ( ) < = 1 )
return const_cast < VariableNode * > ( this ) ;
else
return value - > substituteLeadGreaterThanTwo ( subst_table , neweqs ) ;
default :
return const_cast < VariableNode * > ( this ) ;
}
}
NodeID
VariableNode : : substituteLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
VariableNode * substexpr ;
subst_table_t : : const_iterator it ;
int cur_lag ;
switch ( type )
{
case eEndogenous :
if ( lag > = - 1 )
return const_cast < VariableNode * > ( this ) ;
it = subst_table . find ( this ) ;
if ( it ! = subst_table . end ( ) )
return const_cast < VariableNode * > ( it - > second ) ;
substexpr = datatree . AddVariable ( symb_id , - 1 ) ;
cur_lag = - 2 ;
// Each iteration tries to create an auxvar such that auxvar(-1)=curvar(cur_lag)
// At the beginning (resp. end) of each iteration, substexpr is an expression (possibly an auxvar) equivalent to curvar(cur_lag+1) (resp. curvar(cur_lag))
while ( cur_lag > = lag )
{
VariableNode * orig_expr = datatree . AddVariable ( symb_id , cur_lag ) ;
it = subst_table . find ( orig_expr ) ;
if ( it = = subst_table . end ( ) )
{
int aux_symb_id = datatree . symbol_table . addLagAuxiliaryVar ( symb_id , cur_lag + 1 ) ;
neweqs . push_back ( dynamic_cast < BinaryOpNode * > ( datatree . AddEqual ( datatree . AddVariable ( aux_symb_id , 0 ) , substexpr ) ) ) ;
substexpr = datatree . AddVariable ( aux_symb_id , - 1 ) ;
subst_table [ orig_expr ] = substexpr ;
}
else
substexpr = const_cast < VariableNode * > ( it - > second ) ;
cur_lag - - ;
}
return substexpr ;
case eModelLocalVariable :
return datatree . local_variables_table [ symb_id ] - > substituteLagGreaterThanTwo ( subst_table , neweqs ) ;
default :
return const_cast < VariableNode * > ( this ) ;
}
}
2009-06-05 16:45:23 +02:00
2008-02-03 11:28:36 +01:00
UnaryOpNode : : UnaryOpNode ( DataTree & datatree_arg , UnaryOpcode op_code_arg , const NodeID arg_arg ) :
2009-06-05 16:45:23 +02:00
ExprNode ( datatree_arg ) ,
arg ( arg_arg ) ,
op_code ( op_code_arg )
2008-02-03 11:28:36 +01:00
{
// Add myself to the unary op map
datatree . unary_op_node_map [ make_pair ( arg , op_code ) ] = this ;
2009-09-30 17:10:31 +02:00
}
void
UnaryOpNode : : prepareForDerivation ( )
{
if ( preparedForDerivation )
return ;
preparedForDerivation = true ;
arg - > prepareForDerivation ( ) ;
2008-02-03 11:28:36 +01:00
// Non-null derivatives are those of the argument
non_null_derivatives = arg - > non_null_derivatives ;
}
NodeID
2009-07-06 11:34:21 +02:00
UnaryOpNode : : composeDerivatives ( NodeID darg )
2008-02-03 11:28:36 +01:00
{
NodeID t11 , t12 , t13 ;
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
case oUminus :
return datatree . AddUMinus ( darg ) ;
case oExp :
return datatree . AddTimes ( darg , this ) ;
case oLog :
return datatree . AddDivide ( darg , arg ) ;
case oLog10 :
t11 = datatree . AddExp ( datatree . One ) ;
t12 = datatree . AddLog10 ( t11 ) ;
t13 = datatree . AddDivide ( darg , arg ) ;
return datatree . AddTimes ( t12 , t13 ) ;
case oCos :
t11 = datatree . AddSin ( arg ) ;
t12 = datatree . AddUMinus ( t11 ) ;
return datatree . AddTimes ( darg , t12 ) ;
case oSin :
t11 = datatree . AddCos ( arg ) ;
return datatree . AddTimes ( darg , t11 ) ;
case oTan :
t11 = datatree . AddTimes ( this , this ) ;
t12 = datatree . AddPlus ( t11 , datatree . One ) ;
return datatree . AddTimes ( darg , t12 ) ;
case oAcos :
t11 = datatree . AddSin ( this ) ;
t12 = datatree . AddDivide ( darg , t11 ) ;
return datatree . AddUMinus ( t12 ) ;
case oAsin :
t11 = datatree . AddCos ( this ) ;
return datatree . AddDivide ( darg , t11 ) ;
case oAtan :
t11 = datatree . AddTimes ( arg , arg ) ;
t12 = datatree . AddPlus ( datatree . One , t11 ) ;
return datatree . AddDivide ( darg , t12 ) ;
case oCosh :
2009-04-16 12:33:30 +02:00
t11 = datatree . AddSinh ( arg ) ;
2008-02-03 11:28:36 +01:00
return datatree . AddTimes ( darg , t11 ) ;
case oSinh :
2009-04-16 12:33:30 +02:00
t11 = datatree . AddCosh ( arg ) ;
2008-02-03 11:28:36 +01:00
return datatree . AddTimes ( darg , t11 ) ;
case oTanh :
t11 = datatree . AddTimes ( this , this ) ;
t12 = datatree . AddMinus ( datatree . One , t11 ) ;
return datatree . AddTimes ( darg , t12 ) ;
case oAcosh :
2009-04-16 12:33:30 +02:00
t11 = datatree . AddSinh ( this ) ;
2008-02-03 11:28:36 +01:00
return datatree . AddDivide ( darg , t11 ) ;
case oAsinh :
2009-04-16 12:33:30 +02:00
t11 = datatree . AddCosh ( this ) ;
2008-02-03 11:28:36 +01:00
return datatree . AddDivide ( darg , t11 ) ;
case oAtanh :
t11 = datatree . AddTimes ( arg , arg ) ;
t12 = datatree . AddMinus ( datatree . One , t11 ) ;
return datatree . AddTimes ( darg , t12 ) ;
case oSqrt :
t11 = datatree . AddPlus ( this , this ) ;
return datatree . AddDivide ( darg , t11 ) ;
2009-09-10 22:09:16 +02:00
case oSteadyState :
if ( datatree . isDynamic ( ) )
return datatree . Zero ;
else
return darg ;
2008-02-03 11:28:36 +01:00
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2009-07-06 11:34:21 +02:00
NodeID
UnaryOpNode : : computeDerivative ( int deriv_id )
{
NodeID darg = arg - > getDerivative ( deriv_id ) ;
return composeDerivatives ( darg ) ;
}
2008-02-03 11:28:36 +01:00
int
UnaryOpNode : : cost ( const temporary_terms_type & temporary_terms , bool is_matlab ) const
2009-06-05 16:45:23 +02:00
{
// For a temporary term, the cost is null
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < UnaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
return 0 ;
int cost = arg - > cost ( temporary_terms , is_matlab ) ;
if ( is_matlab )
// Cost for Matlab files
switch ( op_code )
{
case oUminus :
return cost + 70 ;
case oExp :
return cost + 160 ;
case oLog :
return cost + 300 ;
case oLog10 :
return cost + 16000 ;
case oCos :
case oSin :
case oCosh :
return cost + 210 ;
case oTan :
return cost + 230 ;
case oAcos :
return cost + 300 ;
case oAsin :
return cost + 310 ;
case oAtan :
return cost + 140 ;
case oSinh :
return cost + 240 ;
case oTanh :
return cost + 190 ;
case oAcosh :
return cost + 770 ;
case oAsinh :
return cost + 460 ;
case oAtanh :
return cost + 350 ;
case oSqrt :
return cost + 570 ;
2009-09-10 22:09:16 +02:00
case oSteadyState :
2009-09-11 11:16:52 +02:00
return cost ;
2009-06-05 16:45:23 +02:00
}
else
// Cost for C files
switch ( op_code )
{
case oUminus :
return cost + 3 ;
case oExp :
case oAcosh :
return cost + 210 ;
case oLog :
return cost + 137 ;
case oLog10 :
return cost + 139 ;
case oCos :
case oSin :
return cost + 160 ;
case oTan :
return cost + 170 ;
case oAcos :
case oAtan :
return cost + 190 ;
case oAsin :
return cost + 180 ;
case oCosh :
case oSinh :
case oTanh :
return cost + 240 ;
case oAsinh :
return cost + 220 ;
case oAtanh :
return cost + 150 ;
case oSqrt :
return cost + 90 ;
2009-09-10 22:09:16 +02:00
case oSteadyState :
2009-09-11 11:16:52 +02:00
return cost ;
2009-06-05 16:45:23 +02:00
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
void
UnaryOpNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
temporary_terms_type & temporary_terms ,
bool is_matlab ) const
{
NodeID this2 = const_cast < UnaryOpNode * > ( this ) ;
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
map < NodeID , int > : : iterator it = reference_count . find ( this2 ) ;
if ( it = = reference_count . end ( ) )
{
reference_count [ this2 ] = 1 ;
arg - > computeTemporaryTerms ( reference_count , temporary_terms , is_matlab ) ;
}
else
{
reference_count [ this2 ] + + ;
if ( reference_count [ this2 ] * cost ( temporary_terms , is_matlab ) > MIN_COST ( is_matlab ) )
temporary_terms . insert ( this2 ) ;
}
}
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
void
UnaryOpNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
temporary_terms_type & temporary_terms ,
map < NodeID , pair < int , int > > & first_occurence ,
int Curr_block ,
Model_Block * ModelBlock ,
int equation ,
map_idx_type & map_idx ) const
{
NodeID this2 = const_cast < UnaryOpNode * > ( this ) ;
map < NodeID , int > : : iterator it = reference_count . find ( this2 ) ;
if ( it = = reference_count . end ( ) )
2008-02-03 11:28:36 +01:00
{
2009-06-05 16:45:23 +02:00
reference_count [ this2 ] = 1 ;
first_occurence [ this2 ] = make_pair ( Curr_block , equation ) ;
arg - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , ModelBlock , equation , map_idx ) ;
2008-02-03 11:28:36 +01:00
}
2009-06-05 16:45:23 +02:00
else
{
reference_count [ this2 ] + + ;
if ( reference_count [ this2 ] * cost ( temporary_terms , false ) > MIN_COST_C )
{
temporary_terms . insert ( this2 ) ;
ModelBlock - > Block_List [ first_occurence [ this2 ] . first ] . Temporary_Terms_in_Equation [ first_occurence [ this2 ] . second ] - > insert ( this2 ) ;
}
}
}
void
UnaryOpNode : : collectTemporary_terms ( const temporary_terms_type & temporary_terms , Model_Block * ModelBlock , int Curr_Block ) const
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < UnaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
ModelBlock - > Block_List [ Curr_Block ] . Temporary_InUse - > insert ( idx ) ;
else
arg - > collectTemporary_terms ( temporary_terms , ModelBlock , Curr_Block ) ;
}
void
UnaryOpNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_type & temporary_terms ) const
2009-09-18 18:34:11 +02:00
{
2009-06-05 16:45:23 +02:00
// If node is a temporary term
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < UnaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
{
if ( output_type = = oMatlabDynamicModelSparse )
output < < " T " < < idx < < " (it_) " ;
else
output < < " T " < < idx ;
return ;
}
// Always put parenthesis around uminus nodes
if ( op_code = = oUminus )
output < < LEFT_PAR ( output_type ) ;
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
case oUminus :
2009-06-05 16:45:23 +02:00
output < < " - " ;
break ;
2008-02-03 11:28:36 +01:00
case oExp :
2009-06-05 16:45:23 +02:00
output < < " exp " ;
break ;
2008-02-03 11:28:36 +01:00
case oLog :
2009-06-05 16:45:23 +02:00
output < < " log " ;
break ;
2008-02-03 11:28:36 +01:00
case oLog10 :
2009-06-05 16:45:23 +02:00
if ( IS_LATEX ( output_type ) )
output < < " log_{10} " ;
else
output < < " log10 " ;
break ;
2008-02-03 11:28:36 +01:00
case oCos :
2009-06-05 16:45:23 +02:00
output < < " cos " ;
break ;
2008-02-03 11:28:36 +01:00
case oSin :
2009-06-05 16:45:23 +02:00
output < < " sin " ;
break ;
2008-02-03 11:28:36 +01:00
case oTan :
2009-06-05 16:45:23 +02:00
output < < " tan " ;
break ;
2008-02-03 11:28:36 +01:00
case oAcos :
2009-06-05 16:45:23 +02:00
output < < " acos " ;
break ;
2008-02-03 11:28:36 +01:00
case oAsin :
2009-06-05 16:45:23 +02:00
output < < " asin " ;
break ;
case oAtan :
output < < " atan " ;
break ;
2008-02-03 11:28:36 +01:00
case oCosh :
2009-06-05 16:45:23 +02:00
output < < " cosh " ;
break ;
2008-02-03 11:28:36 +01:00
case oSinh :
2009-06-05 16:45:23 +02:00
output < < " sinh " ;
break ;
2008-02-03 11:28:36 +01:00
case oTanh :
2009-06-05 16:45:23 +02:00
output < < " tanh " ;
break ;
case oAcosh :
output < < " acosh " ;
break ;
2008-02-03 11:28:36 +01:00
case oAsinh :
2009-06-05 16:45:23 +02:00
output < < " asinh " ;
break ;
2008-02-03 11:28:36 +01:00
case oAtanh :
2009-06-05 16:45:23 +02:00
output < < " atanh " ;
break ;
2008-02-03 11:28:36 +01:00
case oSqrt :
2009-06-05 16:45:23 +02:00
output < < " sqrt " ;
break ;
2009-09-18 18:34:11 +02:00
case oSteadyState :
ExprNodeOutputType new_output_type ;
2009-09-10 22:09:16 +02:00
switch ( output_type )
2009-09-18 18:34:11 +02:00
{
case oMatlabDynamicModel :
new_output_type = oMatlabDynamicSteadyStateOperator ;
break ;
case oLatexDynamicModel :
new_output_type = oLatexDynamicSteadyStateOperator ;
break ;
case oCDynamicModel :
cerr < < " Steady State Operator not implemented for oCDynamicModel. " < < endl ;
exit ( EXIT_FAILURE ) ;
case oMatlabDynamicModelSparse :
cerr < < " Steady State Operator not implemented for oMatlabDynamicModelSparse. " < < endl ;
exit ( EXIT_FAILURE ) ;
default :
new_output_type = output_type ;
break ;
}
arg - > writeOutput ( output , new_output_type , temporary_terms ) ;
return ;
2008-02-03 11:28:36 +01:00
}
2009-06-05 16:45:23 +02:00
bool close_parenthesis = false ;
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
/* Enclose argument with parentheses if:
- current opcode is not uminus , or
- current opcode is uminus and argument has lowest precedence
*/
2009-09-18 18:34:11 +02:00
if ( op_code ! = oUminus
2009-06-05 16:45:23 +02:00
| | ( op_code = = oUminus
& & arg - > precedence ( output_type , temporary_terms ) < precedence ( output_type , temporary_terms ) ) )
{
output < < LEFT_PAR ( output_type ) ;
close_parenthesis = true ;
}
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
// Write argument
arg - > writeOutput ( output , output_type , temporary_terms ) ;
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
if ( close_parenthesis )
output < < RIGHT_PAR ( output_type ) ;
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
// Close parenthesis for uminus
if ( op_code = = oUminus )
output < < RIGHT_PAR ( output_type ) ;
}
2008-02-03 11:28:36 +01:00
double
UnaryOpNode : : eval_opcode ( UnaryOpcode op_code , double v ) throw ( EvalException )
{
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
case oUminus :
return ( - v ) ;
case oExp :
return ( exp ( v ) ) ;
case oLog :
return ( log ( v ) ) ;
case oLog10 :
return ( log10 ( v ) ) ;
case oCos :
return ( cos ( v ) ) ;
case oSin :
return ( sin ( v ) ) ;
case oTan :
return ( tan ( v ) ) ;
case oAcos :
return ( acos ( v ) ) ;
case oAsin :
return ( asin ( v ) ) ;
case oAtan :
return ( atan ( v ) ) ;
case oCosh :
return ( cosh ( v ) ) ;
case oSinh :
return ( sinh ( v ) ) ;
case oTanh :
return ( tanh ( v ) ) ;
2009-10-07 11:31:58 +02:00
# ifndef WIN64
2008-02-03 11:28:36 +01:00
case oAcosh :
return ( acosh ( v ) ) ;
case oAsinh :
return ( asinh ( v ) ) ;
case oAtanh :
return ( atanh ( v ) ) ;
2009-10-07 11:31:58 +02:00
# endif
2008-02-03 11:28:36 +01:00
case oSqrt :
return ( sqrt ( v ) ) ;
2009-09-10 22:09:16 +02:00
case oSteadyState :
return ( v ) ;
2008-02-03 11:28:36 +01:00
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
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
2009-09-18 18:34:11 +02:00
UnaryOpNode : : compile ( ostream & CompileCode , bool lhs_rhs , const temporary_terms_type & temporary_terms , map_idx_type & map_idx , bool dynamic , bool steady_dynamic ) const
2009-06-05 16:45:23 +02:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < UnaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
{
2009-08-25 11:43:01 +02:00
if ( dynamic )
CompileCode . write ( & FLDT , sizeof ( FLDT ) ) ;
else
CompileCode . write ( & FLDST , sizeof ( FLDST ) ) ;
2009-06-05 16:45:23 +02:00
int var = map_idx [ idx ] ;
CompileCode . write ( reinterpret_cast < char * > ( & var ) , sizeof ( var ) ) ;
return ;
}
2009-09-18 18:34:11 +02:00
if ( op_code = = oSteadyState )
arg - > compile ( CompileCode , lhs_rhs , temporary_terms , map_idx , dynamic , true ) ;
else
{
arg - > compile ( CompileCode , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic ) ;
CompileCode . write ( & FUNARY , sizeof ( FUNARY ) ) ;
UnaryOpcode op_codel = op_code ;
CompileCode . write ( reinterpret_cast < char * > ( & op_codel ) , sizeof ( op_codel ) ) ;
}
2009-06-05 16:45:23 +02:00
}
2008-02-03 11:28:36 +01:00
void
2009-07-10 18:42:08 +02:00
UnaryOpNode : : collectVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
{
arg - > collectVariables ( type_arg , result ) ;
}
2009-06-05 16:45:23 +02:00
2009-08-25 11:43:01 +02:00
pair < int , NodeID >
UnaryOpNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < NodeID , NodeID > > > & List_of_Op_RHS ) const
2009-06-05 16:45:23 +02:00
{
2009-08-25 11:43:01 +02:00
pair < bool , NodeID > res = arg - > normalizeEquation ( var_endo , List_of_Op_RHS ) ;
int is_endogenous_present = res . first ;
2009-06-05 16:45:23 +02:00
NodeID New_NodeID = res . second ;
2009-08-25 11:43:01 +02:00
/*if(res.second.second)*/
if ( is_endogenous_present = = 2 )
return ( make_pair ( 2 , ( NodeID ) NULL ) ) ;
else if ( is_endogenous_present )
{
switch ( op_code )
{
case oUminus :
List_of_Op_RHS . push_back ( make_pair ( oUminus , make_pair ( ( NodeID ) NULL , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oExp :
List_of_Op_RHS . push_back ( make_pair ( oLog , make_pair ( ( NodeID ) NULL , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oLog :
List_of_Op_RHS . push_back ( make_pair ( oExp , make_pair ( ( NodeID ) NULL , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oLog10 :
List_of_Op_RHS . push_back ( make_pair ( oPower , make_pair ( ( NodeID ) NULL , datatree . AddNumConstant ( " 10 " ) ) ) ) ;
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oCos :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oSin :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oTan :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oAcos :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oAsin :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oAtan :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oCosh :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oSinh :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oTanh :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oAcosh :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oAsinh :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oAtanh :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oSqrt :
List_of_Op_RHS . push_back ( make_pair ( oPower , make_pair ( ( NodeID ) NULL , datatree . AddNumConstant ( " 2 " ) ) ) ) ;
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-09-10 22:09:16 +02:00
case oSteadyState :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-08-25 11:43:01 +02:00
}
}
else
2009-06-05 16:45:23 +02:00
{
switch ( op_code )
{
case oUminus :
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddUMinus ( New_NodeID ) ) ) ;
2009-06-05 16:45:23 +02:00
case oExp :
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddExp ( New_NodeID ) ) ) ;
2009-06-05 16:45:23 +02:00
case oLog :
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddLog ( New_NodeID ) ) ) ;
2009-06-05 16:45:23 +02:00
case oLog10 :
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddLog10 ( New_NodeID ) ) ) ;
2009-06-05 16:45:23 +02:00
case oCos :
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddCos ( New_NodeID ) ) ) ;
2009-06-05 16:45:23 +02:00
case oSin :
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddSin ( New_NodeID ) ) ) ;
2009-06-05 16:45:23 +02:00
case oTan :
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddTan ( New_NodeID ) ) ) ;
2009-06-05 16:45:23 +02:00
case oAcos :
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddAcos ( New_NodeID ) ) ) ;
2009-06-05 16:45:23 +02:00
case oAsin :
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddAsin ( New_NodeID ) ) ) ;
2009-06-05 16:45:23 +02:00
case oAtan :
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddAtan ( New_NodeID ) ) ) ;
2009-06-05 16:45:23 +02:00
case oCosh :
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddCosh ( New_NodeID ) ) ) ;
2009-06-05 16:45:23 +02:00
case oSinh :
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddSinh ( New_NodeID ) ) ) ;
2009-06-05 16:45:23 +02:00
case oTanh :
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddTanh ( New_NodeID ) ) ) ;
2009-06-05 16:45:23 +02:00
case oAcosh :
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddAcosh ( New_NodeID ) ) ) ;
2009-06-05 16:45:23 +02:00
case oAsinh :
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddAsinh ( New_NodeID ) ) ) ;
2009-06-05 16:45:23 +02:00
case oAtanh :
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddAtanh ( New_NodeID ) ) ) ;
2009-06-05 16:45:23 +02:00
case oSqrt :
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddSqrt ( New_NodeID ) ) ) ;
2009-09-10 22:09:16 +02:00
case oSteadyState :
return ( make_pair ( 0 , datatree . AddSteadyState ( New_NodeID ) ) ) ;
2009-06-05 16:45:23 +02:00
}
}
2009-08-25 11:43:01 +02:00
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-06-05 16:45:23 +02:00
}
2008-11-14 17:07:47 +01:00
2009-04-14 16:39:53 +02:00
NodeID
2009-07-06 11:34:21 +02:00
UnaryOpNode : : getChainRuleDerivative ( int deriv_id , const map < int , NodeID > & recursive_variables )
2009-04-14 16:39:53 +02:00
{
2009-07-06 11:34:21 +02:00
NodeID darg = arg - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
return composeDerivatives ( darg ) ;
2009-04-14 16:39:53 +02:00
}
2009-09-30 17:10:31 +02:00
NodeID
UnaryOpNode : : buildSimilarUnaryOpNode ( NodeID alt_arg , DataTree & alt_datatree ) const
{
switch ( op_code )
{
case oUminus :
return alt_datatree . AddUMinus ( alt_arg ) ;
case oExp :
return alt_datatree . AddExp ( alt_arg ) ;
case oLog :
return alt_datatree . AddLog ( alt_arg ) ;
case oLog10 :
return alt_datatree . AddLog10 ( alt_arg ) ;
case oCos :
return alt_datatree . AddCos ( alt_arg ) ;
case oSin :
return alt_datatree . AddSin ( alt_arg ) ;
case oTan :
return alt_datatree . AddTan ( alt_arg ) ;
case oAcos :
return alt_datatree . AddAcos ( alt_arg ) ;
case oAsin :
return alt_datatree . AddAsin ( alt_arg ) ;
case oAtan :
return alt_datatree . AddAtan ( alt_arg ) ;
case oCosh :
return alt_datatree . AddCosh ( alt_arg ) ;
case oSinh :
return alt_datatree . AddSinh ( alt_arg ) ;
case oTanh :
return alt_datatree . AddTanh ( alt_arg ) ;
case oAcosh :
return alt_datatree . AddAcosh ( alt_arg ) ;
case oAsinh :
return alt_datatree . AddAsinh ( alt_arg ) ;
case oAtanh :
return alt_datatree . AddAtanh ( alt_arg ) ;
case oSqrt :
return alt_datatree . AddSqrt ( alt_arg ) ;
case oSteadyState :
return alt_datatree . AddSteadyState ( alt_arg ) ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2009-06-05 16:45:23 +02:00
NodeID
UnaryOpNode : : toStatic ( DataTree & static_datatree ) const
2009-09-30 17:10:31 +02:00
{
NodeID sarg = arg - > toStatic ( static_datatree ) ;
return buildSimilarUnaryOpNode ( sarg , static_datatree ) ;
}
int
UnaryOpNode : : maxEndoLead ( ) const
{
return arg - > maxEndoLead ( ) ;
}
NodeID
UnaryOpNode : : decreaseLeadsLags ( int n ) const
{
NodeID argsubst = arg - > decreaseLeadsLags ( n ) ;
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
NodeID
UnaryOpNode : : substituteLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
if ( op_code = = oUminus )
{
NodeID argsubst = arg - > substituteLeadGreaterThanTwo ( subst_table , neweqs ) ;
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
else
{
if ( maxEndoLead ( ) > = 2 )
return createLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
else
return const_cast < UnaryOpNode * > ( this ) ;
}
}
2009-06-05 16:45:23 +02:00
2009-09-30 17:10:31 +02:00
NodeID
UnaryOpNode : : substituteLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
NodeID argsubst = arg - > substituteLagGreaterThanTwo ( subst_table , neweqs ) ;
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
2009-06-05 16:45:23 +02:00
2008-02-03 11:28:36 +01:00
BinaryOpNode : : BinaryOpNode ( DataTree & datatree_arg , const NodeID arg1_arg ,
BinaryOpcode op_code_arg , const NodeID arg2_arg ) :
2009-06-05 16:45:23 +02:00
ExprNode ( datatree_arg ) ,
arg1 ( arg1_arg ) ,
arg2 ( arg2_arg ) ,
op_code ( op_code_arg )
2008-02-03 11:28:36 +01:00
{
datatree . binary_op_node_map [ make_pair ( make_pair ( arg1 , arg2 ) , op_code ) ] = this ;
2009-09-30 17:10:31 +02:00
}
void
BinaryOpNode : : prepareForDerivation ( )
{
if ( preparedForDerivation )
return ;
preparedForDerivation = true ;
arg1 - > prepareForDerivation ( ) ;
arg2 - > prepareForDerivation ( ) ;
2008-02-03 11:28:36 +01:00
// Non-null derivatives are the union of those of the arguments
// Compute set union of arg1->non_null_derivatives and arg2->non_null_derivatives
set_union ( arg1 - > non_null_derivatives . begin ( ) ,
arg1 - > non_null_derivatives . end ( ) ,
arg2 - > non_null_derivatives . begin ( ) ,
arg2 - > non_null_derivatives . end ( ) ,
inserter ( non_null_derivatives , non_null_derivatives . begin ( ) ) ) ;
}
NodeID
2009-07-06 11:34:21 +02:00
BinaryOpNode : : composeDerivatives ( NodeID darg1 , NodeID darg2 )
2008-02-03 11:28:36 +01:00
{
NodeID t11 , t12 , t13 , t14 , t15 ;
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
case oPlus :
return datatree . AddPlus ( darg1 , darg2 ) ;
case oMinus :
return datatree . AddMinus ( darg1 , darg2 ) ;
case oTimes :
t11 = datatree . AddTimes ( darg1 , arg2 ) ;
t12 = datatree . AddTimes ( darg2 , arg1 ) ;
return datatree . AddPlus ( t11 , t12 ) ;
case oDivide :
2009-06-05 16:45:23 +02:00
if ( darg2 ! = datatree . Zero )
{
t11 = datatree . AddTimes ( darg1 , arg2 ) ;
t12 = datatree . AddTimes ( darg2 , arg1 ) ;
t13 = datatree . AddMinus ( t11 , t12 ) ;
t14 = datatree . AddTimes ( arg2 , arg2 ) ;
return datatree . AddDivide ( t13 , t14 ) ;
}
else
return datatree . AddDivide ( darg1 , arg2 ) ;
2008-02-03 11:28:36 +01:00
case oLess :
case oGreater :
case oLessEqual :
case oGreaterEqual :
case oEqualEqual :
case oDifferent :
return datatree . Zero ;
case oPower :
if ( darg2 = = datatree . Zero )
{
if ( darg1 = = datatree . Zero )
return datatree . Zero ;
else
{
t11 = datatree . AddMinus ( arg2 , datatree . One ) ;
t12 = datatree . AddPower ( arg1 , t11 ) ;
t13 = datatree . AddTimes ( arg2 , t12 ) ;
return datatree . AddTimes ( darg1 , t13 ) ;
}
}
else
{
t11 = datatree . AddLog ( arg1 ) ;
t12 = datatree . AddTimes ( darg2 , t11 ) ;
t13 = datatree . AddTimes ( darg1 , arg2 ) ;
t14 = datatree . AddDivide ( t13 , arg1 ) ;
t15 = datatree . AddPlus ( t12 , t14 ) ;
return datatree . AddTimes ( t15 , this ) ;
}
case oMax :
t11 = datatree . AddGreater ( arg1 , arg2 ) ;
t12 = datatree . AddTimes ( t11 , darg1 ) ;
t13 = datatree . AddMinus ( datatree . One , t11 ) ;
t14 = datatree . AddTimes ( t13 , darg2 ) ;
return datatree . AddPlus ( t14 , t12 ) ;
case oMin :
t11 = datatree . AddGreater ( arg2 , arg1 ) ;
t12 = datatree . AddTimes ( t11 , darg1 ) ;
t13 = datatree . AddMinus ( datatree . One , t11 ) ;
t14 = datatree . AddTimes ( t13 , darg2 ) ;
return datatree . AddPlus ( t14 , t12 ) ;
case oEqual :
return datatree . AddMinus ( darg1 , darg2 ) ;
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2009-07-06 11:34:21 +02:00
NodeID
BinaryOpNode : : computeDerivative ( int deriv_id )
{
NodeID darg1 = arg1 - > getDerivative ( deriv_id ) ;
NodeID darg2 = arg2 - > getDerivative ( deriv_id ) ;
return composeDerivatives ( darg1 , darg2 ) ;
}
2008-02-03 11:28:36 +01:00
int
BinaryOpNode : : precedence ( ExprNodeOutputType output_type , const temporary_terms_type & temporary_terms ) const
2009-06-05 16:45:23 +02:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < BinaryOpNode * > ( this ) ) ;
// A temporary term behaves as a variable
if ( it ! = temporary_terms . end ( ) )
2008-02-03 11:28:36 +01:00
return 100 ;
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
2009-06-05 16:45:23 +02:00
case oEqual :
return 0 ;
2008-02-03 11:28:36 +01:00
case oEqualEqual :
case oDifferent :
2009-06-05 16:45:23 +02:00
return 1 ;
2008-02-03 11:28:36 +01:00
case oLessEqual :
case oGreaterEqual :
2009-06-05 16:45:23 +02:00
case oLess :
case oGreater :
return 2 ;
2008-02-03 11:28:36 +01:00
case oPlus :
case oMinus :
2009-06-05 16:45:23 +02:00
return 3 ;
2008-02-03 11:28:36 +01:00
case oTimes :
case oDivide :
2009-06-05 16:45:23 +02:00
return 4 ;
2008-02-03 11:28:36 +01:00
case oPower :
2009-06-05 16:45:23 +02:00
if ( IS_C ( output_type ) )
// In C, power operator is of the form pow(a, b)
return 100 ;
else
return 5 ;
case oMin :
case oMax :
return 100 ;
2008-02-03 11:28:36 +01:00
}
2009-06-05 16:45:23 +02:00
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
int
BinaryOpNode : : cost ( const temporary_terms_type & temporary_terms , bool is_matlab ) const
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < BinaryOpNode * > ( this ) ) ;
// For a temporary term, the cost is null
if ( it ! = temporary_terms . end ( ) )
return 0 ;
int cost = arg1 - > cost ( temporary_terms , is_matlab ) ;
cost + = arg2 - > cost ( temporary_terms , is_matlab ) ;
if ( is_matlab )
// Cost for Matlab files
switch ( op_code )
{
case oLess :
case oGreater :
case oLessEqual :
case oGreaterEqual :
case oEqualEqual :
case oDifferent :
return cost + 60 ;
case oPlus :
case oMinus :
case oTimes :
return cost + 90 ;
case oMax :
case oMin :
return cost + 110 ;
case oDivide :
return cost + 990 ;
case oPower :
return cost + 1160 ;
case oEqual :
return cost ;
}
else
// Cost for C files
switch ( op_code )
{
case oLess :
case oGreater :
case oLessEqual :
case oGreaterEqual :
case oEqualEqual :
case oDifferent :
return cost + 2 ;
case oPlus :
case oMinus :
case oTimes :
return cost + 4 ;
case oMax :
case oMin :
return cost + 5 ;
case oDivide :
return cost + 15 ;
case oPower :
return cost + 520 ;
case oEqual :
return cost ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2008-02-03 11:28:36 +01:00
void
BinaryOpNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
temporary_terms_type & temporary_terms ,
bool is_matlab ) const
2009-06-05 16:45:23 +02:00
{
NodeID this2 = const_cast < BinaryOpNode * > ( this ) ;
map < NodeID , int > : : iterator it = reference_count . find ( this2 ) ;
if ( it = = reference_count . end ( ) )
{
// If this node has never been encountered, set its ref count to one,
// and travel through its children
reference_count [ this2 ] = 1 ;
arg1 - > computeTemporaryTerms ( reference_count , temporary_terms , is_matlab ) ;
arg2 - > computeTemporaryTerms ( reference_count , temporary_terms , is_matlab ) ;
}
else
{
// If the node has already been encountered, increment its ref count
// and declare it as a temporary term if it is too costly
reference_count [ this2 ] + + ;
if ( reference_count [ this2 ] * cost ( temporary_terms , is_matlab ) > MIN_COST ( is_matlab ) )
temporary_terms . insert ( this2 ) ;
}
}
2008-02-03 11:28:36 +01:00
void
BinaryOpNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
temporary_terms_type & temporary_terms ,
2009-01-02 14:00:43 +01:00
map < NodeID , pair < int , int > > & first_occurence ,
2008-02-03 11:28:36 +01:00
int Curr_block ,
Model_Block * ModelBlock ,
2009-01-02 14:00:43 +01:00
int equation ,
2008-02-03 11:28:36 +01:00
map_idx_type & map_idx ) const
2009-06-05 16:45:23 +02:00
{
NodeID this2 = const_cast < BinaryOpNode * > ( this ) ;
map < NodeID , int > : : iterator it = reference_count . find ( this2 ) ;
if ( it = = reference_count . end ( ) )
{
reference_count [ this2 ] = 1 ;
first_occurence [ this2 ] = make_pair ( Curr_block , equation ) ;
arg1 - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , ModelBlock , equation , map_idx ) ;
arg2 - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , ModelBlock , equation , map_idx ) ;
}
else
{
reference_count [ this2 ] + + ;
if ( reference_count [ this2 ] * cost ( temporary_terms , false ) > MIN_COST_C )
{
temporary_terms . insert ( this2 ) ;
ModelBlock - > Block_List [ first_occurence [ this2 ] . first ] . Temporary_Terms_in_Equation [ first_occurence [ this2 ] . second ] - > insert ( this2 ) ;
}
}
}
2008-02-03 11:28:36 +01:00
double
BinaryOpNode : : eval_opcode ( double v1 , BinaryOpcode op_code , double v2 ) throw ( EvalException )
{
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
case oPlus :
return ( v1 + v2 ) ;
case oMinus :
return ( v1 - v2 ) ;
case oTimes :
return ( v1 * v2 ) ;
case oDivide :
return ( v1 / v2 ) ;
case oPower :
return ( pow ( v1 , v2 ) ) ;
case oMax :
if ( v1 < v2 )
return v2 ;
else
return v1 ;
case oMin :
if ( v1 > v2 )
return v2 ;
else
return v1 ;
case oLess :
return ( v1 < v2 ) ;
case oGreater :
return ( v1 > v2 ) ;
case oLessEqual :
return ( v1 < = v2 ) ;
case oGreaterEqual :
return ( v1 > = v2 ) ;
case oEqualEqual :
return ( v1 = = v2 ) ;
case oDifferent :
return ( v1 ! = v2 ) ;
case oEqual :
throw EvalException ( ) ;
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
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
2009-09-18 18:34:11 +02:00
BinaryOpNode : : compile ( ostream & CompileCode , bool lhs_rhs , const temporary_terms_type & temporary_terms , map_idx_type & map_idx , bool dynamic , bool steady_dynamic ) const
2009-06-05 16:45:23 +02:00
{
// If current node is a temporary term
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < BinaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
{
2009-08-25 11:43:01 +02:00
if ( dynamic )
CompileCode . write ( & FLDT , sizeof ( FLDT ) ) ;
else
CompileCode . write ( & FLDST , sizeof ( FLDST ) ) ;
2009-06-05 16:45:23 +02:00
int var = map_idx [ idx ] ;
CompileCode . write ( reinterpret_cast < char * > ( & var ) , sizeof ( var ) ) ;
return ;
}
2009-09-18 18:34:11 +02:00
arg1 - > compile ( CompileCode , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic ) ;
arg2 - > compile ( CompileCode , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic ) ;
2009-06-05 16:45:23 +02:00
CompileCode . write ( & FBINARY , sizeof ( FBINARY ) ) ;
BinaryOpcode op_codel = op_code ;
CompileCode . write ( reinterpret_cast < char * > ( & op_codel ) , sizeof ( op_codel ) ) ;
}
2008-02-03 11:28:36 +01:00
2008-12-24 16:49:01 +01:00
void
BinaryOpNode : : collectTemporary_terms ( const temporary_terms_type & temporary_terms , Model_Block * ModelBlock , int Curr_Block ) const
2009-06-05 16:45:23 +02:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < BinaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
ModelBlock - > Block_List [ Curr_Block ] . Temporary_InUse - > insert ( idx ) ;
else
{
arg1 - > collectTemporary_terms ( temporary_terms , ModelBlock , Curr_Block ) ;
arg2 - > collectTemporary_terms ( temporary_terms , ModelBlock , Curr_Block ) ;
}
}
2008-12-24 16:49:01 +01:00
2008-02-03 11:28:36 +01:00
void
BinaryOpNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_type & temporary_terms ) const
2009-06-05 16:45:23 +02:00
{
//cout << "writeOutput binary\n";
// If current node is a temporary term
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < BinaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
{
if ( output_type = = oMatlabDynamicModelSparse )
output < < " T " < < idx < < " (it_) " ;
else
output < < " T " < < idx ;
return ;
}
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
// Treat special case of power operator in C, and case of max and min operators
if ( ( op_code = = oPower & & IS_C ( output_type ) ) | | op_code = = oMax | | op_code = = oMin )
{
switch ( op_code )
{
case oPower :
output < < " pow( " ;
break ;
case oMax :
output < < " max( " ;
break ;
case oMin :
output < < " min( " ;
break ;
default :
;
}
arg1 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " , " ;
arg2 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " ) " ;
return ;
}
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
int prec = precedence ( output_type , temporary_terms ) ;
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
bool close_parenthesis = false ;
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
if ( IS_LATEX ( output_type ) & & op_code = = oDivide )
output < < " \\ frac{ " ;
else
{
// If left argument has a lower precedence, or if current and left argument are both power operators, add parenthesis around left argument
BinaryOpNode * barg1 = dynamic_cast < BinaryOpNode * > ( arg1 ) ;
if ( arg1 - > precedence ( output_type , temporary_terms ) < prec
| | ( op_code = = oPower & & barg1 ! = NULL & & barg1 - > op_code = = oPower ) )
{
output < < LEFT_PAR ( output_type ) ;
close_parenthesis = true ;
}
}
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
// Write left argument
arg1 - > writeOutput ( output , output_type , temporary_terms ) ;
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
if ( close_parenthesis )
output < < RIGHT_PAR ( output_type ) ;
2009-04-30 15:14:33 +02:00
2009-06-05 16:45:23 +02:00
if ( IS_LATEX ( output_type ) & & op_code = = oDivide )
output < < " } " ;
2009-04-30 15:14:33 +02:00
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
// Write current operator symbol
switch ( op_code )
{
case oPlus :
output < < " + " ;
break ;
case oMinus :
output < < " - " ;
break ;
case oTimes :
if ( IS_LATEX ( output_type ) )
2009-07-02 16:51:14 +02:00
output < < " \\ , " ;
2009-06-05 16:45:23 +02:00
else
output < < " * " ;
break ;
case oDivide :
if ( ! IS_LATEX ( output_type ) )
output < < " / " ;
break ;
case oPower :
output < < " ^ " ;
break ;
case oLess :
output < < " < " ;
break ;
case oGreater :
output < < " > " ;
break ;
case oLessEqual :
if ( IS_LATEX ( output_type ) )
output < < " \\ leq " ;
else
output < < " <= " ;
break ;
case oGreaterEqual :
if ( IS_LATEX ( output_type ) )
output < < " \\ geq " ;
else
output < < " >= " ;
break ;
case oEqualEqual :
output < < " == " ;
break ;
case oDifferent :
if ( IS_MATLAB ( output_type ) )
output < < " ~= " ;
else
{
if ( IS_C ( output_type ) )
output < < " != " ;
else
output < < " \\ neq " ;
}
break ;
case oEqual :
output < < " = " ;
break ;
default :
;
}
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
close_parenthesis = false ;
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
if ( IS_LATEX ( output_type ) & & ( op_code = = oPower | | op_code = = oDivide ) )
output < < " { " ;
else
{
/* Add parenthesis around right argument if:
- its precedence is lower than those of the current node
- it is a power operator and current operator is also a power operator
- it is a minus operator with same precedence than current operator
- it is a divide operator with same precedence than current operator */
BinaryOpNode * barg2 = dynamic_cast < BinaryOpNode * > ( arg2 ) ;
int arg2_prec = arg2 - > precedence ( output_type , temporary_terms ) ;
if ( arg2_prec < prec
| | ( op_code = = oPower & & barg2 ! = NULL & & barg2 - > op_code = = oPower & & ! IS_LATEX ( output_type ) )
| | ( op_code = = oMinus & & arg2_prec = = prec )
| | ( op_code = = oDivide & & arg2_prec = = prec & & ! IS_LATEX ( output_type ) ) )
{
output < < LEFT_PAR ( output_type ) ;
close_parenthesis = true ;
}
}
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
// Write right argument
arg2 - > writeOutput ( output , output_type , temporary_terms ) ;
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
if ( IS_LATEX ( output_type ) & & ( op_code = = oPower | | op_code = = oDivide ) )
output < < " } " ;
2009-04-30 15:14:33 +02:00
2009-06-05 16:45:23 +02:00
if ( close_parenthesis )
output < < RIGHT_PAR ( output_type ) ;
}
2008-02-03 11:28:36 +01:00
void
2009-07-10 18:42:08 +02:00
BinaryOpNode : : collectVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
{
arg1 - > collectVariables ( type_arg , result ) ;
arg2 - > collectVariables ( type_arg , result ) ;
}
2009-06-05 16:45:23 +02:00
2009-08-25 11:43:01 +02:00
NodeID
BinaryOpNode : : Compute_RHS ( NodeID arg1 , NodeID arg2 , int op , int op_type ) const
{
temporary_terms_type temp ;
switch ( op_type )
{
case 0 : /*Unary Operator*/
switch ( op )
{
case oUminus :
return ( datatree . AddUMinus ( arg1 ) ) ;
break ;
case oExp :
return ( datatree . AddExp ( arg1 ) ) ;
break ;
case oLog :
return ( datatree . AddLog ( arg1 ) ) ;
break ;
case oLog10 :
return ( datatree . AddLog10 ( arg1 ) ) ;
break ;
}
break ;
case 1 : /*Binary Operator*/
switch ( op )
{
case oPlus :
return ( datatree . AddPlus ( arg1 , arg2 ) ) ;
break ;
case oMinus :
return ( datatree . AddMinus ( arg1 , arg2 ) ) ;
break ;
case oTimes :
return ( datatree . AddTimes ( arg1 , arg2 ) ) ;
break ;
case oDivide :
return ( datatree . AddDivide ( arg1 , arg2 ) ) ;
break ;
case oPower :
return ( datatree . AddPower ( arg1 , arg2 ) ) ;
break ;
}
break ;
}
return ( ( NodeID ) NULL ) ;
}
pair < int , NodeID >
BinaryOpNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < NodeID , NodeID > > > & List_of_Op_RHS ) const
2009-06-05 16:45:23 +02:00
{
2009-08-25 11:43:01 +02:00
vector < pair < int , pair < NodeID , NodeID > > > List_of_Op_RHS1 , List_of_Op_RHS2 ;
int is_endogenous_present_1 , is_endogenous_present_2 ;
pair < int , NodeID > res ;
NodeID NodeID_1 , NodeID_2 ;
res = arg1 - > normalizeEquation ( var_endo , List_of_Op_RHS1 ) ;
is_endogenous_present_1 = res . first ;
NodeID_1 = res . second ;
res = arg2 - > normalizeEquation ( var_endo , List_of_Op_RHS2 ) ;
is_endogenous_present_2 = res . first ;
NodeID_2 = res . second ;
if ( is_endogenous_present_1 = = 2 | | is_endogenous_present_2 = = 2 )
return ( make_pair ( 2 , ( NodeID ) NULL ) ) ;
else if ( is_endogenous_present_1 & & is_endogenous_present_2 )
return ( make_pair ( 2 , ( NodeID ) NULL ) ) ;
else if ( is_endogenous_present_1 )
{
if ( op_code = = oEqual )
{
pair < int , pair < NodeID , NodeID > > it ;
int oo = List_of_Op_RHS1 . size ( ) ;
for ( int i = 0 ; i < oo ; i + + )
{
it = List_of_Op_RHS1 . back ( ) ;
List_of_Op_RHS1 . pop_back ( ) ;
if ( it . second . first & & ! it . second . second ) /*Binary operator*/
NodeID_2 = Compute_RHS ( NodeID_2 , ( BinaryOpNode * ) it . second . first , it . first , 1 ) ;
else if ( it . second . second & & ! it . second . first ) /*Binary operator*/
NodeID_2 = Compute_RHS ( it . second . second , NodeID_2 , it . first , 1 ) ;
else if ( it . second . second & & it . second . first ) /*Binary operator*/
NodeID_2 = Compute_RHS ( it . second . first , it . second . second , it . first , 1 ) ;
else /*Unary operator*/
NodeID_2 = Compute_RHS ( ( UnaryOpNode * ) NodeID_2 , ( UnaryOpNode * ) it . second . first , it . first , 0 ) ;
}
}
else
List_of_Op_RHS = List_of_Op_RHS1 ;
}
else if ( is_endogenous_present_2 )
{
if ( op_code = = oEqual )
{
int oo = List_of_Op_RHS2 . size ( ) ;
for ( int i = 0 ; i < oo ; i + + )
{
pair < int , pair < NodeID , NodeID > > it ;
it = List_of_Op_RHS2 . back ( ) ;
List_of_Op_RHS2 . pop_back ( ) ;
if ( it . second . first & & ! it . second . second ) /*Binary operator*/
NodeID_1 = Compute_RHS ( ( BinaryOpNode * ) NodeID_1 , ( BinaryOpNode * ) it . second . first , it . first , 1 ) ;
else if ( it . second . second & & ! it . second . first ) /*Binary operator*/
NodeID_1 = Compute_RHS ( ( BinaryOpNode * ) it . second . second , ( BinaryOpNode * ) NodeID_1 , it . first , 1 ) ;
else if ( it . second . second & & it . second . first ) /*Binary operator*/
NodeID_1 = Compute_RHS ( it . second . first , it . second . second , it . first , 1 ) ;
else
NodeID_1 = Compute_RHS ( ( UnaryOpNode * ) NodeID_1 , ( UnaryOpNode * ) it . second . first , it . first , 0 ) ;
}
}
else
List_of_Op_RHS = List_of_Op_RHS2 ;
}
2009-06-05 16:45:23 +02:00
switch ( op_code )
{
case oPlus :
2009-07-06 12:36:36 +02:00
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
{
List_of_Op_RHS . push_back ( make_pair ( oMinus , make_pair ( datatree . AddPlus ( NodeID_1 , NodeID_2 ) , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 0 , datatree . AddPlus ( NodeID_1 , NodeID_2 ) ) ) ;
}
2009-07-06 12:36:36 +02:00
else if ( is_endogenous_present_1 & & is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-07-06 12:36:36 +02:00
else if ( ! is_endogenous_present_1 & & is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
{
List_of_Op_RHS . push_back ( make_pair ( oMinus , make_pair ( NodeID_1 , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , NodeID_1 ) ) ;
}
2009-07-06 12:36:36 +02:00
else if ( is_endogenous_present_1 & & ! is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
{
List_of_Op_RHS . push_back ( make_pair ( oMinus , make_pair ( NodeID_2 , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , NodeID_2 ) ) ;
}
2009-06-05 16:45:23 +02:00
break ;
case oMinus :
2009-07-06 12:36:36 +02:00
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
{
List_of_Op_RHS . push_back ( make_pair ( oMinus , make_pair ( datatree . AddMinus ( NodeID_1 , NodeID_2 ) , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 0 , datatree . AddMinus ( NodeID_1 , NodeID_2 ) ) ) ;
}
2009-07-06 12:36:36 +02:00
else if ( is_endogenous_present_1 & & is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-07-06 12:36:36 +02:00
else if ( ! is_endogenous_present_1 & & is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
{
List_of_Op_RHS . push_back ( make_pair ( oUminus , make_pair ( ( NodeID ) NULL , ( NodeID ) NULL ) ) ) ;
List_of_Op_RHS . push_back ( make_pair ( oMinus , make_pair ( NodeID_1 , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , NodeID_1 ) ) ;
}
2009-07-06 12:36:36 +02:00
else if ( is_endogenous_present_1 & & ! is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
{
List_of_Op_RHS . push_back ( make_pair ( oPlus , make_pair ( NodeID_2 , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , datatree . AddUMinus ( NodeID_2 ) ) ) ;
}
2009-06-05 16:45:23 +02:00
break ;
case oTimes :
2009-07-06 12:36:36 +02:00
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddTimes ( NodeID_1 , NodeID_2 ) ) ) ;
else if ( ! is_endogenous_present_1 & & is_endogenous_present_2 )
{
List_of_Op_RHS . push_back ( make_pair ( oDivide , make_pair ( NodeID_1 , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , NodeID_1 ) ) ;
}
else if ( is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
List_of_Op_RHS . push_back ( make_pair ( oDivide , make_pair ( NodeID_2 , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , NodeID_2 ) ) ;
}
2009-06-05 16:45:23 +02:00
else
2009-08-25 11:43:01 +02:00
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-06-05 16:45:23 +02:00
break ;
case oDivide :
2009-07-06 12:36:36 +02:00
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddDivide ( NodeID_1 , NodeID_2 ) ) ) ;
else if ( ! is_endogenous_present_1 & & is_endogenous_present_2 )
{
List_of_Op_RHS . push_back ( make_pair ( oDivide , make_pair ( ( NodeID ) NULL , NodeID_1 ) ) ) ;
return ( make_pair ( 1 , NodeID_1 ) ) ;
}
else if ( is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
List_of_Op_RHS . push_back ( make_pair ( oTimes , make_pair ( NodeID_2 , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , NodeID_2 ) ) ;
}
2009-06-05 16:45:23 +02:00
else
2009-08-25 11:43:01 +02:00
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-06-05 16:45:23 +02:00
break ;
case oPower :
2009-07-06 12:36:36 +02:00
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddPower ( NodeID_1 , NodeID_2 ) ) ) ;
else if ( is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
List_of_Op_RHS . push_back ( make_pair ( oPower , make_pair ( datatree . AddDivide ( datatree . AddNumConstant ( " 1 " ) , NodeID_2 ) , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
}
2009-06-05 16:45:23 +02:00
break ;
case oEqual :
2009-07-06 12:36:36 +02:00
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2009-06-05 16:45:23 +02:00
{
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 ,
datatree . AddEqual ( datatree . AddVariable ( datatree . symbol_table . getName ( datatree . symbol_table . getID ( eEndogenous , var_endo ) ) , 0 ) , datatree . AddMinus ( NodeID_2 , NodeID_1 ) )
) ) ;
2009-06-05 16:45:23 +02:00
}
2009-07-06 12:36:36 +02:00
else if ( is_endogenous_present_1 & & is_endogenous_present_2 )
2009-06-05 16:45:23 +02:00
{
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 ,
datatree . AddEqual ( datatree . AddVariable ( datatree . symbol_table . getName ( datatree . symbol_table . getID ( eEndogenous , var_endo ) ) , 0 ) , datatree . Zero )
) ) ;
2009-06-05 16:45:23 +02:00
}
2009-07-06 12:36:36 +02:00
else if ( ! is_endogenous_present_1 & & is_endogenous_present_2 )
2009-06-05 16:45:23 +02:00
{
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 ,
datatree . AddEqual ( datatree . AddVariable ( datatree . symbol_table . getName ( datatree . symbol_table . getID ( eEndogenous , var_endo ) ) , 0 ) , /*datatree.AddUMinus(NodeID_1)*/ NodeID_1 )
) ) ;
2009-06-05 16:45:23 +02:00
}
2009-07-06 12:36:36 +02:00
else if ( is_endogenous_present_1 & & ! is_endogenous_present_2 )
2009-06-05 16:45:23 +02:00
{
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 ,
datatree . AddEqual ( datatree . AddVariable ( datatree . symbol_table . getName ( datatree . symbol_table . getID ( eEndogenous , var_endo ) ) , 0 ) , NodeID_2 )
) ) ;
2009-06-05 16:45:23 +02:00
}
break ;
case oMax :
2009-07-06 12:36:36 +02:00
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddMax ( NodeID_1 , NodeID_2 ) ) ) ;
2009-06-05 16:45:23 +02:00
else
2009-08-25 11:43:01 +02:00
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-06-05 16:45:23 +02:00
break ;
case oMin :
2009-07-06 12:36:36 +02:00
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddMin ( NodeID_1 , NodeID_2 ) ) ) ;
2009-06-05 16:45:23 +02:00
else
2009-08-25 11:43:01 +02:00
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-06-05 16:45:23 +02:00
break ;
case oLess :
2009-07-06 12:36:36 +02:00
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddLess ( NodeID_1 , NodeID_2 ) ) ) ;
2009-06-05 16:45:23 +02:00
else
2009-08-25 11:43:01 +02:00
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-06-05 16:45:23 +02:00
break ;
case oGreater :
2009-07-06 12:36:36 +02:00
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddGreater ( NodeID_1 , NodeID_2 ) ) ) ;
2009-06-05 16:45:23 +02:00
else
2009-08-25 11:43:01 +02:00
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-06-05 16:45:23 +02:00
break ;
case oLessEqual :
2009-07-06 12:36:36 +02:00
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddLessEqual ( NodeID_1 , NodeID_2 ) ) ) ;
2009-06-05 16:45:23 +02:00
else
2009-08-25 11:43:01 +02:00
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-06-05 16:45:23 +02:00
break ;
case oGreaterEqual :
2009-07-06 12:36:36 +02:00
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddGreaterEqual ( NodeID_1 , NodeID_2 ) ) ) ;
2009-06-05 16:45:23 +02:00
else
2009-08-25 11:43:01 +02:00
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-06-05 16:45:23 +02:00
break ;
case oEqualEqual :
2009-07-06 12:36:36 +02:00
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddEqualEqual ( NodeID_1 , NodeID_2 ) ) ) ;
2009-06-05 16:45:23 +02:00
else
2009-08-25 11:43:01 +02:00
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-06-05 16:45:23 +02:00
break ;
case oDifferent :
2009-07-06 12:36:36 +02:00
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddDifferent ( NodeID_1 , NodeID_2 ) ) ) ;
2009-06-05 16:45:23 +02:00
else
2009-08-25 11:43:01 +02:00
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-06-05 16:45:23 +02:00
break ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2008-11-14 17:07:47 +01:00
2009-04-14 16:39:53 +02:00
NodeID
2009-07-06 11:34:21 +02:00
BinaryOpNode : : getChainRuleDerivative ( int deriv_id , const map < int , NodeID > & recursive_variables )
2009-04-14 16:39:53 +02:00
{
2009-07-06 11:34:21 +02:00
NodeID darg1 = arg1 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
NodeID darg2 = arg2 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
return composeDerivatives ( darg1 , darg2 ) ;
2009-04-14 16:39:53 +02:00
}
2009-09-30 17:10:31 +02:00
NodeID
BinaryOpNode : : buildSimilarBinaryOpNode ( NodeID alt_arg1 , NodeID alt_arg2 , DataTree & alt_datatree ) const
{
switch ( op_code )
{
case oPlus :
return alt_datatree . AddPlus ( alt_arg1 , alt_arg2 ) ;
case oMinus :
return alt_datatree . AddMinus ( alt_arg1 , alt_arg2 ) ;
case oTimes :
return alt_datatree . AddTimes ( alt_arg1 , alt_arg2 ) ;
case oDivide :
return alt_datatree . AddDivide ( alt_arg1 , alt_arg2 ) ;
case oPower :
return alt_datatree . AddPower ( alt_arg1 , alt_arg2 ) ;
case oEqual :
return alt_datatree . AddEqual ( alt_arg1 , alt_arg2 ) ;
case oMax :
return alt_datatree . AddMax ( alt_arg1 , alt_arg2 ) ;
case oMin :
return alt_datatree . AddMin ( alt_arg1 , alt_arg2 ) ;
case oLess :
return alt_datatree . AddLess ( alt_arg1 , alt_arg2 ) ;
case oGreater :
return alt_datatree . AddGreater ( alt_arg1 , alt_arg2 ) ;
case oLessEqual :
return alt_datatree . AddLessEqual ( alt_arg1 , alt_arg2 ) ;
case oGreaterEqual :
return alt_datatree . AddGreaterEqual ( alt_arg1 , alt_arg2 ) ;
case oEqualEqual :
return alt_datatree . AddEqualEqual ( alt_arg1 , alt_arg2 ) ;
case oDifferent :
return alt_datatree . AddDifferent ( alt_arg1 , alt_arg2 ) ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2009-06-05 16:45:23 +02:00
NodeID
BinaryOpNode : : toStatic ( DataTree & static_datatree ) const
2009-09-30 17:10:31 +02:00
{
NodeID sarg1 = arg1 - > toStatic ( static_datatree ) ;
NodeID sarg2 = arg2 - > toStatic ( static_datatree ) ;
return buildSimilarBinaryOpNode ( sarg1 , sarg2 , static_datatree ) ;
}
int
BinaryOpNode : : maxEndoLead ( ) const
{
return max ( arg1 - > maxEndoLead ( ) , arg2 - > maxEndoLead ( ) ) ;
}
2009-06-05 16:45:23 +02:00
2009-09-30 17:10:31 +02:00
NodeID
BinaryOpNode : : decreaseLeadsLags ( int n ) const
{
NodeID arg1subst = arg1 - > decreaseLeadsLags ( n ) ;
NodeID arg2subst = arg2 - > decreaseLeadsLags ( n ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
NodeID
BinaryOpNode : : substituteLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
NodeID arg1subst , arg2subst ;
int maxlead1 = arg1 - > maxEndoLead ( ) , maxlead2 = arg2 - > maxEndoLead ( ) ;
if ( maxlead1 < 2 & & maxlead2 < 2 )
return const_cast < BinaryOpNode * > ( this ) ;
switch ( op_code )
{
case oPlus :
case oMinus :
case oEqual :
arg1subst = maxlead1 > = 2 ? arg1 - > substituteLeadGreaterThanTwo ( subst_table , neweqs ) : arg1 ;
arg2subst = maxlead2 > = 2 ? arg2 - > substituteLeadGreaterThanTwo ( subst_table , neweqs ) : arg2 ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
case oTimes :
case oDivide :
if ( maxlead1 > = 2 & & maxlead2 = = 0 )
{
arg1subst = arg1 - > substituteLeadGreaterThanTwo ( subst_table , neweqs ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2 , datatree ) ;
}
if ( maxlead1 = = 0 & & maxlead2 > = 2 & & op_code = = oTimes )
{
arg2subst = arg2 - > substituteLeadGreaterThanTwo ( subst_table , neweqs ) ;
return buildSimilarBinaryOpNode ( arg1 , arg2subst , datatree ) ;
}
return createLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
default :
return createLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
}
}
NodeID
BinaryOpNode : : substituteLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
NodeID arg1subst = arg1 - > substituteLagGreaterThanTwo ( subst_table , neweqs ) ;
NodeID arg2subst = arg2 - > substituteLagGreaterThanTwo ( subst_table , neweqs ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2009-04-14 16:39:53 +02:00
2008-02-03 11:28:36 +01:00
TrinaryOpNode : : TrinaryOpNode ( DataTree & datatree_arg , const NodeID arg1_arg ,
2009-01-23 11:59:37 +01:00
TrinaryOpcode op_code_arg , const NodeID arg2_arg , const NodeID arg3_arg ) :
2009-06-05 16:45:23 +02:00
ExprNode ( datatree_arg ) ,
arg1 ( arg1_arg ) ,
arg2 ( arg2_arg ) ,
arg3 ( arg3_arg ) ,
op_code ( op_code_arg )
2008-02-03 11:28:36 +01:00
{
datatree . trinary_op_node_map [ make_pair ( make_pair ( make_pair ( arg1 , arg2 ) , arg3 ) , op_code ) ] = this ;
2009-09-30 17:10:31 +02:00
}
void
TrinaryOpNode : : prepareForDerivation ( )
{
if ( preparedForDerivation )
return ;
preparedForDerivation = true ;
arg1 - > prepareForDerivation ( ) ;
arg2 - > prepareForDerivation ( ) ;
arg3 - > prepareForDerivation ( ) ;
2008-02-03 11:28:36 +01:00
// Non-null derivatives are the union of those of the arguments
// Compute set union of arg{1,2,3}->non_null_derivatives
2008-11-14 17:07:47 +01:00
set < int > non_null_derivatives_tmp ;
2008-02-03 11:28:36 +01:00
set_union ( arg1 - > non_null_derivatives . begin ( ) ,
arg1 - > non_null_derivatives . end ( ) ,
arg2 - > non_null_derivatives . begin ( ) ,
arg2 - > non_null_derivatives . end ( ) ,
inserter ( non_null_derivatives_tmp , non_null_derivatives_tmp . begin ( ) ) ) ;
set_union ( non_null_derivatives_tmp . begin ( ) ,
non_null_derivatives_tmp . end ( ) ,
arg3 - > non_null_derivatives . begin ( ) ,
arg3 - > non_null_derivatives . end ( ) ,
inserter ( non_null_derivatives , non_null_derivatives . begin ( ) ) ) ;
}
NodeID
2009-07-06 11:34:21 +02:00
TrinaryOpNode : : composeDerivatives ( NodeID darg1 , NodeID darg2 , NodeID darg3 )
2008-02-03 11:28:36 +01:00
{
NodeID t11 , t12 , t13 , t14 , t15 ;
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
case oNormcdf :
// normal pdf is inlined in the tree
NodeID y ;
// sqrt(2*pi)
2009-04-16 12:33:30 +02:00
t14 = datatree . AddSqrt ( datatree . AddTimes ( datatree . Two , datatree . Pi ) ) ;
2008-02-03 11:28:36 +01:00
// x - mu
t12 = datatree . AddMinus ( arg1 , arg2 ) ;
// y = (x-mu)/sigma
y = datatree . AddDivide ( t12 , arg3 ) ;
// (x-mu)^2/sigma^2
t12 = datatree . AddTimes ( y , y ) ;
// -(x-mu)^2/sigma^2
t13 = datatree . AddUMinus ( t12 ) ;
// -((x-mu)^2/sigma^2)/2
2009-04-17 23:22:44 +02:00
t12 = datatree . AddDivide ( t13 , datatree . Two ) ;
2008-02-03 11:28:36 +01:00
// exp(-((x-mu)^2/sigma^2)/2)
t13 = datatree . AddExp ( t12 ) ;
// derivative of a standardized normal
// t15 = (1/sqrt(2*pi))*exp(-y^2/2)
t15 = datatree . AddDivide ( t13 , t14 ) ;
// derivatives thru x
t11 = datatree . AddDivide ( darg1 , arg3 ) ;
// derivatives thru mu
t12 = datatree . AddDivide ( darg2 , arg3 ) ;
// intermediary sum
t14 = datatree . AddMinus ( t11 , t12 ) ;
// derivatives thru sigma
t11 = datatree . AddDivide ( y , arg3 ) ;
t12 = datatree . AddTimes ( t11 , darg3 ) ;
//intermediary sum
t11 = datatree . AddMinus ( t14 , t12 ) ;
// total derivative:
2009-05-04 14:59:21 +02:00
// (darg1/sigma - darg2/sigma - darg3*(x-mu)/sigma^2) * t15
// where t15 is the derivative of a standardized normal
2008-02-03 11:28:36 +01:00
return datatree . AddTimes ( t11 , t15 ) ;
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2009-07-06 11:34:21 +02:00
NodeID
TrinaryOpNode : : computeDerivative ( int deriv_id )
{
NodeID darg1 = arg1 - > getDerivative ( deriv_id ) ;
NodeID darg2 = arg2 - > getDerivative ( deriv_id ) ;
NodeID darg3 = arg3 - > getDerivative ( deriv_id ) ;
return composeDerivatives ( darg1 , darg2 , darg3 ) ;
}
2008-02-03 11:28:36 +01:00
int
TrinaryOpNode : : precedence ( ExprNodeOutputType output_type , const temporary_terms_type & temporary_terms ) const
2009-06-05 16:45:23 +02:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < TrinaryOpNode * > ( this ) ) ;
// A temporary term behaves as a variable
if ( it ! = temporary_terms . end ( ) )
2008-02-03 11:28:36 +01:00
return 100 ;
2009-06-05 16:45:23 +02:00
switch ( op_code )
{
case oNormcdf :
return 100 ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2008-02-03 11:28:36 +01:00
int
TrinaryOpNode : : cost ( const temporary_terms_type & temporary_terms , bool is_matlab ) const
2009-06-05 16:45:23 +02:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < TrinaryOpNode * > ( this ) ) ;
// For a temporary term, the cost is null
if ( it ! = temporary_terms . end ( ) )
return 0 ;
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
int cost = arg1 - > cost ( temporary_terms , is_matlab ) ;
cost + = arg2 - > cost ( temporary_terms , is_matlab ) ;
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
if ( is_matlab )
// Cost for Matlab files
switch ( op_code )
{
case oNormcdf :
return cost + 1000 ;
}
else
// Cost for C files
switch ( op_code )
{
case oNormcdf :
return cost + 1000 ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2008-02-03 11:28:36 +01:00
void
TrinaryOpNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
2009-01-23 11:59:37 +01:00
temporary_terms_type & temporary_terms ,
bool is_matlab ) const
2009-06-05 16:45:23 +02:00
{
NodeID this2 = const_cast < TrinaryOpNode * > ( this ) ;
map < NodeID , int > : : iterator it = reference_count . find ( this2 ) ;
if ( it = = reference_count . end ( ) )
{
// If this node has never been encountered, set its ref count to one,
// and travel through its children
reference_count [ this2 ] = 1 ;
arg1 - > computeTemporaryTerms ( reference_count , temporary_terms , is_matlab ) ;
arg2 - > computeTemporaryTerms ( reference_count , temporary_terms , is_matlab ) ;
arg3 - > computeTemporaryTerms ( reference_count , temporary_terms , is_matlab ) ;
}
else
{
// If the node has already been encountered, increment its ref count
// and declare it as a temporary term if it is too costly
reference_count [ this2 ] + + ;
if ( reference_count [ this2 ] * cost ( temporary_terms , is_matlab ) > MIN_COST ( is_matlab ) )
temporary_terms . insert ( this2 ) ;
}
}
2008-02-03 11:28:36 +01:00
void
TrinaryOpNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
2009-01-23 11:59:37 +01:00
temporary_terms_type & temporary_terms ,
map < NodeID , pair < int , int > > & first_occurence ,
int Curr_block ,
Model_Block * ModelBlock ,
int equation ,
map_idx_type & map_idx ) const
2009-06-05 16:45:23 +02:00
{
NodeID this2 = const_cast < TrinaryOpNode * > ( this ) ;
map < NodeID , int > : : iterator it = reference_count . find ( this2 ) ;
if ( it = = reference_count . end ( ) )
{
reference_count [ this2 ] = 1 ;
first_occurence [ this2 ] = make_pair ( Curr_block , equation ) ;
arg1 - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , ModelBlock , equation , map_idx ) ;
arg2 - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , ModelBlock , equation , map_idx ) ;
arg3 - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , ModelBlock , equation , map_idx ) ;
}
else
{
reference_count [ this2 ] + + ;
if ( reference_count [ this2 ] * cost ( temporary_terms , false ) > MIN_COST_C )
{
temporary_terms . insert ( this2 ) ;
ModelBlock - > Block_List [ first_occurence [ this2 ] . first ] . Temporary_Terms_in_Equation [ first_occurence [ this2 ] . second ] - > insert ( this2 ) ;
}
}
}
2008-02-03 11:28:36 +01:00
double
TrinaryOpNode : : eval_opcode ( double v1 , TrinaryOpcode op_code , double v2 , double v3 ) throw ( EvalException )
{
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
case oNormcdf :
cerr < < " NORMCDF: eval not implemented " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
double
TrinaryOpNode : : eval ( const eval_context_type & eval_context ) const throw ( EvalException )
{
double v1 = arg1 - > eval ( eval_context ) ;
double v2 = arg2 - > eval ( eval_context ) ;
double v3 = arg3 - > eval ( eval_context ) ;
return eval_opcode ( v1 , op_code , v2 , v3 ) ;
}
void
2009-09-18 18:34:11 +02:00
TrinaryOpNode : : compile ( ostream & CompileCode , bool lhs_rhs , const temporary_terms_type & temporary_terms , map_idx_type & map_idx , bool dynamic , bool steady_dynamic ) const
2009-06-05 16:45:23 +02:00
{
// If current node is a temporary term
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < TrinaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
{
2009-08-25 11:43:01 +02:00
if ( dynamic )
CompileCode . write ( & FLDT , sizeof ( FLDT ) ) ;
else
CompileCode . write ( & FLDST , sizeof ( FLDST ) ) ;
2009-06-05 16:45:23 +02:00
int var = map_idx [ idx ] ;
CompileCode . write ( reinterpret_cast < char * > ( & var ) , sizeof ( var ) ) ;
return ;
}
2009-09-18 18:34:11 +02:00
arg1 - > compile ( CompileCode , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic ) ;
arg2 - > compile ( CompileCode , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic ) ;
arg3 - > compile ( CompileCode , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic ) ;
2009-06-05 16:45:23 +02:00
CompileCode . write ( & FBINARY , sizeof ( FBINARY ) ) ;
TrinaryOpcode op_codel = op_code ;
CompileCode . write ( reinterpret_cast < char * > ( & op_codel ) , sizeof ( op_codel ) ) ;
}
2008-02-03 11:28:36 +01:00
2008-12-24 16:49:01 +01:00
void
TrinaryOpNode : : collectTemporary_terms ( const temporary_terms_type & temporary_terms , Model_Block * ModelBlock , int Curr_Block ) const
2009-06-05 16:45:23 +02:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < TrinaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
ModelBlock - > Block_List [ Curr_Block ] . Temporary_InUse - > insert ( idx ) ;
else
{
arg1 - > collectTemporary_terms ( temporary_terms , ModelBlock , Curr_Block ) ;
arg2 - > collectTemporary_terms ( temporary_terms , ModelBlock , Curr_Block ) ;
arg3 - > collectTemporary_terms ( temporary_terms , ModelBlock , Curr_Block ) ;
}
}
2008-12-24 16:49:01 +01:00
2008-02-03 11:28:36 +01:00
void
TrinaryOpNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2009-01-23 11:59:37 +01:00
const temporary_terms_type & temporary_terms ) const
2009-06-05 16:45:23 +02:00
{
// TrinaryOpNode not implemented for C output
assert ( ! IS_C ( output_type ) ) ;
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
// If current node is a temporary term
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < TrinaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
{
output < < " T " < < idx ;
return ;
}
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
switch ( op_code )
{
case oNormcdf :
output < < " normcdf( " ;
break ;
}
arg1 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " , " ;
arg2 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " , " ;
arg3 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " ) " ;
}
2008-02-03 11:28:36 +01:00
void
2009-07-10 18:42:08 +02:00
TrinaryOpNode : : collectVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
{
arg1 - > collectVariables ( type_arg , result ) ;
arg2 - > collectVariables ( type_arg , result ) ;
arg3 - > collectVariables ( type_arg , result ) ;
}
2009-06-05 16:45:23 +02:00
2009-08-25 11:43:01 +02:00
pair < int , NodeID >
TrinaryOpNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < NodeID , NodeID > > > & List_of_Op_RHS ) const
2009-06-05 16:45:23 +02:00
{
2009-08-25 11:43:01 +02:00
pair < int , NodeID > res = arg1 - > normalizeEquation ( var_endo , List_of_Op_RHS ) ;
2009-06-05 16:45:23 +02:00
bool is_endogenous_present_1 = res . first ;
NodeID NodeID_1 = res . second ;
2009-08-25 11:43:01 +02:00
res = arg2 - > normalizeEquation ( var_endo , List_of_Op_RHS ) ;
2009-06-05 16:45:23 +02:00
bool is_endogenous_present_2 = res . first ;
NodeID NodeID_2 = res . second ;
2009-08-25 11:43:01 +02:00
res = arg3 - > normalizeEquation ( var_endo , List_of_Op_RHS ) ;
2009-06-05 16:45:23 +02:00
bool is_endogenous_present_3 = res . first ;
NodeID NodeID_3 = res . second ;
2009-07-06 12:36:36 +02:00
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 & & ! is_endogenous_present_3 )
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddNormcdf ( NodeID_1 , NodeID_2 , NodeID_3 ) ) ) ;
2009-06-05 16:45:23 +02:00
else
2009-08-25 11:43:01 +02:00
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-06-05 16:45:23 +02:00
}
2008-11-14 17:07:47 +01:00
2009-04-14 16:39:53 +02:00
NodeID
2009-07-06 11:34:21 +02:00
TrinaryOpNode : : getChainRuleDerivative ( int deriv_id , const map < int , NodeID > & recursive_variables )
2009-04-14 16:39:53 +02:00
{
2009-07-06 11:34:21 +02:00
NodeID darg1 = arg1 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
NodeID darg2 = arg2 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
NodeID darg3 = arg3 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
return composeDerivatives ( darg1 , darg2 , darg3 ) ;
2009-04-14 16:39:53 +02:00
}
2009-09-30 17:10:31 +02:00
NodeID
TrinaryOpNode : : buildSimilarTrinaryOpNode ( NodeID alt_arg1 , NodeID alt_arg2 , NodeID alt_arg3 , DataTree & alt_datatree ) const
{
switch ( op_code )
{
case oNormcdf :
return alt_datatree . AddNormcdf ( alt_arg1 , alt_arg2 , alt_arg3 ) ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2009-06-05 16:45:23 +02:00
NodeID
TrinaryOpNode : : toStatic ( DataTree & static_datatree ) const
2009-09-30 17:10:31 +02:00
{
NodeID sarg1 = arg1 - > toStatic ( static_datatree ) ;
NodeID sarg2 = arg2 - > toStatic ( static_datatree ) ;
NodeID sarg3 = arg3 - > toStatic ( static_datatree ) ;
return buildSimilarTrinaryOpNode ( sarg1 , sarg2 , sarg3 , static_datatree ) ;
}
2009-06-05 16:45:23 +02:00
2009-09-30 17:10:31 +02:00
int
TrinaryOpNode : : maxEndoLead ( ) const
{
return max ( arg1 - > maxEndoLead ( ) , max ( arg2 - > maxEndoLead ( ) , arg3 - > maxEndoLead ( ) ) ) ;
}
NodeID
TrinaryOpNode : : decreaseLeadsLags ( int n ) const
{
NodeID arg1subst = arg1 - > decreaseLeadsLags ( n ) ;
NodeID arg2subst = arg2 - > decreaseLeadsLags ( n ) ;
NodeID arg3subst = arg3 - > decreaseLeadsLags ( n ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
NodeID
TrinaryOpNode : : substituteLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
if ( maxEndoLead ( ) < 2 )
return const_cast < TrinaryOpNode * > ( this ) ;
else
return createLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
}
NodeID
TrinaryOpNode : : substituteLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
NodeID arg1subst = arg1 - > substituteLagGreaterThanTwo ( subst_table , neweqs ) ;
NodeID arg2subst = arg2 - > substituteLagGreaterThanTwo ( subst_table , neweqs ) ;
NodeID arg3subst = arg3 - > substituteLagGreaterThanTwo ( subst_table , neweqs ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2008-11-14 17:07:47 +01:00
2008-02-03 11:28:36 +01:00
UnknownFunctionNode : : UnknownFunctionNode ( DataTree & datatree_arg ,
2009-06-05 16:45:23 +02:00
int symb_id_arg ,
const vector < NodeID > & arguments_arg ) :
ExprNode ( datatree_arg ) ,
symb_id ( symb_id_arg ) ,
arguments ( arguments_arg )
2008-02-03 11:28:36 +01:00
{
}
2009-09-30 17:10:31 +02:00
void
UnknownFunctionNode : : prepareForDerivation ( )
{
cerr < < " UnknownFunctionNode::prepareForDerivation: operation impossible! " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2008-02-03 11:28:36 +01:00
NodeID
2009-04-17 18:26:23 +02:00
UnknownFunctionNode : : computeDerivative ( int deriv_id )
2008-02-03 11:28:36 +01:00
{
cerr < < " UnknownFunctionNode::computeDerivative: operation impossible! " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2009-06-05 16:45:23 +02:00
NodeID
2009-07-06 11:34:21 +02:00
UnknownFunctionNode : : getChainRuleDerivative ( int deriv_id , const map < int , NodeID > & recursive_variables )
2008-02-03 11:28:36 +01:00
{
2009-07-06 11:34:21 +02:00
cerr < < " UnknownFunctionNode::getChainRuleDerivative: operation impossible! " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2009-06-05 16:45:23 +02:00
void
UnknownFunctionNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
temporary_terms_type & temporary_terms ,
bool is_matlab ) const
{
cerr < < " UnknownFunctionNode::computeTemporaryTerms: operation impossible! " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2008-02-03 11:28:36 +01:00
void UnknownFunctionNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_type & temporary_terms ) const
2009-06-05 16:45:23 +02:00
{
output < < datatree . symbol_table . getName ( symb_id ) < < " ( " ;
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ;
it ! = arguments . end ( ) ; it + + )
{
if ( it ! = arguments . begin ( ) )
output < < " , " ;
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
( * it ) - > writeOutput ( output , output_type , temporary_terms ) ;
}
output < < " ) " ;
}
2008-02-03 11:28:36 +01:00
void
UnknownFunctionNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
2009-06-05 16:45:23 +02:00
temporary_terms_type & temporary_terms ,
map < NodeID , pair < int , int > > & first_occurence ,
int Curr_block ,
Model_Block * ModelBlock ,
int equation ,
map_idx_type & map_idx ) const
{
cerr < < " UnknownFunctionNode::computeTemporaryTerms: not implemented " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2008-02-03 11:28:36 +01:00
void
2009-07-10 18:42:08 +02:00
UnknownFunctionNode : : collectVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
{
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ;
it ! = arguments . end ( ) ; it + + )
( * it ) - > collectVariables ( type_arg , result ) ;
}
2008-11-14 17:07:47 +01:00
2008-12-24 16:49:01 +01:00
void
UnknownFunctionNode : : collectTemporary_terms ( const temporary_terms_type & temporary_terms , Model_Block * ModelBlock , int Curr_Block ) const
2009-06-05 16:45:23 +02:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < UnknownFunctionNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
ModelBlock - > Block_List [ Curr_Block ] . Temporary_InUse - > insert ( idx ) ;
else
{
//arg->collectTemporary_terms(temporary_terms, result);
}
}
2008-12-24 16:49:01 +01:00
2008-11-14 17:07:47 +01:00
2008-02-03 11:28:36 +01:00
double
UnknownFunctionNode : : eval ( const eval_context_type & eval_context ) const throw ( EvalException )
{
throw EvalException ( ) ;
}
void
2009-09-18 18:34:11 +02:00
UnknownFunctionNode : : compile ( ostream & CompileCode , bool lhs_rhs , const temporary_terms_type & temporary_terms , map_idx_type & map_idx , bool dynamic , bool steady_dynamic ) const
2009-06-05 16:45:23 +02:00
{
cerr < < " UnknownFunctionNode::compile: operation impossible! " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2009-08-25 11:43:01 +02:00
pair < int , NodeID >
UnknownFunctionNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < NodeID , NodeID > > > & List_of_Op_RHS ) const
2009-06-05 16:45:23 +02:00
{
vector < pair < bool , NodeID > > V_arguments ;
vector < NodeID > V_NodeID ;
bool present = false ;
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ;
it ! = arguments . end ( ) ; it + + )
{
2009-08-25 11:43:01 +02:00
V_arguments . push_back ( ( * it ) - > normalizeEquation ( var_endo , List_of_Op_RHS ) ) ;
2009-07-06 12:36:36 +02:00
present = present | | V_arguments [ V_arguments . size ( ) - 1 ] . first ;
2009-06-05 16:45:23 +02:00
V_NodeID . push_back ( V_arguments [ V_arguments . size ( ) - 1 ] . second ) ;
}
2009-07-06 12:36:36 +02:00
if ( ! present )
2009-08-25 11:43:01 +02:00
return ( make_pair ( 0 , datatree . AddUnknownFunction ( datatree . symbol_table . getName ( symb_id ) , V_NodeID ) ) ) ;
2009-06-05 16:45:23 +02:00
else
2009-08-25 11:43:01 +02:00
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-06-05 16:45:23 +02:00
}
2009-04-14 16:39:53 +02:00
NodeID
UnknownFunctionNode : : toStatic ( DataTree & static_datatree ) const
2009-06-05 16:45:23 +02:00
{
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 ) ;
}
2009-09-30 17:10:31 +02:00
int
UnknownFunctionNode : : maxEndoLead ( ) const
{
int val = 0 ;
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ;
it ! = arguments . end ( ) ; it + + )
val = max ( val , ( * it ) - > maxEndoLead ( ) ) ;
return val ;
}
NodeID
UnknownFunctionNode : : decreaseLeadsLags ( int n ) const
{
cerr < < " UnknownFunctionNode::decreaseLeadsLags: not implemented! " < < endl ;
exit ( EXIT_FAILURE ) ;
}
NodeID
UnknownFunctionNode : : substituteLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
cerr < < " UnknownFunctionNode::substituteLeadGreaterThanTwo: not implemented! " < < endl ;
exit ( EXIT_FAILURE ) ;
}
NodeID
UnknownFunctionNode : : substituteLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
cerr < < " UnknownFunctionNode::substituteLagGreaterThanTwo: not implemented! " < < endl ;
exit ( EXIT_FAILURE ) ;
}