1#![allow(dead_code)]
2use nanorand::Rng;
35use rune::{Any, ContextError, Module};
36
37pub fn module(_stdio: bool) -> Result<Module, ContextError> {
39 let mut module = Module::with_crate("rand")?;
40
41 module.ty::<WyRand>()?;
42 module
43 .function("new", WyRand::new)
44 .build_associated::<WyRand>()?;
45 module
46 .function("new_seed", WyRand::new_seed)
47 .build_associated::<WyRand>()?;
48 module.associated_function("int", WyRand::int)?;
49 module.associated_function("int_range", WyRand::int_range)?;
50
51 module.ty::<Pcg64>()?;
52 module
53 .function("new", Pcg64::new)
54 .build_associated::<Pcg64>()?;
55 module
56 .function("new_seed", Pcg64::new_seed)
57 .build_associated::<Pcg64>()?;
58 module.associated_function("int", Pcg64::int)?;
59 module.associated_function("int_range", Pcg64::int_range)?;
60
61 module.function("int", int).build()?;
62 module.function("int_range", int_range).build()?;
63 Ok(module)
64}
65
66#[derive(Any)]
67#[rune(item = ::rand)]
68struct WyRand {
69 inner: nanorand::WyRand,
70}
71
72impl WyRand {
73 fn new() -> Self {
75 Self {
76 inner: nanorand::WyRand::new(),
77 }
78 }
79
80 fn new_seed(seed: i64) -> Self {
82 Self {
83 inner: nanorand::WyRand::new_seed(seed as u64),
84 }
85 }
86
87 fn int(&mut self) -> i64 {
89 self.inner.generate::<u64>() as i64
90 }
91
92 fn int_range(&mut self, lower: i64, upper: i64) -> i64 {
94 self.inner.generate_range(0..(upper - lower) as u64) as i64 + lower
95 }
96}
97
98#[derive(Any)]
99#[rune(item = ::rand)]
100struct Pcg64 {
101 inner: nanorand::Pcg64,
102}
103
104impl Pcg64 {
105 fn new() -> Self {
107 Self {
108 inner: nanorand::Pcg64::new(),
109 }
110 }
111
112 fn new_seed(seed: i64) -> Self {
114 Self {
115 inner: nanorand::Pcg64::new_seed(seed as u128),
116 }
117 }
118
119 fn int(&mut self) -> i64 {
121 self.inner.generate::<u64>() as i64
122 }
123
124 fn int_range(&mut self, lower: i64, upper: i64) -> i64 {
126 self.inner.generate_range(0..(upper - lower) as u64) as i64 + lower
127 }
128}
129
130fn int() -> rune::support::Result<i64> {
131 Ok(nanorand::WyRand::new().generate::<u64>() as i64)
132}
133
134fn int_range(lower: i64, upper: i64) -> rune::support::Result<i64> {
135 Ok(nanorand::WyRand::new().generate_range(0..(upper - lower) as u64) as i64 + lower)
136}
137
138#[cfg(test)]
139mod tests {
140 use super::{int, int_range};
141
142 #[test]
143 fn test_range_is_exclusive() {
144 for _ in 0..100 {
145 assert_eq!(int_range(0, 1).unwrap(), 0);
146 }
147 }
148
149 #[test]
150 fn test_range_can_be_negative() {
151 for _ in 0..100 {
152 assert_eq!(int_range(-2, -1).unwrap(), -2);
153 }
154 }
155
156 #[test]
157 fn test_int_is_properly_signed() {
158 let mut any_negative = false;
159 let mut any_positive = false;
160
161 for _ in 0..100 {
162 let v: i64 = int().unwrap();
163 any_negative = any_negative || v < 0;
164 any_positive = any_positive || v > 0;
165 }
166
167 assert!(any_positive);
168 assert!(any_negative);
169 }
170}