Created
April 23, 2023 02:31
-
-
Save himanshupal/d3917eaf09ef19a3aea092c7bd7ab7fd to your computer and use it in GitHub Desktop.
Types & helper function added for bit-meddler
This file contains hidden or 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
const INT_MAX = ~(1 << (32 - 1)) | |
const ITSAKINDOFMAGIC = [ | |
0x3, | |
0x6, | |
0x9, | |
0x1d, | |
0x36, | |
0x69, | |
0xa6, // 2 to 8 | |
0x17c, | |
0x32d, | |
0x4f2, | |
0xd34, | |
0x1349, | |
0x2532, | |
0x6699, | |
0xd295, // 9 - 16 | |
0x12933, | |
0x2c93e, | |
0x593ca, | |
0xaff95, | |
0x12b6bc, | |
0x2e652e, | |
0x5373d6, | |
0x9ccdae, // etc | |
0x12ba74d, | |
0x36cd5a7, | |
0x4e5d793, | |
0xf5cde95, | |
0x1a4e6ff2, | |
0x29d1e9eb, | |
0x7a5bc2e3, | |
0xb4bcd35c, | |
] | |
/** | |
* Returns randomish integers in a given range | |
* https://github.com/alanmacleod/bit-meddler | |
*/ | |
class BitMeddler { | |
private maximum: number | |
private start: number | |
private mask: number | |
private cur: number | |
/** | |
* @param maximum The maximum value to return | |
* @param seed should be > 0 and < maximum; if provided | |
*/ | |
constructor(maximum: number, seed = 1) { | |
if (maximum < 2 || maximum > INT_MAX) { | |
throw '`maximum` must be between 2 and ' + INT_MAX + ' inclusive' | |
} | |
this.maximum = maximum | |
this.start = seed % this.maximum | |
this.cur = this.start | |
this.mask = ITSAKINDOFMAGIC[this._msb(this.maximum) - 2] | |
this.next = this._next | |
} | |
private _next() { | |
do { | |
this.cur = this.cur & 1 ? (this.cur = (this.cur >> 1) ^ this.mask) : (this.cur >>= 1) | |
} while (this.cur > this.maximum) | |
this.cur === this.start && (this.next = this._done) | |
return this.cur | |
} | |
private _done() { | |
return null | |
} | |
private _msb(v: number) { | |
let r = 0 | |
while (v) { | |
v >>= 1 | |
r++ | |
} | |
return r | |
} | |
public next(): number | null { | |
return null | |
} | |
public reset() { | |
this.next = this._next | |
this.cur = this.start | |
} | |
public all() { | |
this.reset() | |
let o: number[] = [], | |
v: number | null = null | |
while ((v = this.next())) o.push(v) | |
return o | |
} | |
} | |
export function generateRandomWithin(max: number, seed?: number) { | |
const meddler = new BitMeddler(max, seed) | |
function* nextRandom(reset?: boolean) { | |
let next = meddler.next() | |
if (!next || reset) { | |
meddler.reset() | |
next = meddler.next() | |
} | |
yield next | |
} | |
return function (reset?: boolean) { | |
// We don't need to check for 'done' here because the generator is handling that for us | |
return nextRandom(reset).next().value! | |
} | |
} | |
export default BitMeddler |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment