Skip to main content

steel_utils/random/
gaussian.rs

1use super::Random;
2
3/// A trait for generating gaussian random numbers using the Marsaglia polar method.
4pub trait MarsagliaPolarGaussian: Random {
5    /// Gets the stored next gaussian.
6    fn stored_next_gaussian(&self) -> Option<f64>;
7
8    /// Sets the stored next gaussian.
9    fn set_stored_next_gaussian(&mut self, value: Option<f64>);
10
11    /// Calculates the next gaussian.
12    fn calculate_gaussian(&mut self) -> f64 {
13        if let Some(gaussian) = self.stored_next_gaussian() {
14            self.set_stored_next_gaussian(None);
15            gaussian
16        } else {
17            loop {
18                let d = 2.0 * self.next_f64() - 1.0;
19                let e = 2.0 * self.next_f64() - 1.0;
20                let f = d * d + e * e;
21
22                if f < 1.0 && f != 0.0 {
23                    let g = (-2.0 * f.ln() / f).sqrt();
24                    self.set_stored_next_gaussian(Some(e * g));
25                    return d * g;
26                }
27            }
28        }
29    }
30}