/***************************************************************************
**
**  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: 2016-12-01
**  Copyright: 2016-2019
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#include "FFTWCache.h"

namespace GeopsyCore {

  /*!
    \class FFTWCache FFTWCache.h
    \brief Brief description of class still missing

    Full description of class still missing
  */

  IMPLEMENT_NUMERICALKEY(FFTWKey)
  Mutex FFTWCache::_plannerMutex;

  /*!
    Description of constructor still missing
  */
  FFTWCache::FFTWCache(FFTWKey * key)
    : AbstractNumericalCache(key)
  {
    TRACE;
  }

  /*!
    Description of destructor still missing
  */
  FFTWCache::~FFTWCache()
  {
    TRACE;
    _plannerMutex.lock();
    fftw_destroy_plan(_plan);
    _plannerMutex.unlock();
  }

  /*!
    Return true if it inherits \a className.
    Used by GeopsyCoreEngine to remove all FFTWCache from global object list.
  */
  bool FFTWCache::inherits(const char * className)
  {
    if(strcmp(className, "FFTWCache")==0) {
      return true;
    } else {
      return AbstractNumericalCache::inherits(className);
    }
  }

  void FFTWCache::init()
  {
    TRACE;
    const FFTWKey& fKey=static_cast<const FFTWKey&>(key());
    _fft.setNSamples(fKey.nSamples());

    APP_LOG(1, tr("New fftw plan for %1 samples with direction %2\n")
                      .arg(fKey.nSamples()).arg(fKey.direction()))

    LOCK_SAMPLES(double, samples, &_fft)
      _plannerMutex.lock();
      _plan=fftw_plan_r2r_1d(_fft.nSamples(), samples, samples,
                             fKey.direction()==FFTWKey::R2HC ? FFTW_R2HC : FFTW_HC2R,
                             FFTW_ESTIMATE);
      _plannerMutex.unlock();
    UNLOCK_SAMPLES(&_fft)
  }

  void FFTWCache::execute(double * samples) const
  {
    TRACE;
    fftw_execute_r2r(_plan, samples, samples);
  }

} // namespace GeopsyCore

