FFT(double[] x, double[] y, uint n, FourierDirection direction, ref object temporaryStorage) { ChirpNativeFFTStorage s = temporaryStorage as ChirpNativeFFTStorage; chirpnativefft(x, y, x, y, (int)n, direction, ref s); temporaryStorage = s; }
FourierTransformation2D(IMatrix <double> matrixRe, IMatrix <double> matrixIm, FourierDirection direction) { int numberOfRows = matrixRe.RowCount; int numberOfColumns = matrixRe.ColumnCount; // Do the FFT in the first direction // First direction: transform all columns of the matrix ChirpNativeFFTStorage tempStorage = null; var resultArrayRe = new double[numberOfRows]; var resultArrayIm = new double[numberOfRows]; var inputArrayRe = new double[numberOfRows]; var inputArrayIm = new double[numberOfRows]; for (int c = 0; c < numberOfColumns; ++c) // for each column { for (int r = 0; r < numberOfRows; ++r) { inputArrayRe[r] = matrixRe[r, c]; inputArrayIm[r] = matrixIm[r, c]; } chirpnativefft(resultArrayRe, resultArrayIm, inputArrayRe, inputArrayIm, numberOfRows, direction, ref tempStorage); for (int r = 0; r < numberOfRows; ++r) { matrixRe[r, c] = resultArrayRe[r]; matrixIm[r, c] = resultArrayIm[r]; } } // Second direction: transform all rows of the matrix if (numberOfColumns != numberOfRows) { resultArrayRe = new double[numberOfColumns]; resultArrayIm = new double[numberOfColumns]; inputArrayRe = new double[numberOfColumns]; inputArrayIm = new double[numberOfColumns]; } for (int r = 0; r < numberOfRows; ++r) // for each row { for (int c = 0; c < numberOfColumns; ++c) { inputArrayRe[c] = matrixRe[r, c]; inputArrayIm[c] = matrixIm[r, c]; } chirpnativefft(resultArrayRe, resultArrayIm, inputArrayRe, inputArrayIm, numberOfColumns, direction, ref tempStorage); for (int c = 0; c < numberOfColumns; ++c) { matrixRe[r, c] = resultArrayRe[c]; matrixIm[r, c] = resultArrayIm[c]; } } }
private static void chirpnativefft( double[] resultreal, double[] resultimag, double[] inputreal, double[] inputimag, int arrsize, FourierDirection direction, ref ChirpNativeFFTStorage s) { if (arrsize <= 2) { throw new ArgumentException("This algorithm works for array sizes > 2 only."); } int msize = GetNecessaryTransformationSize(arrsize); if (s == null || arrsize != s._arrSize || direction != s._direction) { s = new ChirpNativeFFTStorage(msize, arrsize, direction); } else // if the temp storage is not fresh, we have to clear the arrays first { Array.Clear(s._xjfj_real, 0, msize); Array.Clear(s._xjfj_imag, 0, msize); } // make the arrays local variables double[] xjfj_real = s._xjfj_real; double[] xjfj_imag = s._xjfj_imag; double[] fserp_real = s._fserp_real; double[] fserp_imag = s._fserp_imag; double[] resarray_real = s._resarray_real; double[] resarray_imag = s._resarray_imag; var chirpfactor_real = s._chirpfactors_real; var chirpfactor_imag = s._chirpfactors_imag; // multiply the input array with the chirpfactors for (int i = 0; i < arrsize; ++i) { xjfj_real[i] = inputreal[i] * chirpfactor_real[i] - inputimag[i] * chirpfactor_imag[i]; xjfj_imag[i] = inputreal[i] * chirpfactor_imag[i] + inputimag[i] * chirpfactor_real[i]; } // convolute xjfj with precomputed fourier-transformation of fserp fhtconvolutionWithFouriertransformed2ndArgument(resarray_real, resarray_imag, xjfj_real, xjfj_imag, fserp_real, fserp_imag, msize); // multiply the result with the chirpfactors for (int i = 0; i < arrsize; ++i) { resultreal[i] = resarray_real[i] * chirpfactor_real[i] - resarray_imag[i] * chirpfactor_imag[i]; resultimag[i] = resarray_real[i] * chirpfactor_imag[i] + resarray_imag[i] * chirpfactor_real[i]; } }
FFT(double[] x, double[] y, FourierDirection direction, ref object temporaryStorage) { if (x.Length != y.Length) { throw new ArgumentException("Length of real and imaginary array do not match!"); } ChirpNativeFFTStorage s = temporaryStorage as ChirpNativeFFTStorage; chirpnativefft(x, y, x, y, x.Length, direction, ref s); temporaryStorage = s; }
private static void chirpnativefft( double[] resultreal, double[] resultimag, double[] inputreal, double[] inputimag, int arrsize, FourierDirection direction, ref ChirpNativeFFTStorage s) { int phasesign = direction == FourierDirection.Forward ? 1 : -1; int arrsize2 = arrsize + arrsize; if (arrsize <= 2) { throw new ArgumentException("This algorithm works for array sizes > 2 only."); } int msize = GetNecessaryTransformationSize(arrsize); if (s == null || s.Length != msize) { s = new ChirpNativeFFTStorage(msize); } double[] xjfj_real = s.xjfj_real; double[] xjfj_imag = s.xjfj_imag; double[] fserp_real = s.fserp_real; double[] fserp_imag = s.fserp_imag; double[] resarray_real = s.resarray_real; double[] resarray_imag = s.resarray_imag; // bilde xj*fj double prefactor = phasesign * Math.PI / arrsize; int np = 0; for (int i = 0; i < arrsize; i++) { double phi = prefactor * np; // np should be equal to (i*i)%arrsize2 double vre = Math.Cos(phi); double vim = Math.Sin(phi); xjfj_real[i] = inputreal[i] * vre - inputimag[i] * vim; xjfj_imag[i] = inputreal[i] * vim + inputimag[i] * vre; np += i + i + 1; // np == (k*k)%n2 if (np >= arrsize2) { np -= arrsize2; } } // fill positive and negative part of fserp fserp_real[0] = 1; fserp_imag[0] = 0; prefactor = -phasesign * Math.PI / arrsize; np = 1; // since we start the loop with 1 for (int i = 1; i < arrsize; i++) { double phi = prefactor * np; // np should be equal to (i*i)%arrsize2 fserp_real[i] = fserp_real[msize - i] = Math.Cos(phi); fserp_imag[i] = fserp_imag[msize - i] = Math.Sin(phi); np += i + i + 1; // np == (k*k)%n2 if (np >= arrsize2) { np -= arrsize2; } } // convolute xjfj with fserp //NativeCyclicConvolution(resarray,xjfj,fserp,msize); fhtconvolution(resarray_real, resarray_imag, xjfj_real, xjfj_imag, fserp_real, fserp_imag, msize); // multipliziere mit fserpschlange prefactor = phasesign * Math.PI / arrsize; np = 0; for (int i = 0; i < arrsize; i++) { double phi = prefactor * np; // np should be equal to (i*i)%arrsize2 double vre = Math.Cos(phi); double vim = Math.Sin(phi); resultreal[i] = resarray_real[i] * vre - resarray_imag[i] * vim; resultimag[i] = resarray_real[i] * vim + resarray_imag[i] * vre; np += i + i + 1; // np == (i*i)%n2 if (np >= arrsize2) { np -= arrsize2; } } }
private static void chirpnativefft( double[] resultreal, double[] resultimag, double[] inputreal, double[] inputimag, int arrsize, FourierDirection direction, ref ChirpNativeFFTStorage s) { if (arrsize <= 2) throw new ArgumentException("This algorithm works for array sizes > 2 only."); int msize = GetNecessaryTransformationSize(arrsize); if (s == null || arrsize != s._arrSize || direction != s._direction) { s = new ChirpNativeFFTStorage(msize, arrsize, direction); } else // if the temp storage is not fresh, we have to clear the arrays first { Array.Clear(s._xjfj_real, 0, msize); Array.Clear(s._xjfj_imag, 0, msize); } // make the arrays local variables double[] xjfj_real = s._xjfj_real; double[] xjfj_imag = s._xjfj_imag; double[] fserp_real = s._fserp_real; double[] fserp_imag = s._fserp_imag; double[] resarray_real = s._resarray_real; double[] resarray_imag = s._resarray_imag; var chirpfactor_real = s._chirpfactors_real; var chirpfactor_imag = s._chirpfactors_imag; // multiply the input array with the chirpfactors for (int i = 0; i < arrsize; ++i) { xjfj_real[i] = inputreal[i] * chirpfactor_real[i] - inputimag[i] * chirpfactor_imag[i]; xjfj_imag[i] = inputreal[i] * chirpfactor_imag[i] + inputimag[i] * chirpfactor_real[i]; } // convolute xjfj with precomputed fourier-transformation of fserp fhtconvolutionWithFouriertransformed2ndArgument(resarray_real, resarray_imag, xjfj_real, xjfj_imag, fserp_real, fserp_imag, msize); // multiply the result with the chirpfactors for (int i = 0; i < arrsize; ++i) { resultreal[i] = resarray_real[i] * chirpfactor_real[i] - resarray_imag[i] * chirpfactor_imag[i]; resultimag[i] = resarray_real[i] * chirpfactor_imag[i] + resarray_imag[i] * chirpfactor_real[i]; } }
private static void chirpnativefft( double[] resultreal, double[] resultimag, double[] inputreal, double[] inputimag, int arrsize, FourierDirection direction, ref ChirpNativeFFTStorage s) { int phasesign = direction==FourierDirection.Forward ? 1 : -1; int arrsize2 = arrsize+arrsize; if(arrsize<=2) throw new ArgumentException("This algorithm works for array sizes > 2 only."); int msize = GetNecessaryTransformationSize(arrsize); if(s==null || s.Length!=msize) { s = new ChirpNativeFFTStorage(msize); } double[] xjfj_real = s.xjfj_real; double[] xjfj_imag = s.xjfj_imag; double[] fserp_real = s.fserp_real; double[] fserp_imag = s.fserp_imag; double[] resarray_real = s.resarray_real; double[] resarray_imag = s.resarray_imag; // bilde xj*fj double prefactor = phasesign * Math.PI / arrsize; int np = 0; for(int i=0;i<arrsize;i++) { double phi = prefactor*np; // np should be equal to (i*i)%arrsize2 double vre = Math.Cos(phi); double vim = Math.Sin(phi); xjfj_real[i] = inputreal[i] * vre - inputimag[i] * vim; xjfj_imag[i] = inputreal[i] * vim + inputimag[i] * vre; np += i+i+1; // np == (k*k)%n2 if ( np >= arrsize2 ) np -= arrsize2; } // fill positive and negative part of fserp fserp_real[0]=1; fserp_imag[0]=0; prefactor = -phasesign * Math.PI / arrsize; np = 1; // since we start the loop with 1 for(int i=1;i<arrsize;i++) { double phi = prefactor * np; // np should be equal to (i*i)%arrsize2 fserp_real[i] = fserp_real[msize-i] = Math.Cos(phi); fserp_imag[i] = fserp_imag[msize-i] = Math.Sin(phi); np += i+i+1; // np == (k*k)%n2 if ( np >= arrsize2 ) np -= arrsize2; } // convolute xjfj with fserp //NativeCyclicConvolution(resarray,xjfj,fserp,msize); fhtconvolution(resarray_real,resarray_imag,xjfj_real,xjfj_imag,fserp_real,fserp_imag,msize); // multipliziere mit fserpschlange prefactor = phasesign * Math.PI / arrsize; np = 0; for(int i=0;i<arrsize;i++) { double phi = prefactor * np; // np should be equal to (i*i)%arrsize2 double vre = Math.Cos(phi); double vim = Math.Sin(phi); resultreal[i] = resarray_real[i]*vre - resarray_imag[i]*vim; resultimag[i] = resarray_real[i]*vim + resarray_imag[i]*vre; np += i+i+1; // np == (i*i)%n2 if ( np >= arrsize2 ) np -= arrsize2; } }