reweb3_num/buint/
bigint_helpers.rs

1use crate::digit;
2use crate::doc;
3
4macro_rules! bigint_helpers {
5    ($BUint: ident, $BInt: ident, $Digit: ident) => {
6        impl<const N: usize> $BUint<N> {
7            #[doc = doc::bigint_helpers::carrying_add!(U)]
8            #[must_use = doc::must_use_op!()]
9            #[inline]
10            pub const fn carrying_add(self, rhs: Self, carry: bool) -> (Self, bool) {
11                let (s1, o1) = self.overflowing_add(rhs);
12                if carry {
13                    let (s2, o2) = s1.overflowing_add(Self::ONE);
14                    (s2, o1 || o2)
15                } else {
16                    (s1, o1)
17                }
18            }
19
20            #[doc = doc::bigint_helpers::borrowing_sub!(U)]
21            #[must_use = doc::must_use_op!()]
22            #[inline]
23            pub const fn borrowing_sub(self, rhs: Self, borrow: bool) -> (Self, bool) {
24                let (s1, o1) = self.overflowing_sub(rhs);
25                if borrow {
26                    let (s2, o2) = s1.overflowing_sub(Self::ONE);
27                    (s2, o1 || o2)
28                } else {
29                    (s1, o1)
30                }
31            }
32
33            #[doc = doc::bigint_helpers::widening_mul!(U)]
34            #[must_use = doc::must_use_op!()]
35            #[inline]
36            pub const fn widening_mul(self, rhs: Self) -> (Self, Self) {
37                let mut low = Self::ZERO;
38                let mut high = Self::ZERO;
39                let mut carry: $Digit;
40
41                let mut i = 0;
42                while i < N {
43                    carry = 0;
44                    let mut j = 0;
45                    while j < N - i {
46                        let index = i + j;
47                        let d = low.digits[index];
48                        let (new_digit, new_carry) =
49                            digit::$Digit::carrying_mul(self.digits[i], rhs.digits[j], carry, d);
50                        carry = new_carry;
51                        low.digits[index] = new_digit;
52                        j += 1;
53                    }
54                    while j < N {
55                        let index = i + j - N;
56                        let d = high.digits[index];
57                        let (new_digit, new_carry) =
58                            digit::$Digit::carrying_mul(self.digits[i], rhs.digits[j], carry, d);
59                        carry = new_carry;
60                        high.digits[index] = new_digit;
61                        j += 1;
62                    }
63                    high.digits[i] = carry;
64                    i += 1;
65                }
66
67                (low, high)
68            }
69
70            #[doc = doc::bigint_helpers::carrying_mul!(U)]
71            #[must_use = doc::must_use_op!()]
72            #[inline]
73            pub const fn carrying_mul(self, rhs: Self, carry: Self) -> (Self, Self) {
74                let (low, high) = self.widening_mul(rhs);
75                let (low, overflow) = low.overflowing_add(carry);
76                if overflow {
77                    (low, high.wrapping_add(Self::ONE))
78                } else {
79                    (low, high)
80                }
81            }
82        }
83    };
84}
85
86crate::macro_impl!(bigint_helpers);