ibig/
bits.rs

1//! Bitwise operators.
2
3use crate::{
4    arch::word::Word,
5    buffer::Buffer,
6    helper_macros,
7    ibig::IBig,
8    math,
9    ops::{AndNot, NextPowerOfTwo, UnsignedAbs},
10    primitive::{double_word, PrimitiveSigned, PrimitiveUnsigned, WORD_BITS_USIZE},
11    sign::Sign::*,
12    ubig::{Repr::*, UBig},
13};
14use core::{
15    mem,
16    ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not},
17};
18
19impl UBig {
20    /// Returns true if the `n`-th bit is set.
21    ///
22    /// # Examples
23    ///
24    /// ```
25    /// # use ibig::ubig;
26    /// assert_eq!(ubig!(0b10010).bit(1), true);
27    /// assert_eq!(ubig!(0b10010).bit(3), false);
28    /// assert_eq!(ubig!(0b10010).bit(100), false);
29    /// ```
30    #[inline]
31    pub fn bit(&self, n: usize) -> bool {
32        match self.repr() {
33            Small(word) => n < WORD_BITS_USIZE && word & 1 << n != 0,
34            Large(buffer) => {
35                let idx = n / WORD_BITS_USIZE;
36                idx < buffer.len() && buffer[idx] & 1 << (n % WORD_BITS_USIZE) != 0
37            }
38        }
39    }
40
41    /// Set the `n`-th bit.
42    ///
43    /// # Examples
44    ///
45    /// ```
46    /// # use ibig::ubig;
47    /// let mut a = ubig!(0b100);
48    /// a.set_bit(0);
49    /// assert_eq!(a, ubig!(0b101));
50    /// a.set_bit(10);
51    /// assert_eq!(a, ubig!(0b10000000101));
52    /// ```
53    #[inline]
54    pub fn set_bit(&mut self, n: usize) {
55        match mem::take(self).into_repr() {
56            Small(word) => {
57                if n < WORD_BITS_USIZE {
58                    *self = UBig::from_word(word | 1 << n)
59                } else {
60                    *self = UBig::with_bit_word_slow(word, n)
61                }
62            }
63            Large(buffer) => *self = UBig::with_bit_large(buffer, n),
64        }
65    }
66
67    fn with_bit_word_slow(word: Word, n: usize) -> UBig {
68        debug_assert!(n >= WORD_BITS_USIZE);
69        let idx = n / WORD_BITS_USIZE;
70        let mut buffer = Buffer::allocate(idx + 1);
71        buffer.push(word);
72        buffer.extend((1..idx).map(|_| 0));
73        buffer.push(1 << (n % WORD_BITS_USIZE));
74        buffer.into()
75    }
76
77    fn with_bit_large(mut buffer: Buffer, n: usize) -> UBig {
78        let idx = n / WORD_BITS_USIZE;
79        if idx < buffer.len() {
80            buffer[idx] |= 1 << (n % WORD_BITS_USIZE);
81        } else {
82            buffer.ensure_capacity(idx + 1);
83            buffer.push_zeros(idx - buffer.len());
84            buffer.push(1 << (n % WORD_BITS_USIZE));
85        }
86        buffer.into()
87    }
88
89    /// Clear the `n`-th bit.
90    ///
91    /// # Examples
92    ///
93    /// ```
94    /// # use ibig::ubig;
95    /// let mut a = ubig!(0b101);
96    /// a.clear_bit(0);
97    /// assert_eq!(a, ubig!(0b100));
98    /// ```
99    #[inline]
100    pub fn clear_bit(&mut self, n: usize) {
101        match mem::take(self).into_repr() {
102            Small(word) => {
103                if n < WORD_BITS_USIZE {
104                    *self = UBig::from_word(word & !(1 << n))
105                }
106            }
107            Large(buffer) => *self = UBig::without_bit_large(buffer, n),
108        }
109    }
110
111    fn without_bit_large(mut buffer: Buffer, n: usize) -> UBig {
112        let idx = n / WORD_BITS_USIZE;
113        if idx < buffer.len() {
114            buffer[idx] &= !(1 << (n % WORD_BITS_USIZE));
115        }
116        buffer.into()
117    }
118
119    /// Returns the number of trailing zeros in the binary representation.
120    ///
121    /// In other words, it is the largest `n` such that 2 to the power of `n` divides the number.
122    ///
123    /// For 0, it returns `None`.
124    ///
125    /// # Examples
126    ///
127    /// ```
128    /// # use ibig::ubig;
129    /// assert_eq!(ubig!(17).trailing_zeros(), Some(0));
130    /// assert_eq!(ubig!(48).trailing_zeros(), Some(4));
131    /// assert_eq!(ubig!(0b101000000).trailing_zeros(), Some(6));
132    /// assert_eq!(ubig!(0).trailing_zeros(), None);
133    /// ```
134    #[inline]
135    pub fn trailing_zeros(&self) -> Option<usize> {
136        match self.repr() {
137            Small(0) => None,
138            Small(word) => Some(word.trailing_zeros() as usize),
139            Large(buffer) => Some(UBig::trailing_zeros_large(buffer)),
140        }
141    }
142
143    fn trailing_zeros_large(words: &[Word]) -> usize {
144        debug_assert!(*words.last().unwrap() != 0);
145
146        for (idx, word) in words.iter().enumerate() {
147            if *word != 0 {
148                return idx * WORD_BITS_USIZE + word.trailing_zeros() as usize;
149            }
150        }
151        panic!("trailing_zeros_large(0)")
152    }
153
154    /// Bit length.
155    ///
156    /// The length of the binary representation of the number.
157    ///
158    /// For 0, the length is 0.
159    ///
160    /// For non-zero numbers it is:
161    /// * `in_radix(2).to_string().len()`
162    /// * the index of the top 1 bit plus one
163    /// * the floor of the logarithm base 2 of the number plus one.
164    ///
165    ///
166    ///
167    /// # Examples
168    ///
169    /// ```
170    /// # use ibig::ubig;
171    /// assert_eq!(ubig!(17).bit_len(), 5);
172    /// assert_eq!(ubig!(0b101000000).bit_len(), 9);
173    /// assert_eq!(ubig!(0).bit_len(), 0);
174    /// let x = ubig!(_0x90ffff3450897234);
175    /// assert_eq!(x.bit_len(), x.in_radix(2).to_string().len());
176    /// ```
177    #[inline]
178    pub fn bit_len(&self) -> usize {
179        match self.repr() {
180            Small(word) => math::bit_len(*word) as usize,
181            Large(buffer) => {
182                buffer.len() * WORD_BITS_USIZE - buffer.last().unwrap().leading_zeros() as usize
183            }
184        }
185    }
186
187    /// True if the number is a power of 2.
188    ///
189    /// # Examples
190    ///
191    /// ```
192    /// # use ibig::ubig;
193    /// assert_eq!(ubig!(0).is_power_of_two(), false);
194    /// assert_eq!(ubig!(8).is_power_of_two(), true);
195    /// assert_eq!(ubig!(9).is_power_of_two(), false);
196    /// ```
197    #[inline]
198    pub fn is_power_of_two(&self) -> bool {
199        match self.repr() {
200            Small(word) => word.is_power_of_two(),
201            Large(buffer) => UBig::is_power_of_two_large(buffer),
202        }
203    }
204
205    fn is_power_of_two_large(words: &[Word]) -> bool {
206        debug_assert!(*words.last().unwrap() != 0);
207
208        words[..words.len() - 1].iter().all(|x| *x == 0) && words.last().unwrap().is_power_of_two()
209    }
210}
211
212impl IBig {
213    /// Returns the number of trailing zeros in the two's complement binary representation.
214    ///
215    /// In other words, it is the largest `n` such that 2 to the power of `n` divides the number.
216    ///
217    /// For 0, it returns `None`.
218    ///
219    /// # Examples
220    ///
221    /// ```
222    /// # use ibig::ibig;
223    /// assert_eq!(ibig!(17).trailing_zeros(), Some(0));
224    /// assert_eq!(ibig!(-48).trailing_zeros(), Some(4));
225    /// assert_eq!(ibig!(-0b101000000).trailing_zeros(), Some(6));
226    /// assert_eq!(ibig!(0).trailing_zeros(), None);
227    /// ```
228    #[inline]
229    pub fn trailing_zeros(&self) -> Option<usize> {
230        self.magnitude().trailing_zeros()
231    }
232}
233
234impl NextPowerOfTwo for UBig {
235    type Output = UBig;
236
237    #[inline]
238    fn next_power_of_two(self) -> UBig {
239        match self.into_repr() {
240            Small(word) => match word.checked_next_power_of_two() {
241                Some(p) => UBig::from_word(p),
242                None => UBig::from(double_word(0, 1)),
243            },
244            Large(buffer) => UBig::next_power_of_two_large(buffer),
245        }
246    }
247}
248
249impl NextPowerOfTwo for &UBig {
250    type Output = UBig;
251
252    #[inline]
253    fn next_power_of_two(self) -> UBig {
254        self.clone().next_power_of_two()
255    }
256}
257
258impl UBig {
259    fn next_power_of_two_large(mut buffer: Buffer) -> UBig {
260        debug_assert!(*buffer.last().unwrap() != 0);
261
262        let n = buffer.len();
263        let mut iter = buffer[..n - 1].iter_mut().skip_while(|x| **x == 0);
264
265        let carry = match iter.next() {
266            None => 0,
267            Some(x) => {
268                *x = 0;
269                for x in iter {
270                    *x = 0;
271                }
272                1
273            }
274        };
275
276        let last = buffer.last_mut().unwrap();
277        match last
278            .checked_add(carry)
279            .and_then(|x| x.checked_next_power_of_two())
280        {
281            Some(p) => *last = p,
282            None => {
283                *last = 0;
284                buffer.ensure_capacity(n + 1);
285                buffer.push(1);
286            }
287        }
288
289        buffer.into()
290    }
291}
292
293impl BitAnd<UBig> for UBig {
294    type Output = UBig;
295
296    #[inline]
297    fn bitand(self, rhs: UBig) -> UBig {
298        match (self.into_repr(), rhs.into_repr()) {
299            (Small(word0), Small(word1)) => UBig::from_word(word0 & word1),
300            (Small(word0), Large(buffer1)) => UBig::from_word(word0 & buffer1.first().unwrap()),
301            (Large(buffer0), Small(word1)) => UBig::from_word(buffer0.first().unwrap() & word1),
302            (Large(buffer0), Large(buffer1)) => {
303                if buffer0.len() <= buffer1.len() {
304                    UBig::bitand_large(buffer0, &buffer1)
305                } else {
306                    UBig::bitand_large(buffer1, &buffer0)
307                }
308            }
309        }
310    }
311}
312
313impl BitAnd<&UBig> for UBig {
314    type Output = UBig;
315
316    #[inline]
317    fn bitand(self, rhs: &UBig) -> UBig {
318        match (self.into_repr(), rhs.repr()) {
319            (Small(word0), Small(word1)) => UBig::from_word(word0 & word1),
320            (Small(word0), Large(buffer1)) => UBig::from_word(word0 & buffer1.first().unwrap()),
321            (Large(buffer0), Small(word1)) => UBig::from_word(buffer0.first().unwrap() & word1),
322            (Large(buffer0), Large(buffer1)) => UBig::bitand_large(buffer0, buffer1),
323        }
324    }
325}
326
327impl BitAnd<UBig> for &UBig {
328    type Output = UBig;
329
330    #[inline]
331    fn bitand(self, rhs: UBig) -> UBig {
332        rhs.bitand(self)
333    }
334}
335
336impl BitAnd<&UBig> for &UBig {
337    type Output = UBig;
338
339    #[inline]
340    fn bitand(self, rhs: &UBig) -> UBig {
341        match (self.repr(), rhs.repr()) {
342            (Small(word0), Small(word1)) => UBig::from_word(word0 & word1),
343            (Small(word0), Large(buffer1)) => UBig::from_word(word0 & buffer1.first().unwrap()),
344            (Large(buffer0), Small(word1)) => UBig::from_word(buffer0.first().unwrap() & word1),
345            (Large(buffer0), Large(buffer1)) => {
346                if buffer0.len() <= buffer1.len() {
347                    UBig::bitand_large(buffer0.clone(), buffer1)
348                } else {
349                    UBig::bitand_large(buffer1.clone(), buffer0)
350                }
351            }
352        }
353    }
354}
355
356impl BitAndAssign<UBig> for UBig {
357    #[inline]
358    fn bitand_assign(&mut self, rhs: UBig) {
359        *self = mem::take(self) & rhs;
360    }
361}
362
363impl BitAndAssign<&UBig> for UBig {
364    #[inline]
365    fn bitand_assign(&mut self, rhs: &UBig) {
366        *self = mem::take(self) & rhs;
367    }
368}
369
370impl UBig {
371    fn bitand_large(mut buffer: Buffer, rhs: &[Word]) -> UBig {
372        if buffer.len() > rhs.len() {
373            buffer.truncate(rhs.len());
374        }
375        for (x, y) in buffer.iter_mut().zip(rhs.iter()) {
376            *x &= *y;
377        }
378        buffer.into()
379    }
380}
381
382impl BitOr<UBig> for UBig {
383    type Output = UBig;
384
385    #[inline]
386    fn bitor(self, rhs: UBig) -> UBig {
387        match (self.into_repr(), rhs.into_repr()) {
388            (Small(word0), Small(word1)) => UBig::from_word(word0 | word1),
389            (Small(word0), Large(buffer1)) => UBig::bitor_large_word(buffer1, word0),
390            (Large(buffer0), Small(word1)) => UBig::bitor_large_word(buffer0, word1),
391            (Large(buffer0), Large(buffer1)) => {
392                if buffer0.len() >= buffer1.len() {
393                    UBig::bitor_large(buffer0, &buffer1)
394                } else {
395                    UBig::bitor_large(buffer1, &buffer0)
396                }
397            }
398        }
399    }
400}
401
402impl BitOr<&UBig> for UBig {
403    type Output = UBig;
404
405    #[inline]
406    fn bitor(self, rhs: &UBig) -> UBig {
407        match (self.into_repr(), rhs.repr()) {
408            (Small(word0), Small(word1)) => UBig::from_word(word0 | word1),
409            (Small(word0), Large(buffer1)) => UBig::bitor_large_word(buffer1.clone(), word0),
410            (Large(buffer0), Small(word1)) => UBig::bitor_large_word(buffer0, *word1),
411            (Large(buffer0), Large(buffer1)) => UBig::bitor_large(buffer0, buffer1),
412        }
413    }
414}
415
416impl BitOr<UBig> for &UBig {
417    type Output = UBig;
418
419    #[inline]
420    fn bitor(self, rhs: UBig) -> UBig {
421        rhs.bitor(self)
422    }
423}
424
425impl BitOr<&UBig> for &UBig {
426    type Output = UBig;
427
428    #[inline]
429    fn bitor(self, rhs: &UBig) -> UBig {
430        match (self.repr(), rhs.repr()) {
431            (Small(word0), Small(word1)) => UBig::from_word(word0 | word1),
432            (Small(word0), Large(buffer1)) => UBig::bitor_large_word(buffer1.clone(), *word0),
433            (Large(buffer0), Small(word1)) => UBig::bitor_large_word(buffer0.clone(), *word1),
434            (Large(buffer0), Large(buffer1)) => {
435                if buffer0.len() >= buffer1.len() {
436                    UBig::bitor_large(buffer0.clone(), buffer1)
437                } else {
438                    UBig::bitor_large(buffer1.clone(), buffer0)
439                }
440            }
441        }
442    }
443}
444
445impl BitOrAssign<UBig> for UBig {
446    #[inline]
447    fn bitor_assign(&mut self, rhs: UBig) {
448        *self = mem::take(self) | rhs;
449    }
450}
451
452impl BitOrAssign<&UBig> for UBig {
453    #[inline]
454    fn bitor_assign(&mut self, rhs: &UBig) {
455        *self = mem::take(self) | rhs;
456    }
457}
458
459impl UBig {
460    fn bitor_large_word(mut buffer: Buffer, rhs: Word) -> UBig {
461        debug_assert!(buffer.len() >= 2);
462
463        *buffer.first_mut().unwrap() |= rhs;
464        buffer.into()
465    }
466
467    fn bitor_large(mut buffer: Buffer, rhs: &[Word]) -> UBig {
468        for (x, y) in buffer.iter_mut().zip(rhs.iter()) {
469            *x |= *y;
470        }
471        if rhs.len() > buffer.len() {
472            buffer.ensure_capacity(rhs.len());
473            buffer.extend(&rhs[buffer.len()..]);
474        }
475        buffer.into()
476    }
477}
478
479impl BitXor<UBig> for UBig {
480    type Output = UBig;
481
482    #[inline]
483    fn bitxor(self, rhs: UBig) -> UBig {
484        match (self.into_repr(), rhs.into_repr()) {
485            (Small(word0), Small(word1)) => UBig::from_word(word0 ^ word1),
486            (Small(word0), Large(buffer1)) => UBig::bitxor_large_word(buffer1, word0),
487            (Large(buffer0), Small(word1)) => UBig::bitxor_large_word(buffer0, word1),
488            (Large(buffer0), Large(buffer1)) => {
489                if buffer0.len() >= buffer1.len() {
490                    UBig::bitxor_large(buffer0, &buffer1)
491                } else {
492                    UBig::bitxor_large(buffer1, &buffer0)
493                }
494            }
495        }
496    }
497}
498
499impl BitXor<&UBig> for UBig {
500    type Output = UBig;
501
502    #[inline]
503    fn bitxor(self, rhs: &UBig) -> UBig {
504        match (self.into_repr(), rhs.repr()) {
505            (Small(word0), Small(word1)) => UBig::from_word(word0 ^ word1),
506            (Small(word0), Large(buffer1)) => UBig::bitxor_large_word(buffer1.clone(), word0),
507            (Large(buffer0), Small(word1)) => UBig::bitxor_large_word(buffer0, *word1),
508            (Large(buffer0), Large(buffer1)) => UBig::bitxor_large(buffer0, buffer1),
509        }
510    }
511}
512
513impl BitXor<UBig> for &UBig {
514    type Output = UBig;
515
516    #[inline]
517    fn bitxor(self, rhs: UBig) -> UBig {
518        rhs.bitxor(self)
519    }
520}
521
522impl BitXor<&UBig> for &UBig {
523    type Output = UBig;
524
525    #[inline]
526    fn bitxor(self, rhs: &UBig) -> UBig {
527        match (self.repr(), rhs.repr()) {
528            (Small(word0), Small(word1)) => UBig::from_word(word0 ^ word1),
529            (Small(word0), Large(buffer1)) => UBig::bitxor_large_word(buffer1.clone(), *word0),
530            (Large(buffer0), Small(word1)) => UBig::bitxor_large_word(buffer0.clone(), *word1),
531            (Large(buffer0), Large(buffer1)) => {
532                if buffer0.len() >= buffer1.len() {
533                    UBig::bitxor_large(buffer0.clone(), buffer1)
534                } else {
535                    UBig::bitxor_large(buffer1.clone(), buffer0)
536                }
537            }
538        }
539    }
540}
541
542impl BitXorAssign<UBig> for UBig {
543    #[inline]
544    fn bitxor_assign(&mut self, rhs: UBig) {
545        *self = mem::take(self) ^ rhs;
546    }
547}
548
549impl BitXorAssign<&UBig> for UBig {
550    #[inline]
551    fn bitxor_assign(&mut self, rhs: &UBig) {
552        *self = mem::take(self) ^ rhs;
553    }
554}
555
556impl UBig {
557    fn bitxor_large_word(mut buffer: Buffer, rhs: Word) -> UBig {
558        debug_assert!(buffer.len() >= 2);
559
560        *buffer.first_mut().unwrap() ^= rhs;
561        buffer.into()
562    }
563
564    fn bitxor_large(mut buffer: Buffer, rhs: &[Word]) -> UBig {
565        for (x, y) in buffer.iter_mut().zip(rhs.iter()) {
566            *x ^= *y;
567        }
568        if rhs.len() > buffer.len() {
569            buffer.ensure_capacity(rhs.len());
570            buffer.extend(&rhs[buffer.len()..]);
571        }
572        buffer.into()
573    }
574}
575
576impl AndNot<UBig> for UBig {
577    type Output = UBig;
578
579    #[inline]
580    fn and_not(self, rhs: UBig) -> UBig {
581        match (self.into_repr(), rhs.into_repr()) {
582            (Small(word0), Small(word1)) => UBig::from_word(word0 & !word1),
583            (Small(word0), Large(buffer1)) => UBig::from_word(word0 & !buffer1.first().unwrap()),
584            (Large(buffer0), Small(word1)) => UBig::and_not_large_word(buffer0, word1),
585            (Large(buffer0), Large(buffer1)) => UBig::and_not_large(buffer0, &buffer1),
586        }
587    }
588}
589
590impl AndNot<&UBig> for UBig {
591    type Output = UBig;
592
593    #[inline]
594    fn and_not(self, rhs: &UBig) -> UBig {
595        match (self.into_repr(), rhs.repr()) {
596            (Small(word0), Small(word1)) => UBig::from_word(word0 & !word1),
597            (Small(word0), Large(buffer1)) => UBig::from_word(word0 & !buffer1.first().unwrap()),
598            (Large(buffer0), Small(word1)) => UBig::and_not_large_word(buffer0, *word1),
599            (Large(buffer0), Large(buffer1)) => UBig::and_not_large(buffer0, buffer1),
600        }
601    }
602}
603
604impl AndNot<UBig> for &UBig {
605    type Output = UBig;
606
607    #[inline]
608    fn and_not(self, rhs: UBig) -> UBig {
609        match (self.repr(), rhs.into_repr()) {
610            (Small(word0), Small(word1)) => UBig::from_word(word0 & !word1),
611            (Small(word0), Large(buffer1)) => UBig::from_word(word0 & !buffer1.first().unwrap()),
612            (Large(buffer0), Small(word1)) => UBig::and_not_large_word(buffer0.clone(), word1),
613            // TODO: Could reuse buffer1 in some cases.
614            (Large(buffer0), Large(buffer1)) => UBig::and_not_large(buffer0.clone(), &buffer1),
615        }
616    }
617}
618
619impl AndNot<&UBig> for &UBig {
620    type Output = UBig;
621
622    #[inline]
623    fn and_not(self, rhs: &UBig) -> UBig {
624        match (self.repr(), rhs.repr()) {
625            (Small(word0), Small(word1)) => UBig::from_word(word0 & !word1),
626            (Small(word0), Large(buffer1)) => UBig::from_word(word0 & !buffer1.first().unwrap()),
627            (Large(buffer0), Small(word1)) => UBig::and_not_large_word(buffer0.clone(), *word1),
628            (Large(buffer0), Large(buffer1)) => UBig::and_not_large(buffer0.clone(), buffer1),
629        }
630    }
631}
632
633impl UBig {
634    fn and_not_large_word(mut buffer: Buffer, rhs: Word) -> UBig {
635        debug_assert!(buffer.len() >= 2);
636
637        *buffer.first_mut().unwrap() &= !rhs;
638        buffer.into()
639    }
640
641    fn and_not_large(mut buffer: Buffer, rhs: &[Word]) -> UBig {
642        for (x, y) in buffer.iter_mut().zip(rhs.iter()) {
643            *x &= !*y;
644        }
645        buffer.into()
646    }
647}
648
649impl Not for IBig {
650    type Output = IBig;
651
652    #[inline]
653    fn not(self) -> IBig {
654        -(self + IBig::from(1u8))
655    }
656}
657
658impl Not for &IBig {
659    type Output = IBig;
660
661    #[inline]
662    fn not(self) -> IBig {
663        -(self + IBig::from(1u8))
664    }
665}
666
667impl BitAnd<IBig> for IBig {
668    type Output = IBig;
669
670    #[inline]
671    fn bitand(self, rhs: IBig) -> IBig {
672        match (self.sign(), rhs.sign()) {
673            (Positive, Positive) => IBig::from(self.unsigned_abs() & rhs.unsigned_abs()),
674            (Positive, Negative) => IBig::from(self.unsigned_abs().and_not((!rhs).unsigned_abs())),
675            (Negative, Positive) => IBig::from(rhs.unsigned_abs().and_not((!self).unsigned_abs())),
676            (Negative, Negative) => !IBig::from((!self).unsigned_abs() | (!rhs).unsigned_abs()),
677        }
678    }
679}
680
681impl BitAnd<&IBig> for IBig {
682    type Output = IBig;
683
684    #[inline]
685    fn bitand(self, rhs: &IBig) -> IBig {
686        match (self.sign(), rhs.sign()) {
687            (Positive, Positive) => IBig::from(self.unsigned_abs() & rhs.magnitude()),
688            (Positive, Negative) => IBig::from(self.unsigned_abs().and_not((!rhs).unsigned_abs())),
689            (Negative, Positive) => IBig::from(rhs.magnitude().and_not((!self).unsigned_abs())),
690            (Negative, Negative) => !IBig::from((!self).unsigned_abs() | (!rhs).unsigned_abs()),
691        }
692    }
693}
694
695impl BitAnd<IBig> for &IBig {
696    type Output = IBig;
697
698    #[inline]
699    fn bitand(self, rhs: IBig) -> IBig {
700        rhs.bitand(self)
701    }
702}
703
704impl BitAnd<&IBig> for &IBig {
705    type Output = IBig;
706
707    #[inline]
708    fn bitand(self, rhs: &IBig) -> IBig {
709        match (self.sign(), rhs.sign()) {
710            (Positive, Positive) => IBig::from(self.magnitude() & rhs.magnitude()),
711            (Positive, Negative) => IBig::from(self.magnitude().and_not((!rhs).unsigned_abs())),
712            (Negative, Positive) => IBig::from(rhs.magnitude().and_not((!self).unsigned_abs())),
713            (Negative, Negative) => !IBig::from((!self).unsigned_abs() | (!rhs).unsigned_abs()),
714        }
715    }
716}
717
718impl BitAndAssign<IBig> for IBig {
719    #[inline]
720    fn bitand_assign(&mut self, rhs: IBig) {
721        *self = mem::take(self) & rhs;
722    }
723}
724
725impl BitAndAssign<&IBig> for IBig {
726    #[inline]
727    fn bitand_assign(&mut self, rhs: &IBig) {
728        *self = mem::take(self) & rhs;
729    }
730}
731
732impl BitOr<IBig> for IBig {
733    type Output = IBig;
734
735    #[inline]
736    fn bitor(self, rhs: IBig) -> IBig {
737        match (self.sign(), rhs.sign()) {
738            (Positive, Positive) => IBig::from(self.unsigned_abs() | rhs.unsigned_abs()),
739            (Positive, Negative) => !IBig::from((!rhs).unsigned_abs().and_not(self.unsigned_abs())),
740            (Negative, Positive) => !IBig::from((!self).unsigned_abs().and_not(rhs.unsigned_abs())),
741            (Negative, Negative) => !IBig::from((!self).unsigned_abs() & (!rhs).unsigned_abs()),
742        }
743    }
744}
745
746impl BitOr<&IBig> for IBig {
747    type Output = IBig;
748
749    #[inline]
750    fn bitor(self, rhs: &IBig) -> IBig {
751        match (self.sign(), rhs.sign()) {
752            (Positive, Positive) => IBig::from(self.unsigned_abs() | rhs.magnitude()),
753            (Positive, Negative) => !IBig::from((!rhs).unsigned_abs().and_not(self.unsigned_abs())),
754            (Negative, Positive) => !IBig::from((!self).unsigned_abs().and_not(rhs.magnitude())),
755            (Negative, Negative) => !IBig::from((!self).unsigned_abs() & (!rhs).unsigned_abs()),
756        }
757    }
758}
759
760impl BitOr<IBig> for &IBig {
761    type Output = IBig;
762
763    #[inline]
764    fn bitor(self, rhs: IBig) -> IBig {
765        rhs.bitor(self)
766    }
767}
768
769impl BitOr<&IBig> for &IBig {
770    type Output = IBig;
771
772    #[inline]
773    fn bitor(self, rhs: &IBig) -> IBig {
774        match (self.sign(), rhs.sign()) {
775            (Positive, Positive) => IBig::from(self.magnitude() | rhs.magnitude()),
776            (Positive, Negative) => !IBig::from((!rhs).unsigned_abs().and_not(self.magnitude())),
777            (Negative, Positive) => !IBig::from((!self).unsigned_abs().and_not(rhs.magnitude())),
778            (Negative, Negative) => !IBig::from((!self).unsigned_abs() & (!rhs).unsigned_abs()),
779        }
780    }
781}
782
783impl BitOrAssign<IBig> for IBig {
784    #[inline]
785    fn bitor_assign(&mut self, rhs: IBig) {
786        *self = mem::take(self) | rhs;
787    }
788}
789
790impl BitOrAssign<&IBig> for IBig {
791    #[inline]
792    fn bitor_assign(&mut self, rhs: &IBig) {
793        *self = mem::take(self) | rhs;
794    }
795}
796
797impl BitXor<IBig> for IBig {
798    type Output = IBig;
799
800    #[inline]
801    fn bitxor(self, rhs: IBig) -> IBig {
802        match (self.sign(), rhs.sign()) {
803            (Positive, Positive) => IBig::from(self.unsigned_abs() ^ rhs.unsigned_abs()),
804            (Positive, Negative) => !IBig::from(self.unsigned_abs() ^ (!rhs).unsigned_abs()),
805            (Negative, Positive) => !IBig::from((!self).unsigned_abs() ^ rhs.unsigned_abs()),
806            (Negative, Negative) => IBig::from((!self).unsigned_abs() ^ (!rhs).unsigned_abs()),
807        }
808    }
809}
810
811impl BitXor<&IBig> for IBig {
812    type Output = IBig;
813
814    #[inline]
815    fn bitxor(self, rhs: &IBig) -> IBig {
816        match (self.sign(), rhs.sign()) {
817            (Positive, Positive) => IBig::from(self.unsigned_abs() ^ rhs.magnitude()),
818            (Positive, Negative) => !IBig::from(self.unsigned_abs() ^ (!rhs).unsigned_abs()),
819            (Negative, Positive) => !IBig::from((!self).unsigned_abs() ^ rhs.magnitude()),
820            (Negative, Negative) => IBig::from((!self).unsigned_abs() ^ (!rhs).unsigned_abs()),
821        }
822    }
823}
824
825impl BitXor<IBig> for &IBig {
826    type Output = IBig;
827
828    #[inline]
829    fn bitxor(self, rhs: IBig) -> IBig {
830        rhs.bitxor(self)
831    }
832}
833
834impl BitXor<&IBig> for &IBig {
835    type Output = IBig;
836
837    #[inline]
838    fn bitxor(self, rhs: &IBig) -> IBig {
839        match (self.sign(), rhs.sign()) {
840            (Positive, Positive) => IBig::from(self.magnitude() ^ rhs.magnitude()),
841            (Positive, Negative) => !IBig::from(self.magnitude() ^ (!rhs).unsigned_abs()),
842            (Negative, Positive) => !IBig::from((!self).unsigned_abs() ^ rhs.magnitude()),
843            (Negative, Negative) => IBig::from((!self).unsigned_abs() ^ (!rhs).unsigned_abs()),
844        }
845    }
846}
847
848impl BitXorAssign<IBig> for IBig {
849    #[inline]
850    fn bitxor_assign(&mut self, rhs: IBig) {
851        *self = mem::take(self) ^ rhs;
852    }
853}
854
855impl BitXorAssign<&IBig> for IBig {
856    #[inline]
857    fn bitxor_assign(&mut self, rhs: &IBig) {
858        *self = mem::take(self) ^ rhs;
859    }
860}
861
862impl AndNot<IBig> for IBig {
863    type Output = IBig;
864
865    #[inline]
866    fn and_not(self, rhs: IBig) -> IBig {
867        match (self.sign(), rhs.sign()) {
868            (Positive, Positive) => IBig::from(self.unsigned_abs().and_not(rhs.unsigned_abs())),
869            (Positive, Negative) => IBig::from(self.unsigned_abs() & (!rhs).unsigned_abs()),
870            (Negative, Positive) => !IBig::from((!self).unsigned_abs() | rhs.unsigned_abs()),
871            (Negative, Negative) => {
872                IBig::from((!rhs).unsigned_abs().and_not((!self).unsigned_abs()))
873            }
874        }
875    }
876}
877
878impl AndNot<&IBig> for IBig {
879    type Output = IBig;
880
881    #[inline]
882    fn and_not(self, rhs: &IBig) -> IBig {
883        match (self.sign(), rhs.sign()) {
884            (Positive, Positive) => IBig::from(self.unsigned_abs().and_not(rhs.magnitude())),
885            (Positive, Negative) => IBig::from(self.unsigned_abs() & (!rhs).unsigned_abs()),
886            (Negative, Positive) => !IBig::from((!self).unsigned_abs() | rhs.magnitude()),
887            (Negative, Negative) => {
888                IBig::from((!rhs).unsigned_abs().and_not((!self).unsigned_abs()))
889            }
890        }
891    }
892}
893
894impl AndNot<IBig> for &IBig {
895    type Output = IBig;
896
897    #[inline]
898    fn and_not(self, rhs: IBig) -> IBig {
899        match (self.sign(), rhs.sign()) {
900            (Positive, Positive) => IBig::from(self.magnitude().and_not(rhs.unsigned_abs())),
901            (Positive, Negative) => IBig::from(self.magnitude() & (!rhs).unsigned_abs()),
902            (Negative, Positive) => !IBig::from((!self).unsigned_abs() | rhs.unsigned_abs()),
903            (Negative, Negative) => {
904                IBig::from((!rhs).unsigned_abs().and_not((!self).unsigned_abs()))
905            }
906        }
907    }
908}
909
910impl AndNot<&IBig> for &IBig {
911    type Output = IBig;
912
913    #[inline]
914    fn and_not(self, rhs: &IBig) -> IBig {
915        match (self.sign(), rhs.sign()) {
916            (Positive, Positive) => IBig::from(self.magnitude().and_not(rhs.magnitude())),
917            (Positive, Negative) => IBig::from(self.magnitude() & (!rhs).unsigned_abs()),
918            (Negative, Positive) => !IBig::from((!self).unsigned_abs() | rhs.magnitude()),
919            (Negative, Negative) => {
920                IBig::from((!rhs).unsigned_abs().and_not((!self).unsigned_abs()))
921            }
922        }
923    }
924}
925
926impl UBig {
927    /// low n bits or'd
928    #[inline]
929    pub(crate) fn are_low_bits_nonzero(&self, n: usize) -> bool {
930        match self.repr() {
931            Small(word) => {
932                let n = n.min(WORD_BITS_USIZE) as u32;
933                word & math::ones::<Word>(n) != 0
934            }
935            Large(buffer) => {
936                let n_words = n / WORD_BITS_USIZE;
937                if n_words >= buffer.len() {
938                    true
939                } else {
940                    let n_top = (n % WORD_BITS_USIZE) as u32;
941                    buffer[..n_words].iter().any(|x| *x != 0)
942                        || buffer[n_words] & math::ones::<Word>(n_top) != 0
943                }
944            }
945        }
946    }
947}
948
949macro_rules! impl_bit_ops_ubig_unsigned {
950    ($t:ty) => {
951        impl BitAnd<$t> for UBig {
952            type Output = $t;
953
954            #[inline]
955            fn bitand(self, rhs: $t) -> $t {
956                self.bitand_unsigned(rhs)
957            }
958        }
959
960        impl BitAnd<$t> for &UBig {
961            type Output = $t;
962
963            #[inline]
964            fn bitand(self, rhs: $t) -> $t {
965                self.bitand_ref_unsigned(rhs)
966            }
967        }
968
969        helper_macros::forward_binop_second_arg_by_value!(impl BitAnd<$t> for UBig, bitand);
970        helper_macros::forward_binop_swap_args!(impl BitAnd<UBig> for $t, bitand);
971
972        impl BitAndAssign<$t> for UBig {
973            #[inline]
974            fn bitand_assign(&mut self, rhs: $t) {
975                self.bitand_assign_unsigned(rhs)
976            }
977        }
978
979        helper_macros::forward_binop_assign_arg_by_value!(impl BitAndAssign<$t> for UBig, bitand_assign);
980
981        impl BitOr<$t> for UBig {
982            type Output = UBig;
983
984            #[inline]
985            fn bitor(self, rhs: $t) -> UBig {
986                self.bitor_unsigned(rhs)
987            }
988        }
989
990        impl BitOr<$t> for &UBig {
991            type Output = UBig;
992
993            #[inline]
994            fn bitor(self, rhs: $t) -> UBig {
995                self.bitor_ref_unsigned(rhs)
996            }
997        }
998
999        helper_macros::forward_binop_second_arg_by_value!(impl BitOr<$t> for UBig, bitor);
1000        helper_macros::forward_binop_swap_args!(impl BitOr<UBig> for $t, bitor);
1001
1002        impl BitOrAssign<$t> for UBig {
1003            #[inline]
1004            fn bitor_assign(&mut self, rhs: $t) {
1005                self.bitor_assign_unsigned(rhs)
1006            }
1007        }
1008
1009        helper_macros::forward_binop_assign_arg_by_value!(impl BitOrAssign<$t> for UBig, bitor_assign);
1010
1011        impl BitXor<$t> for UBig {
1012            type Output = UBig;
1013
1014            #[inline]
1015            fn bitxor(self, rhs: $t) -> UBig {
1016                self.bitxor_unsigned(rhs)
1017            }
1018        }
1019
1020        impl BitXor<$t> for &UBig {
1021            type Output = UBig;
1022
1023            #[inline]
1024            fn bitxor(self, rhs: $t) -> UBig {
1025                self.bitxor_ref_unsigned(rhs)
1026            }
1027        }
1028
1029        helper_macros::forward_binop_second_arg_by_value!(impl BitXor<$t> for UBig, bitxor);
1030        helper_macros::forward_binop_swap_args!(impl BitXor<UBig> for $t, bitxor);
1031
1032        impl BitXorAssign<$t> for UBig {
1033            #[inline]
1034            fn bitxor_assign(&mut self, rhs: $t) {
1035                self.bitxor_assign_unsigned(rhs)
1036            }
1037        }
1038
1039        helper_macros::forward_binop_assign_arg_by_value!(impl BitXorAssign<$t> for UBig, bitxor_assign);
1040
1041        impl AndNot<$t> for UBig {
1042            type Output = UBig;
1043
1044            #[inline]
1045            fn and_not(self, rhs: $t) -> UBig {
1046                self.and_not_unsigned(rhs)
1047            }
1048        }
1049
1050        impl AndNot<$t> for &UBig {
1051            type Output = UBig;
1052
1053            #[inline]
1054            fn and_not(self, rhs: $t) -> UBig {
1055                self.and_not_ref_unsigned(rhs)
1056            }
1057        }
1058
1059        helper_macros::forward_binop_second_arg_by_value!(impl AndNot<$t> for UBig, and_not);
1060    };
1061}
1062
1063impl_bit_ops_ubig_unsigned!(u8);
1064impl_bit_ops_ubig_unsigned!(u16);
1065impl_bit_ops_ubig_unsigned!(u32);
1066impl_bit_ops_ubig_unsigned!(u64);
1067impl_bit_ops_ubig_unsigned!(u128);
1068impl_bit_ops_ubig_unsigned!(usize);
1069
1070macro_rules! impl_bit_ops_ubig_signed {
1071    ($t:ty) => {
1072        impl BitAnd<$t> for UBig {
1073            type Output = UBig;
1074
1075            #[inline]
1076            fn bitand(self, rhs: $t) -> UBig {
1077                self.bitand_signed(rhs)
1078            }
1079        }
1080
1081        impl BitAnd<$t> for &UBig {
1082            type Output = UBig;
1083
1084            #[inline]
1085            fn bitand(self, rhs: $t) -> UBig {
1086                self.bitand_ref_signed(rhs)
1087            }
1088        }
1089
1090        helper_macros::forward_binop_second_arg_by_value!(impl BitAnd<$t> for UBig, bitand);
1091        helper_macros::forward_binop_swap_args!(impl BitAnd<UBig> for $t, bitand);
1092
1093        impl BitAndAssign<$t> for UBig {
1094            #[inline]
1095            fn bitand_assign(&mut self, rhs: $t) {
1096                self.bitand_assign_signed(rhs)
1097            }
1098        }
1099
1100        helper_macros::forward_binop_assign_arg_by_value!(impl BitAndAssign<$t> for UBig, bitand_assign);
1101
1102        impl BitOr<$t> for UBig {
1103            type Output = UBig;
1104
1105            #[inline]
1106            fn bitor(self, rhs: $t) -> UBig {
1107                self.bitor_signed(rhs)
1108            }
1109        }
1110
1111        impl BitOr<$t> for &UBig {
1112            type Output = UBig;
1113
1114            #[inline]
1115            fn bitor(self, rhs: $t) -> UBig {
1116                self.bitor_ref_signed(rhs)
1117            }
1118        }
1119
1120        helper_macros::forward_binop_second_arg_by_value!(impl BitOr<$t> for UBig, bitor);
1121        helper_macros::forward_binop_swap_args!(impl BitOr<UBig> for $t, bitor);
1122
1123        impl BitOrAssign<$t> for UBig {
1124            #[inline]
1125            fn bitor_assign(&mut self, rhs: $t) {
1126                self.bitor_assign_signed(rhs)
1127            }
1128        }
1129
1130        helper_macros::forward_binop_assign_arg_by_value!(impl BitOrAssign<$t> for UBig, bitor_assign);
1131
1132        impl BitXor<$t> for UBig {
1133            type Output = UBig;
1134
1135            #[inline]
1136            fn bitxor(self, rhs: $t) -> UBig {
1137                self.bitxor_signed(rhs)
1138            }
1139        }
1140
1141        impl BitXor<$t> for &UBig {
1142            type Output = UBig;
1143
1144            #[inline]
1145            fn bitxor(self, rhs: $t) -> UBig {
1146                self.bitxor_ref_signed(rhs)
1147            }
1148        }
1149
1150        helper_macros::forward_binop_second_arg_by_value!(impl BitXor<$t> for UBig, bitxor);
1151        helper_macros::forward_binop_swap_args!(impl BitXor<UBig> for $t, bitxor);
1152
1153        impl BitXorAssign<$t> for UBig {
1154            #[inline]
1155            fn bitxor_assign(&mut self, rhs: $t) {
1156                self.bitxor_assign_signed(rhs)
1157            }
1158        }
1159
1160        helper_macros::forward_binop_assign_arg_by_value!(impl BitXorAssign<$t> for UBig, bitxor_assign);
1161
1162        impl AndNot<$t> for UBig {
1163            type Output = UBig;
1164
1165            #[inline]
1166            fn and_not(self, rhs: $t) -> UBig {
1167                self.and_not_signed(rhs)
1168            }
1169        }
1170
1171        impl AndNot<$t> for &UBig {
1172            type Output = UBig;
1173
1174            #[inline]
1175            fn and_not(self, rhs: $t) -> UBig {
1176                self.and_not_ref_signed(rhs)
1177            }
1178        }
1179
1180        helper_macros::forward_binop_second_arg_by_value!(impl AndNot<$t> for UBig, and_not);
1181    };
1182}
1183
1184impl_bit_ops_ubig_signed!(i8);
1185impl_bit_ops_ubig_signed!(i16);
1186impl_bit_ops_ubig_signed!(i32);
1187impl_bit_ops_ubig_signed!(i64);
1188impl_bit_ops_ubig_signed!(i128);
1189impl_bit_ops_ubig_signed!(isize);
1190
1191macro_rules! impl_bit_ops_ibig_unsigned {
1192    ($t:ty) => {
1193        impl BitAnd<$t> for IBig {
1194            type Output = $t;
1195
1196            #[inline]
1197            fn bitand(self, rhs: $t) -> $t {
1198                self.bitand_unsigned(rhs)
1199            }
1200        }
1201
1202        impl BitAnd<$t> for &IBig {
1203            type Output = $t;
1204
1205            #[inline]
1206            fn bitand(self, rhs: $t) -> $t {
1207                self.bitand_ref_unsigned(rhs)
1208            }
1209        }
1210    };
1211}
1212
1213impl_bit_ops_ibig_unsigned!(u8);
1214impl_bit_ops_ibig_unsigned!(u16);
1215impl_bit_ops_ibig_unsigned!(u32);
1216impl_bit_ops_ibig_unsigned!(u64);
1217impl_bit_ops_ibig_unsigned!(u128);
1218impl_bit_ops_ibig_unsigned!(usize);
1219
1220macro_rules! impl_bit_ops_ibig_signed {
1221    ($t:ty) => {
1222        impl BitAnd<$t> for IBig {
1223            type Output = IBig;
1224
1225            #[inline]
1226            fn bitand(self, rhs: $t) -> IBig {
1227                self.bitand_signed(rhs)
1228            }
1229        }
1230
1231        impl BitAnd<$t> for &IBig {
1232            type Output = IBig;
1233
1234            #[inline]
1235            fn bitand(self, rhs: $t) -> IBig {
1236                self.bitand_ref_signed(rhs)
1237            }
1238        }
1239    };
1240}
1241
1242impl_bit_ops_ibig_signed!(i8);
1243impl_bit_ops_ibig_signed!(i16);
1244impl_bit_ops_ibig_signed!(i32);
1245impl_bit_ops_ibig_signed!(i64);
1246impl_bit_ops_ibig_signed!(i128);
1247impl_bit_ops_ibig_signed!(isize);
1248
1249macro_rules! impl_bit_ops_ibig_primitive {
1250    ($t:ty) => {
1251        helper_macros::forward_binop_second_arg_by_value!(impl BitAnd<$t> for IBig, bitand);
1252        helper_macros::forward_binop_swap_args!(impl BitAnd<IBig> for $t, bitand);
1253
1254        impl BitAndAssign<$t> for IBig {
1255            #[inline]
1256            fn bitand_assign(&mut self, rhs: $t) {
1257                self.bitand_assign_primitive(rhs)
1258            }
1259        }
1260
1261        helper_macros::forward_binop_assign_arg_by_value!(impl BitAndAssign<$t> for IBig, bitand_assign);
1262
1263        impl BitOr<$t> for IBig {
1264            type Output = IBig;
1265
1266            #[inline]
1267            fn bitor(self, rhs: $t) -> IBig {
1268                self.bitor_primitive(rhs)
1269            }
1270        }
1271
1272        impl BitOr<$t> for &IBig {
1273            type Output = IBig;
1274
1275            #[inline]
1276            fn bitor(self, rhs: $t) -> IBig {
1277                self.bitor_ref_primitive(rhs)
1278            }
1279        }
1280
1281        helper_macros::forward_binop_second_arg_by_value!(impl BitOr<$t> for IBig, bitor);
1282        helper_macros::forward_binop_swap_args!(impl BitOr<IBig> for $t, bitor);
1283
1284        impl BitOrAssign<$t> for IBig {
1285            #[inline]
1286            fn bitor_assign(&mut self, rhs: $t) {
1287                self.bitor_assign_primitive(rhs)
1288            }
1289        }
1290
1291        helper_macros::forward_binop_assign_arg_by_value!(impl BitOrAssign<$t> for IBig, bitor_assign);
1292
1293        impl BitXor<$t> for IBig {
1294            type Output = IBig;
1295
1296            #[inline]
1297            fn bitxor(self, rhs: $t) -> IBig {
1298                self.bitxor_primitive(rhs)
1299            }
1300        }
1301
1302        impl BitXor<$t> for &IBig {
1303            type Output = IBig;
1304
1305            #[inline]
1306            fn bitxor(self, rhs: $t) -> IBig {
1307                self.bitxor_ref_primitive(rhs)
1308            }
1309        }
1310
1311        helper_macros::forward_binop_second_arg_by_value!(impl BitXor<$t> for IBig, bitxor);
1312        helper_macros::forward_binop_swap_args!(impl BitXor<IBig> for $t, bitxor);
1313
1314        impl BitXorAssign<$t> for IBig {
1315            #[inline]
1316            fn bitxor_assign(&mut self, rhs: $t) {
1317                self.bitxor_assign_primitive(rhs)
1318            }
1319        }
1320
1321        helper_macros::forward_binop_assign_arg_by_value!(impl BitXorAssign<$t> for IBig, bitxor_assign);
1322
1323        impl AndNot<$t> for IBig {
1324            type Output = IBig;
1325
1326            #[inline]
1327            fn and_not(self, rhs: $t) -> IBig {
1328                self.and_not_primitive(rhs)
1329            }
1330        }
1331
1332        impl AndNot<$t> for &IBig {
1333            type Output = IBig;
1334
1335            #[inline]
1336            fn and_not(self, rhs: $t) -> IBig {
1337                self.and_not_ref_primitive(rhs)
1338            }
1339        }
1340
1341        helper_macros::forward_binop_second_arg_by_value!(impl AndNot<$t> for IBig, and_not);
1342    };
1343}
1344
1345impl_bit_ops_ibig_primitive!(u8);
1346impl_bit_ops_ibig_primitive!(u16);
1347impl_bit_ops_ibig_primitive!(u32);
1348impl_bit_ops_ibig_primitive!(u64);
1349impl_bit_ops_ibig_primitive!(u128);
1350impl_bit_ops_ibig_primitive!(usize);
1351impl_bit_ops_ibig_primitive!(i8);
1352impl_bit_ops_ibig_primitive!(i16);
1353impl_bit_ops_ibig_primitive!(i32);
1354impl_bit_ops_ibig_primitive!(i64);
1355impl_bit_ops_ibig_primitive!(i128);
1356impl_bit_ops_ibig_primitive!(isize);
1357
1358impl UBig {
1359    #[inline]
1360    fn bitand_unsigned<T: PrimitiveUnsigned>(self, rhs: T) -> T {
1361        self.bitand(UBig::from_unsigned(rhs))
1362            .try_to_unsigned()
1363            .unwrap()
1364    }
1365
1366    #[inline]
1367    fn bitand_ref_unsigned<T: PrimitiveUnsigned>(&self, rhs: T) -> T {
1368        self.bitand(UBig::from_unsigned(rhs))
1369            .try_to_unsigned()
1370            .unwrap()
1371    }
1372
1373    #[inline]
1374    fn bitand_assign_unsigned<T: PrimitiveUnsigned>(&mut self, rhs: T) {
1375        self.bitand_assign(UBig::from_unsigned(rhs))
1376    }
1377
1378    #[inline]
1379    fn bitor_unsigned<T: PrimitiveUnsigned>(self, rhs: T) -> UBig {
1380        self.bitor(UBig::from_unsigned(rhs))
1381    }
1382
1383    #[inline]
1384    fn bitor_ref_unsigned<T: PrimitiveUnsigned>(&self, rhs: T) -> UBig {
1385        self.bitor(UBig::from_unsigned(rhs))
1386    }
1387
1388    #[inline]
1389    fn bitor_assign_unsigned<T: PrimitiveUnsigned>(&mut self, rhs: T) {
1390        self.bitor_assign(UBig::from_unsigned(rhs))
1391    }
1392
1393    #[inline]
1394    fn bitxor_unsigned<T: PrimitiveUnsigned>(self, rhs: T) -> UBig {
1395        self.bitxor(UBig::from_unsigned(rhs))
1396    }
1397
1398    #[inline]
1399    fn bitxor_ref_unsigned<T: PrimitiveUnsigned>(&self, rhs: T) -> UBig {
1400        self.bitxor(UBig::from_unsigned(rhs))
1401    }
1402
1403    #[inline]
1404    fn bitxor_assign_unsigned<T: PrimitiveUnsigned>(&mut self, rhs: T) {
1405        self.bitxor_assign(UBig::from_unsigned(rhs))
1406    }
1407
1408    #[inline]
1409    fn and_not_unsigned<T: PrimitiveUnsigned>(self, rhs: T) -> UBig {
1410        self.and_not(UBig::from_unsigned(rhs))
1411    }
1412
1413    #[inline]
1414    fn and_not_ref_unsigned<T: PrimitiveUnsigned>(&self, rhs: T) -> UBig {
1415        self.and_not(UBig::from_unsigned(rhs))
1416    }
1417
1418    #[inline]
1419    fn bitand_signed<T: PrimitiveSigned>(self, rhs: T) -> UBig {
1420        UBig::from_ibig_panic_on_overflow(IBig::from(self) & IBig::from_signed(rhs))
1421    }
1422
1423    #[inline]
1424    fn bitand_ref_signed<T: PrimitiveSigned>(&self, rhs: T) -> UBig {
1425        // Avoid big copy if rhs positive.
1426        let rhs_signed = IBig::from_signed(rhs);
1427        match rhs_signed.sign() {
1428            Positive => self & rhs_signed.unsigned_abs(),
1429            Negative => UBig::from_ibig_panic_on_overflow(IBig::from(self) & rhs_signed),
1430        }
1431    }
1432
1433    #[inline]
1434    fn bitand_assign_signed<T: PrimitiveSigned>(&mut self, rhs: T) {
1435        *self = mem::take(self).bitand_signed(rhs)
1436    }
1437
1438    #[inline]
1439    fn bitor_signed<T: PrimitiveSigned>(self, rhs: T) -> UBig {
1440        UBig::from_ibig_panic_on_overflow(IBig::from(self) | IBig::from_signed(rhs))
1441    }
1442
1443    #[inline]
1444    fn bitor_ref_signed<T: PrimitiveSigned>(&self, rhs: T) -> UBig {
1445        UBig::from_ibig_panic_on_overflow(IBig::from(self) | IBig::from_signed(rhs))
1446    }
1447
1448    #[inline]
1449    fn bitor_assign_signed<T: PrimitiveSigned>(&mut self, rhs: T) {
1450        *self = mem::take(self).bitor_signed(rhs)
1451    }
1452
1453    #[inline]
1454    fn bitxor_signed<T: PrimitiveSigned>(self, rhs: T) -> UBig {
1455        UBig::from_ibig_panic_on_overflow(IBig::from(self) ^ IBig::from_signed(rhs))
1456    }
1457
1458    #[inline]
1459    fn bitxor_ref_signed<T: PrimitiveSigned>(&self, rhs: T) -> UBig {
1460        UBig::from_ibig_panic_on_overflow(IBig::from(self) ^ IBig::from_signed(rhs))
1461    }
1462
1463    #[inline]
1464    fn bitxor_assign_signed<T: PrimitiveSigned>(&mut self, rhs: T) {
1465        *self = mem::take(self).bitxor_signed(rhs)
1466    }
1467
1468    #[inline]
1469    fn and_not_signed<T: PrimitiveSigned>(self, rhs: T) -> UBig {
1470        UBig::from_ibig_panic_on_overflow(IBig::from(self).and_not(IBig::from_signed(rhs)))
1471    }
1472
1473    #[inline]
1474    fn and_not_ref_signed<T: PrimitiveSigned>(&self, rhs: T) -> UBig {
1475        UBig::from_ibig_panic_on_overflow(IBig::from(self).and_not(IBig::from_signed(rhs)))
1476    }
1477}
1478
1479impl IBig {
1480    #[inline]
1481    fn bitand_unsigned<T: PrimitiveUnsigned>(self, rhs: T) -> T {
1482        self.bitand(IBig::from_unsigned(rhs))
1483            .try_to_unsigned()
1484            .unwrap()
1485    }
1486
1487    #[inline]
1488    fn bitand_ref_unsigned<T: PrimitiveUnsigned>(&self, rhs: T) -> T {
1489        self.bitand(IBig::from_unsigned(rhs))
1490            .try_to_unsigned()
1491            .unwrap()
1492    }
1493
1494    #[inline]
1495    fn bitand_signed<T: PrimitiveSigned>(self, rhs: T) -> IBig {
1496        self.bitand(IBig::from_signed(rhs))
1497    }
1498
1499    #[inline]
1500    fn bitand_ref_signed<T: PrimitiveSigned>(&self, rhs: T) -> IBig {
1501        self.bitand(IBig::from_signed(rhs))
1502    }
1503
1504    #[inline]
1505    fn bitand_assign_primitive<T>(&mut self, rhs: T)
1506    where
1507        IBig: From<T>,
1508    {
1509        self.bitand_assign(IBig::from(rhs))
1510    }
1511
1512    #[inline]
1513    fn bitor_primitive<T>(self, rhs: T) -> IBig
1514    where
1515        IBig: From<T>,
1516    {
1517        self.bitor(IBig::from(rhs))
1518    }
1519
1520    #[inline]
1521    fn bitor_ref_primitive<T>(&self, rhs: T) -> IBig
1522    where
1523        IBig: From<T>,
1524    {
1525        self.bitor(IBig::from(rhs))
1526    }
1527
1528    #[inline]
1529    fn bitor_assign_primitive<T>(&mut self, rhs: T)
1530    where
1531        IBig: From<T>,
1532    {
1533        self.bitor_assign(IBig::from(rhs))
1534    }
1535
1536    #[inline]
1537    fn bitxor_primitive<T>(self, rhs: T) -> IBig
1538    where
1539        IBig: From<T>,
1540    {
1541        self.bitxor(IBig::from(rhs))
1542    }
1543
1544    #[inline]
1545    fn bitxor_ref_primitive<T>(&self, rhs: T) -> IBig
1546    where
1547        IBig: From<T>,
1548    {
1549        self.bitxor(IBig::from(rhs))
1550    }
1551
1552    #[inline]
1553    fn bitxor_assign_primitive<T>(&mut self, rhs: T)
1554    where
1555        IBig: From<T>,
1556    {
1557        self.bitxor_assign(IBig::from(rhs))
1558    }
1559
1560    #[inline]
1561    fn and_not_primitive<T>(self, rhs: T) -> IBig
1562    where
1563        IBig: From<T>,
1564    {
1565        self.and_not(IBig::from(rhs))
1566    }
1567
1568    #[inline]
1569    fn and_not_ref_primitive<T>(&self, rhs: T) -> IBig
1570    where
1571        IBig: From<T>,
1572    {
1573        self.and_not(IBig::from(rhs))
1574    }
1575}