algebraeon_rings/finite_fields/
modulo.rs1use crate::structure::*;
2use algebraeon_nzq::traits::Abs;
3use algebraeon_nzq::*;
4use algebraeon_sets::structure::*;
5use std::{fmt::Display, hash::Hash};
6
7fn xgcd(mut x: usize, mut y: usize) -> (usize, isize, isize) {
8 let mut pa = 1;
9 let mut a = 0;
10 let mut pb = 0;
11 let mut b = 1;
12 while y != 0 {
13 let (q, r) = (x / y, x % y);
14 let new_a = pa - q as isize * a;
15 (a, pa) = (new_a, a);
16 let new_b = pb - q as isize * b;
17 (b, pb) = (new_b, b);
18 (x, y) = (y, r);
19 }
20 (x, pa, pb)
21}
22
23fn modulo(a: isize, n: usize) -> usize {
24 let mut a = a % n as isize;
25 if a < 0 {
26 a += n as isize;
27 }
28 a as usize
29}
30
31#[derive(Clone)]
32pub struct Modulo<const N: usize> {
33 x: usize,
34}
35
36impl<const N: usize> Modulo<N> {
37 pub const fn new(x: usize) -> Self {
38 Self { x }
39 }
40}
41
42impl<const N: usize> std::fmt::Debug for Modulo<N> {
43 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44 f.debug_struct("Modulo")
45 .field("x", &self.x)
46 .field("N", &N)
47 .finish()
48 }
49}
50
51impl<const N: usize> Modulo<N> {
52 pub fn lift_nat(&self) -> Natural {
53 Natural::from(self.x)
54 }
55 pub fn lift_int(&self) -> Integer {
56 Integer::from(self.x)
57 }
58}
59
60impl<const N: usize> From<&Integer> for Modulo<N> {
61 fn from(value: &Integer) -> Self {
62 let value = value % Integer::from(N);
63 let value = value.abs();
64 Self {
65 x: value.try_into().unwrap(),
66 }
67 }
68}
69impl<const N: usize> From<Integer> for Modulo<N> {
70 fn from(value: Integer) -> Self {
71 let value = value % Integer::from(N);
72 let value = value.abs();
73 Self {
74 x: value.try_into().unwrap(),
75 }
76 }
77}
78impl<const N: usize> From<usize> for Modulo<N> {
79 fn from(value: usize) -> Self {
80 Self { x: value % N }
81 }
82}
83impl<const N: usize> From<isize> for Modulo<N> {
84 fn from(value: isize) -> Self {
85 Self {
86 x: modulo(value, N),
87 }
88 }
89}
90impl<const N: usize> From<i32> for Modulo<N> {
91 fn from(value: i32) -> Self {
92 Self {
93 x: modulo(value as isize, N),
94 }
95 }
96}
97
98impl<const N: usize> From<Modulo<N>> for usize {
99 fn from(value: Modulo<N>) -> Self {
100 value.x
101 }
102}
103
104impl<const N: usize> PartialEq for Modulo<N> {
105 fn eq(&self, other: &Self) -> bool {
106 self.x == other.x
107 }
108}
109impl<const N: usize> Eq for Modulo<N> {}
110impl<const N: usize> Hash for Modulo<N> {
111 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
112 self.x.hash(state);
113 }
114}
115
116impl<const N: usize> Display for Modulo<N> {
117 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118 write!(f, "{}", self.x)
119 }
120}
121
122#[derive(Debug, Clone, PartialEq, Eq)]
123pub struct ModuloCanonicalStructure<const N: usize> {}
124
125impl<const N: usize> Signature for ModuloCanonicalStructure<N> {}
126
127impl<const N: usize> SetSignature for ModuloCanonicalStructure<N> {
128 type Set = Modulo<N>;
129
130 fn is_element(&self, _x: &Self::Set) -> Result<(), String> {
131 Ok(())
132 }
133}
134
135impl<const N: usize> MetaType for Modulo<N> {
136 type Signature = ModuloCanonicalStructure<N>;
137
138 fn structure() -> Self::Signature {
139 ModuloCanonicalStructure {}
140 }
141}
142
143impl<const N: usize> EqSignature for ModuloCanonicalStructure<N> {
144 fn equal(&self, a: &Self::Set, b: &Self::Set) -> bool {
145 a == b
146 }
147}
148
149impl<const N: usize> ToStringSignature for ModuloCanonicalStructure<N> {
150 fn to_string(&self, elem: &Self::Set) -> String {
151 format!("{}", elem)
152 }
153}
154
155impl<const N: usize> RinglikeSpecializationSignature for ModuloCanonicalStructure<N> {}
156
157impl<const N: usize> ZeroSignature for ModuloCanonicalStructure<N> {
158 fn zero(&self) -> Self::Set {
159 Modulo { x: 0 }
160 }
161}
162
163impl<const N: usize> AdditionSignature for ModuloCanonicalStructure<N> {
164 fn add(&self, a: &Self::Set, b: &Self::Set) -> Self::Set {
165 Modulo { x: (a.x + b.x) % N }
166 }
167}
168
169impl<const N: usize> CancellativeAdditionSignature for ModuloCanonicalStructure<N> {
170 fn try_sub(&self, a: &Self::Set, b: &Self::Set) -> Option<Self::Set> {
171 Some(self.sub(a, b))
172 }
173}
174
175impl<const N: usize> TryNegateSignature for ModuloCanonicalStructure<N> {
176 fn try_neg(&self, a: &Self::Set) -> Option<Self::Set> {
177 Some(self.neg(a))
178 }
179}
180
181impl<const N: usize> AdditiveMonoidSignature for ModuloCanonicalStructure<N> {}
182
183impl<const N: usize> AdditiveGroupSignature for ModuloCanonicalStructure<N> {
184 fn neg(&self, a: &Self::Set) -> Self::Set {
185 if a.x == 0 {
186 Modulo { x: 0 }
187 } else {
188 Modulo { x: N - a.x }
189 }
190 }
191}
192
193impl<const N: usize> OneSignature for ModuloCanonicalStructure<N> {
194 fn one(&self) -> Self::Set {
195 if N == 1 {
196 Modulo { x: 0 }
197 } else {
198 Modulo { x: 1 }
199 }
200 }
201}
202
203impl<const N: usize> MultiplicationSignature for ModuloCanonicalStructure<N> {
204 fn mul(&self, a: &Self::Set, b: &Self::Set) -> Self::Set {
205 Modulo { x: (a.x * b.x) % N }
206 }
207}
208
209impl<const N: usize> CommutativeMultiplicationSignature for ModuloCanonicalStructure<N> {}
210
211impl<const N: usize> MultiplicativeMonoidSignature for ModuloCanonicalStructure<N> {}
212
213impl<const N: usize> MultiplicativeAbsorptionMonoidSignature for ModuloCanonicalStructure<N> {}
214
215impl<const N: usize> LeftDistributiveMultiplicationOverAddition for ModuloCanonicalStructure<N> {}
216
217impl<const N: usize> RightDistributiveMultiplicationOverAddition for ModuloCanonicalStructure<N> {}
218
219impl<const N: usize> SemiRingSignature for ModuloCanonicalStructure<N> {}
220
221impl<const N: usize> RingSignature for ModuloCanonicalStructure<N> {}
222
223impl<const N: usize> CharacteristicSignature for ModuloCanonicalStructure<N> {
224 fn characteristic(&self) -> Natural {
225 Natural::from(N)
226 }
227}
228
229impl<const N: usize> TryReciprocalSignature for ModuloCanonicalStructure<N> {
230 fn try_reciprocal(&self, x: &Self::Set) -> Option<Self::Set> {
231 if x == &self.zero() {
232 None
233 } else {
234 let (g, a, b) = xgcd(x.x, N);
235 debug_assert_eq!(g as isize, a * x.x as isize + b * N as isize);
236 if g == 1 {
237 Some(Modulo { x: modulo(a, N) })
238 } else {
239 None
240 }
241 }
242 }
243}
244
245impl<const N: usize> CountableSetSignature for ModuloCanonicalStructure<N> {
246 fn generate_all_elements(&self) -> impl Iterator<Item = Self::Set> + Clone {
247 (0..N).map(Modulo::new)
248 }
249}
250
251impl<const N: usize> FiniteSetSignature for ModuloCanonicalStructure<N> {
252 fn size(&self) -> usize {
253 N
254 }
255}
256
257macro_rules! impl_field {
258 ($N: literal) => {
259 impl CancellativeMultiplicationSignature for ModuloCanonicalStructure<$N> {
260 fn try_divide(&self, top: &Self::Set, bot: &Self::Set) -> Option<Self::Set> {
261 Some(self.mul(top, &self.try_reciprocal(bot)?))
262 }
263 }
264
265 impl MultiplicativeIntegralMonoidSignature for ModuloCanonicalStructure<$N> {}
266
267 impl IntegralDomainSignature for ModuloCanonicalStructure<$N> {}
268
269 impl FieldSignature for ModuloCanonicalStructure<$N> {}
270
271 impl<B: BorrowedStructure<ModuloCanonicalStructure<$N>>> CountableSetSignature
272 for MultiplicativeMonoidUnitsStructure<ModuloCanonicalStructure<$N>, B>
273 {
274 fn generate_all_elements(
275 &self,
276 ) -> impl std::iter::Iterator<Item = Modulo<$N>> + std::clone::Clone {
277 (1..$N).map(|i| Modulo { x: i })
278 }
279 }
280
281 impl<B: BorrowedStructure<ModuloCanonicalStructure<$N>>> FiniteSetSignature
282 for MultiplicativeMonoidUnitsStructure<ModuloCanonicalStructure<$N>, B>
283 {
284 }
285
286 impl FiniteFieldSignature for ModuloCanonicalStructure<$N> {
287 fn characteristic_and_power(&self) -> (Natural, Natural) {
288 (Natural::from($N as usize), Natural::from(1u8))
289 }
290 }
291 };
292}
293
294impl_field!(2);
295impl_field!(3);
296impl_field!(5);
297impl_field!(7);
298impl_field!(11);
299impl_field!(13);
300impl_field!(17);
301impl_field!(19);
302impl_field!(23);
303impl_field!(29);
304impl_field!(31);
305impl_field!(37);
306impl_field!(41);
307impl_field!(43);
308impl_field!(47);
309impl_field!(53);
310impl_field!(59);
311impl_field!(61);
312impl_field!(67);
313impl_field!(71);
314impl_field!(73);
315impl_field!(79);
316impl_field!(83);
317impl_field!(89);
318impl_field!(97);
319impl_field!(101);
320impl_field!(103);
321impl_field!(107);
322impl_field!(109);
323impl_field!(113);
324impl_field!(127);
325impl_field!(131);
326impl_field!(137);
327impl_field!(139);
328impl_field!(149);
329impl_field!(151);
330impl_field!(157);
331impl_field!(163);
332impl_field!(167);
333impl_field!(173);
334impl_field!(179);
335impl_field!(181);
336impl_field!(191);
337impl_field!(193);
338impl_field!(197);
339impl_field!(199);
340impl_field!(211);
341impl_field!(223);
342impl_field!(227);
343impl_field!(229);
344impl_field!(233);
345impl_field!(239);
346impl_field!(241);
347impl_field!(251);
348impl_field!(257);
349impl_field!(263);
350impl_field!(269);
351impl_field!(271);
352impl_field!(277);
353impl_field!(281);
354impl_field!(283);
355impl_field!(293);
356impl_field!(307);
357impl_field!(311);
358impl_field!(313);
359impl_field!(317);
360impl_field!(331);
361impl_field!(337);
362impl_field!(347);
363impl_field!(349);
364impl_field!(353);
365impl_field!(359);
366impl_field!(367);
367impl_field!(373);
368impl_field!(379);
369impl_field!(383);
370impl_field!(389);
371impl_field!(397);
372impl_field!(401);
373impl_field!(409);
374impl_field!(419);
375impl_field!(421);
376impl_field!(431);
377impl_field!(433);
378impl_field!(439);
379impl_field!(443);
380impl_field!(449);
381impl_field!(457);
382impl_field!(461);
383impl_field!(463);
384impl_field!(467);
385impl_field!(479);
386impl_field!(487);
387impl_field!(491);
388impl_field!(499);
389impl_field!(503);
390impl_field!(509);
391impl_field!(521);
392impl_field!(523);
393impl_field!(541);
394impl_field!(547);
395impl_field!(557);
396impl_field!(563);
397impl_field!(569);
398impl_field!(571);
399impl_field!(577);
400impl_field!(587);
401impl_field!(593);
402impl_field!(599);
403impl_field!(601);
404impl_field!(607);
405impl_field!(613);
406impl_field!(617);
407impl_field!(619);
408impl_field!(631);
409impl_field!(641);
410impl_field!(643);
411impl_field!(647);
412impl_field!(653);
413impl_field!(659);
414impl_field!(661);
415impl_field!(673);
416impl_field!(677);
417impl_field!(683);
418impl_field!(691);
419impl_field!(701);
420impl_field!(709);
421impl_field!(719);
422impl_field!(727);
423impl_field!(733);
424impl_field!(739);
425impl_field!(743);
426impl_field!(751);
427impl_field!(757);
428impl_field!(761);
429impl_field!(769);
430impl_field!(773);
431impl_field!(787);
432impl_field!(797);
433impl_field!(809);
434impl_field!(811);
435impl_field!(821);
436impl_field!(823);
437impl_field!(827);
438impl_field!(829);
439impl_field!(839);
440impl_field!(853);
441impl_field!(857);
442impl_field!(859);
443impl_field!(863);
444impl_field!(877);
445impl_field!(881);
446impl_field!(883);
447impl_field!(887);
448impl_field!(907);
449impl_field!(911);
450impl_field!(919);
451impl_field!(929);
452impl_field!(937);
453impl_field!(941);
454impl_field!(947);
455impl_field!(953);
456impl_field!(967);
457impl_field!(971);
458impl_field!(977);
459impl_field!(983);
460impl_field!(991);
461impl_field!(997);
462#[cfg(test)]
465mod tests {
466 use super::*;
467
468 #[test]
469 fn test_gcd_lcm() {
470 for x in 0..100 {
471 for y in 0..100 {
472 let (g, a, b) = xgcd(x, y);
473 assert_eq!(g as isize, a * x as isize + b * y as isize);
474 }
475 }
476 }
477
478 #[test]
479 fn count_elements() {
480 assert_eq!(Modulo::<26>::structure().list_all_elements().len(), 26);
481 }
482}