/***************************************************************************
**
**  This file is part of GeopsyCore.
**
**  GeopsyCore is free software: you can redistribute it and/or modify
**  it under the terms of the GNU General Public License as published by
**  the Free Software Foundation, either version 3 of the License, or
**  (at your option) any later version.
**
**  GeopsyCore is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**  GNU General Public License for more details.
**
**  You should have received a copy of the GNU General Public License
**  along with Foobar.  If not, see <http://www.gnu.org/licenses/>
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2009-04-11
**  Copyright: 2009-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#ifndef FASTPARTIALFOURIERTRANSFORM_H
#define FASTPARTIALFOURIERTRANSFORM_H

#if 0

#include <QGpCoreTools.h>
#include "ComplexSignal.h"

namespace GeopsyCore {

class FastPartialFourierTransformKey : public AbstractNumericalKey
{
  DECLARE_NUMERICALKEY(FastPartialFourierTransformKey)
public:
  enum Direction {Forward, Backward};

  FastPartialFourierTransformKey(double deltaT, int nInSamples, int mOutSamples, int startIndex, Direction direction) {
    _deltaT=deltaT;
    _nInSamples=nInSamples;
    _mOutSamples=mOutSamples;
    _startIndex=startIndex;
    _direction=direction;
  }
  virtual bool operator==(const AbstractNumericalKey& o) {
    const FastPartialFourierTransformKey& mo=static_cast<const FastPartialFourierTransformKey&>(o);
    return _deltaT==mo._deltaT &&
           _nInSamples==mo._nInSamples &&
           _mOutSamples==mo._mOutSamples &&
           _startIndex==mo._startIndex &&
           _direction==mo._direction;
  }
  virtual int hash() const {return (int)floor(1.0/_deltaT)+_nInSamples+_mOutSamples+_startIndex+_direction;}
  inline virtual AbstractNumericalCache * createCache();
  inline virtual int byteCount() const;

  double deltaT() const {return _deltaT;}
  int nInSamples() const {return _nInSamples;}
  int mOutSamples() const {return _mOutSamples;}
  int startIndex() const {return _startIndex;}
  Direction direction() const {return _direction;}
private:
  double _deltaT;
  int _nInSamples, _mOutSamples, _startIndex;
  Direction _direction;
};

class FastPartialFourierTransform : public AbstractNumericalCache
{
public:
  FastPartialFourierTransform(FastPartialFourierTransformKey * key);
  ~FastPartialFourierTransform();

  static inline const FastPartialFourierTransform * begin(double deltaT, int nInSamples, int mOutSamples, int startIndex,
                                                              FastPartialFourierTransformKey::Direction direction);
  virtual void init();

  static ComplexSignal * forward(const DoubleSignal * inSig, int nInSamples, int mOutSamples, int startIndex);
  static ComplexSignal * backward(const DoubleSignal * inSig, int nInSamples, int mOutSamples, int startIndex);
private:
  int inIndex(int i) const {return _inIndexes[i];}
  int outIndex(int i) const {return _outIndexes[i];}
  const Complex& zFactor(int i) const {return _zFactors[i];}
  const Complex& fzFactor(int i) const {return _fzFactors[i];}

  int * _inIndexes, * _outIndexes;
  Complex * _zFactors;
  Complex * _fzFactors;
};

inline AbstractNumericalCache * FastPartialFourierTransformKey::createCache( )
{
  return new FastPartialFourierTransform(this);
}

inline const FastPartialFourierTransform * FastPartialFourierTransform::begin(double deltaT, int nInSamples, int mOutSamples, int startIndex,
                                                                                     FastPartialFourierTransformKey::Direction direction)
{
  return static_cast<const FastPartialFourierTransform *>(
      AbstractNumericalCache::begin(new FastPartialFourierTransformKey(deltaT, nInSamples, mOutSamples, startIndex, direction) ));
}

inline int FastPartialFourierTransformKey::byteCount() const
{
  return 2*_nInSamples*(sizeof(int)+sizeof(Complex));
}

} // namespace GeopsyCore

#endif

#endif // FASTPARTIALFOURIERTRANSFORM_H
