// file: bw_pdf_0.cc
//

// isip include files
//
#include "bw_train.h"
#include "bw_train_constants.h"

// method: acc_pdf_cc
//
// arguments:
//  float_8*** means : (output) the accumulated means
//  float_8*** covars : (output) the accumulated covariance
//  float_8** mix_weights : (output) the accumulated weights
//  float_8* states_occ : (output) the accumulated state occupancy
//  float_8** vectors : (input) the speech data
//  int_4 num_feat : (input) the number of features
//  int_4 num_vect : (input) the number of frames
//  int_4 num_mod : (input) the number of models in current list
//  int_4* model_list : (input) the list of model index
//  int_4** st_map : (input) the mapping to the global state index
//  State** states : (input) the states sequence
//  Train_Model** models : (input) the model sequence
//  float_8 utt_prob : (input) the utterance probability
//  float_8** for_probt : (input) the forward probability of current frame
//  float_8** for_probt1 : (input) the forward prob. of previous frame
//  float_8*** back_prob : (input) the backward probability
//  int_4 frame : (input) the index of current frame
//  int_2* upper : (input) upper bound
//  int_2* lower : (input) lower bound
//  float_4 min_mpd : (input) minimum model score
//  float_4 min_occp : (input) minimum occpancy probability
//  
// return a logical flag to indicate success
//

// this method updates the state accumulators for the current
// utterance
//
logical_1 acc_pdf_cc(float_8*** means_a, float_8*** covars_a,
		     float_8** mix_weights_a, float_8* states_occ_a,
		     float_8** vectors_a, int_4 num_feat_a, int_4 num_vect_a,
		     int_4 num_mod_a, int_4* model_list_a, int_4** st_map_a,
		     Train_State** states_a, Train_Model** models_a, float_8 utt_prob_a,
		     float_8** for_probt_a, float_8** for_probt1_a,
		     float_8*** back_prob_a, int_4 frame_a,
		     int_2* upper_a, int_2* lower_a, float_4 min_mpd_a,
		     float_4 min_occp_a) {

  // local variables
  //
  int_4 loc_st = (int_4)0;
  int_4 loc_mix = (int_4)0;
  float_8 occ_prob = BW_LOG_ZERO;
  float_8 tmp_acc = (float_8)0.0;
  float_8 tmp_mprob = (float_8)0.0;  
  int_4 st_ind = (int_4)0;
  float_4** trans = (float_4**)NULL;
  Train_Model* model = (Train_Model*)NULL;
  Train_State** st_list = (Train_State**)NULL;
  Train_State* state = (Train_State*)NULL;

  // loop over all the models
  //
  for (int_2 q = lower_a[frame_a]; q <= upper_a[frame_a]; q++) {

    // get the model
    //
    model = models_a[model_list_a[q-1]];
    
    // get the transition
    //
    trans = model->get_transitions_cc();
    
    // get the number of states 
    //
    loc_st = model->get_num_states_cc();
    st_list = model->get_states_cc();
    
    // loop over the states
    //
    for (int_4 j = 2; j < loc_st; j++) {

      // bound check
      //
      tmp_mprob = for_probt_a[q][j] + back_prob_a[frame_a][q][j] -
	utt_prob_a;
      if (tmp_mprob > -min_mpd_a) {
	
	// get the current state and global index
	//
	state = st_list[j-1];
	st_ind = st_map_a[model_list_a[q-1]][j-1];
	
	// get the number of mixtures
	//
	loc_mix = state->get_num_mixtures_cc();
	
	// loop over the mixtures
	//
	for (int_4 m = 1; m <= loc_mix; m++) {
	  
	  // reset and compute the occupancy
	  //
	  occ_prob = BW_LOG_ZERO;
	  comp_occ_cc(occ_prob, q, loc_st, frame_a, state, j, m, utt_prob_a,
		      trans, for_probt_a, for_probt1_a, back_prob_a,
		      vectors_a[frame_a-1]);
	  occ_prob = exp(occ_prob);

	  if (occ_prob > min_occp_a) {
	    
	    // loop over the current vector
	    //
	    for (int_4 feat = 0; feat < num_feat_a; feat++) {
	      
	      // accumulate the mean
	      //
	      tmp_acc = occ_prob * vectors_a[frame_a-1][feat];
	      means_a[st_ind][m-1][feat] += tmp_acc;
	      
	      // accumulate the covariance
	      //
	      covars_a[st_ind][m-1][feat] += tmp_acc * vectors_a[frame_a-1][feat];
	    }
	    
	    // accumulate the weights
	    //
	    mix_weights_a[st_ind][m-1] += occ_prob;
	    
	    // accumulate the state occupancy
	    //
	    states_occ_a[st_ind] += occ_prob;

	  } 
	}
      } // end of evaluating a valid state
    }
  } // end of looping over all the valid models
  
  // exit gracefully
  //
  return(ISIP_TRUE);
}
