2011-02-04 16:25:38 +01:00
/*
2011-01-13 15:52:44 +01:00
* Copyright ( C ) 2007 - 2011 Dynare Team
2008-01-11 14:42:14 +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/>.
*/
2007-01-09 20:00:05 +01:00
# 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>
2007-02-22 00:28:16 +01:00
2007-01-09 20:00:05 +01:00
# include "ExprNode.hh"
# include "DataTree.hh"
2009-10-29 18:16:10 +01:00
# include "ModFile.hh"
2007-01-09 20:00:05 +01:00
2009-09-30 17:10:31 +02:00
ExprNode : : ExprNode ( DataTree & datatree_arg ) : datatree ( datatree_arg ) , preparedForDerivation ( false )
2007-01-09 20:00:05 +01:00
{
// Add myself to datatree
datatree . node_list . push_back ( this ) ;
// Set my index and increment counter
idx = datatree . node_counter + + ;
}
ExprNode : : ~ ExprNode ( )
{
}
2010-09-16 19:18:45 +02:00
expr_t
2009-04-17 18:26:23 +02:00
ExprNode : : getDerivative ( int deriv_id )
2007-01-09 20:00:05 +01:00
{
2009-09-30 17:10:31 +02:00
if ( ! preparedForDerivation )
prepareForDerivation ( ) ;
2009-10-02 19:02:35 +02:00
2007-01-09 20:00:05 +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 ) ;
2007-01-09 20:00:05 +01:00
if ( it = = non_null_derivatives . end ( ) )
return datatree . Zero ;
2009-10-02 19:02:35 +02:00
2007-01-09 20:00:05 +01:00
// If derivative is stored in cache, use the cached value, otherwise compute it (and cache it)
2010-09-16 19:18:45 +02:00
map < int , expr_t > : : const_iterator it2 = derivatives . find ( deriv_id ) ;
2007-01-09 20:00:05 +01:00
if ( it2 ! = derivatives . end ( ) )
return it2 - > second ;
else
{
2010-09-16 19:18:45 +02:00
expr_t d = computeDerivative ( deriv_id ) ;
2009-04-17 18:26:23 +02:00
derivatives [ deriv_id ] = d ;
2007-01-09 20:00:05 +01:00
return d ;
}
}
2009-06-05 16:45:23 +02:00
int
2010-09-16 19:00:48 +02:00
ExprNode : : precedence ( ExprNodeOutputType output_type , const temporary_terms_t & temporary_terms ) const
2009-12-16 18:13:23 +01:00
{
// For a constant, a variable, or a unary op, the precedence is maximal
return 100 ;
}
2009-06-05 16:45:23 +02:00
2007-01-09 20:00:05 +01:00
int
2010-09-16 19:00:48 +02:00
ExprNode : : cost ( const temporary_terms_t & temporary_terms , bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
// For a terminal node, the cost is null
return 0 ;
}
2007-01-09 20:00:05 +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 ) ;
2009-12-16 18:13:23 +01:00
for ( set < pair < int , int > > : : const_iterator it = symb_ids . begin ( ) ;
it ! = symb_ids . end ( ) ; it + + )
2009-07-10 18:42:08 +02:00
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 ) ;
2009-12-16 18:13:23 +01:00
for ( set < pair < int , int > > : : const_iterator it = symb_ids . begin ( ) ;
it ! = symb_ids . end ( ) ; it + + )
2009-07-10 18:42:08 +02:00
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
}
2007-01-09 20:00:05 +01:00
void
2010-09-16 19:18:45 +02:00
ExprNode : : computeTemporaryTerms ( map < expr_t , int > & reference_count ,
2010-09-16 19:00:48 +02:00
temporary_terms_t & temporary_terms ,
2007-03-06 18:14:35 +01:00
bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
// Nothing to do for a terminal node
}
2007-01-09 20:00:05 +01:00
2007-02-22 00:28:16 +01:00
void
2010-09-16 19:18:45 +02:00
ExprNode : : computeTemporaryTerms ( map < expr_t , int > & reference_count ,
2010-09-16 19:00:48 +02:00
temporary_terms_t & temporary_terms ,
2010-09-16 19:18:45 +02:00
map < expr_t , pair < int , int > > & first_occurence ,
2007-02-22 00:28:16 +01:00
int Curr_block ,
2010-09-16 19:00:48 +02:00
vector < vector < temporary_terms_t > > & v_temporary_terms ,
2009-12-16 14:21:31 +01:00
int equation ) const
2009-12-16 18:13:23 +01:00
{
// Nothing to do for a terminal node
}
2007-02-22 00:28:16 +01:00
2010-09-16 19:18:45 +02:00
pair < int , expr_t >
ExprNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < expr_t , expr_t > > > & List_of_Op_RHS ) const
2009-12-16 18:13:23 +01:00
{
2011-06-10 11:59:34 +02:00
/* nothing to do */
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
}
2009-08-25 11:43:01 +02:00
2007-03-09 18:27:46 +01:00
void
2010-03-09 12:16:32 +01:00
ExprNode : : writeOutput ( ostream & output ) const
2007-03-09 18:27:46 +01:00
{
2010-09-16 19:00:48 +02:00
writeOutput ( output , oMatlabOutsideModel , temporary_terms_t ( ) ) ;
2007-03-09 18:27:46 +01:00
}
2010-03-09 12:16:32 +01:00
void
ExprNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ) const
{
2010-09-16 19:00:48 +02:00
writeOutput ( output , output_type , temporary_terms_t ( ) ) ;
2010-03-09 12:16:32 +01:00
}
2010-03-04 16:40:07 +01:00
void
2010-09-16 19:00:48 +02:00
ExprNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type , const temporary_terms_t & temporary_terms ) const
2010-03-04 16:40:07 +01:00
{
2010-09-16 19:00:48 +02:00
deriv_node_temp_terms_t tef_terms ;
2010-03-04 16:40:07 +01:00
writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
}
2010-12-10 11:50:27 +01:00
void
ExprNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
2011-02-04 16:25:38 +01:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
const map_idx_t & map_idx , bool dynamic , bool steady_dynamic ) const
2010-12-10 11:50:27 +01:00
{
deriv_node_temp_terms_t tef_terms ;
compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic , tef_terms ) ;
}
2010-03-04 16:40:07 +01:00
void
ExprNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
deriv_node_temp_terms_t & tef_terms ) const
2010-03-04 16:40:07 +01:00
{
// Nothing to do
}
2010-12-10 11:50:27 +01:00
void
ExprNode : : compileExternalFunctionOutput ( ostream & CompileCode , unsigned int & instruction_number ,
2011-02-04 16:25:38 +01:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
const map_idx_t & map_idx , bool dynamic , bool steady_dynamic ,
deriv_node_temp_terms_t & tef_terms ) const
2010-12-10 11:50:27 +01:00
{
// Nothing to do
}
2009-09-30 17:10:31 +02:00
VariableNode *
2009-10-07 16:07:13 +02:00
ExprNode : : createEndoLeadAuxiliaryVarForMyself ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
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 ) ;
2010-09-16 19:18:45 +02:00
expr_t substexpr = decreaseLeadsLags ( n - 1 ) ;
2009-09-30 17:10:31 +02:00
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))
2009-12-16 18:13:23 +01:00
while ( lag > = 0 )
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t orig_expr = decreaseLeadsLags ( lag ) ;
2009-09-30 17:10:31 +02:00
it = subst_table . find ( orig_expr ) ;
if ( it = = subst_table . end ( ) )
{
2009-10-07 16:07:13 +02:00
int symb_id = datatree . symbol_table . addEndoLeadAuxiliaryVar ( orig_expr - > idx ) ;
2009-09-30 17:10:31 +02:00
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-10-07 18:34:42 +02:00
VariableNode *
ExprNode : : createExoLeadAuxiliaryVarForMyself ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
int n = maxExoLead ( ) ;
assert ( n > = 1 ) ;
subst_table_t : : const_iterator it = subst_table . find ( this ) ;
if ( it ! = subst_table . end ( ) )
return const_cast < VariableNode * > ( it - > second ) ;
2010-09-16 19:18:45 +02:00
expr_t substexpr = decreaseLeadsLags ( n ) ;
2009-10-07 18:34:42 +02:00
int lag = n - 1 ;
// 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))
2009-12-16 18:13:23 +01:00
while ( lag > = 0 )
2009-10-07 18:34:42 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t orig_expr = decreaseLeadsLags ( lag ) ;
2009-10-07 18:34:42 +02:00
it = subst_table . find ( orig_expr ) ;
if ( it = = subst_table . end ( ) )
{
int symb_id = datatree . symbol_table . addExoLeadAuxiliaryVar ( 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 ) ;
}
2010-04-16 16:54:55 +02:00
bool
ExprNode : : isNumConstNodeEqualTo ( double value ) const
{
return false ;
}
bool
ExprNode : : isVariableNodeEqualTo ( SymbolType type_arg , int variable_id , int lag_arg ) const
{
return false ;
}
2007-01-09 20:00:05 +01:00
NumConstNode : : NumConstNode ( DataTree & datatree_arg , int id_arg ) :
2009-12-16 18:13:23 +01:00
ExprNode ( datatree_arg ) ,
id ( id_arg )
2007-01-09 20:00:05 +01:00
{
// Add myself to the num const map
datatree . num_const_node_map [ id ] = this ;
2009-09-30 17:10:31 +02:00
}
2007-01-09 20:00:05 +01:00
2009-09-30 17:10:31 +02:00
void
NumConstNode : : prepareForDerivation ( )
{
preparedForDerivation = true ;
2007-01-09 20:00:05 +01:00
// All derivatives are null, so non_null_derivatives is left empty
}
2010-09-16 19:18:45 +02:00
expr_t
2009-04-17 18:26:23 +02:00
NumConstNode : : computeDerivative ( int deriv_id )
2007-01-09 20:00:05 +01:00
{
return datatree . Zero ;
}
2008-12-24 16:49:01 +01:00
void
2010-09-16 19:00:48 +02:00
NumConstNode : : collectTemporary_terms ( const temporary_terms_t & temporary_terms , temporary_terms_inuse_t & temporary_terms_inuse , int Curr_Block ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < NumConstNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
if ( it ! = temporary_terms . end ( ) )
temporary_terms_inuse . insert ( idx ) ;
}
2008-12-24 16:49:01 +01:00
2007-01-09 20:00:05 +01:00
void
2007-03-06 18:14:35 +01:00
NumConstNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < NumConstNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
if ( it ! = temporary_terms . end ( ) )
if ( output_type = = oMatlabDynamicModelSparse )
output < < " T " < < idx < < " (it_) " ;
2007-11-21 00:24:01 +01:00
else
2009-12-16 18:13:23 +01:00
output < < " T " < < idx ;
else
output < < datatree . num_constants . get ( id ) ;
}
2007-01-09 20:00:05 +01:00
2007-03-09 18:27:46 +01:00
double
2010-12-10 11:50:27 +01:00
NumConstNode : : eval ( const eval_context_t & eval_context ) const throw ( EvalException , EvalExternalFunctionException )
2007-02-22 00:28:16 +01:00
{
2009-12-16 18:13:23 +01:00
return ( datatree . num_constants . getDouble ( id ) ) ;
2007-02-22 00:28:16 +01:00
}
2007-10-04 00:01:08 +02:00
void
2010-12-10 11:50:27 +01:00
NumConstNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
const map_idx_t & map_idx , bool dynamic , bool steady_dynamic ,
deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
FLDC_ fldc ( datatree . num_constants . getDouble ( id ) ) ;
2010-07-23 11:20:24 +02:00
fldc . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
2007-10-04 00:01:08 +02:00
2007-02-22 00:28:16 +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
2010-09-16 19:18:45 +02:00
pair < int , expr_t >
NumConstNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < expr_t , expr_t > > > & List_of_Op_RHS ) const
2009-12-16 18:13:23 +01:00
{
2011-06-10 11:59:34 +02:00
/* return the numercial constant */
2010-11-25 13:45:35 +01:00
return ( make_pair ( 0 , datatree . AddNonNegativeConstant ( datatree . num_constants . get ( id ) ) ) ) ;
2009-12-16 18:13:23 +01:00
}
2009-06-05 16:45:23 +02:00
2010-09-16 19:18:45 +02:00
expr_t
NumConstNode : : getChainRuleDerivative ( int deriv_id , const map < int , expr_t > & 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
}
2010-09-16 19:18:45 +02:00
expr_t
2009-04-14 16:39:53 +02:00
NumConstNode : : toStatic ( DataTree & static_datatree ) const
2009-12-16 18:13:23 +01:00
{
2010-11-25 13:45:35 +01:00
return static_datatree . AddNonNegativeConstant ( datatree . num_constants . get ( id ) ) ;
2009-12-16 18:13:23 +01:00
}
2009-04-14 16:39:53 +02:00
2010-10-15 19:05:16 +02:00
expr_t
NumConstNode : : cloneDynamic ( DataTree & dynamic_datatree ) const
{
2010-11-25 13:45:35 +01:00
return dynamic_datatree . AddNonNegativeConstant ( datatree . num_constants . get ( id ) ) ;
2010-10-15 19:05:16 +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-10-07 18:34:42 +02:00
int
NumConstNode : : maxExoLead ( ) const
{
return 0 ;
}
2010-08-19 15:20:54 +02:00
int
NumConstNode : : maxEndoLag ( ) const
{
return 0 ;
}
int
NumConstNode : : maxExoLag ( ) const
{
return 0 ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-09-30 17:10:31 +02:00
NumConstNode : : decreaseLeadsLags ( int n ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-11-09 12:03:18 +01:00
NumConstNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
2009-11-07 19:37:11 +01:00
{
2009-11-09 12:03:18 +01:00
return const_cast < NumConstNode * > ( this ) ;
2009-11-07 19:37:11 +01:00
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
NumConstNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-09-30 17:10:31 +02:00
{
return const_cast < NumConstNode * > ( this ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 16:07:13 +02:00
NumConstNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
NumConstNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-10-07 18:34:42 +02:00
{
return const_cast < NumConstNode * > ( this ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 18:34:42 +02:00
NumConstNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
return const_cast < NumConstNode * > ( this ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-29 18:16:10 +01:00
NumConstNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
2010-04-16 16:54:55 +02:00
bool
NumConstNode : : isNumConstNodeEqualTo ( double value ) const
{
if ( datatree . num_constants . getDouble ( id ) = = value )
return true ;
else
return false ;
}
bool
NumConstNode : : isVariableNodeEqualTo ( SymbolType type_arg , int variable_id , int lag_arg ) const
{
return false ;
}
2010-10-15 19:05:16 +02:00
expr_t
NumConstNode : : replaceTrendVar ( ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
expr_t
NumConstNode : : detrend ( int symb_id , expr_t trend ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
expr_t
NumConstNode : : removeTrendLeadLag ( map < int , expr_t > trend_symbols_map ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
2011-05-10 18:25:33 +02:00
VariableNode : : VariableNode ( DataTree & datatree_arg , int symb_id_arg , int lag_arg ) :
ExprNode ( datatree_arg ) ,
symb_id ( symb_id_arg ) ,
type ( datatree . symbol_table . getType ( symb_id_arg ) ) ,
lag ( lag_arg )
{
// Add myself to the variable map
datatree . variable_node_map [ make_pair ( symb_id , lag ) ] = this ;
// It makes sense to allow a lead/lag on parameters: during steady state calibration, endogenous and parameters can be swapped
assert ( type ! = eExternalFunction
& & ( lag = = 0 | | ( type ! = eModelLocalVariable & & type ! = eModFileLocalVariable ) ) ) ;
}
2009-09-30 17:10:31 +02:00
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
2007-01-09 20:00:05 +01:00
// Fill in non_null_derivatives
2009-06-05 16:45:23 +02:00
switch ( type )
2007-01-09 20:00:05 +01:00
{
case eEndogenous :
case eExogenous :
case eExogenousDet :
case eParameter :
2010-10-15 19:05:16 +02:00
case eTrend :
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 ) ) ;
2007-01-09 20:00:05 +01:00
break ;
2007-04-30 14:09:05 +02:00
case eModelLocalVariable :
2009-09-30 17:10:31 +02:00
datatree . local_variables_table [ symb_id ] - > prepareForDerivation ( ) ;
2007-01-09 20:00:05 +01:00
// Non null derivatives are those of the value of the local parameter
2007-04-30 14:09:05 +02:00
non_null_derivatives = datatree . local_variables_table [ symb_id ] - > non_null_derivatives ;
break ;
case eModFileLocalVariable :
// Such a variable is never derived
2007-01-09 20:00:05 +01:00
break ;
2010-02-22 17:33:38 +01:00
case eExternalFunction :
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 ) ;
2007-01-09 20:00:05 +01:00
}
}
2010-09-16 19:18:45 +02:00
expr_t
2009-09-30 17:10:31 +02:00
VariableNode : : computeDerivative ( int deriv_id )
2007-01-09 20:00:05 +01:00
{
2009-06-05 16:45:23 +02:00
switch ( type )
2007-01-09 20:00:05 +01:00
{
case eEndogenous :
case eExogenous :
case eExogenousDet :
2009-04-20 15:58:15 +02:00
case eParameter :
2010-10-15 19:05:16 +02:00
case eTrend :
2009-09-30 17:10:31 +02:00
if ( deriv_id = = datatree . getDerivID ( symb_id , lag ) )
2007-01-09 20:00:05 +01:00
return datatree . One ;
else
return datatree . Zero ;
2007-04-30 14:09:05 +02:00
case eModelLocalVariable :
2009-09-30 17:10:31 +02:00
return datatree . local_variables_table [ symb_id ] - > getDerivative ( deriv_id ) ;
2007-04-30 14:09:05 +02:00
case eModFileLocalVariable :
cerr < < " ModFileLocalVariable is not derivable " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2010-02-22 17:33:38 +01:00
case eExternalFunction :
2007-10-17 11:36:56 +02:00
cerr < < " Impossible case! " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2007-01-09 20:00:05 +01:00
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2007-01-09 20:00:05 +01:00
}
2008-12-24 16:49:01 +01:00
void
2010-09-16 19:00:48 +02:00
VariableNode : : collectTemporary_terms ( const temporary_terms_t & temporary_terms , temporary_terms_inuse_t & temporary_terms_inuse , int Curr_Block ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < VariableNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
if ( it ! = temporary_terms . end ( ) )
temporary_terms_inuse . insert ( idx ) ;
if ( type = = eModelLocalVariable )
datatree . local_variables_table [ symb_id ] - > collectTemporary_terms ( temporary_terms , temporary_terms_inuse , Curr_Block ) ;
}
2008-12-24 16:49:01 +01:00
2007-01-09 20:00:05 +01:00
void
2007-03-06 18:14:35 +01:00
VariableNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
// If node is a temporary term
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < VariableNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
if ( it ! = temporary_terms . end ( ) )
{
if ( output_type = = oMatlabDynamicModelSparse )
output < < " T " < < idx < < " (it_) " ;
else
output < < " T " < < idx ;
return ;
}
2007-03-06 18:14:35 +01:00
2009-12-16 18:13:23 +01:00
if ( IS_LATEX ( output_type ) )
{
if ( output_type = = oLatexDynamicSteadyStateOperator )
output < < " \\ bar{ " ;
output < < datatree . symbol_table . getTeXName ( symb_id ) ;
if ( output_type = = oLatexDynamicModel
2010-10-15 19:05:16 +02:00
& & ( type = = eEndogenous | | type = = eExogenous | | type = = eExogenousDet | | type = = eModelLocalVariable | | type = = eTrend ) )
2009-12-16 18:13:23 +01:00
{
output < < " _{t " ;
if ( lag ! = 0 )
{
if ( lag > 0 )
output < < " + " ;
output < < lag ;
}
2009-09-11 11:16:52 +02:00
output < < " } " ;
2009-12-16 18:13:23 +01:00
}
else if ( output_type = = oLatexDynamicSteadyStateOperator )
output < < " } " ;
return ;
}
2007-03-06 18:14:35 +01:00
2009-12-16 18:13:23 +01:00
int i ;
int tsid = datatree . symbol_table . getTypeSpecificID ( symb_id ) ;
switch ( type )
{
case eParameter :
2010-04-23 18:39:07 +02:00
if ( output_type = = oMatlabOutsideModel | | output_type = = oSteadyStateFile )
2009-12-16 18:13:23 +01:00
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 ;
2009-06-05 16:45:23 +02:00
2009-12-16 18:13:23 +01:00
case eModelLocalVariable :
2010-09-16 16:57:35 +02:00
if ( output_type = = oMatlabDynamicModelSparse | | output_type = = oMatlabStaticModelSparse )
2009-12-16 18:13:23 +01:00
{
output < < " ( " ;
2011-04-12 13:33:03 +02:00
datatree . local_variables_table [ symb_id ] - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2009-12-16 18:13:23 +01:00
output < < " ) " ;
}
else
2011-02-21 16:32:21 +01:00
/* We append underscores to avoid name clashes with "g1" or "oo_" (see
also ModelTree : : writeModelLocalVariables ) */
output < < datatree . symbol_table . getName ( symb_id ) < < " __ " ;
2009-12-16 18:13:23 +01:00
break ;
2009-06-05 16:45:23 +02:00
2010-04-23 18:39:07 +02:00
case eModFileLocalVariable :
output < < datatree . symbol_table . getName ( symb_id ) ;
break ;
2009-12-16 18:13:23 +01:00
case eEndogenous :
switch ( output_type )
{
case oMatlabDynamicModel :
case oCDynamicModel :
i = datatree . getDynJacobianCol ( datatree . getDerivID ( symb_id , lag ) ) + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
output < < " y " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
2011-08-18 12:44:11 +02:00
case oCStaticModel :
2009-12-16 18:13:23 +01:00
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 :
output < < " oo_.steady_state( " < < tsid + 1 < < " ) " ;
break ;
case oMatlabDynamicSteadyStateOperator :
2010-09-20 17:04:38 +02:00
case oMatlabDynamicSparseSteadyStateOperator :
2011-03-13 17:06:57 +01:00
output < < " steady_state( " < < tsid + 1 < < " ) " ;
2009-12-16 18:13:23 +01:00
break ;
2010-09-20 17:04:38 +02:00
case oCDynamicSteadyStateOperator :
output < < " steady_state[ " < < tsid < < " ] " ;
break ;
2010-04-23 18:39:07 +02:00
case oSteadyStateFile :
output < < " ys_( " < < tsid + 1 < < " ) " ;
break ;
2009-12-16 18:13:23 +01:00
default :
2011-01-13 15:52:44 +01:00
cerr < < " VariableNode::writeOutput: should not reach this point " < < endl ;
exit ( EXIT_FAILURE ) ;
2009-12-16 18:13:23 +01:00
}
break ;
2009-06-05 16:45:23 +02:00
2009-12-16 18:13:23 +01:00
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 ;
2011-08-18 12:44:11 +02:00
case oCStaticModel :
2009-12-16 18:13:23 +01:00
case oMatlabStaticModel :
case oMatlabStaticModelSparse :
output < < " x " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
case oMatlabOutsideModel :
assert ( lag = = 0 ) ;
output < < " oo_.exo_steady_state( " < < i < < " ) " ;
break ;
case oMatlabDynamicSteadyStateOperator :
output < < " oo_.exo_steady_state( " < < i < < " ) " ;
break ;
2010-04-23 18:39:07 +02:00
case oSteadyStateFile :
output < < " exo_( " < < i < < " ) " ;
break ;
2009-12-16 18:13:23 +01:00
default :
2011-01-13 15:52:44 +01:00
cerr < < " VariableNode::writeOutput: should not reach this point " < < endl ;
exit ( EXIT_FAILURE ) ;
2009-12-16 18:13:23 +01:00
}
break ;
2009-06-05 16:45:23 +02:00
2009-12-16 18:13:23 +01:00
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 )
2010-12-08 11:33:20 +01:00
output < < " x[it_+ " < < i < < " *nb_row_x] " ;
2009-12-16 18:13:23 +01:00
else if ( lag > 0 )
2010-12-08 11:33:20 +01:00
output < < " x[it_+ " < < lag < < " + " < < i < < " *nb_row_x] " ;
2009-12-16 18:13:23 +01:00
else
2010-12-08 11:33:20 +01:00
output < < " x[it_ " < < lag < < " + " < < i < < " *nb_row_x] " ;
2009-12-16 18:13:23 +01:00
break ;
2011-08-18 12:44:11 +02:00
case oCStaticModel :
2009-12-16 18:13:23 +01:00
case oMatlabStaticModel :
case oMatlabStaticModelSparse :
output < < " x " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
case oMatlabOutsideModel :
assert ( lag = = 0 ) ;
output < < " oo_.exo_det_steady_state( " < < tsid + 1 < < " ) " ;
break ;
case oMatlabDynamicSteadyStateOperator :
output < < " oo_.exo_det_steady_state( " < < tsid + 1 < < " ) " ;
break ;
2010-04-23 18:39:07 +02:00
case oSteadyStateFile :
output < < " exo_( " < < i < < " ) " ;
break ;
2009-12-16 18:13:23 +01:00
default :
2011-01-13 15:52:44 +01:00
cerr < < " VariableNode::writeOutput: should not reach this point " < < endl ;
exit ( EXIT_FAILURE ) ;
2009-12-16 18:13:23 +01:00
}
break ;
2009-06-05 16:45:23 +02:00
2010-02-22 17:33:38 +01:00
case eExternalFunction :
2010-10-15 19:05:16 +02:00
case eTrend :
2009-12-16 18:13:23 +01:00
cerr < < " Impossible case " < < endl ;
exit ( EXIT_FAILURE ) ;
}
}
2007-01-09 20:00:05 +01:00
2007-03-09 18:27:46 +01:00
double
2010-12-10 11:50:27 +01:00
VariableNode : : eval ( const eval_context_t & eval_context ) const throw ( EvalException , EvalExternalFunctionException )
2007-02-22 00:28:16 +01:00
{
2010-09-16 19:00:48 +02:00
eval_context_t : : const_iterator it = eval_context . find ( symb_id ) ;
2007-03-09 18:27:46 +01:00
if ( it = = eval_context . end ( ) )
2009-02-27 13:19:25 +01:00
throw EvalException ( ) ;
2007-06-06 12:17:27 +02:00
2007-03-09 18:27:46 +01:00
return it - > second ;
2007-02-22 00:28:16 +01:00
}
2007-10-04 00:01:08 +02:00
void
2010-12-10 11:50:27 +01:00
VariableNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
const map_idx_t & map_idx , bool dynamic , bool steady_dynamic ,
deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
if ( type = = eModelLocalVariable | | type = = eModFileLocalVariable )
2010-12-10 11:50:27 +01:00
datatree . local_variables_table [ symb_id ] - > compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic , tef_terms ) ;
2009-12-16 18:13:23 +01:00
else
{
int tsid = datatree . symbol_table . getTypeSpecificID ( symb_id ) ;
if ( type = = eExogenousDet )
tsid + = datatree . symbol_table . exo_nbr ( ) ;
if ( ! lhs_rhs )
{
if ( dynamic )
{
if ( steady_dynamic ) // steady state values in a dynamic model
{
FLDVS_ fldvs ( type , tsid ) ;
2010-07-23 11:20:24 +02:00
fldvs . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
else
{
if ( type = = eParameter )
{
FLDV_ fldv ( type , tsid ) ;
2010-07-23 11:20:24 +02:00
fldv . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
else
{
FLDV_ fldv ( type , tsid , lag ) ;
2010-07-23 11:20:24 +02:00
fldv . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
}
}
else
{
FLDSV_ fldsv ( type , tsid ) ;
2010-07-23 11:20:24 +02:00
fldsv . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
}
else
{
if ( dynamic )
{
if ( steady_dynamic ) // steady state values in a dynamic model
{
cerr < < " Impossible case: steady_state in rhs of equation " < < endl ;
exit ( EXIT_FAILURE ) ;
}
else
{
if ( type = = eParameter )
{
FSTPV_ fstpv ( type , tsid ) ;
2010-07-23 11:20:24 +02:00
fstpv . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
else
{
FSTPV_ fstpv ( type , tsid , lag ) ;
2010-07-23 11:20:24 +02:00
fstpv . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
}
}
else
{
FSTPSV_ fstpsv ( type , tsid ) ;
2010-07-23 11:20:24 +02:00
fstpsv . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
}
}
}
2007-10-04 00:01:08 +02:00
2009-01-02 14:00:43 +01:00
void
2010-09-16 19:18:45 +02:00
VariableNode : : computeTemporaryTerms ( map < expr_t , int > & reference_count ,
2010-09-16 19:00:48 +02:00
temporary_terms_t & temporary_terms ,
2010-09-16 19:18:45 +02:00
map < expr_t , pair < int , int > > & first_occurence ,
2009-01-23 11:59:37 +01:00
int Curr_block ,
2010-09-16 19:00:48 +02:00
vector < vector < temporary_terms_t > > & v_temporary_terms ,
2009-12-16 14:21:31 +01:00
int equation ) const
2009-12-16 18:13:23 +01:00
{
if ( type = = eModelLocalVariable )
datatree . local_variables_table [ symb_id ] - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , v_temporary_terms , equation ) ;
}
2009-01-02 14:00:43 +01:00
2007-02-22 00:28:16 +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
2010-09-16 19:18:45 +02:00
pair < int , expr_t >
VariableNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < expr_t , expr_t > > > & List_of_Op_RHS ) const
2009-12-16 18:13:23 +01:00
{
2011-06-10 11:59:34 +02:00
/* The equation has to be normalized with respect to the current endogenous variable ascribed to it.
The two input arguments are :
- The ID of the endogenous variable associated to the equation .
- The list of operators and operands needed to normalize the equation *
The pair returned by NormalizeEquation is composed of
- a flag indicating if the expression returned contains ( flag = 1 ) or not ( flag = 0 )
the endogenous variable related to the equation .
If the expression contains more than one occurence of the associated endogenous variable ,
the flag is equal to 2.
- an expression equal to the RHS if flag = 0 and equal to NULL elsewhere
*/
2009-12-16 18:13:23 +01:00
if ( type = = eEndogenous )
{
if ( datatree . symbol_table . getTypeSpecificID ( symb_id ) = = var_endo & & lag = = 0 )
2011-06-10 11:59:34 +02:00
/* the endogenous variable */
2010-09-16 19:18:45 +02:00
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
else
return ( make_pair ( 0 , datatree . AddVariableInternal ( symb_id , lag ) ) ) ;
}
else
{
if ( type = = eParameter )
return ( make_pair ( 0 , datatree . AddVariableInternal ( symb_id , 0 ) ) ) ;
else
return ( make_pair ( 0 , datatree . AddVariableInternal ( symb_id , lag ) ) ) ;
}
}
2009-06-05 16:45:23 +02:00
2010-09-16 19:18:45 +02:00
expr_t
VariableNode : : getChainRuleDerivative ( int deriv_id , const map < int , expr_t > & 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 :
2010-10-15 19:05:16 +02:00
case eTrend :
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
2010-09-16 19:18:45 +02:00
map < int , expr_t > : : 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
{
2010-09-16 19:18:45 +02:00
map < int , expr_t > : : const_iterator it2 = derivatives . find ( deriv_id ) ;
2009-08-25 11:43:01 +02:00
if ( it2 ! = derivatives . end ( ) )
return it2 - > second ;
else
{
2010-09-16 19:18:45 +02:00
map < int , expr_t > recursive_vars2 ( recursive_variables ) ;
2009-08-25 11:43:01 +02:00
recursive_vars2 . erase ( it - > first ) ;
2010-11-25 13:45:35 +01:00
//expr_t c = datatree.AddNonNegativeConstant("1");
2010-09-16 19:18:45 +02:00
expr_t 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 ) ;
2010-02-22 17:33:38 +01:00
case eExternalFunction :
2009-06-05 16:45:23 +02:00
cerr < < " Impossible case! " < < endl ;
exit ( EXIT_FAILURE ) ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
2009-04-14 16:39:53 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2009-06-05 16:45:23 +02:00
VariableNode : : toStatic ( DataTree & static_datatree ) const
2009-12-16 18:13:23 +01:00
{
2010-03-16 12:23:59 +01:00
return static_datatree . AddVariable ( symb_id ) ;
2009-12-16 18:13:23 +01:00
}
2009-06-05 16:45:23 +02:00
2010-10-15 19:05:16 +02:00
expr_t
VariableNode : : cloneDynamic ( DataTree & dynamic_datatree ) const
{
return dynamic_datatree . AddVariable ( symb_id , lag ) ;
}
2009-09-30 17:10:31 +02:00
int
VariableNode : : maxEndoLead ( ) const
{
2009-12-16 18:13:23 +01:00
switch ( type )
2009-09-30 17:10:31 +02:00
{
case eEndogenous :
return max ( lag , 0 ) ;
case eModelLocalVariable :
return datatree . local_variables_table [ symb_id ] - > maxEndoLead ( ) ;
default :
return 0 ;
}
}
2009-10-07 18:34:42 +02:00
int
VariableNode : : maxExoLead ( ) const
{
2009-12-16 18:13:23 +01:00
switch ( type )
2009-10-07 18:34:42 +02:00
{
case eExogenous :
return max ( lag , 0 ) ;
case eModelLocalVariable :
return datatree . local_variables_table [ symb_id ] - > maxExoLead ( ) ;
default :
return 0 ;
}
}
2010-08-19 15:20:54 +02:00
int
VariableNode : : maxEndoLag ( ) const
{
switch ( type )
{
case eEndogenous :
return max ( - lag , 0 ) ;
case eModelLocalVariable :
return datatree . local_variables_table [ symb_id ] - > maxEndoLag ( ) ;
default :
return 0 ;
}
}
int
VariableNode : : maxExoLag ( ) const
{
switch ( type )
{
case eExogenous :
return max ( - lag , 0 ) ;
case eModelLocalVariable :
return datatree . local_variables_table [ symb_id ] - > maxExoLag ( ) ;
default :
return 0 ;
}
}
2010-09-16 19:18:45 +02:00
expr_t
2009-09-30 17:10:31 +02:00
VariableNode : : decreaseLeadsLags ( int n ) const
{
2009-12-16 18:13:23 +01:00
switch ( type )
2009-09-30 17:10:31 +02:00
{
case eEndogenous :
case eExogenous :
case eExogenousDet :
2010-10-15 19:05:16 +02:00
case eTrend :
2009-09-30 17:10:31 +02:00
return datatree . AddVariable ( symb_id , lag - n ) ;
case eModelLocalVariable :
return datatree . local_variables_table [ symb_id ] - > decreaseLeadsLags ( n ) ;
default :
return const_cast < VariableNode * > ( this ) ;
}
}
2010-09-16 19:18:45 +02:00
expr_t
2009-11-09 12:03:18 +01:00
VariableNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
2009-11-07 19:37:11 +01:00
{
2009-11-09 12:03:18 +01:00
if ( datatree . symbol_table . isPredetermined ( symb_id ) )
2009-11-07 19:37:11 +01:00
return decreaseLeadsLags ( 1 ) ;
else
return const_cast < VariableNode * > ( this ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
VariableNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t value ;
2009-12-16 18:13:23 +01:00
switch ( type )
2009-09-30 17:10:31 +02:00
{
case eEndogenous :
if ( lag < = 1 )
return const_cast < VariableNode * > ( this ) ;
else
2009-10-07 16:07:13 +02:00
return createEndoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
case eModelLocalVariable :
value = datatree . local_variables_table [ symb_id ] ;
if ( value - > maxEndoLead ( ) < = 1 )
return const_cast < VariableNode * > ( this ) ;
else
2010-08-18 13:45:07 +02:00
return value - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) ;
2009-09-30 17:10:31 +02:00
default :
return const_cast < VariableNode * > ( this ) ;
}
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 16:07:13 +02:00
VariableNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
VariableNode * substexpr ;
2010-09-16 19:18:45 +02:00
expr_t value ;
2009-09-30 17:10:31 +02:00
subst_table_t : : const_iterator it ;
int cur_lag ;
2009-12-16 18:13:23 +01:00
switch ( type )
2009-09-30 17:10:31 +02:00
{
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))
2009-12-16 18:13:23 +01:00
while ( cur_lag > = lag )
2009-09-30 17:10:31 +02:00
{
VariableNode * orig_expr = datatree . AddVariable ( symb_id , cur_lag ) ;
it = subst_table . find ( orig_expr ) ;
if ( it = = subst_table . end ( ) )
{
2009-10-07 16:07:13 +02:00
int aux_symb_id = datatree . symbol_table . addEndoLagAuxiliaryVar ( symb_id , cur_lag + 1 ) ;
2009-09-30 17:10:31 +02:00
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 :
2010-08-19 15:20:54 +02:00
value = datatree . local_variables_table [ symb_id ] ;
if ( value - > maxEndoLag ( ) < = 1 )
return const_cast < VariableNode * > ( this ) ;
else
return value - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
2009-10-07 16:07:13 +02:00
default :
return const_cast < VariableNode * > ( this ) ;
}
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
VariableNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-10-07 18:34:42 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t value ;
2009-12-16 18:13:23 +01:00
switch ( type )
2009-10-07 18:34:42 +02:00
{
case eExogenous :
if ( lag < = 0 )
return const_cast < VariableNode * > ( this ) ;
else
return createExoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
case eModelLocalVariable :
value = datatree . local_variables_table [ symb_id ] ;
if ( value - > maxExoLead ( ) = = 0 )
return const_cast < VariableNode * > ( this ) ;
else
2010-08-18 13:45:07 +02:00
return value - > substituteExoLead ( subst_table , neweqs , deterministic_model ) ;
2009-10-07 18:34:42 +02:00
default :
return const_cast < VariableNode * > ( this ) ;
}
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 18:34:42 +02:00
VariableNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-10-07 16:07:13 +02:00
{
VariableNode * substexpr ;
2010-09-16 19:18:45 +02:00
expr_t value ;
2009-10-07 16:07:13 +02:00
subst_table_t : : const_iterator it ;
int cur_lag ;
2009-12-16 18:13:23 +01:00
switch ( type )
2009-10-07 16:07:13 +02:00
{
case eExogenous :
2009-10-07 18:34:42 +02:00
if ( lag > = 0 )
2009-10-07 16:07:13 +02:00
return const_cast < VariableNode * > ( this ) ;
it = subst_table . find ( this ) ;
if ( it ! = subst_table . end ( ) )
return const_cast < VariableNode * > ( it - > second ) ;
2009-10-07 18:34:42 +02:00
substexpr = datatree . AddVariable ( symb_id , 0 ) ;
cur_lag = - 1 ;
2009-10-07 16:07:13 +02:00
2009-10-07 18:34:42 +02:00
// 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))
2009-12-16 18:13:23 +01:00
while ( cur_lag > = lag )
2009-10-07 16:07:13 +02:00
{
2009-10-07 18:34:42 +02:00
VariableNode * orig_expr = datatree . AddVariable ( symb_id , cur_lag ) ;
it = subst_table . find ( orig_expr ) ;
if ( it = = subst_table . end ( ) )
2009-10-07 16:07:13 +02:00
{
2009-10-07 18:34:42 +02:00
int aux_symb_id = datatree . symbol_table . addExoLagAuxiliaryVar ( 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 ;
2009-10-07 16:07:13 +02:00
}
2009-10-07 18:34:42 +02:00
else
substexpr = const_cast < VariableNode * > ( it - > second ) ;
cur_lag - - ;
2009-10-07 16:07:13 +02:00
}
2009-10-07 18:34:42 +02:00
return substexpr ;
2009-10-07 16:07:13 +02:00
case eModelLocalVariable :
2010-08-19 15:20:54 +02:00
value = datatree . local_variables_table [ symb_id ] ;
if ( value - > maxExoLag ( ) = = 0 )
return const_cast < VariableNode * > ( this ) ;
else
return value - > substituteExoLag ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
default :
return const_cast < VariableNode * > ( this ) ;
}
}
2009-06-05 16:45:23 +02:00
2010-09-16 19:18:45 +02:00
expr_t
2009-10-29 18:16:10 +01:00
VariableNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
return const_cast < VariableNode * > ( this ) ;
}
2010-04-16 16:54:55 +02:00
bool
VariableNode : : isNumConstNodeEqualTo ( double value ) const
{
return false ;
}
bool
VariableNode : : isVariableNodeEqualTo ( SymbolType type_arg , int variable_id , int lag_arg ) const
{
if ( type = = type_arg & & datatree . symbol_table . getTypeSpecificID ( symb_id ) = = variable_id & & lag = = lag_arg )
return true ;
else
return false ;
}
2010-10-15 19:05:16 +02:00
expr_t
VariableNode : : replaceTrendVar ( ) const
{
if ( get_type ( ) = = eTrend )
return datatree . One ;
else
return const_cast < VariableNode * > ( this ) ;
}
expr_t
VariableNode : : detrend ( int symb_id , expr_t trend ) const
{
if ( get_symb_id ( ) ! = symb_id )
return const_cast < VariableNode * > ( this ) ;
if ( get_lag ( ) = = 0 )
return datatree . AddTimes ( const_cast < VariableNode * > ( this ) , trend ) ;
else
return datatree . AddTimes ( const_cast < VariableNode * > ( this ) , trend - > decreaseLeadsLags ( - 1 * get_lag ( ) ) ) ;
}
expr_t
VariableNode : : removeTrendLeadLag ( map < int , expr_t > trend_symbols_map ) const
{
if ( get_type ( ) ! = eTrend | | get_lag ( ) = = 0 )
return const_cast < VariableNode * > ( this ) ;
map < int , expr_t > : : const_iterator it = trend_symbols_map . find ( symb_id ) ;
expr_t noTrendLeadLagNode = new VariableNode ( datatree , it - > first , 0 ) ;
if ( get_lag ( ) > 0 )
{
expr_t growthFactorSequence = it - > second - > decreaseLeadsLags ( - 1 ) ;
2011-02-04 16:25:38 +01:00
for ( int i = 1 ; i < get_lag ( ) ; i + + )
2010-10-15 19:05:16 +02:00
growthFactorSequence = datatree . AddTimes ( growthFactorSequence , it - > second - > decreaseLeadsLags ( - 1 * ( i + 1 ) ) ) ;
return datatree . AddTimes ( noTrendLeadLagNode , growthFactorSequence ) ;
}
else //get_lag < 0
{
expr_t growthFactorSequence = it - > second ;
2011-02-04 16:25:38 +01:00
for ( int i = 1 ; i < abs ( get_lag ( ) ) ; i + + )
2010-10-15 19:05:16 +02:00
growthFactorSequence = datatree . AddTimes ( growthFactorSequence , it - > second - > decreaseLeadsLags ( i ) ) ;
return datatree . AddDivide ( noTrendLeadLagNode , growthFactorSequence ) ;
}
}
2011-01-13 18:08:26 +01:00
UnaryOpNode : : UnaryOpNode ( DataTree & datatree_arg , UnaryOpcode op_code_arg , const expr_t arg_arg , int expectation_information_set_arg , const string & expectation_information_set_name_arg , int param1_symb_id_arg , int param2_symb_id_arg ) :
2009-12-16 18:13:23 +01:00
ExprNode ( datatree_arg ) ,
arg ( arg_arg ) ,
expectation_information_set ( expectation_information_set_arg ) ,
2010-01-18 23:08:44 +01:00
expectation_information_set_name ( expectation_information_set_name_arg ) ,
2011-01-13 18:08:26 +01:00
param1_symb_id ( param1_symb_id_arg ) ,
param2_symb_id ( param2_symb_id_arg ) ,
2009-12-16 18:13:23 +01:00
op_code ( op_code_arg )
2007-01-09 20:00:05 +01:00
{
// Add myself to the unary op map
2010-12-08 12:16:12 +01:00
datatree . unary_op_node_map [ make_pair ( make_pair ( arg , op_code ) ,
2011-01-13 18:08:26 +01:00
make_pair ( make_pair ( expectation_information_set , expectation_information_set_name ) ,
make_pair ( param1_symb_id , param2_symb_id ) ) ) ] = this ;
2009-09-30 17:10:31 +02:00
}
void
UnaryOpNode : : prepareForDerivation ( )
{
if ( preparedForDerivation )
return ;
preparedForDerivation = true ;
arg - > prepareForDerivation ( ) ;
2007-01-09 20:00:05 +01:00
2011-01-13 18:08:26 +01:00
// Non-null derivatives are those of the argument (except for STEADY_STATE)
2007-01-09 20:00:05 +01:00
non_null_derivatives = arg - > non_null_derivatives ;
2011-01-13 18:08:26 +01:00
if ( op_code = = oSteadyState | | op_code = = oSteadyStateParamDeriv
| | op_code = = oSteadyStateParam2ndDeriv )
datatree . addAllParamDerivId ( non_null_derivatives ) ;
2007-01-09 20:00:05 +01:00
}
2010-09-16 19:18:45 +02:00
expr_t
2011-01-13 18:08:26 +01:00
UnaryOpNode : : composeDerivatives ( expr_t darg , int deriv_id )
2007-01-09 20:00:05 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t t11 , t12 , t13 ;
2007-01-09 20:00:05 +01:00
2009-06-05 16:45:23 +02:00
switch ( op_code )
2007-01-09 20:00:05 +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 ) ;
2007-01-09 20:00:05 +01:00
return datatree . AddTimes ( darg , t11 ) ;
case oSinh :
2009-04-16 12:33:30 +02:00
t11 = datatree . AddCosh ( arg ) ;
2007-01-09 20:00:05 +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 ) ;
2007-01-09 20:00:05 +01:00
return datatree . AddDivide ( darg , t11 ) ;
case oAsinh :
2009-04-16 12:33:30 +02:00
t11 = datatree . AddCosh ( this ) ;
2007-01-09 20:00:05 +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 ) ;
2011-08-12 13:20:53 +02:00
case oAbs :
t11 = datatree . AddSign ( arg ) ;
return datatree . AddTimes ( t11 , darg ) ;
case oSign :
return datatree . Zero ;
2009-09-10 22:09:16 +02:00
case oSteadyState :
2009-12-16 18:13:23 +01:00
if ( datatree . isDynamic ( ) )
2011-01-13 18:08:26 +01:00
{
if ( datatree . getTypeByDerivID ( deriv_id ) = = eParameter )
{
VariableNode * varg = dynamic_cast < VariableNode * > ( arg ) ;
if ( varg = = NULL )
{
2011-04-12 13:34:04 +02:00
cerr < < " UnaryOpNode::composeDerivatives: STEADY_STATE() should only be used on "
< < " standalone variables (like STEADY_STATE(y)) to be derivable w.r.t. parameters " < < endl ;
2011-01-13 18:08:26 +01:00
exit ( EXIT_FAILURE ) ;
}
if ( datatree . symbol_table . getType ( varg - > symb_id ) = = eEndogenous )
return datatree . AddSteadyStateParamDeriv ( arg , datatree . getSymbIDByDerivID ( deriv_id ) ) ;
else
return datatree . Zero ;
}
else
return datatree . Zero ;
}
2009-12-16 18:13:23 +01:00
else
return darg ;
2011-01-13 18:08:26 +01:00
case oSteadyStateParamDeriv :
assert ( datatree . isDynamic ( ) ) ;
if ( datatree . getTypeByDerivID ( deriv_id ) = = eParameter )
{
VariableNode * varg = dynamic_cast < VariableNode * > ( arg ) ;
assert ( varg ! = NULL ) ;
assert ( datatree . symbol_table . getType ( varg - > symb_id ) = = eEndogenous ) ;
return datatree . AddSteadyStateParam2ndDeriv ( arg , param1_symb_id , datatree . getSymbIDByDerivID ( deriv_id ) ) ;
}
else
return datatree . Zero ;
case oSteadyStateParam2ndDeriv :
assert ( datatree . isDynamic ( ) ) ;
if ( datatree . getTypeByDerivID ( deriv_id ) = = eParameter )
{
cerr < < " 3rd derivative of STEADY_STATE node w.r.t. three parameters not implemented " < < endl ;
exit ( EXIT_FAILURE ) ;
}
else
return datatree . Zero ;
2009-10-30 06:21:54 +01:00
case oExpectation :
2011-01-13 15:52:44 +01:00
cerr < < " UnaryOpNode::composeDerivatives: not implemented on oExpectation " < < endl ;
exit ( EXIT_FAILURE ) ;
2010-03-11 11:57:34 +01:00
case oErf :
// x^2
t11 = datatree . AddPower ( arg , datatree . Two ) ;
// exp(x^2)
t12 = datatree . AddExp ( t11 ) ;
// sqrt(pi)
t11 = datatree . AddSqrt ( datatree . Pi ) ;
// sqrt(pi)*exp(x^2)
t13 = datatree . AddTimes ( t11 , t12 ) ;
// 2/(sqrt(pi)*exp(x^2));
return datatree . AddDivide ( datatree . Two , t13 ) ;
2007-01-09 20:00:05 +01:00
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2007-01-09 20:00:05 +01:00
}
2010-09-16 19:18:45 +02:00
expr_t
2009-07-06 11:34:21 +02:00
UnaryOpNode : : computeDerivative ( int deriv_id )
{
2010-09-16 19:18:45 +02:00
expr_t darg = arg - > getDerivative ( deriv_id ) ;
2011-01-13 18:08:26 +01:00
return composeDerivatives ( darg , deriv_id ) ;
2009-07-06 11:34:21 +02:00
}
2007-01-09 20:00:05 +01:00
int
2010-09-16 19:00:48 +02:00
UnaryOpNode : : cost ( const temporary_terms_t & temporary_terms , bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
// For a temporary term, the cost is null
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < UnaryOpNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
if ( it ! = temporary_terms . end ( ) )
return 0 ;
2009-06-05 16:45:23 +02:00
2009-12-16 18:13:23 +01:00
int cost = arg - > cost ( temporary_terms , is_matlab ) ;
2007-01-09 20:00:05 +01:00
2009-12-16 18:13:23 +01:00
if ( is_matlab )
// Cost for Matlab files
switch ( op_code )
2009-06-05 16:45:23 +02:00
{
2009-12-16 18:13:23 +01:00
case oUminus :
2011-08-12 13:20:53 +02:00
case oSign :
2009-12-16 18:13:23 +01:00
return cost + 70 ;
case oExp :
return cost + 160 ;
case oLog :
return cost + 300 ;
case oLog10 :
2010-03-11 11:57:34 +01:00
case oErf :
2009-12-16 18:13:23 +01:00
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 :
2011-08-12 13:20:53 +02:00
case oAbs :
2009-12-16 18:13:23 +01:00
return cost + 570 ;
case oSteadyState :
2011-01-13 18:08:26 +01:00
case oSteadyStateParamDeriv :
case oSteadyStateParam2ndDeriv :
2009-12-16 18:13:23 +01:00
case oExpectation :
return cost ;
2009-06-05 16:45:23 +02:00
}
2009-12-16 18:13:23 +01:00
else
// Cost for C files
2009-06-05 16:45:23 +02:00
switch ( op_code )
2007-01-09 20:00:05 +01:00
{
case oUminus :
2011-08-12 13:20:53 +02:00
case oSign :
2009-12-16 18:13:23 +01:00
return cost + 3 ;
2007-01-09 20:00:05 +01:00
case oExp :
2009-12-16 18:13:23 +01:00
case oAcosh :
return cost + 210 ;
2007-01-09 20:00:05 +01:00
case oLog :
2009-12-16 18:13:23 +01:00
return cost + 137 ;
2007-01-09 20:00:05 +01:00
case oLog10 :
2009-12-16 18:13:23 +01:00
return cost + 139 ;
2007-01-09 20:00:05 +01:00
case oCos :
case oSin :
2009-12-16 18:13:23 +01:00
return cost + 160 ;
2007-01-09 20:00:05 +01:00
case oTan :
2009-12-16 18:13:23 +01:00
return cost + 170 ;
2007-01-09 20:00:05 +01:00
case oAcos :
2009-06-05 16:45:23 +02:00
case oAtan :
2009-12-16 18:13:23 +01:00
return cost + 190 ;
case oAsin :
return cost + 180 ;
2007-01-09 20:00:05 +01:00
case oCosh :
case oSinh :
case oTanh :
2010-03-11 11:57:34 +01:00
case oErf :
2009-12-16 18:13:23 +01:00
return cost + 240 ;
2007-01-09 20:00:05 +01:00
case oAsinh :
2009-12-16 18:13:23 +01:00
return cost + 220 ;
2007-01-09 20:00:05 +01:00
case oAtanh :
2009-12-16 18:13:23 +01:00
return cost + 150 ;
2007-01-09 20:00:05 +01:00
case oSqrt :
2011-08-12 13:20:53 +02:00
case oAbs :
2009-12-16 18:13:23 +01:00
return cost + 90 ;
2009-09-18 18:34:11 +02:00
case oSteadyState :
2011-01-13 18:08:26 +01:00
case oSteadyStateParamDeriv :
case oSteadyStateParam2ndDeriv :
2009-10-30 06:21:54 +01:00
case oExpectation :
2009-12-16 18:13:23 +01:00
return cost ;
2007-01-09 20:00:05 +01:00
}
2009-12-16 18:13:23 +01:00
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2007-01-09 20:00:05 +01:00
2009-12-16 18:13:23 +01:00
void
2010-09-16 19:18:45 +02:00
UnaryOpNode : : computeTemporaryTerms ( map < expr_t , int > & reference_count ,
2010-09-16 19:00:48 +02:00
temporary_terms_t & temporary_terms ,
2009-12-16 18:13:23 +01:00
bool is_matlab ) const
{
2010-09-16 19:18:45 +02:00
expr_t this2 = const_cast < UnaryOpNode * > ( this ) ;
2007-01-09 20:00:05 +01:00
2010-09-16 19:18:45 +02:00
map < expr_t , int > : : iterator it = reference_count . find ( this2 ) ;
2009-12-16 18:13:23 +01:00
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 ) ;
}
}
void
2010-09-16 19:18:45 +02:00
UnaryOpNode : : computeTemporaryTerms ( map < expr_t , int > & reference_count ,
2010-09-16 19:00:48 +02:00
temporary_terms_t & temporary_terms ,
2010-09-16 19:18:45 +02:00
map < expr_t , pair < int , int > > & first_occurence ,
2009-12-16 18:13:23 +01:00
int Curr_block ,
2010-09-16 19:00:48 +02:00
vector < vector < temporary_terms_t > > & v_temporary_terms ,
2009-12-16 18:13:23 +01:00
int equation ) const
{
2010-09-16 19:18:45 +02:00
expr_t this2 = const_cast < UnaryOpNode * > ( this ) ;
map < expr_t , int > : : iterator it = reference_count . find ( this2 ) ;
2009-12-16 18:13:23 +01:00
if ( it = = reference_count . end ( ) )
{
reference_count [ this2 ] = 1 ;
first_occurence [ this2 ] = make_pair ( Curr_block , equation ) ;
arg - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , v_temporary_terms , equation ) ;
}
else
{
reference_count [ this2 ] + + ;
if ( reference_count [ this2 ] * cost ( temporary_terms , false ) > MIN_COST_C )
{
temporary_terms . insert ( this2 ) ;
v_temporary_terms [ first_occurence [ this2 ] . first ] [ first_occurence [ this2 ] . second ] . insert ( this2 ) ;
}
}
}
void
2010-09-16 19:00:48 +02:00
UnaryOpNode : : collectTemporary_terms ( const temporary_terms_t & temporary_terms , temporary_terms_inuse_t & temporary_terms_inuse , int Curr_Block ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < UnaryOpNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
if ( it ! = temporary_terms . end ( ) )
temporary_terms_inuse . insert ( idx ) ;
else
arg - > collectTemporary_terms ( temporary_terms , temporary_terms_inuse , Curr_Block ) ;
}
void
UnaryOpNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
// If node is a temporary term
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < UnaryOpNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
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 )
{
case oUminus :
output < < " - " ;
break ;
case oExp :
output < < " exp " ;
break ;
case oLog :
output < < " log " ;
break ;
case oLog10 :
if ( IS_LATEX ( output_type ) )
output < < " log_{10} " ;
else
output < < " log10 " ;
break ;
case oCos :
output < < " cos " ;
break ;
case oSin :
output < < " sin " ;
break ;
case oTan :
output < < " tan " ;
break ;
case oAcos :
output < < " acos " ;
break ;
case oAsin :
output < < " asin " ;
break ;
case oAtan :
output < < " atan " ;
break ;
case oCosh :
output < < " cosh " ;
break ;
case oSinh :
output < < " sinh " ;
break ;
case oTanh :
output < < " tanh " ;
break ;
case oAcosh :
output < < " acosh " ;
break ;
case oAsinh :
output < < " asinh " ;
break ;
case oAtanh :
output < < " atanh " ;
break ;
case oSqrt :
output < < " sqrt " ;
break ;
2011-08-12 13:20:53 +02:00
case oAbs :
output < < " abs " ;
break ;
case oSign :
if ( output_type = = oCDynamicModel )
output < < " copysign " ;
else
output < < " sign " ;
break ;
2009-12-16 18:13:23 +01:00
case oSteadyState :
ExprNodeOutputType new_output_type ;
switch ( output_type )
{
case oMatlabDynamicModel :
new_output_type = oMatlabDynamicSteadyStateOperator ;
break ;
case oLatexDynamicModel :
new_output_type = oLatexDynamicSteadyStateOperator ;
break ;
case oCDynamicModel :
2010-09-20 17:04:38 +02:00
new_output_type = oCDynamicSteadyStateOperator ;
break ;
2009-12-16 18:13:23 +01:00
case oMatlabDynamicModelSparse :
2010-09-20 17:04:38 +02:00
new_output_type = oMatlabDynamicSparseSteadyStateOperator ;
break ;
2009-12-16 18:13:23 +01:00
default :
new_output_type = output_type ;
break ;
}
2011-08-08 18:48:03 +02:00
output < < " ( " ;
2011-04-12 13:33:03 +02:00
arg - > writeOutput ( output , new_output_type , temporary_terms , tef_terms ) ;
2011-08-08 18:48:03 +02:00
output < < " ) " ;
2009-12-16 18:13:23 +01:00
return ;
2011-01-13 18:08:26 +01:00
case oSteadyStateParamDeriv :
{
VariableNode * varg = dynamic_cast < VariableNode * > ( arg ) ;
assert ( varg ! = NULL ) ;
assert ( datatree . symbol_table . getType ( varg - > symb_id ) = = eEndogenous ) ;
assert ( datatree . symbol_table . getType ( param1_symb_id ) = = eParameter ) ;
int tsid_endo = datatree . symbol_table . getTypeSpecificID ( varg - > symb_id ) ;
int tsid_param = datatree . symbol_table . getTypeSpecificID ( param1_symb_id ) ;
assert ( IS_MATLAB ( output_type ) ) ;
output < < " ss_param_deriv( " < < tsid_endo + 1 < < " , " < < tsid_param + 1 < < " ) " ;
}
return ;
case oSteadyStateParam2ndDeriv :
{
VariableNode * varg = dynamic_cast < VariableNode * > ( arg ) ;
assert ( varg ! = NULL ) ;
assert ( datatree . symbol_table . getType ( varg - > symb_id ) = = eEndogenous ) ;
assert ( datatree . symbol_table . getType ( param1_symb_id ) = = eParameter ) ;
assert ( datatree . symbol_table . getType ( param2_symb_id ) = = eParameter ) ;
int tsid_endo = datatree . symbol_table . getTypeSpecificID ( varg - > symb_id ) ;
int tsid_param1 = datatree . symbol_table . getTypeSpecificID ( param1_symb_id ) ;
int tsid_param2 = datatree . symbol_table . getTypeSpecificID ( param2_symb_id ) ;
assert ( IS_MATLAB ( output_type ) ) ;
output < < " ss_param_2nd_deriv( " < < tsid_endo + 1 < < " , " < < tsid_param1 + 1
< < " , " < < tsid_param2 + 1 < < " ) " ;
}
return ;
2009-12-16 18:13:23 +01:00
case oExpectation :
2011-01-13 15:52:44 +01:00
cerr < < " UnaryOpNode::writeOutput: not implemented on oExpectation " < < endl ;
exit ( EXIT_FAILURE ) ;
2010-03-11 11:57:34 +01:00
case oErf :
output < < " erf " ;
break ;
2009-12-16 18:13:23 +01:00
}
bool close_parenthesis = false ;
2007-01-09 20:00:05 +01:00
2009-12-16 18:13:23 +01:00
/* Enclose argument with parentheses if:
- current opcode is not uminus , or
- current opcode is uminus and argument has lowest precedence
*/
if ( op_code ! = oUminus
| | ( op_code = = oUminus
& & arg - > precedence ( output_type , temporary_terms ) < precedence ( output_type , temporary_terms ) ) )
{
output < < LEFT_PAR ( output_type ) ;
2011-08-12 13:20:53 +02:00
if ( op_code = = oSign & & output_type = = oCDynamicModel )
output < < " 1.0, " ;
2009-12-16 18:13:23 +01:00
close_parenthesis = true ;
}
// Write argument
2011-04-12 13:33:03 +02:00
arg - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2007-01-09 20:00:05 +01:00
2009-12-16 18:13:23 +01:00
if ( close_parenthesis )
output < < RIGHT_PAR ( output_type ) ;
2007-01-09 20:00:05 +01:00
2009-12-16 18:13:23 +01:00
// Close parenthesis for uminus
if ( op_code = = oUminus )
output < < RIGHT_PAR ( output_type ) ;
}
2007-01-09 20:00:05 +01:00
2010-03-04 16:40:07 +01:00
void
UnaryOpNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
deriv_node_temp_terms_t & tef_terms ) const
2010-03-04 16:40:07 +01:00
{
arg - > writeExternalFunctionOutput ( output , output_type , temporary_terms , tef_terms ) ;
}
2010-12-10 11:50:27 +01:00
void
UnaryOpNode : : compileExternalFunctionOutput ( ostream & CompileCode , unsigned int & instruction_number ,
2011-02-04 16:25:38 +01:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
const map_idx_t & map_idx , bool dynamic , bool steady_dynamic ,
deriv_node_temp_terms_t & tef_terms ) const
2010-12-10 11:50:27 +01:00
{
arg - > compileExternalFunctionOutput ( CompileCode , instruction_number , lhs_rhs , temporary_terms , map_idx ,
dynamic , steady_dynamic , tef_terms ) ;
}
2007-03-09 18:27:46 +01:00
double
2010-12-10 11:50:27 +01:00
UnaryOpNode : : eval_opcode ( UnaryOpcode op_code , double v ) throw ( EvalException , EvalExternalFunctionException )
2007-02-22 00:28:16 +01:00
{
2009-06-05 16:45:23 +02:00
switch ( op_code )
2007-02-22 00:28:16 +01:00
{
case oUminus :
2009-12-16 18:13:23 +01:00
return ( - v ) ;
2007-02-22 00:28:16 +01:00
case oExp :
2009-12-16 18:13:23 +01:00
return ( exp ( v ) ) ;
2007-02-22 00:28:16 +01:00
case oLog :
2009-12-16 18:13:23 +01:00
return ( log ( v ) ) ;
2007-02-22 00:28:16 +01:00
case oLog10 :
2009-12-16 18:13:23 +01:00
return ( log10 ( v ) ) ;
2007-02-22 00:28:16 +01:00
case oCos :
2009-12-16 18:13:23 +01:00
return ( cos ( v ) ) ;
2007-02-22 00:28:16 +01:00
case oSin :
2009-12-16 18:13:23 +01:00
return ( sin ( v ) ) ;
2007-02-22 00:28:16 +01:00
case oTan :
2009-12-16 18:13:23 +01:00
return ( tan ( v ) ) ;
2007-02-22 00:28:16 +01:00
case oAcos :
2009-12-16 18:13:23 +01:00
return ( acos ( v ) ) ;
2007-02-22 00:28:16 +01:00
case oAsin :
2009-12-16 18:13:23 +01:00
return ( asin ( v ) ) ;
2007-02-22 00:28:16 +01:00
case oAtan :
2009-12-16 18:13:23 +01:00
return ( atan ( v ) ) ;
2007-02-22 00:28:16 +01:00
case oCosh :
2009-12-16 18:13:23 +01:00
return ( cosh ( v ) ) ;
2007-02-22 00:28:16 +01:00
case oSinh :
2009-12-16 18:13:23 +01:00
return ( sinh ( v ) ) ;
2007-02-22 00:28:16 +01:00
case oTanh :
2009-12-16 18:13:23 +01:00
return ( tanh ( v ) ) ;
2007-02-22 00:28:16 +01:00
case oAcosh :
2009-12-16 18:13:23 +01:00
return ( acosh ( v ) ) ;
2007-02-22 00:28:16 +01:00
case oAsinh :
2009-12-16 18:13:23 +01:00
return ( asinh ( v ) ) ;
2007-02-22 00:28:16 +01:00
case oAtanh :
2009-12-16 18:13:23 +01:00
return ( atanh ( v ) ) ;
2007-02-22 00:28:16 +01:00
case oSqrt :
2009-12-16 18:13:23 +01:00
return ( sqrt ( v ) ) ;
2011-08-12 13:20:53 +02:00
case oAbs :
return ( abs ( v ) ) ;
case oSign :
return ( v > 0 ) ? 1 : ( ( v < 0 ) ? - 1 : 0 ) ;
2009-10-30 06:21:54 +01:00
case oSteadyState :
2009-12-16 18:13:23 +01:00
return ( v ) ;
2011-01-13 18:08:26 +01:00
case oSteadyStateParamDeriv :
case oSteadyStateParam2ndDeriv :
2009-10-30 06:21:54 +01:00
case oExpectation :
throw EvalException ( ) ;
2010-03-11 11:57:34 +01:00
case oErf :
return ( erf ( v ) ) ;
2007-02-22 00:28:16 +01:00
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
2007-02-22 00:28:16 +01:00
}
2007-05-08 21:16:35 +02:00
double
2010-12-10 11:50:27 +01:00
UnaryOpNode : : eval ( const eval_context_t & eval_context ) const throw ( EvalException , EvalExternalFunctionException )
2007-05-08 21:16:35 +02:00
{
double v = arg - > eval ( eval_context ) ;
return eval_opcode ( op_code , v ) ;
}
2007-10-04 00:01:08 +02:00
void
2010-12-10 11:50:27 +01:00
UnaryOpNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
2011-02-04 16:25:38 +01:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
const map_idx_t & map_idx , bool dynamic , bool steady_dynamic ,
deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < UnaryOpNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
if ( it ! = temporary_terms . end ( ) )
{
if ( dynamic )
{
2010-09-16 19:00:48 +02:00
map_idx_t : : const_iterator ii = map_idx . find ( idx ) ;
2010-01-22 17:42:08 +01:00
FLDT_ fldt ( ii - > second ) ;
2010-07-23 11:20:24 +02:00
fldt . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
else
{
2010-09-16 19:00:48 +02:00
map_idx_t : : const_iterator ii = map_idx . find ( idx ) ;
2010-01-22 17:42:08 +01:00
FLDST_ fldst ( ii - > second ) ;
2010-07-23 11:20:24 +02:00
fldst . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
return ;
}
if ( op_code = = oSteadyState )
2010-12-10 11:50:27 +01:00
arg - > compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , map_idx , dynamic , true , tef_terms ) ;
2009-12-16 18:13:23 +01:00
else
{
2010-12-10 11:50:27 +01:00
arg - > compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic , tef_terms ) ;
2009-12-16 18:13:23 +01:00
FUNARY_ funary ( op_code ) ;
2010-07-23 11:20:24 +02:00
funary . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
}
2007-10-04 00:01:08 +02:00
2007-02-22 00:28:16 +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
2010-09-16 19:18:45 +02:00
pair < int , expr_t >
UnaryOpNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < expr_t , expr_t > > > & List_of_Op_RHS ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:18:45 +02:00
pair < bool , expr_t > res = arg - > normalizeEquation ( var_endo , List_of_Op_RHS ) ;
2009-12-16 18:13:23 +01:00
int is_endogenous_present = res . first ;
2010-09-16 19:18:45 +02:00
expr_t New_expr_t = res . second ;
2011-06-10 11:59:34 +02:00
if ( is_endogenous_present = = 2 ) /* The equation could not be normalized and the process is given-up*/
2010-09-16 19:18:45 +02:00
return ( make_pair ( 2 , ( expr_t ) NULL ) ) ;
2011-06-10 11:59:34 +02:00
else if ( is_endogenous_present ) /* The argument of the function contains the current values of
the endogenous variable associated to the equation .
In order to normalized , we have to apply the invert function to the RHS . */
2009-12-16 18:13:23 +01:00
{
switch ( op_code )
{
case oUminus :
2010-09-16 19:18:45 +02:00
List_of_Op_RHS . push_back ( make_pair ( oUminus , make_pair ( ( expr_t ) NULL , ( expr_t ) NULL ) ) ) ;
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
case oExp :
2010-09-16 19:18:45 +02:00
List_of_Op_RHS . push_back ( make_pair ( oLog , make_pair ( ( expr_t ) NULL , ( expr_t ) NULL ) ) ) ;
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
case oLog :
2010-09-16 19:18:45 +02:00
List_of_Op_RHS . push_back ( make_pair ( oExp , make_pair ( ( expr_t ) NULL , ( expr_t ) NULL ) ) ) ;
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
case oLog10 :
2010-11-25 13:45:35 +01:00
List_of_Op_RHS . push_back ( make_pair ( oPower , make_pair ( ( expr_t ) NULL , datatree . AddNonNegativeConstant ( " 10 " ) ) ) ) ;
2010-09-16 19:18:45 +02:00
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
case oSqrt :
2010-09-16 19:18:45 +02:00
List_of_Op_RHS . push_back ( make_pair ( oPower , make_pair ( ( expr_t ) NULL , datatree . Two ) ) ) ;
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
case oSteadyState :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2010-03-11 11:57:34 +01:00
case oErf :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2011-06-10 11:59:34 +02:00
default :
cerr < < " Unary operator not handled during the normalization process " < < endl ;
return ( make_pair ( 2 , ( expr_t ) NULL ) ) ; // Could not be normalized
2009-12-16 18:13:23 +01:00
}
}
else
2011-06-10 11:59:34 +02:00
{ /* If the argument of the function do not contain the current values of the endogenous variable
related to the equation , the function with its argument is stored in the RHS */
2009-12-16 18:13:23 +01:00
switch ( op_code )
{
case oUminus :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddUMinus ( New_expr_t ) ) ) ;
2009-12-16 18:13:23 +01:00
case oExp :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddExp ( New_expr_t ) ) ) ;
2009-12-16 18:13:23 +01:00
case oLog :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddLog ( New_expr_t ) ) ) ;
2009-12-16 18:13:23 +01:00
case oLog10 :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddLog10 ( New_expr_t ) ) ) ;
2009-12-16 18:13:23 +01:00
case oCos :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddCos ( New_expr_t ) ) ) ;
2009-12-16 18:13:23 +01:00
case oSin :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddSin ( New_expr_t ) ) ) ;
2009-12-16 18:13:23 +01:00
case oTan :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddTan ( New_expr_t ) ) ) ;
2009-12-16 18:13:23 +01:00
case oAcos :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddAcos ( New_expr_t ) ) ) ;
2009-12-16 18:13:23 +01:00
case oAsin :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddAsin ( New_expr_t ) ) ) ;
2009-12-16 18:13:23 +01:00
case oAtan :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddAtan ( New_expr_t ) ) ) ;
2009-12-16 18:13:23 +01:00
case oCosh :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddCosh ( New_expr_t ) ) ) ;
2009-12-16 18:13:23 +01:00
case oSinh :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddSinh ( New_expr_t ) ) ) ;
2009-12-16 18:13:23 +01:00
case oTanh :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddTanh ( New_expr_t ) ) ) ;
2009-12-16 18:13:23 +01:00
case oAcosh :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddAcosh ( New_expr_t ) ) ) ;
2009-12-16 18:13:23 +01:00
case oAsinh :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddAsinh ( New_expr_t ) ) ) ;
2009-12-16 18:13:23 +01:00
case oAtanh :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddAtanh ( New_expr_t ) ) ) ;
2009-12-16 18:13:23 +01:00
case oSqrt :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddSqrt ( New_expr_t ) ) ) ;
2011-08-12 13:20:53 +02:00
case oAbs :
return ( make_pair ( 0 , datatree . AddAbs ( New_expr_t ) ) ) ;
case oSign :
return ( make_pair ( 0 , datatree . AddSign ( New_expr_t ) ) ) ;
2009-12-16 18:13:23 +01:00
case oSteadyState :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddSteadyState ( New_expr_t ) ) ) ;
2010-03-11 11:57:34 +01:00
case oErf :
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddErf ( New_expr_t ) ) ) ;
2011-06-10 11:59:34 +02:00
default :
cerr < < " Unary operator not handled during the normalization process " < < endl ;
return ( make_pair ( 2 , ( expr_t ) NULL ) ) ; // Could not be normalized
2009-12-16 18:13:23 +01:00
}
}
2011-06-10 11:59:34 +02:00
cerr < < " UnaryOpNode::normalizeEquation: impossible case " < < endl ;
exit ( EXIT_FAILURE ) ;
2009-12-16 18:13:23 +01:00
}
2008-11-14 17:07:47 +01:00
2010-09-16 19:18:45 +02:00
expr_t
UnaryOpNode : : getChainRuleDerivative ( int deriv_id , const map < int , expr_t > & recursive_variables )
2009-04-14 16:39:53 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t darg = arg - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
2011-01-13 18:08:26 +01:00
return composeDerivatives ( darg , deriv_id ) ;
2009-04-14 16:39:53 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
UnaryOpNode : : buildSimilarUnaryOpNode ( expr_t alt_arg , DataTree & alt_datatree ) const
2009-09-30 17:10:31 +02:00
{
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 ) ;
2011-08-12 13:20:53 +02:00
case oAbs :
return alt_datatree . AddAbs ( alt_arg ) ;
case oSign :
return alt_datatree . AddSign ( alt_arg ) ;
2009-09-30 17:10:31 +02:00
case oSteadyState :
return alt_datatree . AddSteadyState ( alt_arg ) ;
2011-01-13 18:08:26 +01:00
case oSteadyStateParamDeriv :
cerr < < " UnaryOpNode::buildSimilarUnaryOpNode: oSteadyStateParamDeriv can't be translated " < < endl ;
exit ( EXIT_FAILURE ) ;
case oSteadyStateParam2ndDeriv :
cerr < < " UnaryOpNode::buildSimilarUnaryOpNode: oSteadyStateParam2ndDeriv can't be translated " < < endl ;
exit ( EXIT_FAILURE ) ;
2009-10-30 06:21:54 +01:00
case oExpectation :
2009-11-06 19:19:52 +01:00
return alt_datatree . AddExpectation ( expectation_information_set , alt_arg ) ;
2010-03-11 11:57:34 +01:00
case oErf :
return alt_datatree . AddErf ( alt_arg ) ;
2009-09-30 17:10:31 +02:00
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-06-05 16:45:23 +02:00
UnaryOpNode : : toStatic ( DataTree & static_datatree ) const
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t sarg = arg - > toStatic ( static_datatree ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarUnaryOpNode ( sarg , static_datatree ) ;
}
2010-10-15 19:05:16 +02:00
expr_t
UnaryOpNode : : cloneDynamic ( DataTree & dynamic_datatree ) const
{
expr_t substarg = arg - > cloneDynamic ( dynamic_datatree ) ;
return buildSimilarUnaryOpNode ( substarg , dynamic_datatree ) ;
}
2009-09-30 17:10:31 +02:00
int
UnaryOpNode : : maxEndoLead ( ) const
{
return arg - > maxEndoLead ( ) ;
}
2009-10-07 18:34:42 +02:00
int
UnaryOpNode : : maxExoLead ( ) const
{
return arg - > maxExoLead ( ) ;
}
2010-08-19 15:20:54 +02:00
int
UnaryOpNode : : maxEndoLag ( ) const
{
return arg - > maxEndoLag ( ) ;
}
int
UnaryOpNode : : maxExoLag ( ) const
{
return arg - > maxExoLag ( ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-09-30 17:10:31 +02:00
UnaryOpNode : : decreaseLeadsLags ( int n ) const
{
2010-09-16 19:18:45 +02:00
expr_t argsubst = arg - > decreaseLeadsLags ( n ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-11-09 12:03:18 +01:00
UnaryOpNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
2009-11-07 19:37:11 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t argsubst = arg - > decreaseLeadsLagsPredeterminedVariables ( ) ;
2009-11-07 19:37:11 +01:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
UnaryOpNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-09-30 17:10:31 +02:00
{
2010-08-18 13:45:07 +02:00
if ( op_code = = oUminus | | deterministic_model )
2009-09-30 17:10:31 +02:00
{
2010-08-18 13:45:07 +02:00
expr_t argsubst = arg - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
else
{
if ( maxEndoLead ( ) > = 2 )
2009-10-07 16:07:13 +02:00
return createEndoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
else
return const_cast < UnaryOpNode * > ( this ) ;
}
}
2009-06-05 16:45:23 +02:00
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 16:07:13 +02:00
UnaryOpNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
2010-09-16 19:18:45 +02:00
expr_t argsubst = arg - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
2009-10-07 16:07:13 +02:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
UnaryOpNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-09-30 17:10:31 +02:00
{
2010-08-18 13:45:07 +02:00
if ( op_code = = oUminus | | deterministic_model )
2009-10-07 18:34:42 +02:00
{
2010-08-18 13:45:07 +02:00
expr_t argsubst = arg - > substituteExoLead ( subst_table , neweqs , deterministic_model ) ;
2009-10-07 18:34:42 +02:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
else
{
if ( maxExoLead ( ) > = 1 )
return createExoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
else
return const_cast < UnaryOpNode * > ( this ) ;
}
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 18:34:42 +02:00
UnaryOpNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
2010-09-16 19:18:45 +02:00
expr_t argsubst = arg - > substituteExoLag ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
2009-06-05 16:45:23 +02:00
2010-09-16 19:18:45 +02:00
expr_t
2009-10-29 18:16:10 +01:00
UnaryOpNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
2009-12-16 18:13:23 +01:00
switch ( op_code )
2009-10-30 06:21:54 +01:00
{
case oExpectation :
{
subst_table_t : : iterator it = subst_table . find ( const_cast < UnaryOpNode * > ( this ) ) ;
if ( it ! = subst_table . end ( ) )
return const_cast < VariableNode * > ( it - > second ) ;
//Arriving here, we need to create an auxiliary variable for this Expectation Operator:
2010-01-18 23:08:44 +01:00
//AUX_EXPECT_(LEAD/LAG)_(period)_(arg.idx) OR
//AUX_EXPECT_(info_set_name)_(arg.idx)
int symb_id = datatree . symbol_table . addExpectationAuxiliaryVar ( expectation_information_set , arg - > idx , expectation_information_set_name ) ;
2010-09-16 19:18:45 +02:00
expr_t newAuxE = datatree . AddVariable ( symb_id , 0 ) ;
2009-10-30 06:21:54 +01:00
2009-12-16 18:13:23 +01:00
if ( partial_information_model & & expectation_information_set = = 0 )
2009-10-30 06:21:54 +01:00
{
if ( dynamic_cast < VariableNode * > ( arg ) = = NULL )
{
2010-01-18 23:08:44 +01:00
cerr < < " ERROR: In Partial Information models, EXPECTATION( " ;
if ( expectation_information_set_name . empty ( ) )
cerr < < 0 ;
else
cerr < < expectation_information_set_name ;
cerr < < " )(X) can only be used when X is a single variable. " < < endl ;
2009-10-30 06:21:54 +01:00
exit ( EXIT_FAILURE ) ;
}
}
2010-01-18 23:08:44 +01:00
if ( ! expectation_information_set_name . empty ( ) )
{
if ( ! partial_information_model )
{
cerr < < " ERROR: EXPECTATION( " < < expectation_information_set_name < < " )(X) is only valid in models with partial information. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
if ( expectation_information_set ! = 0 )
{
cerr < < " ERROR: UnaryOpNode::substituteExpectation() should not arrive here. Please inform Dynare Team. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2011-02-04 16:25:38 +01:00
else if ( dynamic_cast < VariableNode * > ( arg ) - > get_lag ( ) ! = 0 )
2010-01-18 23:08:44 +01:00
{
cerr < < " ERROR: EXPECTATION( " < < expectation_information_set_name < < " )(X) requres that X be from the current period. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
//Will not have nested Expectation operators of this type since we require that X be a single endogenous variable.
//Hence, the newAuxE with lag = 0 is all we need here.
}
2009-10-30 06:21:54 +01:00
else
{
2009-11-09 16:13:47 +01:00
//take care of any nested expectation operators by calling arg->substituteExpectation(.), then decreaseLeadsLags for this oExpectation operator
2009-10-30 06:21:54 +01:00
//arg(lag-period) (holds entire subtree of arg(lag-period)
2010-09-16 19:18:45 +02:00
expr_t substexpr = ( arg - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ) - > decreaseLeadsLags ( expectation_information_set ) ;
2009-10-30 06:21:54 +01:00
assert ( substexpr ! = NULL ) ;
neweqs . push_back ( dynamic_cast < BinaryOpNode * > ( datatree . AddEqual ( newAuxE , substexpr ) ) ) ; //AUXE_period_arg.idx = arg(lag-period)
2009-11-09 16:13:47 +01:00
newAuxE = datatree . AddVariable ( symb_id , expectation_information_set ) ;
2009-10-30 06:21:54 +01:00
}
2009-11-09 16:13:47 +01:00
assert ( dynamic_cast < VariableNode * > ( newAuxE ) ! = NULL ) ;
2009-10-30 06:21:54 +01:00
subst_table [ this ] = dynamic_cast < VariableNode * > ( newAuxE ) ;
return newAuxE ;
}
default :
2010-09-16 19:18:45 +02:00
expr_t argsubst = arg - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
2009-12-16 18:13:23 +01:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
2009-10-30 06:21:54 +01:00
}
2009-10-29 18:16:10 +01:00
}
2010-04-16 16:54:55 +02:00
bool
UnaryOpNode : : isNumConstNodeEqualTo ( double value ) const
{
return false ;
}
bool
UnaryOpNode : : isVariableNodeEqualTo ( SymbolType type_arg , int variable_id , int lag_arg ) const
{
return false ;
}
2010-10-15 19:05:16 +02:00
expr_t
UnaryOpNode : : replaceTrendVar ( ) const
{
expr_t argsubst = arg - > replaceTrendVar ( ) ;
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
expr_t
UnaryOpNode : : detrend ( int symb_id , expr_t trend ) const
{
expr_t argsubst = arg - > detrend ( symb_id , trend ) ;
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
expr_t
UnaryOpNode : : removeTrendLeadLag ( map < int , expr_t > trend_symbols_map ) const
{
expr_t argsubst = arg - > removeTrendLeadLag ( trend_symbols_map ) ;
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
BinaryOpNode : : BinaryOpNode ( DataTree & datatree_arg , const expr_t arg1_arg ,
BinaryOpcode op_code_arg , const expr_t arg2_arg ) :
2009-12-16 18:13:23 +01:00
ExprNode ( datatree_arg ) ,
arg1 ( arg1_arg ) ,
arg2 ( arg2_arg ) ,
2010-12-13 14:07:05 +01:00
op_code ( op_code_arg ) ,
powerDerivOrder ( 0 )
{
datatree . binary_op_node_map [ make_pair ( make_pair ( make_pair ( arg1 , arg2 ) , powerDerivOrder ) , op_code ) ] = this ;
}
BinaryOpNode : : BinaryOpNode ( DataTree & datatree_arg , const expr_t arg1_arg ,
BinaryOpcode op_code_arg , const expr_t arg2_arg , int powerDerivOrder_arg ) :
ExprNode ( datatree_arg ) ,
arg1 ( arg1_arg ) ,
arg2 ( arg2_arg ) ,
op_code ( op_code_arg ) ,
powerDerivOrder ( powerDerivOrder_arg )
2007-01-09 20:00:05 +01:00
{
2010-12-13 14:07:05 +01:00
assert ( powerDerivOrder > = 0 ) ;
datatree . binary_op_node_map [ make_pair ( make_pair ( make_pair ( arg1 , arg2 ) , powerDerivOrder ) , op_code ) ] = this ;
2009-09-30 17:10:31 +02:00
}
void
BinaryOpNode : : prepareForDerivation ( )
{
if ( preparedForDerivation )
return ;
preparedForDerivation = true ;
arg1 - > prepareForDerivation ( ) ;
arg2 - > prepareForDerivation ( ) ;
2007-01-09 20:00:05 +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 ( ) ) ) ;
}
2011-03-21 18:40:57 +01:00
expr_t
BinaryOpNode : : getNonZeroPartofEquation ( ) const
{
assert ( arg1 = = datatree . Zero | | arg2 = = datatree . Zero ) ;
if ( arg1 = = datatree . Zero )
return arg2 ;
return arg1 ;
}
2010-09-16 19:18:45 +02:00
expr_t
BinaryOpNode : : composeDerivatives ( expr_t darg1 , expr_t darg2 )
2007-01-09 20:00:05 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t t11 , t12 , t13 , t14 , t15 ;
2007-01-09 20:00:05 +01:00
2009-06-05 16:45:23 +02:00
switch ( op_code )
2007-01-09 20:00:05 +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-12-16 18:13:23 +01:00
if ( darg2 ! = datatree . Zero )
2009-06-05 16:45:23 +02:00
{
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 ) ;
2007-10-09 00:52:57 +02:00
case oLess :
case oGreater :
case oLessEqual :
case oGreaterEqual :
case oEqualEqual :
case oDifferent :
return datatree . Zero ;
2007-01-09 20:00:05 +01:00
case oPower :
if ( darg2 = = datatree . Zero )
2011-02-04 16:25:38 +01:00
if ( darg1 = = datatree . Zero )
2010-12-13 14:07:05 +01:00
return datatree . Zero ;
else
if ( dynamic_cast < NumConstNode * > ( arg2 ) ! = NULL )
2007-01-09 20:00:05 +01:00
{
t11 = datatree . AddMinus ( arg2 , datatree . One ) ;
t12 = datatree . AddPower ( arg1 , t11 ) ;
t13 = datatree . AddTimes ( arg2 , t12 ) ;
return datatree . AddTimes ( darg1 , t13 ) ;
}
2010-12-13 14:07:05 +01:00
else
return datatree . AddTimes ( darg1 , datatree . AddPowerDeriv ( arg1 , arg2 , powerDerivOrder + 1 ) ) ;
2007-01-09 20:00:05 +01:00
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 ) ;
}
2010-12-13 14:07:05 +01:00
case oPowerDeriv :
if ( darg2 = = datatree . Zero )
return datatree . AddTimes ( darg1 , datatree . AddPowerDeriv ( arg1 , arg2 , powerDerivOrder + 1 ) ) ;
else
{
t11 = datatree . AddTimes ( darg2 , datatree . AddLog ( arg1 ) ) ;
t12 = datatree . AddMinus ( arg2 , datatree . AddPossiblyNegativeConstant ( powerDerivOrder ) ) ;
t13 = datatree . AddTimes ( darg1 , t12 ) ;
t14 = datatree . AddDivide ( t13 , arg1 ) ;
t15 = datatree . AddPlus ( t11 , t14 ) ;
expr_t f = datatree . AddPower ( arg1 , t12 ) ;
expr_t first_part = datatree . AddTimes ( f , t15 ) ;
2011-02-04 16:25:38 +01:00
for ( int i = 0 ; i < powerDerivOrder ; i + + )
2010-12-13 14:07:05 +01:00
first_part = datatree . AddTimes ( first_part , datatree . AddMinus ( arg2 , datatree . AddPossiblyNegativeConstant ( i ) ) ) ;
t13 = datatree . Zero ;
2011-02-04 16:25:38 +01:00
for ( int i = 0 ; i < powerDerivOrder ; i + + )
2010-12-13 14:07:05 +01:00
{
t11 = datatree . One ;
2011-02-04 16:25:38 +01:00
for ( int j = 0 ; j < powerDerivOrder ; j + + )
2010-12-13 14:07:05 +01:00
if ( i ! = j )
{
t12 = datatree . AddMinus ( arg2 , datatree . AddPossiblyNegativeConstant ( j ) ) ;
t11 = datatree . AddTimes ( t11 , t12 ) ;
}
t13 = datatree . AddPlus ( t13 , t11 ) ;
}
t13 = datatree . AddTimes ( darg2 , t13 ) ;
t14 = datatree . AddTimes ( f , t13 ) ;
return datatree . AddPlus ( first_part , t14 ) ;
}
2007-10-05 21:47:27 +02:00
case oMax :
2009-12-16 18:13:23 +01:00
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 ) ;
2007-10-05 21:47:27 +02:00
case oMin :
2009-12-16 18:13:23 +01:00
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 ) ;
2007-01-09 20:00:05 +01:00
case oEqual :
2007-10-15 11:04:08 +02:00
return datatree . AddMinus ( darg1 , darg2 ) ;
2007-01-09 20:00:05 +01:00
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2007-01-09 20:00:05 +01:00
}
2010-12-13 14:07:05 +01:00
expr_t
BinaryOpNode : : unpackPowerDeriv ( ) const
{
if ( op_code ! = oPowerDeriv )
return const_cast < BinaryOpNode * > ( this ) ;
expr_t front = datatree . One ;
2011-02-04 16:25:38 +01:00
for ( int i = 0 ; i < powerDerivOrder ; i + + )
2010-12-13 14:07:05 +01:00
front = datatree . AddTimes ( front ,
datatree . AddMinus ( arg2 ,
datatree . AddPossiblyNegativeConstant ( i ) ) ) ;
expr_t tmp = datatree . AddPower ( arg1 ,
datatree . AddMinus ( arg2 ,
datatree . AddPossiblyNegativeConstant ( powerDerivOrder ) ) ) ;
return datatree . AddTimes ( front , tmp ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-07-06 11:34:21 +02:00
BinaryOpNode : : computeDerivative ( int deriv_id )
{
2010-09-16 19:18:45 +02:00
expr_t darg1 = arg1 - > getDerivative ( deriv_id ) ;
expr_t darg2 = arg2 - > getDerivative ( deriv_id ) ;
2009-07-06 11:34:21 +02:00
return composeDerivatives ( darg1 , darg2 ) ;
}
2007-01-09 20:00:05 +01:00
int
2010-09-16 19:00:48 +02:00
BinaryOpNode : : precedence ( ExprNodeOutputType output_type , const temporary_terms_t & temporary_terms ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < BinaryOpNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
// A temporary term behaves as a variable
if ( it ! = temporary_terms . end ( ) )
return 100 ;
2007-01-09 20:00:05 +01:00
2009-12-16 18:13:23 +01:00
switch ( op_code )
{
case oEqual :
return 0 ;
case oEqualEqual :
case oDifferent :
return 1 ;
case oLessEqual :
case oGreaterEqual :
case oLess :
case oGreater :
return 2 ;
case oPlus :
case oMinus :
return 3 ;
case oTimes :
case oDivide :
return 4 ;
case oPower :
2010-12-13 14:07:05 +01:00
case oPowerDeriv :
2009-12-16 18:13:23 +01:00
if ( IS_C ( output_type ) )
// In C, power operator is of the form pow(a, b)
2009-06-05 16:45:23 +02:00
return 100 ;
2009-12-16 18:13:23 +01:00
else
return 5 ;
case oMin :
case oMax :
return 100 ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2009-06-05 16:45:23 +02:00
int
2010-09-16 19:00:48 +02:00
BinaryOpNode : : cost ( const temporary_terms_t & temporary_terms , bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < BinaryOpNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
// For a temporary term, the cost is null
if ( it ! = temporary_terms . end ( ) )
return 0 ;
2009-06-05 16:45:23 +02:00
2009-12-16 18:13:23 +01:00
int cost = arg1 - > cost ( temporary_terms , is_matlab ) ;
cost + = arg2 - > cost ( temporary_terms , is_matlab ) ;
2009-06-05 16:45:23 +02:00
2009-12-16 18:13:23 +01:00
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 :
2010-12-13 14:07:05 +01:00
case oPowerDeriv :
2009-12-16 18:13:23 +01:00
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 :
2010-12-13 14:07:05 +01:00
case oPowerDeriv :
2009-12-16 18:13:23 +01:00
return cost + 520 ;
case oEqual :
return cost ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2007-01-09 20:00:05 +01:00
void
2010-09-16 19:18:45 +02:00
BinaryOpNode : : computeTemporaryTerms ( map < expr_t , int > & reference_count ,
2010-09-16 19:00:48 +02:00
temporary_terms_t & temporary_terms ,
2007-03-06 18:14:35 +01:00
bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t this2 = const_cast < BinaryOpNode * > ( this ) ;
map < expr_t , int > : : iterator it = reference_count . find ( this2 ) ;
2009-12-16 18:13:23 +01:00
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
{
2010-05-05 10:10:01 +02:00
/* If the node has already been encountered, increment its ref count
and declare it as a temporary term if it is too costly ( except if it is
an equal node : we don ' t want them as temporary terms ) */
2009-12-16 18:13:23 +01:00
reference_count [ this2 ] + + ;
2010-05-05 10:10:01 +02:00
if ( reference_count [ this2 ] * cost ( temporary_terms , is_matlab ) > MIN_COST ( is_matlab )
& & op_code ! = oEqual )
2009-12-16 18:13:23 +01:00
temporary_terms . insert ( this2 ) ;
}
}
2007-01-09 20:00:05 +01:00
2007-02-22 00:28:16 +01:00
void
2010-09-16 19:18:45 +02:00
BinaryOpNode : : computeTemporaryTerms ( map < expr_t , int > & reference_count ,
2010-09-16 19:00:48 +02:00
temporary_terms_t & temporary_terms ,
2010-09-16 19:18:45 +02:00
map < expr_t , pair < int , int > > & first_occurence ,
2007-02-22 00:28:16 +01:00
int Curr_block ,
2010-09-16 19:00:48 +02:00
vector < vector < temporary_terms_t > > & v_temporary_terms ,
2009-12-16 14:21:31 +01:00
int equation ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t this2 = const_cast < BinaryOpNode * > ( this ) ;
map < expr_t , int > : : iterator it = reference_count . find ( this2 ) ;
2009-12-16 18:13:23 +01:00
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 , v_temporary_terms , equation ) ;
arg2 - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , v_temporary_terms , equation ) ;
}
else
{
reference_count [ this2 ] + + ;
2010-05-05 10:10:01 +02:00
if ( reference_count [ this2 ] * cost ( temporary_terms , false ) > MIN_COST_C
& & op_code ! = oEqual )
2009-12-16 18:13:23 +01:00
{
temporary_terms . insert ( this2 ) ;
v_temporary_terms [ first_occurence [ this2 ] . first ] [ first_occurence [ this2 ] . second ] . insert ( this2 ) ;
}
}
}
2007-02-22 00:28:16 +01:00
2007-03-09 18:27:46 +01:00
double
2010-12-13 14:07:05 +01:00
BinaryOpNode : : eval_opcode ( double v1 , BinaryOpcode op_code , double v2 , int derivOrder ) throw ( EvalException , EvalExternalFunctionException )
2007-02-22 00:28:16 +01:00
{
2009-06-05 16:45:23 +02:00
switch ( op_code )
2007-02-22 00:28:16 +01:00
{
case oPlus :
2009-12-16 18:13:23 +01:00
return ( v1 + v2 ) ;
2007-02-22 00:28:16 +01:00
case oMinus :
2009-12-16 18:13:23 +01:00
return ( v1 - v2 ) ;
2007-02-22 00:28:16 +01:00
case oTimes :
2009-12-16 18:13:23 +01:00
return ( v1 * v2 ) ;
2007-02-22 00:28:16 +01:00
case oDivide :
2009-12-16 18:13:23 +01:00
return ( v1 / v2 ) ;
2007-02-22 00:28:16 +01:00
case oPower :
2009-12-16 18:13:23 +01:00
return ( pow ( v1 , v2 ) ) ;
2010-12-13 14:07:05 +01:00
case oPowerDeriv :
2011-02-04 16:25:38 +01:00
if ( fabs ( v1 ) < NEAR_ZERO & & v2 > 0
& & derivOrder > = v2
& & fabs ( v2 - nearbyint ( v2 ) ) < NEAR_ZERO )
2010-12-13 14:07:05 +01:00
return 0.0 ;
else
{
double dxp = pow ( v1 , v2 - derivOrder ) ;
2011-02-04 16:25:38 +01:00
for ( int i = 0 ; i < derivOrder ; i + + )
2010-12-13 14:07:05 +01:00
dxp * = v2 - - ;
return dxp ;
}
2007-10-05 21:47:27 +02:00
case oMax :
2007-12-07 17:02:55 +01:00
if ( v1 < v2 )
return v2 ;
2007-10-05 21:47:27 +02:00
else
2007-12-07 17:02:55 +01:00
return v1 ;
2007-10-05 21:47:27 +02:00
case oMin :
2007-12-07 17:02:55 +01:00
if ( v1 > v2 )
return v2 ;
2007-10-05 21:47:27 +02:00
else
2007-12-07 17:02:55 +01:00
return v1 ;
2007-10-09 00:52:57 +02:00
case oLess :
2007-12-07 17:02:55 +01:00
return ( v1 < v2 ) ;
2007-10-09 00:52:57 +02:00
case oGreater :
2007-12-07 17:02:55 +01:00
return ( v1 > v2 ) ;
2007-10-09 00:52:57 +02:00
case oLessEqual :
2007-12-07 17:02:55 +01:00
return ( v1 < = v2 ) ;
2007-10-09 00:52:57 +02:00
case oGreaterEqual :
2007-12-07 17:02:55 +01:00
return ( v1 > = v2 ) ;
2007-10-09 00:52:57 +02:00
case oEqualEqual :
2007-12-07 17:02:55 +01:00
return ( v1 = = v2 ) ;
2007-10-09 00:52:57 +02:00
case oDifferent :
2007-12-07 17:02:55 +01:00
return ( v1 ! = v2 ) ;
2007-02-22 00:28:16 +01:00
case oEqual :
2007-03-09 18:27:46 +01:00
throw EvalException ( ) ;
2007-02-22 00:28:16 +01:00
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2007-02-22 00:28:16 +01:00
}
2007-05-08 21:16:35 +02:00
double
2010-12-10 11:50:27 +01:00
BinaryOpNode : : eval ( const eval_context_t & eval_context ) const throw ( EvalException , EvalExternalFunctionException )
2007-05-08 21:16:35 +02:00
{
double v1 = arg1 - > eval ( eval_context ) ;
double v2 = arg2 - > eval ( eval_context ) ;
2010-12-13 14:07:05 +01:00
return eval_opcode ( v1 , op_code , v2 , powerDerivOrder ) ;
2007-05-08 21:16:35 +02:00
}
2007-10-04 00:01:08 +02:00
void
2010-12-10 11:50:27 +01:00
BinaryOpNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
const map_idx_t & map_idx , bool dynamic , bool steady_dynamic ,
deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
// If current node is a temporary term
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < BinaryOpNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
if ( it ! = temporary_terms . end ( ) )
{
if ( dynamic )
{
2010-09-16 19:00:48 +02:00
map_idx_t : : const_iterator ii = map_idx . find ( idx ) ;
2010-01-22 17:42:08 +01:00
FLDT_ fldt ( ii - > second ) ;
2010-07-23 11:20:24 +02:00
fldt . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
else
{
2010-09-16 19:00:48 +02:00
map_idx_t : : const_iterator ii = map_idx . find ( idx ) ;
2010-01-22 17:42:08 +01:00
FLDST_ fldst ( ii - > second ) ;
2010-07-23 11:20:24 +02:00
fldst . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
return ;
}
2010-12-17 17:17:40 +01:00
if ( op_code = = oPowerDeriv )
{
FLDC_ fldc ( powerDerivOrder ) ;
fldc . write ( CompileCode , instruction_number ) ;
}
2010-12-10 11:50:27 +01:00
arg1 - > compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic , tef_terms ) ;
arg2 - > compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic , tef_terms ) ;
2009-12-16 18:13:23 +01:00
FBINARY_ fbinary ( op_code ) ;
2010-07-23 11:20:24 +02:00
fbinary . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
2007-10-04 00:01:08 +02:00
2008-12-24 16:49:01 +01:00
void
2010-09-16 19:00:48 +02:00
BinaryOpNode : : collectTemporary_terms ( const temporary_terms_t & temporary_terms , temporary_terms_inuse_t & temporary_terms_inuse , int Curr_Block ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < BinaryOpNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
if ( it ! = temporary_terms . end ( ) )
temporary_terms_inuse . insert ( idx ) ;
else
{
arg1 - > collectTemporary_terms ( temporary_terms , temporary_terms_inuse , Curr_Block ) ;
arg2 - > collectTemporary_terms ( temporary_terms , temporary_terms_inuse , Curr_Block ) ;
}
}
2008-12-24 16:49:01 +01:00
2007-01-09 20:00:05 +01:00
void
2007-03-06 18:14:35 +01:00
BinaryOpNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
// If current node is a temporary term
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < BinaryOpNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
if ( it ! = temporary_terms . end ( ) )
{
if ( output_type = = oMatlabDynamicModelSparse )
output < < " T " < < idx < < " (it_) " ;
else
output < < " T " < < idx ;
return ;
}
2007-01-09 20:00:05 +01:00
2010-12-13 14:07:05 +01:00
// Treat derivative of Power
if ( op_code = = oPowerDeriv )
{
if ( IS_LATEX ( output_type ) )
2011-04-12 13:33:03 +02:00
unpackPowerDeriv ( ) - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2010-12-13 14:07:05 +01:00
else
{
output < < " getPowerDeriv( " ;
2011-04-12 13:33:03 +02:00
arg1 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2010-12-13 14:07:05 +01:00
output < < " , " ;
2011-04-12 13:33:03 +02:00
arg2 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2010-12-13 14:07:05 +01:00
output < < " , " < < powerDerivOrder < < " ) " ;
}
return ;
}
2009-12-16 18:13:23 +01: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 :
;
}
2011-04-12 13:33:03 +02:00
arg1 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2009-12-16 18:13:23 +01:00
output < < " , " ;
2011-04-12 13:33:03 +02:00
arg2 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2009-12-16 18:13:23 +01:00
output < < " ) " ;
return ;
}
2007-01-09 20:00:05 +01:00
2009-12-16 18:13:23 +01:00
int prec = precedence ( output_type , temporary_terms ) ;
2007-01-09 20:00:05 +01:00
2009-12-16 18:13:23 +01:00
bool close_parenthesis = false ;
2007-01-09 20:00:05 +01:00
2009-12-16 18:13:23 +01: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 ;
}
}
2007-01-09 20:00:05 +01:00
2009-12-16 18:13:23 +01:00
// Write left argument
2011-04-12 13:33:03 +02:00
arg1 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2009-04-30 15:14:33 +02:00
2009-12-16 18:13:23 +01:00
if ( close_parenthesis )
output < < RIGHT_PAR ( output_type ) ;
2009-04-30 15:14:33 +02:00
2009-12-16 18:13:23 +01:00
if ( IS_LATEX ( output_type ) & & op_code = = oDivide )
output < < " } " ;
2007-01-09 20:00:05 +01:00
2009-12-16 18:13:23 +01:00
// Write current operator symbol
switch ( op_code )
{
case oPlus :
output < < " + " ;
break ;
case oMinus :
output < < " - " ;
break ;
case oTimes :
if ( IS_LATEX ( output_type ) )
output < < " \\ , " ;
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 :
;
}
2007-01-09 20:00:05 +01:00
2009-12-16 18:13:23 +01:00
close_parenthesis = false ;
2007-01-09 20:00:05 +01:00
2009-12-16 18:13:23 +01: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 ;
}
}
2007-01-09 20:00:05 +01:00
2009-12-16 18:13:23 +01:00
// Write right argument
2011-04-12 13:33:03 +02:00
arg2 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2007-01-09 20:00:05 +01:00
2009-12-16 18:13:23 +01:00
if ( IS_LATEX ( output_type ) & & ( op_code = = oPower | | op_code = = oDivide ) )
output < < " } " ;
2009-04-30 15:14:33 +02:00
2009-12-16 18:13:23 +01:00
if ( close_parenthesis )
output < < RIGHT_PAR ( output_type ) ;
}
2007-02-22 00:28:16 +01:00
2010-03-04 16:40:07 +01:00
void
BinaryOpNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
deriv_node_temp_terms_t & tef_terms ) const
2010-03-04 16:40:07 +01:00
{
arg1 - > writeExternalFunctionOutput ( output , output_type , temporary_terms , tef_terms ) ;
arg2 - > writeExternalFunctionOutput ( output , output_type , temporary_terms , tef_terms ) ;
}
2010-12-10 11:50:27 +01:00
void
BinaryOpNode : : compileExternalFunctionOutput ( ostream & CompileCode , unsigned int & instruction_number ,
2011-02-04 16:25:38 +01:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
const map_idx_t & map_idx , bool dynamic , bool steady_dynamic ,
deriv_node_temp_terms_t & tef_terms ) const
2010-12-10 11:50:27 +01:00
{
arg1 - > compileExternalFunctionOutput ( CompileCode , instruction_number , lhs_rhs , temporary_terms , map_idx ,
2011-02-04 16:25:38 +01:00
dynamic , steady_dynamic , tef_terms ) ;
2010-12-10 11:50:27 +01:00
arg2 - > compileExternalFunctionOutput ( CompileCode , instruction_number , lhs_rhs , temporary_terms , map_idx ,
2011-02-04 16:25:38 +01:00
dynamic , steady_dynamic , tef_terms ) ;
2010-12-10 11:50:27 +01:00
}
2007-02-22 00:28:16 +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
2010-09-16 19:18:45 +02:00
expr_t
BinaryOpNode : : Compute_RHS ( expr_t arg1 , expr_t arg2 , int op , int op_type ) const
2009-08-25 11:43:01 +02:00
{
2010-09-16 19:00:48 +02:00
temporary_terms_t temp ;
2009-12-16 18:13:23 +01:00
switch ( op_type )
2009-08-25 11:43:01 +02:00
{
case 0 : /*Unary Operator*/
2009-12-16 18:13:23 +01:00
switch ( op )
2009-08-25 11:43:01 +02:00
{
case oUminus :
2009-12-16 18:13:23 +01:00
return ( datatree . AddUMinus ( arg1 ) ) ;
2009-08-25 11:43:01 +02:00
break ;
case oExp :
2009-12-16 18:13:23 +01:00
return ( datatree . AddExp ( arg1 ) ) ;
2009-08-25 11:43:01 +02:00
break ;
case oLog :
2009-12-16 18:13:23 +01:00
return ( datatree . AddLog ( arg1 ) ) ;
2009-08-25 11:43:01 +02:00
break ;
case oLog10 :
2009-12-16 18:13:23 +01:00
return ( datatree . AddLog10 ( arg1 ) ) ;
break ;
2011-06-10 11:59:34 +02:00
default :
cerr < < " BinaryOpNode::Compute_RHS: case not handled " ;
exit ( EXIT_FAILURE ) ;
2009-12-16 18:13:23 +01:00
}
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 ) ) ;
2009-08-25 11:43:01 +02:00
break ;
2011-06-10 11:59:34 +02:00
default :
cerr < < " BinaryOpNode::Compute_RHS: case not handled " ;
exit ( EXIT_FAILURE ) ;
2009-08-25 11:43:01 +02:00
}
break ;
2009-12-16 18:13:23 +01:00
}
2010-09-16 19:18:45 +02:00
return ( ( expr_t ) NULL ) ;
2009-12-16 18:13:23 +01:00
}
2010-09-16 19:18:45 +02:00
pair < int , expr_t >
BinaryOpNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < expr_t , expr_t > > > & List_of_Op_RHS ) const
2009-12-16 18:13:23 +01:00
{
2011-06-10 11:59:34 +02:00
/* Checks if the current value of the endogenous variable related to the equation
is present in the arguments of the binary operator . */
2010-09-16 19:18:45 +02:00
vector < pair < int , pair < expr_t , expr_t > > > List_of_Op_RHS1 , List_of_Op_RHS2 ;
2009-12-16 18:13:23 +01:00
int is_endogenous_present_1 , is_endogenous_present_2 ;
2010-09-16 19:18:45 +02:00
pair < int , expr_t > res ;
expr_t expr_t_1 , expr_t_2 ;
2009-12-16 18:13:23 +01:00
res = arg1 - > normalizeEquation ( var_endo , List_of_Op_RHS1 ) ;
is_endogenous_present_1 = res . first ;
2010-09-16 19:18:45 +02:00
expr_t_1 = res . second ;
2009-12-16 18:13:23 +01:00
res = arg2 - > normalizeEquation ( var_endo , List_of_Op_RHS2 ) ;
is_endogenous_present_2 = res . first ;
2010-09-16 19:18:45 +02:00
expr_t_2 = res . second ;
2011-06-10 11:59:34 +02:00
/* If the two expressions contains the current value of the endogenous variable associated to the equation
the equation could not be normalized and the process is given - up . */
2009-12-16 18:13:23 +01:00
if ( is_endogenous_present_1 = = 2 | | is_endogenous_present_2 = = 2 )
2010-09-16 19:18:45 +02:00
return ( make_pair ( 2 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
else if ( is_endogenous_present_1 & & is_endogenous_present_2 )
2010-09-16 19:18:45 +02:00
return ( make_pair ( 2 , ( expr_t ) NULL ) ) ;
2011-06-10 11:59:34 +02:00
else if ( is_endogenous_present_1 ) /*If the current values of the endogenous variable associated to the equation
is present only in the first operand of the expression , we try to normalize the equation */
2009-12-16 18:13:23 +01:00
{
2011-06-10 11:59:34 +02:00
if ( op_code = = oEqual ) /* The end of the normalization process :
All the operations needed to normalize the equation are applied . */
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:18:45 +02:00
pair < int , pair < expr_t , expr_t > > it ;
2009-12-16 18:13:23 +01:00
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*/
2010-09-16 19:18:45 +02:00
expr_t_2 = Compute_RHS ( expr_t_2 , ( BinaryOpNode * ) it . second . first , it . first , 1 ) ;
2009-12-16 18:13:23 +01:00
else if ( it . second . second & & ! it . second . first ) /*Binary operator*/
2010-09-16 19:18:45 +02:00
expr_t_2 = Compute_RHS ( it . second . second , expr_t_2 , it . first , 1 ) ;
2009-12-16 18:13:23 +01:00
else if ( it . second . second & & it . second . first ) /*Binary operator*/
2010-09-16 19:18:45 +02:00
expr_t_2 = Compute_RHS ( it . second . first , it . second . second , it . first , 1 ) ;
2011-02-04 16:25:38 +01:00
else /*Unary operator*/
2010-09-16 19:18:45 +02:00
expr_t_2 = Compute_RHS ( ( UnaryOpNode * ) expr_t_2 , ( UnaryOpNode * ) it . second . first , it . first , 0 ) ;
2009-12-16 18:13:23 +01:00
}
}
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 + + )
{
2010-09-16 19:18:45 +02:00
pair < int , pair < expr_t , expr_t > > it ;
2009-12-16 18:13:23 +01:00
it = List_of_Op_RHS2 . back ( ) ;
List_of_Op_RHS2 . pop_back ( ) ;
if ( it . second . first & & ! it . second . second ) /*Binary operator*/
2010-09-16 19:18:45 +02:00
expr_t_1 = Compute_RHS ( ( BinaryOpNode * ) expr_t_1 , ( BinaryOpNode * ) it . second . first , it . first , 1 ) ;
2009-12-16 18:13:23 +01:00
else if ( it . second . second & & ! it . second . first ) /*Binary operator*/
2010-09-16 19:18:45 +02:00
expr_t_1 = Compute_RHS ( ( BinaryOpNode * ) it . second . second , ( BinaryOpNode * ) expr_t_1 , it . first , 1 ) ;
2009-12-16 18:13:23 +01:00
else if ( it . second . second & & it . second . first ) /*Binary operator*/
2010-09-16 19:18:45 +02:00
expr_t_1 = Compute_RHS ( it . second . first , it . second . second , it . first , 1 ) ;
2009-12-16 18:13:23 +01:00
else
2010-09-16 19:18:45 +02:00
expr_t_1 = Compute_RHS ( ( UnaryOpNode * ) expr_t_1 , ( UnaryOpNode * ) it . second . first , it . first , 0 ) ;
2009-12-16 18:13:23 +01:00
}
}
else
List_of_Op_RHS = List_of_Op_RHS2 ;
}
switch ( op_code )
{
case oPlus :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
2010-09-16 19:18:45 +02:00
List_of_Op_RHS . push_back ( make_pair ( oMinus , make_pair ( datatree . AddPlus ( expr_t_1 , expr_t_2 ) , ( expr_t ) NULL ) ) ) ;
return ( make_pair ( 0 , datatree . AddPlus ( expr_t_1 , expr_t_2 ) ) ) ;
2009-12-16 18:13:23 +01:00
}
else if ( is_endogenous_present_1 & & is_endogenous_present_2 )
2010-09-16 19:18:45 +02:00
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
else if ( ! is_endogenous_present_1 & & is_endogenous_present_2 )
{
2010-09-16 19:18:45 +02:00
List_of_Op_RHS . push_back ( make_pair ( oMinus , make_pair ( expr_t_1 , ( expr_t ) NULL ) ) ) ;
return ( make_pair ( 1 , expr_t_1 ) ) ;
2009-12-16 18:13:23 +01:00
}
else if ( is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
2010-09-16 19:18:45 +02:00
List_of_Op_RHS . push_back ( make_pair ( oMinus , make_pair ( expr_t_2 , ( expr_t ) NULL ) ) ) ;
return ( make_pair ( 1 , expr_t_2 ) ) ;
2009-12-16 18:13:23 +01:00
}
break ;
case oMinus :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
2010-09-16 19:18:45 +02:00
List_of_Op_RHS . push_back ( make_pair ( oMinus , make_pair ( datatree . AddMinus ( expr_t_1 , expr_t_2 ) , ( expr_t ) NULL ) ) ) ;
return ( make_pair ( 0 , datatree . AddMinus ( expr_t_1 , expr_t_2 ) ) ) ;
2009-12-16 18:13:23 +01:00
}
else if ( is_endogenous_present_1 & & is_endogenous_present_2 )
2010-09-16 19:18:45 +02:00
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
else if ( ! is_endogenous_present_1 & & is_endogenous_present_2 )
{
2010-09-16 19:18:45 +02:00
List_of_Op_RHS . push_back ( make_pair ( oUminus , make_pair ( ( expr_t ) NULL , ( expr_t ) NULL ) ) ) ;
List_of_Op_RHS . push_back ( make_pair ( oMinus , make_pair ( expr_t_1 , ( expr_t ) NULL ) ) ) ;
return ( make_pair ( 1 , expr_t_1 ) ) ;
2009-12-16 18:13:23 +01:00
}
else if ( is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
2010-09-16 19:18:45 +02:00
List_of_Op_RHS . push_back ( make_pair ( oPlus , make_pair ( expr_t_2 , ( expr_t ) NULL ) ) ) ;
return ( make_pair ( 1 , datatree . AddUMinus ( expr_t_2 ) ) ) ;
2009-12-16 18:13:23 +01:00
}
break ;
case oTimes :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddTimes ( expr_t_1 , expr_t_2 ) ) ) ;
2009-12-16 18:13:23 +01:00
else if ( ! is_endogenous_present_1 & & is_endogenous_present_2 )
{
2010-09-16 19:18:45 +02:00
List_of_Op_RHS . push_back ( make_pair ( oDivide , make_pair ( expr_t_1 , ( expr_t ) NULL ) ) ) ;
return ( make_pair ( 1 , expr_t_1 ) ) ;
2009-12-16 18:13:23 +01:00
}
else if ( is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
2010-09-16 19:18:45 +02:00
List_of_Op_RHS . push_back ( make_pair ( oDivide , make_pair ( expr_t_2 , ( expr_t ) NULL ) ) ) ;
return ( make_pair ( 1 , expr_t_2 ) ) ;
2009-12-16 18:13:23 +01:00
}
else
2010-09-16 19:18:45 +02:00
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
break ;
case oDivide :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddDivide ( expr_t_1 , expr_t_2 ) ) ) ;
2009-12-16 18:13:23 +01:00
else if ( ! is_endogenous_present_1 & & is_endogenous_present_2 )
{
2010-09-16 19:18:45 +02:00
List_of_Op_RHS . push_back ( make_pair ( oDivide , make_pair ( ( expr_t ) NULL , expr_t_1 ) ) ) ;
return ( make_pair ( 1 , expr_t_1 ) ) ;
2009-12-16 18:13:23 +01:00
}
else if ( is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
2010-09-16 19:18:45 +02:00
List_of_Op_RHS . push_back ( make_pair ( oTimes , make_pair ( expr_t_2 , ( expr_t ) NULL ) ) ) ;
return ( make_pair ( 1 , expr_t_2 ) ) ;
2009-12-16 18:13:23 +01:00
}
else
2010-09-16 19:18:45 +02:00
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
break ;
case oPower :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddPower ( expr_t_1 , expr_t_2 ) ) ) ;
2009-12-16 18:13:23 +01:00
else if ( is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
2010-09-16 19:18:45 +02:00
List_of_Op_RHS . push_back ( make_pair ( oPower , make_pair ( datatree . AddDivide ( datatree . One , expr_t_2 ) , ( expr_t ) NULL ) ) ) ;
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
}
2011-06-10 11:59:34 +02:00
else if ( ! is_endogenous_present_1 & & is_endogenous_present_2 )
{
/* we have to nomalize a^f(X) = RHS */
/* First computes the ln(RHS)*/
List_of_Op_RHS . push_back ( make_pair ( oLog , make_pair ( ( expr_t ) NULL , ( expr_t ) NULL ) ) ) ;
/* Second computes f(X) = ln(RHS) / ln(a)*/
List_of_Op_RHS . push_back ( make_pair ( oDivide , make_pair ( ( expr_t ) NULL , datatree . AddLog ( expr_t_1 ) ) ) ) ;
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
}
2009-12-16 18:13:23 +01:00
break ;
case oEqual :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
return ( make_pair ( 0 ,
2010-09-16 19:18:45 +02:00
datatree . AddEqual ( datatree . AddVariable ( datatree . symbol_table . getID ( eEndogenous , var_endo ) , 0 ) , datatree . AddMinus ( expr_t_2 , expr_t_1 ) )
2009-12-16 18:13:23 +01:00
) ) ;
}
else if ( is_endogenous_present_1 & & is_endogenous_present_2 )
{
return ( make_pair ( 0 ,
2010-03-16 12:23:59 +01:00
datatree . AddEqual ( datatree . AddVariable ( datatree . symbol_table . getID ( eEndogenous , var_endo ) , 0 ) , datatree . Zero )
2009-12-16 18:13:23 +01:00
) ) ;
}
else if ( ! is_endogenous_present_1 & & is_endogenous_present_2 )
{
return ( make_pair ( 0 ,
2010-09-16 19:18:45 +02:00
datatree . AddEqual ( datatree . AddVariable ( datatree . symbol_table . getID ( eEndogenous , var_endo ) , 0 ) , /*datatree.AddUMinus(expr_t_1)*/ expr_t_1 )
2009-12-16 18:13:23 +01:00
) ) ;
}
else if ( is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
return ( make_pair ( 0 ,
2010-09-16 19:18:45 +02:00
datatree . AddEqual ( datatree . AddVariable ( datatree . symbol_table . getID ( eEndogenous , var_endo ) , 0 ) , expr_t_2 )
2009-12-16 18:13:23 +01:00
) ) ;
}
break ;
case oMax :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddMax ( expr_t_1 , expr_t_2 ) ) ) ;
2009-12-16 18:13:23 +01:00
else
2010-09-16 19:18:45 +02:00
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
break ;
case oMin :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddMin ( expr_t_1 , expr_t_2 ) ) ) ;
2009-12-16 18:13:23 +01:00
else
2010-09-16 19:18:45 +02:00
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
break ;
case oLess :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddLess ( expr_t_1 , expr_t_2 ) ) ) ;
2009-12-16 18:13:23 +01:00
else
2010-09-16 19:18:45 +02:00
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
break ;
case oGreater :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddGreater ( expr_t_1 , expr_t_2 ) ) ) ;
2009-12-16 18:13:23 +01:00
else
2010-09-16 19:18:45 +02:00
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
break ;
case oLessEqual :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddLessEqual ( expr_t_1 , expr_t_2 ) ) ) ;
2009-12-16 18:13:23 +01:00
else
2010-09-16 19:18:45 +02:00
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
break ;
case oGreaterEqual :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddGreaterEqual ( expr_t_1 , expr_t_2 ) ) ) ;
2009-12-16 18:13:23 +01:00
else
2010-09-16 19:18:45 +02:00
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
break ;
case oEqualEqual :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddEqualEqual ( expr_t_1 , expr_t_2 ) ) ) ;
2009-12-16 18:13:23 +01:00
else
2010-09-16 19:18:45 +02:00
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
break ;
case oDifferent :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddDifferent ( expr_t_1 , expr_t_2 ) ) ) ;
2009-12-16 18:13:23 +01:00
else
2010-09-16 19:18:45 +02:00
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-08-25 11:43:01 +02:00
break ;
2011-06-10 11:59:34 +02:00
default :
cerr < < " Binary operator not handled during the normalization process " < < endl ;
return ( make_pair ( 2 , ( expr_t ) NULL ) ) ; // Could not be normalized
2009-08-25 11:43:01 +02:00
}
2009-12-16 18:13:23 +01:00
// Suppress GCC warning
2011-06-10 11:59:34 +02:00
cerr < < " BinaryOpNode::normalizeEquation: impossible case " < < endl ;
2009-12-16 18:13:23 +01:00
exit ( EXIT_FAILURE ) ;
2009-08-25 11:43:01 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
BinaryOpNode : : getChainRuleDerivative ( int deriv_id , const map < int , expr_t > & recursive_variables )
2009-04-14 16:39:53 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t darg1 = arg1 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
expr_t darg2 = arg2 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
2009-07-06 11:34:21 +02:00
return composeDerivatives ( darg1 , darg2 ) ;
2009-04-14 16:39:53 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
BinaryOpNode : : buildSimilarBinaryOpNode ( expr_t alt_arg1 , expr_t alt_arg2 , DataTree & alt_datatree ) const
2009-09-30 17:10:31 +02:00
{
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 ) ;
2010-12-13 14:07:05 +01:00
case oPowerDeriv :
2011-03-23 11:36:08 +01:00
return alt_datatree . AddPowerDeriv ( alt_arg1 , alt_arg2 , powerDerivOrder ) ;
2009-09-30 17:10:31 +02:00
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-06-05 16:45:23 +02:00
BinaryOpNode : : toStatic ( DataTree & static_datatree ) const
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t sarg1 = arg1 - > toStatic ( static_datatree ) ;
expr_t sarg2 = arg2 - > toStatic ( static_datatree ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarBinaryOpNode ( sarg1 , sarg2 , static_datatree ) ;
}
2010-10-15 19:05:16 +02:00
expr_t
BinaryOpNode : : cloneDynamic ( DataTree & dynamic_datatree ) const
{
expr_t substarg1 = arg1 - > cloneDynamic ( dynamic_datatree ) ;
expr_t substarg2 = arg2 - > cloneDynamic ( dynamic_datatree ) ;
return buildSimilarBinaryOpNode ( substarg1 , substarg2 , dynamic_datatree ) ;
}
2009-09-30 17:10:31 +02:00
int
BinaryOpNode : : maxEndoLead ( ) const
{
return max ( arg1 - > maxEndoLead ( ) , arg2 - > maxEndoLead ( ) ) ;
}
2009-06-05 16:45:23 +02:00
2009-10-07 18:34:42 +02:00
int
BinaryOpNode : : maxExoLead ( ) const
{
return max ( arg1 - > maxExoLead ( ) , arg2 - > maxExoLead ( ) ) ;
}
2010-08-19 15:20:54 +02:00
int
BinaryOpNode : : maxEndoLag ( ) const
{
return max ( arg1 - > maxEndoLag ( ) , arg2 - > maxEndoLag ( ) ) ;
}
int
BinaryOpNode : : maxExoLag ( ) const
{
return max ( arg1 - > maxExoLag ( ) , arg2 - > maxExoLag ( ) ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-09-30 17:10:31 +02:00
BinaryOpNode : : decreaseLeadsLags ( int n ) const
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > decreaseLeadsLags ( n ) ;
expr_t arg2subst = arg2 - > decreaseLeadsLags ( n ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-11-09 12:03:18 +01:00
BinaryOpNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
2009-11-07 19:37:11 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > decreaseLeadsLagsPredeterminedVariables ( ) ;
expr_t arg2subst = arg2 - > decreaseLeadsLagsPredeterminedVariables ( ) ;
2009-11-07 19:37:11 +01:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
BinaryOpNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst , arg2subst ;
2009-10-07 18:34:42 +02:00
int maxendolead1 = arg1 - > maxEndoLead ( ) , maxendolead2 = arg2 - > maxEndoLead ( ) ;
2009-09-30 17:10:31 +02:00
2009-10-07 18:34:42 +02:00
if ( maxendolead1 < 2 & & maxendolead2 < 2 )
2009-09-30 17:10:31 +02:00
return const_cast < BinaryOpNode * > ( this ) ;
2010-08-18 13:45:07 +02:00
if ( deterministic_model )
2009-09-30 17:10:31 +02:00
{
2010-08-18 13:45:07 +02:00
arg1subst = maxendolead1 > = 2 ? arg1 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) : arg1 ;
arg2subst = maxendolead2 > = 2 ? arg2 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) : arg2 ;
2009-09-30 17:10:31 +02:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
2010-08-18 13:45:07 +02:00
}
else
{
switch ( op_code )
2009-09-30 17:10:31 +02:00
{
2010-08-18 13:45:07 +02:00
case oPlus :
case oMinus :
case oEqual :
arg1subst = maxendolead1 > = 2 ? arg1 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) : arg1 ;
arg2subst = maxendolead2 > = 2 ? arg2 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) : arg2 ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
case oTimes :
case oDivide :
if ( maxendolead1 > = 2 & & maxendolead2 = = 0 & & arg2 - > maxExoLead ( ) = = 0 )
{
arg1subst = arg1 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2 , datatree ) ;
}
if ( maxendolead1 = = 0 & & arg1 - > maxExoLead ( ) = = 0
& & maxendolead2 > = 2 & & op_code = = oTimes )
{
arg2subst = arg2 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) ;
return buildSimilarBinaryOpNode ( arg1 , arg2subst , datatree ) ;
}
return createEndoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
default :
return createEndoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
}
}
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 16:07:13 +02:00
BinaryOpNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
expr_t arg2subst = arg2 - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
2009-10-07 16:07:13 +02:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
BinaryOpNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-10-07 18:34:42 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst , arg2subst ;
2009-10-07 18:34:42 +02:00
int maxexolead1 = arg1 - > maxExoLead ( ) , maxexolead2 = arg2 - > maxExoLead ( ) ;
if ( maxexolead1 < 1 & & maxexolead2 < 1 )
return const_cast < BinaryOpNode * > ( this ) ;
2010-08-18 13:45:07 +02:00
if ( deterministic_model )
2009-10-07 18:34:42 +02:00
{
2010-08-18 13:45:07 +02:00
arg1subst = maxexolead1 > = 1 ? arg1 - > substituteExoLead ( subst_table , neweqs , deterministic_model ) : arg1 ;
arg2subst = maxexolead2 > = 1 ? arg2 - > substituteExoLead ( subst_table , neweqs , deterministic_model ) : arg2 ;
2009-10-07 18:34:42 +02:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
2010-08-18 13:45:07 +02:00
}
else
{
switch ( op_code )
2009-10-07 18:34:42 +02:00
{
2010-08-18 13:45:07 +02:00
case oPlus :
case oMinus :
case oEqual :
arg1subst = maxexolead1 > = 1 ? arg1 - > substituteExoLead ( subst_table , neweqs , deterministic_model ) : arg1 ;
arg2subst = maxexolead2 > = 1 ? arg2 - > substituteExoLead ( subst_table , neweqs , deterministic_model ) : arg2 ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
case oTimes :
case oDivide :
if ( maxexolead1 > = 1 & & maxexolead2 = = 0 & & arg2 - > maxEndoLead ( ) = = 0 )
{
arg1subst = arg1 - > substituteExoLead ( subst_table , neweqs , deterministic_model ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2 , datatree ) ;
}
if ( maxexolead1 = = 0 & & arg1 - > maxEndoLead ( ) = = 0
& & maxexolead2 > = 1 & & op_code = = oTimes )
{
arg2subst = arg2 - > substituteExoLead ( subst_table , neweqs , deterministic_model ) ;
return buildSimilarBinaryOpNode ( arg1 , arg2subst , datatree ) ;
}
return createExoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
default :
return createExoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
2009-10-07 18:34:42 +02:00
}
}
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 18:34:42 +02:00
BinaryOpNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > substituteExoLag ( subst_table , neweqs ) ;
expr_t arg2subst = arg2 - > substituteExoLag ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2009-04-14 16:39:53 +02:00
2010-09-16 19:18:45 +02:00
expr_t
2009-10-29 18:16:10 +01:00
BinaryOpNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
expr_t arg2subst = arg2 - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
2009-10-30 06:21:54 +01:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
2009-10-29 18:16:10 +01:00
}
2011-03-21 18:40:57 +01:00
expr_t
BinaryOpNode : : addMultipliersToConstraints ( int i )
{
int symb_id = datatree . symbol_table . addMultiplierAuxiliaryVar ( i ) ;
expr_t newAuxLM = datatree . AddVariable ( symb_id , 0 ) ;
return datatree . AddEqual ( datatree . AddTimes ( newAuxLM , datatree . AddMinus ( arg1 , arg2 ) ) , datatree . Zero ) ;
}
2010-04-16 16:54:55 +02:00
bool
BinaryOpNode : : isNumConstNodeEqualTo ( double value ) const
{
return false ;
}
bool
BinaryOpNode : : isVariableNodeEqualTo ( SymbolType type_arg , int variable_id , int lag_arg ) const
{
return false ;
}
2010-10-15 19:05:16 +02:00
expr_t
BinaryOpNode : : replaceTrendVar ( ) const
{
expr_t arg1subst = arg1 - > replaceTrendVar ( ) ;
expr_t arg2subst = arg2 - > replaceTrendVar ( ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
expr_t
BinaryOpNode : : detrend ( int symb_id , expr_t trend ) const
{
expr_t arg1subst = arg1 - > detrend ( symb_id , trend ) ;
expr_t arg2subst = arg2 - > detrend ( symb_id , trend ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
expr_t
BinaryOpNode : : removeTrendLeadLag ( map < int , expr_t > trend_symbols_map ) const
{
expr_t arg1subst = arg1 - > removeTrendLeadLag ( trend_symbols_map ) ;
expr_t arg2subst = arg2 - > removeTrendLeadLag ( trend_symbols_map ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
TrinaryOpNode : : TrinaryOpNode ( DataTree & datatree_arg , const expr_t arg1_arg ,
TrinaryOpcode op_code_arg , const expr_t arg2_arg , const expr_t arg3_arg ) :
2009-12-16 18:13:23 +01:00
ExprNode ( datatree_arg ) ,
arg1 ( arg1_arg ) ,
arg2 ( arg2_arg ) ,
arg3 ( arg3_arg ) ,
op_code ( op_code_arg )
2007-11-11 16:24:50 +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 ( ) ;
2007-11-11 16:24:50 +01:00
// Non-null derivatives are the union of those of the arguments
2007-12-07 17:02:55 +01:00
// 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 ;
2007-11-11 16:24:50 +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 ( ) ) ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
TrinaryOpNode : : composeDerivatives ( expr_t darg1 , expr_t darg2 , expr_t darg3 )
2007-11-11 16:24:50 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t t11 , t12 , t13 , t14 , t15 ;
2007-11-11 16:24:50 +01:00
2009-06-05 16:45:23 +02:00
switch ( op_code )
2007-11-11 16:24:50 +01:00
{
case oNormcdf :
// normal pdf is inlined in the tree
2010-09-16 19:18:45 +02:00
expr_t y ;
2007-11-11 16:24:50 +01:00
// sqrt(2*pi)
2009-04-16 12:33:30 +02:00
t14 = datatree . AddSqrt ( datatree . AddTimes ( datatree . Two , datatree . Pi ) ) ;
2007-11-11 16:24:50 +01:00
// x - mu
2009-12-16 18:13:23 +01:00
t12 = datatree . AddMinus ( arg1 , arg2 ) ;
2007-11-11 16:24:50 +01:00
// y = (x-mu)/sigma
2009-12-16 18:13:23 +01:00
y = datatree . AddDivide ( t12 , arg3 ) ;
2007-11-11 16:24:50 +01:00
// (x-mu)^2/sigma^2
2009-12-16 18:13:23 +01:00
t12 = datatree . AddTimes ( y , y ) ;
2007-11-11 16:24:50 +01:00
// -(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 ) ;
2007-11-11 16:24:50 +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)
2009-12-16 18:13:23 +01:00
t15 = datatree . AddDivide ( t13 , t14 ) ;
2007-11-11 16:24:50 +01:00
// derivatives thru x
2009-12-16 18:13:23 +01:00
t11 = datatree . AddDivide ( darg1 , arg3 ) ;
2007-11-11 16:24:50 +01:00
// derivatives thru mu
2009-12-16 18:13:23 +01:00
t12 = datatree . AddDivide ( darg2 , arg3 ) ;
2007-11-11 16:24:50 +01:00
// intermediary sum
2009-12-16 18:13:23 +01:00
t14 = datatree . AddMinus ( t11 , t12 ) ;
2007-11-11 16:24:50 +01:00
// derivatives thru sigma
2009-12-16 18:13:23 +01:00
t11 = datatree . AddDivide ( y , arg3 ) ;
t12 = datatree . AddTimes ( t11 , darg3 ) ;
2007-11-11 16:24:50 +01:00
//intermediary sum
2009-12-16 18:13:23 +01:00
t11 = datatree . AddMinus ( t14 , t12 ) ;
2007-11-11 16:24:50 +01:00
// 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
2007-11-11 16:24:50 +01:00
return datatree . AddTimes ( t11 , t15 ) ;
2010-03-11 09:43:16 +01:00
case oNormpdf :
// (x - mu)
t11 = datatree . AddMinus ( arg1 , arg2 ) ;
// (x - mu)/sigma
t12 = datatree . AddDivide ( t11 , arg3 ) ;
// darg3 * (x - mu)/sigma
t11 = datatree . AddTimes ( darg3 , t12 ) ;
// darg2 - darg1
t13 = datatree . AddMinus ( darg2 , darg1 ) ;
// darg2 - darg1 + darg3 * (x - mu)/sigma
t14 = datatree . AddPlus ( t13 , t11 ) ;
// ((x - mu)/sigma) * (darg2 - darg1 + darg3 * (x - mu)/sigma)
t11 = datatree . AddTimes ( t12 , t14 ) ;
// ((x - mu)/sigma) * (darg2 - darg1 + darg3 * (x - mu)/sigma) - darg3
t12 = datatree . AddMinus ( t11 , darg3 ) ;
// this / sigma
t11 = datatree . AddDivide ( this , arg3 ) ;
// total derivative:
// (this / sigma) * (((x - mu)/sigma) * (darg2 - darg1 + darg3 * (x - mu)/sigma) - darg3)
return datatree . AddTimes ( t11 , t12 ) ;
2007-11-11 16:24:50 +01:00
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2007-11-11 16:24:50 +01:00
}
2010-09-16 19:18:45 +02:00
expr_t
2009-07-06 11:34:21 +02:00
TrinaryOpNode : : computeDerivative ( int deriv_id )
{
2010-09-16 19:18:45 +02:00
expr_t darg1 = arg1 - > getDerivative ( deriv_id ) ;
expr_t darg2 = arg2 - > getDerivative ( deriv_id ) ;
expr_t darg3 = arg3 - > getDerivative ( deriv_id ) ;
2009-07-06 11:34:21 +02:00
return composeDerivatives ( darg1 , darg2 , darg3 ) ;
}
2007-11-11 16:24:50 +01:00
int
2010-09-16 19:00:48 +02:00
TrinaryOpNode : : precedence ( ExprNodeOutputType output_type , const temporary_terms_t & temporary_terms ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < TrinaryOpNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
// A temporary term behaves as a variable
if ( it ! = temporary_terms . end ( ) )
return 100 ;
2009-06-05 16:45:23 +02:00
2009-12-16 18:13:23 +01:00
switch ( op_code )
{
case oNormcdf :
2010-03-11 09:43:16 +01:00
case oNormpdf :
2009-12-16 18:13:23 +01:00
return 100 ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2007-11-11 16:24:50 +01:00
int
2010-09-16 19:00:48 +02:00
TrinaryOpNode : : cost ( const temporary_terms_t & temporary_terms , bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < TrinaryOpNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
// For a temporary term, the cost is null
if ( it ! = temporary_terms . end ( ) )
return 0 ;
2007-11-11 16:24:50 +01:00
2009-12-16 18:13:23 +01:00
int cost = arg1 - > cost ( temporary_terms , is_matlab ) ;
cost + = arg2 - > cost ( temporary_terms , is_matlab ) ;
2007-11-11 16:24:50 +01:00
2009-12-16 18:13:23 +01:00
if ( is_matlab )
// Cost for Matlab files
switch ( op_code )
{
case oNormcdf :
2010-03-11 09:43:16 +01:00
case oNormpdf :
2009-12-16 18:13:23 +01:00
return cost + 1000 ;
}
else
// Cost for C files
switch ( op_code )
{
case oNormcdf :
2010-03-11 09:43:16 +01:00
case oNormpdf :
2009-12-16 18:13:23 +01:00
return cost + 1000 ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2007-11-11 16:24:50 +01:00
void
2010-09-16 19:18:45 +02:00
TrinaryOpNode : : computeTemporaryTerms ( map < expr_t , int > & reference_count ,
2010-09-16 19:00:48 +02:00
temporary_terms_t & temporary_terms ,
2009-01-23 11:59:37 +01:00
bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t this2 = const_cast < TrinaryOpNode * > ( this ) ;
map < expr_t , int > : : iterator it = reference_count . find ( this2 ) ;
2009-12-16 18:13:23 +01:00
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 ) ;
}
}
2007-11-11 16:24:50 +01:00
void
2010-09-16 19:18:45 +02:00
TrinaryOpNode : : computeTemporaryTerms ( map < expr_t , int > & reference_count ,
2010-09-16 19:00:48 +02:00
temporary_terms_t & temporary_terms ,
2010-09-16 19:18:45 +02:00
map < expr_t , pair < int , int > > & first_occurence ,
2009-01-23 11:59:37 +01:00
int Curr_block ,
2010-09-16 19:00:48 +02:00
vector < vector < temporary_terms_t > > & v_temporary_terms ,
2009-12-16 14:21:31 +01:00
int equation ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t this2 = const_cast < TrinaryOpNode * > ( this ) ;
map < expr_t , int > : : iterator it = reference_count . find ( this2 ) ;
2009-12-16 18:13:23 +01:00
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 , v_temporary_terms , equation ) ;
arg2 - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , v_temporary_terms , equation ) ;
arg3 - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , v_temporary_terms , equation ) ;
}
else
{
reference_count [ this2 ] + + ;
if ( reference_count [ this2 ] * cost ( temporary_terms , false ) > MIN_COST_C )
{
temporary_terms . insert ( this2 ) ;
v_temporary_terms [ first_occurence [ this2 ] . first ] [ first_occurence [ this2 ] . second ] . insert ( this2 ) ;
}
}
}
2007-11-11 16:24:50 +01:00
double
2010-12-10 11:50:27 +01:00
TrinaryOpNode : : eval_opcode ( double v1 , TrinaryOpcode op_code , double v2 , double v3 ) throw ( EvalException , EvalExternalFunctionException )
2007-11-11 16:24:50 +01:00
{
2009-06-05 16:45:23 +02:00
switch ( op_code )
2007-11-11 16:24:50 +01:00
{
case oNormcdf :
2010-02-23 14:39:49 +01:00
return ( 0.5 * ( 1 + erf ( ( v1 - v2 ) / v3 / M_SQRT2 ) ) ) ;
2010-03-11 09:43:16 +01:00
case oNormpdf :
2011-02-04 16:25:38 +01:00
return ( 1 / ( v3 * sqrt ( 2 * M_PI ) * exp ( pow ( ( v1 - v2 ) / v3 , 2 ) / 2 ) ) ) ;
2007-11-11 16:24:50 +01:00
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2007-11-11 16:24:50 +01:00
}
double
2010-12-10 11:50:27 +01:00
TrinaryOpNode : : eval ( const eval_context_t & eval_context ) const throw ( EvalException , EvalExternalFunctionException )
2007-11-11 16:24:50 +01:00
{
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
2010-12-10 11:50:27 +01:00
TrinaryOpNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
2011-02-04 16:25:38 +01:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
const map_idx_t & map_idx , bool dynamic , bool steady_dynamic ,
deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
// If current node is a temporary term
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < TrinaryOpNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
if ( it ! = temporary_terms . end ( ) )
{
if ( dynamic )
{
2010-09-16 19:00:48 +02:00
map_idx_t : : const_iterator ii = map_idx . find ( idx ) ;
2010-01-22 17:42:08 +01:00
FLDT_ fldt ( ii - > second ) ;
2010-07-23 11:20:24 +02:00
fldt . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
else
{
2010-09-16 19:00:48 +02:00
map_idx_t : : const_iterator ii = map_idx . find ( idx ) ;
2010-01-22 17:42:08 +01:00
FLDST_ fldst ( ii - > second ) ;
2010-07-23 11:20:24 +02:00
fldst . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
return ;
}
2010-12-10 11:50:27 +01:00
arg1 - > compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic , tef_terms ) ;
arg2 - > compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic , tef_terms ) ;
arg3 - > compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic , tef_terms ) ;
2010-04-16 16:54:55 +02:00
FTRINARY_ ftrinary ( op_code ) ;
2010-07-23 11:20:24 +02:00
ftrinary . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
2007-11-11 16:24:50 +01:00
2008-12-24 16:49:01 +01:00
void
2010-09-16 19:00:48 +02:00
TrinaryOpNode : : collectTemporary_terms ( const temporary_terms_t & temporary_terms , temporary_terms_inuse_t & temporary_terms_inuse , int Curr_Block ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < TrinaryOpNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
if ( it ! = temporary_terms . end ( ) )
temporary_terms_inuse . insert ( idx ) ;
else
{
arg1 - > collectTemporary_terms ( temporary_terms , temporary_terms_inuse , Curr_Block ) ;
arg2 - > collectTemporary_terms ( temporary_terms , temporary_terms_inuse , Curr_Block ) ;
arg3 - > collectTemporary_terms ( temporary_terms , temporary_terms_inuse , Curr_Block ) ;
}
}
2008-12-24 16:49:01 +01:00
2007-11-11 16:24:50 +01:00
void
TrinaryOpNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
// If current node is a temporary term
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < TrinaryOpNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
if ( it ! = temporary_terms . end ( ) )
{
output < < " T " < < idx ;
return ;
}
2007-11-11 16:24:50 +01:00
2009-12-16 18:13:23 +01:00
switch ( op_code )
{
case oNormcdf :
2010-02-23 14:39:49 +01:00
if ( IS_C ( output_type ) )
{
// In C, there is no normcdf() primitive, so use erf()
output < < " (0.5*(1+erf((( " ;
2011-04-12 13:33:03 +02:00
arg1 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2010-02-23 14:39:49 +01:00
output < < " )-( " ;
2011-04-12 13:33:03 +02:00
arg2 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2010-02-23 14:39:49 +01:00
output < < " ))/( " ;
2011-04-12 13:33:03 +02:00
arg3 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2010-02-23 14:39:49 +01:00
output < < " )/M_SQRT2))) " ;
}
else
{
output < < " normcdf( " ;
2011-04-12 13:33:03 +02:00
arg1 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2010-02-23 14:39:49 +01:00
output < < " , " ;
2011-04-12 13:33:03 +02:00
arg2 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2010-02-23 14:39:49 +01:00
output < < " , " ;
2011-04-12 13:33:03 +02:00
arg3 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2010-02-23 14:39:49 +01:00
output < < " ) " ;
}
2010-03-15 12:22:52 +01:00
break ;
2010-03-11 09:43:16 +01:00
case oNormpdf :
if ( IS_C ( output_type ) )
{
//(1/(v3*sqrt(2*M_PI)*exp(pow((v1-v2)/v3,2)/2)))
output < < " (1/( " ;
2011-04-12 13:33:03 +02:00
arg3 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2010-03-11 09:43:16 +01:00
output < < " *sqrt(2*M_PI)*exp(pow(( " ;
2011-04-12 13:33:03 +02:00
arg1 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2010-03-11 09:43:16 +01:00
output < < " - " ;
2011-04-12 13:33:03 +02:00
arg2 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2010-03-11 09:43:16 +01:00
output < < " )/ " ;
2011-04-12 13:33:03 +02:00
arg3 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2010-03-11 09:43:16 +01:00
output < < " ,2)/2))) " ;
}
else
{
output < < " normpdf( " ;
2011-04-12 13:33:03 +02:00
arg1 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2010-03-11 09:43:16 +01:00
output < < " , " ;
2011-04-12 13:33:03 +02:00
arg2 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2010-03-11 09:43:16 +01:00
output < < " , " ;
2011-04-12 13:33:03 +02:00
arg3 - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
2010-03-11 09:43:16 +01:00
output < < " ) " ;
}
2009-12-16 18:13:23 +01:00
break ;
}
}
2007-11-11 16:24:50 +01:00
2010-03-04 16:40:07 +01:00
void
TrinaryOpNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
deriv_node_temp_terms_t & tef_terms ) const
2010-03-04 16:40:07 +01:00
{
arg1 - > writeExternalFunctionOutput ( output , output_type , temporary_terms , tef_terms ) ;
arg2 - > writeExternalFunctionOutput ( output , output_type , temporary_terms , tef_terms ) ;
arg3 - > writeExternalFunctionOutput ( output , output_type , temporary_terms , tef_terms ) ;
}
2010-12-10 11:50:27 +01:00
void
TrinaryOpNode : : compileExternalFunctionOutput ( ostream & CompileCode , unsigned int & instruction_number ,
2011-02-04 16:25:38 +01:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
const map_idx_t & map_idx , bool dynamic , bool steady_dynamic ,
deriv_node_temp_terms_t & tef_terms ) const
2010-12-10 11:50:27 +01:00
{
arg1 - > compileExternalFunctionOutput ( CompileCode , instruction_number , lhs_rhs , temporary_terms , map_idx ,
2011-02-04 16:25:38 +01:00
dynamic , steady_dynamic , tef_terms ) ;
2010-12-10 11:50:27 +01:00
arg2 - > compileExternalFunctionOutput ( CompileCode , instruction_number , lhs_rhs , temporary_terms , map_idx ,
2011-02-04 16:25:38 +01:00
dynamic , steady_dynamic , tef_terms ) ;
2010-12-10 11:50:27 +01:00
arg3 - > compileExternalFunctionOutput ( CompileCode , instruction_number , lhs_rhs , temporary_terms , map_idx ,
2011-02-04 16:25:38 +01:00
dynamic , steady_dynamic , tef_terms ) ;
2010-12-10 11:50:27 +01:00
}
2007-11-11 16:24:50 +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
2010-09-16 19:18:45 +02:00
pair < int , expr_t >
TrinaryOpNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < expr_t , expr_t > > > & List_of_Op_RHS ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:18:45 +02:00
pair < int , expr_t > res = arg1 - > normalizeEquation ( var_endo , List_of_Op_RHS ) ;
2009-12-16 18:13:23 +01:00
bool is_endogenous_present_1 = res . first ;
2010-09-16 19:18:45 +02:00
expr_t expr_t_1 = res . second ;
2009-12-16 18:13:23 +01:00
res = arg2 - > normalizeEquation ( var_endo , List_of_Op_RHS ) ;
bool is_endogenous_present_2 = res . first ;
2010-09-16 19:18:45 +02:00
expr_t expr_t_2 = res . second ;
2009-12-16 18:13:23 +01:00
res = arg3 - > normalizeEquation ( var_endo , List_of_Op_RHS ) ;
bool is_endogenous_present_3 = res . first ;
2010-09-16 19:18:45 +02:00
expr_t expr_t_3 = res . second ;
2009-12-16 18:13:23 +01:00
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 & & ! is_endogenous_present_3 )
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddNormcdf ( expr_t_1 , expr_t_2 , expr_t_3 ) ) ) ;
2009-12-16 18:13:23 +01:00
else
2010-09-16 19:18:45 +02:00
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
}
2008-11-14 17:07:47 +01:00
2010-09-16 19:18:45 +02:00
expr_t
TrinaryOpNode : : getChainRuleDerivative ( int deriv_id , const map < int , expr_t > & recursive_variables )
2009-04-14 16:39:53 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t darg1 = arg1 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
expr_t darg2 = arg2 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
expr_t darg3 = arg3 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
2009-07-06 11:34:21 +02:00
return composeDerivatives ( darg1 , darg2 , darg3 ) ;
2009-04-14 16:39:53 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
TrinaryOpNode : : buildSimilarTrinaryOpNode ( expr_t alt_arg1 , expr_t alt_arg2 , expr_t alt_arg3 , DataTree & alt_datatree ) const
2009-09-30 17:10:31 +02:00
{
switch ( op_code )
{
case oNormcdf :
return alt_datatree . AddNormcdf ( alt_arg1 , alt_arg2 , alt_arg3 ) ;
2010-03-11 09:43:16 +01:00
case oNormpdf :
return alt_datatree . AddNormpdf ( alt_arg1 , alt_arg2 , alt_arg3 ) ;
2009-09-30 17:10:31 +02:00
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-06-05 16:45:23 +02:00
TrinaryOpNode : : toStatic ( DataTree & static_datatree ) const
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t sarg1 = arg1 - > toStatic ( static_datatree ) ;
expr_t sarg2 = arg2 - > toStatic ( static_datatree ) ;
expr_t sarg3 = arg3 - > toStatic ( static_datatree ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarTrinaryOpNode ( sarg1 , sarg2 , sarg3 , static_datatree ) ;
}
2009-06-05 16:45:23 +02:00
2010-10-15 19:05:16 +02:00
expr_t
TrinaryOpNode : : cloneDynamic ( DataTree & dynamic_datatree ) const
{
expr_t substarg1 = arg1 - > cloneDynamic ( dynamic_datatree ) ;
expr_t substarg2 = arg2 - > cloneDynamic ( dynamic_datatree ) ;
expr_t substarg3 = arg3 - > cloneDynamic ( dynamic_datatree ) ;
return buildSimilarTrinaryOpNode ( substarg1 , substarg2 , substarg3 , dynamic_datatree ) ;
}
2009-09-30 17:10:31 +02:00
int
TrinaryOpNode : : maxEndoLead ( ) const
{
return max ( arg1 - > maxEndoLead ( ) , max ( arg2 - > maxEndoLead ( ) , arg3 - > maxEndoLead ( ) ) ) ;
}
2009-10-07 18:34:42 +02:00
int
TrinaryOpNode : : maxExoLead ( ) const
{
return max ( arg1 - > maxExoLead ( ) , max ( arg2 - > maxExoLead ( ) , arg3 - > maxExoLead ( ) ) ) ;
}
2010-08-19 15:20:54 +02:00
int
TrinaryOpNode : : maxEndoLag ( ) const
{
return max ( arg1 - > maxEndoLag ( ) , max ( arg2 - > maxEndoLag ( ) , arg3 - > maxEndoLag ( ) ) ) ;
}
int
TrinaryOpNode : : maxExoLag ( ) const
{
return max ( arg1 - > maxExoLag ( ) , max ( arg2 - > maxExoLag ( ) , arg3 - > maxExoLag ( ) ) ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-09-30 17:10:31 +02:00
TrinaryOpNode : : decreaseLeadsLags ( int n ) const
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > decreaseLeadsLags ( n ) ;
expr_t arg2subst = arg2 - > decreaseLeadsLags ( n ) ;
expr_t arg3subst = arg3 - > decreaseLeadsLags ( n ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-11-09 12:03:18 +01:00
TrinaryOpNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
2009-11-07 19:37:11 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > decreaseLeadsLagsPredeterminedVariables ( ) ;
expr_t arg2subst = arg2 - > decreaseLeadsLagsPredeterminedVariables ( ) ;
expr_t arg3subst = arg3 - > decreaseLeadsLagsPredeterminedVariables ( ) ;
2009-11-07 19:37:11 +01:00
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
TrinaryOpNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-09-30 17:10:31 +02:00
{
if ( maxEndoLead ( ) < 2 )
return const_cast < TrinaryOpNode * > ( this ) ;
2010-08-18 13:45:07 +02:00
else if ( deterministic_model )
{
expr_t arg1subst = arg1 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) ;
expr_t arg2subst = arg2 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) ;
expr_t arg3subst = arg3 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2009-09-30 17:10:31 +02:00
else
2009-10-07 16:07:13 +02:00
return createEndoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 16:07:13 +02:00
TrinaryOpNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
expr_t arg2subst = arg2 - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
expr_t arg3subst = arg3 - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
2009-10-07 16:07:13 +02:00
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
2009-09-30 17:10:31 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
TrinaryOpNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-10-07 18:34:42 +02:00
{
if ( maxExoLead ( ) = = 0 )
return const_cast < TrinaryOpNode * > ( this ) ;
2010-08-18 13:45:07 +02:00
else if ( deterministic_model )
{
expr_t arg1subst = arg1 - > substituteExoLead ( subst_table , neweqs , deterministic_model ) ;
expr_t arg2subst = arg2 - > substituteExoLead ( subst_table , neweqs , deterministic_model ) ;
expr_t arg3subst = arg3 - > substituteExoLead ( subst_table , neweqs , deterministic_model ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2009-10-07 18:34:42 +02:00
else
return createExoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 18:34:42 +02:00
TrinaryOpNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > substituteExoLag ( subst_table , neweqs ) ;
expr_t arg2subst = arg2 - > substituteExoLag ( subst_table , neweqs ) ;
expr_t arg3subst = arg3 - > substituteExoLag ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2008-11-14 17:07:47 +01:00
2010-09-16 19:18:45 +02:00
expr_t
2009-10-29 18:16:10 +01:00
TrinaryOpNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
expr_t arg2subst = arg2 - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
expr_t arg3subst = arg3 - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
2009-10-29 18:16:10 +01:00
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2010-04-16 16:54:55 +02:00
bool
TrinaryOpNode : : isNumConstNodeEqualTo ( double value ) const
{
return false ;
}
bool
TrinaryOpNode : : isVariableNodeEqualTo ( SymbolType type_arg , int variable_id , int lag_arg ) const
{
return false ;
}
2010-10-15 19:05:16 +02:00
expr_t
TrinaryOpNode : : replaceTrendVar ( ) const
{
expr_t arg1subst = arg1 - > replaceTrendVar ( ) ;
expr_t arg2subst = arg2 - > replaceTrendVar ( ) ;
expr_t arg3subst = arg3 - > replaceTrendVar ( ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
expr_t
TrinaryOpNode : : detrend ( int symb_id , expr_t trend ) const
{
expr_t arg1subst = arg1 - > detrend ( symb_id , trend ) ;
expr_t arg2subst = arg2 - > detrend ( symb_id , trend ) ;
expr_t arg3subst = arg3 - > detrend ( symb_id , trend ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
expr_t
TrinaryOpNode : : removeTrendLeadLag ( map < int , expr_t > trend_symbols_map ) const
{
expr_t arg1subst = arg1 - > removeTrendLeadLag ( trend_symbols_map ) ;
expr_t arg2subst = arg2 - > removeTrendLeadLag ( trend_symbols_map ) ;
expr_t arg3subst = arg3 - > removeTrendLeadLag ( trend_symbols_map ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : ExternalFunctionNode ( DataTree & datatree_arg ,
2011-02-04 16:25:38 +01:00
int symb_id_arg ,
const vector < expr_t > & arguments_arg ) :
2009-12-16 18:13:23 +01:00
ExprNode ( datatree_arg ) ,
symb_id ( symb_id_arg ) ,
arguments ( arguments_arg )
2007-03-09 18:27:46 +01:00
{
2010-03-03 11:43:22 +01:00
// Add myself to the external function map
2011-02-04 16:25:38 +01:00
datatree . external_function_node_map [ make_pair ( arguments , symb_id ) ] = this ;
2007-03-09 18:27:46 +01:00
}
2009-09-30 17:10:31 +02:00
void
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : prepareForDerivation ( )
2009-09-30 17:10:31 +02:00
{
2010-02-22 17:33:38 +01:00
if ( preparedForDerivation )
return ;
2010-09-16 19:18:45 +02:00
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
2010-02-22 17:33:38 +01:00
( * it ) - > prepareForDerivation ( ) ;
non_null_derivatives = arguments . at ( 0 ) - > non_null_derivatives ;
2011-02-04 16:25:38 +01:00
for ( int i = 1 ; i < ( int ) arguments . size ( ) ; i + + )
2010-02-22 17:33:38 +01:00
set_union ( non_null_derivatives . begin ( ) ,
non_null_derivatives . end ( ) ,
arguments . at ( i ) - > non_null_derivatives . begin ( ) ,
arguments . at ( i ) - > non_null_derivatives . end ( ) ,
inserter ( non_null_derivatives , non_null_derivatives . begin ( ) ) ) ;
preparedForDerivation = true ;
2009-09-30 17:10:31 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : computeDerivative ( int deriv_id )
2007-03-09 18:27:46 +01:00
{
2010-03-03 11:40:13 +01:00
assert ( datatree . external_functions_table . getNargs ( symb_id ) > 0 ) ;
2010-09-16 19:18:45 +02:00
vector < expr_t > dargs ;
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
2010-02-22 17:33:38 +01:00
dargs . push_back ( ( * it ) - > getDerivative ( deriv_id ) ) ;
return composeDerivatives ( dargs ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
ExternalFunctionNode : : composeDerivatives ( const vector < expr_t > & dargs )
2010-02-22 17:33:38 +01:00
{
2010-09-16 19:18:45 +02:00
vector < expr_t > dNodes ;
2011-02-04 16:25:38 +01:00
for ( int i = 0 ; i < ( int ) dargs . size ( ) ; i + + )
2010-02-22 17:33:38 +01:00
if ( dargs . at ( i ) ! = 0 )
dNodes . push_back ( datatree . AddTimes ( dargs . at ( i ) ,
datatree . AddFirstDerivExternalFunctionNode ( symb_id , arguments , i + 1 ) ) ) ;
2010-09-16 19:18:45 +02:00
expr_t theDeriv = datatree . Zero ;
for ( vector < expr_t > : : const_iterator it = dNodes . begin ( ) ; it ! = dNodes . end ( ) ; it + + )
2010-02-22 17:33:38 +01:00
theDeriv = datatree . AddPlus ( theDeriv , * it ) ;
return theDeriv ;
2007-03-09 18:27:46 +01:00
}
2010-09-16 19:18:45 +02:00
expr_t
ExternalFunctionNode : : getChainRuleDerivative ( int deriv_id , const map < int , expr_t > & recursive_variables )
2007-03-09 18:27:46 +01:00
{
2010-12-10 11:50:27 +01:00
assert ( datatree . external_functions_table . getNargs ( symb_id ) > 0 ) ;
vector < expr_t > dargs ;
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ;
2011-02-04 16:25:38 +01:00
it ! = arguments . end ( ) ; it + + )
2010-12-10 11:50:27 +01:00
dargs . push_back ( ( * it ) - > getChainRuleDerivative ( deriv_id , recursive_variables ) ) ;
return composeDerivatives ( dargs ) ;
2007-03-09 18:27:46 +01:00
}
2009-06-05 16:45:23 +02:00
void
2010-09-16 19:18:45 +02:00
ExternalFunctionNode : : computeTemporaryTerms ( map < expr_t , int > & reference_count ,
2011-02-04 16:25:38 +01:00
temporary_terms_t & temporary_terms ,
bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
2010-03-04 16:40:07 +01:00
temporary_terms . insert ( const_cast < ExternalFunctionNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
}
2007-03-09 18:27:46 +01:00
2009-12-16 18:13:23 +01:00
void
2010-03-04 16:40:07 +01:00
ExternalFunctionNode : : writeExternalFunctionArguments ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:18:45 +02:00
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ;
2009-12-16 18:13:23 +01:00
it ! = arguments . end ( ) ; it + + )
{
if ( it ! = arguments . begin ( ) )
output < < " , " ;
2010-03-04 16:40:07 +01:00
( * it ) - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
}
}
2010-10-05 18:48:15 +02:00
void
ExternalFunctionNode : : writePrhs ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_t & temporary_terms ,
deriv_node_temp_terms_t & tef_terms , const string & ending ) const
{
output < < " mxArray *prhs " < < ending < < " [nrhs " < < ending < < " ]; " < < endl ;
int i = 0 ;
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ;
it ! = arguments . end ( ) ; it + + )
{
output < < " prhs " < < ending < < " [ " < < i + + < < " ] = mxCreateDoubleScalar( " ; // All external_function arguments are scalars
( * it ) - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
output < < " ); " < < endl ;
}
}
2010-03-04 16:40:07 +01:00
void
ExternalFunctionNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
deriv_node_temp_terms_t & tef_terms ) const
2010-03-04 16:40:07 +01:00
{
2011-01-26 19:55:01 +01:00
if ( output_type = = oMatlabOutsideModel | | output_type = = oSteadyStateFile )
2010-03-04 16:40:07 +01:00
{
output < < datatree . symbol_table . getName ( symb_id ) < < " ( " ;
writeExternalFunctionArguments ( output , output_type , temporary_terms , tef_terms ) ;
output < < " ) " ;
return ;
}
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < ExternalFunctionNode * > ( this ) ) ;
2010-03-04 16:40:07 +01:00
if ( it ! = temporary_terms . end ( ) )
{
if ( output_type = = oMatlabDynamicModelSparse )
output < < " T " < < idx < < " (it_) " ;
else
output < < " T " < < idx ;
return ;
}
2010-10-05 18:48:15 +02:00
if ( IS_C ( output_type ) )
output < < " * " ;
2010-03-04 16:40:07 +01:00
output < < " TEF_ " < < getIndxInTefTerms ( symb_id , tef_terms ) ;
}
2010-12-10 11:50:27 +01:00
unsigned int
ExternalFunctionNode : : compileExternalFunctionArguments ( ostream & CompileCode , unsigned int & instruction_number ,
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
const map_idx_t & map_idx , bool dynamic , bool steady_dynamic ,
deriv_node_temp_terms_t & tef_terms ) const
{
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ;
it ! = arguments . end ( ) ; it + + )
2011-02-04 16:25:38 +01:00
( * it ) - > compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , map_idx ,
dynamic , steady_dynamic , tef_terms ) ;
return ( arguments . size ( ) ) ;
2010-12-10 11:50:27 +01:00
}
void
ExternalFunctionNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
const map_idx_t & map_idx , bool dynamic , bool steady_dynamic ,
deriv_node_temp_terms_t & tef_terms ) const
{
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < ExternalFunctionNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
{
if ( dynamic )
{
map_idx_t : : const_iterator ii = map_idx . find ( idx ) ;
FLDT_ fldt ( ii - > second ) ;
fldt . write ( CompileCode , instruction_number ) ;
}
else
{
map_idx_t : : const_iterator ii = map_idx . find ( idx ) ;
FLDST_ fldst ( ii - > second ) ;
fldst . write ( CompileCode , instruction_number ) ;
}
return ;
}
if ( ! lhs_rhs )
{
FLDTEF_ fldtef ( getIndxInTefTerms ( symb_id , tef_terms ) ) ;
fldtef . write ( CompileCode , instruction_number ) ;
}
else
{
FSTPTEF_ fstptef ( getIndxInTefTerms ( symb_id , tef_terms ) ) ;
fstptef . write ( CompileCode , instruction_number ) ;
}
}
2010-03-04 16:40:07 +01:00
void
ExternalFunctionNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
deriv_node_temp_terms_t & tef_terms ) const
2010-03-04 16:40:07 +01:00
{
int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
assert ( first_deriv_symb_id ! = eExtFunSetButNoNameProvided ) ;
2010-09-16 19:18:45 +02:00
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ;
2010-03-04 16:40:07 +01:00
it ! = arguments . end ( ) ; it + + )
( * it ) - > writeExternalFunctionOutput ( output , output_type , temporary_terms , tef_terms ) ;
if ( ! alreadyWrittenAsTefTerm ( symb_id , tef_terms ) )
{
tef_terms [ make_pair ( symb_id , arguments ) ] = ( int ) tef_terms . size ( ) ;
int indx = getIndxInTefTerms ( symb_id , tef_terms ) ;
int second_deriv_symb_id = datatree . external_functions_table . getSecondDerivSymbID ( symb_id ) ;
assert ( second_deriv_symb_id ! = eExtFunSetButNoNameProvided ) ;
2010-10-05 18:48:15 +02:00
if ( IS_C ( output_type ) )
{
stringstream ending ;
ending < < " _tef_ " < < getIndxInTefTerms ( symb_id , tef_terms ) ;
2011-02-04 16:25:38 +01:00
if ( symb_id = = first_deriv_symb_id
& & symb_id = = second_deriv_symb_id )
2010-10-05 18:48:15 +02:00
output < < " int nlhs " < < ending . str ( ) < < " = 3; " < < endl
< < " double *TEF_ " < < indx < < " , "
< < " *TEFD_ " < < indx < < " , "
< < " *TEFDD_ " < < indx < < " ; " < < endl ;
else if ( symb_id = = first_deriv_symb_id )
output < < " int nlhs " < < ending . str ( ) < < " = 2; " < < endl
< < " double *TEF_ " < < indx < < " , "
< < " *TEFD_ " < < indx < < " ; " < < endl ;
else
output < < " int nlhs " < < ending . str ( ) < < " = 1; " < < endl
< < " double *TEF_ " < < indx < < " ; " < < endl ;
output < < " mxArray *plhs " < < ending . str ( ) < < " [nlhs " < < ending . str ( ) < < " ]; " < < endl ;
output < < " int nrhs " < < ending . str ( ) < < " = " < < arguments . size ( ) < < " ; " < < endl ;
writePrhs ( output , output_type , temporary_terms , tef_terms , ending . str ( ) ) ;
output < < " mexCallMATLAB( "
< < " nlhs " < < ending . str ( ) < < " , "
< < " plhs " < < ending . str ( ) < < " , "
< < " nrhs " < < ending . str ( ) < < " , "
< < " prhs " < < ending . str ( ) < < " , \" "
< < datatree . symbol_table . getName ( symb_id ) < < " \" ); " < < endl ;
2011-02-04 16:25:38 +01:00
if ( symb_id = = first_deriv_symb_id
& & symb_id = = second_deriv_symb_id )
2010-10-05 18:48:15 +02:00
output < < " TEF_ " < < indx < < " = mxGetPr(plhs " < < ending . str ( ) < < " [0]); " < < endl
< < " TEFD_ " < < indx < < " = mxGetPr(plhs " < < ending . str ( ) < < " [1]); " < < endl
< < " TEFDD_ " < < indx < < " = mxGetPr(plhs " < < ending . str ( ) < < " [2]); " < < endl
< < " int TEFDD_ " < < indx < < " _nrows = (int)mxGetM(plhs " < < ending . str ( ) < < " [2]); " < < endl ;
else if ( symb_id = = first_deriv_symb_id )
output < < " TEF_ " < < indx < < " = mxGetPr(plhs " < < ending . str ( ) < < " [0]); " < < endl
< < " TEFD_ " < < indx < < " = mxGetPr(plhs " < < ending . str ( ) < < " [1]); " < < endl ;
else
output < < " TEF_ " < < indx < < " = mxGetPr(plhs " < < ending . str ( ) < < " [0]); " < < endl ;
}
2010-03-04 16:40:07 +01:00
else
2010-10-05 18:48:15 +02:00
{
2011-02-04 16:25:38 +01:00
if ( symb_id = = first_deriv_symb_id
& & symb_id = = second_deriv_symb_id )
2010-10-05 18:48:15 +02:00
output < < " [TEF_ " < < indx < < " TEFD_ " < < indx < < " TEFDD_ " < < indx < < " ] = " ;
else if ( symb_id = = first_deriv_symb_id )
output < < " [TEF_ " < < indx < < " TEFD_ " < < indx < < " ] = " ;
else
output < < " TEF_ " < < indx < < " = " ;
2010-03-04 16:40:07 +01:00
2010-10-05 18:48:15 +02:00
output < < datatree . symbol_table . getName ( symb_id ) < < " ( " ;
writeExternalFunctionArguments ( output , output_type , temporary_terms , tef_terms ) ;
output < < " ); " < < endl ;
}
2009-12-16 18:13:23 +01:00
}
}
2007-03-09 18:27:46 +01:00
2010-12-10 11:50:27 +01:00
void
ExternalFunctionNode : : compileExternalFunctionOutput ( ostream & CompileCode , unsigned int & instruction_number ,
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
const map_idx_t & map_idx , bool dynamic , bool steady_dynamic ,
deriv_node_temp_terms_t & tef_terms ) const
{
int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
assert ( first_deriv_symb_id ! = eExtFunSetButNoNameProvided ) ;
2011-02-04 16:25:38 +01:00
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ;
2010-12-10 11:50:27 +01:00
it ! = arguments . end ( ) ; it + + )
( * it ) - > compileExternalFunctionOutput ( CompileCode , instruction_number , lhs_rhs , temporary_terms ,
map_idx , dynamic , steady_dynamic , tef_terms ) ;
if ( ! alreadyWrittenAsTefTerm ( symb_id , tef_terms ) )
{
tef_terms [ make_pair ( symb_id , arguments ) ] = ( int ) tef_terms . size ( ) ;
int indx = getIndxInTefTerms ( symb_id , tef_terms ) ;
int second_deriv_symb_id = datatree . external_functions_table . getSecondDerivSymbID ( symb_id ) ;
assert ( second_deriv_symb_id ! = eExtFunSetButNoNameProvided ) ;
unsigned int nb_output_arguments = 0 ;
2011-02-04 16:25:38 +01:00
if ( symb_id = = first_deriv_symb_id
& & symb_id = = second_deriv_symb_id )
2010-12-10 11:50:27 +01:00
nb_output_arguments = 3 ;
else if ( symb_id = = first_deriv_symb_id )
nb_output_arguments = 2 ;
else
nb_output_arguments = 1 ;
unsigned int nb_input_arguments = compileExternalFunctionArguments ( CompileCode , instruction_number , lhs_rhs , temporary_terms ,
2011-02-04 16:25:38 +01:00
map_idx , dynamic , steady_dynamic , tef_terms ) ;
2010-12-10 11:50:27 +01:00
FCALL_ fcall ( nb_output_arguments , nb_input_arguments , datatree . symbol_table . getName ( symb_id ) , indx ) ;
2011-02-04 16:25:38 +01:00
switch ( nb_output_arguments )
2010-12-10 11:50:27 +01:00
{
2011-02-04 16:25:38 +01:00
case 1 :
fcall . set_function_type ( ExternalFunctionWithoutDerivative ) ;
break ;
case 2 :
fcall . set_function_type ( ExternalFunctionWithFirstDerivative ) ;
break ;
case 3 :
fcall . set_function_type ( ExternalFunctionWithFirstandSecondDerivative ) ;
break ;
2010-12-10 11:50:27 +01:00
}
fcall . write ( CompileCode , instruction_number ) ;
FSTPTEF_ fstptef ( indx ) ;
fstptef . write ( CompileCode , instruction_number ) ;
}
}
2007-03-09 18:27:46 +01:00
void
2010-09-16 19:18:45 +02:00
ExternalFunctionNode : : computeTemporaryTerms ( map < expr_t , int > & reference_count ,
2011-02-04 16:25:38 +01:00
temporary_terms_t & temporary_terms ,
map < expr_t , pair < int , int > > & first_occurence ,
int Curr_block ,
vector < vector < temporary_terms_t > > & v_temporary_terms ,
int equation ) const
2009-12-16 18:13:23 +01:00
{
2010-12-10 11:50:27 +01:00
expr_t this2 = const_cast < ExternalFunctionNode * > ( this ) ;
temporary_terms . insert ( this2 ) ;
first_occurence [ this2 ] = make_pair ( Curr_block , equation ) ;
v_temporary_terms [ Curr_block ] [ equation ] . insert ( this2 ) ;
2009-12-16 18:13:23 +01:00
}
2007-03-09 18:27:46 +01:00
void
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : collectVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
2009-07-10 18:42:08 +02:00
{
2010-09-16 19:18:45 +02:00
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ;
2009-07-10 18:42:08 +02:00
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
2010-09-16 19:00:48 +02:00
ExternalFunctionNode : : collectTemporary_terms ( const temporary_terms_t & temporary_terms , temporary_terms_inuse_t & temporary_terms_inuse , int Curr_Block ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < ExternalFunctionNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
if ( it ! = temporary_terms . end ( ) )
temporary_terms_inuse . insert ( idx ) ;
else
{
2010-12-10 11:50:27 +01:00
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ;
2011-02-04 16:25:38 +01:00
it ! = arguments . end ( ) ; it + + )
( * it ) - > collectTemporary_terms ( temporary_terms , temporary_terms_inuse , Curr_Block ) ;
2009-12-16 18:13:23 +01:00
}
}
2008-11-14 17:07:47 +01:00
2007-03-09 18:27:46 +01:00
double
2010-12-10 11:50:27 +01:00
ExternalFunctionNode : : eval ( const eval_context_t & eval_context ) const throw ( EvalException , EvalExternalFunctionException )
2007-03-09 18:27:46 +01:00
{
2010-12-10 11:50:27 +01:00
throw EvalExternalFunctionException ( ) ;
2007-03-09 18:27:46 +01:00
}
2007-10-04 00:01:08 +02:00
2010-09-16 19:18:45 +02:00
pair < int , expr_t >
ExternalFunctionNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < expr_t , expr_t > > > & List_of_Op_RHS ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:18:45 +02:00
vector < pair < bool , expr_t > > V_arguments ;
vector < expr_t > V_expr_t ;
2009-12-16 18:13:23 +01:00
bool present = false ;
2010-09-16 19:18:45 +02:00
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ;
2009-12-16 18:13:23 +01:00
it ! = arguments . end ( ) ; it + + )
{
V_arguments . push_back ( ( * it ) - > normalizeEquation ( var_endo , List_of_Op_RHS ) ) ;
present = present | | V_arguments [ V_arguments . size ( ) - 1 ] . first ;
2010-09-16 19:18:45 +02:00
V_expr_t . push_back ( V_arguments [ V_arguments . size ( ) - 1 ] . second ) ;
2009-12-16 18:13:23 +01:00
}
if ( ! present )
2010-09-16 19:18:45 +02:00
return ( make_pair ( 0 , datatree . AddExternalFunction ( symb_id , V_expr_t ) ) ) ;
2009-12-16 18:13:23 +01:00
else
2010-09-16 19:18:45 +02:00
return ( make_pair ( 1 , ( expr_t ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
}
2009-04-14 16:39:53 +02:00
2010-09-16 19:18:45 +02:00
expr_t
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : toStatic ( DataTree & static_datatree ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:18:45 +02:00
vector < expr_t > static_arguments ;
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ;
2009-12-16 18:13:23 +01:00
it ! = arguments . end ( ) ; it + + )
static_arguments . push_back ( ( * it ) - > toStatic ( static_datatree ) ) ;
2010-03-16 12:17:17 +01:00
return static_datatree . AddExternalFunction ( symb_id , static_arguments ) ;
2009-12-16 18:13:23 +01:00
}
2009-09-30 17:10:31 +02:00
2010-10-15 19:05:16 +02:00
expr_t
ExternalFunctionNode : : cloneDynamic ( DataTree & dynamic_datatree ) const
{
vector < expr_t > dynamic_arguments ;
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ;
it ! = arguments . end ( ) ; it + + )
dynamic_arguments . push_back ( ( * it ) - > cloneDynamic ( dynamic_datatree ) ) ;
return dynamic_datatree . AddExternalFunction ( symb_id , dynamic_arguments ) ;
}
2009-09-30 17:10:31 +02:00
int
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : maxEndoLead ( ) const
2009-09-30 17:10:31 +02:00
{
int val = 0 ;
2010-09-16 19:18:45 +02:00
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ;
2009-12-16 18:13:23 +01:00
it ! = arguments . end ( ) ; it + + )
2009-09-30 17:10:31 +02:00
val = max ( val , ( * it ) - > maxEndoLead ( ) ) ;
return val ;
}
2009-10-07 18:34:42 +02:00
int
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : maxExoLead ( ) const
2009-10-07 18:34:42 +02:00
{
int val = 0 ;
2010-09-16 19:18:45 +02:00
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ;
2009-12-16 18:13:23 +01:00
it ! = arguments . end ( ) ; it + + )
2009-10-07 18:34:42 +02:00
val = max ( val , ( * it ) - > maxExoLead ( ) ) ;
return val ;
}
2010-08-19 15:20:54 +02:00
int
ExternalFunctionNode : : maxEndoLag ( ) const
{
int val = 0 ;
2010-09-16 19:18:45 +02:00
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ;
2010-08-19 15:20:54 +02:00
it ! = arguments . end ( ) ; it + + )
val = max ( val , ( * it ) - > maxEndoLag ( ) ) ;
return val ;
}
int
ExternalFunctionNode : : maxExoLag ( ) const
{
int val = 0 ;
2010-09-16 19:18:45 +02:00
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ;
2010-08-19 15:20:54 +02:00
it ! = arguments . end ( ) ; it + + )
val = max ( val , ( * it ) - > maxExoLag ( ) ) ;
return val ;
}
2010-09-16 19:18:45 +02:00
expr_t
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : decreaseLeadsLags ( int n ) const
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
vector < expr_t > arguments_subst ;
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
2010-02-22 17:33:38 +01:00
arguments_subst . push_back ( ( * it ) - > decreaseLeadsLags ( n ) ) ;
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
2009-09-30 17:10:31 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
2009-11-07 19:37:11 +01:00
{
2010-09-16 19:18:45 +02:00
vector < expr_t > arguments_subst ;
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
2010-02-22 17:33:38 +01:00
arguments_subst . push_back ( ( * it ) - > decreaseLeadsLagsPredeterminedVariables ( ) ) ;
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
2009-11-07 19:37:11 +01:00
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
ExternalFunctionNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-10-07 16:07:13 +02:00
{
2010-09-16 19:18:45 +02:00
vector < expr_t > arguments_subst ;
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
2010-08-18 13:45:07 +02:00
arguments_subst . push_back ( ( * it ) - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) ) ;
2010-02-22 17:33:38 +01:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
2009-10-07 16:07:13 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
vector < expr_t > arguments_subst ;
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
2010-02-22 17:33:38 +01:00
arguments_subst . push_back ( ( * it ) - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ) ;
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
2009-09-30 17:10:31 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
ExternalFunctionNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-10-07 18:34:42 +02:00
{
2010-09-16 19:18:45 +02:00
vector < expr_t > arguments_subst ;
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
2010-08-18 13:45:07 +02:00
arguments_subst . push_back ( ( * it ) - > substituteExoLead ( subst_table , neweqs , deterministic_model ) ) ;
2010-02-22 17:33:38 +01:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
2009-10-07 18:34:42 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
2010-09-16 19:18:45 +02:00
vector < expr_t > arguments_subst ;
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
2010-02-22 17:33:38 +01:00
arguments_subst . push_back ( ( * it ) - > substituteExoLag ( subst_table , neweqs ) ) ;
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
2010-09-16 19:18:45 +02:00
vector < expr_t > arguments_subst ;
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
2010-02-22 17:33:38 +01:00
arguments_subst . push_back ( ( * it ) - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ) ;
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
ExternalFunctionNode : : buildSimilarExternalFunctionNode ( vector < expr_t > & alt_args , DataTree & alt_datatree ) const
2010-02-22 17:33:38 +01:00
{
return alt_datatree . AddExternalFunction ( symb_id , alt_args ) ;
}
2010-03-04 16:40:07 +01:00
bool
2010-09-16 19:00:48 +02:00
ExternalFunctionNode : : alreadyWrittenAsTefTerm ( int the_symb_id , deriv_node_temp_terms_t & tef_terms ) const
2010-03-04 16:40:07 +01:00
{
2010-09-16 19:00:48 +02:00
deriv_node_temp_terms_t : : const_iterator it = tef_terms . find ( make_pair ( the_symb_id , arguments ) ) ;
2010-03-04 16:40:07 +01:00
if ( it ! = tef_terms . end ( ) )
return true ;
return false ;
}
int
2010-09-16 19:00:48 +02:00
ExternalFunctionNode : : getIndxInTefTerms ( int the_symb_id , deriv_node_temp_terms_t & tef_terms ) const throw ( UnknownFunctionNameAndArgs )
2010-03-04 16:40:07 +01:00
{
2010-09-16 19:00:48 +02:00
deriv_node_temp_terms_t : : const_iterator it = tef_terms . find ( make_pair ( the_symb_id , arguments ) ) ;
2010-03-04 16:40:07 +01:00
if ( it ! = tef_terms . end ( ) )
return it - > second ;
throw UnknownFunctionNameAndArgs ( ) ;
}
2010-04-16 16:54:55 +02:00
bool
ExternalFunctionNode : : isNumConstNodeEqualTo ( double value ) const
{
return false ;
}
bool
ExternalFunctionNode : : isVariableNodeEqualTo ( SymbolType type_arg , int variable_id , int lag_arg ) const
{
return false ;
}
2010-10-15 19:05:16 +02:00
expr_t
ExternalFunctionNode : : replaceTrendVar ( ) const
{
vector < expr_t > arguments_subst ;
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
arguments_subst . push_back ( ( * it ) - > replaceTrendVar ( ) ) ;
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
expr_t
ExternalFunctionNode : : detrend ( int symb_id , expr_t trend ) const
{
vector < expr_t > arguments_subst ;
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
arguments_subst . push_back ( ( * it ) - > detrend ( symb_id , trend ) ) ;
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
expr_t
ExternalFunctionNode : : removeTrendLeadLag ( map < int , expr_t > trend_symbols_map ) const
{
vector < expr_t > arguments_subst ;
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
arguments_subst . push_back ( ( * it ) - > removeTrendLeadLag ( trend_symbols_map ) ) ;
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
2010-02-22 17:33:38 +01:00
FirstDerivExternalFunctionNode : : FirstDerivExternalFunctionNode ( DataTree & datatree_arg ,
int top_level_symb_id_arg ,
2010-09-16 19:18:45 +02:00
const vector < expr_t > & arguments_arg ,
2010-02-22 17:33:38 +01:00
int inputIndex_arg ) :
ExternalFunctionNode ( datatree_arg , top_level_symb_id_arg , arguments_arg ) ,
inputIndex ( inputIndex_arg )
{
2010-03-03 11:43:22 +01:00
// Add myself to the first derivative external function map
2011-02-04 16:25:38 +01:00
datatree . first_deriv_external_function_node_map [ make_pair ( make_pair ( arguments , inputIndex ) , symb_id ) ] = this ;
2010-02-22 17:33:38 +01:00
}
2010-03-04 16:40:07 +01:00
void
2010-09-16 19:18:45 +02:00
FirstDerivExternalFunctionNode : : computeTemporaryTerms ( map < expr_t , int > & reference_count ,
2010-09-16 19:00:48 +02:00
temporary_terms_t & temporary_terms ,
2010-03-04 16:40:07 +01:00
bool is_matlab ) const
{
temporary_terms . insert ( const_cast < FirstDerivExternalFunctionNode * > ( this ) ) ;
}
void
2010-09-16 19:18:45 +02:00
FirstDerivExternalFunctionNode : : computeTemporaryTerms ( map < expr_t , int > & reference_count ,
2010-09-16 19:00:48 +02:00
temporary_terms_t & temporary_terms ,
2010-09-16 19:18:45 +02:00
map < expr_t , pair < int , int > > & first_occurence ,
2010-03-04 16:40:07 +01:00
int Curr_block ,
2010-09-16 19:00:48 +02:00
vector < vector < temporary_terms_t > > & v_temporary_terms ,
2010-03-04 16:40:07 +01:00
int equation ) const
{
2010-12-10 11:50:27 +01:00
expr_t this2 = const_cast < FirstDerivExternalFunctionNode * > ( this ) ;
temporary_terms . insert ( this2 ) ;
first_occurence [ this2 ] = make_pair ( Curr_block , equation ) ;
v_temporary_terms [ Curr_block ] [ equation ] . insert ( this2 ) ;
2010-03-04 16:40:07 +01:00
}
2010-09-16 19:18:45 +02:00
expr_t
FirstDerivExternalFunctionNode : : composeDerivatives ( const vector < expr_t > & dargs )
2010-02-22 17:33:38 +01:00
{
2010-09-16 19:18:45 +02:00
vector < expr_t > dNodes ;
2011-02-04 16:25:38 +01:00
for ( int i = 0 ; i < ( int ) dargs . size ( ) ; i + + )
2010-02-22 17:33:38 +01:00
if ( dargs . at ( i ) ! = 0 )
dNodes . push_back ( datatree . AddTimes ( dargs . at ( i ) ,
datatree . AddSecondDerivExternalFunctionNode ( symb_id , arguments , inputIndex , i + 1 ) ) ) ;
2010-09-16 19:18:45 +02:00
expr_t theDeriv = datatree . Zero ;
for ( vector < expr_t > : : const_iterator it = dNodes . begin ( ) ; it ! = dNodes . end ( ) ; it + + )
2010-02-22 17:33:38 +01:00
theDeriv = datatree . AddPlus ( theDeriv , * it ) ;
return theDeriv ;
}
void
FirstDerivExternalFunctionNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
deriv_node_temp_terms_t & tef_terms ) const
2010-02-22 17:33:38 +01:00
{
2010-03-04 16:40:07 +01:00
assert ( output_type ! = oMatlabOutsideModel ) ;
// If current node is a temporary term
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < FirstDerivExternalFunctionNode * > ( this ) ) ;
2010-03-04 16:40:07 +01:00
if ( it ! = temporary_terms . end ( ) )
2010-02-22 17:33:38 +01:00
{
2010-03-04 16:40:07 +01:00
if ( output_type = = oMatlabDynamicModelSparse )
output < < " T " < < idx < < " (it_) " ;
2010-02-22 17:33:38 +01:00
else
2010-03-04 16:40:07 +01:00
output < < " T " < < idx ;
return ;
2010-02-22 17:33:38 +01:00
}
2010-03-04 16:40:07 +01:00
int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
assert ( first_deriv_symb_id ! = eExtFunSetButNoNameProvided ) ;
2010-10-05 18:48:15 +02:00
int tmpIndx = inputIndex ;
if ( IS_C ( output_type ) )
tmpIndx = tmpIndx - 1 ;
2010-03-04 16:40:07 +01:00
if ( first_deriv_symb_id = = symb_id )
2010-10-05 18:48:15 +02:00
output < < " TEFD_ " < < getIndxInTefTerms ( symb_id , tef_terms )
< < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < tmpIndx < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2010-03-04 16:40:07 +01:00
else if ( first_deriv_symb_id = = eExtFunNotSet )
2010-10-05 18:48:15 +02:00
{
if ( IS_C ( output_type ) )
output < < " * " ;
output < < " TEFD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex ;
}
2010-03-04 16:40:07 +01:00
else
output < < " TEFD_def_ " < < getIndxInTefTerms ( first_deriv_symb_id , tef_terms )
2010-10-05 18:48:15 +02:00
< < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < tmpIndx < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2010-03-04 16:40:07 +01:00
}
2010-12-10 11:50:27 +01:00
void
FirstDerivExternalFunctionNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
2011-02-04 16:25:38 +01:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
const map_idx_t & map_idx , bool dynamic , bool steady_dynamic ,
deriv_node_temp_terms_t & tef_terms ) const
2010-12-10 11:50:27 +01:00
{
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < FirstDerivExternalFunctionNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
{
if ( dynamic )
{
map_idx_t : : const_iterator ii = map_idx . find ( idx ) ;
FLDT_ fldt ( ii - > second ) ;
fldt . write ( CompileCode , instruction_number ) ;
}
else
{
map_idx_t : : const_iterator ii = map_idx . find ( idx ) ;
FLDST_ fldst ( ii - > second ) ;
fldst . write ( CompileCode , instruction_number ) ;
}
return ;
}
int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
assert ( first_deriv_symb_id ! = eExtFunSetButNoNameProvided ) ;
int tmpIndx = inputIndex ;
if ( ! lhs_rhs )
{
FLDTEFD_ fldtefd ( getIndxInTefTerms ( symb_id , tef_terms ) , tmpIndx ) ;
fldtefd . write ( CompileCode , instruction_number ) ;
}
else
{
FSTPTEFD_ fstptefd ( getIndxInTefTerms ( symb_id , tef_terms ) , tmpIndx ) ;
fstptefd . write ( CompileCode , instruction_number ) ;
}
}
2010-03-04 16:40:07 +01:00
void
FirstDerivExternalFunctionNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
deriv_node_temp_terms_t & tef_terms ) const
2010-03-04 16:40:07 +01:00
{
assert ( output_type ! = oMatlabOutsideModel ) ;
int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
assert ( first_deriv_symb_id ! = eExtFunSetButNoNameProvided ) ;
2010-10-05 18:48:15 +02:00
if ( first_deriv_symb_id = = symb_id | | alreadyWrittenAsTefTerm ( first_deriv_symb_id , tef_terms ) )
return ;
if ( IS_C ( output_type ) )
if ( first_deriv_symb_id = = eExtFunNotSet )
{
stringstream ending ;
ending < < " _tefd_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex ;
output < < " int nlhs " < < ending . str ( ) < < " = 1; " < < endl
< < " double *TEFD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex < < " ; " < < endl
< < " mxArray *plhs " < < ending . str ( ) < < " [nlhs " < < ending . str ( ) < < " ]; " < < endl
< < " int nrhs " < < ending . str ( ) < < " = 3; " < < endl
< < " mxArray *prhs " < < ending . str ( ) < < " [nrhs " < < ending . str ( ) < < " ]; " < < endl
< < " mwSize dims " < < ending . str ( ) < < " [2]; " < < endl ;
output < < " dims " < < ending . str ( ) < < " [0] = 1; " < < endl
< < " dims " < < ending . str ( ) < < " [1] = " < < arguments . size ( ) < < " ; " < < endl ;
output < < " prhs " < < ending . str ( ) < < " [0] = mxCreateString( \" " < < datatree . symbol_table . getName ( symb_id ) < < " \" ); " < < endl
< < " prhs " < < ending . str ( ) < < " [1] = mxCreateDoubleScalar( " < < inputIndex < < " ); " < < endl
< < " prhs " < < ending . str ( ) < < " [2] = mxCreateCellArray(2, dims " < < ending . str ( ) < < " ); " < < endl ;
int i = 0 ;
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ;
it ! = arguments . end ( ) ; it + + )
{
output < < " mxSetCell(prhs " < < ending . str ( ) < < " [2], "
< < i + + < < " , "
< < " mxCreateDoubleScalar( " ; // All external_function arguments are scalars
( * it ) - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
output < < " )); " < < endl ;
}
output < < " mexCallMATLAB( "
< < " nlhs " < < ending . str ( ) < < " , "
< < " plhs " < < ending . str ( ) < < " , "
< < " nrhs " < < ending . str ( ) < < " , "
< < " prhs " < < ending . str ( ) < < " , \" "
< < " jacob_element \" ); " < < endl ;
output < < " TEFD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex
< < " = mxGetPr(plhs " < < ending . str ( ) < < " [0]); " < < endl ;
}
else
{
tef_terms [ make_pair ( first_deriv_symb_id , arguments ) ] = ( int ) tef_terms . size ( ) ;
int indx = getIndxInTefTerms ( first_deriv_symb_id , tef_terms ) ;
stringstream ending ;
ending < < " _tefd_def_ " < < indx ;
output < < " int nlhs " < < ending . str ( ) < < " = 1; " < < endl
< < " double *TEFD_def_ " < < indx < < " ; " < < endl
< < " mxArray *plhs " < < ending . str ( ) < < " [nlhs " < < ending . str ( ) < < " ]; " < < endl
< < " int nrhs " < < ending . str ( ) < < " = " < < arguments . size ( ) < < " ; " < < endl ;
writePrhs ( output , output_type , temporary_terms , tef_terms , ending . str ( ) ) ;
output < < " mexCallMATLAB( "
< < " nlhs " < < ending . str ( ) < < " , "
< < " plhs " < < ending . str ( ) < < " , "
< < " nrhs " < < ending . str ( ) < < " , "
< < " prhs " < < ending . str ( ) < < " , \" "
< < datatree . symbol_table . getName ( first_deriv_symb_id ) < < " \" ); " < < endl ;
output < < " TEFD_def_ " < < indx < < " = mxGetPr(plhs " < < ending . str ( ) < < " [0]); " < < endl ;
}
else
2010-02-22 17:33:38 +01:00
{
2010-10-05 18:48:15 +02:00
if ( first_deriv_symb_id = = eExtFunNotSet )
2010-10-07 14:15:56 +02:00
output < < " TEFD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex < < " = jacob_element(' "
< < datatree . symbol_table . getName ( symb_id ) < < " ', " < < inputIndex < < " ,{ " ;
2010-03-04 16:40:07 +01:00
else
{
tef_terms [ make_pair ( first_deriv_symb_id , arguments ) ] = ( int ) tef_terms . size ( ) ;
output < < " TEFD_def_ " < < getIndxInTefTerms ( first_deriv_symb_id , tef_terms )
< < " = " < < datatree . symbol_table . getName ( first_deriv_symb_id ) < < " ( " ;
}
2010-02-22 17:33:38 +01:00
2010-03-04 16:40:07 +01:00
writeExternalFunctionArguments ( output , output_type , temporary_terms , tef_terms ) ;
2010-02-22 17:33:38 +01:00
2010-03-04 16:40:07 +01:00
if ( first_deriv_symb_id = = eExtFunNotSet )
output < < " } " ;
output < < " ); " < < endl ;
}
2010-02-22 17:33:38 +01:00
}
2010-12-10 11:50:27 +01:00
void
FirstDerivExternalFunctionNode : : compileExternalFunctionOutput ( ostream & CompileCode , unsigned int & instruction_number ,
2011-02-04 16:25:38 +01:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
const map_idx_t & map_idx , bool dynamic , bool steady_dynamic ,
deriv_node_temp_terms_t & tef_terms ) const
2010-12-10 11:50:27 +01:00
{
int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
assert ( first_deriv_symb_id ! = eExtFunSetButNoNameProvided ) ;
if ( first_deriv_symb_id = = symb_id | | alreadyWrittenAsTefTerm ( first_deriv_symb_id , tef_terms ) )
return ;
unsigned int nb_add_input_arguments = compileExternalFunctionArguments ( CompileCode , instruction_number , lhs_rhs , temporary_terms ,
2011-02-04 16:25:38 +01:00
map_idx , dynamic , steady_dynamic , tef_terms ) ;
2010-12-10 11:50:27 +01:00
if ( first_deriv_symb_id = = eExtFunNotSet )
{
unsigned int nb_input_arguments = 0 ;
unsigned int nb_output_arguments = 1 ;
unsigned int indx = getIndxInTefTerms ( symb_id , tef_terms ) ;
FCALL_ fcall ( nb_output_arguments , nb_input_arguments , " jacob_element " , indx ) ;
fcall . set_arg_func_name ( datatree . symbol_table . getName ( symb_id ) ) ;
fcall . set_row ( inputIndex ) ;
fcall . set_nb_add_input_arguments ( nb_add_input_arguments ) ;
fcall . set_function_type ( ExternalFunctionNumericalFirstDerivative ) ;
fcall . write ( CompileCode , instruction_number ) ;
FSTPTEFD_ fstptefd ( indx , inputIndex ) ;
fstptefd . write ( CompileCode , instruction_number ) ;
}
else
{
tef_terms [ make_pair ( first_deriv_symb_id , arguments ) ] = ( int ) tef_terms . size ( ) ;
int indx = getIndxInTefTerms ( symb_id , tef_terms ) ;
int second_deriv_symb_id = datatree . external_functions_table . getSecondDerivSymbID ( symb_id ) ;
assert ( second_deriv_symb_id ! = eExtFunSetButNoNameProvided ) ;
unsigned int nb_output_arguments = 1 ;
FCALL_ fcall ( nb_output_arguments , nb_add_input_arguments , datatree . symbol_table . getName ( first_deriv_symb_id ) , indx ) ;
fcall . set_function_type ( ExternalFunctionFirstDerivative ) ;
fcall . write ( CompileCode , instruction_number ) ;
2010-12-31 16:26:25 +01:00
FSTPTEFD_ fstptefd ( indx , inputIndex ) ;
fstptefd . write ( CompileCode , instruction_number ) ;
2010-12-10 11:50:27 +01:00
}
}
2010-02-22 17:33:38 +01:00
SecondDerivExternalFunctionNode : : SecondDerivExternalFunctionNode ( DataTree & datatree_arg ,
int top_level_symb_id_arg ,
2010-09-16 19:18:45 +02:00
const vector < expr_t > & arguments_arg ,
2010-02-22 17:33:38 +01:00
int inputIndex1_arg ,
int inputIndex2_arg ) :
ExternalFunctionNode ( datatree_arg , top_level_symb_id_arg , arguments_arg ) ,
inputIndex1 ( inputIndex1_arg ) ,
inputIndex2 ( inputIndex2_arg )
2009-09-30 17:10:31 +02:00
{
2010-03-03 11:43:22 +01:00
// Add myself to the second derivative external function map
2011-02-04 16:25:38 +01:00
datatree . second_deriv_external_function_node_map [ make_pair ( make_pair ( arguments , make_pair ( inputIndex1 , inputIndex2 ) ) , symb_id ) ] = this ;
2009-09-30 17:10:31 +02:00
}
2009-10-29 18:16:10 +01:00
2010-03-04 16:40:07 +01:00
void
2010-09-16 19:18:45 +02:00
SecondDerivExternalFunctionNode : : computeTemporaryTerms ( map < expr_t , int > & reference_count ,
2010-09-16 19:00:48 +02:00
temporary_terms_t & temporary_terms ,
2010-03-04 16:40:07 +01:00
bool is_matlab ) const
{
temporary_terms . insert ( const_cast < SecondDerivExternalFunctionNode * > ( this ) ) ;
}
void
2010-09-16 19:18:45 +02:00
SecondDerivExternalFunctionNode : : computeTemporaryTerms ( map < expr_t , int > & reference_count ,
2011-02-04 16:25:38 +01:00
temporary_terms_t & temporary_terms ,
map < expr_t , pair < int , int > > & first_occurence ,
int Curr_block ,
vector < vector < temporary_terms_t > > & v_temporary_terms ,
int equation ) const
2010-03-04 16:40:07 +01:00
{
2010-12-10 11:50:27 +01:00
expr_t this2 = const_cast < SecondDerivExternalFunctionNode * > ( this ) ;
temporary_terms . insert ( this2 ) ;
first_occurence [ this2 ] = make_pair ( Curr_block , equation ) ;
v_temporary_terms [ Curr_block ] [ equation ] . insert ( this2 ) ;
2010-03-04 16:40:07 +01:00
}
2010-09-16 19:18:45 +02:00
expr_t
2010-02-22 17:33:38 +01:00
SecondDerivExternalFunctionNode : : computeDerivative ( int deriv_id )
2009-10-29 18:16:10 +01:00
{
2010-02-22 17:33:38 +01:00
cerr < < " ERROR: SecondDerivExternalFunctionNode::computeDerivative(). Not implemented " < < endl ;
2009-10-29 18:16:10 +01:00
exit ( EXIT_FAILURE ) ;
}
2010-02-22 17:33:38 +01:00
void
SecondDerivExternalFunctionNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
deriv_node_temp_terms_t & tef_terms ) const
2010-02-22 17:33:38 +01:00
{
2010-03-04 16:40:07 +01:00
assert ( output_type ! = oMatlabOutsideModel ) ;
// If current node is a temporary term
2010-09-16 19:00:48 +02:00
temporary_terms_t : : const_iterator it = temporary_terms . find ( const_cast < SecondDerivExternalFunctionNode * > ( this ) ) ;
2010-03-04 16:40:07 +01:00
if ( it ! = temporary_terms . end ( ) )
2010-02-22 17:33:38 +01:00
{
2010-03-04 16:40:07 +01:00
if ( output_type = = oMatlabDynamicModelSparse )
output < < " T " < < idx < < " (it_) " ;
2010-02-22 17:33:38 +01:00
else
2010-03-04 16:40:07 +01:00
output < < " T " < < idx ;
return ;
2010-02-22 17:33:38 +01:00
}
2010-03-04 16:40:07 +01:00
int second_deriv_symb_id = datatree . external_functions_table . getSecondDerivSymbID ( symb_id ) ;
assert ( second_deriv_symb_id ! = eExtFunSetButNoNameProvided ) ;
2010-10-05 18:48:15 +02:00
int tmpIndex1 = inputIndex1 ;
int tmpIndex2 = inputIndex2 ;
if ( IS_C ( output_type ) )
{
tmpIndex1 = tmpIndex1 - 1 ;
tmpIndex2 = tmpIndex2 - 1 ;
}
int indx = getIndxInTefTerms ( symb_id , tef_terms ) ;
2010-03-04 16:40:07 +01:00
if ( second_deriv_symb_id = = symb_id )
2010-10-05 18:48:15 +02:00
if ( IS_C ( output_type ) )
output < < " TEFDD_ " < < indx
< < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < tmpIndex1 < < " * TEFDD_ " < < indx < < " _nrows + "
< < tmpIndex2 < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
else
output < < " TEFDD_ " < < getIndxInTefTerms ( symb_id , tef_terms )
< < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < tmpIndex1 < < " , " < < tmpIndex2 < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2010-03-04 16:40:07 +01:00
else if ( second_deriv_symb_id = = eExtFunNotSet )
2010-10-05 18:48:15 +02:00
{
if ( IS_C ( output_type ) )
output < < " * " ;
output < < " TEFDD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex1 < < " _ " < < inputIndex2 ;
}
2010-03-04 16:40:07 +01:00
else
2010-10-05 18:48:15 +02:00
if ( IS_C ( output_type ) )
output < < " TEFDD_def_ " < < getIndxInTefTerms ( second_deriv_symb_id , tef_terms )
< < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < tmpIndex1 < < " * PROBLEM_ " < < indx < < " _nrows "
< < tmpIndex2 < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
else
output < < " TEFDD_def_ " < < getIndxInTefTerms ( second_deriv_symb_id , tef_terms )
< < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < tmpIndex1 < < " , " < < tmpIndex2 < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2010-03-04 16:40:07 +01:00
}
void
SecondDerivExternalFunctionNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
deriv_node_temp_terms_t & tef_terms ) const
2010-03-04 16:40:07 +01:00
{
assert ( output_type ! = oMatlabOutsideModel ) ;
int second_deriv_symb_id = datatree . external_functions_table . getSecondDerivSymbID ( symb_id ) ;
assert ( second_deriv_symb_id ! = eExtFunSetButNoNameProvided ) ;
2011-02-04 16:25:38 +01:00
if ( alreadyWrittenAsTefTerm ( second_deriv_symb_id , tef_terms )
| | second_deriv_symb_id = = symb_id )
2010-10-05 18:48:15 +02:00
return ;
if ( IS_C ( output_type ) )
if ( second_deriv_symb_id = = eExtFunNotSet )
{
stringstream ending ;
ending < < " _tefdd_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex1 < < " _ " < < inputIndex2 ;
output < < " int nlhs " < < ending . str ( ) < < " = 1; " < < endl
< < " double *TEFDD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex1 < < " _ " < < inputIndex2 < < " ; " < < endl
< < " mxArray *plhs " < < ending . str ( ) < < " [nlhs " < < ending . str ( ) < < " ]; " < < endl
< < " int nrhs " < < ending . str ( ) < < " = 4; " < < endl
< < " mxArray *prhs " < < ending . str ( ) < < " [nrhs " < < ending . str ( ) < < " ]; " < < endl
< < " mwSize dims " < < ending . str ( ) < < " [2]; " < < endl ;
output < < " dims " < < ending . str ( ) < < " [0] = 1; " < < endl
< < " dims " < < ending . str ( ) < < " [1] = " < < arguments . size ( ) < < " ; " < < endl ;
output < < " prhs " < < ending . str ( ) < < " [0] = mxCreateString( \" " < < datatree . symbol_table . getName ( symb_id ) < < " \" ); " < < endl
< < " prhs " < < ending . str ( ) < < " [1] = mxCreateDoubleScalar( " < < inputIndex1 < < " ); " < < endl
< < " prhs " < < ending . str ( ) < < " [2] = mxCreateDoubleScalar( " < < inputIndex2 < < " ); " < < endl
< < " prhs " < < ending . str ( ) < < " [3] = mxCreateCellArray(2, dims " < < ending . str ( ) < < " ); " < < endl ;
int i = 0 ;
for ( vector < expr_t > : : const_iterator it = arguments . begin ( ) ;
it ! = arguments . end ( ) ; it + + )
{
output < < " mxSetCell(prhs " < < ending . str ( ) < < " [3], "
< < i + + < < " , "
< < " mxCreateDoubleScalar( " ; // All external_function arguments are scalars
( * it ) - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
output < < " )); " < < endl ;
}
output < < " mexCallMATLAB( "
< < " nlhs " < < ending . str ( ) < < " , "
< < " plhs " < < ending . str ( ) < < " , "
< < " nrhs " < < ending . str ( ) < < " , "
< < " prhs " < < ending . str ( ) < < " , \" "
< < " hess_element \" ); " < < endl ;
output < < " TEFDD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex1 < < " _ " < < inputIndex2
< < " = mxGetPr(plhs " < < ending . str ( ) < < " [0]); " < < endl ;
}
else
{
tef_terms [ make_pair ( second_deriv_symb_id , arguments ) ] = ( int ) tef_terms . size ( ) ;
int indx = getIndxInTefTerms ( second_deriv_symb_id , tef_terms ) ;
stringstream ending ;
ending < < " _tefdd_def_ " < < indx ;
output < < " int nlhs " < < ending . str ( ) < < " = 1; " < < endl
< < " double *TEFDD_def_ " < < indx < < " ; " < < endl
< < " mxArray *plhs " < < ending . str ( ) < < " [nlhs " < < ending . str ( ) < < " ]; " < < endl
< < " int nrhs " < < ending . str ( ) < < " = " < < arguments . size ( ) < < " ; " < < endl ;
writePrhs ( output , output_type , temporary_terms , tef_terms , ending . str ( ) ) ;
output < < " mexCallMATLAB( "
< < " nlhs " < < ending . str ( ) < < " , "
< < " plhs " < < ending . str ( ) < < " , "
< < " nrhs " < < ending . str ( ) < < " , "
< < " prhs " < < ending . str ( ) < < " , \" "
< < datatree . symbol_table . getName ( second_deriv_symb_id ) < < " \" ); " < < endl ;
output < < " TEFDD_def_ " < < indx < < " = mxGetPr(plhs " < < ending . str ( ) < < " [0]); " < < endl ;
}
else
2010-02-22 17:33:38 +01:00
{
2010-10-05 18:48:15 +02:00
if ( second_deriv_symb_id = = eExtFunNotSet )
2010-03-04 16:40:07 +01:00
output < < " TEFDD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex1 < < " _ " < < inputIndex2
2010-10-07 14:15:56 +02:00
< < " = hess_element(' " < < datatree . symbol_table . getName ( symb_id ) < < " ', "
2010-03-04 16:40:07 +01:00
< < inputIndex1 < < " , " < < inputIndex2 < < " ,{ " ;
else
{
tef_terms [ make_pair ( second_deriv_symb_id , arguments ) ] = ( int ) tef_terms . size ( ) ;
output < < " TEFDD_def_ " < < getIndxInTefTerms ( second_deriv_symb_id , tef_terms )
< < " = " < < datatree . symbol_table . getName ( second_deriv_symb_id ) < < " ( " ;
}
writeExternalFunctionArguments ( output , output_type , temporary_terms , tef_terms ) ;
2010-02-22 17:33:38 +01:00
2010-03-04 16:40:07 +01:00
if ( second_deriv_symb_id = = eExtFunNotSet )
output < < " } " ;
output < < " ); " < < endl ;
}
2010-02-22 17:33:38 +01:00
}