Skip to main content

bnum/integer/
numtraits.rs

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    // adapted from crate::cast::float::cast_uint_from_float
320    ($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        // Paul E. Black, "binary GCD", in Dictionary of Algorithms and Data Structures [online], Paul E. Black, ed. 2 November 2020. (accessed 15th June 2022) Available from: https://www.nist.gov/dads/HTML/binaryGCD.html
399        // https://en.wikipedia.org/wiki/Binary_GCD_algorithm#Implementation
400        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        // Normalise `a` and `b` so that both of them has no leading zeros, so both must be odd.
420        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            // Ensure `a_tz >= b_tz`
427            core::mem::swap(&mut a_tz, &mut b_tz);
428        }
429        loop {
430            if a < b {
431                // Ensure `a >= b`
432                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            // in this case, output should be < (2^bit_width)^(1/n) < 2^1 = 2, and output must be at least 1, so output is 1
585            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) // second condition is due to an error in the num_integer crate, which incorrectly panics when calculating the first root of i128::MIN
843            }
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); // lcm(a, b) <= a * b
863                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}