Chris@5
|
1
|
Chris@5
|
2 /* Public domain FFT implementation from Don Cross. */
|
Chris@5
|
3
|
Chris@5
|
4 #include "Cross.h"
|
Chris@5
|
5
|
Chris@5
|
6 #include <math.h>
|
Chris@5
|
7 #include <stdio.h>
|
Chris@5
|
8
|
Chris@5
|
9 void
|
Chris@5
|
10 fftCross(unsigned int n, int inverse,
|
Chris@5
|
11 const double *ri, const double *ii,
|
Chris@5
|
12 double *ro, double *io)
|
Chris@5
|
13 {
|
Chris@5
|
14 if (!ri || !ro || !io) return;
|
Chris@5
|
15
|
Chris@5
|
16 unsigned int bits;
|
Chris@5
|
17 unsigned int i, j, k, m;
|
Chris@5
|
18 unsigned int blockSize, blockEnd;
|
Chris@5
|
19
|
Chris@5
|
20 double tr, ti;
|
Chris@5
|
21
|
Chris@5
|
22 if (n < 2) return;
|
Chris@5
|
23 if (n & (n-1)) return;
|
Chris@5
|
24
|
Chris@5
|
25 double angle = 2.0 * M_PI;
|
Chris@5
|
26 if (inverse) angle = -angle;
|
Chris@5
|
27
|
Chris@5
|
28 for (i = 0; ; ++i) {
|
Chris@5
|
29 if (n & (1 << i)) {
|
Chris@5
|
30 bits = i;
|
Chris@5
|
31 break;
|
Chris@5
|
32 }
|
Chris@5
|
33 }
|
Chris@5
|
34
|
Chris@5
|
35 #ifdef _MSC_VER
|
Chris@5
|
36 int *table = (int *)_malloca(n * sizeof(int));
|
Chris@5
|
37 #else
|
Chris@5
|
38 int table[n];
|
Chris@5
|
39 #endif
|
Chris@5
|
40
|
Chris@5
|
41 for (i = 0; i < n; ++i) {
|
Chris@5
|
42 m = i;
|
Chris@5
|
43 for (j = k = 0; j < bits; ++j) {
|
Chris@5
|
44 k = (k << 1) | (m & 1);
|
Chris@5
|
45 m >>= 1;
|
Chris@5
|
46 }
|
Chris@5
|
47 table[i] = k;
|
Chris@5
|
48 }
|
Chris@5
|
49
|
Chris@5
|
50 if (ii) {
|
Chris@5
|
51 for (i = 0; i < n; ++i) {
|
Chris@5
|
52 ro[table[i]] = ri[i];
|
Chris@5
|
53 io[table[i]] = ii[i];
|
Chris@5
|
54 }
|
Chris@5
|
55 } else {
|
Chris@5
|
56 for (i = 0; i < n; ++i) {
|
Chris@5
|
57 ro[table[i]] = ri[i];
|
Chris@5
|
58 io[table[i]] = 0.0;
|
Chris@5
|
59 }
|
Chris@5
|
60 }
|
Chris@5
|
61
|
Chris@5
|
62 blockEnd = 1;
|
Chris@5
|
63
|
Chris@5
|
64 for (blockSize = 2; blockSize <= n; blockSize <<= 1) {
|
Chris@5
|
65
|
Chris@5
|
66 double delta = angle / (double)blockSize;
|
Chris@5
|
67 double sm2 = -sin(-2 * delta);
|
Chris@5
|
68 double sm1 = -sin(-delta);
|
Chris@5
|
69 double cm2 = cos(-2 * delta);
|
Chris@5
|
70 double cm1 = cos(-delta);
|
Chris@5
|
71 double w = 2 * cm1;
|
Chris@5
|
72 double ar[3], ai[3];
|
Chris@5
|
73
|
Chris@5
|
74 for (i = 0; i < n; i += blockSize) {
|
Chris@5
|
75
|
Chris@5
|
76 ar[2] = cm2;
|
Chris@5
|
77 ar[1] = cm1;
|
Chris@5
|
78
|
Chris@5
|
79 ai[2] = sm2;
|
Chris@5
|
80 ai[1] = sm1;
|
Chris@5
|
81
|
Chris@5
|
82 for (j = i, m = 0; m < blockEnd; j++, m++) {
|
Chris@5
|
83
|
Chris@5
|
84 ar[0] = w * ar[1] - ar[2];
|
Chris@5
|
85 ar[2] = ar[1];
|
Chris@5
|
86 ar[1] = ar[0];
|
Chris@5
|
87
|
Chris@5
|
88 ai[0] = w * ai[1] - ai[2];
|
Chris@5
|
89 ai[2] = ai[1];
|
Chris@5
|
90 ai[1] = ai[0];
|
Chris@5
|
91
|
Chris@5
|
92 k = j + blockEnd;
|
Chris@5
|
93 tr = ar[0] * ro[k] - ai[0] * io[k];
|
Chris@5
|
94 ti = ar[0] * io[k] + ai[0] * ro[k];
|
Chris@5
|
95
|
Chris@5
|
96 ro[k] = ro[j] - tr;
|
Chris@5
|
97 io[k] = io[j] - ti;
|
Chris@5
|
98
|
Chris@5
|
99 ro[j] += tr;
|
Chris@5
|
100 io[j] += ti;
|
Chris@5
|
101 }
|
Chris@5
|
102 }
|
Chris@5
|
103
|
Chris@5
|
104 blockEnd = blockSize;
|
Chris@5
|
105 }
|
Chris@5
|
106
|
Chris@5
|
107 if (inverse) {
|
Chris@5
|
108
|
Chris@5
|
109 double denom = (double)n;
|
Chris@5
|
110
|
Chris@5
|
111 for (i = 0; i < n; i++) {
|
Chris@5
|
112 ro[i] /= denom;
|
Chris@5
|
113 io[i] /= denom;
|
Chris@5
|
114 }
|
Chris@5
|
115 }
|
Chris@5
|
116
|
Chris@5
|
117 #ifdef _MSC_VER
|
Chris@5
|
118 _freea(table);
|
Chris@5
|
119 #endif
|
Chris@5
|
120 }
|
Chris@5
|
121
|