1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.math.distribution;
18
19 import java.io.Serializable;
20
21 /**
22 * Default implementation of
23 * {@link org.apache.commons.math.distribution.CauchyDistribution}.
24 *
25 * @since 1.1
26 * @version $Revision: 348519 $ $Date: 2005-11-23 12:12:18 -0700 (Wed, 23 Nov 2005) $
27 */
28 public class CauchyDistributionImpl extends AbstractContinuousDistribution
29 implements CauchyDistribution, Serializable {
30
31 /** Serializable version identifier */
32 private static final long serialVersionUID = 8589540077390120676L;
33
34 /** The median of this distribution. */
35 private double median = 0;
36
37 /** The scale of this distribution. */
38 private double scale = 1;
39
40 /**
41 * Creates cauchy distribution with the medain equal to zero and scale
42 * equal to one.
43 */
44 public CauchyDistributionImpl(){
45 this(0.0, 1.0);
46 }
47
48 /**
49 * Create a cauchy distribution using the given median and scale.
50 * @param median median for this distribution
51 * @param s scale parameter for this distribution
52 */
53 public CauchyDistributionImpl(double median, double s){
54 super();
55 setMedian(median);
56 setScale(s);
57 }
58
59 /**
60 * For this disbution, X, this method returns P(X < <code>x</code>).
61 * @param x the value at which the CDF is evaluated.
62 * @return CDF evaluted at <code>x</code>.
63 */
64 public double cumulativeProbability(double x) {
65 return 0.5 + (Math.atan((x - median) / scale) / Math.PI);
66 }
67
68 /**
69 * Access the median.
70 * @return median for this distribution
71 */
72 public double getMedian() {
73 return median;
74 }
75
76 /**
77 * Access the scale parameter.
78 * @return scale parameter for this distribution
79 */
80 public double getScale() {
81 return scale;
82 }
83
84 /**
85 * For this distribution, X, this method returns the critical point x, such
86 * that P(X < x) = <code>p</code>.
87 * <p>
88 * Returns <code>Double.NEGATIVE_INFINITY</code> for p=0 and
89 * <code>Double.POSITIVE_INFINITY</code> for p=1.
90 *
91 * @param p the desired probability
92 * @return x, such that P(X < x) = <code>p</code>
93 * @throws IllegalArgumentException if <code>p</code> is not a valid
94 * probability.
95 */
96 public double inverseCumulativeProbability(double p) {
97 double ret;
98 if (p < 0.0 || p > 1.0) {
99 throw new IllegalArgumentException
100 ("probability argument must be between 0 and 1 (inclusive)");
101 } else if (p == 0) {
102 ret = Double.NEGATIVE_INFINITY;
103 } else if (p == 1) {
104 ret = Double.POSITIVE_INFINITY;
105 } else {
106 ret = median + scale * Math.tan(Math.PI * (p - .5));
107 }
108 return ret;
109 }
110
111 /**
112 * Modify the median.
113 * @param median for this distribution
114 */
115 public void setMedian(double median) {
116 this.median = median;
117 }
118
119 /**
120 * Modify the scale parameter.
121 * @param s scale parameter for this distribution
122 * @throws IllegalArgumentException if <code>sd</code> is not positive.
123 */
124 public void setScale(double s) {
125 if (s <= 0.0) {
126 throw new IllegalArgumentException(
127 "Scale must be positive.");
128 }
129 scale = s;
130 }
131
132 /**
133 * Access the domain value lower 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 lower bound, i.e.
139 * P(X < <i>lower bound</i>) < <code>p</code>
140 */
141 protected double getDomainLowerBound(double p) {
142 double ret;
143
144 if (p < .5) {
145 ret = -Double.MAX_VALUE;
146 } else {
147 ret = getMedian();
148 }
149
150 return ret;
151 }
152
153 /**
154 * Access the domain value upper bound, based on <code>p</code>, used to
155 * bracket a CDF root. This method is used by
156 * {@link #inverseCumulativeProbability(double)} to find critical values.
157 *
158 * @param p the desired probability for the critical value
159 * @return domain value upper bound, i.e.
160 * P(X < <i>upper bound</i>) > <code>p</code>
161 */
162 protected double getDomainUpperBound(double p) {
163 double ret;
164
165 if (p < .5) {
166 ret = getMedian();
167 } else {
168 ret = Double.MAX_VALUE;
169 }
170
171 return ret;
172 }
173
174 /**
175 * Access the initial domain value, based on <code>p</code>, used to
176 * bracket a CDF root. This method is used by
177 * {@link #inverseCumulativeProbability(double)} to find critical values.
178 *
179 * @param p the desired probability for the critical value
180 * @return initial domain value
181 */
182 protected double getInitialDomain(double p) {
183 double ret;
184
185 if (p < .5) {
186 ret = getMedian() - getScale();
187 } else if (p > .5) {
188 ret = getMedian() + getScale();
189 } else {
190 ret = getMedian();
191 }
192
193 return ret;
194 }
195 }