/// <summary> /// Smallest file storage should erase file on disk after it is disposed /// </summary> public static void Test4() { Complex4Ks.totalRAM = 0; string fileName = null; using (Complex4Ks data = new Complex4Ks(8192)) { fileName = data.FileName; for (long index = 0; index < data.Length4ks; index++) { data[index] = new Complex[4096]; } if (!File.Exists(data.FileName)) { throw new Exception(); } } if (File.Exists(fileName)) { throw new Exception(); } Complex4Ks.totalRAM = 3L * 1024 * 1024 * 1024; }
/// <summary> /// Smallest file storage should retain values /// </summary> public static void Test6() { Complex4Ks.totalRAM = 0; using (Complex4Ks data = new Complex4Ks(8192)) { for (long index = 0; index < data.Length4ks; index++) { Complex[] fourK = new Complex[4096]; for (int i = 0; i < fourK.Length; i++) { fourK[i] = new Complex(index, i); } data[index] = fourK; } for (long index = 0; index < data.Length4ks; index++) { Complex[] fourK = data[index]; for (int i = 0; i < fourK.Length; i++) { if (!fourK[i].Equals(new Complex(index, i))) { throw new Exception(); } } } } Complex4Ks.totalRAM = 3L * 1024 * 1024 * 1024; }
/// <summary> /// Smallest file storage should be empty and fully readable after it is completely filled with 4K Complex arrays /// </summary> public static void Test2() { Complex4Ks.totalRAM = 0; using (Complex4Ks data = new Complex4Ks(8192)) { for (long index = 0; index < data.Length4ks; index++) { data[index] = new Complex[4096]; } for (long index = 0; index < data.Length4ks; index++) { Complex[] fourK = data[index]; foreach (Complex entry in fourK) { if (!entry.Equals(Complex.Zero)) { throw new Exception(); } } } } Complex4Ks.totalRAM = 3L * 1024 * 1024 * 1024; }
/// <summary> /// Smallest file storage should create file of exact size to fit exact amount of Complex values /// </summary> public static void Test3() { Complex4Ks.totalRAM = 0; string fileName = null; using (Complex4Ks data = new Complex4Ks(8192)) { fileName = data.FileName; long length = new System.IO.FileInfo(fileName).Length; if (length != data.Length4ks * 4096 * Marshal.SizeOf(typeof(Complex))) { throw new Exception(); } } }
/// <summary> /// RAM storage and smallest file storaged non Zero FFT should match exactly /// </summary> public static void Test16() { Complex4Ks result1; Complex4Ks result2; Complex4Ks.totalRAM = 0; using (Complex4Ks data = new Complex4Ks(8192)) { Complex[] zeroOneAndZeroes = new Complex[4096]; zeroOneAndZeroes[1] = Complex.One; data[0] = zeroOneAndZeroes; data[1] = new Complex[4096]; result1 = FourierTransform.FFT(data); } Complex4Ks.totalRAM = 3L * 1024 * 1024 * 1024; using (Complex4Ks data = new Complex4Ks(8192)) { Complex[] zeroOneAndZeroes = new Complex[4096]; zeroOneAndZeroes[1] = Complex.One; data[0] = zeroOneAndZeroes; data[1] = new Complex[4096]; result2 = FourierTransform.FFT(data); } Complex[] fourK1 = result1[0]; Complex[] fourK2 = result2[0]; for (int i = 0; i < fourK1.Length; i++) { if (!fourK1[i].Equals(fourK2[i])) { throw new Exception(); } } fourK1 = result1[1]; fourK2 = result2[1]; for (int i = 0; i < fourK1.Length; i++) { if (!fourK1[i].Equals(fourK2[i])) { throw new Exception(); } } result1.Dispose(); result2.Dispose(); }
/// <summary> /// Medium in core storage FFT should match flat array FFT exactly for given mixed sample /// </summary> public static void Test18() { Complex4Ks.totalRAM = 3L * 1024 * 1024 * 1024; string[] try1 = new string[11]; string[] try2 = new string[11]; using (Complex4Ks data = new Complex4Ks(1024 * 1024)) { Complex[] empty = new Complex[4096]; for (int index = 0; index < data.Length4ks; index++) { data[index] = empty; } Complex[] filled = new Complex[4096]; filled[244] = Complex.One; filled[444] = Complex.One * 2.2; data[7] = filled; using (Complex4Ks result = FourierTransform.FFT(data)) { long bin = 0; for (int index = 0; index < result.Length4ks; index++) { Complex[] fourK = result[index]; for (int i = 0; i < fourK.Length; i++) { if (bin > 60000 && bin < 60010) try1[bin - 60000] = bin + " " + fourK[i].Real + " " + fourK[i].Imaginary; bin++; } } } } Complex[] z = new Complex[1024 * 1024]; z[7 * 4096 + 244] = Complex.One; z[7 * 4096 + 444] = Complex.One * 2.2; Complex[] zz = FourierTransform.FFT(z); long bin2 = 0; for (int i = 0; i < z.Length; i++) { if (bin2 > 60000 && bin2 < 60010) try2[bin2 - 60000] = bin2 + " " + zz[i].Real + " " + zz[i].Imaginary; bin2++; } for (int i = 0; i < try1.Length; i++) { if (string.Compare(try1[i], try2[i]) != 0) throw new Exception(); } }
/// <summary> /// Smallest file storaged Zero FFT having 2nd element = One should provide particular vector /// </summary> public static void Test15() { Complex4Ks.totalRAM = 0; using (Complex4Ks data = new Complex4Ks(8192)) { Complex[] zeroOneAndZeroes = new Complex[4096]; zeroOneAndZeroes[1] = Complex.One; data[0] = zeroOneAndZeroes; data[1] = new Complex[4096]; using (Complex4Ks result = FourierTransform.FFT(data)) { Complex[] fourK = result[0]; Complex[] expect = ConstTestVector_8192_LO_FFT_of_00_10_00_etc(); for (int i = 0; i < fourK.Length; i++) { if (Math.Abs(fourK[i].Real - expect[i].Real) > Math.Max(Math.Abs(expect[i].Real / 1000000), 0.000001)) { throw new Exception(); } if (Math.Abs(fourK[i].Imaginary - expect[i].Imaginary) > Math.Max(Math.Abs(expect[i].Imaginary / 1000000), 0.000001)) { throw new Exception(); } } fourK = result[1]; expect = ConstTestVector_8192_HI_FFT_of_00_10_00_etc(); for (int i = 0; i < fourK.Length; i++) { if (Math.Abs(fourK[i].Real - expect[i].Real) > Math.Max(Math.Abs(expect[i].Real / 1000000), 0.000001)) { throw new Exception(); } if (Math.Abs(fourK[i].Imaginary - expect[i].Imaginary) > Math.Max(Math.Abs(expect[i].Imaginary / 1000000), 0.000001)) { throw new Exception(); } } } } Complex4Ks.totalRAM = 3L * 1024 * 1024 * 1024; }
/// <summary> /// Smallest file storaged Zero FFT starting with One should provide Ones /// </summary> public static void Test14() { Complex4Ks.totalRAM = 0; using (Complex4Ks data = new Complex4Ks(8192)) { Complex[] oneAndZeroes = new Complex[4096]; oneAndZeroes[0] = Complex.One; data[0] = oneAndZeroes; data[1] = new Complex[4096]; using (Complex4Ks result = FourierTransform.FFT(data)) { for (long index = 0; index < result.Length4ks; index++) { Complex[] fourK = result[index]; foreach (Complex entry in fourK) { if (!entry.Equals(Complex.One)) { throw new Exception(); } } } } } Complex4Ks.totalRAM = 3L * 1024 * 1024 * 1024; }
/// <summary> /// Smallest file storaged Zero FFT should provide Zeroes /// </summary> public static void Test13() { Complex4Ks.totalRAM = 0; using (Complex4Ks data = new Complex4Ks(8192)) { for (long index = 0; index < data.Length4ks; index++) { data[index] = new Complex[4096]; } using (Complex4Ks result = FourierTransform.FFT(data)) { for (long index = 0; index < result.Length4ks; index++) { Complex[] fourK = result[index]; foreach (Complex entry in fourK) { if (!entry.Equals(Complex.Zero)) { throw new Exception(); } } } } } Complex4Ks.totalRAM = 3L * 1024 * 1024 * 1024; }
static void Main(string[] args) { { //GigaFFTTest.Test1(); //GigaFFTTest.Test2(); //GigaFFTTest.Test3(); //GigaFFTTest.Test4(); //GigaFFTTest.Test5(); //GigaFFTTest.Test6(); //GigaFFTTest.Test7(); //GigaFFTTest.Test8(); //GigaFFTTest.Test9(); //GigaFFTTest.Test10(); //GigaFFTTest.Test11(); //GigaFFTTest.Test12(); //GigaFFTTest.Test13(); //GigaFFTTest.Test14(); //GigaFFTTest.Test15(); //GigaFFTTest.Test16(); //GigaFFTTest.Test17(); //GigaFFTTest.Test18(); Stopwatch watch1 = Stopwatch.StartNew(); Complex4Ks data = new Complex4Ks(8 * 1024 * 1024); watch1.Stop(); Console.WriteLine("New " + watch1.Elapsed.TotalSeconds); Stopwatch watch2 = Stopwatch.StartNew(); //data[0] = new Complex[4096]; //data[1] = new Complex[4096]; //data[3][10] = new Complex(1, 0); //data[3][20] = new Complex(2.2, 0); for (int i = 0; i < data.Length4ks; i++) { Complex[] part = new Complex[4096]; for (int ii = 0; ii < 4096; ii++) { //part[ii] = new Complex(i, ii); part[ii] = Complex.Zero; } data[i] = part; } Complex[] zz = new Complex[4096]; zz[22] = Complex.One; data[0] = zz; watch2.Stop(); Console.WriteLine("Write " + watch2.Elapsed.TotalSeconds); Stopwatch watch4 = Stopwatch.StartNew(); Complex4Ks data2 = FourierTransform.FFT(data); watch4.Stop(); Console.WriteLine("FFT " + watch4.Elapsed.TotalSeconds); Console.ReadLine(); //for (int i = 0; i < data2.Length4ks; i++) //{ // Complex[] entry = data2[i]; // for (int ii = 0; ii < 4096; ii++) // { // Console.WriteLine(entry[ii]); // } //} } }
public static Complex4Ks FFT(Complex4Ks x, byte forkWidth = 2) { long N = x.Length4ks * 4096; Debug.Assert(N > 4096); Complex4Ks E4ks = null; Complex4Ks D4ks = null; Complex[] E = null; Complex[] D = null; if (N > 8192) { Complex4Ks e4ks = new Complex4Ks(N / 2); Complex4Ks d4ks = new Complex4Ks(N / 2); Debug.Assert(e4ks.Length4ks == N / (2 * 4096)); Debug.Assert(d4ks.Length4ks == N / (2 * 4096)); for (long k = 0; k < N / (2 * 4096); k++) { Complex[] e4k = new Complex[4096]; Complex[] d4k = new Complex[4096]; Complex[] lo = x[k * 2]; Complex[] hi = x[k * 2 + 1]; for (int i = 0; i < 2048; i++) { e4k[i] = lo[2 * i]; d4k[i] = lo[2 * i + 1]; } for (int i = 0; i < 2048; i++) { e4k[2048 + i] = hi[2 * i]; d4k[2048 + i] = hi[2 * i + 1]; } e4ks[k] = e4k; d4ks[k] = d4k; } x.Dispose(); forkWidth = (byte)(forkWidth / 2); Task[] tasks = new Task[] { Task.Factory.StartNew(() => {E4ks = FFT(e4ks, forkWidth);e4ks.Dispose();}, forkWidth > 0 ? TaskCreationOptions.LongRunning: TaskCreationOptions.None), Task.Factory.StartNew(() => {D4ks = FFT(d4ks, forkWidth);d4ks.Dispose();}, forkWidth > 0 ? TaskCreationOptions.LongRunning: TaskCreationOptions.None) }; Task.WaitAll(tasks); } else { Debug.Assert(N / 2 == 4096); Complex[] e = new Complex[N / 2]; Complex[] d = new Complex[N / 2]; Debug.Assert(x.Length4ks == 2); Complex[] lo = x[0]; Complex[] hi = x[1]; x.Dispose(); for (int twok = 0; twok < 2048; twok++) { e[twok] = lo[2 * twok]; d[twok] = lo[2 * twok + 1]; } for (int twok = 0; twok < 2048; twok++) { e[2048 + twok] = hi[2 * twok]; d[2048 + twok] = hi[2 * twok + 1]; } E = FFT(e); D = FFT(d); } Complex4Ks result; if (N > 8192) { result = new Complex4Ks(N); Debug.Assert(E4ks.Length4ks == N / (2 * 4096)); Debug.Assert(D4ks.Length4ks == N / (2 * 4096)); for (int fourK = 0; fourK < N / (2 * 4096); fourK++) { Complex[] resultLO = new Complex[4096]; Complex[] EE = E4ks[fourK]; Complex[] DD = D4ks[fourK]; for (int k = 0; k < 4096; k++) { Complex Dk = DD[k] * Complex.FromPolarCoordinates(1, -2 * Math.PI * (fourK * 4096 + k) / N); resultLO[k] = EE[k] + Dk; } result[fourK] = resultLO; } for (int fourK = 0; fourK < N / (2 * 4096); fourK++) { Complex[] resultHI = new Complex[4096]; Complex[] EE = E4ks[fourK]; Complex[] DD = D4ks[fourK]; for (int k = 0; k < 4096; k++) { Complex Dk = DD[k] * Complex.FromPolarCoordinates(1, -2 * Math.PI * (fourK * 4096 + k) / N); resultHI[k] = EE[k] - Dk; } result[fourK + N / (2 * 4096)] = resultHI; } E4ks.Dispose(); D4ks.Dispose(); } else { Debug.Assert(N / 2 == 4096); result = new Complex4Ks(8192); Debug.Assert(result.Length4ks == 2); Complex[] resultLO = new Complex[4096]; Complex[] resultHI = new Complex[4096]; for (int k = 0; k < 4096; k++) { Complex Dk = D[k] * Complex.FromPolarCoordinates(1, -2 * Math.PI * k / N); resultLO[k] = E[k] + Dk; resultHI[k] = E[k] - Dk; } result[0] = resultLO; result[1] = resultHI; } return result; }