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
//! This module impliments JSF type algorithms

use crate::prng_iter;
use crate::smol_core;
use crate::smol_core::Algorithm;

/// This is the simple struct definition for the 64 Bit JSF Algorithm originally proposed by Bob Jenkins
#[derive(Default)]
pub struct JsfLarge {
    pub(crate) data: [u64; 4],
}

prng_iter! {JsfLarge}

impl Algorithm for JsfLarge {
    type Output = u64;

    ///Translated from original C Source that can  be found [here](https://burtleburtle.net/bob/rand/smallprng.html).
    ///
    /// A copy of the original included here for preservation and verification of correctness.
    ///
    ///```C
    ///typedef unsigned long long u8;
    ///typedef struct ranctx { u8 a; u8 b; u8 c; u8 d; } ranctx;
    ///
    /// #define rot(x,k) (((x)<<(k))|((x)>>(64-(k))))
    /// u8 ranval( ranctx *x ) {
    ///     u8 e = x->a - rot(x->b, 7);
    ///     x->a = x->b ^ rot(x->c, 13);
    ///     x->b = x->c + rot(x->d, 37);
    ///     x->c = x->d + e;
    ///    x->d = e + x->a;
    ///     return x->d;
    ///}
    /// ```

    fn gen(&mut self) -> u64 {
        assert!(3 <= self.data.len());

        let e = self.data[0].overflowing_sub(self.data[1].rotate_left(7)).0;
        self.data[0] = self.data[1] ^ self.data[2].rotate_left(13);
        self.data[1] = self.data[1].overflowing_add(self.data[3].rotate_left(37)).0;
        self.data[2] = self.data[1].overflowing_add(e).0;
        self.data[3] = e.overflowing_add(self.data[0]).0;

        self.data[3]
    }
}