Merge branch 'temporary_terms_array'

issue#70
Sébastien Villemot 2018-06-04 11:40:49 +02:00
commit 28582c4a4b
19 changed files with 2442 additions and 1216 deletions

View File

@ -25,6 +25,7 @@ AM_INIT_AUTOMAKE([1.11 -Wall -Wno-portability foreign no-dist-gzip dist-xz tar-p
AC_PROG_CC
AC_PROG_CXX
AX_CXX_COMPILE_STDCXX_14
AC_CANONICAL_HOST
case ${host_os} in

View File

@ -21,6 +21,16 @@ Copyright: 2008 Thomas Porschberg <thomas@randspringer.de>
2009 Peter Adolphs
License: permissive-autoconf
Files: m4/ax_cxx_compile_stdcxx.m4
m4/ax_cxx_compile_stdcxx_14.m4
Copyright: 2008 Benjamin Kosnik <bkoz@redhat.com>
2012 Zack Weinberg <zackw@panix.com>
2013 Roy Stogner <roystgnr@ices.utexas.edu>
2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
2015 Paul Norman <penorman@mac.com>
2015 Moritz Klammler <moritz@klammler.eu>
License: permissive-autoconf
Files: m4/ax_latex_class.m4 m4/ax_tex_test.m4
Copyright: 2008 Boretti Mathieu <boretti@eig.unige.ch>
2009 Dynare Team

562
m4/ax_cxx_compile_stdcxx.m4 Normal file
View File

@ -0,0 +1,562 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
#
# DESCRIPTION
#
# Check for baseline language coverage in the compiler for the specified
# version of the C++ standard. If necessary, add switches to CXX and
# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard)
# or '14' (for the C++14 standard).
#
# The second argument, if specified, indicates whether you insist on an
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
# -std=c++11). If neither is specified, you get whatever works, with
# preference for an extended mode.
#
# The third argument, if specified 'mandatory' or if left unspecified,
# indicates that baseline support for the specified C++ standard is
# required and that the macro should error out if no mode with that
# support is found. If specified 'optional', then configuration proceeds
# regardless, after defining HAVE_CXX${VERSION} if and only if a
# supporting mode is found.
#
# LICENSE
#
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
# Copyright (c) 2015 Paul Norman <penorman@mac.com>
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 4
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
dnl (serial version number 13).
AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
m4_if([$1], [11], [],
[$1], [14], [],
[$1], [17], [m4_fatal([support for C++17 not yet implemented in AX_CXX_COMPILE_STDCXX])],
[m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
m4_if([$2], [], [],
[$2], [ext], [],
[$2], [noext], [],
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
[$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
[$3], [optional], [ax_cxx_compile_cxx$1_required=false],
[m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
AC_LANG_PUSH([C++])dnl
ac_success=no
AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
ax_cv_cxx_compile_cxx$1,
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
[ax_cv_cxx_compile_cxx$1=yes],
[ax_cv_cxx_compile_cxx$1=no])])
if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
ac_success=yes
fi
m4_if([$2], [noext], [], [dnl
if test x$ac_success = xno; then
for switch in -std=gnu++$1 -std=gnu++0x; do
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
$cachevar,
[ac_save_CXX="$CXX"
CXX="$CXX $switch"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXX="$ac_save_CXX"])
if eval test x\$$cachevar = xyes; then
CXX="$CXX $switch"
if test -n "$CXXCPP" ; then
CXXCPP="$CXXCPP $switch"
fi
ac_success=yes
break
fi
done
fi])
m4_if([$2], [ext], [], [dnl
if test x$ac_success = xno; then
dnl HP's aCC needs +std=c++11 according to:
dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
dnl Cray's crayCC needs "-h std=c++11"
for switch in -std=c++$1 -std=c++0x +std=c++$1 "-h std=c++$1"; do
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
$cachevar,
[ac_save_CXX="$CXX"
CXX="$CXX $switch"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXX="$ac_save_CXX"])
if eval test x\$$cachevar = xyes; then
CXX="$CXX $switch"
if test -n "$CXXCPP" ; then
CXXCPP="$CXXCPP $switch"
fi
ac_success=yes
break
fi
done
fi])
AC_LANG_POP([C++])
if test x$ax_cxx_compile_cxx$1_required = xtrue; then
if test x$ac_success = xno; then
AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
fi
fi
if test x$ac_success = xno; then
HAVE_CXX$1=0
AC_MSG_NOTICE([No compiler with C++$1 support was found])
else
HAVE_CXX$1=1
AC_DEFINE(HAVE_CXX$1,1,
[define if the compiler supports basic C++$1 syntax])
fi
AC_SUBST(HAVE_CXX$1)
])
dnl Test body for checking C++11 support
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
)
dnl Test body for checking C++14 support
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
)
dnl Tests for new features in C++11
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
// If the compiler admits that it is not ready for C++11, why torture it?
// Hopefully, this will speed up the test.
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus < 201103L
#error "This is not a C++11 compiler"
#else
namespace cxx11
{
namespace test_static_assert
{
template <typename T>
struct check
{
static_assert(sizeof(int) <= sizeof(T), "not big enough");
};
}
namespace test_final_override
{
struct Base
{
virtual void f() {}
};
struct Derived : public Base
{
virtual void f() override {}
};
}
namespace test_double_right_angle_brackets
{
template < typename T >
struct check {};
typedef check<void> single_type;
typedef check<check<void>> double_type;
typedef check<check<check<void>>> triple_type;
typedef check<check<check<check<void>>>> quadruple_type;
}
namespace test_decltype
{
int
f()
{
int a = 1;
decltype(a) b = 2;
return a + b;
}
}
namespace test_type_deduction
{
template < typename T1, typename T2 >
struct is_same
{
static const bool value = false;
};
template < typename T >
struct is_same<T, T>
{
static const bool value = true;
};
template < typename T1, typename T2 >
auto
add(T1 a1, T2 a2) -> decltype(a1 + a2)
{
return a1 + a2;
}
int
test(const int c, volatile int v)
{
static_assert(is_same<int, decltype(0)>::value == true, "");
static_assert(is_same<int, decltype(c)>::value == false, "");
static_assert(is_same<int, decltype(v)>::value == false, "");
auto ac = c;
auto av = v;
auto sumi = ac + av + 'x';
auto sumf = ac + av + 1.0;
static_assert(is_same<int, decltype(ac)>::value == true, "");
static_assert(is_same<int, decltype(av)>::value == true, "");
static_assert(is_same<int, decltype(sumi)>::value == true, "");
static_assert(is_same<int, decltype(sumf)>::value == false, "");
static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
return (sumf > 0.0) ? sumi : add(c, v);
}
}
namespace test_noexcept
{
int f() { return 0; }
int g() noexcept { return 0; }
static_assert(noexcept(f()) == false, "");
static_assert(noexcept(g()) == true, "");
}
namespace test_constexpr
{
template < typename CharT >
unsigned long constexpr
strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
{
return *s ? strlen_c_r(s + 1, acc + 1) : acc;
}
template < typename CharT >
unsigned long constexpr
strlen_c(const CharT *const s) noexcept
{
return strlen_c_r(s, 0UL);
}
static_assert(strlen_c("") == 0UL, "");
static_assert(strlen_c("1") == 1UL, "");
static_assert(strlen_c("example") == 7UL, "");
static_assert(strlen_c("another\0example") == 7UL, "");
}
namespace test_rvalue_references
{
template < int N >
struct answer
{
static constexpr int value = N;
};
answer<1> f(int&) { return answer<1>(); }
answer<2> f(const int&) { return answer<2>(); }
answer<3> f(int&&) { return answer<3>(); }
void
test()
{
int i = 0;
const int c = 0;
static_assert(decltype(f(i))::value == 1, "");
static_assert(decltype(f(c))::value == 2, "");
static_assert(decltype(f(0))::value == 3, "");
}
}
namespace test_uniform_initialization
{
struct test
{
static const int zero {};
static const int one {1};
};
static_assert(test::zero == 0, "");
static_assert(test::one == 1, "");
}
namespace test_lambdas
{
void
test1()
{
auto lambda1 = [](){};
auto lambda2 = lambda1;
lambda1();
lambda2();
}
int
test2()
{
auto a = [](int i, int j){ return i + j; }(1, 2);
auto b = []() -> int { return '0'; }();
auto c = [=](){ return a + b; }();
auto d = [&](){ return c; }();
auto e = [a, &b](int x) mutable {
const auto identity = [](int y){ return y; };
for (auto i = 0; i < a; ++i)
a += b--;
return x + identity(a + b);
}(0);
return a + b + c + d + e;
}
int
test3()
{
const auto nullary = [](){ return 0; };
const auto unary = [](int x){ return x; };
using nullary_t = decltype(nullary);
using unary_t = decltype(unary);
const auto higher1st = [](nullary_t f){ return f(); };
const auto higher2nd = [unary](nullary_t f1){
return [unary, f1](unary_t f2){ return f2(unary(f1())); };
};
return higher1st(nullary) + higher2nd(nullary)(unary);
}
}
namespace test_variadic_templates
{
template <int...>
struct sum;
template <int N0, int... N1toN>
struct sum<N0, N1toN...>
{
static constexpr auto value = N0 + sum<N1toN...>::value;
};
template <>
struct sum<>
{
static constexpr auto value = 0;
};
static_assert(sum<>::value == 0, "");
static_assert(sum<1>::value == 1, "");
static_assert(sum<23>::value == 23, "");
static_assert(sum<1, 2>::value == 3, "");
static_assert(sum<5, 5, 11>::value == 21, "");
static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
}
// http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
// Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
// because of this.
namespace test_template_alias_sfinae
{
struct foo {};
template<typename T>
using member = typename T::member_type;
template<typename T>
void func(...) {}
template<typename T>
void func(member<T>*) {}
void test();
void test() { func<foo>(0); }
}
} // namespace cxx11
#endif // __cplusplus >= 201103L
]])
dnl Tests for new features in C++14
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
// If the compiler admits that it is not ready for C++14, why torture it?
// Hopefully, this will speed up the test.
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus < 201402L
#error "This is not a C++14 compiler"
#else
namespace cxx14
{
namespace test_polymorphic_lambdas
{
int
test()
{
const auto lambda = [](auto&&... args){
const auto istiny = [](auto x){
return (sizeof(x) == 1UL) ? 1 : 0;
};
const int aretiny[] = { istiny(args)... };
return aretiny[0];
};
return lambda(1, 1L, 1.0f, '1');
}
}
namespace test_binary_literals
{
constexpr auto ivii = 0b0000000000101010;
static_assert(ivii == 42, "wrong value");
}
namespace test_generalized_constexpr
{
template < typename CharT >
constexpr unsigned long
strlen_c(const CharT *const s) noexcept
{
auto length = 0UL;
for (auto p = s; *p; ++p)
++length;
return length;
}
static_assert(strlen_c("") == 0UL, "");
static_assert(strlen_c("x") == 1UL, "");
static_assert(strlen_c("test") == 4UL, "");
static_assert(strlen_c("another\0test") == 7UL, "");
}
namespace test_lambda_init_capture
{
int
test()
{
auto x = 0;
const auto lambda1 = [a = x](int b){ return a + b; };
const auto lambda2 = [a = lambda1(x)](){ return a; };
return lambda2();
}
}
namespace test_digit_seperators
{
constexpr auto ten_million = 100'000'000;
static_assert(ten_million == 100000000, "");
}
namespace test_return_type_deduction
{
auto f(int& x) { return x; }
decltype(auto) g(int& x) { return x; }
template < typename T1, typename T2 >
struct is_same
{
static constexpr auto value = false;
};
template < typename T >
struct is_same<T, T>
{
static constexpr auto value = true;
};
int
test()
{
auto x = 0;
static_assert(is_same<int, decltype(f(x))>::value, "");
static_assert(is_same<int&, decltype(g(x))>::value, "");
return x;
}
}
} // namespace cxx14
#endif // __cplusplus >= 201402L
]])

View File

@ -0,0 +1,34 @@
# ============================================================================
# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_14.html
# ============================================================================
#
# SYNOPSIS
#
# AX_CXX_COMPILE_STDCXX_14([ext|noext], [mandatory|optional])
#
# DESCRIPTION
#
# Check for baseline language coverage in the compiler for the C++14
# standard; if necessary, add switches to CXX and CXXCPP to enable
# support.
#
# This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX
# macro with the version set to C++14. The two optional arguments are
# forwarded literally as the second and third argument respectively.
# Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for
# more information. If you want to use this macro, you also need to
# download the ax_cxx_compile_stdcxx.m4 file.
#
# LICENSE
#
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 4
AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX])
AC_DEFUN([AX_CXX_COMPILE_STDCXX_14], [AX_CXX_COMPILE_STDCXX([14], [$1], [$2])])

View File

@ -268,6 +268,33 @@ enum NodeTreeReference
eHessianParamsDeriv = 8
};
/*! Lists elements of the NodeTreeReference enum that come “before” the argument.
Used in AbstractExternalFunctionNode::computeTemporaryTerms */
inline auto
nodeTreeReferencesBefore(NodeTreeReference tr)
{
vector<NodeTreeReference> v;
// Should be same order as the one appearing in ModelTree::computeTemporaryTerms()
for (auto tr2 : { eResiduals, eFirstDeriv, eSecondDeriv, eThirdDeriv })
if (tr == tr2)
return v;
else
v.push_back(tr2);
v.clear();
// Should be same order as the one appearing in ModelTree::computeParamsDerivativesTemporaryTerms()
for (auto tr2 : { eResidualsParamsDeriv, eJacobianParamsDeriv, eResidualsParamsSecondDeriv,
eJacobianParamsSecondDeriv, eHessianParamsDeriv})
if (tr == tr2)
return v;
else
v.push_back(tr2);
cerr << "nodeTreeReferencesBelow: impossible case" << endl;
exit(EXIT_FAILURE);
}
struct Block_contain_type
{
int Equation, Variable, Own_Derivative;

View File

@ -966,7 +966,6 @@ RamseyConstraintsStatement::writeOutput(ostream &output, const string &basename,
void
RamseyConstraintsStatement::writeJsonOutput(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "{\"statementName\": \"ramsey_constraints\""
<< ", \"ramsey_model_constraints\": [" << endl;
for (RamseyConstraintsStatement::constraints_t::const_iterator it = constraints.begin(); it != constraints.end(); ++it)
@ -993,7 +992,7 @@ RamseyConstraintsStatement::writeJsonOutput(ostream &output) const
exit(1);
}
output << " ";
it->expression->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->expression->writeJsonOutput(output, {}, {});
output << "\"}" << endl;
}
output << "]" << endl;
@ -1570,7 +1569,6 @@ EstimatedParamsStatement::writeOutput(ostream &output, const string &basename, b
void
EstimatedParamsStatement::writeJsonOutput(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "{\"statementName\": \"estimated_params\", "
<< "\"params\": [";
for (vector<EstimationParams>::const_iterator it = estim_params_list.begin(); it != estim_params_list.end(); it++)
@ -1593,23 +1591,23 @@ EstimatedParamsStatement::writeJsonOutput(ostream &output) const
}
output << ", \"init_val\": \"";
it->init_val->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->init_val->writeJsonOutput(output, {}, {});
output << "\", \"lower_bound\": \"";
it->low_bound->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->low_bound->writeJsonOutput(output, {}, {});
output << "\", \"upper_bound\": \"";
it->up_bound->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->up_bound->writeJsonOutput(output, {}, {});
output << "\", \"prior_distribution\": "
<< it->prior
<< ", \"mean\": \"";
it->mean->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->mean->writeJsonOutput(output, {}, {});
output << "\", \"std\": \"";
it->std->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->std->writeJsonOutput(output, {}, {});
output << "\", \"p3\": \"";
it->p3->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->p3->writeJsonOutput(output, {}, {});
output << "\", \"p4\": \"";
it->p4->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->p4->writeJsonOutput(output, {}, {});
output << "\", \"jscale\": \"";
it->jscale->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->jscale->writeJsonOutput(output, {}, {});
output << "\"}" << endl;
}
output << "]"
@ -1692,7 +1690,6 @@ EstimatedParamsInitStatement::writeOutput(ostream &output, const string &basenam
void
EstimatedParamsInitStatement::writeJsonOutput(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "{\"statementName\": \"estimated_params_init\"";
if (use_calibration)
@ -1718,7 +1715,7 @@ EstimatedParamsInitStatement::writeJsonOutput(ostream &output) const
break;
}
output << ", \"init_val\": \"";
it->init_val->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->init_val->writeJsonOutput(output, {}, {});
output << "\"}";
}
output << "]"
@ -1814,7 +1811,6 @@ EstimatedParamsBoundsStatement::writeOutput(ostream &output, const string &basen
void
EstimatedParamsBoundsStatement::writeJsonOutput(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "{\"statementName\": \"estimated_params_bounds\", "
<< "\"params\": [";
@ -1836,9 +1832,9 @@ EstimatedParamsBoundsStatement::writeJsonOutput(ostream &output) const
break;
}
output << ", \"lower_bound\": ";
it->low_bound->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->low_bound->writeJsonOutput(output, {}, {});
output << ", \"upper_bound\": ";
it->up_bound->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->up_bound->writeJsonOutput(output, {}, {});
output << "}";
}
output << "]"
@ -1874,7 +1870,6 @@ ObservationTrendsStatement::writeOutput(ostream &output, const string &basename,
void
ObservationTrendsStatement::writeJsonOutput(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "{\"statementName\": \"observation_trends\", "
<< "\"trends\" : {";
bool printed = false;
@ -1886,7 +1881,7 @@ ObservationTrendsStatement::writeJsonOutput(ostream &output) const
if (printed)
output << ", ";
output << "\"" << it->first << "\": \"";
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->second->writeJsonOutput(output, {}, {});
output << "\"" << endl;
printed = true;
}
@ -1977,7 +1972,6 @@ OsrParamsBoundsStatement::writeOutput(ostream &output, const string &basename, b
void
OsrParamsBoundsStatement::writeJsonOutput(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "{\"statementName\": \"osr_params_bounds\""
<< ", \"bounds\": [";
for (vector<OsrParams>::const_iterator it = osr_params_list.begin();
@ -1987,9 +1981,9 @@ OsrParamsBoundsStatement::writeJsonOutput(ostream &output) const
output << ", ";
output << "{\"parameter\": \"" << it->name << "\","
<< "\"bounds\": [\"";
it->low_bound->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->low_bound->writeJsonOutput(output, {}, {});
output << "\", \"";
it->up_bound->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->up_bound->writeJsonOutput(output, {}, {});
output << "\"]"
<< "}";
}
@ -2105,7 +2099,6 @@ OptimWeightsStatement::writeOutput(ostream &output, const string &basename, bool
void
OptimWeightsStatement::writeJsonOutput(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "{\"statementName\": \"optim_weights\", "
<< "\"weights\": [";
for (var_weights_t::const_iterator it = var_weights.begin();
@ -2115,7 +2108,7 @@ OptimWeightsStatement::writeJsonOutput(ostream &output) const
output << ", ";
output << "{\"name\": \"" << it->first << "\""
<< ", \"value\": \"";
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->second->writeJsonOutput(output, {}, {});
output << "\"}";
}
@ -2127,7 +2120,7 @@ OptimWeightsStatement::writeJsonOutput(ostream &output) const
output << "{\"name1\": \"" << it->first.first << "\""
<< ", \"name2\": \"" << it->first.second << "\""
<< ", \"value\": \"";
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->second->writeJsonOutput(output, {}, {});
output << "\"}";
}
output << "]"
@ -3998,9 +3991,8 @@ BasicPriorStatement::writeJsonPriorOutput(ostream &output) const
writeJsonShape(output);
if (variance != NULL)
{
deriv_node_temp_terms_t tef_terms;
output << ", \"variance\": \"";
variance->writeJsonOutput(output, temporary_terms_t(), tef_terms);
variance->writeJsonOutput(output, {}, {});
output << "\"";
}
if (options_list.getNumberOfOptions())

File diff suppressed because it is too large Load Diff

View File

@ -109,6 +109,8 @@ private:
//! Writes the dynamic model equations and its derivatives
/*! \todo add third derivatives handling in C output */
void writeDynamicModel(ostream &DynamicOutput, bool use_dll, bool julia) const;
void writeDynamicModel(const string &dynamic_basename, bool use_dll, bool julia) const;
void writeDynamicModel(const string &dynamic_basename, ostream &DynamicOutput, bool use_dll, bool julia) const;
//! Writes the Block reordred structure of the model in M output
void writeModelEquationsOrdered_M(const string &dynamic_basename) const;
//! Writes the code of the Block reordred structure of the model in virtual machine bytecode
@ -161,9 +163,6 @@ private:
/*! Also computes max_{endo,exo}_{lead_lag}, and initializes dynJacobianColsNbr to the number of dynamic endos */
void computeDerivIDs();
//! Write chain rule derivative of a recursive equation w.r. to a variable
void writeChainRuleDerivative(ostream &output, int eq, int var, int lag, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const;
//! Collecte the derivatives w.r. to endogenous of the block, to endogenous of previouys blocks and to exogenous
void collect_block_first_order_derivatives();
@ -235,6 +234,17 @@ private:
//!Maximum lead and lag for each block on endogenous of the block, endogenous of the previous blocks, exogenous and deterministic exogenous
vector<pair<int, int> > endo_max_leadlag_block, other_endo_max_leadlag_block, exo_max_leadlag_block, exo_det_max_leadlag_block, max_leadlag_block;
void writeWrapperFunctions(const string &name, const string &ending) const;
void writeDynamicModelHelper(const string &name, const string &retvalname,
const string &name_tt, size_t ttlen,
const string &previous_tt_name,
const ostringstream &init_s,
const ostringstream &end_s,
const ostringstream &s, const ostringstream &s_tt) const;
//! Create a legacy *_dynamic.m file for Matlab/Octave not yet using the temporary terms array interface
void writeDynamicMatlabCompatLayer(const string &name) const;
public:
DynamicModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_argx);
//! Adds a variable node

View File

@ -101,6 +101,32 @@ ExprNode::cost(const map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
return 0;
}
bool
ExprNode::checkIfTemporaryTermThenWrite(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs) const
{
auto it = temporary_terms.find(const_cast<ExprNode *>(this));
if (it == temporary_terms.end())
return false;
if (output_type == oMatlabDynamicModelSparse)
output << "T" << idx << "(it_)";
else
if (output_type == oMatlabStaticModelSparse || IS_C(output_type))
output << "T" << idx;
else
{
auto it2 = temporary_terms_idxs.find(const_cast<ExprNode *>(this));
// It is the responsibility of the caller to ensure that all temporary terms have their index
assert(it2 != temporary_terms_idxs.end());
output << "T" << LEFT_ARRAY_SUBSCRIPT(output_type)
<< it2->second + ARRAY_SUBSCRIPT_OFFSET(output_type)
<< RIGHT_ARRAY_SUBSCRIPT(output_type);
}
return true;
}
void
ExprNode::collectVariables(SymbolType type, set<int> &result) const
{
@ -159,20 +185,19 @@ ExprNode::normalizeEquation(int var_endo, vector<pair<int, pair<expr_t, expr_t>
void
ExprNode::writeOutput(ostream &output) const
{
writeOutput(output, oMatlabOutsideModel, temporary_terms_t());
writeOutput(output, oMatlabOutsideModel, {}, {});
}
void
ExprNode::writeOutput(ostream &output, ExprNodeOutputType output_type) const
{
writeOutput(output, output_type, temporary_terms_t());
writeOutput(output, output_type, {}, {});
}
void
ExprNode::writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const
ExprNode::writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs) const
{
deriv_node_temp_terms_t tef_terms;
writeOutput(output, output_type, temporary_terms, tef_terms);
writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, {});
}
void
@ -180,13 +205,13 @@ ExprNode::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) const
{
deriv_node_temp_terms_t tef_terms;
compile(CompileCode, instruction_number, lhs_rhs, temporary_terms, map_idx, dynamic, steady_dynamic, tef_terms);
compile(CompileCode, instruction_number, lhs_rhs, temporary_terms, map_idx, dynamic, steady_dynamic, {});
}
void
ExprNode::writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs,
deriv_node_temp_terms_t &tef_terms) const
{
// Nothing to do
@ -337,22 +362,17 @@ NumConstNode::collectTemporary_terms(const temporary_terms_t &temporary_terms, t
void
NumConstNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms) const
const temporary_terms_idxs_t &temporary_terms_idxs,
const deriv_node_temp_terms_t &tef_terms) const
{
temporary_terms_t::const_iterator it = temporary_terms.find(const_cast<NumConstNode *>(this));
if (it != temporary_terms.end())
if (output_type == oMatlabDynamicModelSparse)
output << "T" << idx << "(it_)";
else
output << "T" << idx;
else
if (!checkIfTemporaryTermThenWrite(output, output_type, temporary_terms, temporary_terms_idxs))
output << datatree.num_constants.get(id);
}
void
NumConstNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms,
const deriv_node_temp_terms_t &tef_terms,
const bool isdynamic) const
{
output << datatree.num_constants.get(id);
@ -374,7 +394,7 @@ void
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
const deriv_node_temp_terms_t &tef_terms) const
{
FLDC_ fldc(datatree.num_constants.getDouble(id));
fldc.write(CompileCode, instruction_number);
@ -756,7 +776,7 @@ VariableNode::containsExternalFunction() const
void
VariableNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms,
const deriv_node_temp_terms_t &tef_terms,
const bool isdynamic) const
{
temporary_terms_t::const_iterator it = temporary_terms.find(const_cast<VariableNode *>(this));
@ -774,18 +794,11 @@ VariableNode::writeJsonOutput(ostream &output,
void
VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms) const
const temporary_terms_idxs_t &temporary_terms_idxs,
const deriv_node_temp_terms_t &tef_terms) const
{
// If node is a temporary term
temporary_terms_t::const_iterator it = temporary_terms.find(const_cast<VariableNode *>(this));
if (it != temporary_terms.end())
{
if (output_type == oMatlabDynamicModelSparse)
output << "T" << idx << "(it_)";
else
output << "T" << idx;
return;
}
if (checkIfTemporaryTermThenWrite(output, output_type, temporary_terms, temporary_terms_idxs))
return;
if (IS_LATEX(output_type))
{
@ -825,12 +838,12 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
|| output_type == oCDynamicSteadyStateOperator)
{
output << "(";
datatree.local_variables_table[symb_id]->writeOutput(output, output_type, temporary_terms, tef_terms);
datatree.local_variables_table[symb_id]->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ")";
}
else
/* We append underscores to avoid name clashes with "g1" or "oo_" (see
also ModelTree::writeModelLocalVariables) */
/* We append underscores to avoid name clashes with "g1" or "oo_".
But we probably never arrive here because MLV are temporary terms */
output << datatree.symbol_table.getName(symb_id) << "__";
break;
@ -1051,7 +1064,7 @@ void
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
const deriv_node_temp_terms_t &tef_terms) const
{
if (type == eModelLocalVariable || type == eModFileLocalVariable)
datatree.local_variables_table[symb_id]->compile(CompileCode, instruction_number, lhs_rhs, temporary_terms, map_idx, dynamic, steady_dynamic, tef_terms);
@ -2192,7 +2205,7 @@ UnaryOpNode::containsExternalFunction() const
void
UnaryOpNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms,
const deriv_node_temp_terms_t &tef_terms,
const bool isdynamic) const
{
temporary_terms_t::const_iterator it = temporary_terms.find(const_cast<UnaryOpNode *>(this));
@ -2346,18 +2359,11 @@ UnaryOpNode::writeJsonOutput(ostream &output,
void
UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms) const
const temporary_terms_idxs_t &temporary_terms_idxs,
const deriv_node_temp_terms_t &tef_terms) const
{
// If node is a temporary term
temporary_terms_t::const_iterator it = temporary_terms.find(const_cast<UnaryOpNode *>(this));
if (it != temporary_terms.end())
{
if (output_type == oMatlabDynamicModelSparse)
output << "T" << idx << "(it_)";
else
output << "T" << idx;
return;
}
if (checkIfTemporaryTermThenWrite(output, output_type, temporary_terms, temporary_terms_idxs))
return;
// Always put parenthesis around uminus nodes
if (op_code == oUminus)
@ -2455,7 +2461,7 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
break;
}
output << "(";
arg->writeOutput(output, new_output_type, temporary_terms, tef_terms);
arg->writeOutput(output, new_output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ")";
return;
case oSteadyStateParamDeriv:
@ -2528,7 +2534,7 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
}
// Write argument
arg->writeOutput(output, output_type, temporary_terms, tef_terms);
arg->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
if (close_parenthesis)
output << RIGHT_PAR(output_type);
@ -2541,9 +2547,10 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
void
UnaryOpNode::writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs,
deriv_node_temp_terms_t &tef_terms) const
{
arg->writeExternalFunctionOutput(output, output_type, temporary_terms, tef_terms);
arg->writeExternalFunctionOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
}
void
@ -2638,7 +2645,7 @@ void
UnaryOpNode::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
const deriv_node_temp_terms_t &tef_terms) const
{
temporary_terms_t::const_iterator it = temporary_terms.find(const_cast<UnaryOpNode *>(this));
if (it != temporary_terms.end())
@ -3917,7 +3924,7 @@ void
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
const deriv_node_temp_terms_t &tef_terms) const
{
// If current node is a temporary term
temporary_terms_t::const_iterator it = temporary_terms.find(const_cast<BinaryOpNode *>(this));
@ -3971,7 +3978,7 @@ BinaryOpNode::containsExternalFunction() const
void
BinaryOpNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms,
const deriv_node_temp_terms_t &tef_terms,
const bool isdynamic) const
{
// If current node is a temporary term
@ -4103,33 +4110,26 @@ BinaryOpNode::writeJsonOutput(ostream &output,
void
BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms) const
const temporary_terms_idxs_t &temporary_terms_idxs,
const deriv_node_temp_terms_t &tef_terms) const
{
// If current node is a temporary term
temporary_terms_t::const_iterator it = temporary_terms.find(const_cast<BinaryOpNode *>(this));
if (it != temporary_terms.end())
{
if (output_type == oMatlabDynamicModelSparse)
output << "T" << idx << "(it_)";
else
output << "T" << idx;
return;
}
if (checkIfTemporaryTermThenWrite(output, output_type, temporary_terms, temporary_terms_idxs))
return;
// Treat derivative of Power
if (op_code == oPowerDeriv)
{
if (IS_LATEX(output_type))
unpackPowerDeriv()->writeOutput(output, output_type, temporary_terms, tef_terms);
unpackPowerDeriv()->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
else
{
if (output_type == oJuliaStaticModel || output_type == oJuliaDynamicModel)
output << "get_power_deriv(";
else
output << "getPowerDeriv(";
arg1->writeOutput(output, output_type, temporary_terms, tef_terms);
arg1->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ",";
arg2->writeOutput(output, output_type, temporary_terms, tef_terms);
arg2->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << "," << powerDerivOrder << ")";
}
return;
@ -4152,9 +4152,9 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
default:
;
}
arg1->writeOutput(output, output_type, temporary_terms, tef_terms);
arg1->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ",";
arg2->writeOutput(output, output_type, temporary_terms, tef_terms);
arg2->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ")";
return;
}
@ -4178,7 +4178,7 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
}
// Write left argument
arg1->writeOutput(output, output_type, temporary_terms, tef_terms);
arg1->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
if (close_parenthesis)
output << RIGHT_PAR(output_type);
@ -4271,7 +4271,7 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
}
// Write right argument
arg2->writeOutput(output, output_type, temporary_terms, tef_terms);
arg2->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
if (IS_LATEX(output_type) && (op_code == oPower || op_code == oDivide))
output << "}";
@ -4283,10 +4283,11 @@ BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
void
BinaryOpNode::writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs,
deriv_node_temp_terms_t &tef_terms) const
{
arg1->writeExternalFunctionOutput(output, output_type, temporary_terms, tef_terms);
arg2->writeExternalFunctionOutput(output, output_type, temporary_terms, tef_terms);
arg1->writeExternalFunctionOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
arg2->writeExternalFunctionOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
}
void
@ -5385,7 +5386,7 @@ void
TrinaryOpNode::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
const deriv_node_temp_terms_t &tef_terms) const
{
// If current node is a temporary term
temporary_terms_t::const_iterator it = temporary_terms.find(const_cast<TrinaryOpNode *>(this));
@ -5437,7 +5438,7 @@ TrinaryOpNode::containsExternalFunction() const
void
TrinaryOpNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms,
const deriv_node_temp_terms_t &tef_terms,
const bool isdynamic) const
{
// If current node is a temporary term
@ -5469,15 +5470,11 @@ TrinaryOpNode::writeJsonOutput(ostream &output,
void
TrinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms) const
const temporary_terms_idxs_t &temporary_terms_idxs,
const deriv_node_temp_terms_t &tef_terms) const
{
// If current node is a temporary term
temporary_terms_t::const_iterator it = temporary_terms.find(const_cast<TrinaryOpNode *>(this));
if (it != temporary_terms.end())
{
output << "T" << idx;
return;
}
if (checkIfTemporaryTermThenWrite(output, output_type, temporary_terms, temporary_terms_idxs))
return;
switch (op_code)
{
@ -5486,21 +5483,21 @@ TrinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
{
// In C, there is no normcdf() primitive, so use erf()
output << "(0.5*(1+erf(((";
arg1->writeOutput(output, output_type, temporary_terms, tef_terms);
arg1->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ")-(";
arg2->writeOutput(output, output_type, temporary_terms, tef_terms);
arg2->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << "))/(";
arg3->writeOutput(output, output_type, temporary_terms, tef_terms);
arg3->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ")/M_SQRT2)))";
}
else
{
output << "normcdf(";
arg1->writeOutput(output, output_type, temporary_terms, tef_terms);
arg1->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ",";
arg2->writeOutput(output, output_type, temporary_terms, tef_terms);
arg2->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ",";
arg3->writeOutput(output, output_type, temporary_terms, tef_terms);
arg3->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ")";
}
break;
@ -5509,23 +5506,23 @@ TrinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
{
//(1/(v3*sqrt(2*M_PI)*exp(pow((v1-v2)/v3,2)/2)))
output << "(1/(";
arg3->writeOutput(output, output_type, temporary_terms, tef_terms);
arg3->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << "*sqrt(2*M_PI)*exp(pow((";
arg1->writeOutput(output, output_type, temporary_terms, tef_terms);
arg1->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << "-";
arg2->writeOutput(output, output_type, temporary_terms, tef_terms);
arg2->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ")/";
arg3->writeOutput(output, output_type, temporary_terms, tef_terms);
arg3->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ",2)/2)))";
}
else
{
output << "normpdf(";
arg1->writeOutput(output, output_type, temporary_terms, tef_terms);
arg1->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ",";
arg2->writeOutput(output, output_type, temporary_terms, tef_terms);
arg2->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ",";
arg3->writeOutput(output, output_type, temporary_terms, tef_terms);
arg3->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ")";
}
break;
@ -5535,11 +5532,12 @@ TrinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
void
TrinaryOpNode::writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs,
deriv_node_temp_terms_t &tef_terms) const
{
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);
arg1->writeExternalFunctionOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
arg2->writeExternalFunctionOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
arg3->writeExternalFunctionOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
}
void
@ -6027,7 +6025,7 @@ unsigned int
AbstractExternalFunctionNode::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
const deriv_node_temp_terms_t &tef_terms) const
{
for (vector<expr_t>::const_iterator it = arguments.begin();
it != arguments.end(); it++)
@ -6301,7 +6299,7 @@ AbstractExternalFunctionNode::differentiateForwardVars(const vector<string> &sub
}
bool
AbstractExternalFunctionNode::alreadyWrittenAsTefTerm(int the_symb_id, deriv_node_temp_terms_t &tef_terms) const
AbstractExternalFunctionNode::alreadyWrittenAsTefTerm(int the_symb_id, const deriv_node_temp_terms_t &tef_terms) const
{
deriv_node_temp_terms_t::const_iterator it = tef_terms.find(make_pair(the_symb_id, arguments));
if (it != tef_terms.end())
@ -6310,7 +6308,7 @@ AbstractExternalFunctionNode::alreadyWrittenAsTefTerm(int the_symb_id, deriv_nod
}
int
AbstractExternalFunctionNode::getIndxInTefTerms(int the_symb_id, deriv_node_temp_terms_t &tef_terms) const throw (UnknownFunctionNameAndArgs)
AbstractExternalFunctionNode::getIndxInTefTerms(int the_symb_id, const deriv_node_temp_terms_t &tef_terms) const throw (UnknownFunctionNameAndArgs)
{
deriv_node_temp_terms_t::const_iterator it = tef_terms.find(make_pair(the_symb_id, arguments));
if (it != tef_terms.end())
@ -6318,6 +6316,36 @@ AbstractExternalFunctionNode::getIndxInTefTerms(int the_symb_id, deriv_node_temp
throw UnknownFunctionNameAndArgs();
}
void
AbstractExternalFunctionNode::computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference> > &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) const
{
/* All external function nodes are declared as temporary terms.
Given that temporary terms are separated in several functions (residuals,
jacobian, ), we must make sure that all temporary terms derived from a
given external function call are assigned just after that call.
As a consequence, we need to promote some terms to a previous level (in
the sense that residuals come before jacobian), if a temporary term
corresponding to the same external function call is present in that
previous level. */
for (auto tr2 : nodeTreeReferencesBefore(tr))
{
auto it = find_if(temp_terms_map[tr2].cbegin(), temp_terms_map[tr2].cend(),
sameTefTermPredicate());
if (it != temp_terms_map[tr2].cend())
{
temp_terms_map[tr2].insert(const_cast<AbstractExternalFunctionNode *>(this));
return;
}
}
temp_terms_map[tr].insert(const_cast<AbstractExternalFunctionNode *>(this));
}
bool
AbstractExternalFunctionNode::isNumConstNodeEqualTo(double value) const
{
@ -6451,7 +6479,8 @@ AbstractExternalFunctionNode::normalizeEquation(int var_endo, vector<pair<int, p
void
AbstractExternalFunctionNode::writeExternalFunctionArguments(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms) const
const temporary_terms_idxs_t &temporary_terms_idxs,
const deriv_node_temp_terms_t &tef_terms) const
{
for (vector<expr_t>::const_iterator it = arguments.begin();
it != arguments.end(); it++)
@ -6459,14 +6488,14 @@ AbstractExternalFunctionNode::writeExternalFunctionArguments(ostream &output, Ex
if (it != arguments.begin())
output << ",";
(*it)->writeOutput(output, output_type, temporary_terms, tef_terms);
(*it)->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
}
}
void
AbstractExternalFunctionNode::writeJsonExternalFunctionArguments(ostream &output,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms,
const deriv_node_temp_terms_t &tef_terms,
const bool isdynamic) const
{
for (vector<expr_t>::const_iterator it = arguments.begin();
@ -6482,7 +6511,8 @@ AbstractExternalFunctionNode::writeJsonExternalFunctionArguments(ostream &output
void
AbstractExternalFunctionNode::writePrhs(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms, const string &ending) const
const temporary_terms_idxs_t &temporary_terms_idxs,
const deriv_node_temp_terms_t &tef_terms, const string &ending) const
{
output << "mxArray *prhs"<< ending << "[nrhs"<< ending << "];" << endl;
int i = 0;
@ -6490,7 +6520,7 @@ AbstractExternalFunctionNode::writePrhs(ostream &output, ExprNodeOutputType outp
it != arguments.end(); it++)
{
output << "prhs" << ending << "[" << i++ << "] = mxCreateDoubleScalar("; // All external_function arguments are scalars
(*it)->writeOutput(output, output_type, temporary_terms, tef_terms);
(*it)->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ");" << endl;
}
}
@ -6533,14 +6563,6 @@ ExternalFunctionNode::composeDerivatives(const vector<expr_t> &dargs)
return theDeriv;
}
void
ExternalFunctionNode::computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference> > &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) const
{
temp_terms_map[tr].insert(const_cast<ExternalFunctionNode *>(this));
}
void
ExternalFunctionNode::computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
@ -6559,7 +6581,7 @@ 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
const 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())
@ -6645,7 +6667,7 @@ ExternalFunctionNode::compileExternalFunctionOutput(ostream &CompileCode, unsign
void
ExternalFunctionNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms,
const deriv_node_temp_terms_t &tef_terms,
const bool isdynamic) const
{
temporary_terms_t::const_iterator it = temporary_terms.find(const_cast<ExternalFunctionNode *>(this));
@ -6663,7 +6685,8 @@ ExternalFunctionNode::writeJsonOutput(ostream &output,
void
ExternalFunctionNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms) const
const temporary_terms_idxs_t &temporary_terms_idxs,
const deriv_node_temp_terms_t &tef_terms) const
{
if (output_type == oMatlabOutsideModel || output_type == oSteadyStateFile
|| output_type == oCSteadyStateFile || output_type == oJuliaSteadyStateFile
@ -6672,20 +6695,13 @@ ExternalFunctionNode::writeOutput(ostream &output, ExprNodeOutputType output_typ
string name = IS_LATEX(output_type) ? datatree.symbol_table.getTeXName(symb_id)
: datatree.symbol_table.getName(symb_id);
output << name << "(";
writeExternalFunctionArguments(output, output_type, temporary_terms, tef_terms);
writeExternalFunctionArguments(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ")";
return;
}
temporary_terms_t::const_iterator it = temporary_terms.find(const_cast<ExternalFunctionNode *>(this));
if (it != temporary_terms.end())
{
if (output_type == oMatlabDynamicModelSparse)
output << "T" << idx << "(it_)";
else
output << "T" << idx;
return;
}
if (checkIfTemporaryTermThenWrite(output, output_type, temporary_terms, temporary_terms_idxs))
return;
if (IS_C(output_type))
output << "*";
@ -6695,6 +6711,7 @@ ExternalFunctionNode::writeOutput(ostream &output, ExprNodeOutputType output_typ
void
ExternalFunctionNode::writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs,
deriv_node_temp_terms_t &tef_terms) const
{
int first_deriv_symb_id = datatree.external_functions_table.getFirstDerivSymbID(symb_id);
@ -6702,7 +6719,7 @@ ExternalFunctionNode::writeExternalFunctionOutput(ostream &output, ExprNodeOutpu
for (vector<expr_t>::const_iterator it = arguments.begin();
it != arguments.end(); it++)
(*it)->writeExternalFunctionOutput(output, output_type, temporary_terms, tef_terms);
(*it)->writeExternalFunctionOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
if (!alreadyWrittenAsTefTerm(symb_id, tef_terms))
{
@ -6731,7 +6748,7 @@ ExternalFunctionNode::writeExternalFunctionOutput(ostream &output, ExprNodeOutpu
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());
writePrhs(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms, ending.str());
output << "mexCallMATLAB("
<< "nlhs" << ending.str() << ", "
@ -6763,7 +6780,7 @@ ExternalFunctionNode::writeExternalFunctionOutput(ostream &output, ExprNodeOutpu
output << "TEF_" << indx << " = ";
output << datatree.symbol_table.getName(symb_id) << "(";
writeExternalFunctionArguments(output, output_type, temporary_terms, tef_terms);
writeExternalFunctionArguments(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ");" << endl;
}
}
@ -6841,6 +6858,15 @@ ExternalFunctionNode::buildSimilarExternalFunctionNode(vector<expr_t> &alt_args,
return alt_datatree.AddExternalFunction(symb_id, alt_args);
}
function<bool (expr_t)>
ExternalFunctionNode::sameTefTermPredicate() const
{
return [this](expr_t e) {
auto e2 = dynamic_cast<ExternalFunctionNode *>(e);
return (e2 != nullptr && e2->symb_id == symb_id);
};
}
FirstDerivExternalFunctionNode::FirstDerivExternalFunctionNode(DataTree &datatree_arg,
int top_level_symb_id_arg,
const vector<expr_t> &arguments_arg,
@ -6852,14 +6878,6 @@ FirstDerivExternalFunctionNode::FirstDerivExternalFunctionNode(DataTree &datatre
datatree.first_deriv_external_function_node_map[make_pair(make_pair(arguments, inputIndex), symb_id)] = this;
}
void
FirstDerivExternalFunctionNode::computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference> > &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) const
{
temp_terms_map[tr].insert(const_cast<FirstDerivExternalFunctionNode *>(this));
}
void
FirstDerivExternalFunctionNode::computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
@ -6890,7 +6908,7 @@ FirstDerivExternalFunctionNode::composeDerivatives(const vector<expr_t> &dargs)
void
FirstDerivExternalFunctionNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms,
const deriv_node_temp_terms_t &tef_terms,
const bool isdynamic) const
{
// If current node is a temporary term
@ -6919,7 +6937,8 @@ FirstDerivExternalFunctionNode::writeJsonOutput(ostream &output,
void
FirstDerivExternalFunctionNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms) const
const temporary_terms_idxs_t &temporary_terms_idxs,
const deriv_node_temp_terms_t &tef_terms) const
{
assert(output_type != oMatlabOutsideModel);
@ -6927,21 +6946,13 @@ FirstDerivExternalFunctionNode::writeOutput(ostream &output, ExprNodeOutputType
{
output << "\\frac{\\partial " << datatree.symbol_table.getTeXName(symb_id)
<< "}{\\partial " << inputIndex << "}(";
writeExternalFunctionArguments(output, output_type, temporary_terms, tef_terms);
writeExternalFunctionArguments(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ")";
return;
}
// If current node is a temporary term
temporary_terms_t::const_iterator it = temporary_terms.find(const_cast<FirstDerivExternalFunctionNode *>(this));
if (it != temporary_terms.end())
{
if (output_type == oMatlabDynamicModelSparse)
output << "T" << idx << "(it_)";
else
output << "T" << idx;
return;
}
if (checkIfTemporaryTermThenWrite(output, output_type, temporary_terms, temporary_terms_idxs))
return;
const int first_deriv_symb_id = datatree.external_functions_table.getFirstDerivSymbID(symb_id);
assert(first_deriv_symb_id != eExtFunSetButNoNameProvided);
@ -6966,7 +6977,7 @@ void
FirstDerivExternalFunctionNode::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
const deriv_node_temp_terms_t &tef_terms) const
{
temporary_terms_t::const_iterator it = temporary_terms.find(const_cast<FirstDerivExternalFunctionNode *>(this));
if (it != temporary_terms.end())
@ -7003,6 +7014,7 @@ FirstDerivExternalFunctionNode::compile(ostream &CompileCode, unsigned int &inst
void
FirstDerivExternalFunctionNode::writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs,
deriv_node_temp_terms_t &tef_terms) const
{
assert(output_type != oMatlabOutsideModel);
@ -7014,7 +7026,7 @@ FirstDerivExternalFunctionNode::writeExternalFunctionOutput(ostream &output, Exp
if (first_deriv_symb_id == symb_id)
{
expr_t parent = datatree.AddExternalFunction(symb_id, arguments);
parent->writeExternalFunctionOutput(output, output_type, temporary_terms,
parent->writeExternalFunctionOutput(output, output_type, temporary_terms, temporary_terms_idxs,
tef_terms);
return;
}
@ -7048,7 +7060,7 @@ FirstDerivExternalFunctionNode::writeExternalFunctionOutput(ostream &output, Exp
output << "mxSetCell(prhs" << ending.str() << "[2], "
<< i++ << ", "
<< "mxCreateDoubleScalar("; // All external_function arguments are scalars
(*it)->writeOutput(output, output_type, temporary_terms, tef_terms);
(*it)->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << "));" << endl;
}
@ -7072,7 +7084,7 @@ FirstDerivExternalFunctionNode::writeExternalFunctionOutput(ostream &output, Exp
<< "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());
writePrhs(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms, ending.str());
output << "mexCallMATLAB("
<< "nlhs" << ending.str() << ", "
@ -7095,7 +7107,7 @@ FirstDerivExternalFunctionNode::writeExternalFunctionOutput(ostream &output, Exp
<< " = " << datatree.symbol_table.getName(first_deriv_symb_id) << "(";
}
writeExternalFunctionArguments(output, output_type, temporary_terms, tef_terms);
writeExternalFunctionArguments(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
if (first_deriv_symb_id == eExtFunNotSet)
output << "}";
@ -7227,6 +7239,22 @@ FirstDerivExternalFunctionNode::computeXrefs(EquationInfo &ei) const
(*it)->computeXrefs(ei);
}
function<bool (expr_t)>
FirstDerivExternalFunctionNode::sameTefTermPredicate() const
{
int first_deriv_symb_id = datatree.external_functions_table.getFirstDerivSymbID(symb_id);
if (first_deriv_symb_id == symb_id)
return [this](expr_t e) {
auto e2 = dynamic_cast<ExternalFunctionNode *>(e);
return (e2 != nullptr && e2->symb_id == symb_id);
};
else
return [this](expr_t e) {
auto e2 = dynamic_cast<FirstDerivExternalFunctionNode *>(e);
return (e2 != nullptr && e2->symb_id == symb_id);
};
}
SecondDerivExternalFunctionNode::SecondDerivExternalFunctionNode(DataTree &datatree_arg,
int top_level_symb_id_arg,
const vector<expr_t> &arguments_arg,
@ -7240,14 +7268,6 @@ SecondDerivExternalFunctionNode::SecondDerivExternalFunctionNode(DataTree &datat
datatree.second_deriv_external_function_node_map[make_pair(make_pair(arguments, make_pair(inputIndex1, inputIndex2)), symb_id)] = this;
}
void
SecondDerivExternalFunctionNode::computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference> > &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) const
{
temp_terms_map[tr].insert(const_cast<SecondDerivExternalFunctionNode *>(this));
}
void
SecondDerivExternalFunctionNode::computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
@ -7273,7 +7293,7 @@ SecondDerivExternalFunctionNode::composeDerivatives(const vector<expr_t> &dargs)
void
SecondDerivExternalFunctionNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms,
const deriv_node_temp_terms_t &tef_terms,
const bool isdynamic) const
{
// If current node is a temporary term
@ -7303,7 +7323,8 @@ SecondDerivExternalFunctionNode::writeJsonOutput(ostream &output,
void
SecondDerivExternalFunctionNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms) const
const temporary_terms_idxs_t &temporary_terms_idxs,
const deriv_node_temp_terms_t &tef_terms) const
{
assert(output_type != oMatlabOutsideModel);
@ -7311,21 +7332,13 @@ SecondDerivExternalFunctionNode::writeOutput(ostream &output, ExprNodeOutputType
{
output << "\\frac{\\partial^2 " << datatree.symbol_table.getTeXName(symb_id)
<< "}{\\partial " << inputIndex1 << "\\partial " << inputIndex2 << "}(";
writeExternalFunctionArguments(output, output_type, temporary_terms, tef_terms);
writeExternalFunctionArguments(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << ")";
return;
}
// If current node is a temporary term
temporary_terms_t::const_iterator it = temporary_terms.find(const_cast<SecondDerivExternalFunctionNode *>(this));
if (it != temporary_terms.end())
{
if (output_type == oMatlabDynamicModelSparse)
output << "T" << idx << "(it_)";
else
output << "T" << idx;
return;
}
if (checkIfTemporaryTermThenWrite(output, output_type, temporary_terms, temporary_terms_idxs))
return;
const int second_deriv_symb_id = datatree.external_functions_table.getSecondDerivSymbID(symb_id);
assert(second_deriv_symb_id != eExtFunSetButNoNameProvided);
@ -7361,6 +7374,7 @@ SecondDerivExternalFunctionNode::writeOutput(ostream &output, ExprNodeOutputType
void
SecondDerivExternalFunctionNode::writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs,
deriv_node_temp_terms_t &tef_terms) const
{
assert(output_type != oMatlabOutsideModel);
@ -7372,7 +7386,7 @@ SecondDerivExternalFunctionNode::writeExternalFunctionOutput(ostream &output, Ex
if (second_deriv_symb_id == symb_id)
{
expr_t parent = datatree.AddExternalFunction(symb_id, arguments);
parent->writeExternalFunctionOutput(output, output_type, temporary_terms,
parent->writeExternalFunctionOutput(output, output_type, temporary_terms, temporary_terms_idxs,
tef_terms);
return;
}
@ -7407,7 +7421,7 @@ SecondDerivExternalFunctionNode::writeExternalFunctionOutput(ostream &output, Ex
output << "mxSetCell(prhs" << ending.str() << "[3], "
<< i++ << ", "
<< "mxCreateDoubleScalar("; // All external_function arguments are scalars
(*it)->writeOutput(output, output_type, temporary_terms, tef_terms);
(*it)->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
output << "));" << endl;
}
@ -7432,7 +7446,7 @@ SecondDerivExternalFunctionNode::writeExternalFunctionOutput(ostream &output, Ex
<< "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());
writePrhs(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms, ending.str());
output << "mexCallMATLAB("
<< "nlhs" << ending.str() << ", "
@ -7456,7 +7470,7 @@ SecondDerivExternalFunctionNode::writeExternalFunctionOutput(ostream &output, Ex
<< " = " << datatree.symbol_table.getName(second_deriv_symb_id) << "(";
}
writeExternalFunctionArguments(output, output_type, temporary_terms, tef_terms);
writeExternalFunctionArguments(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
if (second_deriv_symb_id == eExtFunNotSet)
output << "}";
@ -7548,7 +7562,7 @@ void
SecondDerivExternalFunctionNode::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
const deriv_node_temp_terms_t &tef_terms) const
{
cerr << "SecondDerivExternalFunctionNode::compile: not implemented." << endl;
exit(EXIT_FAILURE);
@ -7564,6 +7578,22 @@ SecondDerivExternalFunctionNode::compileExternalFunctionOutput(ostream &CompileC
exit(EXIT_FAILURE);
}
function<bool (expr_t)>
SecondDerivExternalFunctionNode::sameTefTermPredicate() const
{
int second_deriv_symb_id = datatree.external_functions_table.getSecondDerivSymbID(symb_id);
if (second_deriv_symb_id == symb_id)
return [this](expr_t e) {
auto e2 = dynamic_cast<ExternalFunctionNode *>(e);
return (e2 != nullptr && e2->symb_id == symb_id);
};
else
return [this](expr_t e) {
auto e2 = dynamic_cast<SecondDerivExternalFunctionNode *>(e);
return (e2 != nullptr && e2->symb_id == symb_id);
};
}
VarExpectationNode::VarExpectationNode(DataTree &datatree_arg,
int symb_id_arg,
int forecast_horizon_arg,
@ -7614,7 +7644,8 @@ VarExpectationNode::cloneDynamic(DataTree &dynamic_datatree) const
void
VarExpectationNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms) const
const temporary_terms_idxs_t &temporary_terms_idxs,
const deriv_node_temp_terms_t &tef_terms) const
{
assert(output_type != oMatlabOutsideModel);
@ -7626,16 +7657,8 @@ VarExpectationNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
return;
}
// If current node is a temporary term
temporary_terms_t::const_iterator it = temporary_terms.find(const_cast<VarExpectationNode *>(this));
if (it != temporary_terms.end())
{
if (output_type == oMatlabDynamicModelSparse)
output << "T" << idx << "(it_)";
else
output << "T" << idx;
return;
}
if (checkIfTemporaryTermThenWrite(output, output_type, temporary_terms, temporary_terms_idxs))
return;
output << "dynamic_var_forecast_" << model_name << "_" << forecast_horizon << "(" << yidx + 1 << ")";
}
@ -7775,7 +7798,7 @@ void
VarExpectationNode::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
const deriv_node_temp_terms_t &tef_terms) const
{
cerr << "VarExpectationNode::compile not implemented." << endl;
exit(EXIT_FAILURE);
@ -7954,7 +7977,7 @@ VarExpectationNode::substituteStaticAuxiliaryVariable() const
void
VarExpectationNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms,
const deriv_node_temp_terms_t &tef_terms,
const bool isdynamic) const
{
output << "var_expectation("
@ -8010,7 +8033,8 @@ PacExpectationNode::cloneDynamic(DataTree &dynamic_datatree) const
void
PacExpectationNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms) const
const temporary_terms_idxs_t &temporary_terms_idxs,
const deriv_node_temp_terms_t &tef_terms) const
{
assert(output_type != oMatlabOutsideModel);
@ -8215,7 +8239,7 @@ void
PacExpectationNode::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
const deriv_node_temp_terms_t &tef_terms) const
{
cerr << "PacExpectationNode::compile not implemented." << endl;
exit(EXIT_FAILURE);
@ -8378,7 +8402,7 @@ PacExpectationNode::substituteStaticAuxiliaryVariable() const
void
PacExpectationNode::writeJsonOutput(ostream &output,
const temporary_terms_t &temporary_terms,
deriv_node_temp_terms_t &tef_terms,
const deriv_node_temp_terms_t &tef_terms,
const bool isdynamic) const
{
output << "pac_expectation("

View File

@ -24,6 +24,7 @@
#include <map>
#include <vector>
#include <ostream>
#include <functional>
using namespace std;
@ -43,8 +44,11 @@ typedef class ExprNode *expr_t;
struct ExprNodeLess;
//! Type for set of temporary terms
/*! They are ordered by index number thanks to ExprNodeLess */
/*! The ExprNodeLess ordering is important for the temporary terms algorithm,
see the definition of ExprNodeLess */
typedef set<expr_t, ExprNodeLess> temporary_terms_t;
/*! Keeps track of array indices of temporary_terms for writing */
typedef map<expr_t, int> temporary_terms_idxs_t;
//! set of temporary terms used in a block
typedef set<int> temporary_terms_inuse_t;
@ -182,6 +186,12 @@ class ExprNode
set<pair<int, int> > exo_det;
};
//! If this node is a temporary term, writes its temporary term representation
/*! Returns true if node is a temporary term and has therefore been
written to output*/
bool checkIfTemporaryTermThenWrite(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs) const;
public:
ExprNode(DataTree &datatree_arg);
virtual
@ -217,9 +227,12 @@ class ExprNode
\param[in] output the output stream
\param[in] output_type the type of output (MATLAB, C, LaTeX...)
\param[in] temporary_terms the nodes that are marked as temporary terms
\param[in,out] tef_terms the set of already written external function nodes
\param[in] a map from temporary_terms to integers indexes (in the
MATLAB or Julia vector of temporary terms); can be empty
when writing C or MATLAB with block decomposition)
\param[in] tef_terms the set of already written external function nodes
*/
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const = 0;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const = 0;
//! returns true if the expr node contains an external function
virtual bool containsExternalFunction() const = 0;
@ -231,16 +244,17 @@ class ExprNode
void writeOutput(ostream &output, ExprNodeOutputType output_type) const;
//! Writes output of node, using a Txxx notation for nodes in temporary_terms
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const;
void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs) const;
//! Writes output of node in JSON syntax
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms, const bool isdynamic = true) const = 0;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic = true) const = 0;
virtual int precedenceJson(const temporary_terms_t &temporary_terms) const;
//! Writes the output for an external function, ensuring that the external function is called as few times as possible using temporary terms
virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs,
deriv_node_temp_terms_t &tef_terms) const;
//! Write the JSON output of an external function in a string vector
@ -318,7 +332,7 @@ class ExprNode
};
virtual double eval(const eval_context_t &eval_context) const throw (EvalException, EvalExternalFunctionException) = 0;
virtual void 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 = 0;
virtual void 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, const deriv_node_temp_terms_t &tef_terms) const = 0;
void 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) const;
//! Creates a static version of this node
/*!
@ -531,6 +545,9 @@ class ExprNode
};
//! Object used to compare two nodes (using their indexes)
/*! Note that in this ordering, a subexpression is always less than the
expression from which it is extracted. This property is used extensively in
the temporary terms computations. */
struct ExprNodeLess
{
bool
@ -556,14 +573,14 @@ public:
return id;
};
virtual void prepareForDerivation();
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
virtual bool containsExternalFunction() const;
virtual void collectVARLHSVariable(set<expr_t> &result) const;
virtual void collectDynamicVariables(SymbolType type_arg, set<pair<int, int> > &result) const;
virtual void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const;
virtual double eval(const eval_context_t &eval_context) const throw (EvalException, EvalExternalFunctionException);
virtual void 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;
virtual void 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, const deriv_node_temp_terms_t &tef_terms) const;
virtual expr_t toStatic(DataTree &static_datatree) const;
virtual void computeXrefs(EquationInfo &ei) const;
virtual pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t> > > &List_of_Op_RHS) const;
@ -625,8 +642,8 @@ private:
public:
VariableNode(DataTree &datatree_arg, int symb_id_arg, int lag_arg);
virtual void prepareForDerivation();
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
virtual bool containsExternalFunction() const;
virtual void collectVARLHSVariable(set<expr_t> &result) const;
virtual void collectDynamicVariables(SymbolType type_arg, set<pair<int, int> > &result) const;
@ -638,7 +655,7 @@ public:
int equation) const;
virtual void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const;
virtual double eval(const eval_context_t &eval_context) const throw (EvalException, EvalExternalFunctionException);
virtual void 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;
virtual void 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, const deriv_node_temp_terms_t &tef_terms) const;
virtual expr_t toStatic(DataTree &static_datatree) const;
virtual void computeXrefs(EquationInfo &ei) const;
SymbolType
@ -726,11 +743,12 @@ public:
virtual void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference> > &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) const;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
virtual bool containsExternalFunction() const;
virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs,
deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonExternalFunctionOutput(vector<string> &efout,
const temporary_terms_t &temporary_terms,
@ -751,7 +769,7 @@ public:
virtual void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const;
static double eval_opcode(UnaryOpcode op_code, double v) throw (EvalException, EvalExternalFunctionException);
virtual double eval(const eval_context_t &eval_context) const throw (EvalException, EvalExternalFunctionException);
virtual void 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;
virtual void 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, const deriv_node_temp_terms_t &tef_terms) const;
//! Returns operand
expr_t
get_arg() const
@ -840,11 +858,12 @@ public:
virtual void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference> > &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) const;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
virtual bool containsExternalFunction() const;
virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs,
deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonExternalFunctionOutput(vector<string> &efout,
const temporary_terms_t &temporary_terms,
@ -865,7 +884,7 @@ public:
virtual void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const;
static double eval_opcode(double v1, BinaryOpcode op_code, double v2, int derivOrder) throw (EvalException, EvalExternalFunctionException);
virtual double eval(const eval_context_t &eval_context) const throw (EvalException, EvalExternalFunctionException);
virtual void 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;
virtual void 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, const deriv_node_temp_terms_t &tef_terms) const;
virtual expr_t Compute_RHS(expr_t arg1, expr_t arg2, int op, int op_type) const;
//! Returns first operand
expr_t
@ -973,11 +992,12 @@ public:
virtual void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference> > &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) const;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
virtual bool containsExternalFunction() const;
virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs,
deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonExternalFunctionOutput(vector<string> &efout,
const temporary_terms_t &temporary_terms,
@ -998,7 +1018,7 @@ public:
virtual void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const;
static double eval_opcode(double v1, TrinaryOpcode op_code, double v2, double v3) throw (EvalException, EvalExternalFunctionException);
virtual double eval(const eval_context_t &eval_context) const throw (EvalException, EvalExternalFunctionException);
virtual void 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;
virtual void 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, const deriv_node_temp_terms_t &tef_terms) const;
virtual expr_t toStatic(DataTree &static_datatree) const;
virtual void computeXrefs(EquationInfo &ei) const;
virtual pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t> > > &List_of_Op_RHS) const;
@ -1063,24 +1083,29 @@ protected:
const int symb_id;
const vector<expr_t> arguments;
//! Returns true if the given external function has been written as a temporary term
bool alreadyWrittenAsTefTerm(int the_symb_id, deriv_node_temp_terms_t &tef_terms) const;
bool alreadyWrittenAsTefTerm(int the_symb_id, const deriv_node_temp_terms_t &tef_terms) const;
//! Returns the index in the tef_terms map of this external function
int getIndxInTefTerms(int the_symb_id, deriv_node_temp_terms_t &tef_terms) const throw (UnknownFunctionNameAndArgs);
int getIndxInTefTerms(int the_symb_id, const deriv_node_temp_terms_t &tef_terms) const throw (UnknownFunctionNameAndArgs);
//! Helper function to write output arguments of any given external function
void writeExternalFunctionArguments(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
void writeJsonExternalFunctionArguments(ostream &output, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
void writeExternalFunctionArguments(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
void writeJsonExternalFunctionArguments(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
/*! Returns a predicate that tests whether an other ExprNode is an external
function which is computed by the same external function call (i.e. it has
the same so-called "Tef" index) */
virtual function<bool (expr_t)> sameTefTermPredicate() const = 0;
public:
AbstractExternalFunctionNode(DataTree &datatree_arg, int symb_id_arg,
const vector<expr_t> &arguments_arg);
virtual void prepareForDerivation();
virtual void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference> > &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) const = 0;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const = 0;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms, const bool isdynamic = true) const = 0;
bool is_matlab, NodeTreeReference tr) const;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const = 0;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic = true) const = 0;
virtual bool containsExternalFunction() const;
virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs,
deriv_node_temp_terms_t &tef_terms) const = 0;
virtual void writeJsonExternalFunctionOutput(vector<string> &efout,
const temporary_terms_t &temporary_terms,
@ -1103,9 +1128,9 @@ public:
unsigned int 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;
const deriv_node_temp_terms_t &tef_terms) const;
virtual void 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 = 0;
virtual void 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, const deriv_node_temp_terms_t &tef_terms) const = 0;
virtual expr_t toStatic(DataTree &static_datatree) const = 0;
virtual void computeXrefs(EquationInfo &ei) const = 0;
virtual pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t> > > &List_of_Op_RHS) const;
@ -1140,7 +1165,7 @@ public:
virtual bool containsExogenous() const;
virtual int countDiffs() const;
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
virtual void writePrhs(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms, const string &ending) const;
virtual void writePrhs(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms, const string &ending) const;
virtual expr_t replaceTrendVar() const;
virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const;
virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const = 0;
@ -1158,18 +1183,20 @@ public:
class ExternalFunctionNode : public AbstractExternalFunctionNode
{
friend class FirstDerivExternalFunctionNode;
friend class SecondDerivExternalFunctionNode;
private:
virtual expr_t composeDerivatives(const vector<expr_t> &dargs);
protected:
function<bool (expr_t)> sameTefTermPredicate() const override;
public:
ExternalFunctionNode(DataTree &datatree_arg, int symb_id_arg,
const vector<expr_t> &arguments_arg);
virtual void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference> > &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) const;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs,
deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonExternalFunctionOutput(vector<string> &efout,
const temporary_terms_t &temporary_terms,
@ -1185,7 +1212,7 @@ public:
int Curr_block,
vector< vector<temporary_terms_t> > &v_temporary_terms,
int equation) const;
virtual void 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;
virtual void 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, const deriv_node_temp_terms_t &tef_terms) const;
virtual expr_t toStatic(DataTree &static_datatree) const;
virtual void computeXrefs(EquationInfo &ei) const;
virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const;
@ -1197,28 +1224,28 @@ class FirstDerivExternalFunctionNode : public AbstractExternalFunctionNode
private:
const int inputIndex;
virtual expr_t composeDerivatives(const vector<expr_t> &dargs);
protected:
function<bool (expr_t)> sameTefTermPredicate() const override;
public:
FirstDerivExternalFunctionNode(DataTree &datatree_arg,
int top_level_symb_id_arg,
const vector<expr_t> &arguments_arg,
int inputIndex_arg);
virtual void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference> > &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) const;
virtual void computeTemporaryTerms(map<expr_t, int> &reference_count,
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;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
virtual void 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;
const deriv_node_temp_terms_t &tef_terms) const;
virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs,
deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonExternalFunctionOutput(vector<string> &efout,
const temporary_terms_t &temporary_terms,
@ -1240,29 +1267,29 @@ private:
const int inputIndex1;
const int inputIndex2;
virtual expr_t composeDerivatives(const vector<expr_t> &dargs);
protected:
function<bool (expr_t)> sameTefTermPredicate() const override;
public:
SecondDerivExternalFunctionNode(DataTree &datatree_arg,
int top_level_symb_id_arg,
const vector<expr_t> &arguments_arg,
int inputIndex1_arg,
int inputIndex2_arg);
virtual void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference> > &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) const;
virtual void computeTemporaryTerms(map<expr_t, int> &reference_count,
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;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
virtual void 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;
const deriv_node_temp_terms_t &tef_terms) const;
virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs,
deriv_node_temp_terms_t &tef_terms) const;
virtual void writeJsonExternalFunctionOutput(vector<string> &efout,
const temporary_terms_t &temporary_terms,
@ -1290,7 +1317,7 @@ public:
virtual void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference> > &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) const;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
virtual void computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int> > &first_occurence,
@ -1331,7 +1358,7 @@ public:
virtual void 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;
const deriv_node_temp_terms_t &tef_terms) const;
virtual void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const;
virtual void collectVARLHSVariable(set<expr_t> &result) const;
virtual void collectDynamicVariables(SymbolType type_arg, set<pair<int, int> > &result) const;
@ -1353,7 +1380,7 @@ public:
virtual bool isVarModelReferenced(const string &model_info_name) const;
virtual void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const;
virtual expr_t substituteStaticAuxiliaryVariable() const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
};
class PacExpectationNode : public ExprNode
@ -1375,7 +1402,7 @@ public:
virtual void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference> > &reference_count,
map<NodeTreeReference, temporary_terms_t> &temp_terms_map,
bool is_matlab, NodeTreeReference tr) const;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const;
virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
virtual void computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int> > &first_occurence,
@ -1416,7 +1443,7 @@ public:
virtual void 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;
const deriv_node_temp_terms_t &tef_terms) const;
virtual void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const;
virtual void collectVARLHSVariable(set<expr_t> &result) const;
virtual void collectDynamicVariables(SymbolType type_arg, set<pair<int, int> > &result) const;
@ -1438,7 +1465,7 @@ public:
virtual bool isVarModelReferenced(const string &model_info_name) const;
virtual void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const;
virtual expr_t substituteStaticAuxiliaryVariable() const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const;
};
#endif

View File

@ -892,6 +892,17 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
unlink((basename + "_steadystate2.m").c_str());
unlink((basename + "_set_auxiliary_variables.m").c_str());
// Clean generated files for temporary terms array interface
for (auto s1 : { "dynamic", "static" })
{
for (auto s2 : { "resid", "g1", "g2", "g3" })
for (auto s3 : { "", "_tt" })
unlink((basename + "_" + s1 + "_" + s2 + s3 + ".m").c_str());
for (auto s2 : { "resid_g1", "resid_g1_g2", "resid_g1_g2_g3" })
unlink((basename + "_" + s1 + "_" + s2 + ".m").c_str());
}
}
if (!use_dll)
@ -1399,6 +1410,8 @@ ModFile::writeExternalFilesJulia(const string &basename, FileOutputType output,
jlOutputFile << "model_.static = " << basename << "Static.static!" << endl
<< "model_.dynamic = " << basename << "Dynamic.dynamic!" << endl
<< "model_.temporaries.static = " << basename << "Static.tmp_nbr" << endl
<< "model_.temporaries.dynamic = " << basename << "Dynamic.tmp_nbr" << endl
<< "if isfile(\"" << basename << "SteadyState.jl" "\")" << endl
<< " model_.user_written_analytical_steady_state = true" << endl
<< " model_.steady_state = " << basename << "SteadyState.steady_state!" << endl

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2003-2017 Dynare Team
* Copyright (C) 2003-2018 Dynare Team
*
* This file is part of Dynare.
*
@ -280,7 +280,7 @@ ModelTree::evaluateAndReduceJacobian(const eval_context_t &eval_context, jacob_m
catch (ExprNode::EvalException &e)
{
cerr << "ERROR: evaluation of Jacobian failed for equation " << eq+1 << " (line " << equations_lineno[eq] << ") and variable " << symbol_table.getName(symb) << "(" << lag << ") [" << symb << "] !" << endl;
Id->writeOutput(cerr, oMatlabDynamicModelSparse, temporary_terms);
Id->writeOutput(cerr, oMatlabDynamicModelSparse, temporary_terms, {});
cerr << endl;
exit(EXIT_FAILURE);
}
@ -1027,7 +1027,7 @@ ModelTree::writeDerivative(ostream &output, int eq, int symb_id, int lag,
{
first_derivatives_t::const_iterator it = first_derivatives.find(make_pair(eq, getDerivID(symb_id, lag)));
if (it != first_derivatives.end())
(it->second)->writeOutput(output, output_type, temporary_terms);
(it->second)->writeOutput(output, output_type, temporary_terms, {});
else
output << 0;
}
@ -1120,10 +1120,26 @@ ModelTree::computeTemporaryTerms(bool is_matlab)
{
map<expr_t, pair<int, NodeTreeReference> > reference_count;
temporary_terms.clear();
temporary_terms_mlv.clear();
temporary_terms_res.clear();
temporary_terms_g1.clear();
temporary_terms_g2.clear();
temporary_terms_g3.clear();
// Collect all model local variables appearing in equations. See #101
// All used model local variables are automatically set as temporary variables
set<int> used_local_vars;
for (size_t i = 0; i < equations.size(); i++)
equations[i]->collectVariables(eModelLocalVariable, used_local_vars);
for (set<int>::const_iterator it = used_local_vars.begin();
it != used_local_vars.end(); it++)
{
VariableNode *v = AddVariable(*it);
temporary_terms_mlv[v] = local_variables_table.find(*it)->second;
reference_count[v] = make_pair(MIN_COST(is_matlab)+1, eResiduals);
}
map<NodeTreeReference, temporary_terms_t> temp_terms_map;
temp_terms_map[eResiduals] = temporary_terms_res;
temp_terms_map[eFirstDeriv] = temporary_terms_g1;
@ -1156,43 +1172,92 @@ ModelTree::computeTemporaryTerms(bool is_matlab)
for (map<NodeTreeReference, temporary_terms_t>::const_iterator it = temp_terms_map.begin();
it != temp_terms_map.end(); it++)
temporary_terms.insert(it->second.begin(), it->second.end());
temporary_terms.insert(it->second.begin(), it->second.end());
temporary_terms_res = temp_terms_map[eResiduals];
temporary_terms_g1 = temp_terms_map[eFirstDeriv];
temporary_terms_g2 = temp_terms_map[eSecondDeriv];
temporary_terms_g3 = temp_terms_map[eThirdDeriv];
int idx = 0;
for (map<expr_t, expr_t, ExprNodeLess>::const_iterator it = temporary_terms_mlv.begin();
it != temporary_terms_mlv.end(); it++)
temporary_terms_idxs[it->first] = idx++;
for (temporary_terms_t::const_iterator it = temporary_terms_res.begin();
it != temporary_terms_res.end(); it++)
temporary_terms_idxs[*it] = idx++;
for (temporary_terms_t::const_iterator it = temporary_terms_g1.begin();
it != temporary_terms_g1.end(); it++)
temporary_terms_idxs[*it] = idx++;
for (temporary_terms_t::const_iterator it = temporary_terms_g2.begin();
it != temporary_terms_g2.end(); it++)
temporary_terms_idxs[*it] = idx++;
for (temporary_terms_t::const_iterator it = temporary_terms_g3.begin();
it != temporary_terms_g3.end(); it++)
temporary_terms_idxs[*it] = idx++;
}
void
ModelTree::writeTemporaryTerms(const temporary_terms_t &tt, const temporary_terms_t &ttm1, ostream &output,
ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const
ModelTree::writeModelLocalVariableTemporaryTerms(const temporary_terms_t &tto, const map<expr_t, expr_t, ExprNodeLess> &tt,
ostream &output, ExprNodeOutputType output_type,
deriv_node_temp_terms_t &tef_terms) const
{
temporary_terms_t tt2;
for (map<expr_t, expr_t>::const_iterator it = tt.begin();
it != tt.end(); it++)
{
if (IS_C(output_type))
output << "double ";
else if (IS_JULIA(output_type))
output << " @inbounds const ";
it->first->writeOutput(output, output_type, tto, temporary_terms_idxs, tef_terms);
output << " = ";
it->second->writeOutput(output, output_type, tt2, temporary_terms_idxs, tef_terms);
if (IS_C(output_type) || IS_MATLAB(output_type))
output << ";";
output << endl;
// Insert current node into tt2
tt2.insert(it->first);
}
}
void
ModelTree::writeTemporaryTerms(const temporary_terms_t &tt,
const temporary_terms_t &ttm1,
const temporary_terms_idxs_t &tt_idxs,
ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const
{
// Local var used to keep track of temp nodes already written
temporary_terms_t tt2 = ttm1;
for (temporary_terms_t::const_iterator it = tt.begin();
it != tt.end(); it++)
if (ttm1.find(*it) == ttm1.end())
{
if (dynamic_cast<AbstractExternalFunctionNode *>(*it) != NULL)
(*it)->writeExternalFunctionOutput(output, output_type, tt2, tef_terms);
{
if (dynamic_cast<AbstractExternalFunctionNode *>(*it) != NULL)
(*it)->writeExternalFunctionOutput(output, output_type, tt2, tt_idxs, tef_terms);
if (IS_C(output_type))
output << "double ";
else if (IS_JULIA(output_type))
output << " @inbounds const ";
if (IS_C(output_type))
output << "double ";
else if (IS_JULIA(output_type))
output << " @inbounds ";
(*it)->writeOutput(output, output_type, tt, tef_terms);
output << " = ";
(*it)->writeOutput(output, output_type, tt2, tef_terms);
(*it)->writeOutput(output, output_type, tt, tt_idxs, tef_terms);
output << " = ";
(*it)->writeOutput(output, output_type, tt2, tt_idxs, tef_terms);
if (IS_C(output_type) || IS_MATLAB(output_type))
output << ";";
output << endl;
if (IS_C(output_type) || IS_MATLAB(output_type))
output << ";";
output << endl;
// Insert current node into tt2
tt2.insert(*it);
}
// Insert current node into tt2
tt2.insert(*it);
}
}
void
@ -1404,41 +1469,6 @@ ModelTree::compileTemporaryTerms(ostream &code_file, unsigned int &instruction_n
}
}
void
ModelTree::writeModelLocalVariables(ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const
{
/* Collect all model local variables appearing in equations, and print only
them. Printing unused model local variables can lead to a crash (see
ticket #101). */
set<int> used_local_vars;
// Use an empty set for the temporary terms
const temporary_terms_t tt;
for (size_t i = 0; i < equations.size(); i++)
equations[i]->collectVariables(eModelLocalVariable, used_local_vars);
for (vector<int>::const_iterator it = local_variables_vector.begin();
it != local_variables_vector.end(); it++)
if (used_local_vars.find(*it) != used_local_vars.end())
{
int id = *it;
expr_t value = local_variables_table.find(id)->second;
value->writeExternalFunctionOutput(output, output_type, tt, tef_terms);
if (IS_C(output_type))
output << "double ";
else if (IS_JULIA(output_type))
output << " @inbounds ";
/* We append underscores to avoid name clashes with "g1" or "oo_" (see
also VariableNode::writeOutput) */
output << symbol_table.getName(id) << "__ = ";
value->writeOutput(output, output_type, tt, tef_terms);
output << ";" << endl;
}
}
void
ModelTree::writeJsonModelLocalVariables(ostream &output, deriv_node_temp_terms_t &tef_terms) const
{
@ -1491,12 +1521,15 @@ ModelTree::writeJsonModelLocalVariables(ostream &output, deriv_node_temp_terms_t
void
ModelTree::writeModelEquations(ostream &output, ExprNodeOutputType output_type) const
{
temporary_terms_t temp_terms;
if (IS_JULIA(output_type))
temp_terms = temporary_terms_res;
else
temp_terms = temporary_terms;
temporary_terms_t tt;
temporary_terms_idxs_t ttidxs;
writeModelEquations(output, output_type, tt);
}
void
ModelTree::writeModelEquations(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms) const
{
for (int eq = 0; eq < (int) equations.size(); eq++)
{
BinaryOpNode *eq_node = equations[eq];
@ -1514,35 +1547,39 @@ ModelTree::writeModelEquations(ostream &output, ExprNodeOutputType output_type)
}
if (vrhs != 0) // The right hand side of the equation is not empty ==> residual=lhs-rhs;
{
if (IS_JULIA(output_type))
output << " @inbounds ";
output << "lhs =";
lhs->writeOutput(output, output_type, temp_terms);
output << ";" << endl;
if (IS_JULIA(output_type))
output << " @inbounds ";
output << "rhs =";
rhs->writeOutput(output, output_type, temp_terms);
output << ";" << endl;
if (IS_JULIA(output_type))
output << " @inbounds ";
output << "residual" << LEFT_ARRAY_SUBSCRIPT(output_type)
<< eq + ARRAY_SUBSCRIPT_OFFSET(output_type)
<< RIGHT_ARRAY_SUBSCRIPT(output_type)
<< "= lhs-rhs;" << endl;
}
if (IS_JULIA(output_type))
{
output << " @inbounds residual" << LEFT_ARRAY_SUBSCRIPT(output_type)
<< eq + ARRAY_SUBSCRIPT_OFFSET(output_type)
<< RIGHT_ARRAY_SUBSCRIPT(output_type)
<< " = (";
lhs->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs);
output << ") - (";
rhs->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs);
output << ")" << endl;
}
else
{
output << "lhs = ";
lhs->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs);
output << ";" << endl
<< "rhs = ";
rhs->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs);
output << ";" << endl
<< "residual" << LEFT_ARRAY_SUBSCRIPT(output_type)
<< eq + ARRAY_SUBSCRIPT_OFFSET(output_type)
<< RIGHT_ARRAY_SUBSCRIPT(output_type)
<< " = lhs - rhs;" << endl;
}
else // The right hand side of the equation is empty ==> residual=lhs;
{
if (IS_JULIA(output_type))
output << " @inbounds ";
output << " @inbounds ";
output << "residual" << LEFT_ARRAY_SUBSCRIPT(output_type)
<< eq + ARRAY_SUBSCRIPT_OFFSET(output_type)
<< RIGHT_ARRAY_SUBSCRIPT(output_type)
<< " = ";
lhs->writeOutput(output, output_type, temp_terms);
lhs->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs);
output << ";" << endl;
}
}
@ -1787,9 +1824,8 @@ ModelTree::set_cutoff_to_zero()
void
ModelTree::jacobianHelper(ostream &output, int eq_nb, int col_nb, ExprNodeOutputType output_type) const
{
output << " ";
if (IS_JULIA(output_type))
output << "@inbounds ";
output << " @inbounds ";
output << "g1" << LEFT_ARRAY_SUBSCRIPT(output_type);
if (IS_MATLAB(output_type) || IS_JULIA(output_type))
output << eq_nb + 1 << "," << col_nb + 1;
@ -1801,7 +1837,7 @@ ModelTree::jacobianHelper(ostream &output, int eq_nb, int col_nb, ExprNodeOutput
void
ModelTree::sparseHelper(int order, ostream &output, int row_nb, int col_nb, ExprNodeOutputType output_type) const
{
output << " v" << order << LEFT_ARRAY_SUBSCRIPT(output_type);
output << "v" << order << LEFT_ARRAY_SUBSCRIPT(output_type);
if (IS_MATLAB(output_type) || IS_JULIA(output_type))
output << row_nb + 1 << "," << col_nb + 1;
else
@ -1941,6 +1977,22 @@ ModelTree::computeParamsDerivativesTemporaryTerms()
params_derivs_temporary_terms_res2 = temp_terms_map[eResidualsParamsSecondDeriv];
params_derivs_temporary_terms_g12 = temp_terms_map[eJacobianParamsSecondDeriv];
params_derivs_temporary_terms_g2 = temp_terms_map[eHessianParamsDeriv];
int idx = 0;
for (auto tt : params_derivs_temporary_terms_res)
params_derivs_temporary_terms_idxs[tt] = idx++;
for (auto tt : params_derivs_temporary_terms_g1)
params_derivs_temporary_terms_idxs[tt] = idx++;
for (auto tt : params_derivs_temporary_terms_res2)
params_derivs_temporary_terms_idxs[tt] = idx++;
for (auto tt : params_derivs_temporary_terms_g12)
params_derivs_temporary_terms_idxs[tt] = idx++;
for (auto tt : params_derivs_temporary_terms_g2)
params_derivs_temporary_terms_idxs[tt] = idx++;
}
bool
@ -1953,7 +2005,6 @@ ModelTree::isNonstationary(int symb_id) const
void
ModelTree::writeJsonModelEquations(ostream &output, bool residuals) const
{
deriv_node_temp_terms_t tef_terms;
vector<pair<string, string> > eqtags;
temporary_terms_t tt_empty;
if (residuals)
@ -1973,11 +2024,11 @@ ModelTree::writeJsonModelEquations(ostream &output, bool residuals) const
{
output << "{\"residual\": {"
<< "\"lhs\": \"";
lhs->writeJsonOutput(output, temporary_terms, tef_terms);
lhs->writeJsonOutput(output, temporary_terms, {});
output << "\"";
output << ", \"rhs\": \"";
rhs->writeJsonOutput(output, temporary_terms, tef_terms);
rhs->writeJsonOutput(output, temporary_terms, {});
output << "\"";
try
{
@ -1985,7 +2036,7 @@ ModelTree::writeJsonModelEquations(ostream &output, bool residuals) const
if (rhs->eval(eval_context_t()) != 0)
{
output << ", \"rhs\": \"";
rhs->writeJsonOutput(output, temporary_terms, tef_terms);
rhs->writeJsonOutput(output, temporary_terms, {});
output << "\"";
}
}
@ -1997,9 +2048,9 @@ ModelTree::writeJsonModelEquations(ostream &output, bool residuals) const
else
{
output << "{\"lhs\": \"";
lhs->writeJsonOutput(output, tt_empty, tef_terms);
lhs->writeJsonOutput(output, tt_empty, {});
output << "\", \"rhs\": \"";
rhs->writeJsonOutput(output, tt_empty, tef_terms);
rhs->writeJsonOutput(output, tt_empty, {});
output << "\""
<< ", \"line\": " << equations_lineno[eq];

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2003-2017 Dynare Team
* Copyright (C) 2003-2018 Dynare Team
*
* This file is part of Dynare.
*
@ -134,13 +134,16 @@ protected:
*/
third_derivatives_t hessian_params_derivatives;
//! Temporary terms for the static/dynamic file (those which will be noted Txxxx)
//! Temporary terms for the static/dynamic file (those which will be noted T[x])
temporary_terms_t temporary_terms;
map<expr_t, expr_t, ExprNodeLess> temporary_terms_mlv;
temporary_terms_t temporary_terms_res;
temporary_terms_t temporary_terms_g1;
temporary_terms_t temporary_terms_g2;
temporary_terms_t temporary_terms_g3;
temporary_terms_idxs_t temporary_terms_idxs;
//! Temporary terms for the file containing parameters derivatives
temporary_terms_t params_derivs_temporary_terms;
temporary_terms_t params_derivs_temporary_terms_res;
@ -149,6 +152,8 @@ protected:
temporary_terms_t params_derivs_temporary_terms_g12;
temporary_terms_t params_derivs_temporary_terms_g2;
temporary_terms_idxs_t params_derivs_temporary_terms_idxs;
//! Trend variables and their growth factors
map<int, expr_t> trend_symbols_map;
@ -182,7 +187,7 @@ protected:
//! Computes temporary terms for the file containing parameters derivatives
void computeParamsDerivativesTemporaryTerms();
//! Writes temporary terms
void writeTemporaryTerms(const temporary_terms_t &tt, const temporary_terms_t &ttm1, ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const;
void writeTemporaryTerms(const temporary_terms_t &tt, const temporary_terms_t &ttm1, const temporary_terms_idxs_t &tt_idxs, ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const;
void writeJsonTemporaryTerms(const temporary_terms_t &tt, const temporary_terms_t &ttm1, ostream &output, deriv_node_temp_terms_t &tef_terms, string &concat) const;
//! Compiles temporary terms
void compileTemporaryTerms(ostream &code_file, unsigned int &instruction_number, const temporary_terms_t &tt, map_idx_t map_idx, bool dynamic, bool steady_dynamic) const;
@ -192,11 +197,13 @@ protected:
void fixNestedParenthesis(ostringstream &output, map<string, string> &tmp_paren_vars, bool &message_printed) const;
//! Tests if string contains more than 32 nested parens, Issue #1201
bool testNestedParenthesis(const string &str) const;
//! Writes model local variables
/*! No temporary term is used in the output, so that local parameters declarations can be safely put before temporary terms declaration in the output files */
void writeModelLocalVariables(ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const;
void writeModelLocalVariableTemporaryTerms(const temporary_terms_t &tto, const map<expr_t, expr_t, ExprNodeLess> &tt,
ostream &output, ExprNodeOutputType output_type,
deriv_node_temp_terms_t &tef_terms) const;
//! Writes model equations
void writeModelEquations(ostream &output, ExprNodeOutputType output_type) const;
void writeModelEquations(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms) const;
//! Writes JSON model equations
//! if residuals = true, we are writing the dynamic/static model.
//! Otherwise, just the model equations (with line numbers, no tmp terms)

View File

@ -66,9 +66,8 @@ InitParamStatement::writeJuliaOutput(ostream &output, const string &basename)
void
InitParamStatement::writeJsonOutput(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "{\"statementName\": \"param_init\", \"name\": \"" << symbol_table.getName(symb_id) << "\", " << "\"value\": \"";
param_value->writeJsonOutput(output, temporary_terms_t(), tef_terms);
param_value->writeJsonOutput(output, {}, {});
output << "\"}";
}
@ -177,14 +176,13 @@ InitOrEndValStatement::writeInitValues(ostream &output) const
void
InitOrEndValStatement::writeJsonInitValues(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
for (init_values_t::const_iterator it = init_values.begin();
it != init_values.end(); it++)
{
if (it != init_values.begin())
output << ", ";
output << "{\"name\": \"" << symbol_table.getName(it->first) << "\", " << "\"value\": \"";
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->second->writeJsonOutput(output, {}, {});
output << "\"}";
}
}
@ -419,7 +417,6 @@ HistValStatement::writeOutput(ostream &output, const string &basename, bool mini
void
HistValStatement::writeJsonOutput(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "{\"statementName\": \"hist_val\", \"vals\": [";
for (hist_values_t::const_iterator it = hist_values.begin();
it != hist_values.end(); it++)
@ -429,7 +426,7 @@ HistValStatement::writeJsonOutput(ostream &output) const
output << "{ \"name\": \"" << symbol_table.getName(it->first.first) << "\""
<< ", \"lag\": " << it->first.second
<< ", \"value\": \"";
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->second->writeJsonOutput(output, {}, {});
output << "\"}";
}
output << "]}";
@ -516,7 +513,6 @@ HomotopyStatement::writeOutput(ostream &output, const string &basename, bool min
void
HomotopyStatement::writeJsonOutput(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "{\"statementName\": \"homotopy\", "
<< "\"values\": [";
for (homotopy_values_t::const_iterator it = homotopy_values.begin();
@ -527,11 +523,11 @@ HomotopyStatement::writeJsonOutput(ostream &output) const
output << "{\"name\": \"" << symbol_table.getName(it->first) << "\""
<< ", \"initial_value\": \"";
if (it->second.first != NULL)
it->second.first->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->second.first->writeJsonOutput(output, {}, {});
else
output << "NaN";
output << "\", \"final_value\": \"";
it->second.second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->second.second->writeJsonOutput(output, {}, {});
output << "\"}";
}
output << "]"
@ -625,7 +621,6 @@ LoadParamsAndSteadyStateStatement::writeOutput(ostream &output, const string &ba
void
LoadParamsAndSteadyStateStatement::writeJsonOutput(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "{\"statementName\": \"load_params_and_steady_state\""
<< "\"values\": [";
for (map<int, string>::const_iterator it = content.begin();

View File

@ -70,7 +70,6 @@ AbstractShocksStatement::writeDetShocks(ostream &output) const
void
AbstractShocksStatement::writeJsonDetShocks(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "\"deterministic_shocks\": [";
for (det_shocks_t::const_iterator it = det_shocks.begin();
it != det_shocks.end(); it++)
@ -87,7 +86,7 @@ AbstractShocksStatement::writeJsonDetShocks(ostream &output) const
output << "{\"period1\": " << it1->period1 << ", "
<< "\"period2\": " << it1->period2 << ", "
<< "\"value\": \"";
it1->value->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it1->value->writeJsonOutput(output, {}, {});
output << "\"}";
}
output << "]}";
@ -154,7 +153,6 @@ ShocksStatement::writeOutput(ostream &output, const string &basename, bool minim
void
ShocksStatement::writeJsonOutput(ostream &output) const
{
deriv_node_temp_terms_t tef_terms;
output << "{\"statementName\": \"shocks\""
<< ", \"overwrite\": ";
if (overwrite)
@ -173,7 +171,7 @@ ShocksStatement::writeJsonOutput(ostream &output) const
output << ", ";
output << "{\"name\": \"" << symbol_table.getName(it->first) << "\", "
<< "\"variance\": \"";
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->second->writeJsonOutput(output, {}, {});
output << "\"}";
}
output << "]"
@ -184,7 +182,7 @@ ShocksStatement::writeJsonOutput(ostream &output) const
output << ", ";
output << "{\"name\": \"" << symbol_table.getName(it->first) << "\", "
<< "\"stderr\": \"";
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->second->writeJsonOutput(output, {}, {});
output << "\"}";
}
output << "]"
@ -197,7 +195,7 @@ ShocksStatement::writeJsonOutput(ostream &output) const
<< "\"name\": \"" << symbol_table.getName(it->first.first) << "\", "
<< "\"name2\": \"" << symbol_table.getName(it->first.second) << "\", "
<< "\"covariance\": \"";
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->second->writeJsonOutput(output, {}, {});
output << "\"}";
}
output << "]"
@ -210,7 +208,7 @@ ShocksStatement::writeJsonOutput(ostream &output) const
<< "\"name\": \"" << symbol_table.getName(it->first.first) << "\", "
<< "\"name2\": \"" << symbol_table.getName(it->first.second) << "\", "
<< "\"correlation\": \"";
it->second->writeJsonOutput(output, temporary_terms_t(), tef_terms);
it->second->writeJsonOutput(output, {}, {});
output << "\"}";
}
output << "]"

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2003-2017 Dynare Team
* Copyright (C) 2003-2018 Dynare Team
*
* This file is part of Dynare.
*
@ -51,7 +51,7 @@ private:
void writeStaticJuliaFile(const string &basename) const;
//! Writes the static model equations and its derivatives
void writeStaticModel(ostream &StaticOutput, bool use_dll, bool julia) const;
void writeStaticModel(const string &basename, ostream &StaticOutput, bool use_dll, bool julia) const;
//! Writes the static function calling the block to solve (Matlab version)
void writeStaticBlockMFSFile(const string &basename) const;
@ -101,9 +101,6 @@ private:
//! Collect only the first derivatives
map<pair<int, pair<int, int> >, expr_t> collect_first_order_derivatives_endogenous();
//! Write chain rule derivative of a recursive equation w.r. to a variable
void writeChainRuleDerivative(ostream &output, int eq, int var, int lag, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const;
//! Collecte the derivatives w.r. to endogenous of the block, to endogenous of previouys blocks and to exogenous
void collect_block_first_order_derivatives();
@ -148,6 +145,19 @@ protected:
//!Maximum lead and lag for each block on endogenous of the block, endogenous of the previous blocks, exogenous and deterministic exogenous
vector<pair<int, int> > endo_max_leadlag_block, other_endo_max_leadlag_block, exo_max_leadlag_block, exo_det_max_leadlag_block, max_leadlag_block;
//! Helper functions for writeStaticModel
void writeStaticModelHelper(const string &name, const string &retvalname,
const string &name_tt, size_t ttlen,
const string &previous_tt_name,
const ostringstream &init_s, const ostringstream &end_s,
const ostringstream &s, const ostringstream &s_tt) const;
void writeWrapperFunctions(const string &basename, const string &ending) const;
//! Create a legacy *_static.m file for Matlab/Octave not yet using the temporary terms array interface
void writeStaticMatlabCompatLayer(const string &name) const;
void writeStaticModel(ostream &DynamicOutput, bool use_dll, bool julia) const;
void writeStaticModel(const string &dynamic_basename, bool use_dll, bool julia) const;
public:
StaticModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants, ExternalFunctionsTable &external_functions_table_arg);

View File

@ -277,9 +277,7 @@ SteadyStateModel::writeJsonSteadyStateFile(ostream &output, bool transformComput
if (def_table.size() == 0)
return;
deriv_node_temp_terms_t tef_terms;
vector<pair<string, string> > eqtags;
temporary_terms_t tt_empty;
output << "{\"steady_state_model\": [";
@ -299,13 +297,13 @@ SteadyStateModel::writeJsonSteadyStateFile(ostream &output, bool transformComput
variable_node_map.find(make_pair(symb_ids[j], 0));
assert(it != variable_node_map.end());
output << "\"";
dynamic_cast<ExprNode *>(it->second)->writeJsonOutput(output, tt_empty, tef_terms, false);
dynamic_cast<ExprNode *>(it->second)->writeJsonOutput(output, {}, {}, false);
output << "\"";
}
if (symb_ids.size() > 1)
output << "]";
output << ", \"rhs\":\"";
def_table[i].second->writeJsonOutput(output, tt_empty, tef_terms, false);
def_table[i].second->writeJsonOutput(output, {}, {}, false);
output << "\"}" << endl;
}

View File

@ -1110,34 +1110,35 @@ SymbolTable::writeJuliaOutput(ostream &output) const throw (NotYetFrozenExceptio
{
case avEndoLead:
case avExoLead:
break;
case avEndoLag:
case avExoLag:
case avVarModel:
case avUnaryOp:
output << getTypeSpecificID(aux_vars[i].get_orig_symb_id()) + 1 << ", "
<< aux_vars[i].get_orig_lead_lag() << ", NaN, NaN";
<< aux_vars[i].get_orig_lead_lag() << ", typemin(Int), string()";
break;
case avDiff:
case avDiffLag:
if (aux_vars[i].get_orig_symb_id() >= 0)
output << getTypeSpecificID(aux_vars[i].get_orig_symb_id()) + 1 << ", "
<< aux_vars[i].get_orig_lead_lag() << ", NaN, NaN";
<< aux_vars[i].get_orig_lead_lag() << ", typemin(Int), string()";
break;
case avMultiplier:
output << "NaN, NaN, " << aux_vars[i].get_equation_number_for_multiplier() + 1
<< ", NaN";
output << "typemin(Int), typemin(Int), " << aux_vars[i].get_equation_number_for_multiplier() + 1
<< ", string()";
break;
case avDiffForward:
output << getTypeSpecificID(aux_vars[i].get_orig_symb_id())+1 << ", NaN, ";
output << getTypeSpecificID(aux_vars[i].get_orig_symb_id())+1 << ", typemin(Int), typemin(Int), string()";
break;
case avExpectation:
output << "NaN, NaN, NaN, \"\\mathbb{E}_{t"
output << "typemin(Int), typemin(Int), typemin(Int), \"\\mathbb{E}_{t"
<< (aux_vars[i].get_information_set() < 0 ? "" : "+")
<< aux_vars[i].get_information_set() << "}(";
aux_vars[i].get_expr_node()->writeOutput(output, oLatexDynamicModel);
output << ")\"";
break;
default:
output << " typemin(Int), typemin(Int), typemin(Int), string()";
}
output << ")" << endl;
}