reweb3_num/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 #[inline]
51 const fn long_mul(self, rhs: Self) -> (Self, bool) {
52 let mut overflow = false;
53 let mut out = Self::ZERO;
54 let mut carry: $Digit;
55
56 let mut i = 0;
57 while i < N {
58 carry = 0;
59 let mut j = 0;
60 while j < N {
61 let index = i + j;
62 if index < N {
63 let (prod, c) = digit::$Digit::carrying_mul(
64 self.digits[i],
65 rhs.digits[j],
66 carry,
67 out.digits[index],
68 );
69 out.digits[index] = prod;
70 carry = c;
71 } else if self.digits[i] != 0 && rhs.digits[j] != 0 {
72 overflow = true;
73 break;
74 }
75 j += 1;
76 }
77 if carry != 0 {
78 overflow = true;
79 }
80 i += 1;
81 }
82 (out, overflow)
83 }
84
85 #[doc = doc::overflowing::overflowing_mul!(U)]
86 #[must_use = doc::must_use_op!()]
87 #[inline]
88 pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
89 self.long_mul(rhs)
91 }
92
93 #[doc = doc::overflowing::overflowing_div!(U)]
94 #[must_use = doc::must_use_op!()]
95 #[inline]
96 pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) {
97 (self.wrapping_div(rhs), false)
98 }
99
100 #[doc = doc::overflowing::overflowing_div_euclid!(U)]
101 #[must_use = doc::must_use_op!()]
102 #[inline]
103 pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
104 self.overflowing_div(rhs)
105 }
106
107 #[doc = doc::overflowing::overflowing_rem!(U)]
108 #[must_use = doc::must_use_op!()]
109 #[inline]
110 pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
111 (self.wrapping_rem(rhs), false)
112 }
113
114 #[doc = doc::overflowing::overflowing_rem_euclid!(U)]
115 #[must_use = doc::must_use_op!()]
116 #[inline]
117 pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
118 self.overflowing_rem(rhs)
119 }
120
121 #[doc = doc::overflowing::overflowing_neg!(U)]
122 #[must_use = doc::must_use_op!()]
123 #[inline]
124 pub const fn overflowing_neg(self) -> (Self, bool) {
125 let (a, b) = (self.not()).overflowing_add(Self::ONE);
126 (a, !b)
127 }
128
129 #[doc = doc::overflowing::overflowing_shl!(U)]
130 #[must_use = doc::must_use_op!()]
131 #[inline]
132 pub const fn overflowing_shl(self, rhs: ExpType) -> (Self, bool) {
133 unsafe {
134 if rhs >= Self::BITS {
135 (
136 Self::unchecked_shl_internal(self, rhs & (Self::BITS - 1)),
137 true,
138 )
139 } else {
140 (Self::unchecked_shl_internal(self, rhs), false)
141 }
142 }
143 }
144
145 #[doc = doc::overflowing::overflowing_shr!(U)]
146 #[must_use = doc::must_use_op!()]
147 #[inline]
148 pub const fn overflowing_shr(self, rhs: ExpType) -> (Self, bool) {
149 unsafe {
150 if rhs >= Self::BITS {
151 (
152 Self::unchecked_shr_internal(self, rhs & (Self::BITS - 1)),
153 true,
154 )
155 } else {
156 (Self::unchecked_shr_internal(self, rhs), false)
157 }
158 }
159 }
160
161 #[doc = doc::overflowing::overflowing_pow!(U)]
162 #[must_use = doc::must_use_op!()]
163 #[inline]
164 pub const fn overflowing_pow(mut self, mut pow: ExpType) -> (Self, bool) {
165 if pow == 0 {
166 return (Self::ONE, false);
167 }
168 let mut overflow = false;
169 let mut y = Self::ONE;
170 while pow > 1 {
171 if pow & 1 == 1 {
172 let (prod, o) = y.overflowing_mul(self);
173 overflow |= o;
174 y = prod;
175 }
176 let (prod, o) = self.overflowing_mul(self);
177 overflow |= o;
178 self = prod;
179 pow >>= 1;
180 }
181 let (prod, o) = self.overflowing_mul(y);
182 (prod, o || overflow)
183 }
184 }
185 };
186}
187
188crate::macro_impl!(overflowing);