use std::mem;
use rand;
use vec2d::{Vector, Point};
#[inline]
fn u32_to_float(uint: u32, min: f32, max: f32) -> f32 {
let mantissa = uint >> 9;
let bit_pattern = mantissa | 0b0_01111111__0000000_00000000_00000000;
let float_1_to_2: f32 = unsafe { mem::transmute(bit_pattern) };
(float_1_to_2 - 1.0) * (max - min) + min
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Rng(pub u64, pub u64);
impl Rng {
#[inline]
pub fn new() -> Rng {
use rand::Rng as Rand; let (s0, s1) = rand::thread_rng().gen();
Rng::new_seeded(s0, s1)
}
#[inline]
pub fn new_seeded(seed_a: u64, seed_b: u64) -> Rng {
match (seed_a, seed_b) {
(0, 0) => Rng(0x988bafaf1dc4899c, 0x330ef5df7a448957),
_ => Rng(seed_a, seed_b),
}
}
#[inline]
pub fn next_u64(&mut self) -> u64 {
let result = self.0.wrapping_add(self.1);
self.skip();
result
}
#[inline]
pub fn skip(&mut self) {
let mut s1 = self.0;
let s0 = self.1;
self.0 = s0;
s1 ^= s1 << 23;
self.1 = s1 ^ s0 ^ (s1 >> 18) ^ (s0 >> 5);
}
pub fn jump(&mut self) {
const BIT_MASK: [u64; 2] = [0x8a5cd789635d2dff, 0x121fd2155c472f96];
let mut s0 = 0;
let mut s1 = 0;
for bits in BIT_MASK.iter() {
for bit in 0..64 {
if bits & (1 << bit) != 0 {
s0 ^= self.0;
s1 ^= self.1;
}
self.skip();
}
}
self.0 = s0;
self.1 = s1;
}
#[inline]
pub fn rand_int(&mut self, min: i64, max: i64) -> i64 {
assert!(max > min, "The maximum must be smaller than the minimum!");
let delta = (max.wrapping_sub(min)) as u64;
let random = self.next_u64();
min + (random % delta) as i64
}
#[inline]
pub fn rand_uint(&mut self, min: u64, max: u64) -> u64 {
assert!(max > min, "The maximum must be smaller than the minimum!");
let delta = max - min;
let random = self.next_u64();
min + random % delta
}
#[inline]
pub fn rand_float(&mut self, min: f32, max: f32) -> f32 {
u32_to_float(self.next_u64() as u32, min, max)
}
#[inline]
pub fn rand_bool(&mut self, probability: f32) -> bool {
self.rand_float(0.0, 1.0) < probability
}
#[inline]
pub fn rand_vec(&mut self, bound1: Vector, bound2: Vector) -> Vector {
let min = [bound1.x.min(bound2.x), bound1.y.min(bound2.y)];
let max = [bound1.x.max(bound2.x), bound1.y.max(bound2.y)];
let random = self.next_u64();
let split: [u32; 2] = unsafe { mem::transmute(random) };
Vector::new(u32_to_float(split[0], min[0], max[0]),
u32_to_float(split[1], min[1], max[1]))
}
#[inline]
pub fn rand_point(&mut self, bound1: Point, bound2: Point) -> Point {
self.rand_vec(bound1.as_vec(), bound2.as_vec()).as_point()
}
#[inline]
pub fn rand_el<'a, T>(&mut self, arr: &'a [T]) -> &'a T {
assert!(arr.len() > 0, "A random element? There are no elements!");
let random = self.next_u64() as usize;
let index = random % arr.len();
&arr[index]
}
#[inline]
pub fn rand_el_mut<'a, T>(&mut self, arr: &'a mut [T]) -> &'a mut T {
assert!(arr.len() > 0, "A random element? There are no elements!");
let random = self.next_u64() as usize;
let index = random % arr.len();
&mut arr[index]
}
#[inline]
pub fn shuffle_mut<T>(&mut self, arr: &mut [T]) {
for i in (1..arr.len()).rev() {
let j = self.rand_uint(0, i as u64 + 1) as usize;
arr.swap(i, j);
}
}
#[inline]
pub fn shuffle<T: Clone>(&mut self, arr: &[T]) -> Vec<T> {
let mut out = Vec::from(arr);
self.shuffle_mut(&mut out);
out
}
}