// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. use crate::bits::bitblock::{BitBlock, Word}; use crate::bits::bitview::{BitView, MutableBitView}; use crate::bits::index_set::IndexSet; use crate::bits::{Bitwise, BitwiseBinaryOps, Dot, IndexAssignable, OverlapWeight}; use crate::NeutralElement; use super::standard_types::{BitIterator, BitsPerBlock}; use super::{are_supports_equal, BorrowAsBitIterator}; use super::{BitwiseNeutralElement, FromBits}; pub const WORD_COUNT_DEFAULT: usize = 8usize; pub fn block_count(length: usize, bits_per_block: usize) -> usize { let mut block_count = length / bits_per_block; if !length.is_multiple_of(bits_per_block) { block_count += 1; } block_count } #[must_use] #[derive(Eq, Clone, Debug)] pub struct BitVec { pub(crate) blocks: Vec<[Word; WORD_COUNT]>, } impl std::hash::Hash for BitVec { fn hash(&self, state: &mut H) { self.blocks.hash(state); } } impl BitVec { const fn bits_per_block() -> usize { <[Word; WORD_COUNT] as BitsPerBlock>::BITS_PER_BLOCK } pub fn of_length(length: usize) -> BitVec { Self::zeros(length) } pub fn zeros(length: usize) -> BitVec { BitVec { blocks: vec![[0; WORD_COUNT]; block_count(length, Self::bits_per_block())], } } #[must_use] pub fn top(&self) -> u64 { self.blocks[0][0] } pub fn top_mut(&mut self) -> &mut u64 { &mut self.blocks[0][0] } pub fn from_view( view: &BitView, ) -> BitVec { BitVec:: { blocks: view.blocks.to_vec(), } } pub fn from_view_mut( view: &MutableBitView, ) -> BitVec { BitVec:: { blocks: view.blocks.to_vec(), } } pub fn selected_from<'life, Iterable, const WORD_COUNT_IN: usize>( view: &'life BitView, support: Iterable, ) -> BitVec where Iterable: IntoIterator, Iterable::IntoIter: ExactSizeIterator, { let support_iterator = support.into_iter(); let mut bits = BitVec::::of_length(support_iterator.len()); for index in support_iterator { bits.assign_index(*index, view.index(*index)); } bits } #[must_use] pub fn as_view(&self) -> BitView<'_, WORD_COUNT> { BitView { blocks: &self.blocks, } } pub fn as_view_mut(&mut self) -> MutableBitView<'_, WORD_COUNT> { MutableBitView { blocks: &mut self.blocks, } } #[must_use] pub fn len(&self) -> usize { self.blocks.len() * <[Word; WORD_COUNT] as BitsPerBlock>::BITS_PER_BLOCK } #[must_use] pub fn is_empty(&self) -> bool { self.blocks.len() == 0 } } // Bit traits : Unary macro_rules! blocks_neutral_element_body { () => { type NeutralElementType = BitVec; fn neutral_element(&self) -> ::NeutralElementType { BitVec:: { blocks: self.blocks.neutral_element(), } } fn default_size_neutral_element() -> ::NeutralElementType { BitVec::::zeros(0) } fn neutral_element_of_size(size: usize) -> ::NeutralElementType { BitVec::::zeros(size) } }; } impl NeutralElement for BitVec { blocks_neutral_element_body!(); } impl NeutralElement for MutableBitView<'_, WORD_COUNT> { blocks_neutral_element_body!(); } impl NeutralElement for BitView<'_, WORD_COUNT> { blocks_neutral_element_body!(); } impl BitwiseNeutralElement for BitVec {} impl BitwiseNeutralElement for MutableBitView<'_, WORD_COUNT> {} impl BitwiseNeutralElement for BitView<'_, WORD_COUNT> {} macro_rules! blocks_bitwise_body { () => { fn index(&self, index: usize) -> bool { self.blocks.index(index) } fn support(&self) -> impl sorted_iter::SortedIterator { self.blocks.support() } fn weight(&self) -> usize { self.blocks.weight() } fn parity(&self) -> bool { self.blocks.parity() } fn is_zero(&self) -> bool { self.blocks.is_zero() } }; } impl Bitwise for BitVec { blocks_bitwise_body!(); } impl Bitwise for MutableBitView<'_, WORD_COUNT> { blocks_bitwise_body!(); } impl Bitwise for BitView<'_, WORD_COUNT> { blocks_bitwise_body!(); } impl Bitwise for BitBlock { blocks_bitwise_body!(); } impl Bitwise for &BitBlock { blocks_bitwise_body!(); } impl Bitwise for &mut BitBlock { blocks_bitwise_body!(); } macro_rules! blocks_index_assignable_body { () => { fn assign_index(&mut self, index: usize, to: bool) { self.blocks.assign_index(index, to) } fn negate_index(&mut self, index: usize) { self.blocks.negate_index(index) } fn clear_bits(&mut self) { self.blocks.clear_bits() } }; } impl IndexAssignable for BitVec { blocks_index_assignable_body!(); } impl IndexAssignable for MutableBitView<'_, WORD_COUNT> { blocks_index_assignable_body!(); } impl IndexAssignable for &mut BitBlock { blocks_index_assignable_body!(); } impl IndexAssignable for BitBlock { blocks_index_assignable_body!(); } macro_rules! borrow_as_bit_iterator_body { () => { type BitIterator<'life1> = BitIterator<'life1> where Self: 'life1; fn borrow_as_bit_iterator(&self) -> Self::BitIterator<'_> { self.blocks.borrow_as_bit_iterator() } }; } impl BorrowAsBitIterator for BitVec { borrow_as_bit_iterator_body!(); } impl BorrowAsBitIterator for BitBlock { borrow_as_bit_iterator_body!(); } impl BorrowAsBitIterator for &BitBlock { borrow_as_bit_iterator_body!(); } impl BorrowAsBitIterator for &mut BitBlock { borrow_as_bit_iterator_body!(); } impl BorrowAsBitIterator for MutableBitView<'_, WORD_COUNT> { borrow_as_bit_iterator_body!(); } impl BorrowAsBitIterator for BitView<'_, WORD_COUNT> { borrow_as_bit_iterator_body!(); } // Bit traits : Binary macro_rules! blocks_bitwise_binary_ops_body { ($other_type:ty) => { fn assign(&mut self, other: &$other_type) { self.blocks.assign(&other.blocks) } fn bitxor_assign(&mut self, other: &$other_type) { self.blocks.bitxor_assign(&other.blocks) } fn bitand_assign(&mut self, other: &$other_type) { self.blocks.bitand_assign(&other.blocks) } }; } macro_rules! blocks_bitwise_binary_ops_refs { ($other_type:ty,$vec_type:ty) => { impl BitwiseBinaryOps<$other_type> for $vec_type { blocks_bitwise_binary_ops_body!($other_type); } }; } macro_rules! blocks_bitwise_binary_ops { ($vec_type:ty) => { blocks_bitwise_binary_ops_refs!(BitVec, $vec_type); blocks_bitwise_binary_ops_refs!(BitView<'_, WORD_COUNT>, $vec_type); blocks_bitwise_binary_ops_refs!(MutableBitView<'_, WORD_COUNT>, $vec_type); }; } blocks_bitwise_binary_ops!(BitVec); blocks_bitwise_binary_ops!(MutableBitView<'_, WORD_COUNT>); macro_rules! bitblock_bitwise_binary_ops { ($bitblock_type:ty) => { blocks_bitwise_binary_ops_refs!(BitBlock, $bitblock_type); blocks_bitwise_binary_ops_refs!(&BitBlock, $bitblock_type); blocks_bitwise_binary_ops_refs!(&mut BitBlock, $bitblock_type); }; } bitblock_bitwise_binary_ops!(BitBlock); bitblock_bitwise_binary_ops!(&mut BitBlock); macro_rules! blocks_dot_body { ($other_type:ty) => { fn dot(&self, other: &$other_type) -> bool { self.blocks.dot(&other.blocks) } }; } macro_rules! blocks_overlap_weight_body { ($other_type:ty) => { fn and_weight(&self, other: &$other_type) -> usize { self.blocks.and_weight(&other.blocks) } fn or_weight(&self, other: &$other_type) -> usize { self.blocks.or_weight(&other.blocks) } }; } macro_rules! bitblock_dot_refs { ($other_type:ty,$bitblock_type:ty) => { impl Dot<$other_type> for $bitblock_type { blocks_dot_body!($other_type); } impl OverlapWeight<$other_type> for $bitblock_type { blocks_overlap_weight_body!($other_type); } }; } macro_rules! blocks_dot { ($vec_type:ty) => { bitblock_dot_refs!(BitVec, $vec_type); bitblock_dot_refs!(BitView<'_, WORD_COUNT>, $vec_type); bitblock_dot_refs!(MutableBitView<'_, WORD_COUNT>, $vec_type); }; } blocks_dot!(BitVec); blocks_dot!(BitView<'_, WORD_COUNT>); blocks_dot!(MutableBitView<'_, WORD_COUNT>); macro_rules! bitblock_dot { ($bitblock_type:ty) => { bitblock_dot_refs!(BitBlock, $bitblock_type); bitblock_dot_refs!(&BitBlock, $bitblock_type); bitblock_dot_refs!(&mut BitBlock, $bitblock_type); }; } bitblock_dot!(BitBlock); bitblock_dot!(&BitBlock); bitblock_dot!(&mut BitBlock); // Standard traits impl FromIterator for BitVec { fn from_iter>(iterator: Iterator) -> Self { let mut blocks = vec![]; let mut iterator = iterator.into_iter(); // Note: once `Iterator::array_chunks` is stabilized, we can use that instead. loop { let mut block = [0 as Word; WORD_COUNT]; for index in 0..Self::bits_per_block() { match iterator.next() { Some(bit) => block.assign_index(index, bit), None if index == 0 => return BitVec { blocks }, None => { blocks.push(block); return BitVec { blocks }; } } } blocks.push(block); } } } macro_rules! blocks_partial_eq_body { ($other_type:ty) => { fn eq(&self, other: &$other_type) -> bool { self.blocks == other.blocks } }; } macro_rules! blocks_partial_eq_body_bool { ($other_type:ty) => { fn eq(&self, other: &$other_type) -> bool { are_supports_equal(self, other) } }; } macro_rules! blocks_partial_eq_vec_bool { ($vec_bool:ty,$vec_type:ty) => { impl PartialEq<$vec_bool> for $vec_type { blocks_partial_eq_body_bool!($vec_bool); } impl PartialEq<$vec_type> for $vec_bool { blocks_partial_eq_body_bool!($vec_type); } }; } macro_rules! blocks_partial_eq { ($vec_type:ty) => { impl PartialEq> for $vec_type { blocks_partial_eq_body!(BitVec); } impl PartialEq> for $vec_type { blocks_partial_eq_body!(MutableBitView<'_, WORD_COUNT>); } impl PartialEq> for $vec_type { blocks_partial_eq_body!(BitView<'_, WORD_COUNT>); } impl PartialEq for $vec_type { blocks_partial_eq_body_bool!(IndexSet); } blocks_partial_eq_vec_bool!(Vec, $vec_type); blocks_partial_eq_vec_bool!(&[bool], $vec_type); blocks_partial_eq_vec_bool!(&mut [bool], $vec_type); }; } blocks_partial_eq!(BitVec); blocks_partial_eq!(MutableBitView<'_, WORD_COUNT>); blocks_partial_eq!(BitView<'_, WORD_COUNT>); macro_rules! bitblocks_partial_eq { ($vec_type:ty) => { impl PartialEq for $vec_type { blocks_partial_eq_body_bool!(IndexSet); } blocks_partial_eq_vec_bool!(Vec, $vec_type); blocks_partial_eq_vec_bool!(&[bool], $vec_type); blocks_partial_eq_vec_bool!(&mut [bool], $vec_type); }; } bitblocks_partial_eq!(BitBlock); bitblocks_partial_eq!(&mut BitBlock); bitblocks_partial_eq!(&BitBlock); macro_rules! blocks_into_iterator_body { () => { type Item = bool; type IntoIter = BitIterator<'life>; fn into_iter(self) -> Self::IntoIter { self.blocks.borrow_as_bit_iterator() } }; } impl<'life, const WORD_COUNT: usize> IntoIterator for &'life BitVec { blocks_into_iterator_body!(); } impl<'life, const WORD_COUNT: usize> IntoIterator for &'life MutableBitView<'_, WORD_COUNT> { blocks_into_iterator_body!(); } impl<'life, const WORD_COUNT: usize> IntoIterator for &'life BitView<'_, WORD_COUNT> { blocks_into_iterator_body!(); } impl BitVec { #[must_use] pub fn iter(&self) -> BitIterator<'_> { <&Self as IntoIterator>::into_iter(self) } } impl BitView<'_, WORD_COUNT> { #[must_use] pub fn iter(&self) -> BitIterator<'_> { <&Self as IntoIterator>::into_iter(self) } } impl MutableBitView<'_, WORD_COUNT> { #[must_use] pub fn iter(&self) -> BitIterator<'_> { <&Self as IntoIterator>::into_iter(self) } } impl< Other: BorrowAsBitIterator + Bitwise, T: NeutralElement + IndexAssignable + BorrowAsBitIterator, > FromBits for T { fn from_bits(other: &Other) -> Self { let iter = other.borrow_as_bit_iterator(); let mut res = Self::neutral_element_of_size(iter.len()); for index in other.support() { res.assign_index(index, true); } res } }