Skip to main content

num_bigint/bigint/
bits.rs

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