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