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}