pub mod prf;
pub mod prg;
pub mod rng;
use rand::{distributions::Standard, prelude::Distribution};
pub use rand_chacha::rand_core::CryptoRngCore;
#[cfg(any(test, feature = "dev"))]
pub use rng::test_rng;
pub use rng::{BaseRng, Seed, SeedableRng};
use subtle::Choice;
use typenum::Unsigned;
use crate::{
algebra::field::FieldExtension,
constants::Lambda,
errors::PrimitiveError,
utils::IntoExactSizeIterator,
};
pub trait Random: Sized {
fn random(rng: impl CryptoRngCore) -> Self;
fn random_n<Container: FromIterator<Self>>(
mut rng: impl CryptoRngCore,
size: usize,
) -> Container {
(0..size).map(|_| Self::random(&mut rng)).collect()
}
}
impl<T> Random for T
where
Standard: Distribution<T>,
{
#[inline]
fn random(mut source: impl CryptoRngCore) -> Self {
Standard.sample(&mut source)
}
}
pub trait RandomWith<D: Clone>: Sized {
fn random_with(rng: impl CryptoRngCore, data: D) -> Self;
fn random_n_with<Container: FromIterator<Self>>(
mut rng: impl CryptoRngCore,
size: usize,
data: D,
) -> Container {
(0..size)
.map(|_| Self::random_with(&mut rng, data.clone()))
.collect()
}
fn random_n_with_each<Container: FromIterator<Self>>(
mut rng: impl CryptoRngCore,
all_data: impl IntoExactSizeIterator<Item = D>,
) -> Container {
all_data
.into_iter()
.map(|data| Self::random_with(&mut rng, data))
.collect()
}
}
pub trait RandomNonZero: Sized {
fn random_non_zero(rng: impl CryptoRngCore) -> Result<Self, PrimitiveError>;
fn random_n_non_zero<Container: FromIterator<Self>>(
rng: impl CryptoRngCore,
size: usize,
) -> Result<Container, PrimitiveError>;
}
impl<T: FieldExtension> RandomNonZero for T {
#[inline]
fn random_non_zero(mut rng: impl CryptoRngCore) -> Result<Self, PrimitiveError> {
let n_tries = (Lambda::USIZE).div_ceil(std::mem::size_of::<Self>());
for _ in 0..n_tries {
let value = <Self as ff::Field>::random(&mut rng);
if !<Choice as Into<bool>>::into(value.is_zero()) {
return Ok(value);
}
}
Err(PrimitiveError::ZeroValueSampled(
std::any::type_name::<Self>().into(),
))
}
fn random_n_non_zero<Container: FromIterator<Self>>(
mut rng: impl CryptoRngCore,
size: usize,
) -> Result<Container, PrimitiveError> {
(0..size).map(|_| Self::random_non_zero(&mut rng)).collect()
}
}