xref: /aosp_15_r20/system/chre/external/kiss_fft/kiss_fft.c (revision 84e339476a462649f82315436d70fd732297a399)
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