use numrs2::array::Array;
use numrs2::error::Result;
use numrs2::random::distributions::*;
use std::time::Instant;
#[allow(clippy::result_large_err)]
fn main() -> Result<()> {
println!("NumRS2 Random Distributions Example");
println!("====================================");
println!("\nSetting a seed for reproducibility...");
set_seed(12345);
println!("\nPart 1: Continuous Distributions");
println!("--------------------------------");
let normal_samples = normal(0.0, 1.0, &[5])?;
println!("Normal(0, 1) samples: {:?}", normal_samples);
let std_normal_samples = standard_normal::<f64>(&[5])?;
println!("Standard Normal samples: {:?}", std_normal_samples);
let beta_samples = beta(2.0, 5.0, &[5])?;
println!("Beta(2, 5) samples: {:?}", beta_samples);
let gamma_samples = gamma(1.0, 2.0, &[5])?;
println!("Gamma(1, 2) samples: {:?}", gamma_samples);
let chisquare_samples = chisquare(2.0, &[5])?;
println!("Chi-square(2) samples: {:?}", chisquare_samples);
let exponential_samples = exponential(1.0, &[5])?;
println!("Exponential(1) samples: {:?}", exponential_samples);
let uniform_samples = uniform(0.0, 1.0, &[5])?;
println!("Uniform(0, 1) samples: {:?}", uniform_samples);
let lognormal_samples = lognormal(0.0, 1.0, &[5])?;
println!("LogNormal(0, 1) samples: {:?}", lognormal_samples);
let cauchy_samples = cauchy(0.0, 1.0, &[5])?;
println!("Cauchy(0, 1) samples: {:?}", cauchy_samples);
let student_t_samples = student_t(5.0, &[5])?;
println!("Student's t(5) samples: {:?}", student_t_samples);
let weibull_samples = weibull(1.0, 1.0, &[5])?;
println!("Weibull(1, 1) samples: {:?}", weibull_samples);
let pareto_samples = pareto(2.0, &[5])?;
println!("Pareto(2) samples: {:?}", pareto_samples);
let laplace_samples = laplace(0.0, 1.0, &[5])?;
println!("Laplace(0, 1) samples: {:?}", laplace_samples);
let gumbel_samples = gumbel(0.0, 1.0, &[5])?;
println!("Gumbel(0, 1) samples: {:?}", gumbel_samples);
let logistic_samples = logistic(0.0, 1.0, &[5])?;
println!("Logistic(0, 1) samples: {:?}", logistic_samples);
let rayleigh_samples = rayleigh(1.0, &[5])?;
println!("Rayleigh(1) samples: {:?}", rayleigh_samples);
println!("\nAttempting to create Triangular(0, 2, 10) distribution...");
match triangular(0.0, 2.0, 10.0, &[5]) {
Ok(samples) => println!("Triangular(0, 2, 10) samples: {:?}", samples),
Err(e) => println!("Error creating triangular distribution: {:?}", e),
}
println!("\nAttempting to create PERT(0, 5, 10) distribution...");
match pert(0.0, 5.0, 10.0, &[5]) {
Ok(samples) => println!("PERT(0, 5, 10) samples: {:?}", samples),
Err(e) => println!("Error creating PERT distribution: {:?}", e),
}
let wald_samples = wald(1.0, 1.0, &[5])?;
println!("Wald(1, 1) samples: {:?}", wald_samples);
println!("\nPart 2: Discrete Distributions");
println!("-----------------------------");
let binomial_samples = binomial::<u32>(10, 0.5, &[5])?;
println!("Binomial(10, 0.5) samples: {:?}", binomial_samples);
let poisson_samples = poisson::<u32>(5.0, &[5])?;
println!("Poisson(5) samples: {:?}", poisson_samples);
let bernoulli_samples = bernoulli(0.5, &[5])?;
println!("Bernoulli(0.5) samples: {:?}", bernoulli_samples);
let neg_binomial_samples = negative_binomial::<u32>(5.0, 0.5, &[5])?;
println!(
"Negative Binomial(5, 0.5) samples: {:?}",
neg_binomial_samples
);
let geometric_samples = geometric::<u32>(0.5, &[5])?;
println!("Geometric(0.5) samples: {:?}", geometric_samples);
let zipf_samples = zipf::<u32>(2.0, &[5])?;
println!("Zipf(2) samples: {:?}", zipf_samples);
let logseries_samples = logseries::<u32>(0.5, &[5])?;
println!("LogSeries(0.5) samples: {:?}", logseries_samples);
println!("\nAttempting to create Hypergeometric(20, 30, 10) distribution...");
match hypergeometric::<u32>(20, 30, 10, &[5]) {
Ok(samples) => println!("Hypergeometric(20, 30, 10) samples: {:?}", samples),
Err(e) => println!("Error creating hypergeometric distribution: {:?}", e),
}
println!("\nPart 3: Multivariate Distributions");
println!("--------------------------------");
let alpha = vec![1.0, 1.0, 1.0];
let dirichlet_samples = dirichlet(&alpha, &[2])?;
println!("Dirichlet([1, 1, 1]) samples:\n{:?}", dirichlet_samples);
println!(
"Shape of Dirichlet samples: {:?}",
dirichlet_samples.shape()
);
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 mvn_samples = multivariate_normal(&mean, &cov, Some(&[3]))?;
println!("Multivariate Normal samples:\n{:?}", mvn_samples);
println!(
"Shape of Multivariate Normal samples: {:?}",
mvn_samples.shape()
);
let pvals = vec![0.2, 0.3, 0.5];
let multinomial_samples = multinomial::<u32>(10, &pvals, None)?;
println!(
"Multinomial(10, [0.2, 0.3, 0.5]) samples: {:?}",
multinomial_samples
);
println!(
"Shape of Multinomial samples: {:?}",
multinomial_samples.shape()
);
let multinomial_multiple = multinomial::<u32>(10, &pvals, Some(&[2]))?;
println!("Multiple Multinomial samples:\n{:?}", multinomial_multiple);
println!(
"Shape of multiple Multinomial samples: {:?}",
multinomial_multiple.shape()
);
println!("\nPart 4: Demonstration of Distribution Properties");
println!("--------------------------------------------");
println!("\nVerifying properties of Normal(0, 1) distribution with 10,000 samples:");
let start_time = Instant::now();
let large_normal = normal(0.0, 1.0, &[10000])?;
let elapsed = start_time.elapsed();
let data = large_normal.to_vec();
let mean: f64 = data.iter().sum::<f64>() / data.len() as f64;
let variance: f64 = data.iter().map(|&x| (x - mean).powi(2)).sum::<f64>() / data.len() as f64;
let std_dev = variance.sqrt();
println!("Generation time: {:?}", elapsed);
println!("Sample mean: {:.6} (expected: 0)", mean);
println!("Sample standard deviation: {:.6} (expected: 1)", std_dev);
println!("\nPart 5: Seed Effects on Reproducibility");
println!("------------------------------------");
set_seed(42);
let samples1 = normal(0.0, 1.0, &[5])?;
set_seed(42);
let samples2 = normal(0.0, 1.0, &[5])?;
set_seed(84);
let samples3 = normal(0.0, 1.0, &[5])?;
println!("Samples with seed=42 (first run): {:?}", samples1);
println!("Samples with seed=42 (second run): {:?}", samples2);
println!("Samples with seed=84: {:?}", samples3);
println!(
"Are the two runs with seed=42 identical? {}",
samples1.to_vec() == samples2.to_vec()
);
println!(
"Are runs with different seeds different? {}",
samples1.to_vec() != samples3.to_vec()
);
println!("\nPart 6: Generating Multi-dimensional Arrays");
println!("----------------------------------------");
let normal_2d = normal(0.0, 1.0, &[3, 4])?;
println!("2D Normal array shape: {:?}", normal_2d.shape());
println!("2D Normal array:\n{:?}", normal_2d);
let uniform_3d = uniform(0.0, 1.0, &[2, 2, 2])?;
println!("3D Uniform array shape: {:?}", uniform_3d.shape());
println!("3D Uniform array:\n{:?}", uniform_3d);
println!("\nPart 7: SciRS2 Integration for Advanced Distributions");
println!("----------------------------------------------");
println!("\nAdvanced distributions from SciRS2 integration:");
set_seed(12345);
println!("\nAttempting to create Noncentral Chi-square(2, 1) distribution...");
match noncentral_chisquare(2.0, 1.0, &[5]) {
Ok(samples) => {
println!("Non-central Chi-square(2, 1) samples: {:?}", samples);
println!("Shape of samples: {:?}", samples.shape());
let data = samples.to_vec();
let mean = data.iter().sum::<f64>() / data.len() as f64;
println!("Sample mean: {:.4} (expected: approx 3)", mean);
}
Err(e) => println!("Note on noncentral chi-square: {}", e),
}
println!("\nAttempting to create Noncentral F(2, 5, 1) distribution...");
match noncentral_f(2.0, 5.0, 1.0, &[5]) {
Ok(samples) => {
println!("Non-central F(2, 5, 1) samples: {:?}", samples);
println!("Shape of samples: {:?}", samples.shape());
let min_val = samples
.to_vec()
.iter()
.fold(f64::INFINITY, |a, &b| a.min(b));
println!("Minimum value: {:.4} (should be > 0)", min_val);
}
Err(e) => println!("Note on noncentral F: {}", e),
}
println!("\nAttempting to create von Mises(0, 1) distribution...");
match vonmises(0.0, 1.0, &[5]) {
Ok(samples) => {
println!("von Mises(0, 1) samples: {:?}", samples);
println!("Shape of samples: {:?}", samples.shape());
let data = samples.to_vec();
let in_range = data
.iter()
.all(|&x| (-std::f64::consts::PI..=std::f64::consts::PI).contains(&x));
println!("All values in range [-PI, PI]: {}", in_range);
}
Err(e) => println!("Note on von Mises: {}", e),
}
println!("\nAttempting to create Maxwell(1) distribution...");
match maxwell(1.0, &[5]) {
Ok(samples) => {
println!("Maxwell(1) samples: {:?}", samples);
println!("Shape of samples: {:?}", samples.shape());
let data = samples.to_vec();
let all_positive = data.iter().all(|&x| x > 0.0);
println!("All values positive: {}", all_positive);
}
Err(e) => println!("Note on Maxwell: {}", e),
}
println!("\nAttempting to create Truncated Normal(0, 1, -2, 2) distribution...");
match truncated_normal(0.0, 1.0, -2.0, 2.0, &[5]) {
Ok(samples) => {
println!("Truncated Normal(0, 1, -2, 2) samples: {:?}", samples);
println!("Shape of samples: {:?}", samples.shape());
let data = samples.to_vec();
let in_bounds = data.iter().all(|&x| (-2.0..=2.0).contains(&x));
println!("All values within bounds [-2, 2]: {}", in_bounds);
}
Err(e) => println!("Note on truncated normal: {}", e),
}
println!("\nAttempting to create 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]);
match multivariate_normal_with_rotation(&mean, &cov, Some(&[3]), Some(&rotation)) {
Ok(samples) => {
println!("Multivariate normal with rotation samples:\n{:?}", samples);
println!("Shape of samples: {:?}", samples.shape());
}
Err(e) => println!("Note on multivariate normal with rotation: {}", e),
}
println!("\nGenerating 1000 samples from von Mises(0, 5) to demonstrate concentration:");
match vonmises(0.0, 5.0, &[1000]) {
Ok(samples) => {
let data = samples.to_vec();
let count_within_pi_6 = data
.iter()
.filter(|&&x: &&f64| x.abs() <= std::f64::consts::PI / 6.0)
.count();
let percentage = 100.0 * (count_within_pi_6 as f64) / 1000.0;
println!(
"Percentage of samples within [-π/6, π/6]: {:.1}%",
percentage
);
println!("With kappa=5, we expect a higher concentration around the mean direction.");
}
Err(e) => println!("Note on von Mises: {}", e),
}
println!("\nAdvanced distributions note:");
println!("To enable SciRS2 integration for these advanced distributions:");
println!("1. Add the scirs2-stats and scirs2-core dependencies to your project");
println!("2. Enable the 'scirs' feature when building NumRS2");
println!(" cargo build --features scirs");
println!("3. Ensure the SciRS2 library is installed in your environment");
println!("\nExample complete. NumRS2 random distributions successfully demonstrated!");
Ok(())
}