1 public class fft2d extends Thread {
2 //Title: 2-d mixed radix FFT.
4 //Copyright: Copyright (c) 1998
6 //Company: University of Wisconsin-Milwaukee.
8 // . Use fft1d to perform fft2d.
10 // Code borrowed from :Java Digital Signal Processing book by Lyon and Rao
12 public fft1d fft1, fft2;
14 public int x0, x1, y0, y1;
16 // Constructor: 2-d FFT of Complex data.
17 public fft2d(Matrix data, fft1d fft1, fft1d fft2, int x0, int x1, int y0, int y1) {
29 barr = new Barrier("128.195.175.84");
30 double tempdataRe[][];
31 double tempdataIm[][];
32 int rowlength, columnlength;
33 double temRe[];// intermediate results
38 rowlength = data.M; //height
39 columnlength = data.N; //width
40 tempdataRe = data.dataRe;
41 tempdataIm = data.dataIm;
43 // Calculate FFT for each row of the data.
44 // for (int i = 0; i < height; i++)
45 // fft1.fft(dataRe[i], dataIm[i]);
46 for (int i = x0; i < x1; i++) {
48 if(columnlength != N) {
49 System.printString("Error: the length of real part & imaginary part " + "of the input to 1-d FFT are different");
52 //Permute() operation on fft1
54 double inputRe[] = tempdataRe[i]; //local array
55 double inputIm[] = tempdataIm[i];
57 double outputRe[] = fft1.outputRe; //local array
58 double outputIm[] = fft1.outputIm;
59 temRe = fft1.temRe; // intermediate results
61 int count[] = new int[fft1.MaxFactorsNumber];
64 for(int a = 0; a < N-1; a++) {
65 outputRe[a] = inputRe[k];
66 outputIm[a] = inputIm[k];
68 k = k + fft1.remain[j];
69 count[0] = count[0] + 1;
70 while (count[j] >= fft1.factors[j]) {
76 tmp = fft1.remain[j - 1];
77 k = k - tmp + fft1.remain[j + 1];
79 count[j] = count[j] + 1;
82 outputRe[N - 1] = inputRe[N - 1];
83 outputIm[N - 1] = inputIm[N - 1];
85 //Twiddle oeration on fft1
86 for (int factorIndex = 0; factorIndex < fft1.NumofFactors; factorIndex++) {
87 twiddle(factorIndex, fft1, temRe, temIm, outputRe, outputIm);
89 //System.printString("ready to copy");
90 // Copy the output[] data to input[], so the output can be
91 // returned in the input array.
92 for (int b = 0; b < N; b++) {
93 inputRe[b] = outputRe[b];
94 inputIm[b] = outputIm[b];
100 Barrier.enterBarrier(barr);
103 double mytemRe[][], mytemIm[][];
105 tempdataRe = data.dataRe;
106 tempdataIm = data.dataIm;
107 for(int i = x0; i<x1; i++) {
108 double tRe[] = tempdataRe[i];
109 double tIm[] = tempdataIm[i];
110 for(int j = 0; j<columnlength; j++) { //TODO Check this
111 mytemRe[j][i] = tRe[j];
112 mytemIm[j][i] = tIm[j];
118 Barrier.enterBarrier(barr);
119 // double temRe[][] = transpose(data.dataRe);
120 //double temIm[][] = transpose(data.dataIm);
122 // Calculate FFT for each column of the data.
124 for (int j = y0; j < y1; j++) {
125 //fft2.fft(temRe[j], temIm[j]);
128 System.printString("Error: the length of real part & imaginary part " + "of the input to 1-d FFT are different");
131 //Permute() operation on fft2
133 double inputRe[] = mytemRe[j]; //local array
134 double inputIm[] = mytemIm[j];
136 double outputRe[] = fft2.outputRe; //local array
137 double outputIm[] = fft2.outputIm;
138 temRe = fft2.temRe; // intermediate results
140 int count[] = new int[fft2.MaxFactorsNumber];
143 for(int a = 0; a < N-1; a++) {
144 outputRe[a] = inputRe[k];
145 outputIm[a] = inputIm[k];
147 k = k + fft2.remain[r];
148 count[0] = count[0] + 1;
149 while (count[r] >= fft2.factors[r]) {
155 tmp = fft2.remain[r - 1];
156 k = k - tmp + fft2.remain[r + 1];
158 count[r] = count[r] + 1;
161 outputRe[N - 1] = inputRe[N - 1];
162 outputIm[N - 1] = inputIm[N - 1];
164 //Twiddle oeration on fft2
165 for (int factorIndex = 0; factorIndex < fft2.NumofFactors; factorIndex++) {
166 twiddle(factorIndex, fft2, temRe, temIm, outputRe, outputIm);
168 //System.printString("ready to copy");
169 // Copy the output[] data to input[], so the output can be
170 // returned in the input array.
171 for (int b = 0; b < N; b++) {
172 inputRe[b] = outputRe[b];
173 inputIm[b] = outputIm[b];
180 Barrier.enterBarrier(barr);
183 // Copy the result to input[], so the output can be
184 // returned in the input array.
186 for (int i = x0; i < x1; i++) {
187 for (int j = y0; j < y1; j++) {
188 tempdataRe[i][j] = mytemRe[j][i];
189 tempdataIm[i][j] = mytemIm[j][i];
190 //inputRe[i * width + j] = temRe[j][i];
191 //inputIm[i * width + j] = temIm[j][i];
196 //("ready to twiddle");
197 private void twiddle(int factorIndex, fft1d myfft, double[] temRe, double[] temIm,
198 double[] outputRe, double[] outputIm) {
200 int sofarRadix = myfft.sofar[factorIndex];
201 int radix = myfft.factors[factorIndex];
202 int remainRadix = myfft.remain[factorIndex];
204 double tem; // Temporary variable to do data exchange.
206 double W = 2 * (double) Math.setPI() / (sofarRadix * radix);
207 double cosW = (double) Math.cos(W);
208 double sinW = -(double) Math.sin(W);
210 double twiddleRe[] = new double[radix];
211 double twiddleIm[] = new double[radix];
212 double twRe = 1.0f, twIm = 0f;
214 //Initialize twiddle addBk.address variables.
215 int dataOffset = 0, groupOffset = 0, address = 0;
217 for (int dataNo = 0; dataNo < sofarRadix; dataNo++) {
218 //System.printString("datano="+dataNo);
219 if (sofarRadix > 1) {
224 for (int i = 2; i < radix; i++) {
225 twiddleRe[i] = twRe * twiddleRe[i - 1] - twIm * twiddleIm[i - 1];
226 twiddleIm[i] = twIm * twiddleRe[i - 1] + twRe * twiddleIm[i - 1];
228 tem = cosW * twRe - sinW * twIm;
229 twIm = sinW * twRe + cosW * twIm;
232 for (int groupNo = 0; groupNo < remainRadix; groupNo++) {
233 //System.printString("groupNo="+groupNo);
234 if ((sofarRadix > 1) && (dataNo > 0)) {
235 temRe[0] = outputRe[address];
236 temIm[0] = outputIm[address];
239 address = address + sofarRadix;
240 temRe[blockIndex] = twiddleRe[blockIndex] * outputRe[address] -
241 twiddleIm[blockIndex] * outputIm[address];
242 temIm[blockIndex] = twiddleRe[blockIndex] * outputIm[address] +
243 twiddleIm[blockIndex] * outputRe[address];
245 } while (blockIndex < radix);
247 for (int i = 0; i < radix; i++) {
248 //System.printString("temRe.length="+temRe.length);
249 //System.printString("i = "+i);
250 temRe[i] = outputRe[address];
251 temIm[i] = outputIm[address];
252 address += sofarRadix;
254 //System.printString("radix="+radix);
256 tem = temRe[0] + temRe[1];
257 temRe[1] = temRe[0] - temRe[1];
259 tem = temIm[0] + temIm[1];
260 temIm[1] = temIm[0] - temIm[1];
262 } else if( radix == 3) {
263 double t1Re = temRe[1] + temRe[2];
264 double t1Im = temIm[1] + temIm[2];
265 temRe[0] = temRe[0] + t1Re;
266 temIm[0] = temIm[0] + t1Im;
268 double m1Re = myfft.cos2to3PI * t1Re;
269 double m1Im = myfft.cos2to3PI * t1Im;
270 double m2Re = myfft.sin2to3PI * (temIm[1] - temIm[2]);
271 double m2Im = myfft.sin2to3PI * (temRe[2] - temRe[1]);
272 double s1Re = temRe[0] + m1Re;
273 double s1Im = temIm[0] + m1Im;
275 temRe[1] = s1Re + m2Re;
276 temIm[1] = s1Im + m2Im;
277 temRe[2] = s1Re - m2Re;
278 temIm[2] = s1Im - m2Im;
279 } else if(radix == 4) {
281 } else if(radix == 5) {
282 fft5(myfft, temRe, temIm);
283 } else if(radix == 8) {
284 fft8(myfft, temRe, temIm);
285 } else if(radix == 10) {
286 fft10(myfft, temRe, temIm);
288 fftPrime(radix, temRe, temIm);
290 address = groupOffset;
291 for (int i = 0; i < radix; i++) {
292 outputRe[address] = temRe[i];
293 outputIm[address] = temIm[i];
294 address += sofarRadix;
296 groupOffset += sofarRadix * radix;
297 address = groupOffset;
299 groupOffset = ++dataOffset;
300 address = groupOffset;
302 } //twiddle operation
304 // The two arguments dataRe[], dataIm[] are mainly for using in fft8();
305 private void fft4(double dataRe[], double dataIm[]) {
306 double t1Re,t1Im, t2Re,t2Im;
307 double m2Re,m2Im, m3Re,m3Im;
309 t1Re = dataRe[0] + dataRe[2];
310 t1Im = dataIm[0] + dataIm[2];
311 t2Re = dataRe[1] + dataRe[3];
312 t2Im = dataIm[1] + dataIm[3];
314 m2Re = dataRe[0] - dataRe[2];
315 m2Im = dataIm[0] - dataIm[2];
316 m3Re = dataIm[1] - dataIm[3];
317 m3Im = dataRe[3] - dataRe[1];
319 dataRe[0] = t1Re + t2Re;
320 dataIm[0] = t1Im + t2Im;
321 dataRe[2] = t1Re - t2Re;
322 dataIm[2] = t1Im - t2Im;
323 dataRe[1] = m2Re + m3Re;
324 dataIm[1] = m2Im + m3Im;
325 dataRe[3] = m2Re - m3Re;
326 dataIm[3] = m2Im - m3Im;
327 } // End of function fft4().
329 // The two arguments dataRe[], dataIm[] are mainly for using in fft10();
330 private void fft5(fft1d myfft, double dataRe[], double dataIm[]) {
331 double t1Re,t1Im, t2Re,t2Im, t3Re,t3Im, t4Re,t4Im, t5Re,t5Im;
332 double m1Re,m1Im, m2Re,m2Im, m3Re,m3Im, m4Re,m4Im, m5Re,m5Im;
333 double s1Re,s1Im, s2Re,s2Im, s3Re,s3Im, s4Re,s4Im, s5Re,s5Im;
335 t1Re = dataRe[1] + dataRe[4];
336 t1Im = dataIm[1] + dataIm[4];
337 t2Re = dataRe[2] + dataRe[3];
338 t2Im = dataIm[2] + dataIm[3];
339 t3Re = dataRe[1] - dataRe[4];
340 t3Im = dataIm[1] - dataIm[4];
341 t4Re = dataRe[3] - dataRe[2];
342 t4Im = dataIm[3] - dataIm[2];
346 dataRe[0] = dataRe[0] + t5Re;
347 dataIm[0] = dataIm[0] + t5Im;
349 m1Re = myfft.c51 * t5Re;
350 m1Im = myfft.c51 * t5Im;
351 m2Re = myfft.c52 * (t1Re - t2Re);
352 m2Im = myfft.c52 * (t1Im - t2Im);
353 m3Re = -(myfft.c53) * (t3Im + t4Im);
354 m3Im = myfft.c53 * (t3Re + t4Re);
355 m4Re = -(myfft.c54) * t4Im;
356 m4Im = myfft.c54 * t4Re;
357 m5Re = -(myfft.c55) * t3Im;
358 m5Im = myfft.c55 * t3Re;
364 s1Re = dataRe[0] + m1Re;
365 s1Im = dataIm[0] + m1Im;
371 dataRe[1] = s2Re + s3Re;
372 dataIm[1] = s2Im + s3Im;
373 dataRe[2] = s4Re + s5Re;
374 dataIm[2] = s4Im + s5Im;
375 dataRe[3] = s4Re - s5Re;
376 dataIm[3] = s4Im - s5Im;
377 dataRe[4] = s2Re - s3Re;
378 dataIm[4] = s2Im - s3Im;
379 } // End of function fft5().
381 private void fft8(fft1d myfft, double[] temRe, double[] temIm) {
382 double data1Re[] = new double[4];
383 double data1Im[] = new double[4];
384 double data2Re[] = new double[4];
385 double data2Im[] = new double[4];
388 // To improve the speed, use direct assaignment instead for loop here.
389 data1Re[0] = temRe[0];
390 data2Re[0] = temRe[1];
391 data1Re[1] = temRe[2];
392 data2Re[1] = temRe[3];
393 data1Re[2] = temRe[4];
394 data2Re[2] = temRe[5];
395 data1Re[3] = temRe[6];
396 data2Re[3] = temRe[7];
398 data1Im[0] = temIm[0];
399 data2Im[0] = temIm[1];
400 data1Im[1] = temIm[2];
401 data2Im[1] = temIm[3];
402 data1Im[2] = temIm[4];
403 data2Im[2] = temIm[5];
404 data1Im[3] = temIm[6];
405 data2Im[3] = temIm[7];
407 fft4(data1Re, data1Im);
408 fft4(data2Re, data2Im);
410 tem = myfft.OnetoSqrt2 * (data2Re[1] + data2Im[1]);
411 data2Im[1] = myfft.OnetoSqrt2 * (data2Im[1] - data2Re[1]);
414 data2Im[2] = -data2Re[2];
416 tem = myfft.OnetoSqrt2 * (data2Im[3] - data2Re[3]);
417 data2Im[3] = -(myfft.OnetoSqrt2) * (data2Re[3] + data2Im[3]);
420 temRe[0] = data1Re[0] + data2Re[0];
421 temRe[4] = data1Re[0] - data2Re[0];
422 temRe[1] = data1Re[1] + data2Re[1];
423 temRe[5] = data1Re[1] - data2Re[1];
424 temRe[2] = data1Re[2] + data2Re[2];
425 temRe[6] = data1Re[2] - data2Re[2];
426 temRe[3] = data1Re[3] + data2Re[3];
427 temRe[7] = data1Re[3] - data2Re[3];
429 temIm[0] = data1Im[0] + data2Im[0];
430 temIm[4] = data1Im[0] - data2Im[0];
431 temIm[1] = data1Im[1] + data2Im[1];
432 temIm[5] = data1Im[1] - data2Im[1];
433 temIm[2] = data1Im[2] + data2Im[2];
434 temIm[6] = data1Im[2] - data2Im[2];
435 temIm[3] = data1Im[3] + data2Im[3];
436 temIm[7] = data1Im[3] - data2Im[3];
437 } // End of function fft8().
439 private void fft10(fft1d myfft, double[] temRe, double[] temIm) {
440 double data1Re[] = new double[5];
441 double data1Im[] = new double[5];
442 double data2Re[] = new double[5];
443 double data2Im[] = new double[5];
445 // To improve the speed, use direct assaignment instead for loop here.
446 data1Re[0] = temRe[0];
447 data2Re[0] = temRe[5];
448 data1Re[1] = temRe[2];
449 data2Re[1] = temRe[7];
450 data1Re[2] = temRe[4];
451 data2Re[2] = temRe[9];
452 data1Re[3] = temRe[6];
453 data2Re[3] = temRe[1];
454 data1Re[4] = temRe[8];
455 data2Re[4] = temRe[3];
457 data1Im[0] = temIm[0];
458 data2Im[0] = temIm[5];
459 data1Im[1] = temIm[2];
460 data2Im[1] = temIm[7];
461 data1Im[2] = temIm[4];
462 data2Im[2] = temIm[9];
463 data1Im[3] = temIm[6];
464 data2Im[3] = temIm[1];
465 data1Im[4] = temIm[8];
466 data2Im[4] = temIm[3];
468 fft5(myfft, data1Re, data1Im);
469 fft5(myfft, data2Re, data2Im);
471 temRe[0] = data1Re[0] + data2Re[0];
472 temRe[5] = data1Re[0] - data2Re[0];
473 temRe[6] = data1Re[1] + data2Re[1];
474 temRe[1] = data1Re[1] - data2Re[1];
475 temRe[2] = data1Re[2] + data2Re[2];
476 temRe[7] = data1Re[2] - data2Re[2];
477 temRe[8] = data1Re[3] + data2Re[3];
478 temRe[3] = data1Re[3] - data2Re[3];
479 temRe[4] = data1Re[4] + data2Re[4];
480 temRe[9] = data1Re[4] - data2Re[4];
482 temIm[0] = data1Im[0] + data2Im[0];
483 temIm[5] = data1Im[0] - data2Im[0];
484 temIm[6] = data1Im[1] + data2Im[1];
485 temIm[1] = data1Im[1] - data2Im[1];
486 temIm[2] = data1Im[2] + data2Im[2];
487 temIm[7] = data1Im[2] - data2Im[2];
488 temIm[8] = data1Im[3] + data2Im[3];
489 temIm[3] = data1Im[3] - data2Im[3];
490 temIm[4] = data1Im[4] + data2Im[4];
491 temIm[9] = data1Im[4] - data2Im[4];
492 } // End of function fft10().
494 private void fftPrime(int radix, double[] temRe, double[] temIm) {
496 double W = 2 * (double) Math.setPI() / radix;
497 double cosW = (double) Math.cos(W);
498 double sinW = -(double) Math.sin(W);
499 double WRe[] = new double[radix];
500 double WIm[] = new double[radix];
507 for (int i = 2; i < radix; i++) {
508 WRe[i] = cosW * WRe[i - 1] - sinW * WIm[i - 1];
509 WIm[i] = sinW * WRe[i - 1] + cosW * WIm[i - 1];
512 // FFT of prime length data, using DFT, can be improved in the future.
513 double rere, reim, imre, imim;
515 int max = (radix + 1) / 2;
517 double tem1Re[] = new double[max];
518 double tem1Im[] = new double[max];
519 double tem2Re[] = new double[max];
520 double tem2Im[] = new double[max];
522 for (j = 1; j < max; j++) {
523 tem1Re[j] = temRe[j] + temRe[radix - j];
524 tem1Im[j] = temIm[j] - temIm[radix - j];
525 tem2Re[j] = temRe[j] - temRe[radix - j];
526 tem2Im[j] = temIm[j] + temIm[radix - j];
529 for (j = 1; j < max; j++) {
532 temRe[radix - j] = temRe[0];
533 temIm[radix - j] = temIm[0];
535 for (int i = 1; i < max; i++) {
536 rere = WRe[k] * tem1Re[i];
537 imim = WIm[k] * tem1Im[i];
538 reim = WRe[k] * tem2Im[i];
539 imre = WIm[k] * tem2Re[i];
541 temRe[radix - j] += rere + imim;
542 temIm[radix - j] += reim - imre;
543 temRe[j] += rere - imim;
544 temIm[j] += reim + imre;
551 for (j = 1; j < max; j++) {
552 temRe[0] = temRe[0] + tem1Re[j];
553 temIm[0] = temIm[0] + tem2Im[j];
555 } // End of function fftPrime().
557 public static void main(String[] args) {
562 NUM_THREADS=Integer.parseInt(args[0]);
564 SIZE = Integer.parseInt(args[1]);
568 // Matrix inputRe, inputIm;
573 inputRe = global new double[SIZE];
574 inputIm = global new double[SIZE];
576 for(int i = 0; i<SIZE; i++){
582 int[] mid = new int[8];
583 mid[0] = (128<<24)|(195<<16)|(175<<8)|84; //dw-10
584 mid[1] = (128<<24)|(195<<16)|(175<<8)|85; //dw-11
585 mid[2] = (128<<24)|(195<<16)|(175<<8)|86; //dw-12
586 mid[3] = (128<<24)|(195<<16)|(175<<8)|87; //dw-13
587 mid[4] = (128<<24)|(195<<16)|(175<<8)|88; //dw-14
588 mid[5] = (128<<24)|(195<<16)|(175<<8)|89; //dw-15
589 mid[6] = (128<<24)|(195<<16)|(175<<8)|90; //dw-16
590 mid[7] = (128<<24)|(195<<16)|(175<<8)|91; //dw-17
592 // Start Barrier Server
593 BarrierServer mybarr;
595 mybarr = global new BarrierServer(NUM_THREADS);
597 mybarr.start(mid[0]);
600 // Width and height of 2-d matrix inputRe or inputIm.
603 int Relength, Imlength;
605 height = inputRe.length / width;
606 Relength = inputRe.length;
607 Imlength = inputIm.length;
612 // First make sure inputRe & inputIm are of the same length in terms of columns
613 if (Relength != Imlength) {
614 System.printString("Error: the length of real part & imaginary part " +
615 "of the input to 2-d FFT are different");
619 fft1 = global new fft1d(width);
620 fft2 = global new fft1d(height);
621 // Set up data for FFT transform
622 data = global new Matrix(height, width);
623 data.setValues(inputRe, inputIm);
626 // Create threads to do FFT
629 myfft2d = global new fft2d[NUM_THREADS];
630 int increment = SIZE/NUM_THREADS;
632 for(int i =0 ; i<NUM_THREADS; i++) {
633 if((i+1)==NUM_THREADS)
634 myfft2d[i] = global new fft2d(data, fft1, fft2, base, SIZE, 0, SIZE);
636 myfft2d[i] = global new fft2d(data, fft1, fft2, base, base+increment, 0, SIZE);
641 boolean waitfordone=true;
650 //Start a thread to compute each c[l,n]
651 for(int i = 0; i<NUM_THREADS; i++) {
658 //Wait for thread to finish
659 for(int i = 0; i<NUM_THREADS; i++) {
669 // Copy the result to input[], so the output can be
670 // returned in the input array.
672 for (int i = 0; i < height; i++) {
673 for (int j = 0; j < width; j++) {
674 //inputRe[i * width + j] = temRe[j][i];
675 System.printInt((int)inputRe[i * width + j]);
676 //inputIm[i * width + j] = temIm[j][i];
677 System.printInt((int)inputIm[i * width + j]);