In o.a.c.m.transform, introduced an enumeration for the type (forward, inverse) of transform asked by the user (MATH-743).

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1242703 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Sebastien Brisard 2012-02-10 08:46:40 +00:00
parent 49c39e7d1c
commit dee1c0d70b
5 changed files with 307 additions and 514 deletions

View File

@ -25,7 +25,7 @@ import org.apache.commons.math.exception.MathIllegalArgumentException;
import org.apache.commons.math.exception.NonMonotonicSequenceException; import org.apache.commons.math.exception.NonMonotonicSequenceException;
import org.apache.commons.math.exception.NotStrictlyPositiveException; import org.apache.commons.math.exception.NotStrictlyPositiveException;
import org.apache.commons.math.exception.util.LocalizedFormats; import org.apache.commons.math.exception.util.LocalizedFormats;
import org.apache.commons.math.transform.FastFourierTransformer.Normalization; import org.apache.commons.math.transform.FastFourierTransformer.DftNormalization;
import org.apache.commons.math.util.ArithmeticUtils; import org.apache.commons.math.util.ArithmeticUtils;
import org.apache.commons.math.util.FastMath; import org.apache.commons.math.util.FastMath;
@ -273,8 +273,8 @@ public class FastCosineTransformer implements RealTransformer, Serializable {
t1 += c; t1 += c;
} }
FastFourierTransformer transformer; FastFourierTransformer transformer;
transformer = new FastFourierTransformer(Normalization.STANDARD); transformer = new FastFourierTransformer(DftNormalization.STANDARD);
Complex[] y = transformer.transform(x); Complex[] y = transformer.transform(x, TransformType.FORWARD);
// reconstruct the FCT result for the original array // reconstruct the FCT result for the original array
transformed[0] = y[0].getReal(); transformed[0] = y[0].getReal();

View File

@ -85,17 +85,22 @@ import org.apache.commons.math.util.MathArrays;
*/ */
public class FastFourierTransformer implements Serializable { public class FastFourierTransformer implements Serializable {
/** The various types of normalizations that can be applied. */ /**
public static enum Normalization { * The various types of normalizations that can be applied to discrete
/** Standard DFT. */ * Fourier transforms.
*
* @see FastFourierTransformer
*/
public static enum DftNormalization {
/** The normalization to be specified for standard DFT. */
STANDARD, STANDARD,
/** Unitary DFT. */ /** The normalization to be specified for unitary DFT. */
UNITARY; UNITARY;
} }
/** Serializable version identifier. */ /** Serializable version identifier. */
static final long serialVersionUID = 20120902L; static final long serialVersionUID = 20120210L;
/** /**
* {@code W_SUB_N_R[i]} is the real part of * {@code W_SUB_N_R[i]} is the real part of
@ -143,19 +148,18 @@ public class FastFourierTransformer implements Serializable {
, -0x1.921fb54442d18p-54, -0x1.921fb54442d18p-55, -0x1.921fb54442d18p-56, -0x1.921fb54442d18p-57 , -0x1.921fb54442d18p-54, -0x1.921fb54442d18p-55, -0x1.921fb54442d18p-56, -0x1.921fb54442d18p-57
, -0x1.921fb54442d18p-58, -0x1.921fb54442d18p-59, -0x1.921fb54442d18p-60 }; , -0x1.921fb54442d18p-58, -0x1.921fb54442d18p-59, -0x1.921fb54442d18p-60 };
/** /** The type of DFT to be performed. */
* The type of DFT to be performed. private final DftNormalization normalization;
*/
private final Normalization type;
/** /**
* Creates a new instance of this class, with various normalization * Creates a new instance of this class, with various normalization
* conventions. * conventions.
* *
* @param type the type of transform to be computed * @param normalization the type of normalization to be applied to the
* transformed data
*/ */
public FastFourierTransformer(final Normalization type) { public FastFourierTransformer(final DftNormalization normalization) {
this.type = type; this.normalization = normalization;
} }
/** /**
@ -199,21 +203,21 @@ public class FastFourierTransformer implements Serializable {
* Applies the proper normalization to the specified transformed data. * Applies the proper normalization to the specified transformed data.
* *
* @param dataRI the unscaled transformed data * @param dataRI the unscaled transformed data
* @param type the type of transform * @param normalization the normalization to be applied
* @param inverse {@code true} if normalization should be performed for the * @param type the type of transform (forward, inverse) which resulted in the
* inverse transform * specified data
*/ */
private static void normalizeTransformedData(final double[][] dataRI, private static void normalizeTransformedData(final double[][] dataRI,
final Normalization type, final boolean inverse) { final DftNormalization normalization, final TransformType type) {
final double[] dataR = dataRI[0]; final double[] dataR = dataRI[0];
final double[] dataI = dataRI[1]; final double[] dataI = dataRI[1];
final int n = dataR.length; final int n = dataR.length;
assert dataI.length == n; assert dataI.length == n;
switch (type) { switch (normalization) {
case STANDARD: case STANDARD:
if (inverse) { if (type == TransformType.INVERSE) {
final double scaleFactor = 1.0 / ((double) n); final double scaleFactor = 1.0 / ((double) n);
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
dataR[i] *= scaleFactor; dataR[i] *= scaleFactor;
@ -251,18 +255,16 @@ public class FastFourierTransformer implements Serializable {
* *
* @param dataRI the two dimensional array of real and imaginary parts of * @param dataRI the two dimensional array of real and imaginary parts of
* the data * the data
* @param type the type of normalization to be applied to the transformed * @param normalization the normalization to be applied to the transformed
* data * data
* @param inverse {@code true} if the inverse standard transform must be * @param type the type of transform (forward, inverse) to be performed
* performed
* @throws DimensionMismatchException if the number of rows of the specified * @throws DimensionMismatchException if the number of rows of the specified
* array is not two, or the array is not rectangular * array is not two, or the array is not rectangular
* @throws MathIllegalArgumentException if the number of data points is not * @throws MathIllegalArgumentException if the number of data points is not
* a power of two * a power of two
*/ */
public static void transformInPlace(final double[][] dataRI, public static void transformInPlace(final double[][] dataRI,
final Normalization type, final boolean inverse) throws final DftNormalization normalization, final TransformType type) {
DimensionMismatchException, MathIllegalArgumentException {
if (dataRI.length != 2) { if (dataRI.length != 2) {
throw new DimensionMismatchException(dataRI.length, 2); throw new DimensionMismatchException(dataRI.length, 2);
@ -295,14 +297,14 @@ public class FastFourierTransformer implements Serializable {
dataR[1] = srcR0 - srcR1; dataR[1] = srcR0 - srcR1;
dataI[1] = srcI0 - srcI1; dataI[1] = srcI0 - srcI1;
normalizeTransformedData(dataRI, type, inverse); normalizeTransformedData(dataRI, normalization, type);
return; return;
} }
bitReversalShuffle2(dataR, dataI); bitReversalShuffle2(dataR, dataI);
// Do 4-term DFT. // Do 4-term DFT.
if (inverse) { if (type == TransformType.INVERSE) {
for (int i0 = 0; i0 < n; i0 += 4) { for (int i0 = 0; i0 < n; i0 += 4) {
final int i1 = i0 + 1; final int i1 = i0 + 1;
final int i2 = i0 + 2; final int i2 = i0 + 2;
@ -369,7 +371,7 @@ public class FastFourierTransformer implements Serializable {
int logN0 = lastLogN0 + 1; int logN0 = lastLogN0 + 1;
double wSubN0R = W_SUB_N_R[logN0]; double wSubN0R = W_SUB_N_R[logN0];
double wSubN0I = W_SUB_N_I[logN0]; double wSubN0I = W_SUB_N_I[logN0];
if (inverse) { if (type == TransformType.INVERSE) {
wSubN0I = -wSubN0I; wSubN0I = -wSubN0I;
} }
@ -405,41 +407,37 @@ public class FastFourierTransformer implements Serializable {
lastLogN0 = logN0; lastLogN0 = logN0;
} }
normalizeTransformedData(dataRI, type, inverse); normalizeTransformedData(dataRI, normalization, type);
} }
/** /**
* Returns the forward transform of the specified real data set. * Returns the (forward, inverse) transform of the specified real data set.
* *
* @param f the real data array to be transformed * @param f the real data array to be transformed
* @param type the type of transform (forward, inverse) to be performed
* @return the complex transformed array * @return the complex transformed array
* @throws MathIllegalArgumentException if the length of the data array is * @throws MathIllegalArgumentException if the length of the data array is
* not a power of two * not a power of two
*/ */
public Complex[] transform(double[] f) { public Complex[] transform(final double[] f, final TransformType type) {
final double[][] dataRI = new double[][] { final double[][] dataRI = new double[][] {
MathArrays.copyOf(f, f.length), new double[f.length] MathArrays.copyOf(f, f.length), new double[f.length]
}; };
transformInPlace(dataRI, type, false); transformInPlace(dataRI, normalization, type);
// if (unitary) {
// final double s = 1.0 / FastMath.sqrt(f.length);
// TransformUtils.scaleArray(dataRI[0], s);
// TransformUtils.scaleArray(dataRI[1], s);
// }
return TransformUtils.createComplexArray(dataRI); return TransformUtils.createComplexArray(dataRI);
} }
/** /**
* Returns the forward transform of the specified real function, sampled on * Returns the (forward, inverse) transform of the specified real function,
* the specified interval. * sampled on the specified interval.
* *
* @param f the function to be sampled and transformed * @param f the function to be sampled and transformed
* @param min the (inclusive) lower bound for the interval * @param min the (inclusive) lower bound for the interval
* @param max the (exclusive) upper bound for the interval * @param max the (exclusive) upper bound for the interval
* @param n the number of sample points * @param n the number of sample points
* @param type the type of transform (forward, inverse) to be performed
* @return the complex transformed array * @return the complex transformed array
* @throws org.apache.commons.math.exception.NumberIsTooLargeException * @throws org.apache.commons.math.exception.NumberIsTooLargeException
* if the lower bound is greater than, or equal to the upper bound * if the lower bound is greater than, or equal to the upper bound
@ -448,98 +446,28 @@ public class FastFourierTransformer implements Serializable {
* @throws MathIllegalArgumentException if the number of sample points * @throws MathIllegalArgumentException if the number of sample points
* {@code n} is not a power of two * {@code n} is not a power of two
*/ */
public Complex[] transform(UnivariateFunction f, public Complex[] transform(final UnivariateFunction f,
double min, double max, int n) { final double min, final double max, final int n,
final TransformType type) {
final double[] data = FunctionUtils.sample(f, min, max, n); final double[] data = FunctionUtils.sample(f, min, max, n);
return transform(data); return transform(data, type);
} }
/** /**
* Returns the forward transform of the specified complex data set. * Returns the (forward, inverse) transform of the specified complex data
* set.
* *
* @param f the complex data array to be transformed * @param f the complex data array to be transformed
* @param type the type of transform (forward, inverse) to be performed
* @return the complex transformed array * @return the complex transformed array
* @throws MathIllegalArgumentException if the length of the data array is * @throws MathIllegalArgumentException if the length of the data array is
* not a power of two * not a power of two
*/ */
public Complex[] transform(Complex[] f) { public Complex[] transform(final Complex[] f, final TransformType type) {
final double[][] dataRI = TransformUtils.createRealImaginaryArray(f); final double[][] dataRI = TransformUtils.createRealImaginaryArray(f);
transformInPlace(dataRI, type, false); transformInPlace(dataRI, normalization, type);
// if (unitary) {
// final double s = 1.0 / FastMath.sqrt(f.length);
// TransformUtils.scaleArray(dataRI[0], s);
// TransformUtils.scaleArray(dataRI[1], s);
// }
return TransformUtils.createComplexArray(dataRI);
}
/**
* Returns the inverse transform of the specified real data set.
*
* @param f the real data array to be inversely transformed
* @return the complex inversely transformed array
* @throws MathIllegalArgumentException if the length of the data array is
* not a power of two
*/
public Complex[] inverseTransform(double[] f) {
final double[][] dataRI = new double[][] {
MathArrays.copyOf(f, f.length), new double[f.length]
};
transformInPlace(dataRI, type, true);
// if (unitary) {
// final double s = FastMath.sqrt(f.length);
// TransformUtils.scaleArray(dataRI[0], s);
// TransformUtils.scaleArray(dataRI[1], s);
// }
return TransformUtils.createComplexArray(dataRI);
}
/**
* Returns the inverse transform of the specified real function, sampled
* on the given interval.
*
* @param f the function to be sampled and inversely transformed
* @param min the (inclusive) lower bound for the interval
* @param max the (exclusive) upper bound for the interval
* @param n the number of sample points
* @return the complex inversely transformed array
* @throws org.apache.commons.math.exception.NumberIsTooLargeException
* if the lower bound is greater than, or equal to the upper bound
* @throws org.apache.commons.math.exception.NotStrictlyPositiveException
* if the number of sample points {@code n} is negative
* @throws MathIllegalArgumentException if the number of sample points
* {@code n} is not a power of two
*/
public Complex[] inverseTransform(UnivariateFunction f,
double min, double max, int n) {
final double[] data = FunctionUtils.sample(f, min, max, n);
return inverseTransform(data);
}
/**
* Returns the inverse transform of the specified complex data set.
*
* @param f the complex data array to be inversely transformed
* @return the complex inversely transformed array
* @throws MathIllegalArgumentException if the length of the data array is
* not a power of two
*/
public Complex[] inverseTransform(Complex[] f) {
final double[][] dataRI = TransformUtils.createRealImaginaryArray(f);
final double[] dataR = dataRI[0];
final double[] dataI = dataRI[1];
transformInPlace(dataRI, type, true);
// if (unitary) {
// final double s = FastMath.sqrt(f.length);
// TransformUtils.scaleArray(dataR, s);
// TransformUtils.scaleArray(dataI, s);
// }
return TransformUtils.createComplexArray(dataRI); return TransformUtils.createComplexArray(dataRI);
} }
@ -555,19 +483,20 @@ public class FastFourierTransformer implements Serializable {
* *
* @param mdca Multi-Dimensional Complex Array id est * @param mdca Multi-Dimensional Complex Array id est
* {@code Complex[][][][]} * {@code Complex[][][][]}
* @param forward {@link #inverseTransform} is performed if this is * @param type the type of transform (forward, inverse) to be performed
* {@code false}
* @return transform of {@code mdca} as a Multi-Dimensional Complex Array * @return transform of {@code mdca} as a Multi-Dimensional Complex Array
* id est {@code Complex[][][][]} * id est {@code Complex[][][][]}
* @throws IllegalArgumentException if any dimension is not a power of two * @throws IllegalArgumentException if any dimension is not a power of two
* @deprecated see MATH-736
*/ */
public Object mdfft(Object mdca, boolean forward) { @Deprecated
public Object mdfft(Object mdca, TransformType type) {
MultiDimensionalComplexMatrix mdcm = (MultiDimensionalComplexMatrix) MultiDimensionalComplexMatrix mdcm = (MultiDimensionalComplexMatrix)
new MultiDimensionalComplexMatrix(mdca).clone(); new MultiDimensionalComplexMatrix(mdca).clone();
int[] dimensionSize = mdcm.getDimensionSizes(); int[] dimensionSize = mdcm.getDimensionSizes();
//cycle through each dimension //cycle through each dimension
for (int i = 0; i < dimensionSize.length; i++) { for (int i = 0; i < dimensionSize.length; i++) {
mdfft(mdcm, forward, i, new int[0]); mdfft(mdcm, type, i, new int[0]);
} }
return mdcm.getArray(); return mdcm.getArray();
} }
@ -576,14 +505,15 @@ public class FastFourierTransformer implements Serializable {
* Performs one dimension of a multi-dimensional Fourier transform. * Performs one dimension of a multi-dimensional Fourier transform.
* *
* @param mdcm input matrix * @param mdcm input matrix
* @param forward {@link #inverseTransform} is performed if this is * @param type the type of transform (forward, inverse) to be performed
* {@code false}
* @param d index of the dimension to process * @param d index of the dimension to process
* @param subVector recursion subvector * @param subVector recursion subvector
* @throws IllegalArgumentException if any dimension is not a power of two * @throws IllegalArgumentException if any dimension is not a power of two
* @deprecated see MATH-736
*/ */
@Deprecated
private void mdfft(MultiDimensionalComplexMatrix mdcm, private void mdfft(MultiDimensionalComplexMatrix mdcm,
boolean forward, int d, int[] subVector) { TransformType type, int d, int[] subVector) {
int[] dimensionSize = mdcm.getDimensionSizes(); int[] dimensionSize = mdcm.getDimensionSizes();
//if done //if done
@ -595,11 +525,7 @@ public class FastFourierTransformer implements Serializable {
temp[i] = mdcm.get(subVector); temp[i] = mdcm.get(subVector);
} }
if (forward) { temp = transform(temp, type);
temp = transform(temp);
} else {
temp = inverseTransform(temp);
}
for (int i = 0; i < dimensionSize[d]; i++) { for (int i = 0; i < dimensionSize[d]; i++) {
subVector[d] = i; subVector[d] = i;
@ -612,12 +538,12 @@ public class FastFourierTransformer implements Serializable {
//value is not important once the recursion is done. //value is not important once the recursion is done.
//then an fft will be applied along the dimension d. //then an fft will be applied along the dimension d.
vector[d] = 0; vector[d] = 0;
mdfft(mdcm, forward, d, vector); mdfft(mdcm, type, d, vector);
} else { } else {
for (int i = 0; i < dimensionSize[subVector.length]; i++) { for (int i = 0; i < dimensionSize[subVector.length]; i++) {
vector[subVector.length] = i; vector[subVector.length] = i;
//further split along the next dimension //further split along the next dimension
mdfft(mdcm, forward, d, vector); mdfft(mdcm, type, d, vector);
} }
} }
} }
@ -629,7 +555,10 @@ public class FastFourierTransformer implements Serializable {
* eventually be replaced by jsr-83 of the java community process * eventually be replaced by jsr-83 of the java community process
* http://jcp.org/en/jsr/detail?id=83 * http://jcp.org/en/jsr/detail?id=83
* may require additional exception throws for other basic requirements. * may require additional exception throws for other basic requirements.
*
* @deprecated see MATH-736
*/ */
@Deprecated
private static class MultiDimensionalComplexMatrix private static class MultiDimensionalComplexMatrix
implements Cloneable { implements Cloneable {

View File

@ -25,7 +25,7 @@ import org.apache.commons.math.exception.MathIllegalArgumentException;
import org.apache.commons.math.exception.NonMonotonicSequenceException; import org.apache.commons.math.exception.NonMonotonicSequenceException;
import org.apache.commons.math.exception.NotStrictlyPositiveException; import org.apache.commons.math.exception.NotStrictlyPositiveException;
import org.apache.commons.math.exception.util.LocalizedFormats; import org.apache.commons.math.exception.util.LocalizedFormats;
import org.apache.commons.math.transform.FastFourierTransformer.Normalization; import org.apache.commons.math.transform.FastFourierTransformer.DftNormalization;
import org.apache.commons.math.util.ArithmeticUtils; import org.apache.commons.math.util.ArithmeticUtils;
import org.apache.commons.math.util.FastMath; import org.apache.commons.math.util.FastMath;
@ -294,8 +294,8 @@ public class FastSineTransformer implements RealTransformer, Serializable {
x[n - i] = a - b; x[n - i] = a - b;
} }
FastFourierTransformer transformer; FastFourierTransformer transformer;
transformer = new FastFourierTransformer(Normalization.STANDARD); transformer = new FastFourierTransformer(DftNormalization.STANDARD);
Complex[] y = transformer.transform(x); Complex[] y = transformer.transform(x, TransformType.FORWARD);
// reconstruct the FST result for the original array // reconstruct the FST result for the original array
transformed[0] = 0.0; transformed[0] = 0.0;

View File

@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.transform;
/**
* This enumeration defines the type of transform which is to be computed.
*
* @version $Id Revision$
* @since 3.0
*/
public enum TransformType {
/** The type to be specified for forward transforms. */
FORWARD,
/** The type to be specified for inverse transforms. */
INVERSE;
}

View File

@ -26,7 +26,7 @@ import org.apache.commons.math.complex.Complex;
import org.apache.commons.math.exception.MathIllegalArgumentException; import org.apache.commons.math.exception.MathIllegalArgumentException;
import org.apache.commons.math.exception.NotStrictlyPositiveException; import org.apache.commons.math.exception.NotStrictlyPositiveException;
import org.apache.commons.math.exception.NumberIsTooLargeException; import org.apache.commons.math.exception.NumberIsTooLargeException;
import org.apache.commons.math.transform.FastFourierTransformer.Normalization; import org.apache.commons.math.transform.FastFourierTransformer.DftNormalization;
import org.apache.commons.math.util.FastMath; import org.apache.commons.math.util.FastMath;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -44,191 +44,123 @@ public final class FastFourierTransformerTest {
private final static long SEED = 20110111L; private final static long SEED = 20110111L;
/* /*
* Precondition checks for standard transform. * Precondition checks.
*/ */
@Test(expected = MathIllegalArgumentException.class) @Test
public void testStandardTransformComplexSizeNotAPowerOfTwo() { public void testTransformComplexSizeNotAPowerOfTwo() {
final int n = 127; final int n = 127;
final Complex[] x = createComplexData(n); final Complex[] x = createComplexData(n);
final FastFourierTransformer fft; final FastFourierTransformer.DftNormalization[] norm;
fft = new FastFourierTransformer(Normalization.STANDARD); norm = FastFourierTransformer.DftNormalization.values();
fft.transform(x); final TransformType[] type;
type = TransformType.values();
for (int i = 0; i < norm.length; i++) {
for (int j = 0; j < type.length; j++) {
final FastFourierTransformer fft;
fft = new FastFourierTransformer(norm[i]);
try {
fft.transform(x, type[j]);
Assert.fail(norm[i] + ", " + type[j] +
": MathIllegalArgumentException was expected");
} catch (MathIllegalArgumentException e) {
// Expected behaviour
}
}
}
} }
@Test(expected = MathIllegalArgumentException.class) @Test
public void testStandardTransformRealSizeNotAPowerOfTwo() { public void testTransformRealSizeNotAPowerOfTwo() {
final int n = 127; final int n = 127;
final double[] x = createRealData(n); final double[] x = createRealData(n);
final FastFourierTransformer fft; final FastFourierTransformer.DftNormalization[] norm;
fft = new FastFourierTransformer(Normalization.STANDARD); norm = FastFourierTransformer.DftNormalization.values();
fft.transform(x); final TransformType[] type;
type = TransformType.values();
for (int i = 0; i < norm.length; i++) {
for (int j = 0; j < type.length; j++) {
final FastFourierTransformer fft;
fft = new FastFourierTransformer(norm[i]);
try {
fft.transform(x, type[j]);
Assert.fail(norm[i] + ", " + type[j] +
": MathIllegalArgumentException was expected");
} catch (MathIllegalArgumentException e) {
// Expected behaviour
}
}
}
} }
@Test(expected = MathIllegalArgumentException.class) @Test
public void testStandardTransformFunctionSizeNotAPowerOfTwo() { public void testTransformFunctionSizeNotAPowerOfTwo() {
final int n = 127; final int n = 127;
final UnivariateFunction f = new Sin(); final UnivariateFunction f = new Sin();
final FastFourierTransformer fft; final FastFourierTransformer.DftNormalization[] norm;
fft = new FastFourierTransformer(Normalization.STANDARD); norm = FastFourierTransformer.DftNormalization.values();
fft.transform(f, 0.0, Math.PI, n); final TransformType[] type;
type = TransformType.values();
for (int i = 0; i < norm.length; i++) {
for (int j = 0; j < type.length; j++) {
final FastFourierTransformer fft;
fft = new FastFourierTransformer(norm[i]);
try {
fft.transform(f, 0.0, Math.PI, n, type[j]);
Assert.fail(norm[i] + ", " + type[j] +
": MathIllegalArgumentException was expected");
} catch (MathIllegalArgumentException e) {
// Expected behaviour
}
}
}
} }
@Test(expected = NotStrictlyPositiveException.class) @Test
public void testStandardTransformFunctionNotStrictlyPositiveNumberOfSamples() { public void testTransformFunctionNotStrictlyPositiveNumberOfSamples() {
final int n = -128; final int n = -128;
final UnivariateFunction f = new Sin(); final UnivariateFunction f = new Sin();
final FastFourierTransformer fft; final FastFourierTransformer.DftNormalization[] norm;
fft = new FastFourierTransformer(Normalization.STANDARD); norm = FastFourierTransformer.DftNormalization.values();
fft.transform(f, 0.0, Math.PI, n); final TransformType[] type;
type = TransformType.values();
for (int i = 0; i < norm.length; i++) {
for (int j = 0; j < type.length; j++) {
final FastFourierTransformer fft;
fft = new FastFourierTransformer(norm[i]);
try {
fft.transform(f, 0.0, Math.PI, n, type[j]);
fft.transform(f, 0.0, Math.PI, n, type[j]);
Assert.fail(norm[i] + ", " + type[j] +
": NotStrictlyPositiveException was expected");
} catch (NotStrictlyPositiveException e) {
// Expected behaviour
}
}
}
} }
@Test(expected = NumberIsTooLargeException.class) @Test
public void testStandardTransformFunctionInvalidBounds() { public void testTransformFunctionInvalidBounds() {
final int n = 128; final int n = 128;
final UnivariateFunction f = new Sin(); final UnivariateFunction f = new Sin();
final FastFourierTransformer fft; final FastFourierTransformer.DftNormalization[] norm;
fft = new FastFourierTransformer(Normalization.STANDARD); norm = FastFourierTransformer.DftNormalization.values();
fft.transform(f, Math.PI, 0.0, n); final TransformType[] type;
} type = TransformType.values();
for (int i = 0; i < norm.length; i++) {
@Test(expected = MathIllegalArgumentException.class) for (int j = 0; j < type.length; j++) {
public void testStandardInverseTransformComplexSizeNotAPowerOfTwo() { final FastFourierTransformer fft;
final int n = 127; fft = new FastFourierTransformer(norm[i]);
final Complex[] x = createComplexData(n); try {
final FastFourierTransformer fft; fft.transform(f, Math.PI, 0.0, n, type[j]);
fft = new FastFourierTransformer(Normalization.STANDARD); Assert.fail(norm[i] + ", " + type[j] +
fft.inverseTransform(x); ": NumberIsTooLargeException was expected");
} } catch (NumberIsTooLargeException e) {
// Expected behaviour
@Test(expected = MathIllegalArgumentException.class) }
public void testStandardInverseTransformRealSizeNotAPowerOfTwo() { }
final int n = 127; }
final double[] x = createRealData(n);
final FastFourierTransformer fft;
fft = new FastFourierTransformer(Normalization.STANDARD);
fft.inverseTransform(x);
}
@Test(expected = MathIllegalArgumentException.class)
public void testStandardInverseTransformFunctionSizeNotAPowerOfTwo() {
final int n = 127;
final UnivariateFunction f = new Sin();
final FastFourierTransformer fft;
fft = new FastFourierTransformer(Normalization.STANDARD);
fft.inverseTransform(f, 0.0, Math.PI, n);
}
@Test(expected = NotStrictlyPositiveException.class)
public void testStandardInverseTransformFunctionNotStrictlyPositiveNumberOfSamples() {
final int n = -128;
final UnivariateFunction f = new Sin();
final FastFourierTransformer fft;
fft = new FastFourierTransformer(Normalization.STANDARD);
fft.inverseTransform(f, 0.0, Math.PI, n);
}
@Test(expected = NumberIsTooLargeException.class)
public void testStandardInverseTransformFunctionInvalidBounds() {
final int n = 128;
final UnivariateFunction f = new Sin();
final FastFourierTransformer fft;
fft = new FastFourierTransformer(Normalization.STANDARD);
fft.transform(f, Math.PI, 0.0, n);
}
/*
* Precondition checks for unitary transform.
*/
@Test(expected = MathIllegalArgumentException.class)
public void testUnitaryTransformComplexSizeNotAPowerOfTwo() {
final int n = 127;
final Complex[] x = createComplexData(n);
final FastFourierTransformer fft;
fft = new FastFourierTransformer(Normalization.UNITARY);
fft.transform(x);
}
@Test(expected = MathIllegalArgumentException.class)
public void testUnitaryTransformRealSizeNotAPowerOfTwo() {
final int n = 127;
final double[] x = createRealData(n);
final FastFourierTransformer fft;
fft = new FastFourierTransformer(Normalization.UNITARY);
fft.transform(x);
}
@Test(expected = MathIllegalArgumentException.class)
public void testUnitaryTransformFunctionSizeNotAPowerOfTwo() {
final int n = 127;
final UnivariateFunction f = new Sin();
final FastFourierTransformer fft;
fft = new FastFourierTransformer(Normalization.UNITARY);
fft.transform(f, 0.0, Math.PI, n);
}
@Test(expected = NotStrictlyPositiveException.class)
public void testUnitaryTransformFunctionNotStrictlyPositiveNumberOfSamples() {
final int n = -128;
final UnivariateFunction f = new Sin();
final FastFourierTransformer fft;
fft = new FastFourierTransformer(Normalization.UNITARY);
fft.transform(f, 0.0, Math.PI, n);
}
@Test(expected = NumberIsTooLargeException.class)
public void testUnitaryTransformFunctionInvalidBounds() {
final int n = 128;
final UnivariateFunction f = new Sin();
final FastFourierTransformer fft;
fft = new FastFourierTransformer(Normalization.UNITARY);
fft.transform(f, Math.PI, 0.0, n);
}
@Test(expected = MathIllegalArgumentException.class)
public void testUnitaryInverseTransformComplexSizeNotAPowerOfTwo() {
final int n = 127;
final Complex[] x = createComplexData(n);
final FastFourierTransformer fft;
fft = new FastFourierTransformer(Normalization.UNITARY);
fft.inverseTransform(x);
}
@Test(expected = MathIllegalArgumentException.class)
public void testUnitaryInverseTransformRealSizeNotAPowerOfTwo() {
final int n = 127;
final double[] x = createRealData(n);
final FastFourierTransformer fft;
fft = new FastFourierTransformer(Normalization.UNITARY);
fft.inverseTransform(x);
}
@Test(expected = MathIllegalArgumentException.class)
public void testUnitaryInverseTransformFunctionSizeNotAPowerOfTwo() {
final int n = 127;
final UnivariateFunction f = new Sin();
final FastFourierTransformer fft;
fft = new FastFourierTransformer(Normalization.UNITARY);
fft.inverseTransform(f, 0.0, Math.PI, n);
}
@Test(expected = NotStrictlyPositiveException.class)
public void testUnitaryInverseTransformFunctionNotStrictlyPositiveNumberOfSamples() {
final int n = -128;
final UnivariateFunction f = new Sin();
final FastFourierTransformer fft;
fft = new FastFourierTransformer(Normalization.UNITARY);
fft.inverseTransform(f, 0.0, Math.PI, n);
}
@Test(expected = NumberIsTooLargeException.class)
public void testUnitaryInverseTransformFunctionInvalidBounds() {
final int n = 128;
final UnivariateFunction f = new Sin();
final FastFourierTransformer fft;
fft = new FastFourierTransformer(Normalization.UNITARY);
fft.transform(f, Math.PI, 0.0, n);
} }
/* /*
@ -284,28 +216,32 @@ public final class FastFourierTransformerTest {
} }
private static void doTestTransformComplex(final int n, final double tol, private static void doTestTransformComplex(final int n, final double tol,
final boolean forward, final boolean standard) { final FastFourierTransformer.DftNormalization normalization,
final TransformType type) {
final FastFourierTransformer fft; final FastFourierTransformer fft;
if (standard) { fft = new FastFourierTransformer(normalization);
fft = new FastFourierTransformer(Normalization.STANDARD);
} else {
fft = new FastFourierTransformer(Normalization.UNITARY);
}
final Complex[] x = createComplexData(n); final Complex[] x = createComplexData(n);
final Complex[] expected; final Complex[] expected;
final Complex[] actual;
final double s; final double s;
if (forward) { if (type==TransformType.FORWARD) {
expected = dft(x, -1); expected = dft(x, -1);
s = standard ? 1.0 : 1.0 / FastMath.sqrt(n); if (normalization == FastFourierTransformer.DftNormalization.STANDARD){
actual = fft.transform(x); s = 1.0;
} else {
s = 1.0 / FastMath.sqrt(n);
}
} else { } else {
expected = dft(x, 1); expected = dft(x, 1);
s = standard ? 1.0 / n : 1.0 / FastMath.sqrt(n); if (normalization == FastFourierTransformer.DftNormalization.STANDARD) {
actual = fft.inverseTransform(x); s = 1.0 / n;
} else {
s = 1.0 / FastMath.sqrt(n);
}
} }
final Complex[] actual = fft.transform(x, type);
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
final String msg = String.format("%d, %d", n, i); final String msg;
msg = String.format("%s, %s, %d, %d", normalization, type, n, i);
final double re = s * expected[i].getReal(); final double re = s * expected[i].getReal();
Assert.assertEquals(msg, re, actual[i].getReal(), Assert.assertEquals(msg, re, actual[i].getReal(),
tol * FastMath.abs(re)); tol * FastMath.abs(re));
@ -316,32 +252,36 @@ public final class FastFourierTransformerTest {
} }
private static void doTestTransformReal(final int n, final double tol, private static void doTestTransformReal(final int n, final double tol,
final boolean forward, final boolean standard) { final FastFourierTransformer.DftNormalization normalization,
final TransformType type) {
final FastFourierTransformer fft; final FastFourierTransformer fft;
if (standard) { fft = new FastFourierTransformer(normalization);
fft = new FastFourierTransformer(Normalization.STANDARD);
} else {
fft = new FastFourierTransformer(Normalization.UNITARY);
}
final double[] x = createRealData(n); final double[] x = createRealData(n);
final Complex[] xc = new Complex[n]; final Complex[] xc = new Complex[n];
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
xc[i] = new Complex(x[i], 0.0); xc[i] = new Complex(x[i], 0.0);
} }
final Complex[] expected; final Complex[] expected;
final Complex[] actual;
final double s; final double s;
if (forward) { if (type == TransformType.FORWARD) {
expected = dft(xc, -1); expected = dft(xc, -1);
s = standard ? 1.0 : 1.0 / FastMath.sqrt(n); if (normalization == FastFourierTransformer.DftNormalization.STANDARD) {
actual = fft.transform(x); s = 1.0;
} else {
s = 1.0 / FastMath.sqrt(n);
}
} else { } else {
expected = dft(xc, 1); expected = dft(xc, 1);
s = standard ? 1.0 / n : 1.0 / FastMath.sqrt(n); if (normalization == FastFourierTransformer.DftNormalization.STANDARD) {
actual = fft.inverseTransform(x); s = 1.0 / n;
} else {
s = 1.0 / FastMath.sqrt(n);
}
} }
final Complex[] actual = fft.transform(x, type);
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
final String msg = String.format("%d, %d", n, i); final String msg;
msg = String.format("%s, %s, %d, %d", normalization, type, n, i);
final double re = s * expected[i].getReal(); final double re = s * expected[i].getReal();
Assert.assertEquals(msg, re, actual[i].getReal(), Assert.assertEquals(msg, re, actual[i].getReal(),
tol * FastMath.abs(re)); tol * FastMath.abs(re));
@ -353,30 +293,33 @@ public final class FastFourierTransformerTest {
private static void doTestTransformFunction(final UnivariateFunction f, private static void doTestTransformFunction(final UnivariateFunction f,
final double min, final double max, int n, final double tol, final double min, final double max, int n, final double tol,
final boolean forward, final boolean standard) { final FastFourierTransformer.DftNormalization normalization,
final TransformType type) {
final FastFourierTransformer fft; final FastFourierTransformer fft;
if (standard) { fft = new FastFourierTransformer(normalization);
fft = new FastFourierTransformer(Normalization.STANDARD);
} else {
fft = new FastFourierTransformer(Normalization.UNITARY);
}
final Complex[] x = new Complex[n]; final Complex[] x = new Complex[n];
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
final double t = min + i * (max - min) / n; final double t = min + i * (max - min) / n;
x[i] = new Complex(f.value(t)); x[i] = new Complex(f.value(t));
} }
final Complex[] expected; final Complex[] expected;
final Complex[] actual;
final double s; final double s;
if (forward) { if (type == TransformType.FORWARD) {
expected = dft(x, -1); expected = dft(x, -1);
s = standard ? 1.0 : 1.0 / FastMath.sqrt(n); if (normalization == FastFourierTransformer.DftNormalization.STANDARD) {
actual = fft.transform(f, min, max, n); s = 1.0;
} else {
s = 1.0 / FastMath.sqrt(n);
}
} else { } else {
expected = dft(x, 1); expected = dft(x, 1);
s = standard ? 1.0 / n : 1.0 / FastMath.sqrt(n); if (normalization == FastFourierTransformer.DftNormalization.STANDARD) {
actual = fft.inverseTransform(f, min, max, n); s = 1.0 / n;
} else {
s = 1.0 / FastMath.sqrt(n);
}
} }
final Complex[] actual = fft.transform(f, min, max, n, type);
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
final String msg = String.format("%d, %d", n, i); final String msg = String.format("%d, %d", n, i);
final double re = s * expected[i].getReal(); final double re = s * expected[i].getReal();
@ -393,29 +336,41 @@ public final class FastFourierTransformerTest {
*/ */
@Test @Test
public void testStandardTransformComplex() { public void testTransformComplex() {
final boolean forward = true; final FastFourierTransformer.DftNormalization[] norm;
final boolean standard = true; norm = FastFourierTransformer.DftNormalization.values();
doTestTransformComplex(2, 1.0E-15, forward, standard); final TransformType[] type;
doTestTransformComplex(4, 1.0E-14, forward, standard); type = TransformType.values();
doTestTransformComplex(8, 1.0E-14, forward, standard); for (int i = 0; i < norm.length; i++) {
doTestTransformComplex(16, 1.0E-13, forward, standard); for (int j = 0; j < type.length; j++) {
doTestTransformComplex(32, 1.0E-13, forward, standard); doTestTransformComplex(2, 1.0E-15, norm[i], type[j]);
doTestTransformComplex(64, 1.0E-12, forward, standard); doTestTransformComplex(4, 1.0E-14, norm[i], type[j]);
doTestTransformComplex(128, 1.0E-12, forward, standard); doTestTransformComplex(8, 1.0E-14, norm[i], type[j]);
doTestTransformComplex(16, 1.0E-13, norm[i], type[j]);
doTestTransformComplex(32, 1.0E-13, norm[i], type[j]);
doTestTransformComplex(64, 1.0E-12, norm[i], type[j]);
doTestTransformComplex(128, 1.0E-12, norm[i], type[j]);
}
}
} }
@Test @Test
public void testStandardTransformReal() { public void testStandardTransformReal() {
final boolean forward = true; final FastFourierTransformer.DftNormalization[] norm;
final boolean standard = true; norm = FastFourierTransformer.DftNormalization.values();
doTestTransformReal(2, 1.0E-15, forward, standard); final TransformType[] type;
doTestTransformReal(4, 1.0E-14, forward, standard); type = TransformType.values();
doTestTransformReal(8, 1.0E-14, forward, standard); for (int i = 0; i < norm.length; i++) {
doTestTransformReal(16, 1.0E-13, forward, standard); for (int j = 0; j < type.length; j++) {
doTestTransformReal(32, 1.0E-13, forward, standard); doTestTransformReal(2, 1.0E-15, norm[i], type[j]);
doTestTransformReal(64, 1.0E-13, forward, standard); doTestTransformReal(4, 1.0E-14, norm[i], type[j]);
doTestTransformReal(128, 1.0E-11, forward, standard); doTestTransformReal(8, 1.0E-14, norm[i], type[j]);
doTestTransformReal(16, 1.0E-13, norm[i], type[j]);
doTestTransformReal(32, 1.0E-13, norm[i], type[j]);
doTestTransformReal(64, 1.0E-13, norm[i], type[j]);
doTestTransformReal(128, 1.0E-11, norm[i], type[j]);
}
}
} }
@Test @Test
@ -423,145 +378,21 @@ public final class FastFourierTransformerTest {
final UnivariateFunction f = new Sinc(); final UnivariateFunction f = new Sinc();
final double min = -FastMath.PI; final double min = -FastMath.PI;
final double max = FastMath.PI; final double max = FastMath.PI;
final boolean forward = true; final FastFourierTransformer.DftNormalization[] norm;
final boolean standard = true; norm = FastFourierTransformer.DftNormalization.values();
doTestTransformFunction(f, min, max, 2, 1.0E-15, forward, standard); final TransformType[] type;
doTestTransformFunction(f, min, max, 4, 1.0E-14, forward, standard); type = TransformType.values();
doTestTransformFunction(f, min, max, 8, 1.0E-14, forward, standard); for (int i = 0; i < norm.length; i++) {
doTestTransformFunction(f, min, max, 16, 1.0E-13, forward, standard); for (int j = 0; j < type.length; j++) {
doTestTransformFunction(f, min, max, 32, 1.0E-13, forward, standard); doTestTransformFunction(f, min, max, 2, 1.0E-15, norm[i], type[j]);
doTestTransformFunction(f, min, max, 64, 1.0E-12, forward, standard); doTestTransformFunction(f, min, max, 4, 1.0E-14, norm[i], type[j]);
doTestTransformFunction(f, min, max, 128, 1.0E-11, forward, standard); doTestTransformFunction(f, min, max, 8, 1.0E-14, norm[i], type[j]);
} doTestTransformFunction(f, min, max, 16, 1.0E-13, norm[i], type[j]);
doTestTransformFunction(f, min, max, 32, 1.0E-13, norm[i], type[j]);
@Test doTestTransformFunction(f, min, max, 64, 1.0E-12, norm[i], type[j]);
public void testStandardInverseTransformComplex() { doTestTransformFunction(f, min, max, 128, 1.0E-11, norm[i], type[j]);
final boolean forward = false; }
final boolean standard = true; }
doTestTransformComplex(2, 1.0E-15, forward, standard);
doTestTransformComplex(4, 1.0E-14, forward, standard);
doTestTransformComplex(8, 1.0E-14, forward, standard);
doTestTransformComplex(16, 1.0E-13, forward, standard);
doTestTransformComplex(32, 1.0E-13, forward, standard);
doTestTransformComplex(64, 1.0E-12, forward, standard);
doTestTransformComplex(128, 1.0E-12, forward, standard);
}
@Test
public void testStandardInverseTransformReal() {
final boolean forward = false;
final boolean standard = true;
doTestTransformReal(2, 1.0E-15, forward, standard);
doTestTransformReal(4, 1.0E-14, forward, standard);
doTestTransformReal(8, 1.0E-14, forward, standard);
doTestTransformReal(16, 1.0E-13, forward, standard);
doTestTransformReal(32, 1.0E-13, forward, standard);
doTestTransformReal(64, 1.0E-12, forward, standard);
doTestTransformReal(128, 1.0E-11, forward, standard);
}
@Test
public void testStandardInverseTransformFunction() {
final UnivariateFunction f = new Sinc();
final double min = -FastMath.PI;
final double max = FastMath.PI;
final boolean forward = false;
final boolean standard = true;
doTestTransformFunction(f, min, max, 2, 1.0E-15, forward, standard);
doTestTransformFunction(f, min, max, 4, 1.0E-14, forward, standard);
doTestTransformFunction(f, min, max, 8, 1.0E-14, forward, standard);
doTestTransformFunction(f, min, max, 16, 1.0E-13, forward, standard);
doTestTransformFunction(f, min, max, 32, 1.0E-13, forward, standard);
doTestTransformFunction(f, min, max, 64, 1.0E-12, forward, standard);
doTestTransformFunction(f, min, max, 128, 1.0E-11, forward, standard);
}
/*
* Tests of unitary transform (when data is valid).
*/
@Test
public void testUnitaryTransformComplex() {
final boolean forward = true;
final boolean standard = false;
doTestTransformComplex(2, 1.0E-15, forward, standard);
doTestTransformComplex(4, 1.0E-14, forward, standard);
doTestTransformComplex(8, 1.0E-14, forward, standard);
doTestTransformComplex(16, 1.0E-13, forward, standard);
doTestTransformComplex(32, 1.0E-13, forward, standard);
doTestTransformComplex(64, 1.0E-12, forward, standard);
doTestTransformComplex(128, 1.0E-12, forward, standard);
}
@Test
public void testUnitaryTransformReal() {
final boolean forward = true;
final boolean standard = false;
doTestTransformReal(2, 1.0E-15, forward, standard);
doTestTransformReal(4, 1.0E-14, forward, standard);
doTestTransformReal(8, 1.0E-14, forward, standard);
doTestTransformReal(16, 1.0E-13, forward, standard);
doTestTransformReal(32, 1.0E-13, forward, standard);
doTestTransformReal(64, 1.0E-13, forward, standard);
doTestTransformReal(128, 1.0E-11, forward, standard);
}
@Test
public void testUnitaryTransformFunction() {
final UnivariateFunction f = new Sinc();
final double min = -FastMath.PI;
final double max = FastMath.PI;
final boolean forward = true;
final boolean standard = false;
doTestTransformFunction(f, min, max, 2, 1.0E-15, forward, standard);
doTestTransformFunction(f, min, max, 4, 1.0E-14, forward, standard);
doTestTransformFunction(f, min, max, 8, 1.0E-14, forward, standard);
doTestTransformFunction(f, min, max, 16, 1.0E-13, forward, standard);
doTestTransformFunction(f, min, max, 32, 1.0E-13, forward, standard);
doTestTransformFunction(f, min, max, 64, 1.0E-12, forward, standard);
doTestTransformFunction(f, min, max, 128, 1.0E-11, forward, standard);
}
@Test
public void testUnitaryInverseTransformComplex() {
final boolean forward = false;
final boolean standard = false;
doTestTransformComplex(2, 1.0E-14, forward, standard);
doTestTransformComplex(4, 1.0E-14, forward, standard);
doTestTransformComplex(8, 1.0E-14, forward, standard);
doTestTransformComplex(16, 1.0E-13, forward, standard);
doTestTransformComplex(32, 1.0E-13, forward, standard);
doTestTransformComplex(64, 1.0E-12, forward, standard);
doTestTransformComplex(128, 1.0E-12, forward, standard);
}
@Test
public void testUnitaryInverseTransformReal() {
final boolean forward = false;
final boolean standard = false;
doTestTransformReal(2, 1.0E-15, forward, standard);
doTestTransformReal(4, 1.0E-14, forward, standard);
doTestTransformReal(8, 1.0E-14, forward, standard);
doTestTransformReal(16, 1.0E-13, forward, standard);
doTestTransformReal(32, 1.0E-13, forward, standard);
doTestTransformReal(64, 1.0E-12, forward, standard);
doTestTransformReal(128, 1.0E-11, forward, standard);
}
@Test
public void testUnitaryInverseTransformFunction() {
final UnivariateFunction f = new Sinc();
final double min = -FastMath.PI;
final double max = FastMath.PI;
final boolean forward = false;
final boolean standard = false;
doTestTransformFunction(f, min, max, 2, 1.0E-15, forward, standard);
doTestTransformFunction(f, min, max, 4, 1.0E-14, forward, standard);
doTestTransformFunction(f, min, max, 8, 1.0E-14, forward, standard);
doTestTransformFunction(f, min, max, 16, 1.0E-13, forward, standard);
doTestTransformFunction(f, min, max, 32, 1.0E-13, forward, standard);
doTestTransformFunction(f, min, max, 64, 1.0E-12, forward, standard);
doTestTransformFunction(f, min, max, 128, 1.0E-11, forward, standard);
} }
/* /*
@ -574,7 +405,7 @@ public final class FastFourierTransformerTest {
@Test @Test
public void testAdHocData() { public void testAdHocData() {
FastFourierTransformer transformer; FastFourierTransformer transformer;
transformer = new FastFourierTransformer(Normalization.STANDARD); transformer = new FastFourierTransformer(DftNormalization.STANDARD);
Complex result[]; double tolerance = 1E-12; Complex result[]; double tolerance = 1E-12;
double x[] = {1.3, 2.4, 1.7, 4.1, 2.9, 1.7, 5.1, 2.7}; double x[] = {1.3, 2.4, 1.7, 4.1, 2.9, 1.7, 5.1, 2.7};
@ -588,13 +419,13 @@ public final class FastFourierTransformerTest {
new Complex(-2.6, -2.7), new Complex(-2.6, -2.7),
new Complex(-2.09497474683058, -1.91507575950825)}; new Complex(-2.09497474683058, -1.91507575950825)};
result = transformer.transform(x); result = transformer.transform(x, TransformType.FORWARD);
for (int i = 0; i < result.length; i++) { for (int i = 0; i < result.length; i++) {
Assert.assertEquals(y[i].getReal(), result[i].getReal(), tolerance); Assert.assertEquals(y[i].getReal(), result[i].getReal(), tolerance);
Assert.assertEquals(y[i].getImaginary(), result[i].getImaginary(), tolerance); Assert.assertEquals(y[i].getImaginary(), result[i].getImaginary(), tolerance);
} }
result = transformer.inverseTransform(y); result = transformer.transform(y, TransformType.INVERSE);
for (int i = 0; i < result.length; i++) { for (int i = 0; i < result.length; i++) {
Assert.assertEquals(x[i], result[i].getReal(), tolerance); Assert.assertEquals(x[i], result[i].getReal(), tolerance);
Assert.assertEquals(0.0, result[i].getImaginary(), tolerance); Assert.assertEquals(0.0, result[i].getImaginary(), tolerance);
@ -604,14 +435,14 @@ public final class FastFourierTransformerTest {
TransformUtils.scaleArray(x2, 1.0 / FastMath.sqrt(x2.length)); TransformUtils.scaleArray(x2, 1.0 / FastMath.sqrt(x2.length));
Complex y2[] = y; Complex y2[] = y;
transformer = new FastFourierTransformer(Normalization.UNITARY); transformer = new FastFourierTransformer(DftNormalization.UNITARY);
result = transformer.transform(y2); result = transformer.transform(y2, TransformType.FORWARD);
for (int i = 0; i < result.length; i++) { for (int i = 0; i < result.length; i++) {
Assert.assertEquals(x2[i], result[i].getReal(), tolerance); Assert.assertEquals(x2[i], result[i].getReal(), tolerance);
Assert.assertEquals(0.0, result[i].getImaginary(), tolerance); Assert.assertEquals(0.0, result[i].getImaginary(), tolerance);
} }
result = transformer.inverseTransform(x2); result = transformer.transform(x2, TransformType.INVERSE);
for (int i = 0; i < result.length; i++) { for (int i = 0; i < result.length; i++) {
Assert.assertEquals(y2[i].getReal(), result[i].getReal(), tolerance); Assert.assertEquals(y2[i].getReal(), result[i].getReal(), tolerance);
Assert.assertEquals(y2[i].getImaginary(), result[i].getImaginary(), tolerance); Assert.assertEquals(y2[i].getImaginary(), result[i].getImaginary(), tolerance);
@ -625,12 +456,12 @@ public final class FastFourierTransformerTest {
public void testSinFunction() { public void testSinFunction() {
UnivariateFunction f = new SinFunction(); UnivariateFunction f = new SinFunction();
FastFourierTransformer transformer; FastFourierTransformer transformer;
transformer = new FastFourierTransformer(Normalization.STANDARD); transformer = new FastFourierTransformer(DftNormalization.STANDARD);
Complex result[]; int N = 1 << 8; Complex result[]; int N = 1 << 8;
double min, max, tolerance = 1E-12; double min, max, tolerance = 1E-12;
min = 0.0; max = 2.0 * FastMath.PI; min = 0.0; max = 2.0 * FastMath.PI;
result = transformer.transform(f, min, max, N); result = transformer.transform(f, min, max, N, TransformType.FORWARD);
Assert.assertEquals(0.0, result[1].getReal(), tolerance); Assert.assertEquals(0.0, result[1].getReal(), tolerance);
Assert.assertEquals(-(N >> 1), result[1].getImaginary(), tolerance); Assert.assertEquals(-(N >> 1), result[1].getImaginary(), tolerance);
Assert.assertEquals(0.0, result[N-1].getReal(), tolerance); Assert.assertEquals(0.0, result[N-1].getReal(), tolerance);
@ -641,7 +472,7 @@ public final class FastFourierTransformerTest {
} }
min = -FastMath.PI; max = FastMath.PI; min = -FastMath.PI; max = FastMath.PI;
result = transformer.inverseTransform(f, min, max, N); result = transformer.transform(f, min, max, N, TransformType.INVERSE);
Assert.assertEquals(0.0, result[1].getReal(), tolerance); Assert.assertEquals(0.0, result[1].getReal(), tolerance);
Assert.assertEquals(-0.5, result[1].getImaginary(), tolerance); Assert.assertEquals(-0.5, result[1].getImaginary(), tolerance);
Assert.assertEquals(0.0, result[N-1].getReal(), tolerance); Assert.assertEquals(0.0, result[N-1].getReal(), tolerance);
@ -659,7 +490,7 @@ public final class FastFourierTransformerTest {
@Test @Test
public void test2DData() { public void test2DData() {
FastFourierTransformer transformer; FastFourierTransformer transformer;
transformer = new FastFourierTransformer(Normalization.STANDARD); transformer = new FastFourierTransformer(DftNormalization.STANDARD);
double tolerance = 1E-12; double tolerance = 1E-12;
Complex[][] input = new Complex[][] {new Complex[] {new Complex(1, 0), Complex[][] input = new Complex[][] {new Complex[] {new Complex(1, 0),
@ -675,8 +506,8 @@ public final class FastFourierTransformerTest {
FastMath.sqrt(goodOutput[i].length) * FastMath.sqrt(goodOutput[i].length) *
FastMath.sqrt(goodOutput.length)); FastMath.sqrt(goodOutput.length));
} }
Complex[][] output = (Complex[][])transformer.mdfft(input, true); Complex[][] output = (Complex[][])transformer.mdfft(input, TransformType.FORWARD);
Complex[][] output2 = (Complex[][])transformer.mdfft(output, false); Complex[][] output2 = (Complex[][])transformer.mdfft(output, TransformType.INVERSE);
Assert.assertEquals(input.length, output.length); Assert.assertEquals(input.length, output.length);
Assert.assertEquals(input.length, output2.length); Assert.assertEquals(input.length, output2.length);
@ -687,6 +518,8 @@ public final class FastFourierTransformerTest {
for (int i = 0; i < input.length; i++) { for (int i = 0; i < input.length; i++) {
for (int j = 0; j < input[0].length; j++) { for (int j = 0; j < input[0].length; j++) {
System.out.println(i + ", " + j + ", " + input[i][j] + ", " +
goodOutput[i][j] + ", " + output[i][j] + ", ");
Assert.assertEquals(input[i][j].getImaginary(), output2[i][j].getImaginary(), Assert.assertEquals(input[i][j].getImaginary(), output2[i][j].getImaginary(),
tolerance); tolerance);
Assert.assertEquals(input[i][j].getReal(), output2[i][j].getReal(), tolerance); Assert.assertEquals(input[i][j].getReal(), output2[i][j].getReal(), tolerance);
@ -700,7 +533,7 @@ public final class FastFourierTransformerTest {
@Test @Test
public void test2DDataUnitary() { public void test2DDataUnitary() {
FastFourierTransformer transformer; FastFourierTransformer transformer;
transformer = new FastFourierTransformer(Normalization.UNITARY); transformer = new FastFourierTransformer(DftNormalization.UNITARY);
double tolerance = 1E-12; double tolerance = 1E-12;
Complex[][] input = new Complex[][] {new Complex[] {new Complex(1, 0), Complex[][] input = new Complex[][] {new Complex[] {new Complex(1, 0),
new Complex(2, 0)}, new Complex(2, 0)},
@ -709,8 +542,8 @@ public final class FastFourierTransformerTest {
Complex[][] goodOutput = new Complex[][] {new Complex[] {new Complex(5, Complex[][] goodOutput = new Complex[][] {new Complex[] {new Complex(5,
1.5), new Complex(-1, -.5)}, new Complex[] {new Complex(-2, 1.5), new Complex(-1, -.5)}, new Complex[] {new Complex(-2,
-1.5), new Complex(0, .5)}}; -1.5), new Complex(0, .5)}};
Complex[][] output = (Complex[][])transformer.mdfft(input, true); Complex[][] output = (Complex[][])transformer.mdfft(input, TransformType.FORWARD);
Complex[][] output2 = (Complex[][])transformer.mdfft(output, false); Complex[][] output2 = (Complex[][])transformer.mdfft(output, TransformType.INVERSE);
Assert.assertEquals(input.length, output.length); Assert.assertEquals(input.length, output.length);
Assert.assertEquals(input.length, output2.length); Assert.assertEquals(input.length, output2.length);