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
use {SeedableRng, RngCore, u64_from_sl};

#[derive(Debug, Clone, Copy)]
pub struct Xoroshiro128Rng {
  state: [u64; 2]
}

impl Xoroshiro128Rng {
  #[cfg(feature = "rand")]
  /// Creates a new `Xoroshiro128Rng` instance which is randomly seeded.
  ///
  /// # Errors
  ///
  /// When created this way the initial values of this `Rng` are seeded using an `OsRng`. If this
  /// fails then this method will pass through the error from `OsRng`.
  ///
  /// # Examples
  ///
  /// ```rust,no_run
  /// # extern crate rand; extern crate xoroshiro128; fn main() {
  /// use rand::Rng;
  /// use xoroshiro128::Xoroshiro128Rng;
  ///
  /// let mut rng = Xoroshiro128Rng::new();
  /// let x: u32 = rng.gen();
  /// println!("{}", x);
  /// # }
  /// ```
  pub fn new() -> Self {
    use rand::Rng;
    let seed = rand::rngs::OsRng.gen::<<Self as SeedableRng>::Seed>();
    Self::from_seed(seed)
  }

  /// Creates a new `Xoroshiro128Rng` instance which is not seeded.
  ///
  /// The initial values of this Rng are constants, so all generators created by this function
  /// will yield the same stream of random numbers. It is highly recommended that this is created
  /// through `SeedableRng` instead of this function.
  pub fn new_unseeded() -> Self {
    Xoroshiro128Rng::from_seed_u64([
      0x193a6754a8a7d469,
      0x97830e05113ba7bb
    ])
  }

  pub fn from_seed_u64(seed: [u64; 2]) -> Self {
    assert!(seed != [0; 2], "Invalid seed: seed must not be 0.");
    Xoroshiro128Rng { state: seed }
  }
}

impl RngCore for Xoroshiro128Rng {
  fn next_u32(&mut self) -> u32 {
    self.next_u64() as u32
  }

  fn next_u64(&mut self) -> u64 {
    let s0: u64 = self.state[0];
    let mut s1: u64 = self.state[1];
    let result: u64 = s0.wrapping_add(s1);

    s1 ^= s0;
    self.state[0] = s0.rotate_left(55) ^ s1 ^ (s1 << 14); // a, b
    self.state[1] = s1.rotate_left(36); // c

    result
  }

  fn fill_bytes(&mut self, dest: &mut [u8]) {
    let mut ctr = 0;
    let mut v = 0;
    for d in dest.iter_mut() {
      if ctr == 0 {
        v = self.next_u64();
        ctr = 7;
      }
      *d = v as u8;
      v >>= 8;
      ctr -= 1;
    }
  }
  fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
    self.fill_bytes(dest);
    Ok(())
  }
}

/// Seed a `Xoroshiro128Rng` with a given seed.
///
/// # Panics
///
/// `Xoroshiro128Rng` is undefined for the seed `[0, 0]` and will panic if this seed is provided.
impl SeedableRng for Xoroshiro128Rng {
  type Seed = [u8; 16];

  fn from_seed(seed: [u8; 16]) -> Self {
    Self::from_seed_u64([u64_from_sl(&seed[..]), u64_from_sl(&seed[8..])])
  }
}