1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
//! This crates contains functions for generating random values.
//!
//! These functions are intended to be used in tests, benchmarks, and examples. When compiled to
//! WebAssembly target, all of the functions are omitted.
pub use internal::*;
#[cfg(not(target_family = "wasm"))]
mod internal {
use core::{convert::TryInto, fmt::Debug};
use rand::prelude::*;
use utils::Randomizable;
// RANDOM VALUE GENERATION
// ============================================================================================
/// Returns a single random value of the specified type.
///
/// # Panics
/// Panics if:
/// * A valid value requires at over 32 bytes.
/// * A valid value could not be generated after 100 tries.
pub fn rand_value<R: Randomizable>() -> R {
for _ in 0..100 {
let bytes = rand::thread_rng().gen::<[u8; 32]>();
if let Some(value) = R::from_random_bytes(&bytes[..R::VALUE_SIZE]) {
return value;
}
}
panic!("failed generate a random field element");
}
/// Returns a vector of random value of the specified type and the specified length.
///
/// # Panics
/// Panics if:
/// * A valid value requires at over 32 bytes.
/// * A valid value could not be generated after 100 tries.
pub fn rand_vector<R: Randomizable>(n: usize) -> Vec<R> {
let mut result = Vec::with_capacity(n);
let seed = rand::thread_rng().gen::<[u8; 32]>();
let mut g = StdRng::from_seed(seed);
for _ in 0..100 * n {
let bytes = g.gen::<[u8; 32]>();
if let Some(element) = R::from_random_bytes(&bytes[..R::VALUE_SIZE]) {
result.push(element);
if result.len() == n {
return result;
}
}
}
panic!("failed to generate enough random field elements");
}
/// Returns an array of random value of the specified type and the specified length.
///
/// # Panics
/// Panics if:
/// * A valid value requires at over 32 bytes.
/// * A valid value could not be generated after 100 tries.
pub fn rand_array<R: Randomizable + Debug, const N: usize>() -> [R; N] {
let elements = rand_vector(N);
elements
.try_into()
.expect("failed to convert vector to array")
}
/// Returns a vector of value of the specified type and the specified length generated
/// pseudo-randomly from the specified `seed`.
///
/// # Panics
/// Panics if:
/// * A valid value requires at over 32 bytes.
/// * A valid value could not be generated after 100 tries.
pub fn prng_vector<R: Randomizable>(seed: [u8; 32], n: usize) -> Vec<R> {
let mut result = Vec::with_capacity(n);
let mut g = StdRng::from_seed(seed);
for _ in 0..100 * n {
let bytes = g.gen::<[u8; 32]>();
if let Some(element) = R::from_random_bytes(&bytes[..R::VALUE_SIZE]) {
result.push(element);
if result.len() == n {
return result;
}
}
}
panic!("failed to generate enough random field elements");
}
/// Returns an array of value of the specified type and the specified length generated
/// pseudo-randomly from the specified `seed`.
///
/// # Panics
/// Panics if:
/// * A valid value requires at over 32 bytes.
/// * A valid value could not be generated after 100 tries.
pub fn prng_array<R: Randomizable + Debug, const N: usize>(seed: [u8; 32]) -> [R; N] {
let elements = prng_vector(seed, N);
elements
.try_into()
.expect("failed to convert vector to array")
}
// SHUFFLING
// ============================================================================================
/// Randomly shuffles slice elements.
pub fn shuffle<T>(values: &mut [T]) {
values.shuffle(&mut thread_rng());
}
}
#[cfg(target_family = "wasm")]
mod internal {}