bitset_core/
simd.rs

1use super::BitSet;
2
3// Implement SIMD version by relying on very optimizer friendly code
4// Alignment is ignored but cam be taken care of by user code
5macro_rules! impl_bit_set_simd {
6	([[$elem_ty:ident; $elem_len:literal]], $bits_per_word:literal, [$($idx:tt)*]) => {
7		impl BitSet for [[$elem_ty; $elem_len]] {
8			#[inline]
9			fn bit_len(&self) -> usize {
10				self.len() * $bits_per_word
11			}
12			#[inline]
13			fn bit_init(&mut self, value: bool) -> &mut Self {
14				let value = [$elem_ty::wrapping_add(!(value as $elem_ty), 1); $elem_len];
15				for i in 0..self.len() {
16					self[i] = value;
17				}
18				self
19			}
20			#[inline]
21			fn bit_test(&self, bit: usize) -> bool {
22				let index = bit / $bits_per_word;
23				let lane = (bit / ($bits_per_word / $elem_len)) % $elem_len;
24				let mask = 1 << bit % ($bits_per_word / $elem_len);
25				self[index][lane] & mask != 0
26			}
27			#[inline]
28			fn bit_set(&mut self, bit: usize) -> &mut Self {
29				let index = bit / $bits_per_word;
30				let lane = (bit / ($bits_per_word / $elem_len)) % $elem_len;
31				let mask = 1 << bit % ($bits_per_word / $elem_len);
32				self[index][lane] |= mask;
33				self
34			}
35			#[inline]
36			fn bit_reset(&mut self, bit: usize) -> &mut Self {
37				let index = bit / $bits_per_word;
38				let lane = (bit / ($bits_per_word / $elem_len)) % $elem_len;
39				let mask = 1 << bit % ($bits_per_word / $elem_len);
40				self[index][lane] &= !mask;
41				self
42			}
43			#[inline]
44			fn bit_flip(&mut self, bit: usize) -> &mut Self {
45				let index = bit / $bits_per_word;
46				let lane = (bit / ($bits_per_word / $elem_len)) % $elem_len;
47				let mask = 1 << bit % ($bits_per_word / $elem_len);
48				self[index][lane] ^= mask;
49				self
50			}
51			#[inline]
52			fn bit_cond(&mut self, bit: usize, value: bool) -> &mut Self {
53				let index = bit / $bits_per_word;
54				let lane = (bit / ($bits_per_word / $elem_len)) % $elem_len;
55				let mask = 1 << bit % ($bits_per_word / $elem_len);
56				self[index][lane] = (self[index][lane] & !mask) | ($elem_ty::wrapping_add(!(value as $elem_ty), 1) & mask);
57				self
58			}
59			#[inline]
60			fn bit_all(&self) -> bool {
61				for i in 0..self.len() {
62					if self[i] != [!0; $elem_len] {
63						return false;
64					}
65				}
66				true
67			}
68			#[inline]
69			fn bit_any(&self) -> bool {
70				for i in 0..self.len() {
71					if self[i] != [0; $elem_len] {
72						return true;
73					}
74				}
75				false
76			}
77			#[inline]
78			fn bit_eq(&self, rhs: &Self) -> bool {
79				assert_eq!(self.len(), rhs.len());
80				for i in 0..self.len() {
81					if self[i] != rhs[i] {
82						return false;
83					}
84				}
85				true
86			}
87			#[inline]
88			fn bit_disjoint(&self, rhs: &Self) -> bool {
89				assert_eq!(self.len(), rhs.len());
90				for i in 0..self.len() {
91					let tmp = [$(self[i][$idx] & rhs[i][$idx]),*];
92					if tmp != [0; $elem_len] {
93						return false;
94					}
95				}
96				true
97			}
98			#[inline]
99			fn bit_subset(&self, rhs: &Self) -> bool {
100				assert_eq!(self.len(), rhs.len());
101				for i in 0..self.len() {
102					let tmp = [$(self[i][$idx] | rhs[i][$idx]),*];
103					if tmp != rhs[i] {
104						return false;
105					}
106				}
107				true
108			}
109			#[inline]
110			fn bit_or(&mut self, rhs: &Self) -> &mut Self {
111				assert_eq!(self.len(), rhs.len());
112				for i in 0..self.len() {
113					$(self[i][$idx] |= rhs[i][$idx];)*
114				}
115				self
116			}
117			#[inline]
118			fn bit_and(&mut self, rhs: &Self) -> &mut Self {
119				assert_eq!(self.len(), rhs.len());
120				for i in 0..self.len() {
121					$(self[i][$idx] &= rhs[i][$idx];)*
122				}
123				self
124			}
125			#[inline]
126			fn bit_andnot(&mut self, rhs: &Self) -> &mut Self {
127				assert_eq!(self.len(), rhs.len());
128				for i in 0..self.len() {
129					$(self[i][$idx] &= !rhs[i][$idx];)*
130				}
131				self
132			}
133			#[inline]
134			fn bit_xor(&mut self, rhs: &Self) -> &mut Self {
135				assert_eq!(self.len(), rhs.len());
136				for i in 0..self.len() {
137					$(self[i][$idx] ^= rhs[i][$idx];)*
138				}
139				self
140			}
141			#[inline]
142			fn bit_not(&mut self) -> &mut Self {
143				for i in 0..self.len() {
144					$(self[i][$idx] = !self[i][$idx];)*
145				}
146				self
147			}
148			#[inline]
149			fn bit_mask(&mut self, rhs: &Self, mask: &Self) -> &mut Self {
150				let len = self.len();
151				assert_eq!(len, rhs.len());
152				assert_eq!(len, mask.len());
153				for i in 0..len {
154					$(self[i][$idx] = self[i][$idx] & !mask[i][$idx] | rhs[i][$idx] & mask[i][$idx];)*
155				}
156				self
157			}
158			#[inline]
159			fn bit_count(&self) -> usize {
160				let mut result = [0; $elem_len];
161				for i in 0..self.len() {
162					$(result[$idx] += self[i][$idx].count_ones() as usize;)*
163				}
164				0 $(+result[$idx])*
165			}
166		}
167	};
168}
169
170// simd128
171impl_bit_set_simd!([[ u8; 16]], 128, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]);
172impl_bit_set_simd!([[u16;  8]], 128, [0 1 2 3 4 5 6 7]);
173impl_bit_set_simd!([[u32;  4]], 128, [0 1 2 3]);
174impl_bit_set_simd!([[u64;  2]], 128, [0 1]);
175
176// simd256
177impl_bit_set_simd!([[ u8; 32]], 256, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31]);
178impl_bit_set_simd!([[u16; 16]], 256, [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]);
179impl_bit_set_simd!([[u32;  8]], 256, [0 1 2 3 4 5 6 7]);
180impl_bit_set_simd!([[u64;  4]], 256, [0 1 2 3]);
181
182//----------------------------------------------------------------
183
184#[test]
185fn tests128() {
186	let mut bytes = [[0u8; 16]; 32];
187	let mut words = [[0u16; 8]; 16];
188	let mut dwords = [[0u32; 4]; 8];
189	let mut qwords = [[0u64; 2]; 4];
190
191	super::unary_tests(&mut bytes[..]);
192	super::unary_tests(&mut words[..]);
193	super::unary_tests(&mut dwords[..]);
194	super::unary_tests(&mut qwords[..]);
195}
196
197#[test]
198fn tests256() {
199	let mut bytes = [[0u8; 32]; 32];
200	let mut words = [[0u16; 16]; 16];
201	let mut dwords = [[0u32; 8]; 8];
202	let mut qwords = [[0u64; 4]; 4];
203
204	super::unary_tests(&mut bytes[..]);
205	super::unary_tests(&mut words[..]);
206	super::unary_tests(&mut dwords[..]);
207	super::unary_tests(&mut qwords[..]);
208}