View Javadoc

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