Skip to content

Commit 7e61fb8

Browse files
committed
another 64 bit rng
1 parent 637c7b4 commit 7e61fb8

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* java-math-library is a Java library focused on number theory, but not necessarily limited to it. It is based on the PSIQS 4.0 factoring project.
3+
* Copyright (C) 2018-2025 Tilman Neumann - tilman.neumann@web.de
4+
*
5+
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License
6+
* as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
7+
*
8+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9+
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
10+
*
11+
* You should have received a copy of the GNU General Public License along with this program;
12+
* if not, see <http://www.gnu.org/licenses/>.
13+
*/
14+
package de.tilman_neumann.jml.random;
15+
16+
import static org.junit.Assert.assertTrue;
17+
18+
import java.util.Random;
19+
20+
/**
21+
* 64 bit random number generator using Random.nextLong() and the strategy from Java17 for Random.nextLong(long maxValue).
22+
*/
23+
public abstract class Random64 {
24+
25+
private static final boolean DEBUG = false;
26+
27+
private Random random;
28+
29+
public Random64() {
30+
random = new Random();
31+
}
32+
33+
public Random64(long seed) {
34+
random = new Random(seed);
35+
}
36+
37+
public long nextLong() {
38+
return random.nextLong();
39+
}
40+
41+
/**
42+
* Creates a random long from the uniform distribution U[0, maxValue-1], with maxValue > 0.
43+
* This is similar to what Java 17 does in RandomGenerator.nextLong(long).
44+
*
45+
* @param maxValue
46+
* @return random long in the desired range
47+
*
48+
* @see https://github.com/openjdk/jdk17/blob/master/src/java.base/share/classes/java/util/random/RandomGenerator.java
49+
*/
50+
public long nextLong(long maxValue) {
51+
if (Long.bitCount(maxValue) == 1) {
52+
// maxValue is a power of 2
53+
return nextLong() >>> Long.numberOfLeadingZeros(maxValue);
54+
}
55+
56+
long r = nextLong();
57+
long u = r >>> 1;
58+
while (true) {
59+
r = u % maxValue; // now 0 <= r <= u and r < maxValue
60+
if (DEBUG) {
61+
assertTrue(u >= 0);
62+
assertTrue(r >= 0);
63+
assertTrue(r <= u);
64+
assertTrue(r < maxValue);
65+
}
66+
// Using the modulus r = u % maxValue to obtain random numbers < maxValue has its caveats...
67+
// If u is close to 2^63, then r much smaller than maxValue are over-represented.
68+
// We only accept r that are close to maxValue then
69+
if (u + maxValue - r >= 0) break;
70+
// Otherwise reject the last random number and try another one
71+
u = nextLong() >>> 1;
72+
}
73+
74+
return r;
75+
}
76+
77+
/**
78+
* Creates a random long from the uniform distribution U[minValue, maxValue-1].
79+
* Works also for negative arguments; the only requirement is maxValue > minValue.
80+
*
81+
* @param minValue
82+
* @param maxValue
83+
* @return random long in the desired range
84+
*/
85+
public long nextLong(long minValue, long maxValue) {
86+
return minValue + nextLong(maxValue - minValue);
87+
}
88+
}

0 commit comments

Comments
 (0)