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 }