// file: $isip/class/mmedia/FeatureFile/ftrf_02.cc
// version: $Id: ftrf_02.cc 10597 2006-08-08 21:28:39Z ss754 $
//

// isip include files
//
#include "FeatureFile.h"
#include <String.h>
#include <Console.h>
#include <Filename.h>

// method: diagnose
//
// arguments:
//  Integral::DEBUG level: (input) debug level for diagnostics
//
// return: a boolean value indicating status
//
boolean FeatureFile::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();
  }

  // test the constructor and memory management
  //
  FeatureFile ftrs;
  
  FeatureFile::setGrowSize((long)500);
  for (long j = 1; j <= 10; j++) {
    FeatureFile** ftrs = new FeatureFile*[j * 100];
    
    // create the objects
    //
    for (long i = 0; i < j * 100; i++) {
      ftrs[i] = new FeatureFile();
    }
    
    // delete objects
    //
    for (long i = (j * 100) - 1; i >= 0; i--) {
      delete ftrs[i];
    }
    
    delete [] ftrs;
  }

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

  // test the i/o methods
  //
  FeatureFile ftr;
  ftr.name_d.assign(L"stuff");
  ftr.setNumChannels(2);
  
  // we need binary and text sof files
  //
  String tmp_filename0(L"./test0.sof");
  //  Integral::makeTemp(tmp_filename0);
  String tmp_filename1(L"./test1.sof");
  //  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);

  ftr.write(tmp_file0, (long)0);
  ftr.write(tmp_file1, (long)0);
  
  // 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);
  
  FeatureFile ftr1;
  FeatureFile ftr2;
  
  // try to do a read
  //
  FeatureFile ftr1a;
  FeatureFile ftr1b;
  
  // read the value back
  //
  if ((!ftr1.read(tmp_file0, (long)0))
      || (!ftr1.eq(ftr))) {
    return Error::handle(name(), L"read", Error::TEST, __FILE__, __LINE__);
  }
  
  if ((!ftr2.read(tmp_file1, (long)0))
      || (!ftr2.eq(ftr))) {
    ftr2.debug(L"ftr2");
    ftr.debug(L"ftr");
    return Error::handle(name(), L"read", Error::TEST, __FILE__, __LINE__);
  }
  
  // close and  delete the temporary files
  //
  tmp_file0.close();
  tmp_file1.close();

  File::remove(tmp_filename0);
  File::remove(tmp_filename1);

  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }
  
  //--------------------------------------------------------------------------
  //
  // 3. required public methods
  //     partial i/o methods 
  //
  //--------------------------------------------------------------------------
      
  // set indentation
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing required public methods: partial i/o methods...\n");
    Console::increaseIndention();
  }

  // output message
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing sof AlgorithmData features partial writing methods in text...\n");
  }

{
  // want a really big vector for i/o testing
  //
  long num_algd = 3050; 
  FeatureFile algd_vec;
  algd_vec.setDataType(ALGORITHM_DATA);
  MatrixFloat tmp_mat(2, 3, L"1, 2, 3, 4, 5, 6");
  algd_vec.setLength(num_algd);
   for (long i = 0; i < num_algd; i++) {
    algd_vec(i).makeMatrixFloat().assign(tmp_mat);
  }

  // need text sof file
  //
  Filename text_filename2(L"test0.sof");
  //  Integral::makeTemp(text_filename2);
  //  File::registerTemp(text_filename2);

  // open files in write mode
  //
  algd_vec.setFileType(TEXT);
  algd_vec.open(text_filename2, File::WRITE_ONLY);

  algd_vec.writePartialData(0, 50);
  
  for (long i = 0; i < 30; i++) {
    algd_vec.writePartialData(50 + i * 100, 100);
  }
  
  // close the files
  //
  algd_vec.close();

  // output message
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing sof AlgorithmData features partial writing methods in binary...\n");
  }

  Filename bin_filename2(L"test1.sof");
  //  Integral::makeTemp(bin_filename2);
  //  File::registerTemp(bin_filename2);

  // open files in write mode
  //
  algd_vec.setFileType(BINARY);
  algd_vec.open(bin_filename2, File::WRITE_ONLY);

  algd_vec.writePartialData(0, 50);
  for (long i = 0; i < 30; i++) {
    algd_vec.writePartialData(50 + i * 100, 100);
  }
  
  algd_vec.close();
  
  // output message
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing sof AlgorithmData features additional and partial reading methods in binary...\n");
  }
  
  // partial read for Vector<Float>
  //
  FeatureFile read_algd_vec_bin;
  read_algd_vec_bin.setFileType(BINARY);
  read_algd_vec_bin.open(bin_filename2, File::READ_ONLY);
  
  Vector<AlgorithmData> mf_read;
  Vector<AlgorithmData> mf_expected;

  long read_size = 50;
  FeatureFile algd_expected;
  algd_expected.setLength(read_size);

  VectorLong start_positions(L"0, 3, 98, 99, 100, 130, 180, 290, 340, 391, 443, 980, 1273, 1993, 2000, 2100, 841");

  mf_expected.setLength(read_size);
			
  for (long j = 0; j < start_positions.length(); j++) {

    long start = start_positions(j);

    for (long i = 0; i < read_size; i++) {

      // overwrite each time we read in this loop
      //
      algd_expected(i) = algd_vec(i + start);
      mf_expected(i).makeMatrixFloat() = algd_vec(i + start).getMatrixFloat();      
    } // end of i loop

    // test the readPartialData method
    //
    if (!read_algd_vec_bin.readPartialData(start, read_size)
	|| !(read_algd_vec_bin.v_d.eq(algd_expected.v_d))) {
      read_algd_vec_bin.v_d.debug(L"read_algd_vec_bin");
      algd_expected.v_d.debug(L"algd_expected");
      return Error::handle(name(), L"readPartialData algd bin", Error::TEST,
			   __FILE__, __LINE__);
    }
    
    // test the readFeatureData method
    //
    mf_read.clear();
    read_algd_vec_bin.readFeatureData(mf_read, start, read_size);

    if (!mf_read.eq(mf_expected)) {
      mf_read.debug(L"mf_read");
      mf_expected.debug(L"algd_expected");
      return Error::handle(name(), L"readFeatureData algd bin", Error::TEST,
			   __FILE__, __LINE__);
    }    
  } // end of j loop
  
  // close the files
  //
  read_algd_vec_bin.close();

  
  // output message
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing sof AlgorithmData features additional and partial reading methods in text...\n");
  }
  
  // partial read for Vector<Algd>
  //
  FeatureFile read_algd_vec_text;
  read_algd_vec_text.setFileType(TEXT);
  read_algd_vec_text.open(text_filename2, File::READ_ONLY);
  
  for (long j = 0; j < start_positions.length(); j++) {

    long start = start_positions(j);

    for (long i = 0; i < read_size; i++) {
      
      // overwrite each time we read in this loop
      //
      algd_expected(i) = algd_vec(i + start);
      mf_expected(i).makeMatrixFloat() = algd_vec(i + start).getMatrixFloat();      
    } // end of i loop
    
    // test the readPartialData method
    //
    boolean flag1 = read_algd_vec_text.readPartialData(start, read_size);
    boolean flag2 = true;
    MatrixFloat mat1;
    MatrixFloat mat2;
    
    // there is no almostEqual method in the vector
    //
    if (read_algd_vec_text.v_d.length() != algd_expected.v_d.length()) {
      flag2 = false;
    }	
    for (long k = 0; flag2 && (k < read_algd_vec_text.v_d.length()); k++) {
      mat1 = read_algd_vec_text(k).getMatrixFloat();
      mat2 = read_algd_vec_text(k).getMatrixFloat();
      if(!mat1.almostEqual(mat2, 2)) {
	flag2 = false;
      }
    }
    if (!flag1 || !flag2) {
      read_algd_vec_text.v_d.debug(L"read_algd_vec_text");
      algd_expected.v_d.debug(L"algd_expected");
      return Error::handle(name(), L"readPartialData algd text", Error::TEST,
			   __FILE__, __LINE__);
    }
    
    // test the readFeatureData method
    //
    mf_read.clear();
    flag1 = read_algd_vec_text.readFeatureData(mf_read, start, read_size);
    
    // there is no almostEqual method in the vector
    //
    if (mf_read.length() != mf_expected.length()) {
      flag2 = false;
    }
    for (long k = 0; flag2 && (k < mf_read.length()); k++) {
      mat1 = mf_read(k).getMatrixFloat();
      mat2 = mf_expected(k).getMatrixFloat();
      if(!mat1.almostEqual(mat2, 2)) {
	flag2 = false;
      }
    }
    if (!flag1 || !flag2) {
      mf_read.debug(L"mf_read");
      mf_expected.debug(L"algd_expected");
      return Error::handle(name(), L"readFeatureData algd text", Error::TEST,
			   __FILE__, __LINE__);
    }    
  } // end of j loop
  
  // close the files
  //
  read_algd_vec_text.close();
  
}

  // output message
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing sof features partial writing methods in text...\n");
  }

  // want a really big vector for i/o testing
  //
  long num_floats = 3050; 
  FeatureFile float_vec;
  float_vec.setLength(num_floats);
   for (long i = 0; i < num_floats; i++) {
    float_vec(i).makeVectorFloat().setLength(7);
    float_vec(i).getVectorFloat().assign(i * 2.357);
  }

  // need text sof file
  //
  Filename text_filename1;
  Integral::makeTemp(text_filename1);
  File::registerTemp(text_filename1);

  // open files in write mode
  //
  float_vec.setFileType(TEXT);
  float_vec.open(text_filename1, File::WRITE_ONLY);

  float_vec.writePartialData(0, 50);
  
  for (long i = 0; i < 30; i++) {
    float_vec.writePartialData(50 + i * 100, 100);
  }
  
  // close the files
  //
  float_vec.close();

  // output message
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing sof features partial writing methods in binary...\n");
  }

  Filename bin_filename1;
  Integral::makeTemp(bin_filename1);
  File::registerTemp(bin_filename1);

  // open files in write mode
  //
  float_vec.setFileType(BINARY);
  float_vec.open(bin_filename1, File::WRITE_ONLY);

  float_vec.writePartialData(0, 50);
  for (long i = 0; i < 30; i++) {
    float_vec.writePartialData(50 + i * 100, 100);
  }
  
  float_vec.close();

  // output message
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing sof features additional and partial reading methods in binary...\n");
  }
  
  // partial read for Vector<Float>
  //
  FeatureFile read_float_vec_bin;
  read_float_vec_bin.setFileType(BINARY);
  read_float_vec_bin.open(bin_filename1, File::READ_ONLY);
  
  Vector<AlgorithmData> vf_read;
  Vector<AlgorithmData> vf_expected;

  long read_size = 50;
  FeatureFile vecf_expected;
  vecf_expected.setLength(read_size);

  VectorLong start_positions(L"0, 3, 98, 99, 100, 130, 180, 290, 340, 391, 443, 980, 1273, 1993, 2000, 2100, 841");

  vf_expected.setLength(read_size);
			
  for (long j = 0; j < start_positions.length(); j++) {

    long start = start_positions(j);

    for (long i = 0; i < read_size; i++) {

      // overwrite each time we read in this loop
      //
      vecf_expected(i) = float_vec(i + start);
      vf_expected(i).makeVectorFloat() = float_vec(i + start).getVectorFloat();      
    } // end of i loop

    // test the readPartialData method
    //
    if (!read_float_vec_bin.readPartialData(start, read_size)
	|| !(read_float_vec_bin.v_d.eq(vecf_expected.v_d))) {
      read_float_vec_bin.v_d.debug(L"read_float_vec_bin");
      vecf_expected.v_d.debug(L"vecf_expected");
      return Error::handle(name(), L"readPartialData float bin", Error::TEST,
			   __FILE__, __LINE__);
    }
    
    // test the readFeatureData method
    //
    vf_read.clear();
    read_float_vec_bin.readFeatureData(vf_read, start, read_size);

    if (!vf_read.eq(vf_expected)) {
      vf_read.debug(L"vf_read");
      vf_expected.debug(L"vecf_expected");
      return Error::handle(name(), L"readFeatureData float bin", Error::TEST,
			   __FILE__, __LINE__);
    }    
  } // end of j loop
  
  // close the files
  //
  read_float_vec_bin.close();

  // output message
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing sof features additional and partial reading methods in text...\n");
  }
  
  // partial read for Vector<Float>
  //
  FeatureFile read_float_vec_text;
  read_float_vec_text.setFileType(TEXT);
  read_float_vec_text.open(text_filename1, File::READ_ONLY);
  
  for (long j = 0; j < start_positions.length(); j++) {

    long start = start_positions(j);

    for (long i = 0; i < read_size; i++) {
      
      // overwrite each time we read in this loop
      //
      vecf_expected(i) = float_vec(i + start);
      vf_expected(i).makeVectorFloat() = float_vec(i + start).getVectorFloat();      
    } // end of i loop
    
    // test the readPartialData method
    //
    boolean flag1 = read_float_vec_text.readPartialData(start, read_size);
    boolean flag2 = true;
    VectorFloat vec1;
    VectorFloat vec2;
    
    // there is no almostEqual method in the vector
    //
    if (read_float_vec_text.v_d.length() != vecf_expected.v_d.length()) {
      flag2 = false;
    }	
    for (long k = 0; flag2 && (k < read_float_vec_text.v_d.length()); k++) {
      vec1 = read_float_vec_text(k).getVectorFloat();
      vec2 = read_float_vec_text(k).getVectorFloat();
      if(!vec1.almostEqual(vec2, 2)) {
	flag2 = false;
      }
    }
    if (!flag1 || !flag2) {
      read_float_vec_text.v_d.debug(L"read_float_vec_text");
      vecf_expected.v_d.debug(L"vecf_expected");
      return Error::handle(name(), L"readPartialData float text", Error::TEST,
			   __FILE__, __LINE__);
    }
    
    // test the readFeatureData method
    //
    vf_read.clear();
    flag1 = read_float_vec_text.readFeatureData(vf_read, start, read_size);
    
    // there is no almostEqual method in the vector
    //
    if (vf_read.length() != vf_expected.length()) {
      flag2 = false;
    }
    for (long k = 0; flag2 && (k < vf_read.length()); k++) {
      vec1 = vf_read(k).getVectorFloat();
      vec2 = vf_expected(k).getVectorFloat();
      if(!vec1.almostEqual(vec2, 2)) {
	flag2 = false;
      }
    }
    if (!flag1 || !flag2) {
      vf_read.debug(L"vf_read");
      vf_expected.debug(L"vecf_expected");
      return Error::handle(name(), L"readFeatureData  float text", Error::TEST,
			   __FILE__, __LINE__);
    }    
  } // end of j loop
  
  // close the files
  //
  read_float_vec_text.close();

  // text raw features writing method test
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing raw features writing methods in text...");
  }

  // local variable
  //
  long num_vecfloats = 3056;
  FeatureFile raw_features;
  Vector <AlgorithmData> vf;
  vf.setLength(num_vecfloats);
  vf_expected.clear();
  vf_expected.setLength(num_vecfloats);

  // prepare data to write
  //
  for (long i = 0; i < num_vecfloats; i++) {
    vf(i).makeVectorFloat().setLength(8);
    vf(i).getVectorFloat().assign((i + 1) * 2.6350);
    vf_expected(i).makeVectorFloat().setLength(8);
    vf_expected(i).getVectorFloat().assign((i + 1) * 2.6350);
  }

  // open the raw file in text
  //
  raw_features.setFileType(TEXT);
  raw_features.setFileFormat(FeatureFile::RAW);
  text_filename1.concat(L".raw");
  File::registerTemp(text_filename1);
  raw_features.open(text_filename1, File::WRITE_ONLY);

  // set the required variables
  //
  raw_features.setNumFeatures(8);
  raw_features.setNumChannels(1);

  // write the raw features to the file in text
  //
  raw_features.writeFeatureData(vf);
  raw_features.close();
  
  // text raw features reading method test
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing raw features reading methods in text...");
  }

  // open back the raw feature text file in read-mode
  //
  raw_features.open(text_filename1, File::READ_ONLY);

  // initializing elements
  //
  vf.clear();
  long number_input = 8;
  long num_features = 0;

  // read one feature-vector at a time
  //
  while (number_input) {
    number_input = raw_features.readFeatureData(vf);
    if (number_input == 0) break;

    // check this feature-vector with the expected value
    //
    if (!vf(0).getVectorFloat().almostEqual(vf_expected(num_features).getVectorFloat())) {
      Long(num_features).debug(L"num_features");
      vf(0).getVectorFloat().debug(L"vf");
      vf_expected(num_features).getVectorFloat().debug(L"vf_expected");
      return Error::handle(name(), L"read partial float text", Error::TEST,
			   __FILE__, __LINE__);
    }
    num_features++;
  }
  
  raw_features.close();

  // binary raw features writing method test
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing raw features writing methods in binary...");
  }

  // prepare data to write
  //
  vf.setLength(num_vecfloats);
  for (long i = 0; i < num_vecfloats; i++) {
    vf(i).makeVectorFloat().setLength(8);
    vf(i).getVectorFloat().assign((i + 1) * 2.6350);
    vf_expected(i).makeVectorFloat().setLength(8);
    vf_expected(i).getVectorFloat().assign((i + 1) * 2.6350);
  }
  
  // open the raw file in binary
  //
  raw_features.setFileType(BINARY);
  raw_features.setFileFormat(FeatureFile::RAW);
  bin_filename1.concat(L".raw");
  File::registerTemp(bin_filename1);
  raw_features.setNumFeatures(8);
  raw_features.setNumChannels(1);
  raw_features.open(bin_filename1, File::WRITE_ONLY);

  // write the feature-vectors to raw file in binary
  //
  raw_features.writeFeatureData(vf, 0);
  raw_features.close();

  // binary raw features reading test
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing raw features reading methods in binary...");
  }

  // open back the raw feature binary file in read-mode
  //
  raw_features.open(bin_filename1, File::READ_ONLY);
 
  // initializing elements
  //
  vf.clear();
  number_input = 8;
  num_features = 0;
  
  // read one feature-vector at a time
  //
  while (number_input) {
    number_input = raw_features.readFeatureData(vf, 0);
    if (number_input == 0) break;
    
    // check this feature-vector with the expected value
    //    
    if (!vf(0).getVectorFloat().almostEqual(vf_expected(num_features).getVectorFloat())) {
      Long(num_features).debug(L"num_features");      
      vf(0).getVectorFloat().debug(L"vf");
      vf_expected(num_features).getVectorFloat().debug(L"vf_expected");
      return Error::handle(name(), L"read partial float text", Error::TEST,
			   __FILE__, __LINE__);
    }
    
    num_features++;
  }

  raw_features.close();

  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }
  
  //---------------------------------------------------------------------------
  //
  // 4. 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();
  }

  // declare the reference object
  //
  FeatureFile ftr_set;

  // set various variables
  //
  ftr_set.setName(L"FEATURES");
  ftr_set.setFileType(BINARY);
  ftr_set.setFileFormat(RAW);
  //  ftr_set.setCompType(ULAW); // not yet implemented
  ftr_set.setAmplitudeRange(2);
  ftr_set.setNumChannels(4);
  ftr_set.setID(L"tidigits");
  ftr_set.setNumFeatures(20);
  ftr_set.setDataType(VECTOR_FLOAT);
  ftr_set.setCoefType(AlgorithmData::SPECTRUM);
  ftr_set.setFrameDuration(0.05);  
  ftr_set.setSampleFrequency(4000.0);
  ftr_set.setLength(2);
    
  // check the set variables
  //
  if (!ftr_set.name_d.eq(L"FEATURES")) {
    return Error::handle(name(), L"setName", Error::TEST,
			 __FILE__, __LINE__);
  }  
  if (ftr_set.file_type_d != BINARY) {
    return Error::handle(name(), L"setFileType", Error::TEST,
			 __FILE__, __LINE__);
  }  
  if (ftr_set.file_format_d != RAW) {
    return Error::handle(name(), L"setFileFormat", Error::TEST,
			 __FILE__, __LINE__);
  }
  //  if (ftr_set.compression_type_d != ULAW) {
  //    return Error::handle(name(), L"setCompType", Error::TEST,
  //			 __FILE__, __LINE__);
  //  }
  if (ftr_set.amplitude_range_d != ((double)2)) {
    return Error::handle(name(), L"setAmplitudeRange", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (ftr_set.num_channels_d != (long)4) {
    return Error::handle(name(), L"setNumChannels", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (!ftr_set.id_d.eq(L"tidigits")) {
    return Error::handle(name(), L"setID", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (ftr_set.num_features_d != (long)20) {
    return Error::handle(name(), L"setNumFeatures", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (ftr_set.data_type_d != VECTOR_FLOAT) {
    return Error::handle(name(), L"setDataType", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (ftr_set.coef_type_d != AlgorithmData::SPECTRUM) {
    return Error::handle(name(), L"setCoefType", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (!(Integral::almostEqual((double)ftr_set.frame_duration_d, 0.05))) {
    return Error::handle(name(), L"setFrameDuration", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (!(Integral::almostEqual((double)ftr_set.sample_frequency_d, 4000.0))) {
    return Error::handle(name(), L"setSampleFrequency", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (ftr_set.v_d.length() != (long)2) {
    return Error::handle(name(), L"setLength", Error::TEST,
			 __FILE__, __LINE__);
  }

  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }
  
  //---------------------------------------------------------------------------
  //
  // 5. 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();
  }

  // check the get variables
  //
  if (!ftr_set.getName().eq(L"FEATURES")) {
    return Error::handle(name(), L"getName", Error::TEST,
			 __FILE__, __LINE__);
  }  
  if (ftr_set.getFileType() != BINARY) {
    return Error::handle(name(), L"getFileType", Error::TEST,
			 __FILE__, __LINE__);
  }  
  if (ftr_set.getFileFormat() != RAW) {
    return Error::handle(name(), L"getFileFormat", Error::TEST,
			 __FILE__, __LINE__);
  }
  //  if (ftr_set.getCompType() != ULAW) {
  //    return Error::handle(name(), L"getCompType", Error::TEST,
  //			 __FILE__, __LINE__);
  //  }
  if (ftr_set.getAmplitudeRange() != (long)2) {
    return Error::handle(name(), L"getAmplitudeRange", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (ftr_set.getNumChannels() != (long)4) {
    return Error::handle(name(), L"getNumChannels", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (!ftr_set.getID().eq(L"tidigits")) {
    return Error::handle(name(), L"getID", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (ftr_set.getNumFeatures() != (long)20) {
    return Error::handle(name(), L"getNumFeatures", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (ftr_set.getDataType() != VECTOR_FLOAT) {
    return Error::handle(name(), L"getDataType", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (ftr_set.getCoefType() != AlgorithmData::SPECTRUM) {
    return Error::handle(name(), L"getCoefType", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (!(Integral::almostEqual((double)(ftr_set.getFrameDuration()), 0.05))) {
    return Error::handle(name(), L"getFrameDuration", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (!(Integral::almostEqual((double)(ftr_set.getSampleFrequency()),
			      4000.0))) {
    return Error::handle(name(), L"getSampleFrequency", Error::TEST,
			 __FILE__, __LINE__);
  }

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

  //---------------------------------------------------------------------------
  //
  // 6. 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;
  
}
