UNPKG

@augment-vir/common

Version:

A collection of augments, helpers types, functions, and classes for any JavaScript environment.

35 lines (34 loc) 1.39 kB
import { ensureMinMax } from '@augment-vir/core'; /** * Creates a random integer (no decimal points are included) between the given min and max values * (inclusive). * * This function uses cryptographically secure randomness. * * @category Random * @category Package : @augment-vir/common * @package [`@augment-vir/common`](https://www.npmjs.com/package/@augment-vir/common) */ export function randomInteger({ min: rawMin, max: rawMax }) { const { min, max } = ensureMinMax({ min: Math.floor(rawMin), max: Math.floor(rawMax) }); const range = max - min + 1; const bitsNeeded = Math.ceil(Math.log2(range)); const neededBytes = Math.ceil(bitsNeeded / 8); /** * Testing on my system maxes out at 65,536 (Node) or 65,537 (Safari / Chrome / Firefox) bytes. * I don't know why, and that may be system dependent, I don't know. */ if (neededBytes > 65_000) { throw new RangeError(`Cannot create a random integer so large. ({min: ${min}, max: ${max}})`); } const cutoff = Math.floor(256 ** neededBytes / range) * range; const currentBytes = new Uint8Array(neededBytes); let value; do { crypto.getRandomValues(currentBytes); value = currentBytes.reduce((accum, byte, index) => { return accum + byte * 256 ** index; }, 0); } while (value >= cutoff); return min + (value % range); }