@@ -3306,75 +3306,66 @@ impl BigInt {
3306
3306
// |-- bit at position 'trailing_zeros'
3307
3307
// where !x is obtained from x by flipping each bit
3308
3308
let trailing_zeros = self . data . trailing_zeros ( ) . unwrap ( ) ;
3309
- match Ord :: cmp ( & bit, & trailing_zeros) {
3310
- Less => {
3311
- if value {
3312
- // We need to flip each bit from position 'bit' to 'trailing_zeros', both inclusive
3313
- // ... 1 !x 1 0 ... 0 ... 0
3314
- // |-- bit at position 'bit'
3315
- // |-- bit at position 'trailing_zeros'
3316
- // bit_mask: 1 1 ... 1 0 .. 0
3317
- // We do this by xor'ing with the bit_mask
3318
- let index_lo = ( bit / bits_per_digit) . to_usize ( ) . unwrap ( ) ;
3319
- let index_hi =
3320
- ( trailing_zeros / bits_per_digit) . to_usize ( ) . unwrap ( ) ;
3321
- let bit_mask_lo = BigDigit :: MAX << ( bit % bits_per_digit) ;
3322
- let bit_mask_hi = BigDigit :: MAX
3323
- >> ( bits_per_digit - 1 - ( trailing_zeros % bits_per_digit) ) ;
3324
- let digits = self . digits_mut ( ) ;
3325
-
3326
- if index_lo == index_hi {
3327
- digits[ index_lo] ^= bit_mask_lo & bit_mask_hi;
3328
- } else {
3329
- digits[ index_lo] ^= bit_mask_lo;
3330
- for index in ( index_lo + 1 ) ..index_hi {
3331
- digits[ index] = BigDigit :: MAX ;
3332
- }
3333
- digits[ index_hi] ^= bit_mask_hi;
3334
- }
3335
- } else {
3336
- // Bit is already cleared
3309
+ if bit > trailing_zeros {
3310
+ self . data . set_bit ( bit, !value) ;
3311
+ } else if bit == trailing_zeros && !value {
3312
+ // Clearing the bit at position `trailing_zeros` is dealt with by doing
3313
+ // similarly to what `bitand_neg_pos` does, except we start at digit
3314
+ // `bit_index`. All digits below `bit_index` are guaranteed to be zero,
3315
+ // so initially we have `carry_in` = `carry_out` = 1.
3316
+ let bit_index = ( bit / bits_per_digit) . to_usize ( ) . unwrap ( ) ;
3317
+ let bit_mask = ( 1 as BigDigit ) << ( bit % bits_per_digit) ;
3318
+ let mut digit_iter = self . digits_mut ( ) . iter_mut ( ) . skip ( bit_index) ;
3319
+ let mut carry_in = 1 ;
3320
+ let mut carry_out = 1 ;
3321
+
3322
+ let digit = digit_iter. next ( ) . unwrap ( ) ;
3323
+ let twos_in = negate_carry ( * digit, & mut carry_in) ;
3324
+ let twos_out = twos_in & !bit_mask;
3325
+ * digit = negate_carry ( twos_out, & mut carry_out) ;
3326
+
3327
+ for digit in digit_iter {
3328
+ if carry_in == 0 && carry_out == 0 {
3329
+ // Exit the loop since no more digits can change
3330
+ break ;
3337
3331
}
3332
+ let twos = negate_carry ( * digit, & mut carry_in) ;
3333
+ * digit = negate_carry ( twos, & mut carry_out) ;
3338
3334
}
3339
- Equal => {
3340
- if value {
3341
- // Bit is already set
3342
- } else {
3343
- // Clearing the bit at position `trailing_zeros` is the only non-trivial
3344
- // case and is dealt with by doing similarly to what `bitand_neg_pos`
3345
- // does, except we start at digit `bit_index`; all digits below `bit_index`
3346
- // are guaranteed to be zero, so initially we must have
3347
- // `carry_in` = `carry_out` = 1
3348
- let bit_index = ( bit / bits_per_digit) . to_usize ( ) . unwrap ( ) ;
3349
- let bit_mask = ( 1 as BigDigit ) << ( bit % bits_per_digit) ;
3350
- let mut digit_iter = self . digits_mut ( ) . iter_mut ( ) . skip ( bit_index) ;
3351
- let mut carry_in = 1 ;
3352
- let mut carry_out = 1 ;
3353
-
3354
- let digit = digit_iter. next ( ) . unwrap ( ) ;
3355
- let twos_in = negate_carry ( * digit, & mut carry_in) ;
3356
- let twos_out = twos_in & !bit_mask;
3357
- * digit = negate_carry ( twos_out, & mut carry_out) ;
3358
-
3359
- for digit in digit_iter {
3360
- if carry_in == 0 && carry_out == 0 {
3361
- // Exit the loop since no more digits can change
3362
- break ;
3363
- }
3364
- let twos = negate_carry ( * digit, & mut carry_in) ;
3365
- * digit = negate_carry ( twos, & mut carry_out) ;
3366
- }
3367
-
3368
- if carry_out != 0 {
3369
- // All digits have been traversed and there is a carry
3370
- debug_assert_eq ! ( carry_in, 0 ) ;
3371
- self . digits_mut ( ) . push ( 1 ) ;
3372
- }
3373
- }
3335
+
3336
+ if carry_out != 0 {
3337
+ // All digits have been traversed and there is a carry
3338
+ debug_assert_eq ! ( carry_in, 0 ) ;
3339
+ self . digits_mut ( ) . push ( 1 ) ;
3374
3340
}
3375
- Greater => {
3376
- self . data . set_bit ( bit, !value) ;
3341
+ } else if bit < trailing_zeros && value {
3342
+ // Flip each bit from position 'bit' to 'trailing_zeros', both inclusive
3343
+ // ... 1 !x 1 0 ... 0 ... 0
3344
+ // |-- bit at position 'bit'
3345
+ // |-- bit at position 'trailing_zeros'
3346
+ // bit_mask: 1 1 ... 1 0 .. 0
3347
+ // We do this by xor'ing with the bit_mask
3348
+ let index_lo = ( bit / bits_per_digit) . to_usize ( ) . unwrap ( ) ;
3349
+ let index_hi =
3350
+ ( trailing_zeros / bits_per_digit) . to_usize ( ) . unwrap ( ) ;
3351
+ let bit_mask_lo = big_digit:: MAX << ( bit % bits_per_digit) ;
3352
+ let bit_mask_hi = big_digit:: MAX
3353
+ >> ( bits_per_digit - 1 - ( trailing_zeros % bits_per_digit) ) ;
3354
+ let digits = self . digits_mut ( ) ;
3355
+
3356
+ if index_lo == index_hi {
3357
+ digits[ index_lo] ^= bit_mask_lo & bit_mask_hi;
3358
+ } else {
3359
+ digits[ index_lo] ^= bit_mask_lo;
3360
+ for index in ( index_lo + 1 ) ..index_hi {
3361
+ digits[ index] = big_digit:: MAX ;
3362
+ }
3363
+ digits[ index_hi] ^= bit_mask_hi;
3377
3364
}
3365
+ } else {
3366
+ // We end up here in two cases:
3367
+ // * bit == trailing_zeros && value: Bit is already set
3368
+ // * bit < trailing_zeros && !value: Bit is already cleared
3378
3369
}
3379
3370
}
3380
3371
}
0 commit comments