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
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//!  Rust implementation of [SIMD-oriented Fast Mersenne Twister (SFMT)] using [stable SIMD]
//!
//! [SIMD-oriented Fast Mersenne Twister (SFMT)]: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/
//! [stable SIMD]: https://github.com/rust-lang/rfcs/blob/master/text/2325-stable-simd.md
//!
//! ```
//! use rand_core::{RngCore, SeedableRng};
//! let mut rng = sfmt::SFMT::seed_from_u64(42);
//! let r = rng.next_u32();
//! println!("random u32 number = {}", r);
//! ```

mod packed;
mod sfmt;
#[cfg(feature = "thread_rng")]
mod thread_rng;

use rand_core::{impls, Error, RngCore, SeedableRng};

use self::packed::*;
#[cfg(feature = "thread_rng")]
pub use self::thread_rng::{thread_rng, ThreadRng};

/// State of SFMT
///
/// This struct implements random number generation through `rand::Rng`.
#[derive(Clone)]
pub struct SFMT {
    /// the 128-bit internal state array
    state: [i32x4; sfmt::SFMT_N],
    /// index counter to the 32-bit internal state array
    idx: usize,
}

impl SFMT {
    fn pop32(&mut self) -> u32 {
        let val = extract(self.state[self.idx / 4], self.idx % 4);
        self.idx += 1;
        val
    }

    fn pop64(&mut self) -> u64 {
        let p = self.state.as_ptr() as *const u32;
        let val = unsafe {
            let p = p.offset(self.idx as isize);
            *(p as *const u64) // reinterpret cast [u32; 2] -> u64
        };
        self.idx += 2;
        val
    }

    fn gen_all(&mut self) {
        sfmt::sfmt_gen_rand_all(self);
        self.idx = 0;
    }
}

impl SeedableRng for SFMT {
    type Seed = [u8; 4];

    fn from_seed(seed: [u8; 4]) -> Self {
        let mut sfmt = SFMT {
            state: [zero(); sfmt::SFMT_N],
            idx: 0,
        };
        let seed = unsafe { *(seed.as_ptr() as *const u32) };
        sfmt::sfmt_init_gen_rand(&mut sfmt, seed);
        sfmt
    }
}

impl RngCore for SFMT {
    fn next_u32(&mut self) -> u32 {
        if self.idx >= sfmt::SFMT_N32 {
            self.gen_all();
        }
        self.pop32()
    }

    fn next_u64(&mut self) -> u64 {
        if self.idx >= sfmt::SFMT_N32 - 1 {
            // drop last u32 if idx == N32-1
            self.gen_all();
        }
        self.pop64()
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        impls::fill_bytes_via_next(self, dest)
    }

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        Ok(self.fill_bytes(dest))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use rand_core::{RngCore, SeedableRng};

    #[test]
    fn random() {
        let mut rng = SFMT::seed_from_u64(0);
        for _ in 0..sfmt::SFMT_N * 20 {
            // Generate many random numbers to test the overwrap
            let r = rng.next_u64();
            if r % 2 == 0 {
                let _r = rng.next_u32();
            } // shift SFMT.idx randomly
        }
    }
}