mixfft.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. // Copyright (c) 1996 Jens Jorgen Nielsen
  2. // Written by Jens Jorgen Nielsen
  3. // Optimizations by Janik Joire
  4. //
  5. // $History: $
  6. #include <math.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #ifndef PI
  10. #define PI 3.14159265358979323846F
  11. #endif
  12. /************************************************************************
  13. fft(long n,float xRe[],float xIm[],float yRe[],float yIm[])
  14. ------------------------------------------------------------------------
  15. NOTE : This is copyrighted material, Not public domain. See below.
  16. ------------------------------------------------------------------------
  17. Input/output:
  18. long n transformation length.
  19. float xRe[] real part of input sequence.
  20. float xIm[] imaginary part of input sequence.
  21. float yRe[] real part of output sequence.
  22. float yIm[] imaginary part of output sequence.
  23. ------------------------------------------------------------------------
  24. Function:
  25. The procedure performs a fast discrete Fourier transform (FFT) of
  26. a complex sequence, x, of an arbitrary length, n. The output, y,
  27. is also a complex sequence of length n.
  28. y[k] = sum(x[m]*exp(-i*2*pi*k*m/n), m=0..(n-1)), k=0,...,(n-1)
  29. The largest prime factor of n must be less than or equal to the
  30. constant maxPrimeFactor defined below.
  31. ------------------------------------------------------------------------
  32. Author:
  33. Jens Jorgen Nielsen For non-commercial use only.
  34. Bakkehusene 54 A $100 fee must be paid if used
  35. DK-2970 Horsholm commercially. Please contact.
  36. DENMARK
  37. e-mail : jnielsen@internet.dk All rights reserved. March 1996.
  38. ------------------------------------------------------------------------
  39. Implementation notes:
  40. The general idea is to factor the length of the DFT, n, into
  41. factors that are efficiently handled by the routines.
  42. A number of short DFT's are implemented with a minimum of
  43. arithmetical operations and using (almost) straight line code
  44. resulting in very fast execution when the factors of n belong
  45. to this set. Especially radix-10 is optimized.
  46. Prime factors, that are not in the set of short DFT's are handled
  47. with direct evaluation of the DFP expression.
  48. Please report any problems to the author.
  49. Suggestions and improvements are welcomed.
  50. ------------------------------------------------------------------------
  51. Benchmarks:
  52. The Microsoft Visual C++ compiler was used with the following
  53. compile options:
  54. /nologo /Gs /G2 /W4 /AH /Ox /D "NDEBUG" /D "_DOS" /FR
  55. and the FFTBENCH test executed on a 50MHz 486DX :
  56. Length Time [s] Accuracy [dB]
  57. 128 0.0054 -314.8
  58. 256 0.0116 -309.8
  59. 512 0.0251 -290.8
  60. 1024 0.0567 -313.6
  61. 2048 0.1203 -306.4
  62. 4096 0.2600 -291.8
  63. 8192 0.5800 -305.1
  64. 100 0.0040 -278.5
  65. 200 0.0099 -280.3
  66. 500 0.0256 -278.5
  67. 1000 0.0540 -278.5
  68. 2000 0.1294 -280.6
  69. 5000 0.3300 -278.4
  70. 10000 0.7133 -278.5
  71. ------------------------------------------------------------------------
  72. The following procedures are used :
  73. factorize : factor the transformation length.
  74. transTableSetup : setup table with sofar-, actual-, and remainRadix.
  75. permute : permutation allows in-place calculations.
  76. twiddleTransf : twiddle multiplications and DFT's for one stage.
  77. initTrig : initialise sine/cosine table.
  78. fft_4 : length 4 DFT, a la Nussbaumer.
  79. fft_5 : length 5 DFT, a la Nussbaumer.
  80. fft_10 : length 10 DFT using prime factor FFT.
  81. fft_odd : length n DFT, n odd.
  82. *************************************************************************/
  83. #define maxPrimeFactor 37
  84. #define maxPrimeFactorDiv2 (maxPrimeFactor+1)/2
  85. #define maxFactorCount 20
  86. static float c3_1 = -1.5000000000000E+00F; /* c3_1 = cos(2*pi/3)-1; */
  87. static float c3_2 = 8.6602540378444E-01F; /* c3_2 = sin(2*pi/3); */
  88. static float u5 = 1.2566370614359E+00F; /* u5 = 2*pi/5; */
  89. static float c5_1 = -1.2500000000000E+00F; /* c5_1 = (cos(u5)+cos(2*u5))/2-1;*/
  90. static float c5_2 = 5.5901699437495E-01F; /* c5_2 = (cos(u5)-cos(2*u5))/2; */
  91. static float c5_3 = -9.5105651629515E-01F; /* c5_3 = -sin(u5); */
  92. static float c5_4 = -1.5388417685876E+00F; /* c5_4 = -(sin(u5)+sin(2*u5)); */
  93. static float c5_5 = 3.6327126400268E-01F; /* c5_5 = (sin(u5)-sin(2*u5)); */
  94. static float c8 = 7.0710678118655E-01F; /* c8 = 1/sqrt(2); */
  95. static float pi;
  96. static long groupOffset,dataOffset,blockOffset,adr;
  97. static long groupNo,dataNo,blockNo,twNo;
  98. static float omega, tw_re,tw_im;
  99. static float twiddleRe[maxPrimeFactor], twiddleIm[maxPrimeFactor],
  100. trigRe[maxPrimeFactor], trigIm[maxPrimeFactor],
  101. zRe[maxPrimeFactor], zIm[maxPrimeFactor];
  102. static float vRe[maxPrimeFactorDiv2], vIm[maxPrimeFactorDiv2];
  103. static float wRe[maxPrimeFactorDiv2], wIm[maxPrimeFactorDiv2];
  104. void factorize(long n, long *nFact, long fact[])
  105. {
  106. long i,j,k;
  107. long nRadix;
  108. long radices[7];
  109. long factors[maxFactorCount];
  110. nRadix = 6;
  111. radices[1]= 2;
  112. radices[2]= 3;
  113. radices[3]= 4;
  114. radices[4]= 5;
  115. radices[5]= 8;
  116. radices[6]= 10;
  117. if (n==1)
  118. {
  119. j=1;
  120. factors[1]=1;
  121. }
  122. else j=0;
  123. i=nRadix;
  124. while ((n>1) && (i>0))
  125. {
  126. if ((n % radices[i]) == 0)
  127. {
  128. n=n / radices[i];
  129. j=j+1;
  130. factors[j]=radices[i];
  131. }
  132. else i=i-1;
  133. }
  134. if (factors[j] == 2) /*substitute factors 2*8 with 4*4 */
  135. {
  136. i = j-1;
  137. while ((i>0) && (factors[i] != 8)) i--;
  138. if (i>0)
  139. {
  140. factors[j] = 4;
  141. factors[i] = 4;
  142. }
  143. }
  144. if (n>1)
  145. {
  146. for (k=2; k<sqrt(n)+1; k++)
  147. while ((n % k) == 0)
  148. {
  149. n=n / k;
  150. j=j+1;
  151. factors[j]=k;
  152. }
  153. if (n>1)
  154. {
  155. j=j+1;
  156. factors[j]=n;
  157. }
  158. }
  159. for (i=1; i<=j; i++)
  160. {
  161. fact[i] = factors[j-i+1];
  162. }
  163. *nFact=j;
  164. } /* factorize */
  165. /****************************************************************************
  166. After N is factored the parameters that control the stages are generated.
  167. For each stage we have:
  168. sofar : the product of the radices so far.
  169. actual : the radix handled in this stage.
  170. remain : the product of the remaining radices.
  171. ****************************************************************************/
  172. void transTableSetup(long sofar[], long actual[], long remain[],
  173. long *nFact,
  174. long *nPoints)
  175. {
  176. long i;
  177. factorize(*nPoints, nFact, actual);
  178. if (actual[*nFact] > maxPrimeFactor)
  179. {
  180. printf("\nPrime factor of FFT length too large : %6d",actual[*nFact]);
  181. exit(1);
  182. }
  183. remain[0]=*nPoints;
  184. sofar[1]=1;
  185. remain[1]=*nPoints / actual[1];
  186. for (i=2; i<=*nFact; i++)
  187. {
  188. sofar[i]=sofar[i-1]*actual[i-1];
  189. remain[i]=remain[i-1] / actual[i];
  190. }
  191. } /* transTableSetup */
  192. /****************************************************************************
  193. The sequence y is the permuted input sequence x so that the following
  194. transformations can be performed in-place, and the final result is the
  195. normal order.
  196. ****************************************************************************/
  197. void permute(long nPoint, long nFact,
  198. long fact[], long remain[],
  199. float xRe[], float xIm[],
  200. float yRe[], float yIm[])
  201. {
  202. long i,j,k;
  203. long count[maxFactorCount];
  204. for (i=1; i<=nFact; i++) count[i]=0;
  205. k=0;
  206. for (i=0; i<=nPoint-2; i++)
  207. {
  208. yRe[i] = xRe[k];
  209. yIm[i] = xIm[k];
  210. j=1;
  211. k=k+remain[j];
  212. count[1] = count[1]+1;
  213. while (count[j] >= fact[j])
  214. {
  215. count[j]=0;
  216. k=k-remain[j-1]+remain[j+1];
  217. j=j+1;
  218. count[j]=count[j]+1;
  219. }
  220. }
  221. yRe[nPoint-1]=xRe[nPoint-1];
  222. yIm[nPoint-1]=xIm[nPoint-1];
  223. } /* permute */
  224. /****************************************************************************
  225. Twiddle factor multiplications and transformations are performed on a
  226. group of data. The number of multiplications with 1 are reduced by skipping
  227. the twiddle multiplication of the first stage and of the first group of the
  228. following stages.
  229. ***************************************************************************/
  230. void initTrig(long radix)
  231. {
  232. long i;
  233. float w,xre,xim;
  234. w=2*pi/radix;
  235. trigRe[0]=1; trigIm[0]=0;
  236. xre=(float)cos(w);
  237. xim=-(float)sin(w);
  238. trigRe[1]=xre; trigIm[1]=xim;
  239. for (i=2; i<radix; i++)
  240. {
  241. trigRe[i]=xre*trigRe[i-1] - xim*trigIm[i-1];
  242. trigIm[i]=xim*trigRe[i-1] + xre*trigIm[i-1];
  243. }
  244. } /* initTrig */
  245. void fft_4(float aRe[], float aIm[])
  246. {
  247. float t1_re,t1_im, t2_re,t2_im;
  248. float m2_re,m2_im, m3_re,m3_im;
  249. t1_re=aRe[0] + aRe[2]; t1_im=aIm[0] + aIm[2];
  250. t2_re=aRe[1] + aRe[3]; t2_im=aIm[1] + aIm[3];
  251. m2_re=aRe[0] - aRe[2]; m2_im=aIm[0] - aIm[2];
  252. m3_re=aIm[1] - aIm[3]; m3_im=aRe[3] - aRe[1];
  253. aRe[0]=t1_re + t2_re; aIm[0]=t1_im + t2_im;
  254. aRe[2]=t1_re - t2_re; aIm[2]=t1_im - t2_im;
  255. aRe[1]=m2_re + m3_re; aIm[1]=m2_im + m3_im;
  256. aRe[3]=m2_re - m3_re; aIm[3]=m2_im - m3_im;
  257. } /* fft_4 */
  258. void fft_5(float aRe[], float aIm[])
  259. {
  260. float t1_re,t1_im, t2_re,t2_im, t3_re,t3_im;
  261. float t4_re,t4_im, t5_re,t5_im;
  262. float m2_re,m2_im, m3_re,m3_im, m4_re,m4_im;
  263. float m1_re,m1_im, m5_re,m5_im;
  264. float s1_re,s1_im, s2_re,s2_im, s3_re,s3_im;
  265. float s4_re,s4_im, s5_re,s5_im;
  266. t1_re=aRe[1] + aRe[4]; t1_im=aIm[1] + aIm[4];
  267. t2_re=aRe[2] + aRe[3]; t2_im=aIm[2] + aIm[3];
  268. t3_re=aRe[1] - aRe[4]; t3_im=aIm[1] - aIm[4];
  269. t4_re=aRe[3] - aRe[2]; t4_im=aIm[3] - aIm[2];
  270. t5_re=t1_re + t2_re; t5_im=t1_im + t2_im;
  271. aRe[0]=aRe[0] + t5_re; aIm[0]=aIm[0] + t5_im;
  272. m1_re=c5_1*t5_re; m1_im=c5_1*t5_im;
  273. m2_re=c5_2*(t1_re - t2_re); m2_im=c5_2*(t1_im - t2_im);
  274. m3_re=-c5_3*(t3_im + t4_im); m3_im=c5_3*(t3_re + t4_re);
  275. m4_re=-c5_4*t4_im; m4_im=c5_4*t4_re;
  276. m5_re=-c5_5*t3_im; m5_im=c5_5*t3_re;
  277. s3_re=m3_re - m4_re; s3_im=m3_im - m4_im;
  278. s5_re=m3_re + m5_re; s5_im=m3_im + m5_im;
  279. s1_re=aRe[0] + m1_re; s1_im=aIm[0] + m1_im;
  280. s2_re=s1_re + m2_re; s2_im=s1_im + m2_im;
  281. s4_re=s1_re - m2_re; s4_im=s1_im - m2_im;
  282. aRe[1]=s2_re + s3_re; aIm[1]=s2_im + s3_im;
  283. aRe[2]=s4_re + s5_re; aIm[2]=s4_im + s5_im;
  284. aRe[3]=s4_re - s5_re; aIm[3]=s4_im - s5_im;
  285. aRe[4]=s2_re - s3_re; aIm[4]=s2_im - s3_im;
  286. } /* fft_5 */
  287. void fft_8()
  288. {
  289. float aRe[4], aIm[4], bRe[4], bIm[4], gem;
  290. aRe[0] = zRe[0]; bRe[0] = zRe[1];
  291. aRe[1] = zRe[2]; bRe[1] = zRe[3];
  292. aRe[2] = zRe[4]; bRe[2] = zRe[5];
  293. aRe[3] = zRe[6]; bRe[3] = zRe[7];
  294. aIm[0] = zIm[0]; bIm[0] = zIm[1];
  295. aIm[1] = zIm[2]; bIm[1] = zIm[3];
  296. aIm[2] = zIm[4]; bIm[2] = zIm[5];
  297. aIm[3] = zIm[6]; bIm[3] = zIm[7];
  298. fft_4(aRe, aIm); fft_4(bRe, bIm);
  299. gem = c8*(bRe[1] + bIm[1]);
  300. bIm[1] = c8*(bIm[1] - bRe[1]);
  301. bRe[1] = gem;
  302. gem = bIm[2];
  303. bIm[2] =-bRe[2];
  304. bRe[2] = gem;
  305. gem = c8*(bIm[3] - bRe[3]);
  306. bIm[3] =-c8*(bRe[3] + bIm[3]);
  307. bRe[3] = gem;
  308. zRe[0] = aRe[0] + bRe[0]; zRe[4] = aRe[0] - bRe[0];
  309. zRe[1] = aRe[1] + bRe[1]; zRe[5] = aRe[1] - bRe[1];
  310. zRe[2] = aRe[2] + bRe[2]; zRe[6] = aRe[2] - bRe[2];
  311. zRe[3] = aRe[3] + bRe[3]; zRe[7] = aRe[3] - bRe[3];
  312. zIm[0] = aIm[0] + bIm[0]; zIm[4] = aIm[0] - bIm[0];
  313. zIm[1] = aIm[1] + bIm[1]; zIm[5] = aIm[1] - bIm[1];
  314. zIm[2] = aIm[2] + bIm[2]; zIm[6] = aIm[2] - bIm[2];
  315. zIm[3] = aIm[3] + bIm[3]; zIm[7] = aIm[3] - bIm[3];
  316. } /* fft_8 */
  317. void fft_10()
  318. {
  319. float aRe[5], aIm[5], bRe[5], bIm[5];
  320. aRe[0] = zRe[0]; bRe[0] = zRe[5];
  321. aRe[1] = zRe[2]; bRe[1] = zRe[7];
  322. aRe[2] = zRe[4]; bRe[2] = zRe[9];
  323. aRe[3] = zRe[6]; bRe[3] = zRe[1];
  324. aRe[4] = zRe[8]; bRe[4] = zRe[3];
  325. aIm[0] = zIm[0]; bIm[0] = zIm[5];
  326. aIm[1] = zIm[2]; bIm[1] = zIm[7];
  327. aIm[2] = zIm[4]; bIm[2] = zIm[9];
  328. aIm[3] = zIm[6]; bIm[3] = zIm[1];
  329. aIm[4] = zIm[8]; bIm[4] = zIm[3];
  330. fft_5(aRe, aIm); fft_5(bRe, bIm);
  331. zRe[0] = aRe[0] + bRe[0]; zRe[5] = aRe[0] - bRe[0];
  332. zRe[6] = aRe[1] + bRe[1]; zRe[1] = aRe[1] - bRe[1];
  333. zRe[2] = aRe[2] + bRe[2]; zRe[7] = aRe[2] - bRe[2];
  334. zRe[8] = aRe[3] + bRe[3]; zRe[3] = aRe[3] - bRe[3];
  335. zRe[4] = aRe[4] + bRe[4]; zRe[9] = aRe[4] - bRe[4];
  336. zIm[0] = aIm[0] + bIm[0]; zIm[5] = aIm[0] - bIm[0];
  337. zIm[6] = aIm[1] + bIm[1]; zIm[1] = aIm[1] - bIm[1];
  338. zIm[2] = aIm[2] + bIm[2]; zIm[7] = aIm[2] - bIm[2];
  339. zIm[8] = aIm[3] + bIm[3]; zIm[3] = aIm[3] - bIm[3];
  340. zIm[4] = aIm[4] + bIm[4]; zIm[9] = aIm[4] - bIm[4];
  341. } /* fft_10 */
  342. void fft_odd(long radix)
  343. {
  344. float rere, reim, imre, imim;
  345. long i,j,k,n,max;
  346. n = radix;
  347. max = (n + 1)/2;
  348. for (j=1; j < max; j++)
  349. {
  350. vRe[j] = zRe[j] + zRe[n-j];
  351. vIm[j] = zIm[j] - zIm[n-j];
  352. wRe[j] = zRe[j] - zRe[n-j];
  353. wIm[j] = zIm[j] + zIm[n-j];
  354. }
  355. for (j=1; j < max; j++)
  356. {
  357. zRe[j]=zRe[0];
  358. zIm[j]=zIm[0];
  359. zRe[n-j]=zRe[0];
  360. zIm[n-j]=zIm[0];
  361. k=j;
  362. for (i=1; i < max; i++)
  363. {
  364. rere = trigRe[k] * vRe[i];
  365. imim = trigIm[k] * vIm[i];
  366. reim = trigRe[k] * wIm[i];
  367. imre = trigIm[k] * wRe[i];
  368. zRe[n-j] += rere + imim;
  369. zIm[n-j] += reim - imre;
  370. zRe[j] += rere - imim;
  371. zIm[j] += reim + imre;
  372. k = k + j;
  373. if (k >= n) k = k - n;
  374. }
  375. }
  376. for (j=1; j < max; j++)
  377. {
  378. zRe[0]=zRe[0] + vRe[j];
  379. zIm[0]=zIm[0] + wIm[j];
  380. }
  381. } /* fft_odd */
  382. void twiddleTransf(long sofarRadix, long radix, long remainRadix,
  383. float yRe[], float yIm[])
  384. { /* twiddleTransf */
  385. float cosw, sinw, gem;
  386. float t1_re,t1_im, t2_re,t2_im, t3_re,t3_im;
  387. float t4_re,t4_im, t5_re,t5_im;
  388. float m2_re,m2_im, m3_re,m3_im, m4_re,m4_im;
  389. float m1_re,m1_im, m5_re,m5_im;
  390. float s1_re,s1_im, s2_re,s2_im, s3_re,s3_im;
  391. float s4_re,s4_im, s5_re,s5_im;
  392. initTrig(radix);
  393. omega = 2*pi/(float)(sofarRadix*radix);
  394. cosw = (float)cos(omega);
  395. sinw = -(float)sin(omega);
  396. tw_re = 1.0;
  397. tw_im = 0;
  398. dataOffset=0;
  399. groupOffset=dataOffset;
  400. adr=groupOffset;
  401. for (dataNo=0; dataNo<sofarRadix; dataNo++)
  402. {
  403. if (sofarRadix>1)
  404. {
  405. twiddleRe[0] = 1.0;
  406. twiddleIm[0] = 0.0;
  407. twiddleRe[1] = tw_re;
  408. twiddleIm[1] = tw_im;
  409. for (twNo=2; twNo<radix; twNo++)
  410. {
  411. twiddleRe[twNo]=tw_re*twiddleRe[twNo-1]
  412. - tw_im*twiddleIm[twNo-1];
  413. twiddleIm[twNo]=tw_im*twiddleRe[twNo-1]
  414. + tw_re*twiddleIm[twNo-1];
  415. }
  416. gem = cosw*tw_re - sinw*tw_im;
  417. tw_im = sinw*tw_re + cosw*tw_im;
  418. tw_re = gem;
  419. }
  420. for (groupNo=0; groupNo<remainRadix; groupNo++)
  421. {
  422. if ((sofarRadix>1) && (dataNo > 0))
  423. {
  424. zRe[0]=yRe[adr];
  425. zIm[0]=yIm[adr];
  426. blockNo=1;
  427. do {
  428. adr = adr + sofarRadix;
  429. zRe[blockNo]= twiddleRe[blockNo] * yRe[adr]
  430. - twiddleIm[blockNo] * yIm[adr];
  431. zIm[blockNo]= twiddleRe[blockNo] * yIm[adr]
  432. + twiddleIm[blockNo] * yRe[adr];
  433. blockNo++;
  434. } while (blockNo < radix);
  435. }
  436. else
  437. for (blockNo=0; blockNo<radix; blockNo++)
  438. {
  439. zRe[blockNo]=yRe[adr];
  440. zIm[blockNo]=yIm[adr];
  441. adr=adr+sofarRadix;
  442. }
  443. switch(radix) {
  444. case 2 : gem=zRe[0] + zRe[1];
  445. zRe[1]=zRe[0] - zRe[1]; zRe[0]=gem;
  446. gem=zIm[0] + zIm[1];
  447. zIm[1]=zIm[0] - zIm[1]; zIm[0]=gem;
  448. break;
  449. case 3 : t1_re=zRe[1] + zRe[2]; t1_im=zIm[1] + zIm[2];
  450. zRe[0]=zRe[0] + t1_re; zIm[0]=zIm[0] + t1_im;
  451. m1_re=c3_1*t1_re; m1_im=c3_1*t1_im;
  452. m2_re=c3_2*(zIm[1] - zIm[2]);
  453. m2_im=c3_2*(zRe[2] - zRe[1]);
  454. s1_re=zRe[0] + m1_re; s1_im=zIm[0] + m1_im;
  455. zRe[1]=s1_re + m2_re; zIm[1]=s1_im + m2_im;
  456. zRe[2]=s1_re - m2_re; zIm[2]=s1_im - m2_im;
  457. break;
  458. case 4 : t1_re=zRe[0] + zRe[2]; t1_im=zIm[0] + zIm[2];
  459. t2_re=zRe[1] + zRe[3]; t2_im=zIm[1] + zIm[3];
  460. m2_re=zRe[0] - zRe[2]; m2_im=zIm[0] - zIm[2];
  461. m3_re=zIm[1] - zIm[3]; m3_im=zRe[3] - zRe[1];
  462. zRe[0]=t1_re + t2_re; zIm[0]=t1_im + t2_im;
  463. zRe[2]=t1_re - t2_re; zIm[2]=t1_im - t2_im;
  464. zRe[1]=m2_re + m3_re; zIm[1]=m2_im + m3_im;
  465. zRe[3]=m2_re - m3_re; zIm[3]=m2_im - m3_im;
  466. break;
  467. case 5 : t1_re=zRe[1] + zRe[4]; t1_im=zIm[1] + zIm[4];
  468. t2_re=zRe[2] + zRe[3]; t2_im=zIm[2] + zIm[3];
  469. t3_re=zRe[1] - zRe[4]; t3_im=zIm[1] - zIm[4];
  470. t4_re=zRe[3] - zRe[2]; t4_im=zIm[3] - zIm[2];
  471. t5_re=t1_re + t2_re; t5_im=t1_im + t2_im;
  472. zRe[0]=zRe[0] + t5_re; zIm[0]=zIm[0] + t5_im;
  473. m1_re=c5_1*t5_re; m1_im=c5_1*t5_im;
  474. m2_re=c5_2*(t1_re - t2_re);
  475. m2_im=c5_2*(t1_im - t2_im);
  476. m3_re=-c5_3*(t3_im + t4_im);
  477. m3_im=c5_3*(t3_re + t4_re);
  478. m4_re=-c5_4*t4_im; m4_im=c5_4*t4_re;
  479. m5_re=-c5_5*t3_im; m5_im=c5_5*t3_re;
  480. s3_re=m3_re - m4_re; s3_im=m3_im - m4_im;
  481. s5_re=m3_re + m5_re; s5_im=m3_im + m5_im;
  482. s1_re=zRe[0] + m1_re; s1_im=zIm[0] + m1_im;
  483. s2_re=s1_re + m2_re; s2_im=s1_im + m2_im;
  484. s4_re=s1_re - m2_re; s4_im=s1_im - m2_im;
  485. zRe[1]=s2_re + s3_re; zIm[1]=s2_im + s3_im;
  486. zRe[2]=s4_re + s5_re; zIm[2]=s4_im + s5_im;
  487. zRe[3]=s4_re - s5_re; zIm[3]=s4_im - s5_im;
  488. zRe[4]=s2_re - s3_re; zIm[4]=s2_im - s3_im;
  489. break;
  490. case 8 : fft_8(); break;
  491. case 10 : fft_10(); break;
  492. default : fft_odd(radix); break;
  493. }
  494. adr=groupOffset;
  495. for (blockNo=0; blockNo<radix; blockNo++)
  496. {
  497. yRe[adr]=zRe[blockNo]; yIm[adr]=zIm[blockNo];
  498. adr=adr+sofarRadix;
  499. }
  500. groupOffset=groupOffset+sofarRadix*radix;
  501. adr=groupOffset;
  502. }
  503. dataOffset=dataOffset+1;
  504. groupOffset=dataOffset;
  505. adr=groupOffset;
  506. }
  507. } /* twiddleTransf */
  508. void fft(long n,float *xRe,float *xIm,float *yRe,float *yIm)
  509. {
  510. long sofarRadix[maxFactorCount],
  511. actualRadix[maxFactorCount],
  512. remainRadix[maxFactorCount];
  513. long nFactor;
  514. long count;
  515. pi = PI;
  516. transTableSetup(sofarRadix, actualRadix, remainRadix, &nFactor, &n);
  517. permute(n, nFactor, actualRadix, remainRadix, xRe, xIm, yRe, yIm);
  518. for (count=1; count<=nFactor; count++)
  519. twiddleTransf(sofarRadix[count], actualRadix[count], remainRadix[count],
  520. yRe, yIm);
  521. } /* fft */