#![allow(dead_code)]
use nanorand::Rng;
use rune::{Any, ContextError, Module};
pub fn module(_stdio: bool) -> Result<Module, ContextError> {
let mut module = Module::with_crate("rand")?;
module.ty::<WyRand>()?;
module
.function("new", WyRand::new)
.build_associated::<WyRand>()?;
module
.function("new_seed", WyRand::new_seed)
.build_associated::<WyRand>()?;
module.associated_function("int", WyRand::int)?;
module.associated_function("int_range", WyRand::int_range)?;
module.ty::<Pcg64>()?;
module
.function("new", Pcg64::new)
.build_associated::<Pcg64>()?;
module
.function("new_seed", Pcg64::new_seed)
.build_associated::<Pcg64>()?;
module.associated_function("int", Pcg64::int)?;
module.associated_function("int_range", Pcg64::int_range)?;
module.function("int", int).build()?;
module.function("int_range", int_range).build()?;
Ok(module)
}
#[derive(Any)]
#[rune(item = ::rand)]
struct WyRand {
inner: nanorand::WyRand,
}
impl WyRand {
fn new() -> Self {
Self {
inner: nanorand::WyRand::new(),
}
}
fn new_seed(seed: i64) -> Self {
Self {
inner: nanorand::WyRand::new_seed(seed as u64),
}
}
fn int(&mut self) -> i64 {
self.inner.generate::<u64>() as i64
}
fn int_range(&mut self, lower: i64, upper: i64) -> i64 {
self.inner.generate_range(0..(upper - lower) as u64) as i64 + lower
}
}
#[derive(Any)]
#[rune(item = ::rand)]
struct Pcg64 {
inner: nanorand::Pcg64,
}
impl Pcg64 {
fn new() -> Self {
Self {
inner: nanorand::Pcg64::new(),
}
}
fn new_seed(seed: i64) -> Self {
Self {
inner: nanorand::Pcg64::new_seed(seed as u128),
}
}
fn int(&mut self) -> i64 {
self.inner.generate::<u64>() as i64
}
fn int_range(&mut self, lower: i64, upper: i64) -> i64 {
self.inner.generate_range(0..(upper - lower) as u64) as i64 + lower
}
}
fn int() -> rune::support::Result<i64> {
Ok(nanorand::WyRand::new().generate::<u64>() as i64)
}
fn int_range(lower: i64, upper: i64) -> rune::support::Result<i64> {
Ok(nanorand::WyRand::new().generate_range(0..(upper - lower) as u64) as i64 + lower)
}
#[cfg(test)]
mod tests {
use super::{int, int_range};
#[test]
fn test_range_is_exclusive() {
for _ in 0..100 {
assert_eq!(int_range(0, 1).unwrap(), 0);
}
}
#[test]
fn test_range_can_be_negative() {
for _ in 0..100 {
assert_eq!(int_range(-2, -1).unwrap(), -2);
}
}
#[test]
fn test_int_is_properly_signed() {
let mut any_negative = false;
let mut any_positive = false;
for _ in 0..100 {
let v: i64 = int().unwrap();
any_negative = any_negative || v < 0;
any_positive = any_positive || v > 0;
}
assert!(any_positive);
assert!(any_negative);
}
}