XorShift (Xor128)
概要
現在Rustの標準ライブラリには乱数が無い.
実装
#[allow(dead_code)]
struct Xor128 {
x: u32,
y: u32,
z: u32,
w: u32,
}
#[allow(dead_code)]
impl Xor128 {
pub fn new() -> Xor128 {
use std::io::Read;
let mut buf = [0; 4];
let mut urandom = std::fs::File::open("/dev/urandom").expect("failed opening /dev/urandom");
urandom.read(&mut buf).expect("failed reading /dev/urandom");
let mut seed: u32 = 0;
for i in 0..4 {
seed |= (buf[i] as u32) << (4 * i);
}
Xor128::from_seed(seed)
}
pub fn from_seed(seed: u32) -> Xor128 {
let mut res = Xor128 {
x: 123456789,
y: 987654321,
z: 1000000007,
w: seed,
};
for _ in 0..16 {
res.gen();
}
res
}
pub fn gen(&mut self) -> u32 {
let t = self.x ^ (self.x << 11);
self.x = self.y;
self.y = self.z;
self.z = self.w;
self.w = (self.w ^ (self.w >> 19)) ^ (t ^ (t >> 8));
self.w
}
pub fn next(&mut self, high: u32) -> u32 {
self.gen() % high
}
pub fn next_i32(&mut self, low: i32, high: i32) -> i32 {
assert!(low <= high);
low + self.next((high - low + 1) as u32) as i32
}
pub fn next_u32(&mut self, low: u32, high: u32) -> u32 {
assert!(low <= high);
low + self.next(high - low + 1)
}
pub fn sample<'a, T>(&mut self, values: &'a [T]) -> Option<&'a T>
where
Self: Sized,
{
if values.is_empty() {
None
} else {
Some(&values[self.next(values.len() as u32) as usize])
}
}
pub fn sample_mut<'a, T>(&mut self, values: &'a mut [T]) -> Option<&'a mut T>
where
Self: Sized,
{
if values.is_empty() {
None
} else {
Some(&mut values[self.next(values.len() as u32) as usize])
}
}
pub fn shuffle<T>(&mut self, values: &mut [T])
where
Self: Sized,
{
let n = values.len();
for i in 0..n - 1 {
let t = n as u32 - i as u32;
values.swap(i, i + self.next(t) as usize);
}
}
}