//#foreach instanced to 'Double' #region double #region Private Methods /// <summary> /// Fast furier transform, in place. /// </summary> /// <param name="inputs">The inputs.</param> /// <param name="forward">Is it forward or inverse transform.</param> static void InternalFFT(Complexd[] data, bool forward) { // We first permutate the inputs in bit-reversed order. ReverseBitsSort(data); // Is it a forward or backward transform. double exp = forward ? 1.0 : -1.0; int n = data.Length; int lnd = MathHelper.Log2(data.Length) + 1; for (int lmd = 1; lmd <= lnd; lmd++) { int m = 1 << lmd; int mh = m / 2; for (int j = 0; j < mh; j++) { Complexd e = MathHelper.ExpI(exp * (double)(2.0 * MathHelper.PI) * (double)j / (double)m); for (int r = 0; r <= n - m; r += m) { Complexd u = data[r + j]; Complexd v = data[r + j + mh] * e; data[r + j] = u + v; data[r + j + mh] = u - v; } } } }
/// <summary> /// Transforms the specified input. /// </summary> /// <param name="input">The input.</param> /// <param name="type">The type.</param> /// <returns></returns> public static Complexd[] Transform([PowerOfTwoArray] Complexd[] input, FurierTransformType type) { Complexd[] result = new Complexd[input.Length]; input.CopyTo(result, 0); TransformInPlace(result, type); return(result); }
public void SimpleTransform() { Complexd[] r1 = Complexd.ToComplexArray(new double[] { 1, 1, 2, 2, 1, 1, 0, 0 }); Complexd[] r2 = Complexd.ToComplexArray(new double[] { 1, 1, 2, 2, 1, 1, 0, 0 }); r2 = BruteForce(r2); r1 = DFT.Transform(r1, FurierTransformType.Normal); for (int i = 0; i < r1.Length; i++) { Assert.IsTrue(Complexd.NearEqual(r1[i], r2[i])); } }
/// <summary> /// Transforms the specified input. /// </summary> /// <param name="input">The input.</param> /// <param name="type">The type.</param> /// <returns></returns> public static Complexd[] Transform([PowerOfTwoArray] double[] input, FurierTransformType type) { Complexd[] result = new Complexd[input.Length]; for (int i = 0; i < input.Length; i++) { result[i] = new Complexd(input[i], 0.0); } TransformInPlace(result, type); return(result); }
/// <summary> /// Quadratic equation root; e.g. 0 = a*x^2 + b*x + c. The solution is either both with /// real numbers (imagionary = 0) or both with complex numbers. /// </summary> /// <param name="x0">The first complex result.</param> /// <param name="x1">The second complex result.</param> public static void Roots(double a, double b, double c, out Complexd x0, out Complexd x1) { double D = b * b - 4.0 * a * c; if (D < 0.0) { double sD = global::System.Math.Sqrt(-D); x0 = new Complexd((-b) / (2.0 * a), sD / (2.0 * a)); x1 = new Complexd((-b) / (2.0 * a), -sD / (2.0 * a)); } else { double sD = global::System.Math.Sqrt(D); x0 = new Complexd((-b + sD) / (2.0 * a), 0.0); x1 = new Complexd((-b - sD) / (2.0 * a), 0.0); } }
internal static Complexd[] BruteForce(Complexd[] input) { Complexd[] result = new Complexd[input.Length]; double N = (double)input.Length; // We perform the brute force method. for (int i = 0; i < input.Length; i++) { double n = (double)i; result[i] = Complexd.Zero; // We compute the amplitude. for (int j = 0; j < input.Length; j++) { result[i] += input[j] * MathHelper.ExpI((2.0 * MathHelper.PI / N) * n * (double)j); } } return(result); }