/rust/registry/src/index.crates.io-6f17d22bba15001f/num-bigint-0.4.6/src/biguint/subtraction.rs
Line | Count | Source (jump to first uncovered line) |
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 | 0 | fn sbb(borrow: u8, a: u64, b: u64, out: &mut u64) -> u8 { |
21 | 0 | // Safety: There are absolutely no safety concerns with calling `_subborrow_u64`. |
22 | 0 | // It's just unsafe for API consistency with other intrinsics. |
23 | 0 | unsafe { arch::_subborrow_u64(borrow, a, b, out) } |
24 | 0 | } |
25 | | ); |
26 | | |
27 | | #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] |
28 | | cfg_32!( |
29 | | #[inline] |
30 | | fn sbb(borrow: u8, a: u32, b: u32, out: &mut u32) -> u8 { |
31 | | // Safety: There are absolutely no safety concerns with calling `_subborrow_u32`. |
32 | | // It's just unsafe for API consistency with other intrinsics. |
33 | | unsafe { arch::_subborrow_u32(borrow, a, b, out) } |
34 | | } |
35 | | ); |
36 | | |
37 | | // fallback for environments where we don't have a subborrow intrinsic |
38 | | // (copied from the standard library's `borrowing_sub`) |
39 | | #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] |
40 | | #[inline] |
41 | | fn 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 | | |
48 | 0 | pub(super) fn sub2(a: &mut [BigDigit], b: &[BigDigit]) { |
49 | 0 | let mut borrow = 0; |
50 | 0 |
|
51 | 0 | let len = Ord::min(a.len(), b.len()); |
52 | 0 | let (a_lo, a_hi) = a.split_at_mut(len); |
53 | 0 | let (b_lo, b_hi) = b.split_at(len); |
54 | | |
55 | 0 | for (a, b) in a_lo.iter_mut().zip(b_lo) { |
56 | 0 | borrow = sbb(borrow, *a, *b, a); |
57 | 0 | } |
58 | | |
59 | 0 | if borrow != 0 { |
60 | 0 | for a in a_hi { |
61 | 0 | borrow = sbb(borrow, *a, 0, a); |
62 | 0 | if borrow == 0 { |
63 | 0 | break; |
64 | 0 | } |
65 | | } |
66 | 0 | } |
67 | | |
68 | | // note: we're _required_ to fail on underflow |
69 | 0 | assert!( |
70 | 0 | borrow == 0 && b_hi.iter().all(|x| *x == 0), |
71 | 0 | "Cannot subtract b from a because b is larger than a." |
72 | | ); |
73 | 0 | } |
74 | | |
75 | | // Only for the Sub impl. `a` and `b` must have same length. |
76 | | #[inline] |
77 | 0 | fn __sub2rev(a: &[BigDigit], b: &mut [BigDigit]) -> u8 { |
78 | 0 | debug_assert!(b.len() == a.len()); |
79 | | |
80 | 0 | let mut borrow = 0; |
81 | | |
82 | 0 | for (ai, bi) in a.iter().zip(b) { |
83 | 0 | borrow = sbb(borrow, *ai, *bi, bi); |
84 | 0 | } |
85 | | |
86 | 0 | borrow |
87 | 0 | } |
88 | | |
89 | 0 | fn sub2rev(a: &[BigDigit], b: &mut [BigDigit]) { |
90 | 0 | debug_assert!(b.len() >= a.len()); |
91 | | |
92 | 0 | let len = Ord::min(a.len(), b.len()); |
93 | 0 | let (a_lo, a_hi) = a.split_at(len); |
94 | 0 | let (b_lo, b_hi) = b.split_at_mut(len); |
95 | 0 |
|
96 | 0 | let borrow = __sub2rev(a_lo, b_lo); |
97 | 0 |
|
98 | 0 | assert!(a_hi.is_empty()); |
99 | | |
100 | | // note: we're _required_ to fail on underflow |
101 | 0 | assert!( |
102 | 0 | borrow == 0 && b_hi.iter().all(|x| *x == 0), |
103 | 0 | "Cannot subtract b from a because b is larger than a." |
104 | | ); |
105 | 0 | } |
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 | | |
114 | 0 | fn sub(mut self, other: &BigUint) -> BigUint { |
115 | 0 | self -= other; |
116 | 0 | self |
117 | 0 | } |
118 | | } |
119 | | impl SubAssign<&BigUint> for BigUint { |
120 | 0 | fn sub_assign(&mut self, other: &BigUint) { |
121 | 0 | sub2(&mut self.data[..], &other.data[..]); |
122 | 0 | self.normalize(); |
123 | 0 | } |
124 | | } |
125 | | |
126 | | impl Sub<BigUint> for &BigUint { |
127 | | type Output = BigUint; |
128 | | |
129 | 0 | fn sub(self, mut other: BigUint) -> BigUint { |
130 | 0 | let other_len = other.data.len(); |
131 | 0 | if other_len < self.data.len() { |
132 | 0 | let lo_borrow = __sub2rev(&self.data[..other_len], &mut other.data); |
133 | 0 | other.data.extend_from_slice(&self.data[other_len..]); |
134 | 0 | if lo_borrow != 0 { |
135 | 0 | sub2(&mut other.data[other_len..], &[1]) |
136 | 0 | } |
137 | 0 | } else { |
138 | 0 | sub2rev(&self.data[..], &mut other.data[..]); |
139 | 0 | } |
140 | 0 | other.normalized() |
141 | 0 | } |
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] |
154 | 0 | fn sub(mut self, other: u32) -> BigUint { |
155 | 0 | self -= other; |
156 | 0 | self |
157 | 0 | } |
158 | | } |
159 | | |
160 | | impl SubAssign<u32> for BigUint { |
161 | 0 | fn sub_assign(&mut self, other: u32) { |
162 | 0 | sub2(&mut self.data[..], &[other as BigDigit]); |
163 | 0 | self.normalize(); |
164 | 0 | } |
165 | | } |
166 | | |
167 | | impl 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 | 0 | fn sub(self, mut other: BigUint) -> BigUint { |
183 | 0 | if other.data.is_empty() { |
184 | 0 | other.data.push(self as BigDigit); |
185 | 0 | } else { |
186 | 0 | sub2rev(&[self as BigDigit], &mut other.data[..]); |
187 | 0 | } |
188 | 0 | other.normalized() |
189 | 0 | } |
190 | | ); |
191 | | } |
192 | | |
193 | | impl Sub<u64> for BigUint { |
194 | | type Output = BigUint; |
195 | | |
196 | | #[inline] |
197 | 0 | fn sub(mut self, other: u64) -> BigUint { |
198 | 0 | self -= other; |
199 | 0 | self |
200 | 0 | } |
201 | | } |
202 | | |
203 | | impl 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 | 0 | fn sub_assign(&mut self, other: u64) { |
214 | 0 | sub2(&mut self.data[..], &[other as BigDigit]); |
215 | 0 | self.normalize(); |
216 | 0 | } |
217 | | ); |
218 | | } |
219 | | |
220 | | impl 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 | 0 | fn sub(self, mut other: BigUint) -> BigUint { |
237 | 0 | if other.data.is_empty() { |
238 | 0 | other.data.push(self); |
239 | 0 | } else { |
240 | 0 | sub2rev(&[self], &mut other.data[..]); |
241 | 0 | } |
242 | 0 | other.normalized() |
243 | 0 | } |
244 | | ); |
245 | | } |
246 | | |
247 | | impl Sub<u128> for BigUint { |
248 | | type Output = BigUint; |
249 | | |
250 | | #[inline] |
251 | 0 | fn sub(mut self, other: u128) -> BigUint { |
252 | 0 | self -= other; |
253 | 0 | self |
254 | 0 | } |
255 | | } |
256 | | |
257 | | impl 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 | 0 | fn sub_assign(&mut self, other: u128) { |
268 | 0 | let (hi, lo) = big_digit::from_doublebigdigit(other); |
269 | 0 | sub2(&mut self.data[..], &[lo, hi]); |
270 | 0 | self.normalize(); |
271 | 0 | } |
272 | | ); |
273 | | } |
274 | | |
275 | | impl 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 | 0 | fn sub(self, mut other: BigUint) -> BigUint { |
292 | 0 | while other.data.len() < 2 { |
293 | 0 | other.data.push(0); |
294 | 0 | } |
295 | | |
296 | 0 | let (hi, lo) = big_digit::from_doublebigdigit(self); |
297 | 0 | sub2rev(&[lo, hi], &mut other.data[..]); |
298 | 0 | other.normalized() |
299 | 0 | } |
300 | | ); |
301 | | } |
302 | | |
303 | | impl CheckedSub for BigUint { |
304 | | #[inline] |
305 | 0 | fn checked_sub(&self, v: &BigUint) -> Option<BigUint> { |
306 | 0 | match self.cmp(v) { |
307 | 0 | Less => None, |
308 | 0 | Equal => Some(Self::ZERO), |
309 | 0 | Greater => Some(self.sub(v)), |
310 | | } |
311 | 0 | } |
312 | | } |