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.TDistribution}.
026: *
027: * @version $Revision: 348519 $ $Date: 2005-11-23 12:12:18 -0700 (Wed, 23 Nov 2005) $
028: */
029: public class TDistributionImpl extends AbstractContinuousDistribution
030: implements TDistribution, Serializable {
031:
032: /** Serializable version identifier */
033: private static final long serialVersionUID = -5852615386664158222L;
034:
035: /** The degrees of freedom*/
036: private double degreesOfFreedom;
037:
038: /**
039: * Create a t distribution using the given degrees of freedom.
040: * @param degreesOfFreedom the degrees of freedom.
041: */
042: public TDistributionImpl(double degreesOfFreedom) {
043: super ();
044: setDegreesOfFreedom(degreesOfFreedom);
045: }
046:
047: /**
048: * Modify the degrees of freedom.
049: * @param degreesOfFreedom the new degrees of freedom.
050: */
051: public void setDegreesOfFreedom(double degreesOfFreedom) {
052: if (degreesOfFreedom <= 0.0) {
053: throw new IllegalArgumentException(
054: "degrees of freedom must be positive.");
055: }
056: this .degreesOfFreedom = degreesOfFreedom;
057: }
058:
059: /**
060: * Access the degrees of freedom.
061: * @return the degrees of freedom.
062: */
063: public double getDegreesOfFreedom() {
064: return degreesOfFreedom;
065: }
066:
067: /**
068: * For this disbution, X, this method returns P(X < <code>x</code>).
069: * @param x the value at which the CDF is evaluated.
070: * @return CDF evaluted at <code>x</code>.
071: * @throws MathException if the cumulative probability can not be
072: * computed due to convergence or other numerical errors.
073: */
074: public double cumulativeProbability(double x) throws MathException {
075: double ret;
076: if (x == 0.0) {
077: ret = 0.5;
078: } else {
079: double t = Beta.regularizedBeta(getDegreesOfFreedom()
080: / (getDegreesOfFreedom() + (x * x)),
081: 0.5 * getDegreesOfFreedom(), 0.5);
082: if (x < 0.0) {
083: ret = 0.5 * t;
084: } else {
085: ret = 1.0 - 0.5 * t;
086: }
087: }
088:
089: return ret;
090: }
091:
092: /**
093: * For this distribution, X, this method returns the critical point x, such
094: * that P(X < x) = <code>p</code>.
095: * <p>
096: * Returns <code>Double.NEGATIVE_INFINITY</code> for p=0 and
097: * <code>Double.POSITIVE_INFINITY</code> for p=1.
098: *
099: * @param p the desired probability
100: * @return x, such that P(X < x) = <code>p</code>
101: * @throws MathException if the inverse cumulative probability can not be
102: * computed due to convergence or other numerical errors.
103: * @throws IllegalArgumentException if <code>p</code> is not a valid
104: * probability.
105: */
106: public double inverseCumulativeProbability(final double p)
107: throws MathException {
108: if (p == 0) {
109: return Double.NEGATIVE_INFINITY;
110: }
111: if (p == 1) {
112: return Double.POSITIVE_INFINITY;
113: }
114: return super .inverseCumulativeProbability(p);
115: }
116:
117: /**
118: * Access the domain value lower bound, based on <code>p</code>, used to
119: * bracket a CDF root. This method is used by
120: * {@link #inverseCumulativeProbability(double)} to find critical values.
121: *
122: * @param p the desired probability for the critical value
123: * @return domain value lower bound, i.e.
124: * P(X < <i>lower bound</i>) < <code>p</code>
125: */
126: protected double getDomainLowerBound(double p) {
127: return -Double.MAX_VALUE;
128: }
129:
130: /**
131: * Access the domain value upper bound, based on <code>p</code>, used to
132: * bracket a CDF root. This method is used by
133: * {@link #inverseCumulativeProbability(double)} to find critical values.
134: *
135: * @param p the desired probability for the critical value
136: * @return domain value upper bound, i.e.
137: * P(X < <i>upper bound</i>) > <code>p</code>
138: */
139: protected double getDomainUpperBound(double p) {
140: return Double.MAX_VALUE;
141: }
142:
143: /**
144: * Access the initial domain value, based on <code>p</code>, used to
145: * bracket a CDF root. This method is used by
146: * {@link #inverseCumulativeProbability(double)} to find critical values.
147: *
148: * @param p the desired probability for the critical value
149: * @return initial domain value
150: */
151: protected double getInitialDomain(double p) {
152: return 0.0;
153: }
154: }
|