pub mod true_rng{
use candid::Principal;
use ic_cdk::call;
pub async fn async_generate() -> Result<usize, String >{
let (random_bytes,): (Vec<u8>,) = call(Principal::management_canister(), "raw_rand", ()).await.map_err(|err| format!("{:?}", err))?;
let random_number = usize::from_be_bytes(random_bytes[0..4.min(random_bytes.len())].try_into().unwrap());
Ok(random_number)
}
pub fn generate() -> Result<usize, String> {
let future = async_generate(); let result = futures::executor::block_on(future); result
}
}
pub mod rng{
use std::ops::{Add, Mul, Rem};
use std::num::Wrapping;
use num_traits::{PrimInt, FromPrimitive, Unsigned, Bounded};
pub fn random_seed() -> usize {
let x = 42usize;
let y = &x as *const usize as usize;
let z = (y ^ 0xdeadbeef) + (y >> 3);
z
}
pub struct RandomNumberGenerator<T>
where
T: PrimInt + FromPrimitive + Unsigned + Bounded + Mul<Output = T>,
{
seed: Wrapping<T>,
a: Wrapping<T>, c: Wrapping<T>, m: Wrapping<T>, }
impl<T> RandomNumberGenerator<T>
where
T: PrimInt + FromPrimitive + Unsigned + Bounded ,
Wrapping<T>: Mul<Output = Wrapping<T>> + Add<Output = Wrapping<T>> + Rem<Output = Wrapping<T>>
{
pub fn new_custom(seed: T, a: T, c: T, m: T) -> Self {
RandomNumberGenerator {
seed: Wrapping(seed),
a: Wrapping(a),
c: Wrapping(c),
m: Wrapping(m),
}
}
pub fn new() -> Self {
let (a, c, m) = Self::default_values();
RandomNumberGenerator {
seed: Wrapping(T::from(random_seed()).unwrap_or_else(T::min_value)),
a: Wrapping(a),
c: Wrapping(c),
m: Wrapping(m),
}
}
pub fn next(&mut self) -> T {
self.seed = (self.a * self.seed + self.c) % self.m;
self.seed.0
}
pub fn range(&mut self, max: T) -> T {
self.next() % max
}
fn default_values() -> (T, T, T) {
let bits = T::zero().count_zeros();
match bits {
8 => (
T::from(13).unwrap(), T::from(7).unwrap(),
T::from(31).unwrap(), ),
16 => (
T::from(25173).unwrap(), T::from(13849).unwrap(),
T::from(2u32.pow(16) - 1).unwrap(), ),
32 => (
T::from(1664525).unwrap(), T::from(1013904223).unwrap(),
T::from(2u64.pow(32) - 1).unwrap(), ),
_ => (
T::from(1664525).unwrap(), T::from(1013904223).unwrap(),
T::from(2u64.pow(32)).unwrap(),
)
}
}
}
}