Skip to content

Instantly share code, notes, and snippets.

@mattdesl
Created August 2, 2023 12:00
Show Gist options
  • Save mattdesl/43893dec295d4d2cba75438c0027830a to your computer and use it in GitHub Desktop.
Save mattdesl/43893dec295d4d2cba75438c0027830a to your computer and use it in GitHub Desktop.
MIT Licensed — seedable PRNG using xorshift 128 bit + djb2 hash function
const djb2 = (() => {
// http://www.cse.yorku.ca/~oz/hash.html
const _uint32 = new Uint32Array(1);
return function djb2(str) {
_uint32[0] = 5381;
for (let i = 0; i < str.length; i++) {
const c = str.charCodeAt(i);
const h = _uint32[0];
_uint32[0] = (h << 5) + h + c; /* hash * 33 + c */
}
return _uint32[0]; // Convert to 32-bit unsigned integer
};
})();
// non-deterministic randomness to generate a N-character seed string
export const generateSeed = (n = 8) => {
let seed = "";
for (let i = 0; i < n; i++) {
const randomByte = Math.floor(Math.random() * 256);
seed += randomByte.toString(16).padStart(2, "0");
}
return seed;
};
export function PRNG(initialSeed = null) {
// Salts used for seed hashing
const A = "e1f09545";
const B = "261cdc4d";
const C = "4c280a30";
const D = "53f4b637";
let xs_state = new Uint32Array(4);
let _seed;
setSeed(initialSeed);
return {
random,
setSeed,
getSeed,
};
function getSeed() {
return _seed;
}
function setSeed(seed) {
if (typeof seed === "number") {
seed = String(seed);
}
if (!seed) {
seed = generateSeed();
}
_seed = String(seed);
// hash the string into 128 bits using some constant salts
xs_state[0] = djb2(_seed + A);
xs_state[1] = djb2(_seed + B);
xs_state[2] = djb2(_seed + C);
xs_state[3] = djb2(_seed + D);
}
function random() {
/* Algorithm "xor128" from p. 5 of Marsaglia, "Xorshift RNGs" */
let t = xs_state[3];
xs_state[3] = xs_state[2];
xs_state[2] = xs_state[1];
xs_state[1] = xs_state[0];
let s = xs_state[0];
t ^= t << 11;
t ^= t >>> 8;
xs_state[0] = t ^ s ^ (s >>> 19);
return xs_state[0] / 0x100000000;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment