1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
use crate::{Geometric, set_state, update_and_uniform};

impl Geometric {
    /// コンストラクタ
    /// * `_seed` - 乱数の種
    pub fn new(_seed: u32) -> Self {
        Self {
            xyzw: set_state(_seed),
        }
    }

    /// ある確率の事象が初めて生じるまでの試行回数を返す
    /// * `probability` - ある事象が生じる確率
    pub fn sample(&self, probability: f64) -> u32 {
        if probability <= 0f64 {return std::u32::MAX}; // オーバーフロー対策

        // アルゴリズム 4.13
        // step 1: x = 1と初期設定する
        let mut x: u32 = 1;
        loop {
            // step 2: 区間[0, 1]の一様乱数uを発生させる
            // step 3: u ≦ θ(発生確率)のときxを所望の乱数として出力する
            // u > θのときはxの値を1増やしてstep 2に戻る
            if update_and_uniform(&self.xyzw) <= probability { return x; }
            else { x += 1; }
        }
    }
}

#[macro_export]
/// 幾何分布のインスタンスを生成するマクロ
/// * `() =>` - 乱数の種は自動生成
/// * `($seed: expr) =>` - 乱数の種を指定する
macro_rules! create_geometric {
    () => {
        $crate::Geometric::new($crate::create_seed())
    };
    ($seed: expr) => {
        $crate::Geometric::new($seed as u32)
    };
}