// file: $isip/class/math/vector/MVector/MVectorMethods.h
// version: $Id: MVectorMethods.h 7799 2002-02-22 22:31:35Z wang $
//

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

// isip include files
//
#include <MScalar.h>
#include <Long.h>

// forward class definitions
//
template<class TScalar, class TIntegral> class MVector;

// MVectorMethods: a friend class to MVector. Its purpose is mainly to
// provide a mechanism to get source code out of the header file and into
// implementation files.
//
class MVectorMethods {
  
  //---------------------------------------------------------------------------
  //
  // required public methods
  //
  //---------------------------------------------------------------------------
public:
  
  // static methods
  //
  template <class TVector, class TScalar, class TIntegral>
  static boolean diagnose(Integral::DEBUG level);

  // i/o methods
  //
  template <class TScalar, class TIntegral>
  static long sofSize(const MVector<TScalar,TIntegral>& obj);
  
  template <class TScalar, class TIntegral>
  static boolean read(MVector<TScalar,TIntegral>& obj, Sof& sof,
		      long tag, const String& name);
  
  template <class TScalar, class TIntegral>
  static boolean write(const MVector<TScalar,TIntegral>& obj,
		       Sof& sof, long tag, const String& name);
  
  template <class TScalar, class TIntegral>
  static boolean readData(MVector<TScalar,TIntegral>& obj, Sof& sof,
			  const String& pname, long size, boolean param,
			  boolean nested);
  
  template <class TScalar, class TIntegral>
  static boolean writeData(const MVector<TScalar,TIntegral>& obj,
			   Sof& sof, const String& name);
  
  //-------------------------------------------------------------------------
  //
  // class-specific public methods
  //
  //-------------------------------------------------------------------------
  
  // array conversion methods
  //
  template <class TScalar, class TIntegral, class TAIntegral>
  static boolean assign(MVector<TScalar,TIntegral>& obj, long num_elem,
			const TAIntegral* arg);
  
  template <class TScalar, class TIntegral>
  static boolean assign(MVector<TScalar,TIntegral>& obj, long num_elem,
			const String* arg);
  
  // conversion from string using parsing
  //
  template <class TScalar, class TIntegral>
  static boolean assign(MVector<TScalar,TIntegral>& obj, const String& arg,
			unichar delim);
  
  template <class TScalar, class TIntegral>
  static boolean assign(MVector<TScalar,TIntegral>& obj, const unichar* arg,
			unichar delim);
  
  // conversion to string
  //
  template <class TScalar, class TIntegral>
  static boolean get(const MVector<TScalar,TIntegral>& obj, String& output,
		     const String& delim);

  // swap the current vector with the input vector
  //
  template <class TScalar, class TIntegral>
  static boolean swap(MVector<TScalar,TIntegral>& obj,
		      MVector<TScalar,TIntegral>& arg);
  
  // partial i/o methods
  //
  template <class TScalar, class TIntegral>
  static boolean readStart(MVector<TScalar,TIntegral>& obj, Sof& sof,
			   const String& pname, long size,
			   boolean param, boolean nested);

  template <class TScalar, class TIntegral>
  static long readPartialData(MVector<TScalar,TIntegral>& obj, Sof& sof,
			      long start_pos, long num_elem,
			      const String& pname, long size,
			      boolean param, boolean nested);
  
  template <class TScalar, class TIntegral>
  static boolean writeStart(const MVector<TScalar,TIntegral>& obj, Sof& sof,
			    const String& pname);

  template <class TScalar, class TIntegral>
  static long writePartialData(const MVector<TScalar,TIntegral>& obj,
			       Sof& sof, long start_pos, long num_elem);

  template <class TScalar, class TIntegral>
  static boolean writeTerminate(const MVector<TScalar,TIntegral>& obj,
				Sof& sof, const String& pname);
  
  // memory size methods
  //
  template <class TScalar, class TIntegral>
  static long memSize(const MVector<TScalar,TIntegral>& obj);

  // comparison methods
  //
  template <class TScalar, class TIntegral>
  static boolean eq(const MVector<TScalar,TIntegral>& obj, TIntegral value);
  
  template <class TScalar, class TIntegral>
  static boolean ne(const MVector<TScalar,TIntegral>& obj,
		    const MVector<TScalar,TIntegral>& vector);
  
  template <class TScalar, class TIntegral>
  static boolean ne(const MVector<TScalar,TIntegral>& obj, TIntegral value);
  
  template <class TScalar, class TIntegral>
  static boolean gt(const MVector<TScalar,TIntegral>& obj,
		    const MVector<TScalar,TIntegral>& vector);
  
  template <class TScalar, class TIntegral>
  static boolean gt(const MVector<TScalar,TIntegral>& obj, TIntegral value);
  
  template <class TScalar, class TIntegral>
  static boolean lt(const MVector<TScalar,TIntegral>& obj,
		    const MVector<TScalar,TIntegral>& vector);
  
  template <class TScalar, class TIntegral>
  static boolean lt(const MVector<TScalar,TIntegral>& obj, TIntegral value);
  
  template <class TScalar, class TIntegral>
  static boolean ge(const MVector<TScalar,TIntegral>& obj,
		    const MVector<TScalar,TIntegral>& vector);
  
  template <class TScalar, class TIntegral>
  static boolean ge(const MVector<TScalar,TIntegral>& obj, TIntegral value);
    
  template <class TScalar, class TIntegral>
  static boolean le(const MVector<TScalar,TIntegral>& obj,
		    const MVector<TScalar,TIntegral>& vector);
  
  template <class TScalar, class TIntegral>
  static boolean le(const MVector<TScalar,TIntegral>& obj, TIntegral value);
  
  // common mathematical functions
  //
  template <class TScalar, class TIntegral>
  static boolean pow(MVector<TScalar,TIntegral>& obj,
		     const MVector<TScalar,TIntegral>& x, double y);
  
  template <class TScalar, class TIntegral>
  static boolean sort(MVector<TScalar,TIntegral>& obj,
		      const MVector<TScalar,TIntegral>& vector,
		      Integral::ORDER order = Integral::DEF_ORDER);

  template <class TScalar, class TIntegral>
  static boolean index(MVector<TScalar,TIntegral>& obj, 
		       Integral::ORDER order,
                       MVector<Long,long>& sort_index);


  template <class TScalar, class TIntegral>
  static boolean randperm(MVector<TScalar,TIntegral>& obj, long size);

  // mathematical limits, ceiling, floor and rounding functions
  //  
  template <class TScalar, class TIntegral>
  static TIntegral max(const MVector<TScalar,TIntegral>& obj, long& position);
    
  template <class TScalar, class TIntegral>
  static TIntegral min(const MVector<TScalar,TIntegral>& obj, long& position);
    
  template <class TScalar, class TIntegral>
  static double minMag(const MVector<TScalar,TIntegral>& obj,
			  long& position);
    
  template <class TScalar, class TIntegral>
  static double maxMag(const MVector<TScalar,TIntegral>& obj,
			  long& position);
    
  // function generation methods
  //
  template <class TScalar, class TIntegral>
  static boolean ramp(MVector<TScalar,TIntegral>& obj,
		      TIntegral offset, TIntegral incr);
  
  template <class TScalar, class TIntegral>
  static boolean ramp(MVector<TScalar,TIntegral>& obj,
		      TIntegral offset, TIntegral incr, TIntegral end);
  
  // vector to scalar mathematical methods
  //
  template <class TScalar, class TIntegral>
  static TIntegral sum(const MVector<TScalar,TIntegral>& obj);
  
  template <class TScalar, class TIntegral>
  static TIntegral sumSquare(const MVector<TScalar,TIntegral>& obj);
  
  template <class TScalar, class TIntegral>
  static TIntegral mean(const MVector<TScalar,TIntegral>& obj);

  template <class TScalar, class TIntegral>
  static TIntegral median(const MVector<TScalar,TIntegral>& obj);
  
  template <class TScalar, class TIntegral>
  static TIntegral rms(const MVector<TScalar,TIntegral>& obj);
  
  template <class TScalar, class TIntegral>
  static TIntegral var(const MVector<TScalar,TIntegral>& obj);
  
  template <class TScalar, class TIntegral>
  static TIntegral stdev(const MVector<TScalar,TIntegral>& obj);
  
  template <class TScalar, class TIntegral>
  static TIntegral dotProduct(const MVector<TScalar,TIntegral>& obj,
			      const MVector<TScalar,TIntegral>& vector);
  
  template <class TScalar, class TIntegral>
  static TIntegral distanceSquare(const MVector<TScalar,TIntegral>& obj,
				  const MVector<TScalar,TIntegral>& vector);
  
  template <class TScalar, class TIntegral>
  static long numEqual(const MVector<TScalar,TIntegral>& obj,
		       TIntegral test_value);
  
  template <class TScalar, class TIntegral>
  static long numNotEqual(const MVector<TScalar,TIntegral>& obj,
			  TIntegral test_value);
  
  // dsp methods
  // 
  template <class TScalar, class TIntegral>
  static boolean limit(MVector<TScalar,TIntegral>& obj,
		       TIntegral min_val, TIntegral max_val,
		       const MVector<TScalar,TIntegral>& vector);
  
  template <class TScalar, class TIntegral>
  static boolean limitMin(MVector<TScalar,TIntegral>& obj,
			  TIntegral min_val,
			  const MVector<TScalar,TIntegral>& vector);
    
  template <class TScalar, class TIntegral>
  static boolean limitMax(MVector<TScalar,TIntegral>& obj,
			  TIntegral max_val,
			  const MVector<TScalar,TIntegral>& vector);
    
  template <class TScalar, class TIntegral>
  static boolean limitMag(MVector<TScalar,TIntegral>& obj,
			  TIntegral cmp_val, TIntegral new_val,
			  const MVector<TScalar,TIntegral>& vector);
  
  template <class TScalar, class TIntegral>
  static boolean centerClip(MVector<TScalar,TIntegral>& obj,
			    TIntegral min_val, TIntegral max_val,
			    const MVector<TScalar,TIntegral>& vector);
  
  // random number generation methods
  //
  template <class TScalar, class TIntegral>
  static boolean rand(MVector<TScalar,TIntegral>& obj,
		      Random& generator);
  
  template <class TScalar, class TIntegral>
  static boolean rand(MVector<TScalar,TIntegral>& obj,
		      TIntegral min_val, TIntegral max_val,
		      Random& generator);
  
  template <class TScalar, class TIntegral>
  static boolean grand(MVector<TScalar,TIntegral>& obj,
		       TIntegral mean, TIntegral stdev, Random& generator);
  
  // position operation methods
  //
  template <class TScalar, class TIntegral>
  static boolean move(MVector<TScalar,TIntegral>& obj,
		      const MVector<TScalar,TIntegral>& source_vector,
		      long num_elements, long source_offset, long dest_offset);
  
  template <class TScalar, class TIntegral>
  static boolean shift(MVector<TScalar,TIntegral>& obj, long delta);
  
  template <class TScalar, class TIntegral>
  static boolean shift(MVector<TScalar,TIntegral>& obj,
		       const MVector<TScalar,TIntegral>& source_vector,
		       long delta);  
  
  template <class TScalar, class TIntegral>
  static boolean concat(MVector<TScalar,TIntegral>& obj,
			const MVector<TScalar,TIntegral>& v2);
  
  template <class TScalar, class TIntegral>
  static boolean concat(MVector<TScalar,TIntegral>& obj,
			const MVector<TScalar,TIntegral>& v1,
			const MVector<TScalar,TIntegral>& v2);
  
  template <class TScalar, class TIntegral>
  static boolean deleteRange(MVector<TScalar,TIntegral>& obj,
			     const MVector<TScalar,TIntegral>& source_vector,
			     long offset, long num_elements);
  
  template <class TScalar, class TIntegral>
  static boolean setRange(MVector<TScalar,TIntegral>& obj,
			  long offset, long num_elements, TIntegral value);

  // element location and ordering methods
  //
  template <class TScalar, class TIntegral>
  static long first(MVector<TScalar,TIntegral>& obj,
		    TIntegral value, long start_pos);
  
  template <class TScalar, class TIntegral>
  static long last(MVector<TScalar,TIntegral>& obj,
		   TIntegral value, long end_pos);
  
  template <class TScalar, class TIntegral>
  static boolean reorder(MVector<TScalar,TIntegral>& obj,
			 const MVector<Long,long>& indexes);
  
  template <class TScalar, class TIntegral>
  static boolean reorder(MVector<TScalar,TIntegral>& obj,
			 const MVector<TScalar,TIntegral>& arg,
			 const MVector<Long,long>& indexes);

  template <class TScalar, class TIntegral>
  static boolean reverse(MVector<TScalar,TIntegral>& obj);
  
  //---------------------------------------------------------------------------
  //
  // private methods
  //
  //---------------------------------------------------------------------------
private:
  
  // destructor/constructor(s):
  // the constructors and destructors are declared private so that a
  // compilation error will be generated if the user tries to construct an
  // object of this type
  //
  ~MVectorMethods();
  MVectorMethods();
  MVectorMethods(const MVectorMethods& arg);

  // additional diagnose methods: because of the complexity of diagnose,
  // we break it into smaller functions.
  //

  template <class TVector, class TScalar, class TIntegral>
  static boolean diagnose1(Integral::DEBUG level);  

  template <class TVector, class TScalar, class TIntegral>
  static boolean diagnose2(Integral::DEBUG level);

  template <class TVector, class TScalar, class TIntegral>
  static boolean diagnose3(Integral::DEBUG level);

  template <class TVector, class TScalar, class TIntegral>
  static boolean diagnose4(Integral::DEBUG level);

  template <class TVector, class TScalar, class TIntegral>
  static boolean diagnose5(Integral::DEBUG level);
  
  template <class TVector, class TScalar, class TIntegral>
  static boolean diagnose6(Integral::DEBUG level);
  
  template <class TVector, class TScalar, class TIntegral>
  static boolean diagnose7(Integral::DEBUG level);
  
  template <class TVector, class TScalar, class TIntegral>
  static boolean diagnose8(Integral::DEBUG level);

  template <class TVector, class TScalar, class TIntegral>
  static boolean diagnose9(Integral::DEBUG level);  
  
  // dummy name methods
  //
  static const String& name();
};

// end of include file
//
#endif
