1 #[cfg(not(u64_digit))]
2 use super::u32_from_u128;
3 use super::BigUint;
4
5 use crate::big_digit::{self, BigDigit};
6 use crate::UsizePromotion;
7
8 use core::cmp::Ordering::{Equal, Greater, Less};
9 use core::ops::{Sub, SubAssign};
10 use num_traits::{CheckedSub, Zero};
11
12 #[cfg(all(use_addcarry, target_arch = "x86_64"))]
13 use core::arch::x86_64 as arch;
14
15 #[cfg(all(use_addcarry, target_arch = "x86"))]
16 use core::arch::x86 as arch;
17
18 // Subtract with borrow:
19 #[cfg(all(use_addcarry, u64_digit))]
20 #[inline]
sbb(borrow: u8, a: u64, b: u64, out: &mut u64) -> u821 fn sbb(borrow: u8, a: u64, b: u64, out: &mut u64) -> u8 {
22 // Safety: There are absolutely no safety concerns with calling `_subborrow_u64`.
23 // It's just unsafe for API consistency with other intrinsics.
24 unsafe { arch::_subborrow_u64(borrow, a, b, out) }
25 }
26
27 #[cfg(all(use_addcarry, not(u64_digit)))]
28 #[inline]
sbb(borrow: u8, a: u32, b: u32, out: &mut u32) -> u829 fn sbb(borrow: u8, a: u32, b: u32, out: &mut u32) -> u8 {
30 // Safety: There are absolutely no safety concerns with calling `_subborrow_u32`.
31 // It's just unsafe for API consistency with other intrinsics.
32 unsafe { arch::_subborrow_u32(borrow, a, b, out) }
33 }
34
35 // fallback for environments where we don't have a subborrow intrinsic
36 #[cfg(not(use_addcarry))]
37 #[inline]
sbb(borrow: u8, a: BigDigit, b: BigDigit, out: &mut BigDigit) -> u838 fn sbb(borrow: u8, a: BigDigit, b: BigDigit, out: &mut BigDigit) -> u8 {
39 use crate::big_digit::SignedDoubleBigDigit;
40
41 let difference = SignedDoubleBigDigit::from(a)
42 - SignedDoubleBigDigit::from(b)
43 - SignedDoubleBigDigit::from(borrow);
44 *out = difference as BigDigit;
45 u8::from(difference < 0)
46 }
47
sub2(a: &mut [BigDigit], b: &[BigDigit])48 pub(super) fn sub2(a: &mut [BigDigit], b: &[BigDigit]) {
49 let mut borrow = 0;
50
51 let len = Ord::min(a.len(), b.len());
52 let (a_lo, a_hi) = a.split_at_mut(len);
53 let (b_lo, b_hi) = b.split_at(len);
54
55 for (a, b) in a_lo.iter_mut().zip(b_lo) {
56 borrow = sbb(borrow, *a, *b, a);
57 }
58
59 if borrow != 0 {
60 for a in a_hi {
61 borrow = sbb(borrow, *a, 0, a);
62 if borrow == 0 {
63 break;
64 }
65 }
66 }
67
68 // note: we're _required_ to fail on underflow
69 assert!(
70 borrow == 0 && b_hi.iter().all(|x| *x == 0),
71 "Cannot subtract b from a because b is larger than a."
72 );
73 }
74
75 // Only for the Sub impl. `a` and `b` must have same length.
76 #[inline]
__sub2rev(a: &[BigDigit], b: &mut [BigDigit]) -> u877 fn __sub2rev(a: &[BigDigit], b: &mut [BigDigit]) -> u8 {
78 debug_assert!(b.len() == a.len());
79
80 let mut borrow = 0;
81
82 for (ai, bi) in a.iter().zip(b) {
83 borrow = sbb(borrow, *ai, *bi, bi);
84 }
85
86 borrow
87 }
88
sub2rev(a: &[BigDigit], b: &mut [BigDigit])89 fn sub2rev(a: &[BigDigit], b: &mut [BigDigit]) {
90 debug_assert!(b.len() >= a.len());
91
92 let len = Ord::min(a.len(), b.len());
93 let (a_lo, a_hi) = a.split_at(len);
94 let (b_lo, b_hi) = b.split_at_mut(len);
95
96 let borrow = __sub2rev(a_lo, b_lo);
97
98 assert!(a_hi.is_empty());
99
100 // note: we're _required_ to fail on underflow
101 assert!(
102 borrow == 0 && b_hi.iter().all(|x| *x == 0),
103 "Cannot subtract b from a because b is larger than a."
104 );
105 }
106
107 forward_val_val_binop!(impl Sub for BigUint, sub);
108 forward_ref_ref_binop!(impl Sub for BigUint, sub);
109 forward_val_assign!(impl SubAssign for BigUint, sub_assign);
110
111 impl Sub<&BigUint> for BigUint {
112 type Output = BigUint;
113
sub(mut self, other: &BigUint) -> BigUint114 fn sub(mut self, other: &BigUint) -> BigUint {
115 self -= other;
116 self
117 }
118 }
119 impl SubAssign<&BigUint> for BigUint {
sub_assign(&mut self, other: &BigUint)120 fn sub_assign(&mut self, other: &BigUint) {
121 sub2(&mut self.data[..], &other.data[..]);
122 self.normalize();
123 }
124 }
125
126 impl Sub<BigUint> for &BigUint {
127 type Output = BigUint;
128
sub(self, mut other: BigUint) -> BigUint129 fn sub(self, mut other: BigUint) -> BigUint {
130 let other_len = other.data.len();
131 if other_len < self.data.len() {
132 let lo_borrow = __sub2rev(&self.data[..other_len], &mut other.data);
133 other.data.extend_from_slice(&self.data[other_len..]);
134 if lo_borrow != 0 {
135 sub2(&mut other.data[other_len..], &[1])
136 }
137 } else {
138 sub2rev(&self.data[..], &mut other.data[..]);
139 }
140 other.normalized()
141 }
142 }
143
144 promote_unsigned_scalars!(impl Sub for BigUint, sub);
145 promote_unsigned_scalars_assign!(impl SubAssign for BigUint, sub_assign);
146 forward_all_scalar_binop_to_val_val!(impl Sub<u32> for BigUint, sub);
147 forward_all_scalar_binop_to_val_val!(impl Sub<u64> for BigUint, sub);
148 forward_all_scalar_binop_to_val_val!(impl Sub<u128> for BigUint, sub);
149
150 impl Sub<u32> for BigUint {
151 type Output = BigUint;
152
153 #[inline]
sub(mut self, other: u32) -> BigUint154 fn sub(mut self, other: u32) -> BigUint {
155 self -= other;
156 self
157 }
158 }
159
160 impl SubAssign<u32> for BigUint {
sub_assign(&mut self, other: u32)161 fn sub_assign(&mut self, other: u32) {
162 sub2(&mut self.data[..], &[other as BigDigit]);
163 self.normalize();
164 }
165 }
166
167 impl Sub<BigUint> for u32 {
168 type Output = BigUint;
169
170 #[cfg(not(u64_digit))]
171 #[inline]
sub(self, mut other: BigUint) -> BigUint172 fn sub(self, mut other: BigUint) -> BigUint {
173 if other.data.len() == 0 {
174 other.data.push(self);
175 } else {
176 sub2rev(&[self], &mut other.data[..]);
177 }
178 other.normalized()
179 }
180
181 #[cfg(u64_digit)]
182 #[inline]
sub(self, mut other: BigUint) -> BigUint183 fn sub(self, mut other: BigUint) -> BigUint {
184 if other.data.is_empty() {
185 other.data.push(self as BigDigit);
186 } else {
187 sub2rev(&[self as BigDigit], &mut other.data[..]);
188 }
189 other.normalized()
190 }
191 }
192
193 impl Sub<u64> for BigUint {
194 type Output = BigUint;
195
196 #[inline]
sub(mut self, other: u64) -> BigUint197 fn sub(mut self, other: u64) -> BigUint {
198 self -= other;
199 self
200 }
201 }
202
203 impl SubAssign<u64> for BigUint {
204 #[cfg(not(u64_digit))]
205 #[inline]
sub_assign(&mut self, other: u64)206 fn sub_assign(&mut self, other: u64) {
207 let (hi, lo) = big_digit::from_doublebigdigit(other);
208 sub2(&mut self.data[..], &[lo, hi]);
209 self.normalize();
210 }
211
212 #[cfg(u64_digit)]
213 #[inline]
sub_assign(&mut self, other: u64)214 fn sub_assign(&mut self, other: u64) {
215 sub2(&mut self.data[..], &[other as BigDigit]);
216 self.normalize();
217 }
218 }
219
220 impl Sub<BigUint> for u64 {
221 type Output = BigUint;
222
223 #[cfg(not(u64_digit))]
224 #[inline]
sub(self, mut other: BigUint) -> BigUint225 fn sub(self, mut other: BigUint) -> BigUint {
226 while other.data.len() < 2 {
227 other.data.push(0);
228 }
229
230 let (hi, lo) = big_digit::from_doublebigdigit(self);
231 sub2rev(&[lo, hi], &mut other.data[..]);
232 other.normalized()
233 }
234
235 #[cfg(u64_digit)]
236 #[inline]
sub(self, mut other: BigUint) -> BigUint237 fn sub(self, mut other: BigUint) -> BigUint {
238 if other.data.is_empty() {
239 other.data.push(self);
240 } else {
241 sub2rev(&[self], &mut other.data[..]);
242 }
243 other.normalized()
244 }
245 }
246
247 impl Sub<u128> for BigUint {
248 type Output = BigUint;
249
250 #[inline]
sub(mut self, other: u128) -> BigUint251 fn sub(mut self, other: u128) -> BigUint {
252 self -= other;
253 self
254 }
255 }
256
257 impl SubAssign<u128> for BigUint {
258 #[cfg(not(u64_digit))]
259 #[inline]
sub_assign(&mut self, other: u128)260 fn sub_assign(&mut self, other: u128) {
261 let (a, b, c, d) = u32_from_u128(other);
262 sub2(&mut self.data[..], &[d, c, b, a]);
263 self.normalize();
264 }
265
266 #[cfg(u64_digit)]
267 #[inline]
sub_assign(&mut self, other: u128)268 fn sub_assign(&mut self, other: u128) {
269 let (hi, lo) = big_digit::from_doublebigdigit(other);
270 sub2(&mut self.data[..], &[lo, hi]);
271 self.normalize();
272 }
273 }
274
275 impl Sub<BigUint> for u128 {
276 type Output = BigUint;
277
278 #[cfg(not(u64_digit))]
279 #[inline]
sub(self, mut other: BigUint) -> BigUint280 fn sub(self, mut other: BigUint) -> BigUint {
281 while other.data.len() < 4 {
282 other.data.push(0);
283 }
284
285 let (a, b, c, d) = u32_from_u128(self);
286 sub2rev(&[d, c, b, a], &mut other.data[..]);
287 other.normalized()
288 }
289
290 #[cfg(u64_digit)]
291 #[inline]
sub(self, mut other: BigUint) -> BigUint292 fn sub(self, mut other: BigUint) -> BigUint {
293 while other.data.len() < 2 {
294 other.data.push(0);
295 }
296
297 let (hi, lo) = big_digit::from_doublebigdigit(self);
298 sub2rev(&[lo, hi], &mut other.data[..]);
299 other.normalized()
300 }
301 }
302
303 impl CheckedSub for BigUint {
304 #[inline]
checked_sub(&self, v: &BigUint) -> Option<BigUint>305 fn checked_sub(&self, v: &BigUint) -> Option<BigUint> {
306 match self.cmp(v) {
307 Less => None,
308 Equal => Some(Zero::zero()),
309 Greater => Some(self.sub(v)),
310 }
311 }
312 }
313