diff --git a/mex/sources/bytecode/ErrorHandling.hh b/mex/sources/bytecode/ErrorHandling.hh
index a354fa67ae91ccb93422f7ceebc4763c7610a117..df0af76e2ba0ffd9d0645a898542325a0dcfb065 100644
--- a/mex/sources/bytecode/ErrorHandling.hh
+++ b/mex/sources/bytecode/ErrorHandling.hh
@@ -165,35 +165,18 @@ extern "C" bool utIsInterruptPending();
 
 class ErrorMsg
 {
-private:
-  bool is_load_variable_list;
-
-public:
-  double *y, *ya;
-  int y_size;
-  double *T;
-  int nb_row_x, col_x, col_y;
-  int y_kmin, y_kmax, periods;
-  double *x, *params;
-  double *u;
-  double *steady_y, *steady_x;
-  double *g2, *g1, *r, *res;
-  vector<s_plan> splan, spfplan;
-  vector<mxArray *> jacobian_block, jacobian_other_endo_block, jacobian_exo_block, jacobian_det_exo_block;
-  map<int, double> TEF;
-  map<pair<int, int>, double> TEFD;
-  map<tuple<int, int, int>, double> TEFDD;
-
+protected:
   ExpressionType EQN_type;
-  it_code_type it_code_expr;
+  int EQN_equation, EQN_block, EQN_block_number, EQN_dvar1;
   size_t endo_name_length; // Maximum length of endogenous names
-  vector<string> P_endo_names, P_exo_names, P_param_names;
-  int EQN_equation, EQN_block, EQN_block_number;
-  int EQN_dvar1, EQN_dvar2, EQN_dvar3;
+  vector<string> P_endo_names;
+private:
+  bool is_load_variable_list;
+  vector<string> P_exo_names, P_param_names;
   vector<tuple<string, SymbolType, unsigned int>> Variable_list;
 
-  inline
-  ErrorMsg()
+public:
+  ErrorMsg() : is_load_variable_list {false}
   {
     mxArray *M_ = mexGetVariable("global", "M_");
     if (!M_)
@@ -224,14 +207,14 @@ public:
     endo_name_length = 0;
     for (const auto &n : P_endo_names)
       endo_name_length = max(endo_name_length, n.size());
-
-    is_load_variable_list = false;
   }
 
+private:
   /* Given a string which possibly contains a floating-point exception
     (materialized by an operator between braces), returns a string spanning two
-    lines, the second line containing tildes (~) under the faulty operator. */
-  inline string
+    lines, the first line containing the original string without the braces,
+    the second line containing tildes (~) under the faulty operator. */
+  string
   add_underscore_to_fpe(const string &str)
   {
     string temp;
@@ -259,23 +242,22 @@ public:
     return temp;
   }
 
-  inline void
+  void
   load_variable_list()
   {
-    for (unsigned int variable_num = 0; variable_num < P_endo_names.size(); variable_num++)
+    if (exchange(is_load_variable_list, true))
+      return;
+    for (size_t variable_num {0}; variable_num < P_endo_names.size(); variable_num++)
       Variable_list.emplace_back(P_endo_names[variable_num], SymbolType::endogenous, variable_num);
-    for (unsigned int variable_num = 0; variable_num < P_exo_names.size(); variable_num++)
+    for (size_t variable_num {0}; variable_num < P_exo_names.size(); variable_num++)
       Variable_list.emplace_back(P_exo_names[variable_num], SymbolType::exogenous, variable_num);
   }
 
-  inline int
+public:
+  int
   get_ID(const string &variable_name, SymbolType *variable_type)
   {
-    if (!is_load_variable_list)
-      {
-        load_variable_list();
-        is_load_variable_list = true;
-      }
+    load_variable_list();
     size_t n = Variable_list.size();
     int i = 0;
     bool notfound = true;
@@ -292,7 +274,8 @@ public:
     return -1;
   }
 
-  inline string
+protected:
+  string
   get_variable(SymbolType variable_type, unsigned int variable_num) const
   {
     switch (variable_type)
@@ -325,8 +308,8 @@ public:
     exit(EXIT_FAILURE); // Silence GCC warning
   }
 
-  inline string
-  error_location(bool evaluate, bool steady_state, int size, int block_num, int it_, int Per_u_)
+  string
+  error_location(it_code_type expr_begin, it_code_type faulty_op, bool steady_state, int it_)
   {
     ostringstream Error_loc;
     if (!steady_state)
@@ -413,40 +396,33 @@ public:
         default:
           return ("???");
         }
-    it_code_type it_code_ret;
-    Error_loc << endl << add_underscore_to_fpe("      " + print_expression(it_code_expr, evaluate, size, block_num, steady_state, Per_u_, it_, it_code_ret, true));
+    auto [expr_str, it_code_ret] = print_expression(expr_begin, faulty_op);
+    Error_loc << endl << add_underscore_to_fpe("      " + expr_str);
     return Error_loc.str();
   }
 
-  inline string
-  print_expression(it_code_type it_code, bool evaluate, int size, int block_num, bool steady_state, int Per_u_, int it_, it_code_type &it_code_ret, bool compute) const
+  /* Prints a bytecode expression in human readable form.
+     If faulty_op is not default constructed, it should point to a tag withing
+     the expression that created a floating point exception, in which case the
+     corresponding mathematical operator will be printed within braces.
+     The second output argument points to the tag past the expression. */
+  pair<string, it_code_type>
+  print_expression(it_code_type expr_begin, it_code_type faulty_op = {}) const
   {
     int var, lag{0}, eq;
     UnaryOpcode op1;
     BinaryOpcode op2;
     TrinaryOpcode op3;
     stack<string> Stack;
-    stack<double> Stackf;
     ostringstream tmp_out, tmp_out2;
     string v1, v2, v3;
-    double v1f, v2f, v3f = 0.0;
     bool go_on = true;
     double ll;
     ExpressionType equation_type = ExpressionType::TemporaryTerm;
     size_t found;
-    double *jacob = nullptr, *jacob_other_endo = nullptr, *jacob_exo = nullptr, *jacob_exo_det = nullptr;
     ExternalFunctionCallType call_type{ExternalFunctionCallType::levelWithoutDerivative};
 
-    if (evaluate)
-      {
-        jacob = mxGetPr(jacobian_block[block_num]);
-        if (!steady_state)
-          {
-            jacob_other_endo = mxGetPr(jacobian_other_endo_block[block_num]);
-            jacob_exo = mxGetPr(jacobian_exo_block[block_num]);
-            jacob_exo_det = mxGetPr(jacobian_det_exo_block[block_num]);
-          }
-      }
+    it_code_type it_code {expr_begin};
 
     while (go_on)
       {
@@ -490,8 +466,6 @@ public:
               case SymbolType::parameter:
                 var = static_cast<FLDV_ *>(it_code->second)->get_pos();
                 Stack.push(get_variable(SymbolType::parameter, var));
-                if (compute)
-                  Stackf.push(params[var]);
                 break;
               case SymbolType::endogenous:
                 var = static_cast<FLDV_ *>(it_code->second)->get_pos();
@@ -504,13 +478,6 @@ public:
                 else
                   tmp_out << get_variable(SymbolType::endogenous, var);
                 Stack.push(tmp_out.str());
-                if (compute)
-                  {
-                    if (evaluate)
-                      Stackf.push(ya[(it_+lag)*y_size+var]);
-                    else
-                      Stackf.push(y[(it_+lag)*y_size+var]);
-                  }
                 break;
               case SymbolType::exogenous:
                 var = static_cast<FLDV_ *>(it_code->second)->get_pos();
@@ -521,8 +488,6 @@ public:
                 else
                   tmp_out << get_variable(SymbolType::exogenous, var);
                 Stack.push(tmp_out.str());
-                if (compute)
-                  Stackf.push(x[it_+lag+var*nb_row_x]);
                 break;
               case SymbolType::exogenousDet:
                 mexErrMsgTxt("FLDV: exogenous deterministic not supported");
@@ -541,30 +506,14 @@ public:
               case SymbolType::parameter:
                 var = static_cast<FLDSV_ *>(it_code->second)->get_pos();
                 Stack.push(get_variable(SymbolType::parameter, var));
-                if (compute)
-                  Stackf.push(params[var]);
                 break;
               case SymbolType::endogenous:
                 var = static_cast<FLDSV_ *>(it_code->second)->get_pos();
                 Stack.push(get_variable(SymbolType::endogenous, var));
-                if (compute)
-                  {
-                    if (it_code->first == Tags::FLDSV)
-                      {
-                        if (evaluate)
-                          Stackf.push(ya[var]);
-                        else
-                          Stackf.push(y[var]);
-                      }
-                    else
-                      Stackf.push(steady_y[var]);
-                  }
                 break;
               case SymbolType::exogenous:
                 var = static_cast<FLDSV_ *>(it_code->second)->get_pos();
                 Stack.push(get_variable(SymbolType::exogenous, var));
-                if (compute)
-                  Stackf.push(x[var]);
                 break;
               case SymbolType::exogenousDet:
                 mexErrMsgTxt("FLDSV: exogenous deterministic not supported");
@@ -581,8 +530,6 @@ public:
             tmp_out.str("");
             tmp_out << "T" << var+1;
             Stack.push(tmp_out.str());
-            if (compute)
-              Stackf.push(T[var*(periods+y_kmin+y_kmax)+it_]);
             break;
           case Tags::FLDST:
             //load a temporary variable in the processor
@@ -590,8 +537,6 @@ public:
             tmp_out.str("");
             tmp_out << "T" << var+1;
             Stack.push(tmp_out.str());
-            if (compute)
-              Stackf.push(T[var]);
             break;
           case Tags::FLDU:
             //load u variable in the processor
@@ -599,9 +544,6 @@ public:
             tmp_out.str("");
             tmp_out << "u(" << var+1 << " + it_)";
             Stack.push(tmp_out.str());
-            var += Per_u_;
-            if (compute)
-              Stackf.push(u[var]);
             break;
           case Tags::FLDSU:
             //load u variable in the processor
@@ -609,24 +551,18 @@ public:
             tmp_out.str("");
             tmp_out << "u(" << var+1 << ")";
             Stack.push(tmp_out.str());
-            if (compute)
-              Stackf.push(u[var]);
             break;
           case Tags::FLDR:
             var = static_cast<FLDR_ *>(it_code->second)->get_pos();
             tmp_out.str("");
             tmp_out << "residual(" << var+1 << ")";
             Stack.push(tmp_out.str());
-            if (compute)
-              Stackf.push(r[var]);
             break;
           case Tags::FLDZ:
             //load 0 in the processor
             tmp_out.str("");
             tmp_out << 0;
             Stack.push(tmp_out.str());
-            if (compute)
-              Stackf.push(0.0);
             break;
           case Tags::FLDC:
             //load a numerical constant in the processor
@@ -634,8 +570,6 @@ public:
             tmp_out.str("");
             tmp_out << ll;
             Stack.push(tmp_out.str());
-            if (compute)
-              Stackf.push(ll);
             break;
           case Tags::FSTPV:
             //load a variable in the processor
@@ -649,11 +583,6 @@ public:
                 tmp_out.str("");
                 tmp_out << get_variable(SymbolType::parameter, var) << " = " << tmp_out2.str();
                 Stack.pop();
-                if (compute)
-                  {
-                    params[var] = Stackf.top();
-                    Stackf.pop();
-                  }
                 break;
               case SymbolType::endogenous:
                 var = static_cast<FSTPV_ *>(it_code->second)->get_pos();
@@ -668,11 +597,6 @@ public:
                   tmp_out << "(" << lag << ")";
                 tmp_out << " = " << tmp_out2.str();
                 Stack.pop();
-                if (compute)
-                  {
-                    y[(it_+lag)*y_size+var] = Stackf.top();
-                    Stackf.pop();
-                  }
                 break;
               case SymbolType::exogenous:
                 var = static_cast<FSTPV_ *>(it_code->second)->get_pos();
@@ -685,11 +609,6 @@ public:
                   tmp_out << "(" << lag << ")";
                 tmp_out << " = " << tmp_out2.str();
                 Stack.pop();
-                if (compute)
-                  {
-                    x[it_+lag+var*nb_row_x] = Stackf.top();
-                    Stackf.pop();
-                  }
                 break;
               case SymbolType::exogenousDet:
                 mexErrMsgTxt("FSTPV: exogenous deterministic not supported");
@@ -711,11 +630,6 @@ public:
                 tmp_out << get_variable(SymbolType::parameter, var);
                 tmp_out << " = " << tmp_out2.str();
                 Stack.pop();
-                if (compute)
-                  {
-                    params[var] = Stackf.top();
-                    Stackf.pop();
-                  }
                 break;
               case SymbolType::endogenous:
                 var = static_cast<FSTPSV_ *>(it_code->second)->get_pos();
@@ -725,11 +639,6 @@ public:
                 tmp_out << get_variable(SymbolType::endogenous, var);
                 tmp_out << " = " << tmp_out2.str();
                 Stack.pop();
-                if (compute)
-                  {
-                    y[var] = Stackf.top();
-                    Stackf.pop();
-                  }
                 break;
               case SymbolType::exogenous:
                 var = static_cast<FSTPSV_ *>(it_code->second)->get_pos();
@@ -739,11 +648,6 @@ public:
                 tmp_out << get_variable(SymbolType::exogenous, var);
                 tmp_out << " = " << tmp_out2.str();
                 Stack.pop();
-                if (compute)
-                  {
-                    x[var] = Stackf.top();
-                    Stackf.pop();
-                  }
                 break;
               case SymbolType::exogenousDet:
                 mexErrMsgTxt("FSTPSV: exogenous deterministic not supported");
@@ -759,11 +663,6 @@ public:
             tmp_out.str("");
             tmp_out << "T" << var+1 << " = " << Stack.top();
             Stack.pop();
-            if (compute)
-              {
-                T[var*(periods+y_kmin+y_kmax)+it_] = Stackf.top();
-                Stackf.pop();
-              }
             break;
           case Tags::FSTPST:
             go_on = false;
@@ -772,11 +671,6 @@ public:
             tmp_out.str("");
             tmp_out << "T" << var+1 << " = " << Stack.top();
             Stack.pop();
-            if (compute)
-              {
-                T[var] = Stackf.top();
-                Stackf.pop();
-              }
             break;
           case Tags::FSTPU:
             go_on = false;
@@ -784,13 +678,7 @@ public:
             var = static_cast<FSTPU_ *>(it_code->second)->get_pos();
             tmp_out.str("");
             tmp_out << "u(" << var+1 << " + it_) = " << Stack.top();
-            var += Per_u_;
             Stack.pop();
-            if (compute)
-              {
-                u[var] = Stackf.top();
-                Stackf.pop();
-              }
             break;
           case Tags::FSTPSU:
             go_on = false;
@@ -799,11 +687,6 @@ public:
             tmp_out.str("");
             tmp_out << "u(" << var+1 << ") = " << Stack.top();
             Stack.pop();
-            if (compute)
-              {
-                u[var] = Stackf.top();
-                Stackf.pop();
-              }
             break;
           case Tags::FSTPR:
             go_on = false;
@@ -812,11 +695,6 @@ public:
             tmp_out.str("");
             tmp_out << "residual(" << var+1 << ") = " << Stack.top();
             Stack.pop();
-            if (compute)
-              {
-                r[var] = Stackf.top();
-                Stackf.pop();
-              }
             break;
           case Tags::FSTPG:
             go_on = false;
@@ -825,11 +703,6 @@ public:
             tmp_out.str("");
             tmp_out << "g1[" << var+1 << "] = " << Stack.top();
             Stack.pop();
-            if (compute)
-              {
-                g1[var] = Stackf.top();
-                Stackf.pop();
-              }
             break;
           case Tags::FSTPG2:
             go_on = false;
@@ -837,57 +710,31 @@ public:
             eq = static_cast<FSTPG2_ *>(it_code->second)->get_row();
             var = static_cast<FSTPG2_ *>(it_code->second)->get_col();
             tmp_out.str("");
-            tmp_out << "/*jacob(" << eq << ", " << var << ")*/ jacob(" << eq+size*var+1 << ") = " << Stack.top();
+            tmp_out << "jacob(" << eq+1 << ", " << var+1 << ") = " << Stack.top();
             Stack.pop();
-            if (compute)
-              {
-                jacob[eq + size*var] = Stackf.top();
-                Stackf.pop();
-              }
             break;
           case Tags::FSTPG3:
             //store in derivative (g) variable from the processor
-            double r;
-            int pos_col;
             go_on = false;
-            if (compute)
-              {
-                r = Stackf.top();
-                Stackf.pop();
-              }
+            int pos_col;
             eq = static_cast<FSTPG3_ *>(it_code->second)->get_row();
             var = static_cast<FSTPG3_ *>(it_code->second)->get_col();
             lag = static_cast<FSTPG3_ *>(it_code->second)->get_lag();
             pos_col = static_cast<FSTPG3_ *>(it_code->second)->get_col_pos();
+            tmp_out.str("");
             switch (equation_type)
               {
               case ExpressionType::FirstEndoDerivative:
-                if (compute)
-                  jacob[eq + size*pos_col] = r;
-                tmp_out.str("");
-                tmp_out << "/*jacob(" << eq << ", " << pos_col << " var= " << var << ")*/ jacob(" << eq+size*pos_col+1 << ") = " << Stack.top();
-                Stack.pop();
+                tmp_out << "jacob";
                 break;
               case ExpressionType::FirstOtherEndoDerivative:
-                if (compute)
-                  jacob_other_endo[eq + size*pos_col] = r;
-                tmp_out.str("");
-                tmp_out << "jacob_other_endo(" << eq+size*pos_col+1 << ") = " << Stack.top();
-                Stack.pop();
+                tmp_out << "jacob_other_endo";
                 break;
               case ExpressionType::FirstExoDerivative:
-                if (compute)
-                  jacob_exo[eq + size*pos_col] = r;
-                tmp_out.str("");
-                tmp_out << "/*jacob_exo(" << eq << ", " << pos_col << " var=" << var << ")*/ jacob_exo(" << eq+size*pos_col+1 << ") = " << Stack.top();
-                Stack.pop();
+                tmp_out << "jacob_exo";
                 break;
               case ExpressionType::FirstExodetDerivative:
-                if (compute)
-                  jacob_exo_det[eq + size*pos_col] = r;
-                tmp_out.str("");
-                tmp_out << "/*jacob_exo_det(" << eq << ", " << pos_col << " var=" << var << ")*/ jacob_exo_det(" << eq+size*pos_col+1 << ") = " << Stack.top();
-                Stack.pop();
+                tmp_out << "jacob_exo_det";
                 break;
               default:
                 ostringstream tmp;
@@ -895,6 +742,8 @@ public:
                 //throw FatalExceptionHandling(tmp.str());
                 mexPrintf("%s", tmp.str().c_str());
               }
+            tmp_out << "(" << eq+1 << ", " << pos_col+1 << " [var=" << var+1 << ", lag=" << lag << "]) = " << Stack.top();
+            Stack.pop();
             break;
           case Tags::FBINARY:
             op2 = static_cast<FBINARY_ *>(it_code->second)->get_op_type();
@@ -902,25 +751,14 @@ public:
             Stack.pop();
             v1 = Stack.top();
             Stack.pop();
-            if (compute)
-              {
-                v2f = Stackf.top();
-                Stackf.pop();
-                v1f = Stackf.top();
-                Stackf.pop();
-              }
             switch (op2)
               {
               case BinaryOpcode::plus:
-                if (compute)
-                  Stackf.push(v1f + v2f);
                 tmp_out.str("");
                 tmp_out << v1 << " + " << v2;
                 Stack.push(tmp_out.str());
                 break;
               case BinaryOpcode::minus:
-                if (compute)
-                  Stackf.push(v1f - v2f);
                 tmp_out.str("");
                 found = v1.find(" ");
                 if (found != string::npos)
@@ -938,8 +776,6 @@ public:
                 Stack.push(tmp_out.str());
                 break;
               case BinaryOpcode::times:
-                if (compute)
-                  Stackf.push(v1f * v2f);
                 tmp_out.str("");
                 found = v1.find(" ");
                 if (found != string::npos)
@@ -957,11 +793,6 @@ public:
                 Stack.push(tmp_out.str());
                 break;
               case BinaryOpcode::divide:
-                if (compute)
-                  {
-                    r = v1f / v2f;
-                    Stackf.push(r);
-                  }
                 tmp_out.str("");
                 found = v1.find(" ");
                 if (found != string::npos)
@@ -969,7 +800,7 @@ public:
                 tmp_out << v1;
                 if (found != string::npos)
                   tmp_out << ")";
-                if (compute && isinf(r))
+                if (it_code == faulty_op)
                   tmp_out << "{ / }";
                 else
                   tmp_out << " / ";
@@ -982,8 +813,6 @@ public:
                 Stack.push(tmp_out.str());
                 break;
               case BinaryOpcode::less:
-                if (compute)
-                  Stackf.push(static_cast<double>(v1f < v2f));
                 tmp_out.str("");
                 found = v1.find(" ");
                 if (found != string::npos)
@@ -1001,8 +830,6 @@ public:
                 Stack.push(tmp_out.str());
                 break;
               case BinaryOpcode::greater:
-                if (compute)
-                  Stackf.push(static_cast<double>(v1f > v2f));
                 tmp_out.str("");
                 found = v1.find(" ");
                 if (found != string::npos)
@@ -1020,8 +847,6 @@ public:
                 Stack.push(tmp_out.str());
                 break;
               case BinaryOpcode::lessEqual:
-                if (compute)
-                  Stackf.push(static_cast<double>(v1f <= v2f));
                 tmp_out.str("");
                 found = v1.find(" ");
                 if (found != string::npos)
@@ -1039,8 +864,6 @@ public:
                 Stack.push(tmp_out.str());
                 break;
               case BinaryOpcode::greaterEqual:
-                if (compute)
-                  Stackf.push(static_cast<double>(v1f >= v2f));
                 tmp_out.str("");
                 found = v1.find(" ");
                 if (found != string::npos)
@@ -1058,8 +881,6 @@ public:
                 Stack.push(tmp_out.str());
                 break;
               case BinaryOpcode::equalEqual:
-                if (compute)
-                  Stackf.push(static_cast<double>(v1f == v2f));
                 tmp_out.str("");
                 found = v1.find(" ");
                 if (found != string::npos)
@@ -1077,8 +898,6 @@ public:
                 Stack.push(tmp_out.str());
                 break;
               case BinaryOpcode::different:
-                if (compute)
-                  Stackf.push(static_cast<double>(v1f != v2f));
                 tmp_out.str("");
                 found = v1.find(" ");
                 if (found != string::npos)
@@ -1096,11 +915,6 @@ public:
                 Stack.push(tmp_out.str());
                 break;
               case BinaryOpcode::power:
-                if (compute)
-                  {
-                    r = pow(v1f, v2f);
-                    Stackf.push(r);
-                  }
                 tmp_out.str("");
                 found = v1.find(" ");
                 if (found != string::npos)
@@ -1108,7 +922,7 @@ public:
                 tmp_out << v1;
                 if (found != string::npos)
                   tmp_out << ")";
-                if (compute && isnan(r))
+                if (it_code == faulty_op)
                   tmp_out << "{ ^ }";
                 else
                   tmp_out << " ^ ";
@@ -1124,28 +938,8 @@ public:
                 {
                   v3 = Stack.top();
                   Stack.pop();
-                  if (compute)
-                    {
-                      int derivOrder = static_cast<int>(nearbyint(Stackf.top()));
-                      Stackf.pop();
-                      if (fabs(v1f) < power_deriv_near_zero && v2f > 0
-                          && derivOrder > v2f
-                          && fabs(v2f-nearbyint(v2f)) < power_deriv_near_zero)
-                        {
-                          r = 0.0;
-                          Stackf.push(r);
-                        }
-                      else
-                        {
-                          double dxp = pow(v1f, v2f-derivOrder);
-                          for (int i = 0; i < derivOrder; i++)
-                            dxp *= v2f--;
-                          Stackf.push(dxp);
-                          r = dxp;
-                        }
-                    }
                   tmp_out.str("");
-                  if (compute && isnan(r))
+                  if (it_code == faulty_op)
                     tmp_out << "{PowerDeriv}";
                   else
                     tmp_out << "PowerDeriv";
@@ -1154,15 +948,11 @@ public:
                 }
                 break;
               case BinaryOpcode::max:
-                if (compute)
-                  Stackf.push(max(v1f, v2f));
                 tmp_out.str("");
                 tmp_out << "max(" << v1 << ", " << v2 << ")";
                 Stack.push(tmp_out.str());
                 break;
               case BinaryOpcode::min:
-                if (compute)
-                  Stackf.push(min(v1f, v2f));
                 tmp_out.str("");
                 tmp_out << "min(" << v1 << ", " << v2 << ")";
                 Stack.push(tmp_out.str());
@@ -1177,35 +967,21 @@ public:
             op1 = static_cast<FUNARY_ *>(it_code->second)->get_op_type();
             v1 = Stack.top();
             Stack.pop();
-            if (compute)
-              {
-                v1f = Stackf.top();
-                Stackf.pop();
-              }
             switch (op1)
               {
               case UnaryOpcode::uminus:
-                if (compute)
-                  Stackf.push(-v1f);
                 tmp_out.str("");
                 tmp_out << " -" << v1;
                 Stack.push(tmp_out.str());
                 break;
               case UnaryOpcode::exp:
-                if (compute)
-                  Stackf.push(exp(v1f));
                 tmp_out.str("");
                 tmp_out << "exp(" << v1 << ")";
                 Stack.push(tmp_out.str());
                 break;
               case UnaryOpcode::log:
-                if (compute)
-                  {
-                    r = log(v1f);
-                    Stackf.push(r);
-                  }
                 tmp_out.str("");
-                if (compute && isnan(r))
+                if (it_code == faulty_op)
                   tmp_out << "{log}";
                 else
                   tmp_out << "log";
@@ -1213,13 +989,8 @@ public:
                 Stack.push(tmp_out.str());
                 break;
               case UnaryOpcode::log10:
-                if (compute)
-                  {
-                    r = log10(v1f);
-                    Stackf.push(r);
-                  }
                 tmp_out.str("");
-                if (compute && isnan(r))
+                if (it_code == faulty_op)
                   tmp_out << "{log10}";
                 else
                   tmp_out << "log10";
@@ -1227,106 +998,76 @@ public:
                 Stack.push(tmp_out.str());
                 break;
               case UnaryOpcode::cos:
-                if (compute)
-                  Stackf.push(cos(v1f));
                 tmp_out.str("");
                 tmp_out << "cos(" << v1 << ")";
                 Stack.push(tmp_out.str());
                 break;
               case UnaryOpcode::sin:
-                if (compute)
-                  Stackf.push(sin(v1f));
                 tmp_out.str("");
                 tmp_out << "sin(" << v1 << ")";
                 Stack.push(tmp_out.str());
                 break;
               case UnaryOpcode::tan:
-                if (compute)
-                  Stackf.push(tan(v1f));
                 tmp_out.str("");
                 tmp_out << "tan(" << v1 << ")";
                 Stack.push(tmp_out.str());
                 break;
               case UnaryOpcode::acos:
-                if (compute)
-                  Stackf.push(acos(v1f));
                 tmp_out.str("");
                 tmp_out << "acos(" << v1 << ")";
                 Stack.push(tmp_out.str());
                 break;
               case UnaryOpcode::asin:
-                if (compute)
-                  Stackf.push(asin(v1f));
                 tmp_out.str("");
                 tmp_out << "asin(" << v1 << ")";
                 Stack.push(tmp_out.str());
                 break;
               case UnaryOpcode::atan:
-                if (compute)
-                  Stackf.push(atan(v1f));
                 tmp_out.str("");
                 tmp_out << "atan(" << v1 << ")";
                 Stack.push(tmp_out.str());
                 break;
               case UnaryOpcode::cosh:
-                if (compute)
-                  Stackf.push(cosh(v1f));
                 tmp_out.str("");
                 tmp_out << "cosh(" << v1 << ")";
                 Stack.push(tmp_out.str());
                 break;
               case UnaryOpcode::sinh:
-                if (compute)
-                  Stackf.push(sinh(v1f));
                 tmp_out.str("");
                 tmp_out << "sinh(" << v1 << ")";
                 Stack.push(tmp_out.str());
                 break;
               case UnaryOpcode::tanh:
-                if (compute)
-                  Stackf.push(tanh(v1f));
                 tmp_out.str("");
                 tmp_out << "tanh(" << v1 << ")";
                 Stack.push(tmp_out.str());
                 break;
               case UnaryOpcode::acosh:
-                if (compute)
-                  Stackf.push(acosh(v1f));
                 tmp_out.str("");
                 tmp_out << "acosh(" << v1 << ")";
                 Stack.push(tmp_out.str());
                 break;
               case UnaryOpcode::asinh:
-                if (compute)
-                  Stackf.push(asinh(v1f));
                 tmp_out.str("");
                 tmp_out << "asinh(" << v1 << ")";
                 Stack.push(tmp_out.str());
                 break;
               case UnaryOpcode::atanh:
-                if (compute)
-                  Stackf.push(atanh(v1f));
                 tmp_out.str("");
                 tmp_out << "atanh(" << v1 << ")";
                 Stack.push(tmp_out.str());
                 break;
               case UnaryOpcode::sqrt:
-                if (compute)
-                  Stackf.push(sqrt(v1f));
                 tmp_out.str("");
                 tmp_out << "sqrt(" << v1 << ")";
                 Stack.push(tmp_out.str());
                 break;
               case UnaryOpcode::erf:
-                if (compute)
-                  Stackf.push(erf(v1f));
                 tmp_out.str("");
                 tmp_out << "erf(" << v1 << ")";
                 Stack.push(tmp_out.str());
                 break;
               case UnaryOpcode::erfc:
-                if (compute)
-                  Stackf.push(erfc(v1f));
                 tmp_out.str("");
                 tmp_out << "erfc(" << v1 << ")";
                 Stack.push(tmp_out.str());
@@ -1344,27 +1085,14 @@ public:
             Stack.pop();
             v1 = Stack.top();
             Stack.pop();
-            if (compute)
-              {
-                v3f = Stackf.top();
-                Stackf.pop();
-                v2f = Stackf.top();
-                Stackf.pop();
-                v1f = Stackf.top();
-                Stackf.pop();
-              }
             switch (op3)
               {
               case TrinaryOpcode::normcdf:
-                if (compute)
-                  Stackf.push(0.5*(1+erf((v1f-v2f)/v3f/M_SQRT2)));
                 tmp_out.str("");
                 tmp_out << "normcdf(" << v1 << ", " << v2 << ", " << v3 << ")";
                 Stack.push(tmp_out.str());
                 break;
               case TrinaryOpcode::normpdf:
-                if (compute)
-                  Stackf.push(1/(v3f*sqrt(2*M_PI)*exp(pow((v1f-v2f)/v3f, 2)/2)));
                 tmp_out.str("");
                 tmp_out << "normpdf(" << v1 << ", " << v2 << ", " << v3 << ")";
                 Stack.push(tmp_out.str());
@@ -1378,32 +1106,16 @@ public:
               auto *fc = static_cast<FCALL_ *>(it_code->second);
               string function_name = fc->get_function_name();
               int nb_input_arguments{fc->get_nb_input_arguments()};
-              int nb_output_arguments{fc->get_nb_output_arguments()};
 
-              mxArray *output_arguments[3];
               string arg_func_name = fc->get_arg_func_name();
               int nb_add_input_arguments{fc->get_nb_add_input_arguments()};
               call_type = fc->get_call_type();
-              mxArray **input_arguments;
               switch (call_type)
                 {
                 case ExternalFunctionCallType::levelWithoutDerivative:
                 case ExternalFunctionCallType::levelWithFirstDerivative:
                 case ExternalFunctionCallType::levelWithFirstAndSecondDerivative:
                   {
-                    if (compute)
-                      {
-                        input_arguments = static_cast<mxArray **>(mxMalloc(nb_input_arguments * sizeof(mxArray *)));
-                        for (int i{0}; i < nb_input_arguments; i++)
-                          {
-                            mxArray *vv = mxCreateDoubleScalar(Stackf.top());
-                            input_arguments[nb_input_arguments - i - 1] = vv;
-                            Stackf.pop();
-                          }
-                        mexCallMATLAB(nb_output_arguments, output_arguments, nb_input_arguments, input_arguments, function_name.c_str());
-                        double *rr = mxGetPr(output_arguments[0]);
-                        Stackf.push(*rr);
-                      }
                     tmp_out.str("");
                     tmp_out << function_name << "(";
                     vector<string> ss(nb_input_arguments);
@@ -1424,26 +1136,6 @@ public:
                   break;
                 case ExternalFunctionCallType::numericalFirstDerivative:
                   {
-                    if (compute)
-                      {
-                        input_arguments = static_cast<mxArray **>(mxMalloc((nb_input_arguments+1+nb_add_input_arguments) * sizeof(mxArray *)));
-                        mxArray *vv = mxCreateString(arg_func_name.c_str());
-                        input_arguments[0] = vv;
-                        vv = mxCreateDoubleScalar(fc->get_row());
-                        input_arguments[1] = vv;
-                        vv = mxCreateCellMatrix(1, nb_add_input_arguments);
-                        for (int i{0}; i < nb_add_input_arguments; i++)
-                          {
-                            double rr = Stackf.top();
-                            mxSetCell(vv, nb_add_input_arguments - (i+1), mxCreateDoubleScalar(rr));
-                            Stackf.pop();
-                          }
-                        input_arguments[nb_input_arguments+nb_add_input_arguments] = vv;
-                        nb_input_arguments = 3;
-                        mexCallMATLAB(nb_output_arguments, output_arguments, nb_input_arguments, input_arguments, function_name.c_str());
-                        double *rr = mxGetPr(output_arguments[0]);
-                        Stackf.push(*rr);
-                      }
                     tmp_out.str("");
                     tmp_out << function_name << "(";
                     tmp_out << arg_func_name.c_str() << ", " << fc->get_row() << ", {";
@@ -1465,17 +1157,6 @@ public:
                   break;
                 case ExternalFunctionCallType::separatelyProvidedFirstDerivative:
                   {
-                    if (compute)
-                      {
-                        input_arguments = static_cast<mxArray **>(mxMalloc(nb_input_arguments * sizeof(mxArray *)));
-                        for (int i{0}; i < nb_input_arguments; i++)
-                          {
-                            mxArray *vv = mxCreateDoubleScalar(Stackf.top());
-                            input_arguments[(nb_input_arguments - 1) - i] = vv;
-                            Stackf.pop();
-                          }
-                        mexCallMATLAB(nb_output_arguments, output_arguments, nb_input_arguments, input_arguments, function_name.c_str());
-                      }
                     tmp_out.str("");
                     tmp_out << function_name << "(";
                     vector<string> ss(nb_input_arguments);
@@ -1496,28 +1177,6 @@ public:
                   break;
                 case ExternalFunctionCallType::numericalSecondDerivative:
                   {
-                    if (compute)
-                      {
-                        input_arguments = static_cast<mxArray **>(mxMalloc((nb_input_arguments+1+nb_add_input_arguments) * sizeof(mxArray *)));
-                        mxArray *vv = mxCreateString(arg_func_name.c_str());
-                        input_arguments[0] = vv;
-                        vv = mxCreateDoubleScalar(fc->get_row());
-                        input_arguments[1] = vv;
-                        vv = mxCreateDoubleScalar(fc->get_col());
-                        input_arguments[2] = vv;
-                        vv = mxCreateCellMatrix(1, nb_add_input_arguments);
-                        for (int i{0}; i < nb_add_input_arguments; i++)
-                          {
-                            double rr = Stackf.top();
-                            mxSetCell(vv, (nb_add_input_arguments - 1) - i, mxCreateDoubleScalar(rr));
-                            Stackf.pop();
-                          }
-                        input_arguments[nb_input_arguments+nb_add_input_arguments] = vv;
-                        nb_input_arguments = 3;
-                        mexCallMATLAB(nb_output_arguments, output_arguments, nb_input_arguments, input_arguments, function_name.c_str());
-                        double *rr = mxGetPr(output_arguments[0]);
-                        Stackf.push(*rr);
-                      }
                     tmp_out.str("");
                     tmp_out << function_name << "(";
                     tmp_out << arg_func_name.c_str() << ", " << fc->get_row() << ", " << fc->get_col() << ", {";
@@ -1539,17 +1198,6 @@ public:
                   break;
                 case ExternalFunctionCallType::separatelyProvidedSecondDerivative:
                   {
-                    if (compute)
-                      {
-                        input_arguments = static_cast<mxArray **>(mxMalloc(nb_input_arguments * sizeof(mxArray *)));
-                        for (int i{0}; i < nb_input_arguments; i++)
-                          {
-                            mxArray *vv = mxCreateDoubleScalar(Stackf.top());
-                            input_arguments[i] = vv;
-                            Stackf.pop();
-                          }
-                        mexCallMATLAB(nb_output_arguments, output_arguments, nb_input_arguments, input_arguments, function_name.c_str());
-                      }
                     tmp_out.str("");
                     tmp_out << function_name << "(";
                     vector<string> ss(nb_input_arguments);
@@ -1574,10 +1222,6 @@ public:
           case Tags::FSTPTEF:
             go_on = false;
             var = static_cast<FSTPTEF_ *>(it_code->second)->get_number();
-            if (compute)
-              {
-                Stackf.pop();
-              }
             tmp_out.str("");
             switch (call_type)
               {
@@ -1597,11 +1241,6 @@ public:
             break;
           case Tags::FLDTEF:
             var = static_cast<FLDTEF_ *>(it_code->second)->get_number();
-            if (compute)
-              {
-                auto it = TEF.find(var-1);
-                Stackf.push(it->second);
-              }
             tmp_out.str("");
             tmp_out << "TEF(" << var << ")";
             Stack.push(tmp_out.str());
@@ -1612,10 +1251,6 @@ public:
               go_on = false;
               int indx{static_cast<FSTPTEFD_ *>(it_code->second)->get_indx()};
               int row{static_cast<FSTPTEFD_ *>(it_code->second)->get_row()};
-              if (compute)
-                {
-                  Stackf.pop();
-                }
               tmp_out.str("");
               if (call_type == ExternalFunctionCallType::numericalFirstDerivative)
                 tmp_out << "TEFD(" << indx << ", " << row << ") = " << Stack.top();
@@ -1628,11 +1263,6 @@ public:
             {
               int indx{static_cast<FLDTEFD_ *>(it_code->second)->get_indx()};
               int row{static_cast<FLDTEFD_ *>(it_code->second)->get_row()};
-              if (compute)
-                {
-                  auto it = TEFD.find({ indx, row-1 });
-                  Stackf.push(it->second);
-                }
               tmp_out.str("");
               tmp_out << "TEFD(" << indx << ", " << row << ")";
               Stack.push(tmp_out.str());
@@ -1644,10 +1274,6 @@ public:
               int indx{static_cast<FSTPTEFDD_ *>(it_code->second)->get_indx()};
               int row{static_cast<FSTPTEFDD_ *>(it_code->second)->get_row()};
               int col{static_cast<FSTPTEFDD_ *>(it_code->second)->get_col()};
-              if (compute)
-                {
-                  Stackf.pop();
-                }
               tmp_out.str("");
               if (call_type == ExternalFunctionCallType::numericalSecondDerivative)
                 tmp_out << "TEFDD(" << indx << ", " << row << ", " << col << ") = " << Stack.top();
@@ -1662,11 +1288,6 @@ public:
               int indx{static_cast<FLDTEFDD_ *>(it_code->second)->get_indx()};
               int row{static_cast<FLDTEFDD_ *>(it_code->second)->get_row()};
               int col{static_cast<FSTPTEFDD_ *>(it_code->second)->get_col()};
-              if (compute)
-                {
-                  auto it = TEFDD.find({ indx, row-1, col-1 });
-                  Stackf.push(it->second);
-                }
               tmp_out.str("");
               tmp_out << "TEFDD(" << indx << ", " << row << ", " << col << ")";
               Stack.push(tmp_out.str());
@@ -1695,11 +1316,11 @@ public:
           }
         it_code++;
       }
-    it_code_ret = it_code;
-    return tmp_out.str();
+    return { tmp_out.str(), it_code };
   }
-
-  static inline void
+  
+public:
+  static void
   test_mxMalloc(void *z, int line, const string &file, const string &func, int amount)
   {
     if (!z && amount > 0)
diff --git a/mex/sources/bytecode/Evaluate.cc b/mex/sources/bytecode/Evaluate.cc
index 422de877e6cb04f106660ac779609fdd80c426ed..bb5c15f450f64df13f135c35402dc0930c42f0f9 100644
--- a/mex/sources/bytecode/Evaluate.cc
+++ b/mex/sources/bytecode/Evaluate.cc
@@ -118,6 +118,7 @@ Evaluate::compute_block_time(int Per_u_, bool evaluate, bool no_derivative)
   EQN_block = block_num;
   stack<double> Stack;
   ExternalFunctionCallType call_type{ExternalFunctionCallType::levelWithoutDerivative};
+  it_code_type it_code_expr;
 
 #ifdef DEBUG
   mexPrintf("compute_block_time\n");
@@ -704,7 +705,7 @@ Evaluate::compute_block_time(int Per_u_, bool evaluate, bool no_derivative)
                 }
               catch (FloatingPointExceptionHandling &fpeh)
                 {
-                  mexPrintf("%s      %s\n", fpeh.GetErrorMsg().c_str(), error_location(evaluate, steady_state, size, block_num, it_, Per_u_).c_str());
+                  mexPrintf("%s      %s\n", fpeh.GetErrorMsg().c_str(), error_location(it_code_expr, it_code, steady_state, it_).c_str());
                   go_on = false;
                 }
               Stack.push(tmp);
@@ -758,7 +759,7 @@ Evaluate::compute_block_time(int Per_u_, bool evaluate, bool no_derivative)
                 }
               catch (FloatingPointExceptionHandling &fpeh)
                 {
-                  mexPrintf("%s      %s\n", fpeh.GetErrorMsg().c_str(), error_location(evaluate, steady_state, size, block_num, it_, Per_u_).c_str());
+                  mexPrintf("%s      %s\n", fpeh.GetErrorMsg().c_str(), error_location(it_code_expr, it_code, steady_state, it_).c_str());
                   go_on = false;
                 }
               Stack.push(tmp);
@@ -787,7 +788,7 @@ Evaluate::compute_block_time(int Per_u_, bool evaluate, bool no_derivative)
                   }
                 catch (FloatingPointExceptionHandling &fpeh)
                   {
-                    mexPrintf("%s      %s\n", fpeh.GetErrorMsg().c_str(), error_location(evaluate, steady_state, size, block_num, it_, Per_u_).c_str());
+                    mexPrintf("%s      %s\n", fpeh.GetErrorMsg().c_str(), error_location(it_code_expr, it_code, steady_state, it_).c_str());
                     go_on = false;
                   }
               }
@@ -849,7 +850,7 @@ Evaluate::compute_block_time(int Per_u_, bool evaluate, bool no_derivative)
                 }
               catch (FloatingPointExceptionHandling &fpeh)
                 {
-                  mexPrintf("%s      %s\n", fpeh.GetErrorMsg().c_str(), error_location(evaluate, steady_state, size, block_num, it_, Per_u_).c_str());
+                  mexPrintf("%s      %s\n", fpeh.GetErrorMsg().c_str(), error_location(it_code_expr, it_code, steady_state, it_).c_str());
                   go_on = false;
                 }
               Stack.push(tmp);
@@ -865,7 +866,7 @@ Evaluate::compute_block_time(int Per_u_, bool evaluate, bool no_derivative)
                 }
               catch (FloatingPointExceptionHandling &fpeh)
                 {
-                  mexPrintf("%s      %s\n", fpeh.GetErrorMsg().c_str(), error_location(evaluate, steady_state, size, block_num, it_, Per_u_).c_str());
+                  mexPrintf("%s      %s\n", fpeh.GetErrorMsg().c_str(), error_location(it_code_expr, it_code, steady_state, it_).c_str());
                   go_on = false;
                 }
               Stack.push(tmp);
diff --git a/mex/sources/bytecode/Evaluate.hh b/mex/sources/bytecode/Evaluate.hh
index 47233b953d0a8ce520e9cb98d1273aa88030d497..da9258798544de054aba6bdfe0b950b5be112c69 100644
--- a/mex/sources/bytecode/Evaluate.hh
+++ b/mex/sources/bytecode/Evaluate.hh
@@ -33,7 +33,21 @@ class Evaluate : public ErrorMsg
 {
 private:
   int EQN_lag1, EQN_lag2, EQN_lag3;
+  map<int, double> TEF;
+  map<pair<int, int>, double> TEFD;
+  map<tuple<int, int, int>, double> TEFDD;
+
 protected:
+  double *y, *ya;
+  int y_size;
+  double *T;
+  int nb_row_x, col_x, col_y;
+  int y_kmin, y_kmax, periods;
+  double *x, *params;
+  double *u;
+  double *steady_y, *steady_x;
+  double *g1, *r, *res;
+  vector<mxArray *> jacobian_block, jacobian_other_endo_block, jacobian_exo_block, jacobian_det_exo_block;
   mxArray *GlobalTemporaryTerms;
   it_code_type start_code, end_code;
   double pow1(double a, double b);
diff --git a/mex/sources/bytecode/Interpreter.cc b/mex/sources/bytecode/Interpreter.cc
index 42f02873efb0767e65675c40aaa992e2b375f6d1..750266637cbaa0455bb94813dc8f4ae8e7ed470b 100644
--- a/mex/sources/bytecode/Interpreter.cc
+++ b/mex/sources/bytecode/Interpreter.cc
@@ -532,7 +532,8 @@ Interpreter::print_a_block()
         }
       else
         {
-          string s = print_expression(it_code, false, size, block_num, steady_state, Per_u_, it_, it_code, false);
+          string s;
+          tie(s, it_code) = print_expression(it_code);
           if (s == "if (evaluate)" || s == "else")
             space = false;
           if (s.length() > 0)
diff --git a/mex/sources/bytecode/bytecode.cc b/mex/sources/bytecode/bytecode.cc
index 0c1ff91daa06181a09dd2e126fce1bba1c1b714c..c9789439acccf9364e321f13741f235c4f602284 100644
--- a/mex/sources/bytecode/bytecode.cc
+++ b/mex/sources/bytecode/bytecode.cc
@@ -198,7 +198,6 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
   mxArray *GlobalTemporaryTerms;
   mxArray *block_structur = nullptr;
   mxArray *pfplan_struct = nullptr;
-  ErrorMsg error_msg;
   size_t i, row_y = 0, col_y = 0, row_x = 0, col_x = 0;
   size_t steady_row_y, steady_col_y;
   int y_kmin = 0, y_kmax = 0, y_decal = 0;
@@ -339,7 +338,7 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
           double *specific_constrained_int_date_ = mxGetPr(mxGetCell(constrained_int_date_, i));
           int nb_local_periods = mxGetM(Array_constrained_paths_) * mxGetN(Array_constrained_paths_);
           int *constrained_int_date = static_cast<int *>(mxMalloc(nb_local_periods * sizeof(int)));
-          error_msg.test_mxMalloc(constrained_int_date, __LINE__, __FILE__, __func__, nb_local_periods * sizeof(int));
+          ErrorMsg::test_mxMalloc(constrained_int_date, __LINE__, __FILE__, __func__, nb_local_periods * sizeof(int));
           if (nb_periods < nb_local_periods)
             mexErrMsgTxt(("The total number of simulation periods (" + to_string(nb_periods)
                           + ") is lesser than the number of periods in the shock definitions ("
@@ -697,14 +696,14 @@ mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
 
   size_t size_of_direction = col_y*row_y*sizeof(double);
   auto *y = static_cast<double *>(mxMalloc(size_of_direction));
-  error_msg.test_mxMalloc(y, __LINE__, __FILE__, __func__, size_of_direction);
+  ErrorMsg::test_mxMalloc(y, __LINE__, __FILE__, __func__, size_of_direction);
   auto *ya = static_cast<double *>(mxMalloc(size_of_direction));
-  error_msg.test_mxMalloc(ya, __LINE__, __FILE__, __func__, size_of_direction);
+  ErrorMsg::test_mxMalloc(ya, __LINE__, __FILE__, __func__, size_of_direction);
   direction = static_cast<double *>(mxMalloc(size_of_direction));
-  error_msg.test_mxMalloc(direction, __LINE__, __FILE__, __func__, size_of_direction);
+  ErrorMsg::test_mxMalloc(direction, __LINE__, __FILE__, __func__, size_of_direction);
   memset(direction, 0, size_of_direction);
   auto *x = static_cast<double *>(mxMalloc(col_x*row_x*sizeof(double)));
-  error_msg.test_mxMalloc(x, __LINE__, __FILE__, __func__, col_x*row_x*sizeof(double));
+  ErrorMsg::test_mxMalloc(x, __LINE__, __FILE__, __func__, col_x*row_x*sizeof(double));
   for (i = 0; i < row_x*col_x; i++)
     x[i] = static_cast<double>(xd[i]);
   for (i = 0; i < row_y*col_y; i++)