Created
May 18, 2023 13:17
-
-
Save smourier/f77617a802f097aea4b4f3778108b5ef to your computer and use it in GitHub Desktop.
A TypeScript port of .NET's System.Random
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
// by design, this returns the same values as .NET's System.Random | |
export default class Random { | |
private static readonly INT_MAX_VALUE: number = 0x7fffffff; | |
private static readonly INT_MIN_VALUE: number = 0x80000000; | |
private static readonly MSEED = 161803398; | |
private inext = 0; | |
private inextp = 21; | |
private seedArray = new Array(56); | |
constructor(seed: number) { | |
var subtraction = (seed == Random.INT_MIN_VALUE) ? Random.INT_MAX_VALUE : Math.abs(seed); | |
let mj = Random.MSEED - subtraction; | |
this.seedArray[55] = mj; | |
let mk = 1; | |
for (var i = 1; i < 55; i++) { | |
const ii = (21 * i) % 55; | |
this.seedArray[ii] = mk; | |
mk = mj - mk; | |
if (mk < 0) { | |
mk += Random.INT_MAX_VALUE; | |
} | |
mj = this.seedArray[ii]; | |
} | |
for (var k = 1; k < 5; k++) { | |
for (var i = 1; i < 56; i++) { | |
this.seedArray[i] -= this.seedArray[1 + (i + 30) % 55]; | |
if (this.seedArray[i] < 0) { | |
this.seedArray[i] += Random.INT_MAX_VALUE; | |
} | |
} | |
} | |
} | |
protected sample = () => this.internalSample() * (1 / Random.INT_MAX_VALUE); | |
public nextInteger = () => this.internalSample(); | |
public nextIntegerBetween = (minValue: number, maxValue: number) => Math.floor(this.nextNumberBetween(minValue, maxValue)); | |
public nextIntegerLessThan = (maxValue: number) => Math.floor(this.nextNumberLessThan(maxValue)); | |
public nextNumber = () => this.sample(); | |
public nextNumberBetween(minValue: number, maxValue: number) { | |
if (minValue > maxValue) | |
throw new Error("Argument out of range."); | |
var range = maxValue - minValue; | |
if (range <= Random.INT_MAX_VALUE) | |
return this.sample() * range + minValue; | |
return this.getSampleForLargeRange() * range + minValue; | |
} | |
public nextNumberLessThan(maxValue: number) { | |
if (maxValue < 0) | |
throw new Error("Argument out of range."); | |
return this.sample() * maxValue; | |
} | |
private getSampleForLargeRange() { | |
var result = this.internalSample(); | |
var negative = this.internalSample() % 2 == 0; | |
if (negative) { | |
result = -result; | |
} | |
let d = result; | |
d += Random.INT_MAX_VALUE - 1; | |
d /= 2 * Random.INT_MAX_VALUE - 1; | |
return d; | |
} | |
private internalSample() { | |
var locINext = this.inext; | |
var locINextp = this.inextp; | |
if (++locINext >= 56) { | |
locINext = 1; | |
} | |
if (++locINextp >= 56) { | |
locINextp = 1; | |
} | |
let retVal = this.seedArray[locINext] - this.seedArray[locINextp]; | |
if (retVal == Random.INT_MAX_VALUE) { | |
retVal--; | |
} | |
if (retVal < 0) { | |
retVal += Random.INT_MAX_VALUE; | |
} | |
this.seedArray[locINext] = retVal; | |
this.inext = locINext; | |
this.inextp = locINextp; | |
return retVal; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment