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    *      https://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  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.distribution.continuous;
23  
24  import org.hipparchus.exception.LocalizedCoreFormats;
25  import org.hipparchus.exception.MathIllegalArgumentException;
26  import org.hipparchus.util.FastMath;
27  import org.hipparchus.util.MathUtils;
28  
29  /**
30   * Implementation of the Cauchy distribution.
31   *
32   * @see <a href="http://en.wikipedia.org/wiki/Cauchy_distribution">Cauchy distribution (Wikipedia)</a>
33   * @see <a href="http://mathworld.wolfram.com/CauchyDistribution.html">Cauchy Distribution (MathWorld)</a>
34   */
35  public class CauchyDistribution extends AbstractRealDistribution {
36      /** Serializable version identifier */
37      private static final long serialVersionUID = 20160320L;
38      /** The median of this distribution. */
39      private final double median;
40      /** The scale of this distribution. */
41      private final double scale;
42  
43      /**
44       * Creates a Cauchy distribution with the median equal to zero and scale
45       * equal to one.
46       */
47      public CauchyDistribution() {
48          this(0, 1);
49      }
50  
51  
52      /**
53       * Creates a Cauchy distribution.
54       *
55       * @param median Median for this distribution
56       * @param scale Scale parameter for this distribution
57       * @throws MathIllegalArgumentException if {@code scale <= 0}
58       */
59      public CauchyDistribution(double median, double scale)
60          throws MathIllegalArgumentException {
61          if (scale <= 0) {
62              throw new MathIllegalArgumentException(LocalizedCoreFormats.SCALE, scale);
63          }
64  
65          this.scale = scale;
66          this.median = median;
67      }
68  
69      /** {@inheritDoc} */
70      @Override
71      public double cumulativeProbability(double x) {
72          return 0.5 + (FastMath.atan((x - median) / scale) / FastMath.PI);
73      }
74  
75      /**
76       * Access the median.
77       *
78       * @return the median for this distribution.
79       */
80      public double getMedian() {
81          return median;
82      }
83  
84      /**
85       * Access the scale parameter.
86       *
87       * @return the scale parameter for this distribution.
88       */
89      public double getScale() {
90          return scale;
91      }
92  
93      /** {@inheritDoc} */
94      @Override
95      public double density(double x) {
96          final double dev = x - median;
97          return (1 / FastMath.PI) * (scale / (dev * dev + scale * scale));
98      }
99  
100     /**
101      * {@inheritDoc}
102      *
103      * Returns {@code Double.NEGATIVE_INFINITY} when {@code p == 0}
104      * and {@code Double.POSITIVE_INFINITY} when {@code p == 1}.
105      */
106     @Override
107     public double inverseCumulativeProbability(double p) throws MathIllegalArgumentException {
108         MathUtils.checkRangeInclusive(p, 0, 1);
109 
110         double ret;
111         if (p == 0) {
112             ret = Double.NEGATIVE_INFINITY;
113         } else  if (p == 1) {
114             ret = Double.POSITIVE_INFINITY;
115         } else {
116             ret = median + scale * FastMath.tan(FastMath.PI * (p - .5));
117         }
118         return ret;
119     }
120 
121     /**
122      * {@inheritDoc}
123      *
124      * The mean is always undefined no matter the parameters.
125      *
126      * @return mean (always Double.NaN)
127      */
128     @Override
129     public double getNumericalMean() {
130         return Double.NaN;
131     }
132 
133     /**
134      * {@inheritDoc}
135      *
136      * The variance is always undefined no matter the parameters.
137      *
138      * @return variance (always Double.NaN)
139      */
140     @Override
141     public double getNumericalVariance() {
142         return Double.NaN;
143     }
144 
145     /**
146      * {@inheritDoc}
147      *
148      * The lower bound of the support is always negative infinity no matter
149      * the parameters.
150      *
151      * @return lower bound of the support (always Double.NEGATIVE_INFINITY)
152      */
153     @Override
154     public double getSupportLowerBound() {
155         return Double.NEGATIVE_INFINITY;
156     }
157 
158     /**
159      * {@inheritDoc}
160      *
161      * The upper bound of the support is always positive infinity no matter
162      * the parameters.
163      *
164      * @return upper bound of the support (always Double.POSITIVE_INFINITY)
165      */
166     @Override
167     public double getSupportUpperBound() {
168         return Double.POSITIVE_INFINITY;
169     }
170 
171     /**
172      * {@inheritDoc}
173      *
174      * The support of this distribution is connected.
175      *
176      * @return {@code true}
177      */
178     @Override
179     public boolean isSupportConnected() {
180         return true;
181     }
182 }