// file: tr_st_eval_0.cc
//

// isip include files
//
#include "train_state.h"
#include "train_state_constants.h"

static float_8* trans_data = (float_8*)NULL;
static int_4 trans_data_size = 0;

// method: eval_score_cc
//
// arguments:
//  float_8* data : (input) a data feature vector
//  int_4 frame : (input) the current frame index
//  int_4& max_mix : (output) the highest mixture component 
//
// return: a logical_1 indicating success
//
// this method evaluates the input feature vector against the Train_State
// distribution and computes a log-distance metric (i.e. a log score
// of the data given the model)
//
float_8 Train_State::eval_score_cc(float_8* data_a, int_4 frame_a,
			     int_4& max_mix_a) {

  // evaluate this state only if it has not been evaluated before
  //
  if (frame_d != frame_a) {

    // temporary variables
    //
    float_8 tmp_score = (float_8)0;
    float_8 tmp = (float_8)0;
    float_8 max_score = (float_8)TRAIN_STATE_SCORE;
    int_4 max_mix = (int_4)0;
    
    if (trans_data_size < num_features_d) {
      if (trans_data != (float_8*)NULL) {
	delete [] trans_data;
      }
      trans_data = new float_8[num_features_d];
      trans_data_size = num_features_d;
    }
    
    // assign frame index
    //
    frame_d = frame_a;
    
    // initialize score
    //
    score_d = TRAIN_STATE_SCORE;
    
    // loop over all mixture components, find the highest weight
    //
    for (int_4 i = 0; i < num_mixtures_d; i++) {

      // reset tmp score
      //
      tmp_score = (float_8)scale_d[i];
      
      // compute the likelihood of data given mixture
      //
      for (int_4 j = 0; j < num_features_d; j++) {
	
	// compute the translated data and take the product to evaluate
	// likelihood score
	//
	trans_data[j] = data_a[j] - (float_8)mean_d[i][j];
	tmp_score += trans_data[j] * trans_data[j] * (float_8)covar_d[i][j];
      }
    
      // add the mixture weight, use recursive sum to protect against
      // underflow
      //
      tmp_score = (float_8)weights_d[i] - (float_8)0.5 * tmp_score;
            
      if (tmp_score >= max_score) {
	max_score = tmp_score;
	max_mix = i;
      }
      
      if (score_d < tmp_score) {
	tmp = score_d;
	score_d = tmp_score;
	tmp_score = tmp;
      }
      tmp = tmp_score - score_d;
      if (tmp >= TRAIN_STATE_LOG_SCORE) {
	score_d += (float_8)log(1.0 + exp((float_8)tmp));
      }
      else {
	if (score_d < TRAIN_STATE_MIN_SCORE) {
	  score_d = TRAIN_STATE_SCORE;
	}
      }
    }

    // return the index of the highest mixture
    //
    max_mix_a = (int_4)max_mix;
  }
  
  // return the log likelihood score
  //
  return score_d;
}

