Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
389 changes: 259 additions & 130 deletions Cargo.lock.MSRV

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ edition = "2021"
include = ["CHANGELOG.md", "LICENSE.md", "src/", "tests/"]

# When changing MSRV: Also update the README
rust-version = "1.65.0"
rust-version = "1.87.0"

[lib]
name = "statrs"
Expand All @@ -36,12 +36,12 @@ approx = "0.5.0"
num-traits = "0.2.14"

[dependencies.rand]
version = "0.8"
version = "0.9.0"
optional = true
default-features = false

[dependencies.nalgebra]
version = "0.33"
version = "0.34"
optional = true
default-features = false

Expand All @@ -50,7 +50,7 @@ criterion = "0.5"
anyhow = "1.0"

[dev-dependencies.nalgebra]
version = "0.33"
version = "0.34"
default-features = false
features = ["macros"]

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ If you'd like to modify where the data is downloaded, you can use the environmen

## Minimum supported Rust version (MSRV)

This crate requires a Rust version of 1.65.0 or higher. Increases in MSRV will be considered a semver non-breaking API change and require a version increase (PATCH until 1.0.0, MINOR after 1.0.0).
This crate requires a Rust version of 1.87.0 or higher. Increases in MSRV will be considered a semver non-breaking API change and require a version increase (PATCH until 1.0.0, MINOR after 1.0.0).

## Precision
Floating-point numbers cannot always represent decimal values exactly, which can introduce small (and in some cases catastrophically large) errors in computations.
Expand Down
8 changes: 4 additions & 4 deletions benches/order_statistics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ use rand::prelude::*;
use statrs::statistics::*;

fn bench_order_statistic(c: &mut Criterion) {
let mut rng = thread_rng();
let mut rng = rand::rng();
let to_random_owned = |data: &[f64]| -> Data<Vec<f64>> {
let mut rng = thread_rng();
let mut rng = rand::rng();
let mut owned = data.to_vec();
owned.shuffle(&mut rng);
Data::new(owned)
};
let k = black_box(rng.gen());
let tau = black_box(rng.gen_range(0.0..1.0));
let k = black_box(rng.random_range(..=usize::MAX));
let tau = black_box(rng.random_range(0.0..1.0));
let mut group = c.benchmark_group("order statistic");
let data: Vec<_> = (0..100).map(|x| x as f64).collect();
group.bench_function("order_statistic", |b| {
Expand Down
6 changes: 3 additions & 3 deletions src/distribution/bernoulli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,15 @@ impl core::fmt::Display for Bernoulli {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<bool> for Bernoulli {
impl ::rand::distr::Distribution<bool> for Bernoulli {
fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> bool {
rng.gen_bool(self.p())
rng.random_bool(self.p())
}
}

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<f64> for Bernoulli {
impl ::rand::distr::Distribution<f64> for Bernoulli {
fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> f64 {
rng.sample::<bool, _>(self) as u8 as f64
}
Expand Down
2 changes: 1 addition & 1 deletion src/distribution/beta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ impl core::fmt::Display for Beta {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<f64> for Beta {
impl ::rand::distr::Distribution<f64> for Beta {
fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> f64 {
// Generated by sampling two gamma distributions and normalizing.
let x = super::gamma::sample_unchecked(rng, self.shape_a, 1.0);
Expand Down
6 changes: 3 additions & 3 deletions src/distribution/binomial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,10 @@ impl core::fmt::Display for Binomial {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<u64> for Binomial {
impl ::rand::distr::Distribution<u64> for Binomial {
fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> u64 {
(0..self.n).fold(0, |acc, _| {
let n: f64 = rng.gen();
let n: f64 = rng.random();
if n < self.p {
acc + 1
} else {
Expand All @@ -128,7 +128,7 @@ impl ::rand::distributions::Distribution<u64> for Binomial {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<f64> for Binomial {
impl ::rand::distr::Distribution<f64> for Binomial {
fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> f64 {
rng.sample::<u64, _>(self) as f64
}
Expand Down
8 changes: 4 additions & 4 deletions src/distribution/categorical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,23 +127,23 @@ impl core::fmt::Display for Categorical {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<usize> for Categorical {
impl ::rand::distr::Distribution<usize> for Categorical {
fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> usize {
sample_unchecked(rng, &self.cdf)
}
}

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<u64> for Categorical {
impl ::rand::distr::Distribution<u64> for Categorical {
fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> u64 {
sample_unchecked(rng, &self.cdf) as u64
}
}

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<f64> for Categorical {
impl ::rand::distr::Distribution<f64> for Categorical {
fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> f64 {
sample_unchecked(rng, &self.cdf) as f64
}
Expand Down Expand Up @@ -344,7 +344,7 @@ impl Discrete<u64, f64> for Categorical {
#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
pub fn sample_unchecked<R: ::rand::Rng + ?Sized>(rng: &mut R, cdf: &[f64]) -> usize {
let draw = rng.gen::<f64>() * cdf.last().unwrap();
let draw = rng.random::<f64>() * cdf.last().unwrap();
cdf.iter().position(|val| *val >= draw).unwrap()
}

Expand Down
4 changes: 2 additions & 2 deletions src/distribution/cauchy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ impl core::fmt::Display for Cauchy {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<f64> for Cauchy {
impl ::rand::distr::Distribution<f64> for Cauchy {
fn sample<R: ::rand::Rng + ?Sized>(&self, r: &mut R) -> f64 {
self.location + self.scale * (f64::consts::PI * (r.gen::<f64>() - 0.5)).tan()
self.location + self.scale * (f64::consts::PI * (r.random::<f64>() - 0.5)).tan()
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/distribution/chi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ impl core::fmt::Display for Chi {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<f64> for Chi {
impl ::rand::distr::Distribution<f64> for Chi {
fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> f64 {
(0..self.freedom())
.fold(0.0, |acc, _| {
Expand Down
4 changes: 2 additions & 2 deletions src/distribution/chi_squared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ impl core::fmt::Display for ChiSquared {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<f64> for ChiSquared {
impl ::rand::distr::Distribution<f64> for ChiSquared {
fn sample<R: ::rand::Rng + ?Sized>(&self, r: &mut R) -> f64 {
::rand::distributions::Distribution::sample(&self.g, r)
::rand::distr::Distribution::sample(&self.g, r)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/distribution/dirac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl core::fmt::Display for Dirac {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<f64> for Dirac {
impl ::rand::distr::Distribution<f64> for Dirac {
fn sample<R: ::rand::Rng + ?Sized>(&self, _: &mut R) -> f64 {
self.0
}
Expand Down
2 changes: 1 addition & 1 deletion src/distribution/dirichlet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ where

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl<D> ::rand::distributions::Distribution<OVector<f64, D>> for Dirichlet<D>
impl<D> ::rand::distr::Distribution<OVector<f64, D>> for Dirichlet<D>
where
D: Dim,
nalgebra::DefaultAllocator: nalgebra::allocator::Allocator<D>,
Expand Down
6 changes: 3 additions & 3 deletions src/distribution/discrete_uniform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,15 @@ impl core::fmt::Display for DiscreteUniform {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<i64> for DiscreteUniform {
impl ::rand::distr::Distribution<i64> for DiscreteUniform {
fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> i64 {
rng.gen_range(self.min..=self.max)
rng.random_range(self.min..=self.max)
}
}

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<f64> for DiscreteUniform {
impl ::rand::distr::Distribution<f64> for DiscreteUniform {
fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> f64 {
rng.sample::<i64, _>(self) as f64
}
Expand Down
2 changes: 1 addition & 1 deletion src/distribution/empirical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ impl FromIterator<f64> for Empirical {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<f64> for Empirical {
impl ::rand::distr::Distribution<f64> for Empirical {
fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> f64 {
use crate::distribution::Uniform;

Expand Down
4 changes: 2 additions & 2 deletions src/distribution/erlang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,9 @@ impl core::fmt::Display for Erlang {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<f64> for Erlang {
impl ::rand::distr::Distribution<f64> for Erlang {
fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> f64 {
::rand::distributions::Distribution::sample(&self.g, rng)
::rand::distr::Distribution::sample(&self.g, rng)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/distribution/exponential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ impl core::fmt::Display for Exp {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<f64> for Exp {
impl ::rand::distr::Distribution<f64> for Exp {
fn sample<R: ::rand::Rng + ?Sized>(&self, r: &mut R) -> f64 {
use crate::distribution::ziggurat;

Expand Down
2 changes: 1 addition & 1 deletion src/distribution/fisher_snedecor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ impl core::fmt::Display for FisherSnedecor {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<f64> for FisherSnedecor {
impl ::rand::distr::Distribution<f64> for FisherSnedecor {
fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> f64 {
(super::gamma::sample_unchecked(rng, self.freedom_1 / 2.0, 0.5) * self.freedom_2)
/ (super::gamma::sample_unchecked(rng, self.freedom_2 / 2.0, 0.5) * self.freedom_1)
Expand Down
6 changes: 3 additions & 3 deletions src/distribution/gamma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ impl core::fmt::Display for Gamma {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<f64> for Gamma {
impl ::rand::distr::Distribution<f64> for Gamma {
fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> f64 {
sample_unchecked(rng, self.shape, self.rate)
}
Expand Down Expand Up @@ -410,7 +410,7 @@ pub fn sample_unchecked<R: ::rand::Rng + ?Sized>(rng: &mut R, shape: f64, rate:
let mut afix = 1.0;
if shape < 1.0 {
a = shape + 1.0;
afix = rng.gen::<f64>().powf(1.0 / shape);
afix = rng.random::<f64>().powf(1.0 / shape);
}

let d = a - 1.0 / 3.0;
Expand All @@ -428,7 +428,7 @@ pub fn sample_unchecked<R: ::rand::Rng + ?Sized>(rng: &mut R, shape: f64, rate:

v = v * v * v;
x = x * x;
let u: f64 = rng.gen();
let u: f64 = rng.random();
if u < 1.0 - 0.0331 * x * x || u.ln() < 0.5 * x + d * (1.0 - v + v.ln()) {
return afix * d * v / rate;
}
Expand Down
6 changes: 3 additions & 3 deletions src/distribution/geometric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,12 @@ impl core::fmt::Display for Geometric {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<u64> for Geometric {
impl ::rand::distr::Distribution<u64> for Geometric {
fn sample<R: ::rand::Rng + ?Sized>(&self, r: &mut R) -> u64 {
if prec::ulps_eq!(self.p, 1.0) {
1
} else {
let x: f64 = r.sample(::rand::distributions::OpenClosed01);
let x: f64 = r.sample(::rand::distr::OpenClosed01);
// This cast is safe, because the largest finite value this expression can take is when
// `x = 1.4e-45` and `1.0 - self.p = 0.9999999999999999`, in which case we get
// `930262250532780300`, which when casted to a `u64` is `930262250532780288`.
Expand All @@ -110,7 +110,7 @@ impl ::rand::distributions::Distribution<u64> for Geometric {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<f64> for Geometric {
impl ::rand::distr::Distribution<f64> for Geometric {
fn sample<R: ::rand::Rng + ?Sized>(&self, r: &mut R) -> f64 {
r.sample::<u64, _>(self) as f64
}
Expand Down
6 changes: 3 additions & 3 deletions src/distribution/gumbel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,9 @@ impl core::fmt::Display for Gumbel {
}

#[cfg(feature = "rand")]
impl ::rand::distributions::Distribution<f64> for Gumbel {
impl ::rand::distr::Distribution<f64> for Gumbel {
fn sample<R: rand::Rng + ?Sized>(&self, r: &mut R) -> f64 {
self.location - self.scale * ((-(r.gen::<f64>())).ln()).ln()
self.location - self.scale * ((-(r.random::<f64>())).ln()).ln()
}
}

Expand Down Expand Up @@ -385,7 +385,7 @@ mod tests {
test_exact(0.0, 2.0, 2.270362845461478, entropy);
test_exact(0.1, 4.0, 2.9635100260214235, entropy);
test_exact(1.0, 10.0, 3.8798007578955787, entropy);
test_exact(10.0, 11.0, 3.9751109376999034, entropy);
test_exact(10.0, 11.0, 3.9751109376999034, entropy);
}

#[test]
Expand Down
6 changes: 3 additions & 3 deletions src/distribution/hypergeometric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,15 +160,15 @@ impl core::fmt::Display for Hypergeometric {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<u64> for Hypergeometric {
impl ::rand::distr::Distribution<u64> for Hypergeometric {
fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> u64 {
let mut population = self.population as f64;
let mut successes = self.successes as f64;
let mut draws = self.draws;
let mut x = 0;
loop {
let p = successes / population;
let next: f64 = rng.gen();
let next: f64 = rng.random();
if next < p {
x += 1;
successes -= 1.0;
Expand All @@ -185,7 +185,7 @@ impl ::rand::distributions::Distribution<u64> for Hypergeometric {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<f64> for Hypergeometric {
impl ::rand::distr::Distribution<f64> for Hypergeometric {
fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> f64 {
rng.sample::<u64, _>(self) as f64
}
Expand Down
2 changes: 1 addition & 1 deletion src/distribution/inverse_gamma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ impl core::fmt::Display for InverseGamma {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<f64> for InverseGamma {
impl ::rand::distr::Distribution<f64> for InverseGamma {
fn sample<R: ::rand::Rng + ?Sized>(&self, r: &mut R) -> f64 {
1.0 / super::gamma::sample_unchecked(r, self.shape, self.rate)
}
Expand Down
11 changes: 5 additions & 6 deletions src/distribution/laplace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ impl core::fmt::Display for Laplace {

#[cfg(feature = "rand")]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
impl ::rand::distributions::Distribution<f64> for Laplace {
impl ::rand::distr::Distribution<f64> for Laplace {
fn sample<R: ::rand::Rng + ?Sized>(&self, rng: &mut R) -> f64 {
let x: f64 = rng.gen_range(-0.5..0.5);
let x: f64 = rng.random_range(-0.5..0.5);
self.location - self.scale * x.signum() * (1. - 2. * x.abs()).ln()
}
}
Expand Down Expand Up @@ -557,17 +557,16 @@ mod tests {
#[cfg(feature = "rand")]
#[test]
fn test_sample() {
use ::rand::distributions::Distribution;
use ::rand::thread_rng;
use ::rand::distr::Distribution;

let l = create_ok(0.1, 0.5);
l.sample(&mut thread_rng());
l.sample(&mut ::rand::rng());
}

#[cfg(feature = "rand")]
#[test]
fn test_sample_distribution() {
use ::rand::distributions::Distribution;
use ::rand::distr::Distribution;
use ::rand::rngs::StdRng;
use ::rand::SeedableRng;

Expand Down
Loading