Author: celestin Date: Fri Dec 9 06:47:23 2011 New Revision: 1212262 URL: http://svn.apache.org/viewvc?rev=1212262&view=rev Log: In distribution.FastCosineTransformer, replaced the pair transform2() / inverseTransform2() with two factory methods: create() and createOrthogonal() (MATH-677).
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/transform/FastCosineTransformer.java commons/proper/math/trunk/src/test/java/org/apache/commons/math/transform/FastCosineTransformerTest.java Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/transform/FastCosineTransformer.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/transform/FastCosineTransformer.java?rev=1212262&r1=1212261&r2=1212262&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math/transform/FastCosineTransformer.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/transform/FastCosineTransformer.java Fri Dec 9 06:47:23 2011 @@ -40,167 +40,142 @@ import org.apache.commons.math.util.Fast * @since 1.2 */ public class FastCosineTransformer implements RealTransformer { - - /** Construct a default transformer. */ - public FastCosineTransformer() { - super(); - } - /** - * Transform the given real data set. - * <p> - * The formula is F<sub>n</sub> = (1/2) [f<sub>0</sub> + (-1)<sup>n</sup> f<sub>N</sub>] + - * ∑<sub>k=1</sub><sup>N-1</sup> f<sub>k</sub> cos(π nk/N) - * </p> + * {@code true} if the orthogonal version of the DCT should be used. * - * @param f the real data array to be transformed - * @return the real transformed array - * @throws IllegalArgumentException if any parameters are invalid + * @see #create() + * @see #createOrthogonal() */ - public double[] transform(double[] f) throws IllegalArgumentException { - return fct(f); - } + private final boolean orthogonal; /** - * Transform the given real function, sampled on the given interval. - * <p> - * The formula is F<sub>n</sub> = (1/2) [f<sub>0</sub> + (-1)<sup>n</sup> f<sub>N</sub>] + - * ∑<sub>k=1</sub><sup>N-1</sup> f<sub>k</sub> cos(π nk/N) - * </p> + * Creates a new instance of this class, with various normalization + * conventions. * - * @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 IllegalArgumentException if any parameters are invalid + * @param orthogonal {@code false} if the DCT is <em>not</em> to be scaled, + * {@code true} if it is to be scaled so as to make the transform + * orthogonal. + * @see #create() + * @see #createOrthogonal() */ - public double[] transform(UnivariateFunction f, - double min, double max, int n) - throws IllegalArgumentException { - double[] data = FastFourierTransformer.sample(f, min, max, n); - return fct(data); + public FastCosineTransformer(final boolean orthogonal) { + this.orthogonal = orthogonal; } /** - * Transform the given real data set. * <p> - * The formula is F<sub>n</sub> = √(1/2N) [f<sub>0</sub> + (-1)<sup>n</sup> f<sub>N</sub>] + - * √(2/N) ∑<sub>k=1</sub><sup>N-1</sup> f<sub>k</sub> cos(π nk/N) + * Returns a new instance of this class. The returned transformer uses the + * normalizing conventions described below. + * <ul> + * <li>Forward transform: + * y<sub>n</sub> = (1/2) [x<sub>0</sub> + (-1)<sup>n</sup>x<sub>N-1</sub>] + * + ∑<sub>k=1</sub><sup>N-2</sup> + * x<sub>k</sub> cos[π nk / (N - 1)],</li> + * <li>Inverse transform: + * x<sub>k</sub> = [1 / (N - 1)] [y<sub>0</sub> + * + (-1)<sup>k</sup>y<sub>N-1</sub>] + * + [2 / (N - 1)] ∑<sub>n=1</sub><sup>N-2</sup> + * y<sub>n</sub> cos[π nk / (N - 1)],</li> + * </ul> + * where N is the size of the data sample. * </p> * - * @param f the real data array to be transformed - * @return the real transformed array - * @throws IllegalArgumentException if any parameters are invalid + * @return a new DCT transformer, with "standard" normalizing conventions */ - public double[] transform2(double[] f) throws IllegalArgumentException { - - double scalingCoefficient = FastMath.sqrt(2.0 / (f.length - 1)); - return FastFourierTransformer.scaleArray(fct(f), scalingCoefficient); + public static FastCosineTransformer create() { + return new FastCosineTransformer(false); } /** - * Transform the given real function, sampled on the given interval. * <p> - * The formula is F<sub>n</sub> = √(1/2N) [f<sub>0</sub> + (-1)<sup>n</sup> f<sub>N</sub>] + - * √(2/N) ∑<sub>k=1</sub><sup>N-1</sup> f<sub>k</sub> cos(π nk/N) - * + * Returns a new instance of this class. The returned transformer uses the + * normalizing conventions described below. + * <ul> + * <li>Forward transform: + * y<sub>n</sub> = [2(N - 1)]<sup>-1/2</sup> [x<sub>0</sub> + * + (-1)<sup>n</sup>x<sub>N-1</sub>] + * + [2 / (N - 1)]<sup>1/2</sup> ∑<sub>k=1</sub><sup>N-2</sup> + * x<sub>k</sub> cos[π nk / (N - 1)],</li> + * <li>Inverse transform: + * x<sub>k</sub> = [2(N - 1)]<sup>-1/2</sup> [y<sub>0</sub> + * + (-1)<sup>k</sup>y<sub>N-1</sub>] + * + [2 / (N - 1)]<sup>1/2</sup> ∑<sub>n=1</sub><sup>N-2</sup> + * y<sub>n</sub> cos[π nk / (N - 1)],</li> + * </ul> + * which make the transform orthogonal. N is the size of the data sample. * </p> * - * @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 IllegalArgumentException if any parameters are invalid + * @return a new DCT transformer, with "orthogonal" normalizing conventions */ - public double[] transform2(UnivariateFunction f, - double min, double max, int n) - throws IllegalArgumentException { - - double[] data = FastFourierTransformer.sample(f, min, max, n); - double scalingCoefficient = FastMath.sqrt(2.0 / (n - 1)); - return FastFourierTransformer.scaleArray(fct(data), scalingCoefficient); + public static FastCosineTransformer createOrthogonal() { + return new FastCosineTransformer(true); } /** - * Inversely transform the given real data set. - * <p> - * The formula is f<sub>k</sub> = (1/N) [F<sub>0</sub> + (-1)<sup>k</sup> F<sub>N</sub>] + - * (2/N) ∑<sub>n=1</sub><sup>N-1</sup> F<sub>n</sub> cos(π nk/N) - * </p> + * Returns the forward transform of the specified real data set. * - * @param f the real data array to be inversely transformed - * @return the real inversely transformed array + * @param f the real data array to be transformed + * @return the real transformed array * @throws IllegalArgumentException if any parameters are invalid */ - public double[] inverseTransform(double[] f) - throws IllegalArgumentException { + public double[] transform(double[] f) throws IllegalArgumentException { - double scalingCoefficient = 2.0 / (f.length - 1); - return FastFourierTransformer.scaleArray(fct(f), scalingCoefficient); + if (orthogonal) { + final double s = FastMath.sqrt(2.0 / (f.length - 1)); + return FastFourierTransformer.scaleArray(fct(f), s); + } + return fct(f); } /** - * Inversely transform the given real function, sampled on the given - * interval. - * <p> - * The formula is f<sub>k</sub> = (1/N) [F<sub>0</sub> + (-1)<sup>k</sup> F<sub>N</sub>] + - * (2/N) ∑<sub>n=1</sub><sup>N-1</sup> F<sub>n</sub> cos(π nk/N) - * </p> + * Returns the forward transform of the specified real function, sampled on + * the specified 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 f the function to be sampled and 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 real inversely transformed array + * @return the real transformed array * @throws IllegalArgumentException if any parameters are invalid */ - public double[] inverseTransform(UnivariateFunction f, - double min, double max, int n) - throws IllegalArgumentException { + public double[] transform(UnivariateFunction f, + double min, double max, int n) throws IllegalArgumentException { - double[] data = FastFourierTransformer.sample(f, min, max, n); - double scalingCoefficient = 2.0 / (n - 1); - return FastFourierTransformer.scaleArray(fct(data), scalingCoefficient); + final double[] data = FastFourierTransformer.sample(f, min, max, n); + return transform(data); } /** - * Inversely transform the given real data set. - * <p> - * The formula is f<sub>k</sub> = √(1/2N) [F<sub>0</sub> + (-1)<sup>k</sup> F<sub>N</sub>] + - * √(2/N) ∑<sub>n=1</sub><sup>N-1</sup> F<sub>n</sub> cos(π nk/N) - * </p> + * Returns the inverse transform of the specified real data set. * * @param f the real data array to be inversely transformed * @return the real inversely transformed array * @throws IllegalArgumentException if any parameters are invalid */ - public double[] inverseTransform2(double[] f) + public double[] inverseTransform(double[] f) throws IllegalArgumentException { - return transform2(f); + + final double s2 = 2.0 / (f.length - 1); + final double s1 = orthogonal ? FastMath.sqrt(s2) : s2; + return FastFourierTransformer.scaleArray(fct(f), s1); } /** - * Inversely transform the given real function, sampled on the given - * interval. - * <p> - * The formula is f<sub>k</sub> = √(1/2N) [F<sub>0</sub> + (-1)<sup>k</sup> F<sub>N</sub>] + - * √(2/N) ∑<sub>n=1</sub><sup>N-1</sup> F<sub>n</sub> cos(π nk/N) - * </p> + * 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 lower bound for the interval - * @param max the upper bound for the interval + * @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 real inversely transformed array * @throws IllegalArgumentException if any parameters are invalid */ - public double[] inverseTransform2(UnivariateFunction f, - double min, double max, int n) - throws IllegalArgumentException { + public double[] inverseTransform(UnivariateFunction f, + double min, double max, int n) throws IllegalArgumentException { - return transform2(f, min, max, n); + final double[] data = FastFourierTransformer.sample(f, min, max, n); + return inverseTransform(data); } /** Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math/transform/FastCosineTransformerTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/transform/FastCosineTransformerTest.java?rev=1212262&r1=1212261&r2=1212262&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/java/org/apache/commons/math/transform/FastCosineTransformerTest.java (original) +++ commons/proper/math/trunk/src/test/java/org/apache/commons/math/transform/FastCosineTransformerTest.java Fri Dec 9 06:47:23 2011 @@ -36,7 +36,7 @@ public final class FastCosineTransformer */ @Test public void testAdHocData() { - FastCosineTransformer transformer = new FastCosineTransformer(); + FastCosineTransformer transformer = FastCosineTransformer.create(); double result[], tolerance = 1E-12; double x[] = { 0.0, 1.0, 4.0, 9.0, 16.0, 25.0, 36.0, 49.0, 64.0 }; @@ -56,12 +56,13 @@ public final class FastCosineTransformer FastFourierTransformer.scaleArray(x, FastMath.sqrt(0.5 * (x.length-1))); - result = transformer.transform2(y); + transformer = FastCosineTransformer.createOrthogonal(); + result = transformer.transform(y); for (int i = 0; i < result.length; i++) { Assert.assertEquals(x[i], result[i], tolerance); } - result = transformer.inverseTransform2(x); + result = transformer.inverseTransform(x); for (int i = 0; i < result.length; i++) { Assert.assertEquals(y[i], result[i], tolerance); } @@ -73,7 +74,7 @@ public final class FastCosineTransformer @Test public void testSinFunction() { UnivariateFunction f = new SinFunction(); - FastCosineTransformer transformer = new FastCosineTransformer(); + FastCosineTransformer transformer = FastCosineTransformer.create(); double min, max, result[], tolerance = 1E-12; int N = 9; double expected[] = { 0.0, 3.26197262739567, 0.0, @@ -98,7 +99,7 @@ public final class FastCosineTransformer @Test public void testParameters() throws Exception { UnivariateFunction f = new SinFunction(); - FastCosineTransformer transformer = new FastCosineTransformer(); + FastCosineTransformer transformer = FastCosineTransformer.create(); try { // bad interval