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 🙏

© 2026 – Pkg Stats / Ryan Hefner

ranjs

v1.28.0

Published

Library for generating various random variables.

Readme

ranjs

rán · 然 — "so; correct"

Build Coverage Status npm Docs License JavaScript Style Guide

A comprehensive JavaScript library for probability distributions, random variate generation, and statistical analysis.

Features

  • 140+ probability distributions — continuous and discrete, each with PDF/PMF, CDF, quantile (q), hazard, survival, log-likelihood (lnL), AIC/BIC, goodness-of-fit testing, and MLE fitting (fit)
  • Statistical measures — location (mean, median, mode, …), dispersion (variance, IQR, Gini, …), shape (skewness, kurtosis, …), and dependence (Pearson, Spearman, Kendall, …)
  • Hypothesis tests — Bartlett, Levene, Brown–Forsythe, Mann–Whitney U, HSIC
  • Reproducible sampling — every distribution accepts an optional seed for deterministic output
  • TypeScript support — declaration files generated from JSDoc, covering all public APIs
  • Tree-shakeable — import individual distributions without pulling in the full bundle

Installation

npm

npm install ranjs

CDN (browser)

<script src="https://unpkg.com/ranjs/dist/ranjs.min.js"></script>

The library is exported globally as ranjs.

Usage

ESM — single distribution import

Import a single distribution for minimal bundle size:

import Normal from 'ranjs/dist/normal'

const n = new Normal(0, 1)

n.pdf(0)       // => 0.3989422804014327
n.cdf(1.96)    // => 0.9750021048517796
n.sample(5)    // => [0.42, -1.03, 0.17, 1.81, -0.55]

CommonJS / full bundle

const ran = require('ranjs')

const skellam = new ran.dist.Skellam(1, 3)
const values  = skellam.sample(1e4)

skellam.test(values)
// => { statistics: 14.025360669436635, passed: true }

for (let k = -4; k <= 4; k++) {
  console.log(k, skellam.pdf(k), skellam.cdf(k))
}
// => -4  0.10963424740027695  0.21542206959904264
//    -3  0.16622843570192460  0.38165050508716936
//    -2  0.20277318483535026  0.58442368966117290
//    ...

Reproducible sampling

Every distribution can be individually seeded:

import Gamma from 'ranjs/dist/gamma'

const g = new Gamma(2, 1)
g.seed(42)
g.sample(3)  // always produces the same sequence

Model comparison

const ran = require('ranjs')

const data     = new ran.dist.Skellam(1, 3).sample(1e4)
const fitted   = new ran.dist.Skellam(1, 3)
const misfit   = new ran.dist.Skellam(1.2, 7.5)

console.log(fitted.aic(data))   // => 41937.67252974663
console.log(misfit.aic(data))   // => 66508.74299363888

Parameter estimation

ranjs closes the full statistical cycle — define a model, generate data, fit parameters from data via MLE, then verify the fit:

import { dist } from 'ranjs'

// 1. Define and sample
const model = new dist.Normal(3, 1).seed(42)
const data  = model.sample(500)

// 2. Fit parameters from data via MLE
const fitted = dist.Normal.fit(data)
console.log(fitted.p)           // => { mu: 3.000, sigma: 1.000 }

// 3. Test goodness of fit
console.log(fitted.test(data))  // => { statistics: 0.031, passed: true }

fit() is a static method called on the class, not on an instance: dist.Normal.fit(data), not model.fit(data). All 141 exported distributions support fit(). Most have a data-aware initial guess for reliable MLE convergence; zero-parameter distributions skip optimization and return a fresh instance.

API Overview

| Namespace | Contents | |-----------|----------| | ran.dist | 140+ probability distributions | | ran.location | Mean, median, mode, geometric mean, harmonic mean, trimean, midrange | | ran.dispersion | Variance, standard deviation, IQR, Gini coefficient, entropy, CV, … | | ran.shape | Skewness, kurtosis, quantiles, moments, min, max, rank | | ran.dependence | Pearson, Spearman, Kendall, distance correlation, Kullback–Leibler, … | | ran.test | Bartlett, Levene, Brown–Forsythe, Mann–Whitney U, HSIC | | ran.core | Seeded PRNG (xoshiro128+), uniform float/int/bool generators |

Distribution API

Every distribution exposes a consistent interface:

const d = new ran.dist.Gamma(2, 1)

d.type()          // 'continuous' or 'discrete'
d.params()        // current parameter object, e.g. { alpha: 2, beta: 1 }
d.support()       // [{ value, closed }, { value, closed }] — lower/upper bounds
d.sample(n)       // generate n random variates
d.pdf(x)          // probability density / mass function
d.cdf(x)          // cumulative distribution function
d.q(p)            // inverse CDF (quantile function)
d.survival(x)     // complementary CDF  (1 − CDF)
d.hazard(x)       // hazard rate        (pdf / survival)
d.cHazard(x)      // cumulative hazard  (−log survival)
d.lnPdf(x)        // log probability density / mass
d.lnL(data)       // log-likelihood over an array of observations
d.aic(data)       // Akaike information criterion
d.bic(data)       // Bayesian information criterion
d.test(data)      // KS test (continuous) or chi-squared test (discrete)
d.seed(value)     // set PRNG seed; returns the instance
d.save()          // serialise PRNG state + parameters to a plain object
d.load(state)     // restore from a saved state; returns the instance

ran.dist.Gamma.fit(data)  // static — MLE fit; returns a new instance

Return values and errors

ranjs signals an unusual result through one of four channels, chosen by the kind of situation:

| Situation | What you get | | --- | --- | | Invalid input — missing/NaN parameters, broken constraints, wrong arity, mismatched dimensions | a thrown Error | | A valid query whose answer is mathematically undefined (e.g. the mean of a Cauchy distribution) | NaN | | A valid query whose answer diverges (e.g. the variance of a Pareto with shape ≤ 2, any moment of a Lévy) | Infinity (or -Infinity) | | A correct value that simply equals zero (e.g. a density evaluated outside the support) | 0 |

Functions never return undefined to mean "failed" or "does not exist" — numeric results stay numbers (NaN/Infinity), and genuine misuse throws. NaN and Infinity are kept distinct on purpose: NaN means no value exists, Infinity means the value grows without bound. This mirrors the conventions of SciPy and R.

const ran = require('ranjs')

new ran.dist.Cauchy(0, 1).mean()       // => NaN       (undefined moment)
new ran.dist.Pareto(1, 2).variance()   // => Infinity  (divergent moment)
new ran.dist.Normal(0, 1).pdf(-Infinity) // => 0       (outside support)

Numerical precision

ranjs targets ≤ 1e-14 relative error for all public outputs in non-degenerate parameter regions. Outputs involving deeply composed operations (quantile inversion, extreme parameter regimes) have a documented floor of ~1e-12, looser still for a handful of quantiles computed by numerical root-finding or near-boundary asymptotics (see below).

Test reference values

All reference values in test/dist-cases-continuous.js and test/dist-cases-discrete.js are sourced from external tools — mpmath at mp.dps = 50, scipy.stats, or Wolfram Alpha — never computed from ranjs itself. Use scripts/gen-dist-refs.py to generate reference values when adding a new distribution, and verify at least one value per distribution against an independent source. pdf, cdf, and pmf reference-value assertions enforce 1e-14 relative tolerance by default; distributions that cannot reach 1e-14 in specific regimes use 1e-12 with an explanatory comment.

All 31 discrete distributions are verified against mpmath references at 50 decimal places. BetaBinomial and NegativeHypergeometric sit at the ~2e-14 float64 arithmetic floor. The following distributions cap at 1e-12 at certain parameter settings: Binomial, Hypergeometric, NegativeBinomial, Poisson, Skellam.

All 110 continuous distributions are likewise verified against mpmath references at 50 decimal places (three parameter sets each). pdf/cdf cap at 1e-12–1e-13 at certain parameter settings for: Bates, IrwinHall, Levy, NoncentralBeta, NoncentralChi, NoncentralT, DoublyNoncentralT, SkewNormal, Rice, and R. Quantiles with a closed-form or Halley-refined inverse round-trip to 1e-14; those computed by numerical root-finding (BaldingNichols, Bates, BetaPrime, Davis, FisherZ, Muth, NoncentralChi2, NoncentralF, DoublyNoncentralChi2, DoublyNoncentralT, SkewNormal, Student's t/z, UniformProduct, R) round-trip to ~1e-13–1e-10, and BenktanderII's near-boundary asymptotic branch (b → 1) to ~1e-9.

Documentation

Full API reference and distribution catalogue: https://synesenom.github.io/ran/

License

MIT