Coverage Report

Created: 2025-07-23 07:29

/rust/registry/src/index.crates.io-6f17d22bba15001f/num-bigint-0.4.6/src/bigint/bits.rs
Line
Count
Source (jump to first uncovered line)
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
7
use alloc::vec::Vec;
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]
29
0
fn negate_carry(a: BigDigit, acc: &mut DoubleBigDigit) -> BigDigit {
30
0
    *acc += DoubleBigDigit::from(!a);
31
0
    let lo = *acc as BigDigit;
32
0
    *acc >>= big_digit::BITS;
33
0
    lo
34
0
}
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
39
0
fn bitand_pos_neg(a: &mut [BigDigit], b: &[BigDigit]) {
40
0
    let mut carry_b = 1;
41
0
    for (ai, &bi) in a.iter_mut().zip(b.iter()) {
42
0
        let twos_b = negate_carry(bi, &mut carry_b);
43
0
        *ai &= twos_b;
44
0
    }
45
0
    debug_assert!(b.len() > a.len() || carry_b == 0);
46
0
}
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
51
0
fn bitand_neg_pos(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
52
0
    let mut carry_a = 1;
53
0
    for (ai, &bi) in a.iter_mut().zip(b.iter()) {
54
0
        let twos_a = negate_carry(*ai, &mut carry_a);
55
0
        *ai = twos_a & bi;
56
0
    }
57
0
    debug_assert!(a.len() > b.len() || carry_a == 0);
58
0
    match Ord::cmp(&a.len(), &b.len()) {
59
0
        Greater => a.truncate(b.len()),
60
0
        Equal => {}
61
0
        Less => {
62
0
            let extra = &b[a.len()..];
63
0
            a.extend(extra.iter().cloned());
64
0
        }
65
    }
66
0
}
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
72
0
fn bitand_neg_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
73
0
    let mut carry_a = 1;
74
0
    let mut carry_b = 1;
75
0
    let mut carry_and = 1;
76
0
    for (ai, &bi) in a.iter_mut().zip(b.iter()) {
77
0
        let twos_a = negate_carry(*ai, &mut carry_a);
78
0
        let twos_b = negate_carry(bi, &mut carry_b);
79
0
        *ai = negate_carry(twos_a & twos_b, &mut carry_and);
80
0
    }
81
0
    debug_assert!(a.len() > b.len() || carry_a == 0);
82
0
    debug_assert!(b.len() > a.len() || carry_b == 0);
83
0
    match Ord::cmp(&a.len(), &b.len()) {
84
        Greater => {
85
0
            for ai in a[b.len()..].iter_mut() {
86
0
                let twos_a = negate_carry(*ai, &mut carry_a);
87
0
                *ai = negate_carry(twos_a, &mut carry_and);
88
0
            }
89
0
            debug_assert!(carry_a == 0);
90
        }
91
0
        Equal => {}
92
        Less => {
93
0
            let extra = &b[a.len()..];
94
0
            a.extend(extra.iter().map(|&bi| {
95
0
                let twos_b = negate_carry(bi, &mut carry_b);
96
0
                negate_carry(twos_b, &mut carry_and)
97
0
            }));
98
0
            debug_assert!(carry_b == 0);
99
        }
100
    }
101
0
    if carry_and != 0 {
102
0
        a.push(1);
103
0
    }
104
0
}
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 BitAnd<&BigInt> for &BigInt {
112
    type Output = BigInt;
113
114
    #[inline]
115
0
    fn bitand(self, other: &BigInt) -> BigInt {
116
0
        match (self.sign, other.sign) {
117
0
            (NoSign, _) | (_, NoSign) => BigInt::ZERO,
118
0
            (Plus, Plus) => BigInt::from(&self.data & &other.data),
119
0
            (Plus, Minus) => self.clone() & other,
120
0
            (Minus, Plus) => other.clone() & self,
121
            (Minus, Minus) => {
122
                // forward to val-ref, choosing the larger to clone
123
0
                if self.len() >= other.len() {
124
0
                    self.clone() & other
125
                } else {
126
0
                    other.clone() & self
127
                }
128
            }
129
        }
130
0
    }
131
}
132
133
impl BitAnd<&BigInt> for BigInt {
134
    type Output = BigInt;
135
136
    #[inline]
137
0
    fn bitand(mut self, other: &BigInt) -> BigInt {
138
0
        self &= other;
139
0
        self
140
0
    }
141
}
142
143
forward_val_assign!(impl BitAndAssign for BigInt, bitand_assign);
144
145
impl BitAndAssign<&BigInt> for BigInt {
146
0
    fn bitand_assign(&mut self, other: &BigInt) {
147
0
        match (self.sign, other.sign) {
148
0
            (NoSign, _) => {}
149
0
            (_, NoSign) => self.set_zero(),
150
            (Plus, Plus) => {
151
0
                self.data &= &other.data;
152
0
                if self.data.is_zero() {
153
0
                    self.sign = NoSign;
154
0
                }
155
            }
156
0
            (Plus, Minus) => {
157
0
                bitand_pos_neg(self.digits_mut(), other.digits());
158
0
                self.normalize();
159
0
            }
160
0
            (Minus, Plus) => {
161
0
                bitand_neg_pos(self.digits_mut(), other.digits());
162
0
                self.sign = Plus;
163
0
                self.normalize();
164
0
            }
165
0
            (Minus, Minus) => {
166
0
                bitand_neg_neg(self.digits_mut(), other.digits());
167
0
                self.normalize();
168
0
            }
169
        }
170
0
    }
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
176
0
fn bitor_pos_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
177
0
    let mut carry_b = 1;
178
0
    let mut carry_or = 1;
179
0
    for (ai, &bi) in a.iter_mut().zip(b.iter()) {
180
0
        let twos_b = negate_carry(bi, &mut carry_b);
181
0
        *ai = negate_carry(*ai | twos_b, &mut carry_or);
182
0
    }
183
0
    debug_assert!(b.len() > a.len() || carry_b == 0);
184
0
    match Ord::cmp(&a.len(), &b.len()) {
185
0
        Greater => {
186
0
            a.truncate(b.len());
187
0
        }
188
0
        Equal => {}
189
        Less => {
190
0
            let extra = &b[a.len()..];
191
0
            a.extend(extra.iter().map(|&bi| {
192
0
                let twos_b = negate_carry(bi, &mut carry_b);
193
0
                negate_carry(twos_b, &mut carry_or)
194
0
            }));
195
0
            debug_assert!(carry_b == 0);
196
        }
197
    }
198
    // for carry_or to be non-zero, we would need twos_b == 0
199
0
    debug_assert!(carry_or == 0);
200
0
}
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
205
0
fn bitor_neg_pos(a: &mut [BigDigit], b: &[BigDigit]) {
206
0
    let mut carry_a = 1;
207
0
    let mut carry_or = 1;
208
0
    for (ai, &bi) in a.iter_mut().zip(b.iter()) {
209
0
        let twos_a = negate_carry(*ai, &mut carry_a);
210
0
        *ai = negate_carry(twos_a | bi, &mut carry_or);
211
0
    }
212
0
    debug_assert!(a.len() > b.len() || carry_a == 0);
213
0
    if a.len() > b.len() {
214
0
        for ai in a[b.len()..].iter_mut() {
215
0
            let twos_a = negate_carry(*ai, &mut carry_a);
216
0
            *ai = negate_carry(twos_a, &mut carry_or);
217
0
        }
218
0
        debug_assert!(carry_a == 0);
219
0
    }
220
    // for carry_or to be non-zero, we would need twos_a == 0
221
0
    debug_assert!(carry_or == 0);
222
0
}
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
227
0
fn bitor_neg_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
228
0
    let mut carry_a = 1;
229
0
    let mut carry_b = 1;
230
0
    let mut carry_or = 1;
231
0
    for (ai, &bi) in a.iter_mut().zip(b.iter()) {
232
0
        let twos_a = negate_carry(*ai, &mut carry_a);
233
0
        let twos_b = negate_carry(bi, &mut carry_b);
234
0
        *ai = negate_carry(twos_a | twos_b, &mut carry_or);
235
0
    }
236
0
    debug_assert!(a.len() > b.len() || carry_a == 0);
237
0
    debug_assert!(b.len() > a.len() || carry_b == 0);
238
0
    if a.len() > b.len() {
239
0
        a.truncate(b.len());
240
0
    }
241
    // for carry_or to be non-zero, we would need twos_a == 0 or twos_b == 0
242
0
    debug_assert!(carry_or == 0);
243
0
}
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 BitOr<&BigInt> for &BigInt {
251
    type Output = BigInt;
252
253
    #[inline]
254
0
    fn bitor(self, other: &BigInt) -> BigInt {
255
0
        match (self.sign, other.sign) {
256
0
            (NoSign, _) => other.clone(),
257
0
            (_, NoSign) => self.clone(),
258
0
            (Plus, Plus) => BigInt::from(&self.data | &other.data),
259
0
            (Plus, Minus) => other.clone() | self,
260
0
            (Minus, Plus) => self.clone() | other,
261
            (Minus, Minus) => {
262
                // forward to val-ref, choosing the smaller to clone
263
0
                if self.len() <= other.len() {
264
0
                    self.clone() | other
265
                } else {
266
0
                    other.clone() | self
267
                }
268
            }
269
        }
270
0
    }
271
}
272
273
impl BitOr<&BigInt> for BigInt {
274
    type Output = BigInt;
275
276
    #[inline]
277
0
    fn bitor(mut self, other: &BigInt) -> BigInt {
278
0
        self |= other;
279
0
        self
280
0
    }
281
}
282
283
forward_val_assign!(impl BitOrAssign for BigInt, bitor_assign);
284
285
impl BitOrAssign<&BigInt> for BigInt {
286
0
    fn bitor_assign(&mut self, other: &BigInt) {
287
0
        match (self.sign, other.sign) {
288
0
            (_, NoSign) => {}
289
0
            (NoSign, _) => self.clone_from(other),
290
0
            (Plus, Plus) => self.data |= &other.data,
291
0
            (Plus, Minus) => {
292
0
                bitor_pos_neg(self.digits_mut(), other.digits());
293
0
                self.sign = Minus;
294
0
                self.normalize();
295
0
            }
296
0
            (Minus, Plus) => {
297
0
                bitor_neg_pos(self.digits_mut(), other.digits());
298
0
                self.normalize();
299
0
            }
300
0
            (Minus, Minus) => {
301
0
                bitor_neg_neg(self.digits_mut(), other.digits());
302
0
                self.normalize();
303
0
            }
304
        }
305
0
    }
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
311
0
fn bitxor_pos_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
312
0
    let mut carry_b = 1;
313
0
    let mut carry_xor = 1;
314
0
    for (ai, &bi) in a.iter_mut().zip(b.iter()) {
315
0
        let twos_b = negate_carry(bi, &mut carry_b);
316
0
        *ai = negate_carry(*ai ^ twos_b, &mut carry_xor);
317
0
    }
318
0
    debug_assert!(b.len() > a.len() || carry_b == 0);
319
0
    match Ord::cmp(&a.len(), &b.len()) {
320
        Greater => {
321
0
            for ai in a[b.len()..].iter_mut() {
322
0
                let twos_b = !0;
323
0
                *ai = negate_carry(*ai ^ twos_b, &mut carry_xor);
324
0
            }
325
        }
326
0
        Equal => {}
327
        Less => {
328
0
            let extra = &b[a.len()..];
329
0
            a.extend(extra.iter().map(|&bi| {
330
0
                let twos_b = negate_carry(bi, &mut carry_b);
331
0
                negate_carry(twos_b, &mut carry_xor)
332
0
            }));
333
0
            debug_assert!(carry_b == 0);
334
        }
335
    }
336
0
    if carry_xor != 0 {
337
0
        a.push(1);
338
0
    }
339
0
}
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
344
0
fn bitxor_neg_pos(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
345
0
    let mut carry_a = 1;
346
0
    let mut carry_xor = 1;
347
0
    for (ai, &bi) in a.iter_mut().zip(b.iter()) {
348
0
        let twos_a = negate_carry(*ai, &mut carry_a);
349
0
        *ai = negate_carry(twos_a ^ bi, &mut carry_xor);
350
0
    }
351
0
    debug_assert!(a.len() > b.len() || carry_a == 0);
352
0
    match Ord::cmp(&a.len(), &b.len()) {
353
        Greater => {
354
0
            for ai in a[b.len()..].iter_mut() {
355
0
                let twos_a = negate_carry(*ai, &mut carry_a);
356
0
                *ai = negate_carry(twos_a, &mut carry_xor);
357
0
            }
358
0
            debug_assert!(carry_a == 0);
359
        }
360
0
        Equal => {}
361
0
        Less => {
362
0
            let extra = &b[a.len()..];
363
0
            a.extend(extra.iter().map(|&bi| {
364
0
                let twos_a = !0;
365
0
                negate_carry(twos_a ^ bi, &mut carry_xor)
366
0
            }));
367
0
        }
368
    }
369
0
    if carry_xor != 0 {
370
0
        a.push(1);
371
0
    }
372
0
}
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
377
0
fn bitxor_neg_neg(a: &mut Vec<BigDigit>, b: &[BigDigit]) {
378
0
    let mut carry_a = 1;
379
0
    let mut carry_b = 1;
380
0
    for (ai, &bi) in a.iter_mut().zip(b.iter()) {
381
0
        let twos_a = negate_carry(*ai, &mut carry_a);
382
0
        let twos_b = negate_carry(bi, &mut carry_b);
383
0
        *ai = twos_a ^ twos_b;
384
0
    }
385
0
    debug_assert!(a.len() > b.len() || carry_a == 0);
386
0
    debug_assert!(b.len() > a.len() || carry_b == 0);
387
0
    match Ord::cmp(&a.len(), &b.len()) {
388
        Greater => {
389
0
            for ai in a[b.len()..].iter_mut() {
390
0
                let twos_a = negate_carry(*ai, &mut carry_a);
391
0
                let twos_b = !0;
392
0
                *ai = twos_a ^ twos_b;
393
0
            }
394
0
            debug_assert!(carry_a == 0);
395
        }
396
0
        Equal => {}
397
        Less => {
398
0
            let extra = &b[a.len()..];
399
0
            a.extend(extra.iter().map(|&bi| {
400
0
                let twos_a = !0;
401
0
                let twos_b = negate_carry(bi, &mut carry_b);
402
0
                twos_a ^ twos_b
403
0
            }));
404
0
            debug_assert!(carry_b == 0);
405
        }
406
    }
407
0
}
408
409
forward_all_binop_to_val_ref_commutative!(impl BitXor for BigInt, bitxor);
410
411
impl BitXor<&BigInt> for BigInt {
412
    type Output = BigInt;
413
414
    #[inline]
415
0
    fn bitxor(mut self, other: &BigInt) -> BigInt {
416
0
        self ^= other;
417
0
        self
418
0
    }
419
}
420
421
forward_val_assign!(impl BitXorAssign for BigInt, bitxor_assign);
422
423
impl BitXorAssign<&BigInt> for BigInt {
424
0
    fn bitxor_assign(&mut self, other: &BigInt) {
425
0
        match (self.sign, other.sign) {
426
0
            (_, NoSign) => {}
427
0
            (NoSign, _) => self.clone_from(other),
428
            (Plus, Plus) => {
429
0
                self.data ^= &other.data;
430
0
                if self.data.is_zero() {
431
0
                    self.sign = NoSign;
432
0
                }
433
            }
434
0
            (Plus, Minus) => {
435
0
                bitxor_pos_neg(self.digits_mut(), other.digits());
436
0
                self.sign = Minus;
437
0
                self.normalize();
438
0
            }
439
0
            (Minus, Plus) => {
440
0
                bitxor_neg_pos(self.digits_mut(), other.digits());
441
0
                self.normalize();
442
0
            }
443
0
            (Minus, Minus) => {
444
0
                bitxor_neg_neg(self.digits_mut(), other.digits());
445
0
                self.sign = Plus;
446
0
                self.normalize();
447
0
            }
448
        }
449
0
    }
450
}
451
452
0
pub(super) fn set_negative_bit(x: &mut BigInt, bit: u64, value: bool) {
453
0
    debug_assert_eq!(x.sign, Minus);
454
0
    let data = &mut x.data;
455
0
456
0
    let bits_per_digit = u64::from(big_digit::BITS);
457
0
    if bit >= bits_per_digit * data.len() as u64 {
458
0
        if !value {
459
0
            data.set_bit(bit, true);
460
0
        }
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
0
        let trailing_zeros = data.trailing_zeros().unwrap();
469
0
        if bit > trailing_zeros {
470
0
            data.set_bit(bit, !value);
471
0
        } 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
0
            let bit_index = (bit / bits_per_digit).to_usize().unwrap();
478
0
            let bit_mask = (1 as BigDigit) << (bit % bits_per_digit);
479
0
            let mut digit_iter = data.digits_mut().iter_mut().skip(bit_index);
480
0
            let mut carry_in = 1;
481
0
            let mut carry_out = 1;
482
0
483
0
            let digit = digit_iter.next().unwrap();
484
0
            let twos_in = negate_carry(*digit, &mut carry_in);
485
0
            let twos_out = twos_in & !bit_mask;
486
0
            *digit = negate_carry(twos_out, &mut carry_out);
487
488
0
            for digit in digit_iter {
489
0
                if carry_in == 0 && carry_out == 0 {
490
                    // Exit the loop since no more digits can change
491
0
                    break;
492
0
                }
493
0
                let twos = negate_carry(*digit, &mut carry_in);
494
0
                *digit = negate_carry(twos, &mut carry_out);
495
            }
496
497
0
            if carry_out != 0 {
498
                // All digits have been traversed and there is a carry
499
0
                debug_assert_eq!(carry_in, 0);
500
0
                data.digits_mut().push(1);
501
0
            }
502
0
        } 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
0
            let index_lo = (bit / bits_per_digit).to_usize().unwrap();
510
0
            let index_hi = (trailing_zeros / bits_per_digit).to_usize().unwrap();
511
0
            let bit_mask_lo = big_digit::MAX << (bit % bits_per_digit);
512
0
            let bit_mask_hi =
513
0
                big_digit::MAX >> (bits_per_digit - 1 - (trailing_zeros % bits_per_digit));
514
0
            let digits = data.digits_mut();
515
0
516
0
            if index_lo == index_hi {
517
0
                digits[index_lo] ^= bit_mask_lo & bit_mask_hi;
518
0
            } else {
519
0
                digits[index_lo] = bit_mask_lo;
520
0
                for digit in &mut digits[index_lo + 1..index_hi] {
521
0
                    *digit = big_digit::MAX;
522
0
                }
523
0
                digits[index_hi] ^= bit_mask_hi;
524
            }
525
0
        } else {
526
0
            // We end up here in two cases:
527
0
            //   bit == trailing_zeros && value: Bit is already set
528
0
            //   bit < trailing_zeros && !value: Bit is already cleared
529
0
        }
530
    }
531
0
}