// file: $USFS/class/image_eval/v1.0/imgev_corr_0.cc
//

// isip include files
//
#include "image_eval.h"

#include <integral_constants.h>
#include "image_eval_constants.h"

// method: correlation_cc
//
// arguments:
//  char_1** ref_fnames_a: (input) containing filenames of reference data
//  float_4* ref_values_a: (input) containing scores of reference data
//  int_4 ref_num_items_a: (input) indicating how many reference data
//  char_1** tst_fnames_a: (input) containing filenames of test data
//  float_4* tst_values_a: (input) containing scores of test data
//  int_4 tst_num_items: (input) indicating how many test data
//
// return:
//  float_4 correlation value
//
// This method calculates the correlation between two sets
// of scores.
//
//
float_4 Image_eval::correlation_cc(char_1** ref_fnames_a,
				   float_4* ref_values_a,
				   int_4 ref_num_items_a,
				   char_1** tst_fnames_a,
				   float_4* tst_values_a,
				   int_4 tst_num_items_a) {

  // calculate the average scores
  //
  float_4 ref_avg = average_cc(ref_values_a, ref_num_items_a);
  float_4 tst_avg = average_cc(tst_values_a, tst_num_items_a);

  if (debug_level_d > ISIP_DEBUG_BRIEF) {
    fprintf(stdout, IMGEV_DEBUG_FORMAT_I, IMAGE_EVAL_CLASS_NAME,
	    "correlation_cc", ref_avg);
    fprintf(stdout, IMGEV_DEBUG_FORMAT_J, IMAGE_EVAL_CLASS_NAME,
	    "correlation_cc", tst_avg);
  }

  // sort the data to facilitate searching
  //
  int_4 ref_index[ref_num_items_a];

  if (qsort_cc(ref_index, ref_fnames_a, ref_num_items_a) == ISIP_FALSE) {
    error_handler_cc((char_1*)"correlation_cc",
		     (char_1*)"test item not found");
    return IMGEV_ERROR;
  }
  
  // compute the correlation
  //
  float_4 num=0.0;
  float_4 denom1=0.0;
  float_4 denom2=0.0;  
  
  for (int_4 i=0; i<tst_num_items_a; i++) {

    // locate the corresponding reference data
    //
    int_4 pos = lookup_cc(tst_fnames_a[i], ref_fnames_a,
			  ref_num_items_a, ref_index);
    if (pos == IMGEV_NOT_FOUND) {
      error_handler_cc((char_1*)"correlation_cc",
		       (char_1*)"test item not found");
      return ISIP_FALSE;
    }

    // update the correlation sums
    //
    float_4 sum1 = tst_values_a[i] - tst_avg;
    float_4 sum2 = ref_values_a[ref_index[pos]] - ref_avg;

    num += sum1*sum2;
    denom1 += sum1*sum1;
    denom2 += sum2*sum2;
  }

  // check for overflow
  //
  if ((denom1 <= (float_4)0.0) || (denom2 <= (float_4)0.0)) {
    error_handler_cc((char_1*)"correlation_cc",
		     (char_1*)"bad data");
    return IMGEV_ERROR;
  }

  // exit gracefully and return the correlation
  //
  return num / sqrt(denom1*denom2);
}
