Skip to main content

bnum/buint/
ops.rs

1use crate::digit;
2use crate::ExpType;
3use core::ops::{
4    Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
5    Mul, MulAssign, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
6};
7
8macro_rules! ops {
9    ($BUint: ident, $BInt: ident, $Digit: ident) => {
10        impl<const N: usize> Add<$Digit> for $BUint<N> {
11            type Output = Self;
12
13            #[inline]
14            fn add(self, rhs: $Digit) -> Self {
15                let mut out = self;
16                let result = digit::$Digit::carrying_add(out.digits[0], rhs, false);
17                out.digits[0] = result.0;
18                let mut carry = result.1;
19                let mut i = 1;
20                while i < N && carry {
21                    let result = out.digits[i].overflowing_add(1);
22                    out.digits[i] = result.0;
23                    carry = result.1;
24                    i += 1;
25                }
26                out
27            }
28        }
29
30        impl<const N: usize> BitAnd for $BUint<N> {
31            type Output = Self;
32
33            #[inline]
34            fn bitand(self, rhs: Self) -> Self {
35                Self::bitand(self, rhs)
36            }
37        }
38
39        impl<const N: usize> BitOr for $BUint<N> {
40            type Output = Self;
41
42            #[inline]
43            fn bitor(self, rhs: Self) -> Self {
44                Self::bitor(self, rhs)
45            }
46        }
47
48        impl<const N: usize> BitXor for $BUint<N> {
49            type Output = Self;
50
51            #[inline]
52            fn bitxor(self, rhs: Self) -> Self {
53                Self::bitxor(self, rhs)
54            }
55        }
56
57        impl<const N: usize> Div for $BUint<N> {
58            type Output = Self;
59
60            #[inline]
61            fn div(self, rhs: Self) -> Self {
62                Self::div(self, rhs)
63            }
64        }
65
66        impl<const N: usize> Div<$Digit> for $BUint<N> {
67            type Output = Self;
68
69            #[inline]
70            fn div(self, rhs: $Digit) -> Self {
71                self.div_rem_digit(rhs).0
72            }
73        }
74
75        impl<const N: usize> Not for $BUint<N> {
76            type Output = Self;
77
78            #[inline]
79            fn not(self) -> Self {
80                Self::not(self)
81            }
82        }
83
84        impl<const N: usize> Rem for $BUint<N> {
85            type Output = Self;
86
87            #[inline]
88            fn rem(self, rhs: Self) -> Self {
89                Self::rem(self, rhs)
90            }
91        }
92
93        impl<const N: usize> Rem<$Digit> for $BUint<N> {
94            type Output = $Digit;
95
96            #[inline]
97            fn rem(self, rhs: $Digit) -> $Digit {
98                self.div_rem_digit(rhs).1
99            }
100        }
101
102        crate::int::ops::impls!($BUint, $BUint, $BInt);
103
104        #[cfg(all(test, test_int_bits = "64"))]
105        paste::paste! {
106            mod [<$Digit _add_digit_test>] {
107                use super::*;
108                use crate::test::{test_bignum, types::utest};
109                use crate::test::types::big_types::$Digit::*;
110
111                quickcheck::quickcheck! {
112                    fn add_digit(a: utest, b: $Digit) -> quickcheck::TestResult {
113                        use crate::cast::As;
114
115                        let c: utest = b.as_();
116                        match a.checked_add(c) {
117                            None => quickcheck::TestResult::discard(),
118                            Some(_d) => {
119                                let e: UTEST = b.as_();
120                                let f: UTEST = a.as_();
121                                quickcheck::TestResult::from_bool(f + e == f + b)
122                            }
123                        }
124                    }                    
125                }
126            }
127        }
128    };
129}
130
131#[cfg(test)]
132crate::test::all_digit_tests! {
133    use crate::test::{test_bignum, types::utest};
134
135    crate::int::ops::tests!(utest);
136}
137
138crate::macro_impl!(ops);