View Javadoc

1   /*
2    * Copyright 2005 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  
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 &lt; <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 &lt; 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 &lt; 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 &lt; <i>lower bound</i>) &lt; <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 &lt; <i>upper bound</i>) &gt; <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 }