    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    }