randomize 3.0.1

randomization routines
Documentation
#![allow(clippy::unreadable_literal)]
use core::char;
use randomize::*;

fn given_any_pcg32() -> AnyPCG<PCG32> {
  // Note(Evrey): This seed is guaranteed to generate a valid char as initial value.
  //              It is the default seed, but in case one finds a better one in the
  //              future, these values are decoupled from the public constants.
  AnyPCG::new(PCG32::seed(
    201526561274146932589719779721328219291_u128 as u64,
    34172814569070222299_u128 as u64,
  ))
}

#[test]
fn given_pcg_generates_reproducible_results() {
  let mut rng = given_any_pcg32();

  let out_rng = [
    rng.next_u32(),
    rng.next_u32(),
    rng.next_u32(),
    rng.next_u32(),
  ];
  let expected = [0x129536FA, 0xB44462DC, 0xF08B4A2F, 0x8CF1B7FA];

  assert_eq!(out_rng, expected);
}

#[test]
fn any_pcg_generates_data_in_little_endian_order() {
  let mut rng = given_any_pcg32();
  let x0 = rng.next_u8();
  let x1 = rng.next_u8();
  let x2 = rng.next_u8();
  let x3 = rng.next_u8();

  rng = given_any_pcg32();

  let y0 = rng.next_u16();
  let y1 = rng.next_u16();

  let bits32 = given_any_pcg32().next_u32();
  let bits16 = u32::from(y0) | (u32::from(y1) << 16);
  let bits8 = u32::from_le_bytes([x0, x1, x2, x3]);

  assert_eq!(bits32, bits8);
  assert_eq!(bits32, bits16);
}

#[test]
fn any_pcg_generates_a_bunch_of_valid_chars_eventually() {
  let mut rng = given_any_pcg32();

  for _ in 0..7777777 {
    let c = rng.next_char() as u32;

    assert_ne!(c, char::REPLACEMENT_CHARACTER as u32);
    assert!(char::from_u32(c).is_some(), "Failed for: {:#010X}", c);
  }
}

#[test]
fn any_pcg_uses_minimal_random_bits() {
  let mut rng0 = given_any_pcg32();
  let mut rng1 = given_any_pcg32();

  let _ = rng1.next_u32();
  let expected = rng1.next_u32();

  let _ = rng0.next_char(); // 21 bits
  let _ = rng0.next_u8();
  let _ = rng0.next_bool(); // 1 bit
  let _ = rng0.next_bool();
  let _ = rng0.next_bool();
  let got = rng0.next_u32();

  assert_eq!(got, expected);
}

#[cfg(feature = "serde")]
#[test]
fn serde_roundtrip_keeps_all_state() {
  use bincode::{deserialize, serialize};

  let mut rng0 = given_any_pcg32();

  // Some arbitrary sequence of consumed data, so that there will
  // be unused bits in the `extracted` buffer.
  let _ = rng0.next_char(); // 32, 21 + 11
  let _ = rng0.next_bool(); // 32, 22 + 10
  let _ = rng0.next_u64(); // 96, 86 + 12

  // Roundtrip into new RNG.
  let buf = serialize(&rng0).unwrap();
  let mut rng1 = deserialize(&buf[..]).unwrap();

  assert_eq!(rng0, rng1);
  assert_eq!(rng0.next_u128(), rng1.next_u128());
}