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 #[allow(unused_unsafe)] fn sbb(borrow: u8, a: u64, b: u64, out: &mut u64) -> u8 {
22 unsafe { arch::_subborrow_u64(borrow, a, b, out) }
25 }
26);
27
28#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
29cfg_32!(
30 #[inline]
31 #[allow(unused_unsafe)] fn sbb(borrow: u8, a: u32, b: u32, out: &mut u32) -> u8 {
33 unsafe { arch::_subborrow_u32(borrow, a, b, out) }
36 }
37);
38
39#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
42#[inline]
43fn sbb(borrow: u8, lhs: BigDigit, rhs: BigDigit, out: &mut BigDigit) -> u8 {
44 let (a, b) = lhs.overflowing_sub(rhs);
45 let (c, d) = a.overflowing_sub(borrow as BigDigit);
46 *out = c;
47 u8::from(b || d)
48}
49
50pub(super) fn sub2(a: &mut [BigDigit], b: &[BigDigit]) {
51 let mut borrow = 0;
52
53 let len = Ord::min(a.len(), b.len());
54 let (a_lo, a_hi) = a.split_at_mut(len);
55 let (b_lo, b_hi) = b.split_at(len);
56
57 for (a, b) in a_lo.iter_mut().zip(b_lo) {
58 borrow = sbb(borrow, *a, *b, a);
59 }
60
61 if borrow != 0 {
62 for a in a_hi {
63 borrow = sbb(borrow, *a, 0, a);
64 if borrow == 0 {
65 break;
66 }
67 }
68 }
69
70 assert!(
72 borrow == 0 && b_hi.iter().all(|x| *x == 0),
73 "Cannot subtract b from a because b is larger than a."
74 );
75}
76
77#[inline]
79fn __sub2rev(a: &[BigDigit], b: &mut [BigDigit]) -> u8 {
80 debug_assert!(b.len() == a.len());
81
82 let mut borrow = 0;
83
84 for (ai, bi) in a.iter().zip(b) {
85 borrow = sbb(borrow, *ai, *bi, bi);
86 }
87
88 borrow
89}
90
91fn sub2rev(a: &[BigDigit], b: &mut [BigDigit]) {
92 debug_assert!(b.len() >= a.len());
93
94 let len = Ord::min(a.len(), b.len());
95 let (a_lo, a_hi) = a.split_at(len);
96 let (b_lo, b_hi) = b.split_at_mut(len);
97
98 let borrow = __sub2rev(a_lo, b_lo);
99
100 assert!(a_hi.is_empty());
101
102 assert!(
104 borrow == 0 && b_hi.iter().all(|x| *x == 0),
105 "Cannot subtract b from a because b is larger than a."
106 );
107}
108
109forward_val_val_binop!(impl Sub for BigUint, sub);
110forward_ref_ref_binop!(impl Sub for BigUint, sub);
111forward_val_assign!(impl SubAssign for BigUint, sub_assign);
112
113impl Sub<&BigUint> for BigUint {
114 type Output = BigUint;
115
116 fn sub(mut self, other: &BigUint) -> BigUint {
117 self -= other;
118 self
119 }
120}
121impl SubAssign<&BigUint> for BigUint {
122 fn sub_assign(&mut self, other: &BigUint) {
123 sub2(&mut self.data, &other.data);
124 self.data.normalize();
125 }
126}
127
128impl Sub<BigUint> for &BigUint {
129 type Output = BigUint;
130
131 fn sub(self, mut other: BigUint) -> BigUint {
132 let other_len = other.data.len();
133 if other_len < self.data.len() {
134 let (lo, hi) = self.data.split_at(other_len);
135 let lo_borrow = __sub2rev(lo, &mut other.data);
136 other.data.extend_from_slice(hi);
137 if lo_borrow != 0 {
138 sub2(&mut other.data[other_len..], &[1])
139 }
140 } else {
141 sub2rev(&self.data, &mut other.data);
142 }
143 other.data.normalize();
144 other
145 }
146}
147
148promote_unsigned_scalars!(impl Sub for BigUint, sub);
149promote_unsigned_scalars_assign!(impl SubAssign for BigUint, sub_assign);
150forward_all_scalar_binop_to_val_val!(impl Sub<u32> for BigUint, sub);
151forward_all_scalar_binop_to_val_val!(impl Sub<u64> for BigUint, sub);
152forward_all_scalar_binop_to_val_val!(impl Sub<u128> for BigUint, sub);
153
154impl Sub<u32> for BigUint {
155 type Output = BigUint;
156
157 #[inline]
158 fn sub(mut self, other: u32) -> BigUint {
159 self -= other;
160 self
161 }
162}
163
164impl SubAssign<u32> for BigUint {
165 fn sub_assign(&mut self, other: u32) {
166 sub2(&mut self.data, &[other as BigDigit]);
167 self.data.normalize();
168 }
169}
170
171impl Sub<BigUint> for u32 {
172 type Output = BigUint;
173
174 cfg_digit!(
175 #[inline]
176 fn sub(self, mut other: BigUint) -> BigUint {
177 if other.data.is_empty() {
178 other.data.push(self);
179 } else {
180 sub2rev(&[self], &mut other.data);
181 }
182 other.data.normalize();
183 other
184 }
185
186 #[inline]
187 fn sub(self, mut other: BigUint) -> BigUint {
188 if other.data.is_empty() {
189 other.data.push(self as BigDigit);
190 } else {
191 sub2rev(&[self as BigDigit], &mut other.data);
192 }
193 other.data.normalize();
194 other
195 }
196 );
197}
198
199impl Sub<u64> for BigUint {
200 type Output = BigUint;
201
202 #[inline]
203 fn sub(mut self, other: u64) -> BigUint {
204 self -= other;
205 self
206 }
207}
208
209impl SubAssign<u64> for BigUint {
210 cfg_digit!(
211 #[inline]
212 fn sub_assign(&mut self, other: u64) {
213 let (hi, lo) = big_digit::from_doublebigdigit(other);
214 sub2(&mut self.data, &[lo, hi]);
215 self.data.normalize();
216 }
217
218 #[inline]
219 fn sub_assign(&mut self, other: u64) {
220 sub2(&mut self.data, &[other as BigDigit]);
221 self.data.normalize();
222 }
223 );
224}
225
226impl Sub<BigUint> for u64 {
227 type Output = BigUint;
228
229 cfg_digit!(
230 #[inline]
231 fn sub(self, mut other: BigUint) -> BigUint {
232 while other.data.len() < 2 {
233 other.data.push(0);
234 }
235
236 let (hi, lo) = big_digit::from_doublebigdigit(self);
237 sub2rev(&[lo, hi], &mut other.data);
238 other.data.normalize();
239 other
240 }
241
242 #[inline]
243 fn sub(self, mut other: BigUint) -> BigUint {
244 if other.data.is_empty() {
245 other.data.push(self);
246 } else {
247 sub2rev(&[self], &mut other.data);
248 }
249 other.data.normalize();
250 other
251 }
252 );
253}
254
255impl Sub<u128> for BigUint {
256 type Output = BigUint;
257
258 #[inline]
259 fn sub(mut self, other: u128) -> BigUint {
260 self -= other;
261 self
262 }
263}
264
265impl SubAssign<u128> for BigUint {
266 cfg_digit!(
267 #[inline]
268 fn sub_assign(&mut self, other: u128) {
269 let (a, b, c, d) = super::u32_from_u128(other);
270 sub2(&mut self.data, &[d, c, b, a]);
271 self.data.normalize();
272 }
273
274 #[inline]
275 fn sub_assign(&mut self, other: u128) {
276 let (hi, lo) = big_digit::from_doublebigdigit(other);
277 sub2(&mut self.data, &[lo, hi]);
278 self.data.normalize();
279 }
280 );
281}
282
283impl Sub<BigUint> for u128 {
284 type Output = BigUint;
285
286 cfg_digit!(
287 #[inline]
288 fn sub(self, mut other: BigUint) -> BigUint {
289 while other.data.len() < 4 {
290 other.data.push(0);
291 }
292
293 let (a, b, c, d) = super::u32_from_u128(self);
294 sub2rev(&[d, c, b, a], &mut other.data);
295 other.data.normalize();
296 other
297 }
298
299 #[inline]
300 fn sub(self, mut other: BigUint) -> BigUint {
301 while other.data.len() < 2 {
302 other.data.push(0);
303 }
304
305 let (hi, lo) = big_digit::from_doublebigdigit(self);
306 sub2rev(&[lo, hi], &mut other.data);
307 other.data.normalize();
308 other
309 }
310 );
311}
312
313impl CheckedSub for BigUint {
314 #[inline]
315 fn checked_sub(&self, v: &BigUint) -> Option<BigUint> {
316 match self.cmp(v) {
317 Less => None,
318 Equal => Some(Self::ZERO),
319 Greater => Some(self.sub(v)),
320 }
321 }
322}