1use super::{Integer, Uint};
2
3use crate::Exponent;
4use crate::Int;
5use num_integer::{Roots, Integer as IntegerTrait};
6
7use crate::cast::CastFrom;
8
9use num_traits::ops::overflowing::{OverflowingAdd, OverflowingMul, OverflowingSub};
10use num_traits::{
11 AsPrimitive, Bounded, CheckedAdd, CheckedDiv, CheckedEuclid, CheckedMul, CheckedNeg,
12 CheckedRem, CheckedShl, CheckedShr, CheckedSub, ConstOne, ConstZero, Euclid, FromBytes,
13 FromPrimitive, MulAdd, MulAddAssign, Num, One, Pow, PrimInt, Saturating, SaturatingAdd,
14 SaturatingMul, SaturatingSub, Signed, ToBytes, ToPrimitive, Unsigned, WrappingAdd, WrappingMul,
15 WrappingNeg, WrappingShl, WrappingShr, WrappingSub, Zero,
16};
17
18impl<const S: bool, const N: usize, const B: usize, const OM: u8> Bounded for Integer<S, N, B, OM> {
19 #[inline]
20 fn min_value() -> Self {
21 Self::MIN
22 }
23
24 #[inline]
25 fn max_value() -> Self {
26 Self::MAX
27 }
28}
29
30macro_rules! num_trait_impl {
31 ($tr: ident, $method: ident, $ret: ty) => {
32 impl<const S: bool, const N: usize, const B: usize, const OM: u8> $tr for Integer<S, N, B, OM> {
33 #[inline]
34 fn $method(&self, rhs: &Self) -> $ret {
35 Self::$method(*self, *rhs)
36 }
37 }
38 };
39}
40
41num_trait_impl!(CheckedAdd, checked_add, Option<Self>);
42num_trait_impl!(CheckedDiv, checked_div, Option<Self>);
43num_trait_impl!(CheckedMul, checked_mul, Option<Self>);
44num_trait_impl!(CheckedRem, checked_rem, Option<Self>);
45num_trait_impl!(CheckedSub, checked_sub, Option<Self>);
46
47num_trait_impl!(SaturatingAdd, saturating_add, Self);
48num_trait_impl!(SaturatingMul, saturating_mul, Self);
49num_trait_impl!(SaturatingSub, saturating_sub, Self);
50
51num_trait_impl!(WrappingAdd, wrapping_add, Self);
52num_trait_impl!(WrappingMul, wrapping_mul, Self);
53num_trait_impl!(WrappingSub, wrapping_sub, Self);
54
55num_trait_impl!(OverflowingAdd, overflowing_add, (Self, bool));
56num_trait_impl!(OverflowingSub, overflowing_sub, (Self, bool));
57num_trait_impl!(OverflowingMul, overflowing_mul, (Self, bool));
58
59impl<const S: bool, const N: usize, const B: usize, const OM: u8> CheckedNeg for Integer<S, N, B, OM> {
60 #[inline]
61 fn checked_neg(&self) -> Option<Self> {
62 Self::checked_neg(*self)
63 }
64}
65
66impl<const S: bool, const N: usize, const B: usize, const OM: u8> CheckedShl for Integer<S, N, B, OM> {
67 #[inline]
68 fn checked_shl(&self, rhs: Exponent) -> Option<Self> {
69 Self::checked_shl(*self, rhs)
70 }
71}
72
73impl<const S: bool, const N: usize, const B: usize, const OM: u8> CheckedShr for Integer<S, N, B, OM> {
74 #[inline]
75 fn checked_shr(&self, rhs: Exponent) -> Option<Self> {
76 Self::checked_shr(*self, rhs)
77 }
78}
79
80impl<const S: bool, const N: usize, const B: usize, const OM: u8> CheckedEuclid for Integer<S, N, B, OM> {
81 #[inline]
82 fn checked_div_euclid(&self, rhs: &Self) -> Option<Self> {
83 Self::checked_div_euclid(*self, *rhs)
84 }
85
86 #[inline]
87 fn checked_rem_euclid(&self, rhs: &Self) -> Option<Self> {
88 Self::checked_rem_euclid(*self, *rhs)
89 }
90}
91
92impl<const S: bool, const N: usize, const B: usize, const OM: u8> Euclid for Integer<S, N, B, OM> {
93 #[inline]
94 fn div_euclid(&self, rhs: &Self) -> Self {
95 Self::div_euclid(*self, *rhs)
96 }
97
98 #[inline]
99 fn rem_euclid(&self, rhs: &Self) -> Self {
100 Self::rem_euclid(*self, *rhs)
101 }
102}
103
104impl<const S: bool, const N: usize, const B: usize, const OM: u8> WrappingNeg for Integer<S, N, B, OM> {
105 #[inline]
106 fn wrapping_neg(&self) -> Self {
107 Self::wrapping_neg(*self)
108 }
109}
110
111impl<const S: bool, const N: usize, const B: usize, const OM: u8> WrappingShl for Integer<S, N, B, OM> {
112 #[inline]
113 fn wrapping_shl(&self, rhs: Exponent) -> Self {
114 Self::wrapping_shl(*self, rhs)
115 }
116}
117
118impl<const S: bool, const N: usize, const B: usize, const OM: u8> WrappingShr for Integer<S, N, B, OM> {
119 #[inline]
120 fn wrapping_shr(&self, rhs: Exponent) -> Self {
121 Self::wrapping_shr(*self, rhs)
122 }
123}
124
125impl<const S: bool, const N: usize, const B: usize, const OM: u8> Pow<Exponent> for Integer<S, N, B, OM> {
126 type Output = Self;
127
128 #[inline]
129 fn pow(self, exp: Exponent) -> Self {
130 Self::pow(self, exp)
131 }
132}
133
134impl<const S: bool, const N: usize, const B: usize, const OM: u8> Saturating for Integer<S, N, B, OM> {
135 #[inline]
136 fn saturating_add(self, rhs: Self) -> Self {
137 Self::saturating_add(self, rhs)
138 }
139
140 #[inline]
141 fn saturating_sub(self, rhs: Self) -> Self {
142 Self::saturating_sub(self, rhs)
143 }
144}
145
146macro_rules! to_primitive_int {
147 ($primitive: ty, $method: ident) => {
148 #[inline]
149 fn $method(&self) -> Option<$primitive> {
150 (*self).try_into().ok()
151 }
152 };
153}
154
155impl<const S: bool, const N: usize, const B: usize, const OM: u8> ToPrimitive for Integer<S, N, B, OM> {
156 to_primitive_int!(u8, to_u8);
157 to_primitive_int!(u16, to_u16);
158 to_primitive_int!(u32, to_u32);
159 to_primitive_int!(u64, to_u64);
160 to_primitive_int!(u128, to_u128);
161 to_primitive_int!(usize, to_usize);
162 to_primitive_int!(i8, to_i8);
163 to_primitive_int!(i16, to_i16);
164 to_primitive_int!(i32, to_i32);
165 to_primitive_int!(i64, to_i64);
166 to_primitive_int!(i128, to_i128);
167 to_primitive_int!(isize, to_isize);
168
169 #[inline]
170 fn to_f32(&self) -> Option<f32> {
171 Some(self.as_())
172 }
173
174 #[inline]
175 fn to_f64(&self) -> Option<f64> {
176 Some(self.as_())
177 }
178}
179
180macro_rules! impl_as_primitive_for_integer {
181 ($($ty: ty), *) => {
182 $(
183 impl<const S: bool, const N: usize, const B: usize, const OM: u8> AsPrimitive<$ty> for Integer<S, N, B, OM> {
184 #[inline]
185 fn as_(self) -> $ty {
186 <$ty>::cast_from(self)
187 }
188 }
189 )*
190 }
191}
192
193impl_as_primitive_for_integer!(
194 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64
195);
196
197macro_rules! impl_as_primitive_integer_for_primitive {
198 ($($ty: ty), *) => {
199 $(
200 impl<const S: bool, const N: usize, const B: usize, const OM: u8> AsPrimitive<Integer<S, N, B, OM>> for $ty {
201 #[inline]
202 fn as_(self) -> Integer<S, N, B, OM> {
203 Integer::cast_from(self)
204 }
205 }
206 )*
207 }
208}
209
210impl_as_primitive_integer_for_primitive!(
211 u8, u16, u32, usize, u64, u128, i8, i16, i32, isize, i64, i128, f32, f64, char, bool
212);
213
214impl<const S: bool, const N: usize, const B: usize, const R: bool, const M: usize, const A: usize, const OM: u8> AsPrimitive<Integer<R, M, A, OM>>
215 for Integer<S, N, B, OM>
216{
217 #[inline]
218 fn as_(self) -> Integer<R, M, A, OM> {
219 Integer::cast_from(self)
220 }
221}
222
223impl<const S: bool, const N: usize, const OM: u8> FromBytes for Integer<S, N, 0, OM> {
224 type Bytes = [u8; N];
225
226 #[inline]
227 fn from_be_bytes(bytes: &[u8; N]) -> Self {
228 Self::from_be_bytes(*bytes)
229 }
230
231 #[inline]
232 fn from_le_bytes(bytes: &[u8; N]) -> Self {
233 Self::from_le_bytes(*bytes)
234 }
235}
236
237impl<const S: bool, const N: usize, const OM: u8> ToBytes for Integer<S, N, 0, OM> {
238 type Bytes = [u8; N];
239
240 #[inline]
241 fn to_be_bytes(&self) -> [u8; N] {
242 Self::to_be_bytes(*self)
243 }
244
245 #[inline]
246 fn to_le_bytes(&self) -> [u8; N] {
247 Self::to_le_bytes(*self)
248 }
249}
250
251impl<const S: bool, const N: usize, const B: usize, const OM: u8> MulAdd for Integer<S, N, B, OM> {
252 type Output = Self;
253
254 #[inline]
255 fn mul_add(self, a: Self, b: Self) -> Self {
256 (self * a) + b
257 }
258}
259
260impl<const S: bool, const N: usize, const B: usize, const OM: u8> MulAddAssign for Integer<S, N, B, OM> {
261 #[inline]
262 fn mul_add_assign(&mut self, a: Self, b: Self) {
263 *self = self.mul_add(a, b);
264 }
265}
266
267impl<const S: bool, const N: usize, const B: usize, const OM: u8> Num for Integer<S, N, B, OM> {
268 type FromStrRadixErr = crate::errors::ParseIntError;
269
270 #[inline]
271 fn from_str_radix(string: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
272 Self::from_str_radix(string, radix)
273 }
274}
275
276impl<const S: bool, const N: usize, const B: usize, const OM: u8> num_traits::NumCast for Integer<S, N, B, OM> {
277 fn from<T: ToPrimitive>(_n: T) -> Option<Self> {
278 panic!(concat!(
279 crate::errors::err_prefix!(),
280 "`num_traits::NumCast` trait is not supported for ",
281 stringify!($Int)
282 ))
283 }
284}
285
286impl<const S: bool, const N: usize, const B: usize, const OM: u8> One for Integer<S, N, B, OM> {
287 #[inline]
288 fn one() -> Self {
289 Self::ONE
290 }
291
292 #[inline]
293 fn is_one(&self) -> bool {
294 Self::is_one(&self)
295 }
296}
297
298impl<const S: bool, const N: usize, const B: usize, const OM: u8> ConstOne for Integer<S, N, B, OM> {
299 const ONE: Self = Self::ONE;
300}
301
302impl<const S: bool, const N: usize, const B: usize, const OM: u8> Zero for Integer<S, N, B, OM> {
303 #[inline]
304 fn zero() -> Self {
305 Self::ZERO
306 }
307
308 #[inline]
309 fn is_zero(&self) -> bool {
310 Self::is_zero(&self)
311 }
312}
313
314impl<const S: bool, const N: usize, const B: usize, const OM: u8> ConstZero for Integer<S, N, B, OM> {
315 const ZERO: Self = Self::ZERO;
316}
317
318macro_rules! from_primitive_float {
319 ($method: ident, $float: ty, $signed: ident) => {
321 #[inline]
322 fn $method(f: $float) -> Option<Self> {
323 if $signed {
324 if f.is_sign_negative() {
325 let i = Uint::$method(-f)?.force_sign();
326 return if i == Self::MIN {
327 Some(Self::MIN)
328 } else if i.is_negative_internal() {
329 None
330 } else {
331 Some(i.wrapping_neg())
332 };
333 } else {
334 let i = Uint::$method(f)?.force_sign();
335 return if i.is_negative_internal() {
336 None
337 } else {
338 Some(i)
339 };
340 }
341 }
342 match crate::cast::float::uint_try_from_float::<$float, Uint<N, B, OM>>(f) {
343 Ok(u) => Some(u.force_sign::<S>()),
344 Err(_) => None,
345 }
346 }
347 };
348}
349
350macro_rules! from_primitive_int {
351 ($primitive: ty, $method: ident) => {
352 #[inline]
353 fn $method(n: $primitive) -> Option<Self> {
354 Self::try_from(n).ok()
355 }
356 };
357}
358
359impl<const S: bool, const N: usize, const B: usize, const OM: u8> FromPrimitive for Integer<S, N, B, OM> {
360 from_primitive_int!(u8, from_u8);
361 from_primitive_int!(u16, from_u16);
362 from_primitive_int!(u32, from_u32);
363 from_primitive_int!(u64, from_u64);
364 from_primitive_int!(u128, from_u128);
365 from_primitive_int!(usize, from_usize);
366 from_primitive_int!(i8, from_i8);
367 from_primitive_int!(i16, from_i16);
368 from_primitive_int!(i32, from_i32);
369 from_primitive_int!(i64, from_i64);
370 from_primitive_int!(i128, from_i128);
371 from_primitive_int!(isize, from_isize);
372
373 from_primitive_float!(from_f32, f32, S);
374 from_primitive_float!(from_f64, f64, S);
375}
376
377impl<const S: bool, const N: usize, const B: usize, const OM: u8> IntegerTrait for Integer<S, N, B, OM> {
378 #[inline]
379 fn div_floor(&self, other: &Self) -> Self {
380 Self::div_floor(*self, *other)
381 }
382
383 #[inline]
384 fn mod_floor(&self, other: &Self) -> Self {
385 let rem = self % other;
386 if S && rem.is_zero() {
387 return rem;
388 }
389 if rem.is_negative_internal() != other.is_negative_internal() {
390 rem + other
391 } else {
392 rem
393 }
394 }
395
396 #[inline]
397 fn gcd(&self, other: &Self) -> Self {
398 if S {
401 let gcd = self
402 .unsigned_abs_internal()
403 .gcd(&other.unsigned_abs_internal())
404 .force_sign();
405 if gcd == Self::MIN {
406 return crate::Int::MIN.force_sign();
407 }
408 return gcd;
409 }
410 let (mut a, mut b) = (*self, *other);
411 if a.is_zero() {
412 return b;
413 }
414 if b.is_zero() {
415 return a;
416 }
417 let mut a_tz = a.trailing_zeros();
418 let mut b_tz = b.trailing_zeros();
419 unsafe {
421 a = a.unchecked_shr_internal(a_tz);
422 b = b.unchecked_shr_internal(b_tz);
423 }
424
425 if b_tz > a_tz {
426 core::mem::swap(&mut a_tz, &mut b_tz);
428 }
429 loop {
430 if a < b {
431 core::mem::swap(&mut a, &mut b);
433 }
434 a -= b;
435 if a.is_zero() {
436 return unsafe { Self::unchecked_shl_internal(b, b_tz) };
437 }
438 unsafe {
439 a = a.unchecked_shr_internal(a.trailing_zeros());
440 }
441 }
442 }
443
444 #[inline]
445 fn lcm(&self, other: &Self) -> Self {
446 if self.is_zero() || other.is_zero() {
447 Self::ZERO
448 } else {
449 let gcd = (self / self.gcd(other)) * other;
450 if S {
451 gcd.force_sign::<true>().abs().force_sign()
452 } else {
453 gcd
454 }
455 }
456 }
457
458 #[inline]
459 fn divides(&self, other: &Self) -> bool {
460 self.is_multiple_of(other)
461 }
462
463 #[inline]
464 fn is_multiple_of(&self, other: &Self) -> bool {
465 if other.is_zero() {
466 return self.is_zero();
467 }
468 (self % other).is_zero()
469 }
470
471 #[inline]
472 fn is_even(&self) -> bool {
473 self.bytes[0] % 2 == 0
474 }
475
476 #[inline]
477 fn is_odd(&self) -> bool {
478 self.bytes[0] % 2 == 1
479 }
480
481 #[inline]
482 fn div_rem(&self, rhs: &Self) -> (Self, Self) {
483 if self.is_division_overflow(rhs) {
484 panic!(crate::errors::err_msg!("attempt to divide with overflow"));
485 }
486 if rhs.is_zero() {
487 panic!(crate::errors::err_msg!("attempt to divide by zero"));
488 }
489 self.div_rem_unchecked(*rhs)
490 }
491}
492
493macro_rules! prim_int_method {
494 { $(fn $name: ident ($($arg: ident $(: $ty: ty)?), *) -> $ret: ty;) * } => {
495 $(
496 #[inline]
497 fn $name($($arg $(: $ty)?), *) -> $ret {
498 Self::$name($($arg), *)
499 }
500 )*
501 };
502}
503
504impl<const S: bool, const N: usize, const OM: u8> PrimInt for Integer<S, N, 0, OM> {
505 #[inline]
506 fn from_be(x: Self) -> Self {
507 if cfg!(target_endian = "big") {
508 x
509 } else {
510 x.swap_bytes()
511 }
512 }
513
514 #[inline]
515 fn from_le(x: Self) -> Self {
516 if cfg!(target_endian = "little") {
517 x
518 } else {
519 x.swap_bytes()
520 }
521 }
522
523 #[inline]
524 fn to_be(self) -> Self {
525 if cfg!(target_endian = "big") {
526 self
527 } else {
528 self.swap_bytes()
529 }
530 }
531
532 #[inline]
533 fn to_le(self) -> Self {
534 if cfg!(target_endian = "little") {
535 self
536 } else {
537 self.swap_bytes()
538 }
539 }
540
541 prim_int_method! {
542 fn count_ones(self) -> u32;
543 fn count_zeros(self) -> u32;
544 fn leading_zeros(self) -> u32;
545 fn trailing_zeros(self) -> u32;
546 fn rotate_left(self, n: u32) -> Self;
547 fn rotate_right(self, n: u32) -> Self;
548 fn swap_bytes(self) -> Self;
549 fn pow(self, exp: u32) -> Self;
550 fn leading_ones(self) -> u32;
551 fn trailing_ones(self) -> u32;
552 fn reverse_bits(self) -> Self;
553 }
554
555 #[inline]
556 fn signed_shl(self, n: u32) -> Self {
557 self << n
558 }
559
560 #[inline]
561 fn signed_shr(self, n: u32) -> Self {
562 (self.force_sign::<true>() >> n).force_sign()
563 }
564
565 #[inline]
566 fn unsigned_shl(self, n: u32) -> Self {
567 self << n
568 }
569
570 #[inline]
571 fn unsigned_shr(self, n: u32) -> Self {
572 (self.force_sign::<false>() >> n).force_sign()
573 }
574}
575
576impl<const N: usize, const B: usize, const OM: u8> Uint<N, B, OM> {
577 #[inline]
578 const fn nth_root_internal(self, n: Exponent) -> Self {
579 if self.is_zero() {
580 return self;
581 }
582 let bit_width = self.bit_width();
583 if n > bit_width {
584 return Self::ONE;
586 }
587 let e = if bit_width % n == 0 {
588 bit_width / n
589 } else {
590 bit_width / n + 1
591 };
592 let mut x = Self::power_of_two(e);
593 loop {
594 let y = (x.mul_u128_digit(n as u128 - 1).0.add(self.div(x.pow(n - 1))))
595 .div_rem_u64(n as u64)
596 .0;
597 if y.ge(&x) {
598 return x;
599 }
600 x = y;
601 }
602 }
603}
604
605impl<const S: bool, const N: usize, const B: usize, const OM: u8> Roots for Integer<S, N, B, OM> {
606 #[inline]
607 fn sqrt(&self) -> Self {
608 self.isqrt()
609 }
610
611 #[inline]
612 fn cbrt(&self) -> Self {
613 self.nth_root(3)
614 }
615
616 #[inline]
617 fn nth_root(&self, n: u32) -> Self {
618 match n {
619 0 => panic!(crate::errors::err_msg!("attempt to calculate zeroth root")),
620 1 => *self,
621 2 => self.sqrt(),
622 _ => {
623 if self.is_negative_internal() {
624 let out = self.unsigned_abs_internal().nth_root(n);
625 return out.wrapping_neg().force_sign();
626 }
627
628 self.force_sign().nth_root_internal(n).force_sign()
629 }
630 }
631 }
632}
633
634impl<const N: usize, const B: usize, const OM: u8> Unsigned for Uint<N, B, OM> {}
635
636impl<const N: usize, const B: usize, const OM: u8> Signed for Int<N, B, OM> {
637 #[inline]
638 fn abs(&self) -> Self {
639 Self::abs(*self)
640 }
641
642 #[inline]
643 fn abs_sub(&self, other: &Self) -> Self {
644 if self <= other {
645 Self::ZERO
646 } else {
647 *self - *other
648 }
649 }
650
651 #[inline]
652 fn signum(&self) -> Self {
653 Self::signum(*self)
654 }
655
656 #[inline]
657 fn is_positive(&self) -> bool {
658 Self::is_positive(*self)
659 }
660
661 #[inline]
662 fn is_negative(&self) -> bool {
663 self.is_negative_internal()
664 }
665}
666
667#[cfg(test)]
668mod tests {
669 macro_rules! test_to_primitive {
670 ($($prim: ty), *) => {
671 paste::paste! {
672 $(
673 test_bignum! {
674 function: <stest>::[<to_ $prim>](u: ref &stest)
675 }
676 )*
677 }
678 };
679 }
680
681 macro_rules! test_from_primitive {
682 ($($prim: ty), *) => {
683 paste::paste! {
684 $(
685 test_bignum! {
686 function: <stest>::[<from_ $prim>](u: $prim),
687 cases: [
688 (stest::MIN as $prim)
689 ]
690 }
691 )*
692 }
693 };
694 }
695
696 use super::*;
697 use crate::test::{TestConvert, test_bignum, debug_skip};
698
699 crate::test::test_all! {
700 testing integers;
701
702 crate::test::test_into! {
703 function: <stest as AsPrimitive>::as_,
704 into_types: (u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64)
705 }
706
707 test_bignum! {
708 function: <stest as CheckedAdd>::checked_add(a: ref &stest, b: ref &stest)
709 }
710 test_bignum! {
711 function: <stest as CheckedSub>::checked_sub(a: ref &stest, b: ref &stest)
712 }
713 test_bignum! {
714 function: <stest as CheckedMul>::checked_mul(a: ref &stest, b: ref &stest)
715 }
716 test_bignum! {
717 function: <stest as CheckedDiv>::checked_div(a: ref &stest, b: ref &stest)
718 }
719 test_bignum! {
720 function: <stest as CheckedRem>::checked_rem(a: ref &stest, b: ref &stest)
721 }
722 test_bignum! {
723 function: <stest as CheckedNeg>::checked_neg(a: ref &stest)
724 }
725 test_bignum! {
726 function: <stest as CheckedShl>::checked_shl(a: ref &stest, b: u8)
727 }
728 test_bignum! {
729 function: <stest as CheckedShr>::checked_shr(a: ref &stest, b: u8)
730 }
731 test_bignum! {
732 function: <stest as CheckedEuclid>::checked_div_euclid(a: ref &stest, b: ref &stest)
733 }
734 test_bignum! {
735 function: <stest as CheckedEuclid>::checked_rem_euclid(a: ref &stest, b: ref &stest)
736 }
737
738 test_bignum! {
739 function: <stest as Euclid>::div_euclid(a: ref &stest, b: ref &stest),
740 skip: a.checked_div_euclid(b).is_none()
741 }
742 test_bignum! {
743 function: <stest as Euclid>::rem_euclid(a: ref &stest, b: ref &stest),
744 skip: a.checked_rem_euclid(b).is_none()
745 }
746
747 test_bignum! {
748 function: <stest as SaturatingAdd>::saturating_add(a: ref &stest, b: ref &stest)
749 }
750 test_bignum! {
751 function: <stest as SaturatingSub>::saturating_sub(a: ref &stest, b: ref &stest)
752 }
753 test_bignum! {
754 function: <stest as SaturatingMul>::saturating_mul(a: ref &stest, b: ref &stest)
755 }
756
757 test_bignum! {
758 function: <stest as Saturating>::saturating_add(a: stest, b: stest)
759 }
760 test_bignum! {
761 function: <stest as Saturating>::saturating_sub(a: stest, b: stest)
762 }
763
764 test_bignum! {
765 function: <stest as WrappingAdd>::wrapping_add(a: ref &stest, b: ref &stest)
766 }
767 test_bignum! {
768 function: <stest as OverflowingAdd>::overflowing_add(a: ref &stest, b: ref &stest)
769 }
770 test_bignum! {
771 function: <stest as WrappingSub>::wrapping_sub(a: ref &stest, b: ref &stest)
772 }
773 test_bignum! {
774 function: <stest as OverflowingSub>::overflowing_sub(a: ref &stest, b: ref &stest)
775 }
776 test_bignum! {
777 function: <stest as WrappingMul>::wrapping_mul(a: ref &stest, b: ref &stest)
778 }
779 test_bignum! {
780 function: <stest as OverflowingMul>::overflowing_mul(a: ref &stest, b: ref &stest)
781 }
782 test_bignum! {
783 function: <stest as WrappingNeg>::wrapping_neg(a: ref &stest)
784 }
785 test_bignum! {
786 function: <stest as WrappingShl>::wrapping_shl(a: ref &stest, b: u16)
787 }
788 test_bignum! {
789 function: <stest as WrappingShr>::wrapping_shr(a: ref &stest, b: u16)
790 }
791
792 test_bignum! {
793 function: <stest as One>::is_one(a: ref &stest)
794 }
795 test_bignum! {
796 function: <stest as Zero>::is_zero(a: ref &stest)
797 }
798
799 #[test]
800 fn one() {
801 assert_eq!(STEST::one(), TestConvert::into(stest::one()));
802 }
803
804 #[test]
805 fn zero() {
806 assert_eq!(STEST::zero(), TestConvert::into(stest::zero()));
807 }
808
809 #[test]
810 fn min_value() {
811 assert_eq!(STEST::min_value(), TestConvert::into(stest::min_value()));
812 }
813
814 #[test]
815 fn max_value() {
816 assert_eq!(STEST::max_value(), TestConvert::into(stest::max_value()));
817 }
818
819 test_bignum! {
820 function: <stest as MulAdd>::mul_add(a: stest, b: stest, c: stest),
821 skip: a.checked_mul(b).map(|d| d.checked_add(c)).flatten().is_none()
822 }
823
824 test_bignum! {
825 function: <stest as Roots>::sqrt(a: ref &stest),
826 skip: {
827 #[allow(unused_comparisons)]
828 let cond = a < 0;
829
830 cond
831 }
832 }
833 test_bignum! {
834 function: <stest as Roots>::cbrt(a: ref &stest)
835 }
836 test_bignum! {
837 function: <stest as Roots>::nth_root(a: ref &stest, n: u32),
838 skip: n == 0 || {
839 #[allow(unused_comparisons)]
840 let cond = a < 0;
841
842 n % 2 == 0 && cond || (n == 1 && cond && a == <stest>::MIN) }
844 }
845
846 test_to_primitive!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64);
847
848 test_from_primitive!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64);
849
850 test_bignum! {
851 function: <stest as IntegerTrait>::div_floor(a: ref &stest, b: ref &stest),
852 skip: b.is_zero()
853 }
854 test_bignum! {
855 function: <stest as IntegerTrait>::mod_floor(a: ref &stest, b: ref &stest),
856 skip: b.is_zero()
857 }
858 test_bignum! {
859 function: <stest as IntegerTrait>::lcm(a: ref &stest, b: ref &stest),
860 skip: {
861 #[allow(unused_comparisons)]
862 let cond = a.checked_mul(b).is_none() || (a < 0 && a == <stest>::MIN) || (b < 0 && b == <stest>::MIN); cond
864 },
865 cases: [(ref &(1 as stest), ref &(-1i8 as stest))]
866 }
867 test_bignum! {
868 function: <stest as IntegerTrait>::gcd(a: ref &stest, b: ref &stest),
869 skip: {
870 #[allow(unused_comparisons)]
871 let cond = <stest>::MIN < 0 && (a == <stest>::MIN && (b == <stest>::MIN || b == 0)) || (b == <stest>::MIN && (a == <stest>::MIN || a == 0));
872 cond
873 }
874 }
875 test_bignum! {
876 function: <stest as IntegerTrait>::is_multiple_of(a: ref &stest, b: ref &stest)
877 }
878 test_bignum! {
879 function: <stest as IntegerTrait>::is_even(a: ref &stest)
880 }
881 test_bignum! {
882 function: <stest as IntegerTrait>::is_odd(a: ref &stest)
883 }
884 test_bignum! {
885 function: <stest as IntegerTrait>::div_rem(a: ref &stest, b: ref &stest),
886 skip: b.is_zero()
887 }
888
889 test_bignum! {
890 function: <stest as PrimInt>::unsigned_shl(a: stest, n: u8),
891 skip: n >= <stest>::BITS as u8
892 }
893 test_bignum! {
894 function: <stest as PrimInt>::unsigned_shr(a: stest, n: u8),
895 skip: n >= <stest>::BITS as u8
896 }
897 test_bignum! {
898 function: <stest as PrimInt>::signed_shl(a: stest, n: u8),
899 skip: n >= <stest>::BITS as u8
900 }
901 test_bignum! {
902 function: <stest as PrimInt>::signed_shr(a: stest, n: u8),
903 skip: n >= <stest>::BITS as u8
904 }
905 }
906
907 crate::test::test_all! {
908 testing signed;
909
910 test_bignum! {
911 function: <stest as Signed>::abs(a: ref &stest),
912 skip: debug_skip!(a == <stest>::MIN)
913 }
914 test_bignum! {
915 function: <stest as Signed>::abs_sub(a: ref &stest, b: ref &stest),
916 skip: debug_skip!(a > b && a.checked_sub(b).is_none())
917 }
918 test_bignum! {
919 function: <stest as Signed>::signum(a: ref &stest)
920 }
921 test_bignum! {
922 function: <stest as Signed>::is_positive(a: ref &stest)
923 }
924 test_bignum! {
925 function: <stest as Signed>::is_negative(a: ref &stest)
926 }
927 }
928}