1use super::BigUint;
2
3use crate::big_digit::{self, BigDigit};
4use crate::UsizePromotion;
5
6use core::cmp::Ordering::{Equal, Greater, Less};
7use core::ops::{Sub, SubAssign};
8use num_traits::CheckedSub;
9
10#[cfg(target_arch = "x86_64")]
11use core::arch::x86_64 as arch;
12
13#[cfg(target_arch = "x86")]
14use core::arch::x86 as arch;
15
16#[cfg(target_arch = "x86_64")]
18cfg_64!(
19 #[inline]
20 fn sbb(borrow: u8, a: u64, b: u64, out: &mut u64) -> u8 {
21 unsafe { arch::_subborrow_u64(borrow, a, b, out) }
24 }
25);
26
27#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
28cfg_32!(
29 #[inline]
30 fn sbb(borrow: u8, a: u32, b: u32, out: &mut u32) -> u8 {
31 unsafe { arch::_subborrow_u32(borrow, a, b, out) }
34 }
35);
36
37#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
40#[inline]
41fn sbb(borrow: u8, lhs: BigDigit, rhs: BigDigit, out: &mut BigDigit) -> u8 {
42 let (a, b) = lhs.overflowing_sub(rhs);
43 let (c, d) = a.overflowing_sub(borrow as BigDigit);
44 *out = c;
45 u8::from(b || d)
46}
47
48pub(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 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#[inline]
77fn __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
89fn 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 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
107forward_val_val_binop!(impl Sub for BigUint, sub);
108forward_ref_ref_binop!(impl Sub for BigUint, sub);
109forward_val_assign!(impl SubAssign for BigUint, sub_assign);
110
111impl Sub<&BigUint> for BigUint {
112 type Output = BigUint;
113
114 fn sub(mut self, other: &BigUint) -> BigUint {
115 self -= other;
116 self
117 }
118}
119impl SubAssign<&BigUint> for BigUint {
120 fn sub_assign(&mut self, other: &BigUint) {
121 sub2(&mut self.data[..], &other.data[..]);
122 self.normalize();
123 }
124}
125
126impl Sub<BigUint> for &BigUint {
127 type Output = BigUint;
128
129 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
144promote_unsigned_scalars!(impl Sub for BigUint, sub);
145promote_unsigned_scalars_assign!(impl SubAssign for BigUint, sub_assign);
146forward_all_scalar_binop_to_val_val!(impl Sub<u32> for BigUint, sub);
147forward_all_scalar_binop_to_val_val!(impl Sub<u64> for BigUint, sub);
148forward_all_scalar_binop_to_val_val!(impl Sub<u128> for BigUint, sub);
149
150impl Sub<u32> for BigUint {
151 type Output = BigUint;
152
153 #[inline]
154 fn sub(mut self, other: u32) -> BigUint {
155 self -= other;
156 self
157 }
158}
159
160impl SubAssign<u32> for BigUint {
161 fn sub_assign(&mut self, other: u32) {
162 sub2(&mut self.data[..], &[other as BigDigit]);
163 self.normalize();
164 }
165}
166
167impl Sub<BigUint> for u32 {
168 type Output = BigUint;
169
170 cfg_digit!(
171 #[inline]
172 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 #[inline]
182 fn sub(self, mut other: BigUint) -> BigUint {
183 if other.data.is_empty() {
184 other.data.push(self as BigDigit);
185 } else {
186 sub2rev(&[self as BigDigit], &mut other.data[..]);
187 }
188 other.normalized()
189 }
190 );
191}
192
193impl Sub<u64> for BigUint {
194 type Output = BigUint;
195
196 #[inline]
197 fn sub(mut self, other: u64) -> BigUint {
198 self -= other;
199 self
200 }
201}
202
203impl SubAssign<u64> for BigUint {
204 cfg_digit!(
205 #[inline]
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 #[inline]
213 fn sub_assign(&mut self, other: u64) {
214 sub2(&mut self.data[..], &[other as BigDigit]);
215 self.normalize();
216 }
217 );
218}
219
220impl Sub<BigUint> for u64 {
221 type Output = BigUint;
222
223 cfg_digit!(
224 #[inline]
225 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 #[inline]
236 fn sub(self, mut other: BigUint) -> BigUint {
237 if other.data.is_empty() {
238 other.data.push(self);
239 } else {
240 sub2rev(&[self], &mut other.data[..]);
241 }
242 other.normalized()
243 }
244 );
245}
246
247impl Sub<u128> for BigUint {
248 type Output = BigUint;
249
250 #[inline]
251 fn sub(mut self, other: u128) -> BigUint {
252 self -= other;
253 self
254 }
255}
256
257impl SubAssign<u128> for BigUint {
258 cfg_digit!(
259 #[inline]
260 fn sub_assign(&mut self, other: u128) {
261 let (a, b, c, d) = super::u32_from_u128(other);
262 sub2(&mut self.data[..], &[d, c, b, a]);
263 self.normalize();
264 }
265
266 #[inline]
267 fn sub_assign(&mut self, other: u128) {
268 let (hi, lo) = big_digit::from_doublebigdigit(other);
269 sub2(&mut self.data[..], &[lo, hi]);
270 self.normalize();
271 }
272 );
273}
274
275impl Sub<BigUint> for u128 {
276 type Output = BigUint;
277
278 cfg_digit!(
279 #[inline]
280 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) = super::u32_from_u128(self);
286 sub2rev(&[d, c, b, a], &mut other.data[..]);
287 other.normalized()
288 }
289
290 #[inline]
291 fn sub(self, mut other: BigUint) -> BigUint {
292 while other.data.len() < 2 {
293 other.data.push(0);
294 }
295
296 let (hi, lo) = big_digit::from_doublebigdigit(self);
297 sub2rev(&[lo, hi], &mut other.data[..]);
298 other.normalized()
299 }
300 );
301}
302
303impl CheckedSub for BigUint {
304 #[inline]
305 fn checked_sub(&self, v: &BigUint) -> Option<BigUint> {
306 match self.cmp(v) {
307 Less => None,
308 Equal => Some(Self::ZERO),
309 Greater => Some(self.sub(v)),
310 }
311 }
312}