Skip to content

Commit

Permalink
style(vrd): 💄 code formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastienrousseau committed Mar 9, 2024
1 parent 8c2f187 commit c60f270
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 74 deletions.
44 changes: 22 additions & 22 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,15 +251,13 @@ macro_rules! rand_string {
/// * `slice` - A mutable reference to the slice to be shuffled.
#[macro_export]
macro_rules! rand_shuffle {
($rng:expr, $slice:expr) => {
{
let len = $slice.len();
for i in (1..len).rev() {
let j = $rng.random_range(0, (i + 1) as u32) as usize;
$slice.swap(i, j);
}
($rng:expr, $slice:expr) => {{
let len = $slice.len();
for i in (1..len).rev() {
let j = $rng.random_range(0, (i + 1) as u32) as usize;
$slice.swap(i, j);
}
};
}};
}

/// Selects a random element from a slice based on the provided weights.
Expand Down Expand Up @@ -292,7 +290,11 @@ macro_rules! rand_shuffle {
#[macro_export]
macro_rules! rand_weighted_choice {
($rng:expr, $choices:expr, $weights:expr) => {{
assert_eq!($choices.len(), $weights.len(), "Choices and weights must have the same length");
assert_eq!(
$choices.len(),
$weights.len(),
"Choices and weights must have the same length"
);
let total_weight: u32 = $weights.iter().sum();
let mut rnd = $rng.random_range(0, total_weight);
let mut selected_choice = None;
Expand Down Expand Up @@ -378,19 +380,17 @@ macro_rules! rand_exponential {
/// An `u64` representing a random number from a Poisson distribution.
#[macro_export]
macro_rules! rand_poisson {
($rng:expr, $mean:expr) => {
{
let mut k = 0;
let mut p = 1.0;
let l = f64::exp(-$mean);
loop {
k += 1;
p *= $rng.f64();
if p < l {
break;
}
($rng:expr, $mean:expr) => {{
let mut k = 0;
let mut p = 1.0;
let l = f64::exp(-$mean);
loop {
k += 1;
p *= $rng.f64();
if p < l {
break;
}
k - 1
}
};
k - 1
}};
}
16 changes: 14 additions & 2 deletions src/mersenne_twister.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,21 @@
// This file is part of the `Random (VRD)` library, a Rust implementation of the Mersenne Twister RNG.
// See LICENSE-APACHE.md and LICENSE-MIT.md in the repository root for full license information.

use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};

#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
#[derive(
Clone,
Copy,
Debug,
Default,
Deserialize,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
)]
/// Configuration for the Mersenne Twister algorithm.
pub struct MersenneTwisterConfig {
/// The number of elements in the array used for the Mersenne Twister algorithm.
Expand Down
5 changes: 4 additions & 1 deletion src/random.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,10 @@ impl Random {
/// # Notes
/// - This method offers a convenient way to specify the range for random number generation.
pub fn random_range(&mut self, min: u32, max: u32) -> u32 {
assert!(max > min, "max must be greater than min for random_range");
assert!(
max > min,
"max must be greater than min for random_range"
);
let mut rng = rand::thread_rng(); // Get a thread-local RNG
rng.gen_range(min..max) // Use the gen_range method for uniform distribution
}
Expand Down
142 changes: 93 additions & 49 deletions tests/test_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,20 @@ mod tests {
let min = 10;
let max = 20;
let num = random_range!(rng, min, max);
assert!(num >= min && num <= max, "Number should be within the given range.");
assert!(
num >= min && num <= max,
"Number should be within the given range."
);
}

#[test]
fn test_rand_bool_macro_always_true() {
let mut rng = Random::new();
let b = rand_bool!(rng, 1.0);
assert!(b, "rand_bool should always return true with probability 1.0.");
assert!(
b,
"rand_bool should always return true with probability 1.0."
);
}

#[test]
Expand All @@ -36,7 +42,11 @@ mod tests {
let mut rng = Random::new();
let len = 10;
let bytes = rand_bytes!(rng, len);
assert_eq!(bytes.len(), len, "Length of bytes should be equal to the specified length.");
assert_eq!(
bytes.len(),
len,
"Length of bytes should be equal to the specified length."
);
}

#[test]
Expand All @@ -54,14 +64,20 @@ mod tests {
let mut rng = Random::new();
let values = vec![1, 2, 3, 4, 5];
let chosen = rand_choose!(rng, &values).unwrap();
assert!(values.contains(chosen), "Chosen value should be in the provided slice.");
assert!(
values.contains(chosen),
"Chosen value should be in the provided slice."
);
}

#[test]
fn test_rand_float_macro_within_bounds() {
let mut rng = Random::new();
let f = rand_float!(rng);
assert!((0.0..1.0).contains(&f), "Generated float should be within 0.0 and 1.0.");
assert!(
(0.0..1.0).contains(&f),
"Generated float should be within 0.0 and 1.0."
);
}

#[test]
Expand All @@ -70,7 +86,10 @@ mod tests {
let min = 10;
let max = 20;
let num = rand_int!(rng, min, max);
assert!(num >= min && num <= max, "Generated integer should be within the specified range.");
assert!(
num >= min && num <= max,
"Generated integer should be within the specified range."
);
}

#[test]
Expand Down Expand Up @@ -111,7 +130,10 @@ mod tests {
let min = 10;
let max = 20;
let num = random_range!(rng, min, max);
assert!(num >= min && num < max, "Number should be within the given range.");
assert!(
num >= min && num < max,
"Number should be within the given range."
);
}

#[test]
Expand All @@ -127,7 +149,10 @@ mod tests {
let mut rng = Random::new();
let p = 0.0; // Set p to 0.0 to always generate false
let b = rand_bool!(rng, p);
assert!(!b, "The probability of 0.0 should always return false.");
assert!(
!b,
"The probability of 0.0 should always return false."
);
}

#[test]
Expand All @@ -136,7 +161,10 @@ mod tests {
let min = 10;
let max = 20;
let num = rand_int!(rng, min, max);
assert!(num >= min && num <= max, "Number should be within the given range.");
assert!(
num >= min && num <= max,
"Number should be within the given range."
);
}

#[test]
Expand All @@ -154,7 +182,9 @@ mod tests {
let length = 20;
let random_string = rand_string!(rng, length);
assert_eq!(random_string.len(), length);
assert!(random_string.chars().all(|c| c.is_ascii_alphanumeric()));
assert!(random_string
.chars()
.all(|c| c.is_ascii_alphanumeric()));
}

#[test]
Expand All @@ -169,51 +199,60 @@ mod tests {
assert!(numbers.iter().all(|&x| original_numbers.contains(&x)));
}

/// Test the `rand_weighted_choice!` macro for correct weighted choice distribution.
#[test]
fn test_rand_weighted_choice() {
// Create a new Random instance
let mut rng = Random::new();

// Define choices and their corresponding weights
let choices = ["A", "B", "C"];
let weights = [20, 30, 50]; // Weights implying a 2:3:5 ratio

// Initialize counters for each choice
let mut counts = [0; 3];
let num_iterations = 10_000; // Number of iterations to simulate

// Simulate weighted choice selection
for _ in 0..num_iterations {
let selected = rand_weighted_choice!(rng, &choices, &weights);
match *selected {
"A" => counts[0] += 1,
"B" => counts[1] += 1,
"C" => counts[2] += 1,
_ => panic!("Unexpected choice"),
/// Test the `rand_weighted_choice!` macro for correct weighted choice distribution.
#[test]
fn test_rand_weighted_choice() {
// Create a new Random instance
let mut rng = Random::new();

// Define choices and their corresponding weights
let choices = ["A", "B", "C"];
let weights = [20, 30, 50]; // Weights implying a 2:3:5 ratio

// Initialize counters for each choice
let mut counts = [0; 3];
let num_iterations = 10_000; // Number of iterations to simulate

// Simulate weighted choice selection
for _ in 0..num_iterations {
let selected =
rand_weighted_choice!(rng, &choices, &weights);
match *selected {
"A" => counts[0] += 1,
"B" => counts[1] += 1,
"C" => counts[2] += 1,
_ => panic!("Unexpected choice"),
}
}
}

// Calculate the observed distribution ratios
let total_counts: i32 = counts.iter().sum();
let observed_ratios: Vec<f64> = counts.iter().map(|&count| count as f64 / total_counts as f64).collect();
// Calculate the observed distribution ratios
let total_counts: i32 = counts.iter().sum();
let observed_ratios: Vec<f64> = counts
.iter()
.map(|&count| count as f64 / total_counts as f64)
.collect();

// Expected distribution ratios based on weights
let total_weight: u32 = weights.iter().sum();
let expected_ratios: Vec<f64> = weights.iter().map(|&weight| weight as f64 / total_weight as f64).collect();
// Expected distribution ratios based on weights
let total_weight: u32 = weights.iter().sum();
let expected_ratios: Vec<f64> = weights
.iter()
.map(|&weight| weight as f64 / total_weight as f64)
.collect();

// Check if the observed ratios are close to the expected ratios within a tolerance
let tolerance = 0.05; // 5% tolerance for distribution accuracy
for (observed, expected) in observed_ratios.iter().zip(expected_ratios.iter()) {
assert!(
// Check if the observed ratios are close to the expected ratios within a tolerance
let tolerance = 0.05; // 5% tolerance for distribution accuracy
for (observed, expected) in
observed_ratios.iter().zip(expected_ratios.iter())
{
assert!(
(observed - expected).abs() <= tolerance,
"Distribution does not match expected ratios within tolerance: observed {:?}, expected {:?}",
observed_ratios, expected_ratios
);
}
}
}

#[test]
#[test]
fn test_rand_normal() {
let mut rng = Random::new(); // Assuming `Random::new()` provides the necessary `f64()` method.
let mu = 0.0; // Expected mean
Expand All @@ -227,8 +266,13 @@ fn test_rand_weighted_choice() {
}

// Calculate the sample mean and sample standard deviation
let sample_mean: f64 = samples.iter().sum::<f64>() / num_samples as f64;
let sample_variance: f64 = samples.iter().map(|&x| (x - sample_mean).powi(2)).sum::<f64>() / (num_samples - 1) as f64;
let sample_mean: f64 =
samples.iter().sum::<f64>() / num_samples as f64;
let sample_variance: f64 = samples
.iter()
.map(|&x| (x - sample_mean).powi(2))
.sum::<f64>()
/ (num_samples - 1) as f64;
let sample_std_dev = sample_variance.sqrt();

// Define tolerances for the mean and standard deviation
Expand Down Expand Up @@ -260,7 +304,8 @@ fn test_rand_weighted_choice() {
.map(|_| rand_exponential!(rng, rate))
.collect();

let sample_mean: f64 = samples.iter().sum::<f64>() / samples.len() as f64;
let sample_mean: f64 =
samples.iter().sum::<f64>() / samples.len() as f64;

// Tolerance for the difference between the sample mean and the expected mean.
let tolerance = 0.1;
Expand Down Expand Up @@ -292,4 +337,3 @@ fn test_rand_weighted_choice() {
assert!((sample_mean - expected_mean).abs() < 0.1);
}
}

0 comments on commit c60f270

Please sign in to comment.