pub trait RandGen: Send + Sync {
// Required method
fn gen(&mut self) -> u32;
// Provided methods
fn gen_bits(&mut self, bits: u32) -> u32 { ... }
fn seed(&mut self, seed: &Integer) { ... }
fn boxed_clone(&self) -> Option<Box<dyn RandGen>> { ... }
}
Expand description
Custom random number generator to be used with RandState
.
The methods implemented for this trait, as well as possible destructors, can be used by FFI callback functions. If these methods panic, they can cause the program to abort.
Examples
use rug::rand::{RandGen, RandState};
use rug::Integer;
struct SimpleGenerator {
seed: u64,
}
impl RandGen for SimpleGenerator {
fn gen(&mut self) -> u32 {
// linear congruential algorithm with m = 64
const A: u64 = 0x5851_F42D_4C95_7F2D;
const C: u64 = 1;
self.seed = self.seed.wrapping_mul(A).wrapping_add(C);
(self.seed >> 32) as u32
}
fn seed(&mut self, seed: &Integer) {
self.seed = seed.to_u64_wrapping();
}
}
let mut gen = SimpleGenerator { seed: 1 };
let mut state = RandState::new_custom(&mut gen);
assert_eq!(state.bits(32), 0x5851_F42D);
assert_eq!(state.bits(32), 0xC0B1_8CCF);
Required Methods§
sourcefn gen(&mut self) -> u32
fn gen(&mut self) -> u32
Gets a random 32-bit unsigned integer.
Examples
use rug::rand::RandGen;
struct SimpleGenerator {
seed: u64,
}
impl RandGen for SimpleGenerator {
fn gen(&mut self) -> u32 {
// linear congruential algorithm with m = 64
const A: u64 = 0x5851_F42D_4C95_7F2D;
const C: u64 = 1;
self.seed = self.seed.wrapping_mul(A).wrapping_add(C);
(self.seed >> 32) as u32
}
}
let mut rand = SimpleGenerator { seed: 1 };
assert_eq!(rand.gen(), 0x5851_F42D);
assert_eq!(rand.seed, 0x5851_F42D_4C95_7F2E);
assert_eq!(rand.gen(), 0xC0B1_8CCF);
assert_eq!(rand.seed, 0xC0B1_8CCF_4E25_2D17);
Provided Methods§
sourcefn gen_bits(&mut self, bits: u32) -> u32
fn gen_bits(&mut self, bits: u32) -> u32
Gets up to 32 random bits.
The default implementation simply calls the gen
method once and
returns the most significant required bits.
This method can be overridden to store any unused bits for later use. This can be useful for example if the random number generation process is computationally expensive.
Examples
use rug::rand::RandGen;
struct SimpleGenerator {
seed: u64,
buffer: u32,
len: u32,
}
impl RandGen for SimpleGenerator {
fn gen(&mut self) -> u32 {
// linear congruential algorithm with m = 64
const A: u64 = 0x5851_F42D_4C95_7F2D;
const C: u64 = 1;
self.seed = self.seed.wrapping_mul(A).wrapping_add(C);
(self.seed >> 32) as u32
}
fn gen_bits(&mut self, bits: u32) -> u32 {
let mut bits = match bits {
0 => return 0,
1..=31 => bits,
_ => return self.gen(),
};
let mut ret = 0;
if bits > self.len {
bits -= self.len;
ret |= self.buffer << bits;
self.buffer = self.gen();
self.len = 32;
}
self.len -= bits;
ret |= self.buffer >> self.len;
self.buffer &= !(!0 << self.len);
ret
}
}
let mut rand = SimpleGenerator {
seed: 1,
buffer: 0,
len: 0,
};
let (first_32, second_32) = (0x5851_F42D, 0xC0B1_8CCF);
assert_eq!(rand.gen_bits(24), first_32 >> 8);
assert_eq!(rand.gen_bits(24), ((first_32 & 0xFF) << 16) | (second_32 >> 16));
assert_eq!(rand.gen_bits(16), second_32 & 0xFFFF);
sourcefn seed(&mut self, seed: &Integer)
fn seed(&mut self, seed: &Integer)
Seeds the random number generator.
The default implementation of this function does nothing.
Note that the RandState::seed
method
will pass its seed parameter exactly to this function without using it
otherwise.
Examples
use rug::rand::{RandGen, RandState};
use rug::{Assign, Integer};
struct Seed {
inner: Integer,
}
impl RandGen for Seed {
fn gen(&mut self) -> u32 {
self.inner.to_u32_wrapping()
}
fn seed(&mut self, seed: &Integer) {
self.inner.assign(seed);
}
}
let mut seed = Seed {
inner: Integer::from(12),
};
let i = Integer::from(12345);
{
let mut rand = RandState::new_custom(&mut seed);
rand.seed(&i);
}
assert_eq!(seed.inner, i);
sourcefn boxed_clone(&self) -> Option<Box<dyn RandGen>>
fn boxed_clone(&self) -> Option<Box<dyn RandGen>>
Optionally clones the random number generator.
The default implementation returns None
.
Examples
use rug::rand::RandGen;
struct SimpleGenerator {
seed: u64,
}
impl RandGen for SimpleGenerator {
fn gen(&mut self) -> u32 {
// linear congruential algorithm with m = 64
const A: u64 = 0x5851_F42D_4C95_7F2D;
const C: u64 = 1;
self.seed = self.seed.wrapping_mul(A).wrapping_add(C);
(self.seed >> 32) as u32
}
fn boxed_clone(&self) -> Option<Box<dyn RandGen>> {
let other = SimpleGenerator { seed: self.seed };
let boxed = Box::new(other);
Some(boxed)
}
}
let mut rand = SimpleGenerator { seed: 1 };
assert_eq!(rand.gen(), 0x5851_F42D);
assert_eq!(rand.seed, 0x5851_F42D_4C95_7F2E);
let mut other = rand.boxed_clone().unwrap();
assert_eq!(rand.gen(), 0xC0B1_8CCF);
assert_eq!(rand.seed, 0xC0B1_8CCF_4E25_2D17);
assert_eq!(other.gen(), 0xC0B1_8CCF);