View Javadoc

    1   /*
    2    * Copyright 2003-2004 The Apache Software Foundation.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *      http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  package org.apache.commons.math.distribution;
    17
    18  import java.io.Serializable;
    19
    20  import org.apache.commons.math.MathException;
    21  import org.apache.commons.math.special.Beta;
    22
    23  /***
    24   * Default implementation of
    25   * {@link org.apache.commons.math.distribution.FDistribution}.
    26   *
    27   * @version $Revision: 1.19 $ $Date: 2004/07/24 21:41:36 $
    28   */
    29  public class FDistributionImpl
    30      extends AbstractContinuousDistribution
    31      implements FDistribution, Serializable  {
    32
    33      /*** Serializable version identifier */
    34      static final long serialVersionUID = -8516354193418641566L;
    35
    36      /*** The numerator degrees of freedom*/
    37      private double numeratorDegreesOfFreedom;
    38
    39      /*** The numerator degrees of freedom*/
    40      private double denominatorDegreesOfFreedom;
    41
    42      /***
    43       * Create a F distribution using the given degrees of freedom.
    44       * @param numeratorDegreesOfFreedom the numerator degrees of freedom.
    45       * @param denominatorDegreesOfFreedom the denominator degrees of freedom.
    46       */
    47      public FDistributionImpl(double numeratorDegreesOfFreedom,
    48              double denominatorDegreesOfFreedom) {
    49          super();
    50          setNumeratorDegreesOfFreedom(numeratorDegreesOfFreedom);
    51          setDenominatorDegreesOfFreedom(denominatorDegreesOfFreedom);
    52      }
    53
    54      /***
    55       * For this disbution, X, this method returns P(X &lt; x).
    56       *
    57       * The implementation of this method is based on:
    58       * <ul>
    59       * <li>
    60       * <a href="http://mathworld.wolfram.com/F-Distribution.html">
    61       * F-Distribution</a>, equation (4).</li>
    62       * </ul>
    63       *
    64       * @param x the value at which the CDF is evaluated.
    65       * @return CDF for this distribution.
    66       * @throws MathException if the cumulative probability can not be
    67       *            computed due to convergence or other numerical errors.
    68       */
    69      public double cumulativeProbability(double x) throws MathException {
    70          double ret;
    71          if (x <= 0.0) {
    72              ret = 0.0;
    73          } else {
    74              double n = getNumeratorDegreesOfFreedom();
    75              double m = getDenominatorDegreesOfFreedom();
    76
    77              ret = Beta.regularizedBeta((n * x) / (m + n * x),
    78                  0.5 * n,
    79                  0.5 * m);
    80          }
    81          return ret;
    82      }
    83
    84      /***
    85       * For this distribution, X, this method returns the critical point x, such
    86       * that P(X &lt; x) = <code>p</code>.
    87       * <p>
    88       * Returns 0 for p=0 and <code>Double.POSITIVE_INFINITY</code> for p=1.
    89       *
    90       * @param p the desired probability
    91       * @return x, such that P(X &lt; x) = <code>p</code>
    92       * @throws MathException if the inverse cumulative probability can not be
    93       *         computed due to convergence or other numerical errors.
    94       * @throws IllegalArgumentException if <code>p</code> is not a valid
    95       *         probability.
    96       */
    97      public double inverseCumulativeProbability(final double p)
    98          throws MathException {
    99          if (p == 0) {
    100             return 0d;
    101         }
    102         if (p == 1) {
    103             return Double.POSITIVE_INFINITY;
    104         }
    105         return super.inverseCumulativeProbability(p);
    106     }
    107
    108     /***
    109      * Access the domain value lower bound, based on <code>p</code>, used to
    110      * bracket a CDF root.  This method is used by
    111      * {@link #inverseCumulativeProbability(double)} to find critical values.
    112      *
    113      * @param p the desired probability for the critical value
    114      * @return domain value lower bound, i.e.
    115      *         P(X &lt; <i>lower bound</i>) &lt; <code>p</code>
    116      */
    117     protected double getDomainLowerBound(double p) {
    118         return 0.0;
    119     }
    120
    121     /***
    122      * Access the domain value upper bound, based on <code>p</code>, used to
    123      * bracket a CDF root.  This method is used by
    124      * {@link #inverseCumulativeProbability(double)} to find critical values.
    125      *
    126      * @param p the desired probability for the critical value
    127      * @return domain value upper bound, i.e.
    128      *         P(X &lt; <i>upper bound</i>) &gt; <code>p</code>
    129      */
    130     protected double getDomainUpperBound(double p) {
    131         return Double.MAX_VALUE;
    132     }
    133
    134     /***
    135      * Access the initial domain value, based on <code>p</code>, used to
    136      * bracket a CDF root.  This method is used by
    137      * {@link #inverseCumulativeProbability(double)} to find critical values.
    138      *
    139      * @param p the desired probability for the critical value
    140      * @return initial domain value
    141      */
    142     protected double getInitialDomain(double p) {
    143         return getDenominatorDegreesOfFreedom() /
    144             (getDenominatorDegreesOfFreedom() - 2.0);
    145     }
    146
    147     /***
    148      * Modify the numerator degrees of freedom.
    149      * @param degreesOfFreedom the new numerator degrees of freedom.
    150      * @throws IllegalArgumentException if <code>degreesOfFreedom</code> is not
    151      *         positive.
    152      */
    153     public void setNumeratorDegreesOfFreedom(double degreesOfFreedom) {
    154         if (degreesOfFreedom <= 0.0) {
    155             throw new IllegalArgumentException(
    156                 "degrees of freedom must be positive.");
    157         }
    158         this.numeratorDegreesOfFreedom = degreesOfFreedom;
    159     }
    160
    161     /***
    162      * Access the numerator degrees of freedom.
    163      * @return the numerator degrees of freedom.
    164      */
    165     public double getNumeratorDegreesOfFreedom() {
    166         return numeratorDegreesOfFreedom;
    167     }
    168
    169     /***
    170      * Modify the denominator degrees of freedom.
    171      * @param degreesOfFreedom the new denominator degrees of freedom.
    172      * @throws IllegalArgumentException if <code>degreesOfFreedom</code> is not
    173      *         positive.
    174      */
    175     public void setDenominatorDegreesOfFreedom(double degreesOfFreedom) {
    176         if (degreesOfFreedom <= 0.0) {
    177             throw new IllegalArgumentException(
    178                 "degrees of freedom must be positive.");
    179         }
    180         this.denominatorDegreesOfFreedom = degreesOfFreedom;
    181     }
    182
    183     /***
    184      * Access the denominator degrees of freedom.
    185      * @return the denominator degrees of freedom.
    186      */
    187     public double getDenominatorDegreesOfFreedom() {
    188         return denominatorDegreesOfFreedom;
    189     }
    190 }