/// <summary> /// Make recursive FFT /// </summary> /// <param name="a">Polynom. Number of items must be pow of two</param> /// <param name="omega">Proper sqrt of 1</param> /// <returns></returns> public static Polynom RecursiveFFT(Polynom a, Complex omega) { if (ComplexUtils.IsAlmostEqual(omega, 1)) { return(a); } Polynom a_s = new Polynom(); Polynom a_l = new Polynom(); for (int i = 0; i < a.Count / 2; i++) { a_s.Add(a[2 * i]); a_l.Add(a[2 * i + 1]); } Polynom s = RecursiveFFT(a_s, omega * omega); Polynom l = RecursiveFFT(a_l, omega * omega); Complex x = 1; Polynom ret = new Polynom(a.Count); for (int i = 0; i < a.Count / 2; i++) { ret[i] = s[i] + x * l[i]; ret[i + a.Count / 2] = s[i] - x * l[i]; x *= omega; } return(ret); }
public static bool AreAlmostEquival(Polynom p, Polynom q, bool output = false) { p = p.Clone(); q = q.Clone(); p.Trim(); q.Trim(); if (p.Count != q.Count) { if (output) { Console.WriteLine("p.Count: {0},\nq.Count: {1}\n", p.Count, q.Count); } return(false); } for (int i = 0; i < p.Count; i++) { if (!ComplexUtils.IsAlmostEqual(p[i], q[i])) { if (output) { Console.WriteLine("p[i]: {0},\nq[i]: {1},\ni: {2}\n", p[i], q[i], i); } return(false); } } return(true); }
// Remove null members at the end public void Trim() { while (this.Count > 0 && ComplexUtils.IsAlmostEqual(this[this.Count - 1], 0)) { this.RemoveAt(this.Count - 1); } }
public override string ToString() { StringBuilder ret = new StringBuilder(); int i = 0; foreach (Complex c in this) { ret.Append(i + ": "); ret.AppendLine(ComplexUtils.ToNiceString(c)); i++; } return(ret.ToString()); }
public static string ToNiceString(Complex c) { Complex cr = ComplexUtils.RoundComplex(c); double r = cr.Real; double i = cr.Imaginary; if (i == 0) { return(string.Format("{0}", r, i)); } else if (r == 0) { return(string.Format("{1}i", r, i)); } else if (i < 0) { return(string.Format("{0} - {1}i", r, -i)); } else { return(string.Format("{0} + {1}i", r, i)); } }
/// <summary> /// /// </summary> /// <param name="p">Polynom. Must have pow of 2 member. Maybe you can use .ComplementWithNulls()</param> /// <param name="reversed">If true, the method will make reversed FFT (interpolation)</param> /// <returns></returns> public static Polynom NonrecursiveFFT(Polynom p, bool reversed = false) { int layersCount = (int)Math.Ceiling(Math.Log(p.Count, 2)); if (1 << layersCount != p.Count) { throw new ArgumentException("Polynom must have pow of 2 members. Maybe you want to use .ComplementWithNulls() methdo."); } //Permuts coefficients of p so they would suit the coefficients in the last layer of FFT Polynom new_p = new Polynom(p.Count); for (int i = 0; i < p.Count; i++) { int pom_i = i; int new_i = 0; int s = p.Count / 2; for (int l = 0; l < layersCount; l++) { if (pom_i % 2 == 1) { pom_i--; new_i += s; } pom_i /= 2; s /= 2; } new_p[new_i] = p[i]; } p = new_p; for (int layer = 1; layer <= layersCount; layer++) // { int nodeSize = 1 << layer; int nodeCount = p.Count / nodeSize; //division is integer Complex omega = ComplexUtils.GetSqrtOfOne(nodeSize); if (reversed) { omega = 1 / omega; } new_p = new Polynom(p.Count); for (int nodeI = 0; nodeI < nodeCount; nodeI++) { Complex x = 1; for (int i = 0; i < nodeSize / 2; i++) { Complex c1 = p[nodeI * nodeSize + i]; Complex c2 = p[nodeI * nodeSize + i + nodeSize / 2]; new_p[nodeI * nodeSize + i] = c1 + x * c2; new_p[nodeI * nodeSize + i + nodeSize / 2] = c1 - x * c2; x *= omega; } } p = new_p; //Uncomment to see how the algorithm works //Console.WriteLine("Layer {0}:", layer); //Console.WriteLine(p); //Console.WriteLine(); } return(p); }