bnum/buint/
overflowing.rs1use crate::digit;
2use crate::doc;
3use crate::ExpType;
4
5macro_rules! overflowing {
6 ($BUint: ident, $BInt: ident, $Digit: ident) => {
7 #[doc = doc::overflowing::impl_desc!()]
8 impl<const N: usize> $BUint<N> {
9 #[doc = doc::overflowing::overflowing_add!(U)]
10 #[must_use = doc::must_use_op!()]
11 #[inline]
12 pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
13 let mut out = Self::ZERO;
14 let mut carry = false;
15 let mut i = 0;
16 while i < N {
17 let result = digit::$Digit::carrying_add(self.digits[i], rhs.digits[i], carry);
18 out.digits[i] = result.0;
19 carry = result.1;
20 i += 1;
21 }
22 (out, carry)
23 }
24
25 #[doc = doc::overflowing::overflowing_add_signed!(U)]
26 #[must_use = doc::must_use_op!()]
27 #[inline]
28 pub const fn overflowing_add_signed(self, rhs: $BInt<N>) -> (Self, bool) {
29 let (sum, overflow) = self.overflowing_add(rhs.to_bits());
30 (sum, rhs.is_negative() != overflow)
31 }
32
33 #[doc = doc::overflowing::overflowing_sub!(U)]
34 #[must_use = doc::must_use_op!()]
35 #[inline]
36 pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
37 let mut out = Self::ZERO;
38 let mut borrow = false;
39 let mut i = 0;
40 while i < N {
41 let result =
42 digit::$Digit::borrowing_sub(self.digits[i], rhs.digits[i], borrow);
43 out.digits[i] = result.0;
44 borrow = result.1;
45 i += 1;
46 }
47 (out, borrow)
48 }
49
50 #[doc = doc::overflowing::overflowing_mul!(U)]
51 #[must_use = doc::must_use_op!()]
52 #[inline]
53 pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
54 self.long_mul(rhs)
56 }
57
58 #[doc = doc::overflowing::overflowing_div!(U)]
59 #[must_use = doc::must_use_op!()]
60 #[inline]
61 pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) {
62 (self.wrapping_div(rhs), false)
63 }
64
65 #[doc = doc::overflowing::overflowing_div_euclid!(U)]
66 #[must_use = doc::must_use_op!()]
67 #[inline]
68 pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
69 self.overflowing_div(rhs)
70 }
71
72 #[doc = doc::overflowing::overflowing_rem!(U)]
73 #[must_use = doc::must_use_op!()]
74 #[inline]
75 pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
76 (self.wrapping_rem(rhs), false)
77 }
78
79 #[doc = doc::overflowing::overflowing_rem_euclid!(U)]
80 #[must_use = doc::must_use_op!()]
81 #[inline]
82 pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
83 self.overflowing_rem(rhs)
84 }
85
86 #[doc = doc::overflowing::overflowing_neg!(U)]
87 #[must_use = doc::must_use_op!()]
88 #[inline]
89 pub const fn overflowing_neg(self) -> (Self, bool) {
90 let (a, b) = (self.not()).overflowing_add(Self::ONE);
91 (a, !b)
92 }
93
94 #[doc = doc::overflowing::overflowing_shl!(U)]
95 #[must_use = doc::must_use_op!()]
96 #[inline]
97 pub const fn overflowing_shl(self, rhs: ExpType) -> (Self, bool) {
98 unsafe {
99 if rhs >= Self::BITS {
100 (
101 Self::unchecked_shl_internal(self, rhs & (Self::BITS - 1)),
102 true,
103 )
104 } else {
105 (Self::unchecked_shl_internal(self, rhs), false)
106 }
107 }
108 }
109
110 #[doc = doc::overflowing::overflowing_shr!(U)]
111 #[must_use = doc::must_use_op!()]
112 #[inline]
113 pub const fn overflowing_shr(self, rhs: ExpType) -> (Self, bool) {
114 unsafe {
115 if rhs >= Self::BITS {
116 (
117 Self::unchecked_shr_internal(self, rhs & (Self::BITS - 1)),
118 true,
119 )
120 } else {
121 (Self::unchecked_shr_internal(self, rhs), false)
122 }
123 }
124 }
125
126 #[doc = doc::overflowing::overflowing_pow!(U)]
127 #[must_use = doc::must_use_op!()]
128 #[inline]
129 pub const fn overflowing_pow(mut self, mut pow: ExpType) -> (Self, bool) {
130 if pow == 0 {
132 return (Self::ONE, false);
133 }
134 let mut overflow = false;
135 let mut y = Self::ONE;
136 while pow > 1 {
137 if pow & 1 == 1 {
138 let (prod, o) = y.overflowing_mul(self);
139 overflow |= o;
140 y = prod;
141 }
142 let (prod, o) = self.overflowing_mul(self);
143 overflow |= o;
144 self = prod;
145 pow >>= 1;
146 }
147 let (prod, o) = self.overflowing_mul(y);
148 (prod, o || overflow)
149 }
150 }
151 };
152}
153
154#[cfg(test)]
155crate::test::all_digit_tests! {
156 use crate::test::{test_bignum, types::utest};
157
158 test_bignum! {
159 function: <utest>::overflowing_add(a: utest, b: utest)
160 }
161 test_bignum! {
162 function: <utest>::overflowing_sub(a: utest, b: utest)
163 }
164 test_bignum! {
165 function: <utest>::overflowing_mul(a: utest, b: utest)
166 }
167 test_bignum! {
168 function: <utest>::overflowing_div(a: utest, b: utest),
169 skip: b == 0
170 }
171 test_bignum! {
172 function: <utest>::overflowing_div_euclid(a: utest, b: utest),
173 skip: b == 0
174 }
175 test_bignum! {
176 function: <utest>::overflowing_rem(a: utest, b: utest),
177 skip: b == 0
178 }
179 test_bignum! {
180 function: <utest>::overflowing_rem_euclid(a: utest, b: utest),
181 skip: b == 0
182 }
183 test_bignum! {
184 function: <utest>::overflowing_neg(a: utest)
185 }
186 test_bignum! {
187 function: <utest>::overflowing_shl(a: utest, b: u16)
188 }
189 test_bignum! {
190 function: <utest>::overflowing_shr(a: utest, b: u16)
191 }
192 test_bignum! {
193 function: <utest>::overflowing_pow(a: utest, b: u16)
194 }
195}
196
197crate::macro_impl!(overflowing);