Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
Loading items

Target

Select target project
  • normann/preprocessor
  • Dynare/preprocessor
  • FerhatMihoubi/preprocessor
  • MichelJuillard/preprocessor
  • sebastien/preprocessor
  • lnsongxf/preprocessor
  • albop/preprocessor
  • DoraK/preprocessor
  • amg/preprocessor
  • wmutschl/preprocessor
  • JohannesPfeifer/preprocessor
11 results
Select Git revision
Loading items
Show changes
Showing
with 5739 additions and 6675 deletions
# ===========================================================================
# 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
]])
# ============================================================================
# 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])])
# ===========================================================================
# http://www.nongnu.org/autoconf-archive/ax_latex_class.html
# ===========================================================================
#
# OBSOLETE MACRO
#
# Deprecated because of licensing issues. The Lesser GPL imposes licensing
# restrictions on the generated configure script unless it is augmented
# with an Autoconf Exception clause.
#
# SYNOPSIS
#
# AX_LATEX_CLASS(CLASSNAME,VARIABLETOSET[,ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]])
#
# DESCRIPTION
#
# This macros test is class CLASSNAME exists and work and set
# VARIABLETOSET to yes or no If ACTION-IF-FOUND (and ACTION-IF-NOT-FOUND)
# are set, do the correct action
#
# LICENSE
#
# Copyright (c) 2008 Boretti Mathieu <boretti@eig.unige.ch>
# Copyright (c) 2009 Dynare Team
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or (at
# your option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
AC_DEFUN([AX_LATEX_CLASS],[
AC_CACHE_CHECK([for usability of class $1],[ac_cv_latex_class_]translit($1,[-],[_]),[
AX_LATEX_TEST([\documentclass{$1}
\begin{document}
\end{document}],[ac_cv_latex_class_]translit($1,[-],[_]))
])
$2=$[ac_cv_latex_class_]translit($1,[-],[_]) ; export $2;
AC_SUBST($2)
ifelse($#,2,[],$#,3,[
if test "[$]$2" = "yes" ;
then
$3
fi
],$#,4,[
ifelse($3,[],[
if test "[$]$2" = "no" ;
then
$4
fi
],[
if test "[$]$2" = "yes" ;
then
$3
else
$4
fi
])
])
])
# ===========================================================================
# http://www.nongnu.org/autoconf-archive/ax_latex_test.html
# ===========================================================================
#
# OBSOLETE MACRO
#
# Deprecated because of licensing issues. The Lesser GPL imposes licensing
# restrictions on the generated configure script unless it is augmented
# with an Autoconf Exception clause.
#
# SYNOPSIS
#
# AX_LATEX_TEST(FILEDATA,VARIABLETOSET,[NOCLEAN])
#
# DESCRIPTION
#
# This macros execute the latex application with FILEDATA as input and set
# VARIABLETOSET the yes or no depending of the result if NOCLEAN is set,
# the folder used for the test is not delete after testing.
#
# The macro assumes that the variable PDFLATEX is set.
#
# LICENSE
#
# Copyright (c) 2008 Boretti Mathieu <boretti@eig.unige.ch>
# Copyright (c) 2009 Dynare Team
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or (at
# your option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <http://www.gnu.org/licenses/>.
AC_DEFUN([AX_LATEX_TEST],[
rm -rf conftest.dir/.acltx
AS_MKDIR_P([conftest.dir/.acltx])
cd conftest.dir/.acltx
m4_ifval([$2],[$2="no"; export $2;])
cat > conftest.tex << ACLEOF
$1
ACLEOF
cat conftest.tex | $PDFLATEX 2>&1 1>output m4_ifval([$2],[&& $2=yes])
cd ..
cd ..
sed 's/^/| /' conftest.dir/.acltx/conftest.tex >&5
echo "$as_me:$LINENO: executing cat conftest.tex | $PDFLATEX" >&5
sed 's/^/| /' conftest.dir/.acltx/output >&5
m4_ifval([$3],,[rm -rf conftest.dir/.acltx])
])
# Meson file for building the preprocessor in a standalone fashion.
# It is not used when building Dynare as a whole.
project('dynare-preprocessor', 'cpp',
version : '7-unstable',
# NB: update C++ standard in .clang-format whenever the following is modified
default_options : [ 'cpp_std=gnu++20', 'warning_level=2' ],
meson_version : '>=0.64.0')
add_global_arguments('-DPACKAGE_VERSION="' + meson.project_version() + '"', language : 'cpp')
if get_option('warning_level').to_int() >= 2
add_global_arguments('-Wold-style-cast', language : 'cpp')
endif
cpp_compiler = meson.get_compiler('cpp')
subdir('src')
subdir('doc')
# Meson native file for compiling under Homebrew / arm64
[binaries]
cpp = '/opt/homebrew/bin/g++-15'
flex = '/opt/homebrew/opt/flex/bin/flex'
bison = '/opt/homebrew/opt/bison/bin/bison'
[built-in options]
# XCode 15 (on Ventura and Sonoma) has a linker issue, see https://github.com/mesonbuild/meson/issues/12282, workaround is to use ld_classic
cpp_link_args = [ '-Wl,-ld_classic' ]
\ No newline at end of file
# Meson native file for compiling under Homebrew / x86-64
[binaries]
cpp = '/usr/local/bin/g++-15'
flex = '/usr/local/opt/flex/bin/flex'
bison = '/usr/local/opt/bison/bin/bison'
[built-in options]
# XCode 15 (on Ventura and Sonoma) has a linker issue, see https://github.com/mesonbuild/meson/issues/12282, workaround is to use ld_classic
cpp_link_args = [ '-Wl,-ld_classic' ]
\ No newline at end of file
# Meson cross file for targeting Linux arm64
[binaries]
cpp = 'aarch64-linux-gnu-g++'
strip = 'aarch64-linux-gnu-strip'
[host_machine]
system = 'linux'
cpu_family = 'aarch64'
cpu = 'aarch64'
endian = 'little'
# Meson cross file for creating a WebAssembly version of the preprocessor.
#
# Requires emscripten to be installed.
# Was successfully tested with emscripten 3.1.69 installed through emsdk
# tool, as described on: https://emscripten.org/docs/getting_started/downloads.html
# Don’t forget to source script snippet in current shell before running meson.
#
# Compilation creates a .wasm and .js wrapper under <builddir>/src/
#
# Can be run locally with node.js using:
# node dynare-preprocessor.js file.mod
# NB: a version of node.js is shipped with emscripten (under the node/
# subdirectory), but another version should also work.
[binaries]
cpp = 'em++'
[host_machine]
system = 'emscripten'
# Could be changed to wasm64 if 4GB memory constraint is hit
# Some background: https://v8.dev/blog/4gb-wasm-memory
cpu_family = 'wasm32'
cpu = 'wasm32'
endian = 'little'
[built-in options]
# Never do a debug build, because otherwise the lack of optimisations can
# overflow the memory capacities.
buildtype = 'release'
# The -fexceptions flag (for both compilation and linking) is needed for an
# unknown reason (C++ compilers are supposed to always add exception support).
# The -Wno-unqualified-std-cast-call flag removes many warnings about “move”
# not being qualified with “std::” namespace.
# The -fexperimental-library flag is needed to get std::jthread support (it was
# supposed to no longer be necessary for LLVM 20, but for some reason we still
# need it).
cpp_args = [ '-fexceptions', '-Wno-unqualified-std-cast-call', '-fexperimental-library' ]
# NODERAWFS=1 is needed for accessing the local filesystem
cpp_link_args = [ '-s', 'NODERAWFS=1', '-fexceptions' ]
[properties]
# It’s necessary to use a different copy of Boost than the one under
# /usr/include, because otherwise GCC headers confuse Clang
boost_root = '/tmp/boost_1_86_0'
# Meson cross file for targeting Windows from Linux
# NB: The boost_root property must be set, possibly through a second cross file
[binaries]
cpp = 'x86_64-w64-mingw32-g++-posix'
strip = 'x86_64-w64-mingw32-strip'
[host_machine]
system = 'windows'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'
[built-in options]
prefer_static = true
# See the comments in the main Dynare Meson cross-file
cpp_args = [ '-fstack-protector', '-march=nocona', '-msahf', '-mtune=generic' ]
cpp_link_args = [ '-fstack-protector' ]
#[properties]
#boost_root = '/home/sebastien/dynare/unstable/preprocessor/deps/mingw64/'
/*
* Copyright © 2022-2024 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <cstdlib>
#include <ios>
#include <iostream>
#include "Bytecode.hh"
namespace Bytecode
{
Writer::Writer(const filesystem::path& filename)
{
open(filename, ios::out | ios::binary);
if (!is_open())
{
cerr << R"(Error : Can't open file ")" << filename.string() << R"(" for writing)" << endl;
exit(EXIT_FAILURE);
}
}
template<>
Writer&
operator<<(Writer& code_file, const FCALL& instr)
{
code_file.instructions_positions.push_back(code_file.tellp());
auto write_member = [&code_file](const auto& member) {
code_file.write(reinterpret_cast<const char*>(&member), sizeof member);
};
write_member(instr.tag);
write_member(instr.nb_output_arguments);
write_member(instr.nb_input_arguments);
write_member(instr.indx);
write_member(instr.add_input_arguments);
write_member(instr.row);
write_member(instr.col);
write_member(instr.call_type);
int size = static_cast<int>(instr.func_name.size());
write_member(size);
code_file.write(instr.func_name.c_str(), size + 1);
size = static_cast<int>(instr.arg_func_name.size());
write_member(size);
code_file.write(instr.arg_func_name.c_str(), size + 1);
return code_file;
}
template<>
Writer&
operator<<(Writer& code_file, const FBEGINBLOCK& instr)
{
code_file.instructions_positions.push_back(code_file.tellp());
auto write_member = [&code_file](const auto& member) {
code_file.write(reinterpret_cast<const char*>(&member), sizeof member);
};
write_member(instr.tag);
write_member(instr.size);
write_member(instr.type);
for (int i = 0; i < instr.size; i++)
{
write_member(instr.variables[i]);
write_member(instr.equations[i]);
}
if (instr.type == BlockSimulationType::solveTwoBoundariesSimple
|| instr.type == BlockSimulationType::solveTwoBoundariesComplete
|| instr.type == BlockSimulationType::solveBackwardComplete
|| instr.type == BlockSimulationType::solveForwardComplete)
{
write_member(instr.is_linear);
write_member(instr.u_count_int);
}
write_member(instr.nb_col_jacob);
write_member(instr.det_exo_size);
write_member(instr.exo_size);
ranges::for_each_n(instr.det_exogenous.begin(), instr.det_exo_size, write_member);
ranges::for_each_n(instr.exogenous.begin(), instr.exo_size, write_member);
return code_file;
}
}
/*
* Copyright © 2007-2024 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef BYTECODE_HH
#define BYTECODE_HH
#include <concepts>
#include <filesystem>
#include <fstream>
#include <ios>
#include <type_traits>
#include <utility>
#include <vector>
#include "CommonEnums.hh"
using namespace std;
namespace Bytecode
{
// The different tags encoding a bytecode instruction
enum class Tag
{
FLDZ, // Loads a zero onto the stack
FLDC, // Loads a constant term onto the stack
FDIMT, // Defines the number of temporary terms - dynamic context (the period has to be indicated)
FDIMST, // Defines the number of temporary terms - static context (the period hasn’t to be
// indicated)
FLDT, // Loads a temporary term onto the stack - dynamic context (the period has to be indicated)
FLDST, // Loads a temporary term onto the stack - static context (the period hasn’t to be
// indicated)
FSTPT, // Stores a temporary term from the stack - dynamic context (the period has to be
// indicated)
FSTPST, // Stores a temporary term from the stack - static context (the period hasn’t to be
// indicated)
FLDU, // Loads an element of the vector U onto the stack - dynamic context (the period has to be
// indicated)
FLDSU, // Loads an element of the vector U onto the stack - static context (the period hasn’t to
// be indicated)
FSTPU, // Stores an element of the vector U from the stack - dynamic context (the period has to be
// indicated)
FSTPSU, // Stores an element of the vector U from the stack - static context (the period hasn’t to
// be indicated)
FLDV, // Loads a variable (described in SymbolType) onto the stack - dynamic context (the period
// has to be indicated)
FLDSV, // Loads a variable (described in SymbolType) onto the stack - static context (the period
// hasn’t to be indicated)
FLDVS, // Loads a variable (described in SymbolType) onto the stack - dynamic context but inside
// the STEADY_STATE operator (the period hasn’t to be indicated)
FSTPV, // Stores a variable (described in SymbolType) from the stack - dynamic context (the period
// has to be indicated)
FSTPSV, // Stores a variable (described in SymbolType) from the stack - static context (the period
// hasn’t to be indicated)
FLDR, // Loads a residual onto the stack
FSTPR, // Stores a residual from the stack
FSTPG, // Stores the derivative of a simple (single-equation) block in simulate mode
FSTPG2, // Stores the derivative matrix of a block in evaluate mode
FUNARY, // A unary operator
FBINARY, // A binary operator
FTRINARY, // A trinary operator
FJMPIFEVAL, // Jump if evaluate = true
FJMP, // Jump
FBEGINBLOCK, // Marks the beginning of a model block
FENDBLOCK, // Marks the end of a model block
FENDEQU, // Marks the last equation of the block; for a block that has to be solved, the
// derivatives appear just after this flag
FEND, // Marks the end of the model code
FNUMEXPR, // Stores the expression type and references
FCALL, // Call an external function
FLDTEF, // Loads the result of an external function onto the stack
FSTPTEF, // Stores the result of an external function from the stack
FLDTEFD, // Loads the result of the 1st derivative of an external function onto the stack
FSTPTEFD, // Stores the result of the 1st derivative of an external function from the stack
FLDTEFDD, // Loads the result of the 2nd derivative of an external function onto the stack
FSTPTEFDD // Stores the result of the 2nd derivative of an external function from the stack
};
enum class ExpressionType
{
TemporaryTerm,
ModelEquation,
FirstEndoDerivative,
FirstExoDerivative,
FirstExodetDerivative,
};
enum class ExternalFunctionCallType
{
levelWithoutDerivative,
levelWithFirstDerivative,
levelWithFirstAndSecondDerivative,
separatelyProvidedFirstDerivative,
numericalFirstDerivative,
separatelyProvidedSecondDerivative,
numericalSecondDerivative
};
class Writer;
struct Instruction
{
const Tag tag;
explicit Instruction(Tag tag_arg) : tag {tag_arg}
{
}
protected:
/* This is a base class, so the destructor should be either public+virtual or
protected+non-virtual. We opt for the latter, because otherwise this class
would no longer be POD; its memory representation would also include
runtime type information, and our crude serialization technique (copying the
whole object from memory) would thus not work. */
~Instruction() = default;
};
template<typename T>
concept IsInstruction = derived_from<T, Instruction>;
struct FLDZ final : public Instruction
{
FLDZ() : Instruction {Tag::FLDZ}
{
}
};
struct FEND final : public Instruction
{
FEND() : Instruction {Tag::FEND}
{
}
};
struct FENDBLOCK final : public Instruction
{
FENDBLOCK() : Instruction {Tag::FENDBLOCK}
{
}
};
struct FENDEQU final : public Instruction
{
FENDEQU() : Instruction {Tag::FENDEQU}
{
}
};
struct FDIMT final : public Instruction
{
const int size;
explicit FDIMT(int size_arg) : Instruction {Tag::FDIMT}, size {size_arg}
{
}
};
struct FDIMST final : public Instruction
{
const int size;
explicit FDIMST(int size_arg) : Instruction {Tag::FDIMST}, size {size_arg}
{
}
};
struct FLDC final : public Instruction
{
const double value;
explicit FLDC(double value_arg) : Instruction {Tag::FLDC}, value {value_arg}
{
}
};
struct FLDU final : public Instruction
{
const int pos;
explicit FLDU(int pos_arg) : Instruction {Tag::FLDU}, pos {pos_arg}
{
}
};
struct FLDSU final : public Instruction
{
const int pos;
explicit FLDSU(int pos_arg) : Instruction {Tag::FLDSU}, pos {pos_arg}
{
}
};
struct FLDR final : public Instruction
{
const int pos;
explicit FLDR(int pos_arg) : Instruction {Tag::FLDR}, pos {pos_arg}
{
}
};
struct FLDT final : public Instruction
{
const int pos;
explicit FLDT(int pos_arg) : Instruction {Tag::FLDT}, pos {pos_arg}
{
}
};
struct FLDST final : public Instruction
{
const int pos;
explicit FLDST(int pos_arg) : Instruction {Tag::FLDST}, pos {pos_arg}
{
}
};
struct FSTPT final : public Instruction
{
const int pos;
explicit FSTPT(int pos_arg) : Instruction {Tag::FSTPT}, pos {pos_arg}
{
}
};
struct FSTPST final : public Instruction
{
const int pos;
explicit FSTPST(int pos_arg) : Instruction {Tag::FSTPST}, pos {pos_arg}
{
}
};
struct FSTPR final : public Instruction
{
const int pos;
explicit FSTPR(int pos_arg) : Instruction {Tag::FSTPR}, pos {pos_arg}
{
}
};
struct FSTPU final : public Instruction
{
const int pos;
explicit FSTPU(int pos_arg) : Instruction {Tag::FSTPU}, pos {pos_arg}
{
}
};
struct FSTPSU final : public Instruction
{
const int pos;
explicit FSTPSU(int pos_arg) : Instruction {Tag::FSTPSU}, pos {pos_arg}
{
}
};
struct FSTPG final : public Instruction
{
explicit FSTPG() : Instruction {Tag::FSTPG}
{
}
};
struct FSTPG2 final : public Instruction
{
const int row, col;
FSTPG2(int row_arg, int col_arg) : Instruction {Tag::FSTPG2}, row {row_arg}, col {col_arg}
{
}
};
struct FUNARY final : public Instruction
{
const UnaryOpcode op_code;
explicit FUNARY(UnaryOpcode op_code_arg) : Instruction {Tag::FUNARY}, op_code {op_code_arg}
{
}
};
struct FBINARY final : public Instruction
{
const BinaryOpcode op_code;
explicit FBINARY(BinaryOpcode op_code_arg) : Instruction {Tag::FBINARY}, op_code {op_code_arg}
{
}
};
struct FTRINARY final : public Instruction
{
const TrinaryOpcode op_code;
explicit FTRINARY(TrinaryOpcode op_code_arg) : Instruction {Tag::FTRINARY}, op_code {op_code_arg}
{
}
};
struct FJMPIFEVAL final : public Instruction
{
const int pos;
explicit FJMPIFEVAL(int pos_arg) : Instruction {Tag::FJMPIFEVAL}, pos {pos_arg}
{
}
};
struct FJMP final : public Instruction
{
const int pos;
explicit FJMP(int pos_arg) : Instruction {Tag::FJMP}, pos {pos_arg}
{
}
};
struct FLDTEF final : public Instruction
{
const int number;
explicit FLDTEF(int number_arg) : Instruction {Tag::FLDTEF}, number {number_arg}
{
}
};
struct FSTPTEF final : public Instruction
{
const int number;
explicit FSTPTEF(int number_arg) : Instruction {Tag::FSTPTEF}, number {number_arg}
{
}
};
struct FLDTEFD final : public Instruction
{
const int indx, row;
FLDTEFD(int indx_arg, int row_arg) : Instruction {Tag::FLDTEFD}, indx {indx_arg}, row {row_arg}
{
}
};
struct FSTPTEFD final : public Instruction
{
const int indx, row;
FSTPTEFD(int indx_arg, int row_arg) : Instruction {Tag::FSTPTEFD}, indx {indx_arg}, row {row_arg}
{
}
};
struct FLDTEFDD final : public Instruction
{
const int indx, row, col;
FLDTEFDD(int indx_arg, int row_arg, int col_arg) :
Instruction {Tag::FLDTEFDD}, indx {indx_arg}, row {row_arg}, col {col_arg}
{
}
};
struct FSTPTEFDD final : public Instruction
{
const int indx, row, col;
FSTPTEFDD(int indx_arg, int row_arg, int col_arg) :
Instruction {Tag::FSTPTEF}, indx {indx_arg}, row {row_arg}, col {col_arg}
{
}
};
struct FLDVS final : public Instruction
{
const SymbolType type;
const int pos;
FLDVS(SymbolType type_arg, int pos_arg) : Instruction {Tag::FLDVS}, type {type_arg}, pos {pos_arg}
{
}
};
struct FLDSV final : public Instruction
{
const SymbolType type;
const int pos;
FLDSV(SymbolType type_arg, int pos_arg) : Instruction {Tag::FLDSV}, type {type_arg}, pos {pos_arg}
{
}
};
struct FSTPSV final : public Instruction
{
const SymbolType type;
const int pos;
FSTPSV(SymbolType type_arg, int pos_arg) :
Instruction {Tag::FSTPSV}, type {type_arg}, pos {pos_arg}
{
}
};
struct FLDV final : public Instruction
{
const SymbolType type;
const int pos, lead_lag;
FLDV(SymbolType type_arg, int pos_arg, int lead_lag_arg) :
Instruction {Tag::FLDV}, type {type_arg}, pos {pos_arg}, lead_lag {lead_lag_arg}
{
}
};
struct FSTPV final : public Instruction
{
const SymbolType type;
const int pos, lead_lag;
FSTPV(SymbolType type_arg, int pos_arg, int lead_lag_arg) :
Instruction {Tag::FSTPV}, type {type_arg}, pos {pos_arg}, lead_lag {lead_lag_arg}
{
}
};
class FCALL final : public Instruction
{
template<IsInstruction B>
friend Writer& operator<<(Writer& code_file, const B& instr);
private:
int nb_output_arguments, nb_input_arguments, indx;
string func_name;
string arg_func_name;
int add_input_arguments {0}, row {0}, col {0};
ExternalFunctionCallType call_type;
public:
FCALL(int nb_output_arguments_arg, int nb_input_arguments_arg, string func_name_arg, int indx_arg,
ExternalFunctionCallType call_type_arg) :
Instruction {Tag::FCALL},
nb_output_arguments {nb_output_arguments_arg},
nb_input_arguments {nb_input_arguments_arg},
indx {indx_arg},
func_name {move(func_name_arg)},
call_type {call_type_arg}
{
}
/* Deserializing constructor.
Updates the code pointer to point beyond the bytes read. */
FCALL(char*& code) : Instruction {Tag::FCALL}
{
code += sizeof(tag);
auto read_member = [&code](auto& member) {
member = *reinterpret_cast<add_pointer_t<decltype(member)>>(code);
code += sizeof member;
};
read_member(nb_output_arguments);
read_member(nb_input_arguments);
read_member(indx);
read_member(add_input_arguments);
read_member(row);
read_member(col);
read_member(call_type);
int size;
read_member(size);
func_name = code;
code += size + 1;
read_member(size);
arg_func_name = code;
code += size + 1;
}
string
get_function_name()
{
// printf("get_function_name => func_name=%s\n",func_name.c_str());fflush(stdout);
return func_name;
}
int
get_nb_output_arguments()
{
return nb_output_arguments;
}
int
get_nb_input_arguments()
{
return nb_input_arguments;
}
int
get_indx()
{
return indx;
}
void
set_arg_func_name(string arg_arg_func_name)
{
arg_func_name = move(arg_arg_func_name);
}
string
get_arg_func_name()
{
return arg_func_name;
}
void
set_nb_add_input_arguments(int arg_add_input_arguments)
{
add_input_arguments = arg_add_input_arguments;
}
int
get_nb_add_input_arguments()
{
return add_input_arguments;
}
void
set_row(int arg_row)
{
row = arg_row;
}
int
get_row()
{
return row;
}
void
set_col(int arg_col)
{
col = arg_col;
}
int
get_col()
{
return col;
}
ExternalFunctionCallType
get_call_type()
{
return call_type;
}
};
class FNUMEXPR final : public Instruction
{
private:
ExpressionType expression_type;
int equation; // Equation number (non-block-specific) (or temporary term number for
// ExpressionType::TemporaryTerm)
int dvariable1; // For derivatives, type-specific ID of the derivation variable
int lag1; // For derivatives, lead/lag of the derivation variable
public:
FNUMEXPR(const ExpressionType expression_type_arg, int equation_arg) :
Instruction {Tag::FNUMEXPR},
expression_type {expression_type_arg},
equation {equation_arg},
dvariable1 {0},
lag1 {0}
{
}
FNUMEXPR(const ExpressionType expression_type_arg, int equation_arg, int dvariable1_arg) :
Instruction {Tag::FNUMEXPR},
expression_type {expression_type_arg},
equation {equation_arg},
dvariable1 {dvariable1_arg},
lag1 {0}
{
}
FNUMEXPR(const ExpressionType expression_type_arg, int equation_arg, int dvariable1_arg,
int lag1_arg) :
Instruction {Tag::FNUMEXPR},
expression_type {expression_type_arg},
equation {equation_arg},
dvariable1 {dvariable1_arg},
lag1 {lag1_arg}
{
}
ExpressionType
get_expression_type()
{
return expression_type;
}
int
get_equation()
{
return equation;
}
int
get_dvariable1()
{
return dvariable1;
}
int
get_lag1()
{
return lag1;
}
};
class FBEGINBLOCK final : public Instruction
{
template<IsInstruction B>
friend Writer& operator<<(Writer& code_file, const B& instr);
private:
int size {0};
BlockSimulationType type;
vector<int> variables;
vector<int> equations;
vector<int> exogenous;
vector<int> det_exogenous;
bool is_linear {false};
int u_count_int {0};
int nb_col_jacob {0};
int det_exo_size, exo_size;
public:
/* Constructor when derivatives w.r.t. exogenous are present (only makes
sense when there is no block-decomposition, since there is no provision for
derivatives w.r.t. endogenous not belonging to the block) */
FBEGINBLOCK(int size_arg, BlockSimulationType type_arg, int first_element, int block_size,
const vector<int>& variables_arg, const vector<int>& equations_arg,
bool is_linear_arg, int u_count_int_arg, int nb_col_jacob_arg, int det_exo_size_arg,
int exo_size_arg, vector<int> det_exogenous_arg, vector<int> exogenous_arg) :
Instruction {Tag::FBEGINBLOCK},
size {size_arg},
type {type_arg},
variables {variables_arg.begin() + first_element,
variables_arg.begin() + (first_element + block_size)},
equations {equations_arg.begin() + first_element,
equations_arg.begin() + (first_element + block_size)},
exogenous {move(exogenous_arg)},
det_exogenous {move(det_exogenous_arg)},
is_linear {is_linear_arg},
u_count_int {u_count_int_arg},
nb_col_jacob {nb_col_jacob_arg},
det_exo_size {det_exo_size_arg},
exo_size {exo_size_arg}
{
}
// Constructor when derivatives w.r.t. exogenous are absent
FBEGINBLOCK(int size_arg, BlockSimulationType type_arg, int first_element, int block_size,
const vector<int>& variables_arg, const vector<int>& equations_arg,
bool is_linear_arg, int u_count_int_arg, int nb_col_jacob_arg) :
Instruction {Tag::FBEGINBLOCK},
size {size_arg},
type {type_arg},
variables {variables_arg.begin() + first_element,
variables_arg.begin() + (first_element + block_size)},
equations {equations_arg.begin() + first_element,
equations_arg.begin() + (first_element + block_size)},
is_linear {is_linear_arg},
u_count_int {u_count_int_arg},
nb_col_jacob {nb_col_jacob_arg},
det_exo_size {0},
exo_size {0}
{
}
/* Deserializing constructor.
Updates the code pointer to point beyond the bytes read. */
FBEGINBLOCK(char*& code) : Instruction {Tag::FBEGINBLOCK}
{
code += sizeof(tag);
auto read_member = [&code](auto& member) {
member = *reinterpret_cast<add_pointer_t<decltype(member)>>(code);
code += sizeof member;
};
read_member(size);
read_member(type);
variables.resize(size);
equations.resize(size);
for (int i {0}; i < size; i++)
{
read_member(variables[i]);
read_member(equations[i]);
}
if (type == BlockSimulationType::solveTwoBoundariesSimple
|| type == BlockSimulationType::solveTwoBoundariesComplete
|| type == BlockSimulationType::solveBackwardComplete
|| type == BlockSimulationType::solveForwardComplete)
{
read_member(is_linear);
read_member(u_count_int);
}
read_member(nb_col_jacob);
read_member(det_exo_size);
read_member(exo_size);
for (int i {0}; i < det_exo_size; i++)
{
int tmp_i;
read_member(tmp_i);
det_exogenous.push_back(tmp_i);
}
for (int i {0}; i < exo_size; i++)
{
int tmp_i;
read_member(tmp_i);
exogenous.push_back(tmp_i);
}
}
int
get_size()
{
return size;
}
BlockSimulationType
get_type()
{
return type;
}
bool
get_is_linear()
{
return is_linear;
}
int
get_u_count_int()
{
return u_count_int;
}
vector<int>
get_variables()
{
return variables;
}
vector<int>
get_equations()
{
return equations;
}
int
get_nb_col_jacob()
{
return nb_col_jacob;
}
int
get_exo_size()
{
return exo_size;
}
int
get_det_exo_size()
{
return det_exo_size;
}
vector<int>
get_exogenous()
{
return exogenous;
}
};
// Superclass of std::ofstream for writing a sequence of bytecode instructions
class Writer : private ofstream
{
template<IsInstruction B>
friend Writer& operator<<(Writer& code_file, const B& instr);
private:
// Stores the positions of all instructions in the byte stream
vector<pos_type> instructions_positions;
public:
Writer(const filesystem::path& filename);
// Returns the number of the next instruction to be written
int
getInstructionCounter() const
{
return static_cast<int>(instructions_positions.size());
}
/* Overwrites an existing instruction, given its number.
It is the responsibility of the caller to ensure that the new instruction
occupies exactly as many bytes as the former one. */
void
overwriteInstruction(int instruction_number, const IsInstruction auto& new_instruction)
{
seekp(instructions_positions.at(instruction_number));
*this << new_instruction;
instructions_positions.pop_back();
seekp(0, ios_base::end);
}
};
// Overloads of operator<< for writing bytecode instructions
template<IsInstruction B>
Writer&
operator<<(Writer& code_file, const B& instr)
{
code_file.instructions_positions.push_back(code_file.tellp());
code_file.write(reinterpret_cast<const char*>(&instr), sizeof(B));
return code_file;
}
template<>
Writer& operator<<(Writer& code_file, const FCALL& instr);
template<>
Writer& operator<<(Writer& code_file, const FBEGINBLOCK& instr);
}
#endif
/*
* Copyright (C) 2007-2018 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CODEINTERPRETER_HH
#define _CODEINTERPRETER_HH
//#define DEBUGL
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <fstream>
#include <cstring>
#include <utility>
#include <vector>
#ifdef LINBCG
# include "linbcg.hh"
#endif
#ifdef BYTE_CODE
# ifndef DEBUG_EX
# include "mex.h"
# else
# include "mex_interface.hh"
# endif
#endif
using namespace std;
const double near_zero{1e-12};
/**
* \enum Tags
* \brief The differents flags of the bytecode
*/
enum Tags
{
FLDZ, //!< Stores zero in the stack - 0 (0)
FLDC, //!< Stores a constant term in the stack - 1 (1)
FDIMT, //!< Defines the number of temporary terms - dynamic context (the period has to be indicated) - 2 (2)
FDIMST, //!< Defines the number of temporary terms - static context (the period hasn't to be indicated) - 3 (3)
FLDT, //!< Stores a temporary term in the stack - dynamic context (the period has to be indicated) - 4 (4)
FLDST, //!< Stores a temporary term in the stack - static context (the period hasn't to be indicated) - 5 (5)
FSTPT, //!< Loads a temporary term from the stack - dynamic context (the period has to be indicated) - 6 (6)
FSTPST, //!< Loads a temporary term from the stack - static context (the period hasn't to be indicated) - 7 (7)
FLDU, //!< Stores an element of the vector U in the stack - dynamic context (the period has to be indicated) - 8 (8)
FLDSU, //!< Stores an element of the vector U in the stack - static context (the period hasn't to be indicated) - 9 (9)
FSTPU, //!< Loads an element of the vector U from the stack - dynamic context (the period has to be indicated) - A (10)
FSTPSU, //!< Loads an element of the vector U from the stack - static context (the period hasn't to be indicated) - B (11)
FLDV, //!< Stores a variable (described in SymbolType) in the stack - dynamic context (the period has to be indicated) - C (12)
FLDSV, //!< Stores a variable (described in SymbolType) in the stack - static context (the period hasn't to be indicated) - D (13)
FLDVS, //!< Stores a variable (described in SymbolType) in the stack - dynamic context but inside the STEADYSTATE function (the period hasn't to be indicated) - E (14)
FSTPV, //!< Loads a variable (described in SymbolType) from the stack - dynamic context (the period has to be indicated) - F (15)
FSTPSV, //!< Loads a variable (described in SymbolType) from the stack - static context (the period hasn't to be indicated) - 10 (16)
FLDR, //!< Stores a residual in the stack - 11 (17)
FSTPR, //!< Loads a residual from the stack - 12 (18)
FSTPG, //!< Loads a derivative from the stack - 13 (19)
FSTPG2, //!< Loads a derivative matrix for static model from the stack - 14 (20)
FSTPG3, //!< Loads a derivative matrix for a dynamic model from the stack - 15 (21)
FSTPG4, //!< Loads a second order derivative matrix for a dynamic model from the stack - 16 (22)
FUNARY, //!< A Unary operator - 17 (23)
FBINARY, //!< A binary operator - 18 (24)
FTRINARY, //!< A trinary operator - 19 (25)
FCUML, //!< Cumulates the result - 1A (26)
FJMPIFEVAL, //!< Jump if evaluate = true - 1B (27)
FJMP, //!< Jump - 1C (28)
FBEGINBLOCK, //!< Defines the begining of a model block - 1D (29)
FENDBLOCK, //!< Defines the end of a model block - 1E (30)
FENDEQU, //!< Defines the last equation of the block. For block that has to be solved, the derivatives appear just after this flag - 1F (31)
FEND, //!< Defines the end of the model code - 20 (32)
FOK, //!< Used for debugging purpose - 21 (33)
FNUMEXPR, //!< Store the expression type and references - 22 (34)
FCALL, //!< Call an external function - 23 (35)
FPUSH, //!< Push a double in the stack - 24 (36)
FPOP, //!< Pop a double from the stack - 25 (37)
FLDTEF, //!< Stores the result of an external function in the stack - 26 (38)
FSTPTEF, //!< Loads the result of an external function from the stack- 27 (39)
FLDTEFD, //!< Stores the result of an external function in the stack - 28 (40)
FSTPTEFD, //!< Loads the result of an external function from the stack- 29 (41)
FLDTEFDD, //!< Stores the result of an external function in the stack - 28 (42)
FSTPTEFDD //!< Loads the result of an external function from the stack- 29 (43)
};
enum BlockType
{
SIMULTANS, //!< Simultaneous time separable block
PROLOGUE, //!< Prologue block (one equation at the beginning, later merged)
EPILOGUE, //!< Epilogue block (one equation at the beginning, later merged)
SIMULTAN //!< Simultaneous time unseparable block
};
enum EquationType
{
E_UNKNOWN, //!< Unknown equation type
E_EVALUATE, //!< Simple evaluation, normalized variable on left-hand side
E_EVALUATE_S, //!< Simple evaluation, normalize using the first order derivative
E_SOLVE //!< No simple evaluation of the equation, it has to be solved
};
enum BlockSimulationType
{
UNKNOWN, //!< Unknown simulation type
EVALUATE_FORWARD, //!< Simple evaluation, normalized variable on left-hand side, forward
EVALUATE_BACKWARD, //!< Simple evaluation, normalized variable on left-hand side, backward
SOLVE_FORWARD_SIMPLE, //!< Block of one equation, newton solver needed, forward
SOLVE_BACKWARD_SIMPLE, //!< Block of one equation, newton solver needed, backward
SOLVE_TWO_BOUNDARIES_SIMPLE, //!< Block of one equation, newton solver needed, forward & ackward
SOLVE_FORWARD_COMPLETE, //!< Block of several equations, newton solver needed, forward
SOLVE_BACKWARD_COMPLETE, //!< Block of several equations, newton solver needed, backward
SOLVE_TWO_BOUNDARIES_COMPLETE //!< Block of several equations, newton solver needed, forward and backwar
};
//! Enumeration of possible symbol types
/*! Warning: do not to change existing values for 0 to 4: the values matter for homotopy_setup command */
enum class SymbolType
{
endogenous = 0, //!< Endogenous
exogenous = 1, //!< Exogenous
exogenousDet = 2, //!< Exogenous deterministic
parameter = 4, //!< Parameter
modelLocalVariable = 10, //!< Local variable whose scope is model (pound expression)
modFileLocalVariable = 11, //!< Local variable whose scope is mod file (model excluded)
externalFunction = 12, //!< External (user-defined) function
trend = 13, //!< Trend variable
statementDeclaredVariable = 14, //!< Local variable assigned within a Statement (see subsample statement for example)
logTrend = 15, //!< Log-trend variable
unusedEndogenous = 16,
endogenousVAR = 17, //!< Variables declared in a var_model statement
endogenousEpilogue = 18, //!< Endogenous Variables used in the epilogue block
exogenousEpilogue = 19, //!< Variables used in the epilogue block
parameterEpilogue = 20 //!< Variables used in the epilogue block
};
enum ExpressionType
{
TemporaryTerm,
ModelEquation,
FirstEndoDerivative,
FirstOtherEndoDerivative,
FirstExoDerivative,
FirstExodetDerivative,
FirstParamDerivative,
SecondEndoDerivative,
SecondExoDerivative,
SecondExodetDerivative,
SecondParamDerivative,
ThirdEndoDerivative,
ThirdExoDerivative,
ThirdExodetDerivative,
ThirdParamDerivative
};
enum class UnaryOpcode
{
uminus,
exp,
log,
log10,
cos,
sin,
tan,
acos,
asin,
atan,
cosh,
sinh,
tanh,
acosh,
asinh,
atanh,
sqrt,
abs,
sign,
steadyState,
steadyStateParamDeriv, // for the derivative of the STEADY_STATE operator w.r.t. to a parameter
steadyStateParam2ndDeriv, // for the 2nd derivative of the STEADY_STATE operator w.r.t. to a parameter
expectation,
erf,
diff,
adl
};
enum class BinaryOpcode
{
plus,
minus,
times,
divide,
power,
powerDeriv, // for the derivative of the power function (see trac ticket #78)
equal,
max,
min,
less,
greater,
lessEqual,
greaterEqual,
equalEqual,
different
};
enum class TrinaryOpcode
{
normcdf,
normpdf
};
enum class ExternalFunctionType
{
withoutDerivative,
withFirstDerivative,
withFirstAndSecondDerivative,
numericalFirstDerivative,
firstDerivative,
numericalSecondDerivative,
secondDerivative
};
enum class PriorDistributions
{
noShape = 0,
beta = 1,
gamma = 2,
normal = 3,
invGamma = 4,
invGamma1 = 4,
uniform = 5,
invGamma2 = 6,
dirichlet = 7,
weibull = 8
};
enum class NodeTreeReference
{
residuals,
firstDeriv,
secondDeriv,
thirdDeriv,
residualsParamsDeriv,
jacobianParamsDeriv,
residualsParamsSecondDeriv,
jacobianParamsSecondDeriv,
hessianParamsDeriv
};
/*! 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 : { NodeTreeReference::residuals, NodeTreeReference::firstDeriv, NodeTreeReference::secondDeriv, NodeTreeReference::thirdDeriv })
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 : { NodeTreeReference::residualsParamsDeriv, NodeTreeReference::jacobianParamsDeriv, NodeTreeReference::residualsParamsSecondDeriv,
NodeTreeReference::jacobianParamsSecondDeriv, NodeTreeReference::hessianParamsDeriv})
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;
};
#pragma pack(push, 1)
class TagWithoutArgument
{
protected:
uint8_t op_code;
public:
inline explicit
TagWithoutArgument(uint8_t op_code_arg) : op_code{op_code_arg}
{
};
inline void
write(ostream &CompileCode, unsigned int &instruction_number)
{
CompileCode.write(reinterpret_cast<char *>(this), sizeof(*this));
instruction_number++;
};
};
template<typename T1>
class TagWithOneArgument
{
protected:
uint8_t op_code;
T1 arg1;
public:
inline explicit
TagWithOneArgument(uint8_t op_code_arg) : op_code{op_code_arg}
{
};
inline
TagWithOneArgument(uint8_t op_code_arg, T1 arg_arg1) : op_code{op_code_arg}, arg1{arg_arg1}
{
};
inline void
write(ostream &CompileCode, unsigned int &instruction_number)
{
CompileCode.write(reinterpret_cast<char *>(this), sizeof(TagWithOneArgument));
instruction_number++;
};
};
template<typename T1, typename T2>
class TagWithTwoArguments
{
protected:
uint8_t op_code;
T1 arg1;
T2 arg2;
public:
inline explicit
TagWithTwoArguments(uint8_t op_code_arg) : op_code{op_code_arg}
{
};
inline
TagWithTwoArguments(uint8_t op_code_arg, T1 arg_arg1, T2 arg_arg2) : op_code{op_code_arg}, arg1{arg_arg1}, arg2{arg_arg2}
{
};
inline void
write(ostream &CompileCode, unsigned int &instruction_number)
{
CompileCode.write(reinterpret_cast<char *>(this), sizeof(*this));
instruction_number++;
};
};
template<typename T1, typename T2, typename T3>
class TagWithThreeArguments
{
protected:
uint8_t op_code;
T1 arg1;
T2 arg2;
T3 arg3;
public:
inline explicit
TagWithThreeArguments(uint8_t op_code_arg) : op_code{op_code_arg}
{
};
inline
TagWithThreeArguments(uint8_t op_code_arg, T1 arg_arg1, T2 arg_arg2, T3 arg_arg3) : op_code{op_code_arg}, arg1{arg_arg1}, arg2{arg_arg2}, arg3{arg_arg3}
{
};
inline void
write(ostream &CompileCode, unsigned int &instruction_number)
{
CompileCode.write(reinterpret_cast<char *>(this), sizeof(*this));
instruction_number++;
};
};
template<typename T1, typename T2, typename T3, typename T4>
class TagWithFourArguments
{
protected:
uint8_t op_code;
T1 arg1;
T2 arg2;
T3 arg3;
T4 arg4;
public:
inline explicit
TagWithFourArguments(uint8_t op_code_arg) : op_code{op_code_arg}
{
};
inline
TagWithFourArguments(uint8_t op_code_arg, T1 arg_arg1, T2 arg_arg2, T3 arg_arg3, T4 arg_arg4) : op_code{op_code_arg}, arg1{arg_arg1}, arg2{arg_arg2}, arg3{move(arg_arg3)}, arg4{arg_arg4}
{
};
inline void
write(ostream &CompileCode, unsigned int &instruction_number)
{
CompileCode.write(reinterpret_cast<char *>(this), sizeof(*this));
instruction_number++;
};
};
class FLDZ_ : public TagWithoutArgument
{
public:
inline
FLDZ_() : TagWithoutArgument{FLDZ}
{
};
};
class FEND_ : public TagWithoutArgument
{
public:
inline
FEND_() : TagWithoutArgument{FEND}
{
};
};
class FENDBLOCK_ : public TagWithoutArgument
{
public:
inline
FENDBLOCK_() : TagWithoutArgument{FENDBLOCK}
{
};
};
class FENDEQU_ : public TagWithoutArgument
{
public:
inline
FENDEQU_() : TagWithoutArgument{FENDEQU}
{
};
};
class FCUML_ : public TagWithoutArgument
{
public:
inline
FCUML_() : TagWithoutArgument{FCUML}
{
};
};
class FPUSH_ : public TagWithoutArgument
{
public:
inline
FPUSH_() : TagWithoutArgument{FPUSH}
{
};
};
class FPOP_ : public TagWithoutArgument
{
public:
inline
FPOP_() : TagWithoutArgument{FPOP}
{
};
};
class FDIMT_ : public TagWithOneArgument<unsigned int>
{
public:
inline
FDIMT_() : TagWithOneArgument<unsigned int>::TagWithOneArgument{FDIMT}
{
};
inline explicit
FDIMT_(unsigned int size_arg) : TagWithOneArgument<unsigned int>::TagWithOneArgument{FDIMT, size_arg}
{
};
inline unsigned int
get_size()
{
return arg1;
};
};
class FDIMST_ : public TagWithOneArgument<unsigned int>
{
public:
inline
FDIMST_() : TagWithOneArgument<unsigned int>::TagWithOneArgument{FDIMST}
{
};
inline explicit
FDIMST_(const unsigned int size_arg) : TagWithOneArgument<unsigned int>::TagWithOneArgument{FDIMST, size_arg}
{
};
inline unsigned int
get_size()
{
return arg1;
};
};
class FLDC_ : public TagWithOneArgument<double>
{
public:
inline
FLDC_() : TagWithOneArgument<double>::TagWithOneArgument{FLDC}
{
};
inline explicit
FLDC_(const double value_arg) : TagWithOneArgument<double>::TagWithOneArgument{FLDC, value_arg}
{
};
inline double
get_value()
{
return arg1;
};
};
class FLDU_ : public TagWithOneArgument<unsigned int>
{
public:
inline
FLDU_() : TagWithOneArgument<unsigned int>::TagWithOneArgument{FLDU}
{
};
inline explicit
FLDU_(const unsigned int pos_arg) : TagWithOneArgument<unsigned int>::TagWithOneArgument{FLDU, pos_arg}
{
};
inline unsigned int
get_pos()
{
return arg1;
};
};
class FLDSU_ : public TagWithOneArgument<unsigned int>
{
public:
inline
FLDSU_() : TagWithOneArgument<unsigned int>::TagWithOneArgument{FLDSU}
{
};
inline explicit
FLDSU_(const unsigned int pos_arg) : TagWithOneArgument<unsigned int>::TagWithOneArgument{FLDSU, pos_arg}
{
};
inline unsigned int
get_pos()
{
return arg1;
};
};
class FLDR_ : public TagWithOneArgument<unsigned int>
{
public:
inline
FLDR_() : TagWithOneArgument<unsigned int>::TagWithOneArgument{FLDR}
{
};
inline explicit
FLDR_(const unsigned int pos_arg) : TagWithOneArgument<unsigned int>::TagWithOneArgument{FLDR, pos_arg}
{
};
inline unsigned int
get_pos()
{
return arg1;
};
};
class FLDT_ : public TagWithOneArgument<unsigned int>
{
public:
inline
FLDT_() : TagWithOneArgument<unsigned int>::TagWithOneArgument{FLDT}
{
};
inline explicit
FLDT_(const unsigned int pos_arg) : TagWithOneArgument<unsigned int>::TagWithOneArgument{FLDT, pos_arg}
{
};
inline unsigned int
get_pos()
{
return arg1;
};
};
class FLDST_ : public TagWithOneArgument<unsigned int>
{
public:
inline
FLDST_() : TagWithOneArgument<unsigned int>::TagWithOneArgument{FLDST}
{
};
inline explicit
FLDST_(const unsigned int pos_arg) : TagWithOneArgument<unsigned int>::TagWithOneArgument{FLDST, pos_arg}
{
};
inline unsigned int
get_pos()
{
return arg1;
};
};
class FSTPT_ : public TagWithOneArgument<unsigned int>
{
public:
inline
FSTPT_() : TagWithOneArgument<unsigned int>::TagWithOneArgument{FSTPT}
{
};
inline explicit
FSTPT_(const unsigned int pos_arg) : TagWithOneArgument<unsigned int>::TagWithOneArgument{FSTPT, pos_arg}
{
};
inline unsigned int
get_pos()
{
return arg1;
};
};
class FSTPST_ : public TagWithOneArgument<unsigned int>
{
public:
inline
FSTPST_() : TagWithOneArgument<unsigned int>::TagWithOneArgument{FSTPST}
{
};
inline explicit
FSTPST_(const unsigned int pos_arg) : TagWithOneArgument<unsigned int>::TagWithOneArgument{FSTPST, pos_arg}
{
};
inline unsigned int
get_pos()
{
return arg1;
};
};
class FSTPR_ : public TagWithOneArgument<unsigned int>
{
public:
inline
FSTPR_() : TagWithOneArgument<unsigned int>::TagWithOneArgument{FSTPR}
{
};
inline explicit
FSTPR_(const unsigned int pos_arg) : TagWithOneArgument<unsigned int>::TagWithOneArgument{FSTPR, pos_arg}
{
};
inline unsigned int
get_pos()
{
return arg1;
};
};
class FSTPU_ : public TagWithOneArgument<unsigned int>
{
public:
inline
FSTPU_() : TagWithOneArgument<unsigned int>::TagWithOneArgument{FSTPU}
{
};
inline explicit
FSTPU_(const unsigned int pos_arg) : TagWithOneArgument<unsigned int>::TagWithOneArgument{FSTPU, pos_arg}
{
};
inline unsigned int
get_pos()
{
return arg1;
};
};
class FSTPSU_ : public TagWithOneArgument<unsigned int>
{
public:
inline
FSTPSU_() : TagWithOneArgument<unsigned int>::TagWithOneArgument{FSTPSU}
{
};
inline explicit
FSTPSU_(const unsigned int pos_arg) : TagWithOneArgument<unsigned int>::TagWithOneArgument{FSTPSU, pos_arg}
{
};
inline unsigned int
get_pos()
{
return arg1;
};
};
class FSTPG_ : public TagWithOneArgument<unsigned int>
{
public:
inline
FSTPG_() : TagWithOneArgument<unsigned int>::TagWithOneArgument{FSTPG, 0}
{
};
inline explicit
FSTPG_(const unsigned int pos_arg) : TagWithOneArgument<unsigned int>::TagWithOneArgument{FSTPG, pos_arg}
{
};
inline unsigned int
get_pos()
{
return arg1;
};
};
class FSTPG2_ : public TagWithTwoArguments<unsigned int, unsigned int>
{
public:
inline
FSTPG2_() : TagWithTwoArguments<unsigned int, unsigned int>::TagWithTwoArguments{FSTPG2, 0, 0}
{
};
inline
FSTPG2_(const unsigned int pos_arg1, const unsigned int pos_arg2) : TagWithTwoArguments<unsigned int, unsigned int>::TagWithTwoArguments{FSTPG2, pos_arg1, pos_arg2}
{
};
inline unsigned int
get_row()
{
return arg1;
};
inline unsigned int
get_col()
{
return arg2;
};
};
class FSTPG3_ : public TagWithFourArguments<unsigned int, unsigned int, int, unsigned int>
{
public:
inline
FSTPG3_() : TagWithFourArguments<unsigned int, unsigned int, int, unsigned int>::TagWithFourArguments{FSTPG3, 0, 0, 0, 0}
{
};
inline
FSTPG3_(const unsigned int pos_arg1, const unsigned int pos_arg2, const int pos_arg3, const unsigned int pos_arg4) : TagWithFourArguments<unsigned int, unsigned int, int, unsigned int>::TagWithFourArguments{FSTPG3, pos_arg1, pos_arg2, pos_arg3, pos_arg4}
{
};
inline unsigned int
get_row()
{
return arg1;
};
inline unsigned int
get_col()
{
return arg2;
};
inline int
get_lag()
{
return arg2;
};
inline unsigned int
get_col_pos()
{
return arg4;
};
};
class FUNARY_ : public TagWithOneArgument<uint8_t>
{
public:
inline
FUNARY_() : TagWithOneArgument<uint8_t>::TagWithOneArgument{FUNARY}
{
};
inline explicit
FUNARY_(uint8_t op_type_arg) : TagWithOneArgument<uint8_t>::TagWithOneArgument{FUNARY, op_type_arg}
{
};
inline uint8_t
get_op_type()
{
return arg1;
};
};
class FBINARY_ : public TagWithOneArgument<uint8_t>
{
public:
inline
FBINARY_() : TagWithOneArgument<uint8_t>::TagWithOneArgument{FBINARY}
{
};
inline explicit
FBINARY_(const int op_type_arg) : TagWithOneArgument<uint8_t>::TagWithOneArgument{FBINARY, static_cast<uint8_t>(op_type_arg)}
{
};
inline uint8_t
get_op_type()
{
return arg1;
};
};
class FTRINARY_ : public TagWithOneArgument<uint8_t>
{
public:
inline
FTRINARY_() : TagWithOneArgument<uint8_t>::TagWithOneArgument{FTRINARY}
{
};
inline explicit
FTRINARY_(const int op_type_arg) : TagWithOneArgument<uint8_t>::TagWithOneArgument{FTRINARY, static_cast<uint8_t>(op_type_arg)}
{
};
inline uint8_t
get_op_type()
{
return arg1;
};
};
class FOK_ : public TagWithOneArgument<int>
{
public:
inline
FOK_() : TagWithOneArgument<int>::TagWithOneArgument{FOK}
{
};
inline explicit
FOK_(const int arg_arg) : TagWithOneArgument<int>::TagWithOneArgument{FOK, arg_arg}
{
};
inline int
get_arg()
{
return arg1;
};
};
class FJMPIFEVAL_ : public TagWithOneArgument<unsigned int>
{
public:
inline
FJMPIFEVAL_() : TagWithOneArgument<unsigned int>::TagWithOneArgument{FJMPIFEVAL}
{
};
inline explicit
FJMPIFEVAL_(unsigned int arg_pos) : TagWithOneArgument<unsigned int>::TagWithOneArgument{FJMPIFEVAL, arg_pos}
{
};
inline unsigned int
get_pos()
{
return arg1;
}
};
class FJMP_ : public TagWithOneArgument<unsigned int>
{
public:
inline
FJMP_() : TagWithOneArgument<unsigned int>::TagWithOneArgument{FJMP}
{
};
inline explicit
FJMP_(unsigned int arg_pos) : TagWithOneArgument<unsigned int>::TagWithOneArgument{FJMP, arg_pos}
{
};
inline unsigned int
get_pos()
{
return arg1;
}
};
class FLDTEF_ : public TagWithOneArgument<unsigned int>
{
public:
inline
FLDTEF_() : TagWithOneArgument<unsigned int>::TagWithOneArgument{FLDTEF}
{
};
inline explicit
FLDTEF_(unsigned int number) : TagWithOneArgument<unsigned int>::TagWithOneArgument{FLDTEF, number}
{
};
inline unsigned int
get_number()
{
return arg1;
}
};
class FSTPTEF_ : public TagWithOneArgument<unsigned int>
{
public:
inline
FSTPTEF_() : TagWithOneArgument<unsigned int>::TagWithOneArgument{FSTPTEF}
{
};
inline explicit
FSTPTEF_(unsigned int number) : TagWithOneArgument<unsigned int>::TagWithOneArgument{FSTPTEF, number}
{
};
inline unsigned int
get_number()
{
return arg1;
}
};
class FLDTEFD_ : public TagWithTwoArguments<unsigned int, unsigned int>
{
public:
inline
FLDTEFD_() : TagWithTwoArguments<unsigned int, unsigned int>::TagWithTwoArguments{FLDTEFD}
{
};
inline
FLDTEFD_(unsigned int indx, unsigned int row) : TagWithTwoArguments<unsigned int, unsigned int>::TagWithTwoArguments{FLDTEFD, indx, row}
{
};
inline unsigned int
get_indx()
{
return arg1;
};
inline unsigned int
get_row()
{
return arg2;
};
};
class FSTPTEFD_ : public TagWithTwoArguments<unsigned int, unsigned int>
{
public:
inline
FSTPTEFD_() : TagWithTwoArguments<unsigned int, unsigned int>::TagWithTwoArguments{FSTPTEFD}
{
};
inline
FSTPTEFD_(unsigned int indx, unsigned int row) : TagWithTwoArguments<unsigned int, unsigned int>::TagWithTwoArguments{FSTPTEFD, indx, row}
{
};
inline unsigned int
get_indx()
{
return arg1;
};
inline unsigned int
get_row()
{
return arg2;
};
};
class FLDTEFDD_ : public TagWithThreeArguments<unsigned int, unsigned int, unsigned int>
{
public:
inline
FLDTEFDD_() : TagWithThreeArguments<unsigned int, unsigned int, unsigned int>::TagWithThreeArguments{FLDTEFDD}
{
};
inline
FLDTEFDD_(unsigned int indx, unsigned int row, unsigned int col) : TagWithThreeArguments<unsigned int, unsigned int, unsigned int>::TagWithThreeArguments{FLDTEFDD, indx, row, col}
{
};
inline unsigned int
get_indx()
{
return arg1;
};
inline unsigned int
get_row()
{
return arg2;
};
inline unsigned int
get_col()
{
return arg3;
};
};
class FSTPTEFDD_ : public TagWithThreeArguments<unsigned int, unsigned int, unsigned int>
{
public:
inline
FSTPTEFDD_() : TagWithThreeArguments<unsigned int, unsigned int, unsigned int>::TagWithThreeArguments{FSTPTEFDD}
{
};
inline
FSTPTEFDD_(unsigned int indx, unsigned int row, unsigned int col) : TagWithThreeArguments<unsigned int, unsigned int, unsigned int>::TagWithThreeArguments{FSTPTEF, indx, row, col}
{
};
inline unsigned int
get_indx()
{
return arg1;
};
inline unsigned int
get_row()
{
return arg2;
};
inline unsigned int
get_col()
{
return arg3;
};
};
class FLDVS_ : public TagWithTwoArguments<uint8_t, unsigned int>
{
public:
inline
FLDVS_() : TagWithTwoArguments<uint8_t, unsigned int>::TagWithTwoArguments{FLDVS}
{
};
inline
FLDVS_(uint8_t type_arg, const unsigned int pos_arg) : TagWithTwoArguments<uint8_t, unsigned int>::TagWithTwoArguments{FLDVS, type_arg, pos_arg}
{
};
inline uint8_t
get_type()
{
return arg1;
};
inline unsigned int
get_pos()
{
return arg2;
};
};
class FLDSV_ : public TagWithTwoArguments<uint8_t, unsigned int>
{
public:
inline
FLDSV_() : TagWithTwoArguments<uint8_t, unsigned int>::TagWithTwoArguments{FLDSV}
{
};
inline
FLDSV_(const uint8_t type_arg, const unsigned int pos_arg) :
TagWithTwoArguments<uint8_t, unsigned int>::TagWithTwoArguments{FLDSV, type_arg, pos_arg}
{
};
inline uint8_t
get_type()
{
return arg1;
};
inline unsigned int
get_pos()
{
return arg2;
};
};
class FSTPSV_ : public TagWithTwoArguments<uint8_t, unsigned int>
{
public:
inline
FSTPSV_() : TagWithTwoArguments<uint8_t, unsigned int>::TagWithTwoArguments{FSTPSV}
{
};
inline
FSTPSV_(const uint8_t type_arg, const unsigned int pos_arg) :
TagWithTwoArguments<uint8_t, unsigned int>::TagWithTwoArguments{FSTPSV, type_arg, pos_arg}
{
};
inline uint8_t
get_type()
{
return arg1;
};
inline unsigned int
get_pos()
{
return arg2;
};
};
class FLDV_ : public TagWithThreeArguments<uint8_t, unsigned int, int>
{
public:
inline
FLDV_() : TagWithThreeArguments<uint8_t, unsigned int, int>::TagWithThreeArguments{FLDV}
{
};
inline
FLDV_(const int type_arg, const unsigned int pos_arg) :
TagWithThreeArguments<uint8_t, unsigned int, int>::TagWithThreeArguments{FLDV, static_cast<uint8_t>(type_arg), pos_arg, 0}
{
};
inline
FLDV_(const int type_arg, const unsigned int pos_arg, const int lead_lag_arg) :
TagWithThreeArguments<uint8_t, unsigned int, int>::TagWithThreeArguments{FLDV, static_cast<uint8_t>(type_arg), pos_arg, lead_lag_arg}
{
};
inline uint8_t
get_type()
{
return arg1;
};
inline unsigned int
get_pos()
{
return arg2;
};
inline int
get_lead_lag()
{
return arg3;
};
};
class FSTPV_ : public TagWithThreeArguments<uint8_t, unsigned int, int>
{
public:
inline
FSTPV_() : TagWithThreeArguments<uint8_t, unsigned int, int>::TagWithThreeArguments{FSTPV}
{
};
inline
FSTPV_(const int type_arg, const unsigned int pos_arg) :
TagWithThreeArguments<uint8_t, unsigned int, int>::TagWithThreeArguments{FSTPV, static_cast<uint8_t>(type_arg), pos_arg, 0}
{
};
inline
FSTPV_(const int type_arg, const unsigned int pos_arg, const int lead_lag_arg) :
TagWithThreeArguments<uint8_t, unsigned int, int>::TagWithThreeArguments{FSTPV, static_cast<uint8_t>(type_arg), pos_arg, lead_lag_arg}
{
};
inline uint8_t
get_type()
{
return arg1;
};
inline unsigned int
get_pos()
{
return arg2;
};
inline int
get_lead_lag()
{
return arg3;
};
};
class FCALL_ : public TagWithFourArguments<unsigned int, unsigned int, string, unsigned int>
{
string func_name;
string arg_func_name;
unsigned int add_input_arguments, row, col;
ExternalFunctionType function_type;
public:
inline
FCALL_() : TagWithFourArguments<unsigned int, unsigned int, string, unsigned int>::TagWithFourArguments{FCALL}
{
arg_func_name = "";
add_input_arguments = 0;
row = 0;
col = 0;
function_type = ExternalFunctionType::withoutDerivative;
};
inline
FCALL_(unsigned int nb_output_arguments, unsigned int nb_input_arguments, string f_name, unsigned int indx) :
TagWithFourArguments<unsigned int, unsigned int, string, unsigned int>::TagWithFourArguments{FCALL, nb_output_arguments, nb_input_arguments, f_name, indx}
{
arg_func_name = "";
add_input_arguments = 0;
row = 0;
col = 0;
function_type = ExternalFunctionType::withoutDerivative;
func_name = f_name;
};
inline string
get_function_name()
{
//printf("get_function_name => func_name=%s\n",func_name.c_str());fflush(stdout);
return func_name;
};
inline unsigned int
get_nb_output_arguments()
{
return arg1;
};
inline unsigned int
get_nb_input_arguments()
{
return arg2;
};
inline unsigned int
get_indx()
{
return arg4;
};
inline void
set_arg_func_name(string arg_arg_func_name)
{
arg_func_name = arg_arg_func_name;
};
inline string
get_arg_func_name()
{
return arg_func_name;
};
inline void
set_nb_add_input_arguments(unsigned int arg_add_input_arguments)
{
add_input_arguments = arg_add_input_arguments;
};
inline unsigned int
get_nb_add_input_arguments()
{
return add_input_arguments;
};
inline void
set_row(unsigned int arg_row)
{
row = arg_row;
};
inline unsigned int
get_row()
{
return row;
}
inline void
set_col(unsigned int arg_col)
{
col = arg_col;
};
inline unsigned int
get_col()
{
return col;
};
inline void
set_function_type(ExternalFunctionType arg_function_type)
{
function_type = arg_function_type;
};
inline ExternalFunctionType
get_function_type()
{
return (function_type);
}
inline void
write(ostream &CompileCode, unsigned int &instruction_number)
{
CompileCode.write(reinterpret_cast<char *>(&op_code), sizeof(op_code));
CompileCode.write(reinterpret_cast<char *>(&arg1), sizeof(arg1));
CompileCode.write(reinterpret_cast<char *>(&arg2), sizeof(arg2));
CompileCode.write(reinterpret_cast<char *>(&arg4), sizeof(arg4));
CompileCode.write(reinterpret_cast<char *>(&add_input_arguments), sizeof(add_input_arguments));
CompileCode.write(reinterpret_cast<char *>(&row), sizeof(row));
CompileCode.write(reinterpret_cast<char *>(&col), sizeof(col));
CompileCode.write(reinterpret_cast<char *>(&function_type), sizeof(function_type));
size_t size = func_name.size();
CompileCode.write(reinterpret_cast<char *>(&size), sizeof(int));
const char *name = func_name.c_str();
CompileCode.write(reinterpret_cast<const char *>(name), func_name.size());
size = arg_func_name.size();
CompileCode.write(reinterpret_cast<char *>(&size), sizeof(int));
name = arg_func_name.c_str();
CompileCode.write(reinterpret_cast<const char *>(name), arg_func_name.size());
instruction_number++;
};
#ifdef BYTE_CODE
inline uint8_t *
load(uint8_t *code)
{
op_code = FCALL; code += sizeof(op_code);
memcpy(&arg1, code, sizeof(arg1)); code += sizeof(arg1);
memcpy(&arg2, code, sizeof(arg2)); code += sizeof(arg2);
memcpy(&arg4, code, sizeof(arg4)); code += sizeof(arg4);
memcpy(&add_input_arguments, code, sizeof(add_input_arguments)); code += sizeof(add_input_arguments);
memcpy(&row, code, sizeof(row)); code += sizeof(row);
memcpy(&col, code, sizeof(col)); code += sizeof(col);
memcpy(&function_type, code, sizeof(function_type)); code += sizeof(function_type);
int size;
memcpy(&size, code, sizeof(size)); code += sizeof(size);
char *name = (char *) mxMalloc((size+1)*sizeof(char));
memcpy(name, code, size); code += size;
name[size] = 0;
func_name = name;
mxFree(name);
memcpy(&size, code, sizeof(size)); code += sizeof(size);
name = (char *) mxMalloc((size+1)*sizeof(char));
memcpy(name, code, size); code += size;
name[size] = 0;
arg_func_name = name;
mxFree(name);
return code;
}
#endif
};
class FNUMEXPR_ : public TagWithOneArgument<ExpressionType>
{
private:
unsigned int equation;
uint16_t dvariable1, dvariable2, dvariable3;
int8_t lag1, lag2, lag3;
public:
inline
FNUMEXPR_() : TagWithOneArgument<ExpressionType>::TagWithOneArgument{FNUMEXPR}
{
};
inline
FNUMEXPR_(const ExpressionType expression_type, unsigned int equation_arg) :
TagWithOneArgument<ExpressionType>::TagWithOneArgument{FNUMEXPR, expression_type},
equation{equation_arg},
dvariable1{0}, dvariable2{0}, dvariable3{0},
lag1{0}, lag2{0}, lag3{0}
{
};
inline
FNUMEXPR_(const ExpressionType expression_type, unsigned int equation_arg, unsigned int dvariable1_arg) :
TagWithOneArgument<ExpressionType>::TagWithOneArgument{FNUMEXPR, expression_type},
equation{equation_arg},
dvariable1{static_cast<uint16_t>(dvariable1_arg)}, dvariable2{0}, dvariable3{0},
lag1{0}, lag2{0}, lag3{0}
{
};
inline
FNUMEXPR_(const ExpressionType expression_type, unsigned int equation_arg, unsigned int dvariable1_arg, int lag1_arg) :
TagWithOneArgument<ExpressionType>::TagWithOneArgument{FNUMEXPR, expression_type},
equation{equation_arg},
dvariable1{static_cast<uint16_t>(dvariable1_arg)}, dvariable2{0}, dvariable3{0},
lag1{static_cast<int8_t>(lag1_arg)}, lag2{0}, lag3{0}
{
};
inline
FNUMEXPR_(const ExpressionType expression_type, unsigned int equation_arg, unsigned int dvariable1_arg, unsigned int dvariable2_arg) :
TagWithOneArgument<ExpressionType>::TagWithOneArgument{FNUMEXPR, expression_type},
equation{equation_arg},
dvariable1{static_cast<uint16_t>(dvariable1_arg)},
dvariable2{static_cast<uint16_t>(dvariable2_arg)},
dvariable3{0},
lag1{0}, lag2{0}, lag3{0}
{
};
inline
FNUMEXPR_(const ExpressionType expression_type, unsigned int equation_arg, unsigned int dvariable1_arg, int lag1_arg, unsigned int dvariable2_arg, int lag2_arg) :
TagWithOneArgument<ExpressionType>::TagWithOneArgument{FNUMEXPR, expression_type},
equation{equation_arg},
dvariable1{static_cast<uint16_t>(dvariable1_arg)},
dvariable2{static_cast<uint16_t>(dvariable2_arg)},
dvariable3{0},
lag1{static_cast<int8_t>(lag1_arg)},
lag2{static_cast<int8_t>(lag2_arg)},
lag3{0}
{
};
inline
FNUMEXPR_(const ExpressionType expression_type, unsigned int equation_arg, unsigned int dvariable1_arg, unsigned int dvariable2_arg, unsigned int dvariable3_arg) :
TagWithOneArgument<ExpressionType>::TagWithOneArgument{FNUMEXPR, expression_type},
equation{equation_arg},
dvariable1{static_cast<uint16_t>(dvariable1_arg)},
dvariable2{static_cast<uint16_t>(dvariable2_arg)},
dvariable3{static_cast<uint16_t>(dvariable3_arg)},
lag1{0}, lag2{0}, lag3{0}
{
};
inline
FNUMEXPR_(const ExpressionType expression_type, unsigned int equation_arg, unsigned int dvariable1_arg, int lag1_arg, unsigned int dvariable2_arg, int lag2_arg, unsigned int dvariable3_arg, int lag3_arg) :
TagWithOneArgument<ExpressionType>::TagWithOneArgument{FNUMEXPR, expression_type},
equation{equation_arg},
dvariable1{static_cast<uint16_t>(dvariable1_arg)},
dvariable2{static_cast<uint16_t>(dvariable2_arg)},
dvariable3{static_cast<uint16_t>(dvariable3_arg)},
lag1{static_cast<int8_t>(lag1_arg)},
lag2{static_cast<int8_t>(lag2_arg)},
lag3{static_cast<int8_t>(lag3_arg)}
{
};
inline ExpressionType
get_expression_type()
{
return arg1;
}
inline unsigned int
get_equation()
{
return equation;
};
inline unsigned int
get_dvariable1()
{
return dvariable1;
};
inline int
get_lag1()
{
return lag1;
};
inline unsigned int
get_dvariable2()
{
return dvariable2;
};
inline int
get_lag2()
{
return lag2;
};
inline unsigned int
get_dvariable3()
{
return dvariable3;
};
inline int
get_lag3()
{
return lag3;
};
inline void
write(ostream &CompileCode, unsigned int &instruction_number)
{
CompileCode.write(reinterpret_cast<char *>(this), sizeof(FNUMEXPR_));
instruction_number++;
};
};
class FBEGINBLOCK_
{
private:
uint8_t op_code{FBEGINBLOCK};
int size;
uint8_t type;
vector<int> variable;
vector<int> equation;
vector<unsigned int> other_endogenous;
vector<unsigned int> exogenous;
vector<unsigned int> det_exogenous;
bool is_linear;
vector<Block_contain_type> Block_Contain_;
int endo_nbr;
int Max_Lag;
int Max_Lead;
int u_count_int;
int nb_col_jacob;
unsigned int det_exo_size, exo_size, other_endo_size;
unsigned int nb_col_det_exo_jacob, nb_col_exo_jacob, nb_col_other_endo_jacob;
public:
inline
FBEGINBLOCK_() : size{0}, type{UNKNOWN},
is_linear{false}, endo_nbr{0}, Max_Lag{0}, Max_Lead{0}, u_count_int{0}, nb_col_jacob{0}
{
}
inline
FBEGINBLOCK_(unsigned int size_arg, BlockSimulationType type_arg, int unsigned first_element, int unsigned block_size,
const vector<int> &variable_arg, const vector<int> &equation_arg,
bool is_linear_arg, int endo_nbr_arg, int Max_Lag_arg, int Max_Lead_arg, int &u_count_int_arg, int nb_col_jacob_arg,
unsigned int det_exo_size_arg, unsigned int nb_col_det_exo_jacob_arg, unsigned int exo_size_arg, unsigned int nb_col_exo_jacob_arg, unsigned int other_endo_size_arg, unsigned int nb_col_other_endo_jacob_arg,
const vector<unsigned int> &det_exogenous_arg, const vector<unsigned int> &exogenous_arg, const vector<unsigned int> &other_endogenous_arg) :
size{static_cast<int>(size_arg)},
type{static_cast<uint8_t>(type_arg)},
variable{variable_arg.begin()+first_element, variable_arg.begin()+(first_element+block_size)},
equation{equation_arg.begin()+first_element, equation_arg.begin()+(first_element+block_size)},
other_endogenous{other_endogenous_arg},
exogenous{exogenous_arg},
det_exogenous{det_exogenous_arg},
is_linear{is_linear_arg},
endo_nbr{endo_nbr_arg},
Max_Lag{Max_Lag_arg},
Max_Lead{Max_Lead_arg},
u_count_int{u_count_int_arg},
nb_col_jacob{nb_col_jacob_arg},
det_exo_size{det_exo_size_arg},
exo_size{exo_size_arg},
other_endo_size{other_endo_size_arg},
nb_col_det_exo_jacob{nb_col_det_exo_jacob_arg},
nb_col_exo_jacob{nb_col_exo_jacob_arg},
nb_col_other_endo_jacob{nb_col_other_endo_jacob_arg}
{
}
inline
FBEGINBLOCK_(unsigned int size_arg, BlockSimulationType type_arg, int unsigned first_element, int unsigned block_size,
const vector<int> &variable_arg, const vector<int> &equation_arg,
bool is_linear_arg, int endo_nbr_arg, int Max_Lag_arg, int Max_Lead_arg, int &u_count_int_arg, int nb_col_jacob_arg) :
size{static_cast<int>(size_arg)},
type{static_cast<uint8_t>(type_arg)},
variable{variable_arg.begin()+first_element, variable_arg.begin()+(first_element+block_size)},
equation{equation_arg.begin()+first_element, equation_arg.begin()+(first_element+block_size)},
is_linear{is_linear_arg},
endo_nbr{endo_nbr_arg},
Max_Lag{Max_Lag_arg},
Max_Lead{Max_Lead_arg},
u_count_int{u_count_int_arg},
nb_col_jacob{nb_col_jacob_arg},
det_exo_size{0},
exo_size{0},
other_endo_size{0},
nb_col_det_exo_jacob{0},
nb_col_exo_jacob{0},
nb_col_other_endo_jacob{0}
{
}
inline unsigned int
get_size()
{
return size;
};
inline uint8_t
get_type()
{
return type;
};
inline bool
get_is_linear()
{
return is_linear;
};
inline int
get_endo_nbr()
{
return endo_nbr;
};
inline int
get_Max_Lag()
{
return Max_Lag;
};
inline int
get_Max_Lead()
{
return Max_Lead;
};
inline int
get_u_count_int()
{
return u_count_int;
};
inline vector<Block_contain_type>
get_Block_Contain()
{
return Block_Contain_;
};
inline int
get_nb_col_jacob()
{
return nb_col_jacob;
};
inline unsigned int
get_exo_size()
{
return exo_size;
};
inline unsigned int
get_nb_col_exo_jacob()
{
return nb_col_exo_jacob;
};
inline unsigned int
get_det_exo_size()
{
return det_exo_size;
};
inline unsigned int
get_nb_col_det_exo_jacob()
{
return nb_col_det_exo_jacob;
};
inline unsigned int
get_other_endo_size()
{
return other_endo_size;
};
inline unsigned int
get_nb_col_other_endo_jacob()
{
return nb_col_other_endo_jacob;
};
inline vector<int>
get_endogenous()
{
return variable;
}
inline vector<unsigned int>
get_exogenous()
{
return exogenous;
}
inline void
write(ostream &CompileCode, unsigned int &instruction_number)
{
CompileCode.write(reinterpret_cast<char *>(&op_code), sizeof(op_code));
CompileCode.write(reinterpret_cast<char *>(&size), sizeof(size));
CompileCode.write(reinterpret_cast<char *>(&type), sizeof(type));
for (int i = 0; i < size; i++)
{
CompileCode.write(reinterpret_cast<char *>(&variable[i]), sizeof(variable[0]));
CompileCode.write(reinterpret_cast<char *>(&equation[i]), sizeof(equation[0]));
}
if (type == SOLVE_TWO_BOUNDARIES_SIMPLE || type == SOLVE_TWO_BOUNDARIES_COMPLETE
|| type == SOLVE_BACKWARD_COMPLETE || type == SOLVE_FORWARD_COMPLETE)
{
CompileCode.write(reinterpret_cast<char *>(&is_linear), sizeof(is_linear));
CompileCode.write(reinterpret_cast<char *>(&endo_nbr), sizeof(endo_nbr));
CompileCode.write(reinterpret_cast<char *>(&Max_Lag), sizeof(Max_Lag));
CompileCode.write(reinterpret_cast<char *>(&Max_Lead), sizeof(Max_Lead));
CompileCode.write(reinterpret_cast<char *>(&u_count_int), sizeof(u_count_int));
}
CompileCode.write(reinterpret_cast<char *>(&nb_col_jacob), sizeof(nb_col_jacob));
CompileCode.write(reinterpret_cast<char *>(&det_exo_size), sizeof(det_exo_size));
CompileCode.write(reinterpret_cast<char *>(&nb_col_det_exo_jacob), sizeof(nb_col_det_exo_jacob));
CompileCode.write(reinterpret_cast<char *>(&exo_size), sizeof(exo_size));
CompileCode.write(reinterpret_cast<char *>(&nb_col_exo_jacob), sizeof(nb_col_exo_jacob));
CompileCode.write(reinterpret_cast<char *>(&other_endo_size), sizeof(other_endo_size));
CompileCode.write(reinterpret_cast<char *>(&nb_col_other_endo_jacob), sizeof(nb_col_other_endo_jacob));
for (unsigned int i = 0; i < det_exo_size; i++)
CompileCode.write(reinterpret_cast<char *>(&det_exogenous[i]), sizeof(det_exogenous[0]));
for (unsigned int i = 0; i < exo_size; i++)
CompileCode.write(reinterpret_cast<char *>(&exogenous[i]), sizeof(exogenous[0]));
for (unsigned int i = 0; i < other_endo_size; i++)
CompileCode.write(reinterpret_cast<char *>(&other_endogenous[i]), sizeof(other_endogenous[0]));
instruction_number++;
};
#ifdef BYTE_CODE
inline uint8_t *
load(uint8_t *code)
{
op_code = FBEGINBLOCK; code += sizeof(op_code);
memcpy(&size, code, sizeof(size)); code += sizeof(size);
memcpy(&type, code, sizeof(type)); code += sizeof(type);
for (int i = 0; i < size; i++)
{
Block_contain_type bc;
memcpy(&bc.Variable, code, sizeof(bc.Variable)); code += sizeof(bc.Variable);
memcpy(&bc.Equation, code, sizeof(bc.Equation)); code += sizeof(bc.Equation);
Block_Contain_.push_back(bc);
}
if (type == SOLVE_TWO_BOUNDARIES_SIMPLE || type == SOLVE_TWO_BOUNDARIES_COMPLETE
|| type == SOLVE_BACKWARD_COMPLETE || type == SOLVE_FORWARD_COMPLETE)
{
memcpy(&is_linear, code, sizeof(is_linear)); code += sizeof(is_linear);
memcpy(&endo_nbr, code, sizeof(endo_nbr)); code += sizeof(endo_nbr);
memcpy(&Max_Lag, code, sizeof(Max_Lag)); code += sizeof(Max_Lag);
memcpy(&Max_Lead, code, sizeof(Max_Lead)); code += sizeof(Max_Lead);
memcpy(&u_count_int, code, sizeof(u_count_int)); code += sizeof(u_count_int);
}
memcpy(&nb_col_jacob, code, sizeof(nb_col_jacob)); code += sizeof(nb_col_jacob);
memcpy(&det_exo_size, code, sizeof(det_exo_size)); code += sizeof(det_exo_size);
memcpy(&nb_col_det_exo_jacob, code, sizeof(nb_col_det_exo_jacob)); code += sizeof(nb_col_det_exo_jacob);
memcpy(&exo_size, code, sizeof(exo_size)); code += sizeof(exo_size);
memcpy(&nb_col_exo_jacob, code, sizeof(nb_col_exo_jacob)); code += sizeof(nb_col_exo_jacob);
memcpy(&other_endo_size, code, sizeof(other_endo_size)); code += sizeof(other_endo_size);
memcpy(&nb_col_other_endo_jacob, code, sizeof(nb_col_other_endo_jacob)); code += sizeof(nb_col_other_endo_jacob);
for (unsigned int i = 0; i < det_exo_size; i++)
{
unsigned int tmp_i;
memcpy(&tmp_i, code, sizeof(tmp_i)); code += sizeof(tmp_i);
det_exogenous.push_back(tmp_i);
}
for (unsigned int i = 0; i < exo_size; i++)
{
unsigned int tmp_i;
memcpy(&tmp_i, code, sizeof(tmp_i)); code += sizeof(tmp_i);
exogenous.push_back(tmp_i);
}
for (unsigned int i = 0; i < other_endo_size; i++)
{
unsigned int tmp_i;
memcpy(&tmp_i, code, sizeof(tmp_i)); code += sizeof(tmp_i);
other_endogenous.push_back(tmp_i);
}
return code;
};
#endif
};
#ifdef BYTE_CODE
using tags_liste_t = vector<pair<Tags, void * >>;
class CodeLoad
{
private:
uint8_t *code;
unsigned int nb_blocks;
vector<size_t> begin_block;
public:
inline unsigned int
get_block_number()
{
return nb_blocks;
};
size_t inline
get_begin_block(int block)
{
return begin_block[block];
}
inline void *
get_current_code()
{
return code;
};
inline tags_liste_t
get_op_code(string file_name)
{
tags_liste_t tags_liste;
ifstream CompiledCode;
streamoff Code_Size;
CompiledCode.open(file_name + ".cod", std::ios::in | std::ios::binary| std::ios::ate);
if (!CompiledCode.is_open())
{
return tags_liste;
}
Code_Size = CompiledCode.tellg();
CompiledCode.seekg(std::ios::beg);
code = (uint8_t *) mxMalloc(Code_Size);
CompiledCode.seekg(0);
CompiledCode.read(reinterpret_cast<char *>(code), Code_Size);
CompiledCode.close();
nb_blocks = 0;
bool done = false;
int instruction = 0;
while (!done)
{
switch (*code)
{
case FLDZ:
# ifdef DEBUGL
mexPrintf("FLDZ = %d size = %d\n", FLDZ, sizeof(FLDZ_));
# endif
tags_liste.emplace_back(FLDZ, code);
code += sizeof(FLDZ_);
break;
case FEND:
# ifdef DEBUGL
mexPrintf("FEND\n");
# endif
tags_liste.emplace_back(FEND, code);
code += sizeof(FEND_);
done = true;
break;
case FENDBLOCK:
# ifdef DEBUGL
mexPrintf("FENDBLOCK\n");
# endif
tags_liste.emplace_back(FENDBLOCK, code);
code += sizeof(FENDBLOCK_);
break;
case FENDEQU:
# ifdef DEBUGL
mexPrintf("FENDEQU\n");
# endif
tags_liste.emplace_back(FENDEQU, code);
code += sizeof(FENDEQU_);
break;
case FCUML:
# ifdef DEBUGL
mexPrintf("FCUML\n");
# endif
tags_liste.emplace_back(FCUML, code);
code += sizeof(FCUML_);
break;
case FDIMT:
# ifdef DEBUGL
mexPrintf("FDIMT = %d size = %d\n", FDIMT, sizeof(FDIMT_));
# endif
tags_liste.emplace_back(FDIMT, code);
code += sizeof(FDIMT_);
break;
case FDIMST:
# ifdef DEBUGL
mexPrintf("FDIMST\n");
# endif
tags_liste.emplace_back(FDIMST, code);
code += sizeof(FDIMST_);
break;
case FNUMEXPR:
# ifdef DEBUGL
mexPrintf("FNUMEXPR\n");
# endif
tags_liste.emplace_back(FNUMEXPR, code);
code += sizeof(FNUMEXPR_);
break;
case FLDC:
# ifdef DEBUGL
mexPrintf("FLDC\n");
# endif
tags_liste.emplace_back(FLDC, code);
code += sizeof(FLDC_);
break;
case FLDU:
# ifdef DEBUGL
mexPrintf("FLDU\n");
# endif
tags_liste.emplace_back(FLDU, code);
code += sizeof(FLDU_);
break;
case FLDSU:
# ifdef DEBUGL
mexPrintf("FLDSU\n");
# endif
tags_liste.emplace_back(FLDSU, code);
code += sizeof(FLDSU_);
break;
case FLDR:
# ifdef DEBUGL
mexPrintf("FLDR\n");
# endif
tags_liste.emplace_back(FLDR, code);
code += sizeof(FLDR_);
break;
case FLDT:
# ifdef DEBUGL
mexPrintf("FLDT\n");
# endif
tags_liste.emplace_back(FLDT, code);
code += sizeof(FLDT_);
break;
case FLDST:
# ifdef DEBUGL
mexPrintf("FLDST\n");
# endif
tags_liste.emplace_back(FLDST, code);
code += sizeof(FLDST_);
break;
case FSTPT:
# ifdef DEBUGL
mexPrintf("FSTPT = %d size = %d\n", FSTPT, sizeof(FSTPT_));
# endif
tags_liste.emplace_back(FSTPT, code);
code += sizeof(FSTPT_);
break;
case FSTPST:
# ifdef DEBUGL
mexPrintf("FSTPST\n");
# endif
tags_liste.emplace_back(FSTPST, code);
code += sizeof(FSTPST_);
break;
case FSTPR:
# ifdef DEBUGL
mexPrintf("FSTPR\n");
# endif
tags_liste.emplace_back(FSTPR, code);
code += sizeof(FSTPR_);
break;
case FSTPU:
# ifdef DEBUGL
mexPrintf("FSTPU\n");
# endif
tags_liste.emplace_back(FSTPU, code);
code += sizeof(FSTPU_);
break;
case FSTPSU:
# ifdef DEBUGL
mexPrintf("FSTPSU\n");
# endif
tags_liste.emplace_back(FSTPSU, code);
code += sizeof(FSTPSU_);
break;
case FSTPG:
# ifdef DEBUGL
mexPrintf("FSTPG\n");
# endif
tags_liste.emplace_back(FSTPG, code);
code += sizeof(FSTPG_);
break;
case FSTPG2:
# ifdef DEBUGL
mexPrintf("FSTPG2\n");
# endif
tags_liste.emplace_back(FSTPG2, code);
code += sizeof(FSTPG2_);
break;
case FSTPG3:
# ifdef DEBUGL
mexPrintf("FSTPG3\n");
# endif
tags_liste.emplace_back(FSTPG3, code);
code += sizeof(FSTPG3_);
break;
case FUNARY:
# ifdef DEBUGL
mexPrintf("FUNARY\n");
# endif
tags_liste.emplace_back(FUNARY, code);
code += sizeof(FUNARY_);
break;
case FBINARY:
# ifdef DEBUGL
mexPrintf("FBINARY\n");
# endif
tags_liste.emplace_back(FBINARY, code);
code += sizeof(FBINARY_);
break;
case FTRINARY:
# ifdef DEBUGL
mexPrintf("FTRINARY\n");
# endif
tags_liste.emplace_back(FTRINARY, code);
code += sizeof(FTRINARY_);
break;
case FOK:
# ifdef DEBUGL
mexPrintf("FOK\n");
# endif
tags_liste.emplace_back(FOK, code);
code += sizeof(FOK_);
break;
case FLDVS:
# ifdef DEBUGL
mexPrintf("FLDVS\n");
# endif
tags_liste.emplace_back(FLDVS, code);
code += sizeof(FLDVS_);
break;
case FLDSV:
# ifdef DEBUGL
mexPrintf("FLDSV\n");
# endif
tags_liste.emplace_back(FLDSV, code);
code += sizeof(FLDSV_);
break;
case FSTPSV:
# ifdef DEBUGL
mexPrintf("FSTPSV\n");
# endif
tags_liste.emplace_back(FSTPSV, code);
code += sizeof(FSTPSV_);
break;
case FLDV:
# ifdef DEBUGL
mexPrintf("FLDV\n");
# endif
tags_liste.emplace_back(FLDV, code);
code += sizeof(FLDV_);
break;
case FSTPV:
# ifdef DEBUGL
mexPrintf("FSTPV\n");
# endif
tags_liste.emplace_back(FSTPV, code);
code += sizeof(FSTPV_);
break;
case FBEGINBLOCK:
# ifdef DEBUGL
mexPrintf("FBEGINBLOCK\n");
# endif
{
FBEGINBLOCK_ *fbegin_block = new FBEGINBLOCK_;
code = fbegin_block->load(code);
begin_block.push_back(tags_liste.size());
tags_liste.emplace_back(FBEGINBLOCK, fbegin_block);
nb_blocks++;
}
break;
case FJMPIFEVAL:
# ifdef DEBUGL
mexPrintf("FJMPIFEVAL\n");
# endif
tags_liste.emplace_back(FJMPIFEVAL, code);
code += sizeof(FJMPIFEVAL_);
break;
case FJMP:
# ifdef DEBUGL
mexPrintf("FJMP\n");
# endif
tags_liste.emplace_back(FJMP, code);
code += sizeof(FJMP_);
break;
case FCALL:
{
# ifdef DEBUGL
mexPrintf("FCALL\n");
# endif
FCALL_ *fcall = new FCALL_;
code = fcall->load(code);
tags_liste.emplace_back(FCALL, fcall);
# ifdef DEBUGL
mexPrintf("FCALL finish\n"); mexEvalString("drawnow;");
mexPrintf("-- *code=%d\n", *code); mexEvalString("drawnow;");
# endif
}
break;
case FPUSH:
# ifdef DEBUGL
mexPrintf("FPUSH\n");
# endif
tags_liste.emplace_back(FPUSH, code);
code += sizeof(FPUSH_);
break;
case FPOP:
# ifdef DEBUGL
mexPrintf("FPOP\n");
# endif
tags_liste.emplace_back(FPOP, code);
code += sizeof(FPOP_);
break;
case FLDTEF:
# ifdef DEBUGL
mexPrintf("FLDTEF\n");
# endif
tags_liste.emplace_back(FLDTEF, code);
code += sizeof(FLDTEF_);
break;
case FSTPTEF:
# ifdef DEBUGL
mexPrintf("FSTPTEF\n");
# endif
tags_liste.emplace_back(FSTPTEF, code);
code += sizeof(FSTPTEF_);
break;
case FLDTEFD:
# ifdef DEBUGL
mexPrintf("FLDTEFD\n");
# endif
tags_liste.emplace_back(FLDTEFD, code);
code += sizeof(FLDTEFD_);
break;
case FSTPTEFD:
# ifdef DEBUGL
mexPrintf("FSTPTEFD\n");
# endif
tags_liste.emplace_back(FSTPTEFD, code);
code += sizeof(FSTPTEFD_);
break;
case FLDTEFDD:
# ifdef DEBUGL
mexPrintf("FLDTEFDD\n");
# endif
tags_liste.emplace_back(FLDTEFDD, code);
code += sizeof(FLDTEFDD_);
break;
case FSTPTEFDD:
# ifdef DEBUGL
mexPrintf("FSTPTEFDD\n");
# endif
tags_liste.emplace_back(FSTPTEFDD, code);
code += sizeof(FSTPTEFDD_);
break;
default:
mexPrintf("Unknown Tag value=%d code=%x\n", *code, code);
done = true;
}
instruction++;
}
return tags_liste;
};
};
#endif
#pragma pack(pop)
#endif
/*
* Copyright © 2007-2024 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef COMMON_ENUMS_HH
#define COMMON_ENUMS_HH
//! Enumeration of possible symbol types
/*! Warning: do not to change existing values for 0 to 4: the values matter for homotopy_setup
* command */
enum class SymbolType
{
endogenous = 0, // Endogenous (non-heterogeneous)
exogenous = 1, // Exogenous (non-heterogeneous)
exogenousDet = 2, // Exogenous deterministic (non-heterogeneous)
parameter = 4, // Parameter (non-heterogeneous)
heterogeneousEndogenous = 5, // Endogenous that is heterogeneous across some dimension
heterogeneousExogenous = 6, // Exogenous that is heterogeneous across some dimension
heterogeneousParameter = 7, // Parameter that is heterogeneous across some dimension
modelLocalVariable = 10, // Local variable whose scope is model (pound expression)
modFileLocalVariable = 11, // Local variable whose scope is mod file (model excluded)
externalFunction = 12, // External (user-defined) function
trend = 13, // Trend variable
statementDeclaredVariable
= 14, //!< Local variable assigned within a Statement (see subsample statement for example)
logTrend = 15, //!< Log-trend variable
unusedEndogenous
= 16, //!< Type to mark unused endogenous variables when `nostrict` option is passed
// Value 17 is unused for the time being (but could be reused)
epilogue = 18, //!< Variables created in epilogue block
excludedVariable = 19 //!< Variable excluded via model_remove/var_remove/include_eqs/exclude_eqs
};
constexpr bool
isHeterogeneous(SymbolType type)
{
return type == SymbolType::heterogeneousEndogenous || type == SymbolType::heterogeneousExogenous
|| type == SymbolType::heterogeneousParameter;
}
enum class UnaryOpcode
{
uminus,
exp,
log,
log10,
cos,
sin,
tan,
acos,
asin,
atan,
cosh,
sinh,
tanh,
acosh,
asinh,
atanh,
sqrt,
cbrt,
abs,
sign,
steadyState,
steadyStateParamDeriv, // for the derivative of the STEADY_STATE operator w.r.t. to a parameter
steadyStateParam2ndDeriv, // for the 2nd derivative of the STEADY_STATE operator w.r.t. to a
// parameter
expectation,
erf,
erfc,
diff,
adl,
sum
};
enum class BinaryOpcode
{
plus,
minus,
times,
divide,
power,
powerDeriv, // for the derivative of the power function (see trac ticket #78)
equal,
max,
min,
less,
greater,
lessEqual,
greaterEqual,
equalEqual,
different
};
// Small number value used when evaluating powerDeriv opcodes.
// Put here instead of inside BinaryOpNode class, because needed by bytecode MEX.
constexpr double power_deriv_near_zero {1e-12};
enum class TrinaryOpcode
{
normcdf,
normpdf
};
enum class PriorDistributions
{
noShape = 0,
beta = 1,
gamma = 2,
normal = 3,
invGamma = 4,
invGamma1 = 4,
uniform = 5,
invGamma2 = 6,
dirichlet = 7,
weibull = 8
};
enum class EquationType
{
evaluate, //!< Simple evaluation, normalized variable on left-hand side (written as such by the
//!< user)
evaluateRenormalized, //!< Simple evaluation, normalized variable on left-hand side (normalization
//!< computed by the preprocessor)
solve //!< No simple evaluation of the equation, it has to be solved
};
enum class BlockSimulationType
{
evaluateForward = 1, //!< Simple evaluation, normalized variable on left-hand side, forward
evaluateBackward, //!< Simple evaluation, normalized variable on left-hand side, backward
solveForwardSimple, //!< Block of one equation, newton solver needed, forward
solveBackwardSimple, //!< Block of one equation, newton solver needed, backward
solveTwoBoundariesSimple, //!< Block of one equation, Newton solver needed, forward and backward
solveForwardComplete, //!< Block of several equations, Newton solver needed, forward
solveBackwardComplete, //!< Block of several equations, Newton solver needed, backward
solveTwoBoundariesComplete //!< Block of several equations, Newton solver needed, forward and
//!< backwar
};
enum class PacTargetKind
{
unspecified, // Must be the first one, because it’s the default initializer
ll,
dl,
dd
};
#endif
Source diff could not be displayed: it is too large. Options to address this: view the blob.
/*
* Copyright (C) 2003-2018 Dynare Team
* Copyright © 2003-2024 Dynare Team
*
* This file is part of Dynare.
*
......@@ -14,25 +14,28 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _COMPUTINGTASKS_HH
#define _COMPUTINGTASKS_HH
#ifndef COMPUTING_TASKS_HH
#define COMPUTING_TASKS_HH
#include <memory>
#include <optional>
#include <ostream>
#include "SymbolList.hh"
#include "SymbolTable.hh"
#include "Statement.hh"
#include "StaticModel.hh"
#include "DynamicModel.hh"
#include "ModelEquationBlock.hh"
#include "Statement.hh"
#include "StaticModel.hh"
#include "SymbolList.hh"
#include "SymbolTable.hh"
class SteadyStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit SteadyStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -44,6 +47,7 @@ class CheckStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit CheckStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -55,6 +59,7 @@ class SimulStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit SimulStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -66,6 +71,7 @@ class PerfectForesightSetupStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit PerfectForesightSetupStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
......@@ -76,6 +82,7 @@ class PerfectForesightSolverStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit PerfectForesightSolverStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -83,212 +90,197 @@ public:
void writeJsonOutput(ostream& output) const override;
};
class PriorPosteriorFunctionStatement : public Statement
class PerfectForesightWithExpectationErrorsSetupStatement : public Statement
{
private:
const bool prior_func;
const OptionsList options_list;
public:
PriorPosteriorFunctionStatement(const bool prior_func_arg, OptionsList options_list_arg);
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
explicit PerfectForesightWithExpectationErrorsSetupStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class DetCondForecast : public Statement
class PerfectForesightWithExpectationErrorsSolverStatement : public Statement
{
private:
const OptionsList options_list;
const SymbolList symbol_list;
const bool linear_decomposition;
public:
DetCondForecast(const SymbolList &symbol_list_arg,
OptionsList options_list_arg,
const bool linear_decompositiontion_arg);
//virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
explicit PerfectForesightWithExpectationErrorsSolverStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class ModelInfoStatement : public Statement
class PriorPosteriorFunctionStatement : public Statement
{
private:
const bool prior_func;
const OptionsList options_list;
public:
explicit ModelInfoStatement(OptionsList options_list_arg);
PriorPosteriorFunctionStatement(const bool prior_func_arg, OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class StochSimulStatement : public Statement
class ModelInfoStatement : public Statement
{
private:
const SymbolList symbol_list;
const OptionsList options_list;
public:
StochSimulStatement(SymbolList symbol_list_arg,
OptionsList options_list_arg);
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
explicit ModelInfoStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class PacModelStatement : public Statement
class StochSimulStatement : public Statement
{
private:
const string name;
const string aux_model_name;
const string discount;
const string growth;
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
vector<int> lhs;
public:
PacModelStatement(string name_arg,
string aux_model_name_arg,
string discount_arg,
string growth_arg,
StochSimulStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
void fillUndiffedLHS(vector<int> &lhs);
tuple<string, string, int> getPacModelInfoForPacExpectation() const;
};
class VarRestrictionsStatement : public Statement
class ForecastStatement : public Statement
{
private:
using var_restriction_eq_crosseq_t = pair<pair<int, pair<int, int>>, expr_t>;
const string var_model_name;
const map<string, vector<string>> var_map;
const map<int, map<int, SymbolList>> exclusion_restrictions;
using equation_restrictions_t = map<int, pair<pair<var_restriction_eq_crosseq_t, var_restriction_eq_crosseq_t>, double>>;
const equation_restrictions_t equation_restrictions;
using crossequation_restrictions_t = vector<pair<pair<var_restriction_eq_crosseq_t, var_restriction_eq_crosseq_t>, double>>;
const crossequation_restrictions_t crossequation_restrictions;
const map<pair<int, int>, double> covariance_number_restriction;
const map<pair<int, int>, pair<int, int>> covariance_pair_restriction;
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
int findIdxInVector(const vector<string> &vecvars, const string &var) const;
public:
VarRestrictionsStatement(string var_model_name_arg,
map<string, vector<string>> var_map_arg,
map<int, map<int, SymbolList>> exclusion_restrictions_arg,
equation_restrictions_t equation_restrictions_arg,
crossequation_restrictions_t crossequation_restrictions_arg,
map<pair<int, int>, double> covariance_number_restriction_arg,
map<pair<int, int>, pair<int, int>> covariance_pair_restriction_arg,
public:
ForecastStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class VarEstimationStatement : public Statement
class RamseyModelStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit VarEstimationStatement(OptionsList options_list_arg);
explicit RamseyModelStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class ForecastStatement : public Statement
class RamseyPolicyStatement : public Statement
{
private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
ForecastStatement(SymbolList symbol_list_arg,
OptionsList options_list_arg);
RamseyPolicyStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class RamseyModelStatement : public Statement
class EvaluatePlannerObjectiveStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit RamseyModelStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
explicit EvaluatePlannerObjectiveStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class RamseyConstraintsStatement : public Statement
class OccbinSetupStatement : public Statement
{
private:
const OptionsList options_list;
public:
struct Constraint
{
int endo;
BinaryOpcode code;
expr_t expression;
explicit OccbinSetupStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
using constraints_t = vector<Constraint>;
class OccbinSolverStatement : public Statement
{
private:
const SymbolTable &symbol_table;
const constraints_t constraints;
const OptionsList options_list;
public:
RamseyConstraintsStatement(const SymbolTable &symbol_table_arg, constraints_t constraints_arg);
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
explicit OccbinSolverStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class RamseyPolicyStatement : public Statement
class OccbinWriteRegimesStatement : public Statement
{
private:
const SymbolTable &symbol_table;
const vector<string> ramsey_policy_list;
const OptionsList options_list;
public:
RamseyPolicyStatement(const SymbolTable &symbol_table_arg,
vector<string> ramsey_policy_list_arg,
OptionsList options_list_arg);
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
void checkRamseyPolicyList();
explicit OccbinWriteRegimesStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class DiscretionaryPolicyStatement : public Statement
class OccbinGraphStatement : public Statement
{
private:
const SymbolList symbol_list;
const OptionsList options_list;
public:
DiscretionaryPolicyStatement(SymbolList symbol_list_arg,
OptionsList options_list_arg);
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
OccbinGraphStatement(SymbolList symbol_list_arg, OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class RplotStatement : public Statement
class DiscretionaryPolicyStatement : public Statement
{
private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
explicit RplotStatement(SymbolList symbol_list_arg);
DiscretionaryPolicyStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class UnitRootVarsStatement : public Statement
class RplotStatement : public Statement
{
private:
const SymbolList symbol_list;
const SymbolTable& symbol_table;
public:
UnitRootVarsStatement();
RplotStatement(SymbolList symbol_list_arg, const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class PeriodsStatement : public Statement
class UnitRootVarsStatement : public Statement
{
private:
const int periods;
public:
explicit PeriodsStatement(int periods_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -297,6 +289,7 @@ class DsampleStatement : public Statement
{
private:
const int val1, val2;
public:
explicit DsampleStatement(int val1_arg);
DsampleStatement(int val1_arg, int val2_arg);
......@@ -307,22 +300,25 @@ public:
class EstimationStatement : public Statement
{
private:
const SymbolTable& symbol_table;
const SymbolList symbol_list;
const OptionsList options_list;
public:
EstimationStatement(SymbolList symbol_list_arg,
EstimationStatement(const SymbolTable& symbol_table_arg, SymbolList symbol_list_arg,
OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class DynareSensitivityStatement : public Statement
class SensitivityStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit DynareSensitivityStatement(OptionsList options_list_arg);
explicit SensitivityStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
......@@ -332,9 +328,11 @@ class ObservationTrendsStatement : public Statement
{
public:
using trend_elements_t = map<string, expr_t>;
private:
const trend_elements_t trend_elements;
const SymbolTable& symbol_table;
public:
ObservationTrendsStatement(trend_elements_t trend_elements_arg,
const SymbolTable& symbol_table_arg);
......@@ -342,11 +340,44 @@ public:
void writeJsonOutput(ostream& output) const override;
};
class DeterministicTrendsStatement : public Statement
{
public:
using trend_elements_t = map<string, expr_t>;
private:
const trend_elements_t trend_elements;
const SymbolTable& symbol_table;
public:
DeterministicTrendsStatement(trend_elements_t trend_elements_arg,
const SymbolTable& symbol_table_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class FilterInitialStateStatement : public Statement
{
public:
using filter_initial_state_elements_t = map<pair<int, int>, expr_t>;
private:
const filter_initial_state_elements_t filter_initial_state_elements;
const SymbolTable& symbol_table;
public:
FilterInitialStateStatement(filter_initial_state_elements_t filter_initial_state_elements_arg,
const SymbolTable& symbol_table_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class OsrParamsStatement : public Statement
{
private:
const SymbolList symbol_list;
const SymbolTable& symbol_table;
public:
OsrParamsStatement(SymbolList symbol_list_arg, const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -359,9 +390,11 @@ class OsrStatement : public Statement
private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
OsrStatement(SymbolList symbol_list_arg,
OptionsList options_list_arg);
OsrStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
......@@ -387,6 +420,7 @@ class OsrParamsBoundsStatement : public Statement
{
private:
const vector<OsrParams> osr_params_list;
public:
explicit OsrParamsBoundsStatement(vector<OsrParams> osr_params_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -399,9 +433,12 @@ class DynaTypeStatement : public Statement
private:
const SymbolList symbol_list;
const string filename;
const SymbolTable& symbol_table;
public:
DynaTypeStatement(SymbolList symbol_list_arg,
string filename_arg);
DynaTypeStatement(SymbolList symbol_list_arg, string filename_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -411,9 +448,12 @@ class DynaSaveStatement : public Statement
private:
const SymbolList symbol_list;
const string filename;
const SymbolTable& symbol_table;
public:
DynaSaveStatement(SymbolList symbol_list_arg,
string filename_arg);
DynaSaveStatement(SymbolList symbol_list_arg, string filename_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -422,12 +462,13 @@ class ModelComparisonStatement : public Statement
{
public:
using filename_list_t = vector<pair<string, string>>;
private:
filename_list_t filename_list;
OptionsList options_list;
public:
ModelComparisonStatement(filename_list_t filename_list_arg,
OptionsList options_list_arg);
ModelComparisonStatement(filename_list_t filename_list_arg, OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -459,42 +500,77 @@ public:
}
};
class EstimatedParamsStatement : public Statement
class AbstractEstimatedParamsStatement : public Statement
{
private:
protected:
const vector<EstimationParams> estim_params_list;
const SymbolTable& symbol_table;
AbstractEstimatedParamsStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable& symbol_table_arg);
[[nodiscard]] virtual string blockName() const = 0;
// Part of the check pass that is common to the three estimated_params{,_init,bounds} blocks
void commonCheckPass() const;
};
class EstimatedParamsStatement : public AbstractEstimatedParamsStatement
{
private:
const bool overwrite;
public:
EstimatedParamsStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable &symbol_table_arg);
const SymbolTable& symbol_table_arg, bool overwrite_arg);
[[nodiscard]] string
blockName() const override
{
return "estimated_params";
}
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class EstimatedParamsInitStatement : public Statement
class EstimatedParamsInitStatement : public AbstractEstimatedParamsStatement
{
private:
const vector<EstimationParams> estim_params_list;
const SymbolTable &symbol_table;
const bool use_calibration;
public:
EstimatedParamsInitStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable &symbol_table_arg,
const bool use_calibration_arg);
const SymbolTable& symbol_table_arg, const bool use_calibration_arg);
[[nodiscard]] string
blockName() const override
{
return "estimated_params_init";
}
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class EstimatedParamsBoundsStatement : public Statement
class EstimatedParamsBoundsStatement : public AbstractEstimatedParamsStatement
{
private:
const vector<EstimationParams> estim_params_list;
const SymbolTable &symbol_table;
public:
EstimatedParamsBoundsStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable& symbol_table_arg);
[[nodiscard]] string
blockName() const override
{
return "estimated_params_bounds";
}
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class EstimatedParamsRemoveStatement : public Statement
{
public:
// Only the type, name and name2 fields of EstimationParams are used
const vector<EstimationParams> estim_params_list;
const SymbolTable& symbol_table;
EstimatedParamsRemoveStatement(vector<EstimationParams> estim_params_list_arg,
const SymbolTable& symbol_table_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -504,13 +580,14 @@ class OptimWeightsStatement : public Statement
public:
using var_weights_t = map<string, expr_t>;
using covar_weights_t = map<pair<string, string>, expr_t>;
private:
const var_weights_t var_weights;
const covar_weights_t covar_weights;
const SymbolTable& symbol_table;
public:
OptimWeightsStatement(var_weights_t var_weights_arg,
covar_weights_t covar_weights_arg,
OptimWeightsStatement(var_weights_t var_weights_arg, covar_weights_t covar_weights_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
......@@ -520,19 +597,20 @@ public:
class PlannerObjectiveStatement : public Statement
{
private:
StaticModel model_tree;
unique_ptr<PlannerObjective> model_tree;
bool computing_pass_called {false};
public:
PlannerObjectiveStatement(const StaticModel &model_tree_arg);
explicit PlannerObjectiveStatement(unique_ptr<PlannerObjective> model_tree_arg);
/*! \todo check there are only endogenous variables at the current period in the objective
(no exogenous, no lead/lag) */
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
/*! \todo allow for the possibility of disabling temporary terms */
void computingPass() override;
void computingPass(const ModFileStructure& mod_file_struct) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
//! Return a reference the Planner Objective model tree
const StaticModel &getPlannerObjective() const;
[[nodiscard]] const PlannerObjective& getPlannerObjective() const;
};
class BVARDensityStatement : public Statement
......@@ -540,6 +618,7 @@ class BVARDensityStatement : public Statement
private:
const int maxnlags;
const OptionsList options_list;
public:
BVARDensityStatement(int maxnlags_arg, OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -552,6 +631,7 @@ class BVARForecastStatement : public Statement
private:
const int nlags;
const OptionsList options_list;
public:
BVARForecastStatement(int nlags_arg, OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -559,10 +639,24 @@ public:
void writeJsonOutput(ostream& output) const override;
};
class BVARIRFStatement : public Statement
{
private:
const int nirf;
const string identificationname;
public:
BVARIRFStatement(int nirf_arg, string identificationname_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class SBVARStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit SBVARStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -574,6 +668,7 @@ class MSSBVAREstimationStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit MSSBVAREstimationStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -585,6 +680,7 @@ class MSSBVARSimulationStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit MSSBVARSimulationStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -596,6 +692,7 @@ class MSSBVARComputeMDDStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit MSSBVARComputeMDDStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -607,6 +704,7 @@ class MSSBVARComputeProbabilitiesStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit MSSBVARComputeProbabilitiesStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -619,9 +717,11 @@ class MSSBVARIrfStatement : public Statement
private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
MSSBVARIrfStatement(SymbolList symbol_list_arg,
OptionsList options_list_arg);
MSSBVARIrfStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
......@@ -631,6 +731,7 @@ class MSSBVARForecastStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit MSSBVARForecastStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -642,6 +743,7 @@ class MSSBVARVarianceDecompositionStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit MSSBVARVarianceDecompositionStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -653,6 +755,7 @@ class IdentificationStatement : public Statement
{
private:
OptionsList options_list;
public:
explicit IdentificationStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -665,8 +768,10 @@ class WriteLatexDynamicModelStatement : public Statement
private:
const DynamicModel& dynamic_model;
const bool write_equation_tags;
public:
WriteLatexDynamicModelStatement(const DynamicModel &dynamic_model_arg, bool write_equation_tags_arg);
WriteLatexDynamicModelStatement(const DynamicModel& dynamic_model_arg,
bool write_equation_tags_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -676,6 +781,7 @@ class WriteLatexStaticModelStatement : public Statement
private:
const StaticModel& static_model;
const bool write_equation_tags;
public:
WriteLatexStaticModelStatement(const StaticModel& static_model_arg, bool write_equation_tags_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
......@@ -687,8 +793,10 @@ class WriteLatexOriginalModelStatement : public Statement
private:
const DynamicModel& original_model;
const bool write_equation_tags;
public:
WriteLatexOriginalModelStatement(const DynamicModel &original_model_arg, bool write_equation_tags_arg);
WriteLatexOriginalModelStatement(const DynamicModel& original_model_arg,
bool write_equation_tags_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -697,6 +805,7 @@ class WriteLatexSteadyStateModelStatement : public Statement
{
private:
const SteadyStateModel& steady_state_model;
public:
explicit WriteLatexSteadyStateModelStatement(const SteadyStateModel& steady_state_model_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -709,9 +818,12 @@ class ShockDecompositionStatement : public Statement
private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
ShockDecompositionStatement(SymbolList symbol_list_arg,
OptionsList options_list_arg);
ShockDecompositionStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -721,10 +833,14 @@ class RealtimeShockDecompositionStatement : public Statement
private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
RealtimeShockDecompositionStatement(SymbolList symbol_list_arg,
OptionsList options_list_arg);
RealtimeShockDecompositionStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class PlotShockDecompositionStatement : public Statement
......@@ -732,10 +848,14 @@ class PlotShockDecompositionStatement : public Statement
private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
PlotShockDecompositionStatement(SymbolList symbol_list_arg,
OptionsList options_list_arg);
PlotShockDecompositionStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class InitialConditionDecompositionStatement : public Statement
......@@ -743,18 +863,38 @@ class InitialConditionDecompositionStatement : public Statement
private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
InitialConditionDecompositionStatement(SymbolList symbol_list_arg,
OptionsList options_list_arg);
InitialConditionDecompositionStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class SqueezeShockDecompositionStatement : public Statement
{
private:
const SymbolList symbol_list;
const SymbolTable& symbol_table;
public:
SqueezeShockDecompositionStatement(SymbolList symbol_list_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class ConditionalForecastStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit ConditionalForecastStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -762,11 +902,14 @@ public:
class PlotConditionalForecastStatement : public Statement
{
private:
//! A value of -1 indicates that the user didn't specify a value
const int periods;
const optional<int> periods; // The user is allowed not to declare periods
const SymbolList symbol_list;
const SymbolTable& symbol_table;
public:
PlotConditionalForecastStatement(int periods_arg, SymbolList symbol_list_arg);
PlotConditionalForecastStatement(const optional<int>& periods_arg, SymbolList symbol_list_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -776,9 +919,11 @@ class CalibSmootherStatement : public Statement
private:
const SymbolList symbol_list;
const OptionsList options_list;
const SymbolTable& symbol_table;
public:
CalibSmootherStatement(SymbolList symbol_list_arg,
OptionsList options_list_arg);
CalibSmootherStatement(SymbolList symbol_list_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
......@@ -788,6 +933,7 @@ class ExtendedPathStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit ExtendedPathStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -809,17 +955,16 @@ public:
};
using svar_identification_restrictions_t = vector<svar_identification_restriction>;
private:
const svar_identification_restrictions_t restrictions;
const bool upper_cholesky_present;
const bool lower_cholesky_present;
const bool constants_exclusion_present;
const bool upper_cholesky_present, lower_cholesky_present, constants_exclusion_present;
const SymbolTable& symbol_table;
int getMaxLag() const;
[[nodiscard]] int getMaxLag() const;
public:
SvarIdentificationStatement(svar_identification_restrictions_t restrictions_arg,
bool upper_cholesky_present_arg,
bool lower_cholesky_present_arg,
bool upper_cholesky_present_arg, bool lower_cholesky_present_arg,
bool constants_exclusion_present_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -832,11 +977,11 @@ class MarkovSwitchingStatement : public Statement
private:
const OptionsList options_list;
map<pair<int, int>, double> restriction_map;
public:
explicit MarkovSwitchingStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeCOutput(ostream &output, const string &basename) override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -844,6 +989,7 @@ class SvarStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit SvarStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -854,7 +1000,6 @@ public:
class SvarGlobalIdentificationCheckStatement : public Statement
{
public:
SvarGlobalIdentificationCheckStatement();
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -862,9 +1007,10 @@ public:
class SetTimeStatement : public Statement
{
private:
const OptionsList options_list;
const string period;
public:
explicit SetTimeStatement(OptionsList options_list_arg);
explicit SetTimeStatement(string period_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -873,6 +1019,7 @@ class EstimationDataStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit EstimationDataStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -885,17 +1032,16 @@ class SubsamplesStatement : public Statement
public:
//! Storage for declaring subsamples: map<subsample_name, <date1, date2 >
using subsample_declaration_map_t = map<string, pair<string, string>>;
private:
const string name1;
const string name2;
const string name1, name2;
const subsample_declaration_map_t subsample_declaration_map;
const SymbolTable& symbol_table;
public:
SubsamplesStatement(string name1_arg,
string name2_arg,
SubsamplesStatement(string name1_arg, string name2_arg,
subsample_declaration_map_t subsample_declaration_map_arg,
const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -903,17 +1049,12 @@ public:
class SubsamplesEqualStatement : public Statement
{
private:
const string to_name1;
const string to_name2;
const string from_name1;
const string from_name2;
const string to_name1, to_name2, from_name1, from_name2;
const SymbolTable& symbol_table;
public:
SubsamplesEqualStatement(string to_name1_arg,
string to_name2_arg,
string from_name1_arg,
string from_name2_arg,
const SymbolTable &symbol_table_arg);
SubsamplesEqualStatement(string to_name1_arg, string to_name2_arg, string from_name1_arg,
string from_name2_arg, const SymbolTable& symbol_table_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -924,46 +1065,36 @@ private:
const vector<string> joint_parameters;
const PriorDistributions prior_shape;
const OptionsList options_list;
void writeOutputHelper(ostream& output, const string& field, const string& lhs_field) const;
public:
JointPriorStatement(vector<string> joint_parameters_arg,
PriorDistributions prior_shape_arg,
JointPriorStatement(vector<string> joint_parameters_arg, PriorDistributions prior_shape_arg,
OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeOutputHelper(ostream &output, const string &field, const string &lhs_field) const;
void writeJsonOutput(ostream& output) const override;
};
class BasicPriorStatement : public Statement
{
public:
~BasicPriorStatement() override;
protected:
const string name;
const string subsample_name;
const string name, subsample_name;
const PriorDistributions prior_shape;
const expr_t variance;
const OptionsList options_list;
BasicPriorStatement(string name_arg,
string subsample_name_arg,
PriorDistributions prior_shape_arg,
expr_t variance_arg,
BasicPriorStatement(string name_arg, string subsample_name_arg,
PriorDistributions prior_shape_arg, expr_t variance_arg,
OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void get_base_name(const SymbolType symb_type, string& lhs_field) const;
void writeCommonOutput(ostream& output, const string& lhs_field) const;
void writeCommonOutputHelper(ostream& output, const string& field, const string& lhs_field) const;
void writePriorOutput(ostream& output, string& lhs_field, const string& name2) const;
bool is_structural_innovation(const SymbolType symb_type) const;
[[nodiscard]] bool is_structural_innovation(const SymbolType symb_type) const;
void writePriorIndex(ostream& output, const string& lhs_field) const;
void writeVarianceOption(ostream& output, const string& lhs_field) const;
void writeOutputHelper(ostream& output, const string& field, const string& lhs_field) const;
void writeShape(ostream& output, const string& lhs_field) const;
void writeCOutputHelper(ostream &output, const string &field) const;
void writeCShape(ostream &output) const;
void writeCVarianceOption(ostream &output) const;
void writeCDomain(ostream &output) const;
void writeJsonShape(ostream& output) const;
void writeJsonPriorOutput(ostream& output) const;
};
......@@ -971,13 +1102,9 @@ protected:
class PriorStatement : public BasicPriorStatement
{
public:
PriorStatement(string name_arg,
string subsample_name_arg,
PriorDistributions prior_shape_arg,
expr_t variance_arg,
OptionsList options_list_arg);
PriorStatement(string name_arg, string subsample_name_arg, PriorDistributions prior_shape_arg,
expr_t variance_arg, OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeCOutput(ostream &output, const string &basename) override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -985,15 +1112,12 @@ class StdPriorStatement : public BasicPriorStatement
{
private:
const SymbolTable& symbol_table;
public:
StdPriorStatement(string name_arg,
string subsample_name_arg,
PriorDistributions prior_shape_arg,
expr_t variance_arg,
OptionsList options_list_arg,
StdPriorStatement(string name_arg, string subsample_name_arg, PriorDistributions prior_shape_arg,
expr_t variance_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeCOutput(ostream &output, const string &basename) override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -1002,41 +1126,27 @@ class CorrPriorStatement : public BasicPriorStatement
private:
const string name1;
const SymbolTable& symbol_table;
public:
CorrPriorStatement(string name_arg1,
string name_arg2,
string subsample_name_arg,
PriorDistributions prior_shape_arg,
expr_t variance_arg,
OptionsList options_list_arg,
const SymbolTable &symbol_table_arg);
CorrPriorStatement(string name_arg1, string name_arg2, string subsample_name_arg,
PriorDistributions prior_shape_arg, expr_t variance_arg,
OptionsList options_list_arg, const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeCOutput(ostream &output, const string &basename) override;
void writeJsonOutput(ostream& output) const override;
};
class PriorEqualStatement : public Statement
{
private:
const string to_declaration_type;
const string to_name1;
const string to_name2;
const string to_subsample_name;
const string from_declaration_type;
const string from_name1;
const string from_name2;
const string from_subsample_name;
const string to_declaration_type, to_name1, to_name2, to_subsample_name;
const string from_declaration_type, from_name1, from_name2, from_subsample_name;
const SymbolTable& symbol_table;
public:
PriorEqualStatement(string to_declaration_type_arg,
string to_name1_arg,
string to_name2_arg,
string to_subsample_name_arg,
string from_declaration_type_arg,
string from_name1_arg,
string from_name2_arg,
string from_subsample_name_arg,
PriorEqualStatement(string to_declaration_type_arg, string to_name1_arg, string to_name2_arg,
string to_subsample_name_arg, string from_declaration_type_arg,
string from_name1_arg, string from_name2_arg, string from_subsample_name_arg,
const SymbolTable& symbol_table_arg);
void get_base_name(const SymbolType symb_type, string& lhs_field) const;
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
......@@ -1046,25 +1156,17 @@ public:
class BasicOptionsStatement : public Statement
{
public:
~BasicOptionsStatement() override;
protected:
const string name;
const string subsample_name;
const string name, subsample_name;
const OptionsList options_list;
BasicOptionsStatement(string name_arg,
string subsample_name_arg,
OptionsList options_list_arg);
BasicOptionsStatement(string name_arg, string subsample_name_arg, OptionsList options_list_arg);
void get_base_name(const SymbolType symb_type, string& lhs_field) const;
void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
void writeOptionsOutput(ostream& output, string& lhs_field, const string& name2) const;
void writeCommonOutput(ostream& output, const string& lhs_field) const;
void writeCommonOutputHelper(ostream& output, const string& field, const string& lhs_field) const;
bool is_structural_innovation(const SymbolType symb_type) const;
[[nodiscard]] bool is_structural_innovation(const SymbolType symb_type) const;
void writeOptionsIndex(ostream& output, const string& lhs_field) const;
void writeOutputHelper(ostream& output, const string& field, const string& lhs_field) const;
void writeCOutputHelper(ostream &output, const string &field) const;
void writeJsonOptionsOutput(ostream& output) const;
};
......@@ -1073,7 +1175,6 @@ class OptionsStatement : public BasicOptionsStatement
public:
OptionsStatement(string name_arg, string subsample_name_arg, OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeCOutput(ostream &output, const string &basename) override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -1081,13 +1182,11 @@ class StdOptionsStatement : public BasicOptionsStatement
{
private:
const SymbolTable& symbol_table;
public:
StdOptionsStatement(string name_arg,
string subsample_name_arg,
OptionsList options_list_arg,
StdOptionsStatement(string name_arg, string subsample_name_arg, OptionsList options_list_arg,
const SymbolTable& symbol_table_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeCOutput(ostream &output, const string &basename) override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -1096,39 +1195,27 @@ class CorrOptionsStatement : public BasicOptionsStatement
private:
const string name1;
const SymbolTable& symbol_table;
public:
CorrOptionsStatement(string name_arg1, string name_arg2,
string subsample_name_arg,
OptionsList options_list_arg,
const SymbolTable &symbol_table_arg);
CorrOptionsStatement(string name_arg1, string name_arg2, string subsample_name_arg,
OptionsList options_list_arg, const SymbolTable& symbol_table_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeCOutput(ostream &output, const string &basename) override;
void writeJsonOutput(ostream& output) const override;
};
class OptionsEqualStatement : public Statement
{
private:
const string to_declaration_type;
const string to_name1;
const string to_name2;
const string to_subsample_name;
const string from_declaration_type;
const string from_name1;
const string from_name2;
const string from_subsample_name;
const string to_declaration_type, to_name1, to_name2, to_subsample_name;
const string from_declaration_type, from_name1, from_name2, from_subsample_name;
const SymbolTable& symbol_table;
public:
OptionsEqualStatement(string to_declaration_type_arg,
string to_name1_arg,
string to_name2_arg,
string to_subsample_name_arg,
string from_declaration_type_arg,
string from_name1_arg,
string from_name2_arg,
string from_subsample_name_arg,
const SymbolTable &symbol_table_arg);
OptionsEqualStatement(string to_declaration_type_arg, string to_name1_arg, string to_name2_arg,
string to_subsample_name_arg, string from_declaration_type_arg,
string from_name1_arg, string from_name2_arg,
string from_subsample_name_arg, const SymbolTable& symbol_table_arg);
void get_base_name(const SymbolType symb_type, string& lhs_field) const;
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
......@@ -1138,7 +1225,6 @@ public:
class ModelDiagnosticsStatement : public Statement
{
public:
ModelDiagnosticsStatement();
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
......@@ -1147,63 +1233,110 @@ class Smoother2histvalStatement : public Statement
{
private:
const OptionsList options_list;
public:
explicit Smoother2histvalStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class GMMEstimationStatement : public Statement
class MethodOfMomentsStatement : public Statement
{
private:
const SymbolList symbol_list;
const OptionsList options_list;
public:
GMMEstimationStatement(SymbolList symbol_list_arg, OptionsList options_list_arg);
explicit MethodOfMomentsStatement(OptionsList options_list_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class SMMEstimationStatement : public Statement
class GenerateIRFsStatement : public Statement
{
public:
private:
const SymbolList symbol_list;
const OptionsList options_list;
const vector<string> generate_irf_names;
const vector<map<string, double>> generate_irf_elements;
public:
SMMEstimationStatement(SymbolList symbol_list_arg, OptionsList options_list_arg);
GenerateIRFsStatement(OptionsList options_list_arg, vector<string> generate_irf_names_arg,
vector<map<string, double>> generate_irf_elements_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class GenerateIRFsStatement : public Statement
class MatchedMomentsStatement : public Statement
{
private:
const SymbolTable& symbol_table;
public:
/* Each moment is represented by a three vectors: symb_ids, lags, powers.
See the definition of ExprNode::matchMatchedMoment() for more details */
const vector<tuple<vector<int>, vector<int>, vector<int>>> moments;
MatchedMomentsStatement(const SymbolTable& symbol_table_arg,
vector<tuple<vector<int>, vector<int>, vector<int>>> moments_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class OccbinConstraintsStatement : public Statement
{
private:
DataTree data_tree;
public:
// The tuple is (name, bind, relax, error_bind, error_relax) (where relax and error_{bind,relax}
// can be nullptr)
const vector<tuple<string, BinaryOpNode*, BinaryOpNode*, expr_t, expr_t>> constraints;
OccbinConstraintsStatement(
const DataTree& data_tree_arg,
vector<tuple<string, BinaryOpNode*, BinaryOpNode*, expr_t, expr_t>> constraints_arg);
void checkPass(ModFileStructure& mod_file_struct, WarningConsolidation& warnings) override;
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class ResidStatement : public Statement
{
private:
const OptionsList options_list;
const vector<string> generate_irf_names;
const vector<map<string, double>> generate_irf_elements;
public:
GenerateIRFsStatement(OptionsList options_list_arg,
vector<string> generate_irf_names_arg,
vector<map<string, double>> generate_irf_elements_arg);
explicit ResidStatement(OptionsList options_list_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
};
class VarExpectationModelStatement : public Statement
class MatchedIrfsStatement : public Statement
{
public:
const string model_name, variable, aux_model_name, horizon;
const expr_t discount;
const SymbolTable &symbol_table;
// List of generated auxiliary param ids, in variable-major order
vector<int> aux_params_ids; // TODO: move this to some new VarModelTable object
// (endo name, exo name) → vector of (period start, period end, value, weight)
using matched_irfs_t = map<pair<string, string>, vector<tuple<int, int, expr_t, expr_t>>>;
MatchedIrfsStatement(matched_irfs_t values_weights_arg, bool overwrite_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
private:
const matched_irfs_t values_weights;
const bool overwrite;
};
class MatchedIrfsWeightsStatement : public Statement
{
public:
VarExpectationModelStatement(string model_name_arg, string variable_arg, string aux_model_name_arg,
string horizon_arg, expr_t discount_arg, const SymbolTable &symbol_table_arg);
/* (endo1 name, period index or range for endo1, exo1 name, endo2 name, period index or range for
endo2, exo2 name) → weight */
using matched_irfs_weights_t = map<tuple<string, string, string, string, string, string>, expr_t>;
MatchedIrfsWeightsStatement(matched_irfs_weights_t weights_arg, bool overwrite_arg);
void writeOutput(ostream& output, const string& basename, bool minimal_workspace) const override;
void writeJsonOutput(ostream& output) const override;
private:
const matched_irfs_weights_t weights;
const bool overwrite;
};
#endif
/*
* Copyright (C) 2010-2017 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <fstream>
#include <utility>
#include <vector>
#include "ConfigFile.hh"
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/tokenizer.hpp>
using namespace std;
Hook::Hook(string global_init_file_arg)
{
if (global_init_file_arg.empty())
{
cerr << "ERROR: The Hook must have a Global Initialization File argument." << endl;
exit(EXIT_FAILURE);
}
hooks["global_init_file"] = move(global_init_file_arg);
}
Path::Path(vector<string> includepath_arg)
{
if (includepath_arg.empty())
{
cerr << "ERROR: The Path must have an Include argument." << endl;
exit(EXIT_FAILURE);
}
paths["include"] = move(includepath_arg);
}
SlaveNode::SlaveNode(string computerName_arg, string port_arg, int minCpuNbr_arg, int maxCpuNbr_arg, string userName_arg,
string password_arg, string remoteDrive_arg, string remoteDirectory_arg,
string dynarePath_arg, string matlabOctavePath_arg, bool singleCompThread_arg, int numberOfThreadsPerJob_arg,
string operatingSystem_arg) :
computerName{move(computerName_arg)},
port{move(port_arg)},
minCpuNbr{minCpuNbr_arg},
maxCpuNbr{maxCpuNbr_arg},
userName{move(userName_arg)},
password{move(password_arg)},
remoteDrive{move(remoteDrive_arg)},
remoteDirectory{move(remoteDirectory_arg)},
dynarePath{move(dynarePath_arg)},
matlabOctavePath{move(matlabOctavePath_arg)},
singleCompThread{singleCompThread_arg},
numberOfThreadsPerJob{numberOfThreadsPerJob_arg},
operatingSystem{move(operatingSystem_arg)}
{
if (computerName.empty())
{
cerr << "ERROR: The node must have a ComputerName." << endl;
exit(EXIT_FAILURE);
}
if (!operatingSystem.empty())
if (operatingSystem.compare("windows") != 0 && operatingSystem.compare("unix") != 0)
{
cerr << "ERROR: The OperatingSystem must be either 'unix' or 'windows' (Case Sensitive)." << endl;
exit(EXIT_FAILURE);
}
}
Cluster::Cluster(member_nodes_t member_nodes_arg) :
member_nodes{move(member_nodes_arg)}
{
if (member_nodes.empty())
{
cerr << "ERROR: The cluster must have at least one member node." << endl;
exit(EXIT_FAILURE);
}
}
ConfigFile::ConfigFile(bool parallel_arg, bool parallel_test_arg,
bool parallel_slave_open_mode_arg, string cluster_name_arg) :
parallel{parallel_arg}, parallel_test{parallel_test_arg},
parallel_slave_open_mode{parallel_slave_open_mode_arg}, cluster_name{move(cluster_name_arg)}
{
}
void
ConfigFile::getConfigFileInfo(const string &config_file)
{
using namespace boost;
ifstream configFile;
if (config_file.empty())
{
string defaultConfigFile;
// Test OS and try to open default file
#if defined(_WIN32) || defined(__CYGWIN32__)
if (getenv("APPDATA") == NULL)
{
if (parallel || parallel_test)
cerr << "ERROR: ";
else
cerr << "WARNING: ";
cerr << "APPDATA environment variable not found." << endl;
if (parallel || parallel_test)
exit(EXIT_FAILURE);
}
else
{
defaultConfigFile += getenv("APPDATA");
defaultConfigFile += "\\dynare.ini";
}
#else
if (getenv("HOME") == nullptr)
{
if (parallel || parallel_test)
cerr << "ERROR: ";
else
cerr << "WARNING: ";
cerr << "HOME environment variable not found." << endl;
if (parallel || parallel_test)
exit(EXIT_FAILURE);
}
else
{
defaultConfigFile += getenv("HOME");
defaultConfigFile += "/.dynare";
}
#endif
configFile.open(defaultConfigFile, fstream::in);
if (!configFile.is_open())
if (parallel || parallel_test)
{
cerr << "ERROR: Could not open the default config file (" << defaultConfigFile << ")" << endl;
exit(EXIT_FAILURE);
}
else
return;
}
else
{
configFile.open(config_file, fstream::in);
if (!configFile.is_open())
{
cerr << "ERROR: Couldn't open file " << config_file << endl;;
exit(EXIT_FAILURE);
}
}
string name, computerName, port, userName, password, remoteDrive,
remoteDirectory, dynarePath, matlabOctavePath, operatingSystem,
global_init_file;
vector<string> includepath;
int minCpuNbr{0}, maxCpuNbr{0};
int numberOfThreadsPerJob{1};
bool singleCompThread{false};
member_nodes_t member_nodes;
bool inHooks{false};
bool inNode{false};
bool inCluster{false};
bool inPaths{false};
while (configFile.good())
{
string line;
getline(configFile, line);
trim(line);
if (line.empty() || !line.compare(0, 1, "#"))
continue;
if (!line.compare("[node]")
|| !line.compare("[cluster]")
|| !line.compare("[hooks]")
|| !line.compare("[paths]"))
{
if (!global_init_file.empty())
// we were just in [hooks]
addHooksConfFileElement(global_init_file);
else if (!includepath.empty())
// we were just in [paths]
addPathsConfFileElement(includepath);
else
// we were just in [node] or [cluster]
addParallelConfFileElement(inNode, inCluster, member_nodes, name,
computerName, port, minCpuNbr, maxCpuNbr, userName,
password, remoteDrive, remoteDirectory,
dynarePath, matlabOctavePath, singleCompThread, numberOfThreadsPerJob,
operatingSystem);
//! Reset communication vars / option defaults
if (!line.compare("[hooks]"))
{
inHooks = true;
inNode = false;
inCluster = false;
inPaths = false;
}
else if (!line.compare("[node]"))
{
inHooks = false;
inNode = true;
inCluster = false;
inPaths = false;
}
else if (!line.compare("[paths]"))
{
inHooks = false;
inNode = false;
inCluster = false;
inPaths = true;
}
else
{
inHooks = false;
inNode = false;
inCluster = true;
inPaths = false;
}
name = userName = computerName = port = password = remoteDrive
= remoteDirectory = dynarePath = matlabOctavePath
= operatingSystem = global_init_file = "";
includepath.clear();
minCpuNbr = maxCpuNbr = 0;
numberOfThreadsPerJob = 1;
singleCompThread = false;
member_nodes.clear();
}
else
{
vector<string> tokenizedLine;
split(tokenizedLine, line, is_any_of("="));
if (tokenizedLine.size() != 2)
{
cerr << "ERROR (in config file): Options should be formatted as 'option = value'." << endl;
exit(EXIT_FAILURE);
}
trim(tokenizedLine.front());
trim(tokenizedLine.back());
if (inHooks)
if (!tokenizedLine.front().compare("GlobalInitFile"))
if (global_init_file.empty())
global_init_file = tokenizedLine.back();
else
{
cerr << "ERROR: May not have more than one GlobalInitFile option in [hooks] block." << endl;
exit(EXIT_FAILURE);
}
else
{
cerr << "ERROR: Unrecognized option " << tokenizedLine.front() << " in [hooks] block." << endl;
exit(EXIT_FAILURE);
}
else if (inPaths)
if (!tokenizedLine.front().compare("Include"))
if (includepath.empty())
{
vector<string> tokenizedPath;
split(tokenizedPath, tokenizedLine.back(), is_any_of(":"), token_compress_on);
for (auto & it : tokenizedPath)
if (!it.empty())
{
trim(it);
includepath.push_back(it);
}
}
else
{
cerr << "ERROR: May not have more than one Include option in [paths] block." << endl;
exit(EXIT_FAILURE);
}
else
{
cerr << "ERROR: Unrecognized option " << tokenizedLine.front() << " in [paths] block." << endl;
exit(EXIT_FAILURE);
}
else
if (!tokenizedLine.front().compare("Name"))
name = tokenizedLine.back();
else if (!tokenizedLine.front().compare("CPUnbr"))
{
vector<string> tokenizedCpuNbr;
split(tokenizedCpuNbr, tokenizedLine.back(), is_any_of(":"));
try
{
if (tokenizedCpuNbr.size() == 1)
{
minCpuNbr = 1;
maxCpuNbr = stoi(tokenizedCpuNbr.front());
}
else if (tokenizedCpuNbr.size() == 2
&& tokenizedCpuNbr[0].at(0) == '['
&& tokenizedCpuNbr[1].at(tokenizedCpuNbr[1].size()-1) == ']')
{
tokenizedCpuNbr[0].erase(0, 1);
tokenizedCpuNbr[1].erase(tokenizedCpuNbr[1].size()-1, 1);
minCpuNbr = stoi(tokenizedCpuNbr[0]);
maxCpuNbr = stoi(tokenizedCpuNbr[1]);
}
}
catch (const invalid_argument &)
{
cerr << "ERROR: Could not convert value to integer for CPUnbr." << endl;
exit(EXIT_FAILURE);
}
if (minCpuNbr <= 0 || maxCpuNbr <= 0)
{
cerr << "ERROR: Syntax for the CPUnbr option is as follows:" << endl
<< " 1) CPUnbr = <int>" << endl
<< " or 2) CPUnbr = [<int>:<int>]" << endl
<< " where <int> is an Integer > 0." << endl;
exit(EXIT_FAILURE);
}
minCpuNbr--;
maxCpuNbr--;
if (minCpuNbr > maxCpuNbr)
{
int tmp = maxCpuNbr;
maxCpuNbr = minCpuNbr;
minCpuNbr = tmp;
}
}
else if (!tokenizedLine.front().compare("Port"))
port = tokenizedLine.back();
else if (!tokenizedLine.front().compare("ComputerName"))
computerName = tokenizedLine.back();
else if (!tokenizedLine.front().compare("UserName"))
userName = tokenizedLine.back();
else if (!tokenizedLine.front().compare("Password"))
password = tokenizedLine.back();
else if (!tokenizedLine.front().compare("RemoteDrive"))
remoteDrive = tokenizedLine.back();
else if (!tokenizedLine.front().compare("RemoteDirectory"))
remoteDirectory = tokenizedLine.back();
else if (!tokenizedLine.front().compare("DynarePath"))
dynarePath = tokenizedLine.back();
else if (!tokenizedLine.front().compare("MatlabOctavePath"))
matlabOctavePath = tokenizedLine.back();
else if (!tokenizedLine.front().compare("NumberOfThreadsPerJob"))
numberOfThreadsPerJob = stoi(tokenizedLine.back());
else if (!tokenizedLine.front().compare("SingleCompThread"))
if (tokenizedLine.back().compare("true") == 0)
singleCompThread = true;
else if (tokenizedLine.back().compare("false") == 0)
singleCompThread = false;
else
{
cerr << "ERROR (in config file): The value passed to SingleCompThread may only be 'true' or 'false'." << endl;
exit(EXIT_FAILURE);
}
else if (!tokenizedLine.front().compare("OperatingSystem"))
operatingSystem = tokenizedLine.back();
else if (!tokenizedLine.front().compare("Members"))
{
char_separator<char> sep(" ,;", "()", drop_empty_tokens);
tokenizer<char_separator<char>> tokens(tokenizedLine.back(), sep);
bool begin_weight = false;
string node_name;
for (const auto & token : tokens)
{
if (token.compare("(") == 0)
{
begin_weight = true;
continue;
}
else if (token.compare(")") == 0)
{
node_name.clear();
begin_weight = false;
continue;
}
if (!begin_weight)
{
if (!node_name.empty())
if (member_nodes.find(node_name) != member_nodes.end())
{
cerr << "ERROR (in config file): Node entered twice in specification of cluster." << endl;
exit(EXIT_FAILURE);
}
else
member_nodes[node_name] = 1.0;
node_name = token;
}
else
try
{
auto weight = stod(token);
if (weight <= 0)
{
cerr << "ERROR (in config file): Misspecification of weights passed to Members option." << endl;
exit(EXIT_FAILURE);
}
member_nodes[node_name] = weight;
}
catch (const invalid_argument &)
{
cerr << "ERROR (in config file): Misspecification of weights passed to Members option." << endl;
exit(EXIT_FAILURE);
}
}
if (!node_name.empty())
if (member_nodes.find(node_name) == member_nodes.end())
member_nodes[node_name] = 1.0;
else
{
cerr << "ERROR (in config file): Node entered twice in specification of cluster." << endl;
exit(EXIT_FAILURE);
}
}
else
{
cerr << "ERROR (in config file): Option " << tokenizedLine.front() << " is invalid." << endl;
exit(EXIT_FAILURE);
}
}
}
if (!global_init_file.empty())
addHooksConfFileElement(global_init_file);
else if (!includepath.empty())
addPathsConfFileElement(includepath);
else
addParallelConfFileElement(inNode, inCluster, member_nodes, name,
computerName, port, minCpuNbr, maxCpuNbr, userName,
password, remoteDrive, remoteDirectory,
dynarePath, matlabOctavePath, singleCompThread, numberOfThreadsPerJob,
operatingSystem);
configFile.close();
}
void
ConfigFile::addHooksConfFileElement(string global_init_file)
{
if (global_init_file.empty())
{
cerr << "ERROR: The global initialization file must be passed to the GlobalInitFile option." << endl;
exit(EXIT_FAILURE);
}
else
hooks.emplace_back(move(global_init_file));
}
void
ConfigFile::addPathsConfFileElement(vector<string> includepath)
{
if (includepath.empty())
{
cerr << "ERROR: The path to be included must be passed to the Include option." << endl;
exit(EXIT_FAILURE);
}
else
paths.emplace_back(move(includepath));
}
void
ConfigFile::addParallelConfFileElement(bool inNode, bool inCluster, const member_nodes_t &member_nodes, const string &name,
const string &computerName, const string &port, int minCpuNbr, int maxCpuNbr, const string &userName,
const string &password, const string &remoteDrive, const string &remoteDirectory,
const string &dynarePath, const string &matlabOctavePath, bool singleCompThread, int numberOfThreadsPerJob,
const string &operatingSystem)
{
//! ADD NODE
if (inNode)
if (!member_nodes.empty())
{
cerr << "Invalid option passed to [node]." << endl;
exit(EXIT_FAILURE);
}
else
if (name.empty() || slave_nodes.find(name) != slave_nodes.end())
{
cerr << "ERROR: Every node must be assigned a unique name." << endl;
exit(EXIT_FAILURE);
}
else
slave_nodes.emplace(name, SlaveNode{computerName, port, minCpuNbr, maxCpuNbr, userName,
password, remoteDrive, remoteDirectory, dynarePath,
matlabOctavePath, singleCompThread, numberOfThreadsPerJob,
operatingSystem});
//! ADD CLUSTER
else if (inCluster)
if (minCpuNbr > 0 || maxCpuNbr > 0 || !userName.empty()
|| !password.empty() || !remoteDrive.empty() || !remoteDirectory.empty()
|| !dynarePath.empty() || !matlabOctavePath.empty() || !operatingSystem.empty())
{
cerr << "Invalid option passed to [cluster]." << endl;
exit(EXIT_FAILURE);
}
else
if (name.empty() || clusters.find(name) != clusters.end())
{
cerr << "ERROR: The cluster must be assigned a unique name." << endl;
exit(EXIT_FAILURE);
}
else
{
if (clusters.empty())
firstClusterName = name;
clusters.emplace(name, Cluster{member_nodes});
}
}
void
ConfigFile::checkPass(WarningConsolidation &warnings) const
{
bool global_init_file_declared = false;
for (const auto & hook : hooks)
{
for (const auto & mapit : hook.get_hooks())
if (mapit.first.compare("global_init_file") == 0)
if (global_init_file_declared == true)
{
cerr << "ERROR: Only one global initialization file may be provided." << endl;
exit(EXIT_FAILURE);
}
else
global_init_file_declared = true;
}
if (!parallel && !parallel_test)
return;
//! Check Slave Nodes
if (slave_nodes.empty())
{
cerr << "ERROR: At least one node must be defined in the config file." << endl;
exit(EXIT_FAILURE);
}
for (const auto & slave_node : slave_nodes)
{
#if !defined(_WIN32) && !defined(__CYGWIN32__)
//For Linux/Mac, check that cpuNbr starts at 0
if (slave_node.second.minCpuNbr != 0)
warnings << "WARNING: On Unix-based operating systems, you cannot specify the CPU that is "
<< "used in parallel processing. This will be adjusted for you such that the "
<< "same number of CPUs are used." << endl;
#endif
if (!slave_node.second.port.empty())
try
{
stoi(slave_node.second.port);
}
catch (const invalid_argument &)
{
cerr << "ERROR (node " << slave_node.first << "): the port must be an integer." << endl;
exit(EXIT_FAILURE);
}
if (!slave_node.second.computerName.compare("localhost")) // We are working locally
{
if (!slave_node.second.remoteDrive.empty())
{
cerr << "ERROR (node " << slave_node.first << "): the RemoteDrive option may not be passed for a local node." << endl;
exit(EXIT_FAILURE);
}
if (!slave_node.second.remoteDirectory.empty())
{
cerr << "ERROR (node " << slave_node.first << "): the RemoteDirectory option may not be passed for a local node." << endl;
exit(EXIT_FAILURE);
}
}
else
{
if (slave_node.second.userName.empty())
{
cerr << "ERROR (node " << slave_node.first << "): the UserName option must be passed for every remote node." << endl;
exit(EXIT_FAILURE);
}
if (slave_node.second.operatingSystem.compare("windows") == 0)
{
if (slave_node.second.password.empty())
{
cerr << "ERROR (node " << slave_node.first << "): the Password option must be passed under Windows for every remote node." << endl;
exit(EXIT_FAILURE);
}
if (slave_node.second.remoteDrive.empty())
{
cerr << "ERROR (node " << slave_node.first << "): the RemoteDrive option must be passed under Windows for every remote node." << endl;
exit(EXIT_FAILURE);
}
}
#if defined(_WIN32) || defined(__CYGWIN32__)
if (slave_node.second.operatingSystem.empty())
{
if (slave_node.second.password.empty())
{
cerr << "ERROR (node " << slave_node.first << "): the Password option must be passed under Windows for every remote node." << endl;
exit(EXIT_FAILURE);
}
if (slave_node.second.remoteDrive.empty())
{
cerr << "ERROR (node " << slave_node.first << "): the RemoteDrive option must be passed under Windows for every remote node." << endl;
exit(EXIT_FAILURE);
}
}
#endif
if (slave_node.second.remoteDirectory.empty())
{
cerr << "ERROR (node " << slave_node.first << "): the RemoteDirectory must be specified for every remote node." << endl;
exit(EXIT_FAILURE);
}
}
}
//! Check Clusters
if (clusters.empty())
{
cerr << "ERROR: At least one cluster must be defined in the config file." << endl;
exit(EXIT_FAILURE);
}
if (!cluster_name.empty() && clusters.find(cluster_name) == clusters.end())
{
cerr << "ERROR: Cluster Name " << cluster_name << " was not found in the config file." << endl;
exit(EXIT_FAILURE);
}
for (const auto & cluster : clusters)
for (const auto & itmn : cluster.second.member_nodes)
if (slave_nodes.find(itmn.first) == slave_nodes.end())
{
cerr << "Error: node " << itmn.first << " specified in cluster " << cluster.first << " was not found" << endl;
exit(EXIT_FAILURE);
}
}
void
ConfigFile::transformPass()
{
if (!parallel && !parallel_test)
return;
#if !defined(_WIN32) && !defined(__CYGWIN32__)
//For Linux/Mac, check that cpuNbr starts at 0
for (auto & it : slave_nodes)
if (it.second.minCpuNbr != 0)
{
it.second.maxCpuNbr = it.second.maxCpuNbr - it.second.minCpuNbr;
it.second.minCpuNbr = 0;
}
#endif
map<string, Cluster>::iterator cluster_it;
if (cluster_name.empty())
cluster_it = clusters.find(firstClusterName);
else
cluster_it = clusters.find(cluster_name);
double weight_denominator{0.0};
for (const auto & it : cluster_it->second.member_nodes)
weight_denominator += it.second;
for (auto & member_node : cluster_it->second.member_nodes)
member_node.second /= weight_denominator;
}
vector<string>
ConfigFile::getIncludePaths() const
{
vector<string> include_paths;
for (auto path : paths)
for (const auto & mapit : path.get_paths())
for (const auto & vecit : mapit.second)
include_paths.push_back(vecit);
return include_paths;
}
void
ConfigFile::writeHooks(ostream &output) const
{
for (auto hook : hooks)
for (const auto & mapit : hook.get_hooks())
output << "options_." << mapit.first << " = '" << mapit.second << "';" << endl;
}
void
ConfigFile::writeCluster(ostream &output) const
{
if (!parallel && !parallel_test)
return;
map<string, Cluster>::const_iterator cluster_it;
if (cluster_name.empty())
cluster_it = clusters.find(firstClusterName);
else
cluster_it = clusters.find(cluster_name);
int i{1};
for (const auto & slave_node : slave_nodes)
{
bool slave_node_in_member_nodes = false;
for (const auto & itmn : cluster_it->second.member_nodes)
if (!slave_node.first.compare(itmn.first))
slave_node_in_member_nodes = true;
if (!slave_node_in_member_nodes)
continue;
output << "options_.parallel";
if (i > 1)
output << "(" << i << ")";
i++;
output << " = struct('Local', ";
if (slave_node.second.computerName.compare("localhost"))
output << "0, ";
else
output << "1, ";
output << "'ComputerName', '" << slave_node.second.computerName << "', "
<< "'Port', '" << slave_node.second.port << "', "
<< "'CPUnbr', [" << slave_node.second.minCpuNbr << ":" << slave_node.second.maxCpuNbr << "], "
<< "'UserName', '" << slave_node.second.userName << "', "
<< "'Password', '" << slave_node.second.password << "', "
<< "'RemoteDrive', '" << slave_node.second.remoteDrive << "', "
<< "'RemoteDirectory', '" << slave_node.second.remoteDirectory << "', "
<< "'DynarePath', '" << slave_node.second.dynarePath << "', "
<< "'MatlabOctavePath', '" << slave_node.second.matlabOctavePath << "', "
<< "'OperatingSystem', '" << slave_node.second.operatingSystem << "', "
<< "'NodeWeight', '" << (cluster_it->second.member_nodes.find(slave_node.first))->second << "', "
<< "'NumberOfThreadsPerJob', " << slave_node.second.numberOfThreadsPerJob << ", ";
if (slave_node.second.singleCompThread)
output << "'SingleCompThread', 'true');" << endl;
else
output << "'SingleCompThread', 'false');" << endl;
}
if (parallel_slave_open_mode)
output << "options_.parallel_info.leaveSlaveOpen = 1;" << endl;
output << "InitializeComputationalEnvironment();" << endl;
if (parallel_test)
output << "ErrorCode = AnalyseComputationalEnvironment(options_.parallel, options_.parallel_info);" << endl
<< "disp(['AnalyseComputationalEnvironment returned with Error Code: ' num2str(ErrorCode)]);" << endl
<< "diary off;" << endl
<< "return;" << endl;
}
void
ConfigFile::writeEndParallel(ostream &output) const
{
if ((!parallel && !parallel_test) || !parallel_slave_open_mode)
return;
output << "if options_.parallel_info.leaveSlaveOpen == 1" << endl
<< " closeSlave(options_.parallel,options_.parallel_info.RemoteTmpFolder);" << endl
<< "end" << endl;
}
/*
* Copyright (C) 2010-2017 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CONFIG_FILE_HH
#define _CONFIG_FILE_HH
#include <map>
#include <vector>
#include "WarningConsolidation.hh"
using namespace std;
using member_nodes_t = map<string, double>;
class Hook
{
public:
explicit Hook(string global_init_file_arg);
private:
map<string, string> hooks;
public:
inline map<string, string>
get_hooks() const
{
return hooks;
};
};
class Path
{
public:
explicit Path(vector<string> includepath_arg);
private:
map<string, vector<string>> paths;
public:
inline map<string, vector<string>>
get_paths() const
{
return paths;
};
};
class SlaveNode
{
friend class ConfigFile;
public:
SlaveNode(string computerName_arg, string port_arg, int minCpuNbr_arg, int maxCpuNbr_arg, string userName_arg,
string password_arg, string remoteDrive_arg, string remoteDirectory_arg,
string dynarePath_arg, string matlabOctavePath_arg, bool singleCompThread_arg, int numberOfThreadsPerJob_arg,
string operatingSystem_arg);
protected:
const string computerName;
const string port;
int minCpuNbr;
int maxCpuNbr;
const string userName;
const string password;
const string remoteDrive;
const string remoteDirectory;
const string dynarePath;
const string matlabOctavePath;
const bool singleCompThread;
const int numberOfThreadsPerJob;
const string operatingSystem;
};
class Cluster
{
friend class ConfigFile;
public:
explicit Cluster(member_nodes_t member_nodes_arg);
protected:
member_nodes_t member_nodes;
};
//! The abstract representation of a "config" file
class ConfigFile
{
public:
ConfigFile(bool parallel_arg, bool parallel_test_arg, bool parallel_slave_open_mode_arg, string cluster_name);
private:
const bool parallel;
const bool parallel_test;
const bool parallel_slave_open_mode;
const string cluster_name;
string firstClusterName;
//! Hooks
vector<Hook> hooks;
//! Paths
vector<Path> paths;
//! Cluster Table
map<string, Cluster> clusters;
//! Node Map
map<string, SlaveNode> slave_nodes;
//! Add Hooks
void addHooksConfFileElement(string global_init_file);
//! Add Paths
void addPathsConfFileElement(vector<string> includepath);
//! Add a SlaveNode or a Cluster object
void addParallelConfFileElement(bool inNode, bool inCluster, const member_nodes_t &member_nodes, const string &name,
const string &computerName, const string &port, int minCpuNbr, int maxCpuNbr, const string &userName,
const string &password, const string &remoteDrive, const string &remoteDirectory,
const string &dynarePath, const string &matlabOctavePath, bool singleCompThread, int numberOfThreadsPerJob,
const string &operatingSystem);
public:
//! Parse config file
void getConfigFileInfo(const string &parallel_config_file);
//! Check Pass
void checkPass(WarningConsolidation &warnings) const;
//! Check Pass
void transformPass();
//! Get Path Info
vector<string> getIncludePaths() const;
//! Write any hooks
void writeHooks(ostream &output) const;
//! Create options_.parallel structure, write options
void writeCluster(ostream &output) const;
//! Close slave nodes if needed
void writeEndParallel(ostream &output) const;
};
#endif // ! CONFIG_FILE_HH
/*
* Copyright © 2010-2024 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fstream>
#include <iostream>
#include <utility>
#ifdef _WIN32
# include <shlobj.h>
#endif
#include "Configuration.hh"
#include "DataTree.hh" // For strsplit()
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/tokenizer.hpp>
#pragma GCC diagnostic pop
Configuration::Path::Path(vector<string> includepath_arg)
{
if (includepath_arg.empty())
{
cerr << "ERROR: The Path must have an Include argument." << endl;
exit(EXIT_FAILURE);
}
paths["include"] = move(includepath_arg);
}
Configuration::FollowerNode::FollowerNode(string computerName_arg, string port_arg,
int minCpuNbr_arg, int maxCpuNbr_arg, string userName_arg,
string password_arg, string remoteDrive_arg,
string remoteDirectory_arg, string programPath_arg,
string programConfig_arg, string matlabOctavePath_arg,
bool singleCompThread_arg, int numberOfThreadsPerJob_arg,
string operatingSystem_arg) :
computerName {move(computerName_arg)},
port {move(port_arg)},
minCpuNbr {minCpuNbr_arg},
maxCpuNbr {maxCpuNbr_arg},
userName {move(userName_arg)},
password {move(password_arg)},
remoteDrive {move(remoteDrive_arg)},
remoteDirectory {move(remoteDirectory_arg)},
programPath {move(programPath_arg)},
programConfig {move(programConfig_arg)},
matlabOctavePath {move(matlabOctavePath_arg)},
singleCompThread {singleCompThread_arg},
numberOfThreadsPerJob {numberOfThreadsPerJob_arg},
operatingSystem {move(operatingSystem_arg)}
{
if (computerName.empty())
{
cerr << "ERROR: The node must have a ComputerName." << endl;
exit(EXIT_FAILURE);
}
if (!operatingSystem.empty())
if (operatingSystem != "windows" && operatingSystem != "unix")
{
cerr << "ERROR: The OperatingSystem must be either 'unix' or 'windows' (Case Sensitive)."
<< endl;
exit(EXIT_FAILURE);
}
}
Configuration::Cluster::Cluster(member_nodes_t member_nodes_arg) :
member_nodes {move(member_nodes_arg)}
{
if (member_nodes.empty())
{
cerr << "ERROR: The cluster must have at least one member node." << endl;
exit(EXIT_FAILURE);
}
}
Configuration::Configuration(bool parallel_arg, bool parallel_test_arg,
bool parallel_follower_open_mode_arg, bool parallel_use_psexec_arg,
string cluster_name_arg) :
parallel {parallel_arg},
parallel_test {parallel_test_arg},
parallel_follower_open_mode {parallel_follower_open_mode_arg},
parallel_use_psexec {parallel_use_psexec_arg},
cluster_name {move(cluster_name_arg)}
{
}
void
Configuration::getConfigFileInfo(const filesystem::path& conffile_option,
WarningConsolidation& warnings)
{
using namespace boost;
filesystem::path config_file {conffile_option};
if (config_file.empty())
{
config_file = findConfigFile("dynare.ini");
if (config_file.empty()) // Try old default location (Dynare ⩽ 5) for backward compatibility
{
filesystem::path old_default_config_file;
#ifdef _WIN32
array<wchar_t, MAX_PATH + 1> appdata;
if (SHGetFolderPathW(nullptr, CSIDL_APPDATA | CSIDL_FLAG_DONT_VERIFY, nullptr,
SHGFP_TYPE_CURRENT, appdata.data())
== S_OK)
old_default_config_file = filesystem::path {appdata.data()} / "dynare.ini";
#else
if (auto home = getenv("HOME"); home)
old_default_config_file = filesystem::path {home} / ".dynare";
#endif
if (!old_default_config_file.empty() && exists(old_default_config_file))
{
warnings << "WARNING: the location " << old_default_config_file.string()
<< " for the configuration file is obsolete; please see the reference"
<< " manual for the new location." << endl;
config_file = old_default_config_file;
}
}
}
if (config_file.empty())
{
if (parallel || parallel_test)
{
cerr << "ERROR: the parallel or parallel_test option was passed but no configuration "
<< "file was found" << endl;
exit(EXIT_FAILURE);
}
else
return;
}
ifstream configFile;
configFile.open(config_file, fstream::in);
if (!configFile.is_open())
{
cerr << "ERROR: Couldn't open configuration file " << config_file.string() << endl;
exit(EXIT_FAILURE);
}
string name, computerName, port, userName, password, remoteDrive, remoteDirectory, programPath,
programConfig, matlabOctavePath, operatingSystem;
vector<string> includepath;
int minCpuNbr {0}, maxCpuNbr {0};
int numberOfThreadsPerJob {1};
bool singleCompThread {false};
member_nodes_t member_nodes;
bool inHooks {false}, inNode {false}, inCluster {false}, inPaths {false};
while (configFile.good())
{
string line;
getline(configFile, line);
trim(line);
if (line.empty() || !line.compare(0, 1, "#"))
continue;
if (line == "[node]" || line == "[cluster]" || line == "[hooks]" || line == "[paths]")
{
if (!includepath.empty())
// we were just in [paths]
addPathsConfFileElement(includepath);
else
// we were just in [node] or [cluster]
addParallelConfFileElement(
inNode, inCluster, member_nodes, name, computerName, port, minCpuNbr, maxCpuNbr,
userName, password, remoteDrive, remoteDirectory, programPath, programConfig,
matlabOctavePath, singleCompThread, numberOfThreadsPerJob, operatingSystem);
//! Reset communication vars / option defaults
if (line == "[hooks]")
{
inHooks = true;
inNode = false;
inCluster = false;
inPaths = false;
}
else if (line == "[node]")
{
inHooks = false;
inNode = true;
inCluster = false;
inPaths = false;
}
else if (line == "[paths]")
{
inHooks = false;
inNode = false;
inCluster = false;
inPaths = true;
}
else
{
inHooks = false;
inNode = false;
inCluster = true;
inPaths = false;
}
name = userName = computerName = port = password = remoteDrive = remoteDirectory
= programPath = programConfig = matlabOctavePath = operatingSystem = "";
includepath.clear();
minCpuNbr = maxCpuNbr = 0;
numberOfThreadsPerJob = 1;
singleCompThread = false;
member_nodes.clear();
}
else
{
vector<string> tokenizedLine;
split(tokenizedLine, line, is_any_of("="));
if (tokenizedLine.size() != 2)
{
cerr << "ERROR (in config file): Options should be formatted as 'option = value'."
<< endl;
exit(EXIT_FAILURE);
}
trim(tokenizedLine.front());
trim(tokenizedLine.back());
if (inHooks)
if (tokenizedLine.front() == "GlobalInitFile")
if (global_init_file.empty())
global_init_file = tokenizedLine.back();
else
{
cerr
<< "ERROR: May not have more than one GlobalInitFile option in [hooks] block."
<< endl;
exit(EXIT_FAILURE);
}
else
{
cerr << "ERROR: Unrecognized option " << tokenizedLine.front()
<< " in [hooks] block." << endl;
exit(EXIT_FAILURE);
}
else if (inPaths)
if (tokenizedLine.front() == "Include")
if (includepath.empty())
{
vector<string> tokenizedPath;
split(tokenizedPath, tokenizedLine.back(), is_any_of(":"), token_compress_on);
for (auto& it : tokenizedPath)
if (!it.empty())
{
trim(it);
includepath.push_back(it);
}
}
else
{
cerr << "ERROR: May not have more than one Include option in [paths] block."
<< endl;
exit(EXIT_FAILURE);
}
else
{
cerr << "ERROR: Unrecognized option " << tokenizedLine.front()
<< " in [paths] block." << endl;
exit(EXIT_FAILURE);
}
else if (tokenizedLine.front() == "Name")
name = tokenizedLine.back();
else if (tokenizedLine.front() == "CPUnbr")
{
vector<string> tokenizedCpuNbr;
split(tokenizedCpuNbr, tokenizedLine.back(), is_any_of(":"));
try
{
if (tokenizedCpuNbr.size() == 1)
{
minCpuNbr = 1;
maxCpuNbr = stoi(tokenizedCpuNbr.front());
}
else if (tokenizedCpuNbr.size() == 2 && tokenizedCpuNbr[0].at(0) == '['
&& tokenizedCpuNbr[1].at(tokenizedCpuNbr[1].size() - 1) == ']')
{
tokenizedCpuNbr[0].erase(0, 1);
tokenizedCpuNbr[1].erase(tokenizedCpuNbr[1].size() - 1, 1);
minCpuNbr = stoi(tokenizedCpuNbr[0]);
maxCpuNbr = stoi(tokenizedCpuNbr[1]);
}
}
catch (const invalid_argument&)
{
cerr << "ERROR: Could not convert value to integer for CPUnbr." << endl;
exit(EXIT_FAILURE);
}
if (minCpuNbr <= 0 || maxCpuNbr <= 0)
{
cerr << "ERROR: Syntax for the CPUnbr option is as follows:" << endl
<< " 1) CPUnbr = <int>" << endl
<< " or 2) CPUnbr = [<int>:<int>]" << endl
<< " where <int> is an Integer > 0." << endl;
exit(EXIT_FAILURE);
}
minCpuNbr--;
maxCpuNbr--;
if (minCpuNbr > maxCpuNbr)
{
int tmp = maxCpuNbr;
maxCpuNbr = minCpuNbr;
minCpuNbr = tmp;
}
}
else if (tokenizedLine.front() == "Port")
port = tokenizedLine.back();
else if (tokenizedLine.front() == "ComputerName")
computerName = tokenizedLine.back();
else if (tokenizedLine.front() == "UserName")
userName = tokenizedLine.back();
else if (tokenizedLine.front() == "Password")
password = tokenizedLine.back();
else if (tokenizedLine.front() == "RemoteDrive")
remoteDrive = tokenizedLine.back();
else if (tokenizedLine.front() == "RemoteDirectory")
remoteDirectory = tokenizedLine.back();
else if (tokenizedLine.front() == "DynarePath" || tokenizedLine.front() == "ProgramPath")
programPath = tokenizedLine.back();
else if (tokenizedLine.front() == "ProgramConfig")
programConfig = tokenizedLine.back();
else if (tokenizedLine.front() == "MatlabOctavePath")
matlabOctavePath = tokenizedLine.back();
else if (tokenizedLine.front() == "NumberOfThreadsPerJob")
numberOfThreadsPerJob = stoi(tokenizedLine.back());
else if (tokenizedLine.front() == "SingleCompThread")
if (tokenizedLine.back() == "true")
singleCompThread = true;
else if (tokenizedLine.back() == "false")
singleCompThread = false;
else
{
cerr << "ERROR (in config file): The value passed to SingleCompThread may only be "
"'true' or 'false'."
<< endl;
exit(EXIT_FAILURE);
}
else if (tokenizedLine.front() == "OperatingSystem")
operatingSystem = tokenizedLine.back();
else if (tokenizedLine.front() == "Members")
{
char_separator sep(" ,;", "()", drop_empty_tokens);
tokenizer tokens(tokenizedLine.back(), sep);
string node_name;
for (bool begin_weight {false}; const auto& token : tokens)
{
if (token == "(")
{
begin_weight = true;
continue;
}
else if (token == ")")
{
node_name.clear();
begin_weight = false;
continue;
}
if (!begin_weight)
{
if (!node_name.empty())
{
if (member_nodes.contains(node_name))
{
cerr << "ERROR (in config file): Node entered twice in specification "
"of cluster."
<< endl;
exit(EXIT_FAILURE);
}
else
member_nodes[node_name] = 1.0;
}
node_name = token;
}
else
try
{
auto weight = stod(token);
if (weight <= 0)
{
cerr << "ERROR (in config file): Misspecification of weights passed to "
"Members option."
<< endl;
exit(EXIT_FAILURE);
}
member_nodes[node_name] = weight;
}
catch (const invalid_argument&)
{
cerr << "ERROR (in config file): Misspecification of weights passed to "
"Members option."
<< endl;
exit(EXIT_FAILURE);
}
}
if (!node_name.empty())
{
if (!member_nodes.contains(node_name))
member_nodes[node_name] = 1.0;
else
{
cerr << "ERROR (in config file): Node entered twice in specification of "
"cluster."
<< endl;
exit(EXIT_FAILURE);
}
}
}
else
{
cerr << "ERROR (in config file): Option " << tokenizedLine.front() << " is invalid."
<< endl;
exit(EXIT_FAILURE);
}
}
}
if (!includepath.empty())
addPathsConfFileElement(includepath);
else
addParallelConfFileElement(inNode, inCluster, member_nodes, name, computerName, port, minCpuNbr,
maxCpuNbr, userName, password, remoteDrive, remoteDirectory,
programPath, programConfig, matlabOctavePath, singleCompThread,
numberOfThreadsPerJob, operatingSystem);
configFile.close();
}
void
Configuration::addPathsConfFileElement(vector<string> includepath)
{
if (includepath.empty())
{
cerr << "ERROR: The path to be included must be passed to the Include option." << endl;
exit(EXIT_FAILURE);
}
else
paths.emplace_back(move(includepath));
}
void
Configuration::addParallelConfFileElement(bool inNode, bool inCluster,
const member_nodes_t& member_nodes, const string& name,
const string& computerName, const string& port,
int minCpuNbr, int maxCpuNbr, const string& userName,
const string& password, const string& remoteDrive,
const string& remoteDirectory, const string& programPath,
const string& programConfig,
const string& matlabOctavePath, bool singleCompThread,
int numberOfThreadsPerJob, const string& operatingSystem)
{
//! ADD NODE
if (inNode)
if (!member_nodes.empty())
{
cerr << "Invalid option passed to [node]." << endl;
exit(EXIT_FAILURE);
}
else if (name.empty() || follower_nodes.contains(name))
{
cerr << "ERROR: Every node must be assigned a unique name." << endl;
exit(EXIT_FAILURE);
}
else
follower_nodes.try_emplace(name, computerName, port, minCpuNbr, maxCpuNbr, userName, password,
remoteDrive, remoteDirectory, programPath, programConfig,
matlabOctavePath, singleCompThread, numberOfThreadsPerJob,
operatingSystem);
//! ADD CLUSTER
else if (inCluster)
{
if (minCpuNbr > 0 || maxCpuNbr > 0 || !userName.empty() || !password.empty()
|| !remoteDrive.empty() || !remoteDirectory.empty() || !programPath.empty()
|| !programConfig.empty() || !matlabOctavePath.empty() || !operatingSystem.empty())
{
cerr << "Invalid option passed to [cluster]." << endl;
exit(EXIT_FAILURE);
}
else if (name.empty() || clusters.contains(name))
{
cerr << "ERROR: The cluster must be assigned a unique name." << endl;
exit(EXIT_FAILURE);
}
else
{
if (clusters.empty())
firstClusterName = name;
clusters.emplace(name, member_nodes);
}
}
}
void
Configuration::checkPass([[maybe_unused]] WarningConsolidation& warnings) const
{
if (!parallel && !parallel_test)
return;
//! Check Follower Nodes
if (follower_nodes.empty())
{
cerr << "ERROR: At least one node must be defined in the config file." << endl;
exit(EXIT_FAILURE);
}
for (const auto& follower_node : follower_nodes)
{
#if !defined(_WIN32) && !defined(__CYGWIN32__)
// For Linux/Mac, check that cpuNbr starts at 0
if (follower_node.second.minCpuNbr != 0)
warnings << "WARNING: On Unix-based operating systems, you cannot specify the CPU that is "
<< "used in parallel processing. This will be adjusted for you such that the "
<< "same number of CPUs are used." << endl;
#endif
if (!follower_node.second.port.empty())
try
{
stoi(follower_node.second.port);
}
catch (const invalid_argument&)
{
cerr << "ERROR (node " << follower_node.first << "): the port must be an integer."
<< endl;
exit(EXIT_FAILURE);
}
if (follower_node.second.computerName == "localhost") // We are working locally
{
if (!follower_node.second.remoteDrive.empty())
{
cerr << "ERROR (node " << follower_node.first
<< "): the RemoteDrive option may not be passed for a local node." << endl;
exit(EXIT_FAILURE);
}
if (!follower_node.second.remoteDirectory.empty())
{
cerr << "ERROR (node " << follower_node.first
<< "): the RemoteDirectory option may not be passed for a local node." << endl;
exit(EXIT_FAILURE);
}
}
else
{
if (follower_node.second.userName.empty())
{
cerr << "ERROR (node " << follower_node.first
<< "): the UserName option must be passed for every remote node." << endl;
exit(EXIT_FAILURE);
}
if (follower_node.second.operatingSystem == "windows")
{
if (follower_node.second.password.empty())
{
cerr << "ERROR (node " << follower_node.first
<< "): the Password option must be passed under Windows for every remote "
"node."
<< endl;
exit(EXIT_FAILURE);
}
if (follower_node.second.remoteDrive.empty())
{
cerr << "ERROR (node " << follower_node.first
<< "): the RemoteDrive option must be passed under Windows for every remote "
"node."
<< endl;
exit(EXIT_FAILURE);
}
}
#if defined(_WIN32) || defined(__CYGWIN32__)
if (follower_node.second.operatingSystem.empty())
{
if (follower_node.second.password.empty())
{
cerr << "ERROR (node " << follower_node.first
<< "): the Password option must be passed under Windows for every remote "
"node."
<< endl;
exit(EXIT_FAILURE);
}
if (follower_node.second.remoteDrive.empty())
{
cerr << "ERROR (node " << follower_node.first
<< "): the RemoteDrive option must be passed under Windows for every remote "
"node."
<< endl;
exit(EXIT_FAILURE);
}
}
#endif
if (follower_node.second.remoteDirectory.empty())
{
cerr << "ERROR (node " << follower_node.first
<< "): the RemoteDirectory must be specified for every remote node." << endl;
exit(EXIT_FAILURE);
}
}
}
//! Check Clusters
if (clusters.empty())
{
cerr << "ERROR: At least one cluster must be defined in the config file." << endl;
exit(EXIT_FAILURE);
}
if (!cluster_name.empty() && !clusters.contains(cluster_name))
{
cerr << "ERROR: Cluster Name " << cluster_name << " was not found in the config file."
<< endl;
exit(EXIT_FAILURE);
}
for (const auto& cluster : clusters)
for (const auto& itmn : cluster.second.member_nodes)
if (!follower_nodes.contains(itmn.first))
{
cerr << "Error: node " << itmn.first << " specified in cluster " << cluster.first
<< " was not found" << endl;
exit(EXIT_FAILURE);
}
}
void
Configuration::transformPass()
{
/* If the user did not specify the GlobalInitFile option, use global_init.m in configuration
directory if it exists */
if (auto default_global_init_file = findConfigFile("global_init.m");
global_init_file.empty() && !default_global_init_file.empty())
global_init_file = default_global_init_file.string();
if (!parallel && !parallel_test)
return;
#if !defined(_WIN32) && !defined(__CYGWIN32__)
// For Linux/Mac, check that cpuNbr starts at 0
for (auto& it : follower_nodes)
if (it.second.minCpuNbr != 0)
{
it.second.maxCpuNbr = it.second.maxCpuNbr - it.second.minCpuNbr;
it.second.minCpuNbr = 0;
}
#endif
auto& cluster = cluster_name.empty() ? clusters.at(firstClusterName) : clusters.at(cluster_name);
double weight_denominator {0.0};
for (const auto& [name, weight] : cluster.member_nodes)
weight_denominator += weight;
for (auto& [name, weight] : cluster.member_nodes)
weight /= weight_denominator;
}
vector<filesystem::path>
Configuration::getIncludePaths() const
{
vector<filesystem::path> include_paths;
for (const auto& path : paths)
for (const auto& mapit : path.get_paths())
for (const auto& vecit : mapit.second)
include_paths.emplace_back(vecit);
return include_paths;
}
void
Configuration::writeHooks(ostream& output) const
{
if (!global_init_file.empty())
output << "options_.global_init_file = '" << global_init_file << "';" << endl;
}
void
Configuration::writeCluster(ostream& output) const
{
if (!parallel && !parallel_test)
return;
const auto& cluster
= cluster_name.empty() ? clusters.at(firstClusterName) : clusters.at(cluster_name);
for (int i {1}; const auto& [name, node] : follower_nodes)
{
if (!cluster.member_nodes.contains(name))
continue; // Skip nodes not in the selected cluster
output << "options_.parallel";
if (i > 1)
output << "(" << i << ")";
i++;
output << " = struct('Local', " << noboolalpha << (node.computerName == "localhost") << ", "
<< "'ComputerName', '" << node.computerName << "', "
<< "'Port', '" << node.port << "', "
<< "'CPUnbr', [" << node.minCpuNbr << ":" << node.maxCpuNbr << "], "
<< "'UserName', '" << node.userName << "', "
<< "'Password', '" << node.password << "', "
<< "'RemoteDrive', '" << node.remoteDrive << "', "
<< "'RemoteDirectory', '" << node.remoteDirectory
<< "', "
// The following should be switched back to “ProgramPath” once we move to Dragonfly
<< "'DynarePath', '" << node.programPath << "', "
<< "'ProgramConfig', '" << node.programConfig << "', "
<< "'MatlabOctavePath', '" << node.matlabOctavePath << "', "
<< "'OperatingSystem', '" << node.operatingSystem << "', "
<< "'NodeWeight', '" << cluster.member_nodes.at(name) << "', "
<< "'NumberOfThreadsPerJob', " << node.numberOfThreadsPerJob << ", "
<< "'SingleCompThread', '" << boolalpha << node.singleCompThread << "');" << endl;
}
// Default values for the following two are both in DynareMain.cc and
// matlab/default_option_values.m
if (parallel_follower_open_mode)
output << "options_.parallel_info.leaveSlaveOpen = 1;" << endl;
if (!parallel_use_psexec)
output << "options_.parallel_info.use_psexec = false;" << endl;
output << "options_.parallel_info.console_mode= isoctave;" << endl;
output << "InitializeComputationalEnvironment();" << endl;
if (parallel_test)
output
<< "ErrorCode = AnalyseComputationalEnvironment(options_.parallel, options_.parallel_info);"
<< endl
<< "disp(['AnalyseComputationalEnvironment returned with Error Code: ' "
"num2str(ErrorCode)]);"
<< endl
<< "diary off;" << endl
<< "return;" << endl;
}
void
Configuration::writeEndParallel(ostream& output) const
{
if ((!parallel && !parallel_test) || !parallel_follower_open_mode)
return;
output << "if options_.parallel_info.leaveSlaveOpen == 1" << endl
<< " closeSlave(options_.parallel,options_.parallel_info.RemoteTmpFolder);" << endl
<< "end" << endl;
}
filesystem::path
Configuration::findConfigFile(const string& filename)
{
#ifdef _WIN32
array<wchar_t, MAX_PATH + 1> appdata;
if (SHGetFolderPathW(nullptr, CSIDL_APPDATA | CSIDL_FLAG_DONT_VERIFY, nullptr, SHGFP_TYPE_CURRENT,
appdata.data())
== S_OK)
{
filesystem::path candidate {filesystem::path {appdata.data()} / "dynare" / filename};
if (exists(candidate))
return candidate;
}
#else
filesystem::path xdg_config_home;
if (auto xdg_config_home_env = getenv("XDG_CONFIG_HOME"); xdg_config_home_env)
xdg_config_home = xdg_config_home_env;
if (auto home = getenv("HOME"); xdg_config_home.empty() && home)
xdg_config_home = filesystem::path {home} / ".config";
if (!xdg_config_home.empty())
{
filesystem::path candidate {xdg_config_home / "dynare" / filename};
if (exists(candidate))
return candidate;
}
string xdg_config_dirs;
if (auto xdg_config_dirs_env = getenv("XDG_CONFIG_DIRS"); xdg_config_dirs_env)
xdg_config_dirs = xdg_config_dirs_env;
if (xdg_config_dirs.empty())
xdg_config_dirs = "/etc/xdg";
for (const auto& dir : DataTree::strsplit(xdg_config_dirs, ':'))
{
filesystem::path candidate {filesystem::path {dir} / "dynare" / filename};
if (exists(candidate))
return candidate;
}
#endif
return {};
}
/*
* Copyright © 2010-2023 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef CONFIGURATION_HH
#define CONFIGURATION_HH
#include <filesystem>
#include <map>
#include <vector>
#include "WarningConsolidation.hh"
using namespace std;
/* The abstract representation of the configuration.
Merges information from the command-line and from the configuration file. */
class Configuration
{
public:
Configuration(bool parallel_arg, bool parallel_test_arg, bool parallel_follower_open_mode_arg,
bool parallel_use_psexec_arg, string cluster_name);
private:
using member_nodes_t = map<string, double>;
class Path
{
public:
explicit Path(vector<string> includepath_arg);
[[nodiscard]] map<string, vector<string>>
get_paths() const
{
return paths;
}
private:
map<string, vector<string>> paths;
};
struct FollowerNode
{
FollowerNode(string computerName_arg, string port_arg, int minCpuNbr_arg, int maxCpuNbr_arg,
string userName_arg, string password_arg, string remoteDrive_arg,
string remoteDirectory_arg, string programPath_arg, string programConfig_arg,
string matlabOctavePath_arg, bool singleCompThread_arg,
int numberOfThreadsPerJob_arg, string operatingSystem_arg);
const string computerName, port;
int minCpuNbr, maxCpuNbr;
const string userName, password;
const string remoteDrive, remoteDirectory;
const string programPath, programConfig, matlabOctavePath;
const bool singleCompThread;
const int numberOfThreadsPerJob;
const string operatingSystem;
};
struct Cluster
{
explicit Cluster(member_nodes_t member_nodes_arg);
member_nodes_t member_nodes;
};
const bool parallel, parallel_test, parallel_follower_open_mode, parallel_use_psexec;
const string cluster_name;
string firstClusterName;
//! Hooks
string global_init_file;
//! Paths
vector<Path> paths;
//! Cluster Table
map<string, Cluster> clusters;
//! Node Map
map<string, FollowerNode> follower_nodes;
//! Add Paths
void addPathsConfFileElement(vector<string> includepath);
//! Add a FollowerNode or a Cluster object
void addParallelConfFileElement(bool inNode, bool inCluster, const member_nodes_t& member_nodes,
const string& name, const string& computerName,
const string& port, int minCpuNbr, int maxCpuNbr,
const string& userName, const string& password,
const string& remoteDrive, const string& remoteDirectory,
const string& programPath, const string& programConfig,
const string& matlabOctavePath, bool singleCompThread,
int numberOfThreadsPerJob, const string& operatingSystem);
/* Given a filename (e.g. dynare.ini), looks for it in the configuration directory:
– if under Linux or macOS, look into the “dynare” subdirectory of the XDG
configuration directories (following the default values and the precedence order specified in
the XDG specification)
– if under Windows, look into %APPDATA%\dynare\
The returned path will be empty if the file is not found. */
[[nodiscard]] static filesystem::path findConfigFile(const string& filename);
public:
//! Parse config file
void getConfigFileInfo(const filesystem::path& conffile_option, WarningConsolidation& warnings);
//! Check Pass
void checkPass(WarningConsolidation& warnings) const;
//! Check Pass
void transformPass();
//! Get Path Info
[[nodiscard]] vector<filesystem::path> getIncludePaths() const;
//! Write any hooks
void writeHooks(ostream& output) const;
//! Create options_.parallel structure, write options
void writeCluster(ostream& output) const;
//! Close follower nodes if needed
void writeEndParallel(ostream& output) const;
};
#endif