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