/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.nativelibs4java.opencl.util; import org.apache.commons.math.complex.Complex; import com.nativelibs4java.opencl.util.fft.*; import com.nativelibs4java.opencl.*; import com.nativelibs4java.opencl.CLPlatform.DeviceFeature; import java.io.IOException; import java.util.*; import java.nio.*; import org.apache.commons.math.transform.FastFourierTransformer; import org.junit.*; import static org.junit.Assert.*; /** * * @author ochafik */ public class DiscreteFourierTransformTest { static double[] complexToInterleavedDoubles(Complex[] complexInput) { int length = complexInput.length; double[] output = new double[length * 2]; for (int i = 0; i < length; i++) { int o = i * 2; Complex c = complexInput[i]; output[o] = c.getReal(); output[o + 1] = c.getImaginary(); } return output; } static Complex[] interleavedDoublesToComplex(double[] input) { int length = input.length / 2; Complex[] complexOutput = new Complex[length]; for (int i = 0; i < length; i++) { int o = i * 2; complexOutput[i] = new Complex(input[o], input[o + 1]); } return complexOutput; } static Complex[] realDoublesToComplex(double[] input) { int length = input.length; Complex[] complexOutput = new Complex[length]; for (int i = 0; i < length; i++) { complexOutput[i] = new Complex(input[i], 0); } return complexOutput; } /* static void assertArrayEquals(String title, Object a, Object b) { if (a instanceof double[]) { double[] aa = (double[])a, bb = (double[])b; for (int i = 0; i < aa.length; i++) { if (Math.abs(aa[i] - bb[i]) > precisionDouble) throw new RuntimeException("[" + title + "] Values different at index " + i + " : " + aa[i] + " vs. " + bb[i] + " !"); } } else if (a instanceof float[]) { float[] aa = (float[])a, bb = (float[])b; for (int i = 0; i < aa.length; i++) { if (Math.abs(aa[i] - bb[i]) > precisionFloat) throw new RuntimeException("[" + title + "] Values different at index " + i + " : " + aa[i] + " vs. " + bb[i] + " !"); } } }*/ static final float precisionFloat = 1e-3f, precisionInverseFloat = 1e-2f; static final double precisionDouble = 1e-10, precisionInverseDouble = 1e-5; static Collection<double[]> createTestDoubleInputs() { Collection<double[]> ret = new ArrayList<double[]>(); for (int n : new int[] { 1, 2, 4, 8, 16, 1024 }) { double[] in = new double[2 * n]; for (int i = 0; i < n; i++) { in[i * 2] = 1 / (double)(i + 1); in[i * 2 + 1] = 0; } ret.add(in); } return ret; } static Collection<float[]> createTestFloatInputs() { Collection<float[]> ret = new ArrayList<float[]>(); for (double[] in : createTestDoubleInputs()) ret.add(toFloat(in)); return ret; } static float[] toFloat(double[] in) { float[] out = new float[in.length]; for (int i = 0; i < in.length; i++) out[i] = (float)in[i]; return out; } static double[] scale(double factor, double[] in) { double[] out = new double[in.length]; for (int i = 0; i < in.length; i++) out[i] = factor * in[i]; return out; } public void testDoubleValues(String title, Transformer<Double, double[]> tr) { FastFourierTransformer apache = new FastFourierTransformer(); CLQueue queue = tr.getContext() == null ? null : tr.getContext().createDefaultOutOfOrderQueueIfPossible(); for (double[] data : createTestDoubleInputs()) { double[] expected = complexToInterleavedDoubles(apache.transform(interleavedDoublesToComplex(data))); assertArrayEquals(title + " (n = " + (data.length / 2) + ")", expected, tr.transform(queue, data, false), precisionDouble); } } public void testFloatValues(String title, Transformer<Float, float[]> tr) { FastFourierTransformer apache = new FastFourierTransformer(); CLQueue queue = tr.getContext() == null ? null : tr.getContext().createDefaultOutOfOrderQueueIfPossible(); for (double[] data : createTestDoubleInputs()) { float[] dataf = toFloat(data); double[] expected = complexToInterleavedDoubles(apache.transform(interleavedDoublesToComplex(data))); assertArrayEquals(title + " (n = " + (data.length / 2) + ")", toFloat(expected), tr.transform(queue, dataf, false), precisionFloat); } } @Ignore @Test public void testDoubleFFTValues() throws IOException { testDoubleValues("Double FFT", new DoubleFFTPow2()); } @Test public void testFloatFFTValues() throws IOException { testFloatValues("Float FFT", new FloatFFTPow2()); } @Test public void testDoubleDFTValues() throws IOException { testDoubleValues("Double DFT", new DoubleDFT()); } @Test public void testFloatDFTValues() throws IOException { testFloatValues("Float DFT", new FloatDFT()); } @Test public void testDoubleDFTInverse() throws IOException, CLException { testDoubleTransformer("Double FFT Inverse", new DoubleDFT()); } @Test public void testFloatDFTInverse() throws IOException, CLException { testFloatTransformer("Float DFT Inverse", new FloatDFT()); } @Ignore @Test public void testDoubleFFTInverse() throws IOException, CLException { testDoubleTransformer("Double FFT Inverse", new DoubleFFTPow2()); } @Test public void testFloatFFTInverse() throws IOException, CLException { testFloatTransformer("Float FFT Inverse", new FloatFFTPow2()); } void testDoubleTransformer(String title, Transformer<Double, double[]> t) throws IOException, CLException { CLQueue queue = t.getContext().createDefaultOutOfOrderQueueIfPossible(); //System.out.println("Context: " + t.getContext()); for (double[] in : createTestDoubleInputs()) { double[] out = t.transform(queue, in, false); double[] back = t.transform(queue, out, true); assertArrayEquals(title + " (n = " + (in.length / 2) + ")", in, back, precisionInverseDouble); } } void testFloatTransformer(String title, Transformer<Float, float[]> t) throws IOException, CLException { CLQueue queue = t.getContext().createDefaultOutOfOrderQueueIfPossible(); //System.out.println("Context: " + t.getContext()); for (float[] in : createTestFloatInputs()) { float[] out = t.transform(queue, in, false); float[] back = t.transform(queue, out, true); assertArrayEquals(title + " (n = " + (in.length / 2) + ")", in, back, precisionInverseFloat); } } }