Skip to main content

smart_big_rational/
denom.rs

1// Copyright 2023-2026 The SmartBigRational Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use num_bigint::{BigInt, BigUint, Sign};
16use num_integer::Integer;
17use num_traits::{One, Zero};
18use std::cmp::Ordering;
19use std::ops::{Div, DivAssign, Mul, MulAssign};
20
21/// Helper struct to represent the positive denominator of a rational number.
22///
23/// Under the hood, this decomposes the underlying integer as a product of small
24/// primes, multiplied by a regular big integer when that's not sufficient.
25#[derive(Clone, Debug, PartialEq, Eq)]
26pub struct Denom {
27    // Invariant: the representation is in canonical form, i.e. powers of small primes must
28    // saturate the primes array before overflowing into the remainder.
29    primes: [u8; Self::NUM_PRIMES],
30    remainder: Option<BigUint>,
31}
32
33impl Denom {
34    const NUM_PRIMES: usize = 24;
35    const PRIMES: [usize; Self::NUM_PRIMES] = [
36        2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89,
37    ];
38
39    /// Constant value of 1.
40    pub const ONE: Self = Denom {
41        primes: [0; Self::NUM_PRIMES],
42        remainder: None,
43    };
44
45    /// Converts this denominator into a big integer.
46    pub fn into_biguint(self) -> BigUint {
47        self.into()
48    }
49
50    /// Converts this denominator into a big integer.
51    pub fn to_biguint(&self) -> BigUint {
52        self.into()
53    }
54
55    fn decompose_now(mut x: BigUint) -> Self {
56        let mut primes = [0; Self::NUM_PRIMES];
57        'outer: for (i, &p) in Self::PRIMES.iter().enumerate() {
58            let p = BigUint::from(p);
59            while primes[i] != u8::MAX {
60                let (quo, rem) = x.div_rem(&p);
61                if !rem.is_zero() {
62                    break;
63                }
64                x = quo;
65                primes[i] += 1;
66                if x.is_one() {
67                    break 'outer;
68                }
69            }
70        }
71
72        let remainder = if x.is_one() { None } else { Some(x) };
73        Self { primes, remainder }
74    }
75
76    fn decompose_u8(mut x: u8) -> Self {
77        let mut primes = [0; Self::NUM_PRIMES];
78        'outer: for (i, &p) in Self::PRIMES.iter().enumerate() {
79            let p = p as u8;
80            while primes[i] != u8::MAX {
81                if !x.is_multiple_of(p) {
82                    break;
83                }
84                x /= p;
85                primes[i] += 1;
86                if x == 1 {
87                    break 'outer;
88                }
89            }
90        }
91
92        let remainder = if x == 1 { None } else { Some(x.into()) };
93        Self { primes, remainder }
94    }
95
96    fn decompose_u16(mut x: u16) -> Self {
97        let mut primes = [0; Self::NUM_PRIMES];
98        'outer: for (i, &p) in Self::PRIMES.iter().enumerate() {
99            let p = p as u16;
100            while primes[i] != u8::MAX {
101                if !x.is_multiple_of(p) {
102                    break;
103                }
104                x /= p;
105                primes[i] += 1;
106                if x == 1 {
107                    break 'outer;
108                }
109            }
110        }
111
112        let remainder = if x == 1 { None } else { Some(x.into()) };
113        Self { primes, remainder }
114    }
115
116    fn decompose_u32(mut x: u32) -> Self {
117        let mut primes = [0; Self::NUM_PRIMES];
118        'outer: for (i, &p) in Self::PRIMES.iter().enumerate() {
119            let p = p as u32;
120            while primes[i] != u8::MAX {
121                if !x.is_multiple_of(p) {
122                    break;
123                }
124                x /= p;
125                primes[i] += 1;
126                if x == 1 {
127                    break 'outer;
128                }
129            }
130        }
131
132        let remainder = if x == 1 { None } else { Some(x.into()) };
133        Self { primes, remainder }
134    }
135
136    fn decompose_u64(mut x: u64) -> Self {
137        let mut primes = [0; Self::NUM_PRIMES];
138        'outer: for (i, &p) in Self::PRIMES.iter().enumerate() {
139            let p = p as u64;
140            while primes[i] != u8::MAX {
141                if !x.is_multiple_of(p) {
142                    break;
143                }
144                x /= p;
145                primes[i] += 1;
146                if x == 1 {
147                    break 'outer;
148                }
149            }
150        }
151
152        let remainder = if x == 1 { None } else { Some(x.into()) };
153        Self { primes, remainder }
154    }
155
156    fn decompose_u128(mut x: u128) -> Self {
157        let mut primes = [0; Self::NUM_PRIMES];
158        'outer: for (i, &p) in Self::PRIMES.iter().enumerate() {
159            let p = p as u128;
160            while primes[i] != u8::MAX {
161                if !x.is_multiple_of(p) {
162                    break;
163                }
164                x /= p;
165                primes[i] += 1;
166                if x == 1 {
167                    break 'outer;
168                }
169            }
170        }
171
172        let remainder = if x == 1 { None } else { Some(x.into()) };
173        Self { primes, remainder }
174    }
175
176    fn decompose_usize(mut x: usize) -> Self {
177        let mut primes = [0; Self::NUM_PRIMES];
178        'outer: for (i, &p) in Self::PRIMES.iter().enumerate() {
179            while primes[i] != u8::MAX {
180                if !x.is_multiple_of(p) {
181                    break;
182                }
183                x /= p;
184                primes[i] += 1;
185                if x == 1 {
186                    break 'outer;
187                }
188            }
189        }
190
191        let remainder = if x == 1 { None } else { Some(x.into()) };
192        Self { primes, remainder }
193    }
194
195    fn decompose_mask(
196        remainder: &mut Option<BigUint>,
197        primes: &mut [u8; Self::NUM_PRIMES],
198        mask: [bool; Self::NUM_PRIMES],
199    ) {
200        let x: &mut BigUint = match remainder {
201            None => return,
202            Some(x) => x,
203        };
204
205        'outer: for (i, &p) in Self::PRIMES.iter().enumerate() {
206            if !mask[i] || primes[i] == u8::MAX {
207                continue;
208            }
209            let p = BigUint::from(p);
210            while primes[i] != u8::MAX {
211                let (quo, rem) = x.div_rem(&p);
212                if !rem.is_zero() {
213                    break;
214                }
215                *x = quo;
216                primes[i] += 1;
217                if x.is_one() {
218                    break 'outer;
219                }
220            }
221        }
222
223        if x.is_one() {
224            *remainder = None;
225        }
226    }
227
228    const fn decompose_small(mut x: usize) -> Self {
229        let mut primes = [0u8; Self::NUM_PRIMES];
230        // TODO: use a for loop once supported in `const fn` context.
231        let mut i = 0;
232        while x > 1 && i < Self::NUM_PRIMES {
233            let p = Self::PRIMES[i];
234            while x.is_multiple_of(p) {
235                x /= p;
236                primes[i] = primes[i].checked_add(1).unwrap();
237            }
238            i += 1;
239        }
240
241        if x != 1 {
242            panic!("Failed to decompose small integer into small prime factors.");
243        }
244        Self {
245            primes,
246            remainder: None,
247        }
248    }
249
250    // TODO: Use std::array::from_fn when available in const contexts.
251    const DECOMPOSED: [Self; 90] = [
252        Self::decompose_small(1),
253        Self::decompose_small(2),
254        Self::decompose_small(3),
255        Self::decompose_small(4),
256        Self::decompose_small(5),
257        Self::decompose_small(6),
258        Self::decompose_small(7),
259        Self::decompose_small(8),
260        Self::decompose_small(9),
261        Self::decompose_small(10),
262        Self::decompose_small(11),
263        Self::decompose_small(12),
264        Self::decompose_small(13),
265        Self::decompose_small(14),
266        Self::decompose_small(15),
267        Self::decompose_small(16),
268        Self::decompose_small(17),
269        Self::decompose_small(18),
270        Self::decompose_small(19),
271        Self::decompose_small(20),
272        Self::decompose_small(21),
273        Self::decompose_small(22),
274        Self::decompose_small(23),
275        Self::decompose_small(24),
276        Self::decompose_small(25),
277        Self::decompose_small(26),
278        Self::decompose_small(27),
279        Self::decompose_small(28),
280        Self::decompose_small(29),
281        Self::decompose_small(30),
282        Self::decompose_small(31),
283        Self::decompose_small(32),
284        Self::decompose_small(33),
285        Self::decompose_small(34),
286        Self::decompose_small(35),
287        Self::decompose_small(36),
288        Self::decompose_small(37),
289        Self::decompose_small(38),
290        Self::decompose_small(39),
291        Self::decompose_small(40),
292        Self::decompose_small(41),
293        Self::decompose_small(42),
294        Self::decompose_small(43),
295        Self::decompose_small(44),
296        Self::decompose_small(45),
297        Self::decompose_small(46),
298        Self::decompose_small(47),
299        Self::decompose_small(48),
300        Self::decompose_small(49),
301        Self::decompose_small(50),
302        Self::decompose_small(51),
303        Self::decompose_small(52),
304        Self::decompose_small(53),
305        Self::decompose_small(54),
306        Self::decompose_small(55),
307        Self::decompose_small(56),
308        Self::decompose_small(57),
309        Self::decompose_small(58),
310        Self::decompose_small(59),
311        Self::decompose_small(60),
312        Self::decompose_small(61),
313        Self::decompose_small(62),
314        Self::decompose_small(63),
315        Self::decompose_small(64),
316        Self::decompose_small(65),
317        Self::decompose_small(66),
318        Self::decompose_small(67),
319        Self::decompose_small(68),
320        Self::decompose_small(69),
321        Self::decompose_small(70),
322        Self::decompose_small(71),
323        Self::decompose_small(72),
324        Self::decompose_small(73),
325        Self::decompose_small(74),
326        Self::decompose_small(75),
327        Self::decompose_small(76),
328        Self::decompose_small(77),
329        Self::decompose_small(78),
330        Self::decompose_small(79),
331        Self::decompose_small(80),
332        Self::decompose_small(81),
333        Self::decompose_small(82),
334        Self::decompose_small(83),
335        Self::decompose_small(84),
336        Self::decompose_small(85),
337        Self::decompose_small(86),
338        Self::decompose_small(87),
339        Self::decompose_small(88),
340        Self::decompose_small(89),
341        Self::decompose_small(90),
342    ];
343
344    /// Returns the least common multiple of two denominators, adjusting the
345    /// numerators accordingly.
346    pub fn normalize(lnum: &mut BigInt, rnum: &mut BigInt, ldenom: &Self, rdenom: &Self) -> Self {
347        let mut primes = [0; Self::NUM_PRIMES];
348        let mut ltmp = 1_usize;
349        let mut rtmp = 1_usize;
350        for (i, &p) in Self::PRIMES.iter().enumerate() {
351            let lcount = ldenom.primes[i];
352            let rcount = rdenom.primes[i];
353            match lcount.cmp(&rcount) {
354                Ordering::Equal => {
355                    primes[i] = lcount;
356                }
357                Ordering::Less => {
358                    Self::accum_pow(lnum, &mut ltmp, p, rcount - lcount);
359                    primes[i] = rcount;
360                }
361                Ordering::Greater => {
362                    Self::accum_pow(rnum, &mut rtmp, p, lcount - rcount);
363                    primes[i] = lcount;
364                }
365            }
366        }
367
368        *lnum *= ltmp;
369        *rnum *= rtmp;
370        let remainder = match (&ldenom.remainder, &rdenom.remainder) {
371            (None, None) => None,
372            (None, Some(r)) => {
373                *lnum *= BigInt::from_biguint(Sign::Plus, r.clone());
374                Some(r.clone())
375            }
376            (Some(l), None) => {
377                *rnum *= BigInt::from_biguint(Sign::Plus, l.clone());
378                Some(l.clone())
379            }
380            (Some(l), Some(r)) => {
381                if l == r {
382                    Some(l.clone())
383                } else {
384                    *lnum *= BigInt::from_biguint(Sign::Plus, r.clone());
385                    *rnum *= BigInt::from_biguint(Sign::Plus, l.clone());
386                    Some(l * r)
387                }
388            }
389        };
390        Denom { primes, remainder }
391    }
392
393    /// Computes `prime.pow(exponent)` and multiplies it into the accumulated
394    /// `(numerator, tmp)`.
395    fn accum_pow(numerator: &mut BigInt, tmp: &mut usize, prime: usize, exponent: u8) {
396        for _ in 0..exponent {
397            match tmp.checked_mul(prime) {
398                Some(prod) => *tmp = prod,
399                None => {
400                    *numerator *= *tmp;
401                    *tmp = prime;
402                }
403            }
404        }
405    }
406
407    fn pow_primes(
408        this: &[u8; Self::NUM_PRIMES],
409        exponent: u32,
410        remainder: &mut Option<BigUint>,
411    ) -> [u8; Self::NUM_PRIMES] {
412        let mut primes = [0; Self::NUM_PRIMES];
413        for (i, &p) in Self::PRIMES.iter().enumerate() {
414            let product = this[i] as u32 * exponent;
415            if product <= u8::MAX as u32 {
416                primes[i] = product as u8;
417            } else {
418                primes[i] = u8::MAX;
419                let factor = BigUint::from(p).pow(product - u8::MAX as u32);
420                match remainder {
421                    None => *remainder = Some(factor),
422                    Some(r) => *r *= factor,
423                };
424            }
425        }
426        primes
427    }
428
429    fn mul_primes(
430        lhs: &[u8; Self::NUM_PRIMES],
431        rhs: &[u8; Self::NUM_PRIMES],
432        remainder: &mut Option<BigUint>,
433    ) -> [u8; Self::NUM_PRIMES] {
434        let mut primes = [0; Self::NUM_PRIMES];
435        for (i, &p) in Self::PRIMES.iter().enumerate() {
436            let sum = lhs[i] as u32 + rhs[i] as u32;
437            if sum <= u8::MAX as u32 {
438                primes[i] = sum as u8;
439            } else {
440                primes[i] = u8::MAX;
441                let factor = BigUint::from(p).pow(sum - u8::MAX as u32);
442                match remainder {
443                    None => *remainder = Some(factor),
444                    Some(r) => *r *= factor,
445                };
446            }
447        }
448        primes
449    }
450
451    fn div_primes(
452        num: &[u8; Self::NUM_PRIMES],
453        denom: &[u8; Self::NUM_PRIMES],
454        mut remainder: Option<BigUint>,
455    ) -> (Self, [bool; Self::NUM_PRIMES]) {
456        let mut primes = [0; Self::NUM_PRIMES];
457        let mut mask = [false; Self::NUM_PRIMES];
458        for (i, &p) in Self::PRIMES.iter().enumerate() {
459            mask[i] = num[i] == u8::MAX;
460            if num[i] >= denom[i] {
461                primes[i] = num[i] - denom[i];
462            } else {
463                primes[i] = 0;
464                let factor = BigUint::from(p).pow(denom[i] as u32 - num[i] as u32);
465                remainder = match remainder {
466                    None => Some(factor),
467                    Some(r) => Some(r * factor),
468                };
469            }
470        }
471        (Denom { primes, remainder }, mask)
472    }
473
474    /// Reduces this denominator together with the given numerator so that their
475    /// GCD is one.
476    pub fn gcd_reduce(&mut self, num: &mut BigInt) {
477        if let Some(remainder) = &mut self.remainder {
478            let gcd = remainder.gcd(num.magnitude());
479            if !gcd.is_one() {
480                *remainder /= &gcd;
481                if remainder.is_one() {
482                    self.remainder = None;
483                }
484                let gcd: BigInt = gcd.into();
485                *num /= gcd;
486            }
487        }
488
489        'outer: for (i, &p) in Self::PRIMES.iter().enumerate() {
490            if self.primes[i] != 0 {
491                let p = BigInt::from(p);
492                while self.primes[i] != 0 {
493                    let (quo, rem) = num.div_rem(&p);
494                    if !rem.is_zero() {
495                        break;
496                    }
497                    *num = quo;
498                    self.primes[i] -= 1;
499                    if num.magnitude().is_one() {
500                        break 'outer;
501                    }
502                }
503            }
504        }
505    }
506}
507
508impl From<u8> for Denom {
509    fn from(value: u8) -> Denom {
510        if value == 0 {
511            panic!("Attempted to create a denominator of zero");
512        }
513        if value <= 90 {
514            return Denom::DECOMPOSED[value as usize - 1].clone();
515        }
516        Denom::decompose_u8(value)
517    }
518}
519
520impl From<u16> for Denom {
521    fn from(value: u16) -> Denom {
522        if value == 0 {
523            panic!("Attempted to create a denominator of zero");
524        }
525        if value <= 90 {
526            return Denom::DECOMPOSED[value as usize - 1].clone();
527        }
528        Denom::decompose_u16(value)
529    }
530}
531
532impl From<u32> for Denom {
533    fn from(value: u32) -> Denom {
534        if value == 0 {
535            panic!("Attempted to create a denominator of zero");
536        }
537        if value <= 90 {
538            return Denom::DECOMPOSED[value as usize - 1].clone();
539        }
540        Denom::decompose_u32(value)
541    }
542}
543
544impl From<u64> for Denom {
545    fn from(value: u64) -> Denom {
546        if value == 0 {
547            panic!("Attempted to create a denominator of zero");
548        }
549        if value <= 90 {
550            return Denom::DECOMPOSED[value as usize - 1].clone();
551        }
552        Denom::decompose_u64(value)
553    }
554}
555
556impl From<u128> for Denom {
557    fn from(value: u128) -> Denom {
558        if value == 0 {
559            panic!("Attempted to create a denominator of zero");
560        }
561        if value <= 90 {
562            return Denom::DECOMPOSED[value as usize - 1].clone();
563        }
564        Denom::decompose_u128(value)
565    }
566}
567
568impl From<usize> for Denom {
569    fn from(value: usize) -> Denom {
570        if value == 0 {
571            panic!("Attempted to create a denominator of zero");
572        }
573        if value <= 90 {
574            return Denom::DECOMPOSED[value - 1].clone();
575        }
576        Denom::decompose_usize(value)
577    }
578}
579
580impl From<BigUint> for Denom {
581    fn from(value: BigUint) -> Denom {
582        if value.is_zero() {
583            panic!("Attempted to create a denominator of zero");
584        }
585        if value <= BigUint::from(90_usize) {
586            return Denom::DECOMPOSED[TryInto::<usize>::try_into(value).unwrap() - 1].clone();
587        }
588        Denom::decompose_now(value)
589    }
590}
591
592impl From<&BigUint> for Denom {
593    fn from(value: &BigUint) -> Denom {
594        if value.is_zero() {
595            panic!("Attempted to create a denominator of zero");
596        }
597        if *value <= BigUint::from(90_usize) {
598            return Denom::DECOMPOSED[TryInto::<usize>::try_into(value).unwrap() - 1].clone();
599        }
600        Denom::decompose_now(value.clone())
601    }
602}
603
604impl From<Denom> for BigUint {
605    fn from(value: Denom) -> BigUint {
606        let mut result = match value.remainder {
607            Some(x) => x,
608            None => BigUint::ONE,
609        };
610        let mut tmp = 1_usize;
611        for (i, &count) in value.primes.iter().enumerate() {
612            let p = Denom::PRIMES[i];
613            for _ in 0..count {
614                match tmp.checked_mul(p) {
615                    Some(prod) => tmp = prod,
616                    None => {
617                        result *= tmp;
618                        tmp = p;
619                    }
620                }
621            }
622        }
623        result * tmp
624    }
625}
626
627impl From<&Denom> for BigUint {
628    fn from(value: &Denom) -> BigUint {
629        let mut result = match &value.remainder {
630            Some(x) => x.clone(),
631            None => BigUint::ONE,
632        };
633        let mut tmp = 1_usize;
634        for (i, &count) in value.primes.iter().enumerate() {
635            let p = Denom::PRIMES[i];
636            for _ in 0..count {
637                match tmp.checked_mul(p) {
638                    Some(prod) => tmp = prod,
639                    None => {
640                        result *= tmp;
641                        tmp = p;
642                    }
643                }
644            }
645        }
646        result * tmp
647    }
648}
649
650impl One for Denom {
651    fn one() -> Self {
652        Self::ONE
653    }
654}
655
656impl num_traits::Pow<u32> for Denom {
657    type Output = Self;
658
659    fn pow(mut self, rhs: u32) -> Self {
660        if rhs == 0 {
661            return Denom::ONE;
662        }
663        let primes = Denom::pow_primes(&self.primes, rhs, &mut self.remainder);
664        Denom {
665            primes,
666            remainder: self.remainder,
667        }
668    }
669}
670
671impl num_traits::Pow<u32> for &Denom {
672    type Output = Denom;
673
674    fn pow(self, rhs: u32) -> Denom {
675        if rhs == 0 {
676            return Denom::ONE;
677        }
678        let mut remainder = self.remainder.clone();
679        let primes = Denom::pow_primes(&self.primes, rhs, &mut remainder);
680        Denom { primes, remainder }
681    }
682}
683
684impl Mul for Denom {
685    type Output = Self;
686
687    fn mul(self, rhs: Self) -> Self {
688        let mut remainder = match (self.remainder, rhs.remainder) {
689            (None, None) => None,
690            (None, Some(r)) => Some(r),
691            (Some(l), None) => Some(l),
692            (Some(l), Some(r)) => Some(l * r),
693        };
694        let primes = Denom::mul_primes(&self.primes, &rhs.primes, &mut remainder);
695        Denom { primes, remainder }
696    }
697}
698
699impl Mul<&Denom> for Denom {
700    type Output = Self;
701
702    fn mul(self, rhs: &Denom) -> Self {
703        let mut remainder = match (self.remainder, &rhs.remainder) {
704            (None, None) => None,
705            (None, Some(r)) => Some(r.clone()),
706            (Some(l), None) => Some(l),
707            (Some(l), Some(r)) => Some(l * r),
708        };
709        let primes = Denom::mul_primes(&self.primes, &rhs.primes, &mut remainder);
710        Denom { primes, remainder }
711    }
712}
713
714impl Mul for &Denom {
715    type Output = Denom;
716
717    fn mul(self, rhs: Self) -> Denom {
718        let mut remainder = match (&self.remainder, &rhs.remainder) {
719            (None, None) => None,
720            (None, Some(r)) => Some(r.clone()),
721            (Some(l), None) => Some(l.clone()),
722            (Some(l), Some(r)) => Some(l * r),
723        };
724        let primes = Denom::mul_primes(&self.primes, &rhs.primes, &mut remainder);
725        Denom { primes, remainder }
726    }
727}
728
729impl Mul<Denom> for &Denom {
730    type Output = Denom;
731
732    fn mul(self, rhs: Denom) -> Denom {
733        let mut remainder = match (&self.remainder, rhs.remainder) {
734            (None, None) => None,
735            (None, Some(r)) => Some(r),
736            (Some(l), None) => Some(l.clone()),
737            (Some(l), Some(r)) => Some(l * r),
738        };
739        let primes = Denom::mul_primes(&self.primes, &rhs.primes, &mut remainder);
740        Denom { primes, remainder }
741    }
742}
743
744impl MulAssign for Denom {
745    fn mul_assign(&mut self, rhs: Self) {
746        match (&mut self.remainder, rhs.remainder) {
747            (_, None) => (),
748            (None, Some(r)) => self.remainder = Some(r),
749            (Some(l), Some(r)) => *l *= r,
750        };
751        self.primes = Denom::mul_primes(&self.primes, &rhs.primes, &mut self.remainder);
752    }
753}
754
755impl MulAssign<&Denom> for Denom {
756    fn mul_assign(&mut self, rhs: &Denom) {
757        match (&mut self.remainder, &rhs.remainder) {
758            (_, None) => (),
759            (None, Some(r)) => self.remainder = Some(r.clone()),
760            (Some(l), Some(r)) => *l *= r,
761        };
762        self.primes = Denom::mul_primes(&self.primes, &rhs.primes, &mut self.remainder);
763    }
764}
765
766impl Div for Denom {
767    type Output = Self;
768
769    /// Divides this denominator by the other one.
770    ///
771    /// This function panics if the other one doesn't divide this one.
772    fn div(self, rhs: Self) -> Self {
773        let (
774            Denom {
775                mut primes,
776                remainder: rhs_remainder,
777            },
778            mask,
779        ) = Denom::div_primes(&self.primes, &rhs.primes, rhs.remainder);
780
781        let mut remainder = match (self.remainder, rhs_remainder) {
782            (None, None) => None,
783            (None, Some(r)) => {
784                if !r.is_one() {
785                    panic!("Attempted to divide a denominator by a non-divisor");
786                }
787                None
788            }
789            (Some(l), None) => Some(l),
790            (Some(l), Some(r)) => {
791                let (quo, rem) = l.div_rem(&r);
792                if !rem.is_zero() {
793                    panic!("Attempted to divide a denominator by a non-divisor");
794                }
795                if quo.is_one() { None } else { Some(quo) }
796            }
797        };
798
799        Denom::decompose_mask(&mut remainder, &mut primes, mask);
800        Denom { primes, remainder }
801    }
802}
803
804impl Div<&Denom> for Denom {
805    type Output = Self;
806
807    /// Divides this denominator by the other one.
808    ///
809    /// This function panics if the other one doesn't divide this one.
810    fn div(self, rhs: &Denom) -> Self {
811        let (
812            Denom {
813                mut primes,
814                remainder: rhs_remainder,
815            },
816            mask,
817        ) = Denom::div_primes(&self.primes, &rhs.primes, rhs.remainder.clone());
818
819        let mut remainder = match (self.remainder, rhs_remainder) {
820            (None, None) => None,
821            (None, Some(r)) => {
822                if !r.is_one() {
823                    panic!("Attempted to divide a denominator by a non-divisor");
824                }
825                None
826            }
827            (Some(l), None) => Some(l),
828            (Some(l), Some(r)) => {
829                let (quo, rem) = l.div_rem(&r);
830                if !rem.is_zero() {
831                    panic!("Attempted to divide a denominator by a non-divisor");
832                }
833                if quo.is_one() { None } else { Some(quo) }
834            }
835        };
836
837        Denom::decompose_mask(&mut remainder, &mut primes, mask);
838        Denom { primes, remainder }
839    }
840}
841
842impl Div for &Denom {
843    type Output = Denom;
844
845    /// Divides this denominator by the other one.
846    ///
847    /// This function panics if the other one doesn't divide this one.
848    fn div(self, rhs: Self) -> Denom {
849        let (
850            Denom {
851                mut primes,
852                remainder: rhs_remainder,
853            },
854            mask,
855        ) = Denom::div_primes(&self.primes, &rhs.primes, rhs.remainder.clone());
856
857        let mut remainder = match (&self.remainder, rhs_remainder) {
858            (None, None) => None,
859            (None, Some(r)) => {
860                if !r.is_one() {
861                    panic!("Attempted to divide a denominator by a non-divisor");
862                }
863                None
864            }
865            (Some(l), None) => Some(l.clone()),
866            (Some(l), Some(r)) => {
867                let (quo, rem) = l.div_rem(&r);
868                if !rem.is_zero() {
869                    panic!("Attempted to divide a denominator by a non-divisor");
870                }
871                if quo.is_one() { None } else { Some(quo) }
872            }
873        };
874
875        Denom::decompose_mask(&mut remainder, &mut primes, mask);
876        Denom { primes, remainder }
877    }
878}
879
880impl Div<Denom> for &Denom {
881    type Output = Denom;
882
883    /// Divides this denominator by the other one.
884    ///
885    /// This function panics if the other one doesn't divide this one.
886    fn div(self, rhs: Denom) -> Denom {
887        let (
888            Denom {
889                mut primes,
890                remainder: rhs_remainder,
891            },
892            mask,
893        ) = Denom::div_primes(&self.primes, &rhs.primes, rhs.remainder);
894
895        let mut remainder = match (&self.remainder, rhs_remainder) {
896            (None, None) => None,
897            (None, Some(r)) => {
898                if !r.is_one() {
899                    panic!("Attempted to divide a denominator by a non-divisor");
900                }
901                None
902            }
903            (Some(l), None) => Some(l.clone()),
904            (Some(l), Some(r)) => {
905                let (quo, rem) = l.div_rem(&r);
906                if !rem.is_zero() {
907                    panic!("Attempted to divide a denominator by a non-divisor");
908                }
909                if quo.is_one() { None } else { Some(quo) }
910            }
911        };
912
913        Denom::decompose_mask(&mut remainder, &mut primes, mask);
914        Denom { primes, remainder }
915    }
916}
917
918impl DivAssign for Denom {
919    /// Divides this denominator by the other one.
920    ///
921    /// This function panics if the other one doesn't divide this one.
922    fn div_assign(&mut self, rhs: Self) {
923        let (
924            Denom {
925                primes,
926                remainder: rhs_remainder,
927            },
928            mask,
929        ) = Denom::div_primes(&self.primes, &rhs.primes, rhs.remainder);
930        self.primes = primes;
931
932        match (&mut self.remainder, rhs_remainder) {
933            (_, None) => (),
934            (None, Some(r)) => {
935                if !r.is_one() {
936                    panic!("Attempted to divide a denominator by a non-divisor");
937                }
938            }
939            (Some(l), Some(r)) => {
940                let (quo, rem) = l.div_rem(&r);
941                if !rem.is_zero() {
942                    panic!("Attempted to divide a denominator by a non-divisor");
943                }
944                if quo.is_one() {
945                    self.remainder = None
946                } else {
947                    *l = quo;
948                }
949            }
950        };
951
952        Denom::decompose_mask(&mut self.remainder, &mut self.primes, mask);
953    }
954}
955
956impl DivAssign<&Denom> for Denom {
957    /// Divides this denominator by the other one.
958    ///
959    /// This function panics if the other one doesn't divide this one.
960    fn div_assign(&mut self, rhs: &Denom) {
961        let (
962            Denom {
963                primes,
964                remainder: rhs_remainder,
965            },
966            mask,
967        ) = Denom::div_primes(&self.primes, &rhs.primes, rhs.remainder.clone());
968        self.primes = primes;
969
970        match (&mut self.remainder, rhs_remainder) {
971            (_, None) => (),
972            (None, Some(r)) => {
973                if !r.is_one() {
974                    panic!("Attempted to divide a denominator by a non-divisor");
975                }
976            }
977            (Some(l), Some(r)) => {
978                let (quo, rem) = l.div_rem(&r);
979                if !rem.is_zero() {
980                    panic!("Attempted to divide a denominator by a non-divisor");
981                }
982                if quo.is_one() {
983                    self.remainder = None
984                } else {
985                    *l = quo;
986                }
987            }
988        };
989
990        Denom::decompose_mask(&mut self.remainder, &mut self.primes, mask);
991    }
992}
993
994impl Mul<Denom> for BigInt {
995    type Output = Self;
996
997    fn mul(mut self, rhs: Denom) -> Self {
998        let mut tmp = 1_usize;
999        for (i, &p) in Denom::PRIMES.iter().enumerate() {
1000            let count = rhs.primes[i];
1001            if count != 0 {
1002                Denom::accum_pow(&mut self, &mut tmp, p, count);
1003            }
1004        }
1005
1006        self *= tmp;
1007        if let Some(remainder) = rhs.remainder {
1008            self *= BigInt::from_biguint(Sign::Plus, remainder);
1009        }
1010        self
1011    }
1012}
1013
1014impl Mul<&Denom> for BigInt {
1015    type Output = Self;
1016
1017    fn mul(mut self, rhs: &Denom) -> Self {
1018        let mut tmp = 1_usize;
1019        for (i, &p) in Denom::PRIMES.iter().enumerate() {
1020            let count = rhs.primes[i];
1021            if count != 0 {
1022                Denom::accum_pow(&mut self, &mut tmp, p, count);
1023            }
1024        }
1025
1026        self *= tmp;
1027        if let Some(remainder) = &rhs.remainder {
1028            self *= BigInt::from_biguint(Sign::Plus, remainder.clone());
1029        }
1030        self
1031    }
1032}
1033
1034impl Mul<Denom> for &BigInt {
1035    type Output = BigInt;
1036
1037    fn mul(self, rhs: Denom) -> BigInt {
1038        let mut this = self.clone();
1039        let mut tmp = 1_usize;
1040        for (i, &p) in Denom::PRIMES.iter().enumerate() {
1041            let count = rhs.primes[i];
1042            if count != 0 {
1043                Denom::accum_pow(&mut this, &mut tmp, p, count);
1044            }
1045        }
1046
1047        this *= tmp;
1048        if let Some(remainder) = rhs.remainder {
1049            this *= BigInt::from_biguint(Sign::Plus, remainder);
1050        }
1051        this
1052    }
1053}
1054
1055impl Mul<&Denom> for &BigInt {
1056    type Output = BigInt;
1057
1058    fn mul(self, rhs: &Denom) -> BigInt {
1059        let mut this = self.clone();
1060        let mut tmp = 1_usize;
1061        for (i, &p) in Denom::PRIMES.iter().enumerate() {
1062            let count = rhs.primes[i];
1063            if count != 0 {
1064                Denom::accum_pow(&mut this, &mut tmp, p, count);
1065            }
1066        }
1067
1068        this *= tmp;
1069        if let Some(remainder) = &rhs.remainder {
1070            this *= BigInt::from_biguint(Sign::Plus, remainder.clone());
1071        }
1072        this
1073    }
1074}
1075
1076impl Mul<BigInt> for Denom {
1077    type Output = BigInt;
1078
1079    fn mul(self, mut rhs: BigInt) -> BigInt {
1080        let mut tmp = 1_usize;
1081        for (i, &p) in Denom::PRIMES.iter().enumerate() {
1082            let count = self.primes[i];
1083            if count != 0 {
1084                Denom::accum_pow(&mut rhs, &mut tmp, p, count);
1085            }
1086        }
1087
1088        rhs *= tmp;
1089        if let Some(remainder) = self.remainder {
1090            rhs *= BigInt::from_biguint(Sign::Plus, remainder);
1091        }
1092        rhs
1093    }
1094}
1095
1096impl Mul<&BigInt> for Denom {
1097    type Output = BigInt;
1098
1099    fn mul(self, rhs: &BigInt) -> BigInt {
1100        let mut rhs = rhs.clone();
1101        let mut tmp = 1_usize;
1102        for (i, &p) in Denom::PRIMES.iter().enumerate() {
1103            let count = self.primes[i];
1104            if count != 0 {
1105                Denom::accum_pow(&mut rhs, &mut tmp, p, count);
1106            }
1107        }
1108
1109        rhs *= tmp;
1110        if let Some(remainder) = self.remainder {
1111            rhs *= BigInt::from_biguint(Sign::Plus, remainder);
1112        }
1113        rhs
1114    }
1115}
1116
1117impl Mul<BigInt> for &Denom {
1118    type Output = BigInt;
1119
1120    fn mul(self, mut rhs: BigInt) -> BigInt {
1121        let mut tmp = 1_usize;
1122        for (i, &p) in Denom::PRIMES.iter().enumerate() {
1123            let count = self.primes[i];
1124            if count != 0 {
1125                Denom::accum_pow(&mut rhs, &mut tmp, p, count);
1126            }
1127        }
1128
1129        rhs *= tmp;
1130        if let Some(remainder) = &self.remainder {
1131            rhs *= BigInt::from_biguint(Sign::Plus, remainder.clone());
1132        }
1133        rhs
1134    }
1135}
1136
1137impl Mul<&BigInt> for &Denom {
1138    type Output = BigInt;
1139
1140    fn mul(self, rhs: &BigInt) -> BigInt {
1141        let mut rhs = rhs.clone();
1142        let mut tmp = 1_usize;
1143        for (i, &p) in Denom::PRIMES.iter().enumerate() {
1144            let count = self.primes[i];
1145            if count != 0 {
1146                Denom::accum_pow(&mut rhs, &mut tmp, p, count);
1147            }
1148        }
1149
1150        rhs *= tmp;
1151        if let Some(remainder) = &self.remainder {
1152            rhs *= BigInt::from_biguint(Sign::Plus, remainder.clone());
1153        }
1154        rhs
1155    }
1156}
1157
1158impl MulAssign<Denom> for BigInt {
1159    fn mul_assign(&mut self, rhs: Denom) {
1160        let mut tmp = 1_usize;
1161        for (i, &p) in Denom::PRIMES.iter().enumerate() {
1162            let count = rhs.primes[i];
1163            if count != 0 {
1164                Denom::accum_pow(self, &mut tmp, p, count);
1165            }
1166        }
1167
1168        *self *= tmp;
1169        if let Some(remainder) = rhs.remainder {
1170            *self *= BigInt::from_biguint(Sign::Plus, remainder);
1171        }
1172    }
1173}
1174
1175impl MulAssign<&Denom> for BigInt {
1176    fn mul_assign(&mut self, rhs: &Denom) {
1177        let mut tmp = 1_usize;
1178        for (i, &p) in Denom::PRIMES.iter().enumerate() {
1179            let count = rhs.primes[i];
1180            if count != 0 {
1181                Denom::accum_pow(self, &mut tmp, p, count);
1182            }
1183        }
1184
1185        *self *= tmp;
1186        if let Some(remainder) = &rhs.remainder {
1187            *self *= BigInt::from_biguint(Sign::Plus, remainder.clone());
1188        }
1189    }
1190}
1191
1192#[cfg(test)]
1193mod tests {
1194    use super::*;
1195
1196    #[test]
1197    fn test_decompose_small() {
1198        for (i, x) in Denom::DECOMPOSED.iter().enumerate() {
1199            assert_eq!(x, &Denom::decompose_small(i + 1));
1200            assert_eq!(x, &Denom::from(BigUint::from(i + 1)));
1201            assert_eq!(x, &Denom::decompose_now(BigUint::from(i + 1)));
1202        }
1203    }
1204
1205    #[test]
1206    #[should_panic(expected = "Failed to decompose small integer into small prime factors.")]
1207    fn test_decompose_small_out_of_range() {
1208        assert_eq!(
1209            Denom::decompose_small(97).to_biguint(),
1210            BigUint::from(97_usize)
1211        );
1212    }
1213
1214    #[test]
1215    fn test_decompose_is_correct() {
1216        for i in 1_usize..=1000 {
1217            let bigi = BigUint::from(i);
1218            let x = Denom::from(&bigi);
1219            let mut recomposed = x.remainder.unwrap_or_else(BigUint::one);
1220            for (i, &prime) in Denom::PRIMES.iter().enumerate() {
1221                for _ in 0..x.primes[i] {
1222                    recomposed *= prime;
1223                }
1224            }
1225            assert_eq!(recomposed, bigi);
1226        }
1227    }
1228
1229    #[test]
1230    fn test_decompose_known_values() {
1231        assert_eq!(
1232            Denom::from(BigUint::from(128_usize)),
1233            Denom {
1234                primes: [
1235                    7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1236                ],
1237                remainder: None,
1238            }
1239        );
1240        assert_eq!(
1241            Denom::from(BigUint::from(89_usize)),
1242            Denom {
1243                primes: [
1244                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
1245                ],
1246                remainder: None,
1247            }
1248        );
1249        assert_eq!(
1250            Denom::from(BigUint::from(97_usize)),
1251            Denom {
1252                primes: [
1253                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1254                ],
1255                remainder: Some(BigUint::from(97_usize)),
1256            }
1257        );
1258        assert_eq!(
1259            Denom::from(BigUint::from(97000_usize)),
1260            Denom {
1261                primes: [
1262                    3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1263                ],
1264                remainder: Some(BigUint::from(97_usize)),
1265            }
1266        );
1267    }
1268
1269    #[test]
1270    fn test_decompose_prime_powers() {
1271        for (i, &p) in Denom::PRIMES.iter().enumerate() {
1272            let p = BigUint::from(p);
1273            for power in 1..=255 {
1274                assert_eq!(
1275                    Denom::from(p.pow(power as u32)),
1276                    Denom {
1277                        primes: std::array::from_fn(|j| if i == j { power } else { 0 }),
1278                        remainder: None,
1279                    }
1280                );
1281            }
1282            for power in 1..=64 {
1283                assert_eq!(
1284                    Denom::from(p.pow(255 + power)),
1285                    Denom {
1286                        primes: std::array::from_fn(|j| if i == j { 255 } else { 0 }),
1287                        remainder: Some(p.pow(power)),
1288                    }
1289                );
1290            }
1291        }
1292    }
1293
1294    #[test]
1295    fn test_mul_prime_powers() {
1296        let p = BigUint::from(2u32);
1297        for a in 1..=256 {
1298            let denom_a = Denom::from(p.pow(a));
1299            for b in 1..=256 {
1300                let denom_b = Denom::from(p.pow(b));
1301                let denom_ab = Denom::from(p.pow(a + b));
1302                assert_eq!(&denom_a * denom_b, denom_ab);
1303            }
1304        }
1305    }
1306
1307    #[test]
1308    fn test_div_prime_powers() {
1309        let p = BigUint::from(2u32);
1310        for a in 1..=256 {
1311            let denom_a = Denom::from(p.pow(a));
1312            for b in 1..=256 {
1313                let denom_b = Denom::from(p.pow(b));
1314                let denom_ab = Denom::from(p.pow(a + b));
1315                assert_eq!(denom_ab / denom_b, denom_a);
1316            }
1317        }
1318    }
1319
1320    #[test]
1321    fn test_to_biguint() {
1322        for i in 1_usize..=1000 {
1323            let bigi = BigUint::from(i);
1324            let x = Denom::from(&bigi);
1325            assert_eq!(x.to_biguint(), bigi);
1326        }
1327    }
1328
1329    #[test]
1330    fn test_product() {
1331        let values = (100..200)
1332            .map(|i: usize| Denom::from(BigUint::from(i)))
1333            .collect::<Vec<_>>();
1334        for (i, x) in values.iter().enumerate().map(|(i, x)| (i + 100, x)) {
1335            for (j, y) in values.iter().enumerate().map(|(j, y)| (j + 100, y)) {
1336                let z = x * y;
1337                assert_eq!(z, Denom::from(BigUint::from(i * j)));
1338                for k in 0..Denom::NUM_PRIMES {
1339                    assert_eq!(z.primes[k], x.primes[k] + y.primes[k]);
1340                }
1341            }
1342        }
1343    }
1344
1345    #[test]
1346    fn test_normalize() {
1347        let values = (100..200)
1348            .map(|i: usize| Denom::from(BigUint::from(i)))
1349            .collect::<Vec<_>>();
1350        for x in &values {
1351            for y in &values {
1352                let mut xnum = BigInt::one();
1353                let mut ynum = BigInt::one();
1354                let lcm = Denom::normalize(&mut xnum, &mut ynum, x, y);
1355                let lcm_bigint = lcm.to_biguint();
1356                let xnum = xnum.to_biguint().unwrap();
1357                let ynum = ynum.to_biguint().unwrap();
1358
1359                assert_eq!(xnum * x.to_biguint(), lcm_bigint);
1360                assert_eq!(ynum * y.to_biguint(), lcm_bigint);
1361                for k in 0..Denom::NUM_PRIMES {
1362                    assert_eq!(lcm.primes[k], std::cmp::max(x.primes[k], y.primes[k]));
1363                }
1364            }
1365        }
1366    }
1367
1368    #[test]
1369    fn test_gcd_reduce() {
1370        let mut num = BigInt::from(-3 * 97);
1371        let mut denom = Denom::from(BigUint::from(3u32 * 5 * 97));
1372        denom.gcd_reduce(&mut num);
1373        assert_eq!(num, BigInt::from(-1));
1374        assert_eq!(denom, Denom::from(BigUint::from(5u32)));
1375    }
1376}