// file: $isip_ifc/class/stat/Histogram/hist_02.cc
// version: $Id: hist_02.cc 10427 2006-02-13 19:33:54Z srinivas $
//

// isip include files
//
#include "Histogram.h"
#include <Console.h>

// method: diagnose
//
// arguments:
//  Integral::DEBUG level: (input) debug level for diagnostics
//
// return: a boolean value indicating status
//
// this is the diagnose method
//
boolean Histogram::diagnose(Integral::DEBUG level_a) {
  
    
  //---------------------------------------------------------------------------
  //
  // 0. preliminaries
  //
  //---------------------------------------------------------------------------

  // output the class name
  //
  if (level_a > Integral::NONE) {
    SysString output(L"diagnosing class ");
    output.concat(CLASS_NAME);
    output.concat(L": ");
    Console::put(output);
    Console::increaseIndention();
  }
  
  //--------------------------------------------------------------------------
  //
  // 1. required public methods
  //
  //--------------------------------------------------------------------------

  // set indentation
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing required public methods...\n");
    Console::increaseIndention();
  }

  // create data to test with
  //
  Vector<VectorDouble> test_bins(1);
  test_bins(0).assign(L"1, 3, 5, 7, 9");
  VectorDouble test_edges_bins(L"0, 2.5, 5, 7.5, 10");
  VectorLong test_counts(L"3, 2, 2, 2");
  
  //  VectorDouble test_data(L"0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10");
  
  // do a quick test of constructors, destructors and memory management
  // methods
  //
  Histogram::setGrowSize(5);
  Histogram* hist0 = new Histogram(LINEAR);
  Histogram* hist1 = new Histogram(*hist0);
  Histogram* hist2 = new Histogram[10];

  // clear the pointers
  //
  delete hist0;
  delete hist1;
  delete [] hist2;

  // set the internal data of hist0
  //
  hist0 = new Histogram(LINEAR, EDGES, 1);
  hist0->setBins(test_bins);
  hist0->setCounts(test_counts);

  // test the assign and eq methods
  //
  hist1 = new Histogram;
  hist1->assign(*hist0);
  if (!hist1->eq(*hist0)) {
    hist0->debug(L"expected Histogram object");
    hist1->debug(L"actual Histogram object");
    return Error::handle(name(), L"assign/eq", Error::TEST,
			 __FILE__, __LINE__);
  }
  delete hist1;

  // test copy constructor
  //
  hist1 = new Histogram(*hist0);
  if (!hist1->eq(*hist0)) {
    hist0->debug(L"expected Histogram");
    hist1->debug(L"actual Histogram");
    return Error::handle(name(), L"copy constructor", Error::TEST,
			 __FILE__, __LINE__);
  }

  // test the clear method
  //
  hist0->clear();
  if (hist1->eq(*hist0)) {
    hist0->debug(L"hist0 not clear");
    return Error::handle(name(), L"clear", Error::TEST, __FILE__, __LINE__);
  }
  
  // test the operator= method
  //
  *hist0 = *hist1;
  if (!hist1->eq(*hist0)) {
    hist1->debug(L"expected Histogram");
    hist0->debug(L"actual Histogram");
    return Error::handle(name(), L"operator=", Error::TEST, __FILE__,
			 __LINE__);
  }
  
  // clear the pointers
  //
  delete hist0;
  delete hist1;

  // test the i/o methods
  //
  Histogram hist3;
  Histogram hist4;
  Histogram hist5;
  Histogram hist6;
  hist3.setMode(EDGES);
  hist4.setMode(CENTERS);
  hist4.setScale(LOG);

  hist3.setBins(test_bins);
  hist3.setCounts(test_counts);

  test_counts.assign(L"2, 3, 4, 5, 1");
  hist4.setBins(test_bins);
  hist4.setCounts(test_counts);

  
  // we need binary and text sof files
  //
  String tmp_filename0;
  Integral::makeTemp(tmp_filename0);
  String tmp_filename1;
  Integral::makeTemp(tmp_filename1);

  // open files in write mode
  //
  Sof tmp_file0;
  tmp_file0.open(tmp_filename0, File::WRITE_ONLY, File::TEXT);
  Sof tmp_file1;
  tmp_file1.open(tmp_filename1, File::WRITE_ONLY, File::BINARY);

  hist3.write(tmp_file0, (long)0);
  hist4.write(tmp_file0, (long)1);
  hist3.write(tmp_file1, (long)0);
  hist4.write(tmp_file1, (long)1);

  // close the files
  //
  tmp_file0.close();
  tmp_file1.close();

  // open the files in read mode
  //
  tmp_file0.open(tmp_filename0);
  tmp_file1.open(tmp_filename1);

  // read the histograms back in
  //
  hist5.read(tmp_file0, (long)0);
  hist6.read(tmp_file0, (long)1);

  if (!hist5.eq(hist3)) {
    hist3.debug(L"expected Histogram");
    hist5.debug(L"hist5 actual");
    return Error::handle(name(), L"read", Error::TEST, __FILE__, __LINE__);
  }

  if (!hist6.eq(hist4)) {
    hist4.debug(L"expected Histogram");
    hist6.debug(L"hist6 actual");
    return Error::handle(name(), L"read", Error::TEST, __FILE__, __LINE__);
  }

  // read the model written in binary
  //
  hist5.clear();
  hist6.clear();
  hist5.read(tmp_file1, (long)0);
  hist6.read(tmp_file1, (long)1);

  if (!hist5.eq(hist3)) {
    hist3.debug(L"expected Histogram");
    hist5.debug(L"hist5 actual");
    return Error::handle(name(), L"read", Error::TEST, __FILE__, __LINE__);
  }

  if (!hist6.eq(hist4)) {
    hist4.debug(L"expected Histogram");
    hist6.debug(L"hist6 actual");
    return Error::handle(name(), L"read", Error::TEST, __FILE__, __LINE__);
  }

  // close and  delete the temporary files
  //
  tmp_file0.close();
  tmp_file1.close();
  
  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }

  //---------------------------------------------------------------------------
  //
  // 2. class-specific public methods:
  //     set methods
  //
  //---------------------------------------------------------------------------

  // set indentation
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing class-specific public methods: set methods...\n");
    Console::increaseIndention();
  }

  // test setMode
  //
  hist6.setMode(CENTERS);
  if (hist6.mode_d != CENTERS) {
    return Error::handle(name(), L"setMode", Error::TEST, __FILE__,
			 __LINE__);
  }
  
  // test setDim
  //
  long dim = 6;
  hist6.setDim(dim);
  if (hist6.dim_d != dim) {
    return Error::handle(name(), L"setMode", Error::TEST, __FILE__,
			 __LINE__);
  }

  // test setBins
  //
  hist6.clear();
  hist6.setDim(1);
  hist6.setBins(5, 1.0, 3.0);
  VectorDouble expected_bins(L"1.0, 1.4, 1.8, 2.2, 2.6, 3.0");
  if (!hist6.bins_d(0).almostEqual(expected_bins)) {
    hist6.bins_d.debug(L"bins_d");
    return Error::handle(name(), L"setBins", Error::TEST, __FILE__,
			 __LINE__);
  }

  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }
  
  //---------------------------------------------------------------------------
  //
  // 3. class-specific public methods:
  //     get methods
  //
  //---------------------------------------------------------------------------

  // set indentation
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing class-specific public methods: get methods...\n");
    Console::increaseIndention();
  }

  // test getMode
  //
  hist5.setMode(CENTERS);
  if (hist5.getMode() != CENTERS) {
    return Error::handle(name(), L"getMode", Error::TEST, __FILE__,
			 __LINE__);
  }

  // test getBins
  //
  Vector<VectorDouble> tmp;
  if (!hist6.getBins(tmp) || !tmp(0).almostEqual(expected_bins)) {
    return Error::handle(name(), L"getBins", Error::TEST, __FILE__,
			 __LINE__);
  }

  // test getCounts
  //
  VectorLong in_counts(L"1, 2, 3, 4, 5");
  hist6.setCounts(in_counts);
  VectorLong out_counts;
  hist6.getCounts(out_counts);
  
  if (!out_counts.eq(in_counts) || !hist6.counts_d.eq(in_counts)) {
    return Error::handle(name(), L"getCounts", Error::TEST, __FILE__,
			 __LINE__);
  }

  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }

  //---------------------------------------------------------------------------
  //
  // 4. class-specific public methods:
  //     compute, count, pdf and cdf
  //
  //    testing is done only for method cdf as it is built on all the
  //    methods - pdf, count and compute
  //
  //---------------------------------------------------------------------------

  // set indentation
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing class-specific public methods: compute to cdf methods...\n");
    Console::increaseIndention();
  }

  // create the test data and bins
  //
  
  // 1-D data
  //
  Vector<VectorFloat> test_data1(1);
  test_data1(0).assign(L"1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 4.1, 3.1, 2.1, 1.1");
  // 2-D data
  //
  Vector<VectorFloat> test_data2((long)2);
  test_data2(0).assign(L"1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 4.1, 3.1, 2.1, 1.1");
  test_data2(1).assign(L"1.1, 2.1, 3.1, 4.1, 5.1, 7.1, 4.1, 3.1, 2.1, 1.1");  

  // user-defined bins
  //
  Vector<VectorFloat> bins_1a(1), bins_2a(2);
  bins_1a(0).assign(L"1.0, 3.0, 5.0, 7.0");
  bins_2a(0).assign(L"1.0, 3.0, 5.0, 7.0");
  bins_2a(1).assign(L"1.0, 3.0, 5.0, 7.0");

  VectorFloat bins_1b, bins_2b;
  bins_1b.assign(L"1.0, 3.0, 5.0, 7.0");
  bins_2b.assign(L"1.0, 3.0, 5.0, 7.0");
  
  // LINEAR/LOG scale bins
  //
  long num_bins_1c = 3, num_bins_2c = 3;
  float min_1c = 1.0, max_1c = 7.0, min_2c = 1.0, max_2c = 7.0;
  VectorLong num_bins_1d(1), num_bins_2d(2);
  num_bins_1d(0) = 3;
  num_bins_2d(0) = 3;
  num_bins_2d(1) = 3;
  VectorFloat min_1d(1), max_1d(1), min_2d(2), max_2d(2);
  min_1d.assign(L"1.0");
  max_1d.assign(L"7.0");
  min_2d.assign(L"1.0, 1.0");
  max_2d.assign(L"7.0, 7.0");

  // vector of expected results for comparison
  //
  VectorDouble expected_cdf1, expected_cdf2;
  VectorDouble actual_cdf1, actual_cdf2;

  // test a new histogram in EDGES mode for each SCALE and each way of
  // setting bins

  // test 1-d and 2-d hists for USER_DEFINED scale histograms
  //
  expected_cdf1.assign(L"0.4, 0.8, 1");
  expected_cdf2.assign(L"0.4, 0.4, 0.4, 0.4, 0.8, 0.8, 0.4, 0.8, 1");
  
  hist6.clear();
  hist6.setScale(USER_DEFINED);
  hist6.setDim(1);
  hist6.setBins(bins_1a);
  hist6.compute(test_data1);
  hist6.cdf(actual_cdf1);
  if (!actual_cdf1.almostEqual(expected_cdf1)) {
    actual_cdf1.debug(L"actual cdf1");
    expected_cdf1.debug(L"expected cdf1");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
    			 __LINE__);
  }

  hist6.clear();
  hist6.setScale(USER_DEFINED);
  hist6.setDim(2);
  hist6.setBins(bins_2a);
  hist6.compute(test_data2);
  hist6.cdf(actual_cdf2);
  if (!actual_cdf2.almostEqual(expected_cdf2)) {
    actual_cdf2.debug(L"actual cdf2");
    expected_cdf2.debug(L"expected cdf2");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
    			 __LINE__);
  }

  hist6.clear();
  hist6.setScale(USER_DEFINED);
  hist6.setDim(1);
  hist6.setBins(bins_1b);
  hist6.compute(test_data1);
  hist6.cdf(actual_cdf1);
  if (!actual_cdf1.almostEqual(expected_cdf1)) {
    actual_cdf1.debug(L"actual cdf1");
    expected_cdf1.debug(L"expected cdf1");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
      			 __LINE__);
  }

  hist6.clear();
  hist6.setScale(USER_DEFINED);
  hist6.setDim(2);
  hist6.setBins(bins_2b);
  hist6.compute(test_data2);
  hist6.cdf(actual_cdf2);
  if (!actual_cdf2.almostEqual(expected_cdf2)) {
    actual_cdf2.debug(L"actual cdf2");
    expected_cdf2.debug(L"expected cdf2");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
      			 __LINE__);
  }

  // test 1-d and 2-d hists for LINEAR scale histograms
  //

  expected_cdf1.assign(L"0.4, 0.8, 1");
  expected_cdf2.assign(L"0.4, 0.4, 0.4, 0.4, 0.8, 0.8, 0.4, 0.8, 1");
  
  hist6.clear();
  hist6.setDim(1);
  hist6.setBins(num_bins_1c, min_1c, max_1c);
  // test 1D histogram specific compute method
  //
  hist6.compute(test_data1(0));
  hist6.cdf(actual_cdf1);
  if (!actual_cdf1.almostEqual(expected_cdf1)) {
    actual_cdf1.debug(L"actual cdf1");
    expected_cdf1.debug(L"expected cdf1");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
    			 __LINE__);
  }

  hist6.clear();
  hist6.setDim(2);
  hist6.setBins(num_bins_2c, min_2c, max_2c);
  hist6.compute(test_data2);
  // test 2D histogram specific cdf method
  //
  MatrixDouble actual_cdf2_mat;
  MatrixDouble expected_cdf2_mat(3, 3, L"0.4, 0.4, 0.4, 0.4, 0.8, 0.8, 0.4, 0.8, 1");
  actual_cdf2.clear();
  hist6.cdf(actual_cdf2_mat);
  if (!actual_cdf2_mat.almostEqual(expected_cdf2_mat)) {
    actual_cdf2_mat.debug(L"actual cdf2_mat");
    expected_cdf2_mat.debug(L"expected cdf2_mat");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
    			 __LINE__);
  }

  hist6.clear();
  hist6.setDim(1);
  hist6.setBins(num_bins_1d, min_1d, max_1d);
  hist6.compute(test_data1);
  hist6.cdf(actual_cdf1);
  if (!actual_cdf1.almostEqual(expected_cdf1)) {
    actual_cdf1.debug(L"actual cdf1");
    expected_cdf1.debug(L"expected cdf1");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
      			 __LINE__);
  }

  hist6.clear();
  hist6.setDim(2);
  hist6.setBins(num_bins_2d, min_2d, max_2d);
  hist6.compute(test_data2);
  hist6.cdf(actual_cdf2);
  if (!actual_cdf2.almostEqual(expected_cdf2)) {
    actual_cdf2.debug(L"actual cdf2");
    expected_cdf2.debug(L"expected cdf2");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
      			 __LINE__);
  }

  // test 1-d and 2-d hists for LOG scale histograms
  //

  expected_cdf1.assign(L"0.2, 0.6, 1");
  expected_cdf2.assign(L"0.2, 0.2, 0.2, 0.2, 0.6, 0.6, 0.2, 0.6, 1");
  
  hist6.clear();
  hist6.setDim(1);
  hist6.setScale(LOG);
  hist6.setBins(num_bins_1c, min_1c, max_1c);
  hist6.compute(test_data1);
  hist6.cdf(actual_cdf1);
  if (!actual_cdf1.almostEqual(expected_cdf1)) {
    actual_cdf1.debug(L"actual cdf1");
    expected_cdf1.debug(L"expected cdf1");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
			 __LINE__);
  }
  hist6.clear();
  hist6.setScale(LOG);
  hist6.setDim(2);
  hist6.setBins(num_bins_2c, min_2c, max_2c);
  hist6.compute(test_data2);
  hist6.cdf(actual_cdf2);
  if (!actual_cdf2.almostEqual(expected_cdf2)) {
    actual_cdf2.debug(L"actual cdf2");
    expected_cdf2.debug(L"expected cdf2");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
			 __LINE__);
  }

  hist6.clear();
  hist6.setDim(1);
  hist6.setScale(LOG);
  hist6.setBins(num_bins_1d, min_1d, max_1d);
  hist6.compute(test_data1);
  hist6.cdf(actual_cdf1);
  if (!actual_cdf1.almostEqual(expected_cdf1)) {
    actual_cdf1.debug(L"actual cdf1");
    expected_cdf1.debug(L"expected cdf1");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
    			 __LINE__);
  }
  hist6.clear();
  hist6.setScale(LOG);
  hist6.setDim(2);
  hist6.setBins(num_bins_2d, min_2d, max_2d);
  hist6.compute(test_data2);
  hist6.cdf(actual_cdf2);
  if (!actual_cdf2.almostEqual(expected_cdf2)) {
    actual_cdf2.debug(L"actual cdf2");
    expected_cdf2.debug(L"expected cdf2");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
    			 __LINE__);
  }

  // test a new histogram in CENTERS mode for each SCALE and each way of
  // setting bins
  //

  // set bins for USER-DEFINED scale to be used with CENTERS mode
  //
  bins_1a(0).assign(L"2.0, 4.0, 6.0");
  bins_2a(0).assign(L"2.0, 4.0, 6.0");
  bins_2a(1).assign(L"2.0, 4.0, 6.0");

  bins_1b.assign(L"2.0, 4.0, 6.0");
  bins_2b.assign(L"2.0, 4.0, 6.0");

  // test a new histogram in CENTERS mode for each SCALE and each way of
  // setting bins

  // test 1-d and 2-d hists for USER_DEFINED scale histograms
  //
  expected_cdf1.assign(L"0.4, 0.8, 1");
  expected_cdf2.assign(L"0.4, 0.4, 0.4, 0.4, 0.8, 0.8, 0.4, 0.8, 1");
  
  hist6.clear();
  hist6.setMode(CENTERS);
  hist6.setScale(USER_DEFINED);
  hist6.setDim(1);
  hist6.setBins(bins_1a);
  hist6.compute(test_data1);
  hist6.cdf(actual_cdf1);
  if (!actual_cdf1.almostEqual(expected_cdf1)) {
    actual_cdf1.debug(L"actual cdf1");
    expected_cdf1.debug(L"expected cdf1");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
			 __LINE__);
  }
  
  hist6.clear();
  hist6.setMode(CENTERS);
  hist6.setScale(USER_DEFINED);
  hist6.setDim(2);
  hist6.setBins(bins_2a);
  hist6.compute(test_data2);
  hist6.cdf(actual_cdf2);
  if (!actual_cdf2.almostEqual(expected_cdf2)) {
    actual_cdf2.debug(L"actual cdf2");
    expected_cdf2.debug(L"expected cdf2");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
			 __LINE__);
  }
 
  hist6.clear();
  hist6.setMode(CENTERS);
  hist6.setScale(USER_DEFINED);
  hist6.setDim(1);
  hist6.setBins(bins_1b);
  hist6.compute(test_data1);
  hist6.cdf(actual_cdf1);
  if (!actual_cdf1.almostEqual(expected_cdf1)) {
    actual_cdf1.debug(L"actual cdf1");
    expected_cdf1.debug(L"expected cdf1");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
      			 __LINE__);
  }

  hist6.clear();
  hist6.setScale(USER_DEFINED);
  hist6.setDim(2);
  hist6.setMode(CENTERS);
  hist6.setBins(bins_2b);
  hist6.compute(test_data2);
  hist6.cdf(actual_cdf2);
  if (!actual_cdf2.almostEqual(expected_cdf2)) {
    actual_cdf2.debug(L"actual cdf2");
    expected_cdf2.debug(L"expected cdf2");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
      			 __LINE__);
  }
 
  // test 1-d and 2-d hists for LINEAR scale histograms
  //

  expected_cdf1.assign(L"0.4, 0.8, 1");
  expected_cdf2.assign(L"0.4, 0.4, 0.4, 0.4, 0.8, 0.8, 0.4, 0.8, 1");
  
  hist6.clear();
  hist6.setDim(1);
  hist6.setMode(CENTERS);
  hist6.setBins(num_bins_1c, min_1c, max_1c);
  hist6.compute(test_data1);
  hist6.cdf(actual_cdf1);
  if (!actual_cdf1.almostEqual(expected_cdf1)) {
    actual_cdf1.debug(L"actual cdf1");
    expected_cdf1.debug(L"expected cdf1");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
    			 __LINE__);
  }

  hist6.clear();
  hist6.setDim(2);
  hist6.setMode(CENTERS);
  hist6.setBins(num_bins_2c, min_2c, max_2c);
  hist6.compute(test_data2);
  hist6.cdf(actual_cdf2);
  if (!actual_cdf2.almostEqual(expected_cdf2)) {
    actual_cdf2.debug(L"actual cdf2");
    expected_cdf2.debug(L"expected cdf2");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
    			 __LINE__);
  }

  hist6.clear();
  hist6.setDim(1);
  hist6.setMode(CENTERS);
  hist6.setBins(num_bins_1d, min_1d, max_1d);
  hist6.compute(test_data1);
  hist6.cdf(actual_cdf1);
  if (!actual_cdf1.almostEqual(expected_cdf1)) {
    actual_cdf1.debug(L"actual cdf1");
    expected_cdf1.debug(L"expected cdf1");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
      			 __LINE__);
  }

  hist6.clear();
  hist6.setDim(2);
  hist6.setMode(CENTERS);
  hist6.setBins(num_bins_2d, min_2d, max_2d);
  hist6.compute(test_data2);
  hist6.cdf(actual_cdf2);
  if (!actual_cdf2.almostEqual(expected_cdf2)) {
    actual_cdf2.debug(L"actual cdf2");
    expected_cdf2.debug(L"expected cdf2");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
      			 __LINE__);
  }

  // test 1-d and 2-d hists for LOG scale histograms
  //

  expected_cdf1.assign(L"0.2, 0.6, 1");
  expected_cdf2.assign(L"0.2, 0.2, 0.2, 0.2, 0.6, 0.6, 0.2, 0.6, 1");
  
  hist6.clear();
  hist6.setDim(1);
  hist6.setMode(CENTERS);
  hist6.setScale(LOG);
  hist6.setBins(num_bins_1c, min_1c, max_1c);
  hist6.compute(test_data1);
  hist6.cdf(actual_cdf1);
  if (!actual_cdf1.almostEqual(expected_cdf1)) {
    actual_cdf1.debug(L"actual cdf1");
    expected_cdf1.debug(L"expected cdf1");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
			 __LINE__);
  }
  hist6.clear();
  hist6.setScale(LOG);
  hist6.setMode(CENTERS);
  hist6.setDim(2);
  hist6.setBins(num_bins_2c, min_2c, max_2c);
  hist6.compute(test_data2);
  hist6.cdf(actual_cdf2);
  if (!actual_cdf2.almostEqual(expected_cdf2)) {
    actual_cdf2.debug(L"actual cdf2");
    expected_cdf2.debug(L"expected cdf2");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
			 __LINE__);
  }

  hist6.clear();
  hist6.setDim(1);
  hist6.setMode(CENTERS);
  hist6.setScale(LOG);
  hist6.setBins(num_bins_1d, min_1d, max_1d);
  hist6.compute(test_data1);
  hist6.cdf(actual_cdf1);
  if (!actual_cdf1.almostEqual(expected_cdf1)) {
    actual_cdf1.debug(L"actual cdf1");
    expected_cdf1.debug(L"expected cdf1");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
    			 __LINE__);
  }
  hist6.clear();
  hist6.setScale(LOG);
  hist6.setMode(CENTERS);
  hist6.setDim(2);
  hist6.setBins(num_bins_2d, min_2d, max_2d);
  hist6.compute(test_data2);
  hist6.cdf(actual_cdf2);
  if (!actual_cdf2.almostEqual(expected_cdf2)) {
    actual_cdf2.debug(L"actual cdf2");
    expected_cdf2.debug(L"expected cdf2");
    return Error::handle(name(), L"compute", Error::TEST, __FILE__,
    			 __LINE__);
  }

  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }

  //---------------------------------------------------------------------------
  //
  // 5. print completion message
  //
  //---------------------------------------------------------------------------

  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }
  
  if (level_a > Integral::NONE) {
    SysString output(L"diagnostics passed for class ");
    output.concat(name());
    output.concat(L"\n");
    Console::put(output);
  }

 

  // exit gracefully
  //
  return true;
}
