00001 using System;
00002 using System.Threading;
00003 using System.Diagnostics;
00004
00005 namespace FFT
00006 {
00007
00008
00009
00010
00011
00012 public class ParallelFFT : IterativeFFT
00013 {
00014
00015
00016
00017
00018
00019 protected int threadNo;
00020
00021
00022
00023
00024 protected struct FFTBatch
00025 {
00026 public Complex[] a;
00027 public Direction d;
00028 public int fromLevel;
00029 public int toLevel;
00030 public int fromRow;
00031 public int toRow;
00032
00033
00034
00035
00036 public FFTBatch(Complex[] a, Direction d,
00037 int fromLevel, int toLevel, int fromRow, int toRow)
00038 {
00039 this.a = a;
00040 this.d = d;
00041 this.fromLevel = fromLevel;
00042 this.toLevel = toLevel;
00043 this.fromRow = fromRow;
00044 this.toRow = toRow;
00045 }
00046
00047
00048
00049
00050 public void Do()
00051 {
00052 int sgn = (d == Direction.Forward) ? (1) : (-1);
00053
00054 for (int s = fromLevel; s < toLevel; s++) {
00055 int m = Utils.Exp2(s);
00056
00057 for (int j = 0; j < m / 2; j++) {
00058 Complex twiddler = Complex.FromPolar(1, sgn * 2 * j * Math.PI / m);
00059 for (int k = fromRow+j; k < toRow; k += m) {
00060 Complex t = twiddler * a[k + m / 2];
00061 Complex u = a[k];
00062 a[k] = u + t;
00063 a[k + m / 2] = u - t;
00064 }
00065 }
00066 }
00067 }
00068 }
00069
00070
00071
00072
00073
00074
00075
00076
00077 public ParallelFFT(int noThreads)
00078 {
00079 this.threadNo = Utils.Exp2(Utils.Log2(noThreads));
00080 }
00081
00082
00083
00084
00085 protected override Complex[] FFT(Complex[] a, Direction d)
00086 {
00087 Debug.Assert(a != null, "a is null");
00088 Debug.Assert(Utils.IsPowerOf2(a.Length),"length of a is not a power of 2!");
00089
00090 int n = a.Length;
00091 int logN = Utils.Log2(n);
00092 int m = this.threadNo;
00093 int logM = Utils.Log2(m);
00094
00095 a = BitReverseCopy(a);
00096
00097 Thread[] thread = new Thread[m];
00098
00099
00100 for (int i = 0; i < m; i++) {
00101 thread[i] = new Thread(new FFTBatch(a, d, 0, logN - logM, i*n/m, (i+1)*n/m).Do);
00102 thread[i].Start();
00103 }
00104
00105
00106
00107 for (int i = 0; i < m; i++) {
00108 thread[i].Join();
00109 }
00110
00111
00112 new FFTBatch(a, d, logN - logM, logN + 1, 0, n).Do();
00113
00114 if (d == Direction.Backward) {
00115 for (int i = 0; i < n; i++) {
00116 a[i] /= n;
00117 }
00118 }
00119
00120 return a;
00121
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 public override string ToString()
00144 {
00145 return "Parallel(" + threadNo + ")";
00146 }
00147
00148 }
00149 }