1use crate::digit;
2use crate::errors::div_zero;
3use crate::{doc, ExpType};
4
5macro_rules! overflowing {
6 ($BUint: ident, $BInt: ident, $Digit: ident) => {
7 #[doc = doc::overflowing::impl_desc!()]
8 impl<const N: usize> $BInt<N> {
9 #[doc = doc::overflowing::overflowing_add!(I)]
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
16 let self_digits = self.bits.digits;
17 let rhs_digits = rhs.bits.digits;
18
19 let mut i = 0;
20 while i < Self::N_MINUS_1 {
21 let (sum, c) =
22 digit::$Digit::carrying_add(self_digits[i], rhs_digits[i], carry);
23 out.bits.digits[i] = sum;
24 carry = c;
25 i += 1;
26 }
27 let (sum, carry) = digit::$Digit::carrying_add_signed(
28 self_digits[Self::N_MINUS_1] as digit::$Digit::SignedDigit,
29 rhs_digits[Self::N_MINUS_1] as digit::$Digit::SignedDigit,
30 carry,
31 );
32 out.bits.digits[Self::N_MINUS_1] = sum as $Digit;
33
34 (out, carry)
35 }
36
37 #[doc = doc::overflowing::overflowing_add_unsigned!(I)]
38 #[must_use = doc::must_use_op!()]
39 #[inline]
40 pub const fn overflowing_add_unsigned(self, rhs: $BUint<N>) -> (Self, bool) {
41 let rhs = Self::from_bits(rhs);
42 let (sum, overflow) = self.overflowing_add(rhs);
43 (sum, rhs.is_negative() != overflow)
44 }
45
46 #[doc = doc::overflowing::overflowing_sub!(I)]
47 #[must_use = doc::must_use_op!()]
48 #[inline]
49 pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
50 let mut out = Self::ZERO;
51 let mut borrow = false;
52
53 let self_digits = self.bits.digits;
54 let rhs_digits = rhs.bits.digits;
55
56 let mut i = 0;
57 while i < Self::N_MINUS_1 {
58 let (sub, b) =
59 digit::$Digit::borrowing_sub(self_digits[i], rhs_digits[i], borrow);
60 out.bits.digits[i] = sub;
61 borrow = b;
62 i += 1;
63 }
64 let (sub, borrow) = digit::$Digit::borrowing_sub_signed(
65 self_digits[Self::N_MINUS_1] as digit::$Digit::SignedDigit,
66 rhs_digits[Self::N_MINUS_1] as digit::$Digit::SignedDigit,
67 borrow,
68 );
69 out.bits.digits[Self::N_MINUS_1] = sub as $Digit;
70
71 (out, borrow)
72 }
73
74 #[doc = doc::overflowing::overflowing_sub_unsigned!(I)]
75 #[must_use = doc::must_use_op!()]
76 #[inline]
77 pub const fn overflowing_sub_unsigned(self, rhs: $BUint<N>) -> (Self, bool) {
78 let rhs = Self::from_bits(rhs);
79 let (sum, overflow) = self.overflowing_sub(rhs);
80 (sum, rhs.is_negative() != overflow)
81 }
82
83 const BITS_MINUS_1: ExpType = (Self::BITS - 1) as ExpType;
84
85 #[doc = doc::overflowing::overflowing_mul!(I)]
86 #[must_use = doc::must_use_op!()]
87 #[inline]
88 pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
89 let (uint, overflow) = self.unsigned_abs().overflowing_mul(rhs.unsigned_abs());
90 let out = Self::from_bits(uint);
91 if self.is_negative() == rhs.is_negative() {
92 (out, overflow || out.is_negative())
93 } else {
94 match out.checked_neg() {
95 Some(n) => (n, overflow || out.is_negative()),
96 None => (out, overflow),
97 }
98 }
99 }
100
101 #[inline]
102 pub(crate) const fn div_rem_unchecked(self, rhs: Self) -> (Self, Self) {
103 if self.eq(&Self::MIN) && rhs.is_one() {
104 return (self, Self::ZERO);
105 }
106 let (div, rem) = self.unsigned_abs().div_rem_unchecked(rhs.unsigned_abs());
107 let (div, rem) = (Self::from_bits(div), Self::from_bits(rem));
108
109 match (self.is_negative(), rhs.is_negative()) {
110 (false, false) => (div, rem),
111 (false, true) => (div.neg(), rem),
112 (true, false) => (div.neg(), rem.neg()),
113 (true, true) => (div, rem.neg()),
114 }
115 }
116
117 #[doc = doc::overflowing::overflowing_div!(I)]
118 #[must_use = doc::must_use_op!()]
119 #[inline]
120 pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) {
121 if rhs.is_zero() {
122 div_zero!()
123 }
124 if self.eq(&Self::MIN) {
125 if rhs.eq(&Self::NEG_ONE) {
126 return (self, true);
127 } else if rhs.is_one() {
128 return (self, false);
129 }
130 }
131 (self.div_rem_unchecked(rhs).0, false)
132 }
133
134 #[doc = doc::overflowing::overflowing_div_euclid!(I)]
135 #[must_use = doc::must_use_op!()]
136 #[inline]
137 pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
138 if rhs.is_zero() {
139 div_zero!()
140 }
141 if self.eq(&Self::MIN) {
142 if rhs.eq(&Self::NEG_ONE) {
143 return (self, true);
144 } else if rhs.is_one() {
145 return (self, false);
146 }
147 }
148 let (div, rem) = self.div_rem_unchecked(rhs);
149 if self.is_negative() {
150 let r_neg = rhs.is_negative();
151 if !rem.is_zero() {
152 if r_neg {
153 return (div.add(Self::ONE), false);
154 } else {
155 return (div.sub(Self::ONE), false);
156 };
157 }
158 }
159 (div, false)
160 }
161
162 #[doc = doc::overflowing::overflowing_rem!(I)]
163 #[must_use = doc::must_use_op!()]
164 #[inline]
165 pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
166 if rhs.is_zero() {
167 div_zero!()
168 }
169 if self.eq(&Self::MIN) && rhs.eq(&Self::NEG_ONE) {
170 (Self::ZERO, true)
171 } else {
172 (self.div_rem_unchecked(rhs).1, false)
173 }
174 }
175
176 #[doc = doc::overflowing::overflowing_rem_euclid!(I)]
177 #[must_use = doc::must_use_op!()]
178 #[inline]
179 pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
180 if rhs.is_zero() {
181 div_zero!()
182 }
183 if self.eq(&Self::MIN) && rhs.eq(&Self::NEG_ONE) {
184 (Self::ZERO, true)
185 } else {
186 let mut rem = self.div_rem_unchecked(rhs).1;
187 if rem.is_negative() {
188 if rhs.is_negative() {
189 rem = rem.wrapping_sub(rhs);
190 } else {
191 rem = rem.wrapping_add(rhs);
192 }
193 }
194 (rem, false)
195 }
196 }
197
198 #[doc = doc::overflowing::overflowing_neg!(I)]
199 #[must_use = doc::must_use_op!()]
200 #[inline]
201 pub const fn overflowing_neg(mut self) -> (Self, bool) {
202 let mut i = 0;
203 while i < N - 1 {
204 let (s, o) = (!self.bits.digits[i]).overflowing_add(1); self.bits.digits[i] = s;
206 if !o {
207 i += 1;
208 while i < N {
209 self.bits.digits[i] = !self.bits.digits[i];
210 i += 1;
211 }
212 return (self, false);
213 }
214 i += 1;
215 }
216 let (s, o) =
217 (!self.bits.digits[i] as digit::$Digit::SignedDigit).overflowing_add(1);
218 self.bits.digits[i] = s as $Digit;
219 (self, o)
220 }
221
222 #[doc = doc::overflowing::overflowing_shl!(I)]
223 #[must_use = doc::must_use_op!()]
224 #[inline]
225 pub const fn overflowing_shl(self, rhs: ExpType) -> (Self, bool) {
226 let (uint, overflow) = self.bits.overflowing_shl(rhs);
227 (Self::from_bits(uint), overflow)
228 }
229
230 #[doc = doc::overflowing::overflowing_shr!(I)]
231 #[must_use = doc::must_use_op!()]
232 #[inline]
233 pub const fn overflowing_shr(self, rhs: ExpType) -> (Self, bool) {
234 let bits = self.to_bits();
235 let (overflow, shift) = if rhs >= Self::BITS {
236 (true, rhs & Self::BITS_MINUS_1)
237 } else {
238 (false, rhs)
239 };
240 let u = unsafe {
241 if self.is_negative() {
242 $BUint::unchecked_shr_pad_internal::<true>(bits, shift)
243 } else {
244 $BUint::unchecked_shr_pad_internal::<false>(bits, shift)
245 }
246 };
247 (Self::from_bits(u), overflow)
248 }
249
250 #[doc = doc::overflowing::overflowing_abs!(I)]
251 #[must_use = doc::must_use_op!()]
252 #[inline]
253 pub const fn overflowing_abs(self) -> (Self, bool) {
254 if self.is_negative() {
255 self.overflowing_neg()
256 } else {
257 (self, false)
258 }
259 }
260
261 #[doc = doc::overflowing::overflowing_pow!(I)]
262 #[must_use = doc::must_use_op!()]
263 #[inline]
264 pub const fn overflowing_pow(self, pow: ExpType) -> (Self, bool) {
265 let (u, mut overflow) = self.unsigned_abs().overflowing_pow(pow);
266 let out_neg = self.is_negative() && pow & 1 == 1;
267 let mut out = Self::from_bits(u);
268 if out_neg {
269 out = out.wrapping_neg();
270 overflow = overflow || !out.is_negative();
271 } else {
272 overflow = overflow || out.is_negative();
273 }
274 (out, overflow)
275 }
276 }
277 };
278}
279
280crate::macro_impl!(overflowing);