Extract the random number generator

This commit is contained in:
Gwilym Kuiper 2022-03-23 21:52:37 +00:00
parent 9752377a15
commit 610722a1bf
2 changed files with 45 additions and 5 deletions

View file

@ -831,7 +831,7 @@ mod test {
use core::cell::RefCell; use core::cell::RefCell;
use super::*; use super::*;
use crate::Gba; use crate::{rng, Gba};
#[test_case] #[test_case]
fn can_store_and_retrieve_8_elements(_gba: &mut Gba) { fn can_store_and_retrieve_8_elements(_gba: &mut Gba) {
@ -956,14 +956,13 @@ mod test {
#[test_case] #[test_case]
fn extreme_case(_gba: &mut Gba) { fn extreme_case(_gba: &mut Gba) {
let mut map = HashMap::new(); let mut map = HashMap::new();
let mut rng = crate::rng::RandomNumberGenerator::new();
let mut answers: [Option<i32>; 128] = [None; 128]; let mut answers: [Option<i32>; 128] = [None; 128];
for _ in 0..5_000 { for _ in 0..5_000 {
let command = rng.next().rem_euclid(2); let command = rng::next().rem_euclid(2);
let key = rng.next().rem_euclid(answers.len() as i32); let key = rng::next().rem_euclid(answers.len() as i32);
let value = rng.next(); let value = rng::next();
match command { match command {
0 => { 0 => {

41
agb/src/rng.rs Normal file
View file

@ -0,0 +1,41 @@
use core::cell::RefCell;
use bare_metal::Mutex;
use crate::interrupt::free;
pub struct RandomNumberGenerator {
state: [u32; 4],
}
impl RandomNumberGenerator {
pub const fn new() -> Self {
Self {
state: [1014776995, 476057059, 3301633994, 706340607],
}
}
pub fn next(&mut self) -> i32 {
let result = (self.state[0].wrapping_add(self.state[3]))
.rotate_left(7)
.wrapping_mul(9);
let t = self.state[1].wrapping_shr(9);
self.state[2] ^= self.state[0];
self.state[3] ^= self.state[1];
self.state[1] ^= self.state[2];
self.state[0] ^= self.state[3];
self.state[2] ^= t;
self.state[3] = self.state[3].rotate_left(11);
result as i32
}
}
static GLOBAL_RNG: Mutex<RefCell<RandomNumberGenerator>> =
Mutex::new(RefCell::new(RandomNumberGenerator::new()));
pub fn next() -> i32 {
free(|cs| GLOBAL_RNG.borrow(*cs).borrow_mut().next())
}