diff --git a/matlab/optimization/dynare_minimize_objective.m b/matlab/optimization/dynare_minimize_objective.m
index 6a0ef6e857e85bd4ec26693b5680a70fe57626ff..4558edc862df31613f6d59ea49a21ad38ccf2c02 100644
--- a/matlab/optimization/dynare_minimize_objective.m
+++ b/matlab/optimization/dynare_minimize_objective.m
@@ -288,6 +288,8 @@ switch minimizer_algorithm
         newratflag = options_.newrat.hess; %default
     end
     nit=options_.newrat.maxiter;
+    epsilon = options_.gradient_epsilon;
+    crit_rel = NaN;
     Verbose = options_.newrat.verbosity;
     Save_files = options_.newrat.Save_files;
     if ~isempty(options_.optim_opt)
@@ -303,8 +305,12 @@ switch minimizer_algorithm
                 else
                     newratflag=flag;
                 end
+              case 'NumgradEpsilon'
+                epsilon = options_list{i,2};
               case 'TolFun'
                 crit = options_list{i,2};
+              case 'TolFunRel'
+                crit_rel = options_list{i,2};
               case 'verbosity'
                 Verbose = options_list{i,2};
               case 'SaveFiles'
@@ -318,9 +324,10 @@ switch minimizer_algorithm
         Save_files = 0;
         Verbose = 0;
     end
+    hess_info.crit_rel=crit_rel;
     hess_info.gstep=options_.gstep;
     hess_info.htol = 1.e-4;
-    hess_info.h1=options_.gradient_epsilon*ones(n_params,1);
+    hess_info.h1=epsilon*ones(n_params,1);
     % here we force 7th input argument (flagg) to be 0, since outer product
     % gradient Hessian is handled in dynare_estimation_1
     [opt_par_values,hessian_mat,gg,fval,invhess,new_rat_hess_info] = newrat(objective_function,start_par_value,bounds,analytic_grad,crit,nit,0,Verbose,Save_files,hess_info,prior_information.p2,options_.gradient_epsilon,parameter_names,varargin{:});    %hessian_mat is the plain outer product gradient Hessian
diff --git a/matlab/optimization/mr_gstep.m b/matlab/optimization/mr_gstep.m
index a7f39a604152b0f2a2d0fc16f138780793031751..425a495bcb56ace2d9ddcf583312a5b604886acb 100644
--- a/matlab/optimization/mr_gstep.m
+++ b/matlab/optimization/mr_gstep.m
@@ -72,15 +72,77 @@ while i<n
         gg(i)=(f1(i)'-f_1(i)')./(2.*h1(i));
         hh(i) = 1/max(1.e-9,abs( (f1(i)+f_1(i)-2*f0)./(h1(i)*h1(i)) ));
         if gg(i)*(hh(i)*gg(i))/2 > htol(i)
-            [f0, x, ~, ~] = csminit1(func0,x,penalty,f0,gg,0,diag(hh),Verbose,varargin{:});
+            [ff, xx,fcount,retcode] = csminit1(func0,x,penalty,f0,gg,0,diag(hh),Verbose,varargin{:});
+            if retcode
+%                 do_nothing=true;
+                xa=transpose(linspace(x(i)/2, x(i)*3/2, 7));
+                for k=1:7
+                    xh1(i)=xa(k);
+                    fa(k,1) = penalty_objective_function(xh1,func0,penalty,varargin{:});
+                end
+                b=[ones(7,1) xa xa.*xa./2]\fa;
+                gg(i)=x(i)*b(3)+b(2);
+                hh(i)=1/b(3);
+                [ff2, xx2, fcount2, retcode2] = csminit1(func0,x,penalty,f0,gg,0,diag(hh),Verbose,varargin{:});
+                if ff2<ff
+                    ff=ff2;
+                    xx=xx2;
+                end
+                if min(fa)<ff
+                    [ff, im]=min(fa);
+                    xx(i)=xa(im);
+                end
+            end
             ig(i)=1;
+            if not(isequal(xx , check_bounds(xx,bounds)))
+                xx = check_bounds(xx,bounds);
+                if xx(i)<x(i)   
+                    % lower bound
+                    xx(i) = min(xx(i)+h1(i), 0.5*(xx(i)+x(i)));
+                else
+                    % upper bound
+                    xx(i) = max(xx(i)-h1(i), 0.5*(xx(i)+x(i)));
+                end
+                [ff,exit_flag]=penalty_objective_function(xx,func0,penalty,varargin{:});
+                if exit_flag~=1
+                    disp('last step exited with bad status!')
+                elseif ff<f0
+                    f0=ff;
+                    x=xx;
+                end
+            else
+                % check improvement wrt predicted one
+                if abs(f0-ff) < abs(gg(i)*(hh(i)*gg(i))/2/100) || abs(x(i)-xx(i))<1.e-10
+                    [ff1, xx1, fcount, retcode] = csminit1(func0,x,penalty,f0,-gg,0,diag(hh),Verbose,varargin{:});
+                    if not(isequal(xx1 , check_bounds(xx1,bounds)))
+                        xx1 = check_bounds(xx1,bounds);
+                        if xx1(i)<x(i)
+                            % lower bound
+                            xx1(i) = min(xx1(i)+h1(i), 0.5*(xx1(i)+x(i)));
+                        else
+                            % upper bound
+                            xx1(i) = max(xx1(i)-h1(i), 0.5*(xx1(i)+x(i)));
+                        end
+                        [ff1,exit_flag]=penalty_objective_function(xx1,func0,penalty,varargin{:});
+                        if exit_flag~=1
+                            disp('last step exited with bad status!')
+                        end
+                    end
+                    if ff1<ff
+                        ff=ff1;
+                        xx=xx1;
+                    end
+                end
+                f0=ff;
+                x=xx;
+            end
             if Verbose
-                fprintf(['Done for param %s = %8.4f\n'],parameter_names{i},x(i))
+                fprintf(['Done for param %s = %8.4f; f = %8.4f\n'],parameter_names{i},x(i),f0)
             end
         end
         xh1=x;
     end
-    x = check_bounds(x,bounds);
+%     penalty=f0;
     if Save_files
         save('gstep.mat','x','h1','f0')
     end
@@ -96,10 +158,10 @@ function x = check_bounds(x,bounds)
 
 inx = find(x>=bounds(:,2));
 if ~isempty(inx)
-    x(inx) = bounds(inx,2)-eps;
+    x(inx) = bounds(inx,2)-1.e-10;
 end
 
 inx = find(x<=bounds(:,1));
 if ~isempty(inx)
-    x(inx) = bounds(inx,1)+eps;
+    x(inx) = bounds(inx,1)+1.e-10;
 end
diff --git a/matlab/optimization/mr_hessian.m b/matlab/optimization/mr_hessian.m
index 4cd15a90cff0d053eabe09a9f1da727cae57d7fc..03dbc548ec0f79cbb3a285c91579c6c334d0688d 100644
--- a/matlab/optimization/mr_hessian.m
+++ b/matlab/optimization/mr_hessian.m
@@ -78,11 +78,16 @@ else
 end
 
 
-hess_info.h1 = min(hess_info.h1,0.5.*hmax);
+hess_info.h1 = min(hess_info.h1,0.9.*hmax);
 
 if htol0<hess_info.htol
     hess_info.htol=htol0;
 end
+if not(isnan(hess_info.crit_rel))
+    htol1=hess_info.htol;
+    hess_info.htol=abs(hess_info.crit_rel*f0);
+end
+
 xh1=x;
 f1=zeros(size(f0,1),n);
 f_1=f1;
@@ -106,22 +111,39 @@ while i<n
     ic=0;
     icount = 0;
     h0=hess_info.h1(i);
-    while (abs(dx(it))<0.5*hess_info.htol || abs(dx(it))>(3*hess_info.htol)) && icount<10 && ic==0
+    istoobig=false;
+    istoosmall=false;
+    give_it_up=false;
+    while (abs(dx(it))<0.5*hess_info.htol || abs(dx(it))>(3*hess_info.htol)) && icount<10 && ic==0 && hmax(i)>2*1.e-10 && not(give_it_up)
         icount=icount+1;
+        istoobig(it)=false;
+        istoosmall(it)=false;
         if abs(dx(it))<0.5*hess_info.htol
+            istoosmall(it)=true;
+            if hess_info.h1(i)==0.9*hmax(i)% || hess_info.h1(i)==0.3*abs(x(i))
+                give_it_up=true;
+            end
             if abs(dx(it)) ~= 0
-                hess_info.h1(i)=min(max(1.e-10,0.3*abs(x(i))), 0.9*hess_info.htol/abs(dx(it))*hess_info.h1(i));
+%                 htmp=min(max(1.e-10,0.3*abs(x(i))), 0.9*hess_info.htol/abs(dx(it))*hess_info.h1(i));
+                htmp=0.9*hess_info.htol/abs(dx(it))*hess_info.h1(i);
             else
-                hess_info.h1(i)=2.1*hess_info.h1(i);
+                htmp=2.1*hess_info.h1(i);
             end
-            hess_info.h1(i) = min(hess_info.h1(i),0.5*hmax(i));
-            hess_info.h1(i) = max(hess_info.h1(i),1.e-10);
+            htmp = min(htmp,0.9*hmax(i));
+            if any(h0(istoobig(1:it))) %&& htmp>=min(h0(istoobig(1:it)))
+                htmp = 0.5*(min(h0(istoobig))+max(h0(istoosmall)));
+            end
+            hess_info.h1(i) = max(htmp,1.e-10);
             xh1(i)=x(i)+hess_info.h1(i);
             [fx,exit_flag,ffx]=penalty_objective_function(xh1,func,penalty,varargin{:});
         end
         if abs(dx(it))>(3*hess_info.htol)
-            hess_info.h1(i)= hess_info.htol/abs(dx(it))*hess_info.h1(i);
-            hess_info.h1(i) = max(hess_info.h1(i),1e-10);
+            istoobig(it)=true;
+            htmp= hess_info.htol/abs(dx(it))*hess_info.h1(i);
+            if any(h0(istoosmall(1:it))) %&& htmp<=max(h0(istoosmall(1:it)))
+                htmp = 0.5*(min(h0(istoobig))+max(h0(istoosmall)));
+            end
+            hess_info.h1(i) = max(htmp,1e-10);
             xh1(i)=x(i)+hess_info.h1(i);
             [fx,exit_flag,ffx]=penalty_objective_function(xh1,func,penalty,varargin{:});
             iter=0;
@@ -136,11 +158,27 @@ while i<n
         it=it+1;
         dx(it)=(fx-f0);
         h0(it)=hess_info.h1(i);
-        if (hess_info.h1(i)<1.e-12*min(1,h2(i)) && hess_info.h1(i)<0.5*hmax(i))
+        if (hess_info.h1(i)<1.e-12*min(1,h2(i)) && hess_info.h1(i)<0.9*hmax(i))
             ic=1;
             hcheck=1;
         end
     end
+    if icount == 10 || hess_info.h1(i)==1.e-10
+        istoobig(it)=false;
+        istoosmall(it)=false;
+        if abs(dx(it))<0.5*hess_info.htol
+            istoosmall(it)=true;
+        end
+        if abs(dx(it))>(3*hess_info.htol)
+            istoobig(it)=true;
+        end
+        if any(istoobig) && (istoosmall(it) || istoobig(it))
+            % always better to be wrong from above, to avoid numerical noise
+            [ddx, ij]=min(dx(istoobig));
+            fx=f0+ddx;
+            hess_info.h1(i)=h0(ij);
+        end
+    end
     f1(:,i)=fx;
     if outer_product_gradient
         if any(isnan(ffx)) || isempty(ffx)
@@ -265,4 +303,6 @@ else
     hh1 = [];
 end
 
-htol1=hhtol;
+if isnan(hess_info.crit_rel)
+    htol1=hhtol;
+end
\ No newline at end of file
diff --git a/matlab/optimization/newrat.m b/matlab/optimization/newrat.m
index a3c07db051bb281f97f0f922b8ffb453a3e4086f..9832930da8942285677fffda02d9e90bb99cba49 100644
--- a/matlab/optimization/newrat.m
+++ b/matlab/optimization/newrat.m
@@ -94,6 +94,7 @@ fval=fval0;
 
 outer_product_gradient=1;
 if isempty(hh)
+    penalty=fval0;
     [dum, gg, htol0, igg, hhg, h1, hess_info]=mr_hessian(x,func0,penalty,flagit,htol,hess_info,bounds,prior_std,Save_files,varargin{:});
     if isempty(dum)
         outer_product_gradient=0;
@@ -176,9 +177,25 @@ while norm(gg)>gtol && check==0 && jit<nit
         iggx(ig_pos,ig_pos) = inv( hhx(ig_pos,ig_pos) );
         [fvala,x0,fc,retcode] = csminit1(func0,x0,penalty,fval,ggx,0,iggx,Verbose,varargin{:});
     end
-    x0 = check_bounds(x0,bounds);
+    if not(isequal(x0 , check_bounds(x0,bounds)))
+        x0 = check_bounds(x0,bounds);
+        [fvala,exit_flag]=penalty_objective_function(x0,func0,penalty,varargin{:});
+        if exit_flag==1
+            penalty=fvala;
+        else
+            disp('last step exited with bad status!')
+        end
+    end
     [fvala, x0, ig] = mr_gstep(h1,x0,bounds,func0,penalty,htol0,Verbose,Save_files,gradient_epsilon, parameter_names,varargin{:});
-    x0 = check_bounds(x0,bounds);
+    if not(isequal(x0 , check_bounds(x0,bounds)))
+        x0 = check_bounds(x0,bounds);
+        [fvala,exit_flag]=penalty_objective_function(x0,func0,penalty,varargin{:});
+        if exit_flag==1
+            penalty=fvala;
+        else
+            disp('last step exited with bad status!')
+        end
+    end
     if Save_files
         nig=[nig ig];
     end