diff --git a/matlab/disp_identification.m b/matlab/disp_identification.m
index 9c399ebecf5947cc9b39228d18b4be80e2e465b8..716d52f6383ce24231dabffc284f532b28c47c93 100644
--- a/matlab/disp_identification.m
+++ b/matlab/disp_identification.m
@@ -71,7 +71,7 @@ if options_ident.normalize_jacobians == 1
 else
     fprintf('    Normalize Jacobians:                                   No\n');
 end
-fprintf('    Tolerance level for rank computations:                 %.0d\n',options_ident.tol_rank);
+fprintf('    Tolerance level for rank computations:                 %s\n',num2str(options_ident.tol_rank));
 fprintf('    Tolerance level for selecting nonzero columns:         %.0d\n',options_ident.tol_deriv);
 fprintf('    Tolerance level for selecting nonzero singular values: %.0d\n',options_ident.tol_sv);
 
diff --git a/matlab/dynare_identification.m b/matlab/dynare_identification.m
index bb08707df8c379ed1b16278c4c8ddcda9775478f..557083881c239bf1ebd15d776a73958ba23f8c1e 100644
--- a/matlab/dynare_identification.m
+++ b/matlab/dynare_identification.m
@@ -89,6 +89,7 @@ else
     warning('off','MATLAB:specgraph:private:specgraph:UsingOnlyRealComponentOfComplexData');
     warning('off','MATLAB:handle_graphics:exceptions:SceneNode');
     warning('off','MATLAB:divideByZero');
+    warning('off','MATLAB:log:logOfZero');
 end
 
 %% Set all options and create objects
@@ -136,7 +137,7 @@ options_ident = set_default_option(options_ident,'grid_nbr',5000);
             error('IDENTIFICATION: You need to set an even value for ''grid_nbr''');
         end
     end
-options_ident = set_default_option(options_ident,'tol_rank',1.e-10);
+options_ident = set_default_option(options_ident,'tol_rank','robust');
     % tolerance level used for rank computations
 options_ident = set_default_option(options_ident,'tol_deriv',1.e-8);
     % tolerance level for selecting columns of non-zero derivatives
diff --git a/matlab/identification_analysis.m b/matlab/identification_analysis.m
index de0be7db44d593cfdba761bff3ac853a225726fb..c03ea8a0ef042f519b06edea6534a3a3be0e0495 100644
--- a/matlab/identification_analysis.m
+++ b/matlab/identification_analysis.m
@@ -231,14 +231,14 @@ if info(1) == 0 %no errors in solution
         end
         ind_dDYNAMIC = (find(max(abs(dDYNAMIC'),[],1) > tol_deriv)); %index with non-zero rows
     end
-    
+
     DYNAMIC = DYNAMIC(ind_dDYNAMIC); %focus only on non-zero entries
     si_dDYNAMIC = (dDYNAMIC(ind_dDYNAMIC,:)); %focus only on non-zero rows
     if ~no_identification_reducedform
         REDUCEDFORM = REDUCEDFORM(ind_dREDUCEDFORM); %focus only on non-zero entries
         si_dREDUCEDFORM = (dREDUCEDFORM(ind_dREDUCEDFORM,:)); %focus only on non-zero rows
     end
-    
+
     if ~no_identification_moments
         MOMENTS = MOMENTS(ind_dMOMENTS); %focus only on non-zero entries
         si_dMOMENTS   = (dMOMENTS(ind_dMOMENTS,:)); %focus only on non-zero derivatives
@@ -268,6 +268,9 @@ if info(1) == 0 %no errors in solution
 
             try
                 %try to compute asymptotic Hessian for identification strength analysis based on moments
+                if options_.order > 1
+                    error('IDENTIFICATION STRENGTH: Analytic computation of Hessian is not available for ''order>1''. Identification strength is based on simulated moment uncertainty');
+                end                
                 % reset some options for faster computations
                 options_.irf                     = 0;
                 options_.noprint                 = 1;
@@ -282,10 +285,6 @@ if info(1) == 0 %no errors in solution
                 dataset_ = dseries(oo_.endo_simul(options_.varobs_id,100+1:end)',dates('1Q1'), options_.varobs); %get information on moments
                 derivatives_info.no_DLIK = 1;
                 bounds = prior_bounds(bayestopt_, options_.prior_trunc); %reset bounds as lb and ub must only be operational during mode-finding 
-                if options_.order > 1
-                    fprintf('IDENTIFICATION STRENGTH: Analytic computation of Hessian is not available for ''order>1''\n')
-                    fprintf('                         Identification strength is based on simulated moment uncertainty\n');
-                end
                 %note that for order>1 we do not provide any information on DT,DYss,DOM in derivatives_info, such that dsge_likelihood creates an error. Therefore the computation will be based on simulated_moment_uncertainty for order>1.
                 [fval, info, cost_flag, DLIK, AHess, ys, trend_coeff, M_, options_, bayestopt_, oo_] = dsge_likelihood(params', dataset_, dataset_info, options_, M_, estim_params_, bayestopt_, bounds, oo_, derivatives_info); %non-used output variables need to be set for octave for some reason
                     %note that for the order of parameters in AHess we have: stderr parameters come first, corr parameters second, model parameters third. the order within these blocks corresponds to the order specified in the estimated_params block
@@ -315,6 +314,13 @@ if info(1) == 0 %no errors in solution
                 flag_score = 1; %this is used for the title in plot_identification.m
             catch
                 %Asymptotic Hessian via simulation
+                if options_.order > 1       
+                    % reset some options for faster computations
+                    options_.irf                     = 0;
+                    options_.noprint                 = 1;
+                    options_.SpectralDensity.trigger = 0;
+                    options_.periods                 = periods+100;
+                end                
                 replic = max([replic, length(ind_dMOMENTS)*3]);
                 cmm = simulated_moment_uncertainty(ind_dMOMENTS, periods, replic,options_,M_,oo_); %covariance matrix of moments
                 sd = sqrt(diag(cmm));
diff --git a/matlab/identification_checks.m b/matlab/identification_checks.m
index 5fb971d0fb6d60ab7e340da0befcc083b82b6f4e..cb6717470dd5d1dd87c4efeab975bbdf175da372 100644
--- a/matlab/identification_checks.m
+++ b/matlab/identification_checks.m
@@ -51,8 +51,8 @@ function [condX, rankX, ind0, indno, ixno, Mco, Pco, jweak, jweak_pair] = identi
 if issparse(X)
     X = full(X);
 end
-if nargin < 3 || isempty(tol_rank)
-    tol_rank = 1.e-10; %tolerance level used for rank computations
+if nargin < 3 || isempty(tol_rank) || strcmp(tol_rank,'robust')
+    tol_rank = max(size(X)) * eps(norm(X)); %tolerance level used for rank computations
 end
 if nargin < 4 || isempty(tol_sv)
     tol_sv = 1.e-3; %tolerance level for zero singular value
diff --git a/matlab/identification_checks_via_subsets.m b/matlab/identification_checks_via_subsets.m
index e3aa35985599def4d1f15e1fe6e8e5c632cb3c27..63a9bbce322bf77d2c7cf30e702f632702237ce1 100644
--- a/matlab/identification_checks_via_subsets.m
+++ b/matlab/identification_checks_via_subsets.m
@@ -93,7 +93,11 @@ if ~no_identification_dynamic
     if totparam_nbr > modparam_nbr
         dDYNAMIC = [zeros(size(ide_dynamic.dDYNAMIC,1),totparam_nbr-modparam_nbr) dDYNAMIC]; %add derivatives wrt stderr and corr parameters
     end
-    rank_dDYNAMIC = rank(full(dDYNAMIC),tol_rank); %compute rank with imposed tolerance level
+    if strcmp(tol_rank,'robust')
+        rank_dDYNAMIC = rank(full(dDYNAMIC)); %compute rank with imposed tolerance level
+    else
+        rank_dDYNAMIC = rank(full(dDYNAMIC),tol_rank); %compute rank with imposed tolerance level
+    end
     ide_dynamic.rank = rank_dDYNAMIC;
     % check rank criteria for full Jacobian
     if rank_dDYNAMIC == totparam_nbr
@@ -112,7 +116,11 @@ end
 if ~no_identification_reducedform
     dREDUCEDFORM = ide_reducedform.dREDUCEDFORM;
     dREDUCEDFORM(ide_reducedform.ind_dREDUCEDFORM,:) = dREDUCEDFORM(ide_reducedform.ind_dREDUCEDFORM,:)./ide_reducedform.norm_dREDUCEDFORM; %normalize
-    rank_dREDUCEDFORM = rank(full(dREDUCEDFORM),tol_rank); %compute rank with imposed tolerance level
+    if strcmp(tol_rank,'robust')
+        rank_dREDUCEDFORM = rank(full(dREDUCEDFORM)); %compute rank with imposed tolerance level
+    else
+        rank_dREDUCEDFORM = rank(full(dREDUCEDFORM),tol_rank); %compute rank with imposed tolerance level
+    end
     ide_reducedform.rank = rank_dREDUCEDFORM;
     % check rank criteria for full Jacobian
     if rank_dREDUCEDFORM == totparam_nbr
@@ -131,7 +139,11 @@ end
 if ~no_identification_moments
     dMOMENTS = ide_moments.dMOMENTS;
     dMOMENTS(ide_moments.ind_dMOMENTS,:) = dMOMENTS(ide_moments.ind_dMOMENTS,:)./ide_moments.norm_dMOMENTS; %normalize
-    rank_dMOMENTS = rank(full(dMOMENTS),tol_rank); %compute rank with imposed tolerance level
+    if strcmp(tol_rank,'robust')
+        rank_dMOMENTS = rank(full(dMOMENTS)); %compute rank with imposed tolerance level
+    else
+        rank_dMOMENTS = rank(full(dMOMENTS),tol_rank); %compute rank with imposed tolerance level
+    end
     ide_moments.rank = rank_dMOMENTS;
     % check rank criteria for full Jacobian
     if rank_dMOMENTS == totparam_nbr
@@ -152,7 +164,11 @@ if ~no_identification_spectrum
     %alternative normalization
     %dSPECTRUM = ide_spectrum.dSPECTRUM;
     %dSPECTRUM(ide_spectrum.ind_dSPECTRUM,:) = dSPECTRUM(ide_spectrum.ind_dSPECTRUM,:)./ide_spectrum.norm_dSPECTRUM; %normalize
-    rank_dSPECTRUM = rank(full(dSPECTRUM),tol_rank); %compute rank with imposed tolerance level
+    if strcmp(tol_rank,'robust')
+        rank_dSPECTRUM = rank(full(dSPECTRUM)); %compute rank with imposed tolerance level
+    else
+        rank_dSPECTRUM = rank(full(dSPECTRUM),tol_rank); %compute rank with imposed tolerance level
+    end
     ide_spectrum.rank = rank_dSPECTRUM;
     % check rank criteria for full Jacobian
     if rank_dSPECTRUM == totparam_nbr
@@ -173,7 +189,11 @@ if ~no_identification_minimal
     dMINIMAL(ide_minimal.ind_dMINIMAL,:) = dMINIMAL(ide_minimal.ind_dMINIMAL,:)./ide_minimal.norm_dMINIMAL; %normalize
     dMINIMAL_par  = dMINIMAL(:,1:totparam_nbr);       %part of dMINIMAL that is dependent on parameters
     dMINIMAL_rest = dMINIMAL(:,(totparam_nbr+1):end); %part of dMINIMAL that is independent of parameters
-    rank_dMINIMAL = rank(full(dMINIMAL),tol_rank); %compute rank via SVD see function below
+    if strcmp(tol_rank,'robust')
+        rank_dMINIMAL = rank(full(dMINIMAL)); %compute rank via SVD see function below
+    else
+        rank_dMINIMAL = rank(full(dMINIMAL),tol_rank); %compute rank via SVD see function below
+    end
     ide_minimal.rank = rank_dMINIMAL;
     dMINIMAL_fixed_rank_nbr = size(dMINIMAL_rest,2);
     % check rank criteria for full Jacobian
@@ -193,20 +213,38 @@ end
 for j=1:totparam_nbr
     if ~no_identification_dynamic
         % Columns correspond to single parameters, i.e. full rank would be equal to 1
-        if rank(full(dDYNAMIC(:,j)),tol_rank) == 0
-            dynamic_problpars{1} = [dynamic_problpars{1};j];
+        if strcmp(tol_rank,'robust')
+            if rank(full(dDYNAMIC(:,j))) == 0
+                dynamic_problpars{1} = [dynamic_problpars{1};j];
+            end
+        else
+            if rank(full(dDYNAMIC(:,j)),tol_rank) == 0
+                dynamic_problpars{1} = [dynamic_problpars{1};j];
+            end
         end
     end
     if ~no_identification_reducedform
         % Columns correspond to single parameters, i.e. full rank would be equal to 1
-        if rank(full(dREDUCEDFORM(:,j)),tol_rank) == 0
-            reducedform_problpars{1} = [reducedform_problpars{1};j];
+        if strcmp(tol_rank,'robust')
+            if rank(full(dREDUCEDFORM(:,j))) == 0
+                reducedform_problpars{1} = [reducedform_problpars{1};j];
+            end
+        else
+            if rank(full(dREDUCEDFORM(:,j)),tol_rank) == 0
+                reducedform_problpars{1} = [reducedform_problpars{1};j];
+            end
         end
     end
-    if ~no_identification_moments
+    if ~no_identification_moments        
         % Columns correspond to single parameters, i.e. full rank would be equal to 1
-        if rank(full(dMOMENTS(:,j)),tol_rank) == 0
-            moments_problpars{1} = [moments_problpars{1};j];
+        if strcmp(tol_rank,'robust')
+            if rank(full(dMOMENTS(:,j))) == 0
+                moments_problpars{1} = [moments_problpars{1};j];
+            end
+        else
+            if rank(full(dMOMENTS(:,j)),tol_rank) == 0
+                moments_problpars{1} = [moments_problpars{1};j];
+            end
         end
     end
     if ~no_identification_spectrum
@@ -218,8 +256,14 @@ for j=1:totparam_nbr
     if ~no_identification_minimal
         % Columns of dMINIMAL_par correspond to single parameters, needs to be augmented with dMINIMAL_rest (part that is independent of parameters),
         % full rank would be equal to 1+dMINIMAL_fixed_rank_nbr
-        if rank(full([dMINIMAL_par(:,j) dMINIMAL_rest]),tol_rank) == dMINIMAL_fixed_rank_nbr
-            minimal_problpars{1} = [minimal_problpars{1};j];
+        if strcmp(tol_rank,'robust')
+            if rank(full([dMINIMAL_par(:,j) dMINIMAL_rest])) == dMINIMAL_fixed_rank_nbr
+                minimal_problpars{1} = [minimal_problpars{1};j];
+            end
+        else
+            if rank(full([dMINIMAL_par(:,j) dMINIMAL_rest]),tol_rank) == dMINIMAL_fixed_rank_nbr
+                minimal_problpars{1} = [minimal_problpars{1};j];
+            end
         end
     end
 end
@@ -324,35 +368,55 @@ for j=2:min(length(indtotparam),max_dim_subsets_groups) % Check j-element subset
             k_dDYNAMIC = k_dDYNAMIC+1;
             if k_dDYNAMIC <= size(indexj_dDYNAMIC,1)
                 dDYNAMIC_j = dDYNAMIC(:,indexj_dDYNAMIC(k_dDYNAMIC,:)); % pick columns that correspond to parameter subset
-                rankj_dDYNAMIC(k_dDYNAMIC,1) = rank(full(dDYNAMIC_j),tol_rank); %compute rank with imposed tolerance
+                if strcmp(tol_rank,'robust')
+                    rankj_dDYNAMIC(k_dDYNAMIC,1) = rank(full(dDYNAMIC_j)); %compute rank with imposed tolerance
+                else
+                    rankj_dDYNAMIC(k_dDYNAMIC,1) = rank(full(dDYNAMIC_j),tol_rank); %compute rank with imposed tolerance
+                end
             end
         end
         if ~no_identification_reducedform
             k_dREDUCEDFORM = k_dREDUCEDFORM+1;
             if k_dREDUCEDFORM <= size(indexj_dREDUCEDFORM,1)
                 dREDUCEDFORM_j = dREDUCEDFORM(:,indexj_dREDUCEDFORM(k_dREDUCEDFORM,:)); % pick columns that correspond to parameter subset
-                rankj_dREDUCEDFORM(k_dREDUCEDFORM,1) = rank(full(dREDUCEDFORM_j),tol_rank); %compute rank with imposed tolerance
+                if strcmp(tol_rank,'robust')
+                    rankj_dREDUCEDFORM(k_dREDUCEDFORM,1) = rank(full(dREDUCEDFORM_j)); %compute rank with imposed tolerance
+                else
+                    rankj_dREDUCEDFORM(k_dREDUCEDFORM,1) = rank(full(dREDUCEDFORM_j),tol_rank); %compute rank with imposed tolerance
+                end
             end
         end
         if ~no_identification_moments
             k_dMOMENTS = k_dMOMENTS+1;
             if k_dMOMENTS <= size(indexj_dMOMENTS,1)
                 dMOMENTS_j = dMOMENTS(:,indexj_dMOMENTS(k_dMOMENTS,:)); % pick columns that correspond to parameter subset
-                rankj_dMOMENTS(k_dMOMENTS,1) = rank(full(dMOMENTS_j),tol_rank); %compute rank with imposed tolerance
+                if strcmp(tol_rank,'robust')
+                    rankj_dMOMENTS(k_dMOMENTS,1) = rank(full(dMOMENTS_j)); %compute rank with imposed tolerance
+                else
+                    rankj_dMOMENTS(k_dMOMENTS,1) = rank(full(dMOMENTS_j),tol_rank); %compute rank with imposed tolerance
+                end
             end
         end
         if ~no_identification_minimal
             k_dMINIMAL = k_dMINIMAL+1;
             if k_dMINIMAL <= size(indexj_dMINIMAL,1)
                 dMINIMAL_j = [dMINIMAL_par(:,indexj_dMINIMAL(k_dMINIMAL,:)) dMINIMAL_rest]; % pick columns in dMINIMAL_par that correspond to parameter subset and augment with parameter-indepdendet part dMINIMAL_rest
-                rankj_dMINIMAL(k_dMINIMAL,1) = rank(full(dMINIMAL_j),tol_rank); %compute rank with imposed tolerance
+                if strcmp(tol_rank,'robust')
+                    rankj_dMINIMAL(k_dMINIMAL,1) = rank(full(dMINIMAL_j)); %compute rank with imposed tolerance
+                else
+                    rankj_dMINIMAL(k_dMINIMAL,1) = rank(full(dMINIMAL_j),tol_rank); %compute rank with imposed tolerance
+                end
             end
         end
         if ~no_identification_spectrum
             k_dSPECTRUM = k_dSPECTRUM+1;
             if k_dSPECTRUM <= size(indexj_dSPECTRUM,1)
                 dSPECTRUM_j = dSPECTRUM(indexj_dSPECTRUM(k_dSPECTRUM,:),indexj_dSPECTRUM(k_dSPECTRUM,:)); % pick rows and columns that correspond to parameter subset
-                rankj_dSPECTRUM(k_dSPECTRUM,1) = rank(full(dSPECTRUM_j),tol_rank); % Compute rank with imposed tol
+                if strcmp(tol_rank,'robust')
+                    rankj_dSPECTRUM(k_dSPECTRUM,1) = rank(full(dSPECTRUM_j)); % Compute rank with imposed tol
+                else
+                    rankj_dSPECTRUM(k_dSPECTRUM,1) = rank(full(dSPECTRUM_j),tol_rank); % Compute rank with imposed tol
+                end
             end
         end
         dyn_waitbar(k/maxk,h)
diff --git a/matlab/uperm.m b/matlab/uperm.m
index af0d1f6f1f829849bf4e25ca35343f24b83a25e5..bbc690afccd7b511913be92cc270714b72bd5466 100644
--- a/matlab/uperm.m
+++ b/matlab/uperm.m
@@ -1,11 +1,11 @@
-% By Willi Mutschler, September 26, 2016. Email: willi@mutschler.eu
+% By Bruno Luong
 function p = uperm(a)
 [u, ~, J] = unique(a);
 p = u(up(J, length(a)));
 
 
 function p = up(J, n)
-ktab = histcounts(J,1:max(J));
+ktab = histc(J,1:max(J));
 l = n;
 p = zeros(1, n);
 s = 1;
diff --git a/tests/identification/as2007/as2007_QT.mod b/tests/identification/as2007/as2007_QT.mod
index 1837bd236601e251159f1d9ee4b6a9b94a605032..715d58db795ffa29294b7ea7848b67af1620ff8f 100644
--- a/tests/identification/as2007/as2007_QT.mod
+++ b/tests/identification/as2007/as2007_QT.mod
@@ -2,6 +2,8 @@
 % used in their replication file.
 % This file is used to check whether the G matrix is computed correctly.
 % Created by Willi Mutschler (willi@mutschler.eu)
+@#define TOL_RANK = 1e-10
+
 var z g R y pie c piep yp;
 varexo e_z e_g e_R ;
 parameters tau betta nu phi pistar psi1 psi2 rhor rhog rhoz sig2r sig2g sig2z;
@@ -72,6 +74,7 @@ identification(parameter_set=calibration,
                no_identification_reducedform,
                no_identification_moments,
                checks_via_subsets=1,
+               tol_rank=@{TOL_RANK},
                max_dim_subsets_groups=4);
 
 load('G_QT'); %note that this is computed using replication files of Qu and Tkachenko (2012)
@@ -88,7 +91,7 @@ ind_G_QT = (find(max(abs(G_QT'),[],1) > temp.store_options_ident.tol_deriv));
 tilda_G_QT = zeros(size(G_QT));
 delta_G_QT = sqrt(diag(G_QT(ind_G_QT,ind_G_QT)));
 tilda_G_QT(ind_G_QT,ind_G_QT) = G_QT(ind_G_QT,ind_G_QT)./((delta_G_QT)*(delta_G_QT'));
-if ~isequal(rank(tilda_G_QT,temp.store_options_ident.tol_rank),rank(tilda_G_dynare,temp.store_options_ident.tol_rank))
+if ~isequal(rank(tilda_G_QT,@{TOL_RANK}),rank(tilda_G_dynare,@{TOL_RANK}))
     error('ranks are not the same for normalized version')
 end
 
diff --git a/tests/identification/as2007/as2007_order_1_2_3.mod b/tests/identification/as2007/as2007_order_1_2_3.mod
index a8fcbfd2d5d4eca3a89de324f277808e8136b5b3..166f36d6939b5af017169de4903e0691f7ab0a47 100644
--- a/tests/identification/as2007/as2007_order_1_2_3.mod
+++ b/tests/identification/as2007/as2007_order_1_2_3.mod
@@ -99,7 +99,7 @@ end;
 
 steady;
 check;
-stoch_simul(order=3,irf=0,periods=0); %needed for identification(order=3)
+stoch_simul(order=3,irf=0); %needed for identification(order=3)
 
 @#for ORDER in [1, 2, 3]
 @#for KRONFLAG in [-1, -2, 0]