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