fp/prime/
primes_generic.rs1use std::str::FromStr;
2
3use super::*;
4
5def_prime_static!(P2, 2);
6def_prime_static!(P3, 3);
7def_prime_static!(P5, 5);
8def_prime_static!(P7, 7);
9
10impl_prime_ops!(P2);
11impl_prime_ops!(P3);
12impl_prime_ops!(P5);
13impl_prime_ops!(P7);
14
15impl_try_from!(P2);
16impl_try_from!(P3);
17impl_try_from!(P5);
18impl_try_from!(P7);
19
20pub(crate) mod fp {
21 use super::{P2, P3, P5, P7};
22 use crate::field::Fp;
23
24 pub const F2: Fp<P2> = Fp::new(P2);
25 pub const F3: Fp<P3> = Fp::new(P3);
26 pub const F5: Fp<P5> = Fp::new(P5);
27 pub const F7: Fp<P7> = Fp::new(P7);
28}
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
31pub struct ValidPrime {
32 p: u32,
33}
34
35pub const fn is_prime(p: u32) -> bool {
36 let mut k = 2;
38 while k < p {
39 if p.is_multiple_of(k) {
40 return false;
41 }
42 k += 1;
43 }
44 true
45}
46
47impl ValidPrime {
48 pub const fn new(p: u32) -> Self {
49 assert!(p < (1 << 31), "Tried to construct a prime larger than 2^31");
60 assert!(is_prime(p), "Tried to construct a composite dynamic prime");
61 Self { p }
62 }
63
64 pub const fn new_unchecked(p: u32) -> Self {
65 Self { p }
66 }
67}
68
69impl Prime for ValidPrime {
70 fn as_i32(self) -> i32 {
71 self.p as i32
72 }
73
74 fn to_dyn(self) -> Self {
75 self
76 }
77}
78
79impl_prime_ops!(ValidPrime);
80
81impl TryFrom<u32> for ValidPrime {
82 type Error = PrimeError;
83
84 fn try_from(p: u32) -> Result<Self, PrimeError> {
85 if is_prime(p) {
86 Ok(Self { p })
87 } else {
88 Err(PrimeError::InvalidPrime(p))
89 }
90 }
91}
92
93impl FromStr for ValidPrime {
94 type Err = PrimeError;
95
96 fn from_str(s: &str) -> Result<Self, Self::Err> {
97 let p: u32 = s.parse().map_err(PrimeError::NotAnInteger)?;
98 Self::try_from(p)
99 }
100}
101
102impl Serialize for ValidPrime {
103 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
104 where
105 S: Serializer,
106 {
107 self.as_u32().serialize(serializer)
108 }
109}
110
111impl<'de> Deserialize<'de> for ValidPrime {
112 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
113 where
114 D: Deserializer<'de>,
115 {
116 let p: u32 = u32::deserialize(deserializer)?;
117 Self::try_from(p).map_err(D::Error::custom)
118 }
119}
120
121#[cfg(feature = "proptest")]
122impl proptest::arbitrary::Arbitrary for ValidPrime {
123 type Parameters = Option<std::num::NonZeroU32>;
124 type Strategy = proptest::sample::Select<Self>;
125
126 fn arbitrary_with(max: Self::Parameters) -> Self::Strategy {
129 use std::sync::OnceLock;
130
131 static TEST_PRIMES: OnceLock<Vec<ValidPrime>> = OnceLock::new();
132 let test_primes = TEST_PRIMES.get_or_init(|| {
133 const MAX: usize = 1 << 24;
135 let mut is_prime = Vec::new();
136 is_prime.resize_with(MAX, || true);
137 is_prime[0] = false;
138 is_prime[1] = false;
139 for i in 2..MAX {
140 if is_prime[i] {
141 for j in ((2 * i)..MAX).step_by(i) {
142 is_prime[j] = false;
143 }
144 }
145 }
146 (0..MAX)
147 .filter(|&i| is_prime[i])
148 .map(|p| Self::new_unchecked(p as u32))
149 .chain(std::iter::once(Self::new_unchecked(2147483647)))
150 .collect()
151 });
152 let restricted_slice = if let Some(max) = max {
153 let max_index = test_primes
154 .iter()
155 .position(|&p| p >= max.get())
156 .unwrap_or(test_primes.len());
157
158 &test_primes[..max_index]
159 } else {
160 test_primes
161 };
162 proptest::sample::select(restricted_slice)
163 }
164}
165
166impl crate::MaybeArbitrary<Option<NonZeroU32>> for ValidPrime {}