rand_simple/distributions/
levy.rs

1use crate::create_state;
2use crate::standard_distributions::standard_normal;
3
4/// Lévy Distribution
5/// # Example
6/// ```
7/// // Create a new Lévy distribution with a location parameter (μ) of 0 and a scale parameter (θ) of 1
8/// let mut levy = rand_simple::Levy::new([1192_u32, 765_u32]);
9/// assert_eq!(format!("{levy}"), "Lévy(Location parameter, Scale parameter) = Lévy(0, 1)");
10/// println!("Returns a random number following a standard Levy distribution -> {}", levy.sample());
11///
12/// // Modify the distribution's parameters
13/// let location: f64 = -2_f64;
14/// let scale: f64 = 1.5_f64;
15/// // Update the parameters and generate a random number following the modified Levy distribution
16/// let result: Result<(f64, f64), &str> = levy.try_set_params(location, scale);
17/// assert_eq!(format!("{levy}"), "Lévy(Location parameter, Scale parameter) = Lévy(-2, 1.5)");
18/// println!("Returns a random number following a Levy distribution with location μ = {} and scale θ = {} -> {}", location, scale, levy.sample());
19/// ```
20pub struct Levy {
21    xyzuv0: [u32; 5], // 状態変数
22    xyzuv1: [u32; 5], // 状態変数
23    location: f64,    // 位置母数
24    scale: f64,       // 尺度母数
25}
26
27impl Levy {
28    /// Constructor
29    /// * `seeds` - Random number seeds. Adjusted internally to ensure uniqueness.
30    pub fn new(seeds: [u32; 2_usize]) -> Self {
31        let adjusted_seeds = crate::adjust_seeds!(seeds);
32        Self {
33            xyzuv0: create_state(adjusted_seeds[0]),
34            xyzuv1: create_state(adjusted_seeds[1]),
35            location: 0_f64,
36            scale: 1_f64,
37        }
38    }
39
40    /// Generate a random number.
41    pub fn sample(&mut self) -> f64 {
42        loop {
43            let z = standard_normal(&mut self.xyzuv0, &mut self.xyzuv1).abs();
44            if z > 0_f64 {
45                return z.powi(-2_i32) * self.scale + self.location;
46            }
47        }
48    }
49
50    /// Modify the parameters of the probability variable.
51    /// * `location` - Location parameter
52    /// * `scale` - Scale parameter
53    pub fn try_set_params(
54        &mut self,
55        location: f64,
56        scale: f64,
57    ) -> Result<(f64, f64), &'static str> {
58        if scale <= 0_f64 {
59            Err("The scale parameter is less than or equal to 0. The parameters of the probability variable remain unchanged.")
60        } else {
61            self.location = location;
62            self.scale = scale;
63            Ok((location, scale))
64        }
65    }
66}
67
68impl core::fmt::Display for Levy {
69    /// Formatter for use with macros like `println!`
70    /// * Location parameter
71    /// * Scale parameter
72    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
73        write!(
74            f,
75            "Lévy(Location parameter, Scale parameter) = Lévy({}, {})",
76            self.location, self.scale
77        )?;
78        Ok(())
79    }
80}