1 #![allow(clippy::undocumented_unsafe_blocks)] 2 3 #[cfg(target_arch = "x86")] 4 use core::arch::x86::*; 5 #[cfg(target_arch = "x86_64")] 6 use core::arch::x86_64::*; 7 use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not}; 8 9 #[derive(Copy, Clone, Debug)] 10 #[repr(transparent)] 11 pub struct Block(pub(super) __m128i); 12 13 impl Block { 14 #[inline] is_empty(self) -> bool15 pub fn is_empty(self) -> bool { 16 #[cfg(not(target_feature = "sse4.1"))] 17 { 18 self == Self::NONE 19 } 20 #[cfg(target_feature = "sse4.1")] 21 { 22 unsafe { _mm_test_all_zeros(self.0, self.0) == 1 } 23 } 24 } 25 26 #[inline] andnot(self, other: Self) -> Self27 pub fn andnot(self, other: Self) -> Self { 28 Self(unsafe { _mm_andnot_si128(other.0, self.0) }) 29 } 30 } 31 32 impl Not for Block { 33 type Output = Block; 34 #[inline] not(self) -> Self::Output35 fn not(self) -> Self::Output { 36 unsafe { Self(_mm_xor_si128(self.0, Self::ALL.0)) } 37 } 38 } 39 40 impl BitAnd for Block { 41 type Output = Block; 42 #[inline] bitand(self, other: Self) -> Self::Output43 fn bitand(self, other: Self) -> Self::Output { 44 unsafe { Self(_mm_and_si128(self.0, other.0)) } 45 } 46 } 47 48 impl BitAndAssign for Block { 49 #[inline] bitand_assign(&mut self, other: Self)50 fn bitand_assign(&mut self, other: Self) { 51 unsafe { 52 self.0 = _mm_and_si128(self.0, other.0); 53 } 54 } 55 } 56 57 impl BitOr for Block { 58 type Output = Block; 59 #[inline] bitor(self, other: Self) -> Self::Output60 fn bitor(self, other: Self) -> Self::Output { 61 unsafe { Self(_mm_or_si128(self.0, other.0)) } 62 } 63 } 64 65 impl BitOrAssign for Block { 66 #[inline] bitor_assign(&mut self, other: Self)67 fn bitor_assign(&mut self, other: Self) { 68 unsafe { 69 self.0 = _mm_or_si128(self.0, other.0); 70 } 71 } 72 } 73 74 impl BitXor for Block { 75 type Output = Block; 76 #[inline] bitxor(self, other: Self) -> Self::Output77 fn bitxor(self, other: Self) -> Self::Output { 78 unsafe { Self(_mm_xor_si128(self.0, other.0)) } 79 } 80 } 81 82 impl BitXorAssign for Block { 83 #[inline] bitxor_assign(&mut self, other: Self)84 fn bitxor_assign(&mut self, other: Self) { 85 unsafe { self.0 = _mm_xor_si128(self.0, other.0) } 86 } 87 } 88 89 impl PartialEq for Block { 90 #[inline] eq(&self, other: &Self) -> bool91 fn eq(&self, other: &Self) -> bool { 92 unsafe { 93 #[cfg(not(target_feature = "sse4.1"))] 94 { 95 _mm_movemask_epi8(_mm_cmpeq_epi8(self.0, other.0)) == 0xffff 96 } 97 #[cfg(target_feature = "sse4.1")] 98 { 99 let neq = _mm_xor_si128(self.0, other.0); 100 _mm_test_all_zeros(neq, neq) == 1 101 } 102 } 103 } 104 } 105