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 }