Skip to content
Snippets Groups Projects
Select Git revision
  • bfc002a054ad44449671ef2bc54d5fe9f2202138
  • master default protected
  • julia protected
  • 6.x protected
  • python-codegen
  • llvm-15
  • 5.x protected
  • 4.6 protected
  • uop
  • rework_pac
  • aux_vars_fix
  • julia-7.0.0
  • julia-6.4.0
  • julia-6.3.0
  • julia-6.2.0
15 results

CodeInterpreter.hh

Blame
  • Sébastien Villemot's avatar
    e2d5a835
    History
    CodeInterpreter.hh 53.03 KiB
    /*
     * Copyright © 2007-2019 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 <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, //!< Type to mark unused endogenous variables when `nostrict` option is passed
       endogenousVAR = 17, //!< Variables declared in a var_model statement
       epilogue = 18, //!< Variables created in epilogue block
       excludedVariable = 19 //!< Type to use when an equation is excluded via include/exclude_eqs and the LHS variable is not used elsewhere in the model
      };
    
    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,
       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,
       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
      };
    
    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_(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_(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_(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_(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_(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_(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_(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_(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_(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_(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_(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_(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_(unsigned int pos_arg1, 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_(unsigned int pos_arg1, unsigned int pos_arg2, int pos_arg3, 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_(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_(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_(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, 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_(uint8_t type_arg, 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_(uint8_t type_arg, 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_(int type_arg, unsigned int pos_arg) :
        TagWithThreeArguments<uint8_t, unsigned int, int>::TagWithThreeArguments{FLDV, static_cast<uint8_t>(type_arg), pos_arg, 0}
      {
      };
      inline
      FLDV_(int type_arg, unsigned int pos_arg, 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_(int type_arg, unsigned int pos_arg) :
        TagWithThreeArguments<uint8_t, unsigned int, int>::TagWithThreeArguments{FSTPV, static_cast<uint8_t>(type_arg), pos_arg, 0}
      {
      };
      inline
      FSTPV_(int type_arg, unsigned int pos_arg, 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},
        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},
        func_name{f_name},
        add_input_arguments{0},
        row{0},
        col{0},
        function_type{ExternalFunctionType::withoutDerivative}
      {
      };
      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 = static_cast<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 = static_cast<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 = static_cast<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