Skip to content

Commit 0389632

Browse files
committed
Add benchmark for generation of an open interval (0, 1)
1 parent ab37f5a commit 0389632

1 file changed

Lines changed: 67 additions & 1 deletion

File tree

commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/core/FloatingPointGenerationPerformance.java

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,12 @@ public double nextDoubleUsingBitsToDouble(LongSource source) {
9999
// 0x300L = 256 + 512 = 768
100100
// 0x0ff = 255
101101
// This makes a number in the range 1.0 to 2.0 so subtract 1.0
102-
return Double.longBitsToDouble(0x3ffL << 52 | source.nextLong() >>> 12) - 1.0;
102+
//
103+
// Note: This variant using a long constant can be slower:
104+
// Double.longBitsToDouble((source.nextLong() >>> 12) | 0x3ff0000000000001L) - 1.0
105+
// It matches the performance of nextOpenDoubleUsingBitsToDouble so is not
106+
// formally included as a variant.
107+
return Double.longBitsToDouble((source.nextLong() >>> 12) | (0x3ffL << 52)) - 1.0;
103108
}
104109

105110
/**
@@ -120,6 +125,67 @@ public double nextDoubleUsingMultiply53bits(LongSource source) {
120125
return (source.nextLong() >>> 11) * 0x1.0p-53d; // 1.0 / (1L << 53)
121126
}
122127

128+
// Methods for generation of a double in the open interval (0, 1).
129+
// These are similar to the methods above with addition of a 1-bit
130+
// at the end of the mantissa to avoid zero.
131+
132+
/**
133+
* @param source the source
134+
* @return the double
135+
*/
136+
@Benchmark
137+
public double nextOpenDoubleUsingBitsToDouble(LongSource source) {
138+
return Double.longBitsToDouble((source.nextLong() >>> 12) | 0x3ff0000000000001L) - 1.0;
139+
}
140+
141+
/**
142+
* @param source the source
143+
* @return the double
144+
*/
145+
@Benchmark
146+
public double nextOpenDoubleUsingMultiply52bits(LongSource source) {
147+
return ((source.nextLong() >>> 12) + 0.5) * 0x1.0p-52d;
148+
}
149+
150+
/**
151+
* @param source the source
152+
* @return the double
153+
*/
154+
@Benchmark
155+
public double nextOpenDoubleUsingMultiply53bits(LongSource source) {
156+
return ((source.nextLong() >>> 11) | 1) * 0x1.0p-53d;
157+
}
158+
159+
/**
160+
* @param source the source
161+
* @return the double
162+
*/
163+
@Benchmark
164+
public double nextOpenDoubleUsingRejection(LongSource source) {
165+
// Methods adding a single trailing 1-bit will return 2^52 possible doubles.
166+
// Using rejection of zero allows return of 2^53 - 1 possible doubles.
167+
long a;
168+
do {
169+
a = source.nextLong() >>> 11;
170+
} while (a == 0);
171+
return a * 0x1.0p-53d;
172+
}
173+
174+
/**
175+
* @param source the source
176+
* @return the double
177+
*/
178+
@Benchmark
179+
public double nextOpenDoubleUsingRecursion(LongSource source) {
180+
// Rejection by recursion will cause a stack overflow error if the source
181+
// is broken. This uses floating point comparison.
182+
final double a = (source.nextLong() >>> 11) * 0x1.0p-53d;
183+
if (a == 0.0) {
184+
return nextOpenDoubleUsingRejection(source);
185+
}
186+
return a;
187+
}
188+
123189
/**
124190
* @param source the source
125191
* @return the int

0 commit comments

Comments
 (0)