Last active
March 15, 2022 21:17
-
-
Save raybellis/4c15a1746724be7bd03964e9d03e0c75 to your computer and use it in GitHub Desktop.
Emulation of java.util.Random in Javascript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class UInt48 { | |
constructor(n) { | |
if (n instanceof UInt48) { | |
Object.assign(this, n); | |
} else if (typeof n === 'number') { | |
let w0 = n & 0xffff; | |
n /= 0x10000; | |
let w1 = n & 0xffff; | |
n /= 0x10000; | |
let w2 = n & 0xffff; | |
Object.assign(this, { w2, w1, w0 }); | |
} | |
} | |
norm() { | |
if (this.w0 >= 0x10000) { | |
let carry = Math.floor(this.w0 / 0x10000); | |
this.w1 += carry; | |
this.w0 &= 0xffff; | |
} | |
if (this.w1 >= 0x10000) { | |
let carry = Math.floor(this.w1 / 0x10000); | |
this.w2 += carry; | |
this.w1 &= 0xffff; | |
} | |
this.w2 &= 0xffff; | |
return this; | |
} | |
add(n) { | |
let tmp = new UInt48(this); | |
tmp.w0 += n.w0; | |
tmp.w1 += n.w1; | |
tmp.w2 += n.w2; | |
return tmp.norm(); | |
} | |
xor(n) { | |
let tmp = new UInt48(this); | |
tmp.w2 ^= n.w2; | |
tmp.w1 ^= n.w1; | |
tmp.w0 ^= n.w0; | |
return tmp; | |
} | |
mul(n) { | |
let tmp1 = new UInt48(n); | |
tmp1.w2 = tmp1.w2 * this.w0; | |
tmp1.w1 = tmp1.w1 * this.w0; | |
tmp1.w0 = tmp1.w0 * this.w0; | |
tmp1.norm(); | |
let tmp2 = new UInt48(n); | |
tmp2.w2 = tmp2.w1 * this.w1; | |
tmp2.w1 = tmp2.w0 * this.w1; | |
tmp2.w0 = 0; | |
tmp2.norm(); | |
let tmp3 = new UInt48(n); | |
tmp3.w2 = tmp3.w0 * this.w2; | |
tmp3.w1 = 0; | |
tmp3.w0 = 0; | |
tmp3.norm(); | |
return tmp3.add(tmp2).add(tmp1); | |
} | |
valueOf() { | |
return 0x10000 * (0x10000 * this.w2 + this.w1) + this.w0; | |
} | |
} | |
class Random { | |
constructor(seed) { | |
const mul = new UInt48(0x5deece66d); | |
const add = new UInt48(0xb); | |
if (seed === undefined) { | |
seed = Math.floor(Math.random() * 0x1000000000000); | |
} | |
this.setSeed = (n) => { | |
seed = new UInt48(n).xor(mul); | |
} | |
this.setSeed(seed); | |
this.next = (bits) => { | |
seed = seed.mul(mul).add(add); | |
// return ~~(seed / Math.pow(2, 48 - bits)); | |
return (seed / 0x10000) >> (32 - bits); | |
} | |
this.nextInt = () => this.next(32); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment