1use dashu_base::BitTest;
4
5use crate::{arch::word::Word, helper_macros, ibig::IBig, ops::PowerOfTwo, ubig::UBig, Sign::*};
6use core::{
7 cmp::Ordering,
8 mem,
9 ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not},
10};
11
12impl UBig {
15 #[inline]
28 pub fn set_bit(&mut self, n: usize) {
29 self.0 = mem::take(self).into_repr().set_bit(n);
30 }
31
32 #[inline]
43 pub fn clear_bit(&mut self, n: usize) {
44 self.0 = mem::take(self).into_repr().clear_bit(n);
45 }
46
47 #[inline]
64 pub const fn trailing_zeros(&self) -> Option<usize> {
65 self.repr().trailing_zeros()
66 }
67
68 #[inline]
85 pub const fn trailing_ones(&self) -> Option<usize> {
86 Some(self.repr().trailing_ones())
87 }
88
89 #[inline]
107 pub fn split_bits(self, n: usize) -> (UBig, UBig) {
108 let (lo, hi) = self.into_repr().split_bits(n);
109 (UBig(lo), UBig(hi))
110 }
111
112 #[inline]
131 pub fn clear_high_bits(&mut self, n: usize) {
132 self.0 = mem::take(self).into_repr().clear_high_bits(n);
133 }
134
135 #[inline]
149 pub fn count_ones(&self) -> usize {
150 self.repr().count_ones()
151 }
152
153 pub fn count_zeros(&self) -> Option<usize> {
169 self.repr().count_zeros()
170 }
171}
172
173helper_macros::forward_ubig_binop_to_repr!(impl BitAnd, bitand);
174helper_macros::forward_ubig_binop_to_repr!(impl BitOr, bitor);
175helper_macros::forward_ubig_binop_to_repr!(impl BitXor, bitxor);
176helper_macros::forward_ubig_binop_to_repr!(impl AndNot, and_not);
177helper_macros::impl_binop_assign_by_taking!(impl BitAndAssign<UBig> for UBig, bitand_assign, bitand);
178helper_macros::impl_binop_assign_by_taking!(impl BitOrAssign<UBig> for UBig, bitor_assign, bitor);
179helper_macros::impl_binop_assign_by_taking!(impl BitXorAssign<UBig> for UBig, bitxor_assign, bitxor);
180
181impl BitTest for UBig {
182 #[inline]
183 fn bit(&self, n: usize) -> bool {
184 self.repr().bit(n)
185 }
186 #[inline]
187 fn bit_len(&self) -> usize {
188 self.repr().bit_len()
189 }
190}
191
192impl PowerOfTwo for UBig {
193 #[inline]
194 fn is_power_of_two(&self) -> bool {
195 self.repr().is_power_of_two()
196 }
197
198 #[inline]
199 fn next_power_of_two(self) -> UBig {
200 UBig(self.into_repr().next_power_of_two())
201 }
202}
203
204impl IBig {
207 #[inline]
224 pub const fn trailing_zeros(&self) -> Option<usize> {
225 self.as_sign_repr().1.trailing_zeros()
226 }
227
228 pub const fn trailing_ones(&self) -> Option<usize> {
246 let (sign, repr) = self.as_sign_repr();
247 match sign {
248 Positive => Some(repr.trailing_ones()),
249 Negative => repr.trailing_ones_neg(),
250 }
251 }
252}
253
254impl BitTest for IBig {
255 #[inline]
256 fn bit(&self, n: usize) -> bool {
257 let (sign, repr) = self.as_sign_repr();
258 match sign {
259 Positive => repr.bit(n),
260 Negative => {
261 let zeros = repr.trailing_zeros().unwrap();
262 match n.cmp(&zeros) {
263 Ordering::Equal => true,
264 Ordering::Greater => !repr.bit(n),
265 Ordering::Less => false,
266 }
267 }
268 }
269 }
270
271 #[inline]
272 fn bit_len(&self) -> usize {
273 self.as_sign_repr().1.bit_len()
274 }
275}
276
277trait AndNot<Rhs = Self> {
282 type Output;
283
284 fn and_not(self, rhs: Rhs) -> Self::Output;
285}
286
287mod repr {
288 use super::*;
289 use crate::{
290 arch::word::DoubleWord,
291 buffer::Buffer,
292 math::{self, ceil_div, ones_dword, ones_word},
293 primitive::{lowest_dword, split_dword, DWORD_BITS_USIZE, WORD_BITS_USIZE},
294 repr::{
295 Repr,
296 TypedRepr::{self, *},
297 TypedReprRef::{self, *},
298 },
299 shift_ops,
300 };
301
302 impl<'a> TypedReprRef<'a> {
303 #[inline]
304 pub fn bit(self, n: usize) -> bool {
305 match self {
306 RefSmall(dword) => n < DWORD_BITS_USIZE && dword & 1 << n != 0,
307 RefLarge(buffer) => {
308 let idx = n / WORD_BITS_USIZE;
309 idx < buffer.len() && buffer[idx] & 1 << (n % WORD_BITS_USIZE) != 0
310 }
311 }
312 }
313
314 #[inline]
315 pub fn bit_len(self) -> usize {
316 match self {
317 RefSmall(dword) => math::bit_len(dword) as usize,
318 RefLarge(words) => {
319 words.len() * WORD_BITS_USIZE - words.last().unwrap().leading_zeros() as usize
320 }
321 }
322 }
323
324 #[inline]
326 pub fn are_low_bits_nonzero(self, n: usize) -> bool {
327 match self {
328 Self::RefSmall(dword) => are_dword_low_bits_nonzero(dword, n),
329 Self::RefLarge(words) => are_slice_low_bits_nonzero(words, n),
330 }
331 }
332
333 #[inline]
335 pub fn is_power_of_two(self) -> bool {
336 match self {
337 RefSmall(dword) => dword.is_power_of_two(),
338 RefLarge(words) => {
339 words[..words.len() - 1].iter().all(|x| *x == 0)
340 && words.last().unwrap().is_power_of_two()
341 }
342 }
343 }
344
345 pub const fn trailing_zeros(self) -> Option<usize> {
346 match self {
347 RefSmall(0) => None,
348 RefSmall(dword) => Some(dword.trailing_zeros() as usize),
349 RefLarge(words) => Some(trailing_zeros_large(words)),
350 }
351 }
352
353 pub const fn trailing_ones(self) -> usize {
354 match self {
355 RefSmall(dword) => dword.trailing_ones() as usize,
356 RefLarge(words) => trailing_ones_large(words),
357 }
358 }
359
360 pub fn count_ones(self) -> usize {
361 match self {
362 RefSmall(dword) => dword.count_ones() as usize,
363 RefLarge(words) => words.iter().map(|w| w.count_ones() as usize).sum(),
364 }
365 }
366
367 pub fn count_zeros(self) -> Option<usize> {
368 match self {
369 RefSmall(0) => None,
370 RefSmall(dword) => Some((dword.count_zeros() - dword.leading_zeros()) as usize),
371 RefLarge(words) => {
372 let zeros: usize = words.iter().map(|w| w.count_zeros() as usize).sum();
373 Some(zeros - words.last().unwrap().leading_zeros() as usize)
374 }
375 }
376 }
377
378 pub const fn trailing_ones_neg(self) -> Option<usize> {
380 match self {
381 RefSmall(0) => Some(0),
382 RefSmall(1) => None,
383 RefSmall(dword) => Some((!dword + 1).trailing_ones() as usize),
384 RefLarge(words) => {
385 if words[0] & 1 == 0 {
386 Some(0)
387 } else {
388 Some(trailing_zeros_large_shifted_by_one(words) + 1)
389 }
390 }
391 }
392 }
393 }
394
395 impl TypedRepr {
396 #[inline]
397 pub fn next_power_of_two(self) -> Repr {
398 match self {
399 Small(dword) => match dword.checked_next_power_of_two() {
400 Some(p) => Repr::from_dword(p),
401 None => {
402 let mut buffer = Buffer::allocate(3);
403 buffer.push_zeros(2);
404 buffer.push(1);
405 Repr::from_buffer(buffer)
406 }
407 },
408 Large(buffer) => next_power_of_two_large(buffer),
409 }
410 }
411
412 pub fn set_bit(self, n: usize) -> Repr {
413 match self {
414 Small(dword) => {
415 if n < DWORD_BITS_USIZE {
416 Repr::from_dword(dword | 1 << n)
417 } else {
418 with_bit_dword_spilled(dword, n)
419 }
420 }
421 Large(buffer) => with_bit_large(buffer, n),
422 }
423 }
424
425 pub fn clear_bit(self, n: usize) -> Repr {
426 match self {
427 Small(dword) => {
428 if n < DWORD_BITS_USIZE {
429 Repr::from_dword(dword & !(1 << n))
430 } else {
431 Repr::from_dword(dword)
432 }
433 }
434 Large(mut buffer) => {
435 let idx = n / WORD_BITS_USIZE;
436 if idx < buffer.len() {
437 buffer[idx] &= !(1 << (n % WORD_BITS_USIZE));
438 }
439 Repr::from_buffer(buffer)
440 }
441 }
442 }
443
444 pub fn clear_high_bits(self, n: usize) -> Repr {
445 match self {
446 Small(dword) => {
447 if n < DWORD_BITS_USIZE {
448 Repr::from_dword(dword & ones_dword(n as u32))
449 } else {
450 Repr::from_dword(dword)
451 }
452 }
453 Large(buffer) => clear_high_bits_large(buffer, n),
454 }
455 }
456
457 pub fn split_bits(self, n: usize) -> (Repr, Repr) {
458 match self {
459 Small(dword) => {
460 if n < DWORD_BITS_USIZE {
461 (
462 Repr::from_dword(dword & ones_dword(n as u32)),
463 Repr::from_dword(dword >> n),
464 )
465 } else {
466 (Repr::from_dword(dword), Repr::zero())
467 }
468 }
469 Large(buffer) => {
470 if n == 0 {
471 (Repr::zero(), Repr::from_buffer(buffer))
472 } else {
473 let hi = shift_ops::repr::shr_large_ref(&buffer, n);
474 let lo = clear_high_bits_large(buffer, n);
475 (lo, hi)
476 }
477 }
478 }
479 }
480 }
481
482 #[inline]
483 fn are_dword_low_bits_nonzero(dword: DoubleWord, n: usize) -> bool {
484 if n >= DWORD_BITS_USIZE {
488 return dword != 0;
489 }
490 dword & ones_dword(n as u32) != 0
491 }
492
493 fn are_slice_low_bits_nonzero(words: &[Word], n: usize) -> bool {
494 let n_words = n / WORD_BITS_USIZE;
495 if n_words >= words.len() {
496 true
497 } else {
498 let n_top = (n % WORD_BITS_USIZE) as u32;
499 words[..n_words].iter().any(|x| *x != 0) || words[n_words] & ones_word(n_top) != 0
500 }
501 }
502
503 fn next_power_of_two_large(mut buffer: Buffer) -> Repr {
504 debug_assert!(*buffer.last().unwrap() != 0);
505
506 let n = buffer.len();
507 let mut iter = buffer[..n - 1].iter_mut().skip_while(|x| **x == 0);
508
509 let carry = match iter.next() {
510 None => 0,
511 Some(x) => {
512 *x = 0;
513 for x in iter {
514 *x = 0;
515 }
516 1
517 }
518 };
519
520 let last = buffer.last_mut().unwrap();
521 match last
522 .checked_add(carry)
523 .and_then(|x| x.checked_next_power_of_two())
524 {
525 Some(p) => *last = p,
526 None => {
527 *last = 0;
528 buffer.push_resizing(1);
529 }
530 }
531
532 Repr::from_buffer(buffer)
533 }
534
535 fn with_bit_dword_spilled(dword: DoubleWord, n: usize) -> Repr {
536 debug_assert!(n >= DWORD_BITS_USIZE);
537 let idx = n / WORD_BITS_USIZE;
538 let mut buffer = Buffer::allocate(idx + 1);
539 let (lo, hi) = split_dword(dword);
540 buffer.push(lo);
541 buffer.push(hi);
542 buffer.push_zeros(idx - 2);
543 buffer.push(1 << (n % WORD_BITS_USIZE));
544 Repr::from_buffer(buffer)
545 }
546
547 fn with_bit_large(mut buffer: Buffer, n: usize) -> Repr {
548 let idx = n / WORD_BITS_USIZE;
549 if idx < buffer.len() {
550 buffer[idx] |= 1 << (n % WORD_BITS_USIZE);
551 } else {
552 buffer.ensure_capacity(idx + 1);
553 buffer.push_zeros(idx - buffer.len());
554 buffer.push(1 << (n % WORD_BITS_USIZE));
555 }
556 Repr::from_buffer(buffer)
557 }
558
559 #[inline]
562 const fn trailing_zeros_large(words: &[Word]) -> usize {
563 let mut zero_words = 0;
566 while zero_words < words.len() {
567 if words[zero_words] != 0 {
568 break;
569 }
570 zero_words += 1;
571 }
572
573 let zero_bits = words[zero_words].trailing_zeros() as usize;
574 zero_words * WORD_BITS_USIZE + zero_bits
575 }
576
577 #[inline]
580 const fn trailing_zeros_large_shifted_by_one(words: &[Word]) -> usize {
581 debug_assert!(words.len() >= 2);
582 let zero_begin = (words[0] >> 1).trailing_zeros() as usize;
583 if zero_begin < (WORD_BITS_USIZE - 1) {
584 zero_begin
585 } else {
586 let mut zero_words = 1;
587 while zero_words < words.len() {
588 if words[zero_words] != 0 {
589 break;
590 }
591 zero_words += 1;
592 }
593
594 let zero_bits = words[zero_words].trailing_zeros() as usize;
595 (zero_words - 1) * WORD_BITS_USIZE + zero_bits + zero_begin - 1
596 }
597 }
598
599 #[inline]
601 const fn trailing_ones_large(words: &[Word]) -> usize {
602 let mut one_words = 1;
605 while one_words < words.len() {
606 if words[one_words] != Word::MAX {
607 break;
608 }
609 one_words += 1;
610 }
611
612 let one_bits = words[one_words].trailing_ones() as usize;
613 one_words * WORD_BITS_USIZE + one_bits
614 }
615
616 #[inline]
617 fn clear_high_bits_large(mut buffer: Buffer, n: usize) -> Repr {
618 let n_words = ceil_div(n, WORD_BITS_USIZE);
619 if n_words > buffer.len() {
620 Repr::from_buffer(buffer)
621 } else {
622 buffer.truncate(n_words);
623 if n % WORD_BITS_USIZE != 0 {
624 let last = buffer.last_mut().unwrap();
625 *last &= ones_word((n % WORD_BITS_USIZE) as u32);
626 }
627 Repr::from_buffer(buffer)
628 }
629 }
630
631 impl BitAnd<TypedRepr> for TypedRepr {
632 type Output = Repr;
633
634 #[inline]
635 fn bitand(self, rhs: TypedRepr) -> Repr {
636 match (self, rhs) {
637 (Small(dword0), Small(dword1)) => Repr::from_dword(dword0 & dword1),
638 (Small(dword0), Large(buffer1)) => {
639 Repr::from_dword(dword0 & buffer1.lowest_dword())
640 }
641 (Large(buffer0), Small(dword1)) => {
642 Repr::from_dword(buffer0.lowest_dword() & dword1)
643 }
644 (Large(buffer0), Large(buffer1)) => {
645 if buffer0.len() <= buffer1.len() {
646 bitand_large(buffer0, &buffer1)
647 } else {
648 bitand_large(buffer1, &buffer0)
649 }
650 }
651 }
652 }
653 }
654
655 impl<'r> BitAnd<TypedReprRef<'r>> for TypedRepr {
656 type Output = Repr;
657
658 #[inline]
659 fn bitand(self, rhs: TypedReprRef) -> Repr {
660 match (self, rhs) {
661 (Small(dword0), RefSmall(dword1)) => Repr::from_dword(dword0 & dword1),
662 (Small(dword0), RefLarge(buffer1)) => {
663 Repr::from_dword(dword0 & lowest_dword(buffer1))
664 }
665 (Large(buffer0), RefSmall(dword1)) => {
666 Repr::from_dword(buffer0.lowest_dword() & dword1)
667 }
668 (Large(buffer0), RefLarge(buffer1)) => bitand_large(buffer0, buffer1),
669 }
670 }
671 }
672
673 impl<'l> BitAnd<TypedRepr> for TypedReprRef<'l> {
674 type Output = Repr;
675
676 #[inline]
677 fn bitand(self, rhs: TypedRepr) -> Repr {
678 rhs.bitand(self)
680 }
681 }
682
683 impl<'l, 'r> BitAnd<TypedReprRef<'r>> for TypedReprRef<'l> {
684 type Output = Repr;
685
686 #[inline]
687 fn bitand(self, rhs: TypedReprRef) -> Repr {
688 match (self, rhs) {
689 (RefSmall(dword0), RefSmall(dword1)) => Repr::from_dword(dword0 & dword1),
690 (RefSmall(dword0), RefLarge(buffer1)) => {
691 Repr::from_dword(dword0 & lowest_dword(buffer1))
692 }
693 (RefLarge(buffer0), RefSmall(dword1)) => {
694 Repr::from_dword(lowest_dword(buffer0) & dword1)
695 }
696 (RefLarge(buffer0), RefLarge(buffer1)) => {
697 if buffer0.len() <= buffer1.len() {
698 bitand_large(buffer0.into(), buffer1)
699 } else {
700 bitand_large(buffer1.into(), buffer0)
701 }
702 }
703 }
704 }
705 }
706
707 fn bitand_large(mut buffer: Buffer, rhs: &[Word]) -> Repr {
708 if buffer.len() > rhs.len() {
709 buffer.truncate(rhs.len());
710 }
711 for (x, y) in buffer.iter_mut().zip(rhs.iter()) {
712 *x &= *y;
713 }
714 Repr::from_buffer(buffer)
715 }
716
717 impl BitOr<TypedRepr> for TypedRepr {
718 type Output = Repr;
719
720 #[inline]
721 fn bitor(self, rhs: TypedRepr) -> Repr {
722 match (self, rhs) {
723 (Small(dword0), Small(dword1)) => Repr::from_dword(dword0 | dword1),
724 (Small(dword0), Large(buffer1)) => bitor_large_dword(buffer1, dword0),
725 (Large(buffer0), Small(dword1)) => bitor_large_dword(buffer0, dword1),
726 (Large(buffer0), Large(buffer1)) => {
727 if buffer0.len() >= buffer1.len() {
728 bitor_large(buffer0, &buffer1)
729 } else {
730 bitor_large(buffer1, &buffer0)
731 }
732 }
733 }
734 }
735 }
736
737 impl<'r> BitOr<TypedReprRef<'r>> for TypedRepr {
738 type Output = Repr;
739
740 #[inline]
741 fn bitor(self, rhs: TypedReprRef) -> Repr {
742 match (self, rhs) {
743 (Small(dword0), RefSmall(dword1)) => Repr::from_dword(dword0 | dword1),
744 (Small(dword0), RefLarge(buffer1)) => bitor_large_dword(buffer1.into(), dword0),
745 (Large(buffer0), RefSmall(dword1)) => bitor_large_dword(buffer0, dword1),
746 (Large(buffer0), RefLarge(buffer1)) => bitor_large(buffer0, buffer1),
747 }
748 }
749 }
750
751 impl<'l> BitOr<TypedRepr> for TypedReprRef<'l> {
752 type Output = Repr;
753
754 #[inline]
755 fn bitor(self, rhs: TypedRepr) -> Repr {
756 rhs.bitor(self)
758 }
759 }
760
761 impl<'l, 'r> BitOr<TypedReprRef<'r>> for TypedReprRef<'l> {
762 type Output = Repr;
763
764 #[inline]
765 fn bitor(self, rhs: TypedReprRef) -> Repr {
766 match (self, rhs) {
767 (RefSmall(dword0), RefSmall(dword1)) => Repr::from_dword(dword0 | dword1),
768 (RefSmall(dword0), RefLarge(buffer1)) => bitor_large_dword(buffer1.into(), dword0),
769 (RefLarge(buffer0), RefSmall(dword1)) => bitor_large_dword(buffer0.into(), dword1),
770 (RefLarge(buffer0), RefLarge(buffer1)) => {
771 if buffer0.len() >= buffer1.len() {
772 bitor_large(buffer0.into(), buffer1)
773 } else {
774 bitor_large(buffer1.into(), buffer0)
775 }
776 }
777 }
778 }
779 }
780
781 fn bitor_large_dword(mut buffer: Buffer, rhs: DoubleWord) -> Repr {
782 debug_assert!(buffer.len() >= 2);
783
784 let (lo, hi) = split_dword(rhs);
785 let (b_lo, b_hi) = buffer.lowest_dword_mut();
786 *b_lo |= lo;
787 *b_hi |= hi;
788 Repr::from_buffer(buffer)
789 }
790
791 fn bitor_large(mut buffer: Buffer, rhs: &[Word]) -> Repr {
792 for (x, y) in buffer.iter_mut().zip(rhs.iter()) {
793 *x |= *y;
794 }
795 if rhs.len() > buffer.len() {
796 buffer.ensure_capacity(rhs.len());
797 buffer.push_slice(&rhs[buffer.len()..]);
798 }
799 Repr::from_buffer(buffer)
800 }
801
802 impl BitXor<TypedRepr> for TypedRepr {
803 type Output = Repr;
804
805 #[inline]
806 fn bitxor(self, rhs: TypedRepr) -> Repr {
807 match (self, rhs) {
808 (Small(dword0), Small(dword1)) => Repr::from_dword(dword0 ^ dword1),
809 (Small(dword0), Large(buffer1)) => bitxor_large_dword(buffer1, dword0),
810 (Large(buffer0), Small(dword1)) => bitxor_large_dword(buffer0, dword1),
811 (Large(buffer0), Large(buffer1)) => {
812 if buffer0.len() >= buffer1.len() {
813 bitxor_large(buffer0, &buffer1)
814 } else {
815 bitxor_large(buffer1, &buffer0)
816 }
817 }
818 }
819 }
820 }
821
822 impl<'r> BitXor<TypedReprRef<'r>> for TypedRepr {
823 type Output = Repr;
824
825 #[inline]
826 fn bitxor(self, rhs: TypedReprRef) -> Repr {
827 match (self, rhs) {
828 (Small(dword0), RefSmall(dword1)) => Repr::from_dword(dword0 ^ dword1),
829 (Small(dword0), RefLarge(buffer1)) => bitxor_large_dword(buffer1.into(), dword0),
830 (Large(buffer0), RefSmall(dword1)) => bitxor_large_dword(buffer0, dword1),
831 (Large(buffer0), RefLarge(buffer1)) => bitxor_large(buffer0, buffer1),
832 }
833 }
834 }
835
836 impl<'l> BitXor<TypedRepr> for TypedReprRef<'l> {
837 type Output = Repr;
838
839 #[inline]
840 fn bitxor(self, rhs: TypedRepr) -> Repr {
841 rhs.bitxor(self)
843 }
844 }
845
846 impl<'l, 'r> BitXor<TypedReprRef<'r>> for TypedReprRef<'l> {
847 type Output = Repr;
848
849 #[inline]
850 fn bitxor(self, rhs: TypedReprRef) -> Repr {
851 match (self, rhs) {
852 (RefSmall(dword0), RefSmall(dword1)) => Repr::from_dword(dword0 ^ dword1),
853 (RefSmall(dword0), RefLarge(buffer1)) => bitxor_large_dword(buffer1.into(), dword0),
854 (RefLarge(buffer0), RefSmall(dword1)) => bitxor_large_dword(buffer0.into(), dword1),
855 (RefLarge(buffer0), RefLarge(buffer1)) => {
856 if buffer0.len() >= buffer1.len() {
857 bitxor_large(buffer0.into(), buffer1)
858 } else {
859 bitxor_large(buffer1.into(), buffer0)
860 }
861 }
862 }
863 }
864 }
865
866 fn bitxor_large_dword(mut buffer: Buffer, rhs: DoubleWord) -> Repr {
867 debug_assert!(buffer.len() >= 2);
868
869 let (lo, hi) = split_dword(rhs);
870 let (b_lo, b_hi) = buffer.lowest_dword_mut();
871 *b_lo ^= lo;
872 *b_hi ^= hi;
873 Repr::from_buffer(buffer)
874 }
875
876 fn bitxor_large(mut buffer: Buffer, rhs: &[Word]) -> Repr {
877 for (x, y) in buffer.iter_mut().zip(rhs.iter()) {
878 *x ^= *y;
879 }
880 if rhs.len() > buffer.len() {
881 buffer.ensure_capacity(rhs.len());
882 buffer.push_slice(&rhs[buffer.len()..]);
883 }
884 Repr::from_buffer(buffer)
885 }
886
887 impl AndNot<TypedRepr> for TypedRepr {
888 type Output = Repr;
889
890 #[inline]
891 fn and_not(self, rhs: TypedRepr) -> Repr {
892 match (self, rhs) {
893 (Small(dword0), Small(dword1)) => Repr::from_dword(dword0 & !dword1),
894 (Small(dword0), Large(buffer1)) => {
895 Repr::from_dword(dword0 & !buffer1.lowest_dword())
896 }
897 (Large(buffer0), Small(dword1)) => and_not_large_dword(buffer0, dword1),
898 (Large(buffer0), Large(buffer1)) => and_not_large(buffer0, &buffer1),
899 }
900 }
901 }
902
903 impl<'r> AndNot<TypedReprRef<'r>> for TypedRepr {
904 type Output = Repr;
905
906 #[inline]
907 fn and_not(self, rhs: TypedReprRef) -> Repr {
908 match (self, rhs) {
909 (Small(dword0), RefSmall(dword1)) => Repr::from_dword(dword0 & !dword1),
910 (Small(dword0), RefLarge(buffer1)) => {
911 Repr::from_dword(dword0 & !lowest_dword(buffer1))
912 }
913 (Large(buffer0), RefSmall(dword1)) => and_not_large_dword(buffer0, dword1),
914 (Large(buffer0), RefLarge(buffer1)) => and_not_large(buffer0, buffer1),
915 }
916 }
917 }
918
919 impl<'l> AndNot<TypedRepr> for TypedReprRef<'l> {
920 type Output = Repr;
921
922 #[inline]
923 fn and_not(self, rhs: TypedRepr) -> Repr {
924 match (self, rhs) {
925 (RefSmall(dword0), Small(dword1)) => Repr::from_dword(dword0 & !dword1),
926 (RefSmall(dword0), Large(buffer1)) => {
927 Repr::from_dword(dword0 & !buffer1.lowest_dword())
928 }
929 (RefLarge(buffer0), Small(dword1)) => and_not_large_dword(buffer0.into(), dword1),
930 (RefLarge(buffer0), Large(buffer1)) => and_not_large(buffer0.into(), &buffer1),
931 }
932 }
933 }
934
935 impl<'l, 'r> AndNot<TypedReprRef<'r>> for TypedReprRef<'l> {
936 type Output = Repr;
937
938 #[inline]
939 fn and_not(self, rhs: TypedReprRef) -> Repr {
940 match (self, rhs) {
941 (RefSmall(dword0), RefSmall(dword1)) => Repr::from_dword(dword0 & !dword1),
942 (RefSmall(dword0), RefLarge(buffer1)) => {
943 Repr::from_dword(dword0 & !lowest_dword(buffer1))
944 }
945 (RefLarge(buffer0), RefSmall(dword1)) => {
946 and_not_large_dword(buffer0.into(), dword1)
947 }
948 (RefLarge(buffer0), RefLarge(buffer1)) => and_not_large(buffer0.into(), buffer1),
949 }
950 }
951 }
952
953 fn and_not_large_dword(mut buffer: Buffer, rhs: DoubleWord) -> Repr {
954 debug_assert!(buffer.len() >= 2);
955
956 let (lo, hi) = split_dword(rhs);
957 let (b_lo, b_hi) = buffer.lowest_dword_mut();
958 *b_lo &= !lo;
959 *b_hi &= !hi;
960 Repr::from_buffer(buffer)
961 }
962
963 fn and_not_large(mut buffer: Buffer, rhs: &[Word]) -> Repr {
964 for (x, y) in buffer.iter_mut().zip(rhs.iter()) {
965 *x &= !*y;
966 }
967 Repr::from_buffer(buffer)
968 }
969}
970
971impl Not for IBig {
972 type Output = IBig;
973
974 #[inline]
975 fn not(self) -> IBig {
976 let (sign, mag) = self.into_sign_repr();
977 match sign {
978 Positive => IBig(mag.add_one().with_sign(Negative)),
979 Negative => IBig(mag.sub_one().with_sign(Positive)),
980 }
981 }
982}
983
984impl Not for &IBig {
985 type Output = IBig;
986
987 #[inline]
988 fn not(self) -> IBig {
989 let (sign, mag) = self.as_sign_repr();
990 match sign {
991 Positive => IBig(mag.add_one().with_sign(Negative)),
992 Negative => IBig(mag.sub_one().with_sign(Positive)),
993 }
994 }
995}
996
997macro_rules! impl_ibig_bitand {
998 ($sign0:ident, $mag0:ident, $sign1:ident, $mag1:ident) => {
999 match ($sign0, $sign1) {
1000 (Positive, Positive) => IBig($mag0.bitand($mag1)),
1001 (Positive, Negative) => IBig($mag0.and_not($mag1.sub_one().into_typed())),
1002 (Negative, Positive) => IBig($mag1.and_not($mag0.sub_one().into_typed())),
1003 (Negative, Negative) => !IBig(
1004 $mag0
1005 .sub_one()
1006 .into_typed()
1007 .bitor($mag1.sub_one().into_typed()),
1008 ),
1009 }
1010 };
1011}
1012macro_rules! impl_ibig_bitor {
1013 ($sign0:ident, $mag0:ident, $sign1:ident, $mag1:ident) => {
1014 match ($sign0, $sign1) {
1015 (Positive, Positive) => IBig($mag0.bitor($mag1)),
1016 (Positive, Negative) => !IBig($mag1.sub_one().into_typed().and_not($mag0)),
1017 (Negative, Positive) => !IBig($mag0.sub_one().into_typed().and_not($mag1)),
1018 (Negative, Negative) => !IBig(
1019 $mag0
1020 .sub_one()
1021 .into_typed()
1022 .bitand($mag1.sub_one().into_typed()),
1023 ),
1024 }
1025 };
1026}
1027macro_rules! impl_ibig_bitxor {
1028 ($sign0:ident, $mag0:ident, $sign1:ident, $mag1:ident) => {
1029 match ($sign0, $sign1) {
1030 (Positive, Positive) => IBig($mag0.bitxor($mag1)),
1031 (Positive, Negative) => !IBig($mag0.bitxor($mag1.sub_one().into_typed())),
1032 (Negative, Positive) => !IBig($mag0.sub_one().into_typed().bitxor($mag1)),
1033 (Negative, Negative) => IBig(
1034 $mag0
1035 .sub_one()
1036 .into_typed()
1037 .bitxor($mag1.sub_one().into_typed()),
1038 ),
1039 }
1040 };
1041}
1042helper_macros::forward_ibig_binop_to_repr!(impl BitAnd, bitand, Output = IBig, impl_ibig_bitand);
1043helper_macros::forward_ibig_binop_to_repr!(impl BitOr, bitor, Output = IBig, impl_ibig_bitor);
1044helper_macros::forward_ibig_binop_to_repr!(impl BitXor, bitxor, Output = IBig, impl_ibig_bitxor);
1045helper_macros::impl_binop_assign_by_taking!(impl BitAndAssign<IBig> for IBig, bitand_assign, bitand);
1046helper_macros::impl_binop_assign_by_taking!(impl BitOrAssign<IBig> for IBig, bitor_assign, bitor);
1047helper_macros::impl_binop_assign_by_taking!(impl BitXorAssign<IBig> for IBig, bitxor_assign, bitxor);
1048
1049macro_rules! impl_ubig_ibig_bitand {
1052 ($sign0:ident, $mag0:ident, $sign1:ident, $mag1:ident) => {{
1053 debug_assert_eq!($sign0, Positive);
1054 match $sign1 {
1055 Positive => UBig($mag0.bitand($mag1)),
1056 Negative => UBig($mag0.and_not($mag1.sub_one().into_typed())),
1057 }
1058 }};
1059}
1060macro_rules! impl_ibig_ubig_bitand {
1061 ($sign0:ident, $mag0:ident, $sign1:ident, $mag1:ident) => {{
1062 debug_assert_eq!($sign1, Positive);
1063 match $sign0 {
1064 Positive => UBig($mag1.bitand($mag0)),
1065 Negative => UBig($mag1.and_not($mag0.sub_one().into_typed())),
1066 }
1067 }};
1068}
1069helper_macros::forward_ubig_ibig_binop_to_repr!(
1070 impl BitAnd,
1071 bitand,
1072 Output = UBig,
1073 impl_ubig_ibig_bitand
1074);
1075helper_macros::forward_ubig_ibig_binop_to_repr!(impl BitOr, bitor, Output = IBig, impl_ibig_bitor);
1076helper_macros::forward_ubig_ibig_binop_to_repr!(
1077 impl BitXor,
1078 bitxor,
1079 Output = IBig,
1080 impl_ibig_bitxor
1081);
1082helper_macros::impl_binop_assign_by_taking!(impl BitAndAssign<IBig> for UBig, bitand_assign, bitand);
1083helper_macros::forward_ibig_ubig_binop_to_repr!(
1084 impl BitAnd,
1085 bitand,
1086 Output = UBig,
1087 impl_ibig_ubig_bitand
1088);
1089helper_macros::forward_ibig_ubig_binop_to_repr!(impl BitOr, bitor, Output = IBig, impl_ibig_bitor);
1090helper_macros::forward_ibig_ubig_binop_to_repr!(
1091 impl BitXor,
1092 bitxor,
1093 Output = IBig,
1094 impl_ibig_bitxor
1095);
1096helper_macros::impl_binop_assign_by_taking!(impl BitAndAssign<UBig> for IBig, bitand_assign, bitand);
1097helper_macros::impl_binop_assign_by_taking!(impl BitOrAssign<UBig> for IBig, bitor_assign, bitor);
1098helper_macros::impl_binop_assign_by_taking!(impl BitXorAssign<UBig> for IBig, bitxor_assign, bitxor);
1099
1100macro_rules! impl_bit_ops_primitive_with_ubig {
1103 ($($t:ty)*) => {$(
1104 helper_macros::impl_commutative_binop_with_primitive!(impl BitAnd<$t> for UBig, bitand -> $t);
1105 helper_macros::impl_commutative_binop_with_primitive!(impl BitOr<$t> for UBig, bitor);
1106 helper_macros::impl_commutative_binop_with_primitive!(impl BitXor<$t> for UBig, bitxor);
1107 helper_macros::impl_binop_assign_with_primitive!(impl BitAndAssign<$t> for UBig, bitand_assign);
1108 helper_macros::impl_binop_assign_with_primitive!(impl BitOrAssign<$t> for UBig, bitor_assign);
1109 helper_macros::impl_binop_assign_with_primitive!(impl BitXorAssign<$t> for UBig, bitxor_assign);
1110 )*};
1111}
1112impl_bit_ops_primitive_with_ubig!(u8 u16 u32 u64 u128 usize);
1113
1114macro_rules! impl_bit_ops_unsigned_with_ibig {
1115 ($($t:ty)*) => {$(
1116 helper_macros::impl_commutative_binop_with_primitive!(impl BitAnd<$t> for IBig, bitand -> $t);
1117 helper_macros::impl_commutative_binop_with_primitive!(impl BitOr<$t> for IBig, bitor);
1118 helper_macros::impl_commutative_binop_with_primitive!(impl BitXor<$t> for IBig, bitxor);
1119 helper_macros::impl_binop_assign_with_primitive!(impl BitAndAssign<$t> for IBig, bitand_assign);
1120 helper_macros::impl_binop_assign_with_primitive!(impl BitOrAssign<$t> for IBig, bitor_assign);
1121 helper_macros::impl_binop_assign_with_primitive!(impl BitXorAssign<$t> for IBig, bitxor_assign);
1122 )*};
1123}
1124impl_bit_ops_unsigned_with_ibig!(u8 u16 u32 u64 u128 usize);
1125
1126macro_rules! impl_bit_ops_signed_with_ibig {
1127 ($($t:ty)*) => {$(
1128 helper_macros::impl_commutative_binop_with_primitive!(impl BitAnd<$t> for IBig, bitand);
1129 helper_macros::impl_commutative_binop_with_primitive!(impl BitOr<$t> for IBig, bitor);
1130 helper_macros::impl_commutative_binop_with_primitive!(impl BitXor<$t> for IBig, bitxor);
1131 helper_macros::impl_binop_assign_with_primitive!(impl BitAndAssign<$t> for IBig, bitand_assign);
1132 helper_macros::impl_binop_assign_with_primitive!(impl BitOrAssign<$t> for IBig, bitor_assign);
1133 helper_macros::impl_binop_assign_with_primitive!(impl BitXorAssign<$t> for IBig, bitxor_assign);
1134 )*};
1135}
1136impl_bit_ops_signed_with_ibig!(i8 i16 i32 i64 i128 isize);
1137
1138#[cfg(test)]
1139mod tests {
1140 use super::*;
1141
1142 #[test]
1143 fn test_and_not() {
1144 let cases = [
1145 (UBig::from(0xf0f0u16), UBig::from(0xff00u16), UBig::from(0xf0u16)),
1146 (
1147 UBig::from(0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeu128),
1148 UBig::from(0xffu8),
1149 UBig::from(0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00u128),
1150 ),
1151 (
1152 UBig::from(0xffu8),
1153 UBig::from(0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeu128),
1154 UBig::from(0x11u8),
1155 ),
1156 (
1157 UBig::from_str_radix("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 16).unwrap(),
1158 UBig::from_str_radix(
1159 "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
1160 16,
1161 )
1162 .unwrap(),
1163 UBig::from_str_radix("22222222222222222222222222222222", 16).unwrap(),
1164 ),
1165 (
1166 UBig::from_str_radix(
1167 "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
1168 16,
1169 )
1170 .unwrap(),
1171 UBig::from_str_radix("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 16).unwrap(),
1172 UBig::from_str_radix(
1173 "dddddddddddddddddddddddddddddddd11111111111111111111111111111111",
1174 16,
1175 )
1176 .unwrap(),
1177 ),
1178 ];
1179
1180 for (a, b, c) in cases.iter() {
1181 assert_eq!(UBig(a.repr().and_not(b.repr())), *c);
1182 assert_eq!(UBig(a.clone().into_repr().and_not(b.repr())), *c);
1183 assert_eq!(UBig(a.repr().and_not(b.clone().into_repr())), *c);
1184 let (a, b) = (a.clone(), b.clone());
1185 assert_eq!(UBig(a.into_repr().and_not(b.into_repr())), *c);
1186 }
1187 }
1188}