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