1use core::ops::*;
6
7use typenum::*;
8
9use crate::types::{BitOps, Bits};
10
11#[cfg(feature = "std")]
12use std::fmt::{Debug, Error, Formatter};
13
14pub struct Bitmap<Size: Bits> {
22 pub(crate) data: Size::Store,
23}
24
25impl<Size: Bits> Clone for Bitmap<Size> {
26 fn clone(&self) -> Self {
27 Bitmap { data: self.data }
28 }
29}
30
31impl<Size: Bits> Copy for Bitmap<Size> {}
32
33impl<Size: Bits> Default for Bitmap<Size> {
34 fn default() -> Self {
35 Bitmap {
36 data: Size::Store::default(),
37 }
38 }
39}
40
41impl<Size: Bits> PartialEq for Bitmap<Size> {
42 fn eq(&self, other: &Self) -> bool {
43 self.data == other.data
44 }
45}
46
47#[cfg(feature = "std")]
48impl<Size: Bits> Debug for Bitmap<Size> {
49 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
50 write!(f, "{}", Size::Store::to_hex(&self.data))
51 }
52}
53
54impl<Size: Bits> Bitmap<Size> {
55 #[inline]
57 pub fn new() -> Self {
58 Self::default()
59 }
60
61 #[inline]
64 pub fn mask(bits: usize) -> Self {
65 debug_assert!(bits < Size::USIZE);
66 Self {
67 data: Size::Store::make_mask(bits),
68 }
69 }
70
71 #[inline]
73 pub fn from_value(data: Size::Store) -> Self {
74 Self { data }
75 }
76
77 #[inline]
79 pub fn into_value(self) -> Size::Store {
80 self.data
81 }
82
83 #[inline]
85 pub fn len(self) -> usize {
86 Size::Store::len(&self.data)
87 }
88
89 #[inline]
91 pub fn is_empty(self) -> bool {
92 self.first_index().is_none()
93 }
94
95 #[inline]
97 pub fn get(self, index: usize) -> bool {
98 debug_assert!(index < Size::USIZE);
99 Size::Store::get(&self.data, index)
100 }
101
102 #[inline]
106 pub fn set(&mut self, index: usize, value: bool) -> bool {
107 debug_assert!(index < Size::USIZE);
108 Size::Store::set(&mut self.data, index, value)
109 }
110
111 #[inline]
113 pub fn first_index(self) -> Option<usize> {
114 Size::Store::first_index(&self.data)
115 }
116
117 #[inline]
119 pub fn invert(&mut self) {
120 Size::Store::invert(&mut self.data);
121 }
122}
123
124impl<'a, Size: Bits> IntoIterator for &'a Bitmap<Size> {
125 type Item = usize;
126 type IntoIter = Iter<'a, Size>;
127
128 fn into_iter(self) -> Self::IntoIter {
129 Iter {
130 index: 0,
131 data: self,
132 }
133 }
134}
135
136impl<Size: Bits> BitAnd for Bitmap<Size> {
137 type Output = Self;
138 fn bitand(mut self, rhs: Self) -> Self::Output {
139 Size::Store::bit_and(&mut self.data, &rhs.data);
140 self
141 }
142}
143
144impl<Size: Bits> BitOr for Bitmap<Size> {
145 type Output = Self;
146 fn bitor(mut self, rhs: Self) -> Self::Output {
147 Size::Store::bit_or(&mut self.data, &rhs.data);
148 self
149 }
150}
151
152impl<Size: Bits> BitXor for Bitmap<Size> {
153 type Output = Self;
154 fn bitxor(mut self, rhs: Self) -> Self::Output {
155 Size::Store::bit_xor(&mut self.data, &rhs.data);
156 self
157 }
158}
159
160impl<Size: Bits> Not for Bitmap<Size> {
161 type Output = Self;
162 fn not(mut self) -> Self::Output {
163 Size::Store::invert(&mut self.data);
164 self
165 }
166}
167
168impl<Size: Bits> BitAndAssign for Bitmap<Size> {
169 fn bitand_assign(&mut self, rhs: Self) {
170 Size::Store::bit_and(&mut self.data, &rhs.data);
171 }
172}
173
174impl<Size: Bits> BitOrAssign for Bitmap<Size> {
175 fn bitor_assign(&mut self, rhs: Self) {
176 Size::Store::bit_or(&mut self.data, &rhs.data);
177 }
178}
179
180impl<Size: Bits> BitXorAssign for Bitmap<Size> {
181 fn bitxor_assign(&mut self, rhs: Self) {
182 Size::Store::bit_xor(&mut self.data, &rhs.data);
183 }
184}
185
186impl From<[u128; 2]> for Bitmap<U256> {
187 fn from(data: [u128; 2]) -> Self {
188 Bitmap { data }
189 }
190}
191
192impl From<[u128; 3]> for Bitmap<U384> {
193 fn from(data: [u128; 3]) -> Self {
194 Bitmap { data }
195 }
196}
197
198impl From<[u128; 4]> for Bitmap<U512> {
199 fn from(data: [u128; 4]) -> Self {
200 Bitmap { data }
201 }
202}
203
204impl From<[u128; 5]> for Bitmap<U640> {
205 fn from(data: [u128; 5]) -> Self {
206 Bitmap { data }
207 }
208}
209
210impl From<[u128; 6]> for Bitmap<U768> {
211 fn from(data: [u128; 6]) -> Self {
212 Bitmap { data }
213 }
214}
215
216impl From<[u128; 7]> for Bitmap<U896> {
217 fn from(data: [u128; 7]) -> Self {
218 Bitmap { data }
219 }
220}
221
222impl From<[u128; 8]> for Bitmap<U1024> {
223 fn from(data: [u128; 8]) -> Self {
224 Bitmap { data }
225 }
226}
227
228impl Into<[u128; 2]> for Bitmap<U256> {
229 fn into(self) -> [u128; 2] {
230 self.data
231 }
232}
233
234impl Into<[u128; 3]> for Bitmap<U384> {
235 fn into(self) -> [u128; 3] {
236 self.data
237 }
238}
239
240impl Into<[u128; 4]> for Bitmap<U512> {
241 fn into(self) -> [u128; 4] {
242 self.data
243 }
244}
245
246impl Into<[u128; 5]> for Bitmap<U640> {
247 fn into(self) -> [u128; 5] {
248 self.data
249 }
250}
251
252impl Into<[u128; 6]> for Bitmap<U768> {
253 fn into(self) -> [u128; 6] {
254 self.data
255 }
256}
257
258impl Into<[u128; 7]> for Bitmap<U896> {
259 fn into(self) -> [u128; 7] {
260 self.data
261 }
262}
263
264impl Into<[u128; 8]> for Bitmap<U1024> {
265 fn into(self) -> [u128; 8] {
266 self.data
267 }
268}
269
270pub struct Iter<'a, Size: Bits> {
288 index: usize,
289 data: &'a Bitmap<Size>,
290}
291
292impl<'a, Size: Bits> Iterator for Iter<'a, Size> {
293 type Item = usize;
294
295 fn next(&mut self) -> Option<Self::Item> {
296 if self.index >= Size::USIZE {
297 return None;
298 }
299 if self.data.get(self.index) {
300 self.index += 1;
301 Some(self.index - 1)
302 } else {
303 self.index += 1;
304 self.next()
305 }
306 }
307}
308
309#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
310#[allow(clippy::cast_ptr_alignment)]
311mod x86_arch {
312 use super::*;
313 #[cfg(target_arch = "x86")]
314 use core::arch::x86::*;
315 #[cfg(target_arch = "x86_64")]
316 use core::arch::x86_64::*;
317
318 impl Bitmap<U128> {
319 #[target_feature(enable = "sse2")]
320 pub unsafe fn load_m128i(&self) -> __m128i {
321 _mm_loadu_si128(&self.data as *const _ as *const __m128i)
322 }
323 }
324
325 impl Bitmap<U256> {
326 #[target_feature(enable = "sse2")]
327 pub unsafe fn load_m128i(&self) -> [__m128i; 2] {
328 let ptr = &self.data as *const _ as *const __m128i;
329 [_mm_loadu_si128(ptr), _mm_loadu_si128(ptr.add(1))]
330 }
331
332 #[target_feature(enable = "avx")]
333 pub unsafe fn load_m256i(&self) -> __m256i {
334 _mm256_loadu_si256(&self.data as *const _ as *const __m256i)
335 }
336 }
337
338 impl Bitmap<U512> {
339 #[target_feature(enable = "sse2")]
340 pub unsafe fn load_m128i(&self) -> [__m128i; 4] {
341 let ptr = &self.data as *const _ as *const __m128i;
342 [
343 _mm_loadu_si128(ptr),
344 _mm_loadu_si128(ptr.add(1)),
345 _mm_loadu_si128(ptr.add(2)),
346 _mm_loadu_si128(ptr.add(3)),
347 ]
348 }
349
350 #[target_feature(enable = "avx")]
351 pub unsafe fn load_m256i(&self) -> [__m256i; 2] {
352 let ptr = &self.data as *const _ as *const __m256i;
353 [_mm256_loadu_si256(ptr), _mm256_loadu_si256(ptr.add(1))]
354 }
355 }
356
357 impl Bitmap<U768> {
358 #[target_feature(enable = "sse2")]
359 pub unsafe fn load_m128i(&self) -> [__m128i; 6] {
360 let ptr = &self.data as *const _ as *const __m128i;
361 [
362 _mm_loadu_si128(ptr),
363 _mm_loadu_si128(ptr.add(1)),
364 _mm_loadu_si128(ptr.add(2)),
365 _mm_loadu_si128(ptr.add(3)),
366 _mm_loadu_si128(ptr.add(4)),
367 _mm_loadu_si128(ptr.add(5)),
368 ]
369 }
370
371 #[target_feature(enable = "avx")]
372 pub unsafe fn load_m256i(&self) -> [__m256i; 3] {
373 let ptr = &self.data as *const _ as *const __m256i;
374 [
375 _mm256_loadu_si256(ptr),
376 _mm256_loadu_si256(ptr.add(1)),
377 _mm256_loadu_si256(ptr.add(2)),
378 ]
379 }
380 }
381
382 impl Bitmap<U1024> {
383 #[target_feature(enable = "sse2")]
384 pub unsafe fn load_m128i(&self) -> [__m128i; 8] {
385 let ptr = &self.data as *const _ as *const __m128i;
386 [
387 _mm_loadu_si128(ptr),
388 _mm_loadu_si128(ptr.add(1)),
389 _mm_loadu_si128(ptr.add(2)),
390 _mm_loadu_si128(ptr.add(3)),
391 _mm_loadu_si128(ptr.add(4)),
392 _mm_loadu_si128(ptr.add(5)),
393 _mm_loadu_si128(ptr.add(6)),
394 _mm_loadu_si128(ptr.add(7)),
395 ]
396 }
397
398 #[target_feature(enable = "avx")]
399 pub unsafe fn load_m256i(&self) -> [__m256i; 4] {
400 let ptr = &self.data as *const _ as *const __m256i;
401 [
402 _mm256_loadu_si256(ptr),
403 _mm256_loadu_si256(ptr.add(1)),
404 _mm256_loadu_si256(ptr.add(2)),
405 _mm256_loadu_si256(ptr.add(3)),
406 ]
407 }
408 }
409
410 impl From<__m128i> for Bitmap<U128> {
411 fn from(data: __m128i) -> Self {
412 Self {
413 data: unsafe { core::mem::transmute(data) },
414 }
415 }
416 }
417
418 impl From<__m256i> for Bitmap<U256> {
419 fn from(data: __m256i) -> Self {
420 Self {
421 data: unsafe { core::mem::transmute(data) },
422 }
423 }
424 }
425
426 impl Into<__m128i> for Bitmap<U128> {
427 fn into(self) -> __m128i {
428 unsafe { self.load_m128i() }
429 }
430 }
431
432 impl Into<__m256i> for Bitmap<U256> {
433 fn into(self) -> __m256i {
434 unsafe { self.load_m256i() }
435 }
436 }
437
438 #[cfg(test)]
439 mod test {
440 use super::*;
441
442 struct AlignmentTester<B>
443 where
444 B: Bits,
445 {
446 _byte: u8,
447 bits: Bitmap<B>,
448 }
449
450 #[test]
451 fn load_128() {
452 let mut t: AlignmentTester<U128> = AlignmentTester {
453 _byte: 0,
454 bits: Bitmap::new(),
455 };
456 t.bits.set(5, true);
457 let m = unsafe { t.bits.load_m128i() };
458 let mut bits: Bitmap<U128> = m.into();
459 assert!(bits.set(5, false));
460 assert!(bits.is_empty());
461 }
462
463 #[test]
464 fn load_256() {
465 let mut t: AlignmentTester<U256> = AlignmentTester {
466 _byte: 0,
467 bits: Bitmap::new(),
468 };
469 t.bits.set(5, true);
470 let m = unsafe { t.bits.load_m256i() };
471 let mut bits: Bitmap<U256> = m.into();
472 assert!(bits.set(5, false));
473 assert!(bits.is_empty());
474 }
475 }
476}
477
478#[cfg(test)]
479mod test {
480 use super::*;
481 use proptest::collection::btree_set;
482 use proptest::proptest;
483 use typenum::{U1024, U64};
484
485 proptest! {
486 #[test]
487 fn get_set_and_iter_64(bits in btree_set(0..64usize, 0..64)) {
488 let mut bitmap = Bitmap::<U64>::new();
489 for i in &bits {
490 bitmap.set(*i, true);
491 }
492 for i in 0..64 {
493 assert_eq!(bitmap.get(i), bits.contains(&i));
494 }
495 assert!(bitmap.into_iter().eq(bits.into_iter()));
496 }
497
498 #[test]
499 fn get_set_and_iter_1024(bits in btree_set(0..1024usize, 0..1024)) {
500 let mut bitmap = Bitmap::<U1024>::new();
501 for i in &bits {
502 bitmap.set(*i, true);
503 }
504 for i in 0..1024 {
505 assert_eq!(bitmap.get(i), bits.contains(&i));
506 }
507 assert!(bitmap.into_iter().eq(bits.into_iter()));
508 }
509 }
510}