using System; using System.IO; using System.Collections; public class complex { public double Re; public double Img; private double temp; public complex() : this(0, 0) {} public complex(double newRe) : this(newRe, 0) {} public complex(double newRe, double newImg) { Re = newRe; Img = newImg; } public double Real { get { return Re; } set { Re = value; } } public double Image { get { return Img; } set { Img = value; } } public complex Conjugate { get { return new complex(Re, -Img); } } public double Magnitude { get { return Math.Sqrt(Math.Pow(Re,2) + Math.Pow(Img,2)); } } public double ArgGrad { get { if ((Re >= 0) && (Image >= 0)) { temp = Math.Atan(Image / Re) * 180 / Math.PI; } else if (Re < 0) { temp = 180 + Math.Atan(Image / Re) * 180 / Math.PI; } else if ((Re > 0) && (Image < 0)) { temp = 360 + Math.Atan(Image / Re) * 180 / Math.PI; } return temp; } } public complex Polar(double mag, double angle) { return new complex(mag * Math.Cos(Math.PI * angle / 180), mag * Math.Sin(Math.PI * angle / 180)); } public complex Exponential(double mag, double angle) { return new complex(mag * Math.Cos(angle), mag * Math.Sin(angle)); } public static complex operator+(complex fComplex) { return fComplex; } public static complex operator+(double amount, complex sComplex) { return new complex(sComplex.Real + amount, sComplex.Image); } public static complex operator+(complex fComplex, double amount) { return new complex(fComplex.Real + amount, fComplex.Image); } public static complex operator+(complex fComplex, complex sComplex) { return new complex(fComplex.Real + sComplex.Real, fComplex.Image + sComplex.Image); } public static complex operator-(complex fComplex) { return new complex(-fComplex.Real, -fComplex.Image); } public static complex operator-(double amount, complex sComplex) { return new complex(amount - sComplex.Real, -sComplex.Image); } public static complex operator-(complex fComplex, double amount) { return new complex(fComplex.Real - amount, fComplex.Image); } public static complex operator-(complex fComplex, complex sComplex) { return new complex(fComplex.Real - sComplex.Real, fComplex.Image - sComplex.Image); } public static complex operator*(double amount, complex sComplex) { return new complex(amount * sComplex.Real, amount * sComplex.Image); } public static complex operator*(complex fComplex, double amount) { return new complex(fComplex.Real * amount, fComplex.Image * amount); } public static complex operator*(complex fComplex, complex sComplex) { return new complex(fComplex.Real * sComplex.Real - fComplex.Image * sComplex.Image, fComplex.Real * sComplex.Image + fComplex.Image * sComplex.Real); } public static complex operator/(double amount, complex sComplex) { return new complex((amount * sComplex.Real) / (sComplex.Real * sComplex.Real + sComplex.Image * sComplex.Image), (- amount * sComplex.Image) / (sComplex.Real * sComplex.Real + sComplex.Image * sComplex.Image)); } public static complex operator/(complex fComplex, double amount) { return new complex(fComplex.Real / amount, fComplex.Image / amount); } public static complex operator/(complex fComplex, complex sComplex) { return new complex((fComplex.Real * sComplex.Real + fComplex.Image * sComplex.Image) / (sComplex.Real * sComplex.Real + sComplex.Image * sComplex.Image), (sComplex.Real * fComplex.Image - fComplex.Real * sComplex.Image) / (sComplex.Real * sComplex.Real + sComplex.Image * sComplex.Image)); } public override string ToString() { string str1 = "", str2 = "", str3 = ""; if ((this.Real >= 0) && (this.Image >= 0)) { str1 = this.Real.ToString("0.0000000000"); str2 = " + "; str3 = "i * " + this.Image.ToString("0.0000000000"); } else if ((this.Real >= 0) && (this.Image <= 0)) { str1 = this.Real.ToString("0.0000000000"); str2 = " - "; str3 = "i * " + (-this.Image).ToString("0.0000000000"); } else if ((this.Real <= 0) && (this.Image >= 0)) { str1 = "- " + (-this.Real).ToString("0.0000000000"); str2 = " + "; str3 = "i * " + this.Image.ToString("0.0000000000"); } else if ((this.Real <= 0) && (this.Image <= 0)) { str1 = "- " + (-this.Real).ToString("0.0000000000"); str2 = " - "; str3 = "i * " + (-this.Image).ToString("0.0000000000"); } return str1 + str2 + str3; } } public class FFT { public movable Solve(Channel (complex[]) c, complex[] In) { if (In.Length < 2) { c(LocalSolve(In)); } else { uint n = (uint) In.Length; uint nh = (uint) (n / 2); uint k; complex w; complex wn = new complex(); complex[] a0 = new complex[nh]; complex[] a1 = new complex[nh]; complex[] y0 = new complex[nh]; complex[] y1 = new complex[nh]; complex[] y = new complex[n]; wn = wn.Exponential(1, 2 * Math.PI / n); w = new complex(1, 0); for (k = 0; k < nh; k++) { a0[k] = In[k * 2]; a1[k] = In[k * 2 + 1]; } FFT fft = new FFT(); fft.Solve(c1, a0); y1 = LocalSolve(a1); y0 = new complex[nh]; y0 = Get(); for (k = 0; k < nh; k++) { y[k] = y0[k] + w * y1[k]; y[k + nh] = y0[k] - w * y1[k]; w = w * wn; } c(y); } } complex[] Get() & Channel c1(complex[] x) { return (x); } private complex[] LocalSolve(complex[] In) { uint n = (uint) In.Length; uint nh = (uint) (n / 2); uint k; complex w; complex wn = new complex(); complex[] a0 = new complex[nh]; complex[] a1 = new complex[nh]; complex[] y0 = new complex[nh]; complex[] y1 = new complex[nh]; complex[] y = new complex[n]; if (n == 1) { return (In); } wn = wn.Exponential(1, 2 * Math.PI / n); w = new complex(1, 0); for (k = 0; k < nh; k++) { a0[k] = In[k * 2]; a1[k] = In[k * 2 + 1]; } y0 = LocalSolve(a0); y1 = LocalSolve(a1); for (k = 0; k < nh; k++) { y[k] = y0[k] + w * y1[k]; y[k + nh] = y0[k] - w * y1[k]; w = w * wn; } return (y); } } class RecursiveFFT { public static void Main(string[] args) { uint n, i, k; RecursiveFFT rfft = new RecursiveFFT(); FFT fft = new FFT(); try { FileStream f = new FileStream(args[0], FileMode.Open, FileAccess.Read); StreamReader rf = new StreamReader(f); string str = rf.ReadLine(); n = (uint) System.Convert.ToInt32(str); k = (uint) Math.Ceiling(Math.Log(n, 2)); complex[] S = new complex[(int) Math.Pow(2, k)]; string[] ss = new string[2]; for (i = 0; i < n; i++) { str = rf.ReadLine(); if (str != null) { ss = str.Split(new char[] {' '}, 2); S[i] = new complex(System.Convert.ToDouble(ss[0]), System.Convert.ToDouble(ss[1])); } } rf.Close(); fft.Solve(rfft.c, S); // S = new complex[n]; S = rfft.Get(); for (i = 0; i < n; i++) { System.Console.WriteLine("{0}", S[i]); } } catch (Exception e) { Console.WriteLine("\nNow processing Main() Exception:"); while (e != null) { Console.WriteLine("\tInner: {0}", e.Message); e = e.InnerException; } } } complex[] Get() & Channel c(complex[] x) { return (x); } }