use super::engine::{self, Xoshiro256StarStar};
use crate::{Array, Element};
#[derive(Clone)]
pub struct Rng {
inner: Xoshiro256StarStar,
}
impl Rng {
pub fn seed(seed: u64) -> Self {
Self {
inner: Xoshiro256StarStar::seed(seed),
}
}
pub fn from_entropy() -> Self {
Self {
inner: Xoshiro256StarStar::from_entropy(),
}
}
pub fn random(&mut self, shape: &[usize]) -> Array<f64> {
let len: usize = shape.iter().product();
let data = engine::random_vec(&mut self.inner, len);
Array::from_vec(data, shape)
}
pub fn uniform(&mut self, low: f64, high: f64, shape: &[usize]) -> Array<f64> {
let len: usize = shape.iter().product();
let data = engine::uniform_vec(&mut self.inner, low, high, len);
Array::from_vec(data, shape)
}
pub fn normal(&mut self, mean: f64, std: f64, shape: &[usize]) -> Array<f64> {
assert!(std >= 0.0, "scale < 0");
let len: usize = shape.iter().product();
let data = engine::normal_vec(&mut self.inner, mean, std, len);
Array::from_vec(data, shape)
}
pub fn standard_normal(&mut self, shape: &[usize]) -> Array<f64> {
let len: usize = shape.iter().product();
let data = engine::standard_normal_vec(&mut self.inner, len);
Array::from_vec(data, shape)
}
pub fn integers(&mut self, low: i64, high: i64, shape: &[usize]) -> Array<i64> {
assert!(low < high, "low >= high");
let len: usize = shape.iter().product();
let data = engine::integers_vec(&mut self.inner, low, high, len);
Array::from_vec(data, shape)
}
pub fn choice<T: Element>(&mut self, a: &Array<T>, n: usize, replace: bool) -> Array<T> {
assert!(a.ndim() >= 1, "a must be 1-dimensional or an integer");
let pop = a.shape()[0];
assert!(
pop > 0 || n == 0,
"a cannot be empty unless no samples are taken"
);
assert!(
replace || n <= pop,
"Cannot take a larger sample than population when replace is False"
);
let indices = engine::choice_indices(&mut self.inner, pop, n, replace);
a.take(&indices, 0)
}
pub fn shuffle<T: Element>(&mut self, a: &mut Array<T>) {
assert!(
a.ndim() >= 1,
"shuffle requires an array with at least 1 dimension"
);
let order = engine::permutation_vec(&mut self.inner, a.shape()[0]);
*a = a.take(&order, 0);
}
pub fn permutation(&mut self, n: usize) -> Array<usize> {
Array::from_vec(engine::permutation_vec(&mut self.inner, n), &[n])
}
pub fn binomial(&mut self, n: u64, p: f64, shape: &[usize]) -> Array<i64> {
assert!((0.0..=1.0).contains(&p), "p < 0, p > 1 or p is NaN");
assert!(i64::try_from(n).is_ok(), "n is too large");
let len: usize = shape.iter().product();
Array::from_vec(engine::binomial_vec(&mut self.inner, n, p, len), shape)
}
pub fn poisson(&mut self, lam: f64, shape: &[usize]) -> Array<i64> {
assert!(lam >= 0.0, "lam < 0 or lam is NaN");
assert!(lam.is_finite(), "lam value too large");
let len: usize = shape.iter().product();
Array::from_vec(engine::poisson_vec(&mut self.inner, lam, len), shape)
}
pub fn exponential(&mut self, scale: f64, shape: &[usize]) -> Array<f64> {
assert!(scale >= 0.0, "scale < 0");
let len: usize = shape.iter().product();
Array::from_vec(engine::exponential_vec(&mut self.inner, scale, len), shape)
}
pub fn beta(&mut self, a: f64, b: f64, shape: &[usize]) -> Array<f64> {
assert!(a > 0.0, "a <= 0");
assert!(b > 0.0, "b <= 0");
let len: usize = shape.iter().product();
Array::from_vec(engine::beta_vec(&mut self.inner, a, b, len), shape)
}
pub fn gamma(&mut self, shape_param: f64, scale: f64, shape: &[usize]) -> Array<f64> {
assert!(shape_param >= 0.0, "shape < 0");
assert!(scale >= 0.0, "scale < 0");
let len: usize = shape.iter().product();
let data = engine::gamma_vec(&mut self.inner, shape_param, scale, len);
Array::from_vec(data, shape)
}
}