1use crate::structure::*;
2use algebraeon_sets::structure::*;
3use std::{borrow::Borrow, marker::PhantomData};
4
5#[derive(Debug, Clone)]
7pub struct EuclideanRemainderQuotientStructure<
8 RS: EuclideanDomainSignature,
9 RSB: BorrowedStructure<RS>,
10 const IS_FIELD: bool,
11> {
12 _ring: PhantomData<RS>,
13 ring: RSB,
14 modulus: RS::Set,
15}
16
17impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool>
18 EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
19{
20 pub fn new_unchecked(ring: RSB, modulus: RS::Set) -> Self {
21 assert!(!ring.borrow().is_zero(&modulus));
22 Self {
23 _ring: PhantomData,
24 ring,
25 modulus,
26 }
27 }
28
29 pub fn ring(&self) -> &RS {
30 self.ring.borrow()
31 }
32
33 pub fn modulus(&self) -> &RS::Set {
34 &self.modulus
35 }
36
37 pub fn reduce(&self, a: impl Borrow<RS::Set>) -> RS::Set {
38 self.ring().rem(a.borrow(), &self.modulus)
39 }
40}
41
42impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>>
43 EuclideanRemainderQuotientStructure<RS, RSB, false>
44{
45 fn new_ring(ring: RSB, modulus: RS::Set) -> Self {
46 Self::new_unchecked(ring, modulus)
47 }
48}
49
50impl<RS: EuclideanDomainSignature + FactoringMonoidSignature, RSB: BorrowedStructure<RS>>
51 EuclideanRemainderQuotientStructure<RS, RSB, true>
52{
53 fn new_field_unchecked(ring: RSB, modulus: RS::Set) -> Self {
54 debug_assert!(ring.borrow().is_irreducible(&modulus));
55 Self::new_unchecked(ring, modulus)
56 }
57
58 fn new_field(ring: RSB, modulus: RS::Set) -> Result<Self, ()> {
59 if ring.borrow().is_irreducible(&modulus) {
60 Ok(Self::new_unchecked(ring, modulus))
61 } else {
62 Err(())
63 }
64 }
65}
66
67pub trait RingToQuotientRingSignature: EuclideanDomainSignature {
68 fn quotient_ring(
69 &self,
70 modulus: Self::Set,
71 ) -> EuclideanRemainderQuotientStructure<Self, &Self, false> {
72 EuclideanRemainderQuotientStructure::new_ring(self, modulus)
73 }
74
75 fn into_quotient_ring(
76 self,
77 modulus: Self::Set,
78 ) -> EuclideanRemainderQuotientStructure<Self, Self, false> {
79 EuclideanRemainderQuotientStructure::new_ring(self, modulus)
80 }
81}
82impl<Ring: EuclideanDomainSignature> RingToQuotientRingSignature for Ring {}
83
84pub trait RingToQuotientFieldSignature:
85 EuclideanDomainSignature + FactoringMonoidSignature
86{
87 fn quotient_field(
88 &self,
89 modulus: Self::Set,
90 ) -> Result<EuclideanRemainderQuotientStructure<Self, &Self, true>, ()> {
91 EuclideanRemainderQuotientStructure::new_field(self, modulus)
92 }
93
94 fn into_quotient_field(
95 self,
96 modulus: Self::Set,
97 ) -> Result<EuclideanRemainderQuotientStructure<Self, Self, true>, ()> {
98 EuclideanRemainderQuotientStructure::new_field(self, modulus)
99 }
100
101 fn quotient_field_unchecked(
102 &self,
103 modulus: Self::Set,
104 ) -> EuclideanRemainderQuotientStructure<Self, &Self, true> {
105 EuclideanRemainderQuotientStructure::new_field_unchecked(self, modulus)
106 }
107
108 fn into_quotient_field_unchecked(
109 self,
110 modulus: Self::Set,
111 ) -> EuclideanRemainderQuotientStructure<Self, Self, true> {
112 EuclideanRemainderQuotientStructure::new_field_unchecked(self, modulus)
113 }
114}
115impl<Ring: EuclideanDomainSignature + FactoringMonoidSignature> RingToQuotientFieldSignature
116 for Ring
117{
118}
119
120impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool> PartialEq
121 for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
122{
123 fn eq(&self, other: &Self) -> bool {
124 if self.ring == other.ring {
125 debug_assert_eq!(
126 self.ring().equal(&self.modulus, &other.modulus),
127 other.ring().equal(&self.modulus, &other.modulus)
128 );
129 self.ring().equal(&self.modulus, &other.modulus)
130 } else {
131 false
132 }
133 }
134}
135
136impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool> Eq
137 for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
138{
139}
140
141impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool> Signature
142 for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
143{
144}
145
146impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool> SetSignature
147 for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
148{
149 type Set = RS::Set;
150
151 fn is_element(&self, _x: &Self::Set) -> Result<(), String> {
152 Ok(())
153 }
154}
155
156impl<
157 RS: EuclideanDomainSignature + ToStringSignature,
158 RSB: BorrowedStructure<RS>,
159 const IS_FIELD: bool,
160> ToStringSignature for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
161{
162 fn to_string(&self, elem: &Self::Set) -> String {
163 self.ring().to_string(elem)
164 }
165}
166
167impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool> EqSignature
168 for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
169{
170 fn equal(&self, a: &Self::Set, b: &Self::Set) -> bool {
171 self.ring().is_zero(
172 &self
173 .ring()
174 .rem(&self.ring().add(a, &self.ring().neg(b)), &self.modulus),
175 )
176 }
177}
178
179impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool>
180 RinglikeSpecializationSignature for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
181{
182 fn try_ring_restructure(&self) -> Option<impl EqSignature<Set = Self::Set> + RingSignature> {
183 Some(self.clone())
184 }
185}
186
187impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool> ZeroSignature
188 for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
189{
190 fn zero(&self) -> Self::Set {
191 self.ring().zero()
192 }
193}
194
195impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool>
196 AdditionSignature for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
197{
198 fn add(&self, a: &Self::Set, b: &Self::Set) -> Self::Set {
199 self.ring().rem(&self.ring().add(a, b), &self.modulus)
200 }
201}
202
203impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool>
204 CancellativeAdditionSignature for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
205{
206 fn try_sub(&self, a: &Self::Set, b: &Self::Set) -> Option<Self::Set> {
207 Some(self.sub(a, b))
208 }
209}
210
211impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool>
212 TryNegateSignature for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
213{
214 fn try_neg(&self, a: &Self::Set) -> Option<Self::Set> {
215 Some(self.neg(a))
216 }
217}
218
219impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool>
220 AdditiveMonoidSignature for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
221{
222}
223
224impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool>
225 AdditiveGroupSignature for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
226{
227 fn neg(&self, a: &Self::Set) -> Self::Set {
228 self.ring().neg(a)
229 }
230
231 fn sub(&self, a: &Self::Set, b: &Self::Set) -> Self::Set {
232 self.ring().sub(a, b)
233 }
234}
235
236impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool> OneSignature
237 for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
238{
239 fn one(&self) -> Self::Set {
240 self.ring().one()
241 }
242}
243
244impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool>
245 MultiplicationSignature for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
246{
247 fn mul(&self, a: &Self::Set, b: &Self::Set) -> Self::Set {
248 self.ring().rem(&self.ring().mul(a, b), &self.modulus)
249 }
250}
251
252impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool>
253 CommutativeMultiplicationSignature for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
254{
255}
256
257impl<
258 RS: EuclideanDomainSignature + FavoriteAssociateSignature,
259 RSB: BorrowedStructure<RS>,
260 const IS_FIELD: bool,
261> TryReciprocalSignature for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
262{
263 fn try_reciprocal(&self, x: &Self::Set) -> Option<Self::Set> {
264 if self.is_zero(x) {
265 None
266 } else {
267 let (g, a, b) = self.ring().euclidean_xgcd(x.clone(), self.modulus.clone());
268 debug_assert!(
269 self.ring().equal(
270 &g,
271 &self
272 .ring()
273 .add(&self.ring().mul(&a, x), &self.ring().mul(&b, &self.modulus))
274 )
275 );
276 if self.equal(&g, &self.one()) {
277 Some(self.reduce(a))
278 } else {
279 None
280 }
281 }
282 }
283}
284
285impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool>
286 MultiplicativeMonoidSignature for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
287{
288}
289
290impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool>
291 MultiplicativeAbsorptionMonoidSignature
292 for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
293{
294}
295
296impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool>
297 LeftDistributiveMultiplicationOverAddition
298 for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
299{
300}
301
302impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool>
303 RightDistributiveMultiplicationOverAddition
304 for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
305{
306}
307
308impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool>
309 SemiRingSignature for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
310{
311}
312
313impl<RS: EuclideanDomainSignature, RSB: BorrowedStructure<RS>, const IS_FIELD: bool> RingSignature
314 for EuclideanRemainderQuotientStructure<RS, RSB, IS_FIELD>
315{
316 fn is_reduced(&self) -> Result<bool, String> {
317 if IS_FIELD {
318 return Ok(true);
319 }
320 Err("not implemented yet: is_reduced for quotient rings that are not fields".to_string())
321 }
322}
323
324impl<RS: EuclideanDomainSignature + FavoriteAssociateSignature, RSB: BorrowedStructure<RS>>
325 CancellativeMultiplicationSignature for EuclideanRemainderQuotientStructure<RS, RSB, true>
326{
327 fn try_divide(&self, top: &Self::Set, bot: &Self::Set) -> Option<Self::Set> {
328 Some(self.mul(top, &self.try_reciprocal(bot)?))
329 }
330}
331
332impl<RS: EuclideanDomainSignature + FavoriteAssociateSignature, RSB: BorrowedStructure<RS>>
333 MultiplicativeIntegralMonoidSignature for EuclideanRemainderQuotientStructure<RS, RSB, true>
334{
335}
336
337impl<RS: EuclideanDomainSignature + FavoriteAssociateSignature, RSB: BorrowedStructure<RS>>
338 IntegralDomainSignature for EuclideanRemainderQuotientStructure<RS, RSB, true>
339{
340}
341
342impl<RS: EuclideanDomainSignature + FavoriteAssociateSignature, RSB: BorrowedStructure<RS>>
343 FieldSignature for EuclideanRemainderQuotientStructure<RS, RSB, true>
344{
345}
346
347#[cfg(test)]
348mod tests {
349 use super::*;
350 use algebraeon_nzq::*;
351
352 #[test]
353 fn test() {
354 let mod5 =
355 EuclideanRemainderQuotientStructure::new_field(Integer::structure(), Integer::from(5))
356 .unwrap();
357
358 assert!(
359 mod5.equal(
360 &mod5
361 .try_divide(&Integer::from(3), &Integer::from(2))
362 .unwrap(),
363 &Integer::from(9)
364 )
365 );
366 }
367}