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 exponential distribution.
31   *
32   * @see <a href="http://en.wikipedia.org/wiki/Exponential_distribution">Exponential distribution (Wikipedia)</a>
33   * @see <a href="http://mathworld.wolfram.com/ExponentialDistribution.html">Exponential distribution (MathWorld)</a>
34   */
35  public class ExponentialDistribution extends AbstractRealDistribution {
36      /** Serializable version identifier */
37      private static final long serialVersionUID = 20160320L;
38      /** The mean of this distribution. */
39      private final double mean;
40      /** The logarithm of the mean, stored to reduce computing time. **/
41      private final double logMean;
42  
43      /**
44       * Create an exponential distribution with the given mean.
45       *
46       * @param mean Mean of this distribution.
47       * @throws MathIllegalArgumentException if {@code mean <= 0}.
48       */
49      public ExponentialDistribution(double mean)
50          throws MathIllegalArgumentException {
51          if (mean <= 0) {
52              throw new MathIllegalArgumentException(LocalizedCoreFormats.MEAN, mean);
53          }
54  
55          this.mean    = mean;
56          this.logMean = FastMath.log(mean);
57      }
58  
59      /**
60       * Access the mean.
61       *
62       * @return the mean.
63       */
64      public double getMean() {
65          return mean;
66      }
67  
68      /** {@inheritDoc} */
69      @Override
70      public double density(double x) {
71          final double logDensity = logDensity(x);
72          return logDensity == Double.NEGATIVE_INFINITY ? 0 : FastMath.exp(logDensity);
73      }
74  
75      /** {@inheritDoc} **/
76      @Override
77      public double logDensity(double x) {
78          if (x < 0) {
79              return Double.NEGATIVE_INFINITY;
80          }
81          return -x / mean - logMean;
82      }
83  
84      /**
85       * {@inheritDoc}
86       *
87       * The implementation of this method is based on:
88       * <ul>
89       * <li>
90       * <a href="http://mathworld.wolfram.com/ExponentialDistribution.html">
91       * Exponential Distribution</a>, equation (1).</li>
92       * </ul>
93       */
94      @Override
95      public double cumulativeProbability(double x)  {
96          double ret;
97          if (x <= 0.0) {
98              ret = 0.0;
99          } else {
100             ret = 1.0 - FastMath.exp(-x / mean);
101         }
102         return ret;
103     }
104 
105     /**
106      * {@inheritDoc}
107      *
108      * Returns {@code 0} when {@code p= = 0} and
109      * {@code Double.POSITIVE_INFINITY} when {@code p == 1}.
110      */
111     @Override
112     public double inverseCumulativeProbability(double p) throws MathIllegalArgumentException {
113         MathUtils.checkRangeInclusive(p, 0, 1);
114 
115         double ret;
116         if (p == 1.0) {
117             ret = Double.POSITIVE_INFINITY;
118         } else {
119             ret = -mean * FastMath.log(1.0 - p);
120         }
121 
122         return ret;
123     }
124 
125     /**
126      * {@inheritDoc}
127      *
128      * For mean parameter {@code k}, the mean is {@code k}.
129      */
130     @Override
131     public double getNumericalMean() {
132         return getMean();
133     }
134 
135     /**
136      * {@inheritDoc}
137      *
138      * For mean parameter {@code k}, the variance is {@code k^2}.
139      */
140     @Override
141     public double getNumericalVariance() {
142         final double m = getMean();
143         return m * m;
144     }
145 
146     /**
147      * {@inheritDoc}
148      *
149      * The lower bound of the support is always 0 no matter the mean parameter.
150      *
151      * @return lower bound of the support (always 0)
152      */
153     @Override
154     public double getSupportLowerBound() {
155         return 0;
156     }
157 
158     /**
159      * {@inheritDoc}
160      *
161      * The upper bound of the support is always positive infinity
162      * no matter the mean parameter.
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 }