0% found this document useful (0 votes)
84 views4 pages

FFT

This document defines a Fast Fourier Transform (FFT) algorithm using complex numbers. It includes classes for Complex numbers and an FFT method that takes an array of Complex as input and returns the transformed array. The FFT method recursively divides the input into even and odd terms, performs FFT on each, and combines the results. It also includes optimized FFT methods for float arrays.

Uploaded by

The Large
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
84 views4 pages

FFT

This document defines a Fast Fourier Transform (FFT) algorithm using complex numbers. It includes classes for Complex numbers and an FFT method that takes an array of Complex as input and returns the transformed array. The FFT method recursively divides the input into even and odd terms, performs FFT on each, and combines the results. It also includes optimized FFT methods for float arrays.

Uploaded by

The Large
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 4

import static java.lang.Math.

*;
import java.util.Arrays;

public class FFT {

private static Complex[] input;


private static int N;
private static int LOGN;
private static Complex[] output;

private static float[] input2;


private static float[] output2;

private static class Complex {


private final double real;
private final double imag;

public Complex(double re, double im) {


real = re;
imag = im;
}

public Complex(boolean pol, double v1, double v2) {


real = (double) (v1*cos(v2));
imag = (double) (v1*sin(v2));
}

public double getReal() {return real;}


public double getImag() {return imag;}

public Complex plus(Complex aux) {


return new Complex(aux.getReal()+real, aux.getImag()+imag);
}

public Complex minus(Complex aux) {


return new Complex(-aux.getReal()+real, -aux.getImag()+imag);
}

public Complex times(Complex mult) {


double rRes = real*mult.getReal()-imag*mult.getImag();
double iRes = real*mult.getImag()+imag*mult.getReal();
return new Complex(rRes, iRes);
}

@Override
public String toString() {
return String.format("%f + %fi", real, imag);
}
}

// Optimized from Sedgewick's online implementation


public static Complex[] fft(Complex[] x) {
int n = x.length;
if (n == 1) return new Complex[] { x[0] };

// fft of even terms


Complex[] even = new Complex[n/2];
for (int k = 0; k < n/2; k++) {
even[k] = x[2*k];
}
Complex[] q = fft(even);

// fft of odd terms


Complex[] odd = even; // reuse the array
for (int k = 0; k < n/2; k++) {
odd[k] = x[2*k + 1];
}
Complex[] r = fft(odd);

// combine
Complex[] y = new Complex[n];
for (int k = 0; k < n/2; k++) {
double kth = -2 * k * Math.PI / n;
Complex wk = new Complex(Math.cos(kth), Math.sin(kth));
y[k] = q[k].plus(wk.times(r[k]));
y[k + n/2] = q[k].minus(wk.times(r[k]));
}
return y;
}

public static void fftOpt(int start, int lvl) {


int n = N >>> lvl;
int skip = 1 << lvl;

int rev = reverse(lvl, start);

if (n == 1) {
output[rev] = input[start];
return;
}

fftOpt(start, lvl+1);
fftOpt(start+skip, lvl+1);

int REVBS = rev<<(LOGN-lvl);


int AGGBS = REVBS + (n>>1);

for (int k = 0; k < n >>> 1; ++k) {


double kth = -(k << 1)*PI/n;
Complex wk = new Complex(cos(kth), sin(kth));
Complex mult = wk.times(output[k + AGGBS]);
Complex ref1 = output[k + REVBS].plus(mult);
Complex ref2 = output[k + REVBS].minus(mult);
output[k + REVBS] = ref1;
output[k + AGGBS] = ref2;
}
}

// write the first result to the position of locAdd and second at locMult.
public void writePlusMinus(float reScl, float imScl, int locMult, int locAdd) {
float multRe = output2[locMult]; float multIm = input2[locMult+1];
float temp1 = reScl*multRe-imScl*multIm; float temp2 =
reScl*multIm+imScl*multRe;
reScl = temp1; imScl = temp2;
}

public static void fftOpt2(int start, int lvl) {


int n = N >>> lvl;
int skip = 1 << lvl;

int rev = reverse(lvl, start);

if (n == 1) {
output2[rev << 1] = input2[start << 1];
output2[1+(rev << 1)] = input2[1 + (start << 1)];
return;
}

fftOpt2(start, lvl+1);
fftOpt2(start+skip, lvl+1);

int REVBS = rev<<(LOGN-lvl);


int AGGBS = REVBS + (n>>1);

for (int k = 0; k < n >>> 1; ++k) {


double kth = -(k << 1)*PI/n;
double re = cos(kth); double im = sin(kth);
Complex wk = new Complex(cos(kth), sin(kth));
Complex mult = wk.times(output[k + AGGBS]);
Complex ref1 = output[k + REVBS].plus(mult);
Complex ref2 = output[k + REVBS].minus(mult);
output[k + REVBS] = ref1;
output[k + AGGBS] = ref2;
}
}

// inline this or else


private static final int reverse(int len, int bits) {
bits = (bits & 0x5555) << 1 | (bits & 0xAAAA) >> 1;
bits = (bits & 0x3333) << 2 | (bits & 0xCCCC) >> 2;
bits = (bits & 0x0F0F) << 4 | (bits & 0xF0F0) >> 4;
bits = (bits & 0x00FF) << 8 | (bits & 0xFF00) >> 8;
return bits >>> 16-len;
}

public static void main(String[] args) {


Complex[] input = {new Complex(1,0), new Complex(3,0), new Complex(2,0),
new Complex(1,0), new Complex(4,0), new Complex(2,0),
new Complex(3,0), new Complex(2,0)};
Complex[] output = fft(input);
FFT.input = input;

float[] input2 = {1,0,3,0,2,0,1,0,4,0,2,0,3,0,2,0};


FFT.input2 = input2;
float[] output2 = new float[16];
FFT.output2 = output2;

FFT.N = 8;
FFT.LOGN = 3;
for(Complex cpx: output) {
System.out.println(cpx);
}
System.out.println();
FFT.output = new Complex[8];
fftOpt2(0, 0);
for(Complex cpx: FFT.output) {
System.out.println(cpx);
}
}
}

You might also like