import "std/core.zc" import "std/time.zc" // Per-instance xorshift64* PRNG. Each Random owns its own 64-bit state, so // generators seeded the same way produce identical sequences independently of // one another (unlike a process-global srand/rand). struct Random { state: u64; } fn _splitmix64(x: u64) -> u64 { let z = x + 0x9E3779B97F4A7C15; z = z ^ (z >> 30); z = z * 0xBF58476D1CE4E5B9; z = z ^ (z >> 27); z = z * 0x94D049BB133111EB; return z ^ (z >> 31); } impl Random { // Creates a new random generator initialized with the current time fn new() -> Random { let seed = (u64)Time::now(); return Random { state: _splitmix64(seed) | 1 }; } // Creates a new random generator with a specific seed fn from_seed(seed: u32) -> Random { return Random { state: _splitmix64((u64)seed) | 1 }; } // Advances the generator and returns the next raw 64-bit value fn next_raw(self) -> u64 { let x = self.state; x = x ^ (x << 13); x = x ^ (x >> 7); x = x ^ (x << 17); self.state = x; return x; } // Returns a pseudo-random non-negative int in the range [0, INT32_MAX] fn next_int(self) -> int { return (int)(self.next_raw() & 0x7FFFFFFF); } // Returns a pseudo-random integer in the range [min, max] inclusive fn next_int_range(self, min: int, max: int) -> int { if (min > max) { panic("next_int_range: min > max"); } let range = (u64)(max - min + 1); return min + (int)(self.next_raw() % range); } // Returns a pseudo-random f64 in the range [0.0, 1.0) fn next_double(self) -> f64 { let raw = self.next_raw() >> 11; return (f64)raw / 9007199254740992.0; } // Returns a pseudo-random boolean fn next_bool(self) -> bool { return (self.next_raw() & 1) == 1; } }