1use crate::structure::{
2 CancellativeAdditionSignature, CancellativeMultiplicationSignature,
3 CommutativeMultiplicationSignature, FavoriteAssociateSignature, FieldSignature,
4 MetaMultiplicativeMonoidSignature, MetaOneSignature, MultiplicationSignature,
5 MultiplicativeAbsorptionMonoidSignature, MultiplicativeMonoidSignature,
6 MultiplicativeMonoidSquareOpsSignature, OneSignature, RinglikeSpecializationSignature,
7 SemiRingSignature, TryReciprocalSignature, ZeroEqSignature, ZeroSignature,
8};
9use algebraeon_groups::structure::{CompositionSignature, GroupSignature};
10use algebraeon_nzq::{Natural, NaturalCanonicalStructure};
11use algebraeon_sets::structure::{
12 BorrowedStructure, EqSignature, MetaType, OrdSignature, SetSignature, Signature,
13};
14use std::fmt::{Debug, Display};
15use std::marker::PhantomData;
16
17#[derive(Debug, Clone)]
18pub struct NonZeroFactored<ObjectSet: Debug + Clone, ExponentSet: Debug + Clone> {
19 unit: ObjectSet,
20 powers: Vec<(ObjectSet, ExponentSet)>,
21}
22
23impl<ObjectSet: Debug + Clone, ExponentSet: Debug + Clone> NonZeroFactored<ObjectSet, ExponentSet> {
24 pub fn powers(&self) -> &Vec<(ObjectSet, ExponentSet)> {
25 &self.powers
26 }
27
28 pub fn into_powers(self) -> Vec<(ObjectSet, ExponentSet)> {
29 self.powers
30 }
31
32 pub fn unit(&self) -> &ObjectSet {
33 &self.unit
34 }
35
36 pub fn into_unit(self) -> ObjectSet {
37 self.unit
38 }
39
40 pub fn unit_and_powers(&self) -> (&ObjectSet, &Vec<(ObjectSet, ExponentSet)>) {
41 (&self.unit, &self.powers)
42 }
43
44 pub fn into_unit_and_powers(self) -> (ObjectSet, Vec<(ObjectSet, ExponentSet)>) {
45 (self.unit, self.powers)
46 }
47
48 pub fn distinct_irreducibles(&self) -> Vec<&ObjectSet> {
49 self.powers.iter().map(|(p, _)| p).collect()
50 }
51
52 pub fn into_distinct_irreducibles(self) -> Vec<ObjectSet> {
53 self.powers.into_iter().map(|(p, _)| p).collect()
54 }
55}
56
57#[derive(Debug, Clone)]
58pub enum Factored<ObjectSet: Debug + Clone, ExponentSet: Debug + Clone> {
59 Zero,
60 NonZero(NonZeroFactored<ObjectSet, ExponentSet>),
61}
62
63impl<
64 ObjectSet: Debug + Clone,
65 ExponentSet: Debug + Clone + MetaMultiplicativeMonoidSignature + PartialEq + Eq,
66> Display for Factored<ObjectSet, ExponentSet>
67where
68 ObjectSet: Display,
69 ExponentSet: Display,
70 ExponentSet::Signature: MultiplicativeMonoidSignature,
71{
72 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73 match self {
74 Factored::Zero => {
75 write!(f, "0")?;
76 }
77 Factored::NonZero(non_zero_factored) => {
78 write!(f, "{}", non_zero_factored.unit)?;
79 for (factor, k) in &non_zero_factored.powers {
80 write!(f, " * (")?;
81 write!(f, "{}", factor)?;
82 write!(f, ")")?;
83 if k != &ExponentSet::one() {
84 write!(f, "^")?;
85 write!(f, "{}", k)?;
86 }
87 }
88 }
89 }
90 Ok(())
91 }
92}
93
94impl<ObjectSet: Debug + Clone, ExponentSet: Debug + Clone> Factored<ObjectSet, ExponentSet> {
95 pub fn is_zero(&self) -> bool {
96 match self {
97 Factored::Zero => true,
98 Factored::NonZero(_) => false,
99 }
100 }
101
102 pub fn unwrap_nonzero(self) -> NonZeroFactored<ObjectSet, ExponentSet> {
103 match self {
104 Factored::Zero => panic!(),
105 Factored::NonZero(f) => f,
106 }
107 }
108
109 pub fn powers(&self) -> Option<&Vec<(ObjectSet, ExponentSet)>> {
110 match self {
111 Factored::Zero => None,
112 Factored::NonZero(a) => Some(a.powers()),
113 }
114 }
115
116 pub fn into_powers(self) -> Option<Vec<(ObjectSet, ExponentSet)>> {
117 match self {
118 Factored::Zero => None,
119 Factored::NonZero(a) => Some(a.into_powers()),
120 }
121 }
122
123 pub fn unit(&self) -> Option<&ObjectSet> {
124 match self {
125 Factored::Zero => None,
126 Factored::NonZero(a) => Some(a.unit()),
127 }
128 }
129
130 pub fn into_unit(self) -> Option<ObjectSet> {
131 match self {
132 Factored::Zero => None,
133 Factored::NonZero(a) => Some(a.into_unit()),
134 }
135 }
136
137 pub fn unit_and_powers(&self) -> Option<(&ObjectSet, &Vec<(ObjectSet, ExponentSet)>)> {
138 match self {
139 Factored::Zero => None,
140 Factored::NonZero(a) => Some(a.unit_and_powers()),
141 }
142 }
143
144 pub fn into_unit_and_powers(self) -> Option<(ObjectSet, Vec<(ObjectSet, ExponentSet)>)> {
145 match self {
146 Factored::Zero => None,
147 Factored::NonZero(a) => Some(a.into_unit_and_powers()),
148 }
149 }
150
151 pub fn distinct_irreducibles(&self) -> Option<Vec<&ObjectSet>> {
152 match self {
153 Factored::Zero => None,
154 Factored::NonZero(a) => Some(a.distinct_irreducibles()),
155 }
156 }
157
158 pub fn into_distinct_irreducibles(self) -> Option<Vec<ObjectSet>> {
159 match self {
160 Factored::Zero => None,
161 Factored::NonZero(a) => Some(a.into_distinct_irreducibles()),
162 }
163 }
164}
165
166#[derive(Debug, Clone, PartialEq, Eq)]
167pub struct FactoringStructure<
168 Object: UniqueFactorizationMonoidSignature<FactoredExponent = Exponent>,
169 ObjectB: BorrowedStructure<Object>,
170 Exponent: SemiRingSignature + CancellativeAdditionSignature + OrdSignature,
171 ExponentB: BorrowedStructure<Exponent>,
172> {
173 _objects: PhantomData<Object>,
174 objects: ObjectB,
175 _exponents: PhantomData<Exponent>,
176 exponents: ExponentB,
177}
178
179impl<
180 Object: UniqueFactorizationMonoidSignature<FactoredExponent = Exponent>,
181 ObjectB: BorrowedStructure<Object>,
182 Exponent: SemiRingSignature + CancellativeAdditionSignature + OrdSignature,
183 ExponentB: BorrowedStructure<Exponent>,
184> FactoringStructure<Object, ObjectB, Exponent, ExponentB>
185{
186 pub fn new(objects: ObjectB, exponents: ExponentB) -> Self {
187 Self {
188 _objects: PhantomData,
189 objects,
190 _exponents: PhantomData,
191 exponents,
192 }
193 }
194
195 pub fn objects(&self) -> &Object {
196 self.objects.borrow()
197 }
198
199 pub fn exponents(&self) -> &Exponent {
200 self.exponents.borrow()
201 }
202}
203
204impl<
206 Object: UniqueFactorizationMonoidSignature<FactoredExponent = Exponent>,
207 ObjectB: BorrowedStructure<Object>,
208 Exponent: SemiRingSignature + CancellativeAdditionSignature + OrdSignature,
209 ExponentB: BorrowedStructure<Exponent>,
210> FactoringStructure<Object, ObjectB, Exponent, ExponentB>
211{
212 pub(crate) fn mul_mut_impl(
213 &self,
214 a: &mut Factored<Object::Set, Exponent::Set>,
215 b: &Factored<Object::Set, Exponent::Set>,
216 ) {
217 match b {
218 Factored::Zero => {
219 *a = Factored::Zero;
220 }
221 Factored::NonZero(b) => match a {
222 Factored::Zero => {}
223 Factored::NonZero(a) => {
224 a.unit = self.objects().units().compose(&a.unit, &b.unit);
225 for (b_p, b_k) in &b.powers {
226 debug_assert!(self.objects().is_fav_assoc(b_p));
227 'A_LOOP: {
228 for (a_p, a_k) in &mut a.powers {
229 debug_assert!(self.objects().is_fav_assoc(a_p));
230 if self.objects().equal(a_p, b_p) {
231 *a_k = self.exponents().add(a_k, b_k);
232 break 'A_LOOP;
233 }
234 }
235 a.powers.push((b_p.clone(), b_k.clone()));
236 }
237 }
238 a.powers.retain(|(_, k)| !self.exponents().is_zero(k));
239 }
240 },
241 }
242 }
243
244 pub(crate) fn mul_gcd_impl(
245 &self,
246 a: &mut Factored<Object::Set, Exponent::Set>,
247 b: &Factored<Object::Set, Exponent::Set>,
248 ) {
249 match b {
250 Factored::Zero => {}
251 Factored::NonZero(b) => match a {
252 Factored::Zero => {
253 *a = Factored::NonZero(b.clone());
254 }
255 Factored::NonZero(a) => {
256 a.unit = self.objects().units().compose(&a.unit, &b.unit);
257 for (b_p, b_k) in &b.powers {
258 debug_assert!(self.objects().is_fav_assoc(b_p));
259 'A_LOOP: {
260 for (a_p, a_k) in &mut a.powers {
261 debug_assert!(self.objects().is_fav_assoc(a_p));
262 if self.objects().equal(a_p, b_p) {
263 *a_k = self.exponents().min(a_k, b_k);
264 break 'A_LOOP;
265 }
266 }
267 a.powers.push((b_p.clone(), b_k.clone()));
268 }
269 }
270 a.powers.retain(|(_, k)| !self.exponents().is_zero(k));
271 }
272 },
273 }
274 }
275
276 pub(crate) fn mul_lcm_impl(
277 &self,
278 a: &mut NonZeroFactored<Object::Set, Exponent::Set>,
279 b: &NonZeroFactored<Object::Set, Exponent::Set>,
280 ) {
281 a.unit = self.objects().units().compose(&a.unit, &b.unit);
282 for (b_p, b_k) in &b.powers {
283 debug_assert!(self.objects().is_fav_assoc(b_p));
284 'A_LOOP: {
285 for (a_p, a_k) in &mut a.powers {
286 debug_assert!(self.objects().is_fav_assoc(a_p));
287 if self.objects().equal(a_p, b_p) {
288 *a_k = self.exponents().max(a_k, b_k);
289 break 'A_LOOP;
290 }
291 }
292 a.powers.push((b_p.clone(), b_k.clone()));
293 }
294 }
295 a.powers.retain(|(_, k)| !self.exponents().is_zero(k));
296 }
297
298 pub(crate) fn try_divide_mut_impl(
299 &self,
300 a: &mut Option<Factored<Object::Set, Exponent::Set>>,
301 b: &Factored<Object::Set, Exponent::Set>,
302 ) {
303 match b {
304 Factored::Zero => {
305 *a = None;
306 }
307 Factored::NonZero(b) => match a {
308 None => {}
309 Some(Factored::Zero) => {}
310 Some(Factored::NonZero(a_nz)) => {
311 a_nz.unit = self
312 .objects()
313 .units()
314 .compose(&a_nz.unit, &self.objects().units().inverse(&b.unit));
315 for (b_p, b_k) in &b.powers {
316 debug_assert!(self.objects().is_fav_assoc(b_p));
317 'A_LOOP: {
318 for (a_p, a_k) in &mut a_nz.powers {
319 debug_assert!(self.objects().is_fav_assoc(a_p));
320 if self.objects().equal(a_p, b_p) {
321 if let Some(a_k_minus_b_k) = self.exponents().try_sub(a_k, b_k)
322 {
323 *a_k = a_k_minus_b_k;
324 } else {
325 *a = None;
326 return;
327 }
328 break 'A_LOOP;
329 }
330 }
331 if let Some(b_k_neg) = self.exponents().try_neg(b_k) {
332 a_nz.powers.push((b_p.clone(), b_k_neg));
333 } else {
334 *a = None;
335 return;
336 }
337 }
338 }
339 a_nz.powers.retain(|(_, k)| !self.exponents().is_zero(k));
340 }
341 },
342 }
343 }
344
345 pub(crate) fn is_irreducible_impl(&self, a: &Factored<Object::Set, Exponent::Set>) -> bool {
346 match a {
347 Factored::Zero => {}
348 Factored::NonZero(a) => {
349 if a.powers.len() == 1 {
350 let (_, k) = &a.powers[0];
351 if self.exponents().equal(k, &self.exponents().one()) {
352 return true;
353 }
354 }
355 }
356 }
357 false
358 }
359}
360
361impl<
362 Object: UniqueFactorizationMonoidSignature<FactoredExponent = Exponent>,
363 ObjectB: BorrowedStructure<Object>,
364 Exponent: SemiRingSignature + CancellativeAdditionSignature + OrdSignature,
365 ExponentB: BorrowedStructure<Exponent>,
366> Signature for FactoringStructure<Object, ObjectB, Exponent, ExponentB>
367{
368}
369
370impl<
371 Object: UniqueFactorizationMonoidSignature<FactoredExponent = Exponent>,
372 ObjectB: BorrowedStructure<Object>,
373 Exponent: SemiRingSignature + CancellativeAdditionSignature + OrdSignature,
374 ExponentB: BorrowedStructure<Exponent>,
375> SetSignature for FactoringStructure<Object, ObjectB, Exponent, ExponentB>
376{
377 type Set = Factored<Object::Set, Exponent::Set>;
378
379 fn is_element(&self, x: &Self::Set) -> Result<(), String> {
380 match x {
381 Factored::Zero => Ok(()),
382 Factored::NonZero(x) => {
383 self.objects().units().is_element(&x.unit)?;
384 for (prime, exponent) in &x.powers {
385 if !self.objects().is_fav_assoc(prime) {
386 return Err("Factors should be their favorite associate".to_string());
387 }
388 if self.objects().try_is_irreducible(prime) == Some(false) {
389 return Err("Failed to be irreducible".to_string());
390 }
391 self.exponents().is_element(exponent)?;
392 if self.exponents().is_zero(exponent) {
393 return Err("Exponent is zero".to_string());
394 }
395 }
396
397 for i in 0..x.powers.len() {
398 for j in 0..i {
399 let (pi, _ki) = &x.powers[i];
400 let (pj, _kj) = &x.powers[j];
401 if self.objects().equal(pi, pj) {
402 return Err("primes must be distinct".to_string());
403 }
404 }
405 }
406
407 Ok(())
408 }
409 }
410 }
411}
412
413impl<
414 Object: UniqueFactorizationMonoidSignature<FactoredExponent = Exponent>,
415 ObjectB: BorrowedStructure<Object>,
416 Exponent: SemiRingSignature + CancellativeAdditionSignature + OrdSignature,
417 ExponentB: BorrowedStructure<Exponent>,
418> EqSignature for FactoringStructure<Object, ObjectB, Exponent, ExponentB>
419{
420 fn equal(&self, a: &Self::Set, b: &Self::Set) -> bool {
421 #[cfg(debug_assertions)]
422 {
423 self.is_element(a).unwrap();
424 self.is_element(b).unwrap();
425 }
426 self.try_divide(a, b).is_some() && self.try_divide(b, a).is_some()
427 }
428}
429
430impl<
431 Object: UniqueFactorizationMonoidSignature<FactoredExponent = Exponent>,
432 ObjectB: BorrowedStructure<Object>,
433 Exponent: SemiRingSignature + CancellativeAdditionSignature + OrdSignature,
434 ExponentB: BorrowedStructure<Exponent>,
435> RinglikeSpecializationSignature for FactoringStructure<Object, ObjectB, Exponent, ExponentB>
436{
437}
438
439impl<
440 Object: UniqueFactorizationMonoidSignature<FactoredExponent = Exponent>,
441 ObjectB: BorrowedStructure<Object>,
442 Exponent: SemiRingSignature + CancellativeAdditionSignature + OrdSignature,
443 ExponentB: BorrowedStructure<Exponent>,
444> ZeroSignature for FactoringStructure<Object, ObjectB, Exponent, ExponentB>
445{
446 fn zero(&self) -> Self::Set {
447 Factored::Zero
448 }
449}
450
451impl<
452 Object: UniqueFactorizationMonoidSignature<FactoredExponent = Exponent>,
453 ObjectB: BorrowedStructure<Object>,
454 Exponent: SemiRingSignature + CancellativeAdditionSignature + OrdSignature,
455 ExponentB: BorrowedStructure<Exponent>,
456> OneSignature for FactoringStructure<Object, ObjectB, Exponent, ExponentB>
457{
458 fn one(&self) -> Self::Set {
459 Factored::NonZero(NonZeroFactored {
460 unit: self.objects().one(),
461 powers: vec![],
462 })
463 }
464}
465
466impl<
467 Object: UniqueFactorizationMonoidSignature<FactoredExponent = Exponent>,
468 ObjectB: BorrowedStructure<Object>,
469 Exponent: SemiRingSignature + CancellativeAdditionSignature + OrdSignature,
470 ExponentB: BorrowedStructure<Exponent>,
471> MultiplicationSignature for FactoringStructure<Object, ObjectB, Exponent, ExponentB>
472{
473 fn mul(&self, a: &Self::Set, b: &Self::Set) -> Self::Set {
474 #[cfg(debug_assertions)]
475 {
476 self.is_element(a).unwrap();
477 self.is_element(b).unwrap();
478 }
479 let mut s = a.clone();
480 self.mul_mut_impl(&mut s, b);
481 s
482 }
483}
484
485impl<
486 Object: UniqueFactorizationMonoidSignature<FactoredExponent = Exponent>,
487 ObjectB: BorrowedStructure<Object>,
488 Exponent: SemiRingSignature + CancellativeAdditionSignature + OrdSignature,
489 ExponentB: BorrowedStructure<Exponent>,
490> CommutativeMultiplicationSignature for FactoringStructure<Object, ObjectB, Exponent, ExponentB>
491{
492}
493
494impl<
495 Object: UniqueFactorizationMonoidSignature<FactoredExponent = Exponent>,
496 ObjectB: BorrowedStructure<Object>,
497 Exponent: SemiRingSignature + CancellativeAdditionSignature + OrdSignature,
498 ExponentB: BorrowedStructure<Exponent>,
499> MultiplicativeMonoidSignature for FactoringStructure<Object, ObjectB, Exponent, ExponentB>
500{
501}
502
503impl<
504 Object: UniqueFactorizationMonoidSignature<FactoredExponent = Exponent>,
505 ObjectB: BorrowedStructure<Object>,
506 Exponent: SemiRingSignature + CancellativeAdditionSignature + OrdSignature,
507 ExponentB: BorrowedStructure<Exponent>,
508> TryReciprocalSignature for FactoringStructure<Object, ObjectB, Exponent, ExponentB>
509{
510 fn try_reciprocal(&self, a: &Self::Set) -> Option<Self::Set> {
511 #[cfg(debug_assertions)]
512 self.is_element(a).unwrap();
513 match a {
514 Factored::Zero => None,
515 Factored::NonZero(a) => Some(Factored::NonZero(NonZeroFactored {
516 unit: self.objects().units().inverse(&a.unit),
517 powers: a
518 .powers
519 .iter()
520 .map(|(p, k)| self.exponents().try_neg(k).map(|neg_k| (p.clone(), neg_k)))
521 .collect::<Option<Vec<_>>>()?,
522 })),
523 }
524 }
525}
526
527impl<
528 Object: UniqueFactorizationMonoidSignature<FactoredExponent = Exponent>,
529 ObjectB: BorrowedStructure<Object>,
530 Exponent: SemiRingSignature + CancellativeAdditionSignature + OrdSignature,
531 ExponentB: BorrowedStructure<Exponent>,
532> CancellativeMultiplicationSignature for FactoringStructure<Object, ObjectB, Exponent, ExponentB>
533{
534 fn try_divide(&self, a: &Self::Set, b: &Self::Set) -> Option<Self::Set> {
535 let mut s = Some(a.clone());
536 self.try_divide_mut_impl(&mut s, b);
537 s
538 }
539}
540
541impl<
542 Object: UniqueFactorizationMonoidSignature<FactoredExponent = Exponent>,
543 ObjectB: BorrowedStructure<Object>,
544 Exponent: SemiRingSignature + CancellativeAdditionSignature + OrdSignature,
545 ExponentB: BorrowedStructure<Exponent>,
546> FactoringStructure<Object, ObjectB, Exponent, ExponentB>
547{
548 pub fn new_irreducible_unchecked(
549 &self,
550 p: Object::Set,
551 ) -> Factored<Object::Set, Exponent::Set> {
552 self.new_unit_and_powers_unchecked(self.objects().one(), vec![(p, self.exponents().one())])
553 }
554
555 pub fn new_unit_unchecked(&self, unit: Object::Set) -> Factored<Object::Set, Exponent::Set> {
556 self.new_unit_and_powers_unchecked(unit, vec![])
557 }
558
559 pub fn new_powers_unchecked(
560 &self,
561 powers: Vec<(Object::Set, Exponent::Set)>,
562 ) -> Factored<Object::Set, Exponent::Set> {
563 self.new_unit_and_powers_unchecked(self.objects().one(), powers)
564 }
565
566 pub fn new_unit_and_powers_unchecked(
567 &self,
568 mut unit: Object::Set,
569 powers: Vec<(Object::Set, Exponent::Set)>,
570 ) -> Factored<Object::Set, Exponent::Set> {
571 let mut fav_assoc_powers = vec![];
572 for (p, k) in powers {
573 let (u, p) = self.objects().factor_fav_assoc(&p);
574 self.objects()
575 .mul_mut(&mut unit, &self.objects().factorization_pow(&u, &k));
576 fav_assoc_powers.push((p, k));
577 }
578 let f = Factored::NonZero(NonZeroFactored {
579 unit,
580 powers: fav_assoc_powers,
581 });
582 #[cfg(debug_assertions)]
583 self.is_element(&f).unwrap();
584 f
585 }
586
587 pub fn gcd(
588 &self,
589 a: &Factored<Object::Set, Exponent::Set>,
590 b: &Factored<Object::Set, Exponent::Set>,
591 ) -> Factored<Object::Set, Exponent::Set> {
592 #[cfg(debug_assertions)]
593 {
594 self.is_element(a).unwrap();
595 self.is_element(b).unwrap();
596 }
597 let mut s = a.clone();
598 self.mul_gcd_impl(&mut s, b);
599 s
600 }
601
602 pub fn lcm(
603 &self,
604 a: &Factored<Object::Set, Exponent::Set>,
605 b: &Factored<Object::Set, Exponent::Set>,
606 ) -> Option<Factored<Object::Set, Exponent::Set>> {
607 #[cfg(debug_assertions)]
608 {
609 self.is_element(a).unwrap();
610 self.is_element(b).unwrap();
611 }
612 match (a, b) {
613 (Factored::Zero, Factored::Zero)
614 | (Factored::Zero, Factored::NonZero(_))
615 | (Factored::NonZero(_), Factored::Zero) => None,
616 (Factored::NonZero(a), Factored::NonZero(b)) => {
617 let mut s = a.clone();
618 self.mul_lcm_impl(&mut s, b);
619 Some(Factored::NonZero(s))
620 }
621 }
622 }
623
624 pub fn is_irreducible(&self, a: &Factored<Object::Set, Exponent::Set>) -> bool {
625 #[cfg(debug_assertions)]
626 self.is_element(a).unwrap();
627 self.is_irreducible_impl(a)
628 }
629
630 pub fn expand(&self, a: &Factored<Object::Set, Exponent::Set>) -> Object::Set {
631 #[cfg(debug_assertions)]
632 self.is_element(a).unwrap();
633 match a {
634 Factored::Zero => self.objects().zero(),
635 Factored::NonZero(a) => {
636 let mut prod = a.unit.clone();
637 for (p, k) in &a.powers {
638 self.objects()
639 .mul_mut(&mut prod, &self.objects().factorization_pow(p, k));
640 }
641 prod
642 }
643 }
644 }
645
646 pub fn expand_squarefree(&self, a: &Factored<Object::Set, Exponent::Set>) -> Object::Set {
647 #[cfg(debug_assertions)]
648 self.is_element(a).unwrap();
649 match a {
650 Factored::Zero => self.objects().zero(),
651 Factored::NonZero(a) => {
652 let mut prod = a.unit.clone();
653 for (p, _) in &a.powers {
654 self.objects().mul_mut(&mut prod, p);
655 }
656 prod
657 }
658 }
659 }
660
661 pub fn pow(
662 &self,
663 f: &Factored<Object::Set, Exponent::Set>,
664 n: &Exponent::Set,
665 ) -> Factored<Object::Set, Exponent::Set> {
666 match f {
667 Factored::Zero => Factored::Zero,
668 Factored::NonZero(f) => Factored::NonZero(NonZeroFactored {
669 unit: self.objects().factorization_pow(&f.unit, n),
670 powers: f
671 .powers
672 .iter()
673 .map(|(p, k)| (p.clone(), self.exponents().mul(n, k)))
674 .collect(),
675 }),
676 }
677 }
678}
679
680impl<
681 Object: UniqueFactorizationMonoidSignature<FactoredExponent = NaturalCanonicalStructure>,
682 ObjectB: BorrowedStructure<Object>,
683 ExponentB: BorrowedStructure<NaturalCanonicalStructure>,
684> FactoringStructure<Object, ObjectB, NaturalCanonicalStructure, ExponentB>
685{
686 pub fn divisors<'a>(
688 &'a self,
689 a: &'a Factored<Object::Set, Natural>,
690 ) -> Option<Box<dyn Iterator<Item = Object::Set> + 'a>> {
691 match a {
692 Factored::Zero => None,
693 Factored::NonZero(a) => {
694 let factors = &a.powers;
695 if factors.is_empty() {
696 Some(Box::new(vec![self.objects().one()].into_iter()))
697 } else {
698 let mut factor_powers = vec![];
699 for (p, k) in factors {
700 let j = factor_powers.len();
701 factor_powers.push(vec![]);
702 let mut p_pow = self.objects().one();
703 let mut i = Natural::from(0u8);
704 while &i <= k {
705 factor_powers[j].push(p_pow.clone());
706 p_pow = self.objects().mul(&p_pow, p);
707 i += Natural::from(1u8);
708 }
709 }
710
711 #[allow(clippy::redundant_closure_for_method_calls)]
712 Some(Box::new(
713 itertools::Itertools::multi_cartesian_product(
714 factor_powers.into_iter().map(|p_pows| p_pows.into_iter()),
715 )
716 .map(move |prime_power_factors| {
717 self.objects()
718 .product(prime_power_factors.iter().collect())
719 .clone()
720 }),
721 ))
722 }
723 }
724 }
725 }
726
727 pub fn count_divideisors(&self, a: &Factored<Object::Set, Natural>) -> Option<Natural> {
729 #[cfg(debug_assertions)]
730 self.is_element(a).unwrap();
731 match a {
732 Factored::Zero => None,
733 Factored::NonZero(a) => {
734 let factors = &a.powers;
735 let mut count = Natural::from(1u8);
736 for (_p, k) in factors {
737 count *= k + Natural::ONE;
738 }
739 Some(count)
740 }
741 }
742 }
743
744 #[allow(unused)]
746 fn is_square(&self, a: &Factored<Object::Set, Natural>) -> bool {
747 match a {
748 Factored::Zero => true,
749 Factored::NonZero(a) => a
750 .powers()
751 .iter()
752 .all(|(_, exponent)| exponent % Natural::TWO == Natural::ZERO),
753 }
754 }
755
756 fn is_squarefree(&self, a: &Factored<Object::Set, Natural>) -> bool {
758 match a {
759 Factored::Zero => false,
760 Factored::NonZero(a) => a
761 .powers()
762 .iter()
763 .all(|(_, exponent)| exponent <= &Natural::ONE),
764 }
765 }
766}
767
768impl<
770 Object: UniqueFactorizationMonoidSignature<FactoredExponent = NaturalCanonicalStructure>
771 + MultiplicativeMonoidSquareOpsSignature,
772 ObjectB: BorrowedStructure<Object>,
773 ExponentB: BorrowedStructure<NaturalCanonicalStructure>,
774> FactoringStructure<Object, ObjectB, NaturalCanonicalStructure, ExponentB>
775{
776 #[allow(unused)]
778 fn sqrt_if_square(
779 &self,
780 a: &Factored<Object::Set, Natural>,
781 ) -> Option<Factored<Object::Set, Natural>> {
782 #[cfg(debug_assertions)]
783 self.is_element(a).unwrap();
784 match a {
785 Factored::Zero => Some(self.zero()),
786 Factored::NonZero(a) => {
787 if let Some(unit_sqrt) = self.objects().sqrt_if_square(&a.unit) {
788 let mut sqrt_factor_powers = vec![];
789 for (prime, exponent) in a.powers() {
790 if exponent.clone() % Natural::TWO != Natural::ZERO {
791 return None;
792 }
793 let half = exponent / Natural::TWO;
794 if half != Natural::ZERO {
795 sqrt_factor_powers.push((prime.clone(), half.clone()));
796 }
797 }
798 Some(self.new_unit_and_powers_unchecked(unit_sqrt, sqrt_factor_powers))
799 } else {
800 None
801 }
802 }
803 }
804 }
805}
806
807pub trait UniqueFactorizationMonoidSignature:
808 MultiplicativeAbsorptionMonoidSignature + FavoriteAssociateSignature + EqSignature
809{
810 type FactoredExponent: SemiRingSignature + CancellativeAdditionSignature + OrdSignature;
811
812 fn factorization_exponents(&self) -> &Self::FactoredExponent;
813 fn into_factorization_exponents(self) -> Self::FactoredExponent;
814
815 fn factorizations(
816 &self,
817 ) -> FactoringStructure<Self, &Self, Self::FactoredExponent, &Self::FactoredExponent> {
818 FactoringStructure::new(self, self.factorization_exponents())
819 }
820 fn into_factorizations(
821 self,
822 ) -> FactoringStructure<Self, Self, Self::FactoredExponent, Self::FactoredExponent> {
823 FactoringStructure::new(self.clone(), self.into_factorization_exponents())
824 }
825
826 fn factorization_pow(
827 &self,
828 a: &Self::Set,
829 k: &<Self::FactoredExponent as SetSignature>::Set,
830 ) -> Self::Set;
831
832 fn try_is_irreducible(&self, a: &Self::Set) -> Option<bool>;
835}
836pub trait MetaUniqueFactorizationMonoidSignature: MetaType
837where
838 Self::Signature: UniqueFactorizationMonoidSignature,
839{
840 fn try_is_irreducible(&self) -> Option<bool> {
841 Self::structure().try_is_irreducible(self)
842 }
843}
844impl<R: MetaType> MetaUniqueFactorizationMonoidSignature for R where
845 Self::Signature: UniqueFactorizationMonoidSignature
846{
847}
848
849pub trait FactoringMonoidSignature: UniqueFactorizationMonoidSignature {
850 fn is_irreducible(&self, a: &Self::Set) -> bool {
851 self.factorizations()
852 .is_irreducible_impl(&self.factor_unchecked(a))
853 }
854
855 fn factor_unchecked(
856 &self,
857 a: &Self::Set,
858 ) -> Factored<Self::Set, <Self::FactoredExponent as SetSignature>::Set>;
859
860 fn factor(
861 &self,
862 a: &Self::Set,
863 ) -> Factored<Self::Set, <Self::FactoredExponent as SetSignature>::Set> {
864 let f = self.factor_unchecked(a);
865 #[cfg(debug_assertions)]
866 {
867 self.factorizations().is_element(&f).unwrap();
868 assert!(self.equal(a, &self.factorizations().expand(&f)))
869 }
870 f
871 }
872}
873pub trait MetaFactoringMonoid: MetaType
874where
875 Self::Signature: FactoringMonoidSignature,
876{
877 fn is_irreducible(&self) -> bool {
878 Self::structure().is_irreducible(self)
879 }
880
881 fn factor_unchecked(&self) -> Factored<Self, <<Self::Signature as UniqueFactorizationMonoidSignature>::FactoredExponent as SetSignature>::Set>{
882 Self::structure().factor_unchecked(self)
883 }
884
885 fn factor(&self) -> Factored<Self, <<Self::Signature as UniqueFactorizationMonoidSignature>::FactoredExponent as SetSignature>::Set>{
886 Self::structure().factor(self)
887 }
888}
889impl<R: MetaType> MetaFactoringMonoid for R where Self::Signature: FactoringMonoidSignature {}
890
891pub trait FactoringMonoidNaturalExponentSignature:
892 FactoringMonoidSignature<FactoredExponent = NaturalCanonicalStructure>
893{
894 fn gcd_by_factor(&self, a: &Self::Set, b: &Self::Set) -> Self::Set {
895 self.factorizations()
896 .expand(&self.factorizations().gcd(&self.factor(a), &self.factor(b)))
897 }
898
899 fn lcm_by_factor(&self, a: &Self::Set, b: &Self::Set) -> Option<Self::Set> {
900 Some(
901 self.factorizations().expand(
902 &self
903 .factorizations()
904 .lcm(&self.factor(a), &self.factor(b))?,
905 ),
906 )
907 }
908
909 fn is_squarefree(&self, a: &Self::Set) -> bool {
910 self.factorizations().is_squarefree(&self.factor(a))
911 }
912}
913impl<S: FactoringMonoidSignature<FactoredExponent = NaturalCanonicalStructure>>
914 FactoringMonoidNaturalExponentSignature for S
915{
916}
917pub trait MetaFactoringMonoidNaturalExponent: MetaType
918where
919 Self::Signature: FactoringMonoidNaturalExponentSignature,
920{
921 fn gcd_by_factor(a: &Self, b: &Self) -> Self {
922 Self::structure().gcd_by_factor(a, b)
923 }
924
925 fn lcm_by_factor(a: &Self, b: &Self) -> Option<Self> {
926 Self::structure().lcm_by_factor(a, b)
927 }
928
929 fn is_squarefree(&self) -> bool {
930 Self::structure().is_squarefree(self)
931 }
932}
933impl<R: MetaType> MetaFactoringMonoidNaturalExponent for R where
934 Self::Signature: FactoringMonoidNaturalExponentSignature
935{
936}
937
938impl<FS: FieldSignature> UniqueFactorizationMonoidSignature for FS {
939 type FactoredExponent = NaturalCanonicalStructure;
940
941 fn factorization_exponents(&self) -> &Self::FactoredExponent {
942 Natural::structure_ref()
943 }
944
945 fn into_factorization_exponents(self) -> Self::FactoredExponent {
946 Natural::structure()
947 }
948
949 fn try_is_irreducible(&self, _a: &Self::Set) -> Option<bool> {
950 Some(false)
951 }
952
953 fn factorization_pow(&self, a: &Self::Set, k: &Natural) -> Self::Set {
954 self.nat_pow(a, k)
955 }
956}
957
958impl<FS: FieldSignature> FactoringMonoidSignature for FS {
959 fn factor_unchecked(
960 &self,
961 a: &Self::Set,
962 ) -> Factored<Self::Set, <Self::FactoredExponent as SetSignature>::Set> {
963 if self.is_zero(a) {
964 Factored::Zero
965 } else {
966 Factored::NonZero(NonZeroFactored {
967 unit: a.clone(),
968 powers: vec![],
969 })
970 }
971 }
972}
973
974#[derive(Debug)]
975pub enum FindFactorResult<Element> {
976 Irreducible,
977 Composite(Element, Element),
978}
979
980pub fn factorize_by_find_factor<
981 Exponent: SemiRingSignature + CancellativeAdditionSignature + OrdSignature,
982 RS: UniqueFactorizationMonoidSignature<FactoredExponent = Exponent> + ZeroEqSignature,
983>(
984 ring: &RS,
985 elem: RS::Set,
986 partial_factor: &impl Fn(RS::Set) -> FindFactorResult<RS::Set>,
987) -> Factored<RS::Set, Exponent::Set> {
988 debug_assert!(!ring.is_zero(&elem));
989 if ring.is_unit(&elem) {
990 ring.factorizations().new_unit_unchecked(elem)
991 } else {
992 debug_assert!(!ring.is_unit(&elem));
993 match partial_factor(elem.clone()) {
994 FindFactorResult::Composite(g, h) => ring.factorizations().mul(
995 &factorize_by_find_factor(ring, g, partial_factor),
996 &factorize_by_find_factor(ring, h, partial_factor),
997 ),
998 FindFactorResult::Irreducible => {
999 ring.factorizations().new_irreducible_unchecked(elem)
1001 }
1002 }
1003 }
1004}
1005
1006#[cfg(test)]
1007mod tests {
1008 use super::*;
1009 use crate::structure::FactoringMonoidSignature;
1010 use algebraeon_nzq::{Integer, Natural};
1011 use algebraeon_sets::structure::MetaType;
1012
1013 #[test]
1014 fn factorization_invariants() {
1015 let f = Factored::NonZero(NonZeroFactored {
1016 unit: Integer::from(-1),
1017 powers: vec![
1018 (Integer::from(2), Natural::from(2u8)),
1019 (Integer::from(3), Natural::from(1u8)),
1020 ],
1021 });
1022 Integer::structure()
1023 .factorizations()
1024 .is_element(&f)
1025 .unwrap();
1026
1027 let f = Factored::NonZero(NonZeroFactored {
1028 unit: Integer::from(1),
1029 powers: vec![],
1030 });
1031 Integer::structure()
1032 .factorizations()
1033 .is_element(&f)
1034 .unwrap();
1035
1036 let f = Factored::NonZero(NonZeroFactored {
1037 unit: Integer::from(-1),
1038 powers: vec![
1039 (Integer::from(2), Natural::from(2u8)),
1040 (Integer::from(3), Natural::from(1u8)),
1041 (Integer::from(5), Natural::from(0u8)),
1042 ],
1043 });
1044 assert!(
1045 Integer::structure()
1046 .factorizations()
1047 .is_element(&f)
1048 .is_err(),
1049 "can't have a power of zero"
1050 );
1051
1052 let f = Factored::NonZero(NonZeroFactored {
1053 unit: Integer::from(3),
1054 powers: vec![(Integer::from(2), Natural::from(2u8))],
1055 });
1056 assert!(
1057 Integer::structure()
1058 .factorizations()
1059 .is_element(&f)
1060 .is_err(),
1061 "unit should be a unit"
1062 );
1063
1064 let f = Factored::NonZero(NonZeroFactored {
1065 unit: Integer::from(1),
1066 powers: vec![
1067 (Integer::from(0), Natural::from(1u8)),
1068 (Integer::from(3), Natural::from(1u8)),
1069 ],
1070 });
1071 assert!(
1072 Integer::structure()
1073 .factorizations()
1074 .is_element(&f)
1075 .is_err(),
1076 "prime factors must not be zero"
1077 );
1078
1079 let f = Factored::NonZero(NonZeroFactored {
1080 unit: Integer::from(-1),
1081 powers: vec![
1082 (Integer::from(4), Natural::from(1u8)),
1083 (Integer::from(3), Natural::from(1u8)),
1084 ],
1085 });
1086 assert!(
1087 Integer::structure()
1088 .factorizations()
1089 .is_element(&f)
1090 .is_err(),
1091 "prime factors must be prime"
1092 );
1093
1094 let f = Factored::NonZero(NonZeroFactored {
1095 unit: Integer::from(-1),
1096 powers: vec![
1097 (Integer::from(-2), Natural::from(2u8)),
1098 (Integer::from(3), Natural::from(1u8)),
1099 ],
1100 });
1101 assert!(
1102 Integer::structure()
1103 .factorizations()
1104 .is_element(&f)
1105 .is_err(),
1106 "prime factors must be favoriate associate"
1107 );
1108 }
1109
1110 #[test]
1111 fn test_count_divideisors() {
1112 for a in 1..25 {
1113 println!("a = {}", a);
1114 let b = Integer::from(a);
1115 println!("b = {}", b);
1116 let fs = Integer::structure().factor(&b);
1117 println!("fs = {:?}", fs);
1118 assert_eq!(
1119 Integer::structure()
1120 .factorizations()
1121 .count_divideisors(&fs)
1122 .unwrap(),
1123 Natural::from(
1124 Integer::structure()
1125 .factorizations()
1126 .divisors(&fs)
1127 .unwrap()
1128 .collect::<Vec<Integer>>()
1129 .len()
1130 )
1131 );
1132 }
1133 }
1134}