dashu_int/third_party/
num_integer.rs

1//! Implement num-integer traits.
2
3use crate::{ibig::IBig, ubig::UBig};
4use dashu_base::{BitTest, CubicRoot, DivRem, ExtendedGcd, Gcd, Sign, SquareRoot};
5use num_integer_v01 as num_integer;
6
7impl num_integer::Integer for UBig {
8    #[inline]
9    fn div_floor(&self, other: &Self) -> Self {
10        self / other
11    }
12    #[inline]
13    fn div_rem(&self, other: &Self) -> (Self, Self) {
14        DivRem::div_rem(self, other)
15    }
16    #[inline]
17    fn mod_floor(&self, other: &Self) -> Self {
18        self & other
19    }
20    #[inline]
21    fn divides(&self, other: &Self) -> bool {
22        (self % other).is_zero()
23    }
24    #[inline]
25    fn is_multiple_of(&self, other: &Self) -> bool {
26        UBig::is_multiple_of(self, other)
27    }
28    #[inline]
29    fn is_even(&self) -> bool {
30        !self.bit(0)
31    }
32    #[inline]
33    fn is_odd(&self) -> bool {
34        self.bit(0)
35    }
36    #[inline]
37    fn gcd(&self, other: &Self) -> Self {
38        Gcd::gcd(self, other)
39    }
40    #[inline]
41    fn lcm(&self, other: &Self) -> Self {
42        if self.is_zero() && other.is_zero() {
43            UBig::ZERO
44        } else {
45            self / Gcd::gcd(self, other) * other
46        }
47    }
48    #[inline]
49    fn extended_gcd(&self, other: &Self) -> num_integer::ExtendedGcd<Self> {
50        let (g, x, y) = ExtendedGcd::gcd_ext(self, other);
51        num_integer::ExtendedGcd {
52            gcd: g,
53            x: x.try_into().unwrap(),
54            y: y.try_into().unwrap(),
55        }
56    }
57}
58
59impl num_integer::Roots for UBig {
60    #[inline]
61    fn sqrt(&self) -> Self {
62        SquareRoot::sqrt(self)
63    }
64    #[inline]
65    fn cbrt(&self) -> Self {
66        CubicRoot::cbrt(self)
67    }
68    #[inline]
69    fn nth_root(&self, n: u32) -> Self {
70        self.nth_root(n as usize)
71    }
72}
73
74impl num_integer::Integer for IBig {
75    #[inline]
76    fn div_floor(&self, other: &Self) -> Self {
77        let (q, r) = DivRem::div_rem(self, other);
78        if !r.is_zero() && q.sign() == Sign::Negative {
79            q - IBig::ONE
80        } else {
81            q
82        }
83    }
84    #[inline]
85    fn div_rem(&self, other: &Self) -> (Self, Self) {
86        DivRem::div_rem(self, other)
87    }
88    #[inline]
89    fn mod_floor(&self, other: &Self) -> Self {
90        let r = self % other;
91        if !r.is_zero() && self.sign() * other.sign() == Sign::Negative {
92            other + r
93        } else {
94            r
95        }
96    }
97    #[inline]
98    fn divides(&self, other: &Self) -> bool {
99        (self % other).is_zero()
100    }
101    #[inline]
102    fn is_multiple_of(&self, other: &Self) -> bool {
103        IBig::is_multiple_of(self, other)
104    }
105    #[inline]
106    fn is_even(&self) -> bool {
107        (self & IBig::ONE).is_zero()
108    }
109    #[inline]
110    fn is_odd(&self) -> bool {
111        (self & IBig::ONE).is_one()
112    }
113    #[inline]
114    fn gcd(&self, other: &Self) -> Self {
115        Gcd::gcd(self, other).into()
116    }
117    #[inline]
118    fn lcm(&self, other: &Self) -> Self {
119        if self.is_zero() && other.is_zero() {
120            IBig::ZERO
121        } else {
122            self / Gcd::gcd(self, other) * other
123        }
124    }
125    #[inline]
126    fn extended_gcd(&self, other: &Self) -> num_integer::ExtendedGcd<Self> {
127        let (g, x, y) = ExtendedGcd::gcd_ext(self, other);
128        num_integer::ExtendedGcd {
129            gcd: g.into(),
130            x,
131            y,
132        }
133    }
134}
135
136impl num_integer::Roots for IBig {
137    #[inline]
138    fn sqrt(&self) -> Self {
139        SquareRoot::sqrt(self).into()
140    }
141    #[inline]
142    fn cbrt(&self) -> Self {
143        CubicRoot::cbrt(self)
144    }
145    #[inline]
146    fn nth_root(&self, n: u32) -> Self {
147        self.nth_root(n as usize)
148    }
149}