Re: [rng] FiniteDoubleSampler to sample uniformly from a range of representable double values
On 17/01/2020 17:21, Alex Herbert wrote: A uniform sampler of the IEEE 754 finite doubles would sample from a log-uniform distribution as the limiting distribution and I don't think that is actually what people require when creating random double data. So either it: (a) is discarded as an idea; (b) is well documented and put in examples; (c) is actually formalised to correctly sample from the log-uniform distribution using the PDF: 1 / (x (log(b) - log(a))) for x in the interval [a, b] from a uniform deviate (U) in the range of the natural logarithm of the interval: X = exp(U(log(a), log(b))) I think that adding a LogUniformSampler may be of use. It would allow creation of data approximately uniform in the distribution of exponents. The numbers would be uniform on a log scale. The implementation is simple and I don't see the harm in adding it since it is a valid distribution with known PDF and CDF. Likewise the LogUniformDistribution can be added to commons-statistics distribution. There already is a vaguely related LogNormalDistribution/NormalDistribution pair so this would be and the LogUniformDistribution/UniformContinuousDistribution pair. I don't see the need to name it LogUniformContinuousDistribution as there is no discrete version that I could find documented. Alex - To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org For additional commands, e-mail: dev-h...@commons.apache.org
Re: [rng] FiniteDoubleSampler to sample uniformly from a range of representable double values
On 17/01/2020 13:33, Gilles Sadowski wrote: Hi. Le ven. 17 janv. 2020 à 13:15, Alex Herbert a écrit : The UniformRandomProvider and ContinuousUniformSampler can create doubles uniformly in a range [0, 1) and [x, y). I would like to create a sampler that can create doubles with random mantissa bits and a specified range of exponents. These would not follow a standard distribution but would be distributed according to the IEEE 754 floating-point "double format" bit layout. The sampler would ensure all bits of the mantissa are uniformly sampled and the exponent range is uniformly sampled. It could be used for example to create random double data in a specified range for testing. Are there use-cases other than providing inputs for unit tests? Maybe. I haven't got one though. However to use it from other places it would have to be in a distributed maven artifact. So either it goes in commons-rng-sampling or perhaps commons-rng-examples-sampling. Following from UniformRandomProvider I propose to remove the sign bit to allow a maximum range sampler from [0, Double.MAX_VALUE]. Is there a trade-off to allowing generation of the whole range of "double"s? No. I can change the API so the sign bit is optionally removed. At least in some tests it is advantageous to know the data will be randomly signed or only unsigned. Thus we have the API: public final class FiniteDoubleSampler { /** * Creates a new finite double sampler. * * This will return double values from the entire exponent range of a finite * {@code double} including sub-normal numbers. The value will be unsigned. * * @param rng Generator of uniformly distributed random numbers. * @return Sampler. * @since 1.4 */ public static SharedStateContinuousSampler of(UniformRandomProvider rng); /** * Creates a new finite double sampler. * * This will return double values from the specified exponent range of a finite * {@code double}. This assumes all sub-normal numbers are identified with the exponent -1023. * The value will be unsigned. * * @param rng Generator of uniformly distributed random numbers. * @param minExponent Minimum exponent * @param maxExponent Maximum exponent * @see Double#MIN_EXPONENT * @see Double#MAX_EXPONENT * @throws IllegalArgumentException If the exponents are not in the range -1023 inclusive * to 1023 inclusive; or the min exponent is not {@code <=} max exponent. * @return Sampler. * @since 1.4 */ public static SharedStateContinuousSampler of(UniformRandomProvider rng, int minExponent, int maxExponent); } I have written many tests where I wanted full precision random mantissas in double values and wanted the doubles to represent all doubles that could occur. How do you ensure it (short of listing them all)? You cannot practically list all doubles. What you want is a representative set of all doubles. I think this idea satisfies that as doubles are not uniform on a linear scale. Thus randomly sampling from the IEEE 754 representation seems to be more generic than for example rng.nextDouble() * constant. What's the advantage of the former over the latter? Given that doubles are not uniform on a linear scale if you use rng.nextDouble() * constant you are biasing your samples to higher exponents. This may or may not be what you want. If we examine nextDouble() it will uniformly sample all the 2^53 dyadic rationals in the interval [0, 1). These have a large variety of exponents. I do not know the distribution of only the mantissa bits but I would guess that they may not be uniform in order to fall exactly on the spacing interval 1/2^53. For example the first 4 numbers: 1/2^53 2/2^53 = 1/2^52 3/2^53 = 1/2^52 + 1/2^53 4/2^53 = 1/2^51 would have regular mantissas using only 0 or 1 bits. The mantissa is the same for 1, 2, 4 and only different for 3. The interval [0, 1) can be divided into [0, 0.5) and [0.5, 1). The second interval has only 1 exponent. So half the 2^53 random numbers must be represented here using the mantissa and it requires all but the bit combinations in the mantissa. But in the range below 0.5 the mantissa bits will begin to be more and more sparsely used as the representation shifts to using the exponent in the range -2 to -53. What happens when you multiply by a constant? IIUC this is equivalent: x * y = s * m * 2^(e-1075) * s * m * 2^(e-1075) where: long bits = Double.doubleToLongBits(x or y); int s = ((bits >> 63) == 0) ? 1 : -1; int e = (int)((bits >> 52) & 0x7ffL); long m = (e == 0) ? (bits & 0xfL) << 1 : (bits & 0xfL) | 0x10L; So ignoring the sign and exponent (which will just change in magnitude) the result can be computed by multiplying the two normalised mantissas, e.g. // Conditioned so that the exponent of the
Re: [rng] FiniteDoubleSampler to sample uniformly from a range of representable double values
Hi. Le ven. 17 janv. 2020 à 13:15, Alex Herbert a écrit : > > The UniformRandomProvider and ContinuousUniformSampler can create > doubles uniformly in a range [0, 1) and [x, y). > > I would like to create a sampler that can create doubles with random > mantissa bits and a specified range of exponents. These would not follow > a standard distribution but would be distributed according to the IEEE > 754 floating-point "double format" bit layout. > > The sampler would ensure all bits of the mantissa are uniformly sampled > and the exponent range is uniformly sampled. It could be used for > example to create random double data in a specified range for testing. Are there use-cases other than providing inputs for unit tests? > > Following from UniformRandomProvider I propose to remove the sign bit to > allow a maximum range sampler from [0, Double.MAX_VALUE]. Is there a trade-off to allowing generation of the whole range of "double"s? > Thus we have > the API: > > public final class FiniteDoubleSampler { > > /** > * Creates a new finite double sampler. > * > * This will return double values from the entire exponent range of > a finite > * {@code double} including sub-normal numbers. The value will be unsigned. > * > * @param rng Generator of uniformly distributed random numbers. > * @return Sampler. > * @since 1.4 > */ > public static SharedStateContinuousSampler of(UniformRandomProvider rng); > > /** > * Creates a new finite double sampler. > * > * This will return double values from the specified exponent range > of a finite > * {@code double}. This assumes all sub-normal numbers are identified > with the exponent -1023. > * The value will be unsigned. > * > * @param rng Generator of uniformly distributed random numbers. > * @param minExponent Minimum exponent > * @param maxExponent Maximum exponent > * @see Double#MIN_EXPONENT > * @see Double#MAX_EXPONENT > * @throws IllegalArgumentException If the exponents are not in the > range -1023 inclusive > * to 1023 inclusive; or the min exponent is not {@code <=} max exponent. > * @return Sampler. > * @since 1.4 > */ > public static SharedStateContinuousSampler of(UniformRandomProvider rng, >int minExponent, >int maxExponent); > } > > I have written many tests where I wanted full precision random mantissas > in double values and wanted the doubles to represent all doubles that > could occur. How do you ensure it (short of listing them all)? > Thus randomly sampling from the IEEE 754 representation > seems to be more generic than for example rng.nextDouble() * constant. What's the advantage of the former over the latter? > For example: > > // Random numbers: [0, Double.MAX_VALUE] > FiniteDoubleSampler.of(rng); > FiniteDoubleSampler.of(rng, -1023, 1023); > // Random sub-normal numbers: [0, Double.MIN_NORMAL) > FiniteDoubleSampler.of(rng, -1023, -1023); > // Random numbers that are close to overflow: (Double.MAX_VALUE/2, > Double.MAX_VALUE] > FiniteDoubleSampler.of(rng, 1023, 1023); > // Random numbers in the range [1, 32) > FiniteDoubleSampler.of(rng, 0, 4); Will the distribution be the same as for "32 * rng.nextDouble()"? Regards, Gilles > Thoughts on this? > > Alex > - To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org For additional commands, e-mail: dev-h...@commons.apache.org