Author: erans
Date: Fri Aug 17 15:09:59 2012
New Revision: 1374308

URL: http://svn.apache.org/viewvc?rev=1374308&view=rev
Log:
Code cleanup: moved all computations to the constructor, allowing to make
the class immutable.

Modified:
    
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/fitting/HarmonicFitter.java
    
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/HarmonicFitterTest.java

Modified: 
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/fitting/HarmonicFitter.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/fitting/HarmonicFitter.java?rev=1374308&r1=1374307&r2=1374308&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/fitting/HarmonicFitter.java
 (original)
+++ 
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optimization/fitting/HarmonicFitter.java
 Fri Aug 17 15:09:59 2012
@@ -177,20 +177,21 @@ public class HarmonicFitter extends Curv
      * number of measurements.</p>
      */
     public static class ParameterGuesser {
-        /** Sampled observations. */
-        private final WeightedObservedPoint[] observations;
         /** Amplitude. */
-        private double a;
+        private final double a;
         /** Angular frequency. */
-        private double omega;
+        private final double omega;
         /** Phase. */
-        private double phi;
+        private final double phi;
 
         /**
          * Simple constructor.
-         * @param observations sampled observations
-         * @throws NumberIsTooSmallException if the sample is too short or if
-         * the first guess cannot be computed.
+         *
+         * @param observations Sampled observations.
+         * @throws NumberIsTooSmallException if the sample is too short.
+         * @throws ZeroException if the abscissa range is zero.
+         * @throws MathIllegalStateException when the guessing procedure cannot
+         * produce sensible results.
          */
         public ParameterGuesser(WeightedObservedPoint[] observations) {
             if (observations.length < 4) {
@@ -198,7 +199,13 @@ public class HarmonicFitter extends Curv
                                                     observations.length, 4, 
true);
             }
 
-            this.observations = observations.clone();
+            final WeightedObservedPoint[] sorted = 
sortObservations(observations);
+
+            final double aOmega[] = guessAOmega(sorted);
+            a = aOmega[0];
+            omega = aOmega[1];
+
+            phi = guessPhi(sorted);
         }
 
         /**
@@ -212,16 +219,18 @@ public class HarmonicFitter extends Curv
          * </ul>
          */
         public double[] guess() {
-            sortObservations();
-            guessAOmega();
-            guessPhi();
             return new double[] { a, omega, phi };
         }
 
         /**
          * Sort the observations with respect to the abscissa.
+         *
+         * @param unsorted Input observations.
+         * @return the input observations, sorted.
          */
-        private void sortObservations() {
+        private WeightedObservedPoint[] 
sortObservations(WeightedObservedPoint[] unsorted) {
+            final WeightedObservedPoint[] observations = unsorted.clone();
+
             // Since the samples are almost always already sorted, this
             // method is implemented as an insertion sort that reorders the
             // elements in place. Insertion sort is very efficient in this 
case.
@@ -243,6 +252,8 @@ public class HarmonicFitter extends Curv
                     curr = observations[j];
                 }
             }
+
+            return observations;
         }
 
         /**
@@ -250,11 +261,16 @@ public class HarmonicFitter extends Curv
          * This method assumes that the {@link #sortObservations()} method
          * has been called previously.
          *
+         * @param observations Observations, sorted w.r.t. abscissa.
          * @throws ZeroException if the abscissa range is zero.
          * @throws MathIllegalStateException when the guessing procedure cannot
          * produce sensible results.
+         * @return the guessed amplitude (at index 0) and circular frequency
+         * (at index 1).
          */
-        private void guessAOmega() {
+        private double[] guessAOmega(WeightedObservedPoint[] observations) {
+            final double[] aOmega = new double[2];
+
             // initialize the sums for the linear model between the two 
integrals
             double sx2 = 0;
             double sy2 = 0;
@@ -305,7 +321,7 @@ public class HarmonicFitter extends Curv
                 if (xRange == 0) {
                     throw new ZeroException();
                 }
-                omega = 2 * Math.PI / xRange;
+                aOmega[1] = 2 * Math.PI / xRange;
 
                 double yMin = Double.POSITIVE_INFINITY;
                 double yMax = Double.NEGATIVE_INFINITY;
@@ -318,7 +334,7 @@ public class HarmonicFitter extends Curv
                         yMax = y;
                     }
                 }
-                a = 0.5 * (yMax - yMin);
+                aOmega[0] = 0.5 * (yMax - yMin);
             } else {
                 if (c2 == 0) {
                     // In some ill-conditioned cases (cf. MATH-844), the 
guesser
@@ -326,15 +342,20 @@ public class HarmonicFitter extends Curv
                     throw new 
MathIllegalStateException(LocalizedFormats.ZERO_DENOMINATOR);
                 }
 
-                a = FastMath.sqrt(c1 / c2);
-                omega = FastMath.sqrt(c2 / c3);
+                aOmega[0] = FastMath.sqrt(c1 / c2);
+                aOmega[1] = FastMath.sqrt(c2 / c3);
             }
+
+            return aOmega;
         }
 
         /**
          * Estimate a first guess of the phase.
+         *
+         * @param observations Observations, sorted w.r.t. abscissa.
+         * @return the guessed phase.
          */
-        private void guessPhi() {
+        private double guessPhi(WeightedObservedPoint[] observations) {
             // initialize the means
             double fcMean = 0;
             double fsMean = 0;
@@ -356,7 +377,7 @@ public class HarmonicFitter extends Curv
                 fsMean += omega * currentY * sine + currentYPrime * cosine;
             }
 
-            phi = FastMath.atan2(-fsMean, fcMean);
+            return FastMath.atan2(-fsMean, fcMean);
         }
     }
 }

Modified: 
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/HarmonicFitterTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/HarmonicFitterTest.java?rev=1374308&r1=1374307&r2=1374308&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/HarmonicFitterTest.java
 (original)
+++ 
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/optimization/fitting/HarmonicFitterTest.java
 Fri Aug 17 15:09:59 2012
@@ -191,14 +191,12 @@ public class HarmonicFitterTest {
             points[i] = new WeightedObservedPoint(1, i, y[i]);
         }
 
-        final HarmonicFitter.ParameterGuesser guesser
-            = new HarmonicFitter.ParameterGuesser(points);
-
         // The guesser fails because the function is far from an harmonic
         // function: It is a triangular periodic function with amplitude 3
         // and period 12, and all sample points are taken at integer abscissae
         // so function values all belong to the integer subset {-3, -2, -1, 0,
         // 1, 2, 3}.
-        guesser.guess();
+        final HarmonicFitter.ParameterGuesser guesser
+            = new HarmonicFitter.ParameterGuesser(points);
     }
 }


Reply via email to