diff --git a/matlab/dynare_config.m b/matlab/dynare_config.m
index 97b18745dab06319675787eac815ac16da73ccbf..f097e4754bd43b88c28e7356e3c69209277db060 100644
--- a/matlab/dynare_config.m
+++ b/matlab/dynare_config.m
@@ -193,6 +193,9 @@ mex_status(3,3) = {'Kronecker products'};
 mex_status(4,1) = {'sparse_hessian_times_B_kronecker_C'};
 mex_status(4,2) = {'kronecker'};
 mex_status(4,3) = {'Sparse kronecker products'};
+mex_status(5,1) = {'local_state_space_iteration_2'};
+mex_status(5,2) = {'particle/local_state_space_iteration'};
+mex_status(5,3) = {'Local state space iteraton (second order)'};
 number_of_mex_files = size(mex_status,1);
 %% Remove some directories from matlab's path. This is necessary if the user has
 %% added dynare_v4/matlab with the subfolders. Matlab has to ignore these
diff --git a/matlab/particle/local_state_equation_2.m b/matlab/particle/local_state_space_iteration/local_state_space_iteration_2.m
similarity index 91%
rename from matlab/particle/local_state_equation_2.m
rename to matlab/particle/local_state_space_iteration/local_state_space_iteration_2.m
index 97b538765ffb40be1b623e6f2d97271b349804d7..b257c07be9029db8dbc4b59660eef89dd6010df4 100644
--- a/matlab/particle/local_state_equation_2.m
+++ b/matlab/particle/local_state_space_iteration/local_state_space_iteration_2.m
@@ -1,8 +1,8 @@
-function [y,y_] = local_state_equation_2(yhat,epsilon,ghx,ghu,constant,ghxx,ghuu,ghxu,yhat_,ss)
+function [y,y_] = local_state_space_iteration_2(yhat,epsilon,ghx,ghu,constant,ghxx,ghuu,ghxu,yhat_,ss)
 
 %@info:
 %! @deftypefn {Function File} {@var{y}, @var{y_} =} local_state_equation_2 (@var{yhat},@var{epsilon}, @var{ghx}, @var{ghu}, @var{constant}, @var{ghxx}, @var{ghuu}, @var{ghxu}, @var{yhat_}, @var{ss})
-%! @anchor{particle/local_state_equation_2}
+%! @anchor{particle/local_state_space_iteration_2}
 %! @sp 1
 %! Given the states (y) and structural innovations (epsilon), this routine computes the level of selected endogenous variables when the
 %! model is approximated by an order two taylor expansion around the deterministic steady state. Depending on the number of input/output
@@ -76,22 +76,22 @@ function [y,y_] = local_state_equation_2(yhat,epsilon,ghx,ghu,constant,ghxx,ghuu
 % along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 
 % AUTHOR(S) stephane DOT adjemian AT univ DASH lemans DOT fr
-%           frederic DOT karame AT univ DASH evry DOT fr    
+%           frederic DOT karame AT univ DASH evry DOT fr
 
 number_of_threads = 1;
 
 if nargin==8
     pruning = 0;
     if nargout>1
-        error('local_state_equation_2:: Numbers of input and output argument are inconsistent!')
+        error('local_state_space_iteration_2:: Numbers of input and output argument are inconsistent!')
     end
 elseif nargin==10
     pruning = 1;
     if nargout~=2
-        error('local_state_equation_2:: Numbers of input and output argument are inconsistent!')
+        error('local_state_space_iteration_2:: Numbers of input and output argument are inconsistent!')
     end
 else
-    error('local_state_equation_2:: Wrong number of input arguments!')
+    error('local_state_space_iteration_2:: Wrong number of input arguments!')
 end
 
 switch pruning
@@ -152,7 +152,7 @@ end
 %$ n = dr.npred;
 %$ q = size(dr.ghu,2);
 %$ yhat = zeros(n,1);
-%$ epsilon = zeros(q,1); 
+%$ epsilon = zeros(q,1);
 %$ ghx = dr.ghx(istates,:);
 %$ ghu = dr.ghu(istates,:);
 %$ constant = dr.ys(istates,:)+dr.ghs2(istates,:);
diff --git a/mex/build/local_state_space_iterations.am b/mex/build/local_state_space_iterations.am
new file mode 100644
index 0000000000000000000000000000000000000000..7b70d91920ea8427d0ebba41b93fffc42d9dd918
--- /dev/null
+++ b/mex/build/local_state_space_iterations.am
@@ -0,0 +1,5 @@
+vpath %.cc $(top_srcdir)/../../sources/local_state_space_iterations
+
+noinst_PROGRAMS = local_state_space_iteration_2
+
+nodist_local_state_space_iteration_2_SOURCES = local_state_space_iteration_2.cc
\ No newline at end of file
diff --git a/mex/build/matlab/Makefile.am b/mex/build/matlab/Makefile.am
index 58dbd369f8eb5883fb3448f9a8ccfa051dc86165..82904454fa45a094238b50ae3ace743a87563705 100644
--- a/mex/build/matlab/Makefile.am
+++ b/mex/build/matlab/Makefile.am
@@ -2,7 +2,7 @@ ACLOCAL_AMFLAGS = -I ../../../m4
 
 # libdynare++ must come before gensylv, k_order_perturbation, dynare_simul_
 if DO_SOMETHING
-SUBDIRS = mjdgges kronecker bytecode libdynare++ gensylv k_order_perturbation dynare_simul_ estimation block_kalman_filter sobol
+SUBDIRS = mjdgges kronecker bytecode libdynare++ gensylv k_order_perturbation dynare_simul_ estimation block_kalman_filter sobol local_state_space_iterations
 
 if HAVE_GSL
 SUBDIRS += ms_sbvar
diff --git a/mex/build/matlab/configure.ac b/mex/build/matlab/configure.ac
index 4267a3158cbdecac349b0a29a3a22d07131aa46c..337d39ac0bbe011c6faf28cfe766152d4762e562 100644
--- a/mex/build/matlab/configure.ac
+++ b/mex/build/matlab/configure.ac
@@ -144,6 +144,7 @@ AC_CONFIG_FILES([Makefile
                  kalman_steady_state/Makefile
                  ms_sbvar/Makefile
                  block_kalman_filter/Makefile
-	         sobol/Makefile])
+	         sobol/Makefile
+		 local_state_space_iterations/Makefile])
 
 AC_OUTPUT
diff --git a/mex/build/matlab/local_state_space_iterations/Makefile.am b/mex/build/matlab/local_state_space_iterations/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..4b8b7c077e5c5923610ef4edcd0a51a33db3542f
--- /dev/null
+++ b/mex/build/matlab/local_state_space_iterations/Makefile.am
@@ -0,0 +1,2 @@
+include ../mex.am
+include ../../local_state_space_iterations.am
\ No newline at end of file
diff --git a/mex/build/octave/Makefile.am b/mex/build/octave/Makefile.am
index a6d164c9012eaf9d2ac26e2343e5a56eb5bdfb00..2c4a8b7ba3dfd42eeda1dc57bfdbca29ca672ea4 100644
--- a/mex/build/octave/Makefile.am
+++ b/mex/build/octave/Makefile.am
@@ -2,7 +2,7 @@ ACLOCAL_AMFLAGS = -I ../../../m4
 
 # libdynare++ must come before gensylv, k_order_perturbation, dynare_simul_
 if DO_SOMETHING
-SUBDIRS = mjdgges kronecker bytecode libdynare++ gensylv k_order_perturbation dynare_simul_ qzcomplex ordschur block_kalman_filter sobol
+SUBDIRS = mjdgges kronecker bytecode libdynare++ gensylv k_order_perturbation dynare_simul_ qzcomplex ordschur block_kalman_filter sobol local_state_space_iterations
 
 if HAVE_GSL
 SUBDIRS += ms_sbvar
diff --git a/mex/build/octave/configure.ac b/mex/build/octave/configure.ac
index daa13a6af00bdb92dbe6bbe4674bec58b9a12f3d..6762daefbe9d760a95c15485d71c009885f13356 100644
--- a/mex/build/octave/configure.ac
+++ b/mex/build/octave/configure.ac
@@ -131,6 +131,7 @@ AC_CONFIG_FILES([Makefile
                  kalman_steady_state/Makefile
                  ms_sbvar/Makefile
                  block_kalman_filter/Makefile
-		 sobol/Makefile])
+		 sobol/Makefile
+		 local_state_space_iterations/Makefile])
 
 AC_OUTPUT
diff --git a/mex/build/octave/local_state_space_iterations/Makefile.am b/mex/build/octave/local_state_space_iterations/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..d70f78c4f6289887c231885127f27136bcc0ba09
--- /dev/null
+++ b/mex/build/octave/local_state_space_iterations/Makefile.am
@@ -0,0 +1,3 @@
+EXEEXT = .mex
+include ../mex.am
+include ../../local_state_space_iterations.am
diff --git a/mex/sources/local_state_space_iterations/local_state_space_iteration_2.cc b/mex/sources/local_state_space_iterations/local_state_space_iteration_2.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ae1667b43669cb97e447ca6a5ca38b99a944ac3d
--- /dev/null
+++ b/mex/sources/local_state_space_iterations/local_state_space_iteration_2.cc
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2010 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/>.
+ */
+
+/*
+ * This mex file computes particles at time t+1 given particles and innovations at time t, 
+ * using a second order approximation of the nonlinear state space model.
+ */
+
+#include <iostream>
+#include <cstring>
+#include <vector>
+#include <dynmex.h>
+#include <dynblas.h>
+
+#ifdef USE_OMP
+#include <omp.h>
+#endif
+
+using namespace std;
+
+//#define FIRST_ORDER_LOOP 1// Comment out this line to use mkl-blas instead of loops when computing ghx*yhat and ghu*epsilon
+
+void set_vector_of_indices(const int n, const int r, vector<int> &v1, vector<int> &v2, vector<int> &v3)
+{
+  const int m = n*(n+1)/2;
+  v1.resize(m,0);
+  v2.resize(m,0);
+  v3.resize(m,0);
+  for(int i=0, index=0, jndex=0;i<n; i++)
+    {
+      jndex+=i;
+      for(int j=i; j<n; j++, index++, jndex++)
+        {
+          v1[index] = i;
+          v2[index] = j;
+          v3[index] = jndex*r;
+        }
+    }
+}
+
+void ss2Iteration_pruning(double* y2, double* y1, const double* yhat2, const double* yhat1, const double *epsilon, 
+                  double* ghx, double* ghu, 
+                  const double* constant, const double* ghxx, const double* ghuu, const double* ghxu, const double* ss, 
+                  const blas_int m, const blas_int n, const blas_int q, const blas_int s)
+{
+  const char transpose[2] = "N";
+  const double one = 1.0;
+  const blas_int ONE = 1;
+  
+  vector<int> ii1, ii2, ii3;// vector indices for ghxx
+  vector<int> jj1, jj2, jj3;// vector indices for ghuu
+  set_vector_of_indices(n, m, ii1, ii2, ii3);
+  set_vector_of_indices(q, m, jj1, jj2, jj3);
+  
+  for (int particle = 0; particle<s; particle++)
+  {
+    int particle_ = particle*m;
+    int particle__ = particle*n;
+    int particle___ = particle*q;
+    memcpy(&y2[particle_],&constant[0],m*sizeof(double));
+    memcpy(&y1[particle_],&ss[0],m*sizeof(double));
+#ifndef FIRST_ORDER_LOOP
+    dgemv(transpose,&m,&n,&one,&ghx[0],&m,&yhat2[particle__],&ONE,&one,&y2[particle_],&ONE);
+    dgemv(transpose,&m,&q,&one,&ghu[0],&m,&epsilon[particle___],&ONE,&one,&y2[particle_],&ONE);
+#endif
+    for (int variable = 0; variable<m; variable++)
+      {
+        int variable_ = variable + particle_;
+        // +ghx*yhat2+ghu*u
+#ifdef FIRST_ORDER_LOOP
+        for (int column = 0, column_=0; column<q; column++, column_ += m)
+          {
+            int i1 = variable+column_;
+            int i2 = column+particle__;
+            int i3 = column+particle___;
+            y2[variable_] += ghx[i1]*yhat2[i2];
+            y2[variable_] += ghu[i1]*epsilon[i3];
+          }
+        for (int column = q, column_=q*m; column<n; column++, column_ += m)
+          {
+            y2[variable_] += ghx[variable+column_]*yhat2[column+particle__];
+          }
+#endif
+        // +ghxx*kron(yhat1,yhat1)
+        for(int i=0; i<n*(n+1)/2; i++)
+          {
+            int i1 = particle__+ii1[i];
+            int i2 = particle__+ii2[i];
+            if(i1==i2)
+              { 
+                y2[variable_] += .5*ghxx[variable+ii3[i]]*yhat1[i1]*yhat1[i1];
+              }
+            else
+              {
+                y2[variable_] += ghxx[variable+ii3[i]]*yhat1[i1]*yhat1[i2];
+              }
+          }
+        // +ghuu*kron(u,u)
+        for(int j=0; j<q*(q+1)/2; j++)
+          {
+            int j1 = particle___+jj1[j];
+            int j2 = particle___+jj2[j];
+            if(j1==j2)
+              {
+                y2[variable_] += .5*ghuu[variable+jj3[j]]*epsilon[j1]*epsilon[j1];
+              }
+            else
+              {
+                y2[variable_] += ghuu[variable+jj3[j]]*epsilon[j1]*epsilon[j2];
+              }
+          }
+        // +ghxu*kron(yhat1,u)
+        for (int v = particle__, i = 0; v<particle__+n; v++)
+          for (int s = particle___; s<particle___+q; s++, i += m)
+            y2[variable_] += ghxu[variable+i]*epsilon[s]*yhat2[v];
+#ifdef FIRST_ORDER_LOOP
+        for (int column = 0, column_=0; column<q; column++, column_ += m)
+          {
+            int i1 = variable+column_;
+            int i2 = column+particle__;
+            int i3 = column+particle___;
+            y1[variable_] += ghx[i1]*yhat1[i2];
+            y1[variable_] += ghu[i1]*epsilon[i3];
+          }
+        for (int column = q, column_=q*m; column<n; column++, column_ += m)
+          {
+            y1[variable_] += ghx[variable+column_]*yhat1[column+particle__];
+          }
+#endif
+      }
+#ifndef FIRST_ORDER_LOOP
+    dgemv(transpose,&m,&n,&one,&ghx[0],&m,&yhat1[particle__],&ONE,&one,&y1[particle_],&ONE);
+    dgemv(transpose,&m,&q,&one,&ghu[0],&m,&epsilon[particle___],&ONE,&one,&y1[particle_],&ONE);
+#endif
+  }
+}
+
+void ss2Iteration(double* y, const double* yhat, const double *epsilon, 
+                  double* ghx, double* ghu, 
+                  const double* constant, const double* ghxx, const double* ghuu, const double* ghxu, 
+                  const blas_int m, const blas_int n, const blas_int q, const blas_int s)
+{
+  const char transpose[2] = "N";
+  const double one = 1.0;
+  const blas_int ONE = 1;
+  
+  vector<int> ii1, ii2, ii3;// vector indices for ghxx
+  vector<int> jj1, jj2, jj3;// vector indices for ghuu
+  set_vector_of_indices(n, m, ii1, ii2, ii3);
+  set_vector_of_indices(q, m, jj1, jj2, jj3);
+  
+  for (int particle = 0; particle<s; particle++)
+  {
+    int particle_ = particle*m;
+    int particle__ = particle*n;
+    int particle___ = particle*q;
+    memcpy(&y[particle_],&constant[0],m*sizeof(double));
+#ifndef FIRST_ORDER_LOOP
+    dgemv(transpose,&m,&n,&one,&ghx[0],&m,&yhat[particle__],&ONE,&one,&y[particle_],&ONE);
+    dgemv(transpose,&m,&q,&one,&ghu[0],&m,&epsilon[particle___],&ONE,&one,&y[particle_],&ONE);
+#endif
+    for (int variable = 0; variable<m; variable++)
+      {
+        int variable_ = variable + particle_;
+        // +ghx*yhat+ghu*u
+#ifdef FIRST_ORDER_LOOP
+        for (int column = 0, column_=0; column<q; column++, column_ += m)
+          {
+            int i1 = variable+column_;
+            int i2 = column+particle__;
+            int i3 = column+particle___;
+            y[variable_] += ghx[i1]*yhat[i2];
+            y[variable_] += ghu[i1]*epsilon[i3];
+          }
+        for (int column = q, column_=q*m; column<n; column++, column_ += m)
+          {
+            y[variable_] += ghx[variable+column_]*yhat[column+particle__];
+          }
+#endif
+        // +ghxx*kron(yhat,yhat)
+        for(int i=0; i<n*(n+1)/2; i++)
+          {
+            int i1 = particle__+ii1[i];
+            int i2 = particle__+ii2[i];
+            if(i1==i2)
+              { 
+                y[variable_] += .5*ghxx[variable+ii3[i]]*yhat[i1]*yhat[i1];
+              }
+            else
+              {
+                y[variable_] += ghxx[variable+ii3[i]]*yhat[i1]*yhat[i2];
+              }
+          }
+        // +ghuu*kron(u,u)
+        for(int j=0; j<q*(q+1)/2; j++)
+          {
+            int j1 = particle___+jj1[j];
+            int j2 = particle___+jj2[j];
+            if(j1==j2)
+              {
+                y[variable_] += .5*ghuu[variable+jj3[j]]*epsilon[j1]*epsilon[j1];
+              }
+            else
+              {
+                y[variable_] += ghuu[variable+jj3[j]]*epsilon[j1]*epsilon[j2];
+              }
+          }
+        // +ghxu*kron(yhat,u)
+        for (int v = particle__, i = 0; v<particle__+n; v++)
+          for (int s = particle___; s<particle___+q; s++, i += m)
+            y[variable_] += ghxu[variable+i]*epsilon[s]*yhat[v];
+      }
+  }
+}
+
+
+
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+  /*
+  ** prhs[0] yhat          [double]  n*s array, time t particles.
+  ** prhs[1] epsilon       [double]  q*s array, time t innovations.
+  ** prhs[2] ghx           [double]  m*n array, first order reduced form.
+  ** prhs[3] ghu           [double]  m*q array, first order reduced form. 
+  ** prhs[4] constant      [double]  m*1 array, deterministic steady state + second order correction for the union of the states and observed variables.
+  ** prhs[5] ghxx          [double]  m*n^2 array, second order reduced form.
+  ** prhs[6] ghuu          [double]  m*q^2 array, second order reduced form.
+  ** prhs[7] ghxu          [double]  m*nq array, second order reduced form.
+  ** prhs[8] yhat_         [double]  [OPTIONAL] n*s array, time t particles (pruning additional latent variables). 
+  ** prhs[9] ss            [double]  [OPTIONAL] m*1 array, steady state for the union of the states and the observed variables (needed for the pruning mode).
+  **
+  ** plhs[0] y             [double]  n*s array, time t+1 particles.
+  ** plhs[1] y_            [double]  n*s array, time t+1 particles for the pruning latent variables. 
+  **
+  */
+
+  // Check the number of input and output.
+  if ((nrhs != 8) && (nrhs != 10))
+    {
+      mexErrMsgTxt("Eight or ten input arguments are required.");
+    }
+  if (nlhs > 2) 
+    {
+      mexErrMsgTxt("Too many output arguments.");
+    }
+  // Get dimensions.
+  mwSize n = mxGetM(prhs[0]);// Number of states.
+  mwSize s = mxGetN(prhs[0]);// Number of particles.
+  mwSize q = mxGetM(prhs[1]);// Number of innovations.
+  mwSize m = mxGetM(prhs[2]);// Number of elements in the union of states and observed variables.
+  // Check the dimensions.
+  if (
+      (s != mxGetN(prhs[1]))   || // Number of columns for epsilon 
+      (n != mxGetN(prhs[2]))   || // Number of columns for ghx
+      (m != mxGetM(prhs[3]))   || // Number of rows for ghu
+      (q != mxGetN(prhs[3]))   || // Number of columns for ghu
+      (m != mxGetM(prhs[4]))   || // Number of rows for 2nd order constant correction + deterministic steady state
+      (m != mxGetM(prhs[5]))   || // Number of rows for ghxx
+      (n*n != mxGetN(prhs[5])) || // Number of columns for ghxx 
+      (m != mxGetM(prhs[6]))   || // Number of rows for ghuu
+      (q*q != mxGetN(prhs[6])) || // Number of columns for ghuu
+      (m != mxGetM(prhs[7]))   || // Number of rows for ghxu
+      (n*q != mxGetN(prhs[7]))    // Number of rows for ghxu
+      )
+    {
+      mexErrMsgTxt("Input dimension mismatch!.");
+    }
+  if (nrhs>8)
+    {
+      if (
+          (n != mxGetM(prhs[8]))   || // Number of rows for yhat_
+          (s != mxGetN(prhs[8]))   || // Number of columns for yhat_
+          (m != mxGetM(prhs[9]))      // Number of rows for ss
+          )
+        {
+          mexErrMsgTxt("Input dimension mismatch!.");
+        }
+    }
+  // Get Input arrays.
+  double *yhat = mxGetPr(prhs[0]);
+  double *epsilon = mxGetPr(prhs[1]);
+  double *ghx = mxGetPr(prhs[2]);
+  double *ghu = mxGetPr(prhs[3]);
+  double *constant = mxGetPr(prhs[4]);
+  double *ghxx = mxGetPr(prhs[5]);
+  double *ghuu = mxGetPr(prhs[6]);
+  double *ghxu = mxGetPr(prhs[7]);
+  double *yhat_, *ss;
+  if (nrhs>8)
+    {
+      yhat_ = mxGetPr(prhs[8]);
+      ss = mxGetPr(prhs[9]);
+    } 
+  if (nrhs==8)
+    {
+      double *y;
+      plhs[0] = mxCreateDoubleMatrix(m, s, mxREAL);
+      y = mxGetPr(plhs[0]);
+      ss2Iteration(y, yhat, epsilon, ghx, ghu, constant, ghxx, ghuu, ghxu, (int) m, (int) n, (int) q, (int) s);
+    }
+  else
+    {
+      double *y, *y_;
+      plhs[0] = mxCreateDoubleMatrix(m, s, mxREAL);
+      plhs[1] = mxCreateDoubleMatrix(m, s, mxREAL);
+      y = mxGetPr(plhs[0]);
+      y_ = mxGetPr(plhs[1]);
+      ss2Iteration_pruning(y, y_, yhat, yhat_, epsilon, ghx, ghu, constant, ghxx, ghuu, ghxu, ss, (int) m, (int) n, (int) q, (int) s);
+    }
+}