Skip to content

Instantly share code, notes, and snippets.

@masondaniels
Last active March 24, 2023 17:59
Show Gist options
  • Save masondaniels/d58e64eac2c1af917a00be1292dccacd to your computer and use it in GitHub Desktop.
Save masondaniels/d58e64eac2c1af917a00be1292dccacd to your computer and use it in GitHub Desktop.
Tausworthe 223 implementation in java similar to LuaJIT
/*
** LuaJIT -- a Just-In-Time Compiler for Lua. https://luajit.org/
**
** Copyright (C) 2005-2022 Mike Pall. All rights reserved.
** Copyright (C) 2023 Mason Daniels.
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
** "Software"), to deal in the Software without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
** [ MIT license: https://www.opensource.org/licenses/mit-license.php ]
*/
/*
** Basically, this is a java equivalent to the Tausworthe PRNG implementation found in LuaJIT.
** https://github.com/LuaJIT/LuaJIT/blob/v2.1/src/lj_prng.c
**
*/
public class Tausworthe223 {
public static void main(String[] args) {
Tausworthe223 prng = new Tausworthe223(144);
for (int i = 0; i < 100000; i++) {
prng.nextDouble();
}
System.out.println(prng.nextDouble()); // prints 0.587154017020378
/*
** Equal LuaJIT code:
**
** function j(i)
** math.randomseed(i)
** for i=0,99999,1 do math.random() end
** print(math.random())
** end
**
** j(144)
**
** This prints 0.58715401702038 (rounds)
**/
}
private static final int[] R = { 18, 28, 7, 8 }; // This is actually called R iirc
private static final int[] U = { 63, 58, 55, 47 }; // Didn't know what to name this
private static final int[] N = { 31, 19, 24, 21 }; // Or this
private long[] state = new long[4];
private long seed;
public Tausworthe223(long seed) {
this.seed = seed;
seed();
}
private static long pi = 4614256656552045848L;
private static long e = 4613303445314885481L;
// TODO: Ensure MSB is not empty.
public void seed() {
// Set up seed
double result = seed;
for (int i = 0; i < 4; i++) {
result = result * Double.longBitsToDouble(pi) + Double.longBitsToDouble(e);
state[i] = Double.doubleToLongBits(result);
}
// Iterate over steps
for (int i = 0; i < 10; i++) {
nextStep();
}
}
public long nextStep() {
long result = 0;
for (int i = 0; i < 4; i++) {
state[i] = (((state[i] << N[i]) ^ state[i]) >>> (U[i] - R[i]))
^ ((state[i] & 0xFFFFFFFFFFFFFFFFL << (64 - U[i]))) << R[i];
result ^= state[i];
}
return result;
}
public double nextDouble() {
long mask = (0x000fffffL << 32L) | 0xffffffffL;
long exponent = 0x3ff00000L << 32L;
long bits = (nextStep() & mask) | exponent;
return Double.longBitsToDouble(bits) - 1d;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment