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 }