001: /*
002: * Copyright 2003-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.math.distribution;
017:
018: import java.io.Serializable;
019:
020: import org.apache.commons.math.MathException;
021: import org.apache.commons.math.special.Beta;
022:
023: /**
024: * Default implementation of
025: * {@link org.apache.commons.math.distribution.FDistribution}.
026: *
027: * @version $Revision: 348519 $ $Date: 2005-11-23 12:12:18 -0700 (Wed, 23 Nov 2005) $
028: */
029: public class FDistributionImpl extends AbstractContinuousDistribution
030: implements FDistribution, Serializable {
031:
032: /** Serializable version identifier */
033: private static final long serialVersionUID = -8516354193418641566L;
034:
035: /** The numerator degrees of freedom*/
036: private double numeratorDegreesOfFreedom;
037:
038: /** The numerator degrees of freedom*/
039: private double denominatorDegreesOfFreedom;
040:
041: /**
042: * Create a F distribution using the given degrees of freedom.
043: * @param numeratorDegreesOfFreedom the numerator degrees of freedom.
044: * @param denominatorDegreesOfFreedom the denominator degrees of freedom.
045: */
046: public FDistributionImpl(double numeratorDegreesOfFreedom,
047: double denominatorDegreesOfFreedom) {
048: super ();
049: setNumeratorDegreesOfFreedom(numeratorDegreesOfFreedom);
050: setDenominatorDegreesOfFreedom(denominatorDegreesOfFreedom);
051: }
052:
053: /**
054: * For this disbution, X, this method returns P(X < x).
055: *
056: * The implementation of this method is based on:
057: * <ul>
058: * <li>
059: * <a href="http://mathworld.wolfram.com/F-Distribution.html">
060: * F-Distribution</a>, equation (4).</li>
061: * </ul>
062: *
063: * @param x the value at which the CDF is evaluated.
064: * @return CDF for this distribution.
065: * @throws MathException if the cumulative probability can not be
066: * computed due to convergence or other numerical errors.
067: */
068: public double cumulativeProbability(double x) throws MathException {
069: double ret;
070: if (x <= 0.0) {
071: ret = 0.0;
072: } else {
073: double n = getNumeratorDegreesOfFreedom();
074: double m = getDenominatorDegreesOfFreedom();
075:
076: ret = Beta.regularizedBeta((n * x) / (m + n * x), 0.5 * n,
077: 0.5 * m);
078: }
079: return ret;
080: }
081:
082: /**
083: * For this distribution, X, this method returns the critical point x, such
084: * that P(X < x) = <code>p</code>.
085: * <p>
086: * Returns 0 for p=0 and <code>Double.POSITIVE_INFINITY</code> for p=1.
087: *
088: * @param p the desired probability
089: * @return x, such that P(X < x) = <code>p</code>
090: * @throws MathException if the inverse cumulative probability can not be
091: * computed due to convergence or other numerical errors.
092: * @throws IllegalArgumentException if <code>p</code> is not a valid
093: * probability.
094: */
095: public double inverseCumulativeProbability(final double p)
096: throws MathException {
097: if (p == 0) {
098: return 0d;
099: }
100: if (p == 1) {
101: return Double.POSITIVE_INFINITY;
102: }
103: return super .inverseCumulativeProbability(p);
104: }
105:
106: /**
107: * Access the domain value lower bound, based on <code>p</code>, used to
108: * bracket a CDF root. This method is used by
109: * {@link #inverseCumulativeProbability(double)} to find critical values.
110: *
111: * @param p the desired probability for the critical value
112: * @return domain value lower bound, i.e.
113: * P(X < <i>lower bound</i>) < <code>p</code>
114: */
115: protected double getDomainLowerBound(double p) {
116: return 0.0;
117: }
118:
119: /**
120: * Access the domain value upper bound, based on <code>p</code>, used to
121: * bracket a CDF root. This method is used by
122: * {@link #inverseCumulativeProbability(double)} to find critical values.
123: *
124: * @param p the desired probability for the critical value
125: * @return domain value upper bound, i.e.
126: * P(X < <i>upper bound</i>) > <code>p</code>
127: */
128: protected double getDomainUpperBound(double p) {
129: return Double.MAX_VALUE;
130: }
131:
132: /**
133: * Access the initial domain value, based on <code>p</code>, used to
134: * bracket a CDF root. This method is used by
135: * {@link #inverseCumulativeProbability(double)} to find critical values.
136: *
137: * @param p the desired probability for the critical value
138: * @return initial domain value
139: */
140: protected double getInitialDomain(double p) {
141: return getDenominatorDegreesOfFreedom()
142: / (getDenominatorDegreesOfFreedom() - 2.0);
143: }
144:
145: /**
146: * Modify the numerator degrees of freedom.
147: * @param degreesOfFreedom the new numerator degrees of freedom.
148: * @throws IllegalArgumentException if <code>degreesOfFreedom</code> is not
149: * positive.
150: */
151: public void setNumeratorDegreesOfFreedom(double degreesOfFreedom) {
152: if (degreesOfFreedom <= 0.0) {
153: throw new IllegalArgumentException(
154: "degrees of freedom must be positive.");
155: }
156: this .numeratorDegreesOfFreedom = degreesOfFreedom;
157: }
158:
159: /**
160: * Access the numerator degrees of freedom.
161: * @return the numerator degrees of freedom.
162: */
163: public double getNumeratorDegreesOfFreedom() {
164: return numeratorDegreesOfFreedom;
165: }
166:
167: /**
168: * Modify the denominator degrees of freedom.
169: * @param degreesOfFreedom the new denominator degrees of freedom.
170: * @throws IllegalArgumentException if <code>degreesOfFreedom</code> is not
171: * positive.
172: */
173: public void setDenominatorDegreesOfFreedom(double degreesOfFreedom) {
174: if (degreesOfFreedom <= 0.0) {
175: throw new IllegalArgumentException(
176: "degrees of freedom must be positive.");
177: }
178: this .denominatorDegreesOfFreedom = degreesOfFreedom;
179: }
180:
181: /**
182: * Access the denominator degrees of freedom.
183: * @return the denominator degrees of freedom.
184: */
185: public double getDenominatorDegreesOfFreedom() {
186: return denominatorDegreesOfFreedom;
187: }
188: }
|