1use p3_field::PrimeField64;
4use rand::RngCore;
5
6use crate::{Felt, Word};
7
8mod rpo;
9pub use rpo::RpoRandomCoin;
10
11mod rpx;
12pub use rpx::RpxRandomCoin;
13
14#[cfg(any(test, feature = "std"))]
16pub mod test_utils;
17
18pub trait Randomizable: Sized {
23 const VALUE_SIZE: usize;
28
29 fn from_random_bytes(source: &[u8]) -> Option<Self>;
31}
32
33impl Randomizable for u128 {
34 const VALUE_SIZE: usize = 16;
35
36 fn from_random_bytes(source: &[u8]) -> Option<Self> {
37 if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
38 Some(u128::from_le_bytes(bytes))
39 } else {
40 None
41 }
42 }
43}
44
45impl Randomizable for u64 {
46 const VALUE_SIZE: usize = 8;
47
48 fn from_random_bytes(source: &[u8]) -> Option<Self> {
49 if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
50 Some(u64::from_le_bytes(bytes))
51 } else {
52 None
53 }
54 }
55}
56
57impl Randomizable for u32 {
58 const VALUE_SIZE: usize = 4;
59
60 fn from_random_bytes(source: &[u8]) -> Option<Self> {
61 if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
62 Some(u32::from_le_bytes(bytes))
63 } else {
64 None
65 }
66 }
67}
68
69impl Randomizable for u16 {
70 const VALUE_SIZE: usize = 2;
71
72 fn from_random_bytes(source: &[u8]) -> Option<Self> {
73 if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
74 Some(u16::from_le_bytes(bytes))
75 } else {
76 None
77 }
78 }
79}
80
81impl Randomizable for u8 {
82 const VALUE_SIZE: usize = 1;
83
84 fn from_random_bytes(source: &[u8]) -> Option<Self> {
85 Some(source[0])
86 }
87}
88
89impl Randomizable for Felt {
90 const VALUE_SIZE: usize = 8;
91
92 fn from_random_bytes(source: &[u8]) -> Option<Self> {
93 if let Ok(bytes) = source[..Self::VALUE_SIZE].try_into() {
94 let value = u64::from_le_bytes(bytes);
95 if value < Felt::ORDER_U64 {
97 Some(Felt::new(value))
98 } else {
99 None
100 }
101 } else {
102 None
103 }
104 }
105}
106
107pub trait FeltRng: RngCore {
111 fn draw_element(&mut self) -> Felt;
113
114 fn draw_word(&mut self) -> Word;
116}
117
118#[cfg(feature = "std")]
125pub fn random_felt() -> Felt {
126 use rand::Rng;
127 let mut rng = rand::rng();
128 Felt::new(rng.random::<u64>())
131}
132
133#[cfg(feature = "std")]
137pub fn random_word() -> Word {
138 Word::new([random_felt(), random_felt(), random_felt(), random_felt()])
139}