Skip to content

Commit 23351f0

Browse files
committed
more popular rngs
1 parent c9cfc6e commit 23351f0

File tree

10 files changed

+735
-18
lines changed

10 files changed

+735
-18
lines changed

src/main/java/de/tilman_neumann/jml/random/SplitMix64.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
/**
1919
* 64 bit random number generator adapted from https://rosettacode.org/wiki/Pseudo-random_numbers/Splitmix64.
2020
*
21-
* Very fast.
21+
* Very fast, but its statistical properties are poor.
22+
* But according to https://en.wikipedia.org/wiki/Xorshift#Initialization, it is well-suited to initialize other random generators.
2223
*
2324
* @author Tilman Neumann
2425
*/
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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 de.tilman_neumann.jml.base.Uint128;
17+
18+
/**
19+
* 64 bit random number generator.
20+
*
21+
* @see https://nullprogram.com/blog/2017/09/21/
22+
. *
23+
* @author Tilman Neumann
24+
*/
25+
public class Xoroshiro128Plus {
26+
27+
private long state0, state1;
28+
29+
public Xoroshiro128Plus() {
30+
SplitMix64 splitMix = new SplitMix64();
31+
long seed = System.currentTimeMillis();
32+
state0 = seed ^ splitMix.nextLong();
33+
state1 = seed ^ splitMix.nextLong();
34+
}
35+
36+
public long nextLong() {
37+
long s0 = state0;
38+
long s1 = state1;
39+
long result = s0 + s1;
40+
s1 ^= s0;
41+
state0 = ((s0 << 55) | (s0 >>> 9)) ^ s1 ^ (s1 << 14);
42+
state1 = (s1 << 36) | (s1 >>> 28);
43+
return result;
44+
}
45+
46+
/**
47+
* @param max
48+
* @return a random long number N with 0 <= N <= max.
49+
*/
50+
public long nextLong(long max) {
51+
final long l = nextLong(); // take it as unsigned
52+
final Uint128 prod = Uint128.mul64_MH(l, max);
53+
return prod.getHigh();
54+
}
55+
56+
public long nextLong(long min, long max) {
57+
return min + nextLong(max - min);
58+
}
59+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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 de.tilman_neumann.jml.base.Uint128;
17+
18+
/**
19+
* 64 bit random number generator adapted from https://en.wikipedia.org/wiki/Xorshift.
20+
*
21+
* This seems to be the best 64 bit pseudo-random number generator these days, see also https://nullprogram.com/blog/2017/09/21/
22+
*
23+
* @author Tilman Neumann
24+
*/
25+
public class Xoroshiro256StarStar {
26+
27+
private long state0, state1, state2, state3;
28+
29+
public Xoroshiro256StarStar() {
30+
SplitMix64 splitMix = new SplitMix64();
31+
long seed = System.currentTimeMillis();
32+
state0 = seed ^ splitMix.nextLong();
33+
state1 = seed ^ splitMix.nextLong();
34+
state2 = seed ^ splitMix.nextLong();
35+
state3 = seed ^ splitMix.nextLong();
36+
}
37+
38+
public long nextLong() {
39+
final long result = rol64(state1 * 5, 7) * 9;
40+
final long t = state1 << 17;
41+
42+
state2 ^= state0;
43+
state3 ^= state1;
44+
state1 ^= state2;
45+
state0 ^= state3;
46+
47+
state2 ^= t;
48+
state3 = rol64(state3, 45);
49+
50+
return result;
51+
}
52+
53+
private static long rol64(long x, int k) {
54+
return (x << k) | (x >>> (64 - k));
55+
}
56+
57+
/**
58+
* @param max
59+
* @return a random long number N with 0 <= N <= max.
60+
*/
61+
public long nextLong(long max) {
62+
final long l = nextLong(); // take it as unsigned
63+
final Uint128 prod = Uint128.mul64_MH(l, max);
64+
return prod.getHigh();
65+
}
66+
67+
public long nextLong(long min, long max) {
68+
return min + nextLong(max - min);
69+
}
70+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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 de.tilman_neumann.jml.base.Uint128;
17+
18+
/**
19+
* 64 bit random number generator adapted from https://nullprogram.com/blog/2017/09/21/.
20+
. *
21+
* @author Tilman Neumann
22+
*/
23+
public class Xorshift128Plus {
24+
25+
private long state0, state1;
26+
27+
/**
28+
* Standard constructor.
29+
*
30+
* Note https://nullprogram.com/blog/2017/09/21/: There’s one important caveat: That 16-byte state must be well-seeded.
31+
* Having lots of zero bytes will lead terrible initial output until the generator mixes it all up. Having all zero bytes will completely break the generator.
32+
* If you’re going to seed from, say, the unix epoch, then XOR it with 16 static random bytes.
33+
*
34+
* And https://en.wikipedia.org/wiki/Xorshift#Initialization: In the xoshiro paper, it is recommended to initialize the state of the generators using a generator
35+
* which is radically different from the initialized generators, as well as one which will never give the "all-zero" state; for shift-register generators,
36+
* this state is impossible to escape from. The authors specifically recommend using the SplitMix64 generator, from a 64-bit seed.
37+
*/
38+
public Xorshift128Plus() {
39+
SplitMix64 splitMix = new SplitMix64();
40+
long seed = System.currentTimeMillis();
41+
state0 = seed ^ splitMix.nextLong();
42+
state1 = seed ^ splitMix.nextLong();
43+
}
44+
45+
public long nextLong() {
46+
long x = state0;
47+
long y = state1;
48+
state0 = y;
49+
x ^= x << 23;
50+
state1 = x ^ y ^ (x >>> 17) ^ (y >>> 26);
51+
return state1 + y;
52+
}
53+
54+
/**
55+
* @param max
56+
* @return a random long number N with 0 <= N <= max.
57+
*/
58+
public long nextLong(long max) {
59+
final long l = nextLong(); // take it as unsigned
60+
final Uint128 prod = Uint128.mul64_MH(l, max);
61+
return prod.getHigh();
62+
}
63+
64+
public long nextLong(long min, long max) {
65+
return min + nextLong(max - min);
66+
}
67+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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 de.tilman_neumann.jml.base.Uint128;
17+
18+
/**
19+
* 64 bit random number generator adapted from https://nullprogram.com/blog/2017/09/21/.
20+
. *
21+
* @author Tilman Neumann
22+
*/
23+
public class Xorshift64Star {
24+
25+
private static final long multiplier = 0x2545f4914f6cdd1dL;
26+
27+
private long state0;
28+
29+
public Xorshift64Star() {
30+
SplitMix64 splitMix = new SplitMix64();
31+
long seed = System.currentTimeMillis();
32+
state0 = seed ^ splitMix.nextLong();
33+
}
34+
35+
public long nextLong() {
36+
long x = state0;
37+
x ^= x >>> 12;
38+
x ^= x << 25;
39+
x ^= x >>> 27;
40+
state0 = x;
41+
return x * multiplier;
42+
}
43+
44+
/**
45+
* @param max
46+
* @return a random long number N with 0 <= N <= max.
47+
*/
48+
public long nextLong(long max) {
49+
final long l = nextLong(); // take it as unsigned
50+
final Uint128 prod = Uint128.mul64_MH(l, max);
51+
return prod.getHigh();
52+
}
53+
54+
public long nextLong(long min, long max) {
55+
return min + nextLong(max - min);
56+
}
57+
}

0 commit comments

Comments
 (0)