double evaluatePartialGeneric (tree *tr, int i, double ki, int _model)
{
    double result;
    int
    branchReference,
    states = tr->partitionData[_model].states;


    int
    index;

    if(tr->manyPartitions)
        index = i - tr->partitionData[_model].lower;
    else
        index = i;

    if(tr->numBranches > 1)
        branchReference = _model;
    else
        branchReference = 0;

#ifndef _OPTIMIZED_FUNCTIONS
    if(tr->rateHetModel == CAT)
        result = evaluatePartialCAT_FLEX(index, ki, tr->td[0].count, tr->td[0].ti, tr->td[0].ti[0].qz[branchReference],
                                         tr->partitionData[_model].wgt[index],
                                         tr->partitionData[_model].EIGN,
                                         tr->partitionData[_model].EI,
                                         tr->partitionData[_model].EV,
                                         tr->partitionData[_model].tipVector,
                                         tr->partitionData[_model].yVector, branchReference, tr->mxtips, states);
    else
        /*
           the per-site site likelihood function should only be called for the CAT model
           under the GAMMA model this is required only for estimating per-site protein models
           which has however been removed in this version of the code
        */
        assert(0);


#else
    switch(states)
    {

    case 4:   /* DNA */
        assert(tr->rateHetModel == CAT);

        result = evaluatePartialGTRCAT(index, ki, tr->td[0].count, tr->td[0].ti, tr->td[0].ti[0].qz[branchReference],
                                       tr->partitionData[_model].wgt[index],
                                       tr->partitionData[_model].EIGN,
                                       tr->partitionData[_model].EI,
                                       tr->partitionData[_model].EV,
                                       tr->partitionData[_model].tipVector,
                                       tr->partitionData[_model].yVector, branchReference, tr->mxtips);
        break;
    case 20: /* proteins */
        if(tr->rateHetModel == CAT)
            result = evaluatePartialGTRCATPROT(index, ki, tr->td[0].count, tr->td[0].ti, tr->td[0].ti[0].qz[branchReference],
                                               tr->partitionData[_model].wgt[index],
                                               tr->partitionData[_model].EIGN,
                                               tr->partitionData[_model].EI,
                                               tr->partitionData[_model].EV,
                                               tr->partitionData[_model].tipVector,
                                               tr->partitionData[_model].yVector, branchReference, tr->mxtips);
        else
            result =  evaluatePartialGTRGAMMAPROT(index, tr->td[0].count, tr->td[0].ti, tr->td[0].ti[0].qz[branchReference],
                                                  tr->partitionData[_model].wgt[index],
                                                  tr->partitionData[_model].EIGN,
                                                  tr->partitionData[_model].EI,
                                                  tr->partitionData[_model].EV,
                                                  tr->partitionData[_model].tipVector,
                                                  tr->partitionData[_model].yVector,
                                                  tr->partitionData[_model].gammaRates,
                                                  branchReference, tr->mxtips);
        break;
    default:
        assert(0);
    }
#endif


    return result;
}
double evaluatePartialGeneric (tree *tr, int i, double ki, int _model)
{
  double result;
  int 
    branchReference,
    states = tr->partitionData[_model].states;
    
#ifdef _USE_PTHREADS
  int index = i; 
#else
  int index = i - tr->partitionData[_model].lower;
#endif
  
  if(tr->multiBranch)
    branchReference = _model;
  else
    branchReference = 0;

  assert(tr->rateHetModel == CAT);
    
 

  switch(tr->partitionData[_model].dataType)
    {
    case BINARY_DATA:
      result = evaluatePartialGTRCAT_BINARY(index, ki, tr->td[0].count, tr->td[0].ti, tr->td[0].ti[0].qz[branchReference], 
					    tr->partitionData[_model].wgt[index],
					    tr->partitionData[_model].EIGN, 
					    tr->partitionData[_model].EI, 
					    tr->partitionData[_model].EV,
					    tr->partitionData[_model].tipVector,
					    tr->partitionData[_model].yVector, branchReference, tr->mxtips);
      break;
    case DNA_DATA:      
      result = evaluatePartialGTRCAT(index, ki, tr->td[0].count, tr->td[0].ti, tr->td[0].ti[0].qz[branchReference], 
				     tr->partitionData[_model].wgt[index],
				     tr->partitionData[_model].EIGN, 
				     tr->partitionData[_model].EI, 
				     tr->partitionData[_model].EV,
				     tr->partitionData[_model].tipVector,
				     tr->partitionData[_model].yVector, branchReference, tr->mxtips);
      break;
    case AA_DATA:
      result = evaluatePartialGTRCATPROT(index, ki, tr->td[0].count, tr->td[0].ti, tr->td[0].ti[0].qz[branchReference], 
					 tr->partitionData[_model].wgt[index],
					 tr->partitionData[_model].EIGN, 
					 tr->partitionData[_model].EI, 
					 tr->partitionData[_model].EV,
					 tr->partitionData[_model].tipVector, 
					 tr->partitionData[_model].yVector, branchReference, tr->mxtips);
      break;
    case SECONDARY_DATA:
       result = evaluatePartialGTRCATSECONDARY(index, ki, tr->td[0].count, tr->td[0].ti, tr->td[0].ti[0].qz[branchReference], 
					       tr->partitionData[_model].wgt[index],
					       tr->partitionData[_model].EIGN, 
					       tr->partitionData[_model].EI, 
					       tr->partitionData[_model].EV,
					       tr->partitionData[_model].tipVector, 
					       tr->partitionData[_model].yVector, branchReference, tr->mxtips);
      break;
    case SECONDARY_DATA_6:
      result = evaluatePartialGTRCATSECONDARY_6(index, ki, tr->td[0].count, tr->td[0].ti, tr->td[0].ti[0].qz[branchReference], 
						tr->partitionData[_model].wgt[index],
						tr->partitionData[_model].EIGN, 
						tr->partitionData[_model].EI, 
						tr->partitionData[_model].EV,
						tr->partitionData[_model].tipVector, 
						tr->partitionData[_model].yVector, branchReference, tr->mxtips);
      break; 
    case SECONDARY_DATA_7:
      result = evaluatePartialGTRCATSECONDARY_7(index, ki, tr->td[0].count, tr->td[0].ti, tr->td[0].ti[0].qz[branchReference], 
						tr->partitionData[_model].wgt[index],
						tr->partitionData[_model].EIGN, 
						tr->partitionData[_model].EI, 
						tr->partitionData[_model].EV,
						tr->partitionData[_model].tipVector, 
						tr->partitionData[_model].yVector, branchReference, tr->mxtips);
    case GENERIC_32:
      result = evaluatePartialFlex(index, ki, tr->td[0].count, tr->td[0].ti, tr->td[0].ti[0].qz[branchReference], 
				   tr->partitionData[_model].wgt[index],
				   tr->partitionData[_model].EIGN, 
				   tr->partitionData[_model].EI, 
				   tr->partitionData[_model].EV,
				   tr->partitionData[_model].tipVector, 
				   tr->partitionData[_model].yVector, branchReference, tr->mxtips, states);
      break;
    default:
      assert(0);
    }
 

  return result;
}