1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.math.distribution;
17
18 import java.io.Serializable;
19
20 import org.apache.commons.math.MathException;
21
22 /**
23 * The default implementation of {@link ChiSquaredDistribution}
24 *
25 * @version $Revision: 348519 $ $Date: 2005-11-23 12:12:18 -0700 (Wed, 23 Nov 2005) $
26 */
27 public class ChiSquaredDistributionImpl
28 extends AbstractContinuousDistribution
29 implements ChiSquaredDistribution, Serializable {
30
31 /** Serializable version identifier */
32 private static final long serialVersionUID = -8352658048349159782L;
33
34 /** Internal Gamma distribution. */
35 private GammaDistribution gamma;
36
37 /**
38 * Create a Chi-Squared distribution with the given degrees of freedom.
39 * @param degreesOfFreedom degrees of freedom.
40 */
41 public ChiSquaredDistributionImpl(double degreesOfFreedom) {
42 super();
43 setGamma(DistributionFactory.newInstance().createGammaDistribution(
44 degreesOfFreedom / 2.0, 2.0));
45 }
46
47 /**
48 * Modify the degrees of freedom.
49 * @param degreesOfFreedom the new degrees of freedom.
50 */
51 public void setDegreesOfFreedom(double degreesOfFreedom) {
52 getGamma().setAlpha(degreesOfFreedom / 2.0);
53 }
54
55 /**
56 * Access the degrees of freedom.
57 * @return the degrees of freedom.
58 */
59 public double getDegreesOfFreedom() {
60 return getGamma().getAlpha() * 2.0;
61 }
62
63 /**
64 * For this disbution, X, this method returns P(X < x).
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 return getGamma().cumulativeProbability(x);
72 }
73
74 /**
75 * For this distribution, X, this method returns the critical point x, such
76 * that P(X < x) = <code>p</code>.
77 * <p>
78 * Returns 0 for p=0 and <code>Double.POSITIVE_INFINITY</code> for p=1.
79 *
80 * @param p the desired probability
81 * @return x, such that P(X < x) = <code>p</code>
82 * @throws MathException if the inverse cumulative probability can not be
83 * computed due to convergence or other numerical errors.
84 * @throws IllegalArgumentException if <code>p</code> is not a valid
85 * probability.
86 */
87 public double inverseCumulativeProbability(final double p)
88 throws MathException {
89 if (p == 0) {
90 return 0d;
91 }
92 if (p == 1) {
93 return Double.POSITIVE_INFINITY;
94 }
95 return super.inverseCumulativeProbability(p);
96 }
97
98 /**
99 * Access the domain value lower bound, based on <code>p</code>, used to
100 * bracket a CDF root. This method is used by
101 * {@link #inverseCumulativeProbability(double)} to find critical values.
102 *
103 * @param p the desired probability for the critical value
104 * @return domain value lower bound, i.e.
105 * P(X < <i>lower bound</i>) < <code>p</code>
106 */
107 protected double getDomainLowerBound(double p) {
108 return Double.MIN_VALUE * getGamma().getBeta();
109 }
110
111 /**
112 * Access the domain value upper bound, based on <code>p</code>, used to
113 * bracket a CDF root. This method is used by
114 * {@link #inverseCumulativeProbability(double)} to find critical values.
115 *
116 * @param p the desired probability for the critical value
117 * @return domain value upper bound, i.e.
118 * P(X < <i>upper bound</i>) > <code>p</code>
119 */
120 protected double getDomainUpperBound(double p) {
121
122
123
124 double ret;
125
126 if (p < .5) {
127
128 ret = getDegreesOfFreedom();
129 } else {
130
131 ret = Double.MAX_VALUE;
132 }
133
134 return ret;
135 }
136
137 /**
138 * Access the initial domain value, based on <code>p</code>, used to
139 * bracket a CDF root. This method is used by
140 * {@link #inverseCumulativeProbability(double)} to find critical values.
141 *
142 * @param p the desired probability for the critical value
143 * @return initial domain value
144 */
145 protected double getInitialDomain(double p) {
146
147
148
149 double ret;
150
151 if (p < .5) {
152
153 ret = getDegreesOfFreedom() * .5;
154 } else {
155
156 ret = getDegreesOfFreedom();
157 }
158
159 return ret;
160 }
161
162 /**
163 * Modify the Gamma distribution.
164 * @param gamma the new distribution.
165 */
166 private void setGamma(GammaDistribution gamma) {
167 this.gamma = gamma;
168 }
169
170 /**
171 * Access the Gamma distribution.
172 * @return the internal Gamma distribution.
173 */
174 private GammaDistribution getGamma() {
175 return gamma;
176 }
177 }