/rust/registry/src/index.crates.io-1949cf8c6b5b557f/num-bigint-0.4.8/src/biguint/subtraction.rs
Line | Count | Source |
1 | | use super::BigUint; |
2 | | |
3 | | use crate::big_digit::{self, BigDigit}; |
4 | | use crate::UsizePromotion; |
5 | | |
6 | | use core::cmp::Ordering::{Equal, Greater, Less}; |
7 | | use core::ops::{Sub, SubAssign}; |
8 | | use num_traits::CheckedSub; |
9 | | |
10 | | #[cfg(target_arch = "x86_64")] |
11 | | use core::arch::x86_64 as arch; |
12 | | |
13 | | #[cfg(target_arch = "x86")] |
14 | | use core::arch::x86 as arch; |
15 | | |
16 | | // Subtract with borrow: |
17 | | #[cfg(target_arch = "x86_64")] |
18 | | cfg_64!( |
19 | | #[inline] |
20 | | #[allow(unused_unsafe)] // TODO(MSRV 1.93): the intrinsic became safe |
21 | 0 | 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 | 0 | unsafe { arch::_subborrow_u64(borrow, a, b, out) } |
25 | 0 | } |
26 | | ); |
27 | | |
28 | | #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] |
29 | | cfg_32!( |
30 | | #[inline] |
31 | | #[allow(unused_unsafe)] // TODO(MSRV 1.93): the intrinsic became safe |
32 | | fn sbb(borrow: u8, a: u32, b: u32, out: &mut u32) -> u8 { |
33 | | // SAFETY: There are absolutely no safety concerns with calling `_subborrow_u32`. |
34 | | // It's just unsafe for API consistency with other intrinsics. |
35 | | unsafe { arch::_subborrow_u32(borrow, a, b, out) } |
36 | | } |
37 | | ); |
38 | | |
39 | | // fallback for environments where we don't have a subborrow intrinsic |
40 | | // (copied from the standard library's `borrowing_sub`) |
41 | | #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] |
42 | | #[inline] |
43 | | fn 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 | | |
50 | 0 | pub(super) fn sub2(a: &mut [BigDigit], b: &[BigDigit]) { |
51 | 0 | let mut borrow = 0; |
52 | | |
53 | 0 | let len = Ord::min(a.len(), b.len()); |
54 | 0 | let (a_lo, a_hi) = a.split_at_mut(len); |
55 | 0 | let (b_lo, b_hi) = b.split_at(len); |
56 | | |
57 | 0 | for (a, b) in a_lo.iter_mut().zip(b_lo) { |
58 | 0 | borrow = sbb(borrow, *a, *b, a); |
59 | 0 | } |
60 | | |
61 | 0 | if borrow != 0 { |
62 | 0 | for a in a_hi { |
63 | 0 | borrow = sbb(borrow, *a, 0, a); |
64 | 0 | if borrow == 0 { |
65 | 0 | break; |
66 | 0 | } |
67 | | } |
68 | 0 | } |
69 | | |
70 | | // note: we're _required_ to fail on underflow |
71 | 0 | assert!( |
72 | 0 | borrow == 0 && b_hi.iter().all(|x| *x == 0), |
73 | 0 | "Cannot subtract b from a because b is larger than a." |
74 | | ); |
75 | 0 | } |
76 | | |
77 | | // Only for the Sub impl. `a` and `b` must have same length. |
78 | | #[inline] |
79 | 0 | fn __sub2rev(a: &[BigDigit], b: &mut [BigDigit]) -> u8 { |
80 | 0 | debug_assert!(b.len() == a.len()); |
81 | | |
82 | 0 | let mut borrow = 0; |
83 | | |
84 | 0 | for (ai, bi) in a.iter().zip(b) { |
85 | 0 | borrow = sbb(borrow, *ai, *bi, bi); |
86 | 0 | } |
87 | | |
88 | 0 | borrow |
89 | 0 | } |
90 | | |
91 | 0 | fn sub2rev(a: &[BigDigit], b: &mut [BigDigit]) { |
92 | 0 | debug_assert!(b.len() >= a.len()); |
93 | | |
94 | 0 | let len = Ord::min(a.len(), b.len()); |
95 | 0 | let (a_lo, a_hi) = a.split_at(len); |
96 | 0 | let (b_lo, b_hi) = b.split_at_mut(len); |
97 | | |
98 | 0 | let borrow = __sub2rev(a_lo, b_lo); |
99 | | |
100 | 0 | assert!(a_hi.is_empty()); |
101 | | |
102 | | // note: we're _required_ to fail on underflow |
103 | 0 | assert!( |
104 | 0 | borrow == 0 && b_hi.iter().all(|x| *x == 0), |
105 | 0 | "Cannot subtract b from a because b is larger than a." |
106 | | ); |
107 | 0 | } |
108 | | |
109 | | forward_val_val_binop!(impl Sub for BigUint, sub); |
110 | | forward_ref_ref_binop!(impl Sub for BigUint, sub); |
111 | | forward_val_assign!(impl SubAssign for BigUint, sub_assign); |
112 | | |
113 | | impl Sub<&BigUint> for BigUint { |
114 | | type Output = BigUint; |
115 | | |
116 | 0 | fn sub(mut self, other: &BigUint) -> BigUint { |
117 | 0 | self -= other; |
118 | 0 | self |
119 | 0 | } |
120 | | } |
121 | | impl SubAssign<&BigUint> for BigUint { |
122 | 0 | fn sub_assign(&mut self, other: &BigUint) { |
123 | 0 | sub2(&mut self.data, &other.data); |
124 | 0 | self.data.normalize(); |
125 | 0 | } |
126 | | } |
127 | | |
128 | | impl Sub<BigUint> for &BigUint { |
129 | | type Output = BigUint; |
130 | | |
131 | 0 | fn sub(self, mut other: BigUint) -> BigUint { |
132 | 0 | let other_len = other.data.len(); |
133 | 0 | if other_len < self.data.len() { |
134 | 0 | let (lo, hi) = self.data.split_at(other_len); |
135 | 0 | let lo_borrow = __sub2rev(lo, &mut other.data); |
136 | 0 | other.data.extend_from_slice(hi); |
137 | 0 | if lo_borrow != 0 { |
138 | 0 | sub2(&mut other.data[other_len..], &[1]) |
139 | 0 | } |
140 | 0 | } else { |
141 | 0 | sub2rev(&self.data, &mut other.data); |
142 | 0 | } |
143 | 0 | other.data.normalize(); |
144 | 0 | other |
145 | 0 | } |
146 | | } |
147 | | |
148 | | promote_unsigned_scalars!(impl Sub for BigUint, sub); |
149 | | promote_unsigned_scalars_assign!(impl SubAssign for BigUint, sub_assign); |
150 | | forward_all_scalar_binop_to_val_val!(impl Sub<u32> for BigUint, sub); |
151 | | forward_all_scalar_binop_to_val_val!(impl Sub<u64> for BigUint, sub); |
152 | | forward_all_scalar_binop_to_val_val!(impl Sub<u128> for BigUint, sub); |
153 | | |
154 | | impl Sub<u32> for BigUint { |
155 | | type Output = BigUint; |
156 | | |
157 | | #[inline] |
158 | 0 | fn sub(mut self, other: u32) -> BigUint { |
159 | 0 | self -= other; |
160 | 0 | self |
161 | 0 | } |
162 | | } |
163 | | |
164 | | impl SubAssign<u32> for BigUint { |
165 | 0 | fn sub_assign(&mut self, other: u32) { |
166 | 0 | sub2(&mut self.data, &[other as BigDigit]); |
167 | 0 | self.data.normalize(); |
168 | 0 | } |
169 | | } |
170 | | |
171 | | impl 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 | 0 | fn sub(self, mut other: BigUint) -> BigUint { |
188 | 0 | if other.data.is_empty() { |
189 | 0 | other.data.push(self as BigDigit); |
190 | 0 | } else { |
191 | 0 | sub2rev(&[self as BigDigit], &mut other.data); |
192 | 0 | } |
193 | 0 | other.data.normalize(); |
194 | 0 | other |
195 | 0 | } |
196 | | ); |
197 | | } |
198 | | |
199 | | impl Sub<u64> for BigUint { |
200 | | type Output = BigUint; |
201 | | |
202 | | #[inline] |
203 | 0 | fn sub(mut self, other: u64) -> BigUint { |
204 | 0 | self -= other; |
205 | 0 | self |
206 | 0 | } |
207 | | } |
208 | | |
209 | | impl 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 | 0 | fn sub_assign(&mut self, other: u64) { |
220 | 0 | sub2(&mut self.data, &[other as BigDigit]); |
221 | 0 | self.data.normalize(); |
222 | 0 | } |
223 | | ); |
224 | | } |
225 | | |
226 | | impl 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 | 0 | fn sub(self, mut other: BigUint) -> BigUint { |
244 | 0 | if other.data.is_empty() { |
245 | 0 | other.data.push(self); |
246 | 0 | } else { |
247 | 0 | sub2rev(&[self], &mut other.data); |
248 | 0 | } |
249 | 0 | other.data.normalize(); |
250 | 0 | other |
251 | 0 | } |
252 | | ); |
253 | | } |
254 | | |
255 | | impl Sub<u128> for BigUint { |
256 | | type Output = BigUint; |
257 | | |
258 | | #[inline] |
259 | 0 | fn sub(mut self, other: u128) -> BigUint { |
260 | 0 | self -= other; |
261 | 0 | self |
262 | 0 | } |
263 | | } |
264 | | |
265 | | impl 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 | 0 | fn sub_assign(&mut self, other: u128) { |
276 | 0 | let (hi, lo) = big_digit::from_doublebigdigit(other); |
277 | 0 | sub2(&mut self.data, &[lo, hi]); |
278 | 0 | self.data.normalize(); |
279 | 0 | } |
280 | | ); |
281 | | } |
282 | | |
283 | | impl 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 | 0 | fn sub(self, mut other: BigUint) -> BigUint { |
301 | 0 | while other.data.len() < 2 { |
302 | 0 | other.data.push(0); |
303 | 0 | } |
304 | | |
305 | 0 | let (hi, lo) = big_digit::from_doublebigdigit(self); |
306 | 0 | sub2rev(&[lo, hi], &mut other.data); |
307 | 0 | other.data.normalize(); |
308 | 0 | other |
309 | 0 | } |
310 | | ); |
311 | | } |
312 | | |
313 | | impl CheckedSub for BigUint { |
314 | | #[inline] |
315 | 0 | fn checked_sub(&self, v: &BigUint) -> Option<BigUint> { |
316 | 0 | match self.cmp(v) { |
317 | 0 | Less => None, |
318 | 0 | Equal => Some(Self::ZERO), |
319 | 0 | Greater => Some(self.sub(v)), |
320 | | } |
321 | 0 | } |
322 | | } |