npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

fast-prng-wasm

v0.5.0

Published

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

Downloads

48

Readme

fast-prng-wasm

GitHub license npm version

A collection of fast, SIMD-enabled pseudo random number generators that run in WebAssembly.

Features:

  • Simple usage from JavaScript
  • Supports both Node and browsers
  • Transparent, synchronous WASM loading (embedded binaries - no fs or fetch required)
  • Seedable (or self/auto-seeded)
  • Unique stream selection (for shared-seed parallel generation)
  • Single value and bulk array output functions
  • Float (as Number), Integer (as Number), 32-bit Integer (as Number), and 64-bit BigInt output types
  • Designed for speed - WASM SIMD versions allow higher throughput
  • PRNGs can also be imported to other AssemblyScript projects and used as part of a larger WASM compilation

PRNG Algorithms:

  • PCG XSH RR: 32-bit generator with 64 bits of state
  • Xoroshiro128+: 64-bit generator with 128 bits of state (2128 period)
  • Xoroshiro128+ (SIMD): A SIMD-enabled version of above; provides 2 random outputs for the price of 1
  • Xoshiro256+: 64-bit generator with 256 bits of state (2256 period)
  • Xoshiro256+ (SIMD): SIMD-enabled version of above; provides 2 random outputs for the price of 1

Further PRNG Reading:

Usage

ES Module import (bundler / modern browser / modern node)

import { seed64Array, PRNGType, RandomGenerator } from 'fast-prng-wasm';

Node require (legacy node)

const { seed64Array, PRNGType, RandomGenerator } = require('fast-prng-wasm');

UMD (browser)

<script src="https://unpkg.com/fast-prng-wasm"></script>

💡 UMD exposes the same interface in global.fastPRNGWasm:

const { seed64Array, PRNGType, RandomGenerator } = fastPRNGWasm;

Basics

// default PRNG type is Xoroshiro128Plus_SIMD, and self-seeds
const gen = new RandomGenerator();
console.log(gen.nextBigInt());          // unsigned 64-bit BigInt
console.log(gen.nextInteger());         // unsigned 53-bit integer Number
console.log(gen.nextInteger32());       // unsigned 32-bit integer Number
console.log(gen.nextNumber());          // 53-bit float Number in [0, 1)

// all PRNG types expose the same interface
const pcgGen = new RandomGenerator(PRNGType.PCG);
console.log(pcgGen.nextBigInt());       // unsigned 64-bit BigInt
console.log(pcgGen.nextInteger());      // unsigned 53-bit integer Number
console.log(pcgGen.nextInteger32());    // unsigned 32-bit integer Number
console.log(pcgGen.nextNumber());       // 53-bit float Number in [0, 1)

Array Output

The fastest way to get random numbers in bulk is to use the nextArray_* methods of RandomGenerator. Each call to one of these functions fills an internal buffer with the next 1000 (by default) random numbers, and then returns a view of the buffer to JavaScript as an appropriate TypedArray, either BigUint64Array or Float64Array.

💡 SIMD

Array functions must be used instead of single-value functions to get the additional throughput offered by SIMD algorithm types (these have higher throughput because they produce multiple numbers at the same time).

const gen = new RandomGenerator();
const randomArray = gen.nextArray_BigInt();       // 1000 unsigned 64-bit BigInts (in BigUint64Array)
const randomArray2 = gen.nextArray_Integer();     // 1000 unsigned 53-bit integer Numbers (in Float64Array)
const randomArray3 = gen.nextArray_Integer32();   // 1000 unsigned 32-bit integer Numbers (in Float64Array)
const randomArray4 = gen.nextArray_Number();      // 1000 float Numbers in [0, 1) (in Float64Array)

⚠️Shared Buffer Warning⚠️

Because you are consuming random numbers out of a view on a portion of shared WebAssembly memory, and this memory is reused between calls to the nextArray_* functions, you must actually consume (e.g. test/calculate, or copy) these numbers between each call.

const gen = new RandomGenerator();

// ⚠️Warning⚠️: Consume these numbers before making another call to nextArray_*
const randomArray1 = gen.nextArray_Number();   // 1000 float Numbers in [0, 1)
console.log(randomArray1);

// the values originally in randomArray1 will be replaced now!
const randomArray2 = gen.nextArray_Number();   // 1000 floats in [0, 1)
console.log(randomArray2);

console.log(randomArray1 === randomArray2);    // true (same buffer!)

Set Output Array Size

// providing null seeds on instantiation will auto-seed the generator
const gen = new RandomGenerator(PRNGType.PCG, null, 0, 200);
const randomArray = gen.nextArray_Number();    // 200 random floats in [0, 1)

// resize output buffer reserved by WASM instance
gen.outputArraySize = 42;                      // change output array size
randomArray = gen.nextArray_Number();          // 42 random floats in [0, 1)
console.log(randomArray);

// this exceeds the set memory limits of the WASM instance
gen.outputArraySize = 5000;                    // Runtime Error ⚠️

The AssemblyScript configuration in asconfig.release.json specifies a fixed WASM memory size of 1 page. This is intentionally kept small to limit resources allocated to WASM instances -- and because output arrays larger than the default of 1000 don't increase performance any further, even when generating very large quantities of random numbers.

If for some reason you need a larger array, you can increase the configured memory size and rebuild the library.

Seeding

Seeding is optional, such that when no seeds are provided, a RandomGenerator will seed itself automatically (using the seed64Array() function internally). Using high quality seeds is important, as summarized on Vigna's Xoshiro page:

We suggest to use SplitMix64 to initialize the state of our generators starting from a 64-bit seed, as research has shown that initialization must be performed with a generator radically different in nature from the one initialized to avoid correlation on similar seeds.

Manual Seeding

Manual seeding is done by providing a collection of random BigInt values, which will be treated as unsigned 64-bit integers and used to initialize the generator state. Each generator type requires a different number of seeds (between 1 and 8) - see API docs for more details.

const customSeeds = [7n, 9876543210818181n];    // Xoroshiro128+ takes 2 BigInt seeds
const customSeededGen = new RandomGenerator(PRNGType.Xoroshiro128Plus, customSeeds);

Generate a Unique Seed Collection with seed64Array()

The seed64Array() function is also provided as a means of generating your own random seeds, which can then be shared between multiple generators, e.g. each running in a different thread (see the pmc demo for an example of this).

This function returns an Array<BigInt> containing 8 seeds generated with SplitMix64, which in turn was seeded with a combination of the current time and JavaScript's Math.random(). This collection of seeds is suitable to be provided as the seeds argument of any generator type.

Sharing seeds between generators assumes you will also provide a unique jumpCountOrSteamIncrement argument:

  • For the PCG PRNG, this will set the internal increment value within the generator, which selects a unique random stream to be generated given a specific starting state
  • For Xoshiro family PRNGs, this will advance (jump) the initial state to a unique point within the period, allowing for effectively the same behavior - choosing a random stream to be generated given a specific starting state
const sharedSeeds = seed64Array();    // Array<bigint>(8)

// 2 PCG generators, using the same seeds but choosing unique streams
const streamIncrement1 = 17n;
const pcgGen1 = new RandomGenerator(PRNGType.PCG, sharedSeeds, streamIncrement1);
const pcgNum1 = pcgGen1.nextNumber();

const streamIncrement2 = 12345678901234n;
const pcgGen2 = new RandomGenerator(PRNGType.PCG, sharedSeeds, streamIncrement2);
const pcgNum2 = pcgGen2.nextNumber();

console.log(pcgNum1 === pcgNum2);     // false

// Two Xoshiro256+ generators using the same seeds, but with unique jumpCounts
const jumpCount1 = 0;
const seededGen1 = new RandomGenerator(PRNGType.Xoshiro256Plus_SIMD, sharedSeeds, jumpCount1);
const num1 = seededGen1.nextNumber();

const jumpCount2 = 1;
const seededGen2 = new RandomGenerator(PRNGType.Xoshiro256Plus_SIMD, sharedSeeds, jumpCount2);
const num2 = seededGen2.nextNumber();

console.log(num1 === num2);           // false

// Another Xoshiro256+ generator using the same seeds, and same jumpCount as seededGen2
const jumpCount3 = 1;
const seededGen3 = new RandomGenerator(PRNGType.Xoshiro256Plus_SIMD, sharedSeeds, jumpCount3);
const num3 = seededGen3.nextNumber();

console.log(num2 === num3);           // true: using same seeds and jumpCount!!

JavaScript API

Docs coming soon.

Code contains JSDoc comments which should be visible in IDEs.

Also see RandomGenerator source.

AssemblyScript API

Docs coming soon.

For now, see individual generator AssemblyScript source to see the interface.

Compatibility

See the WebAssembly Features Roadmap for the latest compatibility information across various browsers and Node versions.

Note that this library makes use of the following feature extensions:

Demos

See the demo/ folder for all available demos. Each one is treated as a separate project.

  • pmc - Pi Monte Carlo: A Monte Carlo estimation of pi (π) using a large quantity of random numbers
    • Node CLI demo app
    • Uses multiple generator instances (one per worker thread)
    • Shares a single seed set across generators
    • Uses generator jump function to select unique stream per worker

Working With This Repo

Coming soon.

For now, see scripts in package.json.

Roadmap

Planned features are listed in TODO.md