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