package org.das2.qds.math.fft.jnt; import org.das2.qds.math.fft.ComplexArray; /** Abstract Class representing FFT's of complex, single precision data. * Concrete classes are typically named ComplexFloatFFT_method, implement the * FFT using some particular method. *

* Complex data is represented by 2 double values in sequence: the real and imaginary * parts. Thus, in the default case (i0=0, stride=2), N data points is represented * by a double array dimensioned to 2*N. To support 2D (and higher) transforms, * an offset, i0 (where the first element starts) and stride (the distance from the * real part of one value, to the next: at least 2 for complex values) can be supplied. * The physical layout in the array data, of the mathematical data d[i] is as follows: *

  *    Re(d[i]) = data[i0 + stride*i]
  *    Im(d[i]) = data[i0 + stride*i+1]
  *
* The transformed data is returned in the original data array in * wrap-around order. * * @author Bruce R. Miller bruce.miller@nist.gov * @author Contribution of the National Institute of Standards and Technology, * @author not subject to copyright. */ public abstract class ComplexFloatFFT { int n; /** Create an FFT for transforming n points of Complex, single precision data. */ public ComplexFloatFFT(int n){ if (n <= 0) throw new IllegalArgumentException("The transform length must be >=0 : "+n); this.n = n; } /** Creates an instance of a subclass of ComplexFloatFFT appropriate for data * of n elements.*/ public ComplexFloatFFT getInstance(int n){ return new ComplexFloatFFT_Mixed(n); } protected void checkData(ComplexArray.Float data, int i0, int stride){ if (i0 < 0) throw new IllegalArgumentException("The offset must be >=0 : "+i0); if (stride < 1) throw new IllegalArgumentException("The stride must be >=2 : "+stride); if (i0+stride*(n-1)+2 > data.length()) throw new IllegalArgumentException("The data array is too small for "+n+":"+ "i0="+i0+" stride="+stride+ " data.length="+data.length()); } /** Compute the Fast Fourier Transform of data leaving the result in data. * The array data must be dimensioned (at least) 2*n, consisting of alternating * real and imaginary parts. */ public void transform ( ComplexArray.Float data ) { transform (data, 0,1); } /** Compute the Fast Fourier Transform of data leaving the result in data. * The array data must contain the data points in the following locations: *
    *    Re(d[i]) = data[i0 + stride*i]
    *    Im(d[i]) = data[i0 + stride*i+1]
    *
*/ public abstract void transform ( ComplexArray.Float data, int i0, int stride); /** Compute the (unnomalized) inverse FFT of data, leaving it in place.*/ public void backtransform ( ComplexArray.Float data ) { backtransform(data,0,2); } /** Compute the (unnomalized) inverse FFT of data, leaving it in place. * The frequency domain data must be in wrap-around order, and be stored * in the following locations: *
    *    Re(D[i]) = data[i0 + stride*i]
    *    Im(D[i]) = data[i0 + stride*i+1]
    *
*/ public abstract void backtransform (ComplexArray.Float data, int i0, int stride); /** Return the normalization factor. * Multiply the elements of the backtransform'ed data to get the normalized inverse.*/ public float normalization(){ return 1.0f/((float) n); } /** Compute the (nomalized) inverse FFT of data, leaving it in place.*/ public void inverse(ComplexArray.Float data) { inverse(data,0,2); } /** Compute the (nomalized) inverse FFT of data, leaving it in place. * The frequency domain data must be in wrap-around order, and be stored * in the following locations: *
    *    Re(D[i]) = data[i0 + stride*i]
    *    Im(D[i]) = data[i0 + stride*i+1]
    *
*/ public void inverse (ComplexArray.Float data, int i0, int stride) { backtransform(data,0,2); /* normalize inverse fft with 1/n */ float norm = normalization(); for (int i = 0; i < n; i++) { data.setReal( i, data.getReal(i) * norm ); data.setImag( i, data.getImag(i) * norm ); } } }