Added a RealTransformer interface on top of cosine, sine and Hadamard transforms.

The Fourier transform cannot implement this interface since it produces complex results.
Improved error messages.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@729758 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luc Maisonobe 2008-12-28 18:09:28 +00:00
parent f8cc8e9d37
commit dff725b2e8
6 changed files with 303 additions and 207 deletions

View File

@ -343,6 +343,26 @@ public class MessagesResources_fr
{ "{0} is not a power of 2",
"{0} n''est pas une puissance de 2" },
// org.apache.commons.math.transform.FastFourierTransformer
{ "cannot compute 0-th root of unity, indefinite result",
"impossible de calculer la racine z\u00e9roi\u00e8me de l''unit\u00e9, r\u00e9sultat ind\u00e9fini" },
{ "number of sample is not positive: {0}",
"le nombre d''\u00e9chantillons n''est pas positif : {0}" },
{ "{0} is not a power of 2, consider padding for fix",
"{0} n''est pas une puissance de 2, ajoutez des \u00e9l\u00e9ments pour corriger" },
{ "endpoints do not specify an interval: [{0}, {1}]",
"les extr\u00e9mit\u00e9s ne constituent pas un intervalle : [{0}, {1}]" },
{ "some dimensions don't math: {0} != {1}",
"certaines dimensions sont incoh\u00e9rentes : {0} != {1}" },
// org.apache.commons.math.transform.FastCosineTransformer
{ "{0} is not a power of 2 plus one",
"{0} n''est pas une puissance de 2 plus un" },
// org.apache.commons.math.transform.FastSineTransformer
{ "first element is not 0: {0}",
"le premier \u00e9l\u00e9ment n''est pas nul : {0}" },
// org.apache.commons.math.util.OpenIntToDoubleHashMap
{ "map has been modified while iterating",
"la table d''adressage a \u00e9t\u00e9 modifi\u00e9e pendant l''it\u00e9ration" },

View File

@ -16,10 +16,10 @@
*/
package org.apache.commons.math.transform;
import java.io.Serializable;
import org.apache.commons.math.analysis.*;
import org.apache.commons.math.complex.*;
import org.apache.commons.math.MathException;
import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.MathRuntimeException;
import org.apache.commons.math.analysis.UnivariateRealFunction;
import org.apache.commons.math.complex.Complex;
/**
* Implements the <a href="http://documents.wolfram.com/v5/Add-onsLinks/
@ -37,10 +37,10 @@ import org.apache.commons.math.MathException;
* @version $Revision:670469 $ $Date:2008-06-23 10:01:38 +0200 (lun., 23 juin 2008) $
* @since 1.2
*/
public class FastCosineTransformer implements Serializable {
public class FastCosineTransformer implements RealTransformer {
/** serializable version identifier */
static final long serialVersionUID = -7673941545134707766L;
private static final long serialVersionUID = -831323620109865380L;
/**
* Construct a default transformer.
@ -52,26 +52,23 @@ public class FastCosineTransformer implements Serializable {
/**
* Transform the given real data set.
* <p>
* The formula is $ F_n = (1/2) [f_0 + (-1)^n f_N] +
* \Sigma_{k=1}^{N-1} f_k \cos(\pi nk/N) $
* The formula is F<sub>n</sub> = (1/2) [f<sub>0</sub> + (-1)<sup>n</sup> f<sub>N</sub>] +
* &sum;<sub>k=1</sub><sup>N-1</sup> f<sub>k</sub> cos(&pi; nk/N)
* </p>
*
* @param f the real data array to be transformed
* @return the real transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
public double[] transform(double f[]) throws MathException,
IllegalArgumentException {
public double[] transform(double f[]) throws IllegalArgumentException {
return fct(f);
}
/**
* Transform the given real function, sampled on the given interval.
* <p>
* The formula is $ F_n = (1/2) [f_0 + (-1)^n f_N] +
* \Sigma_{k=1}^{N-1} f_k \cos(\pi nk/N) $
* The formula is F<sub>n</sub> = (1/2) [f<sub>0</sub> + (-1)<sup>n</sup> f<sub>N</sub>] +
* &sum;<sub>k=1</sub><sup>N-1</sup> f<sub>k</sub> cos(&pi; nk/N)
* </p>
*
* @param f the function to be sampled and transformed
@ -79,13 +76,13 @@ public class FastCosineTransformer implements Serializable {
* @param max the upper bound for the interval
* @param n the number of sample points
* @return the real transformed array
* @throws MathException if any math-related errors occur
* @throws FunctionEvaluationException if function cannot be evaluated
* at some point
* @throws IllegalArgumentException if any parameters are invalid
*/
public double[] transform(
UnivariateRealFunction f, double min, double max, int n)
throws MathException, IllegalArgumentException {
public double[] transform(UnivariateRealFunction f,
double min, double max, int n)
throws FunctionEvaluationException, IllegalArgumentException {
double data[] = FastFourierTransformer.sample(f, min, max, n);
return fct(data);
}
@ -93,17 +90,15 @@ public class FastCosineTransformer implements Serializable {
/**
* Transform the given real data set.
* <p>
* The formula is $ F_n = \sqrt{1/2N} [f_0 + (-1)^n f_N] +
* \sqrt{2/N} \Sigma_{k=1}^{N-1} f_k \cos(\pi nk/N) $
* The formula is F<sub>n</sub> = \sqrt{1/2N} [f<sub>0</sub> + (-1)<sup>n</sup> f<sub>N</sub>] +
* &radic;(2/N) &sum;<sub>k=1</sub><sup>N-1</sup> f<sub>k</sub> cos(&pi; nk/N)
* </p>
*
* @param f the real data array to be transformed
* @return the real transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
public double[] transform2(double f[]) throws MathException,
IllegalArgumentException {
public double[] transform2(double f[]) throws IllegalArgumentException {
double scaling_coefficient = Math.sqrt(2.0 / (f.length-1));
return FastFourierTransformer.scaleArray(fct(f), scaling_coefficient);
@ -112,8 +107,8 @@ public class FastCosineTransformer implements Serializable {
/**
* Transform the given real function, sampled on the given interval.
* <p>
* The formula is $ F_n = \sqrt{1/2N} [f_0 + (-1)^n f_N] +
* \sqrt{2/N} \Sigma_{k=1}^{N-1} f_k \cos(\pi nk/N) $
* The formula is F<sub>n</sub> = \sqrt{1/2N} [f<sub>0</sub> + (-1)<sup>n</sup> f<sub>N</sub>] +
* &radic;(2/N) &sum;<sub>k=1</sub><sup>N-1</sup> f<sub>k</sub> cos(&pi; nk/N)
*
* </p>
*
@ -122,12 +117,13 @@ public class FastCosineTransformer implements Serializable {
* @param max the upper bound for the interval
* @param n the number of sample points
* @return the real transformed array
* @throws MathException if any math-related errors occur
* @throws FunctionEvaluationException if function cannot be evaluated
* at some point
* @throws IllegalArgumentException if any parameters are invalid
*/
public double[] transform2(
UnivariateRealFunction f, double min, double max, int n)
throws MathException, IllegalArgumentException {
public double[] transform2(UnivariateRealFunction f,
double min, double max, int n)
throws FunctionEvaluationException, IllegalArgumentException {
double data[] = FastFourierTransformer.sample(f, min, max, n);
double scaling_coefficient = Math.sqrt(2.0 / (n-1));
@ -137,17 +133,15 @@ public class FastCosineTransformer implements Serializable {
/**
* Inversely transform the given real data set.
* <p>
* The formula is $ f_k = (1/N) [F_0 + (-1)^k F_N] +
* (2/N) \Sigma_{n=1}^{N-1} F_n \cos(\pi nk/N) $
* The formula is f<sub>k</sub> = (1/N) [F<sub>0</sub> + (-1)<sup>k</sup> F<sub>N</sub>] +
* (2/N) &sum;<sub>n=1</sub><sup>N-1</sup> F<sub>n</sub> cos(&pi; nk/N)
* </p>
*
* @param f the real data array to be inversely transformed
* @return the real inversely transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
public double[] inversetransform(double f[]) throws MathException,
IllegalArgumentException {
public double[] inversetransform(double f[]) throws IllegalArgumentException {
double scaling_coefficient = 2.0 / (f.length - 1);
return FastFourierTransformer.scaleArray(fct(f), scaling_coefficient);
@ -156,8 +150,8 @@ public class FastCosineTransformer implements Serializable {
/**
* Inversely transform the given real function, sampled on the given interval.
* <p>
* The formula is $ f_k = (1/N) [F_0 + (-1)^k F_N] +
* (2/N) \Sigma_{n=1}^{N-1} F_n \cos(\pi nk/N) $
* The formula is f<sub>k</sub> = (1/N) [F<sub>0</sub> + (-1)<sup>k</sup> F<sub>N</sub>] +
* (2/N) &sum;<sub>n=1</sub><sup>N-1</sup> F<sub>n</sub> cos(&pi; nk/N)
* </p>
*
* @param f the function to be sampled and inversely transformed
@ -165,12 +159,13 @@ public class FastCosineTransformer implements Serializable {
* @param max the upper bound for the interval
* @param n the number of sample points
* @return the real inversely transformed array
* @throws MathException if any math-related errors occur
* @throws FunctionEvaluationException if function cannot be evaluated
* at some point
* @throws IllegalArgumentException if any parameters are invalid
*/
public double[] inversetransform(
UnivariateRealFunction f, double min, double max, int n)
throws MathException, IllegalArgumentException {
public double[] inversetransform(UnivariateRealFunction f,
double min, double max, int n)
throws FunctionEvaluationException, IllegalArgumentException {
double data[] = FastFourierTransformer.sample(f, min, max, n);
double scaling_coefficient = 2.0 / (n - 1);
@ -180,26 +175,23 @@ public class FastCosineTransformer implements Serializable {
/**
* Inversely transform the given real data set.
* <p>
* The formula is $ f_k = \sqrt{1/2N} [F_0 + (-1)^k F_N] +
* \sqrt{2/N} \Sigma_{n=1}^{N-1} F_n \cos(\pi nk/N) $
* The formula is f<sub>k</sub> = &radic;(1/2N) [F<sub>0</sub> + (-1)<sup>k</sup> F<sub>N</sub>] +
* &radic;(2/N) &sum;<sub>n=1</sub><sup>N-1</sup> F<sub>n</sub> cos(&pi; nk/N)
* </p>
*
* @param f the real data array to be inversely transformed
* @return the real inversely transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
public double[] inversetransform2(double f[]) throws MathException,
IllegalArgumentException {
public double[] inversetransform2(double f[]) throws IllegalArgumentException {
return transform2(f);
}
/**
* Inversely transform the given real function, sampled on the given interval.
* <p>
* The formula is $ f_k = \sqrt{1/2N} [F_0 + (-1)^k F_N] +
* \sqrt{2/N} \Sigma_{n=1}^{N-1} F_n \cos(\pi nk/N) $
* The formula is f<sub>k</sub> = &radic;(1/2N) [F<sub>0</sub> + (-1)<sup>k</sup> F<sub>N</sub>] +
* &radic;(2/N) &sum;<sub>n=1</sub><sup>N-1</sup> F<sub>n</sub> cos(&pi; nk/N)
* </p>
*
* @param f the function to be sampled and inversely transformed
@ -207,12 +199,13 @@ public class FastCosineTransformer implements Serializable {
* @param max the upper bound for the interval
* @param n the number of sample points
* @return the real inversely transformed array
* @throws MathException if any math-related errors occur
* @throws FunctionEvaluationException if function cannot be evaluated
* at some point
* @throws IllegalArgumentException if any parameters are invalid
*/
public double[] inversetransform2(
UnivariateRealFunction f, double min, double max, int n)
throws MathException, IllegalArgumentException {
public double[] inversetransform2(UnivariateRealFunction f,
double min, double max, int n)
throws FunctionEvaluationException, IllegalArgumentException {
return transform2(f, min, max, n);
}
@ -222,18 +215,17 @@ public class FastCosineTransformer implements Serializable {
*
* @param f the real data array to be transformed
* @return the real transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
protected double[] fct(double f[]) throws MathException,
IllegalArgumentException {
protected double[] fct(double f[])
throws IllegalArgumentException {
double A, B, C, F1, x[], F[] = new double[f.length];
int N = f.length - 1;
if (!FastFourierTransformer.isPowerOf2(N)) {
throw new IllegalArgumentException
("Number of samples not power of 2 plus one: " + f.length);
throw MathRuntimeException.createIllegalArgumentException("{0} is not a power of 2 plus one",
new Object[] { f.length });
}
if (N == 1) { // trivial case
F[0] = 0.5 * (f[0] + f[1]);

View File

@ -19,7 +19,8 @@ package org.apache.commons.math.transform;
import java.io.Serializable;
import java.lang.reflect.Array;
import org.apache.commons.math.MathException;
import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.MathRuntimeException;
import org.apache.commons.math.analysis.UnivariateRealFunction;
import org.apache.commons.math.complex.Complex;
@ -71,12 +72,10 @@ public class FastFourierTransformer implements Serializable {
*
* @param f the real data array to be transformed
* @return the complex transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
public Complex[] transform(double f[]) throws MathException,
IllegalArgumentException {
public Complex[] transform(double f[])
throws IllegalArgumentException {
return fft(f, false);
}
@ -91,13 +90,13 @@ public class FastFourierTransformer implements Serializable {
* @param max the upper bound for the interval
* @param n the number of sample points
* @return the complex transformed array
* @throws MathException if any math-related errors occur
* @throws FunctionEvaluationException if function cannot be evaluated
* at some point
* @throws IllegalArgumentException if any parameters are invalid
*/
public Complex[] transform(
UnivariateRealFunction f, double min, double max, int n)
throws MathException, IllegalArgumentException {
public Complex[] transform(UnivariateRealFunction f,
double min, double max, int n)
throws FunctionEvaluationException, IllegalArgumentException {
double data[] = sample(f, min, max, n);
return fft(data, false);
}
@ -110,12 +109,10 @@ public class FastFourierTransformer implements Serializable {
*
* @param f the complex data array to be transformed
* @return the complex transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
public Complex[] transform(Complex f[]) throws MathException,
IllegalArgumentException {
public Complex[] transform(Complex f[])
throws IllegalArgumentException {
computeOmega(f.length);
return fft(f);
}
@ -128,11 +125,10 @@ public class FastFourierTransformer implements Serializable {
*
* @param f the real data array to be transformed
* @return the complex transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
public Complex[] transform2(double f[]) throws MathException,
IllegalArgumentException {
public Complex[] transform2(double f[])
throws IllegalArgumentException {
double scaling_coefficient = 1.0 / Math.sqrt(f.length);
return scaleArray(fft(f, false), scaling_coefficient);
@ -149,12 +145,13 @@ public class FastFourierTransformer implements Serializable {
* @param max the upper bound for the interval
* @param n the number of sample points
* @return the complex transformed array
* @throws MathException if any math-related errors occur
* @throws FunctionEvaluationException if function cannot be evaluated
* at some point
* @throws IllegalArgumentException if any parameters are invalid
*/
public Complex[] transform2(
UnivariateRealFunction f, double min, double max, int n)
throws MathException, IllegalArgumentException {
public Complex[] transform2(UnivariateRealFunction f,
double min, double max, int n)
throws FunctionEvaluationException, IllegalArgumentException {
double data[] = sample(f, min, max, n);
double scaling_coefficient = 1.0 / Math.sqrt(n);
@ -169,11 +166,10 @@ public class FastFourierTransformer implements Serializable {
*
* @param f the complex data array to be transformed
* @return the complex transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
public Complex[] transform2(Complex f[]) throws MathException,
IllegalArgumentException {
public Complex[] transform2(Complex f[])
throws IllegalArgumentException {
computeOmega(f.length);
double scaling_coefficient = 1.0 / Math.sqrt(f.length);
@ -188,11 +184,10 @@ public class FastFourierTransformer implements Serializable {
*
* @param f the real data array to be inversely transformed
* @return the complex inversely transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
public Complex[] inversetransform(double f[]) throws MathException,
IllegalArgumentException {
public Complex[] inversetransform(double f[])
throws IllegalArgumentException {
double scaling_coefficient = 1.0 / f.length;
return scaleArray(fft(f, true), scaling_coefficient);
@ -209,12 +204,13 @@ public class FastFourierTransformer implements Serializable {
* @param max the upper bound for the interval
* @param n the number of sample points
* @return the complex inversely transformed array
* @throws MathException if any math-related errors occur
* @throws FunctionEvaluationException if function cannot be evaluated
* at some point
* @throws IllegalArgumentException if any parameters are invalid
*/
public Complex[] inversetransform(
UnivariateRealFunction f, double min, double max, int n)
throws MathException, IllegalArgumentException {
public Complex[] inversetransform(UnivariateRealFunction f,
double min, double max, int n)
throws FunctionEvaluationException, IllegalArgumentException {
double data[] = sample(f, min, max, n);
double scaling_coefficient = 1.0 / n;
@ -229,11 +225,10 @@ public class FastFourierTransformer implements Serializable {
*
* @param f the complex data array to be inversely transformed
* @return the complex inversely transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
public Complex[] inversetransform(Complex f[]) throws MathException,
IllegalArgumentException {
public Complex[] inversetransform(Complex f[])
throws IllegalArgumentException {
computeOmega(-f.length); // pass negative argument
double scaling_coefficient = 1.0 / f.length;
@ -248,11 +243,10 @@ public class FastFourierTransformer implements Serializable {
*
* @param f the real data array to be inversely transformed
* @return the complex inversely transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
public Complex[] inversetransform2(double f[]) throws MathException,
IllegalArgumentException {
public Complex[] inversetransform2(double f[])
throws IllegalArgumentException {
double scaling_coefficient = 1.0 / Math.sqrt(f.length);
return scaleArray(fft(f, true), scaling_coefficient);
@ -269,12 +263,13 @@ public class FastFourierTransformer implements Serializable {
* @param max the upper bound for the interval
* @param n the number of sample points
* @return the complex inversely transformed array
* @throws MathException if any math-related errors occur
* @throws FunctionEvaluationException if function cannot be evaluated
* at some point
* @throws IllegalArgumentException if any parameters are invalid
*/
public Complex[] inversetransform2(
UnivariateRealFunction f, double min, double max, int n)
throws MathException, IllegalArgumentException {
public Complex[] inversetransform2(UnivariateRealFunction f,
double min, double max, int n)
throws FunctionEvaluationException, IllegalArgumentException {
double data[] = sample(f, min, max, n);
double scaling_coefficient = 1.0 / Math.sqrt(n);
@ -289,11 +284,10 @@ public class FastFourierTransformer implements Serializable {
*
* @param f the complex data array to be inversely transformed
* @return the complex inversely transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
public Complex[] inversetransform2(Complex f[]) throws MathException,
IllegalArgumentException {
public Complex[] inversetransform2(Complex f[])
throws IllegalArgumentException {
computeOmega(-f.length); // pass negative argument
double scaling_coefficient = 1.0 / Math.sqrt(f.length);
@ -306,11 +300,10 @@ public class FastFourierTransformer implements Serializable {
* @param f the real data array to be transformed
* @param isInverse the indicator of forward or inverse transform
* @return the complex transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
protected Complex[] fft(double f[], boolean isInverse) throws
MathException, IllegalArgumentException {
protected Complex[] fft(double f[], boolean isInverse)
throws IllegalArgumentException {
verifyDataSet(f);
Complex F[] = new Complex[f.length];
@ -350,11 +343,10 @@ public class FastFourierTransformer implements Serializable {
*
* @param data the complex data array to be transformed
* @return the complex transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
protected Complex[] fft(Complex data[]) throws MathException,
IllegalArgumentException {
protected Complex[] fft(Complex data[])
throws IllegalArgumentException {
int i, j, k, m, N = data.length;
Complex A, B, C, D, E, F, z, f[] = new Complex[N];
@ -421,10 +413,11 @@ public class FastFourierTransformer implements Serializable {
* @param n the integer passed in
* @throws IllegalArgumentException if n = 0
*/
protected void computeOmega(int n) throws IllegalArgumentException {
protected void computeOmega(int n)
throws IllegalArgumentException {
if (n == 0) {
throw new IllegalArgumentException
("Cannot compute 0-th root of unity, indefinite result.");
throw MathRuntimeException.createIllegalArgumentException("cannot compute 0-th root of unity, indefinite result",
null);
}
// avoid repetitive calculations
if (n == omegaCount) { return; }
@ -462,15 +455,17 @@ public class FastFourierTransformer implements Serializable {
* @param max the upper bound for the interval
* @param n the number of sample points
* @return the samples array
* @throws MathException if any math-related errors occur
* @throws FunctionEvaluationException if function cannot be evaluated
* at some point
* @throws IllegalArgumentException if any parameters are invalid
*/
public static double[] sample(
UnivariateRealFunction f, double min, double max, int n)
throws MathException, IllegalArgumentException {
public static double[] sample(UnivariateRealFunction f,
double min, double max, int n)
throws FunctionEvaluationException, IllegalArgumentException {
if (n <= 0) {
throw new IllegalArgumentException("Number of samples not positive.");
throw MathRuntimeException.createIllegalArgumentException("number of sample is not positive: {0}",
new Object[] { n });
}
verifyInterval(min, max);
@ -530,8 +525,8 @@ public class FastFourierTransformer implements Serializable {
*/
public static void verifyDataSet(double d[]) throws IllegalArgumentException {
if (!isPowerOf2(d.length)) {
throw new IllegalArgumentException
("Number of samples not power of 2, consider padding for fix.");
throw MathRuntimeException.createIllegalArgumentException("{0} is not a power of 2, consider padding for fix",
new Object[] { d.length });
}
}
@ -543,8 +538,8 @@ public class FastFourierTransformer implements Serializable {
*/
public static void verifyDataSet(Object o[]) throws IllegalArgumentException {
if (!isPowerOf2(o.length)) {
throw new IllegalArgumentException
("Number of samples not power of 2, consider padding for fix.");
throw MathRuntimeException.createIllegalArgumentException("{0} is not a power of 2, consider padding for fix",
new Object[] { o.length });
}
}
@ -555,13 +550,12 @@ public class FastFourierTransformer implements Serializable {
* @param upper upper endpoint
* @throws IllegalArgumentException if not interval
*/
public static void verifyInterval(double lower, double upper) throws
IllegalArgumentException {
public static void verifyInterval(double lower, double upper)
throws IllegalArgumentException {
if (lower >= upper) {
throw new IllegalArgumentException
("Endpoints do not specify an interval: [" + lower +
", " + upper + "]");
throw MathRuntimeException.createIllegalArgumentException("endpoints do not specify an interval: [{0}, {1}]",
new Object[] { lower, upper });
}
}
@ -577,9 +571,10 @@ public class FastFourierTransformer implements Serializable {
* @param mdca Multi-Dimensional Complex Array id est Complex[][][][]
* @param forward inverseTransform2 is preformed if this is false
* @return transform of mdca as a Multi-Dimensional Complex Array id est Complex[][][][]
* @throws MathException if any dimension is not a power of two
* @throws IllegalArgumentException if any dimension is not a power of two
*/
public Object mdfft(Object mdca, boolean forward) throws MathException {
public Object mdfft(Object mdca, boolean forward)
throws IllegalArgumentException {
MultiDimensionalComplexMatrix mdcm = (MultiDimensionalComplexMatrix)
new MultiDimensionalComplexMatrix(mdca).clone();
int[] dimensionSize = mdcm.getDimensionSizes();
@ -597,10 +592,11 @@ public class FastFourierTransformer implements Serializable {
* @param forward inverseTransform2 is preformed if this is false
* @param d index of the dimension to process
* @param subVector recursion subvector
* @throws MathException if any dimension is not a power of two
* @throws IllegalArgumentException if any dimension is not a power of two
*/
private void mdfft(MultiDimensionalComplexMatrix mdcm, boolean forward,
int d, int[] subVector) throws MathException {
int d, int[] subVector)
throws IllegalArgumentException {
int[] dimensionSize = mdcm.getDimensionSizes();
//if done
if (subVector.length == dimensionSize.length) {
@ -646,8 +642,8 @@ public class FastFourierTransformer implements Serializable {
* http://jcp.org/en/jsr/detail?id=83
* may require additional exception throws for other basic requirements.
*/
private class MultiDimensionalComplexMatrix implements Serializable,
Cloneable {
private class MultiDimensionalComplexMatrix
implements Serializable, Cloneable {
/** Serializable version identifier. */
private static final long serialVersionUID = 0x564FCD47EBA8169BL;
@ -693,11 +689,20 @@ public class FastFourierTransformer implements Serializable {
* Get a matrix element.
* @param vector indices of the element
* @return matrix element
* @exception IllegalArgumentException if dimensions do not match
*/
public Complex get(int... vector) {
if ((vector == null && dimensionSize.length > 1) ||
(vector != null && vector.length != dimensionSize.length)) {
throw new IllegalArgumentException("Number of dimensions must match");
public Complex get(int... vector)
throws IllegalArgumentException {
if (vector == null && dimensionSize.length > 1) {
throw MathRuntimeException.createIllegalArgumentException("some dimensions don't math: {0} != {1}",
new Object[] { 0, dimensionSize.length });
}
if (vector != null && vector.length != dimensionSize.length) {
throw MathRuntimeException.createIllegalArgumentException("some dimensions don't math: {0} != {1}",
new Object[] {
vector.length,
dimensionSize.length
});
}
Object lastDimension = multiDimensionalComplexArray;
@ -713,11 +718,20 @@ public class FastFourierTransformer implements Serializable {
* @param magnitude magnitude of the element
* @param vector indices of the element
* @return the previous value
* @exception IllegalArgumentException if dimensions do not match
*/
public Complex set(Complex magnitude, int... vector) {
if ((vector == null && dimensionSize.length > 1) ||
(vector != null && vector.length != dimensionSize.length)) {
throw new IllegalArgumentException("Number of dimensions must match");
public Complex set(Complex magnitude, int... vector)
throws IllegalArgumentException {
if (vector == null && dimensionSize.length > 1) {
throw MathRuntimeException.createIllegalArgumentException("some dimensions don't math: {0} != {1}",
new Object[] { 0, dimensionSize.length });
}
if (vector != null && vector.length != dimensionSize.length) {
throw MathRuntimeException.createIllegalArgumentException("some dimensions don't math: {0} != {1}",
new Object[] {
vector.length,
dimensionSize.length
});
}
Object lastDimension = multiDimensionalComplexArray;

View File

@ -16,9 +16,9 @@
*/
package org.apache.commons.math.transform;
import java.io.Serializable;
import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.MathRuntimeException;
import org.apache.commons.math.analysis.UnivariateRealFunction;
/**
* Implements the <a href="http://www.archive.chipcenter.com/dsp/DSP000517F1.html">Fast Hadamard Transform</a> (FHT).
@ -26,22 +26,35 @@ import org.apache.commons.math.MathRuntimeException;
* @version $Revision$ $Date$
* @since 2.0
*/
public class FastHadamardTransformer implements Serializable {
public class FastHadamardTransformer implements RealTransformer {
/** Serializable version identifier. */
private static final long serialVersionUID = 5044269102877526860L;
private static final long serialVersionUID = -710169279109099264L;
/**
* Wrapper method for fht() for double vectors
*
* @param x input vector
* @return y output vector
* @throws IllegalArgumentException
*/
public double[] transform(double x[]) throws IllegalArgumentException {
return fht(x);
/** {@inheritDoc} */
public double[] transform(double f[]) throws IllegalArgumentException {
return fht(f);
}
/** {@inheritDoc} */
public double[] transform(UnivariateRealFunction f,
double min, double max, int n)
throws FunctionEvaluationException, IllegalArgumentException {
return fht(FastFourierTransformer.sample(f, min, max, n));
}
/** {@inheritDoc} */
public double[] inversetransform(double f[])
throws IllegalArgumentException {
return fht(f);
}
/** {@inheritDoc} */
public double[] inversetransform(UnivariateRealFunction f,
double min, double max, int n)
throws FunctionEvaluationException, IllegalArgumentException {
return fht(FastFourierTransformer.sample(f, min, max, n));
}
/**
* The FHT (Fast Hadamard Transformation) which uses only subtraction and addition.
@ -123,16 +136,11 @@ public class FastHadamardTransformer implements Serializable {
protected double[] fht(double x[]) throws IllegalArgumentException {
// n is the row count of the input vector x
int n = x.length;
final int n = x.length;
final int halfN = n / 2;
// n has to be of the form n = 2^p !!
int p = 0;
int twoP = 1;
while (twoP < n) {
++p;
twoP *= 2;
}
if (n != twoP) {
if (!FastFourierTransformer.isPowerOf2(n)) {
throw MathRuntimeException.createIllegalArgumentException("{0} is not a power of 2",
new Object[] { n });
}
@ -143,7 +151,7 @@ public class FastHadamardTransformer implements Serializable {
double[] yCurrent = x.clone();
// iterate from left to right (column)
for (int j = 0; j < p; j++) {
for (int j = 1; j < n; j <<= 1) {
// switch columns
final double[] yTmp = yCurrent;
@ -151,16 +159,17 @@ public class FastHadamardTransformer implements Serializable {
yPrevious = yTmp;
// iterate from top to bottom (row)
for (int i = 0; i < n; i++) {
if (i < n / 2) {
for (int i = 0; i < halfN; ++i) {
// D<sub>top</sub>
// The top part works with addition
yCurrent[i] = yPrevious[i*2] + yPrevious[i*2 +1];
} else {
final int twoI = 2 * i;
yCurrent[i] = yPrevious[twoI] + yPrevious[twoI + 1];
}
for (int i = halfN; i < n; ++i) {
// D<sub>bottom</sub>
// The bottom part works with subtraction
yCurrent[i] = yPrevious[(i-n/2)*2] - yPrevious[(i-n/2)*2 +1];
}
final int twoI = 2 * i;
yCurrent[i] = yPrevious[twoI - n] - yPrevious[twoI - n + 1];
}
}

View File

@ -16,10 +16,10 @@
*/
package org.apache.commons.math.transform;
import java.io.Serializable;
import org.apache.commons.math.analysis.*;
import org.apache.commons.math.complex.*;
import org.apache.commons.math.MathException;
import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.MathRuntimeException;
/**
* Implements the <a href="http://documents.wolfram.com/v5/Add-onsLinks/
@ -37,10 +37,10 @@ import org.apache.commons.math.MathException;
* @version $Revision$ $Date$
* @since 1.2
*/
public class FastSineTransformer implements Serializable {
public class FastSineTransformer implements RealTransformer {
/** serializable version identifier */
static final long serialVersionUID = -478002039949390854L;
private static final long serialVersionUID = -7557024407476823001L;
/**
* Construct a default transformer.
@ -57,12 +57,10 @@ public class FastSineTransformer implements Serializable {
*
* @param f the real data array to be transformed
* @return the real transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
public double[] transform(double f[]) throws MathException,
IllegalArgumentException {
public double[] transform(double f[])
throws IllegalArgumentException {
return fst(f);
}
@ -77,12 +75,13 @@ public class FastSineTransformer implements Serializable {
* @param max the upper bound for the interval
* @param n the number of sample points
* @return the real transformed array
* @throws MathException if any math-related errors occur
* @throws FunctionEvaluationException if function cannot be evaluated
* at some point
* @throws IllegalArgumentException if any parameters are invalid
*/
public double[] transform(
UnivariateRealFunction f, double min, double max, int n)
throws MathException, IllegalArgumentException {
public double[] transform(UnivariateRealFunction f,
double min, double max, int n)
throws FunctionEvaluationException, IllegalArgumentException {
double data[] = FastFourierTransformer.sample(f, min, max, n);
data[0] = 0.0;
@ -97,11 +96,9 @@ public class FastSineTransformer implements Serializable {
*
* @param f the real data array to be transformed
* @return the real transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
public double[] transform2(double f[]) throws MathException,
IllegalArgumentException {
public double[] transform2(double f[]) throws IllegalArgumentException {
double scaling_coefficient = Math.sqrt(2.0 / f.length);
return FastFourierTransformer.scaleArray(fst(f), scaling_coefficient);
@ -118,12 +115,13 @@ public class FastSineTransformer implements Serializable {
* @param max the upper bound for the interval
* @param n the number of sample points
* @return the real transformed array
* @throws MathException if any math-related errors occur
* @throws FunctionEvaluationException if function cannot be evaluated
* at some point
* @throws IllegalArgumentException if any parameters are invalid
*/
public double[] transform2(
UnivariateRealFunction f, double min, double max, int n)
throws MathException, IllegalArgumentException {
throws FunctionEvaluationException, IllegalArgumentException {
double data[] = FastFourierTransformer.sample(f, min, max, n);
data[0] = 0.0;
@ -139,11 +137,9 @@ public class FastSineTransformer implements Serializable {
*
* @param f the real data array to be inversely transformed
* @return the real inversely transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
public double[] inversetransform(double f[]) throws MathException,
IllegalArgumentException {
public double[] inversetransform(double f[]) throws IllegalArgumentException {
double scaling_coefficient = 2.0 / f.length;
return FastFourierTransformer.scaleArray(fst(f), scaling_coefficient);
@ -160,12 +156,12 @@ public class FastSineTransformer implements Serializable {
* @param max the upper bound for the interval
* @param n the number of sample points
* @return the real inversely transformed array
* @throws MathException if any math-related errors occur
* @throws FunctionEvaluationException if function cannot be evaluated
* at some point
* @throws IllegalArgumentException if any parameters are invalid
*/
public double[] inversetransform(
UnivariateRealFunction f, double min, double max, int n)
throws MathException, IllegalArgumentException {
public double[] inversetransform(UnivariateRealFunction f, double min, double max, int n)
throws FunctionEvaluationException, IllegalArgumentException {
double data[] = FastFourierTransformer.sample(f, min, max, n);
data[0] = 0.0;
@ -181,11 +177,9 @@ public class FastSineTransformer implements Serializable {
*
* @param f the real data array to be inversely transformed
* @return the real inversely transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
public double[] inversetransform2(double f[]) throws MathException,
IllegalArgumentException {
public double[] inversetransform2(double f[]) throws IllegalArgumentException {
return transform2(f);
}
@ -201,12 +195,12 @@ public class FastSineTransformer implements Serializable {
* @param max the upper bound for the interval
* @param n the number of sample points
* @return the real inversely transformed array
* @throws MathException if any math-related errors occur
* @throws FunctionEvaluationException if function cannot be evaluated
* at some point
* @throws IllegalArgumentException if any parameters are invalid
*/
public double[] inversetransform2(
UnivariateRealFunction f, double min, double max, int n)
throws MathException, IllegalArgumentException {
public double[] inversetransform2(UnivariateRealFunction f, double min, double max, int n)
throws FunctionEvaluationException, IllegalArgumentException {
return transform2(f, min, max, n);
}
@ -216,18 +210,16 @@ public class FastSineTransformer implements Serializable {
*
* @param f the real data array to be transformed
* @return the real transformed array
* @throws MathException if any math-related errors occur
* @throws IllegalArgumentException if any parameters are invalid
*/
protected double[] fst(double f[]) throws MathException,
IllegalArgumentException {
protected double[] fst(double f[]) throws IllegalArgumentException {
double A, B, x[], F[] = new double[f.length];
FastFourierTransformer.verifyDataSet(f);
if (f[0] != 0.0) {
throw new IllegalArgumentException
("The first element is not zero: " + f[0]);
throw MathRuntimeException.createIllegalArgumentException("first element is not 0: {0}",
new Object[] { f[0] });
}
int N = f.length;
if (N == 1) { // trivial case

View File

@ -0,0 +1,69 @@
package org.apache.commons.math.transform;
import java.io.Serializable;
import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.analysis.UnivariateRealFunction;
import org.apache.commons.math.complex.Complex;
/**
* Interface for one-dimensional data sets transformations producing real results.
* <p>Such transforms include {@link FastSineTransformer sine transform},
* {@link FastCosineTransformer cosine transform} or {@link
* FastHadamardTransformer Hadamard transform}. {@link FastFourierTransformer
* Fourier transform} is of a different kind and does not implement this
* interface since it produces {@link Complex complex} results instead of real
* ones.
* </p>
* @version $Revision$ $Date$
* @since 2.0
*/
public interface RealTransformer extends Serializable {
/**
* Transform the given real data set.
* @param f the real data array to be transformed (signal)
* @return the real transformed array (spectrum)
* @throws IllegalArgumentException if any parameters are invalid
*/
double[] transform(double f[])
throws IllegalArgumentException;
/**
* Transform the given real function, sampled on the given interval.
* @param f the function to be sampled and transformed
* @param min the lower bound for the interval
* @param max the upper bound for the interval
* @param n the number of sample points
* @return the real transformed array
* @throws FunctionEvaluationException if function cannot be evaluated
* at some point
* @throws IllegalArgumentException if any parameters are invalid
*/
double[] transform(UnivariateRealFunction f, double min, double max, int n)
throws FunctionEvaluationException, IllegalArgumentException;
/**
* Inversely transform the given real data set.
* @param f the real data array to be inversely transformed (spectrum)
* @return the real inversely transformed array (signal)
* @throws IllegalArgumentException if any parameters are invalid
*/
public abstract double[] inversetransform(double f[])
throws IllegalArgumentException;
/**
* Inversely transform the given real function, sampled on the given interval.
* @param f the function to be sampled and inversely transformed
* @param min the lower bound for the interval
* @param max the upper bound for the interval
* @param n the number of sample points
* @return the real inversely transformed array
* @throws FunctionEvaluationException if function cannot be evaluated
* at some point
* @throws IllegalArgumentException if any parameters are invalid
*/
double[] inversetransform(UnivariateRealFunction f, double min, double max, int n)
throws FunctionEvaluationException, IllegalArgumentException;
}