1 use super::BigInt;
2 use super::Sign::{Minus, NoSign, Plus};
3
4 use crate::big_digit::{self, BigDigit, DoubleBigDigit};
5 use crate::biguint::IntDigits;
6 use crate::std_alloc::Vec;
7
8 use core::cmp::Ordering::{Equal, Greater, Less};
9 use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign};
10 use num_traits::{ToPrimitive, Zero};
11
12 // Negation in two's complement.
13 // acc must be initialized as 1 for least-significant digit.
14 //
15 // When negating, a carry (acc == 1) means that all the digits
16 // considered to this point were zero. This means that if all the
17 // digits of a negative BigInt have been considered, carry must be
18 // zero as we cannot have negative zero.
19 //
20 // 01 -> ...f ff
21 // ff -> ...f 01
22 // 01 00 -> ...f ff 00
23 // 01 01 -> ...f fe ff
24 // 01 ff -> ...f fe 01
25 // ff 00 -> ...f 01 00
26 // ff 01 -> ...f 00 ff
27 // ff ff -> ...f 00 01
28 #[inline]
negate_carry(a: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit29 fn negate_carry(a: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit {
30 *acc += DoubleBigDigit::from(!a);
31 let lo = *acc as BigDigit;
32 *acc >>= big_digit::BITS;
33 lo
34 }
35
36 // + 1 & -ff = ...0 01 & ...f 01 = ...0 01 = + 1
37 // +ff & - 1 = ...0 ff & ...f ff = ...0 ff = +ff
38 // answer is pos, has length of a
bitand_pos_neg(a: &mut Vec<BigDigit>, b: &[BigDigit])39 fn bitand_pos_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
40 let mut carry_b = 1;
41 for (ai, &bi) in a.iter_mut().zip(b.iter()) {
42 let twos_b = negate_carry(bi, &mut carry_b);
43 *ai &= twos_b;
44 }
45 debug_assert!(b.len() > a.len() || carry_b == 0);
46 }
47
48 // - 1 & +ff = ...f ff & ...0 ff = ...0 ff = +ff
49 // -ff & + 1 = ...f 01 & ...0 01 = ...0 01 = + 1
50 // answer is pos, has length of b
bitand_neg_pos(a: &mut Vec<BigDigit>, b: &[BigDigit])51 fn bitand_neg_pos(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
52 let mut carry_a = 1;
53 for (ai, &bi) in a.iter_mut().zip(b.iter()) {
54 let twos_a = negate_carry(*ai, &mut carry_a);
55 *ai = twos_a & bi;
56 }
57 debug_assert!(a.len() > b.len() || carry_a == 0);
58 match Ord::cmp(&a.len(), &b.len()) {
59 Greater => a.truncate(b.len()),
60 Equal => {}
61 Less => {
62 let extra = &b[a.len()..];
63 a.extend(extra.iter().cloned());
64 }
65 }
66 }
67
68 // - 1 & -ff = ...f ff & ...f 01 = ...f 01 = - ff
69 // -ff & - 1 = ...f 01 & ...f ff = ...f 01 = - ff
70 // -ff & -fe = ...f 01 & ...f 02 = ...f 00 = -100
71 // answer is neg, has length of longest with a possible carry
bitand_neg_neg(a: &mut Vec<BigDigit>, b: &[BigDigit])72 fn bitand_neg_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
73 let mut carry_a = 1;
74 let mut carry_b = 1;
75 let mut carry_and = 1;
76 for (ai, &bi) in a.iter_mut().zip(b.iter()) {
77 let twos_a = negate_carry(*ai, &mut carry_a);
78 let twos_b = negate_carry(bi, &mut carry_b);
79 *ai = negate_carry(twos_a & twos_b, &mut carry_and);
80 }
81 debug_assert!(a.len() > b.len() || carry_a == 0);
82 debug_assert!(b.len() > a.len() || carry_b == 0);
83 match Ord::cmp(&a.len(), &b.len()) {
84 Greater => {
85 for ai in a[b.len()..].iter_mut() {
86 let twos_a = negate_carry(*ai, &mut carry_a);
87 *ai = negate_carry(twos_a, &mut carry_and);
88 }
89 debug_assert!(carry_a == 0);
90 }
91 Equal => {}
92 Less => {
93 let extra = &b[a.len()..];
94 a.extend(extra.iter().map(|&bi| {
95 let twos_b = negate_carry(bi, &mut carry_b);
96 negate_carry(twos_b, &mut carry_and)
97 }));
98 debug_assert!(carry_b == 0);
99 }
100 }
101 if carry_and != 0 {
102 a.push(1);
103 }
104 }
105
106 forward_val_val_binop!(impl BitAnd for BigInt, bitand);
107 forward_ref_val_binop!(impl BitAnd for BigInt, bitand);
108
109 // do not use forward_ref_ref_binop_commutative! for bitand so that we can
110 // clone as needed, avoiding over-allocation
111 impl<'a, 'b> BitAnd<&'b BigInt> for &'a BigInt {
112 type Output = BigInt;
113
114 #[inline]
bitand(self, other: &BigInt) -> BigInt115 fn bitand(self, other: &BigInt) -> BigInt {
116 match (self.sign, other.sign) {
117 (NoSign, _) | (_, NoSign) => BigInt::zero(),
118 (Plus, Plus) => BigInt::from(&self.data & &other.data),
119 (Plus, Minus) => self.clone() & other,
120 (Minus, Plus) => other.clone() & self,
121 (Minus, Minus) => {
122 // forward to val-ref, choosing the larger to clone
123 if self.len() >= other.len() {
124 self.clone() & other
125 } else {
126 other.clone() & self
127 }
128 }
129 }
130 }
131 }
132
133 impl<'a> BitAnd<&'a BigInt> for BigInt {
134 type Output = BigInt;
135
136 #[inline]
bitand(mut self, other: &BigInt) -> BigInt137 fn bitand(mut self, other: &BigInt) -> BigInt {
138 self &= other;
139 self
140 }
141 }
142
143 forward_val_assign!(impl BitAndAssign for BigInt, bitand_assign);
144
145 impl<'a> BitAndAssign<&'a BigInt> for BigInt {
bitand_assign(&mut self, other: &BigInt)146 fn bitand_assign(&mut self, other: &BigInt) {
147 match (self.sign, other.sign) {
148 (NoSign, _) => {}
149 (_, NoSign) => self.set_zero(),
150 (Plus, Plus) => {
151 self.data &= &other.data;
152 if self.data.is_zero() {
153 self.sign = NoSign;
154 }
155 }
156 (Plus, Minus) => {
157 bitand_pos_neg(self.digits_mut(), other.digits());
158 self.normalize();
159 }
160 (Minus, Plus) => {
161 bitand_neg_pos(self.digits_mut(), other.digits());
162 self.sign = Plus;
163 self.normalize();
164 }
165 (Minus, Minus) => {
166 bitand_neg_neg(self.digits_mut(), other.digits());
167 self.normalize();
168 }
169 }
170 }
171 }
172
173 // + 1 | -ff = ...0 01 | ...f 01 = ...f 01 = -ff
174 // +ff | - 1 = ...0 ff | ...f ff = ...f ff = - 1
175 // answer is neg, has length of b
bitor_pos_neg(a: &mut Vec<BigDigit>, b: &[BigDigit])176 fn bitor_pos_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
177 let mut carry_b = 1;
178 let mut carry_or = 1;
179 for (ai, &bi) in a.iter_mut().zip(b.iter()) {
180 let twos_b = negate_carry(bi, &mut carry_b);
181 *ai = negate_carry(*ai | twos_b, &mut carry_or);
182 }
183 debug_assert!(b.len() > a.len() || carry_b == 0);
184 match Ord::cmp(&a.len(), &b.len()) {
185 Greater => {
186 a.truncate(b.len());
187 }
188 Equal => {}
189 Less => {
190 let extra = &b[a.len()..];
191 a.extend(extra.iter().map(|&bi| {
192 let twos_b = negate_carry(bi, &mut carry_b);
193 negate_carry(twos_b, &mut carry_or)
194 }));
195 debug_assert!(carry_b == 0);
196 }
197 }
198 // for carry_or to be non-zero, we would need twos_b == 0
199 debug_assert!(carry_or == 0);
200 }
201
202 // - 1 | +ff = ...f ff | ...0 ff = ...f ff = - 1
203 // -ff | + 1 = ...f 01 | ...0 01 = ...f 01 = -ff
204 // answer is neg, has length of a
bitor_neg_pos(a: &mut Vec<BigDigit>, b: &[BigDigit])205 fn bitor_neg_pos(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
206 let mut carry_a = 1;
207 let mut carry_or = 1;
208 for (ai, &bi) in a.iter_mut().zip(b.iter()) {
209 let twos_a = negate_carry(*ai, &mut carry_a);
210 *ai = negate_carry(twos_a | bi, &mut carry_or);
211 }
212 debug_assert!(a.len() > b.len() || carry_a == 0);
213 if a.len() > b.len() {
214 for ai in a[b.len()..].iter_mut() {
215 let twos_a = negate_carry(*ai, &mut carry_a);
216 *ai = negate_carry(twos_a, &mut carry_or);
217 }
218 debug_assert!(carry_a == 0);
219 }
220 // for carry_or to be non-zero, we would need twos_a == 0
221 debug_assert!(carry_or == 0);
222 }
223
224 // - 1 | -ff = ...f ff | ...f 01 = ...f ff = -1
225 // -ff | - 1 = ...f 01 | ...f ff = ...f ff = -1
226 // answer is neg, has length of shortest
bitor_neg_neg(a: &mut Vec<BigDigit>, b: &[BigDigit])227 fn bitor_neg_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
228 let mut carry_a = 1;
229 let mut carry_b = 1;
230 let mut carry_or = 1;
231 for (ai, &bi) in a.iter_mut().zip(b.iter()) {
232 let twos_a = negate_carry(*ai, &mut carry_a);
233 let twos_b = negate_carry(bi, &mut carry_b);
234 *ai = negate_carry(twos_a | twos_b, &mut carry_or);
235 }
236 debug_assert!(a.len() > b.len() || carry_a == 0);
237 debug_assert!(b.len() > a.len() || carry_b == 0);
238 if a.len() > b.len() {
239 a.truncate(b.len());
240 }
241 // for carry_or to be non-zero, we would need twos_a == 0 or twos_b == 0
242 debug_assert!(carry_or == 0);
243 }
244
245 forward_val_val_binop!(impl BitOr for BigInt, bitor);
246 forward_ref_val_binop!(impl BitOr for BigInt, bitor);
247
248 // do not use forward_ref_ref_binop_commutative! for bitor so that we can
249 // clone as needed, avoiding over-allocation
250 impl<'a, 'b> BitOr<&'b BigInt> for &'a BigInt {
251 type Output = BigInt;
252
253 #[inline]
bitor(self, other: &BigInt) -> BigInt254 fn bitor(self, other: &BigInt) -> BigInt {
255 match (self.sign, other.sign) {
256 (NoSign, _) => other.clone(),
257 (_, NoSign) => self.clone(),
258 (Plus, Plus) => BigInt::from(&self.data | &other.data),
259 (Plus, Minus) => other.clone() | self,
260 (Minus, Plus) => self.clone() | other,
261 (Minus, Minus) => {
262 // forward to val-ref, choosing the smaller to clone
263 if self.len() <= other.len() {
264 self.clone() | other
265 } else {
266 other.clone() | self
267 }
268 }
269 }
270 }
271 }
272
273 impl<'a> BitOr<&'a BigInt> for BigInt {
274 type Output = BigInt;
275
276 #[inline]
bitor(mut self, other: &BigInt) -> BigInt277 fn bitor(mut self, other: &BigInt) -> BigInt {
278 self |= other;
279 self
280 }
281 }
282
283 forward_val_assign!(impl BitOrAssign for BigInt, bitor_assign);
284
285 impl<'a> BitOrAssign<&'a BigInt> for BigInt {
bitor_assign(&mut self, other: &BigInt)286 fn bitor_assign(&mut self, other: &BigInt) {
287 match (self.sign, other.sign) {
288 (_, NoSign) => {}
289 (NoSign, _) => self.clone_from(other),
290 (Plus, Plus) => self.data |= &other.data,
291 (Plus, Minus) => {
292 bitor_pos_neg(self.digits_mut(), other.digits());
293 self.sign = Minus;
294 self.normalize();
295 }
296 (Minus, Plus) => {
297 bitor_neg_pos(self.digits_mut(), other.digits());
298 self.normalize();
299 }
300 (Minus, Minus) => {
301 bitor_neg_neg(self.digits_mut(), other.digits());
302 self.normalize();
303 }
304 }
305 }
306 }
307
308 // + 1 ^ -ff = ...0 01 ^ ...f 01 = ...f 00 = -100
309 // +ff ^ - 1 = ...0 ff ^ ...f ff = ...f 00 = -100
310 // answer is neg, has length of longest with a possible carry
bitxor_pos_neg(a: &mut Vec<BigDigit>, b: &[BigDigit])311 fn bitxor_pos_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
312 let mut carry_b = 1;
313 let mut carry_xor = 1;
314 for (ai, &bi) in a.iter_mut().zip(b.iter()) {
315 let twos_b = negate_carry(bi, &mut carry_b);
316 *ai = negate_carry(*ai ^ twos_b, &mut carry_xor);
317 }
318 debug_assert!(b.len() > a.len() || carry_b == 0);
319 match Ord::cmp(&a.len(), &b.len()) {
320 Greater => {
321 for ai in a[b.len()..].iter_mut() {
322 let twos_b = !0;
323 *ai = negate_carry(*ai ^ twos_b, &mut carry_xor);
324 }
325 }
326 Equal => {}
327 Less => {
328 let extra = &b[a.len()..];
329 a.extend(extra.iter().map(|&bi| {
330 let twos_b = negate_carry(bi, &mut carry_b);
331 negate_carry(twos_b, &mut carry_xor)
332 }));
333 debug_assert!(carry_b == 0);
334 }
335 }
336 if carry_xor != 0 {
337 a.push(1);
338 }
339 }
340
341 // - 1 ^ +ff = ...f ff ^ ...0 ff = ...f 00 = -100
342 // -ff ^ + 1 = ...f 01 ^ ...0 01 = ...f 00 = -100
343 // answer is neg, has length of longest with a possible carry
bitxor_neg_pos(a: &mut Vec<BigDigit>, b: &[BigDigit])344 fn bitxor_neg_pos(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
345 let mut carry_a = 1;
346 let mut carry_xor = 1;
347 for (ai, &bi) in a.iter_mut().zip(b.iter()) {
348 let twos_a = negate_carry(*ai, &mut carry_a);
349 *ai = negate_carry(twos_a ^ bi, &mut carry_xor);
350 }
351 debug_assert!(a.len() > b.len() || carry_a == 0);
352 match Ord::cmp(&a.len(), &b.len()) {
353 Greater => {
354 for ai in a[b.len()..].iter_mut() {
355 let twos_a = negate_carry(*ai, &mut carry_a);
356 *ai = negate_carry(twos_a, &mut carry_xor);
357 }
358 debug_assert!(carry_a == 0);
359 }
360 Equal => {}
361 Less => {
362 let extra = &b[a.len()..];
363 a.extend(extra.iter().map(|&bi| {
364 let twos_a = !0;
365 negate_carry(twos_a ^ bi, &mut carry_xor)
366 }));
367 }
368 }
369 if carry_xor != 0 {
370 a.push(1);
371 }
372 }
373
374 // - 1 ^ -ff = ...f ff ^ ...f 01 = ...0 fe = +fe
375 // -ff & - 1 = ...f 01 ^ ...f ff = ...0 fe = +fe
376 // answer is pos, has length of longest
bitxor_neg_neg(a: &mut Vec<BigDigit>, b: &[BigDigit])377 fn bitxor_neg_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
378 let mut carry_a = 1;
379 let mut carry_b = 1;
380 for (ai, &bi) in a.iter_mut().zip(b.iter()) {
381 let twos_a = negate_carry(*ai, &mut carry_a);
382 let twos_b = negate_carry(bi, &mut carry_b);
383 *ai = twos_a ^ twos_b;
384 }
385 debug_assert!(a.len() > b.len() || carry_a == 0);
386 debug_assert!(b.len() > a.len() || carry_b == 0);
387 match Ord::cmp(&a.len(), &b.len()) {
388 Greater => {
389 for ai in a[b.len()..].iter_mut() {
390 let twos_a = negate_carry(*ai, &mut carry_a);
391 let twos_b = !0;
392 *ai = twos_a ^ twos_b;
393 }
394 debug_assert!(carry_a == 0);
395 }
396 Equal => {}
397 Less => {
398 let extra = &b[a.len()..];
399 a.extend(extra.iter().map(|&bi| {
400 let twos_a = !0;
401 let twos_b = negate_carry(bi, &mut carry_b);
402 twos_a ^ twos_b
403 }));
404 debug_assert!(carry_b == 0);
405 }
406 }
407 }
408
409 forward_all_binop_to_val_ref_commutative!(impl BitXor for BigInt, bitxor);
410
411 impl<'a> BitXor<&'a BigInt> for BigInt {
412 type Output = BigInt;
413
414 #[inline]
bitxor(mut self, other: &BigInt) -> BigInt415 fn bitxor(mut self, other: &BigInt) -> BigInt {
416 self ^= other;
417 self
418 }
419 }
420
421 forward_val_assign!(impl BitXorAssign for BigInt, bitxor_assign);
422
423 impl<'a> BitXorAssign<&'a BigInt> for BigInt {
bitxor_assign(&mut self, other: &BigInt)424 fn bitxor_assign(&mut self, other: &BigInt) {
425 match (self.sign, other.sign) {
426 (_, NoSign) => {}
427 (NoSign, _) => self.clone_from(other),
428 (Plus, Plus) => {
429 self.data ^= &other.data;
430 if self.data.is_zero() {
431 self.sign = NoSign;
432 }
433 }
434 (Plus, Minus) => {
435 bitxor_pos_neg(self.digits_mut(), other.digits());
436 self.sign = Minus;
437 self.normalize();
438 }
439 (Minus, Plus) => {
440 bitxor_neg_pos(self.digits_mut(), other.digits());
441 self.normalize();
442 }
443 (Minus, Minus) => {
444 bitxor_neg_neg(self.digits_mut(), other.digits());
445 self.sign = Plus;
446 self.normalize();
447 }
448 }
449 }
450 }
451
set_negative_bit(x: &mut BigInt, bit: u64, value: bool)452 pub(super) fn set_negative_bit(x: &mut BigInt, bit: u64, value: bool) {
453 debug_assert_eq!(x.sign, Minus);
454 let data = &mut x.data;
455
456 let bits_per_digit = u64::from(big_digit::BITS);
457 if bit >= bits_per_digit * data.len() as u64 {
458 if !value {
459 data.set_bit(bit, true);
460 }
461 } else {
462 // If the Uint number is
463 // ... 0 x 1 0 ... 0
464 // then the two's complement is
465 // ... 1 !x 1 0 ... 0
466 // |-- bit at position 'trailing_zeros'
467 // where !x is obtained from x by flipping each bit
468 let trailing_zeros = data.trailing_zeros().unwrap();
469 if bit > trailing_zeros {
470 data.set_bit(bit, !value);
471 } else if bit == trailing_zeros && !value {
472 // Clearing the bit at position `trailing_zeros` is dealt with by doing
473 // similarly to what `bitand_neg_pos` does, except we start at digit
474 // `bit_index`. All digits below `bit_index` are guaranteed to be zero,
475 // so initially we have `carry_in` = `carry_out` = 1. Furthermore, we
476 // stop traversing the digits when there are no more carries.
477 let bit_index = (bit / bits_per_digit).to_usize().unwrap();
478 let bit_mask = (1 as BigDigit) << (bit % bits_per_digit);
479 let mut digit_iter = data.digits_mut().iter_mut().skip(bit_index);
480 let mut carry_in = 1;
481 let mut carry_out = 1;
482
483 let digit = digit_iter.next().unwrap();
484 let twos_in = negate_carry(*digit, &mut carry_in);
485 let twos_out = twos_in & !bit_mask;
486 *digit = negate_carry(twos_out, &mut carry_out);
487
488 for digit in digit_iter {
489 if carry_in == 0 && carry_out == 0 {
490 // Exit the loop since no more digits can change
491 break;
492 }
493 let twos = negate_carry(*digit, &mut carry_in);
494 *digit = negate_carry(twos, &mut carry_out);
495 }
496
497 if carry_out != 0 {
498 // All digits have been traversed and there is a carry
499 debug_assert_eq!(carry_in, 0);
500 data.digits_mut().push(1);
501 }
502 } else if bit < trailing_zeros && value {
503 // Flip each bit from position 'bit' to 'trailing_zeros', both inclusive
504 // ... 1 !x 1 0 ... 0 ... 0
505 // |-- bit at position 'bit'
506 // |-- bit at position 'trailing_zeros'
507 // bit_mask: 1 1 ... 1 0 .. 0
508 // This is done by xor'ing with the bit_mask
509 let index_lo = (bit / bits_per_digit).to_usize().unwrap();
510 let index_hi = (trailing_zeros / bits_per_digit).to_usize().unwrap();
511 let bit_mask_lo = big_digit::MAX << (bit % bits_per_digit);
512 let bit_mask_hi =
513 big_digit::MAX >> (bits_per_digit - 1 - (trailing_zeros % bits_per_digit));
514 let digits = data.digits_mut();
515
516 if index_lo == index_hi {
517 digits[index_lo] ^= bit_mask_lo & bit_mask_hi;
518 } else {
519 digits[index_lo] = bit_mask_lo;
520 for index in (index_lo + 1)..index_hi {
521 digits[index] = big_digit::MAX;
522 }
523 digits[index_hi] ^= bit_mask_hi;
524 }
525 } else {
526 // We end up here in two cases:
527 // bit == trailing_zeros && value: Bit is already set
528 // bit < trailing_zeros && !value: Bit is already cleared
529 }
530 }
531 }
532