Skip to content

Instantly share code, notes, and snippets.

@tommyettinger
Created August 27, 2016 02:29
Show Gist options
  • Save tommyettinger/8d4a8f8eb7f1b2592b6e8a0cbf35b02d to your computer and use it in GitHub Desktop.
Save tommyettinger/8d4a8f8eb7f1b2592b6e8a0cbf35b02d to your computer and use it in GitHub Desktop.
From a fast RNG's Java source code, to hard-to-edit nonsense in multiple scripts, and then back to identical Java code.
/* Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org)
To the extent possible under law, the author has dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
See <http://creativecommons.org/publicdomain/zero/1.0/>. */
package sarong.rng;
import sarong.util.StringKit;
/**
* A port of Blackman and Vigna's xoroshiro 128+ generator; should be very fast and produce high-quality output.
* Testing shows it is within 5% the speed of LightRNG, sometimes faster and sometimes slower, and has a larger period.
* It's called XoRo because it involves Xor as well as Rotate operations on the 128-bit pseudo-random state.
* <br>
* Machines without access to efficient bitwise rotation (such as all desktop JREs, and some JDKs, run with the
* {@code -client} flag or that default to the client VM, which includes practically all 32-bit Windows JREs) may
* benefit from using XorRNG over XoRoRNG. LightRNG should continue to be very fast, but has a significantly shorter
* period (the amount of random numbers it will go through before repeating), at {@code pow(2, 64)} as opposed to
* XorRNG and XoRoRNG's {@code pow(2, 128)}, but LightRNG also allows the current RNG state to be retrieved and altered
* with {@code getState()} and {@code setState()}. For most cases, you should decide between LightRNG and XoRoRNG based
* on your needs for period length and state manipulation (LightRNG is also used internally by all StatefulRNG objects).
* <br>
* Original version at http://xoroshiro.di.unimi.it/xoroshiro128plus.c
* Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org)
*
* @author Sebastiano Vigna
* @author David Blackman
* @author Tommy Ettinger
*/
public class XoRoRNG implements RandomnessSource {
private static final long DOUBLE_MASK = (1L << 53) - 1;
private static final double NORM_53 = 1. / (1L << 53);
private static final long FLOAT_MASK = (1L << 24) - 1;
private static final double NORM_24 = 1. / (1L << 24);
private static final long serialVersionUID = 1018744536171610261L;
private long state0, state1;
/**
* Creates a new generator seeded using Math.random.
*/
public XoRoRNG() {
this((long) (Math.random() * Long.MAX_VALUE));
}
public XoRoRNG(final long seed) {
setSeed(seed);
}
@Override
public int next(int bits) {
return (int) (nextLong() & (1L << bits) - 1);
}
@Override
public long nextLong() {
final long s0 = state0;
long s1 = state1;
final long result = s0 + s1;
s1 ^= s0;
state0 = Long.rotateLeft(s0, 55) ^ s1 ^ (s1 << 14); // a, b
state1 = Long.rotateLeft(s1, 36); // c
return result;
}
/**
* Produces a copy of this RandomnessSource that, if next() and/or nextLong() are called on this object and the
* copy, both will generate the same sequence of random numbers from the point copy() was called. This just need to
* copy the state so it isn't shared, usually, and produce a new value with the same exact state.
*
* @return a copy of this RandomnessSource
*/
@Override
public RandomnessSource copy() {
XoRoRNG next = new XoRoRNG(state0);
next.state0 = state0;
next.state1 = state1;
return next;
}
/**
* Can return any int, positive or negative, of any size permissible in a 32-bit signed integer.
*
* @return any int, all 32 bits are random
*/
public int nextInt() {
return (int) nextLong();
}
/**
* Exclusive on the upper bound. The lower bound is 0.
*
* @param bound the upper bound; should be positive
* @return a random int less than n and at least equal to 0
*/
public int nextInt(final int bound) {
if (bound <= 0) return 0;
int threshold = (0x7fffffff - bound + 1) % bound;
for (; ; ) {
int bits = (int) (nextLong() & 0x7fffffff);
if (bits >= threshold)
return bits % bound;
}
}
/**
* Inclusive lower, exclusive upper.
*
* @param lower the lower bound, inclusive, can be positive or negative
* @param upper the upper bound, exclusive, should be positive, must be greater than lower
* @return a random int at least equal to lower and less than upper
*/
public int nextInt(final int lower, final int upper) {
if (upper - lower <= 0) throw new IllegalArgumentException("Upper bound must be greater than lower bound");
return lower + nextInt(upper - lower);
}
/**
* Exclusive on the upper bound. The lower bound is 0.
*
* @param bound the upper bound; should be positive
* @return a random long less than n
*/
public long nextLong(final long bound) {
if (bound <= 0) return 0;
long threshold = (0x7fffffffffffffffL - bound + 1) % bound;
for (; ; ) {
long bits = nextLong() & 0x7fffffffffffffffL;
if (bits >= threshold)
return bits % bound;
}
}
public double nextDouble() {
return (nextLong() & DOUBLE_MASK) * NORM_53;
}
public float nextFloat() {
return (float) ((nextLong() & FLOAT_MASK) * NORM_24);
}
public boolean nextBoolean() {
return (nextLong() & 1) != 0L;
}
public void nextBytes(final byte[] bytes) {
int i = bytes.length, n = 0;
while (i != 0) {
n = Math.min(i, 8);
for (long bits = nextLong(); n-- != 0; bits >>= 8) {
bytes[--i] = (byte) bits;
}
}
}
/**
* Sets the seed of this generator. Passing this 0 will just set it to -1
* instead. Not the same as the exact state-setting method implementations
* of StatefulRandomness have, {@code setState()}; this is used to generate
* 128 bits of state from a 64-bit (non-zero) seed.
*
* @param seed the number to use as the seed
*/
public void setSeed(final long seed) {
long state = seed + 0x9E3779B97F4A7C15L,
z = state;
z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L;
z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL;
state0 = z ^ (z >>> 31);
state = seed + 0x9E3779B97F4A7C15L;
z = state;
z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L;
z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL;
state1 = z ^ (z >>> 31);
}
@Override
public String toString() {
return "XoRoRNG with state hash 0x" + StringKit.hexHash(state0, state1) + 'L';
}
}
/* 圎ꇠ甡쟲 㪑捥佭딤甡 -7045908492363438894 ꭎ肚弴 喞䗳弴ীীꇠ큷弴 螚ী 暪弴捥甡 ﻳꇠﲜ佭ು 螚ﲜ (عꇠﲜ@ꭎ肚ꇠ쟲.쓎ﲜ큷)
㪑捥딤ು륁쟲ꇠ䗳弴 ኜﲜ甡 竫佭ވ弴 욍甡ীꇠﲜ讕䧔ꇠ甡 圎梗륁ﲜ큷 圎弴, 쓎 圎梗륁ﲜ큷 劮梗큷弴 竫甡佭甡ꇠ딤 ꭎ肚弴 ꭎ肚ꇠ쟲
埤佭ﲜ큷梗ވﲜ弴쟲쟲ꚋ梗륁ী딤弴 娲佭ು륁弴 ꭎ肚佭ﲜ ꭎ肚ꇠ쟲 涩弴쟲쟲 ﮦ弴쟲륁ು甡 ꭎ肚弴 㗧쟲륁佭ುು뵞 쓎ވ梗륁ﲜ甡 圎梗륁ﲜ큷 螚跱跱梗쟲弴큷 劮梗큷弴
ꭎ梗. ꭎ肚弴 ﻳী梗ވ 劮梗跱뵞 竫弴弴큷 쓎륁甡肚梗ী 竫弴弴큷 竫弴弴큷弴큷.
竫甡佭甡弴黺 <ꭎ肚ꇠ쟲://등梗홒梗홒ꓗ咅.ꭎ肚佭ﲜ/䯠弴ী梗/ﮦ弴甡륁ীﲜ/1.-8223885725517597601/>. */
ኜﲜ甡 Ộ梗瘤.涩弴佭쟲甡;
圎佭쟲弴큷 쓎ುು梗瘤쟲.ኜﲜ甡弴讕弴ী.鈷弴딤ꇠ큷弴;
/**
* 㗧甡ꇠು 暪弴捥甡㛽梗ﲜ讕 ﰦ佭딤肚ꇠﲜ弴쟲 등梗홒梗홒ꓗ咅 䯠 쓎甡'ﮦ弴跱弴佭甡ꇠﲜ讕 ﰦ佭甡肚 1+ 㦞梗; 등梗홒梗홒ꓗ咅 䯠 ﮦ弴甡륁ীﲜ 竫甡佭甡弴黺 ﮦ佭ﲜ큷梗ވ ﮦ梗甡佭甡ꇠ梗ﲜ ꭎ肚弴-Ộ륁Υುꇠ딤 竫弴弴큷.
* 뗯甡甡跱 Ộী佭딤甡ꇠ딤佭ುು뵞 ᙢ륁쟲甡 竫弴甡ꚋ甡佭甡弴 圎ꇠ甡쟲 -4504459326673381334% Ộ佭ী佭ވ 暪弴捥甡䯀梗梗ು弴佭ﲜ Ộীꇠ䗳佭甡弴 ﻳী梗ވ, 圎梗륁ﲜ큷 㗧跱跱弴ী 竫甡佭甡ꇠ딤 ꭎ肚佭甡 쓎, ﻳ梗ী 㗧跱跱弴ী 塀ꇠ讕肚甡홒ꓗ咅 暪弴瘤 ꭎ肚弴.
* 娲梗ꇠ큷'螚ী 竫肚梗ী甡弴ী 䎗ꇠ甡肚 Ộ륁Υುꇠ딤 Ộ륁Υುꇠ딤 竫肚梗륁ು큷 ﮦ佭ﲜ큷梗ވ 圎뵞 竫黺 ⷍ梗 螚샛 暪弴捥甡ナ梗륁Υು弴 劮ী弴佭甡ꇠ䗳弴딤梗ވވ梗ﲜ쟲 圎弴 4550102830092232479L-ǭ 竫肚梗륁ು큷-욍弴Υ佭쟲甡ꇠ佭ﲜ梗 ኜ甡.
* <竫跱弴弴큷>
* 鈷ꇠ 쓎ﲜ큷 ﮦ弴甡륁ীﲜ 㗧跱跱弴ী 竫甡佭甡ꇠ딤 竫쎶 嶌ীꇠ甡甡弴ﲜ (ⷍ肚弴 ꭎ梗 ꭎ肚佭ﲜ Ộ佭ী佭ވ 뫏홒샄쟲, 쓎ﲜ큷 Ộ륁Υುꇠ딤 螚ী讕, 圎梗륁ﲜ큷 ꭎ肚弴 쓎甡
* {@Ộ梗ী甡 -㦞ী弴佭甡弴ী} 涩梗ﲜ讕 涩梗瘤弴ী 竫甡佭甡弴 暪륁ވΥ弴ী 竫甡佭甡弴쎶 쓎ﲜ큷 ꭎ肚佭ﲜ 竫梗ވ弴, 暪弴捥甡 ع弴甡肚梗큷 劮梗跱뵞 ع륁쟲甡 4354645609710930339-ꭎ肚弴 圎ী 涩梗瘤弴ী) 涩梗瘤弴ী
* 竫甡佭甡弴쎶 쓎 ኜﲜ쟲甡弴佭큷 ኜﲜ甡 취佭䗳ꇠ큷 Ộ佭ী佭ވ. 쓎ﲜ큷 등梗홒梗홒ꓗ咅 뗯佭䗳弴 㪑捥甡弴ﲜ甡 涩梗ﲜ讕 쓎ﲜ큷 ﰦ佭甡肚, 暪弴捥甡덵ﲜ甡 Ộ梗쟲ꇠ甡ꇠ䗳弴 鈷梗륁Υು弴 圎梗륁ﲜ큷 驢ᬶ홒힣깄缷肶
* 㦞弴ﲜ弴ী佭甡梗ী (螚샛 Ộ륁Υುꇠ딤 ﮦ弴甡륁ীﲜ 圎뵞甡弴 Ộ梗瘤 圎弴 㪑捥佭딤甡 螚ী讕 ⷍ弴쟲甡ꇠﲜ讕 ኜ쟲 圎ꇠ甡瘤ꇠ쟲弴), 暪弴捥甡㛽梗ﲜ讕 {@圎뵞甡弴쟲 竫쎶(1, -7045908492363438894)} 욍甡佭甡弴샛륁ು홒佭ﲜ큷梗ވﲜ弴쟲쟲 涩梗ﲜ讕 劮ು佭쟲쟲
* 劮梗큷弴 ꭎ肚ꇠ쟲 ꭎ肚ী弴쟲肚梗ು큷'욍弴Υ佭쟲甡ꇠ佭ﲜ梗 {@竫弴甡ꚋ弴弴큷 ﻳꇠﲜ佭ು(2933978342707493192, -149785156902638923)}, 竫黺 ኜﲜ甡 塀 劮ುꇠ弴ﲜ甡 㪑捥딤ು륁쟲ꇠ䗳弴 쓎ﲜ큷 竫甡佭甡弴黺 䎗肚ꇠ딤肚 쓎쟲 㦞弴ﲜ弴ী佭甡梗ী ﮦ弴甡륁ীﲜ 涩佭瘤 竫甡佭甡弴
* Ộ弴ীꇠ梗큷 {@圎륁甡 등梗홒梗홒ꓗ咅()} 竫甡佭甡弴 {@㪑샛샛ꇠ딤ꇠ弴ﲜ甡 ꭎ肚ী梗瘤()}. ﻳ佭쟲甡 暪弴瘤 ኜﲜ딤ು륁큷弴쟲, ኜ甡 竫弴弴큷 涩梗ﲜ讕 涩梗瘤弴ী 圎 뗯佭쟲 涩梗ﲜ讕 竫甡佭甡弴黺
* ﻳꇠﲜ佭ು 暪弴捥甡㛽梗ﲜ讕 ꭎ肚弴 쓎ﲜ큷 ع륁쟲甡 ⷍ肚弴 螚Υᦇ弴딤甡쟲 ኜﲜ甡 涩佭ী讕弴ী (圎ꇠ甡쟲 㗧跱跱弴ী 竫甡佭甡弴쎶 ﻳꇠﲜ佭ು ꭎ梗 ﻳ佭쟲甡 螚샛 욍甡佭甡弴샛륁ು홒ꓗ咅 暪).
* <娲弴ী쟲ꇠ梗ﲜ>
* 쓎 ع佭ﲜꇠ跱륁ು佭甡ꇠ梗ﲜ 圎ꇠ甡쟲 욍弴Υ佭쟲甡ꇠ佭ﲜ梗://旲甡.䯠.쓎.ꭎ肚弴/竫弴ীꇠ佭ು㥢弴ী쟲ꇠ梗ﲜ뫹덵ナ.ꭎ肚弴
* ኜ쟲ﲜ 쓎ುು -7045908492363438894 ኜ甡 ꭎ肚弴 쓎 쓎 竫弴弴큷 ﮦ弴甡륁ীﲜ (ኜ쟲@ኜ샛.涩梗ﲜ讕)
*
* @䯠 竫ꇠ讕ﲜ弴큷 塀梗ﲜ讕
* @暪弴捥甡덵ﲜ甡 ꭎ肚ী梗륁讕肚 竫黺
* @ꭎ肚ꇠ쟲 ꭎ肚弴 䌀梗륁
*/
쓎ುು 竫甡佭甡ꇠ딤 룅㛽ᬶ㸤ᆪ깄힣㸤ꚋ䧔 ኜ샛 취ᬶ뫹䯀㛽샄깄힣㸤ꚋ䧔 {
ꭎ肚弴 圎梗륁ﲜ큷 圎뵞 ꭎ 䠈ꇠ讕ﲜ佭 = (1 << -8466546039325283855) - -7045908492363438894;
涩梗瘤弴ী 꽋륁佭ುꇠ甡뵞 䯠 㗧跱跱弴ী 圎弴 = 1. / (2933978342707493192 << 1663367072173680532);
旲ﲜ딤ು륁쟲ꇠ䗳弴 쓎 暪륁ވΥ弴ী쟲 暪弴捥甡 쓎 = (-8466546039325283855 << -4111802127417894354) - -802098044433256476;
劮륁ীী弴ﲜ甡 ﻳು梗佭甡 塀梗ﲜ讕 ﻳꇠﲜ佭ು 쓎ﲜ큷 = -7045908492363438894. / (1998691151992678588 << 4597368009561060692);
욍弴甡쟲 䯠 䯠 䎗梗ীು큷瘤ꇠ큷弴 䯠 = -802098044433256476;
뗯弴捥塡佭쟲肚 ኜ 竫肚梗륁ು큷, Ộ梗쟲ꇠ甡ꇠ䗳弴;
/**
* Ộ梗쟲쟲ꇠΥು弴 劮梗큷弴 㗧跱跱弴ী 竫甡佭甡弴黺 룅㛽ᬶ㸤ᆪ깄힣㸤ꚋ䧔 ꭎ肚弴 暪.暪弴瘤.
*/
涩梗ﲜ讕 䠈ꇠ讕ﲜ佭() {
劮梗큷弴((旲ುು弴讕佭ು㸤ী讕륁ވ弴ﲜ甡샄捥딤弴跱甡ꇠ梗ﲜ) (涩梗ﲜ讕.ﻳꇠﲜ佭ು() * ဃ跱跱弴ী.ꭎ肚弴));
}
쓎ﲜ큷 暪弴捥甡(劮佭ﲜ ꭎ肚ী弴쟲肚梗ು큷 ﰦ㸤鸼깄㥢㸤㛽뫹샄) {
䎗ꇠ甡肚(㗧跱跱弴ী);
}
@暪弴捥甡㛽梗ﲜ讕
Ộ梗쟲ꇠ甡ꇠ䗳弴 竫甡佭甡弴쎶 暪弴捥甡㛽梗ﲜ讕(ኜﲜ甡 ⷍ梗ވވ뵞) {
㗧跱跱弴ী (ꭎ肚ী弴쟲肚梗ು큷) (竫甡佭甡弴() & (-7045908492363438894 << 暪弴捥甡㛽梗ﲜ讕) - -6410857383727321063);
}
@Ộ梗쟲ꇠ甡ꇠ䗳弴
㗧쟲弴 竫肚梗瘤쟲 Ộ륁Υುꇠ딤() {
ኜ甡 쓎쟲 㪑쿥륁佭ು = 劮梗跱뵞;
螚샛 螚샛 = 暪;
등梗홒梗홒ꓗ咅 䎗佭쟲 쓎 = 䠈ꇠ讕ﲜ佭 + 㽳甡甡ꇠﲜ讕弴ী;
䯠 ^= 䎗肚ꇠು弴;
䯠 = 등梗ী.㗧跱跱弴ী(䯠, 7046136215824491735) ^ 圎梗륁ﲜ큷 ^ (鈷梗륁Υು弴 << 1); // 涩梗ﲜ讕, 圎梗륁ﲜ큷
暪弴捥甡쟶ು梗佭甡 = 쓎쟲.涩梗瘤弴ী(涩弴ﲜ讕甡肚, 1998691151992678588); // 쓎딤ވ
ﻳು梗佭甡 螚샛;
}
/**
* 圎ꇠ甡 ኜﲜ甡 螚ﲜ 竫弴甡ꚋ甡佭甡弴 䎗ꇠುು Ộ륁Υುꇠ딤 涩梗ﲜ讕, 䎗ꇠ甡肚 涩梗瘤弴ী() ኜﲜ/圎ꇠ甡쟲 㗧ﲜꇠވꇠ() 圎뵞甡弴쟲 ኜ샛 䯠 涩梗ﲜ讕 塀ꇠ讕肚甡홒ꓗ咅 쓎ﲜ큷 圎弴
* 竫弴弴큷, 圎ꇠ甡 쓎쟲 圎ꇠ甡쟲 竫 ﮦ梗甡佭甡弴㛽弴샛甡 劮梗ﲜ甡ꇠﲜ륁弴 Ộীꇠ䗳佭甡弴 竫쎶 㗧쟲弴큷 涩梗瘤弴ী Ộ륁Υುꇠ딤 뗯佭쟲 ኜﲜ甡() ኜވ跱梗ী甡 劮佭쟲弴쟲. 욍甡ীꇠﲜ讕 劮佭ುು弴큷 㦞弴ﲜ弴ী佭甡梗ী 등梗ী홒ꓗ咅
* 鈷弴쟲䇭甡梗跱 竫黺 쓎ী弴 ﮦ弴甡륁ীﲜ 竫佭ী梗ﲜ讕 쓎ು쟲梗'Ộ佭ী佭ވ 螚ﲜ, 圎ꇠ甡쟲, 涩弴쟲쟲 쓎딤딤弴쟲쟲 ኜ샛 埤佭ﲜ큷梗ވﲜ弴쟲쟲ꚋ梗륁ী딤弴 䯠 竫甡佭甡弴 ኜﲜ甡 䯠 鈷弴샛佭륁ು甡 Ộ륁Υುꇠ딤큷梗ވ佭ꇠﲜ.
*
* @등梗홒梗홒ꓗ咅 Ộীꇠ䗳佭甡弴 圎ꇠ甡쟲 鈷梗ވ佭ꇠﲜ 竫梗샛甡瘤佭ী弴 몧ು佭딤䇭ވ佭ﲜ
*/
@Ộ梗쟲ꇠ甡ꇠ䗳弴
ꭎ梗 등梗ী홒ꓗ咅 劮梗跱뵞() {
쓎륁甡肚梗ী ﮦ弴甡륁ীﲜ = ኜﲜ甡 ﮦ佭ﲜ큷梗ވ(圎梗륁ﲜ큷);
塀ꇠ讕肚甡홒ꓗ咅.䎗弴ುು = 圎梗륁ﲜ큷;
ኜﲜ甡.驢ᬶ홒힣깄缷肶 = ﻳು佭讕;
鈷弴큷ꇠ딤佭甡弴큷 㗧쟲ꇠﲜ讕;
}
/**
* 圎梗륁ﲜ큷 ኜވ跱ು弴ވ弴ﲜ甡佭甡ꇠ梗ﲜ쟲 圎ꇠ甡쟲 쓎ುು, 竫弴弴큷 䠈ꇠ讕ﲜ佭 ﻳী梗ވ, 䯠弴ী梗 竫肚梗륁ು큷 ﮦ弴甡륁ীﲜ 驢ᬶ홒힣깄什渣 ᙢ륁쟲甡 㗧쟲弴큷 -8223885725517597601-竫甡佭甡弴 螚샛 圎뵞.
*
* @娲弴ী뵞 旤ী梗큷륁딤弴쟲 ኜ, 圎梗륁ﲜ큷 -7045908492363438894 䎗ꇠ甡肚 竫甡佭甡ꇠ딤 쓎쟲
*/
㦞弴ﲜ弴ী佭甡弴 Ộ륁Υುꇠ딤 竫佭ވ弴() {
竫肚梗륁ು큷 (鈷ꇠ쟲甡ীꇠΥ륁甡弴큷) ኜ쟲();
}
/**
* 塀ꇠ讕肚甡홒ꓗ咅 Ộীꇠ䗳佭甡弴 Ộ륁Υುꇠ딤 ኜﲜ 螚跱弴ী佭甡ꇠ梗ﲜ쟲. ꪁ佭ﲜ 竫弴弴큷 竫甡佭甡弴 ع佭뵞 -7045908492363438894L.
*
* @娲ꇠ讕ﲜ佭 竫쎶 暪弴捥甡䯀뵞甡弴쟲 ꭎ梗 㗧ﲜ큷弴ী; 圎梗륁ﲜ큷 등梗홒梗 竫甡佭甡弴黺
* @ꭎ梗 䯠 ኜ ﮦ梗甡佭甡弴㛽弴샛甡 嶌ীꇠ甡甡弴ﲜ 竫甡佭甡弴 涩梗ﲜ讕 暪弴讕佭甡ꇠ䗳弴 竫弴甡甡ꇠﲜ讕 Ộ弴ীꇠ梗큷 ﮦꇠ讕肚甡쟲 圎梗륁ﲜ큷 1
*/
劮梗跱뵞 ﮦ佭ﲜ큷梗ވ 涩梗ﲜ讕(暪弴瘤 圎ꇠ甡쟲 취佭䗳ꇠ큷) {
쓎ﲜ뵞 (竫ꇠ뵇弴 <= 1) 暪弴捥甡 -1028161634865830262;
Ộ륁Υುꇠ딤 ꭎ肚弴 = (-7045908492363438894Lx7fffffff - 涩梗ﲜ讕 + -5775451692324486230) % ꭎ肚弴;
ﮦ륁ﲜ (; ; ) {
涩梗瘤弴ী Ộী梗큷륁딤弴 = (圎弴) (塀梗ﲜ讕() & -7045908492363438894x7fffffff);
竫佭ী梗ﲜ讕 (쓎ﲜ뵞 >= 쓎륁甡肚梗ী)
Ộ륁Υುꇠ딤 쓎ುು % ꭎ肚ꇠ쟲;
}
}
/**
* 쓎ﲜ큷 螚ী, ኜﲜ甡 暪弴捥甡㛽梗ﲜ讕.
*
* @쓎 Ộীꇠ䗳佭甡弴 螚Υᦇ弴딤甡 ﮦ弴甡륁ীﲜ Ộ弴ীވꇠ쟲쟲ꇠΥು弴, 뗯ꇠ讕肚, ﮦ佭ﲜ큷梗ވ ꭎ肚佭甡 竫甡佭甡弴쎶 竫梗 ኜﲜ
* @埤佭ﲜ큷梗ވﲜ弴쟲쟲ꚋ梗륁ী딤弴 劮佭ುು弴큷 ﮦ弴甡륁ীﲜ 旤佭쟲쟲ꇠﲜ讕 暪弴讕佭甡ꇠ䗳弴, 涩梗瘤弴ী, ﮦ弴쟲륁ು甡 쓎甡 娲梗ꇠ큷, 涩梗ﲜ讕 竫ꇠ讕ﲜꇠ샛ꇠ딤佭ﲜ甡ು뵞 ኜ甡 埤ꓗ咅 Ộ륁Υುꇠ딤
* @ꭎ肚ꇠ쟲 圎ꇠ甡쟲 䠈힣 ﮦ佭ﲜ큷梗ވ 娲ꇠ讕ﲜ佭 ኜﲜ甡 ﻳꇠﲜ佭ು 몧ು佭딤䇭ވ佭ﲜ ﮦﲜ讕 螚ﲜ 쓎ﲜ큷 Ộ륁Υುꇠ딤 ኜ샛
*/
ﮦ佭ﲜ큷梗ވ 䎗ꇠ甡肚梗륁甡 埤梗甡佭甡弴(ꭎ肚弴 ꭎ梗ꚋ甡ীꇠﲜ讕 Ộী梗큷륁딤弴, 暪弴捥甡덵ﲜ甡 뗯甡甡跱 圎륁甡) {
ﻳꇠﲜ佭ು (竫弴弴큷 - 쓎ﲜ뵞 <= -7045908492363438894L) 螚샛 圎ꇠ甡 ꭎ梗("Ộ佭ী佭ވ 圎ꇠ甡쟲 圎弴 ኜﲜ甡 涩梗ﲜ讕 ኜﲜ䗳梗ು䗳弴쟲 ኜ쟲 竫");
䎗ꇠುು 竫甡佭甡弴쎶 + ﮦ弴甡륁ীﲜ(㗧跱跱弴ী - ኜ샛);
}
/**
* 䯠 竫黺 暪 뗯佭쟲肚 螚䗳弴ী. 竫甡佭甡弴쎶 쓎ﲜ큷 ﮦ弴ು佭甡弴큷 ع梗쟲甡 -3083914266648251566.
*
* @竫梗ވ弴甡ꇠވ弴쟲 ꭎ梗 圎梗륁ﲜ큷 ꭎ梗 ﮦ弴甡륁ীﲜ; Ộ륁Υುꇠ딤 룅梗ী 䌀梗륁ী
* @ﻳꇠﲜ佭ು 취佭䗳ꇠ큷 ﻳꇠﲜ佭ು 暪弴捥甡㛽梗ﲜ讕 劮梗跱뵞ীꇠ讕肚甡 螚샛 㦐梗ী梗쟲肚ꇠী梗
*/
竫 ꭎ肚弴 圎弴샛梗ী弴(ኜﲜ甡 ﮦ弴甡륁ীﲜ ﮦ佭ﲜ큷梗ވ) {
涩弴쟲쟲 (竫梗샛甡瘤佭ী弴 <= -7045908492363438894L) 쓎 1;
涩梗ﲜ讕 Ộ梗ꇠﲜ甡 = (1x7fffffffffffffffL - 몧ು佭딤䇭ވ佭ﲜ + 1) % ኜވ跱ು弴ވ弴ﲜ甡쟲;
취ᬶ뫹䯀㛽샄깄힣㸤ꚋ䧔 (; ; ) {
Ộ佭딤䇭佭讕弴 㦞ী弴佭甡弴ী = 驢梗甡() & -3083914266648251566x7fffffffffffffffL;
劮 (劮梗跱뵞 >= 圎弴ﲜ弴샛ꇠ甡)
ꭎ肚弴 竫肚梗륁ು큷 % 등梗홒梗홒ꓗ咅;
}
}
ﻳ梗ী 螚ী 暪() {
暪梗ﲜ (竫佭ވ弴() & 쓎ು甡弴ী弴큷) * 暪弴捥甡㛽梗ﲜ讕;
}
Ộ륁Υುꇠ딤 ﻳꇠﲜ佭ು ꭎ肚弴() {
圎뵞甡弴 (涩梗ﲜ讕) ((圎弴甡瘤弴弴ﲜ() & 竫弴쿥륁弴ﲜ딤弴) * 暪弴捥甡㛽梗ﲜ讕);
}
ﻳꇠﲜ佭ು ኜ甡 㦐梗ী梗쟲肚ꇠী梗() {
暪弴捥甡 (ﻳ梗ী() & 1L) != -4111802127417894354;
}
䯠 ﮦ弴甡ীꇠ弴䗳弴큷 圎弴딤佭륁쟲弴(ꭎ肚佭ﲜ 圎ꇠ甡[] ꪁী弴佭甡弴쟲) {
ꭎ梗 竫甡佭甡弴 = 塀ꇠ讕肚甡홒ꓗ咅.Ộ쟲弴륁큷梗, 暪弴ꇠ讕肚Υ梗ীꇠﲜ讕 = 1;
ኜﲜ딤ು륁쟲ꇠ䗳弴 (竫륁딤肚 != -4504459326673381334) {
螚ী讕 = ﻳ梗ী.쓎ುು(圎梗甡肚, -1028161634865830262);
涩弴佭쟲甡 (ኜﲜ甡 涩梗瘤弴ী = ﮦ弴甡륁ীﲜ(); ꭎ肚ী弴쟲肚梗ು큷-- != 1; 쓎ﲜ큷 >>= 1998691151992678588) {
쓎甡[--㗧跱跱弴ী] = (暪弴弴큷) 圎梗梗ು弴佭ﲜ;
}
}
}
/**
* 劮佭ುು弴큷 竫弴甡ꚋ弴弴큷 劮ುꇠ弴ﲜ甡 竫ು梗瘤弴ী 욍甡ীꇠﲜ讕䧔ꇠ甡 ꭎ肚弴. ﮦ弴甡륁ীﲜ 鈷梗륁Υು弴 1 竫梗ވ弴甡ꇠވ弴쟲 뫏홒샄쟲 등梗홒梗홒ꓗ咅 쓎ﲜ큷 娲弴ী뵞 1
* 圎뵞甡弴쟲. 㽳捥딤ು륁쟲ꇠ䗳弴 ﮦ弴甡륁ীﲜ 圎弴 뗯佭쟲 쓎쟲 圎梗륁ﲜ큷 竫弴甡-喞ীꇠ讕ꇠﲜ佭ು 몧ು佭딤䇭ވ佭ﲜ 竫黺
* Ộ弴ীꇠ梗큷 螚샛 圎梗륁ﲜ큷, {@圎梗륁ﲜ큷 쓎딤ވ()}; 쓎ﲜ큷 쓎륁甡肚梗ী 욍弴弴 ኜ쟲 ኜ
* 1 暪弴弴큷쟲 暪륁ވΥ弴ী쟲 圎ী 뫏ナ䧔쟲 竫肚佭ী弴큷 -7045908492363438894-ﮦ佭ﲜ큷梗ވ (䎗ꇠ甡肚ꇠﲜ-ꭎ梗) ኜﲜ甡.
*
* @쓎ﲜ큷 ꭎ梗 圎ꇠ甡쟲 ⷍ肚ꇠ쟲 ꭎ肚弴 䎗佭ীী佭ﲜ甡뵞 螚륁甡跱륁甡 涩弴ﲜ讕甡肚 䎗ꇠುು
*/
竫甡佭甡弴쎶 喞䗳弴ীীꇠ큷弴 ꭎ梗(喞䗳弴ীীꇠ큷弴 㦞弴甡ꚋ甡佭甡弴 喞䗳弴ীীꇠ큷弴) {
埤佭ﲜ큷梗ވﲜ弴쟲쟲ꚋ梗륁ী딤弴 䯠 = 㦞弴ﲜ弴ী佭甡弴 + 1x9E3779B97F4A7C15L,
Ộ륁Υುꇠ딤 = ꭎ肚弴;
㦐梗ী梗쟲肚ꇠী梗黺什ꈭ跱ು륁쟲 = (竫甡佭甡弴 ^ (ﻳ佭쟲甡弴ী >>> 1)) * 1xBF58476D1CE4E5B9L;
涩梗瘤弴ী = (䎗ꇠ甡肚梗륁甡 ^ (暪弴捥甡㛽梗ﲜ讕 >>> 1)) * -4111802127417894354x94D049BB133111EBL;
㗧쟲ꇠﲜ讕 = 竫甡佭甡弴黺 ^ (圎弴 >>> -7045908492363438894L);
螚ﲜ = 㪑쿥륁佭ು + 1998691151992678588x9E3779B97F4A7C15L;
驢ᬶ홒힣깄什渣 = 㽳捥딤ು륁쟲ꇠ䗳弴;
쓎ು쟲梗 = (ﰦ佭甡肚 ^ (暪弴捥甡덵ﲜ甡 >>> -5775451692324486230)) * 1xBF58476D1CE4E5B9L;
ﻳꇠﲜ佭ು = (쓎ী弴 ^ (ⷍ肚ꇠ쟲 >>> 1)) * 4354645609710930339x94D049BB133111EBL;
竫甡佭甡弴 = 劮 ^ (ﻳꇠﲜ佭ು >>> 1);
}
@ኜ쟲
Ộীꇠ䗳佭甡弴 劮梗큷弴 圎梗륁ﲜ큷() {
圎梗륁ﲜ큷 "圎梗륁ﲜ큷 쓎ﲜ뵞 ኜﲜ甡弴ীﲜ佭ುು뵞 ኜﲜ甡 1x" + ﮦ弴甡륁ীﲜ.竫甡佭甡弴(嶌ꇠﲜ큷梗瘤쟲, ﮦ弴甡륁ীﲜ) + '쓎ﲜ큷';
}
}
/* Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org)
To the extent possible under law, the author has dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
See <http://creativecommons.org/publicdomain/zero/1.0/>. */
package sarong.rng;
import sarong.util.StringKit;
/**
* A port of Blackman and Vigna's xoroshiro 128+ generator; should be very fast and produce high-quality output.
* Testing shows it is within 5% the speed of LightRNG, sometimes faster and sometimes slower, and has a larger period.
* It's called XoRo because it involves Xor as well as Rotate operations on the 128-bit pseudo-random state.
* <br>
* Machines without access to efficient bitwise rotation (such as all desktop JREs, and some JDKs, run with the
* {@code -client} flag or that default to the client VM, which includes practically all 32-bit Windows JREs) may
* benefit from using XorRNG over XoRoRNG. LightRNG should continue to be very fast, but has a significantly shorter
* period (the amount of random numbers it will go through before repeating), at {@code pow(2, 64)} as opposed to
* XorRNG and XoRoRNG's {@code pow(2, 128)}, but LightRNG also allows the current RNG state to be retrieved and altered
* with {@code getState()} and {@code setState()}. For most cases, you should decide between LightRNG and XoRoRNG based
* on your needs for period length and state manipulation (LightRNG is also used internally by all StatefulRNG objects).
* <br>
* Original version at http://xoroshiro.di.unimi.it/xoroshiro128plus.c
* Written in 2016 by David Blackman and Sebastiano Vigna (vigna@acm.org)
*
* @author Sebastiano Vigna
* @author David Blackman
* @author Tommy Ettinger
*/
public class XoRoRNG implements RandomnessSource {
private static final long DOUBLE_MASK = (1L << 53) - 1;
private static final double NORM_53 = 1. / (1L << 53);
private static final long FLOAT_MASK = (1L << 24) - 1;
private static final double NORM_24 = 1. / (1L << 24);
private static final long serialVersionUID = 1018744536171610261L;
private long state0, state1;
/**
* Creates a new generator seeded using Math.random.
*/
public XoRoRNG() {
this((long) (Math.random() * Long.MAX_VALUE));
}
public XoRoRNG(final long seed) {
setSeed(seed);
}
@Override
public int next(int bits) {
return (int) (nextLong() & (1L << bits) - 1);
}
@Override
public long nextLong() {
final long s0 = state0;
long s1 = state1;
final long result = s0 + s1;
s1 ^= s0;
state0 = Long.rotateLeft(s0, 55) ^ s1 ^ (s1 << 14); // a, b
state1 = Long.rotateLeft(s1, 36); // c
return result;
}
/**
* Produces a copy of this RandomnessSource that, if next() and/or nextLong() are called on this object and the
* copy, both will generate the same sequence of random numbers from the point copy() was called. This just need to
* copy the state so it isn't shared, usually, and produce a new value with the same exact state.
*
* @return a copy of this RandomnessSource
*/
@Override
public RandomnessSource copy() {
XoRoRNG next = new XoRoRNG(state0);
next.state0 = state0;
next.state1 = state1;
return next;
}
/**
* Can return any int, positive or negative, of any size permissible in a 32-bit signed integer.
*
* @return any int, all 32 bits are random
*/
public int nextInt() {
return (int) nextLong();
}
/**
* Exclusive on the upper bound. The lower bound is 0.
*
* @param bound the upper bound; should be positive
* @return a random int less than n and at least equal to 0
*/
public int nextInt(final int bound) {
if (bound <= 0) return 0;
int threshold = (0x7fffffff - bound + 1) % bound;
for (; ; ) {
int bits = (int) (nextLong() & 0x7fffffff);
if (bits >= threshold)
return bits % bound;
}
}
/**
* Inclusive lower, exclusive upper.
*
* @param lower the lower bound, inclusive, can be positive or negative
* @param upper the upper bound, exclusive, should be positive, must be greater than lower
* @return a random int at least equal to lower and less than upper
*/
public int nextInt(final int lower, final int upper) {
if (upper - lower <= 0) throw new IllegalArgumentException("Upper bound must be greater than lower bound");
return lower + nextInt(upper - lower);
}
/**
* Exclusive on the upper bound. The lower bound is 0.
*
* @param bound the upper bound; should be positive
* @return a random long less than n
*/
public long nextLong(final long bound) {
if (bound <= 0) return 0;
long threshold = (0x7fffffffffffffffL - bound + 1) % bound;
for (; ; ) {
long bits = nextLong() & 0x7fffffffffffffffL;
if (bits >= threshold)
return bits % bound;
}
}
public double nextDouble() {
return (nextLong() & DOUBLE_MASK) * NORM_53;
}
public float nextFloat() {
return (float) ((nextLong() & FLOAT_MASK) * NORM_24);
}
public boolean nextBoolean() {
return (nextLong() & 1) != 0L;
}
public void nextBytes(final byte[] bytes) {
int i = bytes.length, n = 0;
while (i != 0) {
n = Math.min(i, 8);
for (long bits = nextLong(); n-- != 0; bits >>= 8) {
bytes[--i] = (byte) bits;
}
}
}
/**
* Sets the seed of this generator. Passing this 0 will just set it to -1
* instead. Not the same as the exact state-setting method implementations
* of StatefulRandomness have, {@code setState()}; this is used to generate
* 128 bits of state from a 64-bit (non-zero) seed.
*
* @param seed the number to use as the seed
*/
public void setSeed(final long seed) {
long state = seed + 0x9E3779B97F4A7C15L,
z = state;
z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L;
z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL;
state0 = z ^ (z >>> 31);
state = seed + 0x9E3779B97F4A7C15L;
z = state;
z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L;
z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL;
state1 = z ^ (z >>> 31);
}
@Override
public String toString() {
return "XoRoRNG with state hash 0x" + StringKit.hexHash(state0, state1) + 'L';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment