public static Complex[] RealFastFourierTransform(double[] src, double amplitude = 1.0) { int n4 = 1 << (Mt.Log2Int(src.Length) - 2); int n = n4 * 4, n2 = n4 * 2, n3 = n4 * 3; int n2mask = n2 - 1; Complex[] Data = new Complex[n2 + 1]; for (int i = n2; --i >= 0;) { Data[i] = new Complex(src[i * 2], src[i * 2 + 1]); } Complex[] Dst = FastFourierTransform_(Data, true); TriangularTable Triangle = TriangularTable.Get(n); for (int i = n4; i >= 0; --i) { int j = n2 - i; Complex g1 = Dst[i]; Complex g2 = Complex.Conjugate(Dst[j & n2mask]); Complex h1 = (g1 + g2); Complex h2 = (g1 - g2) * Triangle.Complex(n3 - i); Data[i] = (h1 + h2); Data[j] = Complex.Conjugate(h1 - h2); } LetMul(Data, amplitude / 2); return(Data); }
static Complex[] FastFourierTransform_(Complex[] src, bool sw) { int l = Mt.Log2Int(src.Length); int n = 1 << l; Complex[] Data = new Complex[n]; for (int j = -(n >> 1), i = 0; i < n; i++) { int k = n; while ((k >>= 1) <= j) { j -= k; } j += k; Data[i] = src[j]; } int sign = sw ? -1 : 1; TriangularTable Triangle = TriangularTable.Get(n); for (int m = 0; m < l; m++) { int step = 1 << m; int rotw = sign * (1 << (l - 1 - m)); for (int k = 0; k < step; k++) { Complex u = Triangle.Complex(rotw * k); // (2 * Math.PI / n) * rotw * k for (int i = k; i < n; i += step * 2) { Complex t = Data[i + step] * u; Data[i + step] = Data[i] - t; Data[i] += t; } } } return(Data); }
public static double[] RealFastFourierTransform(Complex[] src, double amplitude = 1.0) { int n4 = 1 << (Mt.Log2Int(src.Length) - 1); int n = n4 * 4, n2 = n4 * 2, n3 = n4 * 3; int n2mask = n2 - 1; Complex[] Data = new Complex[n2]; TriangularTable Triangle = TriangularTable.Get(n); for (int i = n4; i >= 0; --i) { int j = n2 - i; Complex g1 = src[i]; Complex g2 = Complex.Conjugate(src[j]); Complex h1 = (g1 + g2); Complex h2 = (g1 - g2) * Triangle.Complex(n4 + i); Data[i] = (h1 + h2); Data[j & n2mask] = Complex.Conjugate(h1 - h2); } Data = FastFourierTransform_(Data, false); LetMul(Data, amplitude / n); double[] Dst = New.Array(n, i => (i & 1) == 0 ? Data[i / 2].Real : Data[i / 2].Imaginary); return(Dst); }