// file: bw_bound_0.cc
//

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

// method: get_bound_cc
//
// arguments:
//  int_2* upper : (output) the upper model bound for each frame
//  int_2* lower : (output) the lower model bound for each frame
//  int_4 num_vect : (input) the total number of frames
//  Model** models : (input) the model objects
//  int_4 num_mod : (input) the number of models in current transcription
//  int_4* model_list : (input) the index list of current models
//
// return: a logical_1 indicating success
//
// this method loops over all the time frames in the current mfcc file and
// compute the valid upper and lower model bounds for each of them
//
logical_1 get_bound_cc(int_2* upper_a, int_2* lower_a, int_4 num_vect_a,
		       Train_Model** models_a, int_4 num_mod_a,
		       int_4* model_list_a) {

  // local variables
  //
  int_2 upp_ind, low_ind, total_len;
  int_2 tmp = (int_4)0;
  int_2* min_lens = (int_2*)NULL;
  Train_Model* mod = (Train_Model*)NULL;

  // get the shortest lengths for each input model
  //
  min_lens = new int_2[num_mod_a];
  for (int_4 i = 0; i < num_mod_a; i++) {
    mod = models_a[model_list_a[i]];
    get_minlen_cc(tmp, mod);
    min_lens[i] = tmp;
  }
  
  // calculate the upper bound
  //
  total_len = (int_2)0;
  upp_ind = (int_2)0;
  for (int_4 t = 1; t <= num_vect_a; t++) {

    while(total_len < t) {
      total_len += min_lens[upp_ind++];
      if (upp_ind == num_mod_a) {
	break;
      }
    }
    if (upp_ind == num_mod_a) {
      break;
    }
    upper_a[t] = upp_ind;
  }

  // calculate the lower bound
  //
  total_len = (int_2)min_lens[num_mod_a-1];
  low_ind = num_mod_a;
  for (int_4 t = num_vect_a; t >= 1; t--) {

    while(total_len < (num_vect_a - t + 1)) {
      low_ind--;
      total_len += min_lens[low_ind-1];
      if (low_ind == 1) {
	break;
      }
    }
    if (low_ind == 1) {
      break;
    }
    if (((num_vect_a - t + 1) == total_len) && (min_lens[low_ind-2] == 0)) {
      low_ind--;
    }
    lower_a[t] = low_ind;
  }
  
  // clean up
  //
  delete [] min_lens;
  mod = (Train_Model*)NULL;
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
