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.TDistribution}.
26   *
27   * @version $Revision: 348519 $ $Date: 2005-11-23 12:12:18 -0700 (Wed, 23 Nov 2005) $
28   */
29  public class TDistributionImpl
30      extends AbstractContinuousDistribution
31      implements TDistribution, Serializable  {
32  
33      /** Serializable version identifier */
34      private static final long serialVersionUID = -5852615386664158222L;
35      
36      /** The degrees of freedom*/
37      private double degreesOfFreedom;
38  
39      /**
40       * Create a t distribution using the given degrees of freedom.
41       * @param degreesOfFreedom the degrees of freedom.
42       */
43      public TDistributionImpl(double degreesOfFreedom) {
44          super();
45          setDegreesOfFreedom(degreesOfFreedom);
46      }
47  
48      /**
49       * Modify the degrees of freedom.
50       * @param degreesOfFreedom the new degrees of freedom.
51       */
52      public void setDegreesOfFreedom(double degreesOfFreedom) {
53          if (degreesOfFreedom <= 0.0) {
54              throw new IllegalArgumentException("degrees of freedom must be positive.");
55          }
56          this.degreesOfFreedom = degreesOfFreedom;
57      }
58  
59      /**
60       * Access the degrees of freedom.
61       * @return the degrees of freedom.
62       */
63      public double getDegreesOfFreedom() {
64          return degreesOfFreedom;
65      }
66  
67      /**
68       * For this disbution, X, this method returns P(X &lt; <code>x</code>).
69       * @param x the value at which the CDF is evaluated.
70       * @return CDF evaluted at <code>x</code>. 
71       * @throws MathException if the cumulative probability can not be
72       *            computed due to convergence or other numerical errors.
73       */
74      public double cumulativeProbability(double x) throws MathException{
75          double ret;
76          if (x == 0.0) {
77              ret = 0.5;
78          } else {
79              double t =
80                  Beta.regularizedBeta(
81                      getDegreesOfFreedom() / (getDegreesOfFreedom() + (x * x)),
82                      0.5 * getDegreesOfFreedom(),
83                      0.5);
84              if (x < 0.0) {
85                  ret = 0.5 * t;
86              } else {
87                  ret = 1.0 - 0.5 * t;
88              }
89          }
90  
91          return ret;
92      }
93      
94      /**
95       * For this distribution, X, this method returns the critical point x, such
96       * that P(X &lt; x) = <code>p</code>.
97       * <p>
98       * Returns <code>Double.NEGATIVE_INFINITY</code> for p=0 and 
99       * <code>Double.POSITIVE_INFINITY</code> for p=1.
100      *
101      * @param p the desired probability
102      * @return x, such that P(X &lt; x) = <code>p</code>
103      * @throws MathException if the inverse cumulative probability can not be
104      *         computed due to convergence or other numerical errors.
105      * @throws IllegalArgumentException if <code>p</code> is not a valid
106      *         probability.
107      */
108     public double inverseCumulativeProbability(final double p) 
109     throws MathException {
110         if (p == 0) {
111             return Double.NEGATIVE_INFINITY;
112         }
113         if (p == 1) {
114             return Double.POSITIVE_INFINITY;
115         }
116         return super.inverseCumulativeProbability(p);
117     }
118 
119     /**
120      * Access the domain value lower 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 lower bound, i.e.
126      *         P(X &lt; <i>lower bound</i>) &lt; <code>p</code> 
127      */
128     protected double getDomainLowerBound(double p) {
129         return -Double.MAX_VALUE;
130     }
131 
132     /**
133      * Access the domain value upper bound, 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 domain value upper bound, i.e.
139      *         P(X &lt; <i>upper bound</i>) &gt; <code>p</code> 
140      */
141     protected double getDomainUpperBound(double p) {
142         return Double.MAX_VALUE;
143     }
144 
145     /**
146      * Access the initial domain value, based on <code>p</code>, used to
147      * bracket a CDF root.  This method is used by
148      * {@link #inverseCumulativeProbability(double)} to find critical values.
149      * 
150      * @param p the desired probability for the critical value
151      * @return initial domain value
152      */
153     protected double getInitialDomain(double p) {
154         return 0.0;
155     }
156 }