algebraeon_rings/finite_fields/
quaternary_field.rs

1use crate::structure::*;
2use algebraeon_nzq::*;
3use algebraeon_sets::structure::*;
4use std::fmt::Display;
5
6//the finite field of 4 elements
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, CanonicalStructure)]
8#[canonical_structure(eq)]
9pub enum QuaternaryField {
10    Zero,
11    One,
12    Alpha,
13    Beta,
14}
15
16impl ToStringSignature for QuaternaryFieldCanonicalStructure {
17    fn to_string(&self, elem: &Self::Set) -> String {
18        format!("{}", elem)
19    }
20}
21
22impl Display for QuaternaryField {
23    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24        match self {
25            QuaternaryField::Zero => write!(f, "0"),
26            QuaternaryField::One => write!(f, "1"),
27            QuaternaryField::Alpha => write!(f, "a"),
28            QuaternaryField::Beta => write!(f, "b"),
29        }
30    }
31}
32
33impl RinglikeSpecializationSignature for QuaternaryFieldCanonicalStructure {}
34
35impl ZeroSignature for QuaternaryFieldCanonicalStructure {
36    fn zero(&self) -> Self::Set {
37        QuaternaryField::Zero
38    }
39}
40
41impl AdditionSignature for QuaternaryFieldCanonicalStructure {
42    fn add(&self, a: &Self::Set, b: &Self::Set) -> Self::Set {
43        #[allow(clippy::match_same_arms)]
44        match (a, b) {
45            (_, QuaternaryField::Zero) => *a,
46            (QuaternaryField::Zero, _) => *b,
47            (QuaternaryField::One, QuaternaryField::One) => QuaternaryField::Zero,
48            (QuaternaryField::One, QuaternaryField::Alpha) => QuaternaryField::Beta,
49            (QuaternaryField::One, QuaternaryField::Beta) => QuaternaryField::Alpha,
50            (QuaternaryField::Alpha, QuaternaryField::One) => QuaternaryField::Beta,
51            (QuaternaryField::Alpha, QuaternaryField::Alpha) => QuaternaryField::Zero,
52            (QuaternaryField::Alpha, QuaternaryField::Beta) => QuaternaryField::One,
53            (QuaternaryField::Beta, QuaternaryField::One) => QuaternaryField::Alpha,
54            (QuaternaryField::Beta, QuaternaryField::Alpha) => QuaternaryField::One,
55            (QuaternaryField::Beta, QuaternaryField::Beta) => QuaternaryField::Zero,
56        }
57    }
58}
59
60impl CancellativeAdditionSignature for QuaternaryFieldCanonicalStructure {
61    fn try_sub(&self, a: &Self::Set, b: &Self::Set) -> Option<Self::Set> {
62        Some(self.sub(a, b))
63    }
64}
65
66impl TryNegateSignature for QuaternaryFieldCanonicalStructure {
67    fn try_neg(&self, a: &Self::Set) -> Option<Self::Set> {
68        Some(self.neg(a))
69    }
70}
71
72impl AdditiveMonoidSignature for QuaternaryFieldCanonicalStructure {}
73
74impl OneSignature for QuaternaryFieldCanonicalStructure {
75    fn one(&self) -> Self::Set {
76        QuaternaryField::One
77    }
78}
79
80impl MultiplicationSignature for QuaternaryFieldCanonicalStructure {
81    fn mul(&self, a: &Self::Set, b: &Self::Set) -> Self::Set {
82        #[allow(clippy::match_same_arms)]
83        match (a, b) {
84            (_, QuaternaryField::Zero) => QuaternaryField::Zero,
85            (QuaternaryField::Zero, _) => QuaternaryField::Zero,
86            (_, QuaternaryField::One) => *a,
87            (QuaternaryField::One, _) => *b,
88            (QuaternaryField::Alpha, QuaternaryField::Alpha) => QuaternaryField::Beta,
89            (QuaternaryField::Alpha, QuaternaryField::Beta) => QuaternaryField::One,
90            (QuaternaryField::Beta, QuaternaryField::Alpha) => QuaternaryField::One,
91            (QuaternaryField::Beta, QuaternaryField::Beta) => QuaternaryField::Alpha,
92        }
93    }
94}
95
96impl CommutativeMultiplicationSignature for QuaternaryFieldCanonicalStructure {}
97
98impl MultiplicativeMonoidSignature for QuaternaryFieldCanonicalStructure {}
99
100impl MultiplicativeAbsorptionMonoidSignature for QuaternaryFieldCanonicalStructure {}
101
102impl LeftDistributiveMultiplicationOverAddition for QuaternaryFieldCanonicalStructure {}
103
104impl RightDistributiveMultiplicationOverAddition for QuaternaryFieldCanonicalStructure {}
105
106impl SemiRingSignature for QuaternaryFieldCanonicalStructure {}
107
108impl RingSignature for QuaternaryFieldCanonicalStructure {
109    fn is_reduced(&self) -> Result<bool, String> {
110        Ok(true)
111    }
112}
113
114impl CharacteristicSignature for QuaternaryFieldCanonicalStructure {
115    fn characteristic(&self) -> Natural {
116        Natural::TWO
117    }
118}
119
120impl AdditiveGroupSignature for QuaternaryFieldCanonicalStructure {
121    fn neg(&self, a: &Self::Set) -> Self::Set {
122        *a
123    }
124}
125
126impl TryReciprocalSignature for QuaternaryFieldCanonicalStructure {
127    fn try_reciprocal(&self, a: &Self::Set) -> Option<Self::Set> {
128        self.try_divide(&self.one(), a)
129    }
130}
131
132impl CancellativeMultiplicationSignature for QuaternaryFieldCanonicalStructure {
133    fn try_divide(&self, a: &Self::Set, b: &Self::Set) -> Option<Self::Set> {
134        #[allow(clippy::match_same_arms)]
135        match (&a, &b) {
136            (_, QuaternaryField::Zero) => None,
137            (_, QuaternaryField::One) => Some(*a),
138            (QuaternaryField::Zero, _) => Some(QuaternaryField::Zero),
139            (QuaternaryField::One, QuaternaryField::Alpha) => Some(QuaternaryField::Beta),
140            (QuaternaryField::One, QuaternaryField::Beta) => Some(QuaternaryField::Alpha),
141            (QuaternaryField::Alpha, QuaternaryField::Alpha) => Some(QuaternaryField::One),
142            (QuaternaryField::Alpha, QuaternaryField::Beta) => Some(QuaternaryField::Beta),
143            (QuaternaryField::Beta, QuaternaryField::Alpha) => Some(QuaternaryField::Alpha),
144            (QuaternaryField::Beta, QuaternaryField::Beta) => Some(QuaternaryField::One),
145        }
146    }
147}
148
149impl MultiplicativeIntegralMonoidSignature for QuaternaryFieldCanonicalStructure {}
150
151impl IntegralDomainSignature for QuaternaryFieldCanonicalStructure {}
152
153impl FieldSignature for QuaternaryFieldCanonicalStructure {}
154
155impl<B: BorrowedStructure<QuaternaryFieldCanonicalStructure>> CountableSetSignature
156    for MultiplicativeMonoidUnitsStructure<QuaternaryFieldCanonicalStructure, B>
157{
158    fn generate_all_elements(&self) -> impl Iterator<Item = Self::Set> + Clone {
159        self.list_all_elements().into_iter()
160    }
161}
162
163impl<B: BorrowedStructure<QuaternaryFieldCanonicalStructure>> FiniteSetSignature
164    for MultiplicativeMonoidUnitsStructure<QuaternaryFieldCanonicalStructure, B>
165{
166    fn list_all_elements(&self) -> Vec<Self::Set> {
167        vec![
168            QuaternaryField::One,
169            QuaternaryField::Alpha,
170            QuaternaryField::Beta,
171        ]
172    }
173}
174
175impl CountableSetSignature for QuaternaryFieldCanonicalStructure {
176    fn generate_all_elements(&self) -> impl Iterator<Item = Self::Set> + Clone {
177        self.all_units_and_zero().into_iter()
178    }
179}
180
181impl FiniteSetSignature for QuaternaryFieldCanonicalStructure {}
182
183impl FiniteFieldSignature for QuaternaryFieldCanonicalStructure {
184    fn characteristic_and_power(&self) -> (Natural, Natural) {
185        (Natural::from(2u8), Natural::from(2u8))
186    }
187}
188
189#[cfg(test)]
190mod tests {
191    use super::*;
192
193    #[test]
194    fn test_neg() {
195        assert_eq!(QuaternaryField::Zero.neg(), QuaternaryField::Zero);
196        assert_eq!(QuaternaryField::One.neg(), QuaternaryField::One);
197        assert_eq!(QuaternaryField::Alpha.neg(), QuaternaryField::Alpha);
198        assert_eq!(QuaternaryField::Beta.neg(), QuaternaryField::Beta);
199    }
200
201    #[test]
202    fn test_add() {
203        assert_eq!(
204            QuaternaryField::add(&QuaternaryField::Zero, &QuaternaryField::Zero),
205            QuaternaryField::Zero
206        );
207        assert_eq!(
208            QuaternaryField::add(&QuaternaryField::Zero, &QuaternaryField::One),
209            QuaternaryField::One
210        );
211        assert_eq!(
212            QuaternaryField::add(&QuaternaryField::Zero, &QuaternaryField::Alpha),
213            QuaternaryField::Alpha
214        );
215        assert_eq!(
216            QuaternaryField::add(&QuaternaryField::Zero, &QuaternaryField::Beta),
217            QuaternaryField::Beta
218        );
219        assert_eq!(
220            QuaternaryField::add(&QuaternaryField::One, &QuaternaryField::Zero),
221            QuaternaryField::One
222        );
223        assert_eq!(
224            QuaternaryField::add(&QuaternaryField::One, &QuaternaryField::One),
225            QuaternaryField::Zero
226        );
227        assert_eq!(
228            QuaternaryField::add(&QuaternaryField::One, &QuaternaryField::Alpha),
229            QuaternaryField::Beta
230        );
231        assert_eq!(
232            QuaternaryField::add(&QuaternaryField::One, &QuaternaryField::Beta),
233            QuaternaryField::Alpha
234        );
235        assert_eq!(
236            QuaternaryField::add(&QuaternaryField::Alpha, &QuaternaryField::Zero),
237            QuaternaryField::Alpha
238        );
239        assert_eq!(
240            QuaternaryField::add(&QuaternaryField::Alpha, &QuaternaryField::One),
241            QuaternaryField::Beta
242        );
243        assert_eq!(
244            QuaternaryField::add(&QuaternaryField::Alpha, &QuaternaryField::Alpha),
245            QuaternaryField::Zero
246        );
247        assert_eq!(
248            QuaternaryField::add(&QuaternaryField::Alpha, &QuaternaryField::Beta),
249            QuaternaryField::One
250        );
251        assert_eq!(
252            QuaternaryField::add(&QuaternaryField::Beta, &QuaternaryField::Zero),
253            QuaternaryField::Beta
254        );
255        assert_eq!(
256            QuaternaryField::add(&QuaternaryField::Beta, &QuaternaryField::One),
257            QuaternaryField::Alpha
258        );
259        assert_eq!(
260            QuaternaryField::add(&QuaternaryField::Beta, &QuaternaryField::Alpha),
261            QuaternaryField::One
262        );
263        assert_eq!(
264            QuaternaryField::add(&QuaternaryField::Beta, &QuaternaryField::Beta),
265            QuaternaryField::Zero
266        );
267    }
268
269    #[test]
270    fn test_mul() {
271        assert_eq!(
272            QuaternaryField::mul(&QuaternaryField::Zero, &QuaternaryField::Zero),
273            QuaternaryField::Zero
274        );
275        assert_eq!(
276            QuaternaryField::mul(&QuaternaryField::Zero, &QuaternaryField::One),
277            QuaternaryField::Zero
278        );
279        assert_eq!(
280            QuaternaryField::mul(&QuaternaryField::Zero, &QuaternaryField::Alpha),
281            QuaternaryField::Zero
282        );
283        assert_eq!(
284            QuaternaryField::mul(&QuaternaryField::Zero, &QuaternaryField::Beta),
285            QuaternaryField::Zero
286        );
287        assert_eq!(
288            QuaternaryField::mul(&QuaternaryField::One, &QuaternaryField::Zero),
289            QuaternaryField::Zero
290        );
291        assert_eq!(
292            QuaternaryField::mul(&QuaternaryField::One, &QuaternaryField::One),
293            QuaternaryField::One
294        );
295        assert_eq!(
296            QuaternaryField::mul(&QuaternaryField::One, &QuaternaryField::Alpha),
297            QuaternaryField::Alpha
298        );
299        assert_eq!(
300            QuaternaryField::mul(&QuaternaryField::One, &QuaternaryField::Beta),
301            QuaternaryField::Beta
302        );
303        assert_eq!(
304            QuaternaryField::mul(&QuaternaryField::Alpha, &QuaternaryField::Zero),
305            QuaternaryField::Zero
306        );
307        assert_eq!(
308            QuaternaryField::mul(&QuaternaryField::Alpha, &QuaternaryField::One),
309            QuaternaryField::Alpha
310        );
311        assert_eq!(
312            QuaternaryField::mul(&QuaternaryField::Alpha, &QuaternaryField::Alpha),
313            QuaternaryField::Beta
314        );
315        assert_eq!(
316            QuaternaryField::mul(&QuaternaryField::Alpha, &QuaternaryField::Beta),
317            QuaternaryField::One
318        );
319        assert_eq!(
320            QuaternaryField::mul(&QuaternaryField::Beta, &QuaternaryField::Zero),
321            QuaternaryField::Zero
322        );
323        assert_eq!(
324            QuaternaryField::mul(&QuaternaryField::Beta, &QuaternaryField::One),
325            QuaternaryField::Beta
326        );
327        assert_eq!(
328            QuaternaryField::mul(&QuaternaryField::Beta, &QuaternaryField::Alpha),
329            QuaternaryField::One
330        );
331        assert_eq!(
332            QuaternaryField::mul(&QuaternaryField::Beta, &QuaternaryField::Beta),
333            QuaternaryField::Alpha
334        );
335    }
336
337    #[test]
338    fn test_divide() {
339        assert_eq!(
340            QuaternaryField::try_divide(&QuaternaryField::Zero, &QuaternaryField::Zero),
341            None
342        );
343        assert_eq!(
344            QuaternaryField::try_divide(&QuaternaryField::Zero, &QuaternaryField::One),
345            Some(QuaternaryField::Zero)
346        );
347        assert_eq!(
348            QuaternaryField::try_divide(&QuaternaryField::Zero, &QuaternaryField::Alpha),
349            Some(QuaternaryField::Zero)
350        );
351        assert_eq!(
352            QuaternaryField::try_divide(&QuaternaryField::Zero, &QuaternaryField::Beta),
353            Some(QuaternaryField::Zero)
354        );
355        assert_eq!(
356            QuaternaryField::try_divide(&QuaternaryField::One, &QuaternaryField::Zero),
357            None
358        );
359        assert_eq!(
360            QuaternaryField::try_divide(&QuaternaryField::One, &QuaternaryField::One),
361            Some(QuaternaryField::One)
362        );
363        assert_eq!(
364            QuaternaryField::try_divide(&QuaternaryField::One, &QuaternaryField::Alpha),
365            Some(QuaternaryField::Beta)
366        );
367        assert_eq!(
368            QuaternaryField::try_divide(&QuaternaryField::One, &QuaternaryField::Beta),
369            Some(QuaternaryField::Alpha)
370        );
371        assert_eq!(
372            QuaternaryField::try_divide(&QuaternaryField::Alpha, &QuaternaryField::Zero),
373            None
374        );
375        assert_eq!(
376            QuaternaryField::try_divide(&QuaternaryField::Alpha, &QuaternaryField::One),
377            Some(QuaternaryField::Alpha)
378        );
379        assert_eq!(
380            QuaternaryField::try_divide(&QuaternaryField::Alpha, &QuaternaryField::Alpha),
381            Some(QuaternaryField::One)
382        );
383        assert_eq!(
384            QuaternaryField::try_divide(&QuaternaryField::Alpha, &QuaternaryField::Beta),
385            Some(QuaternaryField::Beta)
386        );
387        assert_eq!(
388            QuaternaryField::try_divide(&QuaternaryField::Beta, &QuaternaryField::Zero),
389            None
390        );
391        assert_eq!(
392            QuaternaryField::try_divide(&QuaternaryField::Beta, &QuaternaryField::One),
393            Some(QuaternaryField::Beta)
394        );
395        assert_eq!(
396            QuaternaryField::try_divide(&QuaternaryField::Beta, &QuaternaryField::Alpha),
397            Some(QuaternaryField::Alpha)
398        );
399        assert_eq!(
400            QuaternaryField::try_divide(&QuaternaryField::Beta, &QuaternaryField::Beta),
401            Some(QuaternaryField::One)
402        );
403    }
404}