xref: /aosp_15_r20/external/pffft/pffft.hpp (revision 3f1979aa0d7ad34fcf3763de7b7b8f8cd67e5bdd)
1*3f1979aaSAndroid Build Coastguard Worker /* Copyright (c) 2020  Dario Mambro ( [email protected] )
2*3f1979aaSAndroid Build Coastguard Worker    Copyright (c) 2020  Hayati Ayguen ( [email protected] )
3*3f1979aaSAndroid Build Coastguard Worker 
4*3f1979aaSAndroid Build Coastguard Worker    Redistribution and use of the Software in source and binary forms,
5*3f1979aaSAndroid Build Coastguard Worker    with or without modification, is permitted provided that the
6*3f1979aaSAndroid Build Coastguard Worker    following conditions are met:
7*3f1979aaSAndroid Build Coastguard Worker 
8*3f1979aaSAndroid Build Coastguard Worker    - Neither the names of PFFFT, nor the names of its
9*3f1979aaSAndroid Build Coastguard Worker    sponsors or contributors may be used to endorse or promote products
10*3f1979aaSAndroid Build Coastguard Worker    derived from this Software without specific prior written permission.
11*3f1979aaSAndroid Build Coastguard Worker 
12*3f1979aaSAndroid Build Coastguard Worker    - Redistributions of source code must retain the above copyright
13*3f1979aaSAndroid Build Coastguard Worker    notices, this list of conditions, and the disclaimer below.
14*3f1979aaSAndroid Build Coastguard Worker 
15*3f1979aaSAndroid Build Coastguard Worker    - Redistributions in binary form must reproduce the above copyright
16*3f1979aaSAndroid Build Coastguard Worker    notice, this list of conditions, and the disclaimer below in the
17*3f1979aaSAndroid Build Coastguard Worker    documentation and/or other materials provided with the
18*3f1979aaSAndroid Build Coastguard Worker    distribution.
19*3f1979aaSAndroid Build Coastguard Worker 
20*3f1979aaSAndroid Build Coastguard Worker    THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21*3f1979aaSAndroid Build Coastguard Worker    EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE WARRANTIES OF
22*3f1979aaSAndroid Build Coastguard Worker    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23*3f1979aaSAndroid Build Coastguard Worker    NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT
24*3f1979aaSAndroid Build Coastguard Worker    HOLDERS BE LIABLE FOR ANY CLAIM, INDIRECT, INCIDENTAL, SPECIAL,
25*3f1979aaSAndroid Build Coastguard Worker    EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY, WHETHER IN AN
26*3f1979aaSAndroid Build Coastguard Worker    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27*3f1979aaSAndroid Build Coastguard Worker    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
28*3f1979aaSAndroid Build Coastguard Worker    SOFTWARE.
29*3f1979aaSAndroid Build Coastguard Worker */
30*3f1979aaSAndroid Build Coastguard Worker 
31*3f1979aaSAndroid Build Coastguard Worker #pragma once
32*3f1979aaSAndroid Build Coastguard Worker 
33*3f1979aaSAndroid Build Coastguard Worker #include <complex>
34*3f1979aaSAndroid Build Coastguard Worker #include <vector>
35*3f1979aaSAndroid Build Coastguard Worker #include <limits>
36*3f1979aaSAndroid Build Coastguard Worker 
37*3f1979aaSAndroid Build Coastguard Worker namespace {
38*3f1979aaSAndroid Build Coastguard Worker #if defined(PFFFT_ENABLE_FLOAT) || ( !defined(PFFFT_ENABLE_FLOAT) && !defined(PFFFT_ENABLE_DOUBLE) )
39*3f1979aaSAndroid Build Coastguard Worker #include "pffft.h"
40*3f1979aaSAndroid Build Coastguard Worker #endif
41*3f1979aaSAndroid Build Coastguard Worker #if defined(PFFFT_ENABLE_DOUBLE)
42*3f1979aaSAndroid Build Coastguard Worker #include "pffft_double.h"
43*3f1979aaSAndroid Build Coastguard Worker #endif
44*3f1979aaSAndroid Build Coastguard Worker }
45*3f1979aaSAndroid Build Coastguard Worker 
46*3f1979aaSAndroid Build Coastguard Worker namespace pffft {
47*3f1979aaSAndroid Build Coastguard Worker 
48*3f1979aaSAndroid Build Coastguard Worker // enum { PFFFT_REAL, PFFFT_COMPLEX }
49*3f1979aaSAndroid Build Coastguard Worker typedef pffft_transform_t TransformType;
50*3f1979aaSAndroid Build Coastguard Worker 
51*3f1979aaSAndroid Build Coastguard Worker // define 'Scalar' and 'Complex' (in namespace pffft) with template Types<>
52*3f1979aaSAndroid Build Coastguard Worker // and other type specific helper functions
53*3f1979aaSAndroid Build Coastguard Worker template<typename T> struct Types {};
54*3f1979aaSAndroid Build Coastguard Worker #if defined(PFFFT_ENABLE_FLOAT) || ( !defined(PFFFT_ENABLE_FLOAT) && !defined(PFFFT_ENABLE_DOUBLE) )
55*3f1979aaSAndroid Build Coastguard Worker template<> struct Types<float>  {
56*3f1979aaSAndroid Build Coastguard Worker   typedef float  Scalar;
57*3f1979aaSAndroid Build Coastguard Worker   typedef std::complex<Scalar> Complex;
simd_sizepffft::Types58*3f1979aaSAndroid Build Coastguard Worker   static int simd_size() { return pffft_simd_size(); }
simd_archpffft::Types59*3f1979aaSAndroid Build Coastguard Worker   static const char * simd_arch() { return pffft_simd_arch(); }
60*3f1979aaSAndroid Build Coastguard Worker };
61*3f1979aaSAndroid Build Coastguard Worker template<> struct Types< std::complex<float> >  {
62*3f1979aaSAndroid Build Coastguard Worker   typedef float  Scalar;
63*3f1979aaSAndroid Build Coastguard Worker   typedef std::complex<float>  Complex;
simd_sizepffft::Types64*3f1979aaSAndroid Build Coastguard Worker   static int simd_size() { return pffft_simd_size(); }
simd_archpffft::Types65*3f1979aaSAndroid Build Coastguard Worker   static const char * simd_arch() { return pffft_simd_arch(); }
66*3f1979aaSAndroid Build Coastguard Worker };
67*3f1979aaSAndroid Build Coastguard Worker #endif
68*3f1979aaSAndroid Build Coastguard Worker #if defined(PFFFT_ENABLE_DOUBLE)
69*3f1979aaSAndroid Build Coastguard Worker template<> struct Types<double> {
70*3f1979aaSAndroid Build Coastguard Worker   typedef double Scalar;
71*3f1979aaSAndroid Build Coastguard Worker   typedef std::complex<Scalar> Complex;
simd_sizepffft::Types72*3f1979aaSAndroid Build Coastguard Worker   static int simd_size() { return pffftd_simd_size(); }
simd_archpffft::Types73*3f1979aaSAndroid Build Coastguard Worker   static const char * simd_arch() { return pffftd_simd_arch(); }
74*3f1979aaSAndroid Build Coastguard Worker };
75*3f1979aaSAndroid Build Coastguard Worker template<> struct Types< std::complex<double> > {
76*3f1979aaSAndroid Build Coastguard Worker   typedef double Scalar;
77*3f1979aaSAndroid Build Coastguard Worker   typedef std::complex<double> Complex;
simd_sizepffft::Types78*3f1979aaSAndroid Build Coastguard Worker   static int simd_size() { return pffftd_simd_size(); }
simd_archpffft::Types79*3f1979aaSAndroid Build Coastguard Worker   static const char * simd_arch() { return pffftd_simd_arch(); }
80*3f1979aaSAndroid Build Coastguard Worker };
81*3f1979aaSAndroid Build Coastguard Worker #endif
82*3f1979aaSAndroid Build Coastguard Worker 
83*3f1979aaSAndroid Build Coastguard Worker // Allocator
84*3f1979aaSAndroid Build Coastguard Worker template<typename T> class PFAlloc;
85*3f1979aaSAndroid Build Coastguard Worker 
86*3f1979aaSAndroid Build Coastguard Worker namespace {
87*3f1979aaSAndroid Build Coastguard Worker   template<typename T> class Setup;
88*3f1979aaSAndroid Build Coastguard Worker }
89*3f1979aaSAndroid Build Coastguard Worker 
90*3f1979aaSAndroid Build Coastguard Worker #if (__cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900))
91*3f1979aaSAndroid Build Coastguard Worker 
92*3f1979aaSAndroid Build Coastguard Worker // define AlignedVector<T> utilizing 'using' in C++11
93*3f1979aaSAndroid Build Coastguard Worker template<typename T>
94*3f1979aaSAndroid Build Coastguard Worker using AlignedVector = typename std::vector< T, PFAlloc<T> >;
95*3f1979aaSAndroid Build Coastguard Worker 
96*3f1979aaSAndroid Build Coastguard Worker #else
97*3f1979aaSAndroid Build Coastguard Worker 
98*3f1979aaSAndroid Build Coastguard Worker // define AlignedVector<T> having to derive std::vector<>
99*3f1979aaSAndroid Build Coastguard Worker template <typename T>
100*3f1979aaSAndroid Build Coastguard Worker struct AlignedVector : public std::vector< T, PFAlloc<T> > {
AlignedVectorpffft::AlignedVector101*3f1979aaSAndroid Build Coastguard Worker   AlignedVector() : std::vector< T, PFAlloc<T> >() { }
AlignedVectorpffft::AlignedVector102*3f1979aaSAndroid Build Coastguard Worker   AlignedVector(int N) : std::vector< T, PFAlloc<T> >(N) { }
103*3f1979aaSAndroid Build Coastguard Worker };
104*3f1979aaSAndroid Build Coastguard Worker 
105*3f1979aaSAndroid Build Coastguard Worker #endif
106*3f1979aaSAndroid Build Coastguard Worker 
107*3f1979aaSAndroid Build Coastguard Worker 
108*3f1979aaSAndroid Build Coastguard Worker // T can be float, double, std::complex<float> or std::complex<double>
109*3f1979aaSAndroid Build Coastguard Worker //   define PFFFT_ENABLE_DOUBLE before include this file for double and std::complex<double>
110*3f1979aaSAndroid Build Coastguard Worker template<typename T>
111*3f1979aaSAndroid Build Coastguard Worker class Fft
112*3f1979aaSAndroid Build Coastguard Worker {
113*3f1979aaSAndroid Build Coastguard Worker public:
114*3f1979aaSAndroid Build Coastguard Worker 
115*3f1979aaSAndroid Build Coastguard Worker   // define types value_type, Scalar and Complex
116*3f1979aaSAndroid Build Coastguard Worker   typedef T value_type;
117*3f1979aaSAndroid Build Coastguard Worker   typedef typename Types<T>::Scalar  Scalar;
118*3f1979aaSAndroid Build Coastguard Worker   typedef typename Types<T>::Complex Complex;
119*3f1979aaSAndroid Build Coastguard Worker 
120*3f1979aaSAndroid Build Coastguard Worker   // static retrospection functions
isComplexTransform()121*3f1979aaSAndroid Build Coastguard Worker   static bool isComplexTransform()  { return sizeof(T) == sizeof(Complex); }
isFloatScalar()122*3f1979aaSAndroid Build Coastguard Worker   static bool isFloatScalar()  { return sizeof(Scalar) == sizeof(float); }
isDoubleScalar()123*3f1979aaSAndroid Build Coastguard Worker   static bool isDoubleScalar() { return sizeof(Scalar) == sizeof(double); }
124*3f1979aaSAndroid Build Coastguard Worker 
125*3f1979aaSAndroid Build Coastguard Worker   // simple helper to get minimum possible fft length
minFFtsize()126*3f1979aaSAndroid Build Coastguard Worker   static int minFFtsize() { return pffft_min_fft_size( isComplexTransform() ? PFFFT_COMPLEX : PFFFT_REAL ); }
127*3f1979aaSAndroid Build Coastguard Worker 
128*3f1979aaSAndroid Build Coastguard Worker   // simple helper to determine next power of 2 - without inexact/rounding floating point operations
nextPowerOfTwo(int N)129*3f1979aaSAndroid Build Coastguard Worker   static int nextPowerOfTwo(int N) { return pffft_next_power_of_two(N); }
isPowerOfTwo(int N)130*3f1979aaSAndroid Build Coastguard Worker   static bool isPowerOfTwo(int N) { return pffft_is_power_of_two(N) ? true : false; }
131*3f1979aaSAndroid Build Coastguard Worker 
simd_size()132*3f1979aaSAndroid Build Coastguard Worker   static int simd_size() { return Types<T>::simd_size(); }
simd_arch()133*3f1979aaSAndroid Build Coastguard Worker   static const char * simd_arch() { return Types<T>::simd_arch(); }
134*3f1979aaSAndroid Build Coastguard Worker 
135*3f1979aaSAndroid Build Coastguard Worker   //////////////////
136*3f1979aaSAndroid Build Coastguard Worker 
137*3f1979aaSAndroid Build Coastguard Worker   /*
138*3f1979aaSAndroid Build Coastguard Worker    * Contructor, with transformation length, preparing transforms.
139*3f1979aaSAndroid Build Coastguard Worker    *
140*3f1979aaSAndroid Build Coastguard Worker    * For length <= stackThresholdLen, the stack is used for the internal
141*3f1979aaSAndroid Build Coastguard Worker    * work memory. for bigger length', the heap is used.
142*3f1979aaSAndroid Build Coastguard Worker    *
143*3f1979aaSAndroid Build Coastguard Worker    * Using the stack is probably the best strategy for small
144*3f1979aaSAndroid Build Coastguard Worker    * FFTs, say for N <= 4096). Threads usually have a small stack, that
145*3f1979aaSAndroid Build Coastguard Worker    * there's no sufficient amount of memory, usually leading to a crash!
146*3f1979aaSAndroid Build Coastguard Worker    */
147*3f1979aaSAndroid Build Coastguard Worker   Fft( int length, int stackThresholdLen = 4096 );
148*3f1979aaSAndroid Build Coastguard Worker 
149*3f1979aaSAndroid Build Coastguard Worker   ~Fft();
150*3f1979aaSAndroid Build Coastguard Worker 
151*3f1979aaSAndroid Build Coastguard Worker   /*
152*3f1979aaSAndroid Build Coastguard Worker    * prepare for transformation length 'newLength'.
153*3f1979aaSAndroid Build Coastguard Worker    * length is identical to forward()'s input vector's size,
154*3f1979aaSAndroid Build Coastguard Worker    * and also equals inverse()'s output vector size.
155*3f1979aaSAndroid Build Coastguard Worker    * this function is no simple setter. it pre-calculates twiddle factors.
156*3f1979aaSAndroid Build Coastguard Worker    */
157*3f1979aaSAndroid Build Coastguard Worker   void prepareLength(int newLength);
158*3f1979aaSAndroid Build Coastguard Worker 
159*3f1979aaSAndroid Build Coastguard Worker   /*
160*3f1979aaSAndroid Build Coastguard Worker    * retrieve the transformation length.
161*3f1979aaSAndroid Build Coastguard Worker    */
getLength() const162*3f1979aaSAndroid Build Coastguard Worker   int getLength() const { return length; }
163*3f1979aaSAndroid Build Coastguard Worker 
164*3f1979aaSAndroid Build Coastguard Worker   /*
165*3f1979aaSAndroid Build Coastguard Worker    * retrieve size of complex spectrum vector,
166*3f1979aaSAndroid Build Coastguard Worker    * the output of forward()
167*3f1979aaSAndroid Build Coastguard Worker    */
getSpectrumSize() const168*3f1979aaSAndroid Build Coastguard Worker   int getSpectrumSize() const { return isComplexTransform() ? length : ( length / 2 ); }
169*3f1979aaSAndroid Build Coastguard Worker 
170*3f1979aaSAndroid Build Coastguard Worker   /*
171*3f1979aaSAndroid Build Coastguard Worker    * retrieve size of spectrum vector - in internal layout;
172*3f1979aaSAndroid Build Coastguard Worker    * the output of forwardToInternalLayout()
173*3f1979aaSAndroid Build Coastguard Worker    */
getInternalLayoutSize() const174*3f1979aaSAndroid Build Coastguard Worker   int getInternalLayoutSize() const { return isComplexTransform() ? ( 2 * length ) : length; }
175*3f1979aaSAndroid Build Coastguard Worker 
176*3f1979aaSAndroid Build Coastguard Worker 
177*3f1979aaSAndroid Build Coastguard Worker   ////////////////////////////////////////////
178*3f1979aaSAndroid Build Coastguard Worker   ////
179*3f1979aaSAndroid Build Coastguard Worker   //// API 1, with std::vector<> based containers,
180*3f1979aaSAndroid Build Coastguard Worker   ////   which free the allocated memory themselves (RAII).
181*3f1979aaSAndroid Build Coastguard Worker   ////
182*3f1979aaSAndroid Build Coastguard Worker   //// uses an Allocator for the alignment of SIMD data.
183*3f1979aaSAndroid Build Coastguard Worker   ////
184*3f1979aaSAndroid Build Coastguard Worker   ////////////////////////////////////////////
185*3f1979aaSAndroid Build Coastguard Worker 
186*3f1979aaSAndroid Build Coastguard Worker   // create suitably preallocated aligned vector for one FFT
187*3f1979aaSAndroid Build Coastguard Worker   AlignedVector<T>       valueVector() const;
188*3f1979aaSAndroid Build Coastguard Worker   AlignedVector<Complex> spectrumVector() const;
189*3f1979aaSAndroid Build Coastguard Worker   AlignedVector<Scalar>  internalLayoutVector() const;
190*3f1979aaSAndroid Build Coastguard Worker 
191*3f1979aaSAndroid Build Coastguard Worker   ////////////////////////////////////////////
192*3f1979aaSAndroid Build Coastguard Worker   // although using Vectors for output ..
193*3f1979aaSAndroid Build Coastguard Worker   // they need to have resize() applied before!
194*3f1979aaSAndroid Build Coastguard Worker 
195*3f1979aaSAndroid Build Coastguard Worker   // core API, having the spectrum in canonical order
196*3f1979aaSAndroid Build Coastguard Worker 
197*3f1979aaSAndroid Build Coastguard Worker   /*
198*3f1979aaSAndroid Build Coastguard Worker    * Perform the forward Fourier transform.
199*3f1979aaSAndroid Build Coastguard Worker    *
200*3f1979aaSAndroid Build Coastguard Worker    * Transforms are not scaled: inverse(forward(x)) = N*x.
201*3f1979aaSAndroid Build Coastguard Worker    * Typically you will want to scale the backward transform by 1/N.
202*3f1979aaSAndroid Build Coastguard Worker    *
203*3f1979aaSAndroid Build Coastguard Worker    * The output 'spectrum' is canonically ordered - as expected.
204*3f1979aaSAndroid Build Coastguard Worker    *
205*3f1979aaSAndroid Build Coastguard Worker    * a) for complex input isComplexTransform() == true,
206*3f1979aaSAndroid Build Coastguard Worker    *    and transformation length N  the output array is complex:
207*3f1979aaSAndroid Build Coastguard Worker    *   index k in 0 .. N/2 -1  corresponds to frequency k * Samplerate / N
208*3f1979aaSAndroid Build Coastguard Worker    *   index k in N/2 .. N -1  corresponds to frequency (k -N) * Samplerate / N,
209*3f1979aaSAndroid Build Coastguard Worker    *     resulting in negative frequencies
210*3f1979aaSAndroid Build Coastguard Worker    *
211*3f1979aaSAndroid Build Coastguard Worker    * b) for real input isComplexTransform() == false,
212*3f1979aaSAndroid Build Coastguard Worker    *    and transformation length N  the output array is 'mostly' complex:
213*3f1979aaSAndroid Build Coastguard Worker    *   index k in 1 .. N/2 -1  corresponds to frequency k * Samplerate / N
214*3f1979aaSAndroid Build Coastguard Worker    *   index k == 0 is a special case:
215*3f1979aaSAndroid Build Coastguard Worker    *     the real() part contains the result for the DC frequency 0,
216*3f1979aaSAndroid Build Coastguard Worker    *     the imag() part contains the result for the Nyquist frequency Samplerate/2
217*3f1979aaSAndroid Build Coastguard Worker    *   both 0-frequency and half frequency components, which are real,
218*3f1979aaSAndroid Build Coastguard Worker    *   are assembled in the first entry as  F(0)+i*F(N/2).
219*3f1979aaSAndroid Build Coastguard Worker    *
220*3f1979aaSAndroid Build Coastguard Worker    * input and output may alias - if you do nasty type conversion.
221*3f1979aaSAndroid Build Coastguard Worker    * return is just the given output parameter 'spectrum'.
222*3f1979aaSAndroid Build Coastguard Worker    */
223*3f1979aaSAndroid Build Coastguard Worker   AlignedVector<Complex> & forward(const AlignedVector<T> & input, AlignedVector<Complex> & spectrum);
224*3f1979aaSAndroid Build Coastguard Worker 
225*3f1979aaSAndroid Build Coastguard Worker   /*
226*3f1979aaSAndroid Build Coastguard Worker    * Perform the inverse Fourier transform, see forward().
227*3f1979aaSAndroid Build Coastguard Worker    * return is just the given output parameter 'output'.
228*3f1979aaSAndroid Build Coastguard Worker    */
229*3f1979aaSAndroid Build Coastguard Worker   AlignedVector<T> & inverse(const AlignedVector<Complex> & spectrum, AlignedVector<T> & output);
230*3f1979aaSAndroid Build Coastguard Worker 
231*3f1979aaSAndroid Build Coastguard Worker 
232*3f1979aaSAndroid Build Coastguard Worker   // provide additional functions with spectrum in some internal Layout.
233*3f1979aaSAndroid Build Coastguard Worker   // these are faster, cause the implementation omits the reordering.
234*3f1979aaSAndroid Build Coastguard Worker   // these are useful in special applications, like fast convolution,
235*3f1979aaSAndroid Build Coastguard Worker   // where inverse() is following anyway ..
236*3f1979aaSAndroid Build Coastguard Worker 
237*3f1979aaSAndroid Build Coastguard Worker   /*
238*3f1979aaSAndroid Build Coastguard Worker    * Perform the forward Fourier transform - similar to forward(), BUT:
239*3f1979aaSAndroid Build Coastguard Worker    *
240*3f1979aaSAndroid Build Coastguard Worker    * The z-domain data is stored in the most efficient order
241*3f1979aaSAndroid Build Coastguard Worker    * for transforming it back, or using it for convolution.
242*3f1979aaSAndroid Build Coastguard Worker    * If you need to have its content sorted in the "usual" canonical order,
243*3f1979aaSAndroid Build Coastguard Worker    * either use forward(), or call reorderSpectrum() after calling
244*3f1979aaSAndroid Build Coastguard Worker    * forwardToInternalLayout(), and before the backward fft
245*3f1979aaSAndroid Build Coastguard Worker    *
246*3f1979aaSAndroid Build Coastguard Worker    * return is just the given output parameter 'spectrum_internal_layout'.
247*3f1979aaSAndroid Build Coastguard Worker    */
248*3f1979aaSAndroid Build Coastguard Worker   AlignedVector<Scalar> & forwardToInternalLayout(
249*3f1979aaSAndroid Build Coastguard Worker           const AlignedVector<T> & input,
250*3f1979aaSAndroid Build Coastguard Worker           AlignedVector<Scalar> & spectrum_internal_layout );
251*3f1979aaSAndroid Build Coastguard Worker 
252*3f1979aaSAndroid Build Coastguard Worker   /*
253*3f1979aaSAndroid Build Coastguard Worker    * Perform the inverse Fourier transform, see forwardToInternalLayout()
254*3f1979aaSAndroid Build Coastguard Worker    *
255*3f1979aaSAndroid Build Coastguard Worker    * return is just the given output parameter 'output'.
256*3f1979aaSAndroid Build Coastguard Worker    */
257*3f1979aaSAndroid Build Coastguard Worker   AlignedVector<T> & inverseFromInternalLayout(
258*3f1979aaSAndroid Build Coastguard Worker           const AlignedVector<Scalar> & spectrum_internal_layout,
259*3f1979aaSAndroid Build Coastguard Worker           AlignedVector<T> & output );
260*3f1979aaSAndroid Build Coastguard Worker 
261*3f1979aaSAndroid Build Coastguard Worker   /*
262*3f1979aaSAndroid Build Coastguard Worker    * Reorder the spectrum from internal layout to have the
263*3f1979aaSAndroid Build Coastguard Worker    * frequency components in the correct "canonical" order.
264*3f1979aaSAndroid Build Coastguard Worker    * see forward() for a description of the canonical order.
265*3f1979aaSAndroid Build Coastguard Worker    *
266*3f1979aaSAndroid Build Coastguard Worker    * input and output should not alias.
267*3f1979aaSAndroid Build Coastguard Worker    */
268*3f1979aaSAndroid Build Coastguard Worker   void reorderSpectrum(
269*3f1979aaSAndroid Build Coastguard Worker           const AlignedVector<Scalar> & input,
270*3f1979aaSAndroid Build Coastguard Worker           AlignedVector<Complex> & output );
271*3f1979aaSAndroid Build Coastguard Worker 
272*3f1979aaSAndroid Build Coastguard Worker   /*
273*3f1979aaSAndroid Build Coastguard Worker    * Perform a multiplication of the frequency components of
274*3f1979aaSAndroid Build Coastguard Worker    * spectrum_internal_a and spectrum_internal_b
275*3f1979aaSAndroid Build Coastguard Worker    * into spectrum_internal_ab.
276*3f1979aaSAndroid Build Coastguard Worker    * The arrays should have been obtained with forwardToInternalLayout)
277*3f1979aaSAndroid Build Coastguard Worker    * and should *not* have been reordered with reorderSpectrum().
278*3f1979aaSAndroid Build Coastguard Worker    *
279*3f1979aaSAndroid Build Coastguard Worker    * the operation performed is:
280*3f1979aaSAndroid Build Coastguard Worker    *  spectrum_internal_ab = (spectrum_internal_a * spectrum_internal_b)*scaling
281*3f1979aaSAndroid Build Coastguard Worker    *
282*3f1979aaSAndroid Build Coastguard Worker    * The spectrum_internal_[a][b], pointers may alias.
283*3f1979aaSAndroid Build Coastguard Worker    * return is just the given output parameter 'spectrum_internal_ab'.
284*3f1979aaSAndroid Build Coastguard Worker    */
285*3f1979aaSAndroid Build Coastguard Worker   AlignedVector<Scalar> & convolve(
286*3f1979aaSAndroid Build Coastguard Worker           const AlignedVector<Scalar> & spectrum_internal_a,
287*3f1979aaSAndroid Build Coastguard Worker           const AlignedVector<Scalar> & spectrum_internal_b,
288*3f1979aaSAndroid Build Coastguard Worker           AlignedVector<Scalar> & spectrum_internal_ab,
289*3f1979aaSAndroid Build Coastguard Worker           const Scalar scaling );
290*3f1979aaSAndroid Build Coastguard Worker 
291*3f1979aaSAndroid Build Coastguard Worker   /*
292*3f1979aaSAndroid Build Coastguard Worker    * Perform a multiplication and accumulation of the frequency components
293*3f1979aaSAndroid Build Coastguard Worker    * - similar to convolve().
294*3f1979aaSAndroid Build Coastguard Worker    *
295*3f1979aaSAndroid Build Coastguard Worker    * the operation performed is:
296*3f1979aaSAndroid Build Coastguard Worker    *  spectrum_internal_ab += (spectrum_internal_a * spectrum_internal_b)*scaling
297*3f1979aaSAndroid Build Coastguard Worker    *
298*3f1979aaSAndroid Build Coastguard Worker    * The spectrum_internal_[a][b], pointers may alias.
299*3f1979aaSAndroid Build Coastguard Worker    * return is just the given output parameter 'spectrum_internal_ab'.
300*3f1979aaSAndroid Build Coastguard Worker    */
301*3f1979aaSAndroid Build Coastguard Worker   AlignedVector<Scalar> & convolveAccumulate(
302*3f1979aaSAndroid Build Coastguard Worker           const AlignedVector<Scalar> & spectrum_internal_a,
303*3f1979aaSAndroid Build Coastguard Worker           const AlignedVector<Scalar> & spectrum_internal_b,
304*3f1979aaSAndroid Build Coastguard Worker           AlignedVector<Scalar> & spectrum_internal_ab,
305*3f1979aaSAndroid Build Coastguard Worker           const Scalar scaling );
306*3f1979aaSAndroid Build Coastguard Worker 
307*3f1979aaSAndroid Build Coastguard Worker 
308*3f1979aaSAndroid Build Coastguard Worker   ////////////////////////////////////////////
309*3f1979aaSAndroid Build Coastguard Worker   ////
310*3f1979aaSAndroid Build Coastguard Worker   //// API 2, dealing with raw pointers,
311*3f1979aaSAndroid Build Coastguard Worker   //// which need to be deallocated using alignedFree()
312*3f1979aaSAndroid Build Coastguard Worker   ////
313*3f1979aaSAndroid Build Coastguard Worker   //// the special allocation is required cause SIMD
314*3f1979aaSAndroid Build Coastguard Worker   //// implementations require aligned memory
315*3f1979aaSAndroid Build Coastguard Worker   ////
316*3f1979aaSAndroid Build Coastguard Worker   //// Method descriptions are equal to the methods above,
317*3f1979aaSAndroid Build Coastguard Worker   //// having  AlignedVector<T> parameters - instead of raw pointers.
318*3f1979aaSAndroid Build Coastguard Worker   //// That is why following methods have no documentation.
319*3f1979aaSAndroid Build Coastguard Worker   ////
320*3f1979aaSAndroid Build Coastguard Worker   ////////////////////////////////////////////
321*3f1979aaSAndroid Build Coastguard Worker 
322*3f1979aaSAndroid Build Coastguard Worker   static void alignedFree(void* ptr);
323*3f1979aaSAndroid Build Coastguard Worker 
324*3f1979aaSAndroid Build Coastguard Worker   static T * alignedAllocType(int length);
325*3f1979aaSAndroid Build Coastguard Worker   static Scalar* alignedAllocScalar(int length);
326*3f1979aaSAndroid Build Coastguard Worker   static Complex* alignedAllocComplex(int length);
327*3f1979aaSAndroid Build Coastguard Worker 
328*3f1979aaSAndroid Build Coastguard Worker   // core API, having the spectrum in canonical order
329*3f1979aaSAndroid Build Coastguard Worker 
330*3f1979aaSAndroid Build Coastguard Worker   Complex* forward(const T* input, Complex* spectrum);
331*3f1979aaSAndroid Build Coastguard Worker 
332*3f1979aaSAndroid Build Coastguard Worker   T* inverse(const Complex* spectrum, T* output);
333*3f1979aaSAndroid Build Coastguard Worker 
334*3f1979aaSAndroid Build Coastguard Worker 
335*3f1979aaSAndroid Build Coastguard Worker   // provide additional functions with spectrum in some internal Layout.
336*3f1979aaSAndroid Build Coastguard Worker   // these are faster, cause the implementation omits the reordering.
337*3f1979aaSAndroid Build Coastguard Worker   // these are useful in special applications, like fast convolution,
338*3f1979aaSAndroid Build Coastguard Worker   // where inverse() is following anyway ..
339*3f1979aaSAndroid Build Coastguard Worker 
340*3f1979aaSAndroid Build Coastguard Worker   Scalar* forwardToInternalLayout(const T* input,
341*3f1979aaSAndroid Build Coastguard Worker                                 Scalar* spectrum_internal_layout);
342*3f1979aaSAndroid Build Coastguard Worker 
343*3f1979aaSAndroid Build Coastguard Worker   T* inverseFromInternalLayout(const Scalar* spectrum_internal_layout, T* output);
344*3f1979aaSAndroid Build Coastguard Worker 
345*3f1979aaSAndroid Build Coastguard Worker   void reorderSpectrum(const Scalar* input, Complex* output );
346*3f1979aaSAndroid Build Coastguard Worker 
347*3f1979aaSAndroid Build Coastguard Worker   Scalar* convolve(const Scalar* spectrum_internal_a,
348*3f1979aaSAndroid Build Coastguard Worker                    const Scalar* spectrum_internal_b,
349*3f1979aaSAndroid Build Coastguard Worker                    Scalar* spectrum_internal_ab,
350*3f1979aaSAndroid Build Coastguard Worker                    const Scalar scaling);
351*3f1979aaSAndroid Build Coastguard Worker 
352*3f1979aaSAndroid Build Coastguard Worker   Scalar* convolveAccumulate(const Scalar* spectrum_internal_a,
353*3f1979aaSAndroid Build Coastguard Worker                              const Scalar* spectrum_internal_b,
354*3f1979aaSAndroid Build Coastguard Worker                              Scalar* spectrum_internal_ab,
355*3f1979aaSAndroid Build Coastguard Worker                              const Scalar scaling);
356*3f1979aaSAndroid Build Coastguard Worker 
357*3f1979aaSAndroid Build Coastguard Worker private:
358*3f1979aaSAndroid Build Coastguard Worker   Setup<T> setup;
359*3f1979aaSAndroid Build Coastguard Worker   Scalar* work;
360*3f1979aaSAndroid Build Coastguard Worker   int length;
361*3f1979aaSAndroid Build Coastguard Worker   int stackThresholdLen;
362*3f1979aaSAndroid Build Coastguard Worker };
363*3f1979aaSAndroid Build Coastguard Worker 
364*3f1979aaSAndroid Build Coastguard Worker 
365*3f1979aaSAndroid Build Coastguard Worker template<typename T>
alignedAlloc(int length)366*3f1979aaSAndroid Build Coastguard Worker inline T* alignedAlloc(int length) {
367*3f1979aaSAndroid Build Coastguard Worker   return (T*)pffft_aligned_malloc( length * sizeof(T) );
368*3f1979aaSAndroid Build Coastguard Worker }
369*3f1979aaSAndroid Build Coastguard Worker 
alignedFree(void * ptr)370*3f1979aaSAndroid Build Coastguard Worker inline void alignedFree(void *ptr) {
371*3f1979aaSAndroid Build Coastguard Worker   pffft_aligned_free(ptr);
372*3f1979aaSAndroid Build Coastguard Worker }
373*3f1979aaSAndroid Build Coastguard Worker 
374*3f1979aaSAndroid Build Coastguard Worker 
375*3f1979aaSAndroid Build Coastguard Worker // simple helper to get minimum possible fft length
minFFtsize(pffft_transform_t transform)376*3f1979aaSAndroid Build Coastguard Worker inline int minFFtsize(pffft_transform_t transform) {
377*3f1979aaSAndroid Build Coastguard Worker   return pffft_min_fft_size(transform);
378*3f1979aaSAndroid Build Coastguard Worker }
379*3f1979aaSAndroid Build Coastguard Worker 
380*3f1979aaSAndroid Build Coastguard Worker // simple helper to determine next power of 2 - without inexact/rounding floating point operations
nextPowerOfTwo(int N)381*3f1979aaSAndroid Build Coastguard Worker inline int nextPowerOfTwo(int N) {
382*3f1979aaSAndroid Build Coastguard Worker   return pffft_next_power_of_two(N);
383*3f1979aaSAndroid Build Coastguard Worker }
384*3f1979aaSAndroid Build Coastguard Worker 
isPowerOfTwo(int N)385*3f1979aaSAndroid Build Coastguard Worker inline bool isPowerOfTwo(int N) {
386*3f1979aaSAndroid Build Coastguard Worker   return pffft_is_power_of_two(N) ? true : false;
387*3f1979aaSAndroid Build Coastguard Worker }
388*3f1979aaSAndroid Build Coastguard Worker 
389*3f1979aaSAndroid Build Coastguard Worker 
390*3f1979aaSAndroid Build Coastguard Worker 
391*3f1979aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////
392*3f1979aaSAndroid Build Coastguard Worker 
393*3f1979aaSAndroid Build Coastguard Worker // implementation
394*3f1979aaSAndroid Build Coastguard Worker 
395*3f1979aaSAndroid Build Coastguard Worker namespace {
396*3f1979aaSAndroid Build Coastguard Worker 
397*3f1979aaSAndroid Build Coastguard Worker template<typename T>
398*3f1979aaSAndroid Build Coastguard Worker class Setup
399*3f1979aaSAndroid Build Coastguard Worker {};
400*3f1979aaSAndroid Build Coastguard Worker 
401*3f1979aaSAndroid Build Coastguard Worker #if defined(PFFFT_ENABLE_FLOAT) || ( !defined(PFFFT_ENABLE_FLOAT) && !defined(PFFFT_ENABLE_DOUBLE) )
402*3f1979aaSAndroid Build Coastguard Worker 
403*3f1979aaSAndroid Build Coastguard Worker template<>
404*3f1979aaSAndroid Build Coastguard Worker class Setup<float>
405*3f1979aaSAndroid Build Coastguard Worker {
406*3f1979aaSAndroid Build Coastguard Worker   PFFFT_Setup* self;
407*3f1979aaSAndroid Build Coastguard Worker 
408*3f1979aaSAndroid Build Coastguard Worker public:
409*3f1979aaSAndroid Build Coastguard Worker   typedef float value_type;
410*3f1979aaSAndroid Build Coastguard Worker   typedef Types< value_type >::Scalar Scalar;
411*3f1979aaSAndroid Build Coastguard Worker 
Setup()412*3f1979aaSAndroid Build Coastguard Worker   Setup()
413*3f1979aaSAndroid Build Coastguard Worker     : self(NULL)
414*3f1979aaSAndroid Build Coastguard Worker   {}
415*3f1979aaSAndroid Build Coastguard Worker 
prepareLength(int length)416*3f1979aaSAndroid Build Coastguard Worker   void prepareLength(int length)
417*3f1979aaSAndroid Build Coastguard Worker   {
418*3f1979aaSAndroid Build Coastguard Worker     if (self) {
419*3f1979aaSAndroid Build Coastguard Worker       pffft_destroy_setup(self);
420*3f1979aaSAndroid Build Coastguard Worker     }
421*3f1979aaSAndroid Build Coastguard Worker     self = pffft_new_setup(length, PFFFT_REAL);
422*3f1979aaSAndroid Build Coastguard Worker   }
423*3f1979aaSAndroid Build Coastguard Worker 
~Setup()424*3f1979aaSAndroid Build Coastguard Worker   ~Setup() { pffft_destroy_setup(self); }
425*3f1979aaSAndroid Build Coastguard Worker 
transform_ordered(const Scalar * input,Scalar * output,Scalar * work,pffft_direction_t direction)426*3f1979aaSAndroid Build Coastguard Worker   void transform_ordered(const Scalar* input,
427*3f1979aaSAndroid Build Coastguard Worker                          Scalar* output,
428*3f1979aaSAndroid Build Coastguard Worker                          Scalar* work,
429*3f1979aaSAndroid Build Coastguard Worker                          pffft_direction_t direction)
430*3f1979aaSAndroid Build Coastguard Worker   {
431*3f1979aaSAndroid Build Coastguard Worker     pffft_transform_ordered(self, input, output, work, direction);
432*3f1979aaSAndroid Build Coastguard Worker   }
433*3f1979aaSAndroid Build Coastguard Worker 
transform(const Scalar * input,Scalar * output,Scalar * work,pffft_direction_t direction)434*3f1979aaSAndroid Build Coastguard Worker   void transform(const Scalar* input,
435*3f1979aaSAndroid Build Coastguard Worker                  Scalar* output,
436*3f1979aaSAndroid Build Coastguard Worker                  Scalar* work,
437*3f1979aaSAndroid Build Coastguard Worker                  pffft_direction_t direction)
438*3f1979aaSAndroid Build Coastguard Worker   {
439*3f1979aaSAndroid Build Coastguard Worker     pffft_transform(self, input, output, work, direction);
440*3f1979aaSAndroid Build Coastguard Worker   }
441*3f1979aaSAndroid Build Coastguard Worker 
reorder(const Scalar * input,Scalar * output,pffft_direction_t direction)442*3f1979aaSAndroid Build Coastguard Worker   void reorder(const Scalar* input, Scalar* output, pffft_direction_t direction)
443*3f1979aaSAndroid Build Coastguard Worker   {
444*3f1979aaSAndroid Build Coastguard Worker     pffft_zreorder(self, input, output, direction);
445*3f1979aaSAndroid Build Coastguard Worker   }
446*3f1979aaSAndroid Build Coastguard Worker 
convolveAccumulate(const Scalar * dft_a,const Scalar * dft_b,Scalar * dft_ab,const Scalar scaling)447*3f1979aaSAndroid Build Coastguard Worker   void convolveAccumulate(const Scalar* dft_a,
448*3f1979aaSAndroid Build Coastguard Worker                           const Scalar* dft_b,
449*3f1979aaSAndroid Build Coastguard Worker                           Scalar* dft_ab,
450*3f1979aaSAndroid Build Coastguard Worker                           const Scalar scaling)
451*3f1979aaSAndroid Build Coastguard Worker   {
452*3f1979aaSAndroid Build Coastguard Worker     pffft_zconvolve_accumulate(self, dft_a, dft_b, dft_ab, scaling);
453*3f1979aaSAndroid Build Coastguard Worker   }
454*3f1979aaSAndroid Build Coastguard Worker 
convolve(const Scalar * dft_a,const Scalar * dft_b,Scalar * dft_ab,const Scalar scaling)455*3f1979aaSAndroid Build Coastguard Worker   void convolve(const Scalar* dft_a,
456*3f1979aaSAndroid Build Coastguard Worker                 const Scalar* dft_b,
457*3f1979aaSAndroid Build Coastguard Worker                 Scalar* dft_ab,
458*3f1979aaSAndroid Build Coastguard Worker                 const Scalar scaling)
459*3f1979aaSAndroid Build Coastguard Worker   {
460*3f1979aaSAndroid Build Coastguard Worker     pffft_zconvolve_no_accu(self, dft_a, dft_b, dft_ab, scaling);
461*3f1979aaSAndroid Build Coastguard Worker   }
462*3f1979aaSAndroid Build Coastguard Worker };
463*3f1979aaSAndroid Build Coastguard Worker 
464*3f1979aaSAndroid Build Coastguard Worker template<>
465*3f1979aaSAndroid Build Coastguard Worker class Setup< std::complex<float> >
466*3f1979aaSAndroid Build Coastguard Worker {
467*3f1979aaSAndroid Build Coastguard Worker   PFFFT_Setup* self;
468*3f1979aaSAndroid Build Coastguard Worker 
469*3f1979aaSAndroid Build Coastguard Worker public:
470*3f1979aaSAndroid Build Coastguard Worker   typedef std::complex<float> value_type;
471*3f1979aaSAndroid Build Coastguard Worker   typedef Types< value_type >::Scalar Scalar;
472*3f1979aaSAndroid Build Coastguard Worker 
Setup()473*3f1979aaSAndroid Build Coastguard Worker   Setup()
474*3f1979aaSAndroid Build Coastguard Worker     : self(NULL)
475*3f1979aaSAndroid Build Coastguard Worker   {}
476*3f1979aaSAndroid Build Coastguard Worker 
~Setup()477*3f1979aaSAndroid Build Coastguard Worker   ~Setup() { pffft_destroy_setup(self); }
478*3f1979aaSAndroid Build Coastguard Worker 
prepareLength(int length)479*3f1979aaSAndroid Build Coastguard Worker   void prepareLength(int length)
480*3f1979aaSAndroid Build Coastguard Worker   {
481*3f1979aaSAndroid Build Coastguard Worker     if (self) {
482*3f1979aaSAndroid Build Coastguard Worker       pffft_destroy_setup(self);
483*3f1979aaSAndroid Build Coastguard Worker     }
484*3f1979aaSAndroid Build Coastguard Worker     self = pffft_new_setup(length, PFFFT_COMPLEX);
485*3f1979aaSAndroid Build Coastguard Worker   }
486*3f1979aaSAndroid Build Coastguard Worker 
transform_ordered(const Scalar * input,Scalar * output,Scalar * work,pffft_direction_t direction)487*3f1979aaSAndroid Build Coastguard Worker   void transform_ordered(const Scalar* input,
488*3f1979aaSAndroid Build Coastguard Worker                          Scalar* output,
489*3f1979aaSAndroid Build Coastguard Worker                          Scalar* work,
490*3f1979aaSAndroid Build Coastguard Worker                          pffft_direction_t direction)
491*3f1979aaSAndroid Build Coastguard Worker   {
492*3f1979aaSAndroid Build Coastguard Worker     pffft_transform_ordered(self, input, output, work, direction);
493*3f1979aaSAndroid Build Coastguard Worker   }
494*3f1979aaSAndroid Build Coastguard Worker 
transform(const Scalar * input,Scalar * output,Scalar * work,pffft_direction_t direction)495*3f1979aaSAndroid Build Coastguard Worker   void transform(const Scalar* input,
496*3f1979aaSAndroid Build Coastguard Worker                  Scalar* output,
497*3f1979aaSAndroid Build Coastguard Worker                  Scalar* work,
498*3f1979aaSAndroid Build Coastguard Worker                  pffft_direction_t direction)
499*3f1979aaSAndroid Build Coastguard Worker   {
500*3f1979aaSAndroid Build Coastguard Worker     pffft_transform(self, input, output, work, direction);
501*3f1979aaSAndroid Build Coastguard Worker   }
502*3f1979aaSAndroid Build Coastguard Worker 
reorder(const Scalar * input,Scalar * output,pffft_direction_t direction)503*3f1979aaSAndroid Build Coastguard Worker   void reorder(const Scalar* input, Scalar* output, pffft_direction_t direction)
504*3f1979aaSAndroid Build Coastguard Worker   {
505*3f1979aaSAndroid Build Coastguard Worker     pffft_zreorder(self, input, output, direction);
506*3f1979aaSAndroid Build Coastguard Worker   }
507*3f1979aaSAndroid Build Coastguard Worker 
convolve(const Scalar * dft_a,const Scalar * dft_b,Scalar * dft_ab,const Scalar scaling)508*3f1979aaSAndroid Build Coastguard Worker   void convolve(const Scalar* dft_a,
509*3f1979aaSAndroid Build Coastguard Worker                 const Scalar* dft_b,
510*3f1979aaSAndroid Build Coastguard Worker                 Scalar* dft_ab,
511*3f1979aaSAndroid Build Coastguard Worker                 const Scalar scaling)
512*3f1979aaSAndroid Build Coastguard Worker   {
513*3f1979aaSAndroid Build Coastguard Worker     pffft_zconvolve_no_accu(self, dft_a, dft_b, dft_ab, scaling);
514*3f1979aaSAndroid Build Coastguard Worker   }
515*3f1979aaSAndroid Build Coastguard Worker };
516*3f1979aaSAndroid Build Coastguard Worker 
517*3f1979aaSAndroid Build Coastguard Worker #endif /* defined(PFFFT_ENABLE_FLOAT) || ( !defined(PFFFT_ENABLE_FLOAT) && !defined(PFFFT_ENABLE_DOUBLE) ) */
518*3f1979aaSAndroid Build Coastguard Worker 
519*3f1979aaSAndroid Build Coastguard Worker 
520*3f1979aaSAndroid Build Coastguard Worker #if defined(PFFFT_ENABLE_DOUBLE)
521*3f1979aaSAndroid Build Coastguard Worker 
522*3f1979aaSAndroid Build Coastguard Worker template<>
523*3f1979aaSAndroid Build Coastguard Worker class Setup<double>
524*3f1979aaSAndroid Build Coastguard Worker {
525*3f1979aaSAndroid Build Coastguard Worker   PFFFTD_Setup* self;
526*3f1979aaSAndroid Build Coastguard Worker 
527*3f1979aaSAndroid Build Coastguard Worker public:
528*3f1979aaSAndroid Build Coastguard Worker   typedef double value_type;
529*3f1979aaSAndroid Build Coastguard Worker   typedef Types< value_type >::Scalar Scalar;
530*3f1979aaSAndroid Build Coastguard Worker 
Setup()531*3f1979aaSAndroid Build Coastguard Worker   Setup()
532*3f1979aaSAndroid Build Coastguard Worker     : self(NULL)
533*3f1979aaSAndroid Build Coastguard Worker   {}
534*3f1979aaSAndroid Build Coastguard Worker 
~Setup()535*3f1979aaSAndroid Build Coastguard Worker   ~Setup() { pffftd_destroy_setup(self); }
536*3f1979aaSAndroid Build Coastguard Worker 
prepareLength(int length)537*3f1979aaSAndroid Build Coastguard Worker   void prepareLength(int length)
538*3f1979aaSAndroid Build Coastguard Worker   {
539*3f1979aaSAndroid Build Coastguard Worker     if (self) {
540*3f1979aaSAndroid Build Coastguard Worker       pffftd_destroy_setup(self);
541*3f1979aaSAndroid Build Coastguard Worker       self = NULL;
542*3f1979aaSAndroid Build Coastguard Worker     }
543*3f1979aaSAndroid Build Coastguard Worker     if (length > 0) {
544*3f1979aaSAndroid Build Coastguard Worker       self = pffftd_new_setup(length, PFFFT_REAL);
545*3f1979aaSAndroid Build Coastguard Worker     }
546*3f1979aaSAndroid Build Coastguard Worker   }
547*3f1979aaSAndroid Build Coastguard Worker 
transform_ordered(const Scalar * input,Scalar * output,Scalar * work,pffft_direction_t direction)548*3f1979aaSAndroid Build Coastguard Worker   void transform_ordered(const Scalar* input,
549*3f1979aaSAndroid Build Coastguard Worker                          Scalar* output,
550*3f1979aaSAndroid Build Coastguard Worker                          Scalar* work,
551*3f1979aaSAndroid Build Coastguard Worker                          pffft_direction_t direction)
552*3f1979aaSAndroid Build Coastguard Worker   {
553*3f1979aaSAndroid Build Coastguard Worker     pffftd_transform_ordered(self, input, output, work, direction);
554*3f1979aaSAndroid Build Coastguard Worker   }
555*3f1979aaSAndroid Build Coastguard Worker 
transform(const Scalar * input,Scalar * output,Scalar * work,pffft_direction_t direction)556*3f1979aaSAndroid Build Coastguard Worker   void transform(const Scalar* input,
557*3f1979aaSAndroid Build Coastguard Worker                  Scalar* output,
558*3f1979aaSAndroid Build Coastguard Worker                  Scalar* work,
559*3f1979aaSAndroid Build Coastguard Worker                  pffft_direction_t direction)
560*3f1979aaSAndroid Build Coastguard Worker   {
561*3f1979aaSAndroid Build Coastguard Worker     pffftd_transform(self, input, output, work, direction);
562*3f1979aaSAndroid Build Coastguard Worker   }
563*3f1979aaSAndroid Build Coastguard Worker 
reorder(const Scalar * input,Scalar * output,pffft_direction_t direction)564*3f1979aaSAndroid Build Coastguard Worker   void reorder(const Scalar* input, Scalar* output, pffft_direction_t direction)
565*3f1979aaSAndroid Build Coastguard Worker   {
566*3f1979aaSAndroid Build Coastguard Worker     pffftd_zreorder(self, input, output, direction);
567*3f1979aaSAndroid Build Coastguard Worker   }
568*3f1979aaSAndroid Build Coastguard Worker 
convolveAccumulate(const Scalar * dft_a,const Scalar * dft_b,Scalar * dft_ab,const Scalar scaling)569*3f1979aaSAndroid Build Coastguard Worker   void convolveAccumulate(const Scalar* dft_a,
570*3f1979aaSAndroid Build Coastguard Worker                           const Scalar* dft_b,
571*3f1979aaSAndroid Build Coastguard Worker                           Scalar* dft_ab,
572*3f1979aaSAndroid Build Coastguard Worker                           const Scalar scaling)
573*3f1979aaSAndroid Build Coastguard Worker   {
574*3f1979aaSAndroid Build Coastguard Worker     pffftd_zconvolve_accumulate(self, dft_a, dft_b, dft_ab, scaling);
575*3f1979aaSAndroid Build Coastguard Worker   }
576*3f1979aaSAndroid Build Coastguard Worker 
convolve(const Scalar * dft_a,const Scalar * dft_b,Scalar * dft_ab,const Scalar scaling)577*3f1979aaSAndroid Build Coastguard Worker   void convolve(const Scalar* dft_a,
578*3f1979aaSAndroid Build Coastguard Worker                 const Scalar* dft_b,
579*3f1979aaSAndroid Build Coastguard Worker                 Scalar* dft_ab,
580*3f1979aaSAndroid Build Coastguard Worker                 const Scalar scaling)
581*3f1979aaSAndroid Build Coastguard Worker   {
582*3f1979aaSAndroid Build Coastguard Worker     pffftd_zconvolve_no_accu(self, dft_a, dft_b, dft_ab, scaling);
583*3f1979aaSAndroid Build Coastguard Worker   }
584*3f1979aaSAndroid Build Coastguard Worker };
585*3f1979aaSAndroid Build Coastguard Worker 
586*3f1979aaSAndroid Build Coastguard Worker template<>
587*3f1979aaSAndroid Build Coastguard Worker class Setup< std::complex<double> >
588*3f1979aaSAndroid Build Coastguard Worker {
589*3f1979aaSAndroid Build Coastguard Worker   PFFFTD_Setup* self;
590*3f1979aaSAndroid Build Coastguard Worker 
591*3f1979aaSAndroid Build Coastguard Worker public:
592*3f1979aaSAndroid Build Coastguard Worker   typedef std::complex<double> value_type;
593*3f1979aaSAndroid Build Coastguard Worker   typedef Types< value_type >::Scalar Scalar;
594*3f1979aaSAndroid Build Coastguard Worker 
Setup()595*3f1979aaSAndroid Build Coastguard Worker   Setup()
596*3f1979aaSAndroid Build Coastguard Worker     : self(NULL)
597*3f1979aaSAndroid Build Coastguard Worker   {}
598*3f1979aaSAndroid Build Coastguard Worker 
~Setup()599*3f1979aaSAndroid Build Coastguard Worker   ~Setup() { pffftd_destroy_setup(self); }
600*3f1979aaSAndroid Build Coastguard Worker 
prepareLength(int length)601*3f1979aaSAndroid Build Coastguard Worker   void prepareLength(int length)
602*3f1979aaSAndroid Build Coastguard Worker   {
603*3f1979aaSAndroid Build Coastguard Worker     if (self) {
604*3f1979aaSAndroid Build Coastguard Worker       pffftd_destroy_setup(self);
605*3f1979aaSAndroid Build Coastguard Worker     }
606*3f1979aaSAndroid Build Coastguard Worker     self = pffftd_new_setup(length, PFFFT_COMPLEX);
607*3f1979aaSAndroid Build Coastguard Worker   }
608*3f1979aaSAndroid Build Coastguard Worker 
transform_ordered(const Scalar * input,Scalar * output,Scalar * work,pffft_direction_t direction)609*3f1979aaSAndroid Build Coastguard Worker   void transform_ordered(const Scalar* input,
610*3f1979aaSAndroid Build Coastguard Worker                          Scalar* output,
611*3f1979aaSAndroid Build Coastguard Worker                          Scalar* work,
612*3f1979aaSAndroid Build Coastguard Worker                          pffft_direction_t direction)
613*3f1979aaSAndroid Build Coastguard Worker   {
614*3f1979aaSAndroid Build Coastguard Worker     pffftd_transform_ordered(self, input, output, work, direction);
615*3f1979aaSAndroid Build Coastguard Worker   }
616*3f1979aaSAndroid Build Coastguard Worker 
transform(const Scalar * input,Scalar * output,Scalar * work,pffft_direction_t direction)617*3f1979aaSAndroid Build Coastguard Worker   void transform(const Scalar* input,
618*3f1979aaSAndroid Build Coastguard Worker                  Scalar* output,
619*3f1979aaSAndroid Build Coastguard Worker                  Scalar* work,
620*3f1979aaSAndroid Build Coastguard Worker                  pffft_direction_t direction)
621*3f1979aaSAndroid Build Coastguard Worker   {
622*3f1979aaSAndroid Build Coastguard Worker     pffftd_transform(self, input, output, work, direction);
623*3f1979aaSAndroid Build Coastguard Worker   }
624*3f1979aaSAndroid Build Coastguard Worker 
reorder(const Scalar * input,Scalar * output,pffft_direction_t direction)625*3f1979aaSAndroid Build Coastguard Worker   void reorder(const Scalar* input, Scalar* output, pffft_direction_t direction)
626*3f1979aaSAndroid Build Coastguard Worker   {
627*3f1979aaSAndroid Build Coastguard Worker     pffftd_zreorder(self, input, output, direction);
628*3f1979aaSAndroid Build Coastguard Worker   }
629*3f1979aaSAndroid Build Coastguard Worker 
convolveAccumulate(const Scalar * dft_a,const Scalar * dft_b,Scalar * dft_ab,const Scalar scaling)630*3f1979aaSAndroid Build Coastguard Worker   void convolveAccumulate(const Scalar* dft_a,
631*3f1979aaSAndroid Build Coastguard Worker                           const Scalar* dft_b,
632*3f1979aaSAndroid Build Coastguard Worker                           Scalar* dft_ab,
633*3f1979aaSAndroid Build Coastguard Worker                           const Scalar scaling)
634*3f1979aaSAndroid Build Coastguard Worker   {
635*3f1979aaSAndroid Build Coastguard Worker     pffftd_zconvolve_accumulate(self, dft_a, dft_b, dft_ab, scaling);
636*3f1979aaSAndroid Build Coastguard Worker   }
637*3f1979aaSAndroid Build Coastguard Worker 
convolve(const Scalar * dft_a,const Scalar * dft_b,Scalar * dft_ab,const Scalar scaling)638*3f1979aaSAndroid Build Coastguard Worker   void convolve(const Scalar* dft_a,
639*3f1979aaSAndroid Build Coastguard Worker                 const Scalar* dft_b,
640*3f1979aaSAndroid Build Coastguard Worker                 Scalar* dft_ab,
641*3f1979aaSAndroid Build Coastguard Worker                 const Scalar scaling)
642*3f1979aaSAndroid Build Coastguard Worker   {
643*3f1979aaSAndroid Build Coastguard Worker     pffftd_zconvolve_no_accu(self, dft_a, dft_b, dft_ab, scaling);
644*3f1979aaSAndroid Build Coastguard Worker   }
645*3f1979aaSAndroid Build Coastguard Worker };
646*3f1979aaSAndroid Build Coastguard Worker 
647*3f1979aaSAndroid Build Coastguard Worker #endif /* defined(PFFFT_ENABLE_DOUBLE) */
648*3f1979aaSAndroid Build Coastguard Worker 
649*3f1979aaSAndroid Build Coastguard Worker } // end of anonymous namespace for Setup<>
650*3f1979aaSAndroid Build Coastguard Worker 
651*3f1979aaSAndroid Build Coastguard Worker 
652*3f1979aaSAndroid Build Coastguard Worker template<typename T>
Fft(int length,int stackThresholdLen)653*3f1979aaSAndroid Build Coastguard Worker inline Fft<T>::Fft(int length, int stackThresholdLen)
654*3f1979aaSAndroid Build Coastguard Worker   : length(0)
655*3f1979aaSAndroid Build Coastguard Worker   , stackThresholdLen(stackThresholdLen)
656*3f1979aaSAndroid Build Coastguard Worker   , work(NULL)
657*3f1979aaSAndroid Build Coastguard Worker {
658*3f1979aaSAndroid Build Coastguard Worker #if (__cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900))
659*3f1979aaSAndroid Build Coastguard Worker   static_assert( sizeof(Complex) == 2 * sizeof(Scalar), "pffft requires sizeof(std::complex<>) == 2 * sizeof(Scalar)" );
660*3f1979aaSAndroid Build Coastguard Worker #elif defined(__GNUC__)
661*3f1979aaSAndroid Build Coastguard Worker   char static_assert_like[(sizeof(Complex) == 2 * sizeof(Scalar)) ? 1 : -1]; // pffft requires sizeof(std::complex<>) == 2 * sizeof(Scalar)
662*3f1979aaSAndroid Build Coastguard Worker #endif
663*3f1979aaSAndroid Build Coastguard Worker   prepareLength(length);
664*3f1979aaSAndroid Build Coastguard Worker }
665*3f1979aaSAndroid Build Coastguard Worker 
666*3f1979aaSAndroid Build Coastguard Worker template<typename T>
~Fft()667*3f1979aaSAndroid Build Coastguard Worker inline Fft<T>::~Fft()
668*3f1979aaSAndroid Build Coastguard Worker {
669*3f1979aaSAndroid Build Coastguard Worker   alignedFree(work);
670*3f1979aaSAndroid Build Coastguard Worker }
671*3f1979aaSAndroid Build Coastguard Worker 
672*3f1979aaSAndroid Build Coastguard Worker template<typename T>
673*3f1979aaSAndroid Build Coastguard Worker inline void
prepareLength(int newLength)674*3f1979aaSAndroid Build Coastguard Worker Fft<T>::prepareLength(int newLength)
675*3f1979aaSAndroid Build Coastguard Worker {
676*3f1979aaSAndroid Build Coastguard Worker   const bool wasOnHeap = ( work != NULL );
677*3f1979aaSAndroid Build Coastguard Worker 
678*3f1979aaSAndroid Build Coastguard Worker   const bool useHeap = newLength > stackThresholdLen;
679*3f1979aaSAndroid Build Coastguard Worker 
680*3f1979aaSAndroid Build Coastguard Worker   if (useHeap == wasOnHeap && newLength == length) {
681*3f1979aaSAndroid Build Coastguard Worker     return;
682*3f1979aaSAndroid Build Coastguard Worker   }
683*3f1979aaSAndroid Build Coastguard Worker 
684*3f1979aaSAndroid Build Coastguard Worker   length = newLength;
685*3f1979aaSAndroid Build Coastguard Worker 
686*3f1979aaSAndroid Build Coastguard Worker   setup.prepareLength(length);
687*3f1979aaSAndroid Build Coastguard Worker 
688*3f1979aaSAndroid Build Coastguard Worker   if (work) {
689*3f1979aaSAndroid Build Coastguard Worker     alignedFree(work);
690*3f1979aaSAndroid Build Coastguard Worker     work = NULL;
691*3f1979aaSAndroid Build Coastguard Worker   }
692*3f1979aaSAndroid Build Coastguard Worker 
693*3f1979aaSAndroid Build Coastguard Worker   if (useHeap) {
694*3f1979aaSAndroid Build Coastguard Worker     work = reinterpret_cast<Scalar*>( alignedAllocType(length) );
695*3f1979aaSAndroid Build Coastguard Worker   }
696*3f1979aaSAndroid Build Coastguard Worker }
697*3f1979aaSAndroid Build Coastguard Worker 
698*3f1979aaSAndroid Build Coastguard Worker 
699*3f1979aaSAndroid Build Coastguard Worker template<typename T>
700*3f1979aaSAndroid Build Coastguard Worker inline AlignedVector<T>
valueVector() const701*3f1979aaSAndroid Build Coastguard Worker Fft<T>::valueVector() const
702*3f1979aaSAndroid Build Coastguard Worker {
703*3f1979aaSAndroid Build Coastguard Worker   return AlignedVector<T>(length);
704*3f1979aaSAndroid Build Coastguard Worker }
705*3f1979aaSAndroid Build Coastguard Worker 
706*3f1979aaSAndroid Build Coastguard Worker template<typename T>
707*3f1979aaSAndroid Build Coastguard Worker inline AlignedVector< typename Fft<T>::Complex >
spectrumVector() const708*3f1979aaSAndroid Build Coastguard Worker Fft<T>::spectrumVector() const
709*3f1979aaSAndroid Build Coastguard Worker {
710*3f1979aaSAndroid Build Coastguard Worker   return AlignedVector<Complex>( getSpectrumSize() );
711*3f1979aaSAndroid Build Coastguard Worker }
712*3f1979aaSAndroid Build Coastguard Worker 
713*3f1979aaSAndroid Build Coastguard Worker template<typename T>
714*3f1979aaSAndroid Build Coastguard Worker inline AlignedVector< typename Fft<T>::Scalar >
internalLayoutVector() const715*3f1979aaSAndroid Build Coastguard Worker Fft<T>::internalLayoutVector() const
716*3f1979aaSAndroid Build Coastguard Worker {
717*3f1979aaSAndroid Build Coastguard Worker   return AlignedVector<Scalar>( getInternalLayoutSize() );
718*3f1979aaSAndroid Build Coastguard Worker }
719*3f1979aaSAndroid Build Coastguard Worker 
720*3f1979aaSAndroid Build Coastguard Worker 
721*3f1979aaSAndroid Build Coastguard Worker template<typename T>
722*3f1979aaSAndroid Build Coastguard Worker inline AlignedVector< typename Fft<T>::Complex > &
forward(const AlignedVector<T> & input,AlignedVector<Complex> & spectrum)723*3f1979aaSAndroid Build Coastguard Worker Fft<T>::forward(const AlignedVector<T> & input, AlignedVector<Complex> & spectrum)
724*3f1979aaSAndroid Build Coastguard Worker {
725*3f1979aaSAndroid Build Coastguard Worker   forward( input.data(), spectrum.data() );
726*3f1979aaSAndroid Build Coastguard Worker   return spectrum;
727*3f1979aaSAndroid Build Coastguard Worker }
728*3f1979aaSAndroid Build Coastguard Worker 
729*3f1979aaSAndroid Build Coastguard Worker template<typename T>
730*3f1979aaSAndroid Build Coastguard Worker inline AlignedVector<T> &
inverse(const AlignedVector<Complex> & spectrum,AlignedVector<T> & output)731*3f1979aaSAndroid Build Coastguard Worker Fft<T>::inverse(const AlignedVector<Complex> & spectrum, AlignedVector<T> & output)
732*3f1979aaSAndroid Build Coastguard Worker {
733*3f1979aaSAndroid Build Coastguard Worker   inverse( spectrum.data(), output.data() );
734*3f1979aaSAndroid Build Coastguard Worker   return output;
735*3f1979aaSAndroid Build Coastguard Worker }
736*3f1979aaSAndroid Build Coastguard Worker 
737*3f1979aaSAndroid Build Coastguard Worker 
738*3f1979aaSAndroid Build Coastguard Worker template<typename T>
739*3f1979aaSAndroid Build Coastguard Worker inline AlignedVector< typename Fft<T>::Scalar > &
forwardToInternalLayout(const AlignedVector<T> & input,AlignedVector<Scalar> & spectrum_internal_layout)740*3f1979aaSAndroid Build Coastguard Worker Fft<T>::forwardToInternalLayout(
741*3f1979aaSAndroid Build Coastguard Worker     const AlignedVector<T> & input,
742*3f1979aaSAndroid Build Coastguard Worker     AlignedVector<Scalar> & spectrum_internal_layout )
743*3f1979aaSAndroid Build Coastguard Worker {
744*3f1979aaSAndroid Build Coastguard Worker   forwardToInternalLayout( input.data(), spectrum_internal_layout.data() );
745*3f1979aaSAndroid Build Coastguard Worker   return spectrum_internal_layout;
746*3f1979aaSAndroid Build Coastguard Worker }
747*3f1979aaSAndroid Build Coastguard Worker 
748*3f1979aaSAndroid Build Coastguard Worker template<typename T>
749*3f1979aaSAndroid Build Coastguard Worker inline AlignedVector<T> &
inverseFromInternalLayout(const AlignedVector<Scalar> & spectrum_internal_layout,AlignedVector<T> & output)750*3f1979aaSAndroid Build Coastguard Worker Fft<T>::inverseFromInternalLayout(
751*3f1979aaSAndroid Build Coastguard Worker     const AlignedVector<Scalar> & spectrum_internal_layout,
752*3f1979aaSAndroid Build Coastguard Worker     AlignedVector<T> & output )
753*3f1979aaSAndroid Build Coastguard Worker {
754*3f1979aaSAndroid Build Coastguard Worker   inverseFromInternalLayout( spectrum_internal_layout.data(), output.data() );
755*3f1979aaSAndroid Build Coastguard Worker   return output;
756*3f1979aaSAndroid Build Coastguard Worker }
757*3f1979aaSAndroid Build Coastguard Worker 
758*3f1979aaSAndroid Build Coastguard Worker template<typename T>
759*3f1979aaSAndroid Build Coastguard Worker inline void
reorderSpectrum(const AlignedVector<Scalar> & input,AlignedVector<Complex> & output)760*3f1979aaSAndroid Build Coastguard Worker Fft<T>::reorderSpectrum(
761*3f1979aaSAndroid Build Coastguard Worker     const AlignedVector<Scalar> & input,
762*3f1979aaSAndroid Build Coastguard Worker     AlignedVector<Complex> & output )
763*3f1979aaSAndroid Build Coastguard Worker {
764*3f1979aaSAndroid Build Coastguard Worker   reorderSpectrum( input.data(), output.data() );
765*3f1979aaSAndroid Build Coastguard Worker }
766*3f1979aaSAndroid Build Coastguard Worker 
767*3f1979aaSAndroid Build Coastguard Worker template<typename T>
768*3f1979aaSAndroid Build Coastguard Worker inline AlignedVector< typename Fft<T>::Scalar > &
convolveAccumulate(const AlignedVector<Scalar> & spectrum_internal_a,const AlignedVector<Scalar> & spectrum_internal_b,AlignedVector<Scalar> & spectrum_internal_ab,const Scalar scaling)769*3f1979aaSAndroid Build Coastguard Worker Fft<T>::convolveAccumulate(
770*3f1979aaSAndroid Build Coastguard Worker     const AlignedVector<Scalar> & spectrum_internal_a,
771*3f1979aaSAndroid Build Coastguard Worker     const AlignedVector<Scalar> & spectrum_internal_b,
772*3f1979aaSAndroid Build Coastguard Worker     AlignedVector<Scalar> & spectrum_internal_ab,
773*3f1979aaSAndroid Build Coastguard Worker     const Scalar scaling )
774*3f1979aaSAndroid Build Coastguard Worker {
775*3f1979aaSAndroid Build Coastguard Worker   convolveAccumulate( spectrum_internal_a.data(), spectrum_internal_b.data(),
776*3f1979aaSAndroid Build Coastguard Worker                       spectrum_internal_ab.data(), scaling );
777*3f1979aaSAndroid Build Coastguard Worker   return spectrum_internal_ab;
778*3f1979aaSAndroid Build Coastguard Worker }
779*3f1979aaSAndroid Build Coastguard Worker 
780*3f1979aaSAndroid Build Coastguard Worker template<typename T>
781*3f1979aaSAndroid Build Coastguard Worker inline AlignedVector< typename Fft<T>::Scalar > &
convolve(const AlignedVector<Scalar> & spectrum_internal_a,const AlignedVector<Scalar> & spectrum_internal_b,AlignedVector<Scalar> & spectrum_internal_ab,const Scalar scaling)782*3f1979aaSAndroid Build Coastguard Worker Fft<T>::convolve(
783*3f1979aaSAndroid Build Coastguard Worker     const AlignedVector<Scalar> & spectrum_internal_a,
784*3f1979aaSAndroid Build Coastguard Worker     const AlignedVector<Scalar> & spectrum_internal_b,
785*3f1979aaSAndroid Build Coastguard Worker     AlignedVector<Scalar> & spectrum_internal_ab,
786*3f1979aaSAndroid Build Coastguard Worker     const Scalar scaling )
787*3f1979aaSAndroid Build Coastguard Worker {
788*3f1979aaSAndroid Build Coastguard Worker   convolve( spectrum_internal_a.data(), spectrum_internal_b.data(),
789*3f1979aaSAndroid Build Coastguard Worker             spectrum_internal_ab.data(), scaling );
790*3f1979aaSAndroid Build Coastguard Worker   return spectrum_internal_ab;
791*3f1979aaSAndroid Build Coastguard Worker }
792*3f1979aaSAndroid Build Coastguard Worker 
793*3f1979aaSAndroid Build Coastguard Worker 
794*3f1979aaSAndroid Build Coastguard Worker template<typename T>
795*3f1979aaSAndroid Build Coastguard Worker inline typename Fft<T>::Complex *
forward(const T * input,Complex * spectrum)796*3f1979aaSAndroid Build Coastguard Worker Fft<T>::forward(const T* input, Complex * spectrum)
797*3f1979aaSAndroid Build Coastguard Worker {
798*3f1979aaSAndroid Build Coastguard Worker   setup.transform_ordered(reinterpret_cast<const Scalar*>(input),
799*3f1979aaSAndroid Build Coastguard Worker                           reinterpret_cast<Scalar*>(spectrum),
800*3f1979aaSAndroid Build Coastguard Worker                           work,
801*3f1979aaSAndroid Build Coastguard Worker                           PFFFT_FORWARD);
802*3f1979aaSAndroid Build Coastguard Worker   return spectrum;
803*3f1979aaSAndroid Build Coastguard Worker }
804*3f1979aaSAndroid Build Coastguard Worker 
805*3f1979aaSAndroid Build Coastguard Worker template<typename T>
806*3f1979aaSAndroid Build Coastguard Worker inline T*
inverse(Complex const * spectrum,T * output)807*3f1979aaSAndroid Build Coastguard Worker Fft<T>::inverse(Complex const* spectrum, T* output)
808*3f1979aaSAndroid Build Coastguard Worker {
809*3f1979aaSAndroid Build Coastguard Worker   setup.transform_ordered(reinterpret_cast<const Scalar*>(spectrum),
810*3f1979aaSAndroid Build Coastguard Worker                           reinterpret_cast<Scalar*>(output),
811*3f1979aaSAndroid Build Coastguard Worker                           work,
812*3f1979aaSAndroid Build Coastguard Worker                           PFFFT_BACKWARD);
813*3f1979aaSAndroid Build Coastguard Worker   return output;
814*3f1979aaSAndroid Build Coastguard Worker }
815*3f1979aaSAndroid Build Coastguard Worker 
816*3f1979aaSAndroid Build Coastguard Worker template<typename T>
817*3f1979aaSAndroid Build Coastguard Worker inline typename pffft::Fft<T>::Scalar*
forwardToInternalLayout(const T * input,Scalar * spectrum_internal_layout)818*3f1979aaSAndroid Build Coastguard Worker Fft<T>::forwardToInternalLayout(const T* input, Scalar* spectrum_internal_layout)
819*3f1979aaSAndroid Build Coastguard Worker {
820*3f1979aaSAndroid Build Coastguard Worker   setup.transform(reinterpret_cast<const Scalar*>(input),
821*3f1979aaSAndroid Build Coastguard Worker                   spectrum_internal_layout,
822*3f1979aaSAndroid Build Coastguard Worker                   work,
823*3f1979aaSAndroid Build Coastguard Worker                   PFFFT_FORWARD);
824*3f1979aaSAndroid Build Coastguard Worker   return spectrum_internal_layout;
825*3f1979aaSAndroid Build Coastguard Worker }
826*3f1979aaSAndroid Build Coastguard Worker 
827*3f1979aaSAndroid Build Coastguard Worker template<typename T>
828*3f1979aaSAndroid Build Coastguard Worker inline T*
inverseFromInternalLayout(const Scalar * spectrum_internal_layout,T * output)829*3f1979aaSAndroid Build Coastguard Worker Fft<T>::inverseFromInternalLayout(const Scalar* spectrum_internal_layout, T* output)
830*3f1979aaSAndroid Build Coastguard Worker {
831*3f1979aaSAndroid Build Coastguard Worker   setup.transform(spectrum_internal_layout,
832*3f1979aaSAndroid Build Coastguard Worker                   reinterpret_cast<Scalar*>(output),
833*3f1979aaSAndroid Build Coastguard Worker                   work,
834*3f1979aaSAndroid Build Coastguard Worker                   PFFFT_BACKWARD);
835*3f1979aaSAndroid Build Coastguard Worker   return output;
836*3f1979aaSAndroid Build Coastguard Worker }
837*3f1979aaSAndroid Build Coastguard Worker 
838*3f1979aaSAndroid Build Coastguard Worker template<typename T>
839*3f1979aaSAndroid Build Coastguard Worker inline void
reorderSpectrum(const Scalar * input,Complex * output)840*3f1979aaSAndroid Build Coastguard Worker Fft<T>::reorderSpectrum( const Scalar* input, Complex* output )
841*3f1979aaSAndroid Build Coastguard Worker {
842*3f1979aaSAndroid Build Coastguard Worker   setup.reorder(input, reinterpret_cast<Scalar*>(output), PFFFT_FORWARD);
843*3f1979aaSAndroid Build Coastguard Worker }
844*3f1979aaSAndroid Build Coastguard Worker 
845*3f1979aaSAndroid Build Coastguard Worker template<typename T>
846*3f1979aaSAndroid Build Coastguard Worker inline typename pffft::Fft<T>::Scalar*
convolveAccumulate(const Scalar * dft_a,const Scalar * dft_b,Scalar * dft_ab,const Scalar scaling)847*3f1979aaSAndroid Build Coastguard Worker Fft<T>::convolveAccumulate(const Scalar* dft_a,
848*3f1979aaSAndroid Build Coastguard Worker                            const Scalar* dft_b,
849*3f1979aaSAndroid Build Coastguard Worker                            Scalar* dft_ab,
850*3f1979aaSAndroid Build Coastguard Worker                            const Scalar scaling)
851*3f1979aaSAndroid Build Coastguard Worker {
852*3f1979aaSAndroid Build Coastguard Worker   setup.convolveAccumulate(dft_a, dft_b, dft_ab, scaling);
853*3f1979aaSAndroid Build Coastguard Worker   return dft_ab;
854*3f1979aaSAndroid Build Coastguard Worker }
855*3f1979aaSAndroid Build Coastguard Worker 
856*3f1979aaSAndroid Build Coastguard Worker template<typename T>
857*3f1979aaSAndroid Build Coastguard Worker inline typename pffft::Fft<T>::Scalar*
convolve(const Scalar * dft_a,const Scalar * dft_b,Scalar * dft_ab,const Scalar scaling)858*3f1979aaSAndroid Build Coastguard Worker Fft<T>::convolve(const Scalar* dft_a,
859*3f1979aaSAndroid Build Coastguard Worker                  const Scalar* dft_b,
860*3f1979aaSAndroid Build Coastguard Worker                  Scalar* dft_ab,
861*3f1979aaSAndroid Build Coastguard Worker                  const Scalar scaling)
862*3f1979aaSAndroid Build Coastguard Worker {
863*3f1979aaSAndroid Build Coastguard Worker   setup.convolve(dft_a, dft_b, dft_ab, scaling);
864*3f1979aaSAndroid Build Coastguard Worker   return dft_ab;
865*3f1979aaSAndroid Build Coastguard Worker }
866*3f1979aaSAndroid Build Coastguard Worker 
867*3f1979aaSAndroid Build Coastguard Worker template<typename T>
868*3f1979aaSAndroid Build Coastguard Worker inline void
alignedFree(void * ptr)869*3f1979aaSAndroid Build Coastguard Worker Fft<T>::alignedFree(void* ptr)
870*3f1979aaSAndroid Build Coastguard Worker {
871*3f1979aaSAndroid Build Coastguard Worker   pffft::alignedFree(ptr);
872*3f1979aaSAndroid Build Coastguard Worker }
873*3f1979aaSAndroid Build Coastguard Worker 
874*3f1979aaSAndroid Build Coastguard Worker 
875*3f1979aaSAndroid Build Coastguard Worker template<typename T>
876*3f1979aaSAndroid Build Coastguard Worker inline T*
alignedAllocType(int length)877*3f1979aaSAndroid Build Coastguard Worker pffft::Fft<T>::alignedAllocType(int length)
878*3f1979aaSAndroid Build Coastguard Worker {
879*3f1979aaSAndroid Build Coastguard Worker   return alignedAlloc<T>(length);
880*3f1979aaSAndroid Build Coastguard Worker }
881*3f1979aaSAndroid Build Coastguard Worker 
882*3f1979aaSAndroid Build Coastguard Worker template<typename T>
883*3f1979aaSAndroid Build Coastguard Worker inline typename pffft::Fft<T>::Scalar*
alignedAllocScalar(int length)884*3f1979aaSAndroid Build Coastguard Worker pffft::Fft<T>::alignedAllocScalar(int length)
885*3f1979aaSAndroid Build Coastguard Worker {
886*3f1979aaSAndroid Build Coastguard Worker   return alignedAlloc<Scalar>(length);
887*3f1979aaSAndroid Build Coastguard Worker }
888*3f1979aaSAndroid Build Coastguard Worker 
889*3f1979aaSAndroid Build Coastguard Worker template<typename T>
890*3f1979aaSAndroid Build Coastguard Worker inline typename Fft<T>::Complex *
alignedAllocComplex(int length)891*3f1979aaSAndroid Build Coastguard Worker Fft<T>::alignedAllocComplex(int length)
892*3f1979aaSAndroid Build Coastguard Worker {
893*3f1979aaSAndroid Build Coastguard Worker   return alignedAlloc<Complex>(length);
894*3f1979aaSAndroid Build Coastguard Worker }
895*3f1979aaSAndroid Build Coastguard Worker 
896*3f1979aaSAndroid Build Coastguard Worker 
897*3f1979aaSAndroid Build Coastguard Worker 
898*3f1979aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////
899*3f1979aaSAndroid Build Coastguard Worker 
900*3f1979aaSAndroid Build Coastguard Worker // Allocator - for std::vector<>:
901*3f1979aaSAndroid Build Coastguard Worker // origin: http://www.josuttis.com/cppcode/allocator.html
902*3f1979aaSAndroid Build Coastguard Worker // http://www.josuttis.com/cppcode/myalloc.hpp
903*3f1979aaSAndroid Build Coastguard Worker //
904*3f1979aaSAndroid Build Coastguard Worker // minor renaming and utilizing of pffft (de)allocation functions
905*3f1979aaSAndroid Build Coastguard Worker // are applied to Jossutis' allocator
906*3f1979aaSAndroid Build Coastguard Worker 
907*3f1979aaSAndroid Build Coastguard Worker /* The following code example is taken from the book
908*3f1979aaSAndroid Build Coastguard Worker  * "The C++ Standard Library - A Tutorial and Reference"
909*3f1979aaSAndroid Build Coastguard Worker  * by Nicolai M. Josuttis, Addison-Wesley, 1999
910*3f1979aaSAndroid Build Coastguard Worker  *
911*3f1979aaSAndroid Build Coastguard Worker  * (C) Copyright Nicolai M. Josuttis 1999.
912*3f1979aaSAndroid Build Coastguard Worker  * Permission to copy, use, modify, sell and distribute this software
913*3f1979aaSAndroid Build Coastguard Worker  * is granted provided this copyright notice appears in all copies.
914*3f1979aaSAndroid Build Coastguard Worker  * This software is provided "as is" without express or implied
915*3f1979aaSAndroid Build Coastguard Worker  * warranty, and with no claim as to its suitability for any purpose.
916*3f1979aaSAndroid Build Coastguard Worker  */
917*3f1979aaSAndroid Build Coastguard Worker 
918*3f1979aaSAndroid Build Coastguard Worker template <class T>
919*3f1979aaSAndroid Build Coastguard Worker class PFAlloc {
920*3f1979aaSAndroid Build Coastguard Worker   public:
921*3f1979aaSAndroid Build Coastguard Worker     // type definitions
922*3f1979aaSAndroid Build Coastguard Worker     typedef T        value_type;
923*3f1979aaSAndroid Build Coastguard Worker     typedef T*       pointer;
924*3f1979aaSAndroid Build Coastguard Worker     typedef const T* const_pointer;
925*3f1979aaSAndroid Build Coastguard Worker     typedef T&       reference;
926*3f1979aaSAndroid Build Coastguard Worker     typedef const T& const_reference;
927*3f1979aaSAndroid Build Coastguard Worker     typedef std::size_t    size_type;
928*3f1979aaSAndroid Build Coastguard Worker     typedef std::ptrdiff_t difference_type;
929*3f1979aaSAndroid Build Coastguard Worker 
930*3f1979aaSAndroid Build Coastguard Worker     // rebind allocator to type U
931*3f1979aaSAndroid Build Coastguard Worker     template <class U>
932*3f1979aaSAndroid Build Coastguard Worker     struct rebind {
933*3f1979aaSAndroid Build Coastguard Worker         typedef PFAlloc<U> other;
934*3f1979aaSAndroid Build Coastguard Worker     };
935*3f1979aaSAndroid Build Coastguard Worker 
936*3f1979aaSAndroid Build Coastguard Worker     // return address of values
address(reference value) const937*3f1979aaSAndroid Build Coastguard Worker     pointer address (reference value) const {
938*3f1979aaSAndroid Build Coastguard Worker         return &value;
939*3f1979aaSAndroid Build Coastguard Worker     }
address(const_reference value) const940*3f1979aaSAndroid Build Coastguard Worker     const_pointer address (const_reference value) const {
941*3f1979aaSAndroid Build Coastguard Worker         return &value;
942*3f1979aaSAndroid Build Coastguard Worker     }
943*3f1979aaSAndroid Build Coastguard Worker 
944*3f1979aaSAndroid Build Coastguard Worker     /* constructors and destructor
945*3f1979aaSAndroid Build Coastguard Worker      * - nothing to do because the allocator has no state
946*3f1979aaSAndroid Build Coastguard Worker      */
PFAlloc()947*3f1979aaSAndroid Build Coastguard Worker     PFAlloc() throw() {
948*3f1979aaSAndroid Build Coastguard Worker     }
PFAlloc(const PFAlloc &)949*3f1979aaSAndroid Build Coastguard Worker     PFAlloc(const PFAlloc&) throw() {
950*3f1979aaSAndroid Build Coastguard Worker     }
951*3f1979aaSAndroid Build Coastguard Worker     template <class U>
PFAlloc(const PFAlloc<U> &)952*3f1979aaSAndroid Build Coastguard Worker       PFAlloc (const PFAlloc<U>&) throw() {
953*3f1979aaSAndroid Build Coastguard Worker     }
~PFAlloc()954*3f1979aaSAndroid Build Coastguard Worker     ~PFAlloc() throw() {
955*3f1979aaSAndroid Build Coastguard Worker     }
956*3f1979aaSAndroid Build Coastguard Worker 
957*3f1979aaSAndroid Build Coastguard Worker     // return maximum number of elements that can be allocated
max_size() const958*3f1979aaSAndroid Build Coastguard Worker     size_type max_size () const throw() {
959*3f1979aaSAndroid Build Coastguard Worker         return std::numeric_limits<std::size_t>::max() / sizeof(T);
960*3f1979aaSAndroid Build Coastguard Worker     }
961*3f1979aaSAndroid Build Coastguard Worker 
962*3f1979aaSAndroid Build Coastguard Worker     // allocate but don't initialize num elements of type T
allocate(size_type num,const void * =0)963*3f1979aaSAndroid Build Coastguard Worker     pointer allocate (size_type num, const void* = 0) {
964*3f1979aaSAndroid Build Coastguard Worker         pointer ret = (pointer)( alignedAlloc<T>(num) );
965*3f1979aaSAndroid Build Coastguard Worker         return ret;
966*3f1979aaSAndroid Build Coastguard Worker     }
967*3f1979aaSAndroid Build Coastguard Worker 
968*3f1979aaSAndroid Build Coastguard Worker     // initialize elements of allocated storage p with value value
construct(pointer p,const T & value)969*3f1979aaSAndroid Build Coastguard Worker     void construct (pointer p, const T& value) {
970*3f1979aaSAndroid Build Coastguard Worker         // initialize memory with placement new
971*3f1979aaSAndroid Build Coastguard Worker         new((void*)p)T(value);
972*3f1979aaSAndroid Build Coastguard Worker     }
973*3f1979aaSAndroid Build Coastguard Worker 
974*3f1979aaSAndroid Build Coastguard Worker     // destroy elements of initialized storage p
destroy(pointer p)975*3f1979aaSAndroid Build Coastguard Worker     void destroy (pointer p) {
976*3f1979aaSAndroid Build Coastguard Worker         // destroy objects by calling their destructor
977*3f1979aaSAndroid Build Coastguard Worker         p->~T();
978*3f1979aaSAndroid Build Coastguard Worker     }
979*3f1979aaSAndroid Build Coastguard Worker 
980*3f1979aaSAndroid Build Coastguard Worker     // deallocate storage p of deleted elements
deallocate(pointer p,size_type num)981*3f1979aaSAndroid Build Coastguard Worker     void deallocate (pointer p, size_type num) {
982*3f1979aaSAndroid Build Coastguard Worker         // deallocate memory with pffft
983*3f1979aaSAndroid Build Coastguard Worker         alignedFree( (void*)p );
984*3f1979aaSAndroid Build Coastguard Worker     }
985*3f1979aaSAndroid Build Coastguard Worker };
986*3f1979aaSAndroid Build Coastguard Worker 
987*3f1979aaSAndroid Build Coastguard Worker // return that all specializations of this allocator are interchangeable
988*3f1979aaSAndroid Build Coastguard Worker template <class T1, class T2>
operator ==(const PFAlloc<T1> &,const PFAlloc<T2> &)989*3f1979aaSAndroid Build Coastguard Worker bool operator== (const PFAlloc<T1>&,
990*3f1979aaSAndroid Build Coastguard Worker                  const PFAlloc<T2>&) throw() {
991*3f1979aaSAndroid Build Coastguard Worker     return true;
992*3f1979aaSAndroid Build Coastguard Worker }
993*3f1979aaSAndroid Build Coastguard Worker template <class T1, class T2>
operator !=(const PFAlloc<T1> &,const PFAlloc<T2> &)994*3f1979aaSAndroid Build Coastguard Worker bool operator!= (const PFAlloc<T1>&,
995*3f1979aaSAndroid Build Coastguard Worker                  const PFAlloc<T2>&) throw() {
996*3f1979aaSAndroid Build Coastguard Worker     return false;
997*3f1979aaSAndroid Build Coastguard Worker }
998*3f1979aaSAndroid Build Coastguard Worker 
999*3f1979aaSAndroid Build Coastguard Worker 
1000*3f1979aaSAndroid Build Coastguard Worker } // namespace pffft
1001*3f1979aaSAndroid Build Coastguard Worker 
1002