// file: dtn_compute_2.cc
//

// isip include files
//
#include "dt_node.h"
#include "dt_node_constants.h"

// method:  compute_covar_cc
//                                            
// arguments:
//   float_4* covar: (output) covariance vector (represent a diagonal matrix)
//   float_4& det_covar: (output) determinant of covariance
//   float_4 scale: (output) scale factor
//   State** states: (input) all states associated with this node
//   float_4* occupy: (input) state occupancy
//   int_4 num_feat: (input) the number of features
//   int_4 num_mix: (input) the number of mixtures
//
// return: a logical_1 indicating status
//
logical_1 Dt_node::compute_covar_cc(float_4* covar_a, float_4& det_covar_a,
				    float_4& scale_a, State** states_a,
				    float_4* occupy_a, int_4 num_feat_a,
				    int_4 num_mix_a) {

  // local variables
  //
  float_4** s_mean = (float_4**)NULL;
  float_4** s_covar = (float_4**)NULL;
  float_4 sum_occupy = 0;
  det_covar_a = 0.0;
  
  // make sure memory is allocated for covariance vector
  //
  if(covar_a == (float_4*)NULL) {
    covar_a = new float_4[num_feat_a];
  }
    
  // temporary array for computing the variance
  //
  float_4* tmp_1 = new float_4[num_feat_a];
  float_4* tmp_2 = new float_4[num_feat_a];

  for (int_4 k = 0; k<num_feat_a; k++) {
    covar_a[k] = 0.0;
    tmp_1[k] = 0.0;
    tmp_2[k] = 0.0;
  }
  
  // compute sum of the states occupancy
  //
  for (int_4 i= 0; i<num_states_d; i++) {
    sum_occupy += occupy_a[state_index_d[i]];
  }

  // make sure the division is valid
  //
  if(sum_occupy != 0) {
    
    // loop all the states in this node, compute the covariance
    //
    for (int_4 i = 0; i < num_states_d; i++) {
      
      s_mean = states_a[state_index_d[i]]->get_mean_cc();
      s_covar = states_a[state_index_d[i]]->get_covar_cc();
      
      // for each state, loop all its mixtures and features
      //
      for (int_4 j = 0; j < num_mix_a; j++) {	
	for (int_4 k=0; k<num_feat_a; k++) {
	  
	  tmp_1[k] += occupy_a[state_index_d[i]]*
	    ((1/s_covar[j][k]) + s_mean[j][k]*s_mean[j][k]);
	  tmp_2[k] += occupy_a[state_index_d[i]]*s_mean[j][k];
	}
      }
    }
    
    // assume the covariance matrix to be diagonal
    //
    for (int_4 k = 0; k < num_feat_a; k++) {
      covar_a[k] = (tmp_1[k] - tmp_2[k]*tmp_2[k]/sum_occupy)/sum_occupy;
      det_covar_a += log(covar_a[k]);
      scale_a += log(covar_a[k] * ISIP_TWOPI);
    }
  } // end if sum_occupy != 0
  
  // free memory
  //
  delete [] tmp_1;
  delete [] tmp_2;
  
  return ISIP_TRUE;
}
