FFT.java
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45: package xeij;
46:
47: import java.lang.*;
48:
49: public class FFT {
50:
51: private int fftN;
52: private double[] fftSinCos;
53: private int[] fftSwap;
54:
55:
56:
57: public FFT (int n) {
58: fftN = n;
59: int n2 = n >> 1;
60: int n4 = n >> 2;
61:
62: fftSinCos = new double[5 * n4 + 1];
63: double d = 2.0 * Math.PI / (double) n;
64: for (int i = 1; i < n4; i++) {
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77: fftSinCos[n - i] = fftSinCos[n2 + i] = -(fftSinCos[n2 - i] = fftSinCos[n + i] = fftSinCos[i] = Math.sin (d * (double) i));
78: }
79: fftSinCos[n] = fftSinCos[n2] = fftSinCos[0] = 0.0;
80: fftSinCos[5 * n4] = fftSinCos[n4] = 1.0;
81: fftSinCos[3 * n4] = -1.0;
82:
83: int b = Integer.numberOfTrailingZeros (n);
84: fftSwap = new int[n - (1 << (b + 1 >> 1))];
85: for (int i = 0, k = 0; i < n; i++) {
86: int j = Integer.reverse (i << -b);
87: if (i < j) {
88: fftSwap[k] = i;
89: fftSwap[k + 1] = j;
90: k += 2;
91: }
92: }
93: }
94:
95:
96:
97:
98:
99:
100: public void fftSandeTukey2 (double[] xr, double[] xi) {
101: int n4 = fftN >> 2;
102: int half = fftN >> 1;
103: for (int step = 1; half >= 1; half >>= 1, step <<= 1) {
104: for (int k = 0, theta = 0; k < half; k++, theta += step) {
105: double or = fftSinCos[theta + n4];
106: double oi = -fftSinCos[theta];
107: for (int start = 0; start < fftN; start += half << 1) {
108: int k0 = start + k;
109: int k1 = k0 + half;
110: double pr = xr[k0];
111: double pi = xi[k0];
112: double qr = xr[k1];
113: double qi = xi[k1];
114: xr[k0] = pr + qr;
115: xi[k0] = pi + qi;
116: pr -= qr;
117: pi -= qi;
118: xr[k1] = or * pr - oi * pi;
119: xi[k1] = or * pi + oi * pr;
120: }
121: }
122: }
123:
124: for (int k = 0, l = fftSwap.length; k < l; k += 2) {
125: int i = fftSwap[k];
126: int j = fftSwap[k + 1];
127: double t = xr[i];
128: xr[i] = xr[j];
129: xr[j] = t;
130: t = xi[i];
131: xi[i] = xi[j];
132: xi[j] = t;
133: }
134: }
135:
136:
137:
138:
139:
140:
141:
142:
143: public void fftSandeTukey4 (double[] xr, double[] xi) {
144: int mask = fftN - 1;
145: int n4 = fftN >> 2;
146: int quarter = n4;
147: for (int step = 1; quarter >= 2; quarter >>= 2, step <<= 2) {
148: for (int k = 0, theta1 = 0; k < quarter; k++, theta1 += step) {
149: int theta2 = theta1 + theta1 & mask;
150: int theta3 = theta2 + theta1 & mask;
151: double or1 = fftSinCos[theta1 + n4];
152: double oi1 = -fftSinCos[theta1];
153: double or2 = fftSinCos[theta2 + n4];
154: double oi2 = -fftSinCos[theta2];
155: double or3 = fftSinCos[theta3 + n4];
156: double oi3 = -fftSinCos[theta3];
157: for (int start = 0; start < fftN; start += quarter << 2) {
158: int k0 = start + k;
159: int k1 = k0 + quarter;
160: int k2 = k1 + quarter;
161: int k3 = k2 + quarter;
162: double xr0 = xr[k0];
163: double xi0 = xi[k0];
164: double xr1 = xr[k1];
165: double xi1 = xi[k1];
166: double xr2 = xr[k2];
167: double xi2 = xi[k2];
168: double xr3 = xr[k3];
169: double xi3 = xi[k3];
170: if (false) {
171: xr[k0] = (xr0 + xr2) + (xr1 + xr3);
172: xi[k0] = (xi0 + xi2) + (xi1 + xi3);
173: double tr = (xr0 + xr2) - (xr1 + xr3);
174: double ti = (xi0 + xi2) - (xi1 + xi3);
175: xr[k1] = or2 * tr - oi2 * ti;
176: xi[k1] = or2 * ti + oi2 * tr;
177: tr = (xr0 - xr2) + (xi1 - xi3);
178: ti = (xi0 - xi2) - (xr1 - xr3);
179: xr[k2] = or1 * tr - oi1 * ti;
180: xi[k2] = or1 * ti + oi1 * tr;
181: tr = (xr0 - xr2) - (xi1 - xi3);
182: ti = (xi0 - xi2) + (xr1 - xr3);
183: xr[k3] = or3 * tr - oi3 * ti;
184: xi[k3] = or3 * ti + oi3 * tr;
185: } else {
186: double pr, pi, qr, qi;
187: xr[k0] = (pr = xr0 + xr2) + (qr = xr1 + xr3);
188: xi[k0] = (pi = xi0 + xi2) + (qi = xi1 + xi3);
189: double tr = pr - qr;
190: double ti = pi - qi;
191: xr[k1] = or2 * tr - oi2 * ti;
192: xi[k1] = or2 * ti + oi2 * tr;
193: tr = (pr = xr0 - xr2) + (qr = xi1 - xi3);
194: ti = (pi = xi0 - xi2) - (qi = xr1 - xr3);
195: xr[k2] = or1 * tr - oi1 * ti;
196: xi[k2] = or1 * ti + oi1 * tr;
197: tr = pr - qr;
198: ti = pi + qi;
199: xr[k3] = or3 * tr - oi3 * ti;
200: xi[k3] = or3 * ti + oi3 * tr;
201: }
202: }
203: }
204: }
205: if (quarter == 1) {
206: for (int k0 = 0; k0 < fftN; k0 += 4) {
207: int k1 = k0 + 1;
208: int k2 = k0 + 2;
209: int k3 = k0 + 3;
210: double xr0 = xr[k0];
211: double xi0 = xi[k0];
212: double xr1 = xr[k1];
213: double xi1 = xi[k1];
214: double xr2 = xr[k2];
215: double xi2 = xi[k2];
216: double xr3 = xr[k3];
217: double xi3 = xi[k3];
218: if (false) {
219: xr[k0] = (xr0 + xr2) + (xr1 + xr3);
220: xi[k0] = (xi0 + xi2) + (xi1 + xi3);
221: xr[k1] = (xr0 + xr2) - (xr1 + xr3);
222: xi[k1] = (xi0 + xi2) - (xi1 + xi3);
223: xr[k2] = (xr0 - xr2) + (xi1 - xi3);
224: xi[k2] = (xi0 - xi2) - (xr1 - xr3);
225: xr[k3] = (xr0 - xr2) - (xi1 - xi3);
226: xi[k3] = (xi0 - xi2) + (xr1 - xr3);
227: } else {
228: double t0p2r = xr0 + xr2;
229: double t0p2i = xi0 + xi2;
230: double t0m2r = xr0 - xr2;
231: double t0m2i = xi0 - xi2;
232: double t1p3r = xr1 + xr3;
233: double t1p3i = xi1 + xi3;
234: double t1m3r = xr1 - xr3;
235: double t1m3i = xi1 - xi3;
236: xr[k0] = t0p2r + t1p3r;
237: xi[k0] = t0p2i + t1p3i;
238: xr[k1] = t0p2r - t1p3r;
239: xi[k1] = t0p2i - t1p3i;
240: xr[k2] = t0m2r + t1m3i;
241: xi[k2] = t0m2i - t1m3r;
242: xr[k3] = t0m2r - t1m3i;
243: xi[k3] = t0m2i + t1m3r;
244: }
245: }
246: } else {
247: for (int k0 = 0; k0 < fftN; k0 += 2) {
248: int k1 = k0 + 1;
249: double xr0 = xr[k0];
250: double xi0 = xi[k0];
251: double xr1 = xr[k1];
252: double xi1 = xi[k1];
253: xr[k0] = xr0 + xr1;
254: xi[k0] = xi0 + xi1;
255: xr[k1] = xr0 - xr1;
256: xi[k1] = xi0 - xi1;
257: }
258: }
259:
260: for (int k = 0, l = fftSwap.length; k < l; k += 2) {
261: int i = fftSwap[k];
262: int j = fftSwap[k + 1];
263: double t = xr[i];
264: xr[i] = xr[j];
265: xr[j] = t;
266: t = xi[i];
267: xi[i] = xi[j];
268: xi[j] = t;
269: }
270: }
271:
272: }
273:
274:
275: