// file: $isip/class/stat/UniformModel/UniformModel.h
// version: $Id: UniformModel.h 8756 2002-10-18 21:47:07Z alphonso $
//

// make sure definitions are only made once
//
#ifndef ISIP_UNIFORM_MODEL
#define ISIP_UNIFORM_MODEL

// isip include files
//
#ifndef ISIP_VECTOR_FLOAT
#include <VectorFloat.h>
#endif

#ifndef ISIP_VECTOR_DOUBLE
#include <VectorDouble.h>
#endif

#ifndef ISIP_MATRIX_FLOAT
#include <MatrixFloat.h>
#endif

#ifndef ISIP_FLOAT
#include <Float.h>
#endif

#ifndef ISIP_MEMORY_MANAGER
#include <MemoryManager.h>
#endif

#ifndef ISIP_STATISTICAL_MODEL_BASE
#include <StatisticalModelBase.h>
#endif

// UniformModel: generates a constant score for any test vector input
//
class UniformModel : public StatisticalModelBase {

  //---------------------------------------------------------------------------
  //
  // public constants
  //
  //---------------------------------------------------------------------------
public:

  // define the class name
  //
  static const String CLASS_NAME;

  //----------------------------------------
  //
  // i/o related constants
  //
  //----------------------------------------  

  static const String DEF_PARAM;
  static const String PARAM_MIN;
  static const String PARAM_MAX;

  //----------------------------------------
  //
  // default values and arguments
  //
  //----------------------------------------  

  //----------------------------------------
  //
  // error codes
  //
  //----------------------------------------  

  static const long ERR = 60400;
    
  //---------------------------------------------------------------------------
  //
  // protected data
  //
  //---------------------------------------------------------------------------
protected:

  // declare variables to describe the range
  //
  VectorFloat min_d;
  VectorFloat max_d;

  // probability distribution scale factor
  //
  float scale_d;

  // memory manager
  //
  static MemoryManager mgr_d;
  
  //---------------------------------------------------------------------------
  //
  // required public methods
  //
  //---------------------------------------------------------------------------
public:

  // method: name
  //
  static const String& name() {
    return CLASS_NAME;
  }

  // other static methods
  //
  static boolean diagnose(Integral::DEBUG debug_level);

  // debug methods
  //  setDebug inherited from base class
  //
  boolean debug(const unichar* msg) const;
    
  // method: destructor
  //
  ~UniformModel() {}

  // method: default constructor
  //
  UniformModel(MODE mode = DEF_MODE) {
    mode_d = mode;
    is_valid_d = false;
  }

  // method: copy constructor
  //
  UniformModel(const UniformModel& arg) {
    assign(arg);
  }

  // method: assign
  //
  boolean assign(const UniformModel& arg) {
    mode_d = arg.mode_d;
    min_d.assign(arg.min_d);
    max_d.assign(arg.max_d);
    is_valid_d = false;
    return true;
  }

  // method: operator=
  //
  UniformModel& operator=(const UniformModel& arg) {
    assign(arg);
    return *this;
  }
  
  // method: sofSize
  //
  long sofSize() const {
    return (min_d.sofSize() + max_d.sofSize());
  }

  // method: sofAccumulatorSize
  //
  long sofAccumulatorSize() const {
    return 0;
  }

  // method: sofOccupanciesSize
  //
  long sofOccupanciesSize() const {
    return 0;
  }    
  
  // other i/o methods
  //
  boolean read(Sof& sof, long tag, const String& name = CLASS_NAME);
  boolean write(Sof& sof, long tag,
		const String& name = CLASS_NAME) const;

  boolean readData(Sof& sof, const String& pname = DEF_PARAM,
                   long size = SofParser::FULL_OBJECT,
                   boolean param = true,
                   boolean nested = false);
  boolean writeData(Sof& sof, const String& pname = DEF_PARAM) const;

  // method: readAccumulator
  //
  boolean readAccumulator(Sof& sof, long tag,
		    const String& name = CLASS_NAME) {
    return true;
  }

  // method: writeAccumulator
  //
  boolean writeAccumulator(Sof& sof, long tag,
		     const String& name = CLASS_NAME) const {
    return true;
  }

  // method: readAccumulatorData
  //
  boolean readAccumulatorData(Sof& sof, const String& pname = DEF_PARAM,
			long size = SofParser::FULL_OBJECT,
			boolean param = true,
			boolean nested = false) {
    return true;
  }

  // method: writeAccumulatorData
  //
  boolean writeAccumulatorData(Sof& sof, const String& pname = DEF_PARAM) const {
    return true;
  }
  
  // method: readOccupancies
  //
  boolean readOccupancies(Sof& sof, long tag,
			  const String& name = CLASS_NAME) {
    return true;
  }

  // method: writeOccupancies
  //
  boolean writeOccupancies(Sof& sof, long tag,
		     const String& name = CLASS_NAME) const {
    return true;
  }
  
  // method: readOccupanciesData
  //
  boolean readOccupanciesData(Sof& sof, const String& pname = DEF_PARAM,
			      long size = SofParser::FULL_OBJECT,
			      boolean param = true,
			      boolean nested = false) {
    return true;
  }

  // method: writeOccupanciesData
  //
  boolean writeOccupanciesData(Sof& sof, const String& pname = DEF_PARAM) const {
    return true;
  }
  
  // method: eq
  //
  boolean eq(const UniformModel& arg) const {
    return (min_d.eq(arg.min_d) && max_d.eq(arg.max_d));
  }

  // method: operator new
  //
  static void* operator new(size_t size) {
    return mgr_d.get();
  }

  // method: operator new[]
  //
  static void* operator new[](size_t size) {
    return mgr_d.getBlock(size);
  }

  // method: operator delete
  //
  static void operator delete(void* ptr) {
    mgr_d.release(ptr);
  }

  // method: operator delete[]
  //
  static void operator delete[](void* ptr) {
    mgr_d.releaseBlock(ptr);
  }

  // method: setGrowSize
  //
  static boolean setGrowSize(long grow_size) {
    return mgr_d.setGrow(grow_size);
  }

  // method: clear
  //
  boolean clear(Integral::CMODE cmode = Integral::DEF_CMODE) {
    min_d.clear(cmode);
    max_d.clear(cmode);
    is_valid_d = false;
    return true;
  }
  
  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  additional methods unique to this class needed to support the
  //  interface contract
  //
  //--------------------------------------------------------------------------

  // method: constructor
  //
  UniformModel(VectorFloat min, VectorFloat max, MODE mode = DEF_MODE) {
    min_d.assign(min);
    max_d.assign(max);    
    mode_d = mode;
    is_valid_d = false;
  }

  // method: constructor
  //
  UniformModel(float min, float max, MODE mode = DEF_MODE) {
    VectorFloat vmin(1, min);
    min_d.assign(vmin);
    VectorFloat vmax(1, max);
    max_d.assign(vmax);    
    mode_d = mode;
    is_valid_d = false;
  }

  // method: setMin
  //
  boolean setMin(VectorFloat& arg) {
    min_d.assign(arg);
    is_valid_d = false;
    return true;
  }

  // method: setMin
  //
  boolean setMin(float arg) {
    VectorFloat varg(1, arg);
    min_d.assign(varg);
    is_valid_d = false;
    return true;
  }

  // method: setMax
  //
  boolean setMax(VectorFloat& arg) {
    max_d.assign(arg);
    is_valid_d = false;
    return true;
  }

  // method: setMax
  //
  boolean setMax(float arg) {
    VectorFloat varg(1, arg);
    max_d.assign(varg);
    is_valid_d = false;
    return true;
  }

  // method: getMin
  //
  boolean getMin(VectorFloat& min) const {
    return min.assign(min_d);
  }

  // method: getMax
  //
  boolean getMax(VectorFloat& max) const {
    return max.assign(max_d);
  }

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  required by the interface contract
  //  setMode is inherited from StatisticalModelBase
  //
  //--------------------------------------------------------------------------

  // StatisticalModelBase required methods
  //
  boolean assign(const StatisticalModelBase& arg);
  boolean eq(const StatisticalModelBase& arg) const;

  // method: className
  //
  const String& className() const {
    return CLASS_NAME;
  }

  // initialization methods
  //
  boolean init();

  // method: getMean
  //
  boolean getMean(VectorFloat& mean);

  // method: getCovariance
  //
  boolean getCovariance(MatrixFloat& cov);
  
  // likelihood calculcation methods
  //
  float getLikelihood(const VectorFloat& input);
  float getLogLikelihood(const VectorFloat& input);

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  model reestimation methods
  //
  //---------------------------------------------------------------------------

  // method: resetAccumulators
  //
  boolean resetAccumulators() {
    return Error::handle(name(), L"resetAccumulators", Error::ARG, __FILE__, __LINE__);
  }
  
  // method: getOccupancy
  //
  double getOccupancy() {
    return Error::handle(name(), L"getOccupancy", Error::ARG, __FILE__, __LINE__);
  }

  // method: setOccupancy
  //
  boolean setOccupancy(double arg) {
    Error::handle(name(), L"getOccupancy", Error::ARG, __FILE__, __LINE__);
    return false;
  }  

  // method: getAccessCount
  //
  long getAccessCount() {
    return Error::handle(name(), L"getAccessCount", Error::ARG, __FILE__, __LINE__);
  }

  // method: setAccessCount
  //
  boolean setAccessCount(long arg) {
    return Error::handle(name(), L"setAccessCount", Error::ARG, __FILE__, __LINE__);
  }

  // method: initialize
  //
  boolean initialize(VectorFloat& param) {
    return Error::handle(name(), L"initialize", Error::ARG, __FILE__, __LINE__);
  }

  // method: accumulate
  //
  boolean accumulate(VectorFloat& data) {
    return Error::handle(name(), L"initialize", Error::ARG, __FILE__, __LINE__);
  }  
		     
  // method: accumulate
  //
  boolean accumulate(VectorDouble& param,
		     VectorFloat& data, boolean precomp) {
    return Error::handle(name(), L"accumulate", Error::NOT_IMPLEM, __FILE__, __LINE__);
  }

  // method: update
  //  
  boolean update(VectorFloat& varfloor, long min_count) {
    return Error::handle(name(), L"update", Error::NOT_IMPLEM, __FILE__, __LINE__);
  }
  
  //---------------------------------------------------------------------------
  //
  // private methods
  //
  //---------------------------------------------------------------------------
private:

  // initialization methods
  //
  float initScale();

};

// end of include file
// 
#endif
