/*************************************************************************** * GFft.hpp - Fast Fourier transformation class * * ----------------------------------------------------------------------- * * copyright (C) 2016 by Juergen Knoedlseder * * ----------------------------------------------------------------------- * * * * This program 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. * * * * This program 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 this program. If not, see . * * * ***************************************************************************/ /** * @file GFft.hpp * @brief Fast Fourier transformation class interface definition * @author Juergen Knoedlseder */ #ifndef GFFT_HPP #define GFFT_HPP /* __ Includes ___________________________________________________________ */ #include #include #include #include "GBase.hpp" #include "GFftWavetable.hpp" /* __ Forward declarations _______________________________________________ */ class GNdarray; //class GFftWavetable; /***********************************************************************//** * @class GFft * * @brief Fast Fourier Transformation class * * This class implements a Fast Fourier Transformation of an n-dimensional * double precision floating point array. * * The class implementation is based on the Fast Fourier Transformation * functions that are provided by the GNU Scientific Library (GSL) * (version 2.2.1). The mixed-radix routines for complex numbers have been * adopted that work for any array lengths. The mixed-radix routines are a * reimplementation of the FFTPACK library of Paul Swarztrauber. * * The GSL is documented at https://www.gnu.org/software/gsl/manual ***************************************************************************/ class GFft : public GBase { public: // Constructors and destructors GFft(void); explicit GFft(const GNdarray& array); GFft(const GFft& fft); virtual ~GFft(void); // FFT access operators std::complex& operator()(const int& ix); std::complex& operator()(const int& ix, const int& iy); const std::complex& operator()(const int& ix) const; const std::complex& operator()(const int& ix, const int& iy) const; // Operators GFft& operator=(const GFft& fft); GFft& operator+=(const GFft& fft); GFft& operator-=(const GFft& fft); GFft& operator*=(const GFft& fft); GFft& operator/=(const GFft& fft); GFft operator-(void) const; // Methods void clear(void); GFft* clone(void) const; std::string classname(void) const; int dim(void) const; int size(void) const; const std::vector& shape(void) const; const std::vector& strides(void) const; void forward(const GNdarray& array); GNdarray backward(void) const; std::string print(const GChatter& chatter = NORMAL) const; protected: // Protected methods void init_members(void); void copy_members(const GFft& fft); void free_members(void); void set_data(const GNdarray& array); bool has_same_shape(const GFft& fft) const; void require_same_shape(const std::string& method, const GFft& fft) const; // Low-level FFT methods void transform(std::complex* data, const int& stride, const int& n, const GFftWavetable& wavetable, const bool& forward = true); void factor2(const std::complex* in, const int& istride, std::complex* out, const int& ostride, const GFftWavetable& wavetable, const int& sign, const int& product, const int& n, const int& index); void factor3(const std::complex* in, const int& istride, std::complex* out, const int& ostride, const GFftWavetable& wavetable, const int& sign, const int& product, const int& n, const int& index); void factor4(const std::complex* in, const int& istride, std::complex* out, const int& ostride, const GFftWavetable& wavetable, const int& sign, const int& product, const int& n, const int& index); void factor5(const std::complex* in, const int& istride, std::complex* out, const int& ostride, const GFftWavetable& wavetable, const int& sign, const int& product, const int& n, const int& index); void factor6(const std::complex* in, const int& istride, std::complex* out, const int& ostride, const GFftWavetable& wavetable, const int& sign, const int& product, const int& n, const int& index); void factor7(const std::complex* in, const int& istride, std::complex* out, const int& ostride, const GFftWavetable& wavetable, const int& sign, const int& product, const int& n, const int& index); void factorn(std::complex* in, const int& istride, std::complex* out, const int& ostride, const GFftWavetable& wavetable, const int& sign, const int& factor, const int& product, const int& n, const int& index); std::vector > get_w(const GFftWavetable& wavetable, const int& index, const int& k, const int& q, const int& n, const int& sign) const; std::complex timesi(const std::complex& value) const; // Protected members int m_size; //!< Size of data array std::complex* m_data; //!< Pointer on array data std::vector m_shape; //!< Array dimensions std::vector m_strides; //!< Steps in each dimension std::vector m_wavetable; //!< Trigonometric coefficients }; /***********************************************************************//** * @brief Return class name * * @return String containing the class name ("GFft"). ***************************************************************************/ inline std::string GFft::classname(void) const { return ("GFft"); } /***********************************************************************//** * @brief 1-dimensional FFT element access operator * * @param[in] ix Element index [0,...,shape(0)-1]. * @return Reference to FFT element. ***************************************************************************/ inline std::complex& GFft::operator()(const int& ix) { // Return array element return *(m_data + ix); } /***********************************************************************//** * @brief 2-dimensional FFT element access operator * * @param[in] ix Index in first dimension [0,...,shape(0)-1]. * @param[in] iy Index in second dimension [0,...,shape(1)-1]. * @return Reference to FFT element. ***************************************************************************/ inline std::complex& GFft::operator()(const int& ix, const int& iy) { // Return array element return *(m_data + ix + m_strides[1]*iy); } /***********************************************************************//** * @brief 1-dimensional FFT element access operator (const variant) * * @param[in] ix Element index [0,...,shape(0)-1]. * @return Const reference to FFT element. ***************************************************************************/ inline const std::complex& GFft::operator()(const int& ix) const { // Return array element return *(m_data + ix); } /***********************************************************************//** * @brief 2-dimensional FFT element access operator (const variant) * * @param[in] ix Index in first dimension [0,...,shape(0)-1]. * @param[in] iy Index in second dimension [0,...,shape(1)-1]. * @return Const reference to FFT element. ***************************************************************************/ inline const std::complex& GFft::operator()(const int& ix, const int& iy) const { // Return array element return *(m_data + ix + m_strides[1]*iy); } /***********************************************************************//** * @brief Return dimension of Fast Fourier Transformation * * @return Dimension of Fast Fourier Transformation. * * Returns the dimension of the Fast Fourier Transformation. ***************************************************************************/ inline int GFft::dim(void) const { return m_shape.size(); } /***********************************************************************//** * @brief Return number of elements in array * * @return Number of elements in array * * Returns the number of elements in the array. ***************************************************************************/ inline int GFft::size(void) const { return m_size; } /***********************************************************************//** * @brief Return shape of array * * @return Shape of array * * Returns the shape of the array. ***************************************************************************/ inline const std::vector& GFft::shape(void) const { return m_shape; } /***********************************************************************//** * @brief Return strides of array * * @return Strides of array * * Returns the strides of the array. ***************************************************************************/ inline const std::vector& GFft::strides(void) const { return m_strides; } /***********************************************************************//** * @brief Return sum of two Fast Fourier Transformations * * @param[in] a First Fast Fourier Transformation. * @param[in] b Second Fast Fourier Transformation. * @return Sum of the Fast Fourier Transformations @p a and @p b. * * Returns the sum of the Fast Fourier Transformations @p a and @p b. ***************************************************************************/ inline GFft operator+(const GFft& a, const GFft& b) { GFft result = a; result += b; return result; } /***********************************************************************//** * @brief Return difference of two Fast Fourier Transformations * * @param[in] a First Fast Fourier Transformation. * @param[in] b Second Fast Fourier Transformation. * @return Difference of the Fast Fourier Transformations @p a and @p b. * * Returns the difference of the Fast Fourier Transformations @p a and @p b. ***************************************************************************/ inline GFft operator-(const GFft& a, const GFft& b) { GFft result = a; result -= b; return result; } /***********************************************************************//** * @brief Return product of two Fast Fourier Transformations * * @param[in] a First Fast Fourier Transformation. * @param[in] b Second Fast Fourier Transformation. * @return Product of the Fast Fourier Transformations @p a and @p b. * * Returns the product of the Fast Fourier Transformations @p a and @p b. ***************************************************************************/ inline GFft operator*(const GFft& a, const GFft& b) { GFft result = a; result *= b; return result; } /***********************************************************************//** * @brief Return quotient of two Fast Fourier Transformations * * @param[in] a First Fast Fourier Transformation. * @param[in] b Second Fast Fourier Transformation. * @return Quotient of the Fast Fourier Transformations @p a and @p b. * * Returns the quotient of the Fast Fourier Transformations @p a and @p b. ***************************************************************************/ inline GFft operator/(const GFft& a, const GFft& b) { GFft result = a; result /= b; return result; } /***********************************************************************//** * @brief Return complex value times i * * @param[in] value Complex value. * @return Complex value times i. * * Returns complex value times i. ***************************************************************************/ inline std::complex GFft::timesi(const std::complex& value) const { std::complex result(-value.imag(), value.real()); return result; } #endif /* GFFT_HPP */