Coverage Report

Created: 2026-08-14 08:22

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