// Reimplementation of https://source.dot.net/#System.Private.CoreLib/Random.cs,bb77e610694e64ca const MamiRNG = function(seed) { const MBIG = 0x7FFFFFFF; const MSEED = 161803398; if((typeof seed).toLowerCase() !== 'number') seed = Math.round(Date.now() / 1000); const seedArray = new Int32Array(56); const vars = new Int32Array(2); const mjVal = 0, mkVal = 1; let ii = 0; vars[mjVal] = seed; vars[mjVal] = (vars[mjVal] === -0x80000000) ? 0x7FFFFFFF : Math.abs(vars[mjVal]); vars[mjVal] = MSEED - vars[mjVal]; seedArray[55] = vars[mjVal]; vars[mkVal] = 1; for(let i = 1; i < 55; i++) { if((ii += 21) >= 55) ii -= 55; seedArray[ii] = vars[mkVal]; vars[mkVal] = vars[mjVal] - vars[mkVal]; if(vars[mkVal] < 0) vars[mkVal] += MBIG; vars[mjVal] = seedArray[ii]; } for(let k = 1; k < 5; k++) { for(let i = 0; i < 56; i++) { let n = i + 30; if(n >= 55) n -= 55; seedArray[i] -= seedArray[1 + n]; if(seedArray[i] < 0) seedArray[i] += MBIG; } } let inext = 0, inextp = 21; const internalSample = function() { const retVal = new Int32Array(1); let locINext = inext, locINextp = inextp; if(++locINext >= 56) locINext = 1; if(++locINextp >= 56) locINextp = 1; retVal[0] = seedArray[locINext]; retVal[0] -= seedArray[locINextp]; if(retVal[0] == MBIG) retVal[0]--; if(retVal[0] < 0) retVal[0] += MBIG; seedArray[locINext] = retVal[0]; inext = locINext; inextp = locINextp; return retVal[0]; }; const sample = function() { return internalSample() * (1.0 / MBIG); }; return { sample: sample, next: function(minValue, maxValue) { let hasMinVal = (typeof minValue).toLowerCase() === 'number', hasMaxVal = (typeof maxValue).toLowerCase() === 'number'; const vars = new Int32Array(3), minVal = 0, maxVal = 1, retVal = 2; if(hasMinVal) { if(!hasMaxVal) { hasMinVal = false; hasMaxVal = true; vars[maxVal] = minValue; } else { vars[minVal] = minValue; vars[maxVal] = maxValue; } } if(hasMaxVal) { if(hasMinVal) { if(vars[minVal] > vars[maxVal]) throw 'Argument out of range.'; const range = vars[maxVal] - vars[minVal]; vars[retVal] = sample() * range; vars[retVal] += vars[minVal]; return vars[retVal]; } vars[retVal] = sample() * vars[maxVal]; return vars[retVal]; } return internalSample(); }, }; };