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