1pub mod prf;
2pub mod prg;
3pub mod rng;
4
5use rand::{distributions::Standard, prelude::Distribution};
6pub use rand_chacha::rand_core::CryptoRngCore;
7#[cfg(any(test, feature = "dev"))]
8pub use rng::test_rng;
9pub use rng::{BaseRng, Seed, SeedableRng};
10use subtle::Choice;
11use typenum::Unsigned;
12
13use crate::{
14 algebra::field::FieldExtension,
15 constants::Lambda,
16 errors::PrimitiveError,
17 utils::IntoExactSizeIterator,
18};
19
20pub trait Random: Sized {
23 fn random(rng: impl CryptoRngCore) -> Self;
25
26 fn random_n<Container: FromIterator<Self>>(
28 mut rng: impl CryptoRngCore,
29 size: usize,
30 ) -> Container {
31 (0..size).map(|_| Self::random(&mut rng)).collect()
32 }
33}
34
35impl<T> Random for T
37where
38 Standard: Distribution<T>,
39{
40 #[inline]
41 fn random(mut source: impl CryptoRngCore) -> Self {
42 Standard.sample(&mut source)
43 }
44}
45
46pub trait RandomWith<D: Clone>: Sized {
48 fn random_with(rng: impl CryptoRngCore, data: D) -> Self;
50
51 fn random_n_with<Container: FromIterator<Self>>(
53 mut rng: impl CryptoRngCore,
54 size: usize,
55 data: D,
56 ) -> Container {
57 (0..size)
58 .map(|_| Self::random_with(&mut rng, data.clone()))
59 .collect()
60 }
61
62 fn random_n_with_each<Container: FromIterator<Self>>(
64 mut rng: impl CryptoRngCore,
65 all_data: impl IntoExactSizeIterator<Item = D>,
66 ) -> Container {
67 all_data
68 .into_iter()
69 .map(|data| Self::random_with(&mut rng, data))
70 .collect()
71 }
72}
73
74pub trait RandomNonZero: Sized {
76 fn random_non_zero(rng: impl CryptoRngCore) -> Result<Self, PrimitiveError>;
78
79 fn random_n_non_zero<Container: FromIterator<Self>>(
81 rng: impl CryptoRngCore,
82 size: usize,
83 ) -> Result<Container, PrimitiveError>;
84}
85
86impl<T: FieldExtension> RandomNonZero for T {
87 #[inline]
102 fn random_non_zero(mut rng: impl CryptoRngCore) -> Result<Self, PrimitiveError> {
103 let n_tries = (Lambda::USIZE).div_ceil(std::mem::size_of::<Self>());
104 for _ in 0..n_tries {
105 let value = <Self as ff::Field>::random(&mut rng);
106 if !<Choice as Into<bool>>::into(value.is_zero()) {
107 return Ok(value);
108 }
109 }
110 Err(PrimitiveError::ZeroValueSampled(
111 std::any::type_name::<Self>().into(),
112 ))
113 }
114
115 fn random_n_non_zero<Container: FromIterator<Self>>(
117 mut rng: impl CryptoRngCore,
118 size: usize,
119 ) -> Result<Container, PrimitiveError> {
120 (0..size).map(|_| Self::random_non_zero(&mut rng)).collect()
121 }
122}