protected BSDataObject ProcessUsingFourierDirection(BSDataObject iObject, FourierTransform.Direction iDir) { Complex[] complexDataArray = (from tmp in iObject.DataArray select new Complex(tmp, 0)).ToArray(); FourierTransform.DFT(complexDataArray, iDir); double[] resultingArray = (from tmp in complexDataArray select Math.Sqrt(tmp.Re * tmp.Re + tmp.Im * tmp.Im)).ToArray(); return new BSDataObject(resultingArray, iObject.ObjName + "_Fouirer"); }
/// <summary> /// Two dimensional Fast Fourier Transform. /// </summary> /// /// <param name="data">Data to transform.</param> /// <param name="direction">Transformation direction.</param> /// /// <remarks><para><note>The method accepts <paramref name="data"/> array of 2<sup>n</sup> size /// only in each dimension, where <b>n</b> may vary in the [1, 14] range. For example, 16x16 array /// is valid, but 15x15 is not.</note></para></remarks> /// /// <exception cref="ArgumentException">Incorrect data length.</exception> /// public static void FFT2(Complex[,] data, Direction direction) { int k = data.GetLength(0); int n = data.GetLength(1); // check data size if (!Tools.IsPowerOf2(k) || !Tools.IsPowerOf2(n)) { throw new ArgumentException("The matrix rows and columns must be a power of 2."); } if (k < minLength || k > maxLength || n < minLength || n > maxLength) { throw new ArgumentException("Incorrect data length."); } // process rows var row = new Complex[n]; for (int i = 0; i < k; i++) { // copy row for (int j = 0; j < row.Length; j++) { row[j] = data[i, j]; } // transform it FourierTransform.FFT(row, direction); // copy back for (int j = 0; j < row.Length; j++) { data[i, j] = row[j]; } } // process columns var col = new Complex[k]; for (int j = 0; j < n; j++) { // copy column for (int i = 0; i < k; i++) { col[i] = data[i, j]; } // transform it FourierTransform.FFT(col, direction); // copy back for (int i = 0; i < k; i++) { data[i, j] = col[i]; } } }
/// <summary> /// Two dimensional Fast Fourier Transform. /// </summary> /// /// <param name="data">Data to transform.</param> /// <param name="direction">Transformation direction.</param> /// /// <remarks><para><note>The method accepts <paramref name="data"/> array of 2<sup>n</sup> size /// only in each dimension, where <b>n</b> may vary in the [1, 14] range. For example, 16x16 array /// is valid, but 15x15 is not.</note></para></remarks> /// /// <exception cref="ArgumentException">Incorrect data length.</exception> /// public static void FFT2(Complex[,] data, Direction direction) { int k = data.GetLength(0); int n = data.GetLength(1); // check data size if ( (!Tools.IsPowerOf2(k)) || (!Tools.IsPowerOf2(n)) || (k < minLength) || (k > maxLength) || (n < minLength) || (n > maxLength) ) { throw new ArgumentException("Incorrect data length."); } // process columns Complex[] col = new Complex[k]; for (int j = 0; j < n; j++) { // copy column for (int i = 0; i < k; i++) { col[i] = data[i, j]; } // transform it FourierTransform.FFT(col, direction); // copy back for (int i = 0; i < k; i++) { data[i, j] = col[i]; } } // process rows Complex[] row = new Complex[n]; for (int i = 0; i < k; i++) { // copy row for (int j = 0; j < n; j++) { row[j] = data[i, j]; } // transform it FourierTransform.FFT(row, direction); // copy back for (int j = 0; j < n; j++) { data[i, j] = row[j]; } } }
/// <summary> /// One dimensional Fast Fourier Transform. /// </summary> /// /// <param name="data">Data to transform.</param> /// <param name="direction">Transformation direction.</param> /// /// <remarks><para><note>The method accepts <paramref name="data"/> array of 2<sup>n</sup> size /// only, where <b>n</b> may vary in the [1, 14] range.</note></para></remarks> /// /// <exception cref="ArgumentException">Incorrect data length.</exception> /// public static void FFT(Complex[] data, Direction direction) { int n = data.Length; int m = Tools.Log2(n); // reorder data first ReorderData(data); // compute FFT int tn = 1, tm; for (int k = 1; k <= m; k++) { Complex[] rotation = FourierTransform.GetComplexRotation(k, direction); tm = tn; tn <<= 1; for (int i = 0; i < tm; i++) { Complex t = rotation[i]; for (int even = i; even < n; even += tn) { int odd = even + tm; Complex ce = data[even]; Complex co = data[odd]; double tr = co.Re * t.Re - co.Im * t.Im; double ti = co.Re * t.Im + co.Im * t.Re; data[even].Re += tr; data[even].Im += ti; data[odd].Re = ce.Re - tr; data[odd].Im = ce.Im - ti; } } } if (direction == Direction.Forward) { for (int i = 0; i < n; i++) { data[i].Re /= (double)n; data[i].Im /= (double)n; } } }
/// <summary> /// One dimensional Fast Fourier Transform. /// </summary> /// /// <param name="data">Data to transform.</param> /// <param name="direction">Transformation direction.</param> /// /// <remarks><para><note>The method accepts <paramref name="data"/> array of 2<sup>n</sup> size /// only, where <b>n</b> may vary in the [1, 14] range.</note></para></remarks> /// /// <exception cref="ArgumentException">Incorrect data length.</exception> /// public static void FFT(Complex[] data, Direction direction) { int n = data.Length; int m = Tools.Log2(n); // reorder data first ReorderData(data); // compute FFT int tn = 1, tm; for (int k = 1; k <= m; k++) { Complex[] rotation = FourierTransform.GetComplexRotation(k, direction); tm = tn; tn <<= 1; for (int i = 0; i < tm; i++) { Complex t = rotation[i]; for (int even = i; even < n; even += tn) { int odd = even + tm; Complex ce = data[even]; Complex co = data[odd]; double tr = co.Real * t.Real - co.Imaginary * t.Imaginary; double ti = co.Real * t.Imaginary + co.Imaginary * t.Real; data[even] += new Complex(tr, ti); data[odd] = new Complex(ce.Real - tr, ce.Imaginary - ti); } } } if (direction == Direction.Forward) { for (int i = 0; i < data.Length; i++) { data[i] /= (double)n; } } }
/// <summary> /// One dimensional Fast Fourier Transform. /// </summary> /// /// <param name="data">Data to transform.</param> /// <param name="direction">Transformation direction.</param> /// /// <remarks><para><note>The method accepts <paramref name="data"/> array of 2<sup>n</sup> size /// only, where <b>n</b> may vary in the [1, 14] range.</note></para></remarks> /// /// <exception cref="ArgumentException">Incorrect data length.</exception> /// public static void FFT(Complex[] data, Direction direction) { int n = data.Length; int m = Tools.Log2(n); // reorder data first ReorderData(data); // compute FFT int tn = 1, tm; for (int k = 1; k <= m; k++) { Complex[] rotation = FourierTransform.GetComplexRotation(k, direction); tm = tn; tn <<= 1; for (int i = 0; i < tm; i++) { var t = rotation[i]; for (int even = i; even < n; even += tn) { int odd = even + tm; var ce = data[even]; var cot = data[odd] * t; data[even] += cot; data[odd] = ce - cot; } } } if (direction == Direction.Forward) { for (int i = 0; i < n; i++) { data[i] /= (double)n; } } }
/// <summary> /// 1-D Discrete Fourier Transform. /// </summary> /// /// <param name="data">The data to transform..</param> /// <param name="direction">The transformation direction.</param> /// public static void DFT(Complex[] data, FourierTransform.Direction direction) { int n = data.Length; var c = new Complex[n]; // for each destination element for (int i = 0; i < c.Length; i++) { double sumRe = 0; double sumIm = 0; double phim = 2 * Math.PI * i / (double)n; // sum source elements for (int j = 0; j < n; j++) { double re = data[j].Re(); double im = data[j].Im(); double cosw = Math.Cos(phim * j); double sinw = Math.Sin(phim * j); if (direction == FourierTransform.Direction.Backward) sinw = -sinw; sumRe += (re * cosw + im * sinw); sumIm += (im * cosw - re * sinw); } c[i] = new Complex(sumRe, sumIm); } if (direction == FourierTransform.Direction.Backward) { for (int i = 0; i < c.Length; i++) data[i] = c[i] / n; } else { for (int i = 0; i < c.Length; i++) data[i] = c[i]; } }
/// <summary> /// 2-D Fast Fourier Transform. /// </summary> /// /// <param name="data">The data to transform..</param> /// <param name="direction">The Transformation direction.</param> /// public static void FFT2(Complex[][] data, FourierTransform.Direction direction) { int n = data.Length; int m = data[0].Length; // process rows for (int i = 0; i < data.Length; i++) { // transform it FFT(data[i], direction); } // process columns var col = new Complex[n]; for (int j = 0; j < m; j++) { // copy column for (int i = 0; i < col.Length; i++) col[i] = data[i][j]; // transform it FFT(col, direction); // copy back for (int i = 0; i < col.Length; i++) data[i][j] = col[i]; } }
/// <summary> /// 1-D Fast Fourier Transform. /// </summary> /// /// <param name="real">The real part of the complex numbers to transform.</param> /// <param name="imag">The imaginary part of the complex numbers to transform.</param> /// <param name="direction">The transformation direction.</param> /// public static void FFT(double[] real, double[] imag, FourierTransform.Direction direction) { if (direction == FourierTransform.Direction.Forward) { FFT(real, imag); } else { FFT(imag, real); } if (direction == FourierTransform.Direction.Backward) { for (int i = 0; i < real.Length; i++) { real[i] /= real.Length; imag[i] /= real.Length; } } }
/// <summary> /// 1-D Fast Fourier Transform. /// </summary> /// /// <param name="data">The data to transform..</param> /// <param name="direction">The transformation direction.</param> /// public static void FFT(Complex[] data, FourierTransform.Direction direction) { int n = data.Length; if (n == 0) return; if (direction == FourierTransform.Direction.Backward) { for (int i = 0; i < data.Length; i++) data[i] = new Complex(data[i].Im(), data[i].Re()); } if ((n & (n - 1)) == 0) { // Is power of 2 TransformRadix2(data); } else { // More complicated algorithm for arbitrary sizes TransformBluestein(data); } if (direction == FourierTransform.Direction.Backward) { for (int i = 0; i < data.Length; i++) { double im = data[i].Im(); double re = data[i].Re(); data[i] = new Complex(im / n, re / n); } } }
/// <summary> /// 2-D Discrete Fourier Transform. /// </summary> /// /// <param name="data">The data to transform.</param> /// <param name="direction">The transformation direction.</param> /// public static void DFT2(Complex[][] data, FourierTransform.Direction direction) { int n = data.Length; int m = data[0].Length; // process rows var row = new Complex[m]; for (int i = 0; i < n; i++) { // copy row for (int j = 0; j < row.Length; j++) row[j] = data[i][j]; // transform it DFT(row, direction); // copy back for (int j = 0; j < row.Length; j++) data[i][j] = row[j]; } // process columns var col = new Complex[n]; for (int j = 0; j < n; j++) { // copy column for (int i = 0; i < col.Length; i++) col[i] = data[i][j]; // transform it DFT(col, direction); // copy back for (int i = 0; i < col.Length; i++) data[i][j] = col[i]; } }