use crate::array::Array;
use crate::error::Result;
use crate::random::state::RandomState;
lazy_static::lazy_static! {
static ref GLOBAL_RANDOM_STATE: std::sync::Mutex<RandomState> = std::sync::Mutex::new(RandomState::new());
}
pub fn set_seed(seed: u64) {
match GLOBAL_RANDOM_STATE.lock() {
Ok(mut guard) => {
*guard = RandomState::with_seed(seed);
}
Err(poisoned) => {
let mut guard = poisoned.into_inner();
*guard = RandomState::with_seed(seed);
}
}
}
pub fn get_global_random_state() -> Result<std::sync::MutexGuard<'static, RandomState>> {
match GLOBAL_RANDOM_STATE.lock() {
Ok(guard) => Ok(guard),
Err(poisoned) => {
Ok(poisoned.into_inner())
}
}
}
pub fn beta<T>(a: T, b: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.beta(a, b, shape)
}
pub fn binomial<T>(n: u64, p: f64, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::NumCast + Clone + std::fmt::Debug,
{
let rng = get_global_random_state()?;
rng.binomial(n, p, shape)
}
pub fn chisquare<T>(df: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.chisquare(df, shape)
}
pub fn dirichlet<T>(alpha: &[T], shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.dirichlet(alpha, shape)
}
pub fn gamma<T>(shape_param: T, scale: T, output_shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.gamma(shape_param, scale, output_shape)
}
pub fn normal<T>(mean: T, std: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.normal(mean, std, shape)
}
pub fn standard_normal<T>(shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.standard_normal(shape)
}
pub fn poisson<T>(lam: f64, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::NumCast + Clone + std::fmt::Debug,
{
let rng = get_global_random_state()?;
rng.poisson(lam, shape)
}
pub fn uniform<T>(low: T, high: T, shape: &[usize]) -> Result<Array<T>>
where
T: Clone
+ PartialOrd
+ scirs2_core::ndarray::distributions::uniform::SampleUniform
+ num_traits::ToPrimitive
+ num_traits::NumCast,
{
let rng = get_global_random_state()?;
rng.uniform(low, high, shape)
}
pub fn integers<T>(low: T, high: T, shape: &[usize]) -> Result<Array<T>>
where
T: Clone
+ PartialOrd
+ scirs2_core::ndarray::distributions::uniform::SampleUniform
+ Into<i64>
+ TryFrom<i64>
+ num_traits::ToPrimitive,
<T as TryFrom<i64>>::Error: std::fmt::Debug,
{
let rng = get_global_random_state()?;
rng.integers(low, high, shape)
}
pub fn lognormal<T>(mean: T, sigma: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.lognormal(mean, sigma, shape)
}
pub fn cauchy<T>(loc: T, scale: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.cauchy(loc, scale, shape)
}
pub fn student_t<T>(df: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.student_t(df, shape)
}
pub fn exponential<T>(scale: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.exponential(scale, shape)
}
pub fn weibull<T>(shape_param: T, scale: T, output_shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.weibull(shape_param, scale, output_shape)
}
pub fn bernoulli<T>(p: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.bernoulli(p, shape)
}
pub fn pareto<T>(alpha: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.pareto(alpha, shape)
}
pub fn triangular<T>(low: T, mode: T, high: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.triangular(low, mode, high, shape)
}
pub fn pert<T>(min: T, mode: T, max: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.pert(min, mode, max, shape)
}
pub fn multivariate_normal<T>(
mean: &[T],
cov: &Array<T>,
size: Option<&[usize]>,
) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.multivariate_normal(mean, cov, size)
}
pub fn laplace<T>(loc: T, scale: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.laplace(loc, scale, shape)
}
pub fn gumbel<T>(loc: T, scale: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.gumbel(loc, scale, shape)
}
pub fn logistic<T>(loc: T, scale: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.logistic(loc, scale, shape)
}
pub fn rayleigh<T>(scale: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.rayleigh(scale, shape)
}
pub fn wald<T>(mean: T, scale: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.wald(mean, scale, shape)
}
pub fn negative_binomial<T>(n: f64, p: f64, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::NumCast + Clone + std::fmt::Debug,
{
let rng = get_global_random_state()?;
rng.negative_binomial(n, p, shape)
}
pub fn geometric<T>(p: f64, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::NumCast + Clone + std::fmt::Debug,
{
let rng = get_global_random_state()?;
rng.geometric(p, shape)
}
pub fn multinomial<T>(n: usize, pvals: &[f64], shape: Option<&[usize]>) -> Result<Array<T>>
where
T: num_traits::NumCast + Clone + std::fmt::Debug,
{
let rng = get_global_random_state()?;
rng.multinomial(n, pvals, shape)
}
pub fn hypergeometric<T>(
ngood: usize,
nbad: usize,
nsample: usize,
shape: &[usize],
) -> Result<Array<T>>
where
T: num_traits::NumCast + Clone + std::fmt::Debug,
{
let rng = get_global_random_state()?;
rng.hypergeometric(ngood, nbad, nsample, shape)
}
pub fn zipf<T>(a: f64, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::NumCast + Clone + std::fmt::Debug,
{
let rng = get_global_random_state()?;
rng.zipf(a, shape)
}
pub fn logseries<T>(p: f64, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::NumCast + Clone + std::fmt::Debug,
{
let rng = get_global_random_state()?;
rng.logseries(p, shape)
}
pub fn noncentral_chisquare<T>(df: T, nonc: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.noncentral_chisquare(df, nonc, shape)
}
pub fn noncentral_f<T>(dfnum: T, dfden: T, nonc: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.noncentral_f(dfnum, dfden, nonc, shape)
}
pub fn vonmises<T>(mu: T, kappa: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.vonmises(mu, kappa, shape)
}
pub fn maxwell<T>(scale: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.maxwell(scale, shape)
}
pub fn truncated_normal<T>(mean: T, std: T, low: T, high: T, shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.truncated_normal(mean, std, low, high, shape)
}
pub fn multivariate_normal_with_rotation<T>(
mean: &[T],
cov: &Array<T>,
size: Option<&[usize]>,
rotation: Option<&Array<T>>,
) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.multivariate_normal_with_rotation(mean, cov, size, rotation)
}
pub fn multivariate_t<T>(
mean: &[T],
cov: &Array<T>,
df: T,
size: Option<&[usize]>,
) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.multivariate_t(mean, cov, df, size)
}
pub fn wishart<T>(df: T, scale: &Array<T>, size: Option<&[usize]>) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.wishart(df, scale, size)
}
pub fn frechet<T>(shape: T, loc: T, scale: T, output_shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.frechet(shape, loc, scale, output_shape)
}
pub fn gev<T>(shape: T, loc: T, scale: T, output_shape: &[usize]) -> Result<Array<T>>
where
T: num_traits::Float + num_traits::NumCast + Clone + std::fmt::Debug + std::fmt::Display,
{
let rng = get_global_random_state()?;
rng.gev(shape, loc, scale, output_shape)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_beta_distribution() {
let arr = beta(2.0, 5.0, &[10]).expect("test: beta should succeed");
assert_eq!(arr.shape(), vec![10]);
}
#[test]
fn test_normal_distribution() {
let arr = normal(0.0, 1.0, &[5, 5]).expect("test: normal should succeed");
assert_eq!(arr.shape(), vec![5, 5]);
}
#[test]
fn test_standard_normal_distribution() {
let arr = standard_normal::<f64>(&[3, 3]).expect("test: standard_normal should succeed");
assert_eq!(arr.shape(), vec![3, 3]);
}
#[test]
fn test_binomial_distribution() {
let arr = binomial::<u64>(10, 0.5, &[5]).expect("test: binomial should succeed");
assert_eq!(arr.shape(), vec![5]);
for val in arr.to_vec() {
assert!(val <= 10);
}
}
#[test]
fn test_gamma_distribution() {
let arr = gamma(2.0, 2.0, &[10]).expect("test: gamma should succeed");
assert_eq!(arr.shape(), vec![10]);
for val in arr.to_vec() {
assert!(val > 0.0);
}
}
#[test]
#[ignore = "Seeding behavior changed during SciRS2 migration - requires seeding implementation fix"]
fn test_set_seed() {
let seed1 = 12345u64;
let seed2 = 54321u64;
set_seed(seed1);
let arr1_a = normal(0.0, 1.0, &[5]).expect("test: normal should succeed");
let arr1_b = normal(0.0, 1.0, &[5]).expect("test: normal should succeed");
set_seed(seed1);
let arr2_a = normal(0.0, 1.0, &[5]).expect("test: normal should succeed");
let arr2_b = normal(0.0, 1.0, &[5]).expect("test: normal should succeed");
assert_eq!(
arr1_a.to_vec(),
arr2_a.to_vec(),
"First arrays should be identical"
);
assert_eq!(
arr1_b.to_vec(),
arr2_b.to_vec(),
"Second arrays should be identical"
);
set_seed(seed2);
let arr3_a = normal(0.0, 1.0, &[5]).expect("test: normal should succeed");
assert_ne!(
arr1_a.to_vec(),
arr3_a.to_vec(),
"Different seeds should produce different results"
);
}
#[test]
fn test_pareto_distribution() {
let arr = pareto(2.0, &[10]).expect("test: pareto should succeed");
assert_eq!(arr.shape(), vec![10]);
for val in arr.to_vec() {
assert!(val >= 1.0);
}
}
#[test]
fn test_triangular_distribution() {
let result = triangular(0.0, 2.0, 10.0, &[10]);
let arr = result.expect("test: triangular should succeed");
assert_eq!(arr.shape(), vec![10]);
for val in arr.to_vec() {
assert!((0.0..=10.0).contains(&val));
}
}
#[test]
fn test_pert_distribution() {
let arr = pert(0.0, 5.0, 10.0, &[10]).expect("test: pert should succeed");
assert_eq!(arr.shape(), vec![10]);
for val in arr.to_vec() {
assert!((0.0..=10.0).contains(&val));
}
}
#[test]
fn test_multivariate_normal_distribution() {
let mean = vec![0.0, 0.0];
let cov_data = vec![1.0, 0.5, 0.5, 1.0];
let cov = Array::from_vec(cov_data).reshape(&[2, 2]);
let arr = multivariate_normal(&mean, &cov, Some(&[10]))
.expect("test: multivariate_normal should succeed");
assert_eq!(arr.shape(), vec![10, 2]);
}
#[test]
fn test_laplace_distribution() {
let arr = laplace(0.0, 1.0, &[10]).expect("test: laplace should succeed");
assert_eq!(arr.shape(), vec![10]);
}
#[test]
fn test_negative_binomial_distribution() {
let arr = negative_binomial::<u64>(5.0, 0.5, &[10])
.expect("test: negative_binomial should succeed");
assert_eq!(arr.shape(), vec![10]);
}
#[test]
fn test_multinomial_distribution() {
let pvals = vec![0.2, 0.3, 0.5];
let arr = multinomial::<u64>(10, &pvals, None).expect("test: multinomial should succeed");
assert_eq!(arr.shape(), vec![3]);
let sum: u64 = arr.to_vec().iter().sum();
assert_eq!(sum, 10);
}
#[test]
fn test_noncentral_chisquare_distribution() {
let arr = noncentral_chisquare(2.0, 1.0, &[10])
.expect("test: noncentral_chisquare should succeed");
assert_eq!(arr.shape(), vec![10]);
for val in arr.to_vec() {
assert!(val > 0.0);
}
}
#[test]
fn test_noncentral_f_distribution() {
let arr = noncentral_f(2.0, 5.0, 1.0, &[10]).expect("test: noncentral_f should succeed");
assert_eq!(arr.shape(), vec![10]);
for val in arr.to_vec() {
assert!(val > 0.0);
}
}
#[test]
fn test_vonmises_distribution() {
let arr = vonmises(0.0, 1.0, &[10]).expect("test: vonmises should succeed");
assert_eq!(arr.shape(), vec![10]);
for val in arr.to_vec() {
assert!((-std::f64::consts::PI..std::f64::consts::PI).contains(&val));
}
}
#[test]
fn test_maxwell_distribution() {
let arr = maxwell(1.0, &[10]).expect("test: maxwell should succeed");
assert_eq!(arr.shape(), vec![10]);
for val in arr.to_vec() {
assert!(val > 0.0);
}
}
#[test]
fn test_truncated_normal_distribution() {
let low = -2.0;
let high = 2.0;
let arr = truncated_normal(0.0, 1.0, low, high, &[10])
.expect("test: truncated_normal should succeed");
assert_eq!(arr.shape(), vec![10]);
for val in arr.to_vec() {
assert!(val >= low && val <= high);
}
}
#[test]
fn test_multivariate_normal_with_rotation() {
let mean = vec![0.0, 0.0];
let cov_data = vec![1.0, 0.5, 0.5, 1.0];
let cov = Array::from_vec(cov_data).reshape(&[2, 2]);
let rotation_data = vec![
std::f64::consts::FRAC_1_SQRT_2,
std::f64::consts::FRAC_1_SQRT_2, -std::f64::consts::FRAC_1_SQRT_2,
std::f64::consts::FRAC_1_SQRT_2, ];
let rotation = Array::from_vec(rotation_data).reshape(&[2, 2]);
let arr = multivariate_normal_with_rotation(&mean, &cov, Some(&[5]), Some(&rotation))
.expect("test: multivariate_normal_with_rotation should succeed");
assert_eq!(arr.shape(), vec![5, 2]);
let arr_no_rot = multivariate_normal_with_rotation(&mean, &cov, Some(&[5]), None)
.expect("test: multivariate_normal_with_rotation (no rotation) should succeed");
assert_eq!(arr_no_rot.shape(), vec![5, 2]);
}
#[test]
fn test_multivariate_t_distribution() {
let mean = vec![0.0, 0.0];
let cov_data = vec![1.0, 0.3, 0.3, 1.0];
let cov = Array::from_vec(cov_data).reshape(&[2, 2]);
let df = 5.0;
let arr = multivariate_t(&mean, &cov, df, Some(&[10]))
.expect("test: multivariate_t should succeed");
assert_eq!(arr.shape(), vec![10, 2]);
let arr_single = multivariate_t(&mean, &cov, df, None)
.expect("test: multivariate_t (single sample) should succeed");
assert_eq!(arr_single.shape(), vec![2]);
}
#[test]
fn test_multivariate_t_parameter_validation() {
let mean = vec![0.0, 0.0];
let cov_data = vec![1.0, 0.3, 0.3, 1.0];
let cov = Array::from_vec(cov_data).reshape(&[2, 2]);
let result = multivariate_t::<f64>(&mean, &cov, 0.0, Some(&[5]));
assert!(result.is_err(), "multivariate_t should fail with df = 0");
let result = multivariate_t::<f64>(&mean, &cov, -1.0, Some(&[5]));
assert!(
result.is_err(),
"multivariate_t should fail with negative df"
);
let bad_cov_data = vec![1.0, 2.0, 2.0, 1.0]; let bad_cov = Array::from_vec(bad_cov_data).reshape(&[2, 2]);
let result = multivariate_t::<f64>(&mean, &bad_cov, 5.0, Some(&[5]));
assert!(
result.is_err(),
"multivariate_t should fail with non-positive-definite covariance"
);
}
#[test]
fn test_wishart_distribution() {
let scale_data = vec![1.0, 0.2, 0.2, 1.0];
let scale = Array::from_vec(scale_data).reshape(&[2, 2]);
let df = 5.0;
let arr = wishart(df, &scale, Some(&[3])).expect("test: wishart should succeed");
assert_eq!(arr.shape(), vec![3, 2, 2]);
let arr_single =
wishart(df, &scale, None).expect("test: wishart (single sample) should succeed");
assert_eq!(arr_single.shape(), vec![2, 2]);
}
#[test]
fn test_wishart_parameter_validation() {
let scale_data = vec![1.0, 0.2, 0.2, 1.0];
let scale = Array::from_vec(scale_data).reshape(&[2, 2]);
let result = wishart::<f64>(1.0, &scale, Some(&[3]));
assert!(result.is_err(), "wishart should fail when df < dimension");
let bad_scale_data = vec![1.0, 0.2, 0.2];
let bad_scale = Array::from_vec(bad_scale_data).reshape(&[3, 1]);
let result = wishart::<f64>(5.0, &bad_scale, Some(&[3]));
assert!(
result.is_err(),
"wishart should fail with non-square scale matrix"
);
let bad_scale_data = vec![1.0, 2.0, 2.0, 1.0]; let bad_scale = Array::from_vec(bad_scale_data).reshape(&[2, 2]);
let result = wishart::<f64>(5.0, &bad_scale, Some(&[3]));
assert!(
result.is_err(),
"wishart should fail with non-positive-definite scale matrix"
);
}
#[test]
fn test_frechet_distribution() {
let arr = frechet(2.0, 0.0, 1.0, &[100]).expect("test: frechet should succeed");
assert_eq!(arr.shape(), vec![100]);
let loc = 0.0;
for val in arr.to_vec() {
assert!(val > loc, "Frechet values should be > loc, got {}", val);
}
}
#[test]
fn test_frechet_parameter_validation() {
let result = frechet::<f64>(0.0, 0.0, 1.0, &[10]);
assert!(result.is_err(), "frechet should fail with shape = 0");
let result = frechet::<f64>(-1.0, 0.0, 1.0, &[10]);
assert!(result.is_err(), "frechet should fail with negative shape");
let result = frechet::<f64>(2.0, 0.0, 0.0, &[10]);
assert!(result.is_err(), "frechet should fail with scale = 0");
let result = frechet::<f64>(2.0, 0.0, -1.0, &[10]);
assert!(result.is_err(), "frechet should fail with negative scale");
}
#[test]
fn test_frechet_with_different_parameters() {
let arr = frechet(3.0, 5.0, 2.0, &[50]).expect("test: frechet with loc=5 should succeed");
assert_eq!(arr.shape(), vec![50]);
for val in arr.to_vec() {
assert!(val > 5.0, "Frechet values should be > 5.0, got {}", val);
}
}
#[test]
fn test_gev_distribution_gumbel() {
let arr = gev(0.0, 0.0, 1.0, &[100]).expect("test: gev (Gumbel) should succeed");
assert_eq!(arr.shape(), vec![100]);
assert!(!arr.to_vec().is_empty());
}
#[test]
fn test_gev_distribution_frechet() {
let arr = gev(0.5, 0.0, 1.0, &[100]).expect("test: gev (Frechet) should succeed");
assert_eq!(arr.shape(), vec![100]);
assert!(!arr.to_vec().is_empty());
}
#[test]
fn test_gev_distribution_weibull() {
let arr = gev(-0.5, 0.0, 1.0, &[100]).expect("test: gev (Weibull) should succeed");
assert_eq!(arr.shape(), vec![100]);
assert!(!arr.to_vec().is_empty());
}
#[test]
fn test_gev_parameter_validation() {
let result = gev::<f64>(0.0, 0.0, 0.0, &[10]);
assert!(result.is_err(), "gev should fail with scale = 0");
let result = gev::<f64>(0.0, 0.0, -1.0, &[10]);
assert!(result.is_err(), "gev should fail with negative scale");
}
#[test]
fn test_gev_with_different_parameters() {
let arr = gev(0.2, 10.0, 2.0, &[50]).expect("test: gev with custom params should succeed");
assert_eq!(arr.shape(), vec![50]);
assert!(!arr.to_vec().is_empty());
}
}