public RealFourierTransform(int length) { _numberOfData = length; if (length < 1) { throw new ArgumentException("length smaller than 1 is not appropriate here."); } else if (length < 3) { _method = Method.Trivial; } else if (Calc.BinaryMath.IsPowerOfTwo(length)) { // use Hartley transform _method = Method.Hartley; } else if (Pfa235FFT.CanFactorized(length)) { // use Pfa235 transform _method = Method.Pfa235; _pfa235 = new Pfa235FFT(_numberOfData); } else { // use chirp transform _method = Method.Chirp; } }
/// <summary> /// Executes the fourier transformation itself (without data pretreatment). /// </summary> /// <exception cref="System.InvalidOperationException">The Fourier transformation was already executed.</exception> protected virtual void ExecuteFourierTransformation() { if (_arraysContainTransformation) { throw new InvalidOperationException("The Fourier transformation was already executed."); } var numColumns = NumberOfColumns; var numRows = NumberOfRows; var rePart = ((IMatrixInArray1DRowMajorRepresentation <double>)_realMatrix).GetArray1DRowMajor(); _imagMatrix = new DoubleMatrixInArray1DRowMajorRepresentation(numRows, numColumns); var imPart = ((IMatrixInArray1DRowMajorRepresentation <double>)_imagMatrix).GetArray1DRowMajor(); // fourier transform either with Pfa (faster) or with the Chirp-z-transform if (Pfa235FFT.CanFactorized(numRows) && Pfa235FFT.CanFactorized(numColumns)) { var fft = new Pfa235FFT(numRows, numColumns); fft.FFT(rePart, imPart, FourierDirection.Forward); } else { var matrixRe = new DoubleMatrixInArray1DRowMajorRepresentation(rePart, numRows, numColumns); ChirpFFT.FourierTransformation2D(matrixRe, _imagMatrix, FourierDirection.Forward); } _arraysContainTransformation = true; }
private static void zzTestImOne_ArbPosBothDim(int u, int v) { int upos = rnd.Next(u); int vpos = rnd.Next(v); int n = u * v; double[] re = new double[n]; double[] im = new double[n]; im[upos * v + vpos] = 1; var fft = new Pfa235FFT(u, v); fft.FFT(re, im, FourierDirection.Inverse); for (int i = 0; i < u; i++) { for (int j = 0; j < v; j++) { Assert.AreEqual(Math.Sin(2 * Math.PI * (((double)i) * upos / u + ((double)j) * vpos / v)), re[i * v + j], n * 1E-15, string.Format("FFT({0},{1}) of re 1 at pos 1 re[{2},{3}]", u, v, i, j)); Assert.AreEqual(Math.Cos(2 * Math.PI * (((double)i) * upos / u + ((double)j) * vpos / v)), im[i * v + j], n * 1E-15, string.Format("FFT({0},{1}) of re 1 at pos 1 im[{2},{3}]", u, v, i, j)); } } }
private static int GetRandomN(int max) { int[] pqr = new int[3]; int n = 0; do { n = rnd.Next(max); } while (n < 2 || n > max || !Pfa235FFT.Factorize(n, pqr)); return(n); }
protected static string TwoDimFFT(Altaxo.AltaxoDocument mainDocument, GUI.WorksheetController dg, out double[] rePart, out double[] imPart) { int rows = dg.Doc.DataColumns.RowCount; int cols = dg.Doc.DataColumns.ColumnCount; // reserve two arrays (one for real part, which is filled with the table contents) // and the imaginary part - which is left zero here) rePart = new double[rows * cols]; imPart = new double[rows * cols]; // fill the real part with the table contents for (int i = 0; i < cols; i++) { Altaxo.Data.INumericColumn col = dg.Doc[i] as Altaxo.Data.INumericColumn; if (null == col) { return(string.Format("Can't apply fourier transform, since column number {0}, name:{1} is not numeric", i, dg.Doc[i].FullName)); } for (int j = 0; j < rows; j++) { rePart[i * rows + j] = col[j]; } } // test it can be done if (!Pfa235FFT.CanFactorized(cols)) { return(string.Format("Can't apply fourier transform, since the number of cols ({0}) are not appropriate for this kind of fourier transform.", cols)); } if (!Pfa235FFT.CanFactorized(rows)) { return(string.Format("Can't apply fourier transform, since the number of rows ({0}) are not appropriate for this kind of fourier transform.", rows)); } // fourier transform Pfa235FFT fft = new Pfa235FFT(cols, rows); fft.FFT(rePart, imPart, FourierDirection.Forward); // replace the real part by the amplitude for (int i = 0; i < rePart.Length; i++) { rePart[i] = Math.Sqrt(rePart[i] * rePart[i] + imPart[i] * imPart[i]); } return(null); }
private void MyRoutine2(double[] real1, FourierDirection dir) { int n = real1.Length; var rnd = new System.Random(); double[] real2 = new double[n]; for (int i = 0; i < n; i++) { real2[i] = rnd.NextDouble() / n; } var fft = new Pfa235FFT(n); fft.RealFFT(real2, real1, dir); }
private static void zzTestZero(int u, int v) { int n = u * v; double[] re = new double[n]; double[] im = new double[n]; var fft = new Pfa235FFT(u, v); fft.FFT(re, im, FourierDirection.Inverse); for (int i = 0; i < n; i++) { Assert.AreEqual(0, re[i], 0, "FFT of zero should give re=0"); Assert.AreEqual(0, im[i], 0, "FFT of zero should give im=0"); } }
private static void zzTestReOne_OnePos2ndDim(int u, int v) { int n = u * v; double[] re = new double[n]; double[] im = new double[n]; re[1 * v] = 1; var fft = new Pfa235FFT(u, v); fft.FFT(re, im, FourierDirection.Inverse); for (int i = 0; i < u; i++) { for (int j = 0; j < v; j++) { Assert.AreEqual(Math.Cos((2 * Math.PI * i) / u), re[i * v + j], n * 1E-15, string.Format("FFT({0},{1}) of re 1 at pos 1 re[{2},{3}]", u, v, i, j)); Assert.AreEqual(-Math.Sin((2 * Math.PI * i) / u), im[i * v + j], n * 1E-15, string.Format("FFT({0},{1}) of re 1 at pos 1 im[{2},{3}]", u, v, i, j)); } } }
private static void zzTestReOne_OnePosBothDim(int u, int v) { Console.WriteLine("TestReOn_OnePosBothDim({0},{1})", u, v); int n = u * v; double[] re = new double[n]; double[] im = new double[n]; re[1 * v + 1] = 1; Pfa235FFT fft = new Pfa235FFT(u, v); fft.FFT(re, im, FourierDirection.Inverse); for (int i = 0; i < u; i++) { for (int j = 0; j < v; j++) { Assert.AreEqual(Math.Cos(2 * Math.PI * (((double)i) / u + ((double)j) / v)), re[i * v + j], n * 1E-15, string.Format("FFT({0},{1}) of re 1 at pos 1 re[{2},{3}]", u, v, i, j)); Assert.AreEqual(-Math.Sin(2 * Math.PI * (((double)i) / u + ((double)j) / v)), im[i * v + j], n * 1E-15, string.Format("FFT({0},{1}) of re 1 at pos 1 im[{2},{3}]", u, v, i, j)); } } }
private void MyFFT(double[] real, double[] imag, FourierDirection direction) { var fft = new Pfa235FFT(real.Length); fft.FFT(real, imag, direction); }