38 lines
1.0 KiB
JavaScript
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);
|
|
}
|
|
}
|