mirror of
https://github.com/apache/commons-math.git
synced 2025-02-06 10:09:26 +00:00
In distribution.FastCosineTransformer, replaced the pair transform2() / inverseTransform2() with two factory methods: create() and createOrthogonal() (MATH-677).
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1212262 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
50ab4b74b2
commit
f4f2b63702
@ -40,167 +40,142 @@ import org.apache.commons.math.util.FastMath;
|
|||||||
* @since 1.2
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
public class FastCosineTransformer implements RealTransformer {
|
public class FastCosineTransformer implements RealTransformer {
|
||||||
|
/**
|
||||||
|
* {@code true} if the orthogonal version of the DCT should be used.
|
||||||
|
*
|
||||||
|
* @see #create()
|
||||||
|
* @see #createOrthogonal()
|
||||||
|
*/
|
||||||
|
private final boolean orthogonal;
|
||||||
|
|
||||||
/** Construct a default transformer. */
|
/**
|
||||||
public FastCosineTransformer() {
|
* Creates a new instance of this class, with various normalization
|
||||||
super();
|
* conventions.
|
||||||
|
*
|
||||||
|
* @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 FastCosineTransformer(final boolean orthogonal) {
|
||||||
|
this.orthogonal = orthogonal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform the given real data set.
|
|
||||||
* <p>
|
* <p>
|
||||||
* The formula is F<sub>n</sub> = (1/2) [f<sub>0</sub> + (-1)<sup>n</sup> f<sub>N</sub>] +
|
* Returns a new instance of this class. The returned transformer uses the
|
||||||
* ∑<sub>k=1</sub><sup>N-1</sup> f<sub>k</sub> cos(π nk/N)
|
* 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>
|
* </p>
|
||||||
*
|
*
|
||||||
|
* @return a new DCT transformer, with "standard" normalizing conventions
|
||||||
|
*/
|
||||||
|
public static FastCosineTransformer create() {
|
||||||
|
return new FastCosineTransformer(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 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>
|
||||||
|
*
|
||||||
|
* @return a new DCT transformer, with "orthogonal" normalizing conventions
|
||||||
|
*/
|
||||||
|
public static FastCosineTransformer createOrthogonal() {
|
||||||
|
return new FastCosineTransformer(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the forward 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
|
||||||
* @return the real transformed array
|
* @return the real transformed array
|
||||||
* @throws IllegalArgumentException if any parameters are invalid
|
* @throws IllegalArgumentException if any parameters are invalid
|
||||||
*/
|
*/
|
||||||
public double[] transform(double[] f) throws IllegalArgumentException {
|
public double[] transform(double[] f) throws IllegalArgumentException {
|
||||||
|
|
||||||
|
if (orthogonal) {
|
||||||
|
final double s = FastMath.sqrt(2.0 / (f.length - 1));
|
||||||
|
return FastFourierTransformer.scaleArray(fct(f), s);
|
||||||
|
}
|
||||||
return fct(f);
|
return fct(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform the given real function, sampled on the given interval.
|
* Returns the forward transform of the specified real function, sampled on
|
||||||
* <p>
|
* the specified interval.
|
||||||
* 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>
|
|
||||||
*
|
*
|
||||||
* @param f the function to be sampled and transformed
|
* @param f the function to be sampled and transformed
|
||||||
* @param min the lower bound for the interval
|
* @param min the (inclusive) lower bound for the interval
|
||||||
* @param max the 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
|
||||||
* @return the real transformed array
|
* @return the real transformed array
|
||||||
* @throws IllegalArgumentException if any parameters are invalid
|
* @throws IllegalArgumentException if any parameters are invalid
|
||||||
*/
|
*/
|
||||||
public double[] transform(UnivariateFunction f,
|
public double[] transform(UnivariateFunction f,
|
||||||
double min, double max, int n)
|
double min, double max, int n) throws IllegalArgumentException {
|
||||||
throws IllegalArgumentException {
|
|
||||||
double[] data = FastFourierTransformer.sample(f, min, max, n);
|
final double[] data = FastFourierTransformer.sample(f, min, max, n);
|
||||||
return fct(data);
|
return transform(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform the given real data set.
|
* Returns the inverse transform of the specified 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)
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param f the real data array to be transformed
|
|
||||||
* @return the real transformed array
|
|
||||||
* @throws IllegalArgumentException if any parameters are invalid
|
|
||||||
*/
|
|
||||||
public double[] transform2(double[] f) throws IllegalArgumentException {
|
|
||||||
|
|
||||||
double scalingCoefficient = FastMath.sqrt(2.0 / (f.length - 1));
|
|
||||||
return FastFourierTransformer.scaleArray(fct(f), scalingCoefficient);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
*
|
|
||||||
* </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
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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>
|
|
||||||
*
|
*
|
||||||
* @param f the real data array to be inversely transformed
|
* @param f the real data array to be inversely transformed
|
||||||
* @return the real inversely transformed array
|
* @return the real inversely transformed array
|
||||||
* @throws IllegalArgumentException if any parameters are invalid
|
* @throws IllegalArgumentException if any parameters are invalid
|
||||||
*/
|
*/
|
||||||
public double[] inverseTransform(double[] f)
|
public double[] inverseTransform(double[] f)
|
||||||
throws IllegalArgumentException {
|
throws IllegalArgumentException {
|
||||||
|
|
||||||
double scalingCoefficient = 2.0 / (f.length - 1);
|
final double s2 = 2.0 / (f.length - 1);
|
||||||
return FastFourierTransformer.scaleArray(fct(f), scalingCoefficient);
|
final double s1 = orthogonal ? FastMath.sqrt(s2) : s2;
|
||||||
|
return FastFourierTransformer.scaleArray(fct(f), s1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inversely transform the given real function, sampled on the given
|
* Returns the inverse transform of the specified real function, sampled
|
||||||
* interval.
|
* 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>
|
|
||||||
*
|
*
|
||||||
* @param f the function to be sampled and inversely transformed
|
* @param f the function to be sampled and inversely transformed
|
||||||
* @param min the lower bound for the interval
|
* @param min the (inclusive) lower bound for the interval
|
||||||
* @param max the 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
|
||||||
* @return the real inversely transformed array
|
* @return the real inversely transformed array
|
||||||
* @throws IllegalArgumentException if any parameters are invalid
|
* @throws IllegalArgumentException if any parameters are invalid
|
||||||
*/
|
*/
|
||||||
public double[] inverseTransform(UnivariateFunction f,
|
public double[] inverseTransform(UnivariateFunction f,
|
||||||
double min, double max, int n)
|
double min, double max, int n) throws IllegalArgumentException {
|
||||||
throws IllegalArgumentException {
|
|
||||||
|
|
||||||
double[] data = FastFourierTransformer.sample(f, min, max, n);
|
final double[] data = FastFourierTransformer.sample(f, min, max, n);
|
||||||
double scalingCoefficient = 2.0 / (n - 1);
|
return inverseTransform(data);
|
||||||
return FastFourierTransformer.scaleArray(fct(data), scalingCoefficient);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
* @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)
|
|
||||||
throws IllegalArgumentException {
|
|
||||||
return transform2(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
* @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 IllegalArgumentException if any parameters are invalid
|
|
||||||
*/
|
|
||||||
public double[] inverseTransform2(UnivariateFunction f,
|
|
||||||
double min, double max, int n)
|
|
||||||
throws IllegalArgumentException {
|
|
||||||
|
|
||||||
return transform2(f, min, max, n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,7 +36,7 @@ public final class FastCosineTransformerTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testAdHocData() {
|
public void testAdHocData() {
|
||||||
FastCosineTransformer transformer = new FastCosineTransformer();
|
FastCosineTransformer transformer = FastCosineTransformer.create();
|
||||||
double result[], tolerance = 1E-12;
|
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 };
|
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 FastCosineTransformerTest {
|
|||||||
|
|
||||||
FastFourierTransformer.scaleArray(x, FastMath.sqrt(0.5 * (x.length-1)));
|
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++) {
|
for (int i = 0; i < result.length; i++) {
|
||||||
Assert.assertEquals(x[i], result[i], tolerance);
|
Assert.assertEquals(x[i], result[i], tolerance);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = transformer.inverseTransform2(x);
|
result = transformer.inverseTransform(x);
|
||||||
for (int i = 0; i < result.length; i++) {
|
for (int i = 0; i < result.length; i++) {
|
||||||
Assert.assertEquals(y[i], result[i], tolerance);
|
Assert.assertEquals(y[i], result[i], tolerance);
|
||||||
}
|
}
|
||||||
@ -73,7 +74,7 @@ public final class FastCosineTransformerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSinFunction() {
|
public void testSinFunction() {
|
||||||
UnivariateFunction f = new SinFunction();
|
UnivariateFunction f = new SinFunction();
|
||||||
FastCosineTransformer transformer = new FastCosineTransformer();
|
FastCosineTransformer transformer = FastCosineTransformer.create();
|
||||||
double min, max, result[], tolerance = 1E-12; int N = 9;
|
double min, max, result[], tolerance = 1E-12; int N = 9;
|
||||||
|
|
||||||
double expected[] = { 0.0, 3.26197262739567, 0.0,
|
double expected[] = { 0.0, 3.26197262739567, 0.0,
|
||||||
@ -98,7 +99,7 @@ public final class FastCosineTransformerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testParameters() throws Exception {
|
public void testParameters() throws Exception {
|
||||||
UnivariateFunction f = new SinFunction();
|
UnivariateFunction f = new SinFunction();
|
||||||
FastCosineTransformer transformer = new FastCosineTransformer();
|
FastCosineTransformer transformer = FastCosineTransformer.create();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// bad interval
|
// bad interval
|
||||||
|
Loading…
x
Reference in New Issue
Block a user