1use crate::primes::{
16 ODD_PRIME_DIVIDERS_U16, ODD_PRIME_DIVIDERS_U32, ODD_PRIME_DIVIDERS_U64, ODD_PRIMES,
17 known_odd_prime_factor_indices,
18};
19use crate::util::OddDivider;
20use crate::{Denom, DenomRef};
21use num_bigint::{BigInt, BigUint, Sign};
22use num_integer::Integer;
23use num_traits::{One, Zero};
24use smallvec::SmallVec;
25use std::cmp::Ordering;
26use std::iter::Peekable;
27use std::ops::{Div, DivAssign, Mul, MulAssign};
28
29#[derive(Clone, Debug, PartialEq, Eq)]
33pub struct DenomSparseU16<const NUM_PRIMES: usize, const NUM_INLINE: usize> {
34 primes: SmallVec<[(u16, u16); NUM_INLINE]>,
37 remainder: Option<BigUint>,
38}
39
40pub type DenomSparse6542 = DenomSparseU16<6542, 8>;
44
45impl<const NUM_PRIMES: usize, const NUM_INLINE: usize>
46 DenomRef<DenomSparseU16<NUM_PRIMES, NUM_INLINE>> for &DenomSparseU16<NUM_PRIMES, NUM_INLINE>
47{
48}
49
50impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> Denom
51 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
52{
53 const ONE: Self = Self {
54 primes: SmallVec::new_const(),
55 remainder: None,
56 };
57
58 fn into_biguint(self) -> BigUint {
59 self.into()
60 }
61
62 fn to_biguint(&self) -> BigUint {
63 self.into()
64 }
65
66 fn normalize(lnum: &mut BigInt, rnum: &mut BigInt, ldenom: &Self, rdenom: &Self) -> Self {
67 let mut primes = SmallVec::new();
68 let mut ltmp = 1_usize;
69 let mut rtmp = 1_usize;
70
71 for (p, (lcount, rcount)) in Zip(
72 ldenom.primes.iter().copied().peekable(),
73 rdenom.primes.iter().copied().peekable(),
74 ) {
75 match lcount.cmp(&rcount) {
76 Ordering::Equal => {
77 primes.push((p, lcount));
78 }
79 Ordering::Less => {
80 Self::accum_pow(lnum, &mut ltmp, p, rcount - lcount);
81 primes.push((p, rcount));
82 }
83 Ordering::Greater => {
84 Self::accum_pow(rnum, &mut rtmp, p, lcount - rcount);
85 primes.push((p, lcount));
86 }
87 }
88 }
89
90 *lnum *= ltmp;
91 *rnum *= rtmp;
92 let remainder = match (&ldenom.remainder, &rdenom.remainder) {
93 (None, None) => None,
94 (None, Some(r)) => {
95 *lnum *= BigInt::from_biguint(Sign::Plus, r.clone());
96 Some(r.clone())
97 }
98 (Some(l), None) => {
99 *rnum *= BigInt::from_biguint(Sign::Plus, l.clone());
100 Some(l.clone())
101 }
102 (Some(l), Some(r)) => {
103 if l == r {
104 Some(l.clone())
105 } else {
106 *lnum *= BigInt::from_biguint(Sign::Plus, r.clone());
107 *rnum *= BigInt::from_biguint(Sign::Plus, l.clone());
108 Some(l * r)
109 }
110 }
111 };
112 Self { primes, remainder }
113 }
114
115 fn gcd_reduce(&mut self, num: &mut BigInt) {
116 if let Some(remainder) = &mut self.remainder {
117 let gcd = remainder.gcd(num.magnitude());
118 if !gcd.is_one() {
119 *remainder /= &gcd;
120 if remainder.is_one() {
121 self.remainder = None;
122 }
123 let gcd: BigInt = gcd.into();
124 *num /= gcd;
125 }
126 }
127
128 'outer: for (p, i) in self.primes.iter_mut() {
129 let p = BigInt::from(*p);
130 while *i != 0 {
131 let (quo, rem) = num.div_rem(&p);
132 if !rem.is_zero() {
133 break;
134 }
135 *num = quo;
136 *i -= 1;
137 if num.magnitude().is_one() {
138 break 'outer;
139 }
140 }
141 }
142 self.primes.retain(|(_, i)| *i != 0);
143 }
144}
145
146impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> DenomSparseU16<NUM_PRIMES, NUM_INLINE> {
147 fn decompose(mut x: BigUint) -> Self {
148 const {
149 assert!(NUM_PRIMES <= ODD_PRIMES.len() + 1);
150 }
151
152 let bits = x.bits();
153 if bits <= 8 {
154 return Self::decompose_u8(x.try_into().unwrap());
155 } else if bits <= 16 {
156 return Self::decompose_u16(x.try_into().unwrap());
157 } else if bits <= 32 {
158 return Self::decompose_u32(x.try_into().unwrap());
159 } else if bits <= 64 {
160 return Self::decompose_u64(x.try_into().unwrap());
161 } else if bits <= 128 {
162 return Self::decompose_u128(x.try_into().unwrap());
163 }
164
165 let mut primes = SmallVec::new();
166
167 let mut count2 = x.trailing_zeros().unwrap();
168 if count2 != 0 {
169 x >>= count2;
170 if count2 <= u16::MAX as u64 {
171 primes.push((2, count2 as u16));
172 count2 = 0;
173 } else {
174 primes.push((2, u16::MAX));
175 count2 -= u16::MAX as u64;
176 }
177 }
178
179 'outer: for &p in ODD_PRIMES.iter().take(NUM_PRIMES - 1) {
180 let bigp = BigUint::from(p);
181 let mut count = 0;
182 while count != u16::MAX {
183 let (quo, rem) = x.div_rem(&bigp);
184 if !rem.is_zero() {
185 break;
186 }
187 x = quo;
188
189 count += 1;
190 if x.is_one() {
191 primes.push((p, count));
192 break 'outer;
193 }
194 }
195 if count != 0 {
196 primes.push((p, count));
197 }
198 }
199
200 let remainder = if x.is_one() && count2 == 0 {
201 None
202 } else {
203 Some(x << count2)
204 };
205 Self { primes, remainder }
206 }
207
208 fn decompose_known_factors(
209 mut primes: SmallVec<[(u16, u16); NUM_INLINE]>,
210 p: u16,
211 mut pcount: u16,
212 factor_indices: impl Iterator<Item = (u16, u16)>,
213 ) -> Self {
214 let mut remainder = 1_usize;
215 for (index, mut qcount) in factor_indices {
216 let index = index as usize;
217 let q = ODD_PRIMES[index - 1];
218
219 if pcount != 0 {
220 if p == q {
221 qcount += pcount;
222 } else {
223 primes.push((p, pcount));
224 }
225 pcount = 0;
226 }
227
228 if index < NUM_PRIMES {
229 primes.push((q, qcount));
230 } else {
231 let q = q as usize;
232 for _ in 0..qcount {
233 remainder *= q;
234 }
235 }
236 }
237
238 let remainder = if remainder == 1 {
239 None
240 } else {
241 Some(remainder.into())
242 };
243 Self { primes, remainder }
244 }
245
246 fn decompose_u8(mut x: u8) -> Self {
247 let mut primes = SmallVec::new();
248
249 let count2 = x.trailing_zeros();
250 if count2 != 0 {
251 x >>= count2;
252 primes.push((2, count2 as u16));
253 }
254
255 Self::decompose_known_factors(
257 primes,
258 0,
259 0,
260 known_odd_prime_factor_indices(x.into()).unwrap(),
261 )
262 }
263
264 fn decompose_u16(mut x: u16) -> Self {
265 const {
266 assert!(NUM_PRIMES <= ODD_PRIMES.len() + 1);
267 }
268
269 let mut primes = SmallVec::new();
270
271 let count2 = x.trailing_zeros();
272 if count2 != 0 {
273 x >>= count2;
274 primes.push((2, count2 as u16));
275 }
276
277 'outer: for (i, &p) in ODD_PRIMES.iter().enumerate().take(NUM_PRIMES - 1) {
278 let divider = OddDivider {
279 divisor: p,
280 multiplier: ODD_PRIME_DIVIDERS_U16[i],
281 shift: p.ilog2(),
282 };
283 let mut count = 0;
284 while x != 1 {
285 if let Some(iter) = known_odd_prime_factor_indices(x.into()) {
287 return Self::decompose_known_factors(primes, p, count, iter);
288 }
289
290 let (quo, rem) = divider.div_rem(x);
291 if rem != 0 {
292 break;
293 }
294 x = quo;
295
296 count += 1;
297 if x == 1 {
298 primes.push((p, count));
299 break 'outer;
300 }
301 }
302 if count != 0 {
303 primes.push((p, count));
304 }
305 }
306
307 let remainder = if x == 1 { None } else { Some(x.into()) };
308 Self { primes, remainder }
309 }
310
311 fn decompose_u32(mut x: u32) -> Self {
312 const {
313 assert!(NUM_PRIMES <= ODD_PRIMES.len() + 1);
314 }
315
316 let mut primes = SmallVec::new();
317
318 let count2 = x.trailing_zeros();
319 if count2 != 0 {
320 x >>= count2;
321 primes.push((2, count2 as u16));
322 }
323
324 'outer: for (i, &p) in ODD_PRIMES.iter().enumerate().take(NUM_PRIMES - 1) {
325 let bigp = p as u32;
326 let divider = OddDivider {
327 divisor: bigp,
328 multiplier: ODD_PRIME_DIVIDERS_U32[i],
329 shift: p.ilog2(),
330 };
331 let mut count = 0;
332 while x != 1 {
333 if let Ok(xx) = x.try_into()
335 && let Some(iter) = known_odd_prime_factor_indices(xx)
336 {
337 return Self::decompose_known_factors(primes, p, count, iter);
338 }
339
340 let (quo, rem) = divider.div_rem(x);
341 if rem != 0 {
342 break;
343 }
344 x = quo;
345
346 count += 1;
347 if x == 1 {
348 primes.push((p, count));
349 break 'outer;
350 }
351 }
352 if count != 0 {
353 primes.push((p, count));
354 }
355 }
356
357 let remainder = if x == 1 { None } else { Some(x.into()) };
358 Self { primes, remainder }
359 }
360
361 fn decompose_u64(mut x: u64) -> Self {
362 const {
363 assert!(NUM_PRIMES <= ODD_PRIMES.len() + 1);
364 }
365
366 let mut primes = SmallVec::new();
367
368 let count2 = x.trailing_zeros();
369 if count2 != 0 {
370 x >>= count2;
371 primes.push((2, count2 as u16));
372 }
373
374 'outer: for (i, &p) in ODD_PRIMES.iter().enumerate().take(NUM_PRIMES - 1) {
375 let bigp = p as u64;
376 let divider = OddDivider {
377 divisor: bigp,
378 multiplier: ODD_PRIME_DIVIDERS_U64[i],
379 shift: p.ilog2(),
380 };
381 let mut count = 0;
382 while x != 1 {
383 if let Ok(xx) = x.try_into()
385 && let Some(iter) = known_odd_prime_factor_indices(xx)
386 {
387 return Self::decompose_known_factors(primes, p, count, iter);
388 }
389
390 let (quo, rem) = divider.div_rem(x);
391 if rem != 0 {
392 break;
393 }
394 x = quo;
395
396 count += 1;
397 if x == 1 {
398 primes.push((p, count));
399 break 'outer;
400 }
401 }
402 if count != 0 {
403 primes.push((p, count));
404 }
405 }
406
407 let remainder = if x == 1 { None } else { Some(x.into()) };
408 Self { primes, remainder }
409 }
410
411 fn decompose_u128(mut x: u128) -> Self {
412 const {
413 assert!(NUM_PRIMES <= ODD_PRIMES.len() + 1);
414 }
415
416 let mut primes = SmallVec::new();
417
418 let count2 = x.trailing_zeros();
419 if count2 != 0 {
420 x >>= count2;
421 primes.push((2, count2 as u16));
422 }
423
424 'outer: for &p in ODD_PRIMES.iter().take(NUM_PRIMES - 1) {
425 let bigp = p as u128;
426 let mut count = 0;
427 while x != 1 {
428 if let Ok(xx) = x.try_into()
430 && let Some(iter) = known_odd_prime_factor_indices(xx)
431 {
432 return Self::decompose_known_factors(primes, p, count, iter);
433 }
434
435 if !x.is_multiple_of(bigp) {
436 break;
437 }
438 x /= bigp;
439
440 count += 1;
441 if x == 1 {
442 primes.push((p, count));
443 break 'outer;
444 }
445 }
446 if count != 0 {
447 primes.push((p, count));
448 }
449 }
450
451 let remainder = if x == 1 { None } else { Some(x.into()) };
452 Self { primes, remainder }
453 }
454
455 fn decompose_usize(mut x: usize) -> Self {
456 const {
457 assert!(NUM_PRIMES <= ODD_PRIMES.len() + 1);
458 }
459
460 let mut primes = SmallVec::new();
461
462 let count2 = x.trailing_zeros();
463 if count2 != 0 {
464 x >>= count2;
465 primes.push((2, count2 as u16));
466 }
467
468 'outer: for &p in ODD_PRIMES.iter().take(NUM_PRIMES - 1) {
469 let bigp = p as usize;
470 let mut count = 0;
471 while x != 1 {
472 if let Some(iter) = known_odd_prime_factor_indices(x) {
474 return Self::decompose_known_factors(primes, p, count, iter);
475 }
476
477 if !x.is_multiple_of(bigp) {
478 break;
479 }
480 x /= bigp;
481
482 count += 1;
483 if x == 1 {
484 primes.push((p, count));
485 break 'outer;
486 }
487 }
488 if count != 0 {
489 primes.push((p, count));
490 }
491 }
492
493 let remainder = if x == 1 { None } else { Some(x.into()) };
494 Self { primes, remainder }
495 }
496
497 fn decompose_mask(
499 remainder: &mut Option<BigUint>,
500 primes: &mut SmallVec<[(u16, u16); NUM_INLINE]>,
501 mask: &[u16],
502 ) {
503 let x: &mut BigUint = match remainder {
504 None => return,
505 Some(x) => x,
506 };
507
508 let mut new_primes = SmallVec::new();
509 'outer: for (p, (mut count, flag)) in Zip(
510 primes.iter().copied().peekable(),
511 mask.iter().copied().map(|p| (p, true)).peekable(),
512 ) {
513 if flag && count != u16::MAX {
514 let bigp = BigUint::from(p);
515 while count != u16::MAX {
516 let (quo, rem) = x.div_rem(&bigp);
517 if !rem.is_zero() {
518 break;
519 }
520 *x = quo;
521
522 count += 1;
523 if x.is_one() {
524 new_primes.push((p, count));
525 break 'outer;
526 }
527 }
528 }
529 new_primes.push((p, count));
530 }
531 *primes = new_primes;
532
533 if x.is_one() {
534 *remainder = None;
535 }
536 }
537
538 fn accum_pow(numerator: &mut BigInt, tmp: &mut usize, prime: u16, exponent: u16) {
541 let prime = prime as usize;
542 for _ in 0..exponent {
543 match tmp.checked_mul(prime) {
544 Some(prod) => *tmp = prod,
545 None => {
546 *numerator *= *tmp;
547 *tmp = prime;
548 }
549 }
550 }
551 }
552
553 fn accum_pow_option(
554 remainder: &mut Option<BigUint>,
555 tmp: &mut usize,
556 prime: u16,
557 exponent: u16,
558 ) {
559 let prime = prime as usize;
560 for _ in 0..exponent {
561 match tmp.checked_mul(prime) {
562 Some(prod) => *tmp = prod,
563 None => {
564 match remainder {
565 None => *remainder = Some(BigUint::from(*tmp)),
566 Some(r) => *r *= *tmp,
567 };
568 *tmp = prime;
569 }
570 }
571 }
572 }
573
574 fn pow_primes(primes: &mut [(u16, u16)], exponent: u32, remainder: &mut Option<BigUint>) {
575 for (p, i) in primes.iter_mut() {
576 let product = (*i as u32).strict_mul(exponent);
577 if product <= u16::MAX as u32 {
578 *i = product as u16;
579 } else {
580 *i = u16::MAX;
581 let factor = BigUint::from(*p).pow(product - u16::MAX as u32);
582 match remainder {
583 None => *remainder = Some(factor),
584 Some(r) => *r *= factor,
585 };
586 }
587 }
588 }
589
590 fn mul_primes(
591 lhs: &[(u16, u16)],
592 rhs: &[(u16, u16)],
593 remainder: &mut Option<BigUint>,
594 ) -> SmallVec<[(u16, u16); NUM_INLINE]> {
595 let mut primes = SmallVec::new();
596
597 for (p, (lcount, rcount)) in Zip(
598 lhs.iter().copied().peekable(),
599 rhs.iter().copied().peekable(),
600 ) {
601 let sum = lcount as u32 + rcount as u32;
602 if sum <= u16::MAX as u32 {
603 primes.push((p, sum as u16));
604 } else {
605 primes.push((p, u16::MAX));
606 let factor = BigUint::from(p).pow(sum - u16::MAX as u32);
607 match remainder {
608 None => *remainder = Some(factor),
609 Some(r) => *r *= factor,
610 };
611 }
612 }
613 primes
614 }
615
616 fn div_primes(
617 num: &[(u16, u16)],
618 denom: &[(u16, u16)],
619 mut remainder: Option<BigUint>,
620 ) -> (Self, SmallVec<[u16; NUM_INLINE]>) {
621 let mut primes = SmallVec::new();
622 let mut mask = SmallVec::new();
623 let mut tmp = 1_usize;
624
625 for (p, (num_count, denom_count)) in Zip(
626 num.iter().copied().peekable(),
627 denom.iter().copied().peekable(),
628 ) {
629 if num_count == u16::MAX {
630 mask.push(p);
631 }
632 match num_count.cmp(&denom_count) {
633 Ordering::Greater => {
634 primes.push((p, num_count - denom_count));
635 }
636 Ordering::Equal => (),
637 Ordering::Less => {
638 Self::accum_pow_option(&mut remainder, &mut tmp, p, denom_count - num_count);
639 let factor = BigUint::from(p).pow(denom_count as u32 - num_count as u32);
640 remainder = match remainder {
641 None => Some(factor),
642 Some(r) => Some(r * factor),
643 };
644 }
645 }
646 }
647
648 if tmp != 1 {
649 match remainder.as_mut() {
650 None => remainder = Some(BigUint::from(tmp)),
651 Some(r) => *r *= tmp,
652 };
653 }
654 (Self { primes, remainder }, mask)
655 }
656}
657
658impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> From<u8>
659 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
660{
661 fn from(value: u8) -> Self {
662 if value == 0 {
663 panic!("Attempted to create a denominator of zero");
664 }
665 Self::decompose_u8(value)
666 }
667}
668
669impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> From<u16>
670 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
671{
672 fn from(value: u16) -> Self {
673 if value == 0 {
674 panic!("Attempted to create a denominator of zero");
675 }
676 Self::decompose_u16(value)
677 }
678}
679
680impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> From<u32>
681 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
682{
683 fn from(value: u32) -> Self {
684 if value == 0 {
685 panic!("Attempted to create a denominator of zero");
686 }
687 Self::decompose_u32(value)
688 }
689}
690
691impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> From<u64>
692 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
693{
694 fn from(value: u64) -> Self {
695 if value == 0 {
696 panic!("Attempted to create a denominator of zero");
697 }
698 Self::decompose_u64(value)
699 }
700}
701
702impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> From<u128>
703 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
704{
705 fn from(value: u128) -> Self {
706 if value == 0 {
707 panic!("Attempted to create a denominator of zero");
708 }
709 Self::decompose_u128(value)
710 }
711}
712
713impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> From<usize>
714 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
715{
716 fn from(value: usize) -> Self {
717 if value == 0 {
718 panic!("Attempted to create a denominator of zero");
719 }
720 Self::decompose_usize(value)
721 }
722}
723
724impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> From<BigUint>
725 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
726{
727 fn from(value: BigUint) -> Self {
728 if value.is_zero() {
729 panic!("Attempted to create a denominator of zero");
730 }
731 Self::decompose(value)
732 }
733}
734
735impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> From<&BigUint>
736 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
737{
738 fn from(value: &BigUint) -> Self {
739 if value.is_zero() {
740 panic!("Attempted to create a denominator of zero");
741 }
742 Self::decompose(value.clone())
743 }
744}
745
746impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> From<DenomSparseU16<NUM_PRIMES, NUM_INLINE>>
747 for BigUint
748{
749 fn from(value: DenomSparseU16<NUM_PRIMES, NUM_INLINE>) -> BigUint {
750 let mut result = match value.remainder {
751 Some(x) => x,
752 None => BigUint::ONE,
753 };
754 let mut tmp = 1_usize;
755 for (p, count) in value.primes.into_iter() {
756 let p = p as usize;
757 for _ in 0..count {
758 match tmp.checked_mul(p) {
759 Some(prod) => tmp = prod,
760 None => {
761 result *= tmp;
762 tmp = p;
763 }
764 }
765 }
766 }
767 result * tmp
768 }
769}
770
771impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> From<&DenomSparseU16<NUM_PRIMES, NUM_INLINE>>
772 for BigUint
773{
774 fn from(value: &DenomSparseU16<NUM_PRIMES, NUM_INLINE>) -> BigUint {
775 let mut result = match &value.remainder {
776 Some(x) => x.clone(),
777 None => BigUint::ONE,
778 };
779 let mut tmp = 1_usize;
780 for &(p, count) in value.primes.iter() {
781 let p = p as usize;
782 for _ in 0..count {
783 match tmp.checked_mul(p) {
784 Some(prod) => tmp = prod,
785 None => {
786 result *= tmp;
787 tmp = p;
788 }
789 }
790 }
791 }
792 result * tmp
793 }
794}
795
796impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> One
797 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
798{
799 fn one() -> Self {
800 Self::ONE
801 }
802}
803
804impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> num_traits::Pow<u32>
805 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
806{
807 type Output = Self;
808
809 fn pow(mut self, rhs: u32) -> Self {
810 if rhs == 0 {
811 return Self::ONE;
812 }
813 Self::pow_primes(&mut self.primes, rhs, &mut self.remainder);
814 self
815 }
816}
817
818impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> num_traits::Pow<u32>
819 for &DenomSparseU16<NUM_PRIMES, NUM_INLINE>
820{
821 type Output = DenomSparseU16<NUM_PRIMES, NUM_INLINE>;
822
823 fn pow(self, rhs: u32) -> DenomSparseU16<NUM_PRIMES, NUM_INLINE> {
824 if rhs == 0 {
825 return DenomSparseU16::ONE;
826 }
827 let mut primes = self.primes.clone();
828 let mut remainder = self.remainder.clone();
829 DenomSparseU16::<NUM_PRIMES, NUM_INLINE>::pow_primes(&mut primes, rhs, &mut remainder);
830 DenomSparseU16 { primes, remainder }
831 }
832}
833
834impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> Mul
835 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
836{
837 type Output = Self;
838
839 fn mul(self, rhs: Self) -> Self {
840 let mut remainder = match (self.remainder, rhs.remainder) {
841 (None, None) => None,
842 (None, Some(r)) => Some(r),
843 (Some(l), None) => Some(l),
844 (Some(l), Some(r)) => Some(l * r),
845 };
846 let primes = Self::mul_primes(&self.primes, &rhs.primes, &mut remainder);
847 Self { primes, remainder }
848 }
849}
850
851impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> Mul<&Self>
852 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
853{
854 type Output = Self;
855
856 fn mul(self, rhs: &Self) -> Self {
857 let mut remainder = match (self.remainder, &rhs.remainder) {
858 (None, None) => None,
859 (None, Some(r)) => Some(r.clone()),
860 (Some(l), None) => Some(l),
861 (Some(l), Some(r)) => Some(l * r),
862 };
863 let primes = Self::mul_primes(&self.primes, &rhs.primes, &mut remainder);
864 Self { primes, remainder }
865 }
866}
867
868impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> Mul
869 for &DenomSparseU16<NUM_PRIMES, NUM_INLINE>
870{
871 type Output = DenomSparseU16<NUM_PRIMES, NUM_INLINE>;
872
873 fn mul(self, rhs: Self) -> DenomSparseU16<NUM_PRIMES, NUM_INLINE> {
874 let mut remainder = match (&self.remainder, &rhs.remainder) {
875 (None, None) => None,
876 (None, Some(r)) => Some(r.clone()),
877 (Some(l), None) => Some(l.clone()),
878 (Some(l), Some(r)) => Some(l * r),
879 };
880 let primes = DenomSparseU16::<NUM_PRIMES, NUM_INLINE>::mul_primes(
881 &self.primes,
882 &rhs.primes,
883 &mut remainder,
884 );
885 DenomSparseU16 { primes, remainder }
886 }
887}
888
889impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> Mul<DenomSparseU16<NUM_PRIMES, NUM_INLINE>>
890 for &DenomSparseU16<NUM_PRIMES, NUM_INLINE>
891{
892 type Output = DenomSparseU16<NUM_PRIMES, NUM_INLINE>;
893
894 fn mul(
895 self,
896 rhs: DenomSparseU16<NUM_PRIMES, NUM_INLINE>,
897 ) -> DenomSparseU16<NUM_PRIMES, NUM_INLINE> {
898 let mut remainder = match (&self.remainder, rhs.remainder) {
899 (None, None) => None,
900 (None, Some(r)) => Some(r),
901 (Some(l), None) => Some(l.clone()),
902 (Some(l), Some(r)) => Some(l * r),
903 };
904 let primes = DenomSparseU16::<NUM_PRIMES, NUM_INLINE>::mul_primes(
905 &self.primes,
906 &rhs.primes,
907 &mut remainder,
908 );
909 DenomSparseU16 { primes, remainder }
910 }
911}
912
913impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> MulAssign
914 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
915{
916 fn mul_assign(&mut self, rhs: Self) {
917 match (&mut self.remainder, rhs.remainder) {
918 (_, None) => (),
919 (None, Some(r)) => self.remainder = Some(r),
920 (Some(l), Some(r)) => *l *= r,
921 };
922 self.primes = Self::mul_primes(&self.primes, &rhs.primes, &mut self.remainder);
923 }
924}
925
926impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> MulAssign<&Self>
927 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
928{
929 fn mul_assign(&mut self, rhs: &Self) {
930 match (&mut self.remainder, &rhs.remainder) {
931 (_, None) => (),
932 (None, Some(r)) => self.remainder = Some(r.clone()),
933 (Some(l), Some(r)) => *l *= r,
934 };
935 self.primes = Self::mul_primes(&self.primes, &rhs.primes, &mut self.remainder);
936 }
937}
938
939impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> Div
940 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
941{
942 type Output = Self;
943
944 fn div(self, rhs: Self) -> Self {
948 let (
949 Self {
950 mut primes,
951 remainder: rhs_remainder,
952 },
953 mask,
954 ) = Self::div_primes(&self.primes, &rhs.primes, rhs.remainder);
955
956 let mut remainder = match (self.remainder, rhs_remainder) {
957 (None, None) => None,
958 (None, Some(r)) => {
959 if !r.is_one() {
960 panic!("Attempted to divide a denominator by a non-divisor");
961 }
962 None
963 }
964 (Some(l), None) => Some(l),
965 (Some(l), Some(r)) => {
966 let (quo, rem) = l.div_rem(&r);
967 if !rem.is_zero() {
968 panic!("Attempted to divide a denominator by a non-divisor");
969 }
970 if quo.is_one() { None } else { Some(quo) }
971 }
972 };
973
974 Self::decompose_mask(&mut remainder, &mut primes, &mask);
975 Self { primes, remainder }
976 }
977}
978
979impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> Div<&Self>
980 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
981{
982 type Output = Self;
983
984 fn div(self, rhs: &Self) -> Self {
988 let (
989 Self {
990 mut primes,
991 remainder: rhs_remainder,
992 },
993 mask,
994 ) = Self::div_primes(&self.primes, &rhs.primes, rhs.remainder.clone());
995
996 let mut remainder = match (self.remainder, rhs_remainder) {
997 (None, None) => None,
998 (None, Some(r)) => {
999 if !r.is_one() {
1000 panic!("Attempted to divide a denominator by a non-divisor");
1001 }
1002 None
1003 }
1004 (Some(l), None) => Some(l),
1005 (Some(l), Some(r)) => {
1006 let (quo, rem) = l.div_rem(&r);
1007 if !rem.is_zero() {
1008 panic!("Attempted to divide a denominator by a non-divisor");
1009 }
1010 if quo.is_one() { None } else { Some(quo) }
1011 }
1012 };
1013
1014 Self::decompose_mask(&mut remainder, &mut primes, &mask);
1015 Self { primes, remainder }
1016 }
1017}
1018
1019impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> Div
1020 for &DenomSparseU16<NUM_PRIMES, NUM_INLINE>
1021{
1022 type Output = DenomSparseU16<NUM_PRIMES, NUM_INLINE>;
1023
1024 fn div(self, rhs: Self) -> DenomSparseU16<NUM_PRIMES, NUM_INLINE> {
1028 let (
1029 DenomSparseU16 {
1030 mut primes,
1031 remainder: rhs_remainder,
1032 },
1033 mask,
1034 ) = DenomSparseU16::<NUM_PRIMES, NUM_INLINE>::div_primes(
1035 &self.primes,
1036 &rhs.primes,
1037 rhs.remainder.clone(),
1038 );
1039
1040 let mut remainder = match (&self.remainder, rhs_remainder) {
1041 (None, None) => None,
1042 (None, Some(r)) => {
1043 if !r.is_one() {
1044 panic!("Attempted to divide a denominator by a non-divisor");
1045 }
1046 None
1047 }
1048 (Some(l), None) => Some(l.clone()),
1049 (Some(l), Some(r)) => {
1050 let (quo, rem) = l.div_rem(&r);
1051 if !rem.is_zero() {
1052 panic!("Attempted to divide a denominator by a non-divisor");
1053 }
1054 if quo.is_one() { None } else { Some(quo) }
1055 }
1056 };
1057
1058 DenomSparseU16::<NUM_PRIMES, NUM_INLINE>::decompose_mask(
1059 &mut remainder,
1060 &mut primes,
1061 &mask,
1062 );
1063 DenomSparseU16 { primes, remainder }
1064 }
1065}
1066
1067impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> Div<DenomSparseU16<NUM_PRIMES, NUM_INLINE>>
1068 for &DenomSparseU16<NUM_PRIMES, NUM_INLINE>
1069{
1070 type Output = DenomSparseU16<NUM_PRIMES, NUM_INLINE>;
1071
1072 fn div(
1076 self,
1077 rhs: DenomSparseU16<NUM_PRIMES, NUM_INLINE>,
1078 ) -> DenomSparseU16<NUM_PRIMES, NUM_INLINE> {
1079 let (
1080 DenomSparseU16 {
1081 mut primes,
1082 remainder: rhs_remainder,
1083 },
1084 mask,
1085 ) = DenomSparseU16::<NUM_PRIMES, NUM_INLINE>::div_primes(
1086 &self.primes,
1087 &rhs.primes,
1088 rhs.remainder,
1089 );
1090
1091 let mut remainder = match (&self.remainder, rhs_remainder) {
1092 (None, None) => None,
1093 (None, Some(r)) => {
1094 if !r.is_one() {
1095 panic!("Attempted to divide a denominator by a non-divisor");
1096 }
1097 None
1098 }
1099 (Some(l), None) => Some(l.clone()),
1100 (Some(l), Some(r)) => {
1101 let (quo, rem) = l.div_rem(&r);
1102 if !rem.is_zero() {
1103 panic!("Attempted to divide a denominator by a non-divisor");
1104 }
1105 if quo.is_one() { None } else { Some(quo) }
1106 }
1107 };
1108
1109 DenomSparseU16::<NUM_PRIMES, NUM_INLINE>::decompose_mask(
1110 &mut remainder,
1111 &mut primes,
1112 &mask,
1113 );
1114 DenomSparseU16 { primes, remainder }
1115 }
1116}
1117
1118impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> DivAssign
1119 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
1120{
1121 fn div_assign(&mut self, rhs: Self) {
1125 let (
1126 Self {
1127 primes,
1128 remainder: rhs_remainder,
1129 },
1130 mask,
1131 ) = Self::div_primes(&self.primes, &rhs.primes, rhs.remainder);
1132 self.primes = primes;
1133
1134 match (&mut self.remainder, rhs_remainder) {
1135 (_, None) => (),
1136 (None, Some(r)) => {
1137 if !r.is_one() {
1138 panic!("Attempted to divide a denominator by a non-divisor");
1139 }
1140 }
1141 (Some(l), Some(r)) => {
1142 let (quo, rem) = l.div_rem(&r);
1143 if !rem.is_zero() {
1144 panic!("Attempted to divide a denominator by a non-divisor");
1145 }
1146 if quo.is_one() {
1147 self.remainder = None
1148 } else {
1149 *l = quo;
1150 }
1151 }
1152 };
1153
1154 Self::decompose_mask(&mut self.remainder, &mut self.primes, &mask);
1155 }
1156}
1157
1158impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> DivAssign<&Self>
1159 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
1160{
1161 fn div_assign(&mut self, rhs: &Self) {
1165 let (
1166 Self {
1167 primes,
1168 remainder: rhs_remainder,
1169 },
1170 mask,
1171 ) = Self::div_primes(&self.primes, &rhs.primes, rhs.remainder.clone());
1172 self.primes = primes;
1173
1174 match (&mut self.remainder, rhs_remainder) {
1175 (_, None) => (),
1176 (None, Some(r)) => {
1177 if !r.is_one() {
1178 panic!("Attempted to divide a denominator by a non-divisor");
1179 }
1180 }
1181 (Some(l), Some(r)) => {
1182 let (quo, rem) = l.div_rem(&r);
1183 if !rem.is_zero() {
1184 panic!("Attempted to divide a denominator by a non-divisor");
1185 }
1186 if quo.is_one() {
1187 self.remainder = None
1188 } else {
1189 *l = quo;
1190 }
1191 }
1192 };
1193
1194 Self::decompose_mask(&mut self.remainder, &mut self.primes, &mask);
1195 }
1196}
1197
1198impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> Mul<DenomSparseU16<NUM_PRIMES, NUM_INLINE>>
1199 for BigInt
1200{
1201 type Output = Self;
1202
1203 fn mul(mut self, rhs: DenomSparseU16<NUM_PRIMES, NUM_INLINE>) -> Self {
1204 let mut tmp = 1_usize;
1205 for (p, count) in rhs.primes.into_iter() {
1206 DenomSparseU16::<NUM_PRIMES, NUM_INLINE>::accum_pow(&mut self, &mut tmp, p, count);
1207 }
1208
1209 self *= tmp;
1210 if let Some(remainder) = rhs.remainder {
1211 self *= BigInt::from_biguint(Sign::Plus, remainder);
1212 }
1213 self
1214 }
1215}
1216
1217impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> Mul<&DenomSparseU16<NUM_PRIMES, NUM_INLINE>>
1218 for BigInt
1219{
1220 type Output = Self;
1221
1222 fn mul(mut self, rhs: &DenomSparseU16<NUM_PRIMES, NUM_INLINE>) -> Self {
1223 let mut tmp = 1_usize;
1224 for &(p, count) in rhs.primes.iter() {
1225 DenomSparseU16::<NUM_PRIMES, NUM_INLINE>::accum_pow(&mut self, &mut tmp, p, count);
1226 }
1227
1228 self *= tmp;
1229 if let Some(remainder) = &rhs.remainder {
1230 self *= BigInt::from_biguint(Sign::Plus, remainder.clone());
1231 }
1232 self
1233 }
1234}
1235
1236impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> Mul<DenomSparseU16<NUM_PRIMES, NUM_INLINE>>
1237 for &BigInt
1238{
1239 type Output = BigInt;
1240
1241 fn mul(self, rhs: DenomSparseU16<NUM_PRIMES, NUM_INLINE>) -> BigInt {
1242 let mut this = self.clone();
1243 let mut tmp = 1_usize;
1244 for (p, count) in rhs.primes.into_iter() {
1245 DenomSparseU16::<NUM_PRIMES, NUM_INLINE>::accum_pow(&mut this, &mut tmp, p, count);
1246 }
1247
1248 this *= tmp;
1249 if let Some(remainder) = rhs.remainder {
1250 this *= BigInt::from_biguint(Sign::Plus, remainder);
1251 }
1252 this
1253 }
1254}
1255
1256impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> Mul<&DenomSparseU16<NUM_PRIMES, NUM_INLINE>>
1257 for &BigInt
1258{
1259 type Output = BigInt;
1260
1261 fn mul(self, rhs: &DenomSparseU16<NUM_PRIMES, NUM_INLINE>) -> BigInt {
1262 let mut this = self.clone();
1263 let mut tmp = 1_usize;
1264 for &(p, count) in rhs.primes.iter() {
1265 DenomSparseU16::<NUM_PRIMES, NUM_INLINE>::accum_pow(&mut this, &mut tmp, p, count);
1266 }
1267
1268 this *= tmp;
1269 if let Some(remainder) = &rhs.remainder {
1270 this *= BigInt::from_biguint(Sign::Plus, remainder.clone());
1271 }
1272 this
1273 }
1274}
1275
1276impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> Mul<BigInt>
1277 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
1278{
1279 type Output = BigInt;
1280
1281 fn mul(self, mut rhs: BigInt) -> BigInt {
1282 let mut tmp = 1_usize;
1283 for (p, count) in self.primes.into_iter() {
1284 Self::accum_pow(&mut rhs, &mut tmp, p, count);
1285 }
1286
1287 rhs *= tmp;
1288 if let Some(remainder) = self.remainder {
1289 rhs *= BigInt::from_biguint(Sign::Plus, remainder);
1290 }
1291 rhs
1292 }
1293}
1294
1295impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> Mul<&BigInt>
1296 for DenomSparseU16<NUM_PRIMES, NUM_INLINE>
1297{
1298 type Output = BigInt;
1299
1300 fn mul(self, rhs: &BigInt) -> BigInt {
1301 let mut rhs = rhs.clone();
1302 let mut tmp = 1_usize;
1303 for (p, count) in self.primes.into_iter() {
1304 Self::accum_pow(&mut rhs, &mut tmp, p, count);
1305 }
1306
1307 rhs *= tmp;
1308 if let Some(remainder) = self.remainder {
1309 rhs *= BigInt::from_biguint(Sign::Plus, remainder);
1310 }
1311 rhs
1312 }
1313}
1314
1315impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> Mul<BigInt>
1316 for &DenomSparseU16<NUM_PRIMES, NUM_INLINE>
1317{
1318 type Output = BigInt;
1319
1320 fn mul(self, mut rhs: BigInt) -> BigInt {
1321 let mut tmp = 1_usize;
1322 for &(p, count) in self.primes.iter() {
1323 DenomSparseU16::<NUM_PRIMES, NUM_INLINE>::accum_pow(&mut rhs, &mut tmp, p, count);
1324 }
1325
1326 rhs *= tmp;
1327 if let Some(remainder) = &self.remainder {
1328 rhs *= BigInt::from_biguint(Sign::Plus, remainder.clone());
1329 }
1330 rhs
1331 }
1332}
1333
1334impl<const NUM_PRIMES: usize, const NUM_INLINE: usize> Mul<&BigInt>
1335 for &DenomSparseU16<NUM_PRIMES, NUM_INLINE>
1336{
1337 type Output = BigInt;
1338
1339 fn mul(self, rhs: &BigInt) -> BigInt {
1340 let mut rhs = rhs.clone();
1341 let mut tmp = 1_usize;
1342 for &(p, count) in self.primes.iter() {
1343 DenomSparseU16::<NUM_PRIMES, NUM_INLINE>::accum_pow(&mut rhs, &mut tmp, p, count);
1344 }
1345
1346 rhs *= tmp;
1347 if let Some(remainder) = &self.remainder {
1348 rhs *= BigInt::from_biguint(Sign::Plus, remainder.clone());
1349 }
1350 rhs
1351 }
1352}
1353
1354impl<const NUM_PRIMES: usize, const NUM_INLINE: usize>
1355 MulAssign<DenomSparseU16<NUM_PRIMES, NUM_INLINE>> for BigInt
1356{
1357 fn mul_assign(&mut self, rhs: DenomSparseU16<NUM_PRIMES, NUM_INLINE>) {
1358 let mut tmp = 1_usize;
1359 for (p, count) in rhs.primes.into_iter() {
1360 DenomSparseU16::<NUM_PRIMES, NUM_INLINE>::accum_pow(self, &mut tmp, p, count);
1361 }
1362
1363 *self *= tmp;
1364 if let Some(remainder) = rhs.remainder {
1365 *self *= BigInt::from_biguint(Sign::Plus, remainder);
1366 }
1367 }
1368}
1369
1370impl<const NUM_PRIMES: usize, const NUM_INLINE: usize>
1371 MulAssign<&DenomSparseU16<NUM_PRIMES, NUM_INLINE>> for BigInt
1372{
1373 fn mul_assign(&mut self, rhs: &DenomSparseU16<NUM_PRIMES, NUM_INLINE>) {
1374 let mut tmp = 1_usize;
1375 for &(p, count) in rhs.primes.iter() {
1376 DenomSparseU16::<NUM_PRIMES, NUM_INLINE>::accum_pow(self, &mut tmp, p, count);
1377 }
1378
1379 *self *= tmp;
1380 if let Some(remainder) = &rhs.remainder {
1381 *self *= BigInt::from_biguint(Sign::Plus, remainder.clone());
1382 }
1383 }
1384}
1385
1386struct Zip<A, B>(A, B);
1387
1388impl<U, V, A, B> Iterator for Zip<Peekable<A>, Peekable<B>>
1389where
1390 A: Iterator<Item = (u16, U)>,
1391 B: Iterator<Item = (u16, V)>,
1392 U: Default,
1393 V: Default,
1394{
1395 type Item = (u16, (U, V));
1396
1397 fn next(&mut self) -> Option<Self::Item> {
1398 match (self.0.peek(), self.1.peek()) {
1399 (None, None) => None,
1400 (None, Some(_)) => {
1401 let (p, v) = self.1.next().unwrap();
1402 Some((p, (Default::default(), v)))
1403 }
1404 (Some(_), None) => {
1405 let (p, u) = self.0.next().unwrap();
1406 Some((p, (u, Default::default())))
1407 }
1408 (Some((p, _)), Some((q, _))) => match p.cmp(q) {
1409 Ordering::Less => {
1410 let (p, u) = self.0.next().unwrap();
1411 Some((p, (u, Default::default())))
1412 }
1413 Ordering::Greater => {
1414 let (q, v) = self.1.next().unwrap();
1415 Some((q, (Default::default(), v)))
1416 }
1417 Ordering::Equal => {
1418 let (p, u) = self.0.next().unwrap();
1419 let (_, v) = self.1.next().unwrap();
1420 Some((p, (u, v)))
1421 }
1422 },
1423 }
1424 }
1425}
1426
1427#[cfg(test)]
1428mod tests {
1429 use super::*;
1430 use smallvec::smallvec;
1431
1432 macro_rules! tests {
1433 (
1434 $mod:ident,
1435 $num_primes:expr,
1436 $( $case:ident ,)*
1437 ) => {
1438 mod $mod {
1439 $(
1440 #[test]
1441 fn $case() {
1442 super::$case::<$num_primes>();
1443 }
1444 )*
1445 }
1446 };
1447 }
1448
1449 macro_rules! all_tests {
1450 (
1451 $mod:ident,
1452 $num_primes:expr
1453 ) => {
1454 tests!(
1455 $mod,
1456 $num_primes,
1457 test_decompose_to_biguint,
1458 test_decompose_small_prime_power,
1459 test_mul_prime_powers,
1460 test_div_prime_powers,
1461 test_product,
1462 test_normalize,
1463 test_gcd_reduce,
1464 );
1465 };
1466 }
1467
1468 all_tests!(denom24, 24);
1469 all_tests!(denom6542, 6542);
1470
1471 fn test_decompose_to_biguint<const NUM_PRIMES: usize>() {
1472 for i in 1_usize..=(1 << 20) {
1473 let bigi = BigUint::from(i);
1474 let x = DenomSparseU16::<NUM_PRIMES, 8>::from(&bigi);
1475 assert_eq!(x.to_biguint(), bigi);
1476 }
1477 }
1478
1479 #[test]
1480 fn test_decompose_no_remainder() {
1481 for i in 1_usize..=65536 {
1482 let bigi = BigUint::from(i);
1483 let x = DenomSparse6542::from(&bigi);
1484 assert_eq!(x.remainder, None, "Remainder for {i}");
1485 }
1486 }
1487
1488 #[test]
1489 fn test_decompose_known_values() {
1490 assert_eq!(
1491 DenomSparse6542::from(0xfff1_u16),
1492 DenomSparse6542 {
1493 primes: smallvec![(0xfff1, 1)],
1494 remainder: None,
1495 }
1496 );
1497 assert_eq!(
1498 DenomSparse6542::from(0xffff_fffb_u32),
1499 DenomSparse6542 {
1500 primes: smallvec![],
1501 remainder: Some(0xffff_fffb_u32.into()),
1502 }
1503 );
1504 assert_eq!(
1505 DenomSparse6542::from(0xffff_ffff_ffff_ffc5_u64),
1506 DenomSparse6542 {
1507 primes: smallvec![],
1508 remainder: Some(0xffff_ffff_ffff_ffc5_u64.into()),
1509 }
1510 );
1511 assert_eq!(
1512 DenomSparse6542::from(0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ff61_u128),
1513 DenomSparse6542 {
1514 primes: smallvec![],
1515 remainder: Some(0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ff61_u128.into()),
1516 }
1517 );
1518 assert_eq!(
1519 DenomSparse6542::from(BigUint::from_slice(&[
1520 0xffff_ff43,
1521 0xffff_ffff,
1522 0xffff_ffff,
1523 0xffff_ffff,
1524 0xffff_ffff,
1525 0xffff_ffff,
1526 0xffff_ffff,
1527 0xffff_ffff,
1528 ])),
1529 DenomSparse6542 {
1530 primes: smallvec![],
1531 remainder: Some(BigUint::from_slice(&[
1532 0xffff_ff43,
1533 0xffff_ffff,
1534 0xffff_ffff,
1535 0xffff_ffff,
1536 0xffff_ffff,
1537 0xffff_ffff,
1538 0xffff_ffff,
1539 0xffff_ffff,
1540 ])),
1541 }
1542 );
1543
1544 assert_eq!(
1545 DenomSparse6542::from(2u8 * 3 * 5 * 7),
1546 DenomSparse6542 {
1547 primes: smallvec![(2, 1), (3, 1), (5, 1), (7, 1)],
1548 remainder: None,
1549 }
1550 );
1551 assert_eq!(
1552 DenomSparse6542::from(2u16 * 3 * 5 * 7 * 11 * 13),
1553 DenomSparse6542 {
1554 primes: smallvec![(2, 1), (3, 1), (5, 1), (7, 1), (11, 1), (13, 1)],
1555 remainder: None,
1556 }
1557 );
1558 assert_eq!(
1559 DenomSparse6542::from(2u32 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23),
1560 DenomSparse6542 {
1561 primes: smallvec![
1562 (2, 1),
1563 (3, 1),
1564 (5, 1),
1565 (7, 1),
1566 (11, 1),
1567 (13, 1),
1568 (17, 1),
1569 (19, 1),
1570 (23, 1)
1571 ],
1572 remainder: None,
1573 }
1574 );
1575 assert_eq!(
1576 DenomSparse6542::from(
1577 2u64 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 31 * 37 * 41 * 43 * 47 * 53
1578 ),
1579 DenomSparse6542 {
1580 primes: smallvec![
1581 (2, 1),
1582 (3, 1),
1583 (5, 1),
1584 (7, 1),
1585 (11, 1),
1586 (13, 1),
1587 (17, 1),
1588 (19, 1),
1589 (23, 1),
1590 (31, 1),
1591 (37, 1),
1592 (41, 1),
1593 (43, 1),
1594 (47, 1),
1595 (53, 1)
1596 ],
1597 remainder: None,
1598 }
1599 );
1600 assert_eq!(
1601 DenomSparse6542::from(
1602 2u128
1603 * 3
1604 * 5
1605 * 7
1606 * 11
1607 * 13
1608 * 17
1609 * 19
1610 * 23
1611 * 31
1612 * 37
1613 * 41
1614 * 43
1615 * 47
1616 * 53
1617 * 59
1618 * 61
1619 * 67
1620 * 71
1621 * 73
1622 * 79
1623 * 83
1624 * 89
1625 * 97
1626 * 101,
1627 ),
1628 DenomSparse6542 {
1629 primes: smallvec![
1630 (2, 1),
1631 (3, 1),
1632 (5, 1),
1633 (7, 1),
1634 (11, 1),
1635 (13, 1),
1636 (17, 1),
1637 (19, 1),
1638 (23, 1),
1639 (31, 1),
1640 (37, 1),
1641 (41, 1),
1642 (43, 1),
1643 (47, 1),
1644 (53, 1),
1645 (59, 1),
1646 (61, 1),
1647 (67, 1),
1648 (71, 1),
1649 (73, 1),
1650 (79, 1),
1651 (83, 1),
1652 (89, 1),
1653 (97, 1),
1654 (101, 1),
1655 ],
1656 remainder: None,
1657 }
1658 );
1659 assert_eq!(
1660 DenomSparse6542::from(
1661 BigUint::try_from(
1662 BigInt::from(2)
1663 * 3
1664 * 5
1665 * 7
1666 * 11
1667 * 13
1668 * 17
1669 * 19
1670 * 23
1671 * 31
1672 * 37
1673 * 41
1674 * 43
1675 * 47
1676 * 53
1677 * 59
1678 * 61
1679 * 67
1680 * 71
1681 * 73
1682 * 79
1683 * 83
1684 * 89
1685 * 97
1686 * 101
1687 * 103
1688 * 107
1689 * 109
1690 * 113
1691 * 127
1692 * 131
1693 * 137
1694 * 139
1695 * 149
1696 * 151
1697 * 157
1698 * 163
1699 * 167
1700 * 173
1701 * 179
1702 * 181
1703 * 191
1704 * 193
1705 * 197
1706 * 199
1707 * 211
1708 * 223
1709 * 227
1710 * 229
1711 * 233
1712 )
1713 .unwrap(),
1714 ),
1715 DenomSparse6542 {
1716 primes: smallvec![
1717 (2, 1),
1718 (3, 1),
1719 (5, 1),
1720 (7, 1),
1721 (11, 1),
1722 (13, 1),
1723 (17, 1),
1724 (19, 1),
1725 (23, 1),
1726 (31, 1),
1727 (37, 1),
1728 (41, 1),
1729 (43, 1),
1730 (47, 1),
1731 (53, 1),
1732 (59, 1),
1733 (61, 1),
1734 (67, 1),
1735 (71, 1),
1736 (73, 1),
1737 (79, 1),
1738 (83, 1),
1739 (89, 1),
1740 (97, 1),
1741 (101, 1),
1742 (103, 1),
1743 (107, 1),
1744 (109, 1),
1745 (113, 1),
1746 (127, 1),
1747 (131, 1),
1748 (137, 1),
1749 (139, 1),
1750 (149, 1),
1751 (151, 1),
1752 (157, 1),
1753 (163, 1),
1754 (167, 1),
1755 (173, 1),
1756 (179, 1),
1757 (181, 1),
1758 (191, 1),
1759 (193, 1),
1760 (197, 1),
1761 (199, 1),
1762 (211, 1),
1763 (223, 1),
1764 (227, 1),
1765 (229, 1),
1766 (233, 1),
1767 ],
1768 remainder: None,
1769 }
1770 );
1771
1772 assert_eq!(
1773 DenomSparse6542::from(0xfb_u16 * 0xf1),
1774 DenomSparse6542 {
1775 primes: smallvec![(0xf1, 1), (0xfb, 1)],
1776 remainder: None,
1777 }
1778 );
1779 assert_eq!(
1780 DenomSparse6542::from(0xfff1_u32 * 0xffef),
1781 DenomSparse6542 {
1782 primes: smallvec![(0xffef, 1), (0xfff1, 1)],
1783 remainder: None,
1784 }
1785 );
1786 assert_eq!(
1787 DenomSparse6542::from(0xfff1_u64 * 0xffef * 0xffd9 * 0xffc7),
1788 DenomSparse6542 {
1789 primes: smallvec![(0xffc7, 1), (0xffd9, 1), (0xffef, 1), (0xfff1, 1)],
1790 remainder: None,
1791 }
1792 );
1793 assert_eq!(
1794 DenomSparse6542::from(
1795 0xfff1_u128 * 0xffef * 0xffd9 * 0xffc7 * 0xffa9 * 0xffa7 * 0xff9d * 0xff8f,
1796 ),
1797 DenomSparse6542 {
1798 primes: smallvec![
1799 (0xff8f, 1),
1800 (0xff9d, 1),
1801 (0xffa7, 1),
1802 (0xffa9, 1),
1803 (0xffc7, 1),
1804 (0xffd9, 1),
1805 (0xffef, 1),
1806 (0xfff1, 1)
1807 ],
1808 remainder: None,
1809 }
1810 );
1811 assert_eq!(
1812 DenomSparse6542::from(
1813 BigUint::from(0xfff1_u16)
1814 * 0xffef_u16
1815 * 0xffd9_u16
1816 * 0xffc7_u16
1817 * 0xffa9_u16
1818 * 0xffa7_u16
1819 * 0xff9d_u16
1820 * 0xff8f_u16
1821 * 0xff8b_u16
1822 * 0xff85_u16
1823 * 0xff7f_u16
1824 * 0xff71_u16
1825 * 0xff65_u16
1826 * 0xff5b_u16
1827 * 0xff4d_u16
1828 * 0xff49_u16,
1829 ),
1830 DenomSparse6542 {
1831 primes: smallvec![
1832 (0xff49, 1),
1833 (0xff4d, 1),
1834 (0xff5b, 1),
1835 (0xff65, 1),
1836 (0xff71, 1),
1837 (0xff7f, 1),
1838 (0xff85, 1),
1839 (0xff8b, 1),
1840 (0xff8f, 1),
1841 (0xff9d, 1),
1842 (0xffa7, 1),
1843 (0xffa9, 1),
1844 (0xffc7, 1),
1845 (0xffd9, 1),
1846 (0xffef, 1),
1847 (0xfff1, 1)
1848 ],
1849 remainder: None,
1850 }
1851 );
1852
1853 assert_eq!(
1854 DenomSparse6542::from(BigUint::from(128_usize)),
1855 DenomSparse6542 {
1856 primes: smallvec![(2, 7)],
1857 remainder: None,
1858 }
1859 );
1860 assert_eq!(
1861 DenomSparse6542::from(BigUint::from(89_usize)),
1862 DenomSparse6542 {
1863 primes: smallvec![(89, 1)],
1864 remainder: None,
1865 }
1866 );
1867 assert_eq!(
1868 DenomSparse6542::from(BigUint::from(97_usize)),
1869 DenomSparse6542 {
1870 primes: smallvec![(97, 1)],
1871 remainder: None,
1872 }
1873 );
1874 assert_eq!(
1875 DenomSparse6542::from(BigUint::from(97000_usize)),
1876 DenomSparse6542 {
1877 primes: smallvec![(2, 3), (5, 3), (97, 1)],
1878 remainder: None,
1879 }
1880 );
1881 }
1882
1883 fn test_decompose_small_prime_power<const NUM_PRIMES: usize>() {
1884 for p in std::iter::once(2).chain(ODD_PRIMES).take(NUM_PRIMES) {
1885 let bigp = BigUint::from(p);
1886 assert_eq!(
1887 DenomSparseU16::<NUM_PRIMES, 8>::from(bigp.pow(100)),
1888 DenomSparseU16 {
1889 primes: smallvec![(p, 100)],
1890 remainder: None,
1891 }
1892 );
1893 }
1894 }
1895
1896 fn test_mul_prime_powers<const NUM_PRIMES: usize>() {
1897 let p = BigUint::from(2u32);
1898 for a in 1..=256 {
1899 let denom_a = DenomSparseU16::<NUM_PRIMES, 8>::from(p.pow(a));
1900 for b in 1..=256 {
1901 let denom_b = DenomSparseU16::<NUM_PRIMES, 8>::from(p.pow(b));
1902 let denom_ab = DenomSparseU16::<NUM_PRIMES, 8>::from(p.pow(a + b));
1903 assert_eq!(&denom_a * denom_b, denom_ab);
1904 }
1905 }
1906 }
1907
1908 fn test_div_prime_powers<const NUM_PRIMES: usize>() {
1909 let p = BigUint::from(2u32);
1910 for a in 1..=256 {
1911 let denom_a = DenomSparseU16::<NUM_PRIMES, 8>::from(p.pow(a));
1912 for b in 1..=256 {
1913 let denom_b = DenomSparseU16::<NUM_PRIMES, 8>::from(p.pow(b));
1914 let denom_ab = DenomSparseU16::<NUM_PRIMES, 8>::from(p.pow(a + b));
1915 assert_eq!(denom_ab / denom_b, denom_a);
1916 }
1917 }
1918 }
1919
1920 fn test_product<const NUM_PRIMES: usize>() {
1921 let values = (100..200)
1922 .map(|i: usize| DenomSparseU16::<NUM_PRIMES, 8>::from(BigUint::from(i)))
1923 .collect::<Vec<_>>();
1924 for (i, x) in values.iter().enumerate().map(|(i, x)| (i + 100, x)) {
1925 for (j, y) in values.iter().enumerate().map(|(j, y)| (j + 100, y)) {
1926 let z = x * y;
1927 assert_eq!(
1928 z,
1929 DenomSparseU16::<NUM_PRIMES, 8>::from(BigUint::from(i * j))
1930 );
1931
1932 for (p, (zcount, (xcount, ycount))) in Zip(
1933 z.primes.into_iter().peekable(),
1934 Zip(
1935 x.primes.iter().copied().peekable(),
1936 y.primes.iter().copied().peekable(),
1937 )
1938 .peekable(),
1939 ) {
1940 assert_eq!(
1941 zcount,
1942 xcount + ycount,
1943 "{zcount} != {xcount} + {ycount} for {p}"
1944 );
1945 }
1946 }
1947 }
1948 }
1949
1950 fn test_normalize<const NUM_PRIMES: usize>() {
1951 let values = (100..200)
1952 .map(|i: usize| DenomSparseU16::<NUM_PRIMES, 8>::from(BigUint::from(i)))
1953 .collect::<Vec<_>>();
1954 for x in &values {
1955 for y in &values {
1956 let mut xnum = BigInt::one();
1957 let mut ynum = BigInt::one();
1958 let lcm = DenomSparseU16::<NUM_PRIMES, 8>::normalize(&mut xnum, &mut ynum, x, y);
1959 let lcm_bigint = lcm.to_biguint();
1960 let xnum = xnum.to_biguint().unwrap();
1961 let ynum = ynum.to_biguint().unwrap();
1962
1963 assert_eq!(xnum * x.to_biguint(), lcm_bigint);
1964 assert_eq!(ynum * y.to_biguint(), lcm_bigint);
1965
1966 for (p, (lcm_count, (xcount, ycount))) in Zip(
1967 lcm.primes.into_iter().peekable(),
1968 Zip(
1969 x.primes.iter().copied().peekable(),
1970 y.primes.iter().copied().peekable(),
1971 )
1972 .peekable(),
1973 ) {
1974 assert_eq!(
1975 lcm_count,
1976 std::cmp::max(xcount, ycount),
1977 "{lcm_count} != max({xcount}, {ycount}) for {p}"
1978 );
1979 }
1980 }
1981 }
1982 }
1983
1984 fn test_gcd_reduce<const NUM_PRIMES: usize>() {
1985 let mut num = BigInt::from(-3 * 97);
1986 let mut denom = DenomSparseU16::<NUM_PRIMES, 8>::from(BigUint::from(3u32 * 5 * 97));
1987 denom.gcd_reduce(&mut num);
1988 assert_eq!(num, BigInt::from(-1));
1989 assert_eq!(
1990 denom,
1991 DenomSparseU16::<NUM_PRIMES, 8>::from(BigUint::from(5u32))
1992 );
1993 }
1994}