// Code adapted from https://github.com/macmcmeans/aleaPRNG import { type PRNG } from "./types.js"; // A port of an algorithm by Johannes Baagøe , 2010 // http://baagoe.com/en/RandomMusings/javascript/ // https://github.com/nquinlan/better-random-numbers-for-javascript-mirror // Original work is under MIT license - // Copyright (C) 2010 by Johannes Baagøe // // 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. function getMash() { let n = 0xefc8249d; return (data: string): number => { for (let i = 0; i < data.length; i++) { n += data.charCodeAt(i); let h = 0.02519603282416938 * n; n = h >>> 0; h -= n; h *= n; n = h >>> 0; h -= n; n += h * 0x100000000; // 2^32 } return (n >>> 0) * 2.3283064365386963e-10; // 2^-32 }; } type State = { c: number; s0: number; s1: number; s2: number; }; function getInitialState(seed: string): State { const mash = getMash(); // Apply the seeding algorithm from Baagoe. let s0 = mash(" "); let s1 = mash(" "); let s2 = mash(" "); s0 -= mash(seed); if (s0 < 0) { s0 += 1; } s1 -= mash(seed); if (s1 < 0) { s1 += 1; } s2 -= mash(seed); if (s2 < 0) { s2 += 1; } return { s0, s1, s2, c: 1 }; } export function getAleaRng(seed?: string): PRNG { const state = getInitialState(seed ?? "undefined"); return () => { const t = 2091639 * state.s0 + state.c * 2.3283064365386963e-10; // 2^-32 state.s0 = state.s1; state.s1 = state.s2; return (state.s2 = t - (state.c = t | 0)); }; }