[go: up one dir, main page]

oorandom 11.1.5

A tiny, robust PRNG implementation.
Documentation
<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <style>html, body {
  margin: 0;
  padding: 0;
}

.app {
  margin: 10px;
  padding: 0;
}

.files-list {
  margin: 10px 0 0;
  width: 100%;
  border-collapse: collapse;
}
.files-list__head {
  border: 1px solid #999;
}
.files-list__head > tr > th {
  padding: 10px;
  border: 1px solid #999;
  text-align: left;
  font-weight: normal;
  background: #ddd;
}
.files-list__body {
}
.files-list__file {
  cursor: pointer;
}
.files-list__file:hover {
  background: #ccf;
}
.files-list__file > td {
  padding: 10px;
  border: 1px solid #999;
}
.files-list__file > td:first-child::before {
  content: '\01F4C4';
  margin-right: 1em;
}
.files-list__file_low {
  background: #fcc;
}
.files-list__file_medium {
  background: #ffc;
}
.files-list__file_high {
  background: #cfc;
}
.files-list__file_folder > td:first-child::before {
  content: '\01F4C1';
  margin-right: 1em;
}

.file-header {
  border: 1px solid #999;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.file-header__back {
  margin: 10px;
  cursor: pointer;
  flex-shrink: 0;
  flex-grow: 0;
  text-decoration: underline;
  color: #338;
}

.file-header__name {
  margin: 10px;
  flex-shrink: 2;
  flex-grow: 2;
}

.file-header__stat {
  margin: 10px;
  flex-shrink: 0;
  flex-grow: 0;
}

.file-content {
  margin: 10px 0 0;
  border: 1px solid #999;
  padding: 10px;
}

.code-line {
  margin: 0;
  padding: 0.3em;
  height: 1em;
}
.code-line_covered {
  background: #cfc;
}
.code-line_uncovered {
  background: #fcc;
}
</style>
</head>
<body>
    <div id="root"></div>
    <script>
        var data = {"files":[{"path":["/","home","srv","hg","icefox","srht","icefox","oorandom","src","lib.rs"],"content":"//! A tiny, robust PRNG implementation.\n//!\n//! More specifically, it implements a single GOOD PRNG algorithm,\n//! which is currently a permuted congruential generator.  It has two\n//! implementations, one that returns `u32` and one that returns\n//! `u64`.  It also has functions that return floats or integer\n//! ranges.  And that's it.  What more do you need?\n//!\n//! For more info on PCG generators, see http://www.pcg-random.org/\n//!\n//! This was designed as a minimalist utility for video games.  No\n//! promises are made about its quality, and if you use it for\n//! cryptography you will get what you deserve.\n//!\n//! Works with `#![no_std]`, has no global state, no dependencies\n//! apart from some in the unit tests, and is generally neato.\n\n#![forbid(unsafe_code)]\n#![forbid(missing_docs)]\n#![forbid(missing_debug_implementations)]\n#![forbid(unused_results)]\n#![no_std]\nuse core::ops::Range;\n\n/// A PRNG producing a 32-bit output.\n///\n/// The current implementation is `PCG-XSH-RR`.\n#[derive(Copy, Clone, Debug, PartialEq)]\npub struct Rand32 {\n    state: u64,\n    inc: u64,\n}\n\nimpl Rand32 {\n    /// The default value for `increment`.\n    /// This is basically arbitrary, it comes from the\n    /// PCG reference C implementation:\n    /// https://github.com/imneme/pcg-c/blob/master/include/pcg_variants.h#L284\n    pub const DEFAULT_INC: u64 = 1442695040888963407;\n\n    /// This is the number that you have to Really Get Right.\n    ///\n    /// The value used here is from the PCG C implementation:\n    /// https://github.com/imneme/pcg-c/blob/master/include/pcg_variants.h#L278\n    pub(crate) const MULTIPLIER: u64 = 6364136223846793005;\n\n    /// Creates a new PRNG with the given seed and a default increment.\n    pub fn new(seed: u64) -\u003e Self {\n        Self::new_inc(seed, Self::DEFAULT_INC)\n    }\n\n    /// Creates a new PRNG.  The two inputs, `seed` and `increment`,\n    /// determine what you get; `increment` basically selects which\n    /// sequence of all those possible the PRNG will produce, and the\n    /// `seed` selects where in that sequence you start.\n    ///\n    /// Both are arbitrary; increment must be an odd number but this\n    /// handles that for you\n    pub fn new_inc(seed: u64, increment: u64) -\u003e Self {\n        let mut rng = Self {\n            state: 0,\n            inc: increment.wrapping_shl(1) | 1,\n        };\n        // This initialization song-and-dance is a little odd,\n        // but seems to be just how things go.\n        let _ = rng.rand_u32();\n        rng.state = rng.state.wrapping_add(seed);\n        let _ = rng.rand_u32();\n        rng\n    }\n\n    /// Returns the internal state of the PRNG.  This allows\n    /// you to save a PRNG and create a new one that will resume\n    /// from the same spot in the sequence.\n    pub fn state(\u0026self) -\u003e (u64, u64) {\n        (self.state, self.inc)\n    }\n\n    /// Creates a new PRNG from a saved state from `Rand32::state()`.\n    /// This is NOT quite the same as `new_inc()` because `new_inc()` does\n    /// a little extra setup work to initialize the state.\n    pub fn from_state(state: (u64, u64)) -\u003e Self {\n        let (state, inc) = state;\n        Self { state, inc }\n    }\n\n    /// Produces a random `u32` in the range `[0, u32::MAX]`.\n    pub fn rand_u32(\u0026mut self) -\u003e u32 {\n        let oldstate: u64 = self.state;\n        self.state = oldstate\n            .wrapping_mul(Self::MULTIPLIER)\n            .wrapping_add(self.inc);\n        let xorshifted: u32 = (((oldstate \u003e\u003e 18) ^ oldstate) \u003e\u003e 27) as u32;\n        let rot: u32 = (oldstate \u003e\u003e 59) as u32;\n        xorshifted.rotate_right(rot)\n    }\n\n    /// Produces a random `i32` in the range `[i32::MIN, i32::MAX]`.\n    pub fn rand_i32(\u0026mut self) -\u003e i32 {\n        self.rand_u32() as i32\n    }\n\n    /// Produces a random `f32` in the range `[0.0, 1.0)`.\n    pub fn rand_float(\u0026mut self) -\u003e f32 {\n        // This impl was taken more or less from `rand`, see\n        // \u003chttps://docs.rs/rand/0.7.0/src/rand/distributions/float.rs.html#104-117\u003e\n        // There MAY be better ways to do this, see:\n        // https://mumble.net/~campbell/2014/04/28/uniform-random-float\n        // https://mumble.net/~campbell/2014/04/28/random_real.c\n        // https://github.com/Lokathor/randomize/issues/34\n        const TOTAL_BITS: u32 = 32;\n        const PRECISION: u32 = core::f32::MANTISSA_DIGITS + 1;\n        const MANTISSA_SCALE: f32 = 1.0 / ((1u32 \u003c\u003c PRECISION) as f32);\n        let mut u = self.rand_u32();\n        u \u003e\u003e= TOTAL_BITS - PRECISION;\n        u as f32 * MANTISSA_SCALE\n    }\n\n    /// Produces a random within the given bounds.  Like any `Range`,\n    /// it includes the lower bound and excludes the upper one.\n    ///\n    /// This should be faster than `Self::rand() % end + start`, but the\n    /// real advantage is it's more convenient.  Requires that\n    /// `range.end \u003c= range.start`.\n    pub fn rand_range(\u0026mut self, range: Range\u003cu32\u003e) -\u003e u32 {\n        // This is harder to do well than it looks, it seems.  I don't\n        // trust Lokathor's implementation 'cause I don't understand\n        // it, so I went to numpy's, which points me to \"Lemire's\n        // rejection algorithm\": http://arxiv.org/abs/1805.10941\n        //\n        // Algorithms 3, 4 and 5 in that paper all seem fine modulo\n        // minor performance differences, so this is algorithm 5.\n        // It uses numpy's implementation, `buffered_bounded_lemire_uint32()`\n\n        debug_assert!(range.start \u003c range.end);\n        let range_starting_from_zero = 0..(range.end - range.start);\n\n        let s: u32 = range_starting_from_zero.end;\n        let mut m: u64 = u64::from(self.rand_u32()) * u64::from(s);\n        let mut leftover: u32 = (m \u0026 0xFFFF_FFFF) as u32;\n\n        if leftover \u003c s {\n            // TODO: verify the wrapping_neg() here\n            let threshold: u32 = s.wrapping_neg() % s;\n            while leftover \u003c threshold {\n                m = u64::from(self.rand_u32()).wrapping_mul(u64::from(s));\n                leftover = (m \u0026 0xFFFF_FFFF) as u32;\n            }\n        }\n        (m \u003e\u003e 32) as u32 + range.start\n    }\n}\n\n/// A PRNG producing a 64-bit output.\n///\n/// The current implementation is `PCG-XSH-RR`.\n// BUGGO: The recommended algorithm is PCG-XSL-RR?\n// See https://github.com/imneme/pcg-c/blob/master/include/pcg_variants.h#L2405\n// Not sure if it matters?\n#[derive(Copy, Clone, Debug, PartialEq)]\npub struct Rand64 {\n    state: u128,\n    inc: u128,\n}\n\nimpl Rand64 {\n    /// The default value for `increment`.\n    ///\n    /// The value used here is from the PCG default C implementation: http://www.pcg-random.org/download.html\n    pub const DEFAULT_INC: u128 = 0x2FE0E169_FFBD06E3_5BC307BD_4D2F814F;\n\n    /// This is the number that you have to Really Get Right.\n    ///\n    /// The value used here is from the PCG C implementation:\n    /// https://github.com/imneme/pcg-c/blob/master/include/pcg_variants.h#L288\n    pub(crate) const MULTIPLIER: u128 = 47026247687942121848144207491837523525;\n\n    /// Creates a new PRNG with the given seed and a default increment.\n    pub fn new(seed: u128) -\u003e Self {\n        Self::new_inc(seed, Self::DEFAULT_INC)\n    }\n\n    /// Same as `Rand32::new_inc()`\n    fn new_inc(seed: u128, increment: u128) -\u003e Self {\n        let mut rng = Self {\n            state: 0,\n            inc: increment.wrapping_shl(1) | 1,\n        };\n        let _ = rng.rand_u64();\n        rng.state = rng.state.wrapping_add(seed);\n        let _ = rng.rand_u64();\n        rng\n    }\n\n    /// Returns the internal state of the PRNG.  This allows\n    /// you to save a PRNG and create a new one that will resume\n    /// from the same spot in the sequence.\n    pub fn state(\u0026self) -\u003e (u128, u128) {\n        (self.state, self.inc)\n    }\n\n    /// Creates a new PRNG from a saved state from `Rand32::state()`.\n    /// This is NOT quite the same as `new_inc()` because `new_inc()` does\n    /// a little extra setup work to initialize the state.\n    pub fn from_state(state: (u128, u128)) -\u003e Self {\n        let (state, inc) = state;\n        Self { state, inc }\n    }\n\n    /// Produces a random `u64` in the range`[0, u64::MAX]`.\n    pub fn rand_u64(\u0026mut self) -\u003e u64 {\n        let oldstate: u128 = self.state;\n        self.state = oldstate\n            .wrapping_mul(Self::MULTIPLIER)\n            .wrapping_add(self.inc);\n        let xorshifted: u64 = (((oldstate \u003e\u003e 29) ^ oldstate) \u003e\u003e 58) as u64;\n        let rot: u32 = (oldstate \u003e\u003e 122) as u32;\n        xorshifted.rotate_right(rot)\n    }\n\n    /// Produces a random `i64` in the range `[i64::MIN, i64::MAX]`.\n    pub fn rand_i64(\u0026mut self) -\u003e i64 {\n        self.rand_u64() as i64\n    }\n\n    /// Produces a random `f64` in the range `[0.0, 1.0)`.\n    pub fn rand_float(\u0026mut self) -\u003e f64 {\n        const TOTAL_BITS: u32 = 64;\n        const PRECISION: u32 = core::f64::MANTISSA_DIGITS + 1;\n        const MANTISSA_SCALE: f64 = 1.0 / ((1u64 \u003c\u003c PRECISION) as f64);\n        let mut u = self.rand_u64();\n        u \u003e\u003e= TOTAL_BITS - PRECISION;\n        u as f64 * MANTISSA_SCALE\n    }\n\n    /// Produces a random within the given bounds.  Like any `Range`,\n    /// it includes the lower bound and excludes the upper one.\n    ///\n    /// This should be faster than `Self::rand() % end + start`, but the\n    /// real advantage is it's more convenient.  Requires that\n    /// `range.end \u003c= range.start`.\n    pub fn rand_range(\u0026mut self, range: Range\u003cu64\u003e) -\u003e u64 {\n        // Same as `Rand32::rand_range()`\n        debug_assert!(range.start \u003c range.end);\n        let range_starting_from_zero = 0..(range.end - range.start);\n\n        let s: u64 = range_starting_from_zero.end;\n        let mut m: u128 = u128::from(self.rand_u64()) * u128::from(s);\n        let mut leftover: u64 = (m \u0026 0xFFFFFFFF_FFFFFFFF) as u64;\n\n        if leftover \u003c s {\n            // TODO: Verify the wrapping_negate() here\n            let threshold: u64 = s.wrapping_neg() % s;\n            while leftover \u003c threshold {\n                m = u128::from(self.rand_u64()) * u128::from(s);\n                leftover = (m \u0026 0xFFFFFFFF_FFFFFFFF) as u64;\n            }\n        }\n        (m.wrapping_shr(64)) as u64 + range.start\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use randomize::{self, PCG32, PCG64};\n\n    #[test]\n    fn test_rand32_vs_randomize() {\n        // Generate some random numbers and validate them against\n        // a known-good generator.\n        {\n            let seed = 54321;\n            let mut r1 = Rand32::new(seed);\n            let mut r2 = PCG32::seed(seed, Rand32::DEFAULT_INC);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u32(), r2.next_u32());\n                assert_eq!(r1.rand_i32(), r2.next_u32() as i32);\n            }\n        }\n\n        {\n            let seed = 3141592653;\n            let inc = 0xDEADBEEF;\n            let mut r1 = Rand32::new_inc(seed, inc);\n            let mut r2 = PCG32::seed(seed, inc);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u32(), r2.next_u32());\n                assert_eq!(r1.rand_i32(), r2.next_u32() as i32);\n            }\n        }\n    }\n\n    #[test]\n    fn test_rand64_vs_randomize() {\n        // Generate some random numbers and validate them against\n        // a known-good generator.\n        {\n            let seed = 54321;\n            let mut r1 = Rand64::new(seed);\n            let mut r2 = PCG64::seed(seed, Rand64::DEFAULT_INC);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u64(), r2.next_u64());\n                assert_eq!(r1.rand_i64(), r2.next_u64() as i64);\n            }\n        }\n\n        {\n            let seed = 3141592653;\n            let inc = 0xDEADBEEF;\n            let mut r1 = Rand64::new_inc(seed, inc);\n            let mut r2 = PCG64::seed(seed, inc);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u64(), r2.next_u64());\n                assert_eq!(r1.rand_i64(), r2.next_u64() as i64);\n            }\n        }\n    }\n\n    #[test]\n    fn test_float32() {\n        {\n            let seed = 2718281828;\n            let mut r1 = Rand32::new(seed);\n            let mut r2 = PCG32::seed(seed, Rand32::DEFAULT_INC);\n            for _ in 0..1000 {\n                // First just make sure they both work with randomize's\n                // f32 conversion function -- sanity checks.\n                let i1 = r1.rand_u32();\n                let i2 = r2.next_u32();\n                assert_eq!(i1, i2);\n                let f1 = randomize::f32_half_open_right(i1);\n                let f2 = randomize::f32_half_open_right(i2);\n                // We can directly compare floats 'cause we do no math, it's\n                // literally the same bitwise algorithm with the same inputs.\n                assert_eq!(f1, f2);\n\n                // Make sure result is in [0.0, 1.0)\n                assert!(f1 \u003e= 0.0);\n                assert!(f1 \u003c 1.0);\n            }\n\n            // At least make sure our float's from rand_float() are in the valid range.\n            for _ in 0..1000 {\n                let f1 = r1.rand_float();\n                assert!(f1 \u003e= 0.0);\n                assert!(f1 \u003c 1.0);\n            }\n\n            /*\n            TODO: Randomize changed its int-to-float conversion functions and now they don't\n            match ours.\n                        for _ in 0..1000 {\n                            // Now make sure our own float conversion function works.\n                            let f1 = r1.rand_float();\n                            //let f2 = randomize::f32_half_open_right(r2.next_u32());\n                            let f2 = randomize::f32_open(r2.next_u32());\n                            assert_eq!(f1, f2);\n                            assert!(f1 \u003e= 0.0);\n                            assert!(f1 \u003c 1.0);\n                        }\n                         */\n        }\n    }\n\n    #[test]\n    fn test_float64() {\n        {\n            let seed = 2718281828;\n            let mut r1 = Rand64::new(seed);\n            let mut r2 = PCG64::seed(seed, Rand64::DEFAULT_INC);\n            for _ in 0..1000 {\n                // First just make sure they both work with randomize's\n                // f64 conversion function -- sanity checks.\n                let i1 = r1.rand_u64();\n                let i2 = r2.next_u64();\n                assert_eq!(i1, i2);\n                let f1 = randomize::f64_half_open_right(i1);\n                let f2 = randomize::f64_half_open_right(i2);\n                // We can directly compare floats 'cause we do no math, it's\n                // literally the same bitwise algorithm with the same inputs.\n                assert_eq!(f1, f2);\n\n                // Make sure result is in [0.0, 1.0)\n                assert!(f1 \u003e= 0.0);\n                assert!(f1 \u003c 1.0);\n            }\n\n            // At least make sure our float's from rand_float() are in the valid range.\n            for _ in 0..1000 {\n                let f1 = r1.rand_float();\n                assert!(f1 \u003e= 0.0);\n                assert!(f1 \u003c 1.0);\n            }\n\n            /*\n            TODO: Randomize changed its int-to-float conversion functions and now they don't\n            match ours.\n                        for _ in 0..1000 {\n                            // Now make sure our own float conversion function works.\n                            let f1 = r1.rand_float();\n                            //let f2 = randomize::f32_half_open_right(r2.next_u32());\n                            let f2 = randomize::f32_open(r2.next_u32());\n                            assert_eq!(f1, f2);\n                            assert!(f1 \u003e= 0.0);\n                            assert!(f1 \u003c 1.0);\n                        }\n                         */\n        }\n    }\n\n    #[test]\n    fn test_randrange32() {\n        // Make sure ranges are valid and in the given range\n        let seed = 2342_3141;\n        let mut r1 = Rand32::new(seed);\n        for _ in 0..1000 {\n            // Generate our bounds at random\n            let a = r1.rand_u32();\n            let b = r1.rand_u32();\n            if a == b {\n                continue;\n            }\n            let (low, high) = if a \u003c b { (a, b) } else { (b, a) };\n\n            // Get a number in that range\n            let in_range = r1.rand_range(low..high);\n            assert!(in_range \u003e= low);\n            assert!(in_range \u003c high);\n        }\n    }\n\n    #[test]\n    fn test_randrange64() {\n        // Make sure ranges are valid and in the given range\n        let seed = 2342_2718;\n        let mut r1 = Rand64::new(seed);\n        for _ in 0..1000 {\n            // Generate our bounds at random\n            let a = r1.rand_u64();\n            let b = r1.rand_u64();\n            if a == b {\n                continue;\n            }\n            let (low, high) = if a \u003c b { (a, b) } else { (b, a) };\n\n            // Get a number in that range\n            let in_range = r1.rand_range(low..high);\n            assert!(in_range \u003e= low);\n            assert!(in_range \u003c high);\n        }\n    }\n\n    #[test]\n    fn test_rand32_vs_rand() {\n        use rand_core::RngCore;\n        use rand_pcg;\n        {\n            let seed = 54321;\n            let mut r1 = Rand32::new(seed);\n            let mut r2 = rand_pcg::Pcg32::new(seed, Rand32::DEFAULT_INC);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u32(), r2.next_u32());\n            }\n        }\n\n        {\n            let seed = 3141592653;\n            let inc = 0xDEADBEEF;\n            let mut r1 = Rand32::new_inc(seed, inc);\n            let mut r2 = rand_pcg::Pcg32::new(seed, inc);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u32(), r2.next_u32());\n            }\n        }\n    }\n\n    // This doesn't work 'cause for 64-bit output `rand` uses\n    // PCG-XSL-RR\n    // and we use\n    // PCG-XSH-RR\n    /*\n        #[test]\n        fn test_rand64_vs_rand() {\n            use rand_pcg;\n            use rand_core::RngCore;\n            {\n                let seed = 54321;\n                let mut r1 = Rand64::new(seed);\n                let mut r2 = rand_pcg::Pcg64::new(seed, Rand64::DEFAULT_INC);\n                for _ in 0..1000 {\n                    assert_eq!(r1.rand(), r2.next_u64());\n                }\n            }\n\n            {\n                let seed = 3141592653;\n                let inc = 0xDEADBEEF;\n                let mut r1 = Rand64::new_inc(seed, inc);\n                let mut r2 = rand_pcg::Pcg64::new(seed, inc);\n                for _ in 0..1000 {\n                    assert_eq!(r1.rand(), r2.next_u64());\n                }\n            }\n        }\n    */\n\n    // Test vs. random-fast-rng, which I will call rfr\n    // rfr's float conversion uses yet a different algorithm\n    // than ours, so we can't really check that.\n    #[test]\n    fn test_rand32_vs_rfr() {\n        use random_fast_rng as rfr;\n        use rfr::Random;\n        {\n            let seed = 54321;\n            let mut r1 = Rand32::new(seed);\n            let mut r2 = rfr::FastRng::seed(seed, Rand32::DEFAULT_INC);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u32(), r2.get_u32());\n            }\n        }\n\n        {\n            let seed = 3141592653;\n            let inc = 0xDEADBEEF;\n            let mut r1 = Rand32::new_inc(seed, inc);\n            let mut r2 = rfr::FastRng::seed(seed, inc);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u32(), r2.get_u32());\n            }\n        }\n    }\n\n    /// Make sure that saving a RNG state and restoring\n    /// it works.\n    /// See https://todo.sr.ht/~icefox/oorandom/1\n    #[test]\n    fn test_save_restore() {\n        {\n            let seed = 54321;\n            let mut r1 = Rand32::new(seed);\n            let s1 = r1.state();\n            let mut r2 = Rand32::from_state(s1);\n            assert_eq!(r1, r2);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u32(), r2.rand_u32());\n            }\n        }\n\n        {\n            let seed = 3141592653;\n            let inc = 0xDEADBEEF;\n            let mut r1 = Rand32::new_inc(seed, inc);\n            let s1 = r1.state();\n            let mut r2 = Rand32::from_state(s1);\n            assert_eq!(r1, r2);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u32(), r2.rand_u32());\n            }\n        }\n\n        {\n            let seed = 54321;\n            let mut r1 = Rand64::new(seed);\n            let s1 = r1.state();\n            let mut r2 = Rand64::from_state(s1);\n            assert_eq!(r1, r2);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u64(), r2.rand_u64());\n            }\n        }\n\n        {\n            let seed = 3141592653;\n            let inc = 0xDEADBEEF;\n            let mut r1 = Rand64::new_inc(seed, inc);\n            let s1 = r1.state();\n            let mut r2 = Rand64::from_state(s1);\n            assert_eq!(r1, r2);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u64(), r2.rand_u64());\n            }\n        }\n    }\n}\n","traces":[{"line":48,"address":[4213216],"length":1,"stats":{"Line":3},"fn_name":"new"},{"line":49,"address":[4213225],"length":1,"stats":{"Line":3},"fn_name":null},{"line":59,"address":[4213264],"length":1,"stats":{"Line":3},"fn_name":"new_inc"},{"line":62,"address":[4213283],"length":1,"stats":{"Line":3},"fn_name":null},{"line":66,"address":[4213326],"length":1,"stats":{"Line":3},"fn_name":null},{"line":67,"address":[4213336],"length":1,"stats":{"Line":4},"fn_name":null},{"line":68,"address":[4213364],"length":1,"stats":{"Line":5},"fn_name":null},{"line":69,"address":[4213374],"length":1,"stats":{"Line":4},"fn_name":null},{"line":75,"address":[4213392],"length":1,"stats":{"Line":1},"fn_name":"state"},{"line":76,"address":[4213401],"length":1,"stats":{"Line":1},"fn_name":null},{"line":82,"address":[4213440],"length":1,"stats":{"Line":1},"fn_name":"from_state"},{"line":83,"address":[4213454],"length":1,"stats":{"Line":1},"fn_name":null},{"line":88,"address":[4213488],"length":1,"stats":{"Line":3},"fn_name":"rand_u32"},{"line":89,"address":[4213497],"length":1,"stats":{"Line":5},"fn_name":null},{"line":90,"address":[4213552,4213510],"length":1,"stats":{"Line":6},"fn_name":null},{"line":91,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":92,"address":[4213543],"length":1,"stats":{"Line":5},"fn_name":null},{"line":93,"address":[4213580],"length":1,"stats":{"Line":5},"fn_name":null},{"line":94,"address":[4213627],"length":1,"stats":{"Line":3},"fn_name":null},{"line":95,"address":[4213655],"length":1,"stats":{"Line":5},"fn_name":null},{"line":99,"address":[4213680],"length":1,"stats":{"Line":1},"fn_name":"rand_i32"},{"line":100,"address":[4213689],"length":1,"stats":{"Line":1},"fn_name":null},{"line":104,"address":[4213712],"length":1,"stats":{"Line":1},"fn_name":"rand_float"},{"line":114,"address":[4213721],"length":1,"stats":{"Line":1},"fn_name":null},{"line":115,"address":[4213730],"length":1,"stats":{"Line":1},"fn_name":null},{"line":116,"address":[4213757],"length":1,"stats":{"Line":1},"fn_name":null},{"line":125,"address":[4213792],"length":1,"stats":{"Line":1},"fn_name":"rand_range"},{"line":135,"address":[4213821,4213873],"length":1,"stats":{"Line":1},"fn_name":null},{"line":136,"address":[4213853,4213903,4214282],"length":1,"stats":{"Line":2},"fn_name":null},{"line":138,"address":[4213919],"length":1,"stats":{"Line":1},"fn_name":null},{"line":139,"address":[4213939,4214312],"length":1,"stats":{"Line":1},"fn_name":null},{"line":140,"address":[4214021],"length":1,"stats":{"Line":1},"fn_name":null},{"line":142,"address":[4214045,4214127],"length":1,"stats":{"Line":2},"fn_name":null},{"line":144,"address":[4214063,4214342],"length":1,"stats":{"Line":1},"fn_name":null},{"line":145,"address":[4214118,4214224],"length":1,"stats":{"Line":2},"fn_name":null},{"line":146,"address":[4214134],"length":1,"stats":{"Line":1},"fn_name":null},{"line":147,"address":[4214204],"length":1,"stats":{"Line":1},"fn_name":null},{"line":150,"address":[4214226,4214372,4214402],"length":1,"stats":{"Line":1},"fn_name":null},{"line":179,"address":[4214416],"length":1,"stats":{"Line":1},"fn_name":"new"},{"line":180,"address":[4214463],"length":1,"stats":{"Line":1},"fn_name":null},{"line":184,"address":[4214576],"length":1,"stats":{"Line":1},"fn_name":"new_inc"},{"line":187,"address":[4214620],"length":1,"stats":{"Line":1},"fn_name":null},{"line":189,"address":[4214701],"length":1,"stats":{"Line":1},"fn_name":null},{"line":190,"address":[4214711],"length":1,"stats":{"Line":1},"fn_name":null},{"line":191,"address":[4214766],"length":1,"stats":{"Line":1},"fn_name":null},{"line":192,"address":[4214776],"length":1,"stats":{"Line":1},"fn_name":null},{"line":198,"address":[4214832],"length":1,"stats":{"Line":1},"fn_name":"state"},{"line":199,"address":[4214844],"length":1,"stats":{"Line":1},"fn_name":null},{"line":205,"address":[4214928],"length":1,"stats":{"Line":1},"fn_name":"from_state"},{"line":206,"address":[4214955],"length":1,"stats":{"Line":1},"fn_name":null},{"line":211,"address":[4215040],"length":1,"stats":{"Line":1},"fn_name":"rand_u64"},{"line":212,"address":[4215052],"length":1,"stats":{"Line":1},"fn_name":null},{"line":213,"address":[4215097,4215164],"length":1,"stats":{"Line":2},"fn_name":null},{"line":214,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":215,"address":[4215146],"length":1,"stats":{"Line":1},"fn_name":null},{"line":216,"address":[4215211],"length":1,"stats":{"Line":1},"fn_name":null},{"line":217,"address":[4215301],"length":1,"stats":{"Line":1},"fn_name":null},{"line":218,"address":[4215338],"length":1,"stats":{"Line":2},"fn_name":null},{"line":222,"address":[4215376],"length":1,"stats":{"Line":1},"fn_name":"rand_i64"},{"line":223,"address":[4215385],"length":1,"stats":{"Line":1},"fn_name":null},{"line":227,"address":[4215408],"length":1,"stats":{"Line":1},"fn_name":"rand_float"},{"line":231,"address":[4215417],"length":1,"stats":{"Line":1},"fn_name":null},{"line":232,"address":[4215427],"length":1,"stats":{"Line":1},"fn_name":null},{"line":233,"address":[4215457],"length":1,"stats":{"Line":1},"fn_name":null},{"line":242,"address":[4215520],"length":1,"stats":{"Line":1},"fn_name":"rand_range"},{"line":244,"address":[4215551,4215628],"length":1,"stats":{"Line":1},"fn_name":null},{"line":245,"address":[4216411,4215658,4215603],"length":1,"stats":{"Line":2},"fn_name":null},{"line":247,"address":[4215686],"length":1,"stats":{"Line":1},"fn_name":null},{"line":248,"address":[4215718,4216441],"length":1,"stats":{"Line":1},"fn_name":null},{"line":249,"address":[4215965],"length":1,"stats":{"Line":1},"fn_name":null},{"line":251,"address":[4215989,4216094],"length":1,"stats":{"Line":2},"fn_name":null},{"line":253,"address":[4216471,4216012],"length":1,"stats":{"Line":1},"fn_name":null},{"line":254,"address":[4216331,4216084],"length":1,"stats":{"Line":2},"fn_name":null},{"line":255,"address":[4216107,4216501],"length":1,"stats":{"Line":1},"fn_name":null},{"line":256,"address":[4216315],"length":1,"stats":{"Line":1},"fn_name":null},{"line":259,"address":[4216561,4216336,4216531],"length":1,"stats":{"Line":1},"fn_name":null},{"line":269,"address":[4219504,4219509],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":273,"address":[4222375],"length":1,"stats":{"Line":1},"fn_name":null},{"line":274,"address":[4222392],"length":1,"stats":{"Line":1},"fn_name":null},{"line":275,"address":[4222428],"length":1,"stats":{"Line":1},"fn_name":null},{"line":276,"address":[4222449,4222635,4223285],"length":1,"stats":{"Line":2},"fn_name":null},{"line":277,"address":[4222828,4222658],"length":1,"stats":{"Line":1},"fn_name":null},{"line":278,"address":[4223290,4222796,4223153],"length":1,"stats":{"Line":2},"fn_name":null},{"line":283,"address":[4222582],"length":1,"stats":{"Line":1},"fn_name":null},{"line":284,"address":[4222595],"length":1,"stats":{"Line":1},"fn_name":null},{"line":285,"address":[4222603],"length":1,"stats":{"Line":1},"fn_name":null},{"line":286,"address":[4223635],"length":1,"stats":{"Line":1},"fn_name":null},{"line":287,"address":[4223792,4224394,4223656],"length":1,"stats":{"Line":2},"fn_name":null},{"line":288,"address":[4223985,4223815],"length":1,"stats":{"Line":1},"fn_name":null},{"line":289,"address":[4224399,4223953,4224274],"length":1,"stats":{"Line":2},"fn_name":null},{"line":295,"address":[4219536,4219541],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":299,"address":[4224695],"length":1,"stats":{"Line":1},"fn_name":null},{"line":300,"address":[4224736],"length":1,"stats":{"Line":1},"fn_name":null},{"line":301,"address":[4224842],"length":1,"stats":{"Line":1},"fn_name":null},{"line":302,"address":[4224911,4225205,4225865],"length":1,"stats":{"Line":2},"fn_name":null},{"line":303,"address":[4225403,4225228],"length":1,"stats":{"Line":1},"fn_name":null},{"line":304,"address":[4225370,4225728,4225870],"length":1,"stats":{"Line":2},"fn_name":null},{"line":309,"address":[4225047],"length":1,"stats":{"Line":1},"fn_name":null},{"line":310,"address":[4225072],"length":1,"stats":{"Line":1},"fn_name":null},{"line":311,"address":[4225112],"length":1,"stats":{"Line":1},"fn_name":null},{"line":312,"address":[4226235],"length":1,"stats":{"Line":1},"fn_name":null},{"line":313,"address":[4227082,4226470,4226334],"length":1,"stats":{"Line":2},"fn_name":null},{"line":314,"address":[4226668,4226493],"length":1,"stats":{"Line":1},"fn_name":null},{"line":315,"address":[4226957,4227087,4226635],"length":1,"stats":{"Line":2},"fn_name":null},{"line":321,"address":[4219573,4219568],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":323,"address":[4227388],"length":1,"stats":{"Line":1},"fn_name":null},{"line":324,"address":[4227396],"length":1,"stats":{"Line":1},"fn_name":null},{"line":325,"address":[4227435],"length":1,"stats":{"Line":1},"fn_name":null},{"line":326,"address":[4228624,4227456,4227644],"length":1,"stats":{"Line":2},"fn_name":null},{"line":329,"address":[4227667],"length":1,"stats":{"Line":1},"fn_name":null},{"line":330,"address":[4227687],"length":1,"stats":{"Line":1},"fn_name":null},{"line":331,"address":[4227707,4227838],"length":1,"stats":{"Line":1},"fn_name":null},{"line":332,"address":[4227805],"length":1,"stats":{"Line":1},"fn_name":null},{"line":333,"address":[4228127],"length":1,"stats":{"Line":1},"fn_name":null},{"line":336,"address":[4228148,4228280],"length":1,"stats":{"Line":1},"fn_name":null},{"line":339,"address":[4228247,4228594],"length":1,"stats":{"Line":1},"fn_name":null},{"line":340,"address":[4228629,4228575],"length":1,"stats":{"Line":1},"fn_name":null},{"line":344,"address":[4228666,4228870,4228740,4227584],"length":1,"stats":{"Line":3},"fn_name":null},{"line":345,"address":[4228763],"length":1,"stats":{"Line":1},"fn_name":null},{"line":346,"address":[4228791,4228840],"length":1,"stats":{"Line":1},"fn_name":null},{"line":347,"address":[4228905,4228826,4228875],"length":1,"stats":{"Line":1},"fn_name":null},{"line":367,"address":[4219605,4219600],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":369,"address":[4228924],"length":1,"stats":{"Line":1},"fn_name":null},{"line":370,"address":[4228956],"length":1,"stats":{"Line":1},"fn_name":null},{"line":371,"address":[4229065],"length":1,"stats":{"Line":1},"fn_name":null},{"line":372,"address":[4230317,4229322,4229134],"length":1,"stats":{"Line":2},"fn_name":null},{"line":375,"address":[4229345],"length":1,"stats":{"Line":1},"fn_name":null},{"line":376,"address":[4229366],"length":1,"stats":{"Line":1},"fn_name":null},{"line":377,"address":[4229387,4229521],"length":1,"stats":{"Line":1},"fn_name":null},{"line":378,"address":[4229487],"length":1,"stats":{"Line":1},"fn_name":null},{"line":379,"address":[4229816],"length":1,"stats":{"Line":1},"fn_name":null},{"line":382,"address":[4229972,4229838],"length":1,"stats":{"Line":1},"fn_name":null},{"line":385,"address":[4229938,4230287],"length":1,"stats":{"Line":1},"fn_name":null},{"line":386,"address":[4230267,4230322],"length":1,"stats":{"Line":1},"fn_name":null},{"line":390,"address":[4229262,4230565,4230433,4230359],"length":1,"stats":{"Line":3},"fn_name":null},{"line":391,"address":[4230456],"length":1,"stats":{"Line":1},"fn_name":null},{"line":392,"address":[4230535,4230484],"length":1,"stats":{"Line":1},"fn_name":null},{"line":393,"address":[4230600,4230520,4230570],"length":1,"stats":{"Line":1},"fn_name":null},{"line":413,"address":[4219632,4219637],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":415,"address":[4230615],"length":1,"stats":{"Line":1},"fn_name":null},{"line":416,"address":[4230629],"length":1,"stats":{"Line":1},"fn_name":null},{"line":417,"address":[4230988,4230738,4230644],"length":1,"stats":{"Line":2},"fn_name":null},{"line":419,"address":[4230752],"length":1,"stats":{"Line":1},"fn_name":null},{"line":420,"address":[4230770],"length":1,"stats":{"Line":1},"fn_name":null},{"line":421,"address":[4230796],"length":1,"stats":{"Line":1},"fn_name":null},{"line":422,"address":[4230814],"length":1,"stats":{"Line":0},"fn_name":null},{"line":424,"address":[4230820,4230808],"length":1,"stats":{"Line":2},"fn_name":null},{"line":427,"address":[4230869],"length":1,"stats":{"Line":1},"fn_name":null},{"line":428,"address":[4230922,4230958],"length":1,"stats":{"Line":1},"fn_name":null},{"line":429,"address":[4230943,4231023,4230993],"length":1,"stats":{"Line":2},"fn_name":null},{"line":434,"address":[4219669,4219664],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":436,"address":[4231031],"length":1,"stats":{"Line":1},"fn_name":null},{"line":437,"address":[4231069],"length":1,"stats":{"Line":1},"fn_name":null},{"line":438,"address":[4231114,4231217,4231551],"length":1,"stats":{"Line":2},"fn_name":null},{"line":440,"address":[4231240],"length":1,"stats":{"Line":1},"fn_name":null},{"line":441,"address":[4231263],"length":1,"stats":{"Line":1},"fn_name":null},{"line":442,"address":[4231296],"length":1,"stats":{"Line":1},"fn_name":null},{"line":443,"address":[4231318],"length":1,"stats":{"Line":0},"fn_name":null},{"line":445,"address":[4231311,4231328],"length":1,"stats":{"Line":2},"fn_name":null},{"line":448,"address":[4231409],"length":1,"stats":{"Line":1},"fn_name":null},{"line":449,"address":[4231521,4231482],"length":1,"stats":{"Line":1},"fn_name":null},{"line":450,"address":[4231586,4231505,4231556],"length":1,"stats":{"Line":1},"fn_name":null},{"line":455,"address":[4219701,4219696],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":459,"address":[4231607],"length":1,"stats":{"Line":1},"fn_name":null},{"line":460,"address":[4231624],"length":1,"stats":{"Line":1},"fn_name":null},{"line":461,"address":[4231645],"length":1,"stats":{"Line":1},"fn_name":null},{"line":462,"address":[4231871,4231685,4232032],"length":1,"stats":{"Line":2},"fn_name":null},{"line":463,"address":[4232044,4231894],"length":1,"stats":{"Line":1},"fn_name":null},{"line":468,"address":[4231818],"length":1,"stats":{"Line":1},"fn_name":null},{"line":469,"address":[4231831],"length":1,"stats":{"Line":1},"fn_name":null},{"line":470,"address":[4231839],"length":1,"stats":{"Line":1},"fn_name":null},{"line":471,"address":[4232333],"length":1,"stats":{"Line":1},"fn_name":null},{"line":472,"address":[4232647,4232368,4232492],"length":1,"stats":{"Line":2},"fn_name":null},{"line":473,"address":[4232659,4232515],"length":1,"stats":{"Line":1},"fn_name":null},{"line":512,"address":[4219728,4219733],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":516,"address":[4232951],"length":1,"stats":{"Line":1},"fn_name":null},{"line":517,"address":[4232968],"length":1,"stats":{"Line":1},"fn_name":null},{"line":518,"address":[4232989],"length":1,"stats":{"Line":1},"fn_name":null},{"line":519,"address":[4233377,4233029,4233215],"length":1,"stats":{"Line":2},"fn_name":null},{"line":520,"address":[4233238,4233389],"length":1,"stats":{"Line":1},"fn_name":null},{"line":525,"address":[4233162],"length":1,"stats":{"Line":1},"fn_name":null},{"line":526,"address":[4233175],"length":1,"stats":{"Line":1},"fn_name":null},{"line":527,"address":[4233183],"length":1,"stats":{"Line":1},"fn_name":null},{"line":528,"address":[4233678],"length":1,"stats":{"Line":1},"fn_name":null},{"line":529,"address":[4233837,4233713,4233993],"length":1,"stats":{"Line":2},"fn_name":null},{"line":530,"address":[4233860,4234005],"length":1,"stats":{"Line":1},"fn_name":null},{"line":539,"address":[4219760,4219765],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":541,"address":[4234295],"length":1,"stats":{"Line":1},"fn_name":null},{"line":542,"address":[4234312],"length":1,"stats":{"Line":1},"fn_name":null},{"line":543,"address":[4234333],"length":1,"stats":{"Line":1},"fn_name":null},{"line":544,"address":[4234394],"length":1,"stats":{"Line":1},"fn_name":null},{"line":545,"address":[4234415,4234586],"length":1,"stats":{"Line":1},"fn_name":null},{"line":546,"address":[4234526,4235052,4235213,4234928],"length":1,"stats":{"Line":3},"fn_name":null},{"line":547,"address":[4235075,4235225],"length":1,"stats":{"Line":1},"fn_name":null},{"line":552,"address":[4234999],"length":1,"stats":{"Line":1},"fn_name":null},{"line":553,"address":[4235012],"length":1,"stats":{"Line":1},"fn_name":null},{"line":554,"address":[4235020],"length":1,"stats":{"Line":1},"fn_name":null},{"line":555,"address":[4235550],"length":1,"stats":{"Line":1},"fn_name":null},{"line":556,"address":[4235611],"length":1,"stats":{"Line":1},"fn_name":null},{"line":557,"address":[4235632,4235803],"length":1,"stats":{"Line":1},"fn_name":null},{"line":558,"address":[4236326,4236487,4236145,4235743],"length":1,"stats":{"Line":3},"fn_name":null},{"line":559,"address":[4236349,4236499],"length":1,"stats":{"Line":1},"fn_name":null},{"line":564,"address":[4236211],"length":1,"stats":{"Line":1},"fn_name":null},{"line":565,"address":[4236252],"length":1,"stats":{"Line":1},"fn_name":null},{"line":566,"address":[4236840],"length":1,"stats":{"Line":1},"fn_name":null},{"line":567,"address":[4236981],"length":1,"stats":{"Line":1},"fn_name":null},{"line":568,"address":[4237221,4237050],"length":1,"stats":{"Line":1},"fn_name":null},{"line":569,"address":[4237563,4237795,4237161,4237960],"length":1,"stats":{"Line":3},"fn_name":null},{"line":570,"address":[4237818,4237972],"length":1,"stats":{"Line":1},"fn_name":null},{"line":575,"address":[4237637],"length":1,"stats":{"Line":1},"fn_name":null},{"line":576,"address":[4237662],"length":1,"stats":{"Line":1},"fn_name":null},{"line":577,"address":[4237702],"length":1,"stats":{"Line":1},"fn_name":null},{"line":578,"address":[4238313],"length":1,"stats":{"Line":1},"fn_name":null},{"line":579,"address":[4238454],"length":1,"stats":{"Line":1},"fn_name":null},{"line":580,"address":[4238694,4238523],"length":1,"stats":{"Line":1},"fn_name":null},{"line":581,"address":[4239233,4239000,4238634,4239074],"length":1,"stats":{"Line":3},"fn_name":null},{"line":582,"address":[4239245,4239097],"length":1,"stats":{"Line":1},"fn_name":null}],"covered":213,"coverable":217}]};
        var previousData = {"files":[{"path":["/","home","srv","hg","icefox","srht","icefox","oorandom","src","lib.rs"],"content":"//! A tiny, robust PRNG implementation.\n//!\n//! More specifically, it implements a single GOOD PRNG algorithm,\n//! which is currently a permuted congruential generator.  It has two\n//! implementations, one that returns `u32` and one that returns\n//! `u64`.  It also has functions that return floats or integer\n//! ranges.  And that's it.  What more do you need?\n//!\n//! For more info on PCG generators, see http://www.pcg-random.org/\n//!\n//! This was designed as a minimalist utility for video games.  No\n//! promises are made about its quality, and if you use it for\n//! cryptography you will get what you deserve.\n//!\n//! Works with `#![no_std]`, has no global state, no dependencies\n//! apart from some in the unit tests, and is generally neato.\n\n#![forbid(unsafe_code)]\n#![forbid(missing_docs)]\n#![forbid(missing_debug_implementations)]\n#![forbid(unused_results)]\n#![no_std]\nuse core::ops::Range;\n\n/// A PRNG producing a 32-bit output.\n///\n/// The current implementation is `PCG-XSH-RR`.\n#[derive(Copy, Clone, Debug, PartialEq)]\npub struct Rand32 {\n    state: u64,\n    inc: u64,\n}\n\nimpl Rand32 {\n    /// The default value for `increment`.\n    /// This is basically arbitrary, it comes from the\n    /// PCG reference C implementation:\n    /// https://github.com/imneme/pcg-c/blob/master/include/pcg_variants.h#L284\n    pub const DEFAULT_INC: u64 = 1442695040888963407;\n\n    /// This is the number that you have to Really Get Right.\n    ///\n    /// The value used here is from the PCG C implementation:\n    /// https://github.com/imneme/pcg-c/blob/master/include/pcg_variants.h#L278\n    pub(crate) const MULTIPLIER: u64 = 6364136223846793005;\n\n    /// Creates a new PRNG with the given seed and a default increment.\n    pub fn new(seed: u64) -\u003e Self {\n        Self::new_inc(seed, Self::DEFAULT_INC)\n    }\n\n    /// Creates a new PRNG.  The two inputs, `seed` and `increment`,\n    /// determine what you get; `increment` basically selects which\n    /// sequence of all those possible the PRNG will produce, and the\n    /// `seed` selects where in that sequence you start.\n    ///\n    /// Both are arbitrary; increment must be an odd number but this\n    /// handles that for you\n    pub fn new_inc(seed: u64, increment: u64) -\u003e Self {\n        let mut rng = Self {\n            state: 0,\n            inc: increment.wrapping_shl(1) | 1,\n        };\n        // This initialization song-and-dance is a little odd,\n        // but seems to be just how things go.\n        let _ = rng.rand_u32();\n        rng.state = rng.state.wrapping_add(seed);\n        let _ = rng.rand_u32();\n        rng\n    }\n\n    /// Returns the internal state of the PRNG.  This allows\n    /// you to save a PRNG and create a new one that will resume\n    /// from the same spot in the sequence.\n    pub fn state(\u0026self) -\u003e (u64, u64) {\n        (self.state, self.inc)\n    }\n\n    /// Creates a new PRNG from a saved state from `Rand32::state()`.\n    /// This is NOT quite the same as `new_inc()` because `new_inc()` does\n    /// a little extra setup work to initialize the state.\n    pub fn from_state(state: (u64, u64)) -\u003e Self {\n        let (state, inc) = state;\n        Self { state, inc }\n    }\n\n    /// Produces a random `u32` in the range `[0, u32::MAX]`.\n    pub fn rand_u32(\u0026mut self) -\u003e u32 {\n        let oldstate: u64 = self.state;\n        self.state = oldstate\n            .wrapping_mul(Self::MULTIPLIER)\n            .wrapping_add(self.inc);\n        let xorshifted: u32 = (((oldstate \u003e\u003e 18) ^ oldstate) \u003e\u003e 27) as u32;\n        let rot: u32 = (oldstate \u003e\u003e 59) as u32;\n        xorshifted.rotate_right(rot)\n    }\n\n    /// Produces a random `i32` in the range `[i32::MIN, i32::MAX]`.\n    pub fn rand_i32(\u0026mut self) -\u003e i32 {\n        self.rand_u32() as i32\n    }\n\n    /// Produces a random `f32` in the range `[0.0, 1.0)`.\n    pub fn rand_float(\u0026mut self) -\u003e f32 {\n        // This impl was taken more or less from `rand`, see\n        // \u003chttps://docs.rs/rand/0.7.0/src/rand/distributions/float.rs.html#104-117\u003e\n        // There MAY be better ways to do this, see:\n        // https://mumble.net/~campbell/2014/04/28/uniform-random-float\n        // https://mumble.net/~campbell/2014/04/28/random_real.c\n        // https://github.com/Lokathor/randomize/issues/34\n        const TOTAL_BITS: u32 = 32;\n        const PRECISION: u32 = core::f32::MANTISSA_DIGITS + 1;\n        const MANTISSA_SCALE: f32 = 1.0 / ((1u32 \u003c\u003c PRECISION) as f32);\n        let mut u = self.rand_u32();\n        u \u003e\u003e= TOTAL_BITS - PRECISION;\n        u as f32 * MANTISSA_SCALE\n    }\n\n    /// Produces a random within the given bounds.  Like any `Range`,\n    /// it includes the lower bound and excludes the upper one.\n    ///\n    /// This should be faster than `Self::rand() % end + start`, but the\n    /// real advantage is it's more convenient.  Requires that\n    /// `range.end \u003c= range.start`.\n    pub fn rand_range(\u0026mut self, range: Range\u003cu32\u003e) -\u003e u32 {\n        // This is harder to do well than it looks, it seems.  I don't\n        // trust Lokathor's implementation 'cause I don't understand\n        // it, so I went to numpy's, which points me to \"Lemire's\n        // rejection algorithm\": http://arxiv.org/abs/1805.10941\n        //\n        // Algorithms 3, 4 and 5 in that paper all seem fine modulo\n        // minor performance differences, so this is algorithm 5.\n        // It uses numpy's implementation, `buffered_bounded_lemire_uint32()`\n\n        debug_assert!(range.start \u003c range.end);\n        let range_starting_from_zero = 0..(range.end - range.start);\n\n        let s: u32 = range_starting_from_zero.end;\n        let mut m: u64 = u64::from(self.rand_u32()) * u64::from(s);\n        let mut leftover: u32 = (m \u0026 0xFFFF_FFFF) as u32;\n\n        if leftover \u003c s {\n            // TODO: verify the wrapping_neg() here\n            let threshold: u32 = s.wrapping_neg() % s;\n            while leftover \u003c threshold {\n                m = u64::from(self.rand_u32()).wrapping_mul(u64::from(s));\n                leftover = (m \u0026 0xFFFF_FFFF) as u32;\n            }\n        }\n        (m \u003e\u003e 32) as u32 + range.start\n    }\n}\n\n/// A PRNG producing a 64-bit output.\n///\n/// The current implementation is `PCG-XSH-RR`.\n// BUGGO: The recommended algorithm is PCG-XSL-RR?\n// See https://github.com/imneme/pcg-c/blob/master/include/pcg_variants.h#L2405\n// Not sure if it matters?\n#[derive(Copy, Clone, Debug, PartialEq)]\npub struct Rand64 {\n    state: u128,\n    inc: u128,\n}\n\nimpl Rand64 {\n    /// The default value for `increment`.\n    ///\n    /// The value used here is from the PCG default C implementation: http://www.pcg-random.org/download.html\n    pub const DEFAULT_INC: u128 = 0x2FE0E169_FFBD06E3_5BC307BD_4D2F814F;\n\n    /// This is the number that you have to Really Get Right.\n    ///\n    /// The value used here is from the PCG C implementation:\n    /// https://github.com/imneme/pcg-c/blob/master/include/pcg_variants.h#L288\n    pub(crate) const MULTIPLIER: u128 = 47026247687942121848144207491837523525;\n\n    /// Creates a new PRNG with the given seed and a default increment.\n    pub fn new(seed: u128) -\u003e Self {\n        Self::new_inc(seed, Self::DEFAULT_INC)\n    }\n\n    /// Same as `Rand32::new_inc()`\n    fn new_inc(seed: u128, increment: u128) -\u003e Self {\n        let mut rng = Self {\n            state: 0,\n            inc: increment.wrapping_shl(1) | 1,\n        };\n        let _ = rng.rand_u64();\n        rng.state = rng.state.wrapping_add(seed);\n        let _ = rng.rand_u64();\n        rng\n    }\n\n    /// Returns the internal state of the PRNG.  This allows\n    /// you to save a PRNG and create a new one that will resume\n    /// from the same spot in the sequence.\n    pub fn state(\u0026self) -\u003e (u128, u128) {\n        (self.state, self.inc)\n    }\n\n    /// Creates a new PRNG from a saved state from `Rand32::state()`.\n    /// This is NOT quite the same as `new_inc()` because `new_inc()` does\n    /// a little extra setup work to initialize the state.\n    pub fn from_state(state: (u128, u128)) -\u003e Self {\n        let (state, inc) = state;\n        Self { state, inc }\n    }\n\n    /// Produces a random `u64` in the range`[0, u64::MAX]`.\n    pub fn rand_u64(\u0026mut self) -\u003e u64 {\n        let oldstate: u128 = self.state;\n        self.state = oldstate\n            .wrapping_mul(Self::MULTIPLIER)\n            .wrapping_add(self.inc);\n        let xorshifted: u64 = (((oldstate \u003e\u003e 29) ^ oldstate) \u003e\u003e 58) as u64;\n        let rot: u32 = (oldstate \u003e\u003e 122) as u32;\n        xorshifted.rotate_right(rot)\n    }\n\n    /// Produces a random `i64` in the range `[i64::MIN, i64::MAX]`.\n    pub fn rand_i64(\u0026mut self) -\u003e i64 {\n        self.rand_u64() as i64\n    }\n\n    /// Produces a random `f64` in the range `[0.0, 1.0)`.\n    pub fn rand_float(\u0026mut self) -\u003e f64 {\n        const TOTAL_BITS: u32 = 64;\n        const PRECISION: u32 = core::f64::MANTISSA_DIGITS + 1;\n        const MANTISSA_SCALE: f64 = 1.0 / ((1u64 \u003c\u003c PRECISION) as f64);\n        let mut u = self.rand_u64();\n        u \u003e\u003e= TOTAL_BITS - PRECISION;\n        u as f64 * MANTISSA_SCALE\n    }\n\n    /// Produces a random within the given bounds.  Like any `Range`,\n    /// it includes the lower bound and excludes the upper one.\n    ///\n    /// This should be faster than `Self::rand() % end + start`, but the\n    /// real advantage is it's more convenient.  Requires that\n    /// `range.end \u003c= range.start`.\n    pub fn rand_range(\u0026mut self, range: Range\u003cu64\u003e) -\u003e u64 {\n        // Same as `Rand32::rand_range()`\n        debug_assert!(range.start \u003c range.end);\n        let range_starting_from_zero = 0..(range.end - range.start);\n\n        let s: u64 = range_starting_from_zero.end;\n        let mut m: u128 = u128::from(self.rand_u64()) * u128::from(s);\n        let mut leftover: u64 = (m \u0026 0xFFFFFFFF_FFFFFFFF) as u64;\n\n        if leftover \u003c s {\n            // TODO: Verify the wrapping_negate() here\n            let threshold: u64 = s.wrapping_neg() % s;\n            while leftover \u003c threshold {\n                m = u128::from(self.rand_u64()) * u128::from(s);\n                leftover = (m \u0026 0xFFFFFFFF_FFFFFFFF) as u64;\n            }\n        }\n        (m.wrapping_shr(64)) as u64 + range.start\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use randomize::{self, PCG32, PCG64};\n\n    #[test]\n    fn test_rand32_vs_randomize() {\n        // Generate some random numbers and validate them against\n        // a known-good generator.\n        {\n            let seed = 54321;\n            let mut r1 = Rand32::new(seed);\n            let mut r2 = PCG32::seed(seed, Rand32::DEFAULT_INC);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u32(), r2.next_u32());\n                assert_eq!(r1.rand_i32(), r2.next_u32() as i32);\n            }\n        }\n\n        {\n            let seed = 3141592653;\n            let inc = 0xDEADBEEF;\n            let mut r1 = Rand32::new_inc(seed, inc);\n            let mut r2 = PCG32::seed(seed, inc);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u32(), r2.next_u32());\n                assert_eq!(r1.rand_i32(), r2.next_u32() as i32);\n            }\n        }\n    }\n\n    #[test]\n    fn test_rand64_vs_randomize() {\n        // Generate some random numbers and validate them against\n        // a known-good generator.\n        {\n            let seed = 54321;\n            let mut r1 = Rand64::new(seed);\n            let mut r2 = PCG64::seed(seed, Rand64::DEFAULT_INC);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u64(), r2.next_u64());\n                assert_eq!(r1.rand_i64(), r2.next_u64() as i64);\n            }\n        }\n\n        {\n            let seed = 3141592653;\n            let inc = 0xDEADBEEF;\n            let mut r1 = Rand64::new_inc(seed, inc);\n            let mut r2 = PCG64::seed(seed, inc);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u64(), r2.next_u64());\n                assert_eq!(r1.rand_i64(), r2.next_u64() as i64);\n            }\n        }\n    }\n\n    #[test]\n    fn test_float32() {\n        {\n            let seed = 2718281828;\n            let mut r1 = Rand32::new(seed);\n            let mut r2 = PCG32::seed(seed, Rand32::DEFAULT_INC);\n            for _ in 0..1000 {\n                // First just make sure they both work with randomize's\n                // f32 conversion function -- sanity checks.\n                let i1 = r1.rand_u32();\n                let i2 = r2.next_u32();\n                assert_eq!(i1, i2);\n                let f1 = randomize::f32_half_open_right(i1);\n                let f2 = randomize::f32_half_open_right(i2);\n                // We can directly compare floats 'cause we do no math, it's\n                // literally the same bitwise algorithm with the same inputs.\n                assert_eq!(f1, f2);\n\n                // Make sure result is in [0.0, 1.0)\n                assert!(f1 \u003e= 0.0);\n                assert!(f1 \u003c 1.0);\n            }\n\n            // At least make sure our float's from rand_float() are in the valid range.\n            for _ in 0..1000 {\n                let f1 = r1.rand_float();\n                assert!(f1 \u003e= 0.0);\n                assert!(f1 \u003c 1.0);\n            }\n\n            /*\n            TODO: Randomize changed its int-to-float conversion functions and now they don't\n            match ours.\n                        for _ in 0..1000 {\n                            // Now make sure our own float conversion function works.\n                            let f1 = r1.rand_float();\n                            //let f2 = randomize::f32_half_open_right(r2.next_u32());\n                            let f2 = randomize::f32_open(r2.next_u32());\n                            assert_eq!(f1, f2);\n                            assert!(f1 \u003e= 0.0);\n                            assert!(f1 \u003c 1.0);\n                        }\n                         */\n        }\n    }\n\n    #[test]\n    fn test_float64() {\n        {\n            let seed = 2718281828;\n            let mut r1 = Rand64::new(seed);\n            let mut r2 = PCG64::seed(seed, Rand64::DEFAULT_INC);\n            for _ in 0..1000 {\n                // First just make sure they both work with randomize's\n                // f64 conversion function -- sanity checks.\n                let i1 = r1.rand_u64();\n                let i2 = r2.next_u64();\n                assert_eq!(i1, i2);\n                let f1 = randomize::f64_half_open_right(i1);\n                let f2 = randomize::f64_half_open_right(i2);\n                // We can directly compare floats 'cause we do no math, it's\n                // literally the same bitwise algorithm with the same inputs.\n                assert_eq!(f1, f2);\n\n                // Make sure result is in [0.0, 1.0)\n                assert!(f1 \u003e= 0.0);\n                assert!(f1 \u003c 1.0);\n            }\n\n            // At least make sure our float's from rand_float() are in the valid range.\n            for _ in 0..1000 {\n                let f1 = r1.rand_float();\n                assert!(f1 \u003e= 0.0);\n                assert!(f1 \u003c 1.0);\n            }\n\n            /*\n            TODO: Randomize changed its int-to-float conversion functions and now they don't\n            match ours.\n                        for _ in 0..1000 {\n                            // Now make sure our own float conversion function works.\n                            let f1 = r1.rand_float();\n                            //let f2 = randomize::f32_half_open_right(r2.next_u32());\n                            let f2 = randomize::f32_open(r2.next_u32());\n                            assert_eq!(f1, f2);\n                            assert!(f1 \u003e= 0.0);\n                            assert!(f1 \u003c 1.0);\n                        }\n                         */\n        }\n    }\n\n    #[test]\n    fn test_randrange32() {\n        // Make sure ranges are valid and in the given range\n        let seed = 2342_3141;\n        let mut r1 = Rand32::new(seed);\n        for _ in 0..1000 {\n            // Generate our bounds at random\n            let a = r1.rand_u32();\n            let b = r1.rand_u32();\n            if a == b {\n                continue;\n            }\n            let (low, high) = if a \u003c b { (a, b) } else { (b, a) };\n\n            // Get a number in that range\n            let in_range = r1.rand_range(low..high);\n            assert!(in_range \u003e= low);\n            assert!(in_range \u003c high);\n        }\n    }\n\n    #[test]\n    fn test_randrange64() {\n        // Make sure ranges are valid and in the given range\n        let seed = 2342_2718;\n        let mut r1 = Rand64::new(seed);\n        for _ in 0..1000 {\n            // Generate our bounds at random\n            let a = r1.rand_u64();\n            let b = r1.rand_u64();\n            if a == b {\n                continue;\n            }\n            let (low, high) = if a \u003c b { (a, b) } else { (b, a) };\n\n            // Get a number in that range\n            let in_range = r1.rand_range(low..high);\n            assert!(in_range \u003e= low);\n            assert!(in_range \u003c high);\n        }\n    }\n\n    #[test]\n    fn test_rand32_vs_rand() {\n        use rand_core::RngCore;\n        use rand_pcg;\n        {\n            let seed = 54321;\n            let mut r1 = Rand32::new(seed);\n            let mut r2 = rand_pcg::Pcg32::new(seed, Rand32::DEFAULT_INC);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u32(), r2.next_u32());\n            }\n        }\n\n        {\n            let seed = 3141592653;\n            let inc = 0xDEADBEEF;\n            let mut r1 = Rand32::new_inc(seed, inc);\n            let mut r2 = rand_pcg::Pcg32::new(seed, inc);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u32(), r2.next_u32());\n            }\n        }\n    }\n\n    // This doesn't work 'cause for 64-bit output `rand` uses\n    // PCG-XSL-RR\n    // and we use\n    // PCG-XSH-RR\n    /*\n        #[test]\n        fn test_rand64_vs_rand() {\n            use rand_pcg;\n            use rand_core::RngCore;\n            {\n                let seed = 54321;\n                let mut r1 = Rand64::new(seed);\n                let mut r2 = rand_pcg::Pcg64::new(seed, Rand64::DEFAULT_INC);\n                for _ in 0..1000 {\n                    assert_eq!(r1.rand(), r2.next_u64());\n                }\n            }\n\n            {\n                let seed = 3141592653;\n                let inc = 0xDEADBEEF;\n                let mut r1 = Rand64::new_inc(seed, inc);\n                let mut r2 = rand_pcg::Pcg64::new(seed, inc);\n                for _ in 0..1000 {\n                    assert_eq!(r1.rand(), r2.next_u64());\n                }\n            }\n        }\n    */\n\n    // Test vs. random-fast-rng, which I will call rfr\n    // rfr's float conversion uses yet a different algorithm\n    // than ours, so we can't really check that.\n    #[test]\n    fn test_rand32_vs_rfr() {\n        use random_fast_rng as rfr;\n        use rfr::Random;\n        {\n            let seed = 54321;\n            let mut r1 = Rand32::new(seed);\n            let mut r2 = rfr::FastRng::seed(seed, Rand32::DEFAULT_INC);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u32(), r2.get_u32());\n            }\n        }\n\n        {\n            let seed = 3141592653;\n            let inc = 0xDEADBEEF;\n            let mut r1 = Rand32::new_inc(seed, inc);\n            let mut r2 = rfr::FastRng::seed(seed, inc);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u32(), r2.get_u32());\n            }\n        }\n    }\n\n    /// Make sure that saving a RNG state and restoring\n    /// it works.\n    /// See https://todo.sr.ht/~icefox/oorandom/1\n    #[test]\n    fn test_save_restore() {\n        {\n            let seed = 54321;\n            let mut r1 = Rand32::new(seed);\n            let s1 = r1.state();\n            let mut r2 = Rand32::from_state(s1);\n            assert_eq!(r1, r2);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u32(), r2.rand_u32());\n            }\n        }\n\n        {\n            let seed = 3141592653;\n            let inc = 0xDEADBEEF;\n            let mut r1 = Rand32::new_inc(seed, inc);\n            let s1 = r1.state();\n            let mut r2 = Rand32::from_state(s1);\n            assert_eq!(r1, r2);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u32(), r2.rand_u32());\n            }\n        }\n\n        {\n            let seed = 54321;\n            let mut r1 = Rand64::new(seed);\n            let s1 = r1.state();\n            let mut r2 = Rand64::from_state(s1);\n            assert_eq!(r1, r2);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u64(), r2.rand_u64());\n            }\n        }\n\n        {\n            let seed = 3141592653;\n            let inc = 0xDEADBEEF;\n            let mut r1 = Rand64::new_inc(seed, inc);\n            let s1 = r1.state();\n            let mut r2 = Rand64::from_state(s1);\n            assert_eq!(r1, r2);\n            for _ in 0..1000 {\n                assert_eq!(r1.rand_u64(), r2.rand_u64());\n            }\n        }\n    }\n}\n","traces":[{"line":48,"address":[4213216],"length":1,"stats":{"Line":4},"fn_name":"new"},{"line":49,"address":[4213225],"length":1,"stats":{"Line":4},"fn_name":null},{"line":59,"address":[4213264],"length":1,"stats":{"Line":4},"fn_name":"new_inc"},{"line":62,"address":[4213283],"length":1,"stats":{"Line":4},"fn_name":null},{"line":66,"address":[4213326],"length":1,"stats":{"Line":4},"fn_name":null},{"line":67,"address":[4213336],"length":1,"stats":{"Line":4},"fn_name":null},{"line":68,"address":[4213364],"length":1,"stats":{"Line":5},"fn_name":null},{"line":69,"address":[4213374],"length":1,"stats":{"Line":4},"fn_name":null},{"line":75,"address":[4213392],"length":1,"stats":{"Line":1},"fn_name":"state"},{"line":76,"address":[4213401],"length":1,"stats":{"Line":1},"fn_name":null},{"line":82,"address":[4213440],"length":1,"stats":{"Line":1},"fn_name":"from_state"},{"line":83,"address":[4213454],"length":1,"stats":{"Line":1},"fn_name":null},{"line":88,"address":[4213488],"length":1,"stats":{"Line":4},"fn_name":"rand_u32"},{"line":89,"address":[4213497],"length":1,"stats":{"Line":5},"fn_name":null},{"line":90,"address":[4213552,4213510],"length":1,"stats":{"Line":8},"fn_name":null},{"line":91,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":92,"address":[4213543],"length":1,"stats":{"Line":5},"fn_name":null},{"line":93,"address":[4213580],"length":1,"stats":{"Line":5},"fn_name":null},{"line":94,"address":[4213627],"length":1,"stats":{"Line":4},"fn_name":null},{"line":95,"address":[4213655],"length":1,"stats":{"Line":5},"fn_name":null},{"line":99,"address":[4213680],"length":1,"stats":{"Line":1},"fn_name":"rand_i32"},{"line":100,"address":[4213689],"length":1,"stats":{"Line":1},"fn_name":null},{"line":104,"address":[4213712],"length":1,"stats":{"Line":1},"fn_name":"rand_float"},{"line":114,"address":[4213721],"length":1,"stats":{"Line":1},"fn_name":null},{"line":115,"address":[4213730],"length":1,"stats":{"Line":1},"fn_name":null},{"line":116,"address":[4213757],"length":1,"stats":{"Line":1},"fn_name":null},{"line":125,"address":[4213792],"length":1,"stats":{"Line":1},"fn_name":"rand_range"},{"line":135,"address":[4213821,4213873],"length":1,"stats":{"Line":1},"fn_name":null},{"line":136,"address":[4214282,4213853,4213903],"length":1,"stats":{"Line":2},"fn_name":null},{"line":138,"address":[4213919],"length":1,"stats":{"Line":1},"fn_name":null},{"line":139,"address":[4213939,4214312],"length":1,"stats":{"Line":1},"fn_name":null},{"line":140,"address":[4214021],"length":1,"stats":{"Line":1},"fn_name":null},{"line":142,"address":[4214127,4214045],"length":1,"stats":{"Line":2},"fn_name":null},{"line":144,"address":[4214342,4214063],"length":1,"stats":{"Line":1},"fn_name":null},{"line":145,"address":[4214118,4214224],"length":1,"stats":{"Line":2},"fn_name":null},{"line":146,"address":[4214134],"length":1,"stats":{"Line":1},"fn_name":null},{"line":147,"address":[4214204],"length":1,"stats":{"Line":1},"fn_name":null},{"line":150,"address":[4214402,4214372,4214226],"length":1,"stats":{"Line":1},"fn_name":null},{"line":179,"address":[4214416],"length":1,"stats":{"Line":1},"fn_name":"new"},{"line":180,"address":[4214463],"length":1,"stats":{"Line":1},"fn_name":null},{"line":184,"address":[4214576],"length":1,"stats":{"Line":1},"fn_name":"new_inc"},{"line":187,"address":[4214620],"length":1,"stats":{"Line":1},"fn_name":null},{"line":189,"address":[4214701],"length":1,"stats":{"Line":1},"fn_name":null},{"line":190,"address":[4214711],"length":1,"stats":{"Line":1},"fn_name":null},{"line":191,"address":[4214766],"length":1,"stats":{"Line":1},"fn_name":null},{"line":192,"address":[4214776],"length":1,"stats":{"Line":1},"fn_name":null},{"line":198,"address":[4214832],"length":1,"stats":{"Line":1},"fn_name":"state"},{"line":199,"address":[4214844],"length":1,"stats":{"Line":1},"fn_name":null},{"line":205,"address":[4214928],"length":1,"stats":{"Line":1},"fn_name":"from_state"},{"line":206,"address":[4214955],"length":1,"stats":{"Line":1},"fn_name":null},{"line":211,"address":[4215040],"length":1,"stats":{"Line":1},"fn_name":"rand_u64"},{"line":212,"address":[4215052],"length":1,"stats":{"Line":1},"fn_name":null},{"line":213,"address":[4215164,4215097],"length":1,"stats":{"Line":2},"fn_name":null},{"line":214,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":215,"address":[4215146],"length":1,"stats":{"Line":1},"fn_name":null},{"line":216,"address":[4215211],"length":1,"stats":{"Line":1},"fn_name":null},{"line":217,"address":[4215301],"length":1,"stats":{"Line":1},"fn_name":null},{"line":218,"address":[4215338],"length":1,"stats":{"Line":2},"fn_name":null},{"line":222,"address":[4215376],"length":1,"stats":{"Line":1},"fn_name":"rand_i64"},{"line":223,"address":[4215385],"length":1,"stats":{"Line":1},"fn_name":null},{"line":227,"address":[4215408],"length":1,"stats":{"Line":1},"fn_name":"rand_float"},{"line":231,"address":[4215417],"length":1,"stats":{"Line":1},"fn_name":null},{"line":232,"address":[4215427],"length":1,"stats":{"Line":1},"fn_name":null},{"line":233,"address":[4215457],"length":1,"stats":{"Line":1},"fn_name":null},{"line":242,"address":[4215520],"length":1,"stats":{"Line":1},"fn_name":"rand_range"},{"line":244,"address":[4215551,4215628],"length":1,"stats":{"Line":1},"fn_name":null},{"line":245,"address":[4216411,4215658,4215603],"length":1,"stats":{"Line":2},"fn_name":null},{"line":247,"address":[4215686],"length":1,"stats":{"Line":1},"fn_name":null},{"line":248,"address":[4216441,4215718],"length":1,"stats":{"Line":1},"fn_name":null},{"line":249,"address":[4215965],"length":1,"stats":{"Line":1},"fn_name":null},{"line":251,"address":[4216094,4215989],"length":1,"stats":{"Line":2},"fn_name":null},{"line":253,"address":[4216012,4216471],"length":1,"stats":{"Line":1},"fn_name":null},{"line":254,"address":[4216084,4216331],"length":1,"stats":{"Line":2},"fn_name":null},{"line":255,"address":[4216107,4216501],"length":1,"stats":{"Line":1},"fn_name":null},{"line":256,"address":[4216315],"length":1,"stats":{"Line":1},"fn_name":null},{"line":259,"address":[4216531,4216561,4216336],"length":1,"stats":{"Line":1},"fn_name":null},{"line":269,"address":[4219504,4219509],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":273,"address":[4222375],"length":1,"stats":{"Line":1},"fn_name":null},{"line":274,"address":[4222392],"length":1,"stats":{"Line":1},"fn_name":null},{"line":275,"address":[4222428],"length":1,"stats":{"Line":1},"fn_name":null},{"line":276,"address":[4223285,4222635,4222449],"length":1,"stats":{"Line":2},"fn_name":null},{"line":277,"address":[4222658,4222828],"length":1,"stats":{"Line":1},"fn_name":null},{"line":278,"address":[4222796,4223153,4223290],"length":1,"stats":{"Line":2},"fn_name":null},{"line":283,"address":[4222582],"length":1,"stats":{"Line":1},"fn_name":null},{"line":284,"address":[4222595],"length":1,"stats":{"Line":1},"fn_name":null},{"line":285,"address":[4222603],"length":1,"stats":{"Line":1},"fn_name":null},{"line":286,"address":[4223635],"length":1,"stats":{"Line":1},"fn_name":null},{"line":287,"address":[4224394,4223792,4223656],"length":1,"stats":{"Line":2},"fn_name":null},{"line":288,"address":[4223985,4223815],"length":1,"stats":{"Line":1},"fn_name":null},{"line":289,"address":[4224274,4223953,4224399],"length":1,"stats":{"Line":2},"fn_name":null},{"line":295,"address":[4219541,4219536],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":299,"address":[4224695],"length":1,"stats":{"Line":1},"fn_name":null},{"line":300,"address":[4224736],"length":1,"stats":{"Line":1},"fn_name":null},{"line":301,"address":[4224842],"length":1,"stats":{"Line":1},"fn_name":null},{"line":302,"address":[4225865,4224911,4225205],"length":1,"stats":{"Line":2},"fn_name":null},{"line":303,"address":[4225228,4225403],"length":1,"stats":{"Line":1},"fn_name":null},{"line":304,"address":[4225728,4225870,4225370],"length":1,"stats":{"Line":2},"fn_name":null},{"line":309,"address":[4225047],"length":1,"stats":{"Line":1},"fn_name":null},{"line":310,"address":[4225072],"length":1,"stats":{"Line":1},"fn_name":null},{"line":311,"address":[4225112],"length":1,"stats":{"Line":1},"fn_name":null},{"line":312,"address":[4226235],"length":1,"stats":{"Line":1},"fn_name":null},{"line":313,"address":[4227082,4226470,4226334],"length":1,"stats":{"Line":2},"fn_name":null},{"line":314,"address":[4226668,4226493],"length":1,"stats":{"Line":1},"fn_name":null},{"line":315,"address":[4227087,4226635,4226957],"length":1,"stats":{"Line":2},"fn_name":null},{"line":321,"address":[4219568,4219573],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":323,"address":[4227388],"length":1,"stats":{"Line":1},"fn_name":null},{"line":324,"address":[4227396],"length":1,"stats":{"Line":1},"fn_name":null},{"line":325,"address":[4227435],"length":1,"stats":{"Line":1},"fn_name":null},{"line":326,"address":[4227456,4227644,4228624],"length":1,"stats":{"Line":2},"fn_name":null},{"line":329,"address":[4227667],"length":1,"stats":{"Line":1},"fn_name":null},{"line":330,"address":[4227687],"length":1,"stats":{"Line":1},"fn_name":null},{"line":331,"address":[4227838,4227707],"length":1,"stats":{"Line":1},"fn_name":null},{"line":332,"address":[4227805],"length":1,"stats":{"Line":1},"fn_name":null},{"line":333,"address":[4228127],"length":1,"stats":{"Line":1},"fn_name":null},{"line":336,"address":[4228148,4228280],"length":1,"stats":{"Line":1},"fn_name":null},{"line":339,"address":[4228247,4228594],"length":1,"stats":{"Line":1},"fn_name":null},{"line":340,"address":[4228629,4228575],"length":1,"stats":{"Line":1},"fn_name":null},{"line":344,"address":[4228740,4228870,4228666,4227584],"length":1,"stats":{"Line":3},"fn_name":null},{"line":345,"address":[4228763],"length":1,"stats":{"Line":1},"fn_name":null},{"line":346,"address":[4228791,4228840],"length":1,"stats":{"Line":1},"fn_name":null},{"line":347,"address":[4228875,4228826,4228905],"length":1,"stats":{"Line":1},"fn_name":null},{"line":367,"address":[4219605,4219600],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":369,"address":[4228924],"length":1,"stats":{"Line":1},"fn_name":null},{"line":370,"address":[4228956],"length":1,"stats":{"Line":1},"fn_name":null},{"line":371,"address":[4229065],"length":1,"stats":{"Line":1},"fn_name":null},{"line":372,"address":[4229134,4229322,4230317],"length":1,"stats":{"Line":2},"fn_name":null},{"line":375,"address":[4229345],"length":1,"stats":{"Line":1},"fn_name":null},{"line":376,"address":[4229366],"length":1,"stats":{"Line":1},"fn_name":null},{"line":377,"address":[4229387,4229521],"length":1,"stats":{"Line":1},"fn_name":null},{"line":378,"address":[4229487],"length":1,"stats":{"Line":1},"fn_name":null},{"line":379,"address":[4229816],"length":1,"stats":{"Line":1},"fn_name":null},{"line":382,"address":[4229838,4229972],"length":1,"stats":{"Line":1},"fn_name":null},{"line":385,"address":[4229938,4230287],"length":1,"stats":{"Line":1},"fn_name":null},{"line":386,"address":[4230267,4230322],"length":1,"stats":{"Line":1},"fn_name":null},{"line":390,"address":[4229262,4230359,4230433,4230565],"length":1,"stats":{"Line":3},"fn_name":null},{"line":391,"address":[4230456],"length":1,"stats":{"Line":1},"fn_name":null},{"line":392,"address":[4230535,4230484],"length":1,"stats":{"Line":1},"fn_name":null},{"line":393,"address":[4230570,4230600,4230520],"length":1,"stats":{"Line":1},"fn_name":null},{"line":413,"address":[4219637,4219632],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":415,"address":[4230615],"length":1,"stats":{"Line":1},"fn_name":null},{"line":416,"address":[4230629],"length":1,"stats":{"Line":1},"fn_name":null},{"line":417,"address":[4230738,4230988,4230644],"length":1,"stats":{"Line":2},"fn_name":null},{"line":419,"address":[4230752],"length":1,"stats":{"Line":1},"fn_name":null},{"line":420,"address":[4230770],"length":1,"stats":{"Line":1},"fn_name":null},{"line":421,"address":[4230796],"length":1,"stats":{"Line":1},"fn_name":null},{"line":422,"address":[4230814],"length":1,"stats":{"Line":0},"fn_name":null},{"line":424,"address":[4230808,4230820],"length":1,"stats":{"Line":2},"fn_name":null},{"line":427,"address":[4230869],"length":1,"stats":{"Line":1},"fn_name":null},{"line":428,"address":[4230958,4230922],"length":1,"stats":{"Line":1},"fn_name":null},{"line":429,"address":[4231023,4230943,4230993],"length":1,"stats":{"Line":2},"fn_name":null},{"line":434,"address":[4219669,4219664],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":436,"address":[4231031],"length":1,"stats":{"Line":1},"fn_name":null},{"line":437,"address":[4231069],"length":1,"stats":{"Line":1},"fn_name":null},{"line":438,"address":[4231217,4231114,4231551],"length":1,"stats":{"Line":2},"fn_name":null},{"line":440,"address":[4231240],"length":1,"stats":{"Line":1},"fn_name":null},{"line":441,"address":[4231263],"length":1,"stats":{"Line":1},"fn_name":null},{"line":442,"address":[4231296],"length":1,"stats":{"Line":1},"fn_name":null},{"line":443,"address":[4231318],"length":1,"stats":{"Line":0},"fn_name":null},{"line":445,"address":[4231328,4231311],"length":1,"stats":{"Line":2},"fn_name":null},{"line":448,"address":[4231409],"length":1,"stats":{"Line":1},"fn_name":null},{"line":449,"address":[4231482,4231521],"length":1,"stats":{"Line":1},"fn_name":null},{"line":450,"address":[4231586,4231505,4231556],"length":1,"stats":{"Line":1},"fn_name":null},{"line":455,"address":[4219701,4219696],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":459,"address":[4231607],"length":1,"stats":{"Line":1},"fn_name":null},{"line":460,"address":[4231624],"length":1,"stats":{"Line":1},"fn_name":null},{"line":461,"address":[4231645],"length":1,"stats":{"Line":1},"fn_name":null},{"line":462,"address":[4232032,4231685,4231871],"length":1,"stats":{"Line":2},"fn_name":null},{"line":463,"address":[4231894,4232044],"length":1,"stats":{"Line":1},"fn_name":null},{"line":468,"address":[4231818],"length":1,"stats":{"Line":1},"fn_name":null},{"line":469,"address":[4231831],"length":1,"stats":{"Line":1},"fn_name":null},{"line":470,"address":[4231839],"length":1,"stats":{"Line":1},"fn_name":null},{"line":471,"address":[4232333],"length":1,"stats":{"Line":1},"fn_name":null},{"line":472,"address":[4232492,4232368,4232647],"length":1,"stats":{"Line":2},"fn_name":null},{"line":473,"address":[4232659,4232515],"length":1,"stats":{"Line":1},"fn_name":null},{"line":512,"address":[4219733,4219728],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":516,"address":[4232951],"length":1,"stats":{"Line":1},"fn_name":null},{"line":517,"address":[4232968],"length":1,"stats":{"Line":1},"fn_name":null},{"line":518,"address":[4232989],"length":1,"stats":{"Line":1},"fn_name":null},{"line":519,"address":[4233029,4233377,4233215],"length":1,"stats":{"Line":2},"fn_name":null},{"line":520,"address":[4233389,4233238],"length":1,"stats":{"Line":1},"fn_name":null},{"line":525,"address":[4233162],"length":1,"stats":{"Line":1},"fn_name":null},{"line":526,"address":[4233175],"length":1,"stats":{"Line":1},"fn_name":null},{"line":527,"address":[4233183],"length":1,"stats":{"Line":1},"fn_name":null},{"line":528,"address":[4233678],"length":1,"stats":{"Line":1},"fn_name":null},{"line":529,"address":[4233713,4233837,4233993],"length":1,"stats":{"Line":2},"fn_name":null},{"line":530,"address":[4234005,4233860],"length":1,"stats":{"Line":1},"fn_name":null},{"line":539,"address":[4219760,4219765],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":541,"address":[4234295],"length":1,"stats":{"Line":1},"fn_name":null},{"line":542,"address":[4234312],"length":1,"stats":{"Line":1},"fn_name":null},{"line":543,"address":[4234333],"length":1,"stats":{"Line":1},"fn_name":null},{"line":544,"address":[4234394],"length":1,"stats":{"Line":1},"fn_name":null},{"line":545,"address":[4234586,4234415],"length":1,"stats":{"Line":1},"fn_name":null},{"line":546,"address":[4234928,4234526,4235213,4235052],"length":1,"stats":{"Line":3},"fn_name":null},{"line":547,"address":[4235075,4235225],"length":1,"stats":{"Line":1},"fn_name":null},{"line":552,"address":[4234999],"length":1,"stats":{"Line":1},"fn_name":null},{"line":553,"address":[4235012],"length":1,"stats":{"Line":1},"fn_name":null},{"line":554,"address":[4235020],"length":1,"stats":{"Line":1},"fn_name":null},{"line":555,"address":[4235550],"length":1,"stats":{"Line":1},"fn_name":null},{"line":556,"address":[4235611],"length":1,"stats":{"Line":1},"fn_name":null},{"line":557,"address":[4235803,4235632],"length":1,"stats":{"Line":1},"fn_name":null},{"line":558,"address":[4236487,4236326,4236145,4235743],"length":1,"stats":{"Line":3},"fn_name":null},{"line":559,"address":[4236349,4236499],"length":1,"stats":{"Line":1},"fn_name":null},{"line":564,"address":[4236211],"length":1,"stats":{"Line":1},"fn_name":null},{"line":565,"address":[4236252],"length":1,"stats":{"Line":1},"fn_name":null},{"line":566,"address":[4236840],"length":1,"stats":{"Line":1},"fn_name":null},{"line":567,"address":[4236981],"length":1,"stats":{"Line":1},"fn_name":null},{"line":568,"address":[4237050,4237221],"length":1,"stats":{"Line":1},"fn_name":null},{"line":569,"address":[4237795,4237161,4237563,4237960],"length":1,"stats":{"Line":3},"fn_name":null},{"line":570,"address":[4237818,4237972],"length":1,"stats":{"Line":1},"fn_name":null},{"line":575,"address":[4237637],"length":1,"stats":{"Line":1},"fn_name":null},{"line":576,"address":[4237662],"length":1,"stats":{"Line":1},"fn_name":null},{"line":577,"address":[4237702],"length":1,"stats":{"Line":1},"fn_name":null},{"line":578,"address":[4238313],"length":1,"stats":{"Line":1},"fn_name":null},{"line":579,"address":[4238454],"length":1,"stats":{"Line":1},"fn_name":null},{"line":580,"address":[4238694,4238523],"length":1,"stats":{"Line":1},"fn_name":null},{"line":581,"address":[4239233,4239074,4238634,4239000],"length":1,"stats":{"Line":3},"fn_name":null},{"line":582,"address":[4239245,4239097],"length":1,"stats":{"Line":1},"fn_name":null}],"covered":213,"coverable":217}]};
    </script>
    <script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
    <script>const e = React.createElement;

function pathToString(path) {
  if (path[0] === '/') {
    return '/' + path.slice(1).join('/');
  } else {
    return path.join('/');
  }
}

function findCommonPath(files) {
  if (!files || !files.length) {
    return [];
  }

  function isPrefix(arr, prefix) {
    if (arr.length < prefix.length) {
      return false;
    }
    for (let i = prefix.length - 1; i >= 0; --i) {
      if (arr[i] !== prefix[i]) {
        return false;
      }
    }
    return true;
  }

  let commonPath = files[0].path.slice(0, -1);
  while (commonPath.length) {
    if (files.every(file => isPrefix(file.path, commonPath))) {
      break;
    }
    commonPath.pop();
  }
  return commonPath;
}

function findFolders(files) {
  if (!files || !files.length) {
    return [];
  }

  let folders = files.filter(file => file.path.length > 1).map(file => file.path[0]);
  folders = [...new Set(folders)]; // unique
  folders.sort();

  folders = folders.map(folder => {
    let filesInFolder = files
      .filter(file => file.path[0] === folder)
      .map(file => ({
        ...file,
        path: file.path.slice(1),
        parent: [...file.parent, file.path[0]],
      }));

    const children = findFolders(filesInFolder); // recursion

    return {
      is_folder: true,
      path: [folder],
      parent: files[0].parent,
      children,
      covered: children.reduce((sum, file) => sum + file.covered, 0),
      coverable: children.reduce((sum, file) => sum + file.coverable, 0),
      prevRun: {
        covered: children.reduce((sum, file) => sum + file.prevRun.covered, 0),
        coverable: children.reduce((sum, file) => sum + file.prevRun.coverable, 0),
      }
    };
  });

  return [
    ...folders,
    ...files.filter(file => file.path.length === 1),
  ];
}

class App extends React.Component {
  constructor(...args) {
    super(...args);

    this.state = {
      current: [],
    };
  }

  componentDidMount() {
    this.updateStateFromLocation();
    window.addEventListener("hashchange", () => this.updateStateFromLocation(), false);
  }

  updateStateFromLocation() {
    if (window.location.hash.length > 1) {
      const current = window.location.hash.substr(1).split('/');
      this.setState({current});
    } else {
      this.setState({current: []});
    }
  }

  getCurrentPath() {
    let file = this.props.root;
    let path = [file];
    for (let p of this.state.current) {
      file = file.children.find(file => file.path[0] === p);
      if (!file) {
        return path;
      }
      path.push(file);
    }
    return path;
  }

  render() {
    const path = this.getCurrentPath();
    const file = path[path.length - 1];

    let w = null;
    if (file.is_folder) {
      w = e(FilesList, {
        folder: file,
        onSelectFile: this.selectFile.bind(this),
        onBack: path.length > 1 ? this.back.bind(this) : null,
      });
    } else {
      w = e(DisplayFile, {
        file,
        onBack: this.back.bind(this),
      });
    }

    return e('div', {className: 'app'}, w);
  }

  selectFile(file) {
    this.setState(({current}) => {
      return {current: [...current, file.path[0]]};
    }, () => this.updateHash());
  }

  back(file) {
    this.setState(({current}) => {
      return {current: current.slice(0, current.length - 1)};
    }, () => this.updateHash());
  }

  updateHash() {
    if (!this.state.current || !this.state.current.length) {
      window.location = '#';
    } else {
      window.location = '#' + this.state.current.join('/');
    }
  }
}

function FilesList({folder, onSelectFile, onBack}) {
  let files = folder.children;
  return e('div', {className: 'display-folder'},
    e(FileHeader, {file: folder, onBack}),
    e('table', {className: 'files-list'},
      e('thead', {className: 'files-list__head'},
        e('tr', null,
          e('th', null, "Path"),
          e('th', null, "Coverage")
        )
      ),
      e('tbody', {className: 'files-list__body'},
        files.map(file => e(File, {file, onClick: onSelectFile}))
      )
    )
  );
}

function File({file, onClick}) {
  const coverage = file.coverable ? file.covered / file.coverable * 100 : -1;
  const coverageDelta = file.prevRun &&
    (file.covered / file.coverable * 100 - file.prevRun.covered / file.prevRun.coverable * 100);

  return e('tr', {
      className: 'files-list__file'
        + (coverage >= 0 && coverage < 50 ? ' files-list__file_low': '')
        + (coverage >= 50 && coverage < 80 ? ' files-list__file_medium': '')
        + (coverage >= 80 ? ' files-list__file_high': '')
        + (file.is_folder ? ' files-list__file_folder': ''),
      onClick: () => onClick(file),
    },
    e('td', null, pathToString(file.path)),
    e('td', null,
      file.covered + ' / ' + file.coverable +
      (coverage >= 0 ? ' (' + coverage.toFixed(2) + '%)' : ''),
      e('span', {title: 'Change from the previous run'},
        (coverageDelta ? ` (${coverageDelta > 0 ? '+' : ''}${coverageDelta.toFixed(2)}%)` : ''))
    )
  );
}

function DisplayFile({file, onBack}) {
  return e('div', {className: 'display-file'},
    e(FileHeader, {file, onBack}),
    e(FileContent, {file})
  );
}

function FileHeader({file, onBack}) {
  const coverage = file.covered / file.coverable * 100;
  const coverageDelta = file.prevRun && (coverage - file.prevRun.covered / file.prevRun.coverable * 100);

  return e('div', {className: 'file-header'},
    onBack ? e('a', {className: 'file-header__back', onClick: onBack}, 'Back') : null,
    e('div', {className: 'file-header__name'}, pathToString([...file.parent, ...file.path])),
    e('div', {className: 'file-header__stat'},
      'Covered: ' + file.covered + ' of ' + file.coverable +
      (file.coverable ? ' (' + coverage.toFixed(2) + '%)' : ''),
      e('span', {title: 'Change from the previous run'},
        (coverageDelta ? ` (${coverageDelta > 0 ? '+' : ''}${coverageDelta.toFixed(2)}%)` : ''))
    )
  );
}

function FileContent({file}) {
  return e('div', {className: 'file-content'},
    file.content.split(/\r?\n/).map((line, index) => {
      const trace = file.traces.find(trace => trace.line === index + 1);
      const covered = trace && trace.stats.Line;
      const uncovered = trace && !trace.stats.Line;
      return e('pre', {
          className: 'code-line'
            + (covered ? ' code-line_covered' : '')
            + (uncovered ? ' code-line_uncovered' : ''),
          title: trace ? JSON.stringify(trace.stats, null, 2) : null,
        }, line);
    })
  );
}

(function(){
  const commonPath = findCommonPath(data.files);
  const prevFilesMap = new Map();

  previousData && previousData.files.forEach((file) => {
    const path = file.path.slice(commonPath.length).join('/');
    prevFilesMap.set(path, file);
  });

  const files = data.files.map((file) => {
    const path = file.path.slice(commonPath.length);
    const { covered = 0, coverable = 0 } = prevFilesMap.get(path.join('/')) || {};
    return {
      ...file,
      path,
      parent: commonPath,
      prevRun: { covered, coverable },
    };
  });

  const children = findFolders(files);

  const root = {
    is_folder: true,
    children,
    path: commonPath,
    parent: [],
    covered: children.reduce((sum, file) => sum + file.covered, 0),
    coverable: children.reduce((sum, file) => sum + file.coverable, 0),
    prevRun: {
      covered: children.reduce((sum, file) => sum + file.prevRun.covered, 0),
      coverable: children.reduce((sum, file) => sum + file.prevRun.coverable, 0),
    }
  };

  ReactDOM.render(e(App, {root, prevFilesMap}), document.getElementById('root'));
}());
</script>
</body>
</html>