rand_simple/distributions/
power_function.rs

1use crate::create_state;
2use crate::standard_distributions::xorshift160_greater_than_0_and_less_than_1;
3
4/// Power function distribution
5/// # Examples
6/// ```
7/// let mut power_function = rand_simple::PowerFunction::new(1192u32);
8/// assert_eq!(format!("{power_function}"), "PF(Shape parameter γ, Boundary parameter a, Boundary parameter b) = PF(1, 0, 1)");
9///
10/// // If you want to change the parameters of the random variable
11/// let shape: f64 = 2_f64;
12/// let min: f64 = -1_f64;
13/// let max: f64 = 1_f64;
14/// let result: Result<(f64, f64, f64), &str> = power_function.try_set_params(shape, min, max);
15/// assert_eq!(format!("{power_function}"), "PF(Shape parameter γ, Boundary parameter a, Boundary parameter b) = PF(2, -1, 1)");
16/// ```
17pub struct PowerFunction {
18    xyzuv: [u32; 5], // 状態変数
19    shape: f64,      // 形状母数
20    min_a: f64,      // 境界母数(小範)
21    max_b: f64,      // 境界母数(大範)
22}
23
24impl PowerFunction {
25    /// Constructor
26    /// * `_seed` - Random seed
27    pub fn new(_seed: u32) -> Self {
28        Self {
29            xyzuv: create_state(_seed),
30            shape: 1_f64,
31            min_a: 0_f64,
32            max_b: 1_f64,
33        }
34    }
35
36    /// Computes a random number
37    pub fn sample(&mut self) -> f64 {
38        // Algorithm 3.67
39        // Step 1
40        // Generate a uniform random number U in the interval (0, 1) and calculate Y = U^γ_inv
41        // Step 2
42        // Calculate X = a + (b - a)Y as the desired random number
43        xorshift160_greater_than_0_and_less_than_1(&mut self.xyzuv).powf(self.shape.powi(-1))
44            * (self.max_b - self.min_a)
45            + self.min_a
46    }
47
48    /// Changes the parameters of the probability variable
49    /// * `shape` - Shape parameter γ
50    /// * `min_a` - Lower boundary parameter a
51    /// * `max_b` - Upper boundary parameter b
52    pub fn try_set_params(
53        &mut self,
54        shape: f64,
55        min_a: f64,
56        max_b: f64,
57    ) -> Result<(f64, f64, f64), &str> {
58        if shape <= 0_f64 {
59            Err("The shape parameter γ is less than or equal to 0. The parameters of the probability variable will remain unchanged.")
60        } else if min_a >= max_b {
61            Err("The upper boundary parameter b is equal to or greater than the lower boundary parameter a. The parameters of the probability variable will remain unchanged.")
62        } else {
63            self.shape = shape;
64            self.min_a = min_a;
65            self.max_b = max_b;
66            Ok((shape, min_a, max_b))
67        }
68    }
69}
70
71impl core::fmt::Display for PowerFunction {
72    /// Formatter for displaying using println! macro
73    /// * Type of the structure
74    /// * Scale parameter
75    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
76        write!(
77            f,
78            "PF(Shape parameter γ, Boundary parameter a, Boundary parameter b) = PF({}, {}, {})",
79            self.shape, self.min_a, self.max_b
80        )?;
81        Ok(())
82    }
83}