1*59d799daSIngo Weinhold
2*59d799daSIngo Weinhold /*
3*59d799daSIngo Weinhold * M_APM - mapm_fft.c
4*59d799daSIngo Weinhold *
5*59d799daSIngo Weinhold * This FFT (Fast Fourier Transform) is from Takuya OOURA
6*59d799daSIngo Weinhold *
7*59d799daSIngo Weinhold * Copyright(C) 1996-1999 Takuya OOURA
8*59d799daSIngo Weinhold * email: ooura@mmm.t.u-tokyo.ac.jp
9*59d799daSIngo Weinhold *
10*59d799daSIngo Weinhold * See full FFT documentation below ... (MCR)
11*59d799daSIngo Weinhold *
12*59d799daSIngo Weinhold * This software is provided "as is" without express or implied warranty.
13*59d799daSIngo Weinhold */
14*59d799daSIngo Weinhold
15*59d799daSIngo Weinhold /*
16*59d799daSIngo Weinhold * $Id: mapm_fft.c,v 1.15 2007/12/03 01:37:42 mike Exp $
17*59d799daSIngo Weinhold *
18*59d799daSIngo Weinhold * This file contains the FFT based FAST MULTIPLICATION function
19*59d799daSIngo Weinhold * as well as its support functions.
20*59d799daSIngo Weinhold *
21*59d799daSIngo Weinhold * $Log: mapm_fft.c,v $
22*59d799daSIngo Weinhold * Revision 1.15 2007/12/03 01:37:42 mike
23*59d799daSIngo Weinhold * no changes
24*59d799daSIngo Weinhold *
25*59d799daSIngo Weinhold * Revision 1.14 2003/07/28 19:39:01 mike
26*59d799daSIngo Weinhold * change 16 bit constant
27*59d799daSIngo Weinhold *
28*59d799daSIngo Weinhold * Revision 1.13 2003/07/21 20:11:55 mike
29*59d799daSIngo Weinhold * Modify error messages to be in a consistent format.
30*59d799daSIngo Weinhold *
31*59d799daSIngo Weinhold * Revision 1.12 2003/05/01 21:55:36 mike
32*59d799daSIngo Weinhold * remove math.h
33*59d799daSIngo Weinhold *
34*59d799daSIngo Weinhold * Revision 1.11 2003/03/31 22:10:09 mike
35*59d799daSIngo Weinhold * call generic error handling function
36*59d799daSIngo Weinhold *
37*59d799daSIngo Weinhold * Revision 1.10 2002/11/03 22:11:48 mike
38*59d799daSIngo Weinhold * Updated function parameters to use the modern style
39*59d799daSIngo Weinhold *
40*59d799daSIngo Weinhold * Revision 1.9 2001/07/16 19:16:15 mike
41*59d799daSIngo Weinhold * add function M_free_all_fft
42*59d799daSIngo Weinhold *
43*59d799daSIngo Weinhold * Revision 1.8 2000/08/01 22:23:24 mike
44*59d799daSIngo Weinhold * use sizeof(int) from function call to stop
45*59d799daSIngo Weinhold * some compilers from complaining.
46*59d799daSIngo Weinhold *
47*59d799daSIngo Weinhold * Revision 1.7 2000/07/30 22:39:21 mike
48*59d799daSIngo Weinhold * lower 16 bit malloc size
49*59d799daSIngo Weinhold *
50*59d799daSIngo Weinhold * Revision 1.6 2000/07/10 22:54:26 mike
51*59d799daSIngo Weinhold * malloc the local data arrays
52*59d799daSIngo Weinhold *
53*59d799daSIngo Weinhold * Revision 1.5 2000/07/10 00:09:02 mike
54*59d799daSIngo Weinhold * use local static arrays for smaller numbers
55*59d799daSIngo Weinhold *
56*59d799daSIngo Weinhold * Revision 1.4 2000/07/08 18:24:23 mike
57*59d799daSIngo Weinhold * minor optimization tweak
58*59d799daSIngo Weinhold *
59*59d799daSIngo Weinhold * Revision 1.3 2000/07/08 17:52:49 mike
60*59d799daSIngo Weinhold * do the FFT in base 10000 instead of MAPM numbers base 100
61*59d799daSIngo Weinhold * this runs faster and uses 1/2 the RAM
62*59d799daSIngo Weinhold *
63*59d799daSIngo Weinhold * Revision 1.2 2000/07/06 21:04:34 mike
64*59d799daSIngo Weinhold * added more comments
65*59d799daSIngo Weinhold *
66*59d799daSIngo Weinhold * Revision 1.1 2000/07/06 20:42:05 mike
67*59d799daSIngo Weinhold * Initial revision
68*59d799daSIngo Weinhold */
69*59d799daSIngo Weinhold
70*59d799daSIngo Weinhold #include "m_apm_lc.h"
71*59d799daSIngo Weinhold
72*59d799daSIngo Weinhold #ifndef MM_PI_2
73*59d799daSIngo Weinhold #define MM_PI_2 1.570796326794896619231321691639751442098584699687
74*59d799daSIngo Weinhold #endif
75*59d799daSIngo Weinhold
76*59d799daSIngo Weinhold #ifndef WR5000 /* cos(MM_PI_2*0.5000) */
77*59d799daSIngo Weinhold #define WR5000 0.707106781186547524400844362104849039284835937688
78*59d799daSIngo Weinhold #endif
79*59d799daSIngo Weinhold
80*59d799daSIngo Weinhold #ifndef RDFT_LOOP_DIV /* control of the RDFT's speed & tolerance */
81*59d799daSIngo Weinhold #define RDFT_LOOP_DIV 64
82*59d799daSIngo Weinhold #endif
83*59d799daSIngo Weinhold
84*59d799daSIngo Weinhold extern void M_fast_mul_fft(UCHAR *, UCHAR *, UCHAR *, int);
85*59d799daSIngo Weinhold
86*59d799daSIngo Weinhold extern void M_rdft(int, int, double *);
87*59d799daSIngo Weinhold extern void M_bitrv2(int, double *);
88*59d799daSIngo Weinhold extern void M_cftfsub(int, double *);
89*59d799daSIngo Weinhold extern void M_cftbsub(int, double *);
90*59d799daSIngo Weinhold extern void M_rftfsub(int, double *);
91*59d799daSIngo Weinhold extern void M_rftbsub(int, double *);
92*59d799daSIngo Weinhold extern void M_cft1st(int, double *);
93*59d799daSIngo Weinhold extern void M_cftmdl(int, int, double *);
94*59d799daSIngo Weinhold
95*59d799daSIngo Weinhold static double *M_aa_array, *M_bb_array;
96*59d799daSIngo Weinhold static int M_size = -1;
97*59d799daSIngo Weinhold
98*59d799daSIngo Weinhold static char *M_fft_error_msg = "\'M_fast_mul_fft\', Out of memory";
99*59d799daSIngo Weinhold
100*59d799daSIngo Weinhold /****************************************************************************/
M_free_all_fft()101*59d799daSIngo Weinhold void M_free_all_fft()
102*59d799daSIngo Weinhold {
103*59d799daSIngo Weinhold if (M_size > 0)
104*59d799daSIngo Weinhold {
105*59d799daSIngo Weinhold MAPM_FREE(M_aa_array);
106*59d799daSIngo Weinhold MAPM_FREE(M_bb_array);
107*59d799daSIngo Weinhold M_size = -1;
108*59d799daSIngo Weinhold }
109*59d799daSIngo Weinhold }
110*59d799daSIngo Weinhold /****************************************************************************/
111*59d799daSIngo Weinhold /*
112*59d799daSIngo Weinhold * multiply 'uu' by 'vv' with nbytes each
113*59d799daSIngo Weinhold * yielding a 2*nbytes result in 'ww'.
114*59d799daSIngo Weinhold * each byte contains a base 100 'digit',
115*59d799daSIngo Weinhold * i.e.: range from 0-99.
116*59d799daSIngo Weinhold *
117*59d799daSIngo Weinhold * MSB LSB
118*59d799daSIngo Weinhold *
119*59d799daSIngo Weinhold * uu,vv [0] [1] [2] ... [N-1]
120*59d799daSIngo Weinhold * ww [0] [1] [2] ... [2N-1]
121*59d799daSIngo Weinhold */
122*59d799daSIngo Weinhold
M_fast_mul_fft(UCHAR * ww,UCHAR * uu,UCHAR * vv,int nbytes)123*59d799daSIngo Weinhold void M_fast_mul_fft(UCHAR *ww, UCHAR *uu, UCHAR *vv, int nbytes)
124*59d799daSIngo Weinhold {
125*59d799daSIngo Weinhold int mflag, i, j, nn2, nn;
126*59d799daSIngo Weinhold double carry, nnr, dtemp, *a, *b;
127*59d799daSIngo Weinhold UCHAR *w0;
128*59d799daSIngo Weinhold unsigned long ul;
129*59d799daSIngo Weinhold
130*59d799daSIngo Weinhold if (M_size < 0) /* if first time in, setup working arrays */
131*59d799daSIngo Weinhold {
132*59d799daSIngo Weinhold if (M_get_sizeof_int() == 2) /* if still using 16 bit compilers */
133*59d799daSIngo Weinhold M_size = 516;
134*59d799daSIngo Weinhold else
135*59d799daSIngo Weinhold M_size = 8200;
136*59d799daSIngo Weinhold
137*59d799daSIngo Weinhold M_aa_array = (double *)MAPM_MALLOC(M_size * sizeof(double));
138*59d799daSIngo Weinhold M_bb_array = (double *)MAPM_MALLOC(M_size * sizeof(double));
139*59d799daSIngo Weinhold
140*59d799daSIngo Weinhold if ((M_aa_array == NULL) || (M_bb_array == NULL))
141*59d799daSIngo Weinhold {
142*59d799daSIngo Weinhold /* fatal, this does not return */
143*59d799daSIngo Weinhold
144*59d799daSIngo Weinhold M_apm_log_error_msg(M_APM_FATAL, M_fft_error_msg);
145*59d799daSIngo Weinhold }
146*59d799daSIngo Weinhold }
147*59d799daSIngo Weinhold
148*59d799daSIngo Weinhold nn = nbytes;
149*59d799daSIngo Weinhold nn2 = nbytes >> 1;
150*59d799daSIngo Weinhold
151*59d799daSIngo Weinhold if (nn > M_size)
152*59d799daSIngo Weinhold {
153*59d799daSIngo Weinhold mflag = TRUE;
154*59d799daSIngo Weinhold
155*59d799daSIngo Weinhold a = (double *)MAPM_MALLOC((nn + 8) * sizeof(double));
156*59d799daSIngo Weinhold b = (double *)MAPM_MALLOC((nn + 8) * sizeof(double));
157*59d799daSIngo Weinhold
158*59d799daSIngo Weinhold if ((a == NULL) || (b == NULL))
159*59d799daSIngo Weinhold {
160*59d799daSIngo Weinhold /* fatal, this does not return */
161*59d799daSIngo Weinhold
162*59d799daSIngo Weinhold M_apm_log_error_msg(M_APM_FATAL, M_fft_error_msg);
163*59d799daSIngo Weinhold }
164*59d799daSIngo Weinhold }
165*59d799daSIngo Weinhold else
166*59d799daSIngo Weinhold {
167*59d799daSIngo Weinhold mflag = FALSE;
168*59d799daSIngo Weinhold
169*59d799daSIngo Weinhold a = M_aa_array;
170*59d799daSIngo Weinhold b = M_bb_array;
171*59d799daSIngo Weinhold }
172*59d799daSIngo Weinhold
173*59d799daSIngo Weinhold /*
174*59d799daSIngo Weinhold * convert normal base 100 MAPM numbers to base 10000
175*59d799daSIngo Weinhold * for the FFT operation.
176*59d799daSIngo Weinhold */
177*59d799daSIngo Weinhold
178*59d799daSIngo Weinhold i = 0;
179*59d799daSIngo Weinhold for (j=0; j < nn2; j++)
180*59d799daSIngo Weinhold {
181*59d799daSIngo Weinhold a[j] = (double)((int)uu[i] * 100 + uu[i+1]);
182*59d799daSIngo Weinhold b[j] = (double)((int)vv[i] * 100 + vv[i+1]);
183*59d799daSIngo Weinhold i += 2;
184*59d799daSIngo Weinhold }
185*59d799daSIngo Weinhold
186*59d799daSIngo Weinhold /* zero fill the second half of the arrays */
187*59d799daSIngo Weinhold
188*59d799daSIngo Weinhold for (j=nn2; j < nn; j++)
189*59d799daSIngo Weinhold {
190*59d799daSIngo Weinhold a[j] = 0.0;
191*59d799daSIngo Weinhold b[j] = 0.0;
192*59d799daSIngo Weinhold }
193*59d799daSIngo Weinhold
194*59d799daSIngo Weinhold /* perform the forward Fourier transforms for both numbers */
195*59d799daSIngo Weinhold
196*59d799daSIngo Weinhold M_rdft(nn, 1, a);
197*59d799daSIngo Weinhold M_rdft(nn, 1, b);
198*59d799daSIngo Weinhold
199*59d799daSIngo Weinhold /* perform the convolution ... */
200*59d799daSIngo Weinhold
201*59d799daSIngo Weinhold b[0] *= a[0];
202*59d799daSIngo Weinhold b[1] *= a[1];
203*59d799daSIngo Weinhold
204*59d799daSIngo Weinhold for (j=3; j <= nn; j += 2)
205*59d799daSIngo Weinhold {
206*59d799daSIngo Weinhold dtemp = b[j-1];
207*59d799daSIngo Weinhold b[j-1] = dtemp * a[j-1] - b[j] * a[j];
208*59d799daSIngo Weinhold b[j] = dtemp * a[j] + b[j] * a[j-1];
209*59d799daSIngo Weinhold }
210*59d799daSIngo Weinhold
211*59d799daSIngo Weinhold /* perform the inverse transform on the result */
212*59d799daSIngo Weinhold
213*59d799daSIngo Weinhold M_rdft(nn, -1, b);
214*59d799daSIngo Weinhold
215*59d799daSIngo Weinhold /* perform a final pass to release all the carries */
216*59d799daSIngo Weinhold /* we are still in base 10000 at this point */
217*59d799daSIngo Weinhold
218*59d799daSIngo Weinhold carry = 0.0;
219*59d799daSIngo Weinhold j = nn;
220*59d799daSIngo Weinhold nnr = 2.0 / (double)nn;
221*59d799daSIngo Weinhold
222*59d799daSIngo Weinhold while (1)
223*59d799daSIngo Weinhold {
224*59d799daSIngo Weinhold dtemp = b[--j] * nnr + carry + 0.5;
225*59d799daSIngo Weinhold ul = (unsigned long)(dtemp * 1.0E-4);
226*59d799daSIngo Weinhold carry = (double)ul;
227*59d799daSIngo Weinhold b[j] = dtemp - carry * 10000.0;
228*59d799daSIngo Weinhold
229*59d799daSIngo Weinhold if (j == 0)
230*59d799daSIngo Weinhold break;
231*59d799daSIngo Weinhold }
232*59d799daSIngo Weinhold
233*59d799daSIngo Weinhold /* copy result to our destination after converting back to base 100 */
234*59d799daSIngo Weinhold
235*59d799daSIngo Weinhold w0 = ww;
236*59d799daSIngo Weinhold M_get_div_rem((int)ul, w0, (w0 + 1));
237*59d799daSIngo Weinhold
238*59d799daSIngo Weinhold for (j=0; j <= (nn - 2); j++)
239*59d799daSIngo Weinhold {
240*59d799daSIngo Weinhold w0 += 2;
241*59d799daSIngo Weinhold M_get_div_rem((int)b[j], w0, (w0 + 1));
242*59d799daSIngo Weinhold }
243*59d799daSIngo Weinhold
244*59d799daSIngo Weinhold if (mflag)
245*59d799daSIngo Weinhold {
246*59d799daSIngo Weinhold MAPM_FREE(b);
247*59d799daSIngo Weinhold MAPM_FREE(a);
248*59d799daSIngo Weinhold }
249*59d799daSIngo Weinhold }
250*59d799daSIngo Weinhold /****************************************************************************/
251*59d799daSIngo Weinhold
252*59d799daSIngo Weinhold /*
253*59d799daSIngo Weinhold * The following info is from Takuya OOURA's documentation :
254*59d799daSIngo Weinhold *
255*59d799daSIngo Weinhold * NOTE : MAPM only uses the 'RDFT' function (as well as the
256*59d799daSIngo Weinhold * functions RDFT calls). All the code from here down
257*59d799daSIngo Weinhold * in this file is from Takuya OOURA. The only change I
258*59d799daSIngo Weinhold * made was to add 'M_' in front of all the functions
259*59d799daSIngo Weinhold * I used. This was to guard against any possible
260*59d799daSIngo Weinhold * name collisions in the future.
261*59d799daSIngo Weinhold *
262*59d799daSIngo Weinhold * MCR 06 July 2000
263*59d799daSIngo Weinhold *
264*59d799daSIngo Weinhold *
265*59d799daSIngo Weinhold * General Purpose FFT (Fast Fourier/Cosine/Sine Transform) Package
266*59d799daSIngo Weinhold *
267*59d799daSIngo Weinhold * Description:
268*59d799daSIngo Weinhold * A package to calculate Discrete Fourier/Cosine/Sine Transforms of
269*59d799daSIngo Weinhold * 1-dimensional sequences of length 2^N.
270*59d799daSIngo Weinhold *
271*59d799daSIngo Weinhold * fft4g_h.c : FFT Package in C - Simple Version I (radix 4,2)
272*59d799daSIngo Weinhold *
273*59d799daSIngo Weinhold * rdft: Real Discrete Fourier Transform
274*59d799daSIngo Weinhold *
275*59d799daSIngo Weinhold * Method:
276*59d799daSIngo Weinhold * -------- rdft --------
277*59d799daSIngo Weinhold * A method with a following butterfly operation appended to "cdft".
278*59d799daSIngo Weinhold * In forward transform :
279*59d799daSIngo Weinhold * A[k] = sum_j=0^n-1 a[j]*W(n)^(j*k), 0<=k<=n/2,
280*59d799daSIngo Weinhold * W(n) = exp(2*pi*i/n),
281*59d799daSIngo Weinhold * this routine makes an array x[] :
282*59d799daSIngo Weinhold * x[j] = a[2*j] + i*a[2*j+1], 0<=j<n/2
283*59d799daSIngo Weinhold * and calls "cdft" of length n/2 :
284*59d799daSIngo Weinhold * X[k] = sum_j=0^n/2-1 x[j] * W(n/2)^(j*k), 0<=k<n.
285*59d799daSIngo Weinhold * The result A[k] are :
286*59d799daSIngo Weinhold * A[k] = X[k] - (1+i*W(n)^k)/2 * (X[k]-conjg(X[n/2-k])),
287*59d799daSIngo Weinhold * A[n/2-k] = X[n/2-k] +
288*59d799daSIngo Weinhold * conjg((1+i*W(n)^k)/2 * (X[k]-conjg(X[n/2-k]))),
289*59d799daSIngo Weinhold * 0<=k<=n/2
290*59d799daSIngo Weinhold * (notes: conjg() is a complex conjugate, X[n/2]=X[0]).
291*59d799daSIngo Weinhold * ----------------------
292*59d799daSIngo Weinhold *
293*59d799daSIngo Weinhold * Reference:
294*59d799daSIngo Weinhold * * Masatake MORI, Makoto NATORI, Tatuo TORII: Suchikeisan,
295*59d799daSIngo Weinhold * Iwanamikouzajyouhoukagaku18, Iwanami, 1982 (Japanese)
296*59d799daSIngo Weinhold * * Henri J. Nussbaumer: Fast Fourier Transform and Convolution
297*59d799daSIngo Weinhold * Algorithms, Springer Verlag, 1982
298*59d799daSIngo Weinhold * * C. S. Burrus, Notes on the FFT (with large FFT paper list)
299*59d799daSIngo Weinhold * http://www-dsp.rice.edu/research/fft/fftnote.asc
300*59d799daSIngo Weinhold *
301*59d799daSIngo Weinhold * Copyright:
302*59d799daSIngo Weinhold * Copyright(C) 1996-1999 Takuya OOURA
303*59d799daSIngo Weinhold * email: ooura@mmm.t.u-tokyo.ac.jp
304*59d799daSIngo Weinhold * download: http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html
305*59d799daSIngo Weinhold * You may use, copy, modify this code for any purpose and
306*59d799daSIngo Weinhold * without fee. You may distribute this ORIGINAL package.
307*59d799daSIngo Weinhold */
308*59d799daSIngo Weinhold
309*59d799daSIngo Weinhold /*
310*59d799daSIngo Weinhold
311*59d799daSIngo Weinhold functions
312*59d799daSIngo Weinhold rdft: Real Discrete Fourier Transform
313*59d799daSIngo Weinhold
314*59d799daSIngo Weinhold function prototypes
315*59d799daSIngo Weinhold void rdft(int, int, double *);
316*59d799daSIngo Weinhold
317*59d799daSIngo Weinhold -------- Real DFT / Inverse of Real DFT --------
318*59d799daSIngo Weinhold [definition]
319*59d799daSIngo Weinhold <case1> RDFT
320*59d799daSIngo Weinhold R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2
321*59d799daSIngo Weinhold I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0<k<n/2
322*59d799daSIngo Weinhold <case2> IRDFT (excluding scale)
323*59d799daSIngo Weinhold a[k] = (R[0] + R[n/2]*cos(pi*k))/2 +
324*59d799daSIngo Weinhold sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) +
325*59d799daSIngo Weinhold sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k<n
326*59d799daSIngo Weinhold [usage]
327*59d799daSIngo Weinhold <case1>
328*59d799daSIngo Weinhold rdft(n, 1, a);
329*59d799daSIngo Weinhold <case2>
330*59d799daSIngo Weinhold rdft(n, -1, a);
331*59d799daSIngo Weinhold [parameters]
332*59d799daSIngo Weinhold n :data length (int)
333*59d799daSIngo Weinhold n >= 2, n = power of 2
334*59d799daSIngo Weinhold a[0...n-1] :input/output data (double *)
335*59d799daSIngo Weinhold <case1>
336*59d799daSIngo Weinhold output data
337*59d799daSIngo Weinhold a[2*k] = R[k], 0<=k<n/2
338*59d799daSIngo Weinhold a[2*k+1] = I[k], 0<k<n/2
339*59d799daSIngo Weinhold a[1] = R[n/2]
340*59d799daSIngo Weinhold <case2>
341*59d799daSIngo Weinhold input data
342*59d799daSIngo Weinhold a[2*j] = R[j], 0<=j<n/2
343*59d799daSIngo Weinhold a[2*j+1] = I[j], 0<j<n/2
344*59d799daSIngo Weinhold a[1] = R[n/2]
345*59d799daSIngo Weinhold [remark]
346*59d799daSIngo Weinhold Inverse of
347*59d799daSIngo Weinhold rdft(n, 1, a);
348*59d799daSIngo Weinhold is
349*59d799daSIngo Weinhold rdft(n, -1, a);
350*59d799daSIngo Weinhold for (j = 0; j <= n - 1; j++) {
351*59d799daSIngo Weinhold a[j] *= 2.0 / n;
352*59d799daSIngo Weinhold }
353*59d799daSIngo Weinhold */
354*59d799daSIngo Weinhold
355*59d799daSIngo Weinhold
M_rdft(int n,int isgn,double * a)356*59d799daSIngo Weinhold void M_rdft(int n, int isgn, double *a)
357*59d799daSIngo Weinhold {
358*59d799daSIngo Weinhold double xi;
359*59d799daSIngo Weinhold
360*59d799daSIngo Weinhold if (isgn >= 0) {
361*59d799daSIngo Weinhold if (n > 4) {
362*59d799daSIngo Weinhold M_bitrv2(n, a);
363*59d799daSIngo Weinhold M_cftfsub(n, a);
364*59d799daSIngo Weinhold M_rftfsub(n, a);
365*59d799daSIngo Weinhold } else if (n == 4) {
366*59d799daSIngo Weinhold M_cftfsub(n, a);
367*59d799daSIngo Weinhold }
368*59d799daSIngo Weinhold xi = a[0] - a[1];
369*59d799daSIngo Weinhold a[0] += a[1];
370*59d799daSIngo Weinhold a[1] = xi;
371*59d799daSIngo Weinhold } else {
372*59d799daSIngo Weinhold a[1] = 0.5 * (a[0] - a[1]);
373*59d799daSIngo Weinhold a[0] -= a[1];
374*59d799daSIngo Weinhold if (n > 4) {
375*59d799daSIngo Weinhold M_rftbsub(n, a);
376*59d799daSIngo Weinhold M_bitrv2(n, a);
377*59d799daSIngo Weinhold M_cftbsub(n, a);
378*59d799daSIngo Weinhold } else if (n == 4) {
379*59d799daSIngo Weinhold M_cftfsub(n, a);
380*59d799daSIngo Weinhold }
381*59d799daSIngo Weinhold }
382*59d799daSIngo Weinhold }
383*59d799daSIngo Weinhold
384*59d799daSIngo Weinhold
385*59d799daSIngo Weinhold
M_bitrv2(int n,double * a)386*59d799daSIngo Weinhold void M_bitrv2(int n, double *a)
387*59d799daSIngo Weinhold {
388*59d799daSIngo Weinhold int j0, k0, j1, k1, l, m, i, j, k;
389*59d799daSIngo Weinhold double xr, xi, yr, yi;
390*59d799daSIngo Weinhold
391*59d799daSIngo Weinhold l = n >> 2;
392*59d799daSIngo Weinhold m = 2;
393*59d799daSIngo Weinhold while (m < l) {
394*59d799daSIngo Weinhold l >>= 1;
395*59d799daSIngo Weinhold m <<= 1;
396*59d799daSIngo Weinhold }
397*59d799daSIngo Weinhold if (m == l) {
398*59d799daSIngo Weinhold j0 = 0;
399*59d799daSIngo Weinhold for (k0 = 0; k0 < m; k0 += 2) {
400*59d799daSIngo Weinhold k = k0;
401*59d799daSIngo Weinhold for (j = j0; j < j0 + k0; j += 2) {
402*59d799daSIngo Weinhold xr = a[j];
403*59d799daSIngo Weinhold xi = a[j + 1];
404*59d799daSIngo Weinhold yr = a[k];
405*59d799daSIngo Weinhold yi = a[k + 1];
406*59d799daSIngo Weinhold a[j] = yr;
407*59d799daSIngo Weinhold a[j + 1] = yi;
408*59d799daSIngo Weinhold a[k] = xr;
409*59d799daSIngo Weinhold a[k + 1] = xi;
410*59d799daSIngo Weinhold j1 = j + m;
411*59d799daSIngo Weinhold k1 = k + 2 * m;
412*59d799daSIngo Weinhold xr = a[j1];
413*59d799daSIngo Weinhold xi = a[j1 + 1];
414*59d799daSIngo Weinhold yr = a[k1];
415*59d799daSIngo Weinhold yi = a[k1 + 1];
416*59d799daSIngo Weinhold a[j1] = yr;
417*59d799daSIngo Weinhold a[j1 + 1] = yi;
418*59d799daSIngo Weinhold a[k1] = xr;
419*59d799daSIngo Weinhold a[k1 + 1] = xi;
420*59d799daSIngo Weinhold j1 += m;
421*59d799daSIngo Weinhold k1 -= m;
422*59d799daSIngo Weinhold xr = a[j1];
423*59d799daSIngo Weinhold xi = a[j1 + 1];
424*59d799daSIngo Weinhold yr = a[k1];
425*59d799daSIngo Weinhold yi = a[k1 + 1];
426*59d799daSIngo Weinhold a[j1] = yr;
427*59d799daSIngo Weinhold a[j1 + 1] = yi;
428*59d799daSIngo Weinhold a[k1] = xr;
429*59d799daSIngo Weinhold a[k1 + 1] = xi;
430*59d799daSIngo Weinhold j1 += m;
431*59d799daSIngo Weinhold k1 += 2 * m;
432*59d799daSIngo Weinhold xr = a[j1];
433*59d799daSIngo Weinhold xi = a[j1 + 1];
434*59d799daSIngo Weinhold yr = a[k1];
435*59d799daSIngo Weinhold yi = a[k1 + 1];
436*59d799daSIngo Weinhold a[j1] = yr;
437*59d799daSIngo Weinhold a[j1 + 1] = yi;
438*59d799daSIngo Weinhold a[k1] = xr;
439*59d799daSIngo Weinhold a[k1 + 1] = xi;
440*59d799daSIngo Weinhold for (i = n >> 1; i > (k ^= i); i >>= 1);
441*59d799daSIngo Weinhold }
442*59d799daSIngo Weinhold j1 = j0 + k0 + m;
443*59d799daSIngo Weinhold k1 = j1 + m;
444*59d799daSIngo Weinhold xr = a[j1];
445*59d799daSIngo Weinhold xi = a[j1 + 1];
446*59d799daSIngo Weinhold yr = a[k1];
447*59d799daSIngo Weinhold yi = a[k1 + 1];
448*59d799daSIngo Weinhold a[j1] = yr;
449*59d799daSIngo Weinhold a[j1 + 1] = yi;
450*59d799daSIngo Weinhold a[k1] = xr;
451*59d799daSIngo Weinhold a[k1 + 1] = xi;
452*59d799daSIngo Weinhold for (i = n >> 1; i > (j0 ^= i); i >>= 1);
453*59d799daSIngo Weinhold }
454*59d799daSIngo Weinhold } else {
455*59d799daSIngo Weinhold j0 = 0;
456*59d799daSIngo Weinhold for (k0 = 2; k0 < m; k0 += 2) {
457*59d799daSIngo Weinhold for (i = n >> 1; i > (j0 ^= i); i >>= 1);
458*59d799daSIngo Weinhold k = k0;
459*59d799daSIngo Weinhold for (j = j0; j < j0 + k0; j += 2) {
460*59d799daSIngo Weinhold xr = a[j];
461*59d799daSIngo Weinhold xi = a[j + 1];
462*59d799daSIngo Weinhold yr = a[k];
463*59d799daSIngo Weinhold yi = a[k + 1];
464*59d799daSIngo Weinhold a[j] = yr;
465*59d799daSIngo Weinhold a[j + 1] = yi;
466*59d799daSIngo Weinhold a[k] = xr;
467*59d799daSIngo Weinhold a[k + 1] = xi;
468*59d799daSIngo Weinhold j1 = j + m;
469*59d799daSIngo Weinhold k1 = k + m;
470*59d799daSIngo Weinhold xr = a[j1];
471*59d799daSIngo Weinhold xi = a[j1 + 1];
472*59d799daSIngo Weinhold yr = a[k1];
473*59d799daSIngo Weinhold yi = a[k1 + 1];
474*59d799daSIngo Weinhold a[j1] = yr;
475*59d799daSIngo Weinhold a[j1 + 1] = yi;
476*59d799daSIngo Weinhold a[k1] = xr;
477*59d799daSIngo Weinhold a[k1 + 1] = xi;
478*59d799daSIngo Weinhold for (i = n >> 1; i > (k ^= i); i >>= 1);
479*59d799daSIngo Weinhold }
480*59d799daSIngo Weinhold }
481*59d799daSIngo Weinhold }
482*59d799daSIngo Weinhold }
483*59d799daSIngo Weinhold
484*59d799daSIngo Weinhold
485*59d799daSIngo Weinhold
M_cftfsub(int n,double * a)486*59d799daSIngo Weinhold void M_cftfsub(int n, double *a)
487*59d799daSIngo Weinhold {
488*59d799daSIngo Weinhold int j, j1, j2, j3, l;
489*59d799daSIngo Weinhold double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
490*59d799daSIngo Weinhold
491*59d799daSIngo Weinhold l = 2;
492*59d799daSIngo Weinhold if (n > 8) {
493*59d799daSIngo Weinhold M_cft1st(n, a);
494*59d799daSIngo Weinhold l = 8;
495*59d799daSIngo Weinhold while ((l << 2) < n) {
496*59d799daSIngo Weinhold M_cftmdl(n, l, a);
497*59d799daSIngo Weinhold l <<= 2;
498*59d799daSIngo Weinhold }
499*59d799daSIngo Weinhold }
500*59d799daSIngo Weinhold if ((l << 2) == n) {
501*59d799daSIngo Weinhold for (j = 0; j < l; j += 2) {
502*59d799daSIngo Weinhold j1 = j + l;
503*59d799daSIngo Weinhold j2 = j1 + l;
504*59d799daSIngo Weinhold j3 = j2 + l;
505*59d799daSIngo Weinhold x0r = a[j] + a[j1];
506*59d799daSIngo Weinhold x0i = a[j + 1] + a[j1 + 1];
507*59d799daSIngo Weinhold x1r = a[j] - a[j1];
508*59d799daSIngo Weinhold x1i = a[j + 1] - a[j1 + 1];
509*59d799daSIngo Weinhold x2r = a[j2] + a[j3];
510*59d799daSIngo Weinhold x2i = a[j2 + 1] + a[j3 + 1];
511*59d799daSIngo Weinhold x3r = a[j2] - a[j3];
512*59d799daSIngo Weinhold x3i = a[j2 + 1] - a[j3 + 1];
513*59d799daSIngo Weinhold a[j] = x0r + x2r;
514*59d799daSIngo Weinhold a[j + 1] = x0i + x2i;
515*59d799daSIngo Weinhold a[j2] = x0r - x2r;
516*59d799daSIngo Weinhold a[j2 + 1] = x0i - x2i;
517*59d799daSIngo Weinhold a[j1] = x1r - x3i;
518*59d799daSIngo Weinhold a[j1 + 1] = x1i + x3r;
519*59d799daSIngo Weinhold a[j3] = x1r + x3i;
520*59d799daSIngo Weinhold a[j3 + 1] = x1i - x3r;
521*59d799daSIngo Weinhold }
522*59d799daSIngo Weinhold } else {
523*59d799daSIngo Weinhold for (j = 0; j < l; j += 2) {
524*59d799daSIngo Weinhold j1 = j + l;
525*59d799daSIngo Weinhold x0r = a[j] - a[j1];
526*59d799daSIngo Weinhold x0i = a[j + 1] - a[j1 + 1];
527*59d799daSIngo Weinhold a[j] += a[j1];
528*59d799daSIngo Weinhold a[j + 1] += a[j1 + 1];
529*59d799daSIngo Weinhold a[j1] = x0r;
530*59d799daSIngo Weinhold a[j1 + 1] = x0i;
531*59d799daSIngo Weinhold }
532*59d799daSIngo Weinhold }
533*59d799daSIngo Weinhold }
534*59d799daSIngo Weinhold
535*59d799daSIngo Weinhold
536*59d799daSIngo Weinhold
M_cftbsub(int n,double * a)537*59d799daSIngo Weinhold void M_cftbsub(int n, double *a)
538*59d799daSIngo Weinhold {
539*59d799daSIngo Weinhold int j, j1, j2, j3, l;
540*59d799daSIngo Weinhold double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
541*59d799daSIngo Weinhold
542*59d799daSIngo Weinhold l = 2;
543*59d799daSIngo Weinhold if (n > 8) {
544*59d799daSIngo Weinhold M_cft1st(n, a);
545*59d799daSIngo Weinhold l = 8;
546*59d799daSIngo Weinhold while ((l << 2) < n) {
547*59d799daSIngo Weinhold M_cftmdl(n, l, a);
548*59d799daSIngo Weinhold l <<= 2;
549*59d799daSIngo Weinhold }
550*59d799daSIngo Weinhold }
551*59d799daSIngo Weinhold if ((l << 2) == n) {
552*59d799daSIngo Weinhold for (j = 0; j < l; j += 2) {
553*59d799daSIngo Weinhold j1 = j + l;
554*59d799daSIngo Weinhold j2 = j1 + l;
555*59d799daSIngo Weinhold j3 = j2 + l;
556*59d799daSIngo Weinhold x0r = a[j] + a[j1];
557*59d799daSIngo Weinhold x0i = -a[j + 1] - a[j1 + 1];
558*59d799daSIngo Weinhold x1r = a[j] - a[j1];
559*59d799daSIngo Weinhold x1i = -a[j + 1] + a[j1 + 1];
560*59d799daSIngo Weinhold x2r = a[j2] + a[j3];
561*59d799daSIngo Weinhold x2i = a[j2 + 1] + a[j3 + 1];
562*59d799daSIngo Weinhold x3r = a[j2] - a[j3];
563*59d799daSIngo Weinhold x3i = a[j2 + 1] - a[j3 + 1];
564*59d799daSIngo Weinhold a[j] = x0r + x2r;
565*59d799daSIngo Weinhold a[j + 1] = x0i - x2i;
566*59d799daSIngo Weinhold a[j2] = x0r - x2r;
567*59d799daSIngo Weinhold a[j2 + 1] = x0i + x2i;
568*59d799daSIngo Weinhold a[j1] = x1r - x3i;
569*59d799daSIngo Weinhold a[j1 + 1] = x1i - x3r;
570*59d799daSIngo Weinhold a[j3] = x1r + x3i;
571*59d799daSIngo Weinhold a[j3 + 1] = x1i + x3r;
572*59d799daSIngo Weinhold }
573*59d799daSIngo Weinhold } else {
574*59d799daSIngo Weinhold for (j = 0; j < l; j += 2) {
575*59d799daSIngo Weinhold j1 = j + l;
576*59d799daSIngo Weinhold x0r = a[j] - a[j1];
577*59d799daSIngo Weinhold x0i = -a[j + 1] + a[j1 + 1];
578*59d799daSIngo Weinhold a[j] += a[j1];
579*59d799daSIngo Weinhold a[j + 1] = -a[j + 1] - a[j1 + 1];
580*59d799daSIngo Weinhold a[j1] = x0r;
581*59d799daSIngo Weinhold a[j1 + 1] = x0i;
582*59d799daSIngo Weinhold }
583*59d799daSIngo Weinhold }
584*59d799daSIngo Weinhold }
585*59d799daSIngo Weinhold
586*59d799daSIngo Weinhold
587*59d799daSIngo Weinhold
M_cft1st(int n,double * a)588*59d799daSIngo Weinhold void M_cft1st(int n, double *a)
589*59d799daSIngo Weinhold {
590*59d799daSIngo Weinhold int j, kj, kr;
591*59d799daSIngo Weinhold double ew, wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i;
592*59d799daSIngo Weinhold double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
593*59d799daSIngo Weinhold
594*59d799daSIngo Weinhold x0r = a[0] + a[2];
595*59d799daSIngo Weinhold x0i = a[1] + a[3];
596*59d799daSIngo Weinhold x1r = a[0] - a[2];
597*59d799daSIngo Weinhold x1i = a[1] - a[3];
598*59d799daSIngo Weinhold x2r = a[4] + a[6];
599*59d799daSIngo Weinhold x2i = a[5] + a[7];
600*59d799daSIngo Weinhold x3r = a[4] - a[6];
601*59d799daSIngo Weinhold x3i = a[5] - a[7];
602*59d799daSIngo Weinhold a[0] = x0r + x2r;
603*59d799daSIngo Weinhold a[1] = x0i + x2i;
604*59d799daSIngo Weinhold a[4] = x0r - x2r;
605*59d799daSIngo Weinhold a[5] = x0i - x2i;
606*59d799daSIngo Weinhold a[2] = x1r - x3i;
607*59d799daSIngo Weinhold a[3] = x1i + x3r;
608*59d799daSIngo Weinhold a[6] = x1r + x3i;
609*59d799daSIngo Weinhold a[7] = x1i - x3r;
610*59d799daSIngo Weinhold wn4r = WR5000;
611*59d799daSIngo Weinhold x0r = a[8] + a[10];
612*59d799daSIngo Weinhold x0i = a[9] + a[11];
613*59d799daSIngo Weinhold x1r = a[8] - a[10];
614*59d799daSIngo Weinhold x1i = a[9] - a[11];
615*59d799daSIngo Weinhold x2r = a[12] + a[14];
616*59d799daSIngo Weinhold x2i = a[13] + a[15];
617*59d799daSIngo Weinhold x3r = a[12] - a[14];
618*59d799daSIngo Weinhold x3i = a[13] - a[15];
619*59d799daSIngo Weinhold a[8] = x0r + x2r;
620*59d799daSIngo Weinhold a[9] = x0i + x2i;
621*59d799daSIngo Weinhold a[12] = x2i - x0i;
622*59d799daSIngo Weinhold a[13] = x0r - x2r;
623*59d799daSIngo Weinhold x0r = x1r - x3i;
624*59d799daSIngo Weinhold x0i = x1i + x3r;
625*59d799daSIngo Weinhold a[10] = wn4r * (x0r - x0i);
626*59d799daSIngo Weinhold a[11] = wn4r * (x0r + x0i);
627*59d799daSIngo Weinhold x0r = x3i + x1r;
628*59d799daSIngo Weinhold x0i = x3r - x1i;
629*59d799daSIngo Weinhold a[14] = wn4r * (x0i - x0r);
630*59d799daSIngo Weinhold a[15] = wn4r * (x0i + x0r);
631*59d799daSIngo Weinhold ew = MM_PI_2 / n;
632*59d799daSIngo Weinhold kr = 0;
633*59d799daSIngo Weinhold for (j = 16; j < n; j += 16) {
634*59d799daSIngo Weinhold for (kj = n >> 2; kj > (kr ^= kj); kj >>= 1);
635*59d799daSIngo Weinhold wk1r = cos(ew * kr);
636*59d799daSIngo Weinhold wk1i = sin(ew * kr);
637*59d799daSIngo Weinhold wk2r = 1 - 2 * wk1i * wk1i;
638*59d799daSIngo Weinhold wk2i = 2 * wk1i * wk1r;
639*59d799daSIngo Weinhold wk3r = wk1r - 2 * wk2i * wk1i;
640*59d799daSIngo Weinhold wk3i = 2 * wk2i * wk1r - wk1i;
641*59d799daSIngo Weinhold x0r = a[j] + a[j + 2];
642*59d799daSIngo Weinhold x0i = a[j + 1] + a[j + 3];
643*59d799daSIngo Weinhold x1r = a[j] - a[j + 2];
644*59d799daSIngo Weinhold x1i = a[j + 1] - a[j + 3];
645*59d799daSIngo Weinhold x2r = a[j + 4] + a[j + 6];
646*59d799daSIngo Weinhold x2i = a[j + 5] + a[j + 7];
647*59d799daSIngo Weinhold x3r = a[j + 4] - a[j + 6];
648*59d799daSIngo Weinhold x3i = a[j + 5] - a[j + 7];
649*59d799daSIngo Weinhold a[j] = x0r + x2r;
650*59d799daSIngo Weinhold a[j + 1] = x0i + x2i;
651*59d799daSIngo Weinhold x0r -= x2r;
652*59d799daSIngo Weinhold x0i -= x2i;
653*59d799daSIngo Weinhold a[j + 4] = wk2r * x0r - wk2i * x0i;
654*59d799daSIngo Weinhold a[j + 5] = wk2r * x0i + wk2i * x0r;
655*59d799daSIngo Weinhold x0r = x1r - x3i;
656*59d799daSIngo Weinhold x0i = x1i + x3r;
657*59d799daSIngo Weinhold a[j + 2] = wk1r * x0r - wk1i * x0i;
658*59d799daSIngo Weinhold a[j + 3] = wk1r * x0i + wk1i * x0r;
659*59d799daSIngo Weinhold x0r = x1r + x3i;
660*59d799daSIngo Weinhold x0i = x1i - x3r;
661*59d799daSIngo Weinhold a[j + 6] = wk3r * x0r - wk3i * x0i;
662*59d799daSIngo Weinhold a[j + 7] = wk3r * x0i + wk3i * x0r;
663*59d799daSIngo Weinhold x0r = wn4r * (wk1r - wk1i);
664*59d799daSIngo Weinhold wk1i = wn4r * (wk1r + wk1i);
665*59d799daSIngo Weinhold wk1r = x0r;
666*59d799daSIngo Weinhold wk3r = wk1r - 2 * wk2r * wk1i;
667*59d799daSIngo Weinhold wk3i = 2 * wk2r * wk1r - wk1i;
668*59d799daSIngo Weinhold x0r = a[j + 8] + a[j + 10];
669*59d799daSIngo Weinhold x0i = a[j + 9] + a[j + 11];
670*59d799daSIngo Weinhold x1r = a[j + 8] - a[j + 10];
671*59d799daSIngo Weinhold x1i = a[j + 9] - a[j + 11];
672*59d799daSIngo Weinhold x2r = a[j + 12] + a[j + 14];
673*59d799daSIngo Weinhold x2i = a[j + 13] + a[j + 15];
674*59d799daSIngo Weinhold x3r = a[j + 12] - a[j + 14];
675*59d799daSIngo Weinhold x3i = a[j + 13] - a[j + 15];
676*59d799daSIngo Weinhold a[j + 8] = x0r + x2r;
677*59d799daSIngo Weinhold a[j + 9] = x0i + x2i;
678*59d799daSIngo Weinhold x0r -= x2r;
679*59d799daSIngo Weinhold x0i -= x2i;
680*59d799daSIngo Weinhold a[j + 12] = -wk2i * x0r - wk2r * x0i;
681*59d799daSIngo Weinhold a[j + 13] = -wk2i * x0i + wk2r * x0r;
682*59d799daSIngo Weinhold x0r = x1r - x3i;
683*59d799daSIngo Weinhold x0i = x1i + x3r;
684*59d799daSIngo Weinhold a[j + 10] = wk1r * x0r - wk1i * x0i;
685*59d799daSIngo Weinhold a[j + 11] = wk1r * x0i + wk1i * x0r;
686*59d799daSIngo Weinhold x0r = x1r + x3i;
687*59d799daSIngo Weinhold x0i = x1i - x3r;
688*59d799daSIngo Weinhold a[j + 14] = wk3r * x0r - wk3i * x0i;
689*59d799daSIngo Weinhold a[j + 15] = wk3r * x0i + wk3i * x0r;
690*59d799daSIngo Weinhold }
691*59d799daSIngo Weinhold }
692*59d799daSIngo Weinhold
693*59d799daSIngo Weinhold
694*59d799daSIngo Weinhold
M_cftmdl(int n,int l,double * a)695*59d799daSIngo Weinhold void M_cftmdl(int n, int l, double *a)
696*59d799daSIngo Weinhold {
697*59d799daSIngo Weinhold int j, j1, j2, j3, k, kj, kr, m, m2;
698*59d799daSIngo Weinhold double ew, wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i;
699*59d799daSIngo Weinhold double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
700*59d799daSIngo Weinhold
701*59d799daSIngo Weinhold m = l << 2;
702*59d799daSIngo Weinhold for (j = 0; j < l; j += 2) {
703*59d799daSIngo Weinhold j1 = j + l;
704*59d799daSIngo Weinhold j2 = j1 + l;
705*59d799daSIngo Weinhold j3 = j2 + l;
706*59d799daSIngo Weinhold x0r = a[j] + a[j1];
707*59d799daSIngo Weinhold x0i = a[j + 1] + a[j1 + 1];
708*59d799daSIngo Weinhold x1r = a[j] - a[j1];
709*59d799daSIngo Weinhold x1i = a[j + 1] - a[j1 + 1];
710*59d799daSIngo Weinhold x2r = a[j2] + a[j3];
711*59d799daSIngo Weinhold x2i = a[j2 + 1] + a[j3 + 1];
712*59d799daSIngo Weinhold x3r = a[j2] - a[j3];
713*59d799daSIngo Weinhold x3i = a[j2 + 1] - a[j3 + 1];
714*59d799daSIngo Weinhold a[j] = x0r + x2r;
715*59d799daSIngo Weinhold a[j + 1] = x0i + x2i;
716*59d799daSIngo Weinhold a[j2] = x0r - x2r;
717*59d799daSIngo Weinhold a[j2 + 1] = x0i - x2i;
718*59d799daSIngo Weinhold a[j1] = x1r - x3i;
719*59d799daSIngo Weinhold a[j1 + 1] = x1i + x3r;
720*59d799daSIngo Weinhold a[j3] = x1r + x3i;
721*59d799daSIngo Weinhold a[j3 + 1] = x1i - x3r;
722*59d799daSIngo Weinhold }
723*59d799daSIngo Weinhold wn4r = WR5000;
724*59d799daSIngo Weinhold for (j = m; j < l + m; j += 2) {
725*59d799daSIngo Weinhold j1 = j + l;
726*59d799daSIngo Weinhold j2 = j1 + l;
727*59d799daSIngo Weinhold j3 = j2 + l;
728*59d799daSIngo Weinhold x0r = a[j] + a[j1];
729*59d799daSIngo Weinhold x0i = a[j + 1] + a[j1 + 1];
730*59d799daSIngo Weinhold x1r = a[j] - a[j1];
731*59d799daSIngo Weinhold x1i = a[j + 1] - a[j1 + 1];
732*59d799daSIngo Weinhold x2r = a[j2] + a[j3];
733*59d799daSIngo Weinhold x2i = a[j2 + 1] + a[j3 + 1];
734*59d799daSIngo Weinhold x3r = a[j2] - a[j3];
735*59d799daSIngo Weinhold x3i = a[j2 + 1] - a[j3 + 1];
736*59d799daSIngo Weinhold a[j] = x0r + x2r;
737*59d799daSIngo Weinhold a[j + 1] = x0i + x2i;
738*59d799daSIngo Weinhold a[j2] = x2i - x0i;
739*59d799daSIngo Weinhold a[j2 + 1] = x0r - x2r;
740*59d799daSIngo Weinhold x0r = x1r - x3i;
741*59d799daSIngo Weinhold x0i = x1i + x3r;
742*59d799daSIngo Weinhold a[j1] = wn4r * (x0r - x0i);
743*59d799daSIngo Weinhold a[j1 + 1] = wn4r * (x0r + x0i);
744*59d799daSIngo Weinhold x0r = x3i + x1r;
745*59d799daSIngo Weinhold x0i = x3r - x1i;
746*59d799daSIngo Weinhold a[j3] = wn4r * (x0i - x0r);
747*59d799daSIngo Weinhold a[j3 + 1] = wn4r * (x0i + x0r);
748*59d799daSIngo Weinhold }
749*59d799daSIngo Weinhold ew = MM_PI_2 / n;
750*59d799daSIngo Weinhold kr = 0;
751*59d799daSIngo Weinhold m2 = 2 * m;
752*59d799daSIngo Weinhold for (k = m2; k < n; k += m2) {
753*59d799daSIngo Weinhold for (kj = n >> 2; kj > (kr ^= kj); kj >>= 1);
754*59d799daSIngo Weinhold wk1r = cos(ew * kr);
755*59d799daSIngo Weinhold wk1i = sin(ew * kr);
756*59d799daSIngo Weinhold wk2r = 1 - 2 * wk1i * wk1i;
757*59d799daSIngo Weinhold wk2i = 2 * wk1i * wk1r;
758*59d799daSIngo Weinhold wk3r = wk1r - 2 * wk2i * wk1i;
759*59d799daSIngo Weinhold wk3i = 2 * wk2i * wk1r - wk1i;
760*59d799daSIngo Weinhold for (j = k; j < l + k; j += 2) {
761*59d799daSIngo Weinhold j1 = j + l;
762*59d799daSIngo Weinhold j2 = j1 + l;
763*59d799daSIngo Weinhold j3 = j2 + l;
764*59d799daSIngo Weinhold x0r = a[j] + a[j1];
765*59d799daSIngo Weinhold x0i = a[j + 1] + a[j1 + 1];
766*59d799daSIngo Weinhold x1r = a[j] - a[j1];
767*59d799daSIngo Weinhold x1i = a[j + 1] - a[j1 + 1];
768*59d799daSIngo Weinhold x2r = a[j2] + a[j3];
769*59d799daSIngo Weinhold x2i = a[j2 + 1] + a[j3 + 1];
770*59d799daSIngo Weinhold x3r = a[j2] - a[j3];
771*59d799daSIngo Weinhold x3i = a[j2 + 1] - a[j3 + 1];
772*59d799daSIngo Weinhold a[j] = x0r + x2r;
773*59d799daSIngo Weinhold a[j + 1] = x0i + x2i;
774*59d799daSIngo Weinhold x0r -= x2r;
775*59d799daSIngo Weinhold x0i -= x2i;
776*59d799daSIngo Weinhold a[j2] = wk2r * x0r - wk2i * x0i;
777*59d799daSIngo Weinhold a[j2 + 1] = wk2r * x0i + wk2i * x0r;
778*59d799daSIngo Weinhold x0r = x1r - x3i;
779*59d799daSIngo Weinhold x0i = x1i + x3r;
780*59d799daSIngo Weinhold a[j1] = wk1r * x0r - wk1i * x0i;
781*59d799daSIngo Weinhold a[j1 + 1] = wk1r * x0i + wk1i * x0r;
782*59d799daSIngo Weinhold x0r = x1r + x3i;
783*59d799daSIngo Weinhold x0i = x1i - x3r;
784*59d799daSIngo Weinhold a[j3] = wk3r * x0r - wk3i * x0i;
785*59d799daSIngo Weinhold a[j3 + 1] = wk3r * x0i + wk3i * x0r;
786*59d799daSIngo Weinhold }
787*59d799daSIngo Weinhold x0r = wn4r * (wk1r - wk1i);
788*59d799daSIngo Weinhold wk1i = wn4r * (wk1r + wk1i);
789*59d799daSIngo Weinhold wk1r = x0r;
790*59d799daSIngo Weinhold wk3r = wk1r - 2 * wk2r * wk1i;
791*59d799daSIngo Weinhold wk3i = 2 * wk2r * wk1r - wk1i;
792*59d799daSIngo Weinhold for (j = k + m; j < l + (k + m); j += 2) {
793*59d799daSIngo Weinhold j1 = j + l;
794*59d799daSIngo Weinhold j2 = j1 + l;
795*59d799daSIngo Weinhold j3 = j2 + l;
796*59d799daSIngo Weinhold x0r = a[j] + a[j1];
797*59d799daSIngo Weinhold x0i = a[j + 1] + a[j1 + 1];
798*59d799daSIngo Weinhold x1r = a[j] - a[j1];
799*59d799daSIngo Weinhold x1i = a[j + 1] - a[j1 + 1];
800*59d799daSIngo Weinhold x2r = a[j2] + a[j3];
801*59d799daSIngo Weinhold x2i = a[j2 + 1] + a[j3 + 1];
802*59d799daSIngo Weinhold x3r = a[j2] - a[j3];
803*59d799daSIngo Weinhold x3i = a[j2 + 1] - a[j3 + 1];
804*59d799daSIngo Weinhold a[j] = x0r + x2r;
805*59d799daSIngo Weinhold a[j + 1] = x0i + x2i;
806*59d799daSIngo Weinhold x0r -= x2r;
807*59d799daSIngo Weinhold x0i -= x2i;
808*59d799daSIngo Weinhold a[j2] = -wk2i * x0r - wk2r * x0i;
809*59d799daSIngo Weinhold a[j2 + 1] = -wk2i * x0i + wk2r * x0r;
810*59d799daSIngo Weinhold x0r = x1r - x3i;
811*59d799daSIngo Weinhold x0i = x1i + x3r;
812*59d799daSIngo Weinhold a[j1] = wk1r * x0r - wk1i * x0i;
813*59d799daSIngo Weinhold a[j1 + 1] = wk1r * x0i + wk1i * x0r;
814*59d799daSIngo Weinhold x0r = x1r + x3i;
815*59d799daSIngo Weinhold x0i = x1i - x3r;
816*59d799daSIngo Weinhold a[j3] = wk3r * x0r - wk3i * x0i;
817*59d799daSIngo Weinhold a[j3 + 1] = wk3r * x0i + wk3i * x0r;
818*59d799daSIngo Weinhold }
819*59d799daSIngo Weinhold }
820*59d799daSIngo Weinhold }
821*59d799daSIngo Weinhold
822*59d799daSIngo Weinhold
823*59d799daSIngo Weinhold
M_rftfsub(int n,double * a)824*59d799daSIngo Weinhold void M_rftfsub(int n, double *a)
825*59d799daSIngo Weinhold {
826*59d799daSIngo Weinhold int i, i0, j, k;
827*59d799daSIngo Weinhold double ec, w1r, w1i, wkr, wki, wdr, wdi, ss, xr, xi, yr, yi;
828*59d799daSIngo Weinhold
829*59d799daSIngo Weinhold ec = 2 * MM_PI_2 / n;
830*59d799daSIngo Weinhold wkr = 0;
831*59d799daSIngo Weinhold wki = 0;
832*59d799daSIngo Weinhold wdi = cos(ec);
833*59d799daSIngo Weinhold wdr = sin(ec);
834*59d799daSIngo Weinhold wdi *= wdr;
835*59d799daSIngo Weinhold wdr *= wdr;
836*59d799daSIngo Weinhold w1r = 1 - 2 * wdr;
837*59d799daSIngo Weinhold w1i = 2 * wdi;
838*59d799daSIngo Weinhold ss = 2 * w1i;
839*59d799daSIngo Weinhold i = n >> 1;
840*59d799daSIngo Weinhold while (1) {
841*59d799daSIngo Weinhold i0 = i - 4 * RDFT_LOOP_DIV;
842*59d799daSIngo Weinhold if (i0 < 4) {
843*59d799daSIngo Weinhold i0 = 4;
844*59d799daSIngo Weinhold }
845*59d799daSIngo Weinhold for (j = i - 4; j >= i0; j -= 4) {
846*59d799daSIngo Weinhold k = n - j;
847*59d799daSIngo Weinhold xr = a[j + 2] - a[k - 2];
848*59d799daSIngo Weinhold xi = a[j + 3] + a[k - 1];
849*59d799daSIngo Weinhold yr = wdr * xr - wdi * xi;
850*59d799daSIngo Weinhold yi = wdr * xi + wdi * xr;
851*59d799daSIngo Weinhold a[j + 2] -= yr;
852*59d799daSIngo Weinhold a[j + 3] -= yi;
853*59d799daSIngo Weinhold a[k - 2] += yr;
854*59d799daSIngo Weinhold a[k - 1] -= yi;
855*59d799daSIngo Weinhold wkr += ss * wdi;
856*59d799daSIngo Weinhold wki += ss * (0.5 - wdr);
857*59d799daSIngo Weinhold xr = a[j] - a[k];
858*59d799daSIngo Weinhold xi = a[j + 1] + a[k + 1];
859*59d799daSIngo Weinhold yr = wkr * xr - wki * xi;
860*59d799daSIngo Weinhold yi = wkr * xi + wki * xr;
861*59d799daSIngo Weinhold a[j] -= yr;
862*59d799daSIngo Weinhold a[j + 1] -= yi;
863*59d799daSIngo Weinhold a[k] += yr;
864*59d799daSIngo Weinhold a[k + 1] -= yi;
865*59d799daSIngo Weinhold wdr += ss * wki;
866*59d799daSIngo Weinhold wdi += ss * (0.5 - wkr);
867*59d799daSIngo Weinhold }
868*59d799daSIngo Weinhold if (i0 == 4) {
869*59d799daSIngo Weinhold break;
870*59d799daSIngo Weinhold }
871*59d799daSIngo Weinhold wkr = 0.5 * sin(ec * i0);
872*59d799daSIngo Weinhold wki = 0.5 * cos(ec * i0);
873*59d799daSIngo Weinhold wdr = 0.5 - (wkr * w1r - wki * w1i);
874*59d799daSIngo Weinhold wdi = wkr * w1i + wki * w1r;
875*59d799daSIngo Weinhold wkr = 0.5 - wkr;
876*59d799daSIngo Weinhold i = i0;
877*59d799daSIngo Weinhold }
878*59d799daSIngo Weinhold xr = a[2] - a[n - 2];
879*59d799daSIngo Weinhold xi = a[3] + a[n - 1];
880*59d799daSIngo Weinhold yr = wdr * xr - wdi * xi;
881*59d799daSIngo Weinhold yi = wdr * xi + wdi * xr;
882*59d799daSIngo Weinhold a[2] -= yr;
883*59d799daSIngo Weinhold a[3] -= yi;
884*59d799daSIngo Weinhold a[n - 2] += yr;
885*59d799daSIngo Weinhold a[n - 1] -= yi;
886*59d799daSIngo Weinhold }
887*59d799daSIngo Weinhold
888*59d799daSIngo Weinhold
889*59d799daSIngo Weinhold
M_rftbsub(int n,double * a)890*59d799daSIngo Weinhold void M_rftbsub(int n, double *a)
891*59d799daSIngo Weinhold {
892*59d799daSIngo Weinhold int i, i0, j, k;
893*59d799daSIngo Weinhold double ec, w1r, w1i, wkr, wki, wdr, wdi, ss, xr, xi, yr, yi;
894*59d799daSIngo Weinhold
895*59d799daSIngo Weinhold ec = 2 * MM_PI_2 / n;
896*59d799daSIngo Weinhold wkr = 0;
897*59d799daSIngo Weinhold wki = 0;
898*59d799daSIngo Weinhold wdi = cos(ec);
899*59d799daSIngo Weinhold wdr = sin(ec);
900*59d799daSIngo Weinhold wdi *= wdr;
901*59d799daSIngo Weinhold wdr *= wdr;
902*59d799daSIngo Weinhold w1r = 1 - 2 * wdr;
903*59d799daSIngo Weinhold w1i = 2 * wdi;
904*59d799daSIngo Weinhold ss = 2 * w1i;
905*59d799daSIngo Weinhold i = n >> 1;
906*59d799daSIngo Weinhold a[i + 1] = -a[i + 1];
907*59d799daSIngo Weinhold while (1) {
908*59d799daSIngo Weinhold i0 = i - 4 * RDFT_LOOP_DIV;
909*59d799daSIngo Weinhold if (i0 < 4) {
910*59d799daSIngo Weinhold i0 = 4;
911*59d799daSIngo Weinhold }
912*59d799daSIngo Weinhold for (j = i - 4; j >= i0; j -= 4) {
913*59d799daSIngo Weinhold k = n - j;
914*59d799daSIngo Weinhold xr = a[j + 2] - a[k - 2];
915*59d799daSIngo Weinhold xi = a[j + 3] + a[k - 1];
916*59d799daSIngo Weinhold yr = wdr * xr + wdi * xi;
917*59d799daSIngo Weinhold yi = wdr * xi - wdi * xr;
918*59d799daSIngo Weinhold a[j + 2] -= yr;
919*59d799daSIngo Weinhold a[j + 3] = yi - a[j + 3];
920*59d799daSIngo Weinhold a[k - 2] += yr;
921*59d799daSIngo Weinhold a[k - 1] = yi - a[k - 1];
922*59d799daSIngo Weinhold wkr += ss * wdi;
923*59d799daSIngo Weinhold wki += ss * (0.5 - wdr);
924*59d799daSIngo Weinhold xr = a[j] - a[k];
925*59d799daSIngo Weinhold xi = a[j + 1] + a[k + 1];
926*59d799daSIngo Weinhold yr = wkr * xr + wki * xi;
927*59d799daSIngo Weinhold yi = wkr * xi - wki * xr;
928*59d799daSIngo Weinhold a[j] -= yr;
929*59d799daSIngo Weinhold a[j + 1] = yi - a[j + 1];
930*59d799daSIngo Weinhold a[k] += yr;
931*59d799daSIngo Weinhold a[k + 1] = yi - a[k + 1];
932*59d799daSIngo Weinhold wdr += ss * wki;
933*59d799daSIngo Weinhold wdi += ss * (0.5 - wkr);
934*59d799daSIngo Weinhold }
935*59d799daSIngo Weinhold if (i0 == 4) {
936*59d799daSIngo Weinhold break;
937*59d799daSIngo Weinhold }
938*59d799daSIngo Weinhold wkr = 0.5 * sin(ec * i0);
939*59d799daSIngo Weinhold wki = 0.5 * cos(ec * i0);
940*59d799daSIngo Weinhold wdr = 0.5 - (wkr * w1r - wki * w1i);
941*59d799daSIngo Weinhold wdi = wkr * w1i + wki * w1r;
942*59d799daSIngo Weinhold wkr = 0.5 - wkr;
943*59d799daSIngo Weinhold i = i0;
944*59d799daSIngo Weinhold }
945*59d799daSIngo Weinhold xr = a[2] - a[n - 2];
946*59d799daSIngo Weinhold xi = a[3] + a[n - 1];
947*59d799daSIngo Weinhold yr = wdr * xr + wdi * xi;
948*59d799daSIngo Weinhold yi = wdr * xi - wdi * xr;
949*59d799daSIngo Weinhold a[2] -= yr;
950*59d799daSIngo Weinhold a[3] = yi - a[3];
951*59d799daSIngo Weinhold a[n - 2] += yr;
952*59d799daSIngo Weinhold a[n - 1] = yi - a[n - 1];
953*59d799daSIngo Weinhold a[1] = -a[1];
954*59d799daSIngo Weinhold }
955*59d799daSIngo Weinhold
956