Skip to content

Instantly share code, notes, and snippets.

@Rulexec
Created May 1, 2020 08:43
Show Gist options
  • Save Rulexec/895ed976bd1f7ff7b29b6f1adbd94e74 to your computer and use it in GitHub Desktop.
Save Rulexec/895ed976bd1f7ff7b29b6f1adbd94e74 to your computer and use it in GitHub Desktop.
JavaScript xoroshiro128+ implementation, can be optimized
export { Xoroshiro128Plus };
function Xoroshiro128Plus(options) {
let { state } = options || {};
if (!state) {
let time = (Date.now() | 0) >>> 0;
state = [
(time & ((Math.random() * 0xffffffff) | 0)) >>> 0,
(time & ((Math.random() * 0xffffffff) | 0)) >>> 0,
(time & ((Math.random() * 0xffffffff) | 0)) >>> 0,
(time & ((Math.random() * 0xffffffff) | 0)) >>> 0,
];
}
this.next64 = () => xoroshiro128plus(state);
this.getState = () => state.slice();
}
function xoroshiro128plus(state) {
let s0 = [state[0], state[1]];
let s1 = [state[2], state[3]];
let result = sum64(s0, s1);
s1 = xor64(s1, s0);
let [a, b] = xor64(
xor64(or64(shiftLeft64(s0, 55), shiftRight64(s0, 9)), s1),
shiftLeft64(s1, 14),
);
let [c, d] = or64(shiftLeft64(s1, 36), shiftRight64(s1, 28));
state[0] = a;
state[1] = b;
state[2] = c;
state[3] = d;
return result;
function shiftLeft64([x, y], count) {
// `32` case is not handled
if (count < 32) {
x = x << count;
let a = (y >>> (32 - count)) & (Math.pow(2, count) - 1);
x += a;
return [x >>> 0, (y << count) >>> 0];
} else {
x = (y & (Math.pow(2, 64 - count) - 1)) << (count - 32);
return [x >>> 0, 0];
}
}
function shiftRight64([x, y], count) {
// `32` case is not handled
if (count < 32) {
let a = x & (Math.pow(2, count) - 1);
y = (y >>> count) + (a << (32 - count));
return [x >>> count, y >>> 0];
} else {
let a = (x >> (count - 32)) & (Math.pow(2, 64 - count) - 1);
x = (x >> (count - 32)) & (Math.pow(2, 64 - count) - 1);
x = x + (a << (count - 32));
return [0, x >>> 0];
}
}
function or64([a0, a1], [b0, b1]) {
return [(a0 | b0) >>> 0, (a1 | b1) >>> 0];
}
function xor64([a0, a1], [b0, b1]) {
return [(a0 ^ b0) >>> 0, (a1 ^ b1) >>> 0];
}
function sum64([a0, a1], [b0, b1]) {
let [y, overflow] = sum32(a1, b1);
let x = (a0 + b0 + (overflow ? 1 : 0)) >>> 0;
return [x, y];
}
function sum32(a, b) {
let overflow = false;
let max = 0xffffffff;
max -= a;
if (b > max) {
overflow = true;
}
return [(a + b) >>> 0, overflow];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment