// file: $isip/class/algo/Energy/enrgy_00.cc
// version: $Id: enrgy_00.cc 7592 2002-01-01 00:13:30Z picone $
//

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

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

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

  // assign data from the input energy object
  //
  algorithm_d = arg_a.algorithm_d;
  implementation_d = arg_a.implementation_d;
  floor_d = arg_a.floor_d;
  
  // assign filter data
  //
  ma_coef_d.assign(arg_a.ma_coef_d);
  ar_coef_d.assign(arg_a.ar_coef_d);
  ma_mem_d.assign(arg_a.ma_mem_d);
  ar_mem_d.assign(arg_a.ar_mem_d);

  // assign AlgorithmBase and exit gracefully
  //
  return AlgorithmBase::assign(arg_a);
}

// method: eq
//
// arguments:
//  const Energy& 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 Energy::eq(const Energy& arg_a) const {

  // compare the data members
  //
  if ((algorithm_d != arg_a.algorithm_d) ||
      (implementation_d != arg_a.implementation_d) ||
      (floor_d != arg_a.floor_d) ||
      (!ma_coef_d.eq(arg_a.ma_coef_d)) ||
      (!ar_coef_d.eq(arg_a.ar_coef_d))) {
    return false;
  }

  // exit gracefully
  //
  return true;
}

// 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 Energy::clear(Integral::CMODE ctype_a) {
  
  // reset the data members unless the mode is RETAIN
  //
  if (ctype_a != Integral::RETAIN) {

    // clear the design parameters
    //
    algorithm_d = DEF_ALGORITHM;
    implementation_d = DEF_IMPLEMENTATION;  
    floor_d = DEF_FLOOR;

    // clear the vector data
    //
    ma_coef_d.clear(ctype_a);
    ar_coef_d.clear(ctype_a);
  }
  
  // handle the other class data appropriately:
  //  note that even in RETAIN mode we need to clear the filter history
  //
  ma_mem_d.clear(ctype_a);
  ar_mem_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 value indicating status
//
// this method assigns the input algorithm object to the current object.
//
boolean Energy::assign(const AlgorithmBase& arg_a) {

  // case: input is an Energy object
  //
  if (typeid(arg_a) == typeid(Energy)) {
    return assign((Energy&)arg_a);
  }

  // case: other
  //  if the input algorithm object is not an Energy object, error.
  //
  else {
    return Error::handle(name(), L"assign", Error::ARG, __FILE__, __LINE__);
  }
}

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

  // case: input is an Energy object
  //
  if (typeid(arg_a) == typeid(Energy)) {
    return eq((Energy&)arg_a);
  }

  // case: other
  //  if the input algorithm object is not an Energy object, error.
  //
  else {
    return Error::handle(name(), L"eq", Error::ARG, __FILE__, __LINE__);
  }
}

// method: init
//
// arguments: none
//
// return: a boolean value indicating status
//
// this method precomputes various constants used in this class
// 
boolean Energy::init() {

  // check algorithm: SUM
  //
  if (algorithm_d == SUM) {
    // no initialization needed
  }
  
  // check algorithm: FILTER
  //
  else if (algorithm_d == FILTER) {

    // check for degenerate cases
    //
    if (ma_coef_d.length() == 0) {
      ma_coef_d.setLength(1);
      ma_coef_d(0) = 1.0;
    }
    if (ar_coef_d.length() == 0) {
      ar_coef_d.setLength(1);
      ar_coef_d(0) = 1;
    }

    // create space for each channel
    //
    ma_mem_d.setLength(num_channels_d);
    ar_mem_d.setLength(num_channels_d);

    // size the delay lines
    //
    for (long nchan = 0; nchan < num_channels_d; nchan++) {
      ma_mem_d(nchan).setLength(ma_coef_d.length());
      ma_mem_d(nchan).clear(Integral::RETAIN);
      ar_mem_d(nchan).setLength(ar_coef_d.length());
      ar_mem_d(nchan).clear(Integral::RETAIN);    
    }
  }

  // set the initialization flag
  //
  is_valid_d = true;
  
  // exit gracefully
  //
  return true;
}

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

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

// constants: i/o related constants
//
const String Energy::DEF_PARAM(L"");
const String Energy::PARAM_ALGORITHM(L"algorithm");
const String Energy::PARAM_IMPLEMENTATION(L"implementation");
const String Energy::PARAM_FLOOR(L"floor");
const String Energy::PARAM_MA_COEF(L"ma_coef");
const String Energy::PARAM_AR_COEF(L"ar_coef");

// constants: default values of the class data
//
const VectorFloat Energy::DEF_MA_COEF(L"1");
const VectorFloat Energy::DEF_AR_COEF(L"1");

// constants: name map(s) for the enumerated values
//
const NameMap Energy::ALGO_MAP(L"SUM, FILTER");
const NameMap Energy::IMPL_MAP(L"IDENTITY, LOG, DB, POWER, LOG_POWER, DB_POWER, RMS, LOG_RMS, DB_RMS");

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