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
11 changes: 5 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ cfg-if = "1.0.0"
ndarray = { version = "0.15", optional = true }
num-traits = "0.2.12"
num = "0.4"
rand = { version = "0.8.5", default-features = false, features = ["small_rng"] }
rand_distr = { version = "0.4", optional = true }
rand = { version = "0.10.1", default-features = false, features = ["alloc"] }
serde = { version = "1", features = ["derive"], optional = true }
ordered-float = "5.1.0"

Expand All @@ -37,13 +36,13 @@ typetag = { version = "0.2", optional = true }
default = []
serde = ["dep:serde", "dep:typetag"]
ndarray-bindings = ["dep:ndarray"]
datasets = ["dep:rand_distr", "std_rand", "serde"]
std_rand = ["rand/std_rng", "rand/std"]
datasets = ["std_rand", "serde"]
std_rand = ["rand/std_rng", "rand/std", "rand/thread_rng"]
# used by wasm32-unknown-unknown for in-browser usage
js = ["getrandom/js"]
js = ["getrandom/wasm_js"]

[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.2.8", optional = true }
getrandom = { version = "0.4", optional = true }

[target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi")))'.dev-dependencies]
wasm-bindgen-test = "0.3"
Expand Down
6 changes: 3 additions & 3 deletions src/cluster/kmeans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
use std::fmt::Debug;
use std::marker::PhantomData;

use rand::Rng;
use rand::RngExt;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -356,7 +356,7 @@ impl<TX: Number, TY: Number, X: Array2<TX>, Y: Array1<TY>> KMeans<TX, TY, X, Y>
let (n, _) = data.shape();
let mut y = vec![0; n];
let mut centroid: Vec<TX> = data
.get_row(rng.gen_range(0..n))
.get_row(rng.random_range(0..n))
.iterator(0)
.cloned()
.collect();
Expand All @@ -382,7 +382,7 @@ impl<TX: Number, TY: Number, X: Array2<TX>, Y: Array1<TY>> KMeans<TX, TY, X, Y>
for i in d.iter() {
sum += *i;
}
let cutoff = rng.gen::<f64>() * sum;
let cutoff = rng.random::<f64>() * sum;
let mut cost = 0f64;
let mut index = 0;
while index < n {
Expand Down
61 changes: 34 additions & 27 deletions src/dataset/generator.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,47 @@
//! # Dataset Generators
//!
use rand::distributions::Uniform;
use rand::prelude::*;
use rand_distr::Normal;
use rand::distr::Distribution;
use rand::distr::Uniform;

use crate::dataset::Dataset;

/// Sample from N(mean, std) via Box-Muller transform using only rand 0.10
#[inline]
fn sample_normal(mean: f32, std: f32, rng: &mut impl rand::Rng) -> f32 {
let unit = Uniform::new(f32::EPSILON, 1.0f32).unwrap();
let u1 = unit.sample(rng);
let u2 = unit.sample(rng);
let z = (-2.0 * u1.ln()).sqrt() * (2.0 * std::f32::consts::PI * u2).cos();
mean + std * z
}

/// Generate `num_centers` clusters of normally distributed points
pub fn make_blobs(
num_samples: usize,
num_features: usize,
num_centers: usize,
) -> Dataset<f32, f32> {
let center_box = Uniform::from(-10.0..10.0);
let cluster_std = 1.0;
let mut centers: Vec<Vec<Normal<f32>>> = Vec::with_capacity(num_centers);
let center_box = Uniform::new(-10.0f32, 10.0f32).expect("Invalid uniform range");
let cluster_std = 1.0f32;
let mut rng = rand::rng();

let mut rng = rand::thread_rng();
for _ in 0..num_centers {
centers.push(
// Pre-compute cluster centers (one mean per feature per cluster)
let centers: Vec<Vec<f32>> = (0..num_centers)
.map(|_| {
(0..num_features)
.map(|_| Normal::new(center_box.sample(&mut rng), cluster_std).unwrap())
.collect(),
);
}
.map(|_| center_box.sample(&mut rng))
.collect()
})
.collect();

let mut y: Vec<f32> = Vec::with_capacity(num_samples);
let mut x: Vec<f32> = Vec::with_capacity(num_samples);
let mut x: Vec<f32> = Vec::with_capacity(num_samples * num_features);

for i in 0..num_samples {
let label = i % num_centers;
y.push(label as f32);
for j in 0..num_features {
x.push(centers[label][j].sample(&mut rng));
x.push(sample_normal(centers[label][j], cluster_std, &mut rng));
}
}

Expand All @@ -59,21 +68,20 @@ pub fn make_circles(num_samples: usize, factor: f32, noise: f32) -> Dataset<f32,
let linspace_out = linspace(0.0, 2.0 * std::f32::consts::PI, num_samples_out);
let linspace_in = linspace(0.0, 2.0 * std::f32::consts::PI, num_samples_in);

let noise = Normal::new(0.0, noise).unwrap();
let mut rng = rand::thread_rng();
let mut rng = rand::rng();

let mut x: Vec<f32> = Vec::with_capacity(num_samples * 2);
let mut y: Vec<f32> = Vec::with_capacity(num_samples);

for v in linspace_out {
x.push(v.cos() + noise.sample(&mut rng));
x.push(v.sin() + noise.sample(&mut rng));
x.push(v.cos() + sample_normal(0.0, noise, &mut rng));
x.push(v.sin() + sample_normal(0.0, noise, &mut rng));
y.push(0.0);
}

for v in linspace_in {
x.push(v.cos() * factor + noise.sample(&mut rng));
x.push(v.sin() * factor + noise.sample(&mut rng));
x.push(v.cos() * factor + sample_normal(0.0, noise, &mut rng));
x.push(v.sin() * factor + sample_normal(0.0, noise, &mut rng));
y.push(1.0);
}

Expand All @@ -96,21 +104,20 @@ pub fn make_moons(num_samples: usize, noise: f32) -> Dataset<f32, u32> {
let linspace_out = linspace(0.0, std::f32::consts::PI, num_samples_out);
let linspace_in = linspace(0.0, std::f32::consts::PI, num_samples_in);

let noise = Normal::new(0.0, noise).unwrap();
let mut rng = rand::thread_rng();
let mut rng = rand::rng();

let mut x: Vec<f32> = Vec::with_capacity(num_samples * 2);
let mut y: Vec<f32> = Vec::with_capacity(num_samples);

for v in linspace_out {
x.push(v.cos() + noise.sample(&mut rng));
x.push(v.sin() + noise.sample(&mut rng));
x.push(v.cos() + sample_normal(0.0, noise, &mut rng));
x.push(v.sin() + sample_normal(0.0, noise, &mut rng));
y.push(0.0);
}

for v in linspace_in {
x.push(1.0 - v.cos() + noise.sample(&mut rng));
x.push(1.0 - v.sin() + noise.sample(&mut rng) - 0.5);
x.push(1.0 - v.cos() + sample_normal(0.0, noise, &mut rng));
x.push(1.0 - v.sin() + sample_normal(0.0, noise, &mut rng) - 0.5);
y.push(1.0);
}

Expand Down
6 changes: 3 additions & 3 deletions src/ensemble/base_forest_regressor.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rand::Rng;
use rand::RngExt;
use std::fmt::Debug;

#[cfg(feature = "serde")]
Expand Down Expand Up @@ -209,10 +209,10 @@ impl<TX: Number + FloatNumber + PartialOrd, TY: Number, X: Array2<TX>, Y: Array1
result / TY::from(n_trees).unwrap()
}

fn sample_with_replacement(nrows: usize, rng: &mut impl Rng) -> Vec<usize> {
fn sample_with_replacement(nrows: usize, rng: &mut impl rand::Rng) -> Vec<usize> {
let mut samples = vec![0; nrows];
for _ in 0..nrows {
let xi = rng.gen_range(0..nrows);
let xi = rng.random_range(0..nrows);
samples[xi] += 1;
}
samples
Expand Down
10 changes: 7 additions & 3 deletions src/ensemble/random_forest_classifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
//!
//! <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
//! <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
use rand::Rng;
use rand::RngExt;

use std::default::Default;
use std::fmt::Debug;
Expand Down Expand Up @@ -587,7 +587,11 @@ impl<TX: FloatNumber + PartialOrd, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY
which_max(&result)
}

fn sample_with_replacement(y: &[usize], num_classes: usize, rng: &mut impl Rng) -> Vec<usize> {
fn sample_with_replacement(
y: &[usize],
num_classes: usize,
rng: &mut impl rand::Rng,
) -> Vec<usize> {
let class_weight = vec![1.; num_classes];
let nrows = y.len();
let mut samples = vec![0; nrows];
Expand All @@ -603,7 +607,7 @@ impl<TX: FloatNumber + PartialOrd, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY

let size = ((n_samples as f64) / *class_weight_l) as usize;
for _ in 0..size {
let xi: usize = rng.gen_range(0..n_samples);
let xi: usize = rng.random_range(0..n_samples);
samples[index[xi]] += 1;
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/numbers/floatnum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ impl FloatNumber for f64 {
}

fn rand() -> f64 {
use rand::Rng;
use rand::RngExt;
let mut rng = get_rng_impl(None);
rng.gen()
rng.random()
}

fn two() -> Self {
Expand Down Expand Up @@ -98,9 +98,9 @@ impl FloatNumber for f32 {
}

fn rand() -> f32 {
use rand::Rng;
use rand::RngExt;
let mut rng = get_rng_impl(None);
rng.gen()
rng.random()
}

fn two() -> Self {
Expand Down
14 changes: 5 additions & 9 deletions src/numbers/realnum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! This module defines real number and some useful functions that are used in [Linear Algebra](../../linalg/index.html) module.

use rand::rngs::SmallRng;
use rand::{Rng, SeedableRng};
use rand::{RngExt, SeedableRng};

use num_traits::Float;

Expand Down Expand Up @@ -69,10 +69,8 @@ impl RealNumber for f64 {
fn rand() -> f64 {
let mut small_rng = get_rng_impl(None);

let mut rngs: Vec<SmallRng> = (0..3)
.map(|_| SmallRng::from_rng(&mut small_rng).unwrap())
.collect();
rngs[0].gen::<f64>()
let mut rngs: Vec<SmallRng> = (0..3).map(|_| SmallRng::from_rng(&mut small_rng)).collect();
rngs[0].random::<f64>()
}

fn two() -> Self {
Expand Down Expand Up @@ -118,10 +116,8 @@ impl RealNumber for f32 {
fn rand() -> f32 {
let mut small_rng = get_rng_impl(None);

let mut rngs: Vec<SmallRng> = (0..3)
.map(|_| SmallRng::from_rng(&mut small_rng).unwrap())
.collect();
rngs[0].gen::<f32>()
let mut rngs: Vec<SmallRng> = (0..3).map(|_| SmallRng::from_rng(&mut small_rng)).collect();
rngs[0].random::<f32>()
}

fn two() -> Self {
Expand Down
7 changes: 5 additions & 2 deletions src/rand_custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ pub fn get_rng_impl(seed: Option<u64>) -> RngImpl {
None => {
cfg_if::cfg_if! {
if #[cfg(feature = "std_rand")] {
use rand::RngCore;
RngImpl::seed_from_u64(rand::thread_rng().next_u64())
use rand::Rng;
// FIX: thread_rng() deprecated in rand 0.9 → use rng()
// FIX: rand 0.10 no longer re-exports RngCore at root;
// import rand::Rng (supertrait) instead so next_u64() resolves
RngImpl::seed_from_u64(rand::rng().next_u64())
} else {
// no std_random feature build, use getrandom
#[cfg(feature = "js")]
Expand Down
4 changes: 2 additions & 2 deletions src/readers/io_testing.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! This module contains functionality to test IO. It has both functions that write
//! to the file-system for end-to-end tests, but also abstractions to avoid this by
//! reading from strings instead.
use rand::distributions::{Alphanumeric, DistString};
use rand::distr::{Alphanumeric, SampleString};
use std::fs;
use std::io::Bytes;
use std::io::Read;
Expand All @@ -16,7 +16,7 @@ pub struct TemporaryTextFile {
impl TemporaryTextFile {
pub fn new(contents: &str) -> std::io::Result<Self> {
let test_text_file = TemporaryTextFile {
random_path: Alphanumeric.sample_string(&mut rand::thread_rng(), 16),
random_path: Alphanumeric.sample_string(&mut rand::rng(), 16),
};
string_to_file(contents, &test_text_file.random_path)?;
Ok(test_text_file)
Expand Down
10 changes: 5 additions & 5 deletions src/tree/base_tree_regressor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::fmt::Debug;
use std::marker::PhantomData;

use rand::seq::SliceRandom;
use rand::Rng;
use rand::RngExt;

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -292,7 +292,7 @@ impl<TX: Number + PartialOrd, TY: Number, X: Array2<TX>, Y: Array1<TY>>
&mut self,
visitor: &mut NodeVisitor<'_, TX, TY, X, Y>,
mtry: usize,
rng: &mut impl Rng,
rng: &mut impl rand::Rng,
) -> bool {
let (_, n_attr) = visitor.x.shape();

Expand Down Expand Up @@ -336,7 +336,7 @@ impl<TX: Number + PartialOrd, TY: Number, X: Array2<TX>, Y: Array1<TY>>
sum: f64,
parent_gain: f64,
j: usize,
rng: &mut impl Rng,
rng: &mut impl rand::Rng,
) {
let (min_val, max_val) = {
let mut min_opt = None;
Expand All @@ -363,7 +363,7 @@ impl<TX: Number + PartialOrd, TY: Number, X: Array2<TX>, Y: Array1<TY>>
return;
}

let split_value = rng.gen_range(min_val.to_f64().unwrap()..max_val.to_f64().unwrap());
let split_value = rng.random_range(min_val.to_f64().unwrap()..max_val.to_f64().unwrap());

let mut true_sum = 0f64;
let mut true_count = 0;
Expand Down Expand Up @@ -476,7 +476,7 @@ impl<TX: Number + PartialOrd, TY: Number, X: Array2<TX>, Y: Array1<TY>>
mut visitor: NodeVisitor<'a, TX, TY, X, Y>,
mtry: usize,
visitor_queue: &mut LinkedList<NodeVisitor<'a, TX, TY, X, Y>>,
rng: &mut impl Rng,
rng: &mut impl rand::Rng,
) -> bool {
let (n, _) = visitor.x.shape();
let mut tc = 0;
Expand Down
Loading