// file: st_eval_0.cc
//

// isip include files
//
#include "state.h"
#include "state_constants.h"

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

// method: eval_score_cc
//
// arguments:
//  float_4* data : (input) a data feature vector
//  int_4 frame : (input) the current frame index
//
// return: a logical_1 indicating success
//
// this function evaluates the input feature vector against the State
// distribution and computes a log-distance metric (i.e. a log score
// of the data given the model
//
float_4 State::eval_score_cc(float_4* data_a, int_4 frame_a) {

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

    // dummy variables
    //
    float_4 tmp_score = (float_4)0;
    float_4 tmp = (float_4)0;

    if (trans_data_size < num_features_d) {
      if (trans_data != (float_4*)NULL) {
	delete [] trans_data;
      }
      trans_data = new float_4[num_features_d];
      trans_data_size = num_features_d;
    }
    
    // assign frame index
    //
    frame_d = frame_a;
    
    // initialize score
    //
    score_d = STATE_SCORE;
    
    // loop over all mixture components
    //
    for (int_4 i = 0; i < num_mixtures_d; i++) {
      
      // reset tmp score
      //
      tmp_score = (float_4)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_4)mean_d[i][j];
	tmp_score += trans_data[j] * trans_data[j] * (float_4)covar_d[i][j];
      }

      // add the mixture weight, use recursive sum to protect against
      // underflow
      //
      tmp_score = (float_4)weights_d[i] - (float_4)0.5 * tmp_score;
      if (score_d < tmp_score) {
	tmp = score_d;
	score_d = tmp_score;
	tmp_score = tmp;
      }
      tmp = tmp_score - score_d;
      if (tmp >= STATE_LOG_SCORE) {
	score_d += log(1.0 + exp(tmp));
      }
    }
  }

  // return the log likelihood score
  //
  return score_d;
}
