// file: $isip/class/algo/FourierTransform/ft_00.cc
// version: $Id: ft_00.cc 8311 2002-07-08 20:41:34Z parihar $
//

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

//------------------------------------------------------------------------
//
// required public methods
//
//-----------------------------------------------------------------------

// method: default constructor
//
// arguments:
//  ALGORITHM algorithm: (input) algorithm used in fourier transform
//
// return: none
//
FourierTransform::FourierTransform(ALGORITHM algorithm_a) {

  // initialize protected data
  //
  algorithm_d = algorithm_a;
  implementation_d = DEF_IMPLEMENTATION;
  direction_d = DEF_DIRECTION;
  otype_d = DEF_OTYPE;
  resolution_d = DEF_RESOLUTION;
  ilen_d = DEF_LENGTH;
  olen_d = DEF_LENGTH;
  order_d = DEF_ORDER;
  normalization_d = DEF_NORM;
}

// method: assign
//
// arguments:
//  const FourierTransform& arg: (input) object to be assigned
//
// return: a boolean value indicating status
//
// this method assign the input object to the current object
//
boolean FourierTransform::assign(const FourierTransform& arg_a) {

  // assign parameters related to the algorithm specification
  //
  algorithm_d = arg_a.algorithm_d;
  implementation_d = arg_a.implementation_d;
  direction_d = arg_a.direction_d;
  otype_d = arg_a.otype_d;  
  resolution_d = arg_a.resolution_d;
  ilen_d = arg_a.ilen_d;
  olen_d = arg_a.olen_d;
  order_d = arg_a.order_d;
  normalization_d = arg_a.normalization_d;

  // assign parameters related to fourier transform computation
  //
  wd_real_d.assign(arg_a.wd_real_d);
  wd_imag_d.assign(arg_a.wd_imag_d);
  tempd_d.assign(arg_a.tempd_d);
  
  // assign parameters related to the decimation in time frequency algorithm
  //
  ditf_trans_factor_indices_d.assign(arg_a.ditf_trans_factor_indices_d);
  ditf_indices_d.assign(arg_a.ditf_indices_d);

  // assign parameters related to the quick fourier transform algorithm
  //
  qf_comp_real_coeff_d.assign(arg_a.qf_comp_real_coeff_d);
  qf_comp_imag_coeff_d.assign(arg_a.qf_comp_imag_coeff_d);
  qf_comp_temp_d.assign(arg_a.qf_comp_temp_d);

  // assign workspace related pointers for quick fourier transform
  //
  qf_ws_d.assign(arg_a.qf_ws_d); //	Workspace
  qf_sc_d = arg_a.qf_sc_d;    //	Secant table addr.	
  qf_nc_d = arg_a.qf_nc_d;    //	Current QFT length	
  qf_ic_d = arg_a.qf_ic_d;    //	Current secant inc.	
  qf_mc_d = arg_a.qf_mc_d;    //	Current output pruning
  qf_nn_d = arg_a.qf_nn_d;    //	Pruned QFT input length
  qf_mm_d = arg_a.qf_mm_d;    //	Pruned QFT output length
  qf_ii_d = arg_a.qf_ii_d;    //	Current QFT recursion level
  qf_input_d = arg_a.qf_input_d;      //  dct/dst calling arguments
  qf_output_d = arg_a.qf_output_d;    //  dct/dst calling arguments
  
  // assign AlgorithmBase and exit gracefully
  //
  return AlgorithmBase::assign(arg_a);
}

// method: eq
//
// arguments:
//  const FourierTransform& arg: (input) object to be compared
//
// return: a boolean value indicating status
//
// this method checks whether the current object is identical to the
// input object
//
boolean FourierTransform::eq(const FourierTransform& arg_a) const {

  return ((algorithm_d == arg_a.algorithm_d) &&
	  (implementation_d == arg_a.implementation_d) &&
	  (direction_d == arg_a.direction_d) &&
	  (otype_d == arg_a.otype_d) &&
	  (resolution_d == arg_a.resolution_d) &&
	  (ilen_d == arg_a.ilen_d) &&
	  (olen_d == arg_a.olen_d) &&	  
	  (order_d == arg_a.order_d) &&
	  (normalization_d == arg_a.normalization_d));
}

// method: clear
//
// arguments:
//  Integral::CMODE ctype: (input) clear mode
//
// return: a boolean value indicating status
//
// this method resets the data members to the default values
//
boolean FourierTransform::clear(Integral::CMODE ctype_a) {
  
  // reset the parameters related to the algorithm specification
  //
  algorithm_d = DEF_ALGORITHM;
  implementation_d = DEF_IMPLEMENTATION;
  direction_d = DEF_DIRECTION;
  otype_d = DEF_OTYPE;
  resolution_d = DEF_RESOLUTION;
  ilen_d = DEF_LENGTH;
  olen_d = DEF_LENGTH;
  order_d = DEF_ORDER;
  normalization_d = DEF_NORM;

  // reset the parameters (clear the memory) related to fourier transform
  // computation
  //
  is_valid_d = false;

  wd_real_d.clear(ctype_a);
  wd_imag_d.clear(ctype_a);
  tempd_d.clear(ctype_a);

  // exit gracefully
  //
  return AlgorithmBase::clear(ctype_a);
}

//---------------------------------------------------------------------------
//
// class-specific public methods:
//  public methods required by the AlgorithmBase interface contract
//
//---------------------------------------------------------------------------

// method: assign
//
// arguments:
//  const AlgorithmBase& arg: (input) object to be assigned
//
// return: a boolean valude indicating status
//
// this method assigns the input algorithm object to the current
// FourierTransform object, if the input algorithm object is not a
// FourierTransform object, it is an error
//
boolean FourierTransform::assign(const AlgorithmBase& arg_a) {

  if (typeid(arg_a) == typeid(FourierTransform)) {
    return assign((FourierTransform&)arg_a);
  }
  else {
    return Error::handle(name(), L"assign", Error::ARG, __FILE__, __LINE__);
  }
  
  // exit gracefully
  //
  return true;
}

// method: eq
//
// arguments:
//  const AlgorithmBase& arg: (input) object to be compared
//
// return: a boolean valude indicating status
//
// this method checks whether the current FourierTransform object is
// identical to the input algorithm object, if the input algorithm
// object is not a FourierTransform object, it returns an error
//
boolean FourierTransform::eq(const AlgorithmBase& arg_a) const {

  if (typeid(arg_a) == typeid(FourierTransform)) {
    return eq((FourierTransform&)arg_a);
  }
  else {
    return Error::handle(name(), L"eq", Error::ARG, __FILE__, __LINE__);
  }
  
  // exit gracefully
  //
  return true;
}

//-----------------------------------------------------------------------------
//
// we define non-integral constants in the default constructor
//      
//-----------------------------------------------------------------------------

// constants: class name
//
const String FourierTransform::CLASS_NAME(L"FourierTransform");

// constants: i/o related constants
//
const String FourierTransform::DEF_PARAM(L"");
const String FourierTransform::PARAM_ALGORITHM(L"algorithm");
const String FourierTransform::PARAM_IMPLEMENTATION(L"implementation");
const String FourierTransform::PARAM_DIRECTION(L"direction");
const String FourierTransform::PARAM_OTYPE(L"output_type");
const String FourierTransform::PARAM_RESOLUTION(L"resolution");
const String FourierTransform::PARAM_INPUT_LEN(L"input_length");
const String FourierTransform::PARAM_OUTPUT_LEN(L"output_length");
const String FourierTransform::PARAM_ORDER(L"order");
const String FourierTransform::PARAM_NORMALIZATION(L"normalization");

// constants: NameMap(s) for the enumerated values
//
const NameMap FourierTransform::ALGO_MAP(L"DFT, FFT, DCT");
const NameMap FourierTransform::IMPL_MAP(L"CONVENTIONAL, TRIGONOMETRIC, SPLIT_RADIX, RADIX_2, RADIX_4, FAST_HARTLEY, QF, DITF, TYPE_I, TYPE_II, TYPE_III, TYPE_IV");
const NameMap FourierTransform::DIRE_MAP(L"FORWARD, INVERSE");
const NameMap FourierTransform::OUTM_MAP(L"FULL, SYMMETRIC");
const NameMap FourierTransform::RESO_MAP(L"AUTO, FIXED");
const NameMap FourierTransform::NORM_MAP(L"NONE, UNIT_ENERGY");

// static instantiations: memory manager
//
MemoryManager FourierTransform::mgr_d(sizeof(FourierTransform),
				      FourierTransform::name());

