rand_simple/distributions/
reflected_weibull.rs

1use crate::create_state;
2use crate::standard_distributions::xorshift160_greater_than_0_and_less_than_1;
3
4/// Reflected Weibull Distribution
5///
6/// # Example Usage
7/// ```
8/// // Create an instance of the Reflected Weibull distribution with default parameters
9/// let mut reflected_weibull = rand_simple::ReflectedWeibull::new(1192u32);
10///
11/// // The default parameters are:
12/// // Shape = 1, Location = 0, Scale = 1
13/// assert_eq!(format!("{reflected_weibull}"), "RWeibull(Shape parameter, Location Parameter, Scale parameter) = RWeibull(1, 0, 1)");
14///
15/// // Adjusting the parameters of the distribution:
16/// let shape: f64 = 2f64;     // The shape parameter, controlling the distribution's tail
17/// let location: f64 = 3f64;  // The location parameter, shifting the distribution
18/// let scale: f64 = 1.5f64;   // The scale parameter, stretching or compressing the distribution
19/// let result: Result<(f64, f64, f64), &str> = reflected_weibull.try_set_params(shape, location, scale);
20///
21/// // After updating the parameters, verify the distribution's state
22/// assert_eq!(format!("{reflected_weibull}"), "RWeibull(Shape parameter, Location Parameter, Scale parameter) = RWeibull(2, 3, 1.5)");
23/// ```
24pub struct ReflectedWeibull {
25    xyzuv: [u32; 5], // 状態変数
26    shape: f64,      // 形状母数の逆数
27    location: f64,   // 位置母数
28    scale: f64,      // 尺度母数
29}
30
31impl ReflectedWeibull {
32    /// Constructor
33    /// * `_seed` - Random seed
34    pub fn new(_seed: u32) -> Self {
35        Self {
36            xyzuv: create_state(_seed),
37            shape: 1_f64,
38            location: 0_f64,
39            scale: 1_f64,
40        }
41    }
42
43    /// Computes a random number.
44    pub fn sample(&mut self) -> f64 {
45        // Algorithm 3.53: Inverse Transform Sampling
46        // Step 1: Uniform random number in (0, 1)
47        let u = xorshift160_greater_than_0_and_less_than_1(&mut self.xyzuv);
48        // Step 2
49        if u < 0.5_f64 {
50            // Apply the inverse function for the lower half of the distribution
51            -(-(2_f64 * u).ln()).powf(self.shape.powi(-1)) * self.scale + self.location
52        } else {
53            // Apply the inverse function for the upper half of the distribution
54            (-(2_f64 * (1_f64 - u)).ln()).powf(self.shape.powi(-1)) * self.scale + self.location
55        }
56    }
57
58    /// Changes the parameters of the probability variable.
59    /// * `shape` - Shape parameter
60    /// * `location` - Location parameter
61    /// * `scale` - Scale parameter
62    pub fn try_set_params(
63        &mut self,
64        shape: f64,
65        location: f64,
66        scale: f64,
67    ) -> Result<(f64, f64, f64), &str> {
68        if shape <= 0_f64 || scale <= 0_f64 {
69            // Returns an error if the shape or scale parameters are less than or equal to 0.
70            Err("Shape or scale parameter is less than or equal to 0. The parameters of the probability variable will remain unchanged.")
71        } else {
72            // Updates the parameters and returns the new values.
73            self.shape = shape;
74            self.location = location;
75            self.scale = scale;
76            Ok((shape, location, scale))
77        }
78    }
79}
80
81impl std::fmt::Display for ReflectedWeibull {
82    /// Formatter for displaying using println! macro and similar constructs.
83    /// * Type of the struct
84    /// * Shape parameter (inverse)
85    /// * Location parameter
86    /// * Scale parameter
87    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
88        write!(
89            f,
90            "RWeibull(Shape parameter, Location Parameter, Scale parameter) = RWeibull({}, {}, {})",
91            self.shape, self.location, self.scale
92        )?;
93        Ok(())
94    }
95}