/********************************************************************************************************
 * QRNA - Comparative analysis of biological sequences 
 *         with pair hidden Markov models, pair stochastic context-free
 *        grammars, and probabilistic evolutionary  models.
 *       
 * Version 2.0.0 (JUN 2003)
 *
 * Copyright (C) 2000-2003 Howard Hughes Medical Institute/Washington University School of Medicine
 * All Rights Reserved
 * 
 *     This source code is distributed under the terms of the
 *     GNU General Public License. See the files COPYING and LICENSE
 *     for details.
 ***********************************************************************************************************/

/* codmodel.c
 *
 * E. Rivas [St. Louis]
 * 
 * 9 april 1999.
 * 
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>

#include "funcs.h"
#include "globals.h"
#include "squid.h"
#include "structs.h"

#ifdef MEMDEBUG
#include "dbmalloc.h"
#endif

static double   normalizecodparam(struct codparam_s codparam);
static double **cod_A_transfermatrix(struct codparam_s codparam, int dim);
static double  *cod_B_transfermatrix(struct codparam_s codparam, int dim);
static double **cod_A_transfermatrix_at_infty(double **T, double **T_zero, int dim);
static double  *cod_B_transfermatrix_at_infty(double **T, double **T_zero, int dim);
static double **cod_A_transfermatrix_rate(int dim);
static double  *cod_B_transfermatrix_rate(int dim);
static double **cod_A_transfermatrix_Rdiag(int dim);
static double  *cod_B_transfermatrix_Rdiag(int dim);


/* Function: AllocCODModel()
 * Date:     ER,  Mon Jun  7 11:46:48 CDT 1999 [St. Louis]
 *
 * Purpose:  Allocates memory for the transition and emission probs of the codingmodel
 *
 * Args:     codmodel - codmodel structure
 *
 * Returns:  void
 *           allocates cod->t[], cod->pcodon[], which must be free'd by caller.
 */
struct codmodel_s *
AllocCODModel(void)
{
  struct codmodel_s *cod;    /* codmodel structure           */
  int                codx;   /* symbols for codon prob's     */

  cod              = (struct codmodel_s *)  MallocOrDie (sizeof(struct codmodel_s));
  cod->t           = (double  *)            MallocOrDie (sizeof(double  ) * CTRANS);
  cod->pmut        = (double  *)            MallocOrDie (sizeof(double  ) * 16);
  cod->pcodon      = (double **)            MallocOrDie (sizeof(double *) * 64);
  cod->pcodon[0]   = (double  *)            MallocOrDie (sizeof(double  ) * 64 * 64);
  cod->phexa       = (double **)            MallocOrDie (sizeof(double *) * 64);
  cod->phexa[0]    = (double  *)            MallocOrDie (sizeof(double  ) * 64 * 64);

  cod->COB = AllocOTHModel();
  cod->COJ = AllocOTHModel();
  cod->COE = AllocOTHModel();

  for (codx = 1; codx < 64; codx++) {
    cod->pcodon[codx] = cod->pcodon[0] + codx * 64;
    cod->phexa[codx]  = cod->phexa[0]  + codx * 64;
  }

  PatternCODModel(cod);
  
  return cod;
}

struct pamcond_s *
AllocPamCond(void)
{
  struct pamcond_s *pamcond;
  int               codx, cody;

  pamcond = (struct pamcond_s *)  MallocOrDie (sizeof(struct pamcond_s));

  pamcond->pXY    = (double **) MallocOrDie (sizeof(double *) * 64);
  pamcond->pYX    = (double **) MallocOrDie (sizeof(double *) * 64);
  pamcond->pXY[0] = (double  *) MallocOrDie (sizeof(double  ) * 64 * 64);
  pamcond->pYX[0] = (double  *) MallocOrDie (sizeof(double  ) * 64 * 64);

  for (codx = 1; codx < 64; codx++) {
    pamcond->pXY[codx] =  pamcond->pXY[0] + codx * 64;
    pamcond->pYX[codx] =  pamcond->pYX[0] + codx * 64;
  }
  
  /* Initialize */
  for (codx = 0; codx < 64; codx++) 
    for (cody = 0; cody < 64; cody++) {
      pamcond->pXY[codx][cody] = 0.0;
      pamcond->pYX[codx][cody] = 0.0;
    }

  return pamcond;
}

/* Function: CheckCODProbs()
 * Date:     ER, Mon Jun  7 12:18:45 CDT 1999 [St. Louis]
 *
 * Purpose:  Verify that transition and emission prob's of a codmodel add up to one
 *
 * Args:     cod - the structure for an codmodel
 *
 * Returns:  void. 
 */
void
CheckCODProbs(struct codmodel_s *cod)
{
  int    idx;               /* index for transition prob's      +*/
  int    st;                /* state we are at                  +*/
  double sum;

  /* check transition prob's add up to one
   */
  for (st = 0; st < CSTATES; st++) {
    sum = 0.0; 
    for (idx = IdxTransCOD[st]; idx < IdxTransCOD[st]+TransPerCODState[st]; idx++) 
      {
	switch (idx) {
	case stC34: sum += 4.0 * cod->t[idx]; break; 
	case stC43: sum += 4.0 * cod->t[idx]; break; 
	case stC32: sum += 3.0 * cod->t[idx]; break; 
	case stC23: sum += 3.0 * cod->t[idx]; break; 
	default:  sum += cod->t[idx];         break; 
	}
      }
    
    if (sum > 2.-accuracy || sum < accuracy) {
      printf("N %d %d\n", IdxTransCOD[st], TransPerCODState[st]);
      for (idx = IdxTransCOD[st]; idx < IdxTransCOD[st]+TransPerCODState[st]; idx++) 
	printf("idx %d %f\n", idx, cod->t[idx]);
      Die("CheckCODProbs(): transition prob's sum for state %d(%s) is %f \n", st, cstNAME[st], sum); 
    }
  }
  
  /* check emission prob's add up to one
   */
  CheckSingleProb(cod->pmut, 16);
  CheckDoubleProb(cod->pcodon, 64, 64);
}

/* Function: CheckPAMModel()
 * Date:     SRE, Wed Jun 10 13:40:01 1998 [St. Louis]
 *
 * Purpose:  Verify that a PAM model is OK
 *
 * Args:     pammodel - model to check [64][64]
 *
 * Returns:  void. prints stuff.
 */
void
CheckPAMModel(double **pammodel)
{
  int x, y;
  double sum = 0.0;

  for (x = 0; x < 64; x++)
    for (y = 0; y < 64; y++)
      sum += pammodel[x][y];

  if (sum > 1.01 || sum < 0.99) Die ("pam sum is %f\n", sum);
}

/* Function: CODToLog2()
 * Date:     ER, Mon Jun  7 12:24:32 CDT 1999 [St. Louis]
 *
 * Purpose:  Converts transition and emission prob's of a codmodel to log2 form
 *
 * Args:     cod - the structure for a codmodel
 *
 * Returns:  void. 
 */
void
CODToLog2(struct codmodel_s *cod)
{
  int idx;   /* index for transition prob's      +*/
  int x,y;   /* symbols for emission prob's      +*/

  /* transition prob's 
   */
  for (idx = 0; idx < CTRANS; idx++) 
    cod->t[idx] = LOG2(cod->t[idx]);
  
  /* emission prob's 
   */
  for (x = 0; x < 16; x++) 
    cod->pmut[x] = LOG2(cod->pmut[x]);
  for (x = 0; x < 64; x++) 
    for (y = 0; y < 64; y++) 
      cod->pcodon[x][y] = LOG2(cod->pcodon[x][y]);

}

/* Function: CODLog2ToOdds()
 * Date:     ER, Mon Jun  7 12:22:42 CDT 1999 [St. Louis]
 *
 * Purpose:  Converts transition and emission prob's of a codingmodel
 *           from log2 to log2odds form
 *
 * Args:     coding - the structure for an codingmodel
 *
 * Returns:  void. 
 */
void
CODLog2ToOdds(struct codmodel_s *cod, struct nullmodel_s *null)
{
  int    st;          /* index for states                   +*/
  int    tr;          /* index for transitions              +*/
  int    emit;        /* number of emissions per state      +*/
  int    x, y;        /* symbols for emission prob's        +*/
  
  OTHLog2ToOdds(cod->COB, null);
  OTHLog2ToOdds(cod->COJ, null);
  OTHLog2ToOdds(cod->COE, null);

  /* transition prob's 
   */
  for (st = 0; st < CSTATES; st++) {

    emit = EmitsPerCODState[st];
    /* [emit =   1] ==> no emission    or 
     * [emit = 4^x] ==> x  emissions   
     */
    if (emit%4 == 0)
      for (tr = IdxTransCOD[st]; tr < IdxTransCOD[st]+TransPerCODState[st]; tr++)
	cod->t[tr] -= 0.5 * LOG2(emit) * null->meta;   
    else if (emit != 1)
      Die ("wrong number of emissions (%d) for state %s", emit, cstNAME[st]);
  }

  /* emission prob's 
   */
  for (x = 0; x < 16; x++) 
    cod->pmut[x] -= (null->xem[x/4] + null->yem[x%4]);
  for (x = 0; x < 64; x++) 
    for (y = 0; y < 64; y++) 
      cod->pcodon[x][y] -= (null->xem[x/16] + null->xem[(x%16)/4] + null->xem[x%4] +
			    null->yem[y/16] + null->yem[(y%16)/4] + null->yem[y%4]);

}

/* Function: ConstructCODModel()
 * Date:     ER, Sat Jun  5 08:54:20 CDT 1999  [St. Louis]
 *
 * Purpose:  Constructs a codingmodel_s
 *
 * Args:     codingparam - the list of parameters that define a codingmodel           
 *
 * Returns:  (void)
 *           fills all prob's for othermodel, log2 form 
 *           (allc'ed here, freed by caller)
 */
void
ConstructCODModel(double **pammodel_star, int **pam, double scale, double *codon_joint, int add_codon, double **hexa, int win, double tfactor, 
		  double *targetfreq, int changefreq, struct codmodel_s *cod, int add_hexamer, int pedantic, int verbose)
{
  double           **pammodel;
  double            *mutpxy_cod;
  double            *mut5pxy_cod;
  double             ave_len_COB;             /* expected length of the other models */
  double             ave_len_COE;
  double             ave_len_COJ;
  double             ave_len_COB_zero;             /* expected length of the other models */
  double             ave_len_COE_zero;
  double             ave_len_COJ_zero;
  double             ave_len_COB_infty;             /* expected length of the other models */
  double             ave_len_COE_infty;
  double             ave_len_COJ_infty;

  if (verbose) printf("Construct COD Model at time = %.4f\n", tfactor);

  ConstructTimeDependentPAMModel(pam, scale, tfactor, codon_joint, &pammodel, add_codon, pedantic, verbose);
  ConstructTiedProbs(pammodel_star, tfactor, &mutpxy_cod, &mut5pxy_cod, targetfreq, changefreq, pedantic, verbose);
  if (verbose) PrintPAMModel (pammodel, mutpxy_cod); 

  /* the oth model has a paramente tau that set the invers of the average length generated by those models
   * This is how I set them as a few percentages of the length under analysis. This parameter does not evolve
   */
  ave_len_COB_zero = EXP2(0.25*LOG2(win));
  ave_len_COE_zero = EXP2(0.25*LOG2(win));
  ave_len_COJ_zero = EXP2(0.25*LOG2(win));
  
  ave_len_COB       = EXP2(1.00*LOG2(ave_len_COB_zero));
  ave_len_COE       = EXP2(1.00*LOG2(ave_len_COE_zero));
  ave_len_COJ       = EXP2(1.00*LOG2(ave_len_COJ_zero));
  
  ave_len_COB_infty = EXP2(1.00*LOG2(ave_len_COB_zero));
  ave_len_COE_infty = EXP2(1.00*LOG2(ave_len_COE_zero));
  ave_len_COJ_infty = EXP2(1.00*LOG2(ave_len_COJ_zero));
  
  ConstructOTHModel(pammodel_star, COBparam, COBparam_zero, COBparam_infty, ave_len_COB, ave_len_COB_zero, ave_len_COB_infty, 
		    tfactor, targetfreq, changefreq, cod->COB, pedantic, verbose);
  ConstructOTHModel(pammodel_star, COJparam, COJparam_zero, COJparam_infty, ave_len_COJ, ave_len_COJ_zero, ave_len_COJ_infty, 
		    tfactor, targetfreq, changefreq, cod->COJ, pedantic, verbose);
  ConstructOTHModel(pammodel_star, COEparam, COEparam_zero, COEparam_infty, ave_len_COE, ave_len_COE_zero, ave_len_COE_infty, 
		    tfactor, targetfreq, changefreq, cod->COE, pedantic, verbose);
  
  
  /* 24 JUL 02
   *
   * The evolutionary COD model is as follows: T = T^A X T^B
   *
   *       - A 2x2 matrix for transitions T^A              Cb      COE                          
   *                                               COB  |  psi    1-psi |
   *                                     T^A =          |               |
   *                                                Ce  | 1-eta    eta  |
   * 
   *
   *               at t=0                               |  1        0   |
   *                                   T^A_0 =          |               |
   *                                                    |  0        1   |
   *
   *
   *      - A 17x17 matrix for transitions T^B                 xi_1    xi_2  ...  xi_16   Ce
   *                                                     Cb | T_b1      ...       T_b6     0  |
   *                                                   xi_1 |  0        ...         0      1  |
   *                                           T^B =     .  |  0        ...         0      1  |
   *                                                     .  |  0        ...         0      1  |
   *                                                     .  |  0        ...         0      1  |
   *                                                 xi_16  |  0        ...         0      1  |
   *
   *                 at t=0                           
   *                                                     Cb | T0_b1     ...       T0_b6    0  |
   *                                                   xi_1 |  0        ...         0      1  |
   *                                         T^B_0 =     .  |  0        ...         0      1  |
   *                                                     .  |  0        ...         0      1  |
   *                                                     .  |  0        ...         0      1  |
   *                                                 xi_16  |  0        ...         0      1  |
   *
   *
   *
   *
   *
   *              parametric family:      T = T_0 exp [tA] with T_0 = T^A_0 X T^B_0
   *
   */
  CODmodelTransitionProbabilities(win, tfactor, cod, pedantic, verbose);  
 
  /* Calculate emission prob's: model.mem[], model.xem[], model.yem[]
   */
  ConstructCODEmitProbs(pammodel, cod->pmut, cod->pcodon);
  
  /* check prob's add up to one
   */
  CheckCODProbs(cod);
  
  /* convert to Log2 form
   */
  CODToLog2(cod);

  ConstructHexamerProbs(hexa, cod->phexa, add_hexamer);

  /* Print Transition Probabilities if asked for it
   */
  if (FALSE) PrintCODTrProbs(cod);
  if (FALSE) PrintCODModel(cod);

  /* free memory */
  FreePAMModel(pammodel);
  free(mutpxy_cod);
  free(mut5pxy_cod);

}


/* Function: ConstructCODEmitProbs()
 * Date:     ER, Mon Jun  7 12:03:23 CDT 1999 [St. Louis]
 *
 * Purpose:  construct codon probs
 *
 * Args:     pammodel  - 64x64 AAA..UUUxAAA..UUU joint prob matrix (prealloc)
 *           pm        - 4x4 A..UxA..U joint prob matrix (prealloc)           
 *
 * Returns:  (void)
 *           Fills in other->mem. (already allocated)
 */
void
ConstructCODEmitProbs(double **pammodel, double *pmut, double **pcodon)
{
  int     x, y;
  int     x1, x2, x3;
  int     y1, y2, y3;

  for (x1 = 0; x1 < 4; x1++)
    for (y1 = 0; y1 < 4; y1++)
      pmut[idx(x1,y1)] = 0.0;

  /* Marginalize and average over three positions
   */
  for (x1 = 0; x1 < 4; x1++)
    for (x2 = 0; x2 < 4; x2++)
      for (x3 = 0; x3 < 4; x3++)
	for (y1 = 0; y1 < 4; y1++)
	  for (y2 = 0; y2 < 4; y2++)
	    for (y3 = 0; y3 < 4; y3++)
	      {
		pmut[idx(x1,y1)] += pammodel[CODON(x1,x2,x3)][CODON(y1,y2,y3)] / 3.0;
		pmut[idx(x2,y2)] += pammodel[CODON(x1,x2,x3)][CODON(y1,y2,y3)] / 3.0;
		pmut[idx(x3,y3)] += pammodel[CODON(x1,x2,x3)][CODON(y1,y2,y3)] / 3.0;

	      }
  CheckSingleProb(pmut, 16);

  for (x = 0; x < 64; x++)
    for (y = 0; y < 64; y++) 
      pcodon[x][y] = pammodel[x][y];

  CheckDoubleProb(pcodon, 64, 64);

}

/* Function: ConstructESTModel()
 * Date:     SRE, Wed Jun 10 08:46:06 1998 [St. Louis]
 *
 * Purpose:  Return an estmodel: a 20x64 matrix for P(xyz | a),
 *           for converting an amino acid into a distribution
 *           over possible codons. Incorporates an error
 *           model as well as a codon bias model.
 *
 * Derivation:
 *           call observed codon x
 *           call actual codon y
 *           call actual amino acid a.
 *           want: P(x | a)
 *            
 *           P(x,a) = \sum_y P(x,y,a)     
 *           P(x,a) = \sum_y P(x | y,a) P(y,a)
 *           P(x,a) = \sum_y P(x | y,a) P(y | a) P(a)
 *                           ^ assume base errors independent of a
 *           P(x,a) = 
 *           P(x | a) P(a) =  \sum_y P(x | y) P(y | a) P(a)                 
 *           P(x | a) = \sum_y P(x | y) P(y | a) 
 *                   error model ^        ^ codon bias model
 *                   
 * Args:     accuracy - per-base sequence accuracy
 *           aacode   - genetic code, 0..63 lookup for aa indices 0..19
 *           codebias - 0..63 codon bias probabilities per aa
 *           estmodel - RETURN: [20][64] A..YxAAA..UUU P(x | a)
 *
 * Returns:  (void)
 *           Fills in the estmodel.
 */
void
ConstructESTModel(double **estmodel)
{
  int    *aacode;       /*          */
  double *codebias;     /*          */
  double pxy;		/* P(x | y) */
  int    x, y, a;	/* indices  */

  aacode   = (int    *) MallocOrDie (sizeof(int)    * 64);
  codebias = (double *) MallocOrDie (sizeof(double) * 64);

  DefaultGeneticCode(aacode);
  DefaultCodonBias(codebias);

  for (a = 0; a < 20; a++)
    for (x = 0; x < 64; x++)
      {
	estmodel[a][x] = 0.0;
	for (y = 0; y < 64; y++)
	  {
	    if (aacode[y] != a) continue; /* genetic code, P(y|a) = 0.0 */

				/* count mutations from y to x brute force */
	    pxy =   (x / 16 == y / 16)     ? accuracy : 1.0 - accuracy;
	    pxy *=  ((x%16)/4 == (y%16)/4) ? accuracy : 1.0 - accuracy;
	    pxy *=  (x%4 == y%4)           ? accuracy : 1.0 - accuracy;
    
	    estmodel[a][x] += pxy * codebias[y];
	  }
      }

  free(aacode);
  free(codebias);
}

/* Function: ConstructHexamerProbs()
 * Date:     ER, Fri Sep 15 17:55:30 CDT 2000 [St. Louis]
 *
 * Purpose:  construct codon probs
 *
 * Args:     hexa  - 64x64 AAA..UUUxAAA..UUU joint hexamer prob matrix (prealloc)
 *           phexa -   phexa(c1,c2) = hexa(c1,c2) / [p(c1)*p(c2)] (prealloc)           
 *
 * Returns:  (void)
 *           Fills in phexa. (already allocated)
 */
void
ConstructHexamerProbs(double **hexa, double **phexa, int add_hexamer)
{
  double *pc;
  int     i;
  int     c1, c2;

  if (!add_hexamer) 
    {
      for (c1 = 0; c1 < 64; c1++)
	for (c2 = 0; c2 < 64; c2++)
	  phexa[c1][c2] = 0.0;
      return;
    }

  else {
    
    pc = (double *) MallocOrDie (sizeof(double) * 64);
    
    /* initialization 
     */
    for (i = 0; i < 64; i++) pc[i] = 0.0;
    
    /* marginalize 
     */
    for (c1 = 0; c1 < 64; c1++)
      for (c2 = 0; c2 < 64; c2++) 
	pc[c1] += 0.5*EXP2(hexa[c2][c1]) + 0.5*EXP2(hexa[c1][c2]);
    
    /* check
     */
    CheckSingleProb(pc, 64);
    
    /* Transform hexamer frecuencies to 
     *
     *  phexa(c1,c2)/p(c1)*p(c2) in log2 form
     *  (these guys are odds-indepentent)
     *
     */
    for (c1 = 0; c1 < 64; c1++)
      for (c2 = 0; c2 < 64; c2++)
	phexa[c1][c2] = hexa[c1][c2] - LOG2(pc[c1]) - LOG2(pc[c2]);
    
    free(pc);
  }
}


/* Function: ConstructPAMModel()
 * Date:     ER, Thu Mar  2 22:47:21 CST 2000  [St. Louis]
 *           Modified from: SRE, Wed Jun 10 08:13:35 1998 [St. Louis]
 *
 * Purpose:  Given a substitution matrix, return a
 *           PAMmodel: a 64x64 joint probability matrix
 *           for codons aligned to codons.
 *           Modification: it allows to change the "time"
 *              
 *           Sean used P(a,b, t_o) = q(a) * q(b) e^{\lambada*S_ab}
 *
 *           Here we are allowed to calculate:
 *
 *                                P(a,b, rt_o) = P(b|a, t_o)^r * P(a, t_o)
 *      
 *             where: P(b|a, t_o) = P(a,b, t_o) / P(a)
 *
 *                    P(a, t_o)   = \sum_b P(a,b, t_o)
 *
 * Args:     pam      - 27x27 integer score matrix, alphabetic
 *           scale    - scale of pam matrix           
 *           aafq     - background amino acid frequencies 0..19
 *           estmodel - 64x20 AAA..UUUxA..Y P(xyz | a) conversion to codons
 *           pammodel - 64x64 AAA..UUUxAAA..UUU joint prob matrix (alloc'ed here)
 *
 * Returns:  (void)
 *           fills in pammodel.
 */
void
ConstructPAMModel(int **pam, double scale, double *codon_joint, double ***ret_pammodel, 
		  int add_codon, double *targetfreq, int changefreq, int pedantic, int verbose)
{
  double **pammodel;
  double **pamcond;
  double **pt2codon;
  double  *pcod;
  double  *pm;
  double **estmodel;
  double  *aajoint;	        /* joint       aa probs P(ab)    */
  double  *Id;
  double  *codonX;
  double  *codonY;
  double   sum;
  int      a, b;		/* 0..20 indices for amino acids */
  int      idxa, idxb;		/* 0..26 indices for amino acids */
  int      xyz, xyz1, xyz2;	/* indices for codons 0..63      */

   /* allocate pammodel[64][64]
   */
  estmodel    = (double **) MallocOrDie (sizeof(double *) * 20);
  pammodel    = (double **) MallocOrDie (sizeof(double *) * 64);
  pamcond     = (double **) MallocOrDie (sizeof(double *) * 64);
  pt2codon    = (double **) MallocOrDie (sizeof(double *) * 64);
  estmodel[0] = (double  *) MallocOrDie (sizeof(double  ) * 20 * 64);
  pammodel[0] = (double  *) MallocOrDie (sizeof(double  ) * 64 * 64);
  pamcond[0]  = (double  *) MallocOrDie (sizeof(double  ) * 64 * 64);
  aajoint     = (double  *) MallocOrDie (sizeof(double  ) * 64 * 64);
  pt2codon[0] = (double  *) MallocOrDie (sizeof(double  ) * 64 * 64);
  codonX      = (double  *) MallocOrDie (sizeof(double  ) * 64);
  codonY      = (double  *) MallocOrDie (sizeof(double  ) * 64);
  pcod        = (double  *) MallocOrDie (sizeof(double  ) * 64);
  pm          = (double  *) MallocOrDie (sizeof(double  ) * 4);

  if (verbose) {
    fprintf(stdout, "pam\n");
    for (a = 0; a < 20; a++)
      for (b = 0; b < 20; b++) 
	printf("%d ", pam[a][b]);
    fprintf(stdout, "\n");
  }   

  Id = Cal_Id (20);

  for (a = 1; a < 20; a++) estmodel[a] = estmodel[0] + a * 64;

  for (xyz = 1; xyz < 64; xyz++) {
    pammodel[xyz] = pammodel[0] + xyz * 64;
    pamcond[xyz]  = pamcond[0]  + xyz * 64;
    pt2codon[xyz] = pt2codon[0] + xyz * 64;
  }

  for (xyz = 1; xyz < 64; xyz++) 
    pcod[xyz] = 0.0;

  ConstructESTModel(estmodel);
  
  if (verbose) {
    fprintf(stdout, "estmodel probabilities\n");
    PrintProbs2D(stdout, estmodel, 20, 64);
  }

 /* Convert integer pam matrix back to joint probabilities P(ab)
  */
  sum = 0.0;
  for (a = 0; a < 20; a++)
    for (b = 0; b < 20; b++) {
      
      idxa = Alphabet[a] - 'A';
      idxb = Alphabet[b] - 'A';
      aajoint[a*20+b] = aafq[a] * aafq[b] * exp((double) pam[idxa][idxb] * scale);
      sum += aajoint[a*20+b];
    }

  /* normalize */
  for (a = 0; a < 20; a++)
    for (b = 0; b < 20; b++)
      aajoint[a*20+b] /= sum;
  CheckSingleProb(aajoint, 20*20);  
  
  if (verbose) {
    fprintf(stdout, "PAM(i,j, t^*) Joint probabilities\n");
    PrintProbs(stdout, aajoint, 20);
  }

  /* There is an additional term :
   *
   *                   pcodcod(c1,c2 |t^*) / [ pcod(c1) * pcod(c2) ]
   *
   *         Eventually, these at t = t^* will be given as an input. 
   *
   *         For now (21 AUG 02) we assume independence, so this term is 1.
   *
   */ 
  if (add_codon) {
    MarginalizeJointProbs(codon_joint, codonX, 64, 1);
    MarginalizeJointProbs(codon_joint, codonY, 64, 0);
  }

  for (xyz1 = 0; xyz1 < 64; xyz1++)
    for (xyz2 = 0; xyz2 < 64; xyz2++)
      if (add_codon) pt2codon[xyz1][xyz2] = codon_joint[xyz1*64+xyz2] / ( codonX[xyz1] * codonY[xyz2] );
      else           pt2codon[xyz1][xyz2] = 1.0;
  
  /* Fill in pammodel
   *   P(xyz1,xyz2) = \sum_ab P(xyz1,xyz2 | ab) P(ab)
   *
   *     independence assumption for converting aa to codon gives:
   *
   *   P(xyz1,xyz2) =  pcodcod(c1,c2|t) / [ pcod(c1) * pcod(c2) ]  \sum_ab P(xyz1 | a) P(xyz2 | b) P(ab |t)
   *                                                                            ^ estmodel  ^estmodel  ^aajoint  
   */
  for (xyz1 = 0; xyz1 < 64; xyz1++)
    for (xyz2 = 0; xyz2 < 64; xyz2++)
      {
	pammodel[xyz1][xyz2] = 0.0;
	for (a = 0; a < 20; a++)
	  for (b = 0; b < 20; b++) {
	      pammodel[xyz1][xyz2] += pt2codon[xyz1][xyz2]  *
		estmodel[a][xyz1] * estmodel[b][xyz2] * aajoint[a*20+b];
	  }
      }

    
  /* Normalize it
   */
  NormalizePAMModel(pammodel);

  /* Check it
   */
  CheckPAMModel(pammodel); 

  if (changefreq) ChangeStationaryPAMProbsGW(pammodel, targetfreq, verbose);

  if (verbose) {
    fprintf(stdout, "PAM(i,j, t*) probabilities\n");
    PrintProbs2D(stdout, pammodel, 64, 64);
  }

  free(Id);
  free(pcod);
  free(aajoint);
  free(estmodel[0]);
  free(pamcond[0]);
  free(pt2codon[0]);
  free(estmodel);
  free(pamcond);
  free(pm);
  free(pt2codon);
  free(codonX); 
  free(codonY);

  *ret_pammodel = pammodel;
}

/* Function: ConstructTimeDependentPAMModel()
 * Date:     ER, Tue Aug 20 17:07:47 CDT 2002  [St. Louis]
 *           Modified from: SRE, Wed Jun 10 08:13:35 1998 [St. Louis]
 *
 * Purpose:  Given a substitution matrix, return a
 *           PAMmodel: a 64x64 joint probability matrix
 *           for codons aligned to codons.
 *           Modification: it allows to change the "time"
 *              
 *           Sean used P(a,b, t_o) = q(a) * q(b) e^{\lambada*S_ab}
 *
 *           Here we are allowed to calculate:
 *
 *                                P(a,b, rt_o) = P(b|a, t_o)^r * P(a, t_o)
 *      
 *             where: P(b|a, t_o) = P(a,b, t_o) / P(a)
 *
 *                    P(a, t_o)   = \sum_b P(a,b, t_o)
 *
 * Args:     pam      - 27x27 integer score matrix, alphabetic
 *           scale    - scale of pam matrix           
 *           aafq     - background amino acid frequencies 0..19
 *           estmodel - 64x20 AAA..UUUxA..Y P(xyz | a) conversion to codons
 *           pammodel - 64x64 AAA..UUUxAAA..UUU joint prob matrix (alloc'ed here)
 *
 * Returns:  (void)
 *           fills in pammodel.
 */
void
ConstructTimeDependentPAMModel(int **pam, double scale, double tfactor, double *codon_joint, double ***ret_pammodel, 
			       int add_codon, int pedantic, int verbose)
{
  double **pammodel;
  double **pamcond;
  double  *pt2codon;
  double  *pt2codon_zero;
  double  *pcod;
  double  *pm;
  double **estmodel;
  double  *aajoint;	        /* joint       aa probs P(ab)    */
  double  *Id;
  double  *codonX;
  double  *codonY;
  double  *p4, *p4_zero;
  double  *aafreq;
  double  *codfreq;
  double   sum;
  int      a, b;		/* 0..20 indices for amino acids */
  int      idxa, idxb;		/* 0..26 indices for amino acids */
  int      xyz, xyz1, xyz2;	/* indices for codons 0..63      */
  int      x,y;

   /* allocate pammodel[64][64]
   */
  estmodel          = (double **) MallocOrDie (sizeof(double *) * 20);
  pammodel          = (double **) MallocOrDie (sizeof(double *) * 64);
  pamcond           = (double **) MallocOrDie (sizeof(double *) * 64);
  estmodel[0]       = (double  *) MallocOrDie (sizeof(double  ) * 20 * 64);
  pammodel[0]       = (double  *) MallocOrDie (sizeof(double  ) * 64 * 64);
  pamcond[0]        = (double  *) MallocOrDie (sizeof(double  ) * 64 * 64);
  pt2codon          = (double  *) MallocOrDie (sizeof(double  ) * 64 * 64);
  pt2codon_zero     = (double  *) MallocOrDie (sizeof(double  ) * 64 * 64);
  aajoint           = (double  *) MallocOrDie (sizeof(double  ) * 64 * 64);
  codonX            = (double  *) MallocOrDie (sizeof(double  ) * 64);
  codonY            = (double  *) MallocOrDie (sizeof(double  ) * 64);
  pcod              = (double  *) MallocOrDie (sizeof(double  ) * 64);
  pm                = (double  *) MallocOrDie (sizeof(double  ) * 4);

  Id = Cal_Id (20);

  for (a = 1; a < 20; a++) estmodel[a] = estmodel[0] + a * 64;

  for (xyz = 1; xyz < 64; xyz++) {
    pammodel[xyz] = pammodel[0] + xyz * 64;
    pamcond[xyz]  = pamcond[0]  + xyz * 64;
  }

  for (xyz = 1; xyz < 64; xyz++) 
    pcod[xyz] = 0.0;

  ConstructESTModel(estmodel);
  
 /* Convert integer pam matrix back to joint probabilities P(ab)
  */
  sum = 0.0;
  for (a = 0; a < 20; a++)
    for (b = 0; b < 20; b++)
      {
	idxa = Alphabet[a] - 'A';
	idxb = Alphabet[b] - 'A';
	aajoint[a*20+b] = aafq[a] * aafq[b] * exp((double) pam[idxa][idxb] * scale);
	sum += aajoint[a*20+b];
      }

  /* normalize */
  for (a = 0; a < 20; a++)
    for (b = 0; b < 20; b++)
      aajoint[a*20+b] /= sum;
  CheckSingleProb(aajoint, 20*20);
  
  /* Convert 
   *         joint probabilities aajoint(ab, t_o) 
   *   to 
   *         joint probabilities aajoint(ab, tfactor*t_o)
   */
  Joint2Joint(aajoint, Id, Id, 20, tfactor, aafreq, FALSE, FALSE, FALSE, pedantic, verbose);
  
  /* There is an additional term that needs to be evolved:
   *
   *                  pt2cod(c2 c1 t) = pcodcod(c2, c1 | t) /  pcod(c1 | t) pcod(c2 | t)
   *
   *  The three "points" to make it evolve are:
   *
   *            t=0         pt2cod(c2 c1 t=0)     = delta(c1,c2)
   *
   *            t=t^*       pt2cod(c2 c1 t^*)     = 1    (we assume independence for now)
   *
   *            t=t^infty   pt2cod(c2 c1 t^infty) =  (made up)
   *
  
   for (xyz1 = 0; xyz1 < 64; xyz1++) 
   for (xyz2 = 0; xyz2 < 64; xyz2++) {
   if (xyz1 == xyz2)  pt2codon_zero[xyz1*64+xyz2] = 1.0;
   else               pt2codon_zero[xyz1*64+xyz2] = 0.0;
   
   if (add_codon) 
   pt2codon[xyz1*64+xyz2] = codon_joint[xyz1*64+xyz2];
   else {      
	pt2codon[xyz1*64+xyz2]  = px[xyz1/16] * px[(xyz1%16)/4] * px[xyz1%4]; 
	pt2codon[xyz1*64+xyz2] *= py[xyz2/16] * py[(xyz2%16)/4] * py[xyz2%4]; 
      }     
      }
      
      Joint2Joint(pt2codon, pt2codon_zero, 64, tfactor, pedantic, verbose);
  */
  /* this is a hack 
   */
  p4 = (double *) MallocOrDie(sizeof(double) * 16);
  p4_zero = Cal_Id (4);

  for (x = 0; x < 4; x++)
    for (y = 0; y < 4; y++) p4[x*4+y] = 0.25 * 0.25;

  Joint2Joint(p4, p4_zero, p4_zero, 4, (tfactor<1.0)?tfactor:1.0, codfreq, FALSE, FALSE, FALSE, pedantic, verbose);

  for (xyz1 = 0; xyz1 < 64; xyz1++)
    for (xyz2 = 0; xyz2 < 64; xyz2++) {
      pt2codon[xyz1*64+xyz2]  = p4[(xyz1/16)*4+(xyz2/16)] * p4[((xyz1%16)/4)*4+(xyz2%16)/4] * p4[(xyz1%4)*4+xyz2%4];
      pt2codon[xyz1*64+xyz2] /= 0.25 * 0.25 * 0.25 * 0.25 * 0.25 * 0.25;
     }

  /* Fill in pammodel
   *   P(xyz1,xyz2) = \sum_ab P(xyz1,xyz2 | ab) P(ab)
   *
   *     independence assumption for converting aa to codon gives:
   *
   *   P(xyz1,xyz2) =  pcodcod(c1,c2|t) / [ pcod(c1) * pcod(c2) ]  \sum_ab P(xyz1 | a) P(xyz2 | b) P(ab |t)
   *                                                                            ^ estmodel  ^estmodel  ^aajoint  
   */
  for (xyz1 = 0; xyz1 < 64; xyz1++)
    for (xyz2 = 0; xyz2 < 64; xyz2++)
      {
	pammodel[xyz1][xyz2] = 0.0;
	for (a = 0; a < 20; a++)
	  for (b = 0; b < 20; b++) 
	      pammodel[xyz1][xyz2] += pt2codon[xyz1*64+xyz2] *
		estmodel[a][xyz1] * estmodel[b][xyz2] * aajoint[a*20+b];
      }

    
  /* Normalize it
   */
  NormalizePAMModel(pammodel);

  /* Check it
   */
  CheckPAMModel(pammodel); 

  free(Id);
  free(pcod);
  free(codonX);
  free(codonY);
  free(aajoint);
  free(estmodel[0]);
  free(pamcond[0]);
  free(estmodel);
  free(pamcond);
  free(pm);
  free(p4);
  free(p4_zero);
  free(pt2codon);
  free(pt2codon_zero);

  *ret_pammodel = pammodel;

}

/* Function: ConstructPAMCondi()
 * Date:     ER, Fri Sep 22 13:56:23 CDT 2000  [St. Louis]
 *
 * Purpose:  Given a substitution matrix, return a
 *           PAMmodel: a 64x64 coditional probability matrix
 *           for codons aligned to codons.
 *
 * Args:     pam      - 27x27 integer score matrix, alphabetic
 *           scale    - scale of pam matrix           
 *           aafq     - background amino acid frequencies 0..19
 *           estmodel - 64x20 AAA..UUUxA..Y P(xyz | a) conversion to codons
 *           pammodel - 64x64 AAA..UUUxAAA..UUU joint prob matrix (alloc'ed here)
 *
 * Returns:  (void)
 *           fills in pammodel.
 */
void
ConstructPAMCondi(int **pam, double scale, double tfactor, double *codon_joint, struct pamcond_s **ret_pamcond, 
		  int add_codon, int pedantic, int verbose)
{
  struct pamcond_s   *pamcond;
  double            **pt2codon;
  double             *pcodX;
  double             *pcodY;
  double            **pammodel;
  double            **estmodel;
  double             *aajoint;	        /* joint       aa probs P(ab)    */
  double             *Id;
  double             *codonX;
  double             *codonY;
  double             *aafreq;
  double             *codfreq;
  int                 a, b;		/* 0..20 indices for amino acids */
  int                 idxa, idxb;	/* 0..26 indices for amino acids */
  int                 xyz, xyz1, xyz2;	/* indices for codons 0..63      */


  /* allocate estmodel[20][64]
   */
  estmodel    = (double **) MallocOrDie (sizeof(double *) * 20);
  estmodel[0] = (double  *) MallocOrDie (sizeof(double  ) * 20 * 64);

  for (a = 1; a < 20; a++) estmodel[a] = estmodel[0] + a * 64;

  ConstructESTModel(estmodel);
 
   /* allocate pamcond[64][64]
   */
  pamcond     = AllocPamCond();
  pammodel    = (double **) MallocOrDie (sizeof(double *) * 64);
  pt2codon    = (double **) MallocOrDie (sizeof(double *) * 64);
  pammodel[0] = (double  *) MallocOrDie (sizeof(double  ) * 64 * 64);
  pt2codon[0] = (double  *) MallocOrDie (sizeof(double  ) * 64 * 64);
  aajoint     = (double  *) MallocOrDie (sizeof(double  ) * 64 * 64);
  codonX      = (double  *) MallocOrDie (sizeof(double  ) * 64);
  codonY      = (double  *) MallocOrDie (sizeof(double  ) * 64);
  pcodX       = (double  *) MallocOrDie (sizeof(double  ) * 64);
  pcodY       = (double  *) MallocOrDie (sizeof(double  ) * 64);

  Id = Cal_Id (20);

  for (xyz = 1; xyz < 64; xyz++) {
    pammodel[xyz] = pammodel[0] + xyz * 64;
    pt2codon[xyz] = pt2codon[0] + xyz * 64;
  }

  for (xyz1 = 0; xyz1 < 64; xyz1++) 
    for (xyz2 = 0; xyz2 < 64; xyz2++) 
      pammodel[xyz1][xyz2] = 0.0;
  
  for (xyz = 0; xyz < 64; xyz++) {
    pcodX[xyz] = 0.0;
    pcodY[xyz] = 0.0;
  }

 /* Convert integer pam matrix back to joint probabilities P(ab)
  */
  for (a = 0; a < 20; a++)
    {
      for (b = 0; b < 20; b++)
	{
	  idxa = Alphabet[a] - 'A';
	  idxb = Alphabet[b] - 'A';
	  aajoint[a*20+b] = aafq[a] * aafq[b] * exp((double) pam[idxa][idxb] * scale);
	}
    }
  
  /* Convert 
   *         joint probabilities aajoint(ab, t_o) 
   *   to 
   *         joint probabilities aajoint(ab, tfactor*t_o)
   */
  Joint2Joint(aajoint, Id, Id, 20, tfactor, aafreq, FALSE, FALSE, FALSE, pedantic, verbose);
  
  /* Fill in pammodel
   *   P(xyz1,xyz2) = \sum_ab P(xyz1,xyz2 | ab) P(ab)
   *
   *     independence assumption for converting aa to codon gives:
   *
   *   P(xyz1,xyz2) =  pcodcod(c1,c2|t) / [ pcod(c1) * pcod(c2) ]  \sum_ab P(xyz1 | a) P(xyz2 | b) P(ab |t)
   *                                                                            ^ estmodel  ^estmodel  ^aajoint  
   */
  if (add_codon) {
    MarginalizeJointProbs(codon_joint, codonX, 64, 1);
    MarginalizeJointProbs(codon_joint, codonY, 64, 0);
  }

  for (xyz1 = 0; xyz1 < 64; xyz1++)
    for (xyz2 = 0; xyz2 < 64; xyz2++)
      if (add_codon) pt2codon[xyz1][xyz2] = codon_joint[xyz1*64+xyz2] / ( codonX[xyz1] * codonY[xyz2] );
      else           pt2codon[xyz1][xyz2] = 1.0;
  
  /* Fill in pammodel
   *   P(xyz1,xyz2) = \sum_ab P(xyz1,xyz2 | ab) P(ab)
   *     independence assumption for converting aa to codon gives:
   *   P(xyz1,xyz2) = \sum_ab P(xyz1 | a) P(xyz2 | b) P(ab)
   *                             ^ estmodel  ^estmodel  ^aajoint  
   */
  for (xyz1 = 0; xyz1 < 64; xyz1++)
    for (xyz2 = 0; xyz2 < 64; xyz2++)
      {
	pammodel[xyz1][xyz2] = 0.0;
	for (a = 0; a < 20; a++)
	  for (b = 0; b < 20; b++)
	    pammodel[xyz1][xyz2] += pt2codon[xyz1][xyz2] *
	      estmodel[a][xyz1] * estmodel[b][xyz2] * aajoint[a*20+b];
      }

  /* Normalize it
   */
  NormalizePAMModel(pammodel);

  /* Check it
   */
  CheckPAMModel(pammodel); 

  /* Calculate conditionals:   P(xyz1|xyz2) = P(xyz1, xyz2) / P(xyz2)
   *
   */
  for (xyz1 = 0; xyz1 < 64; xyz1++)
    for (xyz2 = 0; xyz2 < 64; xyz2++) {
      pcodX[xyz1] += pammodel[xyz1][xyz2];
      pcodY[xyz2] += pammodel[xyz1][xyz2];
    }
  
  for (xyz1 = 0; xyz1 < 64; xyz1++)
    for (xyz2 = 0; xyz2 < 64; xyz2++) {
      pamcond->pXY[xyz1][xyz2] = pammodel[xyz1][xyz2] / pcodY[xyz2];
      pamcond->pYX[xyz2][xyz1] = pammodel[xyz1][xyz2] / pcodX[xyz1];
    }
  
  free(Id);
  free(pcodX);
  free(pcodY);
  free(aajoint);
  free(estmodel[0]);
  free(estmodel);
  free(pt2codon[0]);
  free(pt2codon);
  free(pammodel[0]);
  free(pammodel);
  free(codonX); 
  free(codonY);

  *ret_pamcond = pamcond;
}

/* Function: ConstructPsingle()
 * Date:     ER, Mon Sep 25 17:43:48 CDT 2000  [St. Louis]
 *
 * Purpose:  Given a PAMmodel: a 64x64 coditional probability matrix
 *                             for codons aligned to codons.
 *
 * Args:     pammodel - 64x64 AAA..UUUxAAA..UUU joint prob matrix 
 *           psingle  - 4 X 4 single nucleotide frequencies (alloc'ed here)
 *
 * Returns:  (void)
 *           psingle allocated and filled here.
 */
void
ConstructPsingle (double **pammodel, double **ret_psingle)
{
  double *psingle;
  int     cod;
  int     x, y, z;

  /* allocate psingle[4]
   */
  psingle = (double *) MallocOrDie (sizeof(double) * 4);
  DSet(psingle, 4, 0.0);

  for (x = 0; x < 4; x++)
    for (y = 0; y < 4; y++)
      for (z = 0; z < 4; z++)
	for (cod = 0; cod < 64; cod++) 
	  psingle [x] += pammodel[CODON(x,y,z)][cod] + pammodel[CODON(y,x,z)][cod] +
	    pammodel[CODON(y,z,x)][cod];
  
  DScale(psingle, 4, 1./(64.*3.));

  *ret_psingle = psingle;
}

/* Function: ConstructPAMJoint()
 * Date:     ER, Fri Sep 22 14:51:09 CDT 2000 [St. Louis]
 *
 * Purpose: 
 *
 * Args:     pam      - 27x27 integer score matrix, alphabetic
 *           scale    - scale of pam matrix           
 *           aafq     - background amino acid frequencies 0..19
 *           estmodel - 64x20 AAA..UUUxA..Y P(xyz | a) conversion to codons
 *           pammodel - 64x64 AAA..UUUxAAA..UUU joint prob matrix (alloc'ed here)
 *
 * Returns:  (void)
 *           fills in pammodel.
 */
void
ConstructPAMJoint(struct pamcond_s *pamcond, double ***ret_pammodel, double *freqX, double *freqY, int pedantic, int verbose)
{
  double  *pcodX;
  double  *pcodY;
  double **pammodel;
  int      xyz, xyz1, xyz2;	/* indices for codons 0..63      */

  pammodel    = (double **) MallocOrDie (sizeof(double  *) * 64);
  pammodel[0] = (double  *) MallocOrDie (sizeof(double   ) * 64 * 64);
  pcodX       = (double  *) MallocOrDie (sizeof(double   ) * 64);
  pcodY       = (double  *) MallocOrDie (sizeof(double   ) * 64);

  for (xyz = 1; xyz < 64; xyz++) 
    pammodel[xyz] = pammodel[0] + xyz*64;
  
  
  for (xyz1 = 0; xyz1 < 64; xyz1++)  
    {
      pcodX[xyz1] = 0.0;
      pcodY[xyz1] = 0.0;

      for (xyz2 = 0; xyz2 < 64; xyz2++) 
	pammodel[xyz1][xyz2] = 0.0;
       
    }
  
  for (xyz = 0; xyz < 64; xyz++) {
    pcodX[xyz] = freqX[xyz/16] * freqX[(xyz%16)/4] * freqX[xyz%4];
    pcodY[xyz] = freqY[xyz/16] * freqY[(xyz%16)/4] * freqY[xyz%4];
  }
  
  for (xyz1 = 0; xyz1 < 64; xyz1++)
    for (xyz2 = 0; xyz2 < 64; xyz2++)
      pammodel[xyz1][xyz2] = 0.5 * pamcond->pXY[xyz1][xyz2] * pcodY[xyz2] + 0.5 * pamcond->pYX[xyz2][xyz1] * pcodX[xyz1];
  
  NormalizePAMModel(pammodel);
  CheckPAMModel(pammodel); 

  *ret_pammodel = pammodel;

  free(pcodX);
  free(pcodY);
}


/* Function: DefaultCodonBias()
 * 
 * Purpose:  Configure a codonbias table, mapping triplets to
 *           probability of using the triplet for the amino acid
 *           it represents: P(triplet | aa).
 *           The default is to assume codons are used equiprobably.
 *           
 * Args:     codebias:  0..63 array of P(triplet|aa), preallocated.
 * 
 * Return:   (void)
 */
void
DefaultCodonBias(double codebias[64])
{
  codebias[0]  = 1./2.; /* AAA Lys 2 */
  codebias[1]  = 1./2.; /* AAC Asn 2 */
  codebias[2]  = 1./2.; /* AAG Lys 2 */
  codebias[3]  = 1./2.; /* AAU Asn 2 */
  codebias[4]  = 1./4.; /* ACA Thr 4 */
  codebias[5]  = 1./4.; /* ACC Thr 4 */
  codebias[6]  = 1./4.; /* ACG Thr 4 */
  codebias[7]  = 1./4.; /* ACU Thr 4 */
  codebias[8]  = 1./6.; /* AGA Ser 6 */
  codebias[9]  = 1./6.; /* AGC Arg 6 */
  codebias[10] = 1./6.; /* AGG Ser 6 */
  codebias[11] = 1./6.; /* AGU Arg 6 */
  codebias[12] = 1./3.; /* AUA Ile 3 */
  codebias[13] = 1./3.; /* AUC Ile 3 */
  codebias[14] = 1.;    /* AUG Met 1 */
  codebias[15] = 1./3.; /* AUU Ile 3 */
  codebias[16] = 1./2.; /* CAA Gln 2 */
  codebias[17] = 1./2.; /* CAC His 2 */
  codebias[18] = 1./2.; /* CAG Gln 2 */
  codebias[19] = 1./2.; /* CAU His 2 */
  codebias[20] = 1./4.; /* CCA Pro 4 */
  codebias[21] = 1./4.; /* CCC Pro 4 */
  codebias[22] = 1./4.; /* CCG Pro 4 */
  codebias[23] = 1./4.; /* CCU Pro 4 */
  codebias[24] = 1./6.; /* CGA Arg 6 */
  codebias[25] = 1./6.; /* CGC Arg 6 */
  codebias[26] = 1./6.; /* CGG Arg 6 */
  codebias[27] = 1./6.; /* CGU Arg 6 */
  codebias[28] = 1./6.; /* CUA Leu 6 */
  codebias[29] = 1./6.; /* CUC Leu 6 */
  codebias[30] = 1./6.; /* CUG Leu 6 */
  codebias[31] = 1./6.; /* CUU Leu 6 */
  codebias[32] = 1./2.; /* GAA Glu 2 */
  codebias[33] = 1./2.; /* GAC Asp 2 */
  codebias[34] = 1./2.; /* GAG Glu 2 */
  codebias[35] = 1./2.; /* GAU Asp 2 */
  codebias[36] = 1./4.; /* GCA Ala 4 */
  codebias[37] = 1./4.; /* GCC Ala 4 */
  codebias[38] = 1./4.; /* GCG Ala 4 */
  codebias[39] = 1./4.; /* GCU Ala 4 */
  codebias[40] = 1./4.; /* GGA Gly 4 */
  codebias[41] = 1./4.; /* GGC Gly 4 */
  codebias[42] = 1./4.; /* GGG Gly 4 */
  codebias[43] = 1./4.; /* GGU Gly 4 */
  codebias[44] = 1./4.; /* GUA Val 4 */
  codebias[45] = 1./4.; /* GUC Val 4 */
  codebias[46] = 1./4.; /* GUG Val 4 */
  codebias[47] = 1./4.; /* GUU Val 4 */
  codebias[48] = 0.;    /* UAA och - */
  codebias[49] = 1./2.; /* UAC Tyr 2 */
  codebias[50] = 0.;    /* UAG amb - */
  codebias[51] = 1./2.; /* UAU Tyr 2 */
  codebias[52] = 1./6.; /* UCA Ser 6 */
  codebias[53] = 1./6.; /* UCC Ser 6 */
  codebias[54] = 1./6.; /* UCG Ser 6 */
  codebias[55] = 1./6.; /* UCU Ser 6 */
  codebias[56] = 0.;    /* UGA opa - */
  codebias[57] = 1./2.; /* UGC Cys 2 */
  codebias[58] = 1.;    /* UGG Trp 1 */
  codebias[59] = 1./2.; /* UGU Cys 2 */
  codebias[60] = 1./6.; /* UUA Leu 6 */
  codebias[61] = 1./2.; /* UUC Phe 2 */
  codebias[62] = 1./6.; /* UUG Leu 6 */
  codebias[63] = 1./2.; /* UUU Phe 2 */
}


/* Function: DefaultGeneticCode()
 * 
 * Purpose:  Configure aacode, mapping triplets to amino acids.
 *           Triplet index: AAA = 0, AAC = 1, ... UUU = 63.
 *           AA index: alphabetical: A=0,C=1... Y=19
 *           Stop codon: -1. 
 *           Uses the stdcode1[] global translation table from SQUID.
 *           
 * Args:     aacode  - preallocated 0.63 array for genetic code
 *                     
 * Return:   (void)
 */
void
DefaultGeneticCode(int aacode[64])
{
  int x;

  for (x = 0; x < 64; x++) {
    if (*(stdcode1[x]) == '*') aacode[x] = -1;
    else                       aacode[x] = SYMIDX(*(stdcode1[x]));
  }
}


void
FreeCODModel(struct codmodel_s *cod)
{
  FreeOTHModel(cod->COB);
  FreeOTHModel(cod->COJ);
  FreeOTHModel(cod->COE);

  free(cod->t);
  free(cod->pmut);

  free(cod->phexa[0]);
  free(cod->phexa);

  free(cod->pcodon[0]);
  free(cod->pcodon);

  free(cod);
}

void     
FreePAMModel(double **pammodel)
{
  free (pammodel[0]);
  free (pammodel);
}

void     
FreePamCond(struct pamcond_s *pamcond)
{

  free(pamcond->pXY[0]);
  free(pamcond->pYX[0]);

  free(pamcond->pXY);
  free(pamcond->pYX);

  free(pamcond);
}

/* Function: NormalizePAMModel()
 * Date:     SRE, Wed Jun 10 13:41:57 1998 [St. Louis]
 *
 * Purpose:  Normalize a PAM model; because of integer->double
 *           conversion, can expect some rough edges.
 *
 * Args:     pammodel[64][64]
 *
 * Returns:  void
 */
void
NormalizePAMModel(double **pammodel)
{
  int x, y;
  double sum = 0.0;

  for (x = 0; x < 64; x++)
    for (y = 0; y < 64; y++)
      sum += pammodel[x][y];
  for (x = 0; x < 64; x++)
    for (y = 0; y < 64; y++)
      pammodel[x][y] /= sum;
}


void     
PatternCODModel(struct codmodel_s *cod)
{
  int idx;
  int x;
  int codx, cody;

  PatternOTHModel(cod->COB);
  PatternOTHModel(cod->COJ);
  PatternOTHModel(cod->COE);

 /* Initialize all prob's to zero
   */
  for (idx = 0; idx < CTRANS; idx++)
    cod->t[idx] = 0.0;

  for (x = 0; x < 16; x++)
    cod->pmut[x] = 0.0;

  for (codx = 0; codx < 64; codx++) 
    for (cody = 0; cody < 64; cody++) {
      cod->pcodon[codx][cody] = 0.0;
      cod->phexa[codx][cody]  = 0.0;
    }

}


/* Function: PrintCodonString()
 * Date:     SRE, Wed Jun 10 14:00:28 1998 [St. Louis]
 */
void
PrintCodonString(int x)
{
  char *s;

  s = (char *) MallocOrDie (sizeof(char)*4);

  s[0] = DNAAlphabet[x/16];
  s[1] = DNAAlphabet[(x%16)/4];
  s[2] = DNAAlphabet[x%4];
  s[3] = '\0';
  printf("%3s ", s);

  free(s);
}


/* Function: PrintCODModel()
 * Date:     ER, Mon Jun  7 17:44:21 CDT 1999 [St. Louis]
 *
 * Purpose:  Print a cod model
 *
 * Args:     codmodel -- the codmodel prob's, in log2 form
 *
 * Returns:  void. prints transition and emission probs for cod model, in [0,1] form.
 */
void
PrintCODModel(struct codmodel_s *cod)
{
  int codx, cody;   /* symbols for emission prob's      +*/

  printf("\nCOB MODEL \n");
  PrintOTHModel(cod->COB);

  printf("\nCOJ MODEL \n");
  PrintOTHModel(cod->COJ);

  printf("\nCOE MODEL \n");
  PrintOTHModel(cod->COE);

  printf("\n***COD MODEL*** -- Emission probabilities\n");
  for (codx = 0; codx < 64; codx++)
    for (cody = 0; cody < 64; cody++) {
      PrintCodonString(codx);
      PrintCodonString(cody);
      printf("%3s %3s %12f \n",
	     stdcode3[codx], stdcode3[cody],
	     EXP2(cod->pcodon[codx][cody]));
    }
}

/* Function: PrintCODTrProbs()
 * Date:     ER, Tue Aug  6 16:53:02 CDT 2002 [St. Louis]
 *
 * Purpose:  Print a COD model transition probabilities
 *
 * Args:     codmodel -- the codmodel prob's, in log2 form
 *
 * Returns:  void. prints transition and emission probs for cod model, in [0,1] form.
 */
void
PrintCODTrProbs(struct codmodel_s *cod) 
{
  int    idx;               /* index for transition prob's      +*/
  double tr;

  printf("\n***COD MODEL*** -- Transition probabilities\n");
  for (idx = 0; idx < CTRANS; idx++) {
    tr = EXP2(cod->t[idx]);
    if (tr <= 1.0)
      printf("t[%s]\t = %f\n", ctrNAME[idx], tr); 
    else if (tr > 1.0) {
      if (tr > 1.0+MARGIN)
	Die ("tr prob larger than 1.0 at %s (%f)\n", ctrNAME[idx], tr);
    }
  }
  
}


/* Function: PrintPAMModel()
 * Date:     SRE, Wed Jun 10 13:51:53 1998 [St. Louis]
 *
 * Purpose:  Print a pam model
 *
 * Args:     pammodel[64][64]
 *           mutpxy[4][4]
 *
 * Returns:  void. prints stuff.
 */
void
PrintPAMModel(double **pammodel, double *mutpxy)
{
  int      x,y;
  double   mutp;
  double   info = 0.0;
  double   expect = 0.0;

  printf("PAM probabilities\n");
  for (x = 0; x < 64; x++)
    for (y = 0; y < 64; y++)
      {
	mutp  = mutpxy[idx((x/16),y/16)];
	mutp *= mutpxy[idx(((x%16)/4),((y%16)/4))];
	mutp *= mutpxy[idx((x%4),(y%4))];

	PrintCodonString(x);
	PrintCodonString(y); 
	if (mutp > 0.0) {
	  printf("%3s %3s %12f %12f %12f\n",
		 stdcode3[x], stdcode3[y], pammodel[x][y], mutp,
		 LOG2(pammodel[x][y] / mutp));
	  
	  info += pammodel[x][y] * LOG2(pammodel[x][y] / mutp);
	  expect += mutp * LOG2(pammodel[x][y] / mutp);
	}
	else 
	  printf("%3s %3s %12f %12f \n", stdcode3[x], stdcode3[y], pammodel[x][y], mutp);
	
      }

    printf("info content per codon: %f bits\n", info);
    printf("expectation per codon:  %f bits\n", expect);
}


/* Function: CODmodelTransition_Probabilities()
 * Date:     ER, Tue Aug 13 19:19:55 CDT 2002  [St. Louis]
 *
 * Purpose:  Constructs a codmodel_s
 *
 * Args:     CODparam - the list of parameters that define a CODmodel           
 *
 * Returns:  (void)
 *           fills all prob's for codmodel, log2 form 
 *           (allc'ed here, freed by caller)
 */
void     
CODmodelTransitionProbabilities(int len, double tfactor, struct codmodel_s *cod, int pedantic, int verbose)
{
  double             tr;              /* transition prob's                         +*/
  double           **TA;              /* 2x2  matrix of transition probs.          +*/
  double           **RA_diag;         /* 2x2  matrix of transition probs.          +*/
  double           **TA_zero;         /* 2x2  matrix of transition probs.          +*/
  double           **TA_infty;        /* 2x2  matrix of transition probs.          +*/
  double            *TB;              /* 1x16 matrix of transition probs.          +*/
  double            *RB_diag;         /* 1x16 matrix of transition probs.          +*/
  double            *TB_zero;         /* 1x16 matrix of transition probs.          +*/
  double            *TB_infty;        /* 1x16 matrix of transition probs.          +*/
  double             ave_len_zero;
  double             ave_len_star;
  double             ave_len_infty;
  int                idx;             /* index for transition prob's               +*/
  int                i;
  int                dimA, dimB;

  dimA = 2;
  dimB = 16;

  /* 24 JUL 02
   *
   * The evolutionary COD model is as follows: T = T^A X T^B
   *
   *       - A 2x2 matrix for transitions T^A              Cb      COE                          
   *                                               COB  |  psi    1-psi |
   *                                     T^A =          |               |
   *                                                Ce  | 1-eta    eta  |
   * 
   *
   *               at t=0                               |  1        0   |
   *                                   T^A_0 =          |               |
   *                                                    |  0        1   |
   *
   *
   *      - A 17x17 matrix for transitions T^B                 xi_1    xi_2  ...  xi_16   Ce
   *                                                     Cb | T_b1      ...       T_b6     0  |
   *                                                   xi_1 |  0        ...         0      1  |
   *                                           T^B =     .  |  0        ...         0      1  |
   *                                                     .  |  0        ...         0      1  |
   *                                                     .  |  0        ...         0      1  |
   *                                                 xi_16  |  0        ...         0      1  |
   *
   *                 at t=0                           
   *                                                     Cb | T0_b1     ...       T0_b6    0  |
   *                                                   xi_1 |  0        ...         0      1  |
   *                                         T^B_0 =     .  |  0        ...         0      1  |
   *                                                     .  |  0        ...         0      1  |
   *                                                     .  |  0        ...         0      1  |
   *                                                 xi_16  |  0        ...         0      1  |
   *
   *
   *
   *
   *
   *              parametric family:      T = T_0 exp [tA] with T_0 = T^A_0 X T^B_0
   *
   */
 
  /* allocate Rate matrices
   */
  RA_diag = (double **) MallocOrDie (sizeof(double *) * dimA);

  /* fix parameter Ce --> COE to have the desired estimated length
   */
  ave_len_zero  = (double)len/3.0;
  ave_len_star  = EXP2(0.99*LOG2(ave_len_zero));
  ave_len_infty = EXP2(0.18*LOG2(ave_len_zero));

  if (len > 3) {
    CODparam.eta       = 1.0 / ave_len_star;
    CODparam_zero.eta  = 1.0 / ave_len_zero;
    CODparam_infty.eta = 1.0 / ave_len_infty;
  }
  else {
    CODparam.eta       = 1.0;
    CODparam_zero.eta  = 1.0;
    CODparam_infty.eta = 1.0;

  }
  
  /* Convert 
   *         conditional probabilities T^A(ab, t_o) 
   *   to 
   *         conditional probabilities T^A(ab, tfactor*t_o)
   */
  TA       = cod_A_transfermatrix(CODparam,       dimA);
  TA_zero  = cod_A_transfermatrix(CODparam_zero,  dimA);
  TA_infty = cod_A_transfermatrix(CODparam_infty, dimA);
  
  for (i = 0; i < dimA; i++) {
    RA_diag[i] = TransitionsExpVector(TA[i], TA_zero[i], TA_infty[i], dimA);
    TransitionsEvolved(stdout, TA[i], TA_zero[i], TA_infty[i], RA_diag[i], dimA, tfactor, pedantic, FALSE);
  }
  
  /* Convert 
   *         conditional probabilities T^B(ab, t_o) 
   *   to 
   *         conditional probabilities T^B(ab, tfactor*t_o)
   */
  TB       = cod_B_transfermatrix(CODparam,       dimB);
  TB_zero  = cod_B_transfermatrix(CODparam_zero,  dimB);
  TB_infty = cod_B_transfermatrix(CODparam_infty, dimB);

  RB_diag = TransitionsExpVector(TB, TB_zero, TB_infty, dimB);
  TransitionsEvolved(stdout, TB, TB_zero, TB_infty, RB_diag, dimB, tfactor, pedantic, FALSE);
  
  /* Calculate COD model transitions */
  for (idx = 0; idx < CTRANS; idx++) {
    switch (idx) {
    case TCOBCb:  tr = TA[0][0];             break;
    case TCOBCOE: tr = TA[0][1];             break;
    case TCbCe:   tr = TB[15];               break;
    case TCbC33:  tr = TB[0*4+0];            break;
    case TCbC34:  tr = TB[0*4+1]/4.0;        break;
    case TCbC32:  tr = TB[0*4+2]/3.0;        break;
    case TCbC43:  tr = TB[1*4+0]/4.0;        break;
    case TCbC44:  tr = TB[1*4+1];            break;
    case TCbC42:  tr = TB[1*4+2]/6.0;        break;
    case TCbC23:  tr = TB[2*4+0]/3.0;        break;
    case TCbC24:  tr = TB[2*4+1]/6.0;        break;
    case TCbC22:  tr = TB[2*4+2];            break;
    case TCbC30:  tr = TB[0*4+3];            break;
    case TCbC40:  tr = TB[1*4+3];            break;
    case TCbC20:  tr = TB[2*4+3];            break;
    case TCbC03:  tr = TB[3*4+0];            break;
    case TCbC04:  tr = TB[3*4+1];            break;
    case TCbC02:  tr = TB[3*4+2];            break;
    case TC33Ce:  tr = 1.0;                  break;
    case TC34Ce:  tr = 1.0;                  break;
    case TC32Ce:  tr = 1.0;                  break;
    case TC43Ce:  tr = 1.0;                  break;
    case TC44Ce:  tr = 1.0;                  break;
    case TC42Ce:  tr = 1.0;                  break;
    case TC23Ce:  tr = 1.0;                  break;
    case TC24Ce:  tr = 1.0;                  break;
    case TC22Ce:  tr = 1.0;                  break;
    case TC30Ce:  tr = 1.0;                  break;
    case TC40Ce:  tr = 1.0;                  break;
    case TC20Ce:  tr = 1.0;                  break;
    case TC03Ce:  tr = 1.0;                  break;
    case TC04Ce:  tr = 1.0;                  break;
    case TC02Ce:  tr = 1.0;                  break;
    case TCeCOJ:  tr = TA[1][0];             break;
    case TCeCOE:  tr = TA[1][1];             break;
    case TCOJCb:  tr = 1.0;                  break;
    case TCOECOE: tr = 1.0;                  break;
    default:  Die("transition (%d) does not exits", idx);
    }

    if (tr > 1.0+MARGIN || tr < 0.0-MARGIN) Die ("transition %s in COD model is wrong (tr=%f)", ctrNAME[idx], tr);
    else  cod->t[idx] = tr;
  }

  if (FALSE) 
    for (idx = 0; idx < CTRANS; idx++) { printf("%s = %f (%f)\n", ctrNAME[idx], cod->t[idx], LOG2(cod->t[idx])); }
 
  free(TA[0]);
  free(TA_zero[0]);
  free(TA_infty[0]);
  for (i = 0; i < dimA; i++) free(RA_diag[i]);
 
  free(TA);
  free(TB);
  free(TA_zero);
  free(TB_zero);
  free(TA_infty);
  free(TB_infty);
  free(RA_diag);
  free(RB_diag);

}



/* Function: cod_A_transfermatrix()
 * Date:     ER, Wed Jul 24 16:16:30 CDT 2002
 *
 * Purpose:  Fill the coding model transition matrix T^A
 *
 * Args:     
 *
 * Returns:  void. T^A is allocated and filled here. T^A freed by caller.
 */
double **
cod_A_transfermatrix(struct codparam_s codparam, int dim)
{
  double **TA;
  int      row, col, idx;

  /* allocate TA
   */
  TA    = (double **) MallocOrDie (sizeof(double *) * dim      );
  TA[0] = (double  *) MallocOrDie (sizeof(double  ) * dim * dim);

  for (row = 1; row < dim; row++)
    TA[row] = TA[0] + row*dim;

  /* fill TA
   */
  for (row = 0; row < dim; row++) 
    for (col = 0; col < dim; col++) {

      idx = row*dim + col;

	if      (idx == 0) TA[row][col] = codparam.psi;
	else if (idx == 1) TA[row][col] = 1.0 - codparam.psi;
	else if (idx == 2) TA[row][col] = 1.0 - codparam.eta;
	else if (idx == 3) TA[row][col] = codparam.eta;
    }
  
  if (FALSE) {
    printf("COD T^A transition matrix\n");
    for (row = 0; row < dim; row++) {
      for (col = 0; col < dim; col++) {
	printf("%.4f ", TA[row][col]);
    }
      printf("\n");
    }
  }

  /* Check they are conditional probabilities
   */
  for (row = 0; row < dim; row++) 
    CheckSingleProb(TA[row], dim);
   
  return TA;
}

double **
cod_A_transfermatrix_at_infty(double **TA, double **TA_zero, int dim)
{
  double **TA_infty;
  int      row, col;
  
  /* allocate TA_infty
   */
  TA_infty    = (double **) MallocOrDie (sizeof(double *) * dim      );
  TA_infty[0] = (double  *) MallocOrDie (sizeof(double  ) * dim * dim);

  for (row = 1; row < dim; row++)
    TA_infty[row] = TA_infty[0] + row*dim;

  /* fill TA
   */
   for (row = 0; row < dim; row++) 
      for (col = 0; col < dim; col++) 
	  TA_infty[row][col] = 1.0/(float)dim;
  
  if (FALSE) {
    printf("COD T^A transition matrix at t=infty\n");
    for (row = 0; row < dim; row++) {
      for (col = 0; col < dim; col++) {
	printf("%.4f ", TA_infty[row][col]);
    }
      printf("\n");
    }
  }
  
  /* Check they are conditional probabilities
   */
  for (row = 0; row < dim; row++) 
    CheckSingleProb(TA_infty[row], dim);
   
  return TA_infty;
}


/* Function: cod_B_transfermatrix()
 * Date:     ER, Wed Jul 24 16:16:30 CDT 2002
 *
 * Purpose:  Fill the coding model transition matrix T^B
 *
 * Args:     
 *
 * Returns:  void. T^B is allocated and filled here. T^B freed by caller.
 */
double *
cod_B_transfermatrix(struct codparam_s codparam, int dim)
{
  double *TB;
  double  sumcb;
  int     idx;

  /* allocate TB
   */
  TB = (double *) MallocOrDie (sizeof(double) * dim);

  /* normalize transition for state Cb (codon begins) */
  sumcb = normalizecodparam(codparam);  

  /* fill TB
   */
  for (idx = 0; idx < dim-1; idx++) TB[idx] = codparam.xi[idx] / sumcb;
  TB[idx] = codparam.tau;   /* Cb --> Ce transition which is always zero for us */
  
  if (FALSE) {
    printf("COD T^B transition matrix\n");
    printf("3\t4\t2\t0");
    for (idx = 0; idx < dim; idx++) {
       if ((idx*idx)%dim == 0) printf("\n");
       printf("%.4f ", TB[idx]);
    }
    printf("\n");
  }
  
  /* Check they are conditional probabilities
   */
  CheckSingleProb(TB, dim);
   
  return TB;
}

double *
cod_B_transfermatrix_at_infty(double **TB, double **TB_zero, int dim)
{
  double *TB_infty;
  double  sumcb;
  int     idx;
  
  /* allocate TB
   */
  TB_infty = (double *) MallocOrDie (sizeof(double) * dim);
  
  /* normalize transition for state Cb (codon begins) */
  sumcb = normalizecodparam(CODparam_infty);  

  /* fill TB_infty
   */
  for (idx = 0; idx < dim-1; idx++) TB_infty[idx] = CODparam_infty.xi[idx] / sumcb;
  TB_infty[idx] = CODparam_infty.tau;   /* Cb --> Ce transition which is always zero for us */
  
  if (FALSE) {
    printf("COD T^B transition matrix at t=infty\n");

    printf("3\t4\t2\t0");
    for (idx = 0; idx < dim; idx++) {
       if ((idx*idx)%dim == 0) printf("\n");
       printf("%.4f ", LOG2(TB_infty[idx]));
    }
    printf("\n");
  }
  printf("\n");
  
  /* Check they are conditional probabilities
   */
  CheckSingleProb(TB_infty, dim);

  return TB_infty;
}


double **
cod_A_transfermatrix_Rdiag(int dim)
{
  double **R_diag;
  int      row, col;

  /* allocate R_diag
   */
  R_diag    = (double **) MallocOrDie (sizeof(double *) * dim      );
  R_diag[0] = (double  *) MallocOrDie (sizeof(double  ) * dim * dim);

  for (row = 1; row < dim; row++)
    R_diag[row] = R_diag[0] + row*dim;

  /* fill R_diag.
   * 
   */
    for (row = 0; row < dim; row++) 
      for (col = 0; col < dim; col++)  
	R_diag[row][col] = 0.0;
      
  if (FALSE) {
    printf("RA_diag - COD transfer matrix\n");
    for (row = 0; row < dim; row++) {
      for (col = 0; col < dim; col++) {
	printf("%.4f ", R_diag[row][col]);
      }
      printf("\n");
    }
  }
  
  return R_diag;
}

double *
cod_B_transfermatrix_Rdiag(int dim)
{
  double *R_diag;
  int     col;

  /* allocate R_diag
   */
  R_diag = (double *) MallocOrDie (sizeof(double) * dim * dim);

  /* fill R_diag.
   * 
   */
  for (col = 0; col < dim; col++)  
    R_diag[col] = 0.0;
      
  if (FALSE) {
    printf("RB_diag - COD B transfer matrix\n");
    for (col = 0; col < dim; col++) 
      printf("%.4f ", R_diag[col]);
    
    printf("\n");
  }
  
  return R_diag;
}

/* Function: OTH_transferA_rate()
 * Date:     ER, Fri Aug  9 17:07:41 CDT 2002 [St. Louis] 
 * 
 * Purpose:  Fill R of the transfer matrix for the OTH model  
 * 
 * Args:     R --  
 * 
 * 
 * Returns:  R is allocated and filled here. R freed by caller. 
 */ 
double **
cod_A_transfermatrix_rate(int dim)
{
  double **R;
  int      row, col;
  
  /* allocate T_rate
   */
  R    = (double **) MallocOrDie (sizeof(double *) * dim      );
  R[0] = (double  *) MallocOrDie (sizeof(double  ) * dim * dim);
  
  for (row = 1; row < dim; row++)
    R[row] = R[0] + row*dim;
  
  /* fill T_rate.
   * 
   */ 
  for (row = 0; row < dim; row++) 
    for (col = 0; col < dim; col++)  
      R[row][col] = 0.5;
  
  if (FALSE) {
    printf("TA_rate - COD  transfer matrix\n");
    for (row = 0; row < dim; row++) {
      for (col = 0; col < dim; col++) {
	printf("%.4f ", R[row][col]);
      }
      printf("\n");
    }
  }
  
  return R;
}

double *
cod_B_transfermatrix_rate(int dim)
{
  double *R;
  int     col;

  /* allocate T_rate
   */
  R = (double  *) MallocOrDie (sizeof(double) * dim * dim);

  /* fill T_rate.
   * 
   */
  for (col = 0; col < dim; col++)  
    R[col] = 1.0/(float)dim;
  
  if (FALSE) {
    printf("TB_rate - COD transfer matrix\n");
      for (col = 0; col < dim; col++) 
	printf("%.4f ", R[col]);
      
      printf("\n");
    }
  
  return R;
}


double
normalizecodparam(struct codparam_s codparam)
{
  int    i,j;
  double sum = 0.;

  for (i = 0; i < 4; i++)
    for (j = 0; j < 4; j++)

      sum += codparam.xi[i*4+j];
  
  sum /= (1.0 - (double)codparam.tau);

  return sum;
}

