|
| 1 | +use crate::{BST_BITS, BitSliceType, INLINE_SLICE_PARTS, SmolBitSet}; |
| 2 | + |
| 3 | +use core::iter; |
| 4 | +use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign}; |
| 5 | + |
| 6 | +macro_rules! impl_bitop { |
| 7 | + ($($OP:ident :: $op:ident, $OPA:ident :: $opa:ident),+) => {$( |
| 8 | + impl $OP<Self> for SmolBitSet { |
| 9 | + type Output = Self; |
| 10 | + |
| 11 | + #[inline] |
| 12 | + fn $op(self, rhs: Self) -> Self { |
| 13 | + let mut lhs = self; |
| 14 | + lhs.$opa(rhs); |
| 15 | + lhs |
| 16 | + } |
| 17 | + } |
| 18 | + |
| 19 | + impl $OPA<Self> for SmolBitSet { |
| 20 | + #[inline] |
| 21 | + fn $opa(&mut self, rhs: Self) { |
| 22 | + self.$opa(&rhs); |
| 23 | + } |
| 24 | + } |
| 25 | + |
| 26 | + impl_bitop!(@ref $OP :: $op, $OPA :: $opa); |
| 27 | + )*}; |
| 28 | + (@ref $OP:ident :: $op:ident, $OPA:ident :: $opa:ident) => { |
| 29 | + impl $OP<&Self> for SmolBitSet { |
| 30 | + type Output = Self; |
| 31 | + |
| 32 | + #[inline] |
| 33 | + fn $op(self, rhs: &Self) -> Self { |
| 34 | + let mut lhs = self; |
| 35 | + lhs.$opa(rhs); |
| 36 | + lhs |
| 37 | + } |
| 38 | + } |
| 39 | + |
| 40 | + impl $OPA<&Self> for SmolBitSet { |
| 41 | + fn $opa(&mut self, rhs: &Self) { |
| 42 | + match (self.is_inline(), rhs.is_inline()) { |
| 43 | + (true, true) => unsafe { |
| 44 | + let lhs = self.get_inline_data_unchecked(); |
| 45 | + let rhs = rhs.get_inline_data_unchecked(); |
| 46 | + self.write_inline_data_unchecked(lhs.$op(rhs)); |
| 47 | + }, |
| 48 | + (_, false) => { |
| 49 | + let rhs_hb = rhs.highest_set_bit(); |
| 50 | + if rhs_hb > self.highest_set_bit() { |
| 51 | + self.ensure_capacity(rhs_hb); |
| 52 | + } |
| 53 | + |
| 54 | + let lhs = unsafe { self.as_slice_mut_unchecked() }; |
| 55 | + let rhs = unsafe { rhs.as_slice_unchecked() }; |
| 56 | + |
| 57 | + assert!(lhs.len() >= rhs.len()); |
| 58 | + |
| 59 | + // in case lhs > rhs we need to have extra elements |
| 60 | + let rhs_iter = rhs.iter().chain(iter::repeat(&0)); |
| 61 | + |
| 62 | + for (lhs, rhs) in lhs.iter_mut().zip(rhs_iter) { |
| 63 | + (*lhs).$opa(*rhs); |
| 64 | + } |
| 65 | + } |
| 66 | + (false, true) => { |
| 67 | + let lhs = unsafe { self.as_slice_mut_unchecked() }; |
| 68 | + let rhs = unsafe { rhs.get_inline_data_unchecked() }; |
| 69 | + |
| 70 | + lhs.iter_mut() |
| 71 | + .enumerate() |
| 72 | + .take(INLINE_SLICE_PARTS) |
| 73 | + .for_each(|(idx, lhs)| { |
| 74 | + (*lhs).$opa((rhs >> (idx * BST_BITS)) as BitSliceType); |
| 75 | + }); |
| 76 | + } |
| 77 | + } |
| 78 | + } |
| 79 | + } |
| 80 | + }; |
| 81 | +} |
| 82 | + |
| 83 | +impl_bitop! { |
| 84 | + BitOr::bitor, BitOrAssign::bitor_assign, |
| 85 | + BitAnd::bitand, BitAndAssign::bitand_assign, |
| 86 | + BitXor::bitxor, BitXorAssign::bitxor_assign |
| 87 | +} |
| 88 | + |
| 89 | +macro_rules! impl_bitop_prim { |
| 90 | + ($($OP:ident :: $op:ident, $OPA:ident :: $opa:ident, $t:ty),+) => {$( |
| 91 | + impl $OP<$t> for SmolBitSet { |
| 92 | + type Output = Self; |
| 93 | + |
| 94 | + #[inline] |
| 95 | + fn $op(self, rhs: $t) -> Self { |
| 96 | + let mut lhs = self; |
| 97 | + lhs.$opa(rhs); |
| 98 | + lhs |
| 99 | + } |
| 100 | + } |
| 101 | + |
| 102 | + impl $OPA<$t> for SmolBitSet { |
| 103 | + #[inline] |
| 104 | + fn $opa(&mut self, rhs: $t) { |
| 105 | + self.$opa(Self::from(rhs)) |
| 106 | + } |
| 107 | + } |
| 108 | + |
| 109 | + impl_bitop_prim!(@ref $OP :: $op, $OPA :: $opa, $t); |
| 110 | + )*}; |
| 111 | + (@ref $OP:ident :: $op:ident, $OPA:ident :: $opa:ident, $t:ty) => { |
| 112 | + impl $OP<&$t> for SmolBitSet { |
| 113 | + type Output = Self; |
| 114 | + |
| 115 | + #[inline] |
| 116 | + fn $op(self, rhs: &$t) -> Self { |
| 117 | + self.$op(*rhs) |
| 118 | + } |
| 119 | + } |
| 120 | + |
| 121 | + impl $OPA<&$t> for SmolBitSet { |
| 122 | + #[inline] |
| 123 | + fn $opa(&mut self, rhs: &$t) { |
| 124 | + self.$opa(*rhs) |
| 125 | + } |
| 126 | + } |
| 127 | + }; |
| 128 | + ($($t:ty),+) => {$( |
| 129 | + impl_bitop_prim!{ |
| 130 | + BitOr::bitor, BitOrAssign::bitor_assign, $t, |
| 131 | + BitAnd::bitand, BitAndAssign::bitand_assign, $t, |
| 132 | + BitXor::bitxor, BitXorAssign::bitxor_assign, $t |
| 133 | + } |
| 134 | + )*}; |
| 135 | +} |
| 136 | + |
| 137 | +impl_bitop_prim!(u8, u16, u32, u64, u128, usize); |
0 commit comments