/*
 * Copyright (C) 1996-2011 Daniel Waggoner and Tao Zha
 *
 * This 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.
 *
 * It 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.
 *
 * If you did not received a copy of the GNU General Public License
 * with this software, see <http://www.gnu.org/licenses/>.
 */

#include "dw_switch.h"
#include "dw_switchio.h"
#include "dw_histogram.h"
#include "dw_matrix_sort.h"
#include "VARio.h"
#include "VARbase.h"
#include "dw_sbvar_command_line.h"
#include "dw_parse_cmd.h"
#include "dw_ascii.h"
#include "dw_error.h"
#include "dw_math.h"
#include "dw_std.h"

#include <stdlib.h>
#include <string.h>
#include <math.h>

// define to use ECB normalization versions
//#define ECB_VERSION

static int GetNumberDraws(FILE *f)
{
  int count=0, n;
  char *buffer=(char*)NULL;
  rewind(f);
  while ((buffer=dw_ReadLine(f,buffer,&n))) count++;
  rewind(f);
  return count;
}

/*

*/
static TVector* RandomSamplePosterior(FILE *posterior_file, __attribute__ ((unused)) int nposterior_draws, __attribute__ ((unused)) int size)
{
  TVector *sample=(TVector*)NULL;
  rewind(posterior_file);


  rewind(posterior_file);
  return sample;
}

/*
   Assumes
     ir    : horizon x nvar*nvar matrix
     S     : integer array of length horizon
     A0_Xi : nvar x nvar matrix equal to A0[S[0]]*Xi[S[0]]
     B     : h dimensional array of nvar x nvar*nlags matrices or null pointer.
             See GetIRMatrices() for a description of B.  A null pointer implies
             that nlags is zero.

   Notes:
     The element in position (k,i+j*nvars) of ir is the response of the ith 
     variable to the jth shock at horizon k.  Horizon 0 is the contemporaneous 
     response.
*/
void impulse_response(TMatrix ir, int *S, TMatrix A0_Xi, TMatrix* B)
{
  int  nvars=RowM(A0_Xi), horizon=RowM(ir), t, i, j;
  TMatrix Y_t, X_t, epsilon_t;
  
  Y_t=CreateMatrix(nvars,nvars);
  epsilon_t=IdentityMatrix((TMatrix)NULL,nvars);

  ProductInverseMM(Y_t,epsilon_t,A0_Xi);
  for (i=nvars-1; i >= 0; i--)
    for (j=nvars-1; j >= 0; j--)
      ElementM(ir,0,nvars*i+j)=ElementM(Y_t,i,j);

  if (B)
    {
      InitializeMatrix(X_t=CreateMatrix(nvars,RowM(B[0])),0.0);
      for (t=1; t < horizon; t++)
	{
	  for (i=nvars-1; i >= 0; i--)
	    {
	      for (j=RowM(B[0])-1; j >= nvars; j--) ElementM(X_t,i,j)=ElementM(X_t,i,j-nvars);
	      for (j=nvars-1; j >= 0; j--) ElementM(X_t,i,j)=ElementM(Y_t,i,j);
	    }
	  ProductMM(Y_t,X_t,B[S[t]]);
	  for (i=nvars-1; i >= 0; i--)
	    for (j=nvars-1; j >= 0; j--)
	      ElementM(ir,t,nvars*i+j)=ElementM(Y_t,i,j);
	}
      FreeMatrix(X_t);
    }
  else
    for (t=horizon-1; t > 0; t--)
      for (j=ColM(ir)-1; j >= 0; j--) 
	ElementM(ir,t,j)=0.0;

  FreeMatrix(Y_t);
  FreeMatrix(epsilon_t);
}


/*
   Computes the matrices A0(s)*Xi(s) and B(s) = Ahat(s) * inverse(A0(s))
   where Ahat(s) are the first nvars*nlags rows of Aplus(s), for 0 <= s < h.
   The integer h is the number of regimes.  Both A0_Xi and B must be matrix
   arrays of length h and each element of A0_Xi and B must be of the proper
   size.
*/
static void GetIRMatrices(int h, TMatrix *A0_Xi, TMatrix *B, T_VAR_Parameters *p)
{
  TMatrix Aplus;
  int i, j, k;
  PRECISION tmp;
  for (k=h-1; k >= 0; k--)
    {
      MakeA0(A0_Xi[k],k,p);
      Aplus=MakeAplus((TMatrix)NULL,k,p);
      SubMatrix(B[k],Aplus,0,0,p->nvars*p->nlags,p->nvars);
      FreeMatrix(Aplus);
      ProductInverseMM(B[k],B[k],A0_Xi[k]);
      for (j=p->nvars-1; j >= 0; j--)
	for (tmp=sqrt(p->Zeta[j][p->var_states[j][k]]), i=p->nvars-1; i >= 0; i--)
	  ElementM(A0_Xi[k],i,j)*=tmp;
    }
}

/*
   Returns the largest of the absolute values of the eigenvalues of the companion
    matrix of B
*/
PRECISION LargestRoot(TMatrix B)
{
  TMatrix X;
  TVector re_eig, im_eig;
  int i, k=RowM(B), n=ColM(B);
  PRECISION max, tmp;
  InitializeMatrix(X=CreateMatrix(k,k),0.0);
  for (i=n; i < k; i++) ElementM(X,i-n,i)=1.0;
  InsertSubMatrix(X,B,0,0,0,0,k,n);
  re_eig=CreateVector(k);
  im_eig=CreateVector(k);
  Eigenvalues(re_eig,im_eig,X);
  max=ElementV(re_eig,0)*ElementV(re_eig,0)+ElementV(im_eig,0)*ElementV(im_eig,0);
  for (i=k-1; i > 0; i--)
    if ((tmp=ElementV(re_eig,i)*ElementV(re_eig,i)+ElementV(im_eig,i)*ElementV(im_eig,i)) > max) max=tmp;;
  FreeVector(im_eig);
  FreeVector(re_eig);
  FreeMatrix(X);
  return sqrt(max);
}

/*
   Returns 1 if any of the squares of the eigenvalues of the companion matrix of 
   B are greater than max.
*/
int IsExplosive(TMatrix B, PRECISION max)
{
  TMatrix X;
  TVector re_eig, im_eig;
  int i, k=RowM(B), n=ColM(B);
  InitializeMatrix(X=CreateMatrix(k,k),0.0);
  for (i=n; i < k; i++) ElementM(X,i-n,i)=1.0;
  InsertSubMatrix(X,B,0,0,0,0,k,n);
  re_eig=CreateVector(k);
  im_eig=CreateVector(k);
  Eigenvalues(re_eig,im_eig,X);
  for (i=k-1; i >= 0; i--)
    if (ElementV(re_eig,i)*ElementV(re_eig,i)+ElementV(im_eig,i)*ElementV(im_eig,i) > max) break;
  FreeVector(im_eig);
  FreeVector(re_eig);
  FreeMatrix(X);
  return (i < 0) ? 0 : 1;
}

/*
   Creates the matrix F if necessary and fills it with the given percentile
   computed from the matrix histogram.  IR must be sorted and percentile must 
   be between 0 and 1, inclusive.
*/
static TMatrix IRPercentile(TMatrix F, PRECISION percentile, TVector **IR, TStateModel *model)
{
  T_VAR_Parameters *p=(T_VAR_Parameters*)(model->theta);
  int i, j, k, n=DimV(IR[0][0])-1, horizon=dw_DimA(IR);
  PRECISION a, b;
  if (!F)
    {
      if (!(F=CreateMatrix(horizon,p->nvars*p->nvars))) return (TMatrix)NULL;
    }
  else
    if ((RowM(F) != horizon) || (ColM(F) != p->nvars*p->nvars))
      {
	dw_Error(SIZE_ERR);
	return (TMatrix)NULL;
      }
  percentile*=n;
  k=(int)floor(percentile);
  b=percentile - k;
  a=1.0-b;
  if (k < n)
    for (i=RowM(F)-1; i >= 0; i--)
      for (j=ColM(F)-1; j >= 0; j--)
	ElementM(F,i,j)=a*ElementV(IR[i][j],k)+b*ElementV(IR[i][j],k+1);
  else
    for (i=RowM(F)-1; i >= 0; i--)
      for (j=ColM(F)-1; j >= 0; j--)
	ElementM(F,i,j)=ElementV(IR[i][j],k);
  return F;
}

static void SortIR(TVector **IR)
{
  int n=dw_DimA(IR), m=dw_DimA(IR[0]), i, j;
  for(i=n-1; i >= 0; i--)
    for (j=m-1; j >= 0; j--)
      {
	//printf("Sorting irf(%d,%d)\n",i,j);
        SortVectorAscending(IR[i][j],IR[i][j]);
      }
}

/*
   Assumes
    draws : number of draws of the regime path to make for each posterior draw
    posterior_file : FILE pointer to file containing posterior draws.  If null, 
                     current parameters are used.
    thin : thinning factor to use if posterior_file is not null.
    horizon : non-negative integer
    ergodic : if set, uses the ergodic distribution to draw the initial regime, 
              otherwise uses the filtered probabilities at time nobs.
    model : point to valid TStateModel structure
    flag : determines the type of posterior draws file passed.

   Results:
    Creates matrix histogram containing the impulse responses.

   Returns:
    Pointer to matrix histogram upon success and null pointer on failure.

   Notes:
     The element in position (k,i+j*nvars) of ir is the response of the ith 
     variable to the jth shock at horizon k.  Horizon 0 is the contemporaneous 
     response.
*/
TVector** impulse_response_percentile_ergodic_full(int draws, FILE *posterior_file, int nposterior_draws, int thin, int ergodic, int horizon, TStateModel *model, int flag)
{
  T_VAR_Parameters *p;
  int done=0, *S, i, j, k, m, n=1000, r, T=model->nobs, K;
  TMatrix ir, *A0_Xi, *B;
  TVector init_prob, prob, **IR;

 // quick check of passed parameters
  if ((nposterior_draws <= 0) || (horizon <= 0) || !model) return 0;

  p=(T_VAR_Parameters*)(model->theta);
  K=draws*((nposterior_draws - 1)/thin + 1);

  // allocate memory
  S=(int*)dw_malloc(horizon*sizeof(int));
  ir=CreateMatrix(horizon,p->nvars*p->nvars);
  IR=dw_CreateRectangularArray_vector(horizon,p->nvars*p->nvars);
  for (i=horizon-1; i >= 0; i--)
    for (j=p->nvars*p->nvars-1; j >= 0; j--)
      IR[i][j]=CreateVector(K);
  A0_Xi=dw_CreateArray_matrix(model->sv->nstates);
  B=dw_CreateArray_matrix(model->sv->nstates);
  for (i=model->sv->nstates-1; i >= 0; i--)
    {
      A0_Xi[i]=CreateMatrix(p->nvars,p->nvars);
      B[i]=CreateMatrix(p->nvars*p->nlags,p->nvars);
    }
  init_prob=CreateVector(p->nstates);
  prob=CreateVector(p->nstates);

  k=0;
  while (!done)
    {
      // Read parameters and push them into model
      if (!posterior_file)
	done=1;
      else
	{
#ifdef OCTAVE_MEX_FILE
      OCTAVE_QUIT;
#elif defined(MATLAB_MEX_FILE)
      if (utIsInterruptPending())
        {
          mexPrintf("\n\n** Ctrl-C detected, quitting...\n");
          dw_exit(0);
        }
#endif
	  dw_NextLine(posterior_file,thin-1);
	  if ((k >= K) || !GetPosteriorDraw(posterior_file,model,flag))
	    {
	      done=2;
	      printf("total posterior/regime draws processed - %d\n",k);
	    }
	  else
	    if (k == n)
	      {
		printf("%d posterior/regime draws processed\n",k);
		n+=1000;
	      }
	}

      if (done != 2)
	{
	  // Compute A0_Xi and B
	  GetIRMatrices(model->sv->nstates,A0_Xi,B,p);

	  // Use ergodic initial probability or filtered probability at time T
	  if (ergodic)
	    Ergodic(init_prob,model->sv->Q);
	  else
	    for (j=p->nstates-1; j >= 0; j--)
	      ElementV(init_prob,j)=ProbabilityStateConditionalCurrent(j,T,model);

	  for (r=draws; r > 0; r--)
	    {
	      // Draw time T regime
	      m=DrawDiscrete(init_prob);
              
	      // Draw regimes from time T+1 through T+h inclusive
	      for (j=0; j < horizon; j++)
		{
		  ColumnVector(prob,model->sv->Q,m);
		  S[j]=m=DrawDiscrete(prob);
		}

	      // Compute impulse response
	      impulse_response(ir,S,A0_Xi[S[0]],B);

	      // Accumulate impulse response
	      for (i=horizon-1; i >= 0; i--)
		for (j=p->nvars*p->nvars-1; j >= 0; j--)
		  ElementV(IR[i][j],k)=ElementM(ir,i,j);
	      k++;
	    }
	}
    }

  FreeMatrix(ir);
  dw_free(S);
  dw_FreeArray(A0_Xi);
  dw_FreeArray(B);
  FreeVector(prob);
  FreeVector(init_prob);

  return IR;
}

/*
   Assumes
    draws : number of draws of the regime path to make for each posterior draw
    posterior_file : FILE pointer to file containing posterior draws.  If null, 
                     current parameters are used.
    thin : thinning factor to use if posterior_file is not null.
    horizon : non-negative integer
    ergodic : if set, uses the ergodic distribution to draw the initial regime, 
              otherwise uses the filtered probabilities at time nobs.
    model : point to valid TStateModel structure
    flag : determines the type of posterior draws file passed.

   Results:
    Creates matrix histogram containing the impulse responses.

   Returns:
    Pointer to matrix histogram upon success and null pointer on failure.

   Notes:
     The element in position (k,i+j*nvars) of ir is the response of the ith 
     variable to the jth shock at horizon k.  Horizon 0 is the contemporaneous 
     response.
*/
TMatrixHistogram* impulse_response_percentile_ergodic(int draws, FILE *posterior_file, int thin, int ergodic, int horizon, TStateModel *model, int flag)
{
  T_VAR_Parameters *p;
  int done=0, *S, i, j, k, m, n=1000, T=model->nobs;
  TMatrix ir, *A0_Xi, *B;
  TMatrixHistogram *histogram;
  TVector init_prob, prob;

 // quick check of passed parameters
  if ((horizon <= 0) || !model) return 0;

  p=(T_VAR_Parameters*)(model->theta);

  // allocate memory
  S=(int*)dw_malloc(horizon*sizeof(int));
  ir=CreateMatrix(horizon,p->nvars*p->nvars);
  histogram=CreateMatrixHistogram(horizon,p->nvars*p->nvars,100,HISTOGRAM_VARIABLE);
  A0_Xi=dw_CreateArray_matrix(model->sv->nstates);
  B=dw_CreateArray_matrix(model->sv->nstates);
  for (i=model->sv->nstates-1; i >= 0; i--)
    {
      A0_Xi[i]=CreateMatrix(p->nvars,p->nvars);
      B[i]=CreateMatrix(p->nvars*p->nlags,p->nvars);
    }
  init_prob=CreateVector(p->nstates);
  prob=CreateVector(p->nstates);

  i=0;
  while (!done)
    {
      // Read parameters and push them into model
      if (!posterior_file)
	done=1;
      else
	{
	  dw_NextLine(posterior_file,thin-1);
	  if (!GetPosteriorDraw(posterior_file,model,flag))
	    {
	      done=2;
	      printf("total posterior draws processed - %d\n",i);
	    }
	  else
	    if (i++ == n)
	      {
		printf("%d posterior draws processed\n",i);
		n+=1000;
	      }
	}

      if (done != 2)
	{
	  // Compute A0_Xi and B
	  GetIRMatrices(model->sv->nstates,A0_Xi,B,p);

	  // Use ergodic initial probability or filtered probability at time T
	  if (ergodic)
	    Ergodic(init_prob,model->sv->Q);
	  else
	    for (j=p->nstates-1; j >= 0; j--)
	      ElementV(init_prob,j)=ProbabilityStateConditionalCurrent(j,T,model);

	  for (k=draws; k > 0; k--)
	    {
	      // Draw time T regime
	      m=DrawDiscrete(init_prob);
              
	      // Draw regimes from time T+1 through T+h inclusive
	      for (j=0; j < horizon; j++)
		{
		  ColumnVector(prob,model->sv->Q,m);
		  S[j]=m=DrawDiscrete(prob);
		}

	      // Compute impulse response
	      impulse_response(ir,S,A0_Xi[S[0]],B);

	      // Accumulate impulse response
	      AddMatrixObservation(ir,histogram);
	    }
	}
    }

  FreeMatrix(ir);
  dw_free(S);
  dw_FreeArray(A0_Xi);
  dw_FreeArray(B);
  FreeVector(prob);
  FreeVector(init_prob);

  return histogram;
}

/*
   Assumes
    posterior_file : FILE pointer to file containing posterior draws.  If null, 
                     current parameters are used.
    thin : thinning factor to use if posterior_file is not null.
    s : fixed regime
    horizon : non-negative integer
    model : point to valid TStateModel structure
    flag : determines the type of posterior draws file passed.

   Results:
    Creates matrix histogram containing the impulse responses.

   Returns:
    Pointer to matrix histogram upon success and null pointer on failure.

   Notes:
     The element in position (k,i+j*nvars) of ir is the response of the ith 
     variable to the jth shock at horizon k.  Horizon 0 is the contemporaneous 
     response.
*/
TVector** impulse_response_percentile_regime_full(FILE *posterior_file, int nposterior_draws, int thin, int s, int horizon, TStateModel *model, int flag)
{
  T_VAR_Parameters *p;
  int done=0, *S, i, j, k, n=1000, K;
  TMatrix ir, *A0_Xi, *B;
  TVector **IR;

 // quick check of passed parameters
  if ((nposterior_draws <= 0) || (horizon <= 0) || !model) return 0;

  p=(T_VAR_Parameters*)(model->theta);
  K=(nposterior_draws - 1)/thin + 1;

  // allocate memory
  S=(int*)dw_malloc(horizon*sizeof(int));
  for (i=0; i < horizon; i++) S[i]=s;
  ir=CreateMatrix(horizon,p->nvars*p->nvars);
  IR=dw_CreateRectangularArray_vector(horizon,p->nvars*p->nvars);
  for (i=horizon-1; i >= 0; i--)
    for (j=p->nvars*p->nvars-1; j >= 0; j--)
      IR[i][j]=CreateVector(K);
  A0_Xi=dw_CreateArray_matrix(model->sv->nstates);
  B=dw_CreateArray_matrix(model->sv->nstates);
  for (i=model->sv->nstates-1; i >= 0; i--)
    {
      A0_Xi[i]=CreateMatrix(p->nvars,p->nvars);
      B[i]=CreateMatrix(p->nvars*p->nlags,p->nvars);
    }

  k=0;
  while (!done)
    {
      // Read parameters and push them into model
      if (!posterior_file)
	done=1;
      else
	{
	  if ((k >= K) || !GetPosteriorDraw(posterior_file,model,flag))
	    {
	      done=2;
	      printf("total posterior draws processed - %d\n",k);
	    }
	  else
	    {
	      dw_NextLine(posterior_file,thin-1);
	      if (k == n)
		{
		  printf("%d posterior draws processed\n",k);
		  n+=1000;
		}
	    }
	}

      if (done != 2)
	{
	  // Compute A0_Xi and B
	  GetIRMatrices(model->sv->nstates,A0_Xi,B,p);

	  // Compute impulse response
	  impulse_response(ir,S,A0_Xi[s],B);

	  // Accumulate impulse response
	  for (i=horizon-1; i >= 0; i--)
	    for (j=p->nvars*p->nvars-1; j >= 0; j--)
	      ElementV(IR[i][j],k)=ElementM(ir,i,j);
	  k++;
	}
    }

  FreeMatrix(ir);
  dw_free(S);
  dw_FreeArray(A0_Xi);
  dw_FreeArray(B);

  return IR;
}

#ifdef ECB_VERSION
/*
   Normalization for ECB.  Works for three cases.
     (1) One Markov process controlling coefficients
     (2) One Markov process controlling variances
     (3) Two Markov processes, one controlling variances and the other 
         controlling coefficents

     If the coefficients are time varing, then its controlling process must have
     two regimes.
     

   Assumes
     N - integer array of length model->sv->nstates
     model - valid SBVAR TStateModel

   Results
     N[i] for 0 <= i < model->sv->nstates is the index of the un-normalized 
     regime given that the normalized regime index is i.
   
*/
static int DATA_FIRST=-1;
static int DATA_LAST=-1;
static int COEF_PROCESS=-1;
static int VAR_PROCESS=-1;
void sbvar_normalize_regimes_ecb_set_globals(int nargs, char **args, TStateModel *model)
{
  COEF_PROCESS=dw_ParseInteger_String(nargs,args,"ecb_coef_process",0)-1;
  VAR_PROCESS=dw_ParseInteger_String(nargs,args,"ecb_var_process",0)-1;
  if (VAR_PROCESS < 0)
    {
      if (COEF_PROCESS < 0)
	{
	  printf("Neither coef nor var process specified\n");
	  dw_exit(0);
	}
      if (model->sv->n_state_variables != 0)
	{
	  printf("Only coef process specified but more than one Markov processes\n");
	  dw_exit(0);
	}
      if (COEF_PROCESS != 0)
	{
	  printf("coef process specified to be %d, but only one Markov process\n",COEF_PROCESS+1);
	  dw_exit(0);
	}
    }
  else
    {
      if (COEF_PROCESS < 0)
	{
	  if (model->sv->n_state_variables != 0)
	    {
	      printf("Only var process specified but more than one Markov processes\n");
	      dw_exit(0);
	    }
	  if (VAR_PROCESS != 0)
	    {
	      printf("var process specified to be %d, but only one Markov process\n",VAR_PROCESS+1);
	      dw_exit(0);
	    }
	}
      else
	{
	  if (model->sv->n_state_variables != 2)
	    {
	      printf("Both coef and var process specified but there are not two Markov processes\n");
	      dw_exit(0);
	    }
	  if (COEF_PROCESS == VAR_PROCESS) 
	    {
	      printf("Same Markov process cannot control both coef and var\n");
	      dw_exit(0);
	    }
	  if ((COEF_PROCESS > 1) || (VAR_PROCESS > 1))
	    {
	      printf("Either coef or var process greater than two\n");
	      dw_exit(0);
	    }
	}
    }

  if (COEF_PROCESS >= 0)
    {
      DATA_FIRST=dw_ParseInteger_String(nargs,args,"ecb_coef_start",0);
      DATA_LAST=dw_ParseInteger_String(nargs,args,"ecb_coef_end",0);
      if ((DATA_FIRST <= 0) || (DATA_LAST > model->nobs) || (DATA_FIRST > DATA_LAST))
	{
	  printf("Error in specifying ecb_coef_start and/or ecb_coef_end\n");
	  dw_exit(0);
	}
    }
}
/*

*/
static int normalized_coef=0;
static int normalized_var=0;
void sbvar_normalize_regimes_ecb(int *N, TStateModel *model)
{
  T_VAR_Parameters *p=(T_VAR_Parameters*)(model->theta);
  int i, j, k, t, *var_idx=(int*)NULL, *coef_idx=(int*)NULL, var_regimes, coef_regimes, var_m, coef_m, var_change=0, coef_change=0;
  PRECISION *x;

  var_regimes=(VAR_PROCESS < 0) ? 1 : ((model->sv->n_state_variables == 0) ? model->sv->nstates : model->sv->state_variable[VAR_PROCESS]->nstates);
  coef_regimes=(COEF_PROCESS < 0) ? 1 : ((model->sv->n_state_variables == 0) ? model->sv->nstates : model->sv->state_variable[COEF_PROCESS]->nstates);

  var_m=(VAR_PROCESS == 0) ? coef_regimes : 1;
  coef_m=(COEF_PROCESS == 0) ? var_regimes : 1;

  if (VAR_PROCESS >= 0)
    {
      var_idx=dw_malloc(var_regimes*sizeof(PRECISION));
      x=(PRECISION*)dw_malloc(var_regimes*sizeof(PRECISION));

      // compute traces
      for (i=var_regimes-1; i >= 0; i--)
	for (x[i]=0.0, j=p->nvars-1; j >= 0; j--) 
	  x[i]+=sqrt(p->Zeta[j][p->var_states[j][i*var_m]]);

      // order traces
      for (i=0; i < var_regimes; i++) var_idx[i]=i;
      for (i=0; i < var_regimes; i++)
	{
	  for (k=i, j=i+1; j < var_regimes; j++)
	    if (x[var_idx[k]] < x[var_idx[j]]) k=j;
	  if (k != i)
	    {
	      j=var_idx[k];
	      var_idx[k]=var_idx[i];
	      var_idx[i]=j;
	      var_change=1;
	    }
	}

      dw_free(x);
    }

  if (COEF_PROCESS >= 0)
    {
      coef_idx=dw_malloc(var_regimes*sizeof(PRECISION));
      x=(PRECISION*)dw_malloc(var_regimes*sizeof(PRECISION));

      // compute average smoothed probabilities
      ComputeSmoothedProbabilities(model);
      for (i=coef_regimes-1; i >= 0; i--) 
	for (x[i]=0.0, t=DATA_FIRST; t <= DATA_LAST; t++)
	  for (j=0; j < var_regimes; j++)
	    x[i]+=ElementV(model->SP[t],i*coef_m+j*var_m);

      // order probabilities
      for (i=0; i < coef_regimes; i++) coef_idx[i]=i;
      for (i=0; i < coef_regimes; i++)
	{
	  for (k=i, j=i+1; j < coef_regimes; j++)
	    if (x[coef_idx[k]] < x[coef_idx[j]]) k=j;
	  if (k != i)
	    {
	      j=coef_idx[k];
	      coef_idx[k]=coef_idx[i];
	      coef_idx[i]=j;
	      coef_change=1;
	    }
	}

      dw_free(x);
    }

  if (var_change) normalized_var++;
  if (coef_change) normalized_coef++;

  if (VAR_PROCESS  < 0)
    { if (COEF_PROCESS >= 0) memcpy(N,coef_idx,model->sv->nstates*sizeof(int)); }
  else
    if (COEF_PROCESS < 0)
      memcpy(N,var_idx,model->sv->nstates*sizeof(int));
    else
      for (i=0; i < var_regimes; i++)
	for (j=0; j < coef_regimes; j++)
	  N[i*var_m+j*coef_m]=var_idx[i]*var_m+coef_idx[j]*coef_m;

  //================== Test Normalization =======================
  /* static int iter=0; */
  /* TMatrix Zeta=(TMatrix)NULL; */
  /* PRECISION sum; */

  /* iter++; */
  /* for (i=0; i < model->sv->nstates; i++) */
  /*   if (N[i] != i) break; */

  /* //if (i < model->sv->nstates) */
  /* { */
  /*   printf("iter: %d\n",iter); */

  /*   for (i=0; i < model->sv->nstates; i++) */
  /*     printf("%d ",N[i]); */
  /*   printf("\n"); */

  /*   printf("var: "); */
  /*   for (i=0; i < var_regimes; i++) printf("%d ",var_idx[i]); */
  /*   printf("\n"); */

  /*   printf("coef: "); */
  /*   for (i=0; i < coef_regimes; i++) printf("%d ",coef_idx[i]); */
  /*   printf("\n"); */

  /*   printf("var_m: %d  coef_m: %d\n",var_m,coef_m); */

  /*   for (i=0; i < model->sv->nstates; i++) */
  /*     { */
  /* 	printf("i = %d = (%d,%d)    N[i] = %d = (%d,%d)\n",i,model->sv->index[i][0],model->sv->index[i][1],N[i],model->sv->index[N[i]][0],model->sv->index[N[i]][1]); */
  /* 	Zeta=MakeZeta(Zeta,N[i],p); */
  /* 	for (sum=0.0, j=0; j < p->nvars; sum+=sqrt(ElementM(Zeta,j,j)), j++) */
  /* 	  printf("%lf ",sqrt(ElementM(Zeta,j,j))); */
  /* 	printf("\ntrace = %lf\n",sum); */
  /*     } */

  /*   printf("smoothed probabilities\n"); */
  /*   //for (t=DATA_FIRST; t <= DATA_LAST; t++) */
  /*   for (t=1; t <= p->nobs; t++) */
  /*     { */
  /* 	printf("t = %d : ",t); */
  /* 	for (i=0; i < model->sv->nstates; i++) */
  /* 	  printf("%lf  ",ElementV(model->SP[t],N[i])); */
  /* 	printf("\n"); */
  /*     } */

  /*   getchar(); */
  /* } */
  //=============================================================

  if (coef_idx) dw_free(coef_idx);
  if (var_idx) dw_free(var_idx);
}

/*
   Assumes
    posterior_file : FILE pointer to file containing posterior draws.  If null, 
                     current parameters are used.
    thin : thinning factor to use if posterior_file is not null.
    s : fixed regime
    horizon : non-negative integer
    model : point to valid TStateModel structure
    flag : determines the type of posterior draws file passed.

   Results:
    Creates matrix histogram containing the impulse responses.

   Returns:
    Pointer to matrix histogram upon success and null pointer on failure.

   Notes:
     The element in position (k,i+j*nvars) of ir is the response of the ith 
     variable to the jth shock at horizon k.  Horizon 0 is the contemporaneous 
     response.
*/
TVector** impulse_response_percentile_regime_full_normalized(FILE *posterior_file, int nposterior_draws, int thin, int s, int horizon, PRECISION explosive_cutoff, TStateModel *model, int flag)
{
  T_VAR_Parameters *p;
  int done=0, *S, i, j, k=0, n=1000, m=0, *N, normalized_wz=0, explosive=0, K;
  TMatrix ir, *A0_Xi, *B;
  TVector **IR, tmp;
  PRECISION max_root=0.0, min_root=PLUS_INFINITY, root;

 // quick check of passed parameters
  if ((nposterior_draws <= 0) || (horizon <= 0) || !model) return 0;

  p=(T_VAR_Parameters*)(model->theta);
  K=(nposterior_draws - 1)/thin + 1;

  // allocate memory
  N=(int*)dw_malloc(model->sv->nstates*sizeof(int));
  S=(int*)dw_malloc(horizon*sizeof(int));
  ir=CreateMatrix(horizon,p->nvars*p->nvars);
  IR=dw_CreateRectangularArray_vector(horizon,p->nvars*p->nvars);
  for (i=horizon-1; i >= 0; i--)
    for (j=p->nvars*p->nvars-1; j >= 0; j--)
      IR[i][j]=CreateVector(K);
  A0_Xi=dw_CreateArray_matrix(model->sv->nstates);
  B=dw_CreateArray_matrix(model->sv->nstates);
  for (i=model->sv->nstates-1; i >= 0; i--)
    {
      A0_Xi[i]=CreateMatrix(p->nvars,p->nvars);
      B[i]=CreateMatrix(p->nvars*p->nlags,p->nvars);
    }

  normalized_var=normalized_coef=0;
  while (!done)
    {
      // Read parameters and push them into model
      if (!posterior_file)
	done=1;
      else
	{
	  if ((m >= K) || !GetPosteriorDraw(posterior_file,model,flag))
	    {
	      done=2;
	      printf("total posterior draws processed - %d\n",m);
	    }
	  else
	    {
	      dw_NextLine(posterior_file,thin-1);
	      if (m == n)
		{
		  printf("%d posterior draws processed (explosive %d)\n",m,explosive);
		  n+=1000;
		}
	    }
	}

      if (done != 2)
	{
	  m++;

	  // Normalize sbvar
	  normalized_wz+=Normalize_VAR(model,(PRECISION*)NULL);

	  // Compute A0_Xi and B
	  GetIRMatrices(model->sv->nstates,A0_Xi,B,p);

	  // Get Normalization
#ifdef ECB_VERSION
	  sbvar_normalize_regimes_ecb(N,model);
#endif
	  for (i=0; i < horizon; i++) S[i]=N[s];

	  // all the same?
	  //if ((N[0] != 2) || (N[1] != 3) || (N[2] != 4) || (N[3] != 5) || (N[4] != 0) || (N[5] != 1)) { for (i=0; i < model->sv->nstates; i++) printf("%d ",N[i]); getchar();}

	  // Explosive?
	  root=(explosive_cutoff < PLUS_INFINITY) ? LargestRoot(B[N[s]]) : 0.0;
	  if (root > max_root) max_root=root;
	  if (root < min_root) min_root=root;
	  if (root > explosive_cutoff)
	    {
	      explosive++;
	      /* dw_PrintMatrix(stdout,B[N[s]],"%lf "); */
	      /* printf("\nroot = %lf\n",sqrt(root)); */
	      /* getchar(); */
	    }
	  else
	    {
	      // Compute impulse response
	      impulse_response(ir,S,A0_Xi[N[s]],B);

	      // Accumulate impulse response
	      for (i=horizon-1; i >= 0; i--)
		for (j=p->nvars*p->nvars-1; j >= 0; j--)
		  ElementV(IR[i][j],k)=ElementM(ir,i,j);
	      k++;
	    }
	}
    }

  if (k == 0)
    {
      dw_FreeArray(IR);
      IR=(TVector**)NULL;
    }
  else
    if (k < K)
      for (i=horizon-1; i >= 0; i--)
	for (j=p->nvars*p->nvars-1; j >= 0; j--)
	  {
	    tmp=CreateVector(k);
	    memcpy(pElementV(tmp),pElementV(IR[i][j]),k*sizeof(PRECISION));
	    FreeVector(IR[i][j]);
	    IR[i][j]=tmp;
	  }

  printf("Number variance state normalizations: %d out of %d\n",normalized_var,m);
  printf("Number coefficient regime normalizations: %d out of %d\n",normalized_coef,m);
  printf("Number Waggoner/Zha normalizations: %d out of %d\n",normalized_wz,m);
  printf("Number explosive parameterizations: %d out of %d\n",explosive,m);
  printf("Maximum root: %lf\n",max_root);
  printf("Minimum root: %lf\n",min_root);

  FreeMatrix(ir);
  dw_free(S);
  dw_free(N);
  dw_FreeArray(A0_Xi);
  dw_FreeArray(B);

  return IR;
}
#endif  // ECB_VERSION


/*
   Assumes
    posterior_file : FILE pointer to file containing posterior draws.  If null, 
                     current parameters are used.
    thin : thinning factor to use if posterior_file is not null.
    s : fixed regime
    horizon : non-negative integer
    model : point to valid TStateModel structure
    flag : determines the type of posterior draws file passed.

   Results:
    Creates matrix histogram containing the impulse responses.

   Returns:
    Pointer to matrix histogram upon success and null pointer on failure.

   Notes:
     The element in position (k,i+j*nvars) of ir is the response of the ith 
     variable to the jth shock at horizon k.  Horizon 0 is the contemporaneous 
     response.
*/
TMatrixHistogram* impulse_response_percentile_regime(FILE *posterior_file, TVector *posterior_sample, PRECISION cut, int thin, int s, int horizon, TStateModel *model, int flag)
{
  T_VAR_Parameters *p;
  int done=0, *S, i, j, k, n=1000, nt;
  TMatrix ir, *A0_Xi, *B, min, max;
  TVector **IR;
  TMatrixHistogram *histogram;

  // Quick check of passed parameters
  if ((horizon <= 0) || (thin <= 0) || (s < 0) || (s >= model->sv->nstates) || !posterior_sample || !model) return 0;

  p=(T_VAR_Parameters*)(model->theta);
  nt=NumberFreeParametersTheta(model);

  // allocate local memory
  histogram=CreateMatrixHistogram(horizon,p->nvars*p->nvars,500,HISTOGRAM_FIXED);
  S=(int*)dw_malloc(horizon*sizeof(int));
  for (i=0; i < horizon; i++) S[i]=s;
  ir=CreateMatrix(horizon,p->nvars*p->nvars);
  A0_Xi=dw_CreateArray_matrix(model->sv->nstates);
  B=dw_CreateArray_matrix(model->sv->nstates);
  for (i=model->sv->nstates-1; i >= 0; i--)
    {
      A0_Xi[i]=CreateMatrix(p->nvars,p->nvars);
      B[i]=CreateMatrix(p->nvars*p->nlags,p->nvars);
    }

  // Compute histogram bounds
  IR=dw_CreateRectangularArray_vector(horizon,p->nvars*p->nvars);
  for (i=horizon-1; i >= 0; i--)
    for (j=p->nvars*p->nvars-1; j >= 0; j--)
      IR[i][j]=CreateVector(dw_DimA(posterior_sample));
  for (k=dw_DimA(posterior_sample)-1; k >= 0; k--)
    {
      // Push parameters into model
      ConvertFreeParametersToTheta(model,pElementV(posterior_sample[k])+2);
      ConvertFreeParametersToQ(model,pElementV(posterior_sample[k])+2+nt);

      // Compute A0_Xi and B
      GetIRMatrices(model->sv->nstates,A0_Xi,B,p);

      // Compute impulse response
      impulse_response(ir,S,A0_Xi[s],B);

      // Accumulate impulse response
      for (i=horizon-1; i >= 0; i--)
	for (j=p->nvars*p->nvars-1; j >= 0; j--)
	  ElementV(IR[i][j],k)=ElementM(ir,i,j);
    }
  SortIR(IR);
  min=IRPercentile((TMatrix)NULL,cut,IR,model);
  max=IRPercentile((TMatrix)NULL,1.0-cut,IR,model);
  SetMaxMinMatrixHistogram(min,max,histogram);
  FreeMatrix(max);
  FreeMatrix(min);
  dw_FreeArray(IR);

  i=0;
  while (!done)
    {
      // Read parameters and push them into model
      if (!posterior_file)
	done=1;
      else
	if (!GetPosteriorDraw(posterior_file,model,flag))
	  {
	    done=2;
	    printf("total posterior draws processed - %d\n",i);
	  }
	else
	  {
	    dw_NextLine(posterior_file,thin-1);
	    if (i == n)
	      {
		printf("%d posterior draws processed\n",i);
		n+=1000;
	      }
	    i++;
	  }

      if (done != 2)
	{
	  // Compute A0_Xi and B
	  GetIRMatrices(model->sv->nstates,A0_Xi,B,p);

	  // Compute impulse response
	  impulse_response(ir,S,A0_Xi[s],B);

	  // Accumulate impulse response
	  AddMatrixObservation(ir,histogram);
	}
    }

  FreeMatrix(ir);
  dw_free(S);
  dw_FreeArray(A0_Xi);
  dw_FreeArray(B);

  return histogram;
}


/*
  Additional command line parameters

   -horizon <integer>
      If this argument exists, then the forecast horizon is given by the passed 
      integer.  The default value is 12.

   -filtered
      Uses filtered probabilities at the end of the sample as initial conditions 
      for regime probabilities.  The default behavior is to us the erogdic 
      distribution for the initial conditions.  This flag only applies if neither 
      -regimes nor -regime is specified. 

   -error_bands 
      Output error bands.  (default = off - only median is computed)

   -percentiles n p_1 p_2 ... p_n
      Percentiles to compute. The first parameter after percentiles must be the 
      number of percentiles and the following values are the actual percentiles. 
      default = 3  0.16  0.50  0.84   if error_bands flag is set
              = 1  0.50               otherwise

   -parameter_uncertainty 
      Apply parameter uncertainty when computing error bands or median.

   -shocks_per_parameter <integer> 
      Number of regime paths to draw for each parameter draw.  The default value 
      is 1 if parameter_uncertainty is set and 10,000 otherwise.
     
   -thin 
      Thinning factor.  Only 1/thin of the draws in posterior draws file are 
      used. The default value is 1.

   -regimes 
      Produces forecasts as if each regime were permanent. (default = off)

   -regime <integer>
      Produces forecasts as if regime were permanent.  Regime numbers are zero
      based.  (default = off)

   -flat
      Assumes that posterior draws is a flat file format.  The default is that 
      the posterior draws are in a free file format.  

*/
void dw_sbvar_impulse_response_command_line(int nargs, char **args)
{
  char *post=(char*)NULL, *out_filename, *fmt="%%sir_percentiles_regime_%d_%%s.out", *buffer;
  TStateModel *model;
  T_VAR_Parameters *p;
  TVector percentiles=(TVector)NULL;
  int ergodic, type, s, horizon, thin, draws, i, j, n, T __attribute__ ((unused)), nposterior_draws;
  FILE *f_out, *posterior_file;
  //TMatrixHistogram *histogram;
  TMatrix ir;
  TVector **IR, *sample __attribute__ ((unused)) = (TVector*)NULL;
  PRECISION explosive_cutoff __attribute__ ((unused));

  TVARCommandLine *cmd=(TVARCommandLine*)NULL;

  // Setup model and initial parameters
  if (!(cmd=CreateTStateModel_VARCommandLine(nargs,args,(TVARCommandLine*)NULL)))
    dw_Error(MEM_ERR);
  else
    if (!cmd->model)
      dw_UserError("Unable to setup SBVAR from command line parameters");
    else
      if (!cmd->parameters_filename_actual)
	dw_UserError("Unable to initialize parameters from command line parameters");
      else
	{
	  model=cmd->model;
	  p=(T_VAR_Parameters*)(model->theta);

	  // Is posterior mode explosive
	  TMatrix *A0_Xi, *B;
	  A0_Xi=dw_CreateArray_matrix(model->sv->nstates);
	  B=dw_CreateArray_matrix(model->sv->nstates);
	  for (i=model->sv->nstates-1; i >= 0; i--)
	    {
	      A0_Xi[i]=CreateMatrix(p->nvars,p->nvars);
	      B[i]=CreateMatrix(p->nvars*p->nlags,p->nvars);
	    }
	  GetIRMatrices(model->sv->nstates,A0_Xi,B,p);
	  for (i=0; i < model->sv->nstates; i++)
	    printf("Largest root at posterior mode regime[%d]: %lf\n",i,LargestRoot(B[i]));

	  // setup normalization
	  Setup_WZ_Normalization_VAR(p->A0,p);

	  // horizon
	  horizon=dw_ParseInteger_String(nargs,args,"horizon",12);

	  // Output tag
	  OutTag_VARCommandLine(cmd);

	  // Type
	  type=(dw_FindArgument_String(nargs,args,"flat") >= 0) ? F_FLAT : F_FREE;

	  // Ergodic distribution for initial value of shocks
	  ergodic=(dw_FindArgument_String(nargs,args,"filtered") >= 0) ? 0 : 1;

	  // Last data point
	  T=p->nobs;

	  // discard explosive parameters
	  explosive_cutoff=dw_ParseFloating_String(nargs,args,"explosive",PLUS_INFINITY);

	  //============================= Compute impulse responses  ============================= 

	  // Parameter uncertainty
	  if (dw_FindArgument_String(nargs,args,"parameter_uncertainty") != -1)
	    {
	      // Open posterior draws file
	      post=CreateFilenameFromTag((type == F_FREE) ? "%ssimulation_%s.out" : "%sdraws_%s.out",cmd->in_tag ? cmd->in_tag : "notag",cmd->in_directory);
	      if (!(posterior_file=fopen(post,"rt")))
		{
		  dw_free(post);
		  printf("dw_sbvar_forecast command line(): Unable to open posterior draws file: %s\n",post);
		  return;
		}
	      else
		dw_free(post);

	      // get number posterior draws and sample
	      sample=RandomSamplePosterior(posterior_file,nposterior_draws=GetNumberDraws(posterior_file),1000);

	      // Get thinning factor from command line
	      thin=dw_ParseInteger_String(nargs,args,"thin",1);
	      if (thin <= 0) thin=1;

	      // Get shocks_per_parameter from command line
	      draws=dw_ParseInteger_String(nargs,args,"shocks_per_parameter",1);
	    }
	  else
	    {
	      // Using posterior estimate
	      posterior_file=(FILE*)NULL;
	      nposterior_draws=1;

	      // thinning factor not used
	      thin=1;

	      // Get shocks_per_parameter from command line
	      draws=dw_ParseInteger_String(nargs,args,"shocks_per_parameter",10000);
	    }

	  // Setup percentiles
	  if ((i=dw_FindArgument_String(nargs,args,"percentiles")) == -1)
	    if (dw_FindArgument_String(nargs,args,"error_bands") == -1)
	      {
		percentiles=CreateVector(1);
		ElementV(percentiles,0)=0.5;
	      }
	    else
	      {
		percentiles=CreateVector(3);
		ElementV(percentiles,0)=0.16; ElementV(percentiles,1)=0.5; ElementV(percentiles,2)=0.84;
	      }
	  else
	    if ((i+1 < nargs) && dw_IsInteger(args[i+1]) && ((n=atoi(args[i+1])) > 0) && (i+1+n < nargs))
	      {
		percentiles=CreateVector(n);
		for (j=0; j < n; j++)
		  if (!dw_IsFloat(args[i+2+j])|| ((ElementV(percentiles,j)=atof(args[i+2+j])) <= 0.0) || (ElementV(percentiles,j) >= 1.0)) 
		    break;
		if (j < n)
		  {
		    FreeVector(percentiles);
		    dw_UserError("sbvar_impulse_response_command_line():  Error parsing percentiles\n");
		    return;
		  }
	      }
	    else
	      {
		dw_UserError("sbvar_impulse_response_command_line():  Error parsing percentiles\n");
		return;
	      }

	  if (dw_FindArgument_String(nargs,args,"regimes") != -1)
	    for (s=0; s < p->nstates; s++)
	      {
#ifdef ECB_VERSION
		sbvar_normalize_regimes_ecb_set_globals(nargs,args,model);
#endif
		if (posterior_file) rewind(posterior_file);
		// s must not contain more than 10 digits 
		sprintf(buffer=(char*)dw_malloc(strlen(fmt) + 10),fmt,s);
		out_filename=CreateFilenameFromTag(buffer,cmd->out_tag,cmd->out_directory);
		dw_free(buffer);
		if ((f_out=fopen(out_filename,"wt")))
		  {		
		    printf("Constructing percentiles for impulse responses - regime %d\n",s);
		    //if (histogram=impulse_response_percentile_regime(posterior_file,sample,0.01,thin,s,horizon,model,type))      //
#ifdef ECB_VERSION
		    if ((IR=impulse_response_percentile_regime_full_normalized(posterior_file,nposterior_draws,thin,s,horizon,explosive_cutoff,model,type)))
#else
		    if ((IR=impulse_response_percentile_regime_full(posterior_file,nposterior_draws,thin,s,horizon,model,type)))
#endif
		      {
			SortIR(IR);                                                                                              //
			for (i=0; i < DimV(percentiles); i++)
			  //if (ir=MatrixPercentile((TMatrix)NULL,ElementV(percentiles,i),histogram))                              //
			  if ((ir=IRPercentile((TMatrix)NULL,ElementV(percentiles,i),IR,model)))                                   //
			    {
			      dw_PrintMatrix(f_out,ir,"%lg ");
			      fprintf(f_out,"\n");
			      FreeMatrix(ir);
			    }
			//FreeMatrixHistogram(histogram);                                                                          //
			dw_FreeArray(IR);                                                                                        //
		      }
		    fclose(f_out);
		  }
		dw_free(out_filename);
	      }
	  else
	    if (dw_FindArgument_String(nargs,args,"regime") != -1)
              if (((s=dw_ParseInteger_String(nargs,args,"regime",-1)) >= 0) && (s < p->nstates))
		{
#ifdef ECB_VERSION
		  sbvar_normalize_regimes_ecb_set_globals(nargs,args,model);
#endif
		  if (posterior_file) rewind(posterior_file);
		  // s must not contain more than 10 digits 
		  sprintf(buffer=(char*)dw_malloc(strlen(fmt) + 10),fmt,s);
		  out_filename=CreateFilenameFromTag(buffer,cmd->out_tag,cmd->out_directory);
		  dw_free(buffer);
		  if ((f_out=fopen(out_filename,"wt")))
		    {		
		      printf("Constructing percentiles for impulse responses - regime %d\n",s);
		      //if (histogram=impulse_response_percentile_regime(posterior_file,thin,s,horizon,model,type))                  //
#ifdef ECB_VERSION
		      if ((IR=impulse_response_percentile_regime_full_normalized(posterior_file,nposterior_draws,thin,s,horizon,explosive_cutoff,model,type)))
#else
		      if ((IR=impulse_response_percentile_regime_full(posterior_file,nposterior_draws,thin,s,horizon,model,type)))
#endif
			{
			  SortIR(IR);                                                                                              //
			  for (i=0; i < DimV(percentiles); i++)
			    //if (ir=IRHistogramToPercentile((TMatrix)NULL,horizon,ElementV(percentiles,i),histogram,model))         //
			    if ((ir=IRPercentile((TMatrix)NULL,ElementV(percentiles,i),IR,model)))                                   //
			      {
				dw_PrintMatrix(f_out,ir,"%lg ");
				fprintf(f_out,"\n");
				FreeMatrix(ir);
			      }
			  //FreeMatrixHistogram(histogram);                                                                          //
			  dw_FreeArray(IR);                                                                                        //
			}
		      fclose(f_out);
		    }
		  dw_free(out_filename);
		}
	      else
		{
		  printf("dw_sbvar_forecast command line(): regime number must be between 0 and %d inclusive\n",p->nstates-1);
		  return;
		}
	    else
	      {
		out_filename=CreateFilenameFromTag(ergodic ? "%sir_percentiles_ergodic_%s.out" : "%sir_percentiles_filtered_%s.out",
						   cmd->out_tag,cmd->out_directory);
		if ((f_out=fopen(out_filename,"wt")))
		  {
		    printf(ergodic ? "Constructing percentiles for ergodic impulse responses - %d draws of regimes per posterior value\n"
			   : "Constructing percentiles for filtered impulse responses - %d draws of regimes per posterior value\n",draws);
		    //if (histogram=impulse_response_percentile_ergodic(draws,posterior_file,thin,ergodic,horizon,model,type))                  //
		    if ((IR=impulse_response_percentile_ergodic_full(draws,posterior_file,nposterior_draws,thin,ergodic,horizon,model,type)))   //
		      {
			SortIR(IR);                                                                                                           //
			for (i=0; i < DimV(percentiles); i++)
			  //if (ir=IRHistogramToPercentile((TMatrix)NULL,horizon,ElementV(percentiles,i),histogram,model))                      //
			  if ((ir=IRPercentile((TMatrix)NULL,ElementV(percentiles,i),IR,model)))                                                // 
			    {
			      dw_PrintMatrix(f_out,ir,"%lg ");
			      fprintf(f_out,"\n");
			      FreeMatrix(ir);
			    }
			//FreeMatrixHistogram(histogram);                                                                                       //
			dw_FreeArray(IR);                                                                                                     //
		      }
		    fclose(f_out);
		  }
		dw_free(out_filename);
	      }

	  if (posterior_file) fclose(posterior_file);
	  FreeVector(percentiles);
	  //=============================================================================
	}

  Free_VARCommandLine(cmd);
}
