1macro_rules! to_int {
2 { $Digit: ident; $($name: ident -> $int: ty), * } => {
3 $(
4 #[inline]
5 fn $name(&self) -> Option<$int> {
6 let mut out = 0;
7 let mut i = 0;
8 if $Digit::BITS > <$int>::BITS {
9 let small = self.digits[i] as $int;
10 let trunc = small as $Digit;
11 if self.digits[i] != trunc {
12 return None;
13 }
14 out = small;
15 i = 1;
16 } else {
17 loop {
18 let shift = i << crate::digit::$Digit::BIT_SHIFT;
19 if i >= N || shift >= <$int>::BITS as usize {
20 break;
21 }
22 out |= self.digits[i] as $int << shift;
23 i += 1;
24 }
25 }
26
27 #[allow(unused_comparisons)]
28 if out < 0 {
29 return None;
30 }
31
32 while i < N {
33 if self.digits[i] != 0 {
34 return None;
35 }
36 i += 1;
37 }
38
39 Some(out)
40 }
41 )*
42 };
43}
44
45pub const fn u32_bits(u: u32) -> ExpType {
46 32 - u.leading_zeros() as ExpType
47}
48
49pub const fn u64_bits(u: u64) -> ExpType {
50 64 - u.leading_zeros() as ExpType
51}
52use crate::buint::cast::{decode_f32, decode_f64};
53use crate::ExpType;
55use num_integer::{Integer, Roots};
56use num_traits::{
57 AsPrimitive, Bounded, CheckedAdd, CheckedDiv, CheckedEuclid, CheckedMul, CheckedNeg,
58 CheckedRem, CheckedShl, CheckedShr, CheckedSub, Euclid, FromPrimitive, MulAdd, MulAddAssign,
59 Num, One, Pow, PrimInt, Saturating, SaturatingAdd, SaturatingMul, SaturatingSub, ToPrimitive,
60 Unsigned, WrappingAdd, WrappingMul, WrappingNeg, WrappingShl, WrappingShr, WrappingSub, Zero,
61};
62
63use crate::cast::CastFrom;
64use crate::int::numtraits::num_trait_impl;
65
66macro_rules! numtraits {
67 ($BUint: ident, $BInt: ident, $Digit: ident) => {
68 crate::int::numtraits::impls!($BUint, $BUint, $BInt);
69
70 macro_rules! from_float {
71 ($method: ident, $float: ty, $decoder: ident, $mant_bits: ident) => {
72 #[inline]
73 fn $method(f: $float) -> Option<Self> {
74 if !f.is_finite() {
75 return None;
76 }
77 if f == 0.0 {
78 return Some(Self::ZERO);
79 }
80 if f.is_sign_negative() {
81 return None;
82 }
83 let (mut mant, exp) = $decoder(f);
84 if exp.is_negative() {
85 mant = mant.checked_shr((-exp) as ExpType).unwrap_or(0);
86 if $mant_bits(mant) > Self::BITS {
87 return None;
88 }
89 Some(Self::cast_from(mant))
90 } else {
91 if $mant_bits(mant) + exp as ExpType > Self::BITS {
92 return None;
93 }
94 Some(Self::cast_from(mant) << exp)
95 }
96 }
97 };
98 }
99
100 impl<const N: usize> FromPrimitive for $BUint<N> {
102 #[inline]
103 fn from_u64(int: u64) -> Option<Self> {
104 const UINT_BITS: usize = u64::BITS as usize;
105 let mut out = $BUint::ZERO;
106 let mut i = 0;
107 while i << crate::digit::$Digit::BIT_SHIFT < UINT_BITS {
108 let d = (int >> (i << crate::digit::$Digit::BIT_SHIFT)) as $Digit;
109 if d != 0 {
110 if i < N {
111 out.digits[i] = d;
112 } else {
113 return None;
114 }
115 }
116 i += 1;
117 }
118 Some(out)
119 }
120
121 #[inline]
122 fn from_i64(int: i64) -> Option<Self> {
123 match u64::try_from(int) {
124 Ok(int) => Self::from_u64(int),
125 _ => None,
126 }
127 }
128
129 #[inline]
130 fn from_u128(int: u128) -> Option<Self> {
131 const UINT_BITS: usize = u128::BITS as usize;
132 let mut out = $BUint::ZERO;
133 let mut i = 0;
134 while i << crate::digit::$Digit::BIT_SHIFT < UINT_BITS {
135 let d = (int >> (i << crate::digit::$Digit::BIT_SHIFT)) as $Digit;
136 if d != 0 {
137 if i < N {
138 out.digits[i] = d;
139 } else {
140 return None;
141 }
142 }
143 i += 1;
144 }
145 Some(out)
146 }
147
148 #[inline]
149 fn from_i128(n: i128) -> Option<Self> {
150 match u128::try_from(n) {
151 Ok(n) => Self::from_u128(n),
152 _ => None,
153 }
154 }
155
156 from_float!(from_f32, f32, decode_f32, u32_bits);
157 from_float!(from_f64, f64, decode_f64, u64_bits);
158 }
159 impl<const N: usize> Integer for $BUint<N> {
163 #[inline]
164 fn div_floor(&self, other: &Self) -> Self {
165 *self / *other
166 }
167
168 #[inline]
169 fn mod_floor(&self, other: &Self) -> Self {
170 *self % *other
171 }
172
173 #[inline]
174 fn gcd(&self, other: &Self) -> Self {
175 let (mut a, mut b) = (*self, *other);
179 if a.is_zero() {
180 return b;
181 }
182 if b.is_zero() {
183 return a;
184 }
185 let mut a_tz = a.trailing_zeros();
186 let mut b_tz = b.trailing_zeros();
187 unsafe {
189 a = Self::unchecked_shr_internal(a, a_tz);
190 b = Self::unchecked_shr_internal(b, b_tz);
191 }
192
193 if b_tz > a_tz {
194 core::mem::swap(&mut a_tz, &mut b_tz);
196 }
197 loop {
198 if a < b {
199 core::mem::swap(&mut a, &mut b);
201 }
202 a -= b;
203 if a.is_zero() {
204 return unsafe { Self::unchecked_shl_internal(b, b_tz) };
205 }
206 unsafe {
207 a = Self::unchecked_shr_internal(a, a.trailing_zeros());
208 }
209 }
210 }
211
212 #[inline]
213 fn lcm(&self, other: &Self) -> Self {
214 if self.is_zero() || other.is_zero() {
215 Self::ZERO
216 } else {
217 self.div_floor(&self.gcd(other)) * *other
218 }
219 }
220
221 #[inline]
222 fn divides(&self, other: &Self) -> bool {
223 self.is_multiple_of(other)
224 }
225
226 #[inline]
227 fn is_multiple_of(&self, other: &Self) -> bool {
228 self.mod_floor(other).is_zero()
229 }
230
231 #[inline]
232 fn is_even(&self) -> bool {
233 self.digits[0] & 1 == 0
234 }
235
236 #[inline]
237 fn is_odd(&self) -> bool {
238 self.digits[0] & 1 == 1
239 }
240
241 #[inline]
242 fn div_rem(&self, rhs: &Self) -> (Self, Self) {
243 Self::div_rem(*self, *rhs)
244 }
245 }
246 impl<const N: usize> PrimInt for $BUint<N> {
250 crate::int::numtraits::prim_int_methods!();
251
252 #[inline]
253 fn signed_shl(self, n: u32) -> Self {
254 self << n
255 }
256
257 #[inline]
258 fn signed_shr(self, n: u32) -> Self {
259 ($BInt::from_bits(self) >> n).to_bits()
260 }
261
262 #[inline]
263 fn unsigned_shl(self, n: u32) -> Self {
264 self << n
265 }
266
267 #[inline]
268 fn unsigned_shr(self, n: u32) -> Self {
269 self >> n
270 }
271 }
272 macro_rules! check_zero_or_one {
275 ($self: ident) => {
276 if N == 0 {
277 return *$self;
278 }
279 if $self.last_digit_index() == 0 {
280 let d = $self.digits[0];
281 if d == 0 || d == 1 {
282 return *$self;
283 }
284 }
285 };
286 }
287
288 impl<const N: usize> $BUint<N> {
298 #[inline]
299 fn fixpoint<F>(mut self, max_bits: ExpType, f: F) -> Self
300 where
301 F: Fn(Self) -> Self,
302 {
303 let mut xn = f(self);
304 while self < xn {
305 self = if xn.bits() > max_bits {
306 Self::power_of_two(max_bits)
307 } else {
308 xn
309 };
310 xn = f(self);
311 }
312 while self > xn {
313 self = xn;
314 xn = f(self);
315 }
316 self
317 }
318 }
319
320 impl<const N: usize> Roots for $BUint<N> {
321 #[inline]
322 fn sqrt(&self) -> Self {
323 check_zero_or_one!(self);
324
325 #[cfg(not(test))]
326 if let Some(n) = self.to_u128() {
328 return n.sqrt().into();
329 }
330 let bits = self.bits();
331 let max_bits = bits / 2 + 1;
332
333 let guess = Self::power_of_two(max_bits);
334 guess.fixpoint(max_bits, |s| {
335 let q = self / s;
336 let t = s + q;
337 t >> 1
338 })
339 }
340
341 #[inline]
342 fn cbrt(&self) -> Self {
343 check_zero_or_one!(self);
344
345 #[cfg(not(test))]
346 if let Some(n) = self.to_u128() {
348 return n.cbrt().into();
349 }
350 let bits = self.bits();
351 let max_bits = bits / 3 + 1;
352
353 let guess = Self::power_of_two(max_bits);
354 guess.fixpoint(max_bits, |s| {
355 let q = self / (s * s);
356 let t: Self = (s << 1) + q;
357 t.div_rem_digit(3).0
358 })
359 }
360
361 #[inline]
362 fn nth_root(&self, n: u32) -> Self {
363 match n {
364 0 => panic!(crate::errors::err_msg!("attempt to calculate zeroth root")),
365 1 => *self,
366 2 => self.sqrt(),
367 3 => self.cbrt(),
368 _ => {
369 check_zero_or_one!(self);
370
371 #[cfg(not(test))]
372 if let Some(x) = self.to_u128() {
374 return x.nth_root(n).into();
375 }
376 let bits = self.bits();
377 let n = n as ExpType;
378 if bits <= n {
379 return Self::ONE;
380 }
381
382 let max_bits = bits / n + 1;
383
384 let guess = Self::power_of_two(max_bits);
385 let n_minus_1 = n - 1;
386
387 guess.fixpoint(max_bits, |s| {
388 let q = self / s.pow(n_minus_1);
389 let mul: Self = n_minus_1.into();
390 let t: Self = s * mul + q;
391 t.div_rem_unchecked(n.into()).0
392 })
393 }
394 }
395 }
396 }
397
398 impl<const N: usize> ToPrimitive for $BUint<N> {
400 to_int! {
401 $Digit;
402 to_u8 -> u8,
403 to_u16 -> u16,
404 to_u32 -> u32,
405 to_u64 -> u64,
406 to_u128 -> u128,
407 to_usize -> usize,
408
409 to_i8 -> i8,
410 to_i16 -> i16,
411 to_i32 -> i32,
412 to_i64 -> i64,
413 to_i128 -> i128,
414 to_isize -> isize
415 }
416
417 #[inline]
418 fn to_f32(&self) -> Option<f32> {
419 Some(self.as_())
420 }
421
422 #[inline]
423 fn to_f64(&self) -> Option<f64> {
424 Some(self.as_())
425 }
426 }
427 impl<const N: usize> Unsigned for $BUint<N> {}
430 };
431}
432
433crate::macro_impl!(numtraits);