commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From celes...@apache.org
Subject svn commit: r1211318 - in /commons/proper/math/trunk/src/main/java/org/apache/commons/math/transform: FastCosineTransformer.java FastFourierTransformer.java FastSineTransformer.java
Date Wed, 07 Dec 2011 07:35:09 GMT
Author: celestin
Date: Wed Dec  7 07:35:09 2011
New Revision: 1211318

URL: http://svn.apache.org/viewvc?rev=1211318&view=rev
Log:
In package transform, replaced FastFourierTransformer.transform2 and FastFourierTransformer.inverseTransform2
with a combination of transform()/inverseTransform(), combined with appropriate factory methods
(MATH-677).

Modified:
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/transform/FastCosineTransformer.java
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/transform/FastFourierTransformer.java
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/transform/FastSineTransformer.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=1211318&r1=1211317&r2=1211318&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
Wed Dec  7 07:35:09 2011
@@ -241,7 +241,7 @@ public class FastCosineTransformer imple
             x[n - i] = a + b;
             t1 += c;
         }
-        FastFourierTransformer transformer = new FastFourierTransformer();
+        FastFourierTransformer transformer = FastFourierTransformer.create();
         Complex[] y = transformer.transform(x);
 
         // reconstruct the FCT result for the original array

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/transform/FastFourierTransformer.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/transform/FastFourierTransformer.java?rev=1211318&r1=1211317&r2=1211318&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/transform/FastFourierTransformer.java
(original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/transform/FastFourierTransformer.java
Wed Dec  7 07:35:09 2011
@@ -32,14 +32,17 @@ import org.apache.commons.math.util.Fast
  * chapter 6.
  * <p>
  * There are several conventions for the definition of FFT and inverse FFT,
- * mainly on different coefficient and exponent. Here the equations are listed
- * in the comments of the corresponding methods.</p>
+ * mainly on different coefficient and exponent. The conventions adopted in the
+ * present implementation are specified in the comments of the two provided
+ * factory methods, {@link #create()} and {@link #createUnitary()}.
+ * </p>
  * <p>
  * We require the length of data set to be power of 2, this greatly simplifies
  * and speeds up the code. Users can pad the data with zeros to meet this
  * requirement. There are other flavors of FFT, for reference, see S. Winograd,
- * <i>On computing the discrete Fourier transform</i>, Mathematics of Computation,
- * 32 (1978), 175 - 199.</p>
+ * <i>On computing the discrete Fourier transform</i>, Mathematics of
+ * Computation, 32 (1978), 175 - 199.
+ * </p>
  *
  * @version $Id$
  * @since 1.2
@@ -49,127 +52,137 @@ public class FastFourierTransformer impl
     /** Serializable version identifier. */
     static final long serialVersionUID = 5138259215438106000L;
 
+
+    /**
+     * {@code true} if the orthogonal version of the FFT should be used.
+     *
+     * @see #create()
+     * @see #createUnitary()
+     */
+    private final boolean unitary;
+
     /** The roots of unity. */
     private RootsOfUnity roots = new RootsOfUnity();
 
     /** Construct a default transformer. */
-    public FastFourierTransformer() {
+    private FastFourierTransformer() {
         super();
+        this.unitary = false;
     }
 
     /**
-     * Transform the given real data set.
-     * <p>
-     * The formula is $ y_n = \Sigma_{k=0}^{N-1} e^{-2 \pi i nk/N} x_k $
-     * </p>
+     * Creates a new instance of this class, with various normalization
+     * conventions.
      *
-     * @param f the real data array to be transformed
-     * @return the complex transformed array
-     * @throws IllegalArgumentException if any parameters are invalid
+     * @param unitary {@code false} if the direct Fourier transform is
+     * <em>not</em> to be scaled, {@code true} if it is to be scaled so as to
+     * make the transform unitary.
+     * @see #create()
+     * @see #createUnitary()
      */
-    public Complex[] transform(double[] f)
-        throws IllegalArgumentException {
-        return fft(f, false);
+    private FastFourierTransformer(final boolean unitary) {
+        this.unitary = unitary;
     }
 
     /**
-     * Transform the given real function, sampled on the given interval.
      * <p>
-     * The formula is $ y_n = \Sigma_{k=0}^{N-1} e^{-2 \pi i nk/N} x_k $
+     * Returns a new instance of this class. The returned transformer uses the
+     * normalizing conventions described below.
      * </p>
+     * <ul>
+     * <li>Forward transform:
+     * y<sub>n</sub> = &sum;<sub>k=0</sub><sup>N-1</sup>
+     * x<sub>k</sub> exp(-2&pi;i n k / N),</li>
+     * <li>Inverse transform:
+     * x<sub>k</sub> = N<sup>-1</sup> &sum;<sub>n=0</sub><sup>N-1</sup>
+     * y<sub>n</sub> exp(2&pi;i n k / N).</li>
+     * </ul>
      *
-     * @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 complex transformed array
-     * @throws IllegalArgumentException if any parameters are invalid
+     * @return a new FFT transformer, with "standard" normalizing conventions
      */
-    public Complex[] transform(UnivariateFunction f,
-                               double min, double max, int n)
-        throws IllegalArgumentException {
-        double[] data = sample(f, min, max, n);
-        return fft(data, false);
+    public static FastFourierTransformer create() {
+        return new FastFourierTransformer(false);
     }
 
     /**
-     * Transform the given complex data set.
      * <p>
-     * The formula is $ y_n = \Sigma_{k=0}^{N-1} e^{-2 \pi i nk/N} x_k $
+     * Returns a new instance of this class. The returned transformer uses the
+     * normalizing conventions described below.
+     * <ul>
+     * <li>Forward transform:
+     * y<sub>n</sub> = N<sup>-1/2</sup> &sum;<sub>k=0</sub><sup>N-1</sup>
+     * x<sub>k</sub> exp(-2&pi;i n k / N),</li>
+     * <li>Inverse transform:
+     * x<sub>k</sub> = N<sup>-1/2</sup> &sum;<sub>n=0</sub><sup>N-1</sup>
+     * y<sub>n</sub> exp(2&pi;i n k / N),</li>
+     * </ul>
+     * which make the transform unitary.
      * </p>
      *
-     * @param f the complex data array to be transformed
-     * @return the complex transformed array
-     * @throws IllegalArgumentException if any parameters are invalid
+     * @return a new FFT transformer, with unitary normalizing conventions
      */
-    public Complex[] transform(Complex[] f)
-        throws IllegalArgumentException {
-        roots.computeOmega(f.length);
-        return fft(f);
+    public static FastFourierTransformer createUnitary() {
+        return new FastFourierTransformer(true);
     }
 
+
     /**
-     * Transform the given real data set.
-     * <p>
-     * The formula is $y_n = (1/\sqrt{N}) \Sigma_{k=0}^{N-1} e^{-2 \pi i nk/N} x_k$
-     * </p>
+     * Returns the forward transform of the specified real data set.
      *
      * @param f the real data array to be transformed
      * @return the complex transformed array
      * @throws IllegalArgumentException if any parameters are invalid
      */
-    public Complex[] transform2(double[] f)
+    public Complex[] transform(double[] f)
         throws IllegalArgumentException {
-
-        double scalingCoefficient = 1.0 / FastMath.sqrt(f.length);
-        return scaleArray(fft(f, false), scalingCoefficient);
+        if (unitary) {
+            final double s = 1.0 / FastMath.sqrt(f.length);
+            return scaleArray(fft(f, false), s);
+        }
+        return fft(f, false);
     }
 
     /**
-     * Transform the given real function, sampled on the given interval.
-     * <p>
-     * The formula is $y_n = (1/\sqrt{N}) \Sigma_{k=0}^{N-1} e^{-2 \pi i nk/N} x_k$
-     * </p>
+     * Returns the forward transform of the specified real function, sampled on
+     * the specified 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 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 transformed array
      * @throws IllegalArgumentException if any parameters are invalid
      */
-    public Complex[] transform2(UnivariateFunction f,
-                                double min, double max, int n)
+    public Complex[] transform(UnivariateFunction f,
+                               double min, double max, int n)
         throws IllegalArgumentException {
-
-        double[] data = sample(f, min, max, n);
-        double scalingCoefficient = 1.0 / FastMath.sqrt(n);
-        return scaleArray(fft(data, false), scalingCoefficient);
+        final double[] data = sample(f, min, max, n);
+        if (unitary) {
+            final double s = 1.0 / FastMath.sqrt(n);
+            return scaleArray(fft(data, false), s);
+        }
+        return fft(data, false);
     }
 
     /**
-     * Transform the given complex data set.
-     * <p>
-     * The formula is $y_n = (1/\sqrt{N}) \Sigma_{k=0}^{N-1} e^{-2 \pi i nk/N} x_k$
-     * </p>
+     * Returns the forward transform of the specified complex data set.
      *
      * @param f the complex data array to be transformed
      * @return the complex transformed array
      * @throws IllegalArgumentException if any parameters are invalid
      */
-    public Complex[] transform2(Complex[] f)
+    public Complex[] transform(Complex[] f)
         throws IllegalArgumentException {
-
         roots.computeOmega(f.length);
-        double scalingCoefficient = 1.0 / FastMath.sqrt(f.length);
-        return scaleArray(fft(f), scalingCoefficient);
+        if (unitary) {
+            final double s = 1.0 / FastMath.sqrt(f.length);
+            return scaleArray(fft(f), s);
+        }
+        return fft(f);
     }
 
     /**
-     * Inversely transform the given real data set.
-     * <p>
-     * The formula is $ x_k = (1/N) \Sigma_{n=0}^{N-1} e^{2 \pi i nk/N} y_n $
-     * </p>
+     * 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
@@ -178,19 +191,17 @@ public class FastFourierTransformer impl
     public Complex[] inverseTransform(double[] f)
         throws IllegalArgumentException {
 
-        double scalingCoefficient = 1.0 / f.length;
-        return scaleArray(fft(f, true), scalingCoefficient);
+        final double s = 1.0 / (unitary ? FastMath.sqrt(f.length) : f.length);
+        return scaleArray(fft(f, true), s);
     }
 
     /**
-     * Inversely transform the given real function, sampled on the given interval.
-     * <p>
-     * The formula is $ x_k = (1/N) \Sigma_{n=0}^{N-1} e^{2 \pi i nk/N} y_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 complex inversely transformed array
      * @throws IllegalArgumentException if any parameters are invalid
@@ -199,16 +210,13 @@ public class FastFourierTransformer impl
                                       double min, double max, int n)
         throws IllegalArgumentException {
 
-        double[] data = sample(f, min, max, n);
-        double scalingCoefficient = 1.0 / n;
-        return scaleArray(fft(data, true), scalingCoefficient);
+        final double[] data = sample(f, min, max, n);
+        final double s = 1.0 / (unitary ? FastMath.sqrt(n) : n);
+        return scaleArray(fft(data, true), s);
     }
 
     /**
-     * Inversely transform the given complex data set.
-     * <p>
-     * The formula is $ x_k = (1/N) \Sigma_{n=0}^{N-1} e^{2 \pi i nk/N} y_n $
-     * </p>
+     * 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
@@ -218,65 +226,8 @@ public class FastFourierTransformer impl
         throws IllegalArgumentException {
 
         roots.computeOmega(-f.length);    // pass negative argument
-        double scalingCoefficient = 1.0 / f.length;
-        return scaleArray(fft(f), scalingCoefficient);
-    }
-
-    /**
-     * Inversely transform the given real data set.
-     * <p>
-     * The formula is $x_k = (1/\sqrt{N}) \Sigma_{n=0}^{N-1} e^{2 \pi i nk/N} y_n$
-     * </p>
-     *
-     * @param f the real data array to be inversely transformed
-     * @return the complex inversely transformed array
-     * @throws IllegalArgumentException if any parameters are invalid
-     */
-    public Complex[] inverseTransform2(double[] f)
-        throws IllegalArgumentException {
-
-        double scalingCoefficient = 1.0 / FastMath.sqrt(f.length);
-        return scaleArray(fft(f, true), scalingCoefficient);
-    }
-
-    /**
-     * Inversely transform the given real function, sampled on the given interval.
-     * <p>
-     * The formula is $x_k = (1/\sqrt{N}) \Sigma_{n=0}^{N-1} e^{2 \pi i nk/N} y_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 complex inversely transformed array
-     * @throws IllegalArgumentException if any parameters are invalid
-     */
-    public Complex[] inverseTransform2(UnivariateFunction f,
-                                       double min, double max, int n)
-        throws IllegalArgumentException {
-
-        double[] data = sample(f, min, max, n);
-        double scalingCoefficient = 1.0 / FastMath.sqrt(n);
-        return scaleArray(fft(data, true), scalingCoefficient);
-    }
-
-    /**
-     * Inversely transform the given complex data set.
-     * <p>
-     * The formula is $x_k = (1/\sqrt{N}) \Sigma_{n=0}^{N-1} e^{2 \pi i nk/N} y_n$
-     * </p>
-     *
-     * @param f the complex data array to be inversely transformed
-     * @return the complex inversely transformed array
-     * @throws IllegalArgumentException if any parameters are invalid
-     */
-    public Complex[] inverseTransform2(Complex[] f)
-        throws IllegalArgumentException {
-
-        roots.computeOmega(-f.length);    // pass negative argument
-        double scalingCoefficient = 1.0 / FastMath.sqrt(f.length);
-        return scaleArray(fft(f), scalingCoefficient);
+        final double s = 1.0 / (unitary ? FastMath.sqrt(f.length) : f.length);
+        return scaleArray(fft(f), s);
     }
 
     /**
@@ -387,10 +338,10 @@ public class FastFourierTransformer impl
                     final double omegaKmImag = roots.getOmegaImaginary(km);
                     //z = f[i+j+k].multiply(omega[k*m]);
                     final Complex z = new Complex(
-                        f[i + j + k].getReal() * omegaKmReal
-                        - f[i + j + k].getImaginary() * omegaKmImag,
-                        f[i + j + k].getReal() * omegaKmImag
-                        + f[i + j + k].getImaginary() * omegaKmReal);
+                        f[i + j + k].getReal() * omegaKmReal -
+                        f[i + j + k].getImaginary() * omegaKmImag,
+                        f[i + j + k].getReal() * omegaKmImag +
+                        f[i + j + k].getImaginary() * omegaKmReal);
 
                     f[i + j + k] = f[j + k].subtract(z);
                     f[j + k] = f[j + k].add(z);
@@ -409,8 +360,8 @@ public class FastFourierTransformer impl
      * require that.</p>
      *
      * @param f the function to be sampled
-     * @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 samples array
      * @throws IllegalArgumentException if any parameters are invalid
@@ -517,17 +468,20 @@ public class FastFourierTransformer impl
     }
 
     /**
-     * Performs a multi-dimensional Fourier transform on a given array.
-     * Use {@link #inverseTransform2(Complex[])} and
-     * {@link #transform2(Complex[])} in a row-column implementation
-     * in any number of dimensions with O(N&times;log(N)) complexity with
-     * N=n<sub>1</sub>&times;n<sub>2</sub>&times;n<sub>3</sub>&times;...&times;n<sub>d</sub>,
-     * n<sub>x</sub>=number of elements in dimension x,
-     * and d=total number of dimensions.
-     *
-     * @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[][][][]
+     * Performs a multi-dimensional Fourier transform on a given array. Use
+     * {@link #transform(Complex[])} and {@link #inverseTransform(Complex[])} in
+     * a row-column implementation in any number of dimensions with
+     * O(N&times;log(N)) complexity with
+     * N = n<sub>1</sub> &times; n<sub>2</sub> &times;n<sub>3</sub>
&times; ...
+     * &times; n<sub>d</sub>, where n<sub>k</sub> is the number
of elements in
+     * dimension k, and d is the total number of dimensions.
+     *
+     * @param mdca Multi-Dimensional Complex Array id est
+     * {@code Complex[][][][]}
+     * @param forward {@link #inverseTransform} is performed if this is
+     * {@code false}
+     * @return transform of {@code mdca} as a Multi-Dimensional Complex Array
+     * id est {@code Complex[][][][]}
      * @throws IllegalArgumentException if any dimension is not a power of two
      */
     public Object mdfft(Object mdca, boolean forward)
@@ -546,7 +500,8 @@ public class FastFourierTransformer impl
      * Performs one dimension of a multi-dimensional Fourier transform.
      *
      * @param mdcm input matrix
-     * @param forward inverseTransform2 is preformed if this is false
+     * @param forward {@link #inverseTransform} is performed if this is
+     * {@code false}
      * @param d index of the dimension to process
      * @param subVector recursion subvector
      * @throws IllegalArgumentException if any dimension is not a power of two
@@ -565,9 +520,9 @@ public class FastFourierTransformer impl
             }
 
             if (forward) {
-                temp = transform2(temp);
+                temp = transform(temp);
             } else {
-                temp = inverseTransform2(temp);
+                temp = inverseTransform(temp);
             }
 
             for (int i = 0; i < dimensionSize[d]; i++) {
@@ -842,10 +797,10 @@ public class FastFourierTransformer impl
         omegaImaginaryForward[0] = 0.0;
         omegaImaginaryInverse[0] = 0.0;
         for (int i = 1; i < absN; i++) {
-          omegaReal[i] = omegaReal[i - 1] * cosT
-                         + omegaImaginaryForward[i - 1] * sinT;
-          omegaImaginaryForward[i] = omegaImaginaryForward[i - 1] * cosT
-                                     - omegaReal[i - 1] * sinT;
+          omegaReal[i] = omegaReal[i - 1] * cosT +
+                         omegaImaginaryForward[i - 1] * sinT;
+          omegaImaginaryForward[i] = omegaImaginaryForward[i - 1] * cosT -
+                                     omegaReal[i - 1] * sinT;
           omegaImaginaryInverse[i] = -omegaImaginaryForward[i];
         }
         omegaCount = absN;

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/transform/FastSineTransformer.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/transform/FastSineTransformer.java?rev=1211318&r1=1211317&r2=1211318&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/transform/FastSineTransformer.java
(original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/transform/FastSineTransformer.java
Wed Dec  7 07:35:09 2011
@@ -227,7 +227,7 @@ public class FastSineTransformer impleme
             x[i]     = a + b;
             x[n - i] = a - b;
         }
-        FastFourierTransformer transformer = new FastFourierTransformer();
+        FastFourierTransformer transformer = FastFourierTransformer.create();
         Complex[] y = transformer.transform(x);
 
         // reconstruct the FST result for the original array



Mime
View raw message