Library / SDK
statrs-dev/statrs avatar
statrs-dev/statrs

statrs: statistical computing for Rust, with precision treated as a feature

Statistical computation library for Rust

834 stars123 forksRustMIT

At a glance

What is it?
A Rust crate of probability distributions and statistical functions that grew out of a port of Math.NET, ships a no_std path, and made its precision module private in v0.19.0 while keeping the constants visible.
Who is it for?
Adopt statrs when you need probability distributions, sampling or statistical functions inside a Rust codebase and cannot pull in a numerical stack, especially if you build for no_std or wasm32. Do not reach for it as a data analysis environment or a dataframe engine, and do not write code against the prec module, which became private in v0.19.0.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 34 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A port of Math.NET that is now the primary implementation

statrs began as a port of the statistical capabilities in the C# Math.NET library, and the project notes are explicit about the lineage: unit tests were borrowed from Math.NET where possible and filled in where not. That history explains the shape of the crate. It is organised like a numerical library, with named distributions and named special functions rather than a data analysis API.

What it provides is a set of common distributions that can be sampled, including Normal, Exponential, Student's T, Gamma and Uniform, plus statistical functions such as the gamma function, the beta function and the error function. The stated plan for future releases is continued implementations of distributions and porting over more statistical utilities.

The audience is Rust developers doing scientific computing who want these primitives in the type system and the dependency tree of their existing project, rather than shelling out to a separate numerical program. The homepage points to the docs.rs documentation, and the repository lists its crates.io categories as science.

One naming detail is worth knowing before you start reading the source: the crate and the library are both named `statrs`, with the library path declared as `src/lib.rs`.

Precision is a documented contract, not an afterthought

Most of the project documentation is about floating point precision, and that is the most distinctive thing about the crate. The premise is stated plainly: floating-point numbers cannot always represent decimal values exactly, which can introduce small and in some cases catastrophically large errors, and in statistical applications those errors accumulate.

The response is a set of conventions rather than a single tolerance. The crate uses standardized precision checks throughout, default precision levels are chosen to balance correctness against performance, and module-specific requirements are documented where they differ from the defaults. The test suite verifies numerical accuracy against common reference libraries.

The knobs are public constants in the `prec` module, which is where a reader should look first: `DEFAULT_RELATIVE_ACC`, `DEFAULT_EPS` and `DEFAULT_ULPS` for the crate defaults, and `MODULE_RELATIVE_ACC`, `MODULE_EPS` and `MODULE_ULPS` for modules whose defaults differ.

Here is the catch, and it is a breaking change worth catching in your dependency review. Starting from v0.19.0 the `prec` module is no longer public, moving from `pub mod prec` to `mod prec`. The constants remain stable and documented and are reexported at the crate level, but the module's utilities are no longer reachable, on the stated grounds that precision handling is an internal implementation detail. Code that reached into `prec` utilities directly will not compile after the upgrade.

no_std means you bring your own allocator

The crate can be built without the standard library by disabling default features:

toml
[dependencies]
statrs = { version = "*", default-features = false }

No separate Cargo feature is required for the allocation-backed APIs. Heap-backed APIs use Rust's `alloc` crate, and the documentation is direct about the consequence: a `no_std` application that calls them must provide and initialize a global allocator suitable for its target. The pattern given is a `#[global_allocator]` static of type `PlatformAllocator`, whose type, heap memory and initialization are platform specific. statrs does not provide or select an allocator. When `std` is enabled, its global allocator is used and no setup is required.

Matrix-backed distributions without `std` need the `nalgebra` feature enabled directly:

toml
[dependencies]
statrs = { version = "*", default-features = false, features = ["nalgebra"] }

The default feature set in Cargo.toml is `std`, `nalgebra` and `rand`, so a bare `statrs = "*"` dependency already brings in the matrix library and the random number generator. Turning default features off is what actually shrinks the dependency surface.

Randomness on wasm32 is your problem to solve

The WebAssembly story is documented in its own section, which tells you it is not automatic. On `wasm32-unknown-unknown`, sampling works with an explicitly seeded random number generator, because there is no host entropy source. Applications that need JavaScript entropy, the documentation gives `rand::rng()` as an example, must select the `getrandom` backend themselves:

toml
[dependencies]
statrs = "*"
rand = "0.10"
getrandom = { version = "0.4", features = ["wasm_js"] }

The rule the project states is that statrs does not select a randomness backend for downstream applications. That is a deliberate layering decision, and it also means a browser build can fail at the entropy layer rather than at a statistical call, so it is worth setting up early.

For a desktop or server target the same principle holds in reverse: with `std` enabled, the global allocator and the platform entropy source are already there, so nothing needs wiring.

Running the NIST reference tests

The test suite has a special tier that needs external data. The project notes state that running all suggested tests requires downloading data from NIST, and that a script handles the download and the formatting into the `tests/` folder.

Two commands cover it:

bash
cargo test
./tests/gather_nist_data.sh && cargo test -- --include-ignored nist_

The first is the ordinary test run. The second fetches the reference data and then runs the tests that are otherwise skipped, selected by the `nist_` prefix and enabled through `--include-ignored`. Where the data lands is configurable through the `STATRS_NIST_DATA_DIR` environment variable, which the project notes say covers both the script and the tests.

This is the part of the crate that shows how the accuracy claim is checked rather than asserted. A distribution implementation that matches published reference values to a stated tolerance is a different claim from one that merely runs its own unit tests, and the `nist_` prefix makes it clear which set of tests carries the external reference data.

MSRV bumps and the cost of following the crate

The crate requires Rust 1.89.0 or higher, and Cargo.toml declares `rust-version = "1.89.0"` with a comment reminding maintainers to update the README when the MSRV changes. The policy is spelled out: increases in MSRV are treated as a semver non-breaking API change, and require a version increase, a PATCH bump until 1.0.0 and a MINOR bump after 1.0.0.

That policy is unusual enough to be worth reading twice, because a Rust version floor that can rise without a breaking change is a real constraint on downstream users. A project pinned to an older toolchain cannot simply take the newest statrs release. The crate is still pre-1.0, currently at version 0.19.1 in Cargo.toml, and it has been for a while: v0.17.1 shipped on 2024-06-08, then v0.19.0 on 2026-07-20 and v0.19.1 on 2026-08-11.

The top level of the repository also carries `Cargo.lock.MSRV`, a separate lock file for the minimum supported Rust version, alongside `Cargo.toml`, `Cargo.lock`, `RELEASING.md` and `CHANGELOG.md`. A separate MSRV lock file is the mechanism that lets the project test the floor in CI while keeping the main lock file current.

The licence is MIT, declared in Cargo.toml and with the text in LICENSE.md. For a crate embedded in a commercial product that is a permissive licence with no copyleft obligation on the surrounding code.

What statrs is not, and when to look elsewhere

statrs is a numerical primitives crate, and reading it as anything larger will disappoint. It has no dataframe, no tabular query layer, no plotting and no statistics notebook. If your need is to read a CSV, group it, run a regression and print a table, statrs will give you the regression and nothing else, and you will be assembling the rest of that stack yourself in Rust.

The alternative for that class of work is a data analysis tool written for the job, which operates over labelled tabular data and comes with transformations, grouping and reporting built in. The difference in approach is that such a tool treats data as a collection of named columns and performs operations across them, while statrs operates on numbers and distributions with no notion of a row or a column. statrs is the piece that sits underneath such an engine, not a replacement for it.

There is also a scope boundary inside the crate itself. The `kde` feature, which brings in a kd-tree for density estimation, is not part of the default set, and the benchmarks in Cargo.toml show which combinations are exercised: an `order_statistics` bench needs the `rand` and `std` features, and a `density` bench additionally needs `kde`. A `no_std` user wanting kernel density estimation is pulling in `kdtree` and `nalgebra`, and the `kde` feature definition states it requires `std`.

On activity, the repository is not archived and the last push was on 2026-09-23, with two releases in the two months before that.

Editorial conclusion

Adopt statrs when you need probability distributions, sampling or statistical functions inside a Rust codebase and cannot pull in a numerical stack, especially if you build for no_std or wasm32. Do not reach for it as a data analysis environment or a dataframe engine, and do not write code against the prec module, which became private in v0.19.0. Verify first that your toolchain is at Rust 1.89.0 or newer, then decide whether the default features, which pull in std, nalgebra and rand, are the combination your target actually needs.

Frequently asked questions

How do I add statrs to a Rust project?

Add the dependency to Cargo.toml under `[dependencies]`, replacing the wildcard with the latest version of the crate. The project points to the docs.rs documentation for examples.

Can statrs be used without the Rust standard library?

Yes. Disable the default features with `statrs = { version = "*", default-features = false }`. Heap-backed APIs use the `alloc` crate, so a no_std application must provide and initialize a global allocator, and matrix-backed distributions need the `nalgebra` feature enabled directly.

What Rust version does statrs require?

The crate requires Rust 1.89.0 or higher, and increases in MSRV are treated as a semver non-breaking API change, requiring a version increase, PATCH until 1.0.0 and MINOR after 1.0.0.

Why does my code stop compiling after upgrading statrs to v0.19.0?

From v0.19.0 the `prec` module is no longer public, changing from `pub mod prec` to `mod prec`. The precision constants remain documented and are reexported at the crate level, but direct access to the module's utilities is now restricted.

How do I run the statrs tests that need reference data?

The NIST tests need external data. Run `cargo test` for the normal suite, then run `./tests/gather_nist_data.sh && cargo test -- --include-ignored nist_` to download the data and run the ignored tests. The download location can be changed with the `STATRS_NIST_DATA_DIR` environment variable.

Does statrs work on WebAssembly?

Sampling works on wasm32-unknown-unknown with an explicitly seeded random number generator. Applications needing JavaScript entropy must select the getrandom backend themselves with the `wasm_js` feature, since statrs does not select a randomness backend for downstream applications.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. statrs-dev/statrs on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/statrs-dev-statrs.svg)](https://hysenlabs.com/projects/statrs-dev-statrs)

Was this useful?