/*
 * 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_switchio.h"
#include "dw_metropolis_theta.h"
#include "dw_array.h"
#include "dw_matrix_array.h"
#include "dw_error.h"
#include "dw_ascii.h"
#include "dw_std.h"
#include "dw_math.h"

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

/******************************************************************************/
/************************** TStateVariable Routines ***************************/
/******************************************************************************/
/*
   Assumes:
    f        : pointer to valid FILE structure or null pointer
    filename : pointer to null terminated string or null

   Returns:
    Valid pointer to a TMarkovStateVariable structure upon success and null 
    pointer upon failure.

   Results:
    Reads Markov specification from file and creates TMarkovStateVariable 
    structure. 

   Notes:
    One of f or filename should be non-null.
*/
TMarkovStateVariable* ReadMarkovSpecification(FILE *f, char *filename)
{
  FILE *f_in=f ? f : filename ? fopen(filename,"rt") : (FILE*)NULL;
  TMarkovStateVariable *sv=(f_in) ? sv_ReadMarkovSpecification(f_in,"") : (TMarkovStateVariable*)NULL;
  if (!f && f_in) fclose(f_in);
  return sv;
}

/*
   Assumes:
    f        : pointer to valid FILE structure or null pointer
    filename : pointer to null terminated string or null
    model    : pointer to valid TStateModel structure.

   Returns:
    one upon upon success and zero upon failure.

   Results:
    Appends Markov specification to file. 

   Notes:
    One of f or filename should be non-null.
*/
int WriteMarkovSpecification(FILE *f, char *filename, TStateModel *model)
{
  FILE *f_out=f ? f : filename ? fopen(filename,"at") : (FILE*)NULL;
  int rtrn=(f_out) ? sv_WriteMarkovSpecification(f_out,model->sv,"") : 0;
  if (!f && f_out) fclose(f_out);
  return rtrn;
}

/*
   Assumes:
    f        : pointer to valid FILE structure or null pointer
    filename : pointer to null terminated string or null
    header   : pointer to null terminated string or null
    model    : pointer to valid TStateModel structure.

   Returns:
    one upon upon success and zero upon failure.

   Results:
    Reads states from file and checks to ensure that the states are valid. 

   Notes:
    One of f or filename should be non-null.
*/
int ReadStates(FILE *f, char *filename, char *header, TStateModel *model)
{
  FILE *f_in=f ? f : filename ? fopen(filename,"rt") : (FILE*)NULL;
  char *format="//== %sStates ==//";
  int err, i;

  if (!f_in)
    err=SWITCHIO_FILE_ERROR;
  else
    {
      if (!(err=ReadIntArray(f_in,format,header,model->S)))
	{
	  // Check states
	  for (i=model->nobs; i >= 0; i--)
	    if ((model->S[i] < 0) || (model->S[i] >= model->sv->nstates))
	      {
		for ( ; i >= 0; i--) model->S[i]=0;
		err=SWITCHIO_ERROR_READING_DATA;
		break;
	      }
	}
      else
	for (i=model->nobs; i >= 0; i--) model->S[i]=0;
      StatesChanged(model);
    }

  if (err) ReadError(format,header,err);

  if (!f && f_in) fclose(f_in);

  return err ? 0 : 1;
}

/*
   Assumes:
    f        : pointer to valid FILE structure or null pointer
    filename : pointer to null terminated string or null
    header   : pointer to null terminated string or null
    model    : pointer to valid TStateModel structure.

   Returns:
    one upon upon success and zero upon failure.

   Results:
    Writes states to file. 

   Notes:
    One of f or filename should be non-null.
*/
int WriteStates(FILE *f, char *filename, char *header, TStateModel *model)
{
  FILE *f_out=f ? f : filename ? fopen(filename,"at") : (FILE*)NULL;
  fprintf(f_out,"//== %sStates ==//\n",header);
  dw_PrintArray(f_out,model->S,"%d ");
  fprintf(f_out,"\n");
  if (!f && f_out) fclose(f_out);
  return 1;
}


/*
   Assumes:
    f        : pointer to valid FILE structure or null pointer
    filename : pointer to null terminated string or null
    header   : pointer to null terminated string.
    model    : pointer to valid TStateModel structure.

   Returns:
    One upon success and zero upon failure.

   Results:
    Attempts to read transition matrix parameters into model.

   Notes:
    One of f or filename should be non-null.  Calls TransitionMatricesParametersChanged().
*/
int ReadTransitionMatrixParameters(FILE *f, char *filename, char *header, TStateModel *model)
{
  FILE *f_in=f ? f : filename ? fopen(filename,"rt") : (FILE*)NULL;
  int rtrn=(f_in) ? sv_ReadTransitionMatrixParameters(f_in,model->sv,header) : 0;
  TransitionMatrixParametersChanged(model);
  if (!f && f_in) fclose(f_in);
  return rtrn;
}

/*
   Assumes:
    f        : pointer to valid FILE pointer or null pointer
    filename : pointer to null terminated string or null
    header   : pointer to null terminated string.
    model    : pointer to valid TStateModel structure.

   Returns:
    One upon success and zero upon failure.

   Results:
    Writes free transition matrix parameters

   Notes:
    One of f or filename should be non-null. 
*/
int WriteTransitionMatrixParameters(FILE *f, char *filename, char *header, TStateModel *model)
{
  FILE *f_out=f ? f : filename ? fopen(filename,"at") : (FILE*)NULL;
  int rtrn=(f_out) ? sv_WriteTransitionMatrixParameters(f_out,model->sv,header) : 0;
  if (!f && f_out) fclose(f_out);
  return rtrn;
}

/*
   Assumes:
    f        : pointer to valid FILE pointer or null pointer.
    filename : pointer to null terminated string or null.
    header   : pointer to null terminated string.
    model    : pointer to valid TStateModel structure.

   Returns:
    One upon success and zero otherwise.

   Results:
    Writes free theta parameters

   Notes:
    One of f or filename should be non-null. 
*/
int ReadTheta(FILE *f, char *filename, char *header, TStateModel *model)
{
  int err, n=NumberFreeParametersTheta(model);
  char *format="//== %sFree Theta Parameters ==//";
  TVector theta;
  FILE *f_in;
  if (n == 0) return 1;
  if ((f_in=f ? f : filename ? fopen(filename,"rt") : (FILE*)NULL))
    {
      if (!header) header="";
      if ((err=ReadVector(f_in,format,header,theta=CreateVector(n))))
        ReadError(format,header,err);
      else
        ConvertFreeParametersToTheta(model,pElementV(theta));
      FreeVector(theta);
      if (!f) fclose(f_in);
      return err ? 0 : 1;
    }
  else
    {
      ReadError((char*)NULL,(char*)NULL,SWITCHIO_FILE_ERROR);
      return 0;
    }
}

/*
   Assumes:
    f        : pointer to valid FILE pointer or null pointer.
    filename : pointer to null terminated string or null.
    header   : pointer to null terminated string.
    model    : pointer to valid TStateModel structure.

   Returns:
    One upon success and zero otherwise.

   Results:
    Writes free theta parameters

   Notes:
    One of f or filename should be non-null. 
*/
int WriteTheta(FILE *f, char *filename, char *header, TStateModel *model)
{
  PRECISION *theta;
  int i, rtrn=0, n=NumberFreeParametersTheta(model);
  FILE *f_out;
  if (n == 0) return 1;
  if ((f_out=f ? f : filename ? fopen(filename,"at") : (FILE*)NULL))
    {
      if ((theta=(PRECISION*)dw_malloc(n*sizeof(PRECISION))))
        {
          ConvertThetaToFreeParameters(model,theta);
          if (!header) header="";
          fprintf(f_out,"//== %sFree Theta Parameters ==//\n",header);
          for (i=0; i < n; i++) fprintf(f_out,"%22.14le ",(double)(theta[i]));
          fprintf(f_out,"\n\n");
          dw_free(theta);
          rtrn=1;
        }
      if (!f) fclose(f_out);
    }
  else
    ReadError((char*)NULL,(char*)NULL,SWITCHIO_FILE_ERROR);
  return rtrn;
}

/*
   Assumes:
    f        : pointer to valid FILE structure or null pointer
    filename : pointer to null terminated string or null
    header   : pointer to null terminated string or null
    model    : pointer to valid TStateModel structure.

   Returns:
    One upon success and zero upon failure.

   Results:
    Attempts to read transition matrix into model.

   Notes:
    One of f or filename should be non-null.  Calls TransitionMatricesParametersChanged().
*/
int ReadBaseTransitionMatrices_t(int t, FILE *f, char *filename, char *header, TStateModel *model)
{
  int rtrn=0;
  FILE *f_in=f ? f : filename ? fopen(filename,"rt") : (FILE*)NULL;
  if (f_in)
    {
      TransitionMatrixParametersChanged(model);
      rtrn=sv_ReadBaseTransitionMatrices_t(t,f_in,header,"",model->sv,model);
      if (!f) fclose(f_in);
    }
  return rtrn;
}

/*
   Assumes:
    f        : pointer to valid FILE structure or null pointer
    filename : pointer to null terminated string or null
    header   : pointer to null terminated string or null
    model    : pointer to valid TStateModel structure.

   Returns:
    One upon success and zero upon failure.

   Results:
    Attempts to read transition matrix into model.

   Notes:
    One of f or filename should be non-null.  Calls TransitionMatricesParametersChanged().
*/
int ReadBaseTransitionMatricesFlat_t(int t, FILE *f, char *filename, TStateModel *model)
{
  int rtrn=0;
  FILE *f_in=f ? f : filename ? fopen(filename,"rt") : (FILE*)NULL;
  if (f_in)
    {
      TransitionMatrixParametersChanged(model);
      rtrn=sv_ReadBaseTransitionMatricesFlat_t(t,f_in,model->sv,model);
      if (!f) fclose(f_in);
    }
  return rtrn;
}


/*
   Assumes:
    t        : time
    f        : pointer to valid FILE structure or null pointer
    filename : pointer to null terminated string or null
    header   : pointer to null terminated string
    model    : pointer to valid TStateModel structure.

   Returns:
    One upon success and zero upon failure.

   Results:
    Writes transition matrix.

   Notes:
    One of f or filename should be non-null. 
*/
int WriteGrandTransitionMatrix_t(int t, FILE *f, char *filename, char *header, TStateModel *model)
{
  FILE *f_out;
  int rtrn=0;
  if (sv_ComputeTransitionMatrix(t,model->sv,model))
    if ((f_out=f ? f : filename ? fopen(filename,"at") : (FILE*)NULL))
      {
	fprintf(f_out,"//== %sGrand transition matrix%s ==//\n",header ? header : "","");
	rtrn=dw_PrintMatrix(f_out,model->sv->Q,"%.14le ");
	fprintf(f_out,"\n");
	if (!f) fclose(f_out);
      }
  return rtrn;
}

/*
   Assumes:
    f        : pointer to valid FILE structure or null pointer
    filename : pointer to null terminated string or null
    header   : pointer to null terminated string
    model    : pointer to valid TStateModel structure.

   Returns:
    One upon success and zero upon failure.

   Results:
    Writes transition matrix.

   Notes:
    One of f or filename should be non-null. 
*/
int WriteBaseTransitionMatrices_t(int t, FILE *f, char *filename, char *header, TStateModel *model)
{
  FILE *f_out;
  int rtrn=0;
  if (sv_ComputeTransitionMatrix(t,model->sv,model))
    {
      f_out=f ? f : filename ? fopen(filename,"at") : (FILE*)NULL;
      rtrn=(f_out) ? sv_WriteBaseTransitionMatrices(f_out,model->sv,header,"") : 0;
      if (!f && f_out) fclose(f_out);
    }
  return rtrn;
}

/*
   Assumes:
    f        : pointer to valid FILE structure or null pointer
    filename : pointer to null terminated string or null
    header   : pointer to null terminated string
    model    : pointer to valid TStateModel structure.

   Returns:
    One upon success and zero upon failure.

   Results:
    Writes transition matrix in a flat format.

   Notes:
    One of f or filename should be non-null. 
*/
int WriteBaseTransitionMatricesFlat_t(int t, FILE *f, char *filename, TStateModel *model, char* fmt)
{
  FILE *f_out;
  int rtrn=0;
  if (sv_ComputeTransitionMatrix(t,model->sv,model))
    {
      f_out=f ? f : filename ? fopen(filename,"at") : (FILE*)NULL;
      rtrn=(f_out) ? sv_WriteBaseTransitionMatricesFlat(f_out,model->sv,fmt) : 0;
      if (!f && f_out) fclose(f_out);
    }
  return rtrn;
}

int WriteBaseTransitionMatricesFlat_Headers(FILE *f, TStateModel *model)
{
  return f ? sv_WriteBaseTransitionMatricesFlat_Headers(f,model->sv,"") : 0;
}

int ReadFreeParameters(FILE *f, char *filename, TStateModel *model)
{
  int n;
  TVector parameters;
  FILE *f_in=f ? f : filename ? fopen(filename,"at") : (FILE*)NULL;
  if (f_in)
    {
      if (dw_ReadVector(f_in,parameters=CreateVector((n=NumberFreeParametersTheta(model))+NumberFreeParametersQ(model))))
	{
	  ConvertFreeParametersToTheta(model,pElementV(parameters));
	  ConvertFreeParametersToQ(model,pElementV(parameters)+n);
	}
      FreeVector(parameters);
      if (!f) fclose(f_in);
      return 1;
    }
  return 0;
}

/*
   Writes the free parameters to the file pointer f in non-null or the file 
   specified by filename.  Writes the free Theta parameters first followed by the
   free Q parameters.
*/
int WriteFreeParameters(FILE *f, char *filename, TStateModel *model)
{
  int n;
  TVector parameters;
  FILE *f_out=f ? f : filename ? fopen(filename,"at") : (FILE*)NULL;
  if (f_out)
    {
      if ((parameters=CreateVector((n=NumberFreeParametersTheta(model))+NumberFreeParametersQ(model))))
	{
	  ConvertThetaToFreeParameters(model,pElementV(parameters));
	  ConvertQToFreeParameters(model,pElementV(parameters)+n);
	  dw_PrintVector(f_out,parameters,"%.12le ");
	  FreeVector(parameters);
	  if (!f) fclose(f_out);
	  return 1;
	}
      if (!f) fclose(f_out);
    }
  return 0;
}
/*******************************************************************************/
/*******************************************************************************/
/*******************************************************************************/

/*
   The file contains 2 + nparameters columns which are to be interpreted as

      Column  0 : 0               = log posterior density
      Column  1 : 1               = log likelihood
      Columns 2 : 1 + nparameters = parameters

   The file is a delimited ascii file and the delimiter is a space (' ').

   Creates and returns a m x (2 + nparameters) matrix containing the data in the
   file.

   Fields that are empty or do not parse into valid floating point numbers are 
   ignored.

   Rows that do not contain 2 + nparameter valid fields are ignored.

   One of f_in, filename or tag must not be null.  If f_in is not null, this file 
   is read, starting at the current pointer.  Otherwise, if filename is not null 
   then it is opened and read.  If both f_in and filename are null, then the file
   simulation_<tag>.out is opened and read.
*/
TMatrix dw_ReadPosteriorDraws(FILE *f_in, char *filename, char *tag, int nparameters)
{
  char *fmt="simulation_%s.out", delimiter=' ';
  TMatrix posterior_draws=(TMatrix)NULL;
  int free_filename=0, m=0, cols=2+nparameters, i, j, k;
  double** Y;

  // setup filename
  if (!f_in && !filename)
    {
      if (!tag)
        {
          dw_UserError("dw_ReadPosterior(): Must specify FILE pointer, filename or tag");
          return (TMatrix)NULL;
        }
      else
        {
          sprintf(filename=(char*)dw_malloc(strlen(fmt) + strlen(tag) - 1),fmt,tag);
          free_filename=1;
        }
    }

  // Get matrix
  if ((Y=dw_ReadDelimitedFile_floating(f_in,filename,delimiter,REMOVE_EMPTY_FIELDS,0.0)))
    {
      for (k=dw_DimA(Y)-1; k >= 0; k--)
	if (dw_DimA(Y[k]) == cols) m++;
      if ((m > 0) && (posterior_draws=CreateMatrix(m,cols)))
	{
	  for (k=i=0; k < dw_DimA(Y); k++)
	    if (dw_DimA(Y[k]) == cols)
	      {
		for (j=cols-1; j >= 0; j--) ElementM(posterior_draws,i,j)=Y[k][j];
		i++;
	      }
	}
      dw_FreeArray(Y);
    }

  // Clean up
  if (free_filename) dw_free(filename);

  // Return
  return posterior_draws;
}

/*
   The file contains (2 + ntheta + nq) columns which are to be 
   interpreted as

      Column  0 : 0               = log posterior density
      Column  1 : 1               = log likelihood
      Columns 2 : 1 + ntheta + nq = parameters

   The file is a delimited ascii file and the delimiter is a space (' ').

   Attempts to read parameters from file, and upon success sets the parameters in 
   the model and returns 1.  Returns 0 upon failure. 
*/
int dw_ReadPosteriorDraw(FILE *f_in, TStateModel *model)
{
  int i, rtrn=0, terminal=dw_SetTerminalErrors(0), verbose=dw_SetVerboseErrors(0), 
    nt=NumberFreeParametersTheta(model), nq=NumberFreeParametersQ(model);
  PRECISION *x;
  char **v;
  if (f_in)
    if ((v=dw_ReadDelimitedLine(f_in,' ',REMOVE_EMPTY_FIELDS)))
      {
	if (dw_DimA(v) == 2+nt+nq)
	  if ((x=(PRECISION*)dw_malloc((nt+nq)*sizeof(PRECISION))))
	    {
	      for (i=nt+nq+1; i >= 2; i--)
		if (dw_IsFloat(v[i]))
		  x[i-2]=atof(v[i]);
		else
		  break;
	      if (i < 2)
		{
		  ConvertFreeParametersToTheta(model,x);
		  ConvertFreeParametersToQ(model,x+nt);
		  rtrn=1;
		}
	      dw_free(x);
	    }
	dw_FreeArray(v);
      }
  dw_SetTerminalErrors(terminal);
  dw_SetVerboseErrors(verbose);
  return rtrn;
}

/*******************************************************************************/
/******************************** Metropolis IO ********************************/
/*******************************************************************************/
int Read_metropolis_theta(FILE *f, char *filename, char *header, TMetropolis_theta *metropolis)
{
  int *dims, err, i, j, n, m;
  char *format;
  TMatrix X;
  FILE *f_in;
  if ((f_in=f ? f : filename ? fopen(filename,"rt") : (FILE*)NULL))
    {
      if (!header) header="";
      format="//== %sNumber blocks/dimensions theta ==//";
      if ((err=ReadInteger(f_in,format,header,&n)))
        ReadError(format,header,err);
      else
        if (n <= 0)
          ReadError(format,header,err=SWITCHIO_ERROR_READING_DATA);
        else
          {
            if (!dw_ReadArray(f_in,dims=dw_CreateArray_int(n)))
              ReadError(format,header,err=SWITCHIO_ERROR_READING_DATA);
            else
              {
                for (m=metropolis->n_parameters, i=n-1; i >= 0; i--) 
                  if (dims[i] <= 0)
                    break;
                  else
                    m-=dims[i];
                if ((i >= 0) || (m != 0))
                  ReadError(format,header,err=SWITCHIO_ERROR_READING_DATA);
                else
                  {
                    format="//== %sMetropolis scales theta ==//";
                    if ((err=ReadVector(f_in,format,header,metropolis->scale)))
                      ReadError(format,header,err);
                    else
                      {
			for (i=0; i < metropolis->n_parameters; i++) 
			  if (metropolis->direction[i])
			    {
			      FreeVector(metropolis->direction[i]);
			      metropolis->direction[i]=(TVector)NULL;
			    }
                        format="//== %sMetropolis directions theta ==//";
                        if ((err=ReadMatrix(f_in,format,header,X=CreateMatrix(metropolis->n_parameters,metropolis->n_parameters))))
                          ReadError(format,header,err=SWITCHIO_LINE_ID_NOT_FOUND);
                        else
                          {
                            for (i=0; i < metropolis->n_parameters; i++)
			      {
				for (j=0; j < metropolis->n_parameters; j++)
				  {
				    if ((i == j) && (ElementM(X,i,j) != 1.0)) break;
				    if ((i != j) && (ElementM(X,i,j) != 0.0)) break;
				  }
				if (j < metropolis->n_parameters)
				  metropolis->direction[i]=ColumnVector(metropolis->direction[i],X,i);
			      }
                            Setup_metropolis_theta_blocks(metropolis,n,dims);
                          }
                        FreeMatrix(X);
                      }
                  }
              }
            dw_FreeArray(dims);
          }
      if (!f) fclose(f_in);
      return err ? 0 : 1;
    }
  return 0;
}

int Write_metropolis_theta(FILE *f, char *filename, char *header, TMetropolis_theta *metropolis)
{
  int i;
  TMatrix X;
  FILE *f_out;
  if ((f_out=f ? f : filename ? fopen(filename,"at") : (FILE*)NULL))
    {
      if (!header) header="";

      fprintf(f_out,"//== %sNumber blocks/dimensions theta ==//\n%d\n",header,metropolis->n_blocks);
      for (i=0; i < metropolis->n_blocks; i++)
        fprintf(f_out,"%d ",metropolis->block_dims[i]);
      fprintf(f_out,"\n\n");
     
      fprintf(f_out,"//== %sMetropolis scales theta ==//\n",header);
      dw_PrintVector(f_out,metropolis->scale,"%.14le ");
      fprintf(f_out,"\n");
   
      X=IdentityMatrix((TMatrix)NULL,metropolis->n_parameters);
      for (i=0; i < metropolis->n_parameters; i++)
        if (metropolis->direction[i]) InsertColumnVector(X,metropolis->direction[i],i);
      fprintf(f_out,"//== %sMetropolis directions theta ==//\n",header);
      dw_PrintMatrix(f_out,X,"%.14lf ");
      fprintf(f_out,"\n");
      FreeMatrix(X);

      if (!f) fclose(f_out);
      return 1;
    }
  return 0;
}
/*******************************************************************************/
/*******************************************************************************/
/*******************************************************************************/

/*******************************************************************************/
/***************** TMarkovStateVariable Input/Output Routines ******************/
/*******************************************************************************/
/*
   Assumes:
    f        : pointer to valid FILE structure
    idstring : pointer to null terminated string

   Returns:
    Valid pointer to a TMarkovStateVariable structure upon success and null 
    pointer upon failure.

   Results:
    Reads Markov specification from file and creates TMarkovStateVariable 
    structure. 

   Notes:
    The null terminated string idstring is of the form "" or "[i][j]...[k]".  
    Usually, this function will be called with idstring equal to "".  The routine 
    is called recursively with the more general form for idstring.  For each path 
    of Markov state variables of the form

        sv->state_variable[i]->state_variable[j]-> ... ->state_variable[k]

    which corresponds to a single Markov state variable, there must be an entries 
    in the file of the form:
*/
TMarkovStateVariable* sv_ReadMarkovSpecification(FILE *f_in, char *idstring)
{
  char *idformat, *trailer, *fmt, *idstring_new;
  int err, i, j, n_state_variables, nstates, nlags_encoded, nbasestates, nfree;
  TMarkovStateVariable *sv=(TMarkovStateVariable*)NULL, **sv_array;
  void *info;

  if (!f_in) return (TMarkovStateVariable*)NULL;

  // Construct trailer
  if (idstring[0])
    {
      fmt="for state_variable%s ==//";
      sprintf(trailer=(char*)dw_malloc(strlen(fmt)+strlen(idstring)-1),fmt,idstring);
    }
  else
    {
      fmt="==//";
      strcpy(trailer=(char*)dw_malloc(strlen(fmt)+1),fmt);
    }

  // Read number of state variables
  if (!(err=ReadInteger(f_in,idformat="//== Number independent state variables %s",trailer,&n_state_variables))) 
    {
      if (n_state_variables < 0) 
        err=SWITCHIO_ERROR_READING_DATA;
      else
        if (n_state_variables == 0)
          {
            // Read number states
            switch (err=ReadInteger(f_in,idformat="//== Number states %s",trailer,&nstates))
              {
              case SWITCHIO_ERROR_READING_DATA:
                break;
              case SWITCHIO_LINE_ID_NOT_FOUND:  // allows nstates to be computed from nlags_encoded and nbasestates.
                nstates=0;
                err=0;
                break;
              case 0:
                if (nstates <= 0) err=SWITCHIO_ERROR_READING_DATA;
                break;
              }

            // Read number of lags to encode
            if (!err)
              switch (err=ReadInteger(f_in,idformat="//== Number of lags encoded %s",trailer,&nlags_encoded))
                {
                case SWITCHIO_ERROR_READING_DATA:
                  break;
                case SWITCHIO_LINE_ID_NOT_FOUND:
                  nlags_encoded=0;
                  err=0;
                  break;
                case 0:
                  if (nlags_encoded < 0) err=SWITCHIO_ERROR_READING_DATA;
                  break;
                }

            // Read number of base states
            if (!err)
              switch(err=ReadInteger(f_in,idformat="//== Number of base states %s",trailer,&nbasestates))
                {
                case SWITCHIO_ERROR_READING_DATA:
                  break;
                case SWITCHIO_LINE_ID_NOT_FOUND:
                  if ((nlags_encoded == 0) && (nstates > 0))
                    {
                      nbasestates=nstates;
                      err=0;
                    }
                  else
                    err=SWITCHIO_ERROR_READING_DATA;
                  break;
                case 0:
                  if (nbasestates <= 0) 
                    err=SWITCHIO_ERROR_READING_DATA;
                  else
                    {
                      // Check consistency of nlags_encoded, nstates, and nbasestates
                      for (j=nbasestates, i=nlags_encoded; i > 0; i--) j*=nbasestates;
                      if (nstates == 0)
                        nstates=j;
                      else
                        if (j != nstates) 
                          err=SWITCHIO_ERROR_READING_DATA;
                    }
                  break;
                }

            // Setup single restricted Markov state variable
            if (!err)
              {
                if ((info=ReadSpecification_dirichlet_restrictions(f_in,trailer,nbasestates)))
                  {
                    nfree=((TDirichletRestrictions*)(info))->total_Dirichlet_parameters 
                      - dw_DimA(((TDirichletRestrictions*)(info))->DirichletDim);
                    sv=CreateMarkovStateVariable_Single(nbasestates,nfree,nlags_encoded,dirichlet_restrictions_CreateQRoutines(),info);
                  }
                else
                  err=SWITCHIO_ERROR_READING_DATA;
              }
          }
        else
          {
            // Read number of lags to encode  
            switch (err=ReadInteger(f_in,idformat="//== Number of lags encoded %s",trailer,&nlags_encoded))
              {
              case SWITCHIO_ERROR_READING_DATA:
                break;
              case SWITCHIO_LINE_ID_NOT_FOUND:
                nlags_encoded=0;
                err=0;
                break;
              case 0:
                if (nlags_encoded < 0) err=SWITCHIO_ERROR_READING_DATA;
                break;
              }

            // Setup multiple Markov state variables
            if (!err)
              {
                sv_array=(TMarkovStateVariable**)dw_CreateArray_pointer(n_state_variables,(void (*)(void*))FreeMarkovStateVariable);
                for (i=0; i < n_state_variables; i++)
                  {
                    idstring_new=CreateIntegerString("%s[%d]",idstring,i+1);
                    sv_array[i]=sv_ReadMarkovSpecification(f_in,idstring_new);
                    dw_free(idstring_new);
                    if (!sv_array[i])
                      {
                        dw_FreeArray(sv_array);
                        break;
                      }
                  }
                if ((i != n_state_variables) || !(sv=CreateMarkovStateVariable_Multiple(nlags_encoded,sv_array)))
                  err=SWITCHIO_ERROR_READING_DATA;
              }
          }
    }

  if (err) ReadError(idformat,trailer,err);
  if (trailer) dw_free(trailer);
  return sv;
}

/*
   Assumes:
    f        : pointer to valid FILE structure
    idstring : pointer to null terminated string

   Returns:
    One upon success and zero upon upon failure. (This routine cannot fail).

   Results:
    Writes Markov specification to file.

   Notes:
    The null terminated string idstring is of the form "" or "[i][j]...[k]".  
    Usually, this function will be called with idstring equal to "".  The routine 
    is called recursively with the more general form for idstring.  For each path 
    of Markov state variables of the form

        sv->state_variable[i]->state_variable[j]-> ... ->state_variable[k]

    a specification is written.  See sv_ReadMarkovSpecification() for details.

*/
int sv_WriteMarkovSpecification(FILE *f_out, TMarkovStateVariable *sv, char *idstring)
{
  int i;
  char *trailer, *idbuffer, *fmt;

  if (!f_out) return 0;

  if (idstring[0])
    {
      fmt="for state_variable%s ==//";
      sprintf(trailer=(char*)dw_malloc(strlen(fmt)+strlen(idstring)-1),fmt,idstring);

      fprintf(f_out,"//********************** Specification for state_variable%s **********************//\n\n",idstring);
    }
  else
    {
      fmt="==//";
      strcpy(trailer=(char*)dw_malloc(strlen(fmt)+1),fmt);

      fprintf(f_out,"//*********************** State Variable Specification ************************//\n");
    }

  fprintf(f_out,"//== Number independent state variables %s\n%d\n",trailer,sv->n_state_variables);

  if (sv->n_state_variables > 0)
    {
      if (sv->nlags_encoded > 0)
	fprintf(f_out,"\n//== Number of lags encoded %s\n%d\n",trailer,sv->nlags_encoded);

      fprintf(f_out,"//*****************************************************************************//\n\n");
      for (i=0; i < sv->n_state_variables; i++)
	{
	  idbuffer=CreateIntegerString("%s[%d]",idstring,i+1);
	  if (!sv_WriteMarkovSpecification(f_out,sv->state_variable[i],idbuffer)) 
            {
	      dw_free(idbuffer);
	      return 0;
	    }
	  dw_free(idbuffer);
	}
    }
  else
    {
      fprintf(f_out,"\n//== Number states %s\n%d\n\n",trailer,sv->nstates);

      fprintf(f_out,"//== Number of lags encoded %s\n%d\n\n",trailer,sv->nlags_encoded);

      fprintf(f_out,"//== Number of base states %s\n%d\n\n",trailer,sv->nbasestates);

      if (sv->routines->WriteSpecification)
	sv->routines->WriteSpecification(f_out,sv,trailer);

      fprintf(f_out,"//*****************************************************************************//\n\n");
    }

  dw_free(trailer);
  return 1;
}

/*
   Assumes:
    f        : pointer to valid FILE structure
    sv       : pointer to valid TMarkovStateVariable structure
    header   : pointer to null terminated string or null pointer

   Returns:
    One upon success and zero upon failure.

   Results:
    Reads transition matrix parameters from sv to a file.
*/
int sv_ReadTransitionMatrixParameters(FILE *f_in, TMarkovStateVariable *sv, char *header)
{
  int i;

  if (sv->nfree == 0) return 1;

  if (!f_in) return 0;

  if (!header) header="";
  if (SetFilePosition(f_in,"//== %sFree Transition Matrix Parameters ==//",header) == SWITCHIO_LINE_ID_NOT_FOUND)
    return 0;

  for (i=0; i < sv->nfree; i++)
#if (PRECISION_SIZE == 8)
    if (fscanf(f_in," %lf ",sv->q+i) != 1) return 0; 
#else
    if (fscanf(f_in," %f ",sv->q+i) != 1) return 0;
#endif

  return 1;
}

/*
   Assumes:
    f        : pointer to valid FILE structure
    sv       : pointer to valid TMarkovStateVariable structure
    header   : pointer to null terminated string or null pointer

   Returns:
    One upon success and zero upon failure.

   Results:
    Writes transition matrix parameters from sv to a file.
*/
int sv_WriteTransitionMatrixParameters(FILE *f_out, TMarkovStateVariable *sv, char *header)
{
  int i;

  if (sv->nfree == 0) return 1;

  if (!f_out) return 0;

  if (!header) header="";
  fprintf(f_out,"//== %sFree Transition Matrix Parameters ==//\n",header);
  for (i=0; i < sv->nfree; i++)
    fprintf(f_out,"%22.14le ",sv->q[i]);
  fprintf(f_out,"\n\n");

  return 1;
}

/*
   Assumes:
    t        : integer - time at which transition matrix is valid
    f        : pointer to valid FILE structure
    header   : pointer to null terminate string or null pointer
    idstring : pointer to null terminated string
    sv       : pointer to valid TMarkovStateVariable structure
    model    : pointer to valit TStateModel structure

   Returns:
    One upon success and zero upon failure.

   Results:
    Reads base transition matrices from file into sv.  All transition matrices and the
    associated free parameters are set.  

   Notes:
    The null terminated string idstring is of the form "" or "[i][j]...[k]".  
    Usually, this function will be called with idstring equal to "".  The routine 
    is called recursively with the more general form for idstring.  For each path 
    of Markov state variables of the form

        sv->state_variable[i]->state_variable[j]-> ... ->state_variable[k]

    which corresponds to a single Markov state variable, there must be an entry 
    in the file of the form:

    //== <header>Transition matrix[i][j]...[k] ==//
    x x ... x
    x x ... x
    . .     .
    x x ... x

    If sv itself is a single Markov state variable, then the format can be 

    //== <header>Transition matrix[1] ==//
    x x ... x
    x x ... x
    . .     .
    x x ... x

    or

    //== <header>Transition matrix ==//
    x x ... x
    x x ... x
    . .     .
    x x ... x

    Here the term <header> is replaced with the null terminated string header.
    Note that the spacing is important.
*/
int sv_ReadBaseTransitionMatrices_t(int t, FILE *f_in, char *header, char *idstring, TMarkovStateVariable* sv, TStateModel *model)
{
  int i, j, err;
  char *format, *buffer;
  PRECISION sum;

  if (sv->n_state_variables > 0)
    {
      format="%s[%d]";
      sv->t0=0;
      sv->t1=INT_MAX;
      for (i=0; i < sv->n_state_variables; i++)
	{
	  buffer=CreateIntegerString(format,idstring,i+1);
	  if (!sv_ReadBaseTransitionMatrices_t(t,f_in,header,buffer,sv->state_variable[i],model)) 
            {
	      sv->t1=-1;
	      dw_free(buffer);
	      return 0;
	    }
	  else
	    {
	      if (sv->t0 < sv->state_variable[i]->t0) sv->t0=sv->state_variable[i]->t0;
	      if (sv->t1 > sv->state_variable[i]->t1) sv->t1=sv->state_variable[i]->t1;
	    }
	  dw_free(buffer);
	}
      MatrixTensor(sv->baseQ,sv->QA);
      if (sv->nlags_encoded > 0) ConvertBaseTransitionMatrix(sv->Q,sv->baseQ,sv->nlags_encoded);
      return 1;
    }
  else
    {
      // Read transition matrix
      if (!header) header="";
      format="//== %sBase transition matrix%s ==//";
      sprintf(buffer=(char*)dw_malloc(strlen(header) + strlen(format) + strlen(idstring) - 3),format,header,idstring);
      if ((err=ReadMatrix(f_in,(char*)NULL,buffer,sv->baseQ)) && !idstring[0])
	{
	  dw_free(buffer);
	  sprintf(buffer=(char*)dw_malloc(strlen(header) + strlen(format) + strlen(idstring) - 3),format,header,"[1]");
	  err=ReadMatrix(f_in,(char*)NULL,buffer,sv->baseQ);
	}
      dw_free(buffer);
      if (!err)
	{      
	  // Scale the columns of Q - loose requirement on sumation to one
	  for (j=sv->nbasestates-1; j >= 0; j--)
	    {
	      for (sum=0.0, i=sv->nbasestates-1; i >= 0; i--) 
		if (ElementM(sv->baseQ,i,j) < 0.0)
		  {
		    dw_UserError("Transition matrix can not have negative elements.");
		    sv->t1=-1;
		    return 0;
		  }
		else
		  sum+=ElementM(sv->baseQ,i,j);
	      if (fabs(sum-1.0) > SQRT_MACHINE_EPSILON)
		{
		  dw_UserError("Transition matrix columns must sum to one.");
		  sv->t1=-1;
		  return 0;
		}
	      for (sum=1.0/sum, i=sv->nstates-1; i >= 0; i--) 
		ElementM(sv->baseQ,i,j)*=sum;
	    }

	  if (sv->nlags_encoded > 0) ConvertBaseTransitionMatrix(sv->Q,sv->baseQ,sv->nlags_encoded);

	  // Update and set sv->t0 and sv->t1
	  if (!sv->routines || !sv->routines->Update_q_from_BaseTransitionMatrix || !sv->routines->Update_q_from_BaseTransitionMatrix(t,sv,model))
	    {
	      dw_UserError("Unable to extract free parameters from transition matrix");
	      sv->t1=-1;
	      return 0;
	    }
	  else
	    return 1;
	}
      else
	{
	  sv->t1=-1;
	  return 0;
	}
    }
}

/*
   Assumes:
    t        : integer - time at which transition matrix is valid
    f        : pointer to valid FILE structure
    sv       : pointer to valid TMarkovStateVariable structure
    model    : pointer to valit TStateModel structure

   Returns:
    One upon success and zero upon failure.

   Results:
    Reads base transition matrices from file into sv.  All transition matrices and the
    associated free parameters are set.  
*/
int sv_ReadBaseTransitionMatricesFlat_t(int t, FILE *f_in, TMarkovStateVariable *sv, TStateModel *model)
{
  int i, j;
  PRECISION sum;

  if (sv->n_state_variables > 0)
    {
      sv->t0=0;
      sv->t1=INT_MAX;
      for (i=0; i < sv->n_state_variables; i++)
	if (!sv_ReadBaseTransitionMatricesFlat_t(t,f_in,sv->state_variable[i],model)) 
	  {
	    sv->t1=-1;
	    return 0;
	  }
	else
	  {
	    if (sv->t0 < sv->state_variable[i]->t0) sv->t0=sv->state_variable[i]->t0;
	    if (sv->t1 > sv->state_variable[i]->t1) sv->t1=sv->state_variable[i]->t1;
	  }
      MatrixTensor(sv->baseQ,sv->QA);
      if (sv->nlags_encoded > 0) ConvertBaseTransitionMatrix(sv->Q,sv->baseQ,sv->nlags_encoded);
      return 1;
    }
  else
    {
      // Read transition matrix
      for (j=0; j < sv->nbasestates; j++)
	for (i=0; i < sv->nbasestates; i++)
	  if (fscanf(f_in," %lf ",&ElementM(sv->baseQ,i,j)) != 1)
	    {
	      sv->t1=-1;
	      dw_UserError("Unable to read transition matrix.");
	      return 0;
	    }
  
      // Scale the columns of Q - loose requirement on sumation to one
      for (j=sv->nbasestates-1; j >= 0; j--)
	{
	  for (sum=0.0, i=sv->nbasestates-1; i >= 0; i--) 
	    if (ElementM(sv->baseQ,i,j) < 0.0)
	      {
		dw_UserError("Transition matrix can not have negative elements.");
		sv->t1=-1;
		return 0;
	      }
	    else
	      sum+=ElementM(sv->baseQ,i,j);
	  if (fabs(sum-1.0) > SQRT_MACHINE_EPSILON)
	    {
	      dw_UserError("Transition matrix columns must sum to one.");
	      sv->t1=-1;
	      return 0;
	    }
	  for (sum=1.0/sum, i=sv->nstates-1; i >= 0; i--) 
	    ElementM(sv->baseQ,i,j)*=sum;
	}

      if (sv->nlags_encoded > 0) ConvertBaseTransitionMatrix(sv->Q,sv->baseQ,sv->nlags_encoded);

      // Update and set sv->t0 and sv->t1
      if (!sv->routines || !sv->routines->Update_q_from_BaseTransitionMatrix || !sv->routines->Update_q_from_BaseTransitionMatrix(t,sv,model))
	{
	  dw_UserError("Unable to extract free parameters from transition matrix");
	  sv->t1=-1;
	  return 0;
	}
      else
	return 1;
    }
}

/*
   Assumes:
    f        : pointer to valid FILE structure
    sv       : pointer to valid TMarkovStateVariable structure
    header   : pointer to null terminated string or null terminated string
    idstring : pointer to null terminated string

   Returns:
    One is always returned.

   Results:
    Writes base transition matrices from sv to a file.

   Notes:
    The null terminated string idstring is of the form  "" or "[i][j]...[k]".
    Usually, this routine will be called with idstring equal to "".  The routine
    is called recursively with the more general form for idstring.
*/
int sv_WriteBaseTransitionMatrices(FILE *f_out, TMarkovStateVariable* sv, char *header, char *idstring)
{
  int i, rtrn=1;
  char *idbuffer;

  if (sv->n_state_variables > 0)
    for (i=0; i < sv->n_state_variables; i++)
      {
	idbuffer=CreateIntegerString("%s[%d]",idstring,i+1);
	rtrn=sv_WriteBaseTransitionMatrices(f_out,sv->state_variable[i],header,idbuffer);
	dw_free(idbuffer);
	if (!rtrn) break;
      }
  else
    {
      if (!header) header="";
      fprintf(f_out,"//== %sBase transition matrix%s ==//\n",header,idstring);
      rtrn=dw_PrintMatrix(f_out,sv->baseQ,"%.14le ");
      fprintf(f_out,"\n");
    }
  
  return rtrn;
}

/*
   Assumes:
    f        : pointer to valid FILE structure
    sv       : pointer to valid TMarkovStateVariable structure

   Returns:
    One is always returned.

   Results:
    Writes base transition matrices from sv to a file in a flat format.  See
    sv_WriteBaseTransitionMatricsFlat_headers() for the format.

   Notes:
    A line feed is NOT written at the end of the transition matrix.
*/
int sv_WriteBaseTransitionMatricesFlat(FILE *f_out, TMarkovStateVariable* sv, char *fmt)
{
  int i, n, rtrn=1;
  PRECISION *p;

  if (sv->n_state_variables > 0)
    for (i=0; i < sv->n_state_variables; i++)
      {
	rtrn=sv_WriteBaseTransitionMatricesFlat(f_out,sv->state_variable[i],fmt);
	if (!rtrn) break;
      }
  else
    {
      if (!fmt) fmt="%.5lf ";
      for (p=pElementM(sv->baseQ), n=RowM(sv->baseQ)*ColM(sv->baseQ), i=0; i < n; i++) 
	fprintf(f_out,fmt,p[i]);
    }
  
  return rtrn;
}

/*
   Assumes:
    f:  valid file pointer or null pointer
    sv:  pointer to valid TMarkovStateVariable structure
    header: pointer to null terminated string
    idstring:  pointer to null terminated string

   Returns:
    One is always returned.

   Results:
    Writes base transition matrices from sv to a file.

   Notes:
    The null terminated string idstring is of the form  "" or "[i][j]...[k]".  
    Usually, this routine will be called with idstring equal to "".  The routine 
    is called recursively with the more general form for idstring.

    The matrices are written column by column. 
*/
int sv_WriteBaseTransitionMatricesFlat_Headers(FILE *f_out, TMarkovStateVariable* sv, char *idstring)
{
  int i, j;
  char *idbuffer;

  if (sv->n_state_variables > 0)
    {
      for (j=10, i=1; sv->n_state_variables >= j; j*=10, i++);
      strcpy(idbuffer=(char*)dw_malloc((j=(int)strlen(idstring))+i+3),idstring);
      for (i=0; i < sv->n_state_variables; i++)
	{
	  sprintf(idbuffer+j,"[%d]",i+1);
	  sv_WriteBaseTransitionMatricesFlat_Headers(f_out,sv->state_variable[i],idbuffer);
	}
      dw_free(idbuffer);
    }
  else
    {
      for (j=0; j < sv->nbasestates; j++)
	for (i=0; i < sv->nbasestates; i++)
	  fprintf(f_out,"Q%s(%d,%d) ",idstring,i+1,j+1);
    }

  return 1;
}

/*******************************************************************************/
/*******************************************************************************/
/*******************************************************************************/

/*******************************************************************************/
/*********** Creating TMarkovStateVariable with simple restrictions ************/
/*******************************************************************************/
/*
//== Markov State Variables with Simple Restrictions ==//

//-----------------------------------------------------------------------------//
//-- If n_state_variables is one, then there must be entries for             --//
//-- state_variable[1] and all others are ignored.                           --//
//-----------------------------------------------------------------------------//
//== Number independent state variables ==//
n_state_variables

//-----------------------------------------------------------------------------//
//-- state_variable[i][j]...[j]                                              --//
//-----------------------------------------------------------------------------//

//-----------------------------------------------------------------------------//
//-- If this identifier is not present, the number of independent state      --//
//-- variables is set to one.                                                --//
//-----------------------------------------------------------------------------//
//== Number independent state variables for state_variable[i][j]...[k] ==//
n_state_variables

//-----------------------------------------------------------------------------//
//-- The following fields must be present if n_state_variable is 1 and are   --//
//-- ignored otherwise.                                                      --//
//-----------------------------------------------------------------------------//

//== Number of states for state_variable[i][j]...[k] ==//
n_states

//-----------------------------------------------------------------------------//
//-- Allows for lagged values of the state variable to be encoded.  If this  --//
//-- identifier is not present, then the value of nlags_encoded is set to    --//
//-- zero.                                                                   --//
//-----------------------------------------------------------------------------//
//== Number of lags encoded for state_variable[i][j]...[k] ==//
nlags_encoded

//-----------------------------------------------------------------------------//
//-- Each column contains the parameters for a Dirichlet prior on the        --//
//-- corresponding column of the transition matrix.  Each element must be    --//
//-- positive.  For each column, the relative size of the prior elements     --//
//-- determine the relative size of the elements of the transition matrix    --//
//-- and overall larger sizes implies a tighter prior.  The prior must be    --//
//-- nstates by nstates.
//-----------------------------------------------------------------------------//
//== Transition matrix prior for state_variable[i][j]...[k] ==//
prior
//-----------------------------------------------------------------------------//
//-- Dimension of the Dirichlet variable controlling each of the columns of  --//
//-- transition matrix.                                                      --//
//-----------------------------------------------------------------------------//
//== Free Dirichet dimensions for state_variable[i][j]...[k] ==//
free[0] ... free[n_states - 1]

//-----------------------------------------------------------------------------//
//-- The jth restriction matrix is n_states x free[j].  Each row of the      --//
//-- restriction matrix has exactly one non-zero entry and the sum of each   --//
//-- column of the restriction matrix must be one.  If entry (i,k) of the    --//
//-- jth restriction matrix is non-zero, then entry (i,j) in the transition  --//
//-- matrix is controlled by the kth element of jth free Dirichlet random    --//
//-- variable                                                                --//
//-----------------------------------------------------------------------------//
//== Column restrictions for state_variable[i][j]...[k] ==//
restriction[0]
     .
     .
     .
restriction[n_states - 1]
*/
TMarkovStateVariable* CreateMarkovStateVariable_Simple(FILE *f_in, char *idstring)
{
  int nlags, n_state_variables, nstates, i, j, err=0;
  char *format, *old_format, *idstring_new, *trailer=(char*)NULL;
  TMatrix prior=(TMatrix)NULL;
  int *dims=(int*)NULL;
  TMatrix* restrictions=(TMatrix*)NULL;
  TMarkovStateVariable **sv_array=(TMarkovStateVariable**)NULL, *sv=(TMarkovStateVariable*)NULL;

  // Check file pointer
  if (!f_in)
    {
      dw_UserError("CreateMarkovStateVariable_Simple():  null file pointer\n");
      return (TMarkovStateVariable*)NULL;
    }

  // Construct trailer
  if (idstring[0])
    sprintf(trailer=(char*)dw_malloc(24+strlen(idstring)),"for state_variable%s ==//",idstring);
  else
    strcpy(trailer=(char*)dw_malloc(5),"==//");

  // Read number of Markov state variables
  if ((err=ReadInteger(f_in,format="//== Number independent state variables %s",trailer,&n_state_variables) == SWITCHIO_LINE_ID_NOT_FOUND))
    if (!(err=ReadInteger(f_in,format="//== Number Independent State Variables %s",trailer,&n_state_variables)))
      printf("Warning CreateMarkovStateVariable_Simple(): Using old file format for Number independent state variables\n");
  if (err == SWITCHIO_LINE_ID_NOT_FOUND)
    n_state_variables=1;
  else
    if (err == SWITCHIO_ERROR_READING_DATA)
      goto CLEAN_UP;
    else
      if (n_state_variables <= 0)
	{
	  err=SWITCHIO_ERROR_READING_DATA;
	  goto CLEAN_UP;
	}

  if (n_state_variables > 1)
    {
      dw_free(trailer);
      sv_array=(TMarkovStateVariable**)dw_CreateArray_pointer(n_state_variables,(void (*)(void*))FreeMarkovStateVariable);
      for (i=0; i < n_state_variables; i++)
	{
	  sv_array[i]=CreateMarkovStateVariable_Simple(f_in,idstring_new=CreateIntegerString("%s[%d]",idstring,i+1));
	  dw_free(idstring_new);
	  if (!sv_array[i]) break;
	}
      if (i != n_state_variables)
	dw_FreeArray(sv_array);
      else
	if (!(sv=CreateMarkovStateVariable_Multiple(0,sv_array)))
	  {
	    dw_FreeArray(sv_array);
	    dw_UserError("Unexpected error:  unable to create multiple TMarkovStateVariable structure\n");
	  }
      return sv;
    }

  //===== Single Markov state variable =====//
  // Reset trailer if necessary
  if (!idstring[0])
    {
      dw_free(trailer);
      memcpy(trailer=(char*)dw_malloc(27),"for state_variable[1] ==//",27);
    }

  // Read number of states
  if ((err=ReadInteger(f_in,format="//== Number of states %s",trailer,&nstates))) goto CLEAN_UP;
  if (nstates <= 0)
    {
      err=SWITCHIO_ERROR_READING_DATA;
      goto CLEAN_UP;
    }

  // Read number of lags
  if ((err=ReadInteger(f_in,format="//== Number of lags encoded %s",trailer,&nlags)) == SWITCHIO_LINE_ID_NOT_FOUND)
    {
      err=0;
      nlags=0;
    }
  else
    if (err == SWITCHIO_ERROR_READING_DATA)
      goto CLEAN_UP;
    else
      if (nlags < 0)
	{
	  err=SWITCHIO_ERROR_READING_DATA;
	  goto CLEAN_UP;
	}

  //===== TDirichletRestrictions data =====//
  // Read prior
  if ((err=ReadMatrix(f_in,format="//== Transition matrix prior %s",trailer,prior=CreateMatrix(nstates,nstates))))
    {
      // Old format
      if (prior) FreeMatrix(prior);
      if (strlen(trailer) >= 5)
	trailer[strlen(trailer)-5]='\0';
      else
	trailer[0]='\0';
      err=ReadMatrix(f_in,old_format="//== Transition matrix prior %s. (n_states x n_states) ==//",trailer,prior=CreateMatrix(nstates,nstates));
      if (trailer[0])
	trailer[strlen(trailer)]=' ';
      else
	trailer[0]='=';
      if (err)
	goto CLEAN_UP;
      else
	printf("Warning CreateMarkovStateVariable_Simple():  Using old format for Transition matrix prior.\n");
    }

  // Read dimension of Dirichlet random variable controlling each column
  if ((err=ReadIntArray(f_in,format="//== Dirichlet dimensions %s",trailer,dims=dw_CreateArray_int(nstates))))
    {
      dw_FreeArray(dims);
      if (strlen(trailer) >= 5)
	trailer[strlen(trailer)-5]='\0';
      else
	trailer[0]='\0';
      err=ReadIntArray(f_in,format="//== Free Dirichet dimensions %s  ==//",trailer,dims=dw_CreateArray_int(nstates));
      if (!err)
        {
          if (trailer[0])
            trailer[strlen(trailer)]=' ';
          else
            trailer[0]='=';
        }
      if (err)
	goto CLEAN_UP;
      else
	printf("Warning CreateMarkovStateVariable_Simple():  Using old format for Dirichlet dimensions.\n");
    }
  for (j=0; j < nstates; j++)
    if (dims[j] <= 0)
      {
	err=SWITCHIO_ERROR_READING_DATA;
	goto CLEAN_UP;
      }

  // Read restrictions
  if ((err=SetFilePosition(f_in,format="//== Column restrictions %s",trailer)))  goto CLEAN_UP;

  restrictions=dw_CreateArray_matrix(nstates);

  for (j=0; j < nstates; j++)
    if (!dw_ReadMatrix(f_in,restrictions[j]=CreateMatrix(nstates,dims[j])))
      {
	err=SWITCHIO_ERROR_READING_DATA;
	goto CLEAN_UP;
      }

  // Create Markov state variable
  if (!(sv=CreateMarkovStateVariable_SimpleRestrictions(nstates,nlags,prior,restrictions)))
    dw_UserError("CreateMarkovStateVariable_Simple():  unable to create Markov state variable with simple restrictions\n");

 CLEAN_UP:

  // Print error message if necessary
  if (err) ReadError(format,trailer,err);

  // Free memory as necessary
  if (restrictions) dw_FreeArray(restrictions);
  if (dims) dw_FreeArray(dims);
  if (prior) FreeMatrix(prior);
  if (trailer) dw_free(trailer);

  // Return
  return sv;
}

TMarkovStateVariable* CreateMarkovStateVariable_File(FILE *f, char *filename)
{
  FILE *f_in;
  char *str, *str_old;
  int err;
  TMarkovStateVariable *sv=(TMarkovStateVariable*)NULL;

  // Open file if necessary
  if (f)
    f_in=f;
  else
    if (!(f_in=fopen(filename,"rt")))
      {
	err=SWITCHIO_FILE_ERROR;
	return (TMarkovStateVariable*)NULL;
      }

  // Check for file type
  if ((err=SetFilePosition(f_in,(char*)NULL,str="//== Markov State Variables with Simple Restrictions ==//")))
    {
      if ((err=SetFilePosition(f_in,(char*)NULL,str_old="//== Flat Independent Markov States and Simple Restrictions ==//")))
	ReadError((char*)NULL,str,err);
      else
	printf("Warning CreateMarkovStateVariable_File():  Old file format for file type.\n");
    }
  sv=CreateMarkovStateVariable_Simple(f_in,"");

  // Close file if necessary
  if (!f && f_in) fclose(f_in);

  // Return
  return sv;
}
/*******************************************************************************/
/*******************************************************************************/
/*******************************************************************************/


/*******************************************************************************/
/************************** TDirichletRestrictions IO **************************/ 
/*******************************************************************************/
TDirichletRestrictions* ReadSpecification_dirichlet_restrictions(FILE *f_in, char *trailer, int nstates)
{
  TMatrix Prior, MQ;
  int *FreeDim, **NonZeroIndex, i, err;
  char *idformat;
  TDirichletRestrictions *restrictions=(TDirichletRestrictions*)NULL;

  // Read prior
  Prior=CreateMatrix(nstates,nstates);
  if (!(err=ReadMatrix(f_in,idformat="//== Prior %s",trailer,Prior)))
    {
      // Read free Restricted dimensions
      if (!(err=ReadInteger(f_in,idformat="//== Number Dirichlet variables %s",trailer,&i)))
	{
	  FreeDim=dw_CreateArray_int(i);
	  if (!(err=ReadIntArray(f_in,idformat="//== Dirichlet dimensions %s",trailer,FreeDim)))
	    {
	      // Read free Restricted index
	      NonZeroIndex=dw_CreateRectangularArray_int(nstates,nstates);
	      if (!(err=ReadIntArray(f_in,idformat="//== Dirichlet index (total) %s",trailer,NonZeroIndex)))
		{
		  // Read free Restricted multipliers
		  MQ=CreateMatrix(nstates,nstates);
		  if (!(err=ReadMatrix(f_in,idformat="//== Dirichlet multipliers %s",trailer,MQ)))
		    restrictions=CreateDirichletRestrictions(nstates,Prior,FreeDim,NonZeroIndex,MQ);
		  FreeMatrix(MQ);
		}
	      dw_FreeArray(NonZeroIndex);
	    }
	  dw_FreeArray(FreeDim);
	}
    }
  FreeMatrix(Prior);
  return restrictions;
}

int WriteSpecification_dirichlet_restrictions(FILE *f_out, TMarkovStateVariable *sv, char *trailer)
{
  TDirichletRestrictions *restricted=(TDirichletRestrictions*)(sv->info);

  fprintf(f_out,"//== Prior %s\n",trailer);
  dw_PrintMatrix(f_out,restricted->Prior,"%22.14le ");
  fprintf(f_out,"\n");

  fprintf(f_out,"//== Number Dirichlet variables %s\n%d\n\n",trailer,dw_DimA(restricted->DirichletDim));

  fprintf(f_out,"//== Dirichlet dimensions %s\n",trailer);
  dw_PrintArray(f_out,restricted->DirichletDim,"%d ");
  fprintf(f_out,"\n");

  fprintf(f_out,"//== Dirichlet index (total) %s\n",trailer);
  dw_PrintArray(f_out,restricted->NonZeroIndex,"%d ");

  fprintf(f_out,"//== Dirichlet multipliers %s\n",trailer);
  dw_PrintMatrix(f_out,restricted->MQ,"%22.14le ");

  return 1;
}

/*******************************************************************************/
/*******************************************************************************/
/*******************************************************************************/

/*******************************************************************************/
/************************** Reading Tao's dsge model ***************************/ 
/*******************************************************************************/
/*
   Assumes
     j      :  An integer with 0 <= j < number of columns in states
     states :  Rectangular array of non-negative integers

   Results
     Returns the number of regimes associated with the jth column of states.

   Notes:
     The rectangular array states is a translation matrix.  Each column of states
     provides a translation from the Markov state variable with dw_DimA(states) 
     regimes to the Markov state variable with
*/
int GetNumberStatesFromTranslationMatrix(int j, int **states)
{
  int i, n=0;
  for (i=dw_DimA(states[j])-1; i >= 0; i--)
    if (states[j][i] > n) n=states[j][i];
  return n+1;
}

/*
   Assumes 
*/
static int GetTotalNumberStateVariablesIncludingLags(TMarkovStateVariable *sv)
{
  int i, n=0;
  if (sv->n_state_variables > 0)
    for (i=sv->n_state_variables-1; i >= 0; i--)
      n+=GetTotalNumberStateVariablesIncludingLags(sv->state_variable[i]);
  else
    n=sv->nlags_encoded+1;
  return n;
}

static void GetDimStateVariablesIncludingLags(int *tv_dims, TMarkovStateVariable *sv)
{
  int i;
  if (sv->n_state_variables > 0)
    for (i=0; i < sv->n_state_variables; tv_dims+=GetTotalNumberStateVariablesIncludingLags(sv->state_variable[i]), i++)
      GetDimStateVariablesIncludingLags(tv_dims,sv->state_variable[i]);
  else
    for (i=sv->nlags_encoded; i >= 0; i--)
      tv_dims[i]=sv->nbasestates;
}

/*
   Assumes
     states -  An rectangular array of integers.  The integer states[j][k] will 
               be non-zero if the kth state (appropriately counted) effects the 
               jth group.
     sv     -  Valid pointer to TMarkovStateVariable structure.  It must be the 
               case that the number of columns in states is equal to 
               GetTotalNumberStateVariablesIncludingLags(sv).

   Returns
     A rectangular  array of integers that is a translation from the values of
     the state variable sv to the state variable that is a product of the state
     variables with non-zero entries in states. 
*/
static int** CreateTranslationMatrix(int **table, TMarkovStateVariable *sv)
{
  int **translation, *state, *tv_dims;
  int tv, cols=dw_DimA(table), i, j, k;

  translation=dw_CreateRectangularArray_int(sv->nstates,cols);
  tv=GetTotalNumberStateVariablesIncludingLags(sv);
  tv_dims=(int*)dw_malloc(tv*sizeof(int));
  state=(int*)dw_malloc(tv*sizeof(int));
  GetDimStateVariablesIncludingLags(tv_dims,sv);

  for (j=tv-1; j >= 0; j--) state[j]=0;
  i=0;
  do
    {
      for (j=cols-1; j >= 0; j--)
	{
	  translation[i][j]=0;
	  for (k=0; k < tv; k++)
	    if (table[j][k]) 
	      translation[i][j]=translation[i][j]*tv_dims[k] + state[k];
	}

      for (k=tv-1; k >= 0; k--)
	if (state[k] < tv_dims[k]-1)
	  {
	    state[k]++;
	    break;
	  }
	else
	  state[k]=0;
      i++;
    }
  while (k >= 0);

  dw_free(tv_dims);

  return translation;
}

/*
   Assumes:
     not_time_varying : pointer to integer.
     n_coef           : pointer to integer array.  *n_coef should be unallocated.
     cum_total_coef   : pointer to integer array.  *cum_total_coef should be unallocated.
     idx_coef         : pointer to integer matrix.  *idx_coef should be unallocated.
     n_var            : pointer to integer array.  *n_var should be unallocated.
     cum_total_var    : pointer to integer array.  *cum_total_var should be unallocated.
     idx_var          : pointer to integer matrix.  *idx_var should be unallocated.
     f_in             : pointer to valid file sturcture.
     sv               : pointer to valid TMarkovStateVariable structure.

   Returns:
     One upon success and zero otherwise.

   Results:
     Upon success, *not_time_varying is set and memory is allocated for *n_coef, 
     *cum_total_coef, *idx_coef, *n_var, *cum_total_var, and *idx_var.  Upon 
     failure, theses are set to null.  

   Notes:
     Upon success, the calling routines should free the allocated memory.  The 
     routine dw_FreeArray() MUST be used to free *n_coef, *cum_total_coef, 
     *idx_coef, *n_var, *cum_total_var, and *idx_var.

     The total number of coefficient variables can be obtained by the call 
     dw_DimA(n_coef) and will be zero if n_coef is null.  The total number 
     of variance variables can be obtained by the call dw_DimA(n_var) and 
     will be zero if n_var is zero.

     (*n_coef)[i] is the number of regimes associated with the ith coefficient 
       parameter.

     (*cum_total_coef)[i] is the offset of the ith coefficient parameter.  Note 
       that (*cum_total_coef)[i] + (*n_coef)[i] = *cum_total_coef[i+1].

     (*idx_coef)[k][i] is the regime of the ith coefficient parameter associated
       with grand regime k.

     (*n_var)[i] is the number of regimes associated with the ith variance 
       parameter.

     (*cum_total_var)[i] is the offset of the ith variance parameter.  Note that
       (*cum_total_var)[i] + (*n_var)[i] = *cum_total_var[i+1].

     (*idx_var)[k][i] is the regime of the ith variable parameter associated with
       grand regime k.
*/
int ReadDSGEControllingVariables(int *not_time_varying, int **n_coef, int **cum_total_coef, int*** idx_coef,
				 int **n_var, int **cum_total_var, int ***idx_var, FILE *f_in, TMarkovStateVariable *sv)
{
  int j, k, m, err=0, offset, ncoef, nvar, tv;
  int *tv_dim, **table=(int**)NULL;
  char *str;

  *idx_coef=(int**)NULL;
  *n_coef=(int*)NULL;;
  *cum_total_coef=(int*)NULL;
  *idx_var=(int**)NULL;
  *n_var=(int*)NULL;;
  *cum_total_var=(int*)NULL;

  if (!f_in) return 0;

  tv=GetTotalNumberStateVariablesIncludingLags(sv);
  tv_dim=(int*)dw_malloc(tv*sizeof(int));
  GetDimStateVariablesIncludingLags(tv_dim,sv);

  // Read number of free parameters not time varying
  if ((err=ReadInteger(f_in,(char*)NULL,str="//== Number of free parameters not time varying ==//",not_time_varying)))
    goto CLEAN_UP;
  else
    if (*not_time_varying < 0)
      {
	err=SWITCHIO_ERROR_READING_DATA;
	goto CLEAN_UP;
      }
  offset=*not_time_varying;

  // Read time varying coefficient parameters
  if ((err=ReadInteger(f_in,(char*)NULL,str="//== Time varying coefficient parameters ==//",&ncoef)))
    goto CLEAN_UP;
  else
    if (ncoef < 0)
      {
	err=SWITCHIO_ERROR_READING_DATA;
	goto CLEAN_UP;
      }
  if (ncoef > 0)
    {
      if (!dw_ReadArray(f_in,table=dw_CreateRectangularArray_int(ncoef,tv)))
	{
	  err=SWITCHIO_ERROR_READING_DATA;
	  goto CLEAN_UP;
	}

      *idx_coef=CreateTranslationMatrix(table,sv);

      *n_coef=dw_CreateArray_int(ncoef);
      *cum_total_coef=dw_CreateArray_int(ncoef);
      for (j=0; j < ncoef; j++)
	{
	  (*cum_total_coef)[j]=offset;
	  for (m=1, k=0; k < tv; k++)
	    if (table[j][k]) m*=tv_dim[k];
	  (*n_coef)[j]=m;
	  offset+=m;
	}

      dw_FreeArray(table);
      table=(int**)NULL;
    }

  // Read time varying variance parameters
  if ((err=ReadInteger(f_in,(char*)NULL,str="//== Time varying variance parameters ==//",&nvar)))
    goto CLEAN_UP;
  else
    if (nvar < 0)
      {
	err=SWITCHIO_ERROR_READING_DATA;
	goto CLEAN_UP;
      }
  if (nvar > 0)
    {
      if (!dw_ReadArray(f_in,table=dw_CreateRectangularArray_int(nvar,tv)))
	{
	  err=SWITCHIO_ERROR_READING_DATA;
	  goto CLEAN_UP;
	}

      *idx_var=CreateTranslationMatrix(table,sv);

      *n_var=dw_CreateArray_int(nvar);
      *cum_total_var=dw_CreateArray_int(nvar);
      for (j=0; j < nvar; j++)
	{
	  (*cum_total_var)[j]=offset;
	  for (m=1, k=0; k < tv; k++)
	    if (table[j][k]) m*=tv_dim[k];
	  (*n_var)[j]=m;
	  offset+=m;
	}

      dw_FreeArray(table);
      table=(int**)NULL;
    }

  return 1;

CLEAN_UP:
  if (table) dw_FreeArray(table);
  if (*idx_coef) 
    {
      dw_FreeArray(*idx_coef);
      *idx_coef=(int**)NULL;
    }
  if (*n_coef)  
    {
      dw_FreeArray(*n_coef);
      *n_coef=(int*)NULL;
    }
  if (*cum_total_coef)  
    {
      dw_FreeArray(*cum_total_coef);
      *cum_total_coef=(int*)NULL;
    }
  if (*idx_var)  
    {
      dw_FreeArray(*idx_var);
      *idx_var=(int**)NULL;
    }
  if (*n_var)  
    {
      dw_FreeArray(*n_var);
      *n_var=(int*)NULL;
    }
  if (*cum_total_var)  
    {
      dw_FreeArray(*cum_total_var);
      *cum_total_var=(int*)NULL;
    }
  return 0;
}
/*******************************************************************************/
/*******************************************************************************/
/*******************************************************************************/


/*
   Assumes
     states -  An m x sv->n_state_variables array of integers.  The integer 
               states[j][k] will be non-zero if the kth state effects the jth 
               group.
     sv     -  Valid pointer to TMarkovStateVariable structure.  It must be the 
               case that the number of columns in states is equal to 
               sv->n_state_variables.

   Returns
     An m x nstates array of integers that is a translation from the values of
     the state variable sv to the state variable that is a product of the state
     variables with non-zero entries in states. 
*/
/* static int** CreateTranslationMatrix_Flat_old(int **table, TMarkovStateVariable *sv) */
/* { */
/*   int **translation; */
/*   int i, j, k; */
/*   translation=dw_CreateRectangularArray_int(dw_DimA(table),sv->nstates); */

/*   for (j=dw_DimA(table)-1; j >= 0; j--) */
/*     for (i=sv->nstates-1; i >= 0; i--) */
/*       for (translation[j][i]=k=0; k < sv->n_state_variables; k++) */
/* 	if (table[j][k])  */
/* 	  translation[j][i]=translation[j][i]*sv->state_variable[k]->nstates + sv->index[i][k]; */

/*   return translation; */
/* } */
/*
   Assumes:
     not_time_varying : pointer to integer.
     n_coef           : pointer to integer array.  *n_coef should be unallocated.
     cum_total_coef   : pointer to integer array.  *cum_total_coef should be unallocated.
     idx_coef         : pointer to integer matrix.  *idx_coef should be unallocated.
     n_var            : pointer to integer array.  *n_var should be unallocated.
     cum_total_var    : pointer to integer array.  *cum_total_var should be unallocated.
     idx_var          : pointer to integer matrix.  *idx_var should be unallocated.
     f_in             : pointer to valid file sturcture.
     sv               : pointer to valid TMarkovStateVariable structure.

   Returns:
     One upon success and zero otherwise.

   Results:
     Upon success, *not_time_varying is set and memory is allocated for *n_coef, 
     *cum_total_coef, *idx_coef, *n_var, *cum_total_var, and *idx_var.  Upon 
     failure, theses are set to null.  

   Notes:
     Upon success, the calling routines should free the allocated memory.  The 
     routine dw_FreeArray() MUST be used to free *n_coef, *cum_total_coef, 
     *idx_coef, *n_var, *cum_total_var, and *idx_var.

     The total number of coefficient variables can be obtained by the call 
     dw_DimA(n_coef) and will be zero if n_coef is null.  The total number 
     of variance variables can be obtained by the call dw_DimA(n_var) and 
     will be zero if n_var is zero.

     (*n_coef)[i] is the number of regimes associated with the ith coefficient 
       parameter.

     (*cum_total_coef)[i] is the offset of the ith coefficient parameter.  Note 
       that (*cum_total_coef)[i] + (*n_coef)[i] = *cum_total_coef[i+1].

     (*idx_coef)[k][i] is the regime of the ith coefficient parameter associated
       with grand regime k.

     (*n_var)[i] is the number of regimes associated with the ith variance 
       parameter.

     (*cum_total_var)[i] is the offset of the ith variance parameter.  Note that
       (*cum_total_var)[i] + (*n_var)[i] = *cum_total_var[i+1].

     (*idx_var)[k][i] is the regime of the ith variable parameter associated with
       grand regime k.
*/
int ReadDSGEControllingVariables_old(int *not_time_varying, int **n_coef, int **cum_total_coef, int*** idx_coef,
				     int **n_var, int **cum_total_var, int ***idx_var, FILE *f_in, TMarkovStateVariable *sv)
{
  int j, k, m, err=0, offset, ncoef, nvar;
  int **table=(int**)NULL;
  char *str;

  *idx_coef=(int**)NULL;
  *n_coef=(int*)NULL;;
  *cum_total_coef=(int*)NULL;
  *idx_var=(int**)NULL;
  *n_var=(int*)NULL;;
  *cum_total_var=(int*)NULL;

  if (!f_in) return 0;

  // Read number of free parameters not time varying
  if ((err=ReadInteger(f_in,(char*)NULL,str="//== Number of free parameters not time varying ==//",not_time_varying)))
    goto CLEAN_UP;
  else
    if (*not_time_varying < 0)
      {
	err=SWITCHIO_ERROR_READING_DATA;
	goto CLEAN_UP;
      }
  offset=*not_time_varying;

  // Read time varying coefficient parameters
  if ((err=ReadInteger(f_in,(char*)NULL,str="//== Time varying coefficient parameters ==//",&ncoef)))
    goto CLEAN_UP;
  else
    if (ncoef < 0)
      {
	err=SWITCHIO_ERROR_READING_DATA;
	goto CLEAN_UP;
      }
  if (ncoef > 0)
    {
      if (!dw_ReadArray(f_in,table=dw_CreateRectangularArray_int(ncoef,sv->n_state_variables)))
	{
	  err=SWITCHIO_ERROR_READING_DATA;
	  goto CLEAN_UP;
	}
      *idx_coef=CreateTranslationMatrix(table,sv);
      *n_coef=dw_CreateArray_int(ncoef);
      *cum_total_coef=dw_CreateArray_int(ncoef);
      for (j=0; j < ncoef; j++)
	{
	  (*cum_total_coef)[j]=offset;
	  for (m=1, k=0; k < sv->n_state_variables; k++)
	    if (table[j][k]) m*=sv->state_variable[k]->nstates;
	  (*n_coef)[j]=m;
	  offset+=m;
	}
      dw_FreeArray(table);
      table=(int**)NULL;
    }

  // Read time varying variance parameters
  if ((err=ReadInteger(f_in,(char*)NULL,str="//== Time varying variance parameters ==//",&nvar)))
    goto CLEAN_UP;
  else
    if (nvar < 0)
      {
	err=SWITCHIO_ERROR_READING_DATA;
	goto CLEAN_UP;
      }
  if (nvar > 0)
    {
      if (!dw_ReadArray(f_in,table=dw_CreateRectangularArray_int(nvar,sv->n_state_variables)))
	{
	  err=SWITCHIO_ERROR_READING_DATA;
	  goto CLEAN_UP;
	}
      *idx_var=CreateTranslationMatrix(table,sv);
      *n_var=dw_CreateArray_int(nvar);
      *cum_total_var=dw_CreateArray_int(nvar);
      for (j=0; j < nvar; j++)
	{
	  (*cum_total_var)[j]=offset;
	  for (m=1, k=0; k < sv->n_state_variables; k++)
	    if (table[j][k]) m*=sv->state_variable[k]->nstates;
	  (*n_var)[j]=m;
	  offset+=m;
	}
      dw_FreeArray(table);
      table=(int**)NULL;
    }

  return 1;

CLEAN_UP:
  if (table) dw_FreeArray(table);
  if (*idx_coef) 
    {
      dw_FreeArray(*idx_coef);
      *idx_coef=(int**)NULL;
    }
  if (*n_coef)  
    {
      dw_FreeArray(*n_coef);
      *n_coef=(int*)NULL;
    }
  if (*cum_total_coef)  
    {
      dw_FreeArray(*cum_total_coef);
      *cum_total_coef=(int*)NULL;
    }
  if (*idx_var)  
    {
      dw_FreeArray(*idx_var);
      *idx_var=(int**)NULL;
    }
  if (*n_var)  
    {
      dw_FreeArray(*n_var);
      *n_var=(int*)NULL;
    }
  if (*cum_total_var)  
    {
      dw_FreeArray(*cum_total_var);
      *cum_total_var=(int*)NULL;
    }
  return 0;
}

/*******************************************************************************/
/*******************************************************************************/
/*******************************************************************************/


/*******************************************************************************/
/****************************** Utility Routines *******************************/
/*******************************************************************************/
/*
   Assumes:
     format : null or "*%s*"
     str    : "*"
     err    : error flag

   Results:
     Assembles error message and calls error routines.  If USER_ERR is a verbose
     error, then an error message is displayed.  If USER_ERR is a terminal error
     the the program will terminate.  
*/
void ReadError(char *format, char *str, int err)
{
  char *errmsg, *errmsg_format, *buffer;
  switch (err)
    {
    case SWITCHIO_LINE_ID_NOT_FOUND:
      errmsg_format="Line identifier ""%s"" not found.";
      break;
    case SWITCHIO_ERROR_READING_DATA:
      errmsg_format="Error reading data after line identifier ""%s"".";
      break;
    case SWITCHIO_FILE_ERROR:
      if (str)
	{
	  errmsg_format="Error reading/opening %s.";
	  sprintf(errmsg=(char*)dw_malloc(strlen(errmsg_format)+strlen(str)-1),errmsg_format,str);
	  dw_UserError(errmsg);
	  dw_free(errmsg);
	}
      else
	dw_Error(FILE_ERR);
    case 0:
      return;
    default:
      dw_Error(UNKNOWN_ERR);
      return;
    }
  if (format)
    sprintf(buffer=(char*)dw_malloc(strlen(format)+strlen(str)-1),format,str);
  else
    buffer=str;
  sprintf(errmsg=(char*)dw_malloc(strlen(errmsg_format)+strlen(buffer)-1),errmsg_format,buffer);
  if (buffer != str) dw_free(buffer);
  dw_UserError(errmsg);
  dw_free(errmsg);
}

/*
   Assumes
     f_in   : pointer to valid file structure
     format : "*%s*" or null 
     str    : "*" 

   Returns:
     Zero upon success and SWITCHIO_LINE_ID_NOT_FOUND upon failure.   

   Results
     Starting at the current position, and wrapping around the end of the file if
     necessary, finds the first occurance of the string at the beginning of a 
     line.  Upon success, the file pointer is positioned at the beginning of the 
     next line.
*/
int SetFilePosition(FILE *f_in, char *format, char *str)
{
  char *buffer;
  int rtrn;
  if (format)
    sprintf(buffer=(char*)dw_malloc(strlen(format)+strlen(str)-1),format,str);
  else
    buffer=str;
  rtrn=dw_SetFilePosition(f_in,buffer);
  if (buffer != str) dw_free(buffer);
  return rtrn ? 0 : SWITCHIO_LINE_ID_NOT_FOUND;
}

/*
   Assumes
     f_in   : pointer to valid file structure
     format : "*%s*" or null 
     str    : "*" 
     i      : pointer to integer

   Returns:
     Zero upon success and SWITCHIO_LINE_ID_NOT_FOUND or 
     SWITCHIO_ERROR_READING_DATA on failure.   

   Results
     Attempts to read integer from the first line following the first occurance 
     of the string at the beginning of a line.
*/
int ReadInteger(FILE *f_in, char *format, char *str, int *i)
{
  if (SetFilePosition(f_in,format,str)) return SWITCHIO_LINE_ID_NOT_FOUND;
  return (fscanf(f_in," %d ",i) == 1) ? 0 : SWITCHIO_ERROR_READING_DATA;
}

/*
   Assumes
     f_in   : pointer to valid file structure
     format : "*%s*" or null 
     str    : "*" 
     X      : pointer to valid matrix structure

   Returns:
     Zero upon success and SWITCHIO_LINE_ID_NOT_FOUND or 
     SWITCHIO_ERROR_READING_DATA on failure.   

   Results
     Attempts to read integer from the first line following the first occurance 
     of the string at the beginning of a line.
*/
int ReadMatrix(FILE *f_in, char *format, char *str, TMatrix X)
{
  if (SetFilePosition(f_in,format,str)) return SWITCHIO_LINE_ID_NOT_FOUND;
  return dw_ReadMatrix(f_in,X) ? 0 : SWITCHIO_ERROR_READING_DATA;
}

/*
   Assumes
     f_in   : pointer to valid file structure
     format : "*%s*" or null 
     str    : "*" 
     v      : pointer to valid vector structure

   Returns:
     Zero upon success and SWITCHIO_LINE_ID_NOT_FOUND or 
     SWITCHIO_ERROR_READING_DATA on failure.   

   Results
     Attempts to read integer from the first line following the first occurance 
     of the string at the beginning of a line.
*/
int ReadVector(FILE *f_in, char *format, char *str, TVector v)
{
  if (SetFilePosition(f_in,format,str)) return SWITCHIO_LINE_ID_NOT_FOUND;
  return dw_ReadVector(f_in,v) ? 0 : SWITCHIO_ERROR_READING_DATA;
}

/*
   Assumes
     f_in   : pointer to valid file structure
     format : "*%s*" or null 
     str    : "*" 
     A      : pointer to valid integer array

   Returns:
     Zero upon success and SWITCHIO_LINE_ID_NOT_FOUND or 
     SWITCHIO_ERROR_READING_DATA on failure.   

   Results
     Attempts to read integer from the first line following the first occurance 
     of the string at the beginning of a line.
*/
int ReadIntArray(FILE *f_in, char *format, char *str, void *X)
{
  if (SetFilePosition(f_in,format,str)) return SWITCHIO_LINE_ID_NOT_FOUND;
  return dw_ReadArray(f_in,X) ? 0 : SWITCHIO_ERROR_READING_DATA;
}

/*
   Assumes
     format - either null or null terminated string of the form "*%s*%d" or "*%d*"
     str    - either null or null terminated string
     k      - integer

   Returns
     Allocates memory and returns null terminated string using the supplied 
     format.

   Notes
     Calling routine is responsible for freeing returned memory.  If both
     format and str are not null, then format must be of the form "*%s*%d*".  If
     format is not null but str is null, then format must be of the form "*%d*".
*/
char* CreateIntegerString(char *format, char *str, int k)
{
  int i, j;
  char *buffer;
  for (j=10, i=1; k >= j; j*=10, i++);
  if (format)
    if (str)
      sprintf(buffer=(char*)dw_malloc(strlen(format)+strlen(str)+i-3),format,str,k);
    else
      sprintf(buffer=(char*)dw_malloc(strlen(format)+i-1),format,k);
  else
    sprintf(buffer=(char*)dw_malloc(i+1),"%d",k);
  return buffer;
}
/*******************************************************************************/
/*******************************************************************************/
/*******************************************************************************/
