Author: brentworden
Date: Thu Sep 25 20:09:53 2008
New Revision: 699157

URL: http://svn.apache.org/viewvc?rev=699157&view=rev
Log:
MATH-227.  fixed F distribution inverse CDF computation for small denominator 
degrees of freedom.

Modified:
    
commons/proper/math/trunk/src/java/org/apache/commons/math/distribution/FDistributionImpl.java
    commons/proper/math/trunk/src/site/xdoc/changes.xml
    
commons/proper/math/trunk/src/test/org/apache/commons/math/distribution/FDistributionTest.java

Modified: 
commons/proper/math/trunk/src/java/org/apache/commons/math/distribution/FDistributionImpl.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/distribution/FDistributionImpl.java?rev=699157&r1=699156&r2=699157&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/java/org/apache/commons/math/distribution/FDistributionImpl.java
 (original)
+++ 
commons/proper/math/trunk/src/java/org/apache/commons/math/distribution/FDistributionImpl.java
 Thu Sep 25 20:09:53 2008
@@ -24,168 +24,188 @@
 /**
  * Default implementation of
  * [EMAIL PROTECTED] org.apache.commons.math.distribution.FDistribution}.
- *
- * @version $Revision$ $Date$
+ * 
+ * @version $Revision$ $Date: 2008-02-08 09:44:11 -0600 (Fri, 08 Feb
+ *          2008) $
  */
-public class FDistributionImpl
-    extends AbstractContinuousDistribution
-    implements FDistribution, Serializable  {
-
-    /** Serializable version identifier */
-    private static final long serialVersionUID = -8516354193418641566L;
-
-    /** The numerator degrees of freedom*/
-    private double numeratorDegreesOfFreedom;
-
-    /** The numerator degrees of freedom*/
-    private double denominatorDegreesOfFreedom;
-    
-    /**
-     * Create a F distribution using the given degrees of freedom.
-     * @param numeratorDegreesOfFreedom the numerator degrees of freedom.
-     * @param denominatorDegreesOfFreedom the denominator degrees of freedom.
-     */
-    public FDistributionImpl(double numeratorDegreesOfFreedom,
-            double denominatorDegreesOfFreedom) {
-        super();
-        setNumeratorDegreesOfFreedom(numeratorDegreesOfFreedom);
-        setDenominatorDegreesOfFreedom(denominatorDegreesOfFreedom);
-    }
-    
-    /**
-     * For this distribution, X, this method returns P(X < x).
-     * 
-     * The implementation of this method is based on:
-     * <ul>
-     * <li>
-     * <a href="http://mathworld.wolfram.com/F-Distribution.html";>
-     * F-Distribution</a>, equation (4).</li>
-     * </ul>
-     * 
-     * @param x the value at which the CDF is evaluated.
-     * @return CDF for this distribution. 
-     * @throws MathException if the cumulative probability can not be
-     *            computed due to convergence or other numerical errors.
-     */
-    public double cumulativeProbability(double x) throws MathException {
-        double ret;
-        if (x <= 0.0) {
-            ret = 0.0;
-        } else {
-            double n = getNumeratorDegreesOfFreedom();
-            double m = getDenominatorDegreesOfFreedom();
-            
-            ret = Beta.regularizedBeta((n * x) / (m + n * x),
-                0.5 * n,
-                0.5 * m);
-        }
-        return ret;
-    }
-    
-    /**
-     * For this distribution, X, this method returns the critical point x, such
-     * that P(X &lt; x) = <code>p</code>.
-     * <p>
-     * Returns 0 for p=0 and <code>Double.POSITIVE_INFINITY</code> for p=1.</p>
-     *
-     * @param p the desired probability
-     * @return x, such that P(X &lt; x) = <code>p</code>
-     * @throws MathException if the inverse cumulative probability can not be
-     *         computed due to convergence or other numerical errors.
-     * @throws IllegalArgumentException if <code>p</code> is not a valid
-     *         probability.
-     */
-    public double inverseCumulativeProbability(final double p) 
-        throws MathException {
-        if (p == 0) {
-            return 0d;
-        }
-        if (p == 1) {
-            return Double.POSITIVE_INFINITY;
-        }
-        return super.inverseCumulativeProbability(p);
-    }
-        
-    /**
-     * Access the domain value lower bound, based on <code>p</code>, used to
-     * bracket a CDF root.  This method is used by
-     * [EMAIL PROTECTED] #inverseCumulativeProbability(double)} to find 
critical values.
-     * 
-     * @param p the desired probability for the critical value
-     * @return domain value lower bound, i.e.
-     *         P(X &lt; <i>lower bound</i>) &lt; <code>p</code> 
-     */
-    protected double getDomainLowerBound(double p) {
-        return 0.0;
-    }
-
-    /**
-     * Access the domain value upper bound, based on <code>p</code>, used to
-     * bracket a CDF root.  This method is used by
-     * [EMAIL PROTECTED] #inverseCumulativeProbability(double)} to find 
critical values.
-     * 
-     * @param p the desired probability for the critical value
-     * @return domain value upper bound, i.e.
-     *         P(X &lt; <i>upper bound</i>) &gt; <code>p</code> 
-     */
-    protected double getDomainUpperBound(double p) {
-        return Double.MAX_VALUE;
-    }
-
-    /**
-     * Access the initial domain value, based on <code>p</code>, used to
-     * bracket a CDF root.  This method is used by
-     * [EMAIL PROTECTED] #inverseCumulativeProbability(double)} to find 
critical values.
-     * 
-     * @param p the desired probability for the critical value
-     * @return initial domain value
-     */
-    protected double getInitialDomain(double p) {
-        return getDenominatorDegreesOfFreedom() /
-            (getDenominatorDegreesOfFreedom() - 2.0);
-    }
-    
-    /**
-     * Modify the numerator degrees of freedom.
-     * @param degreesOfFreedom the new numerator degrees of freedom.
-     * @throws IllegalArgumentException if <code>degreesOfFreedom</code> is not
-     *         positive.
-     */
-    public void setNumeratorDegreesOfFreedom(double degreesOfFreedom) {
-        if (degreesOfFreedom <= 0.0) {
-            throw new IllegalArgumentException(
-                "degrees of freedom must be positive.");
-        }
-        this.numeratorDegreesOfFreedom = degreesOfFreedom;
-    }
-    
-    /**
-     * Access the numerator degrees of freedom.
-     * @return the numerator degrees of freedom.
-     */
-    public double getNumeratorDegreesOfFreedom() {
-        return numeratorDegreesOfFreedom;
-    }
-    
-    /**
-     * Modify the denominator degrees of freedom.
-     * @param degreesOfFreedom the new denominator degrees of freedom.
-     * @throws IllegalArgumentException if <code>degreesOfFreedom</code> is not
-     *         positive.
-     */
-    public void setDenominatorDegreesOfFreedom(double degreesOfFreedom) {
-        if (degreesOfFreedom <= 0.0) {
-            throw new IllegalArgumentException(
-                "degrees of freedom must be positive.");
-        }
-        this.denominatorDegreesOfFreedom = degreesOfFreedom;
-    }
-    
-    /**
-     * Access the denominator degrees of freedom.
-     * @return the denominator degrees of freedom.
-     */
-    public double getDenominatorDegreesOfFreedom() {
-        return denominatorDegreesOfFreedom;
-    }
+public class FDistributionImpl extends AbstractContinuousDistribution 
implements
+               FDistribution, Serializable {
+
+       /** Serializable version identifier */
+       private static final long serialVersionUID = -8516354193418641566L;
+
+       /** The numerator degrees of freedom */
+       private double numeratorDegreesOfFreedom;
+
+       /** The numerator degrees of freedom */
+       private double denominatorDegreesOfFreedom;
+
+       /**
+        * Create a F distribution using the given degrees of freedom.
+        * 
+        * @param numeratorDegreesOfFreedom
+        *            the numerator degrees of freedom.
+        * @param denominatorDegreesOfFreedom
+        *            the denominator degrees of freedom.
+        */
+       public FDistributionImpl(double numeratorDegreesOfFreedom,
+                       double denominatorDegreesOfFreedom) {
+               super();
+               setNumeratorDegreesOfFreedom(numeratorDegreesOfFreedom);
+               setDenominatorDegreesOfFreedom(denominatorDegreesOfFreedom);
+       }
+
+       /**
+        * For this distribution, X, this method returns P(X &lt; x).
+        * 
+        * The implementation of this method is based on:
+        * <ul>
+        * <li>
+        * <a href="http://mathworld.wolfram.com/F-Distribution.html";>
+        * F-Distribution</a>, equation (4).</li>
+        * </ul>
+        * 
+        * @param x
+        *            the value at which the CDF is evaluated.
+        * @return CDF for this distribution.
+        * @throws MathException
+        *             if the cumulative probability can not be computed due to
+        *             convergence or other numerical errors.
+        */
+       public double cumulativeProbability(double x) throws MathException {
+               double ret;
+               if (x <= 0.0) {
+                       ret = 0.0;
+               } else {
+                       double n = getNumeratorDegreesOfFreedom();
+                       double m = getDenominatorDegreesOfFreedom();
+
+                       ret = Beta.regularizedBeta((n * x) / (m + n * x), 0.5 * 
n, 0.5 * m);
+               }
+               return ret;
+       }
+
+       /**
+        * For this distribution, X, this method returns the critical point x, 
such
+        * that P(X &lt; x) = <code>p</code>.
+        * <p>
+        * Returns 0 for p=0 and <code>Double.POSITIVE_INFINITY</code> for p=1.
+        * </p>
+        * 
+        * @param p
+        *            the desired probability
+        * @return x, such that P(X &lt; x) = <code>p</code>
+        * @throws MathException
+        *             if the inverse cumulative probability can not be 
computed due
+        *             to convergence or other numerical errors.
+        * @throws IllegalArgumentException
+        *             if <code>p</code> is not a valid probability.
+        */
+       public double inverseCumulativeProbability(final double p)
+                       throws MathException {
+               if (p == 0) {
+                       return 0d;
+               }
+               if (p == 1) {
+                       return Double.POSITIVE_INFINITY;
+               }
+               return super.inverseCumulativeProbability(p);
+       }
+
+       /**
+        * Access the domain value lower bound, based on <code>p</code>, used to
+        * bracket a CDF root. This method is used by
+        * [EMAIL PROTECTED] #inverseCumulativeProbability(double)} to find 
critical values.
+        * 
+        * @param p
+        *            the desired probability for the critical value
+        * @return domain value lower bound, i.e. P(X &lt; <i>lower bound</i>) 
&lt;
+        *         <code>p</code>
+        */
+       protected double getDomainLowerBound(double p) {
+               return 0.0;
+       }
+
+       /**
+        * Access the domain value upper bound, based on <code>p</code>, used to
+        * bracket a CDF root. This method is used by
+        * [EMAIL PROTECTED] #inverseCumulativeProbability(double)} to find 
critical values.
+        * 
+        * @param p
+        *            the desired probability for the critical value
+        * @return domain value upper bound, i.e. P(X &lt; <i>upper bound</i>) 
&gt;
+        *         <code>p</code>
+        */
+       protected double getDomainUpperBound(double p) {
+               return Double.MAX_VALUE;
+       }
+
+       /**
+        * Access the initial domain value, based on <code>p</code>, used to 
bracket
+        * a CDF root. This method is used by
+        * [EMAIL PROTECTED] #inverseCumulativeProbability(double)} to find 
critical values.
+        * 
+        * @param p
+        *            the desired probability for the critical value
+        * @return initial domain value
+        */
+       protected double getInitialDomain(double p) {
+               double ret = 1.0;
+               double d = getDenominatorDegreesOfFreedom();
+               if (d > 2.0) {
+                       // use mean
+                       ret = d / (d - 2.0);
+               }
+               return ret;
+       }
+
+       /**
+        * Modify the numerator degrees of freedom.
+        * 
+        * @param degreesOfFreedom
+        *            the new numerator degrees of freedom.
+        * @throws IllegalArgumentException
+        *             if <code>degreesOfFreedom</code> is not positive.
+        */
+       public void setNumeratorDegreesOfFreedom(double degreesOfFreedom) {
+               if (degreesOfFreedom <= 0.0) {
+                       throw new IllegalArgumentException(
+                                       "degrees of freedom must be positive.");
+               }
+               this.numeratorDegreesOfFreedom = degreesOfFreedom;
+       }
+
+       /**
+        * Access the numerator degrees of freedom.
+        * 
+        * @return the numerator degrees of freedom.
+        */
+       public double getNumeratorDegreesOfFreedom() {
+               return numeratorDegreesOfFreedom;
+       }
+
+       /**
+        * Modify the denominator degrees of freedom.
+        * 
+        * @param degreesOfFreedom
+        *            the new denominator degrees of freedom.
+        * @throws IllegalArgumentException
+        *             if <code>degreesOfFreedom</code> is not positive.
+        */
+       public void setDenominatorDegreesOfFreedom(double degreesOfFreedom) {
+               if (degreesOfFreedom <= 0.0) {
+                       throw new IllegalArgumentException(
+                                       "degrees of freedom must be positive.");
+               }
+               this.denominatorDegreesOfFreedom = degreesOfFreedom;
+       }
+
+       /**
+        * Access the denominator degrees of freedom.
+        * 
+        * @return the denominator degrees of freedom.
+        */
+       public double getDenominatorDegreesOfFreedom() {
+               return denominatorDegreesOfFreedom;
+       }
 }

Modified: commons/proper/math/trunk/src/site/xdoc/changes.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/site/xdoc/changes.xml?rev=699157&r1=699156&r2=699157&view=diff
==============================================================================
--- commons/proper/math/trunk/src/site/xdoc/changes.xml (original)
+++ commons/proper/math/trunk/src/site/xdoc/changes.xml Thu Sep 25 20:09:53 2008
@@ -65,6 +65,9 @@
       <action dev="brentworden" type="fix" issue="MATH-204" due-to="Mick">
         Added root checks for the endpoints.
       </action>
+      <action dev="brentworden" type="fix" issue="MATH-227" due-to="Joerg 
Henning">
+        Fixed F distribution inverse CDF computation for small denominator 
degrees of freedom.
+      </action>
     </release>
     <release version="1.2" date="2008-02-24"
     description="This release combines bug fixes and new features. Most notable

Modified: 
commons/proper/math/trunk/src/test/org/apache/commons/math/distribution/FDistributionTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/org/apache/commons/math/distribution/FDistributionTest.java?rev=699157&r1=699156&r2=699157&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/test/org/apache/commons/math/distribution/FDistributionTest.java
 (original)
+++ 
commons/proper/math/trunk/src/test/org/apache/commons/math/distribution/FDistributionTest.java
 Thu Sep 25 20:09:53 2008
@@ -105,4 +105,18 @@
         double x = fd.inverseCumulativeProbability(p);
         assertEquals(.999, x, 1.0e-5);
     }
+
+    public void testSmallDegreesOfFreedom() throws Exception {
+        org.apache.commons.math.distribution.FDistributionImpl fd =
+            new org.apache.commons.math.distribution.FDistributionImpl(
+                1.0, 1.0);
+        double p = fd.cumulativeProbability(0.975);
+        double x = fd.inverseCumulativeProbability(p);
+        assertEquals(0.975, x, 1.0e-5);
+
+        fd.setDenominatorDegreesOfFreedom(2.0);
+        p = fd.cumulativeProbability(0.975);
+        x = fd.inverseCumulativeProbability(p);
+        assertEquals(0.975, x, 1.0e-5);
+    }
 }


Reply via email to