#statistics #simd #libm #no-std

no-std mv-norm

Multivariate Normal Distribution functions, CDF etc

7 releases

Uses new Rust 2024

0.1.6 Apr 30, 2025
0.1.5 Apr 21, 2025

#756 in Math

Download history 308/week @ 2025-04-16 20/week @ 2025-04-23 133/week @ 2025-04-30

461 downloads per month

MIT/Apache

60KB
942 lines

mv-norm

Crates.io Crates.io License

API Docs

Fast and accurate calcluations related to multivariate normal distributions, in pure rust. (Note: Right now we only have the bivariate normal CDF.)

This rust crate ports a subset of the R package mvtnorm, which is widely used for these purposes.

Additionally, this crate provides "batch evaluation" APIs which may be much faster if you need to evaluate many points. These APIs are designed to allow easy precomputation based on some of the parameters, so that work is shared across many evaluations, and to take advantage of SIMD.

Why?

A common practice for statistics, numerical integration, modeling, etc. is:

  • Use R, or Python with Numpy, which has many high-level functions you need and a nice repl with plotting.
  • Low-level statistical primitives, which are perf critical, are obtained by binding to existing C or Fortran code. These are fast, accurate, and widely used.

In this crate, we ported fortran code such as Alan Genz' tvpack algorithm, and tested against the original for fidelity.

Then we used wide and precomputation tricks to make it significantly faster, especially in a batch evaluation, where we get more then 5x improved throughput (but run benchmarks to see if you can repro this.)

This greatly accelerated a numerical integration routine for a statistical model.

Future Directions

  • Port more of the mvtnorm sources, and use Rust's nice SIMD facilities to optimize them. (Eventually, the core::simd stuff when it is stabilized.) For example support for Genz-Bretz, or the tvpack trivariate normal CDF routine, would be great.
  • Provide an f32 version of algorithms, especially if it can be significantly faster.
  • Allow the user to choose larger error tolerances and get faster algorithms when possible. Whether this should be done by providing differently named functions (see SLEEF for example) or a "policy object" like in boost::math, I'm not sure.
  • Expose python bindings and publish them.

Licensing and Distribution

GPLv2, because we ported code from mvtnorm which is GPLv2 licensed.

Dependencies

~1.5MB
~35K SLoC