std::rand: Add a trait for seeding RNGs: SeedableRng.
This provides 2 methods: .reseed() and ::from_seed that modify and create respecitively. Implement this trait for the RNGs in the stdlib for which this makes sense.
This commit is contained in:
parent
0223cf65e4
commit
92725ae765
@ -1524,8 +1524,8 @@ mod tests {
|
||||
}
|
||||
|
||||
fn rng() -> rand::IsaacRng {
|
||||
let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
|
||||
rand::IsaacRng::new_seeded(seed)
|
||||
let seed = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
|
||||
rand::SeedableRng::from_seed(seed)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
|
@ -1013,7 +1013,7 @@ mod test_treemap {
|
||||
check_equal(ctrl, &map);
|
||||
assert!(map.find(&5).is_none());
|
||||
|
||||
let mut rng = rand::IsaacRng::new_seeded(&[42]);
|
||||
let mut rng: rand::IsaacRng = rand::SeedableRng::from_seed(&[42]);
|
||||
|
||||
do 3.times {
|
||||
do 90.times {
|
||||
|
@ -10,15 +10,10 @@
|
||||
|
||||
//! The ISAAC random number generator.
|
||||
|
||||
use rand::{seed, Rng};
|
||||
use iter::{Iterator, range, range_step};
|
||||
use rand::{seed, Rng, SeedableRng};
|
||||
use iter::{Iterator, range, range_step, Repeat};
|
||||
use option::{None, Some};
|
||||
|
||||
use cast;
|
||||
use cmp;
|
||||
use sys;
|
||||
use vec;
|
||||
|
||||
static RAND_SIZE_LEN: u32 = 8;
|
||||
static RAND_SIZE: u32 = 1 << RAND_SIZE_LEN;
|
||||
|
||||
@ -38,30 +33,8 @@ pub struct IsaacRng {
|
||||
impl IsaacRng {
|
||||
/// Create an ISAAC random number generator with a random seed.
|
||||
pub fn new() -> IsaacRng {
|
||||
IsaacRng::new_seeded(seed(RAND_SIZE as uint * 4))
|
||||
}
|
||||
|
||||
/// Create an ISAAC random number generator with a seed. This can be any
|
||||
/// length, although the maximum number of bytes used is 1024 and any more
|
||||
/// will be silently ignored. A generator constructed with a given seed
|
||||
/// will generate the same sequence of values as all other generators
|
||||
/// constructed with the same seed.
|
||||
pub fn new_seeded(seed: &[u8]) -> IsaacRng {
|
||||
let mut rng = IsaacRng {
|
||||
cnt: 0,
|
||||
rsl: [0, .. RAND_SIZE],
|
||||
mem: [0, .. RAND_SIZE],
|
||||
a: 0, b: 0, c: 0
|
||||
};
|
||||
|
||||
let array_size = sys::size_of_val(&rng.rsl);
|
||||
let copy_length = cmp::min(array_size, seed.len());
|
||||
|
||||
// manually create a &mut [u8] slice of randrsl to copy into.
|
||||
let dest = unsafe { cast::transmute((&mut rng.rsl, array_size)) };
|
||||
vec::bytes::copy_memory(dest, seed, copy_length);
|
||||
rng.init(true);
|
||||
rng
|
||||
let s = unsafe {seed::<u32>(RAND_SIZE as uint)};
|
||||
SeedableRng::from_seed(s.as_slice())
|
||||
}
|
||||
|
||||
/// Create an ISAAC random number generator using the default
|
||||
@ -197,6 +170,43 @@ impl Rng for IsaacRng {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self> SeedableRng<&'self [u32]> for IsaacRng {
|
||||
fn reseed(&mut self, seed: &'self [u32]) {
|
||||
// make the seed into [seed[0], seed[1], ..., seed[seed.len()
|
||||
// - 1], 0, 0, ...], to fill rng.rsl.
|
||||
let seed_iter = seed.iter().map(|&x| x).chain(Repeat::new(0u32));
|
||||
|
||||
for (rsl_elem, seed_elem) in self.rsl.mut_iter().zip(seed_iter) {
|
||||
*rsl_elem = seed_elem;
|
||||
}
|
||||
self.cnt = 0;
|
||||
self.a = 0;
|
||||
self.b = 0;
|
||||
self.c = 0;
|
||||
|
||||
self.init(true);
|
||||
}
|
||||
|
||||
/// Create an ISAAC random number generator with a seed. This can
|
||||
/// be any length, although the maximum number of elements used is
|
||||
/// 256 and any more will be silently ignored. A generator
|
||||
/// constructed with a given seed will generate the same sequence
|
||||
/// of values as all other generators constructed with that seed.
|
||||
fn from_seed(seed: &'self [u32]) -> IsaacRng {
|
||||
let mut rng = IsaacRng {
|
||||
cnt: 0,
|
||||
rsl: [0, .. RAND_SIZE],
|
||||
mem: [0, .. RAND_SIZE],
|
||||
a: 0, b: 0, c: 0
|
||||
};
|
||||
|
||||
rng.reseed(seed);
|
||||
|
||||
rng
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static RAND_SIZE_64_LEN: uint = 8;
|
||||
static RAND_SIZE_64: uint = 1 << RAND_SIZE_64_LEN;
|
||||
|
||||
@ -218,31 +228,8 @@ impl Isaac64Rng {
|
||||
/// Create a 64-bit ISAAC random number generator with a random
|
||||
/// seed.
|
||||
pub fn new() -> Isaac64Rng {
|
||||
Isaac64Rng::new_seeded(seed(RAND_SIZE_64 as uint * 8))
|
||||
}
|
||||
|
||||
/// Create a 64-bit ISAAC random number generator with a
|
||||
/// seed. This can be any length, although the maximum number of
|
||||
/// bytes used is 2048 and any more will be silently ignored. A
|
||||
/// generator constructed with a given seed will generate the same
|
||||
/// sequence of values as all other generators constructed with
|
||||
/// the same seed.
|
||||
pub fn new_seeded(seed: &[u8]) -> Isaac64Rng {
|
||||
let mut rng = Isaac64Rng {
|
||||
cnt: 0,
|
||||
rsl: [0, .. RAND_SIZE_64],
|
||||
mem: [0, .. RAND_SIZE_64],
|
||||
a: 0, b: 0, c: 0,
|
||||
};
|
||||
|
||||
let array_size = sys::size_of_val(&rng.rsl);
|
||||
let copy_length = cmp::min(array_size, seed.len());
|
||||
|
||||
// manually create a &mut [u8] slice of randrsl to copy into.
|
||||
let dest = unsafe { cast::transmute((&mut rng.rsl, array_size)) };
|
||||
vec::bytes::copy_memory(dest, seed, copy_length);
|
||||
rng.init(true);
|
||||
rng
|
||||
let s = unsafe {seed::<u64>(RAND_SIZE_64)};
|
||||
SeedableRng::from_seed(s.as_slice())
|
||||
}
|
||||
|
||||
/// Create a 64-bit ISAAC random number generator using the
|
||||
@ -378,22 +365,58 @@ impl Rng for Isaac64Rng {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self> SeedableRng<&'self [u64]> for Isaac64Rng {
|
||||
fn reseed(&mut self, seed: &'self [u64]) {
|
||||
// make the seed into [seed[0], seed[1], ..., seed[seed.len()
|
||||
// - 1], 0, 0, ...], to fill rng.rsl.
|
||||
let seed_iter = seed.iter().map(|&x| x).chain(Repeat::new(0u64));
|
||||
|
||||
for (rsl_elem, seed_elem) in self.rsl.mut_iter().zip(seed_iter) {
|
||||
*rsl_elem = seed_elem;
|
||||
}
|
||||
self.cnt = 0;
|
||||
self.a = 0;
|
||||
self.b = 0;
|
||||
self.c = 0;
|
||||
|
||||
self.init(true);
|
||||
}
|
||||
|
||||
/// Create an ISAAC random number generator with a seed. This can
|
||||
/// be any length, although the maximum number of elements used is
|
||||
/// 256 and any more will be silently ignored. A generator
|
||||
/// constructed with a given seed will generate the same sequence
|
||||
/// of values as all other generators constructed with that seed.
|
||||
fn from_seed(seed: &'self [u64]) -> Isaac64Rng {
|
||||
let mut rng = Isaac64Rng {
|
||||
cnt: 0,
|
||||
rsl: [0, .. RAND_SIZE_64],
|
||||
mem: [0, .. RAND_SIZE_64],
|
||||
a: 0, b: 0, c: 0,
|
||||
};
|
||||
rng.reseed(seed);
|
||||
rng
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use rand::{Rng, seed};
|
||||
use option::{Option, Some};
|
||||
use rand::{Rng, SeedableRng, seed};
|
||||
use option::Some;
|
||||
use iter::range;
|
||||
use vec;
|
||||
|
||||
#[test]
|
||||
fn test_rng_seeded() {
|
||||
let seed = seed(1024);
|
||||
let mut ra = IsaacRng::new_seeded(seed);
|
||||
let mut rb = IsaacRng::new_seeded(seed);
|
||||
let s = unsafe {seed::<u32>(256)};
|
||||
let mut ra: IsaacRng = SeedableRng::from_seed(s.as_slice());
|
||||
let mut rb: IsaacRng = SeedableRng::from_seed(s.as_slice());
|
||||
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
|
||||
|
||||
let seed = seed(2048);
|
||||
let mut ra = Isaac64Rng::new_seeded(seed);
|
||||
let mut rb = Isaac64Rng::new_seeded(seed);
|
||||
let s = unsafe {seed::<u64>(256)};
|
||||
let mut ra: Isaac64Rng = SeedableRng::from_seed(s.as_slice());
|
||||
let mut rb: Isaac64Rng = SeedableRng::from_seed(s.as_slice());
|
||||
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
|
||||
}
|
||||
|
||||
@ -401,29 +424,59 @@ mod test {
|
||||
fn test_rng_seeded_custom_seed() {
|
||||
// much shorter than generated seeds which are 1024 & 2048
|
||||
// bytes resp.
|
||||
let seed = [2u8, 32u8, 4u8, 32u8, 51u8];
|
||||
let mut ra = IsaacRng::new_seeded(seed);
|
||||
let mut rb = IsaacRng::new_seeded(seed);
|
||||
let seed = &[2, 32, 4, 32, 51];
|
||||
let mut ra: IsaacRng = SeedableRng::from_seed(seed);
|
||||
let mut rb: IsaacRng = SeedableRng::from_seed(seed);
|
||||
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
|
||||
|
||||
let mut ra = Isaac64Rng::new_seeded(seed);
|
||||
let mut rb = Isaac64Rng::new_seeded(seed);
|
||||
let seed = &[2, 32, 4, 32, 51];
|
||||
let mut ra: Isaac64Rng = SeedableRng::from_seed(seed);
|
||||
let mut rb: Isaac64Rng = SeedableRng::from_seed(seed);
|
||||
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rng_seeded_custom_seed2() {
|
||||
let seed = [2u8, 32u8, 4u8, 32u8, 51u8];
|
||||
let mut ra = IsaacRng::new_seeded(seed);
|
||||
fn test_rng_32_true_values() {
|
||||
let seed = &[2, 32, 4, 32, 51];
|
||||
let mut ra: IsaacRng = SeedableRng::from_seed(seed);
|
||||
// Regression test that isaac is actually using the above vector
|
||||
let r = ra.next_u32();
|
||||
error2!("{:?}", r);
|
||||
assert_eq!(r, 2935188040u32);
|
||||
let v = vec::from_fn(10, |_| ra.next_u32());
|
||||
assert_eq!(v,
|
||||
~[447462228, 2081944040, 3163797308, 2379916134, 2377489184,
|
||||
1132373754, 536342443, 2995223415, 1265094839, 345325140]);
|
||||
|
||||
let mut ra = Isaac64Rng::new_seeded(seed);
|
||||
let seed = &[500, -4000, 123456, 9876543, 1, 1, 1, 1, 1];
|
||||
let mut rb: IsaacRng = SeedableRng::from_seed(seed);
|
||||
// skip forward to the 10000th number
|
||||
for _ in range(0, 10000) { rb.next_u32(); }
|
||||
|
||||
let v = vec::from_fn(10, |_| rb.next_u32());
|
||||
assert_eq!(v,
|
||||
~[612373032, 292987903, 1819311337, 3141271980, 422447569,
|
||||
310096395, 1083172510, 867909094, 2478664230, 2073577855]);
|
||||
}
|
||||
#[test]
|
||||
fn test_rng_64_true_values() {
|
||||
let seed = &[2, 32, 4, 32, 51];
|
||||
let mut ra: Isaac64Rng = SeedableRng::from_seed(seed);
|
||||
// Regression test that isaac is actually using the above vector
|
||||
let r = ra.next_u64();
|
||||
error2!("{:?}", r);
|
||||
assert!(r == 0 && r == 1); // FIXME: find true value
|
||||
let v = vec::from_fn(10, |_| ra.next_u64());
|
||||
assert_eq!(v,
|
||||
~[15015576812873463115, 12461067598045625862, 14818626436142668771,
|
||||
5562406406765984441, 11813289907965514161, 13443797187798420053,
|
||||
6935026941854944442, 7750800609318664042, 14428747036317928637,
|
||||
14028894460301215947]);
|
||||
|
||||
let seed = &[500, -4000, 123456, 9876543, 1, 1, 1, 1, 1];
|
||||
let mut rb: Isaac64Rng = SeedableRng::from_seed(seed);
|
||||
// skip forward to the 10000th number
|
||||
for _ in range(0, 10000) { rb.next_u64(); }
|
||||
|
||||
let v = vec::from_fn(10, |_| rb.next_u64());
|
||||
assert_eq!(v,
|
||||
~[13557216323596688637, 17060829581390442094, 4927582063811333743,
|
||||
2699639759356482270, 4819341314392384881, 6047100822963614452,
|
||||
11086255989965979163, 11901890363215659856, 5370800226050011580,
|
||||
16496463556025356451]);
|
||||
}
|
||||
}
|
||||
|
@ -638,6 +638,42 @@ pub trait Rng {
|
||||
}
|
||||
}
|
||||
|
||||
/// A random number generator that can be explicitly seeded to produce
|
||||
/// the same stream of randomness multiple times.
|
||||
pub trait SeedableRng<Seed>: Rng {
|
||||
/// Reseed an RNG with the given seed.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::rand;
|
||||
/// use std::rand::Rng;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let mut rng: rand::XorShiftRng = rand::SeedableRng::from_seed(&[1, 2, 3, 4]);
|
||||
/// println!("{}", rng.gen::<f64>());
|
||||
/// rng.reseed([5, 6, 7, 8]);
|
||||
/// println!("{}", rng.gen::<f64>());
|
||||
/// }
|
||||
/// ```
|
||||
fn reseed(&mut self, Seed);
|
||||
|
||||
/// Create a new RNG with the given seed.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::rand;
|
||||
/// use std::rand::Rng;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let mut rng: rand::XorShiftRng = rand::SeedableRng::from_seed(&[1, 2, 3, 4]);
|
||||
/// println!("{}", rng.gen::<f64>());
|
||||
/// }
|
||||
/// ```
|
||||
fn from_seed(seed: Seed) -> Self;
|
||||
}
|
||||
|
||||
/// Create a random number generator with a default algorithm and seed.
|
||||
///
|
||||
/// It returns the cryptographically-safest `Rng` algorithm currently
|
||||
@ -686,6 +722,18 @@ impl Rng for StdRng {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self> SeedableRng<&'self [uint]> for StdRng {
|
||||
fn reseed(&mut self, seed: &'self [uint]) {
|
||||
// the internal RNG can just be seeded from the above
|
||||
// randomness.
|
||||
self.rng.reseed(unsafe {cast::transmute(seed)})
|
||||
}
|
||||
|
||||
fn from_seed(seed: &'self [uint]) -> StdRng {
|
||||
StdRng { rng: SeedableRng::from_seed(unsafe {cast::transmute(seed)}) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a weak random number generator with a default algorithm and seed.
|
||||
///
|
||||
/// It returns the fastest `Rng` algorithm currently available in Rust without
|
||||
@ -723,11 +771,35 @@ impl Rng for XorShiftRng {
|
||||
}
|
||||
}
|
||||
|
||||
impl SeedableRng<[u32, .. 4]> for XorShiftRng {
|
||||
/// Reseed an XorShiftRng. This will fail if `seed` is entirely 0.
|
||||
fn reseed(&mut self, seed: [u32, .. 4]) {
|
||||
assert!(!seed.iter().all(|&x| x == 0),
|
||||
"XorShiftRng.reseed called with an all zero seed.");
|
||||
|
||||
self.x = seed[0];
|
||||
self.y = seed[1];
|
||||
self.z = seed[2];
|
||||
self.w = seed[3];
|
||||
}
|
||||
|
||||
/// Create a new XorShiftRng. This will fail if `seed` is entirely 0.
|
||||
fn from_seed(seed: [u32, .. 4]) -> XorShiftRng {
|
||||
assert!(!seed.iter().all(|&x| x == 0),
|
||||
"XorShiftRng::from_seed called with an all zero seed.");
|
||||
|
||||
XorShiftRng {
|
||||
x: seed[0],
|
||||
y: seed[1],
|
||||
z: seed[2],
|
||||
w: seed[3]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl XorShiftRng {
|
||||
/// Create an xor shift random number generator with a random seed.
|
||||
pub fn new() -> XorShiftRng {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
// generate seeds the same way as seed(), except we have a
|
||||
// specific size, so we can just use a fixed buffer.
|
||||
let mut s = [0u8, ..16];
|
||||
@ -740,29 +812,21 @@ impl XorShiftRng {
|
||||
}
|
||||
}
|
||||
let s: &[u32, ..4] = unsafe { cast::transmute(&s) };
|
||||
XorShiftRng::new_seeded(s[0], s[1], s[2], s[3])
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a random number generator using the specified seed. A generator
|
||||
* constructed with a given seed will generate the same sequence of values
|
||||
* as all other generators constructed with the same seed.
|
||||
*/
|
||||
pub fn new_seeded(x: u32, y: u32, z: u32, w: u32) -> XorShiftRng {
|
||||
XorShiftRng {
|
||||
x: x,
|
||||
y: y,
|
||||
z: z,
|
||||
w: w,
|
||||
}
|
||||
SeedableRng::from_seed(*s)
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new random seed of length `n`.
|
||||
pub fn seed(n: uint) -> ~[u8] {
|
||||
let mut s = vec::from_elem(n as uint, 0_u8);
|
||||
/// Create a new random seed of length `n`. This should only be used
|
||||
/// to create types for which *any* bit pattern is valid.
|
||||
pub unsafe fn seed<T: Clone>(n: uint) -> ~[T] {
|
||||
use unstable::intrinsics;
|
||||
let mut s = vec::from_elem(n, intrinsics::init());
|
||||
let mut r = OSRng::new();
|
||||
r.fill_bytes(s);
|
||||
|
||||
{
|
||||
let s_u8 = cast::transmute::<&mut [T], &mut [u8]>(s);
|
||||
r.fill_bytes(s_u8);
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
|
@ -97,6 +97,8 @@ mod test {
|
||||
use super::*;
|
||||
use rand::Rng;
|
||||
use default::Default;
|
||||
use iter::range;
|
||||
use option::{None, Some};
|
||||
|
||||
struct Counter {
|
||||
i: u32
|
||||
@ -117,7 +119,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_reseeding() {
|
||||
let mut rs = ReseedingRng::from_options(Counter {i:0}, 100, ReseedWithDefault);
|
||||
let mut rs = ReseedingRng::new(Counter {i:0}, 400, ReseedWithDefault);
|
||||
|
||||
let mut i = 0;
|
||||
for _ in range(0, 1000) {
|
||||
|
@ -26,7 +26,7 @@ use rt::local::Local;
|
||||
use rt::rtio::{RemoteCallback, PausibleIdleCallback};
|
||||
use borrow::{to_uint};
|
||||
use cell::Cell;
|
||||
use rand::{XorShiftRng, Rng, Rand};
|
||||
use rand::{SeedableRng, XorShiftRng, Rng, Rand};
|
||||
use iter::range;
|
||||
use vec::{OwnedVector};
|
||||
|
||||
@ -895,7 +895,7 @@ fn new_sched_rng() -> XorShiftRng {
|
||||
// know that the only way that we can fail here is `abort`ing?
|
||||
unsafe {libc::fclose(file);}
|
||||
|
||||
XorShiftRng::new_seeded(seeds[0], seeds[1], seeds[2], seeds[3])
|
||||
SeedableRng::from_seed(seeds)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -15,7 +15,7 @@ use extra::treemap::TreeMap;
|
||||
use std::hashmap::{HashMap, HashSet};
|
||||
use std::io;
|
||||
use std::os;
|
||||
use std::rand::Rng;
|
||||
use std::rand::{Rng, IsaacRng, SeedableRng};
|
||||
use std::trie::TrieMap;
|
||||
use std::uint;
|
||||
use std::vec;
|
||||
@ -106,7 +106,7 @@ fn main() {
|
||||
let mut rand = vec::with_capacity(n_keys);
|
||||
|
||||
{
|
||||
let mut rng = std::rand::IsaacRng::new_seeded([1, 1, 1, 1, 1, 1, 1]);
|
||||
let mut rng: IsaacRng = SeedableRng::from_seed(&[1, 1, 1, 1, 1, 1, 1]);
|
||||
let mut set = HashSet::new();
|
||||
while set.len() != n_keys {
|
||||
let next = rng.gen();
|
||||
|
@ -163,11 +163,11 @@ fn main() {
|
||||
}
|
||||
};
|
||||
|
||||
let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
let seed = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
let max = 200000;
|
||||
|
||||
{
|
||||
let mut rng = rand::IsaacRng::new_seeded(seed);
|
||||
let mut rng: rand::IsaacRng = rand::SeedableRng::from_seed(seed);
|
||||
let mut results = empty_results();
|
||||
results.bench_int(&mut rng, num_keys, max, || {
|
||||
let s: HashSet<uint> = HashSet::new();
|
||||
@ -181,7 +181,7 @@ fn main() {
|
||||
}
|
||||
|
||||
{
|
||||
let mut rng = rand::IsaacRng::new_seeded(seed);
|
||||
let mut rng: rand::IsaacRng = rand::SeedableRng::from_seed(seed);
|
||||
let mut results = empty_results();
|
||||
results.bench_int(&mut rng, num_keys, max, || {
|
||||
let s: TreeSet<uint> = TreeSet::new();
|
||||
@ -195,7 +195,7 @@ fn main() {
|
||||
}
|
||||
|
||||
{
|
||||
let mut rng = rand::IsaacRng::new_seeded(seed);
|
||||
let mut rng: rand::IsaacRng = rand::SeedableRng::from_seed(seed);
|
||||
let mut results = empty_results();
|
||||
results.bench_int(&mut rng, num_keys, max, || BitvSet::new());
|
||||
write_results("extra::bitv::BitvSet", &results);
|
||||
|
Loading…
Reference in New Issue
Block a user