// file: $isip_ifc/class/algo/Constant/const_06.cc
// version: $Id: const_06.cc 10532 2006-03-29 21:26:30Z raghavan $
//

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

// method: computeWrite
//
// arguments:
//  Vector<AlgorithmData>& output: (output) output data
//  const Vector< CircularBuffer<AlgorithmData> >& input: (input) input data
//
// return: a boolean value indicating status
//
// this method writes a constant to a file.
//
boolean Constant::computeWrite(Vector<AlgorithmData>& output_a,
			       const Vector< CircularBuffer<AlgorithmData> >& input_a) {

  // error: unknown implementation
  //
  if (implementation_d != WRITE) {
    return Error::handle(name(), L"computeWrite",
			 ERR_UNKIMP, __FILE__, __LINE__);
  }
    
  // declare an sof object
  //
  Sof sof;
  String filename = filename_d;
  
  // open the sof file
  //
  if (!sof.open(filename, File::WRITE_ONLY)) {
    return Error::handle(filename, L"computeWrite",
			 Error::TEST, __FILE__, __LINE__);
  }

  // loop over the channels 
  //
  long len = input_a.length();

  for (long c = 0; c < len; c++) {
    
    // display the channel number
    //
    displayChannel(c);
    
    // check for the specified data type (set by the user)
    //
    if (data_type_d == input_a(c)(0).getDataType()) {

      // branch on the data type: VECTOR_FLOAT
      //
      AlgorithmData::DATA_TYPE dtype = input_a(c)(0).getDataType() ;
      
      if (dtype == AlgorithmData::VECTOR_FLOAT) {
	
	output_a(c).makeVectorFloat().assign(input_a(c)(0).getVectorFloat());
	
	// write the data
	//
	if (!output_a(c).getVectorFloat().write(sof, (long)c)) {
	  return Error::handle(name(), L"computeWrite", Error::WRITE,
			       __FILE__, __LINE__, Error::WARNING);
	}
	output_a(c).getVectorFloat().setLength(0);
      }
      
      // branch on the data type: VECTOR_COMPLEX_FLOAT
      //
      else if (dtype == AlgorithmData::VECTOR_COMPLEX_FLOAT) {
	
	output_a(c).makeVectorComplexFloat().assign(input_a(c)(0).getVectorComplexFloat());
	
	// write the data
	//
	if (!output_a(c).getVectorComplexFloat().write(sof, (long)c)) {
	  return Error::handle(name(), L"computeWrite", Error::WRITE,
			       __FILE__, __LINE__, Error::WARNING);
	}
	output_a(c).getVectorComplexFloat().setLength(0);
      }
      
      // branch on the data type: MATRIX_FLOAT
      //
      else if (dtype == AlgorithmData::MATRIX_FLOAT) {
	
	output_a(c).makeMatrixFloat().assign(input_a(c)(0).getMatrixFloat());	  
	// write the data
	//
	if (!output_a(c).getMatrixFloat().write(sof, (long)c)) {
	  return Error::handle(name(), L"computeWrite", Error::WRITE,
			       __FILE__, __LINE__, Error::WARNING);
	}
      }
      
      // branch on the data type: MATRIX_COMPELX_FLOAT
      //
      else if (dtype == AlgorithmData::MATRIX_COMPLEX_FLOAT) {
	
	output_a(c).makeMatrixComplexFloat().assign(input_a(c)(0).getMatrixComplexFloat());	  

	// write the data
	//
	if (!output_a(c).getMatrixComplexFloat().write(sof, (long)c)) {
	  return Error::handle(name(), L"computeWrite", Error::WRITE,
			       __FILE__, __LINE__, Error::WARNING);
	}      
      }
      
      // branch on the data type: VECTOR_DOUBLE
      //
      else if (dtype == AlgorithmData::VECTOR_DOUBLE) {
	
	output_a(c).makeVectorDouble().assign(input_a(c)(0).getVectorDouble());

	// write the data
	//
	if (!output_a(c).getVectorDouble().write(sof, (long)c)) {
	  return Error::handle(name(), L"computeWrite", Error::WRITE,
			       __FILE__, __LINE__, Error::WARNING);
	}
      }
      
      // branch on the data type: VECTOR_COMPLEX_DOUBLE
      //
      else if (dtype == AlgorithmData::VECTOR_COMPLEX_DOUBLE) {
	
	output_a(c).makeVectorComplexDouble().assign(input_a(c)(0).getVectorComplexDouble());

	// write the data
	//
	if (!output_a(c).getVectorComplexDouble().write(sof, (long)c)) {
	  return Error::handle(name(), L"computeWrite", Error::WRITE,
			       __FILE__, __LINE__, Error::WARNING);
	}      
      }
      
      // branch on the data type: MATRIX_DOUBLE
      //
      else if (dtype == AlgorithmData::MATRIX_DOUBLE) {
	
	output_a(c).makeMatrixDouble().assign(input_a(c)(0).getMatrixDouble());

	// write the data
	//
	if (!output_a(c).getMatrixDouble().write(sof, (long)c)) {
	  return Error::handle(name(), L"computeWrite", Error::WRITE,
			       __FILE__, __LINE__, Error::WARNING);
	}      
      }
      
      // branch on the data type: MATRIX_COMPLEX_DOUBLE
      //
      else if (dtype == AlgorithmData::MATRIX_COMPLEX_DOUBLE) {
	
	output_a(c).makeVectorComplexDouble().assign(input_a(c)(0).getVectorComplexDouble());	  

	// write the data
	//
	if (!output_a(c).getMatrixComplexDouble().write(sof, (long)c)) {
	  return Error::handle(name(), L"computeWrite", Error::WRITE,
			       __FILE__, __LINE__, Error::WARNING);
	}      
      }

      // branch on the data type: COMBINATION
      //
      else if (dtype == AlgorithmData::COMBINATION) {
	return Error::handle(name(), L"computeWrite",
			     ERR_UNSUPM, __FILE__, __LINE__);
      }
    }
    
    // error: unsupported data type
    //
    else {
      return Error::handle(name(), L"computeWrite",
			   ERR_UNSUPM, __FILE__, __LINE__);
    }
    
    // possibly display the data
    //
    display(output_a, input_a,  name());
    data_d(c).assign(input_a(c)(0));
  }
  
  // close file
  //
  sof.close();
  
  // exit gracefully
  //
  return true;
}

// method: computeRead
//
// arguments:
//  Vector<AlgorithmData>& output: (output) output data
//  const Vector< CircularBuffer<AlgorithmData> >& input: (input) input data
//
// return: a boolean value indicating status
//
// this method reads a constant from a file.
//
boolean Constant::computeRead(Vector<AlgorithmData>& output_a,
			      const Vector< CircularBuffer<AlgorithmData> >& input_a) {
  
  // error: unknown implementation
  //
  if (implementation_d != READ) {
    return Error::handle(name(), L"computeRead",
			 ERR_UNKIMP, __FILE__, __LINE__);
  }
  
  // set the number of channels
  //
  long len = channels_d;
  output_a.setLength(len);
  
  // check if the data exists (implies it has already has been read)
  //
  if (data_exist_d) {
    output_a.assign(data_d);
    return true;    
  }

  // else: read the data
  //
  else {

    // declare an sof object
    //
    Sof sof;
    String filename = filename_d;
    
    // open the sof file
    //
    if (!sof.open(filename, File::READ_ONLY)) {
      return Error::handle(filename, L"computeRead", Error::TEST,
			   __FILE__, __LINE__);
    }
    
    // loop over the channels 
    //
    for (long c = 0; c < len; c++) {
      
      // display the channel number
      //
      displayChannel(c);
      
      // branch on the data type: VECTOR_FLOAT
      //
      if (data_type_d == AlgorithmData::VECTOR_FLOAT ||
	  data_type_d == AlgorithmData::DEF_DTYPE) {
	
	output_a(c).makeVectorFloat();
	
	// read the data
	//
	if (!output_a(c).getVectorFloat().read(sof, (long)c)) {
	  return Error::handle(name(), L"computeRead", Error::READ,
			       __FILE__, __LINE__, Error::WARNING);
	}
      }

      // branch on the data type: VECTOR_COMPLEX_FLOAT
      //
      else if (data_type_d == AlgorithmData::VECTOR_COMPLEX_FLOAT) {
	
	output_a(c).makeVectorComplexFloat();
	
	// read the data
	//
	if (!output_a(c).getVectorComplexFloat().read(sof, (long)c)) {
	  return Error::handle(name(), L"computeRead", Error::READ,
			       __FILE__, __LINE__, Error::WARNING);
	}
      }

      // branch on the data type: MATRIX_FLOAT
      //
      else if (data_type_d == AlgorithmData::MATRIX_FLOAT) {
	
	output_a(c).makeMatrixFloat();
	
	// read the data
	//
	if (!output_a(c).getMatrixFloat().read(sof, (long)c)) {
	  return Error::handle(name(), L"computeRead", Error::READ,
			       __FILE__, __LINE__, Error::WARNING);
	}   
      }

      // branch on the data type: MATRIX_COMPLEX_FLOAT
      //
      else if (data_type_d == AlgorithmData::MATRIX_COMPLEX_FLOAT) {
	
	output_a(c).makeMatrixComplexFloat();
	
	// read the data
	//
	if (!output_a(c).getMatrixComplexFloat().read(sof, (long)c)) {
	  return Error::handle(name(), L"computeRead", Error::READ,
			       __FILE__, __LINE__, Error::WARNING);
	}      
      }
      
      // branch on the data type: VECTOR_DOUBLE
      //
      else if (data_type_d == AlgorithmData::VECTOR_DOUBLE) {
	
	output_a(c).makeVectorDouble();
	
	// read the data
	//
	if (!output_a(c).getVectorDouble().read(sof, (long)c)) {
	  return Error::handle(name(), L"computeRead", Error::READ,
			       __FILE__, __LINE__, Error::WARNING);
	}
      }

      // branch on the data type: VECTOR_COMPLEX_DOUBLE
      //
      else if (data_type_d == AlgorithmData::VECTOR_COMPLEX_DOUBLE) {
	
	output_a(c).makeVectorComplexDouble();
	
	// read the data
	//
	if (!output_a(c).getVectorComplexDouble().read(sof, (long)c)) {
	  return Error::handle(name(), L"computeRead", Error::READ,
			       __FILE__, __LINE__, Error::WARNING);
	}      
      }

      // branch on the data type: MATRIX_DOUBLE
      //
      else if (data_type_d == AlgorithmData::MATRIX_DOUBLE) {
	
	output_a(c).makeMatrixDouble();
	
	// read the data
	//
	if (!output_a(c).getMatrixDouble().read(sof, (long)c)) {
	  return Error::handle(name(), L"computeRead", Error::READ,
			       __FILE__, __LINE__, Error::WARNING);
	}      
      }

      // branch on the data type: MATRIX_COMPLEX_DOUBLE
      //
      else if (data_type_d == AlgorithmData::MATRIX_COMPLEX_DOUBLE) {
	
	output_a(c).makeMatrixComplexDouble();
	
	// read the data
	//
	if (!output_a(c).getMatrixComplexDouble().read(sof, (long)c)) {
	  return Error::handle(name(), L"computeRead", Error::READ,
			       __FILE__, __LINE__, Error::WARNING);
	}      
      }

      // branch on the data type: COMBINATION
      //
      else if (data_type_d == AlgorithmData::COMBINATION) {
	
	return Error::handle(name(), L"computeRead",
			     ERR_UNSUPM, __FILE__, __LINE__);
      }
      
      // set the coefficient type for the output
      //            
      output_a(c).setCoefType(AlgorithmData::GENERIC);
      
      // possibly display the data
      //
      display(output_a, input_a,  name());
      
    }
    
    // close the open file
    //
    sof.close();
  }
  
  // save the data
  //
  data_d.assign(output_a);
  data_exist_d = true;  
  
  // exit gracefully
  //
  return true;
}

// method: getFromHash
//
// arguments: none
//  
// return: a boolean value indicating status
//
// this method will insert or retrieve a temporary filename
// corresponding to the given filename
//
boolean Constant::getFromHash() {
  
  // declare local variables
  //
  String in_filename = filename_d;
  String temp_filename;
  
  // check if the file exists in the hash
  //
  if (!hash_files_d.containsKey(in_filename)) {
    
    // store a temporary filename in the hash table and rename the
    // input file
    //
    Integral::makeTemp(temp_filename);
    hash_files_d.insert(in_filename, &temp_filename);
    filename_d = temp_filename;
  }
  else {
    String* temp = hash_files_d.get(in_filename);
    filename_d = *temp;
  }
  
  // exit gracefully
  //
  return true;
}
