//   FFT (Fast Fourier Transform) Server Interface
//        R. Ansari     1999-2000
// DAPNIA/SPP (Saclay) / CEA    LAL - IN2P3/CNRS  (Orsay)

#ifndef  FFTServerIntf_H_SEEN
#define  FFTServerIntf_H_SEEN

#include "machdefs.h"
#include "pexceptions.h"
#include <complex>
#include "tmatrix.h"
#include "tvector.h"

// Classe definissant l'interface pour les transformees de Fourier 
// L'implementation par defaut est vide et lance une exception 

namespace SOPHYA {

class FFTServerInterface {
 public:

// Methodes de la classe 
  FFTServerInterface(string info);
  virtual ~FFTServerInterface();

  
  virtual FFTServerInterface * Clone() = 0;

//! Set/clear the flag for normalizing Fourier transforms.
  inline void setNormalize(bool fg=false) { _fgnorm = fg; }
//! Returns the status of normalization flag for the server
  inline bool getNormalize() const { return(_fgnorm); } 
//! Returns the information string associated with the server
  inline string getInfo() const { return _info; }

  //---------------------------------------------------
  // Transforme N-dim sur des doubles
  virtual void FFTForward(TArray< complex<r_8> > const & in, TArray< complex<r_8> > & out);
  virtual void FFTBackward(TArray< complex<r_8> > const & in, TArray< complex<r_8> > & out);
  virtual r_8  TransfEnergyFFT(TVector< complex<r_8> > const & x, TVector< complex<r_8> > const& fftx
                              , r_8& A, r_8& B);
   //! Compute the factor to be applied to "fftx=FFT(x)" so that "x" and "FFT(x)" have the same energy
  virtual inline r_8  TransfEnergyFFT(TVector< complex<r_8> > const & x, TVector< complex<r_8> > const& fftx)
                      {r_8 A,B; return TransfEnergyFFT(x,fftx,A,B);}

  virtual void FFTForward(TArray< r_8 > const & in, TArray< complex<r_8> > & out); 
  virtual void FFTBackward(TArray< complex<r_8> > const & in, TArray< r_8 > & out, 
			   bool usoutsz=false);
  virtual r_8  TransfEnergyFFT(TVector< r_8 > const & x, TVector< complex<r_8> > const& fftx
                              , r_8& A, r_8& B);
   //! Compute the factor to be applied to "fftx=FFT(x)" so that "x" and "FFT(x)" have the same energy
  virtual inline r_8  TransfEnergyFFT(TVector< r_8 > const & x, TVector< complex<r_8> > const& fftx)
                      {r_8 A,B; return TransfEnergyFFT(x,fftx,A,B);}

  // Transforme N-dim sur des float
  virtual void FFTForward(TArray< complex<r_4> > const & in, TArray< complex<r_4> > & out);
  virtual void FFTBackward(TArray< complex<r_4> > const & in, TArray< complex<r_4> > & out);
  virtual r_8  TransfEnergyFFT(TVector< complex<r_4> > const & x, TVector< complex<r_4> > const& fftx
                              , r_8& A, r_8& B);
   //! Compute the factor to be applied to "fftx=FFT(x)" so that "x" and "FFT(x)" have the same energy
  virtual inline r_8  TransfEnergyFFT(TVector< complex<r_4> > const & x, TVector< complex<r_4> > const& fftx)
                      {r_8 A,B; return TransfEnergyFFT(x,fftx,A,B);}

  virtual void FFTForward(TArray< r_4 > const & in, TArray< complex<r_4> > & out);
  virtual void FFTBackward(TArray< complex<r_4> > const & in, TArray< r_4 > & out,
			   bool usoutsz=false);
  virtual r_8  TransfEnergyFFT(TVector< r_4 > const & x, TVector< complex<r_4> > const& fftx
                              , r_8& A, r_8& B);
   //! Compute the factor to be applied to "fftx=FFT(x)" so that "x" and "FFT(x)" have the same energy
  virtual inline r_8  TransfEnergyFFT(TVector< r_4 > const & x, TVector< complex<r_4> > const& fftx)
                      {r_8 A,B; return TransfEnergyFFT(x,fftx,A,B);}

 protected:

  bool _fgnorm;
  string _info;
  
};


template <class T> 
class FFTArrayChecker {
public:
		FFTArrayChecker(string msg, bool checkpack=true, 
				bool onedonly=false);
  virtual	~FFTArrayChecker();
  static T	ZeroThreshold();
  
  inline void	SetMsg(string const & msg) { _msg = msg; }
  inline void	CheckPackedArray(bool ck=true) { _checkpack = ck; }
  inline void	Accept1DOnly(bool ac1d=false) { _onedonly = ac1d; }

  virtual int	CheckResize(TArray< complex<T> > const & in, TArray< complex<T> > & out);
  virtual int	CheckResize(TArray< T > const & in, TArray< complex<T> > & out);
  virtual int	CheckResize(TArray< complex<T> > const & in, TArray< T > & out, 
			    bool usoutsz=false);

protected:
  string _msg;
  bool _checkpack;
  bool _onedonly;

};

} // Fin du namespace

#endif
