public void test3Random() { int n1 = 11; int n2 = 12; int n3 = 13; int n1fft = FftComplex.nfftSmall(n1); int n2fft = FftComplex.nfftSmall(n2); int n3fft = FftComplex.nfftSmall(n3); FftComplex fft1 = new FftComplex(n1fft); FftComplex fft2 = new FftComplex(n2fft); FftComplex fft3 = new FftComplex(n3fft); float[][][] cr = crandfloat(n1fft,n2fft,n3fft); float[][][] cx = ccopy(cr); fft1.complexToComplex1( 1,n2fft,n3fft,cx,cx); fft2.complexToComplex2( 1,n1fft,n3fft,cx,cx); fft3.complexToComplex3( 1,n1fft,n2fft,cx,cx); fft1.complexToComplex1(-1,n2fft,n3fft,cx,cx); fft2.complexToComplex2(-1,n1fft,n3fft,cx,cx); fft3.complexToComplex3(-1,n1fft,n2fft,cx,cx); fft1.scale(n1fft,n2fft,n3fft,cx); fft2.scale(n1fft,n2fft,n3fft,cx); fft3.scale(n1fft,n2fft,n3fft,cx); assertEqual(cr,cx); }
private static double time(int nfft) { double maxtime = 2.0; FftComplex fft = new FftComplex(nfft); float[] cx = crandfloat(nfft); int count; Stopwatch sw = new Stopwatch(); sw.start(); for (count=0; sw.time()<maxtime; ++count) { fft.complexToComplex(-1,cx,cx); fft.complexToComplex( 1,cx,cx); fft.scale(nfft,cx); } sw.stop(); double time = sw.time()/(float)count; return time; } }
/** * Computes a complex-to-complex dimension-1 fast Fourier transform. * Transforms a 2-D input array cx[n2][2*nfft] of n2*nfft complex numbers * to a 2-D output array cy[n2][2*nfft] of n2*nfft complex numbers. * @param sign the sign (1 or -1) of the exponent used in the FFT. * @param n2 the 2nd dimension of arrays. * @param cx the input array. * @param cy the output array. */ public void complexToComplex1(int sign, int n2, float[][] cx, float[][] cy) { checkSign(sign); checkArray(2*_nfft,n2,cx,"cx"); checkArray(2*_nfft,n2,cy,"cy"); for (int i2=0; i2<n2; ++i2) complexToComplex(sign,cx[i2],cy[i2]); }
/** * Computes a complex-to-complex dimension-1 fast Fourier transform. * Transforms a 3-D input array cx[n3][n2][2*nfft] of n3*n2*nfft complex * numbers to a 3-D output array cy[n3][n2][2*nfft] of n3*n2*nfft complex * numbers. * @param sign the sign (1 or -1) of the exponent used in the FFT. * @param n2 the 2nd dimension of arrays. * @param n3 the 3rd dimension of arrays. * @param cx the input array. * @param cy the output array. */ public void complexToComplex1( int sign, int n2, int n3, float[][][] cx, float[][][] cy) { checkSign(sign); checkArray(2*_nfft,n2,n3,cx,"cx"); checkArray(2*_nfft,n2,n3,cy,"cy"); for (int i3=0; i3<n3; ++i3) complexToComplex1(sign,n2,cx[i3],cy[i3]); }
public void run() { float[] tempIn = new float[depth * 2]; float[] tempOut; FftComplex fftc = new FftComplex(depth); int myNumber = ai.getAndIncrement(); for (int y = 0; y < height; y++) if (y % numThreads == myNumber) for (int x = 0; x < complexWidth / 2; x++) { tempOut = new float[depth * 2]; for (int z = 0; z < depth; z++) { tempIn[z * 2] = result.get(x * 2, y, z); tempIn[z * 2 + 1] = result.get(x * 2 + 1, y, z); } fftc.complexToComplex( -1, tempIn, tempOut); for (int z = 0; z < depth; z++) { result.set(tempOut[z * 2], x * 2, y, z); result.set(tempOut[z * 2 + 1], x * 2 + 1, y, z); } } } });
public void test1Random() { int nmax = 1000; for (int n=2; n<nmax; ++n) { int nfft = FftComplex.nfftSmall(n); FftComplex fft = new FftComplex(nfft); float[] cr = crandfloat(nfft); float[] cx = ccopy(cr); float[] cy = czerofloat(nfft); fft.complexToComplex( 1,cx,cy); fft.complexToComplex(-1,cy,cx); fft.scale(nfft,cx); assertEqual(cr,cx); } }
_nx3 = nx3; _nfft1 = FftReal.nfftFast(_nx1+_nh1); _nfft2 = FftComplex.nfftFast(_nx2+_nh2); _nfft3 = FftComplex.nfftFast(_nx3+_nh3); _fft1 = new FftReal(_nfft1); _fft2 = new FftComplex(_nfft2); _fft3 = new FftComplex(_nfft3); _h1fft = null; _h2fft = null; _fft2.complexToComplex2(-1,_nfft1/2+1,_nfft3,_h3fft,_h3fft); _fft3.complexToComplex3(-1,_nfft1/2+1,_nfft2,_h3fft,_h3fft);
private void updateSampling3() { if (_sx3==null) return; int nx = _sx3.getCount(); double dx = _sx3.getDelta(); int npad = nx+_padding3; int nfft = FftComplex.nfftSmall(npad); double dk = 1.0/(nfft*dx); double fk; int nk; if (_center3) { boolean even = nfft%2==0; nk = even?nfft+1:nfft; fk = even?-0.5/dx:-0.5/dx+0.5*dk; } else { nk = nfft; fk = 0.0; } if (_fft3==null || _nfft3!=nfft) { _fft3 = new FftComplex(nfft); _nfft3 = nfft; } _sk3 = new Sampling(nk,dk,fk); //trace("sk3: nfft="+nfft+" nk="+nk+" dk="+dk+" fk="+fk); }
private FloatArray3D zeroPadImage(FloatArray3D img) { int widthFFT = FftReal.nfftFast(img.width); int heightFFT = FftComplex.nfftFast(img.height); int depthFFT = FftComplex.nfftFast(img.depth); FloatArray3D result = zeroPad(img, widthFFT, heightFFT, depthFFT); img.data = null; img = null; return result; }
int nl2 = (n2-1)/lfactor+1; int nl1 = (n1-1)/lfactor+1; int nf3 = FftComplex.nfftSmall(nl3+mpad*2); int nf2 = FftComplex.nfftSmall(nl2+mpad*2); int nf1 = FftReal.nfftSmall(nl1+mpad*2); int nf1c = nf1/2+1; float[][][] cx = czerofloat(nf1c,nf2,nf3); fft1 = new FftReal(nf1); fft2 = new FftComplex(nf2); fft3 = new FftComplex(nf3); fft1.realToComplex1(1,nf2,nf3,xr,cx); flipSign(2, cx); fft2.complexToComplex2(1,nf1c,nf3,cx,cx); flipSign(3, cx); fft3.complexToComplex3(1,nf1c,nf2,cx,cx); return cx;
private void updateFfts(int nx1, int nx2) { if (_fft2==null || _h2fft==null || _nx1!=nx1 || _nx2!=nx2) { _nx1 = nx1; _nx2 = nx2; _nx3 = 0; _nfft1 = FftReal.nfftFast(_nx1+_nh1); _nfft2 = FftComplex.nfftFast(_nx2+_nh2); _fft1 = new FftReal(_nfft1); _fft2 = new FftComplex(_nfft2); _fft3 = null; _h1fft = null; _h2fft = new float[_nfft2][_nfft1+2]; _h3fft = null; float scale = 1.0f/(float)_nfft1/(float)_nfft2; for (int ih2=0; ih2<_nh2; ++ih2) { int jh2 = ih2-_kh2; if (jh2<0) jh2 += _nfft2; for (int ih1=0; ih1<_nh1; ++ih1) { int jh1 = ih1-_kh1; if (jh1<0) jh1 += _nfft1; _h2fft[jh2][jh1] = scale*_h2[ih2][ih1]; } } _fft1.realToComplex1(-1,_nfft2,_h2fft,_h2fft); _fft2.complexToComplex2(-1,_nfft1/2+1,_h2fft,_h2fft); } }
/** * Applies forward 2D Fourier transform. * @param level level number. * @param x input 2D image. * @return a 2D complex array, which is the forward 2D Fourier transform of * the input image. */ private float[][] ftForward(int level, float[][] x) { FftReal fft1; FftComplex fft2; int ny2 = x.length; int ny1 = x[0].length; int mpad = round(20.0f/(1.0f+(float)level)); int lfactor = (int)pow(2.0,(double)level); int nl2 = (n2-1)/lfactor+1; int nl1 = (n1-1)/lfactor+1; int nf1 = FftReal.nfftSmall(nl1+mpad*2); int nf1c = nf1/2+1; int nf2 = FftComplex.nfftSmall(nl2+mpad*2); float[][] xr = zerofloat(nf1,nf2); copy(ny1,ny2,0,0,x,mpad,mpad,xr); float[][] cx = czerofloat(nf1c,nf2); fft1 = new FftReal(nf1); fft2 = new FftComplex(nf2); fft1.realToComplex1(1,nf2,xr,cx); flipSign(2,cx); fft2.complexToComplex2(1,nf1c,cx,cx); return cx; }
int nl1 = (n1-1)/lfactor+1; fft1 = new FftReal(nf1); fft2 = new FftComplex(nf2); fft3 = new FftComplex(nf3); fft3.complexToComplex3(-1,nf1c,nf2,cf,cf); flipSign(3, cf); fft3.scale(nf1c,nf2,nf3,cf); fft2.complexToComplex2(-1,nf1c,nf3,cf,cf); flipSign(2, cf); fft2.scale(nf1c,nf2,nf3,cf); fft1.complexToReal1(-1,nf2,nf3,cf,cf); fft1.scale(nf1,nf2,nf3,cf);
final float[] tempOut = new float[size * 2]; final FftComplex fft = new FftComplex(size); final float[] tempOut = new float[size * 2]; final FftComplex fft = new FftComplex(size);
/** * Computes the supported dimensionality of an input dataset (of complex numbers) for a forward/inverse FFT of the entire dataset AS SMALL AS POSSIBLE * * @param inputDimensions - the dimensions of the input * @param paddedDimensions - the required dimensions of the input/output (computed) */ final static public void dimensionsComplexToComplexSmall( final Dimensions inputDimensions, final long[] paddedDimensions ) { for ( int d = 0; d < inputDimensions.numDimensions(); ++d ) paddedDimensions[ d ] = FftComplex.nfftSmall( (int)inputDimensions.dimension( d ) ); }
/** * Applies inverse 2D Fourier transform to an input wavenumber-domain image. * The output space-domain image is written to the appropriate part of the * steerable pyramid array. * @param lev level number. * @param dir basis filter orientation index for the input image. * @param cf input image in wavenumber domain (complex array). * @param spyr input/output 2D steerable pyramid. */ private void ftInverse(int lev,int dir, float[][] cf,float spyr[][][][]) { FftReal fft1; FftComplex fft2; int nf2 = cf.length; int nf1c = cf[0].length/2; int nf1 = (nf1c-1)*2; int mpad = round(20.0f/(1.0f+(float)lev)); int lfactor = (int)pow(2.0,(double)lev); int nl2 = (n2-1)/lfactor+1; int nl1 = (n1-1)/lfactor+1; fft1 = new FftReal(nf1); fft2 = new FftComplex(nf2); fft2.complexToComplex2(-1,nf1c,cf,cf); flipSign(2,cf); fft2.scale(nf1c,nf2,cf); fft1.complexToReal1(-1,nf2,cf,cf); fft1.scale(nf1,nf2,cf); copy(nl1,nl2,mpad,mpad,1,1,cf,0,0,1,1,spyr[lev][dir]); }
/** * Applies a forward space-to-frequency transform of a 1D array. * @param f the array to be transformed, a sampled function of space. * @return the transformed array, a sampled function of frequency. */ public float[] applyForward(float[] f) { ensureSamplingX1(f); float[] fpad = pad(f); if (_complex) { _fft1c.complexToComplex(_sign1,fpad,fpad); } else { _fft1r.realToComplex(_sign1,fpad,fpad); } phase(fpad); center(fpad); return fpad; }
/** * Applies an inverse frequency-to-space transform of a 1D array. * @param g the array to be transformed, a sampled function of frequency. * @return the transformed array, a sampled function of space. */ public float[] applyInverse(float[] g) { ensureSamplingK1(g); int nx1 = _sx1.getCount(); float[] gpad = (_overwrite)?g:copy(g); uncenter(gpad); unphase(gpad); if (_complex) { _fft1c.complexToComplex(-_sign1,gpad,gpad); _fft1c.scale(nx1,gpad); return ccopy(nx1,gpad); } else { _fft1r.complexToReal(-_sign1,gpad,gpad); _fft1r.scale(nx1,gpad); return copy(nx1,gpad); } }
unphase(gpad); if (_complex) { _fft3.complexToComplex3(-_sign3,_nfft1,_nfft2,gpad,gpad); _fft3.scale(_nfft1,_nfft2,nx3,gpad); _fft2.complexToComplex2(-_sign2,_nfft1,nx3,gpad,gpad); _fft2.scale(_nfft1,nx2,nx3,gpad); _fft1c.complexToComplex1(-_sign1,nx2,nx3,gpad,gpad); _fft1c.scale(nx1,nx2,nx3,gpad); return ccopy(nx1,nx2,nx3,gpad); } else { _fft3.complexToComplex3(-_sign3,_nfft1/2+1,_nfft2,gpad,gpad); _fft3.scale(_nfft1/2+1,_nfft2,nx3,gpad); _fft2.complexToComplex2(-_sign2,_nfft1/2+1,nx3,gpad,gpad); _fft2.scale(_nfft1/2+1,nx2,nx3,gpad); _fft1r.complexToReal1(-_sign1,nx2,nx3,gpad,gpad); _fft1r.scale(nx1,nx2,nx3,gpad);