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    *      http://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  package org.apache.commons.math3.distribution;
19  
20  import org.apache.commons.math3.exception.NumberIsTooLargeException;
21  import org.apache.commons.math3.exception.OutOfRangeException;
22  import org.apache.commons.math3.exception.util.LocalizedFormats;
23  import org.apache.commons.math3.random.RandomGenerator;
24  import org.apache.commons.math3.random.Well19937c;
25  
26  /**
27   * Implementation of the uniform real distribution.
28   *
29   * @see <a href="http://en.wikipedia.org/wiki/Uniform_distribution_(continuous)"
30   * >Uniform distribution (continuous), at Wikipedia</a>
31   *
32   * @since 3.0
33   */
34  public class UniformRealDistribution extends AbstractRealDistribution {
35      /** Default inverse cumulative probability accuracy.
36       * @deprecated as of 3.2 not used anymore, will be removed in 4.0
37       */
38      @Deprecated
39      public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;
40      /** Serializable version identifier. */
41      private static final long serialVersionUID = 20120109L;
42      /** Lower bound of this distribution (inclusive). */
43      private final double lower;
44      /** Upper bound of this distribution (exclusive). */
45      private final double upper;
46  
47      /**
48       * Create a standard uniform real distribution with lower bound (inclusive)
49       * equal to zero and upper bound (exclusive) equal to one.
50       * <p>
51       * <b>Note:</b> this constructor will implicitly create an instance of
52       * {@link Well19937c} as random generator to be used for sampling only (see
53       * {@link #sample()} and {@link #sample(int)}). In case no sampling is
54       * needed for the created distribution, it is advised to pass {@code null}
55       * as random generator via the appropriate constructors to avoid the
56       * additional initialisation overhead.
57       */
58      public UniformRealDistribution() {
59          this(0, 1);
60      }
61  
62      /**
63       * Create a uniform real distribution using the given lower and upper
64       * bounds.
65       * <p>
66       * <b>Note:</b> this constructor will implicitly create an instance of
67       * {@link Well19937c} as random generator to be used for sampling only (see
68       * {@link #sample()} and {@link #sample(int)}). In case no sampling is
69       * needed for the created distribution, it is advised to pass {@code null}
70       * as random generator via the appropriate constructors to avoid the
71       * additional initialisation overhead.
72       *
73       * @param lower Lower bound of this distribution (inclusive).
74       * @param upper Upper bound of this distribution (exclusive).
75       * @throws NumberIsTooLargeException if {@code lower >= upper}.
76       */
77      public UniformRealDistribution(double lower, double upper)
78          throws NumberIsTooLargeException {
79          this(new Well19937c(), lower, upper);
80      }
81  
82      /**
83       * Create a uniform distribution.
84       *
85       * @param lower Lower bound of this distribution (inclusive).
86       * @param upper Upper bound of this distribution (exclusive).
87       * @param inverseCumAccuracy Inverse cumulative probability accuracy.
88       * @throws NumberIsTooLargeException if {@code lower >= upper}.
89       * @deprecated as of 3.2, inverse CDF is now calculated analytically, use
90       *             {@link #UniformRealDistribution(double, double)} instead.
91       */
92      @Deprecated
93      public UniformRealDistribution(double lower, double upper, double inverseCumAccuracy)
94          throws NumberIsTooLargeException {
95          this(new Well19937c(), lower, upper);
96      }
97  
98      /**
99       * Creates a uniform distribution.
100      *
101      * @param rng Random number generator.
102      * @param lower Lower bound of this distribution (inclusive).
103      * @param upper Upper bound of this distribution (exclusive).
104      * @param inverseCumAccuracy Inverse cumulative probability accuracy.
105      * @throws NumberIsTooLargeException if {@code lower >= upper}.
106      * @since 3.1
107      * @deprecated as of 3.2, inverse CDF is now calculated analytically, use
108      *             {@link #UniformRealDistribution(RandomGenerator, double, double)}
109      *             instead.
110      */
111     @Deprecated
112     public UniformRealDistribution(RandomGenerator rng,
113                                    double lower,
114                                    double upper,
115                                    double inverseCumAccuracy){
116         this(rng, lower, upper);
117     }
118 
119     /**
120      * Creates a uniform distribution.
121      *
122      * @param rng Random number generator.
123      * @param lower Lower bound of this distribution (inclusive).
124      * @param upper Upper bound of this distribution (exclusive).
125      * @throws NumberIsTooLargeException if {@code lower >= upper}.
126      * @since 3.1
127      */
128     public UniformRealDistribution(RandomGenerator rng,
129                                    double lower,
130                                    double upper)
131         throws NumberIsTooLargeException {
132         super(rng);
133         if (lower >= upper) {
134             throw new NumberIsTooLargeException(
135                             LocalizedFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND,
136                             lower, upper, false);
137         }
138 
139         this.lower = lower;
140         this.upper = upper;
141     }
142 
143     /** {@inheritDoc} */
144     public double density(double x) {
145         if (x < lower || x > upper) {
146             return 0.0;
147         }
148         return 1 / (upper - lower);
149     }
150 
151     /** {@inheritDoc} */
152     public double cumulativeProbability(double x)  {
153         if (x <= lower) {
154             return 0;
155         }
156         if (x >= upper) {
157             return 1;
158         }
159         return (x - lower) / (upper - lower);
160     }
161 
162     @Override
163     public double inverseCumulativeProbability(final double p)
164             throws OutOfRangeException {
165         if (p < 0.0 || p > 1.0) {
166             throw new OutOfRangeException(p, 0, 1);
167         }
168         return p * (upper - lower) + lower;
169     }
170 
171     /**
172      * {@inheritDoc}
173      *
174      * For lower bound {@code lower} and upper bound {@code upper}, the mean is
175      * {@code 0.5 * (lower + upper)}.
176      */
177     public double getNumericalMean() {
178         return 0.5 * (lower + upper);
179     }
180 
181     /**
182      * {@inheritDoc}
183      *
184      * For lower bound {@code lower} and upper bound {@code upper}, the
185      * variance is {@code (upper - lower)^2 / 12}.
186      */
187     public double getNumericalVariance() {
188         double ul = upper - lower;
189         return ul * ul / 12;
190     }
191 
192     /**
193      * {@inheritDoc}
194      *
195      * The lower bound of the support is equal to the lower bound parameter
196      * of the distribution.
197      *
198      * @return lower bound of the support
199      */
200     public double getSupportLowerBound() {
201         return lower;
202     }
203 
204     /**
205      * {@inheritDoc}
206      *
207      * The upper bound of the support is equal to the upper bound parameter
208      * of the distribution.
209      *
210      * @return upper bound of the support
211      */
212     public double getSupportUpperBound() {
213         return upper;
214     }
215 
216     /** {@inheritDoc} */
217     public boolean isSupportLowerBoundInclusive() {
218         return true;
219     }
220 
221     /** {@inheritDoc} */
222     public boolean isSupportUpperBoundInclusive() {
223         return true;
224     }
225 
226     /**
227      * {@inheritDoc}
228      *
229      * The support of this distribution is connected.
230      *
231      * @return {@code true}
232      */
233     public boolean isSupportConnected() {
234         return true;
235     }
236 
237     /** {@inheritDoc} */
238     @Override
239     public double sample()  {
240         final double u = random.nextDouble();
241         return u * upper + (1 - u) * lower;
242     }
243 }