00001 using System; 00002 using System.Diagnostics; 00003 00004 namespace FFT 00005 { 00006 /// 00007 /// Iterative Discrete Fourier Transformation. 00008 /// 00009 public class IterativeFFT : IDFT 00010 { 00011 /// 00012 /// Direction of DFT. 00013 /// 00014 protected enum Direction : int { 00015 Forward, ///< Indicating the standard DFT. 00016 Backward ///< Indicating the inverse DFT. 00017 } 00018 00019 /// 00020 /// \copydoc FFT::IDFT::DFT(Complex[]) 00021 /// 00022 public Complex[] DFT(Complex[] a) 00023 { 00024 return FFT(a, Direction.Forward); 00025 } 00026 00027 /// 00028 /// \copydoc FFT::IDFT::InverseDFT(Complex[]) 00029 /// 00030 public Complex[] InverseDFT(Complex[] y) 00031 { 00032 return FFT(y, Direction.Backward); 00033 } 00034 00035 /// 00036 /// Copy table and rearrange the elements. 00037 /// 00038 /// The length <tt>n</tt> of the input table must be a power of 2. 00039 /// The index of an element <tt>a[i]</tt> in the output table 00040 /// is the bit reverse of the binary representation <tt>i</tt> 00041 /// (relative to the number of bits of <tt>n-1</tt>). For instance, if the 00042 /// array <tt>a</tt> has 16 elements indexed with numbers 00043 /// from <tt>0=0000B</tt> to <tt>15=1111B</tt>, then the 00044 /// index of the element <tt>a[5]</tt> in the output is <tt>10</tt> 00045 /// since <tt>5=0101B</tt> and <tt>10=1010B</tt>. 00046 /// 00047 /// \param a table whose length is a power of 2. 00048 /// 00049 /// Example: 00050 /// \code 00051 /// Complex[] a = {0,1,2,3,4,5,6,7}; 00052 /// Complex[] b = BitReverseCopy(a); // {0,4,2,6,1,5,3,7} 00053 /// Complex[] c = {5,3,4,6,7,2,9,1}; 00054 /// Complex[] d = BitReverseCopy(c); // {5,7,4,9,3,2,6,1} 00055 /// \endcode 00056 /// 00057 protected internal Complex[] BitReverseCopy(Complex[] a) 00058 { 00059 Debug.Assert(a != null, "a is null"); 00060 Debug.Assert(Utils.IsPowerOf2(a.Length),"length of a is not a power of 2!"); 00061 00062 Complex[] result = new Complex[a.Length]; 00063 00064 // Iteratively perform an increment of counter c in the reversed bit order 00065 // Start with the counter equal to 0. After each increment, copy an element of a 00066 // An example of sequence of counter increments for n=8: 00067 // i = 0 = 000B; c = 0 = 000B; result[0] = a[0]; 00068 // i = 1 = 001B; c = 4 = 100B; result[4] = a[1]; 00069 // i = 2 = 010B; c = 2 = 010B; result[2] = a[2]; 00070 // i = 3 = 110B; c = 6 = 110B; result[6] = a[3]; 00071 // i = 4 = 001B; c = 1 = 001B; result[1] = a[4]; 00072 // i = 5 = 101B; c = 5 = 101B; result[5] = a[5]; 00073 // i = 6 = 110B; c = 3 = 011B; result[3] = a[6]; 00074 // i = 7 = 111B; c = 7 = 111B; result[7] = a[7]; 00075 00076 00077 int n = a.Length; 00078 int c = 0; // the counter increased in the reversed bit order 00079 int i = 0; // the current index (the number of times counter has been increased) 00080 00081 result[c] = a[i]; 00082 while (c < n - 1) { 00083 00084 int bit = n / 2; //start with the "least" significant bit 00085 00086 while ((bit & c) != 0) { //while the current bit is set to 1, 00087 //carry the increment to the following bit, i.e. 00088 00089 c -= bit; // 1. set the bit to 0 00090 bit /= 2; // 2. move to the "more" significant bit 00091 00092 } //found the "least" significant bit set to 0 00093 00094 c += bit; //set this bit to 1 00095 00096 i++; 00097 00098 result[c] = a[i]; 00099 } 00100 00101 return result; 00102 } // BitReverseCopy 00103 00104 /// 00105 /// Computes DFT in the given direction. 00106 /// 00107 protected virtual Complex[] FFT(Complex[] a, Direction d) 00108 { 00109 int n = a.Length; 00110 int logN = Utils.Log2(n); 00111 int sgn = (d == Direction.Forward) ? (1) : (-1); 00112 00113 a = BitReverseCopy(a); 00114 00115 for (int s = 1; s < logN + 1; s++) { 00116 int m = Utils.Exp2(s); 00117 00118 for (int j = 0; j < m / 2; j++) { 00119 Complex twiddle = Complex.FromPolar(1, sgn * 2 * j * Math.PI / m); 00120 for (int k = j; k < n; k += m) { 00121 Complex t = twiddle * a[k + m / 2]; 00122 Complex u = a[k]; 00123 a[k] = u + t; 00124 a[k + m / 2] = u - t; 00125 } 00126 } 00127 } 00128 00129 if (d == Direction.Backward) { 00130 for (int i = 0; i < n; i++) { 00131 a[i] = a[i] / n; 00132 } 00133 } 00134 00135 return a; 00136 } //FFT 00137 00138 /// 00139 /// \copybrief FFT::IDFT::ToString() 00140 /// 00141 /// Returns the string <tt>"Iterative"</tt> 00142 public override string ToString() 00143 { 00144 return "Iterative"; 00145 } 00146 00147 } //class IterativeDFT 00148 00149 } //namespace FFT