pub(crate) mod imp;
use std::panic::Location;
use crate::axes::{Axis, IntoShape};
use crate::{Array, DType, Error};
pub use imp::{key, seed};
#[track_caller]
pub fn next_key() -> Array {
Array::sticky("next_key", Location::caller(), &[], imp::next_key)
}
#[doc(hidden)]
pub fn sequence_key() -> Array {
imp::sequence_key()
}
#[doc(hidden)]
pub fn set_sequence_key(key: Array) {
imp::set_sequence_key(key);
}
#[track_caller]
pub fn bits<'a>(shape: impl IntoShape, width: i32, key: impl Into<Option<&'a Array>>) -> Array {
let key = key.into();
let spec = shape.shape_spec();
let dtype = match width {
1 => DType::U8,
2 => DType::U16,
_ => DType::U32,
};
Array::constructor("bits", Location::caller(), dtype, &spec, |shape| {
let width = usize::try_from(width)
.map_err(|_| Error::InvalidArgument(format!("bits: invalid width {width}")))?;
imp::bits(shape, width, key)
})
}
#[track_caller]
pub fn split(key: &Array, num: usize) -> Array {
Array::sticky("split", Location::caller(), &[key], || imp::split(key, num))
}
#[track_caller]
pub fn split_n<const N: usize>(key: &Array) -> [Array; N] {
Array::sticky_n("split", Location::caller(), &[key], || {
let all = imp::split(key, N)?;
let mut out = Vec::with_capacity(N);
for i in 0..N {
let row = crate::ops::imp::slice(
&all,
&[
crate::SliceArg::new(Some(i as isize), Some(i as isize + 1), 1),
crate::SliceArg::full(),
],
)?;
out.push(crate::ops::imp::reshape(&row, &[2])?);
}
Ok(out
.try_into()
.unwrap_or_else(|_| unreachable!("N keys were split")))
})
}
#[track_caller]
pub fn uniform<'a>(
low: f64,
high: f64,
shape: impl IntoShape,
dtype: DType,
key: impl Into<Option<&'a Array>>,
) -> Array {
let key = key.into();
let spec = shape.shape_spec();
Array::constructor("uniform", Location::caller(), dtype, &spec, |shape| {
imp::uniform(low, high, shape, dtype, key)
})
}
#[track_caller]
pub fn normal<'a>(
shape: impl IntoShape,
dtype: DType,
loc: f64,
scale: f64,
key: impl Into<Option<&'a Array>>,
) -> Array {
let key = key.into();
let spec = shape.shape_spec();
Array::constructor("normal", Location::caller(), dtype, &spec, |shape| {
imp::normal(shape, dtype, Some(loc), Some(scale), key)
})
}
#[track_caller]
pub fn gumbel<'a>(shape: impl IntoShape, dtype: DType, key: impl Into<Option<&'a Array>>) -> Array {
let key = key.into();
let spec = shape.shape_spec();
Array::constructor("gumbel", Location::caller(), dtype, &spec, |shape| {
imp::gumbel(shape, dtype, key)
})
}
#[track_caller]
pub fn categorical<'a>(
logits: &Array,
axis: impl Axis,
key: impl Into<Option<&'a Array>>,
) -> Array {
let key = key.into();
let spec = axis.axis_spec();
let mut ins = vec![logits];
ins.extend(key);
Array::sticky(
"categorical",
Location::caller(),
&ins,
|| match crate::axes::one_axis(spec, logits.ndim())? {
Some(axis) => imp::categorical(logits, axis as isize, key),
None => imp::categorical(&crate::ops::imp::reshape(logits, &[-1])?, 0, key),
},
)
}
#[track_caller]
pub fn randint<'a>(
low: i64,
high: i64,
shape: impl IntoShape,
dtype: DType,
key: impl Into<Option<&'a Array>>,
) -> Array {
let key = key.into();
let spec = shape.shape_spec();
Array::constructor("randint", Location::caller(), dtype, &spec, |shape| {
imp::randint(low, high, shape, dtype, key)
})
}
#[track_caller]
pub fn bernoulli<'a>(p: f64, shape: impl IntoShape, key: impl Into<Option<&'a Array>>) -> Array {
let key = key.into();
let spec = shape.shape_spec();
Array::constructor(
"bernoulli",
Location::caller(),
DType::Bool,
&spec,
|shape| imp::bernoulli(p, shape, key),
)
}