UNPKG

fast-prng-wasm

Version:

A collection of fast, SIMD-enabled, pseudo random number generators in WebAssembly. Simple to use from JavaScript (node or browser), and AssemblyScript.

419 lines (361 loc) 38.2 kB
'use strict'; /** * @module Seeds Utilites for generating random seeds that can be used to * initialize WASM PRNGs. */ function seed32() { return Date.now() ^ (Math.random() * 0x100000000); } function seed64() { return (BigInt(seed32()) << 32n) | BigInt(seed32()); } /* Adapted from: https://xoshiro.di.unimi.it/splitmix64.c by Sebastiano Vigna (vigna@acm.org) This is a fixed-increment version of Java 8's SplittableRandom generator See http://dx.doi.org/10.1145/2714064.2660195 and http://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html */ /** * Splitmix64 is the default pseudo-random number generator algorithm in Java. * It's a good generator for 64 bit seeds. This version is is included mainly * for seeding the other generators, but can be used independantly if desired. * It does not confirm to the same interface as the WASM PRNGs. */ class SplitMix64 { constructor(seed = null) { this.x = seed ? BigInt(seed) : seed64(); } next() { this.x += BigInt(0x9e3779b97f4a7c15); let z = this.x; z = (z ^ (z >> BigInt(30))) * BigInt(0xbf58476d1ce4e5b9); z = (z ^ (z >> BigInt(27))) * BigInt(0x94d049bb133111eb); return z ^ (z >> BigInt(31)); } } /** * Generates an array of random 64-bit integers that are suitable for seeding * various other generators. * @param {number} count Number of seeds to generate * @param {number | bigint} seed Optional seed for the SplitMix64 generator * @returns {Array<bigint>} Array of unique 64-bit seeds */ function seed64Array(count = 8, seed = null) { const sm64 = new SplitMix64(seed); return new Array(count).fill(0n).map(() => sm64.next()); } function _loadWasmModule (sync, filepath, src, imports) { var buf = null; var isNode = typeof process !== 'undefined' && process.versions != null && process.versions.node != null; if (isNode) { buf = Buffer.from(src, 'base64'); } else { var raw = globalThis.atob(src); var rawLength = raw.length; buf = new Uint8Array(new ArrayBuffer(rawLength)); for(var i = 0; i < rawLength; i++) { buf[i] = raw.charCodeAt(i); } } { var mod = new WebAssembly.Module(buf); return imports ? new WebAssembly.Instance(mod, imports) : mod } } function PCG(imports){return _loadWasmModule(1, null, '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', imports)} function Xoroshiro128Plus(imports){return _loadWasmModule(1, null, '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', imports)} function Xoroshiro128Plus_SIMD(imports){return _loadWasmModule(1, null, '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', imports)} function Xoshiro256Plus(imports){return _loadWasmModule(1, null, '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', imports)} function Xoshiro256Plus_SIMD(imports){return _loadWasmModule(1, null, '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', imports)} /** * @enum {string} PRNG Algorithm Type */ const PRNGType = { PCG: 'PCG', Xoroshiro128Plus: 'Xoroshiro128Plus', Xoroshiro128Plus_SIMD: 'Xoroshiro128Plus_SIMD', Xoshiro256Plus: 'Xoshiro256Plus', Xoshiro256Plus_SIMD: 'Xoshiro256Plus_SIMD' }; const wasmImports = { env: { abort(_msg, _file, line, column) { console.error(`WASM abort at:${line}:${column}: `, _msg); }, trace(_msg, _n, a0, a1, a2, a3) { console.log(`WASM trace:`, a0, a1, a2, a3); } } }; const GENERATORS = { [PRNGType.PCG]: () => PCG(wasmImports), [PRNGType.Xoroshiro128Plus]: () => Xoroshiro128Plus(wasmImports), [PRNGType.Xoroshiro128Plus_SIMD]: () => Xoroshiro128Plus_SIMD(wasmImports), [PRNGType.Xoshiro256Plus]: () => Xoshiro256Plus(wasmImports), [PRNGType.Xoshiro256Plus_SIMD]: () => Xoshiro256Plus_SIMD(wasmImports) }; /** * A seedable pseudo random number generator that runs in WebAssembly. */ class RandomGenerator { #prngType = null; #seeds = null; #outputArraySize = 0; #instance = null; #bigIntOutputArrayPtr = null; #bigIntOutputArray = null; #floatOutputArrayPtr = null; #floatOutputArray = null; #setupOutputArrays = outputArraySize => { const dataView = new DataView(this.#instance.memory.buffer); this.#bigIntOutputArrayPtr = this.#instance.allocUint64Array(outputArraySize); this.#bigIntOutputArray = new BigUint64Array( this.#instance.memory.buffer, dataView.getUint32(this.#bigIntOutputArrayPtr + 4, true), // array byte offset dataView.getUint32(this.#bigIntOutputArrayPtr + 8, true) / BigUint64Array.BYTES_PER_ELEMENT // array length ); this.#floatOutputArrayPtr = this.#instance.allocFloat64Array(outputArraySize); this.#floatOutputArray = new Float64Array( this.#instance.memory.buffer, dataView.getUint32(this.#floatOutputArrayPtr + 4, true), // array byte offset dataView.getUint32(this.#floatOutputArrayPtr + 8, true) / Float64Array.BYTES_PER_ELEMENT // array length ); } /** * Creates a seedable pseudo random number generator that * runs in WebAssembly. * * @param {PRNGType} prngType The PRNG algorithm to use. Defaults to * Xoroshiro128Plus. * * @param {Array<bigint>} seeds Collection of 64-bit integers used to seed * the generator. 1-8 seeds are required depending on generator type. * Defaults to auto-seed itself if no seeds are provided. * * @param {number | bigint} jumpCountOrStreamIncrement Either: * - Optional number of state jumps to make after seeding, which allows * Xoshiro generators to choose a unique random stream. * - Or for PCG generators, this value is set as the unique steam * increment used by the generator, to accomplish the same purpose * as the Xoshiro state jumps. * * In both cases, this is intended to be used when sharing the same seeds * across multiple generators in parallel (e.g. worker threads or * distributed computation environments). * * This number should be unique across generators when `seeds` are shared. * * @param {number} outputArraySize Size of the output array used when * fetching arrays from the generator. This size is pre-allocated in WASM * memory for performance, rather than a param in the nextArray methods. */ constructor(prngType, seeds, jumpCountOrStreamIncrement = 0, outputArraySize = 1000) { this.#prngType = prngType || PRNGType.Xoroshiro128Plus_SIMD; this.#seeds = seeds || seed64Array(); // instantiate the WASM instance and get its exports this.#instance = GENERATORS[this.#prngType]().exports; this.#outputArraySize = outputArraySize; this.#setupOutputArrays(outputArraySize); const requiredSeedCount = this.#instance.SEED_COUNT.value; if (this.#seeds.length < requiredSeedCount) { throw new Error(`Generator type ${this.#prngType} requires ${requiredSeedCount} seeds, got ${this.#seeds.length}`); } this.#instance.setSeed(...this.#seeds); // 'Jump' the generator state by a unique count to ensure a different // stream is used when the same seeds are shared across generators, // e.g. across multiple worker threads. // // Applies to the xoshiro/xoroshiro generator family if (this.#instance.jump && jumpCountOrStreamIncrement > 0) { for (let i = 0; i < jumpCountOrStreamIncrement; i++) { this.#instance.jump(); } } // Set a unique stream increment to ensure a different // stream is used when the same seeds are shared across generators, // e.g. across multiple worker threads. // // Applies to the PCG generator family. // // Note that some PCG implementations provide jump-ahead and jump-back // functionality as well, similar to the Xoshiro Jump function. In this // library's PCG implementation, we only expose the increment as a way // to choose a stream, and haven't implemented PCG state jumps. if (this.#instance.setStreamIncrement && jumpCountOrStreamIncrement > 0) { this.#instance.setStreamIncrement(BigInt(jumpCountOrStreamIncrement)); } } get prngType() { return this.#prngType; } get seeds() { return this.#seeds; } set seeds(newSeeds) { if (prngType !== PRNGType.MathRandom) { this.#seeds = newSeeds; this.#instance.setSeed(...this.#seeds); } } /** The size of the array returned by the `nextArray` methods. */ get outputArraySize() { return this.#outputArraySize; } set outputArraySize(newSize) { if (this.#prngType !== PRNGType.MathRandom) { this.#instance.freeArray(this.#bigIntOutputArrayPtr); this.#instance.freeArray(this.#floatOutputArrayPtr); this.#outputArraySize = newSize; this.#setupOutputArrays(newSize); } } /** * Get the generator's next unsigned 64-bit integer * * @returns {bigint} An unsigned `bigint` providing 64-bits of randomness, * between 0 and 2^64 - 1 */ nextBigInt() { // `u64` return type in WASM is treated as an `i64` and converted to a // signed BigInt in JS, so we mask it before returning to ensure the // value is treated as unsigned return this.#instance.nextInt64() & 0xFFFFFFFFFFFFFFFFn; } /** * Get the generator's next unsigned 53-bit integer * * @returns {number} An unsigned integer `number` providing 53-bits of * randomness (the most we can fit into a JavaScript `number`), between * 0 and 2^53 - 1 (`Number.MAX_SAFE_INTEGER`) */ nextInteger() { // bit-shifted and returned as an f64 from WASM, so we get an unsigned // integer that fits nicely into a `number` without any more transformation return this.#instance.nextInt53Number(); } /** * Get the generator's next unsigned 32-bit integer * @returns {number} An unsigned integer `number` providing 32-bits of * randomness, between 0 and 2^32 - 1 */ nextInteger32() { // bit-shifted and returned as an f64 from WASM, so we get an unsigned // integer that fits nicely into a `number` without any more transformation return this.#instance.nextInt32Number(); } /** * Get the generator's next floating point number in range [0, 1) * * @returns {number} A floating point `number` between 0 and 1 */ nextNumber() { return this.#instance.nextNumber(); } /** * Get the generator's next floating point number in range (-1, 1). * Can be considered a "coordinate" in a unit circle. Useful for Monte * Carlo simulation. * * @returns {number} A floating point `number` between -1 and 1 */ nextCoord() { return this.#instance.nextCoord(); } /** * Get the square of the generator's next floating point number in range * (-1, 1). Useful for Monte Carlo simulation. * * @returns {number} A floating point `number` between -1 and 1, multiplied * by itself */ nextCoordSquared() { return this.#instance.nextCoordSquared(); } /** * Get the generator's next set of 64-bit integers between * 0 and 2^64 - 1. Array size is set when generator is created, * or by changing {@link outputArraySize}. * * @returns {BigUint64Array} An array of 64-bit integers, represented as * `u64` values in WASM and viewed as unsigned `bigint` values in * JavaScript. This output buffer is reused with each call. */ nextArray_BigInt() { this.#instance.fillUint64Array_Int64(this.#bigIntOutputArrayPtr); return this.#bigIntOutputArray; } /** * Get the generator's next set of 53-bit integers between * 0 and 2^53 - 1 (i.e. `Number.MAX_SAFE_INTEGER`). Array size is set * when generator is created, or by changing {@link outputArraySize}. * @returns {Float64Array} An array of 53-bit integers, represented as * `f64` values in WASM so they can be viewed as `number` values in * JavaScript. This output buffer is reused with each call. */ nextArray_Integer() { this.#instance.fillFloat64Array_Int53Numbers(this.#floatOutputArrayPtr); return this.#floatOutputArray; } /** * Get the generator's next set of 32-bit integers between * 0 and 2^32 - 1. Array size is set when generator is created, * or by changing {@link outputArraySize}. * @returns {Float64Array} An array of 32-bit integers, represented as * `f64` values in WASM so they can be viewed as `number` values in * JavaScript. This output buffer is reused with each call. */ nextArray_Integer32() { this.#instance.fillFloat64Array_Int32Numbers(this.#floatOutputArrayPtr); return this.#floatOutputArray; } /** * Get the generator's next set of floating point numbers in range [0, 1). * Array size is set when generator is created, or by changing * {@link outputArraySize}. * @returns {Float64Array} An array of `f64` values in WASM viewed as * `number` values. This output buffer is reused with each call. */ nextArray_Number() { this.#instance.fillFloat64Array_Numbers(this.#floatOutputArrayPtr); return this.#floatOutputArray; } /** * Get the generator's next set of Float numbers in range (-1, 1). * Array size is set when generator is created, or by changing * {@link outputArraySize}. Useful for Monte Carlo simulation. * @returns {Float64Array} An array of `f64` values in WASM viewed as * `number` values. This output buffer is reused with each call. */ nextArray_Coord() { this.#instance.fillFloat64Array_Coords(this.#floatOutputArrayPtr); return this.#floatOutputArray; } /** * Get the generator's next set of squared Float numbers in range (-1, 1). * Array size is set when generator is created, or by changing * {@link outputArraySize}. Useful for Monte Carlo simulation. * @returns {Float64Array} An array of `f64` values in WASM viewed as * `number` values. This output buffer is reused with each call. */ nextArray_CoordSquared() { this.#instance.fillFloat64Array_CoordsSquared(this.#floatOutputArrayPtr); return this.#floatOutputArray; } /** * Perform a batch test in WASM of random (x, y) points between -1 and 1 * and check if they fall within the corresponding unit circle of radius 1. * Useful for Monte Carlo simulation. * @param {number} pointCount Number of random (x, y) points to generate * and test * @returns {number} Number of tested points which fall inside of the * unit circle. */ batchTestUnitCirclePoints(pointCount) { return this.#instance.batchTestUnitCirclePoints(pointCount); } } exports.PRNGType = PRNGType; exports.RandomGenerator = RandomGenerator; exports.SplitMix64 = SplitMix64; exports.seed64Array = seed64Array;