shark/tidepool-utils/lib/prng.js

38 lines
1.0 KiB
JavaScript

export class Rng {
genU32() { throw new Error('not implemented'); }
// precisely mirrors Rust's `rand::Rng::gen_range()` for `Range<u32>`
genRange(min, max) {
let range = max - min;
let zone = (range << Math.clz32(range)) - 1 >>> 0;
let v, lo, hi;
do {
v = this.genU32();
lo = Math.imul(v, range) >>> 0; // (u32) (v * range)
} while (lo > zone);
hi = BigInt(v) * BigInt(range) >> 32n;
return min + Number(hi);
}
}
export class SplitMix64 extends Rng {
constructor(seed) {
super();
this.seed = BigInt(seed);
}
clone() {
return new this.constructor(this.seed);
}
genU32() {
this.seed = BigInt.asUintN(64, this.seed + 0x9E3779B97F4A7C15n);
let z = this.seed;
z ^= BigInt.asUintN(64, z >> 33n);
z = BigInt.asUintN(64, z * 0x62A9D9ED799705F5n);
z ^= BigInt.asUintN(64, z >> 28n);
z = BigInt.asUintN(64, z * 0xCB24D0A5C88C35B3n);
return Number(z >> 32n);
}
}