001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.math3.distribution;
019
020 import org.apache.commons.math3.exception.NumberIsTooLargeException;
021 import org.apache.commons.math3.exception.util.LocalizedFormats;
022 import org.apache.commons.math3.random.RandomGenerator;
023 import org.apache.commons.math3.random.Well19937c;
024
025 /**
026 * Implementation of the uniform real distribution.
027 *
028 * @see <a href="http://en.wikipedia.org/wiki/Uniform_distribution_(continuous)"
029 * >Uniform distribution (continuous), at Wikipedia</a>
030 *
031 * @version $Id: UniformRealDistribution.java 1416643 2012-12-03 19:37:14Z tn $
032 * @since 3.0
033 */
034 public class UniformRealDistribution extends AbstractRealDistribution {
035 /** Default inverse cumulative probability accuracy. */
036 public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;
037 /** Serializable version identifier. */
038 private static final long serialVersionUID = 20120109L;
039 /** Lower bound of this distribution (inclusive). */
040 private final double lower;
041 /** Upper bound of this distribution (exclusive). */
042 private final double upper;
043 /** Inverse cumulative probability accuracy. */
044 private final double solverAbsoluteAccuracy;
045
046 /**
047 * Create a standard uniform real distribution with lower bound (inclusive)
048 * equal to zero and upper bound (exclusive) equal to one.
049 */
050 public UniformRealDistribution() {
051 this(0, 1);
052 }
053
054 /**
055 * Create a uniform real distribution using the given lower and upper
056 * bounds.
057 *
058 * @param lower Lower bound of this distribution (inclusive).
059 * @param upper Upper bound of this distribution (exclusive).
060 * @throws NumberIsTooLargeException if {@code lower >= upper}.
061 */
062 public UniformRealDistribution(double lower, double upper)
063 throws NumberIsTooLargeException {
064 this(lower, upper, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
065 }
066
067 /**
068 * Create a uniform distribution.
069 *
070 * @param lower Lower bound of this distribution (inclusive).
071 * @param upper Upper bound of this distribution (exclusive).
072 * @param inverseCumAccuracy Inverse cumulative probability accuracy.
073 * @throws NumberIsTooLargeException if {@code lower >= upper}.
074 */
075 public UniformRealDistribution(double lower, double upper, double inverseCumAccuracy)
076 throws NumberIsTooLargeException {
077 this(new Well19937c(), lower, upper, inverseCumAccuracy);
078 }
079
080 /**
081 * Creates a uniform distribution.
082 *
083 * @param rng Random number generator.
084 * @param lower Lower bound of this distribution (inclusive).
085 * @param upper Upper bound of this distribution (exclusive).
086 * @param inverseCumAccuracy Inverse cumulative probability accuracy.
087 * @throws NumberIsTooLargeException if {@code lower >= upper}.
088 * @since 3.1
089 */
090 public UniformRealDistribution(RandomGenerator rng,
091 double lower,
092 double upper,
093 double inverseCumAccuracy)
094 throws NumberIsTooLargeException {
095 super(rng);
096 if (lower >= upper) {
097 throw new NumberIsTooLargeException(
098 LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND,
099 lower, upper, false);
100 }
101
102 this.lower = lower;
103 this.upper = upper;
104 solverAbsoluteAccuracy = inverseCumAccuracy;
105 }
106
107 /** {@inheritDoc} */
108 public double density(double x) {
109 if (x < lower || x > upper) {
110 return 0.0;
111 }
112 return 1 / (upper - lower);
113 }
114
115 /** {@inheritDoc} */
116 public double cumulativeProbability(double x) {
117 if (x <= lower) {
118 return 0;
119 }
120 if (x >= upper) {
121 return 1;
122 }
123 return (x - lower) / (upper - lower);
124 }
125
126 /** {@inheritDoc} */
127 @Override
128 protected double getSolverAbsoluteAccuracy() {
129 return solverAbsoluteAccuracy;
130 }
131
132 /**
133 * {@inheritDoc}
134 *
135 * For lower bound {@code lower} and upper bound {@code upper}, the mean is
136 * {@code 0.5 * (lower + upper)}.
137 */
138 public double getNumericalMean() {
139 return 0.5 * (lower + upper);
140 }
141
142 /**
143 * {@inheritDoc}
144 *
145 * For lower bound {@code lower} and upper bound {@code upper}, the
146 * variance is {@code (upper - lower)^2 / 12}.
147 */
148 public double getNumericalVariance() {
149 double ul = upper - lower;
150 return ul * ul / 12;
151 }
152
153 /**
154 * {@inheritDoc}
155 *
156 * The lower bound of the support is equal to the lower bound parameter
157 * of the distribution.
158 *
159 * @return lower bound of the support
160 */
161 public double getSupportLowerBound() {
162 return lower;
163 }
164
165 /**
166 * {@inheritDoc}
167 *
168 * The upper bound of the support is equal to the upper bound parameter
169 * of the distribution.
170 *
171 * @return upper bound of the support
172 */
173 public double getSupportUpperBound() {
174 return upper;
175 }
176
177 /** {@inheritDoc} */
178 public boolean isSupportLowerBoundInclusive() {
179 return true;
180 }
181
182 /** {@inheritDoc} */
183 public boolean isSupportUpperBoundInclusive() {
184 return true;
185 }
186
187 /**
188 * {@inheritDoc}
189 *
190 * The support of this distribution is connected.
191 *
192 * @return {@code true}
193 */
194 public boolean isSupportConnected() {
195 return true;
196 }
197
198 /** {@inheritDoc} */
199 @Override
200 public double sample() {
201 final double u = random.nextDouble();
202 return u * upper + (1 - u) * lower;
203 }
204 }