diff --git a/src/CodeInterpreter.hh b/src/CodeInterpreter.hh
index cbd5fc53e4dfb31c1aaf5b5de745bfe501f805dd..e4cf5bbd2765d1554360374a4d4b621d13ecefde 100644
--- a/src/CodeInterpreter.hh
+++ b/src/CodeInterpreter.hh
@@ -1406,9 +1406,9 @@ private:
   uint8_t type;
   vector<int> variable;
   vector<int> equation;
-  vector<unsigned int> other_endogenous;
-  vector<unsigned int> exogenous;
-  vector<unsigned int> det_exogenous;
+  vector<int> other_endogenous;
+  vector<int> exogenous;
+  vector<int> det_exogenous;
   bool is_linear;
   vector<Block_contain_type> Block_Contain_;
   int endo_nbr;
@@ -1429,14 +1429,14 @@ public:
                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) :
+               vector<int> det_exogenous_arg, vector<int> exogenous_arg, vector<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},
+    other_endogenous{move(other_endogenous_arg)},
+    exogenous{move(exogenous_arg)},
+    det_exogenous{move(det_exogenous_arg)},
     is_linear{is_linear_arg},
     endo_nbr{endo_nbr_arg},
     Max_Lag{Max_Lag_arg},
@@ -1553,7 +1553,7 @@ public:
   {
     return variable;
   }
-  inline vector<unsigned int>
+  inline vector<int>
   get_exogenous()
   {
     return exogenous;
@@ -1632,19 +1632,19 @@ public:
 
     for (unsigned int i = 0; i < det_exo_size; i++)
       {
-        unsigned int tmp_i;
+        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;
+        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;
+        int tmp_i;
         memcpy(&tmp_i, code, sizeof(tmp_i)); code += sizeof(tmp_i);
         other_endogenous.push_back(tmp_i);
       }
diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index ca8988a3093620f54e8fb6572b3b04e1ac351a04..6b3a84bbb6228832391c6c60972929eb3c04a703 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -99,10 +99,14 @@ DynamicModel::DynamicModel(const DynamicModel &m) :
   nonzero_hessian_eqs{m.nonzero_hessian_eqs},
   dynJacobianColsNbr{m.dynJacobianColsNbr},
   variableMapping{m.variableMapping},
+  blocks_other_endo{m.blocks_other_endo},
+  blocks_exo{m.blocks_exo},
+  blocks_exo_det{m.blocks_exo_det},
+  blocks_jacob_cols_endo{m.blocks_jacob_cols_endo},
+  blocks_jacob_cols_other_endo{m.blocks_jacob_cols_other_endo},
+  blocks_jacob_cols_exo{m.blocks_jacob_cols_exo},
+  blocks_jacob_cols_exo_det{m.blocks_jacob_cols_exo_det},
   global_temporary_terms{m.global_temporary_terms},
-  other_endo_block{m.other_endo_block},
-  exo_block{m.exo_block},
-  exo_det_block{m.exo_det_block},
   var_expectation_functions_to_write{m.var_expectation_functions_to_write},
   pac_mce_alpha_symb_ids{m.pac_mce_alpha_symb_ids},
   pac_h0_indices{m.pac_h0_indices},
@@ -157,11 +161,15 @@ DynamicModel::operator=(const DynamicModel &m)
   blocks_derivatives_other_endo.clear();
   blocks_derivatives_exo.clear();
   blocks_derivatives_exo_det.clear();
+  blocks_other_endo = m.blocks_other_endo;
+  blocks_exo = m.blocks_exo;
+  blocks_exo_det = m.blocks_exo_det;
+  blocks_jacob_cols_endo = m.blocks_jacob_cols_endo;
+  blocks_jacob_cols_other_endo = m.blocks_jacob_cols_other_endo;
+  blocks_jacob_cols_exo = m.blocks_jacob_cols_exo;
+  blocks_jacob_cols_exo_det = m.blocks_jacob_cols_exo_det;
   global_temporary_terms = m.global_temporary_terms;
 
-  other_endo_block = m.other_endo_block;
-  exo_block = m.exo_block;
-  exo_det_block = m.exo_det_block;
   var_expectation_functions_to_write = m.var_expectation_functions_to_write;
 
   pac_mce_alpha_symb_ids = m.pac_mce_alpha_symb_ids;
@@ -348,73 +356,6 @@ DynamicModel::writeModelEquationsOrdered_M(const string &basename) const
       if (global_temporary_terms)
         local_temporary_terms = temporary_terms;
 
-      int prev_lag;
-      int prev_var, count_col, count_col_endo, count_col_exo, count_col_exo_det, count_col_other_endo;
-      map<tuple<int, int, int>, expr_t> tmp_block_endo_derivative;
-      for (const auto &[idx, d] : blocks_derivatives[block])
-        tmp_block_endo_derivative[{ get<2>(idx), get<1>(idx), get<0>(idx) }] = d;
-      prev_var = 999999999;
-      prev_lag = -9999999;
-      count_col_endo = 0;
-      for (const auto &it : tmp_block_endo_derivative)
-        {
-          auto [lag, var, ignore] = it.first;
-          if (var != prev_var || lag != prev_lag)
-            {
-              prev_var = var;
-              prev_lag = lag;
-              count_col_endo++;
-            }
-        }
-      map<tuple<int, int, int>, expr_t> tmp_block_exo_derivative;
-      for (const auto &[idx, d] : blocks_derivatives_exo[block])
-        tmp_block_exo_derivative[{ get<2>(idx), get<1>(idx), get<0>(idx) }] = d;
-      prev_var = 999999999;
-      prev_lag = -9999999;
-      count_col_exo = 0;
-      for (const auto &it : tmp_block_exo_derivative)
-        {
-          auto [lag, var, ignore] = it.first;
-          if (var != prev_var || lag != prev_lag)
-            {
-              prev_var = var;
-              prev_lag = lag;
-              count_col_exo++;
-            }
-        }
-      map<tuple<int, int, int>, expr_t> tmp_block_exo_det_derivative;
-      for (const auto &[idx, d] : blocks_derivatives_exo_det[block])
-        tmp_block_exo_det_derivative[{ get<2>(idx), get<1>(idx), get<0>(idx) }] = d;
-      prev_var = 999999999;
-      prev_lag = -9999999;
-      count_col_exo_det = 0;
-      for (const auto &it : tmp_block_exo_det_derivative)
-        {
-          auto [lag, var, ignore] = it.first;
-          if (var != prev_var || lag != prev_lag)
-            {
-              prev_var = var;
-              prev_lag = lag;
-              count_col_exo_det++;
-            }
-        }
-      map<tuple<int, int, int>, expr_t> tmp_block_other_endo_derivative;
-      for (const auto &[idx, d] : blocks_derivatives_other_endo[block])
-        tmp_block_other_endo_derivative[{ get<2>(idx), get<1>(idx), get<0>(idx) }] = d;
-      prev_var = 999999999;
-      prev_lag = -9999999;
-      count_col_other_endo = 0;
-      for (const auto &it : tmp_block_other_endo_derivative)
-        {
-          auto [lag, var, ignore] = it.first;
-          if (var != prev_var || lag != prev_lag)
-            {
-              prev_var = var;
-              prev_lag = lag;
-              count_col_other_endo++;
-            }
-        }
-
       tmp1_output.str("");
       tmp1_output << packageDir(basename + ".block") << "/dynamic_" << block+1 << ".m";
       output.open(tmp1_output.str(), ios::out | ios::binary);
@@ -449,19 +390,19 @@ DynamicModel::writeModelEquationsOrdered_M(const string &basename) const
           || simulation_type == BlockSimulationType::evaluateForward)
         {
           output << "  if(jacobian_eval)" << endl
-                 << "    g1 = spalloc(" << block_mfs  << ", " << count_col_endo << ", " << nze << ");" << endl
-                 << "    g1_x=spalloc(" << block_size << ", " << count_col_exo  << ", " << nze_exo << ");" << endl
-                 << "    g1_xd=spalloc(" << block_size << ", " << count_col_exo_det  << ", " << nze_exo_det << ");" << endl
-                 << "    g1_o=spalloc(" << block_size << ", " << count_col_other_endo << ", " << nze_other_endo << ");" << endl
+                 << "    g1 = spalloc(" << block_mfs  << ", " << blocks_jacob_cols_endo[block].size() << ", " << nze << ");" << endl
+                 << "    g1_x=spalloc(" << block_size << ", " << blocks_jacob_cols_exo[block].size() << ", " << nze_exo << ");" << endl
+                 << "    g1_xd=spalloc(" << block_size << ", " << blocks_jacob_cols_exo_det[block].size() << ", " << nze_exo_det << ");" << endl
+                 << "    g1_o=spalloc(" << block_size << ", " << blocks_jacob_cols_other_endo[block].size() << ", " << nze_other_endo << ");" << endl
                  << "  end;" << endl;
         }
       else
         {
           output << "  if(jacobian_eval)" << endl
-                 << "    g1 = spalloc(" << block_size << ", " << count_col_endo << ", " << nze << ");" << endl
-                 << "    g1_x=spalloc(" << block_size << ", " << count_col_exo  << ", " << nze_exo << ");" << endl
-                 << "    g1_xd=spalloc(" << block_size << ", " << count_col_exo_det  << ", " << nze_exo_det << ");" << endl
-                 << "    g1_o=spalloc(" << block_size << ", " << count_col_other_endo << ", " << nze_other_endo << ");" << endl
+                 << "    g1 = spalloc(" << block_size << ", " << blocks_jacob_cols_endo[block].size() << ", " << nze << ");" << endl
+                 << "    g1_x=spalloc(" << block_size << ", " << blocks_jacob_cols_exo[block].size() << ", " << nze_exo << ");" << endl
+                 << "    g1_xd=spalloc(" << block_size << ", " << blocks_jacob_cols_exo_det[block].size() << ", " << nze_exo_det << ");" << endl
+                 << "    g1_o=spalloc(" << block_size << ", " << blocks_jacob_cols_other_endo[block].size() << ", " << nze_other_endo << ");" << endl
                  << "  else" << endl;
           if (simulation_type == BlockSimulationType::solveTwoBoundariesComplete
               || simulation_type == BlockSimulationType::solveTwoBoundariesSimple)
@@ -650,93 +591,37 @@ DynamicModel::writeModelEquationsOrdered_M(const string &basename) const
           output << "  % Jacobian  " << endl << "  if jacobian_eval" << endl;
         else
           output << "    % Jacobian  " << endl << "    if jacobian_eval" << endl;
-      prev_var = 999999999;
-      prev_lag = -9999999;
-      count_col = 0;
-      for (const auto &it : tmp_block_endo_derivative)
+      for (const auto &[indices, d] : blocks_derivatives[block])
         {
-          auto [lag, var, eq] = it.first;
-          int eqr = getBlockEquationID(block, eq);
-          int varr = getBlockVariableID(block, var);
-          if (var != prev_var || lag != prev_lag)
-            {
-              prev_var = var;
-              prev_lag = lag;
-              count_col++;
-            }
-
-          expr_t id = it.second;
-
-          output << "      g1(" << eq+1 << ", " << count_col << ") = ";
-          id->writeOutput(output, local_output_type, local_temporary_terms, {});
-          output << "; % variable=" << symbol_table.getName(symbol_table.getID(SymbolType::endogenous, varr))
-                 << "(" << lag
-                 << ") " << varr+1 << ", " << var+1
-                 << ", equation=" << eqr+1 << ", " << eq+1 << endl;
+          auto [eq, var, lag] = indices;
+          int jacob_col = blocks_jacob_cols_endo[block].at({ var, lag });
+          output << "      g1(" << eq+1 << ", " << jacob_col+1 << ") = ";
+          d->writeOutput(output, local_output_type, local_temporary_terms, {});
+          output << ";" << endl;
         }
-      prev_var = 999999999;
-      prev_lag = -9999999;
-      count_col = 0;
-      for (const auto &it : tmp_block_exo_derivative)
+      for (const auto &[indices, d] : blocks_derivatives_exo[block])
         {
-          auto [lag, var, eqr] = it.first;
-          int eq = getBlockEquationID(block, eqr);
-          if (var != prev_var || lag != prev_lag)
-            {
-              prev_var = var;
-              prev_lag = lag;
-              count_col++;
-            }
-          expr_t id = it.second;
-          output << "      g1_x(" << eqr+1 << ", " << count_col << ") = ";
-          id->writeOutput(output, local_output_type, local_temporary_terms, {});
-          output << "; % variable=" << symbol_table.getName(symbol_table.getID(SymbolType::exogenous, var))
-                 << "(" << lag
-                 << ") " << var+1
-                 << ", equation=" << eq+1 << endl;
+          auto [eq, var, lag] = indices;
+          int jacob_col = blocks_jacob_cols_exo[block].at({ var, lag });
+          output << "      g1_x(" << eq+1 << ", " << jacob_col+1 << ") = ";
+          d->writeOutput(output, local_output_type, local_temporary_terms, {});
+          output << ";" << endl;
         }
-      prev_var = 999999999;
-      prev_lag = -9999999;
-      count_col = 0;
-      for (const auto &it : tmp_block_exo_det_derivative)
+      for (const auto &[indices, d] : blocks_derivatives_exo_det[block])
         {
-          auto [lag, var, eqr] = it.first;
-          int eq = getBlockEquationID(block, eqr);
-          if (var != prev_var || lag != prev_lag)
-            {
-              prev_var = var;
-              prev_lag = lag;
-              count_col++;
-            }
-          expr_t id = it.second;
-          output << "      g1_xd(" << eqr+1 << ", " << count_col << ") = ";
-          id->writeOutput(output, local_output_type, local_temporary_terms, {});
-          output << "; % variable=" << symbol_table.getName(symbol_table.getID(SymbolType::exogenous, var))
-                 << "(" << lag
-                 << ") " << var+1
-                 << ", equation=" << eq+1 << endl;
+          auto [eq, var, lag] = indices;
+          int jacob_col = blocks_jacob_cols_exo_det[block].at({ var, lag });
+          output << "      g1_xd(" << eq+1 << ", " << jacob_col+1 << ") = ";
+          d->writeOutput(output, local_output_type, local_temporary_terms, {});
+          output << ";" << endl;
         }
-      prev_var = 999999999;
-      prev_lag = -9999999;
-      count_col = 0;
-      for (const auto &it : tmp_block_other_endo_derivative)
+      for (const auto &[indices, d] : blocks_derivatives_other_endo[block])
         {
-          auto [lag, var, eqr] = it.first;
-          int eq = getBlockEquationID(block, eqr);
-          if (var != prev_var || lag != prev_lag)
-            {
-              prev_var = var;
-              prev_lag = lag;
-              count_col++;
-            }
-          expr_t id = it.second;
-
-          output << "      g1_o(" << eqr+1 << ", " << /*var+1+(lag+block_max_lag)*block_size*/ count_col << ") = ";
-          id->writeOutput(output, local_output_type, local_temporary_terms, {});
-          output << "; % variable=" << symbol_table.getName(symbol_table.getID(SymbolType::endogenous, var))
-                 << "(" << lag
-                 << ") " << var+1
-                 << ", equation=" << eq+1 << endl;
+          auto [eq, var, lag] = indices;
+          int jacob_col = blocks_jacob_cols_other_endo[block].at({ var, lag });
+          output << "      g1_o(" << eq+1 << ", " << jacob_col+1 << ") = ";
+          d->writeOutput(output, local_output_type, local_temporary_terms, {});
+          output << ";" << endl;
         }
       output << "      varargout{1}=g1_x;" << endl
              << "      varargout{2}=g1_xd;" << endl
@@ -899,7 +784,7 @@ DynamicModel::writeModelEquationsCode(const string &basename, const map_idx_t &m
   FDIMT_ fdimt(temporary_terms.size());
   fdimt.write(code_file, instruction_number);
 
-  vector<unsigned int> exo, exo_det, other_endo;
+  vector<int> exo, exo_det, other_endo;
 
   for (int i = 0; i < symbol_table.exo_det_nbr(); i++)
     exo_det.push_back(i);
@@ -977,8 +862,7 @@ DynamicModel::writeModelEquationsCode(const string &basename, const map_idx_t &m
                            0,
                            exo_det,
                            exo,
-                           other_endo
-                           );
+                           other_endo);
   fbeginblock.write(code_file, instruction_number);
 
   compileTemporaryTerms(code_file, instruction_number, temporary_terms, map_idx, true, false);
@@ -1178,61 +1062,6 @@ DynamicModel::writeModelEquationsCode_Block(const string &basename, const map_id
                                       simulation_type == BlockSimulationType::solveTwoBoundariesComplete || simulation_type == BlockSimulationType::solveTwoBoundariesSimple, linear_decomposition);
           file_open = true;
         }
-      map<tuple<int, int, int>, expr_t> tmp_block_endo_derivative;
-      for (const auto &[idx, d] : blocks_derivatives[block])
-        tmp_block_endo_derivative[{ get<2>(idx), get<1>(idx), get<0>(idx) }] = d;
-      map<tuple<int, int, int>, expr_t> tmp_exo_derivative;
-      for (const auto &[idx, d] : blocks_derivatives_exo[block])
-        tmp_exo_derivative[{ get<2>(idx), get<1>(idx), get<0>(idx) }] = d;
-      map<tuple<int, int, int>, expr_t> tmp_exo_det_derivative;
-      for (const auto &[idx, d] : blocks_derivatives_exo_det[block])
-        tmp_exo_det_derivative[{ get<2>(idx), get<1>(idx), get<0>(idx) }] = d;
-      map<tuple<int, int, int>, expr_t> tmp_other_endo_derivative;
-      for (const auto &[idx, d] : blocks_derivatives_other_endo[block])
-        tmp_other_endo_derivative[{ get<2>(idx), get<1>(idx), get<0>(idx) }] = d;
-      int prev_var = -1;
-      int prev_lag = -999999999;
-      int count_col_endo = 0;
-      for (const auto &it : tmp_block_endo_derivative)
-        {
-          int lag, var;
-          tie(lag, var, ignore) = it.first;
-          if (prev_var != var || prev_lag != lag)
-            {
-              prev_var = var;
-              prev_lag = lag;
-              count_col_endo++;
-            }
-        }
-      int count_col_det_exo = 0;
-      vector<unsigned int> exo_det;
-      for (const auto &it : exo_det_block[block])
-        for (const auto &it1 : it.second)
-          {
-            count_col_det_exo++;
-            if (find(exo_det.begin(), exo_det.end(), it1) == exo_det.end())
-              exo_det.push_back(it1);
-          }
-
-      int count_col_exo = 0;
-      vector<unsigned int> exo;
-      for (const auto &it : exo_block[block])
-        for (const auto &it1 : it.second)
-          {
-            count_col_exo++;
-            if (find(exo.begin(), exo.end(), it1) == exo.end())
-              exo.push_back(it1);
-          }
-
-      vector<unsigned int> other_endo;
-      int count_col_other_endo = 0;
-      for (const auto &it : other_endo_block[block])
-        for (const auto &it1 : it.second)
-          {
-            count_col_other_endo++;
-            if (find(other_endo.begin(), other_endo.end(), it1) == other_endo.end())
-              other_endo.push_back(it1);
-          }
 
       FBEGINBLOCK_ fbeginblock(block_mfs,
                                simulation_type,
@@ -1245,17 +1074,16 @@ DynamicModel::writeModelEquationsCode_Block(const string &basename, const map_id
                                block_max_lag,
                                block_max_lead,
                                u_count_int,
-                               count_col_endo,
-                               exo_det.size(),
-                               count_col_det_exo,
-                               exo.size(),
-                               count_col_exo,
-                               other_endo.size(),
-                               count_col_other_endo,
-                               exo_det,
-                               exo,
-                               other_endo
-                               );
+                               blocks_jacob_cols_endo[block].size(),
+                               blocks_exo_det[block].size(),
+                               blocks_jacob_cols_exo_det[block].size(),
+                               blocks_exo[block].size(),
+                               blocks_jacob_cols_exo[block].size(),
+                               blocks_other_endo[block].size(),
+                               blocks_jacob_cols_other_endo[block].size(),
+                               vector<int>(blocks_exo_det[block].begin(), blocks_exo_det[block].end()),
+                               vector<int>(blocks_exo[block].begin(), blocks_exo[block].end()),
+                               vector<int>(blocks_other_endo[block].begin(), blocks_other_endo[block].end()));
       fbeginblock.write(code_file, instruction_number);
 
       if (linear_decomposition)
@@ -1476,90 +1304,48 @@ DynamicModel::writeModelEquationsCode_Block(const string &basename, const map_id
       prev_instruction_number = instruction_number;
       // The Jacobian if we have to solve the block determinsitic block
 
-      prev_var = -1;
-      prev_lag = -999999999;
-      count_col_endo = 0;
-      for (const auto &it : tmp_block_endo_derivative)
+      for (const auto &[indices, d] : blocks_derivatives[block])
         {
-          auto [lag, var, eq] = it.first;
+          auto [eq, var, lag] = indices;
           int eqr = getBlockEquationID(block, eq);
           int varr = getBlockVariableID(block, var);
-          if (prev_var != var || prev_lag != lag)
-            {
-              prev_var = var;
-              prev_lag = lag;
-              count_col_endo++;
-            }
           FNUMEXPR_ fnumexpr(FirstEndoDerivative, eqr, varr, lag);
           fnumexpr.write(code_file, instruction_number);
           compileDerivative(code_file, instruction_number, eqr, varr, lag, map_idx);
-          FSTPG3_ fstpg3(eq, var, lag, count_col_endo-1);
+          FSTPG3_ fstpg3(eq, var, lag, blocks_jacob_cols_endo[block].at({ var, lag }));
           fstpg3.write(code_file, instruction_number);
         }
-      prev_var = -1;
-      prev_lag = -999999999;
-      count_col_exo = 0;
-      for (const auto &it : tmp_exo_derivative)
+      for (const auto &[indices, d] : blocks_derivatives_exo[block])
         {
-          auto [lag, var, eqr] = it.first;
+          auto [eqr, var, lag] = indices;
           int eq = getBlockEquationID(block, eqr);
           int varr = 0; // Dummy value, actually unused by the bytecode MEX
-          if (prev_var != var || prev_lag != lag)
-            {
-              prev_var = var;
-              prev_lag = lag;
-              count_col_exo++;
-            }
-          expr_t id = it.second;
-
           FNUMEXPR_ fnumexpr(FirstExoDerivative, eqr, varr, lag);
           fnumexpr.write(code_file, instruction_number);
-          id->compile(code_file, instruction_number, false, temporary_terms, map_idx, true, false);
-          FSTPG3_ fstpg3(eq, var, lag, count_col_exo-1);
+          d->compile(code_file, instruction_number, false, temporary_terms, map_idx, true, false);
+          FSTPG3_ fstpg3(eq, var, lag, blocks_jacob_cols_exo[block].at({ var, lag }));
           fstpg3.write(code_file, instruction_number);
         }
-      prev_var = -1;
-      prev_lag = -999999999;
-      int count_col_exo_det = 0;
-      for (const auto &it : tmp_exo_det_derivative)
+      for (const auto &[indices, d] : blocks_derivatives_exo_det[block])
         {
-          auto [lag, var, eqr] = it.first;
+          auto [eqr, var, lag] = indices;
           int eq = getBlockEquationID(block, eqr);
           int varr = 0; // Dummy value, actually unused by the bytecode MEX
-          if (prev_var != var || prev_lag != lag)
-            {
-              prev_var = var;
-              prev_lag = lag;
-              count_col_exo_det++;
-            }
-          expr_t id = it.second;
-
           FNUMEXPR_ fnumexpr(FirstExodetDerivative, eqr, varr, lag);
           fnumexpr.write(code_file, instruction_number);
-          id->compile(code_file, instruction_number, false, temporary_terms, map_idx, true, false);
-          FSTPG3_ fstpg3(eq, var, lag, count_col_exo_det-1);
+          d->compile(code_file, instruction_number, false, temporary_terms, map_idx, true, false);
+          FSTPG3_ fstpg3(eq, var, lag, blocks_jacob_cols_exo_det[block].at({ var, lag }));
           fstpg3.write(code_file, instruction_number);
         }
-      prev_var = -1;
-      prev_lag = -999999999;
-      count_col_other_endo = 0;
-      for (const auto &it : tmp_other_endo_derivative)
+      for (const auto &[indices, d] : blocks_derivatives_other_endo[block])
         {
-          auto [lag, var, eqr] = it.first;
+          auto [eqr, var, lag] = indices;
           int eq = getBlockEquationID(block, eqr);
           int varr = 0; // Dummy value, actually unused by the bytecode MEX
-          if (prev_var != var || prev_lag != lag)
-            {
-              prev_var = var;
-              prev_lag = lag;
-              count_col_other_endo++;
-            }
-          expr_t id = it.second;
-
           FNUMEXPR_ fnumexpr(FirstOtherEndoDerivative, eqr, varr, lag);
           fnumexpr.write(code_file, instruction_number);
-          id->compile(code_file, instruction_number, false, temporary_terms, map_idx, true, false);
-          FSTPG3_ fstpg3(eq, var, lag, count_col_other_endo-1);
+          d->compile(code_file, instruction_number, false, temporary_terms, map_idx, true, false);
+          FSTPG3_ fstpg3(eq, var, lag, blocks_jacob_cols_other_endo[block].at({ var, lag }));
           fstpg3.write(code_file, instruction_number);
         }
 
@@ -3149,18 +2935,6 @@ DynamicModel::writeOutput(ostream &output, const string &basename, bool block_de
               tmp_s << " " << getBlockVariableID(block, i)+1;
               tmp_s_eq << " " << getBlockEquationID(block, i)+1;
             }
-          set<int> exogenous;
-          for (const auto &it : exo_block[block])
-            for (int it1 : it.second)
-              exogenous.insert(it1);
-          set<int> exogenous_det;
-          for (const auto &it : exo_det_block[block])
-            for (int it1 : it.second)
-              exogenous_det.insert(it1);
-          set<int> other_endogenous;
-          for (const auto &it : other_endo_block[block])
-            for (int it1 : it.second)
-              other_endogenous.insert(it1);
           output << "block_structure.block(" << block+1 << ").Simulation_Type = " << static_cast<int>(simulation_type) << ";" << endl
                  << "block_structure.block(" << block+1 << ").maximum_lag = " << max_lag << ";" << endl
                  << "block_structure.block(" << block+1 << ").maximum_lead = " << max_lead << ";" << endl
@@ -3175,58 +2949,37 @@ DynamicModel::writeOutput(ostream &output, const string &basename, bool block_de
                  << "block_structure.block(" << block+1 << ").equation = [" << tmp_s_eq.str() << "];" << endl
                  << "block_structure.block(" << block+1 << ").variable = [" << tmp_s.str() << "];" << endl
                  << "block_structure.block(" << block+1 << ").exogenous = [";
-          int i = 0;
-          for (int exo : exogenous)
-            if (exo >= 0)
-              {
-                output << " " << exo+1;
-                i++;
-              }
+          for (int exo : blocks_exo[block])
+            output << " " << exo+1;
           output << "];" << endl
-                 << "block_structure.block(" << block+1 << ").exo_nbr = " << i << ";" << endl
+                 << "block_structure.block(" << block+1 << ").exo_nbr = " << blocks_exo[block].size() << ";" << endl
 
                  << "block_structure.block(" << block+1 << ").exogenous_det = [";
-          i = 0;
-          for (int exo_det : exogenous_det)
-            if (exo_det >= 0)
-              {
-                output << " " << exo_det+1;
-                i++;
-              }
+          for (int exo_det : blocks_exo_det[block])
+            output << " " << exo_det+1;
           output << "];" << endl
-                 << "block_structure.block(" << block+1 << ").exo_det_nbr = " << i << ";" << endl
+                 << "block_structure.block(" << block+1 << ").exo_det_nbr = " << blocks_exo_det[block].size() << ";" << endl
                  << "block_structure.block(" << block+1 << ").other_endogenous = [";
-          i = 0;
-          for (int other_endo : other_endogenous)
-            if (other_endo >= 0)
-              {
-                output << " " << other_endo+1;
-                i++;
-              }
+          for (int other_endo : blocks_other_endo[block])
+            output << " " << other_endo+1;
           output << "];" << endl
                  << "block_structure.block(" << block+1 << ").other_endogenous_block = [";
-          i = 0;
-          for (int other_endo : other_endogenous)
-            if (other_endo >= 0)
-              {
-                output << " " << endo2block[other_endo]+1;
-                i++;
-              }
+          for (int other_endo : blocks_other_endo[block])
+            output << " " << endo2block[other_endo]+1;
           output << "];" << endl;
 
-          output << "block_structure.block(" << block+1 << ").tm1 = zeros(" << i << ", " << state_var.size() << ");" << endl;
-          int count_other_endogenous = 1;
-          for (int other_endo : other_endogenous)
+          output << "block_structure.block(" << block+1 << ").tm1 = zeros(" << blocks_other_endo[block].size() << ", " << state_var.size() << ");" << endl;
+          int line = 1;
+          for (auto other_endo : blocks_other_endo[block])
             {
               for (auto it = state_var.begin(); it != state_var.end(); ++it)
                 if (*it == other_endo + 1)
                   output << "block_structure.block(" << block+1 << ").tm1("
-                         << count_other_endogenous << ", "
+                         << line << ", "
                          << it - state_var.begin()+1 << ") = 1;" << endl;
-              count_other_endogenous++;
+              line++;
             }
-
-          output << "block_structure.block(" << block+1 << ").other_endo_nbr = " << i << ";" << endl;
+          output << "block_structure.block(" << block+1 << ").other_endo_nbr = " << blocks_other_endo[block].size() << ";" << endl;
 
           tmp_s.str("");
           count_lead_lag_incidence = 0;
@@ -3273,7 +3026,7 @@ DynamicModel::writeOutput(ostream &output, const string &basename, bool block_de
           for (int lag = -1; lag <= 1; lag++)
             {
               tmp_s.str("");
-              for (int other_endo : other_endogenous)
+              for (int other_endo : blocks_other_endo[block])
                 {
                   bool done = false;
                   for (int eq = 0; eq < block_size; eq++)
@@ -4770,7 +4523,7 @@ DynamicModel::computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsO
 
       determineLinearBlocks();
 
-      collect_block_first_order_derivatives();
+      computeBlockDynJacobianCols();
 
       global_temporary_terms = true;
       if (!no_tmp_terms)
@@ -4800,7 +4553,7 @@ DynamicModel::computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsO
 
       determineLinearBlocks();
 
-      collect_block_first_order_derivatives();
+      computeBlockDynJacobianCols();
 
       global_temporary_terms = true;
       if (!no_tmp_terms)
@@ -4999,18 +4752,19 @@ DynamicModel::computeChainRuleJacobian()
 }
 
 void
-DynamicModel::collect_block_first_order_derivatives()
+DynamicModel::computeBlockDynJacobianCols()
 {
   int nb_blocks = blocks.size();
-  other_endo_block = vector<lag_var_t>(nb_blocks);
-  exo_block = vector<lag_var_t>(nb_blocks);
-  exo_det_block = vector<lag_var_t>(nb_blocks);
-  blocks_derivatives_other_endo.clear();
   blocks_derivatives_other_endo.resize(nb_blocks);
-  blocks_derivatives_exo.clear();
   blocks_derivatives_exo.resize(nb_blocks);
-  blocks_derivatives_exo_det.clear();
   blocks_derivatives_exo_det.resize(nb_blocks);
+  blocks_other_endo.resize(nb_blocks);
+  blocks_exo.resize(nb_blocks);
+  blocks_exo_det.resize(nb_blocks);
+  // Structures used for lexicographic ordering over (lag, var ID)
+  vector<set<pair<int, int>>> dynamic_endo(nb_blocks), dynamic_other_endo(nb_blocks),
+    dynamic_exo(nb_blocks), dynamic_exo_det(nb_blocks);
+
   for (auto & [indices, d1] : derivatives[1])
     {
       int eq_orig = indices[0];
@@ -5021,42 +4775,56 @@ DynamicModel::collect_block_first_order_derivatives()
       switch (getTypeByDerivID(indices[1]))
         {
         case SymbolType::endogenous:
-          if (block_eq != endo2block[var])
+          if (block_eq == endo2block[var])
+            {
+              int var_in_block = getBlockInitialVariableID(block_eq, var);
+              dynamic_endo[block_eq].emplace(lag, var_in_block);
+            }
+          else
             {
               blocks_derivatives_other_endo[block_eq][{ eq, var, lag }] = derivatives[1][{ eq_orig, getDerivID(symbol_table.getID(SymbolType::endogenous, var), lag) }];
-
-              {
-                auto &lag_var = other_endo_block[block_eq];
-                if (lag_var.find(lag) == lag_var.end())
-                  lag_var[lag].clear();
-                lag_var[lag].insert(var);
-              }
+              blocks_other_endo[block_eq].insert(var);
+              dynamic_other_endo[block_eq].emplace(lag, var);
             }
           break;
         case SymbolType::exogenous:
           blocks_derivatives_exo[block_eq][{ eq, var, lag }] = derivatives[1][{ eq_orig, getDerivID(symbol_table.getID(SymbolType::exogenous, var), lag) }];
-
-          {
-            auto &lag_var = exo_block[block_eq];
-            if (lag_var.find(lag) == lag_var.end())
-              lag_var[lag].clear();
-            lag_var[lag].insert(var);
-          }
+          blocks_exo[block_eq].insert(var);
+          dynamic_exo[block_eq].emplace(lag, var);
           break;
         case SymbolType::exogenousDet:
           blocks_derivatives_exo_det[block_eq][{ eq, var, lag }] = derivatives[1][{ eq_orig, getDerivID(symbol_table.getID(SymbolType::exogenous, var), lag) }];
-
-          {
-            auto &lag_var = exo_det_block[block_eq];
-            if (lag_var.find(lag) == lag_var.end())
-              lag_var[lag].clear();
-            lag_var[lag].insert(var);
-          }
+          blocks_exo_det[block_eq].insert(var);
+          dynamic_exo_det[block_eq].emplace(lag, var);
           break;
         default:
           break;
         }
     }
+
+  // Compute Jacobian column indices
+  blocks_jacob_cols_endo.resize(nb_blocks);
+  blocks_jacob_cols_other_endo.resize(nb_blocks);
+  blocks_jacob_cols_exo.resize(nb_blocks);
+  blocks_jacob_cols_exo_det.resize(nb_blocks);
+  for (int blk = 0; blk < nb_blocks; blk++)
+    {
+      int index = 0;
+      for (auto [lag, var] : dynamic_endo[blk])
+        blocks_jacob_cols_endo[blk][{ var, lag }] = index++;
+
+      index = 0;
+      for (auto [lag, var] : dynamic_other_endo[blk])
+        blocks_jacob_cols_other_endo[blk][{ var, lag }] = index++;
+
+      index = 0;
+      for (auto [lag, var] : dynamic_exo[blk])
+        blocks_jacob_cols_exo[blk][{ var, lag }] = index++;
+
+      index = 0;
+      for (auto [lag, var] : dynamic_exo_det[blk])
+        blocks_jacob_cols_exo_det[blk][{ var, lag }] = index++;
+    }
 }
 
 void
diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh
index 861f6ad8ffc2d628c44d777fcc8fce9cf9f06c81..c61c2e9e21389b6ca9706a2e04e4359f55d77dc8 100644
--- a/src/DynamicModel.hh
+++ b/src/DynamicModel.hh
@@ -110,6 +110,15 @@ private:
   vector<map<tuple<int, int, int>, expr_t>> blocks_derivatives_other_endo,
     blocks_derivatives_exo, blocks_derivatives_exo_det;
 
+  // For each block, gives type-specific other endos / exo / exo det that appear in it
+  vector<set<int>> blocks_other_endo, blocks_exo, blocks_exo_det;
+
+  /* For each block, and for each variable type, maps (variable ID, lag) to
+     Jacobian column.
+     For the “endo” version, the variable ID is the index within the block. For
+     the three others, it’s the type-specific ID */
+  vector<map<pair<int, int>, int>> blocks_jacob_cols_endo, blocks_jacob_cols_other_endo, blocks_jacob_cols_exo, blocks_jacob_cols_exo_det;
+
   //! Writes dynamic model file (Matlab version)
   void writeDynamicMFile(const string &basename) const;
   //! Writes dynamic model file (Julia version)
@@ -177,8 +186,11 @@ private:
   /*! Also computes max_{endo,exo}_{lead_lag}, and initializes dynJacobianColsNbr to the number of dynamic endos */
   void computeDerivIDs();
 
-  //! Collecte the derivatives w.r. to endogenous of the block, to endogenous of previouys blocks and to exogenous
-  void collect_block_first_order_derivatives();
+  /* Compute the Jacobian column indices in the block decomposition case
+     (stored in blocks_jacob_cols_*).
+     Also fills auxiliary structures related to “other” endogenous and
+     exogenous: blocks{,_derivatives}_{other_endo,exo_exo_det} */
+  void computeBlockDynJacobianCols();
 
   //! Factorized code for substitutions of leads/lags
   /*! \param[in] type determines which type of variables is concerned
@@ -190,11 +202,6 @@ private:
   //! Indicate if the temporary terms are computed for the overall model (true) or not (false). Default value true
   bool global_temporary_terms{true};
 
-  //!List for each block and for each lag-lead all the other endogenous variables and exogenous variables
-  using var_t = set<int>;
-  using lag_var_t = map<int, var_t>;
-  vector<lag_var_t> other_endo_block, exo_block, exo_det_block;
-
   //! Help computeXrefs to compute the reverse references (i.e. param->eqs, endo->eqs, etc)
   void computeRevXref(map<pair<int, int>, set<int>> &xrefset, const set<pair<int, int>> &eiref, int eqn);