Bug: Uniform Distribution of Integers does not work if range is >= Integer.MAX_VALUE
jlink opened this issue · comments
Johannes Link commented
Testing Problem
Consider the following test:
@Example
void integers() {
IntegerArbitrary integers = Arbitraries.integers().withDistribution(RandomDistribution.uniform());
integers.sampleStream().limit(50).forEach(System.out::println);
}
Which will only create three different values:
-2147483647
-2147483648
1
Discussion
The problem is the implementation of SmallUniformGenerator:
class SmallUniformNumericGenerator implements RandomDistribution.RandomNumericGenerator {
private final int min;
private final int max;
SmallUniformNumericGenerator(BigInteger min, BigInteger max) {
this.min = min.intValueExact();
this.max = max.intValueExact();
}
@Override
public BigInteger next(Random random) {
int bound = Math.abs(max - min) + 1;
int value = random.nextInt(bound >= 0 ? bound : Integer.MAX_VALUE) + min;
return BigInteger.valueOf(value);
}
}
which should only be used if max-min < Integer.MAX_VALUE
. See:
public class UniformRandomDistribution implements RandomDistribution {
@Override
public RandomNumericGenerator createGenerator(
int genSize,
BigInteger min,
BigInteger max,
BigInteger center
) {
// Small number generation can be faster
if (isWithinIntegerRange(min, max)) {
return new SmallUniformNumericGenerator(min, max);
} else {
return new BigUniformNumericGenerator(min, max);
}
}
private static boolean isWithinIntegerRange(BigInteger min, BigInteger max) {
return min.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) >= 0
&& max.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) <= 0;
}
}
Johannes Link commented
Fixed in 0313063
Johannes Link commented
Released in 1.8.3-SNAPSHOT