Chris@31
|
1 /*
|
Chris@31
|
2 Copyright (c) 2003-2010, Mark Borgerding
|
Chris@31
|
3
|
Chris@31
|
4 All rights reserved.
|
Chris@31
|
5
|
Chris@31
|
6 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
Chris@31
|
7
|
Chris@31
|
8 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
Chris@31
|
9 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
Chris@31
|
10 * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
Chris@31
|
11
|
Chris@31
|
12 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
Chris@31
|
13 */
|
Chris@31
|
14
|
Chris@31
|
15
|
Chris@31
|
16 #include "_kiss_fft_guts.h"
|
Chris@31
|
17 /* The guts header contains all the multiplication and addition macros that are defined for
|
Chris@31
|
18 fixed or floating point complex numbers. It also delares the kf_ internal functions.
|
Chris@31
|
19 */
|
Chris@31
|
20
|
Chris@37
|
21 void kiss_fft_free(struct kiss_fft_state *state) {
|
Chris@37
|
22 free(state);
|
Chris@37
|
23 }
|
Chris@37
|
24
|
Chris@31
|
25 static void kf_bfly2(
|
Chris@31
|
26 kiss_fft_cpx * Fout,
|
Chris@31
|
27 const size_t fstride,
|
Chris@31
|
28 const kiss_fft_cfg st,
|
Chris@31
|
29 int m
|
Chris@31
|
30 )
|
Chris@31
|
31 {
|
Chris@31
|
32 kiss_fft_cpx * Fout2;
|
Chris@31
|
33 kiss_fft_cpx * tw1 = st->twiddles;
|
Chris@31
|
34 kiss_fft_cpx t;
|
Chris@31
|
35 Fout2 = Fout + m;
|
Chris@31
|
36 do{
|
Chris@31
|
37 C_FIXDIV(*Fout,2); C_FIXDIV(*Fout2,2);
|
Chris@31
|
38
|
Chris@31
|
39 C_MUL (t, *Fout2 , *tw1);
|
Chris@31
|
40 tw1 += fstride;
|
Chris@31
|
41 C_SUB( *Fout2 , *Fout , t );
|
Chris@31
|
42 C_ADDTO( *Fout , t );
|
Chris@31
|
43 ++Fout2;
|
Chris@31
|
44 ++Fout;
|
Chris@31
|
45 }while (--m);
|
Chris@31
|
46 }
|
Chris@31
|
47
|
Chris@31
|
48 static void kf_bfly4(
|
Chris@31
|
49 kiss_fft_cpx * Fout,
|
Chris@31
|
50 const size_t fstride,
|
Chris@31
|
51 const kiss_fft_cfg st,
|
Chris@31
|
52 const size_t m
|
Chris@31
|
53 )
|
Chris@31
|
54 {
|
Chris@31
|
55 kiss_fft_cpx *tw1,*tw2,*tw3;
|
Chris@31
|
56 kiss_fft_cpx scratch[6];
|
Chris@31
|
57 size_t k=m;
|
Chris@31
|
58 const size_t m2=2*m;
|
Chris@31
|
59 const size_t m3=3*m;
|
Chris@31
|
60
|
Chris@31
|
61
|
Chris@31
|
62 tw3 = tw2 = tw1 = st->twiddles;
|
Chris@31
|
63
|
Chris@31
|
64 do {
|
Chris@31
|
65 C_FIXDIV(*Fout,4); C_FIXDIV(Fout[m],4); C_FIXDIV(Fout[m2],4); C_FIXDIV(Fout[m3],4);
|
Chris@31
|
66
|
Chris@31
|
67 C_MUL(scratch[0],Fout[m] , *tw1 );
|
Chris@31
|
68 C_MUL(scratch[1],Fout[m2] , *tw2 );
|
Chris@31
|
69 C_MUL(scratch[2],Fout[m3] , *tw3 );
|
Chris@31
|
70
|
Chris@31
|
71 C_SUB( scratch[5] , *Fout, scratch[1] );
|
Chris@31
|
72 C_ADDTO(*Fout, scratch[1]);
|
Chris@31
|
73 C_ADD( scratch[3] , scratch[0] , scratch[2] );
|
Chris@31
|
74 C_SUB( scratch[4] , scratch[0] , scratch[2] );
|
Chris@31
|
75 C_SUB( Fout[m2], *Fout, scratch[3] );
|
Chris@31
|
76 tw1 += fstride;
|
Chris@31
|
77 tw2 += fstride*2;
|
Chris@31
|
78 tw3 += fstride*3;
|
Chris@31
|
79 C_ADDTO( *Fout , scratch[3] );
|
Chris@31
|
80
|
Chris@31
|
81 if(st->inverse) {
|
Chris@31
|
82 Fout[m].r = scratch[5].r - scratch[4].i;
|
Chris@31
|
83 Fout[m].i = scratch[5].i + scratch[4].r;
|
Chris@31
|
84 Fout[m3].r = scratch[5].r + scratch[4].i;
|
Chris@31
|
85 Fout[m3].i = scratch[5].i - scratch[4].r;
|
Chris@31
|
86 }else{
|
Chris@31
|
87 Fout[m].r = scratch[5].r + scratch[4].i;
|
Chris@31
|
88 Fout[m].i = scratch[5].i - scratch[4].r;
|
Chris@31
|
89 Fout[m3].r = scratch[5].r - scratch[4].i;
|
Chris@31
|
90 Fout[m3].i = scratch[5].i + scratch[4].r;
|
Chris@31
|
91 }
|
Chris@31
|
92 ++Fout;
|
Chris@31
|
93 }while(--k);
|
Chris@31
|
94 }
|
Chris@31
|
95
|
Chris@31
|
96 static void kf_bfly3(
|
Chris@31
|
97 kiss_fft_cpx * Fout,
|
Chris@31
|
98 const size_t fstride,
|
Chris@31
|
99 const kiss_fft_cfg st,
|
Chris@31
|
100 size_t m
|
Chris@31
|
101 )
|
Chris@31
|
102 {
|
Chris@31
|
103 size_t k=m;
|
Chris@31
|
104 const size_t m2 = 2*m;
|
Chris@31
|
105 kiss_fft_cpx *tw1,*tw2;
|
Chris@31
|
106 kiss_fft_cpx scratch[5];
|
Chris@31
|
107 kiss_fft_cpx epi3;
|
Chris@31
|
108 epi3 = st->twiddles[fstride*m];
|
Chris@31
|
109
|
Chris@31
|
110 tw1=tw2=st->twiddles;
|
Chris@31
|
111
|
Chris@31
|
112 do{
|
Chris@31
|
113 C_FIXDIV(*Fout,3); C_FIXDIV(Fout[m],3); C_FIXDIV(Fout[m2],3);
|
Chris@31
|
114
|
Chris@31
|
115 C_MUL(scratch[1],Fout[m] , *tw1);
|
Chris@31
|
116 C_MUL(scratch[2],Fout[m2] , *tw2);
|
Chris@31
|
117
|
Chris@31
|
118 C_ADD(scratch[3],scratch[1],scratch[2]);
|
Chris@31
|
119 C_SUB(scratch[0],scratch[1],scratch[2]);
|
Chris@31
|
120 tw1 += fstride;
|
Chris@31
|
121 tw2 += fstride*2;
|
Chris@31
|
122
|
Chris@31
|
123 Fout[m].r = Fout->r - HALF_OF(scratch[3].r);
|
Chris@31
|
124 Fout[m].i = Fout->i - HALF_OF(scratch[3].i);
|
Chris@31
|
125
|
Chris@31
|
126 C_MULBYSCALAR( scratch[0] , epi3.i );
|
Chris@31
|
127
|
Chris@31
|
128 C_ADDTO(*Fout,scratch[3]);
|
Chris@31
|
129
|
Chris@31
|
130 Fout[m2].r = Fout[m].r + scratch[0].i;
|
Chris@31
|
131 Fout[m2].i = Fout[m].i - scratch[0].r;
|
Chris@31
|
132
|
Chris@31
|
133 Fout[m].r -= scratch[0].i;
|
Chris@31
|
134 Fout[m].i += scratch[0].r;
|
Chris@31
|
135
|
Chris@31
|
136 ++Fout;
|
Chris@31
|
137 }while(--k);
|
Chris@31
|
138 }
|
Chris@31
|
139
|
Chris@31
|
140 static void kf_bfly5(
|
Chris@31
|
141 kiss_fft_cpx * Fout,
|
Chris@31
|
142 const size_t fstride,
|
Chris@31
|
143 const kiss_fft_cfg st,
|
Chris@31
|
144 int m
|
Chris@31
|
145 )
|
Chris@31
|
146 {
|
Chris@31
|
147 kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
|
Chris@31
|
148 int u;
|
Chris@31
|
149 kiss_fft_cpx scratch[13];
|
Chris@31
|
150 kiss_fft_cpx * twiddles = st->twiddles;
|
Chris@31
|
151 kiss_fft_cpx *tw;
|
Chris@31
|
152 kiss_fft_cpx ya,yb;
|
Chris@31
|
153 ya = twiddles[fstride*m];
|
Chris@31
|
154 yb = twiddles[fstride*2*m];
|
Chris@31
|
155
|
Chris@31
|
156 Fout0=Fout;
|
Chris@31
|
157 Fout1=Fout0+m;
|
Chris@31
|
158 Fout2=Fout0+2*m;
|
Chris@31
|
159 Fout3=Fout0+3*m;
|
Chris@31
|
160 Fout4=Fout0+4*m;
|
Chris@31
|
161
|
Chris@31
|
162 tw=st->twiddles;
|
Chris@31
|
163 for ( u=0; u<m; ++u ) {
|
Chris@31
|
164 C_FIXDIV( *Fout0,5); C_FIXDIV( *Fout1,5); C_FIXDIV( *Fout2,5); C_FIXDIV( *Fout3,5); C_FIXDIV( *Fout4,5);
|
Chris@31
|
165 scratch[0] = *Fout0;
|
Chris@31
|
166
|
Chris@31
|
167 C_MUL(scratch[1] ,*Fout1, tw[u*fstride]);
|
Chris@31
|
168 C_MUL(scratch[2] ,*Fout2, tw[2*u*fstride]);
|
Chris@31
|
169 C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]);
|
Chris@31
|
170 C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]);
|
Chris@31
|
171
|
Chris@31
|
172 C_ADD( scratch[7],scratch[1],scratch[4]);
|
Chris@31
|
173 C_SUB( scratch[10],scratch[1],scratch[4]);
|
Chris@31
|
174 C_ADD( scratch[8],scratch[2],scratch[3]);
|
Chris@31
|
175 C_SUB( scratch[9],scratch[2],scratch[3]);
|
Chris@31
|
176
|
Chris@31
|
177 Fout0->r += scratch[7].r + scratch[8].r;
|
Chris@31
|
178 Fout0->i += scratch[7].i + scratch[8].i;
|
Chris@31
|
179
|
Chris@31
|
180 scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r);
|
Chris@31
|
181 scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r);
|
Chris@31
|
182
|
Chris@31
|
183 scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i);
|
Chris@31
|
184 scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i);
|
Chris@31
|
185
|
Chris@31
|
186 C_SUB(*Fout1,scratch[5],scratch[6]);
|
Chris@31
|
187 C_ADD(*Fout4,scratch[5],scratch[6]);
|
Chris@31
|
188
|
Chris@31
|
189 scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r);
|
Chris@31
|
190 scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r);
|
Chris@31
|
191 scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i);
|
Chris@31
|
192 scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i);
|
Chris@31
|
193
|
Chris@31
|
194 C_ADD(*Fout2,scratch[11],scratch[12]);
|
Chris@31
|
195 C_SUB(*Fout3,scratch[11],scratch[12]);
|
Chris@31
|
196
|
Chris@31
|
197 ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
|
Chris@31
|
198 }
|
Chris@31
|
199 }
|
Chris@31
|
200
|
Chris@31
|
201 /* perform the butterfly for one stage of a mixed radix FFT */
|
Chris@31
|
202 static void kf_bfly_generic(
|
Chris@31
|
203 kiss_fft_cpx * Fout,
|
Chris@31
|
204 const size_t fstride,
|
Chris@31
|
205 const kiss_fft_cfg st,
|
Chris@31
|
206 int m,
|
Chris@31
|
207 int p
|
Chris@31
|
208 )
|
Chris@31
|
209 {
|
Chris@31
|
210 int u,k,q1,q;
|
Chris@31
|
211 kiss_fft_cpx * twiddles = st->twiddles;
|
Chris@31
|
212 kiss_fft_cpx t;
|
Chris@31
|
213 int Norig = st->nfft;
|
Chris@31
|
214
|
Chris@31
|
215 kiss_fft_cpx * scratch = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC(sizeof(kiss_fft_cpx)*p);
|
Chris@31
|
216
|
Chris@31
|
217 for ( u=0; u<m; ++u ) {
|
Chris@31
|
218 k=u;
|
Chris@31
|
219 for ( q1=0 ; q1<p ; ++q1 ) {
|
Chris@31
|
220 scratch[q1] = Fout[ k ];
|
Chris@31
|
221 C_FIXDIV(scratch[q1],p);
|
Chris@31
|
222 k += m;
|
Chris@31
|
223 }
|
Chris@31
|
224
|
Chris@31
|
225 k=u;
|
Chris@31
|
226 for ( q1=0 ; q1<p ; ++q1 ) {
|
Chris@31
|
227 int twidx=0;
|
Chris@31
|
228 Fout[ k ] = scratch[0];
|
Chris@31
|
229 for (q=1;q<p;++q ) {
|
Chris@31
|
230 twidx += fstride * k;
|
Chris@31
|
231 if (twidx>=Norig) twidx-=Norig;
|
Chris@31
|
232 C_MUL(t,scratch[q] , twiddles[twidx] );
|
Chris@31
|
233 C_ADDTO( Fout[ k ] ,t);
|
Chris@31
|
234 }
|
Chris@31
|
235 k += m;
|
Chris@31
|
236 }
|
Chris@31
|
237 }
|
Chris@31
|
238 KISS_FFT_TMP_FREE(scratch);
|
Chris@31
|
239 }
|
Chris@31
|
240
|
Chris@31
|
241 static
|
Chris@31
|
242 void kf_work(
|
Chris@31
|
243 kiss_fft_cpx * Fout,
|
Chris@31
|
244 const kiss_fft_cpx * f,
|
Chris@31
|
245 const size_t fstride,
|
Chris@31
|
246 int in_stride,
|
Chris@31
|
247 int * factors,
|
Chris@31
|
248 const kiss_fft_cfg st
|
Chris@31
|
249 )
|
Chris@31
|
250 {
|
Chris@31
|
251 kiss_fft_cpx * Fout_beg=Fout;
|
Chris@31
|
252 const int p=*factors++; /* the radix */
|
Chris@31
|
253 const int m=*factors++; /* stage's fft length/p */
|
Chris@31
|
254 const kiss_fft_cpx * Fout_end = Fout + p*m;
|
Chris@31
|
255
|
Chris@31
|
256 #ifdef _OPENMP
|
Chris@31
|
257 // use openmp extensions at the
|
Chris@31
|
258 // top-level (not recursive)
|
Chris@31
|
259 if (fstride==1 && p<=5)
|
Chris@31
|
260 {
|
Chris@31
|
261 int k;
|
Chris@31
|
262
|
Chris@31
|
263 // execute the p different work units in different threads
|
Chris@31
|
264 # pragma omp parallel for
|
Chris@31
|
265 for (k=0;k<p;++k)
|
Chris@31
|
266 kf_work( Fout +k*m, f+ fstride*in_stride*k,fstride*p,in_stride,factors,st);
|
Chris@31
|
267 // all threads have joined by this point
|
Chris@31
|
268
|
Chris@31
|
269 switch (p) {
|
Chris@31
|
270 case 2: kf_bfly2(Fout,fstride,st,m); break;
|
Chris@31
|
271 case 3: kf_bfly3(Fout,fstride,st,m); break;
|
Chris@31
|
272 case 4: kf_bfly4(Fout,fstride,st,m); break;
|
Chris@31
|
273 case 5: kf_bfly5(Fout,fstride,st,m); break;
|
Chris@31
|
274 default: kf_bfly_generic(Fout,fstride,st,m,p); break;
|
Chris@31
|
275 }
|
Chris@31
|
276 return;
|
Chris@31
|
277 }
|
Chris@31
|
278 #endif
|
Chris@31
|
279
|
Chris@31
|
280 if (m==1) {
|
Chris@31
|
281 do{
|
Chris@31
|
282 *Fout = *f;
|
Chris@31
|
283 f += fstride*in_stride;
|
Chris@31
|
284 }while(++Fout != Fout_end );
|
Chris@31
|
285 }else{
|
Chris@31
|
286 do{
|
Chris@31
|
287 // recursive call:
|
Chris@31
|
288 // DFT of size m*p performed by doing
|
Chris@31
|
289 // p instances of smaller DFTs of size m,
|
Chris@31
|
290 // each one takes a decimated version of the input
|
Chris@31
|
291 kf_work( Fout , f, fstride*p, in_stride, factors,st);
|
Chris@31
|
292 f += fstride*in_stride;
|
Chris@31
|
293 }while( (Fout += m) != Fout_end );
|
Chris@31
|
294 }
|
Chris@31
|
295
|
Chris@31
|
296 Fout=Fout_beg;
|
Chris@31
|
297
|
Chris@31
|
298 // recombine the p smaller DFTs
|
Chris@31
|
299 switch (p) {
|
Chris@31
|
300 case 2: kf_bfly2(Fout,fstride,st,m); break;
|
Chris@31
|
301 case 3: kf_bfly3(Fout,fstride,st,m); break;
|
Chris@31
|
302 case 4: kf_bfly4(Fout,fstride,st,m); break;
|
Chris@31
|
303 case 5: kf_bfly5(Fout,fstride,st,m); break;
|
Chris@31
|
304 default: kf_bfly_generic(Fout,fstride,st,m,p); break;
|
Chris@31
|
305 }
|
Chris@31
|
306 }
|
Chris@31
|
307
|
Chris@31
|
308 /* facbuf is populated by p1,m1,p2,m2, ...
|
Chris@31
|
309 where
|
Chris@31
|
310 p[i] * m[i] = m[i-1]
|
Chris@31
|
311 m0 = n */
|
Chris@31
|
312 static
|
Chris@31
|
313 void kf_factor(int n,int * facbuf)
|
Chris@31
|
314 {
|
Chris@31
|
315 int p=4;
|
Chris@31
|
316 double floor_sqrt;
|
Chris@31
|
317 floor_sqrt = floor( sqrt((double)n) );
|
Chris@31
|
318
|
Chris@31
|
319 /*factor out powers of 4, powers of 2, then any remaining primes */
|
Chris@31
|
320 do {
|
Chris@31
|
321 while (n % p) {
|
Chris@31
|
322 switch (p) {
|
Chris@31
|
323 case 4: p = 2; break;
|
Chris@31
|
324 case 2: p = 3; break;
|
Chris@31
|
325 default: p += 2; break;
|
Chris@31
|
326 }
|
Chris@31
|
327 if (p > floor_sqrt)
|
Chris@31
|
328 p = n; /* no more factors, skip to end */
|
Chris@31
|
329 }
|
Chris@31
|
330 n /= p;
|
Chris@31
|
331 *facbuf++ = p;
|
Chris@31
|
332 *facbuf++ = n;
|
Chris@31
|
333 } while (n > 1);
|
Chris@31
|
334 }
|
Chris@31
|
335
|
Chris@31
|
336 /*
|
Chris@31
|
337 *
|
Chris@31
|
338 * User-callable function to allocate all necessary storage space for the fft.
|
Chris@31
|
339 *
|
Chris@31
|
340 * The return value is a contiguous block of memory, allocated with malloc. As such,
|
Chris@31
|
341 * It can be freed with free(), rather than a kiss_fft-specific function.
|
Chris@31
|
342 * */
|
Chris@31
|
343 kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem )
|
Chris@31
|
344 {
|
Chris@31
|
345 kiss_fft_cfg st=NULL;
|
Chris@31
|
346 size_t memneeded = sizeof(struct kiss_fft_state)
|
Chris@31
|
347 + sizeof(kiss_fft_cpx)*(nfft-1); /* twiddle factors*/
|
Chris@31
|
348
|
Chris@31
|
349 if ( lenmem==NULL ) {
|
Chris@31
|
350 st = ( kiss_fft_cfg)KISS_FFT_MALLOC( memneeded );
|
Chris@31
|
351 }else{
|
Chris@31
|
352 if (mem != NULL && *lenmem >= memneeded)
|
Chris@31
|
353 st = (kiss_fft_cfg)mem;
|
Chris@31
|
354 *lenmem = memneeded;
|
Chris@31
|
355 }
|
Chris@31
|
356 if (st) {
|
Chris@31
|
357 int i;
|
Chris@31
|
358 st->nfft=nfft;
|
Chris@31
|
359 st->inverse = inverse_fft;
|
Chris@31
|
360
|
Chris@31
|
361 for (i=0;i<nfft;++i) {
|
Chris@31
|
362 const double pi=3.141592653589793238462643383279502884197169399375105820974944;
|
Chris@31
|
363 double phase = -2*pi*i / nfft;
|
Chris@31
|
364 if (st->inverse)
|
Chris@31
|
365 phase *= -1;
|
Chris@31
|
366 kf_cexp(st->twiddles+i, phase );
|
Chris@31
|
367 }
|
Chris@31
|
368
|
Chris@31
|
369 kf_factor(nfft,st->factors);
|
Chris@31
|
370 }
|
Chris@31
|
371 return st;
|
Chris@31
|
372 }
|
Chris@31
|
373
|
Chris@31
|
374
|
Chris@31
|
375 void kiss_fft_stride(kiss_fft_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride)
|
Chris@31
|
376 {
|
Chris@31
|
377 if (fin == fout) {
|
Chris@31
|
378 //NOTE: this is not really an in-place FFT algorithm.
|
Chris@31
|
379 //It just performs an out-of-place FFT into a temp buffer
|
Chris@31
|
380 kiss_fft_cpx * tmpbuf = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC( sizeof(kiss_fft_cpx)*st->nfft);
|
Chris@31
|
381 kf_work(tmpbuf,fin,1,in_stride, st->factors,st);
|
Chris@31
|
382 memcpy(fout,tmpbuf,sizeof(kiss_fft_cpx)*st->nfft);
|
Chris@31
|
383 KISS_FFT_TMP_FREE(tmpbuf);
|
Chris@31
|
384 }else{
|
Chris@31
|
385 kf_work( fout, fin, 1,in_stride, st->factors,st );
|
Chris@31
|
386 }
|
Chris@31
|
387 }
|
Chris@31
|
388
|
Chris@31
|
389 void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
|
Chris@31
|
390 {
|
Chris@31
|
391 kiss_fft_stride(cfg,fin,fout,1);
|
Chris@31
|
392 }
|
Chris@31
|
393
|
Chris@31
|
394
|
Chris@31
|
395 void kiss_fft_cleanup(void)
|
Chris@31
|
396 {
|
Chris@31
|
397 // nothing needed any more
|
Chris@31
|
398 }
|
Chris@31
|
399
|
Chris@31
|
400 int kiss_fft_next_fast_size(int n)
|
Chris@31
|
401 {
|
Chris@31
|
402 while(1) {
|
Chris@31
|
403 int m=n;
|
Chris@31
|
404 while ( (m%2) == 0 ) m/=2;
|
Chris@31
|
405 while ( (m%3) == 0 ) m/=3;
|
Chris@31
|
406 while ( (m%5) == 0 ) m/=5;
|
Chris@31
|
407 if (m<=1)
|
Chris@31
|
408 break; /* n is completely factorable by twos, threes, and fives */
|
Chris@31
|
409 n++;
|
Chris@31
|
410 }
|
Chris@31
|
411 return n;
|
Chris@31
|
412 }
|