// 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<const WORD_COUNT: usize = WORD_COUNT_DEFAULT> {
pub(crate) blocks: Vec<[Word; WORD_COUNT]>,
}
impl<const WORD_COUNT: usize> std::hash::Hash for BitVec<WORD_COUNT> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.blocks.hash(state);
}
}
impl<const WORD_COUNT: usize> BitVec<WORD_COUNT> {
const fn bits_per_block() -> usize {
<[Word; WORD_COUNT] as BitsPerBlock>::BITS_PER_BLOCK
}
pub fn of_length(length: usize) -> BitVec<WORD_COUNT> {
Self::zeros(length)
}
pub fn zeros(length: usize) -> BitVec<WORD_COUNT> {
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<const WORD_COUNT_IN: usize>(
view: &BitView<WORD_COUNT_IN>,
) -> BitVec<WORD_COUNT_IN> {
BitVec::<WORD_COUNT_IN> {
blocks: view.blocks.to_vec(),
}
}
pub fn from_view_mut<const WORD_COUNT_IN: usize>(
view: &MutableBitView<WORD_COUNT_IN>,
) -> BitVec<WORD_COUNT_IN> {
BitVec::<WORD_COUNT_IN> {
blocks: view.blocks.to_vec(),
}
}
pub fn selected_from<'life, Iterable, const WORD_COUNT_IN: usize>(
view: &'life BitView<WORD_COUNT_IN>,
support: Iterable,
) -> BitVec<WORD_COUNT_IN>
where
Iterable: IntoIterator<Item = &'life usize>,
Iterable::IntoIter: ExactSizeIterator<Item = &'life usize>,
{
let support_iterator = support.into_iter();
let mut bits = BitVec::<WORD_COUNT_IN>::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<WORD_COUNT>;
fn neutral_element(&self) -> <Self as NeutralElement>::NeutralElementType {
BitVec::<WORD_COUNT> {
blocks: self.blocks.neutral_element(),
}
}
fn default_size_neutral_element() -> <Self as NeutralElement>::NeutralElementType {
BitVec::<WORD_COUNT>::zeros(0)
}
fn neutral_element_of_size(size: usize) -> <Self as NeutralElement>::NeutralElementType {
BitVec::<WORD_COUNT>::zeros(size)
}
};
}
impl<const WORD_COUNT: usize> NeutralElement for BitVec<WORD_COUNT> {
blocks_neutral_element_body!();
}
impl<const WORD_COUNT: usize> NeutralElement for MutableBitView<'_, WORD_COUNT> {
blocks_neutral_element_body!();
}
impl<const WORD_COUNT: usize> NeutralElement for BitView<'_, WORD_COUNT> {
blocks_neutral_element_body!();
}
impl<const WORD_COUNT: usize> BitwiseNeutralElement for BitVec<WORD_COUNT> {}
impl<const WORD_COUNT: usize> BitwiseNeutralElement for MutableBitView<'_, WORD_COUNT> {}
impl<const WORD_COUNT: usize> 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<Item = usize> {
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<const WORD_COUNT: usize> Bitwise for BitVec<WORD_COUNT> {
blocks_bitwise_body!();
}
impl<const WORD_COUNT: usize> Bitwise for MutableBitView<'_, WORD_COUNT> {
blocks_bitwise_body!();
}
impl<const WORD_COUNT: usize> Bitwise for BitView<'_, WORD_COUNT> {
blocks_bitwise_body!();
}
impl<const WORD_COUNT: usize> Bitwise for BitBlock<WORD_COUNT> {
blocks_bitwise_body!();
}
impl<const WORD_COUNT: usize> Bitwise for &BitBlock<WORD_COUNT> {
blocks_bitwise_body!();
}
impl<const WORD_COUNT: usize> Bitwise for &mut BitBlock<WORD_COUNT> {
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<const WORD_COUNT: usize> IndexAssignable for BitVec<WORD_COUNT> {
blocks_index_assignable_body!();
}
impl<const WORD_COUNT: usize> IndexAssignable for MutableBitView<'_, WORD_COUNT> {
blocks_index_assignable_body!();
}
impl<const WORD_COUNT: usize> IndexAssignable for &mut BitBlock<WORD_COUNT> {
blocks_index_assignable_body!();
}
impl<const WORD_COUNT: usize> IndexAssignable for BitBlock<WORD_COUNT> {
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<const WORD_COUNT: usize> BorrowAsBitIterator for BitVec<WORD_COUNT> {
borrow_as_bit_iterator_body!();
}
impl<const WORD_COUNT: usize> BorrowAsBitIterator for BitBlock<WORD_COUNT> {
borrow_as_bit_iterator_body!();
}
impl<const WORD_COUNT: usize> BorrowAsBitIterator for &BitBlock<WORD_COUNT> {
borrow_as_bit_iterator_body!();
}
impl<const WORD_COUNT: usize> BorrowAsBitIterator for &mut BitBlock<WORD_COUNT> {
borrow_as_bit_iterator_body!();
}
impl<const WORD_COUNT: usize> BorrowAsBitIterator for MutableBitView<'_, WORD_COUNT> {
borrow_as_bit_iterator_body!();
}
impl<const WORD_COUNT: usize> 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<const WORD_COUNT: usize> 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<WORD_COUNT>, $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<WORD_COUNT>);
blocks_bitwise_binary_ops!(MutableBitView<'_, WORD_COUNT>);
macro_rules! bitblock_bitwise_binary_ops {
($bitblock_type:ty) => {
blocks_bitwise_binary_ops_refs!(BitBlock<WORD_COUNT>, $bitblock_type);
blocks_bitwise_binary_ops_refs!(&BitBlock<WORD_COUNT>, $bitblock_type);
blocks_bitwise_binary_ops_refs!(&mut BitBlock<WORD_COUNT>, $bitblock_type);
};
}
bitblock_bitwise_binary_ops!(BitBlock<WORD_COUNT>);
bitblock_bitwise_binary_ops!(&mut BitBlock<WORD_COUNT>);
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<const WORD_COUNT: usize> Dot<$other_type> for $bitblock_type {
blocks_dot_body!($other_type);
}
impl<const WORD_COUNT: usize> OverlapWeight<$other_type> for $bitblock_type {
blocks_overlap_weight_body!($other_type);
}
};
}
macro_rules! blocks_dot {
($vec_type:ty) => {
bitblock_dot_refs!(BitVec<WORD_COUNT>, $vec_type);
bitblock_dot_refs!(BitView<'_, WORD_COUNT>, $vec_type);
bitblock_dot_refs!(MutableBitView<'_, WORD_COUNT>, $vec_type);
};
}
blocks_dot!(BitVec<WORD_COUNT>);
blocks_dot!(BitView<'_, WORD_COUNT>);
blocks_dot!(MutableBitView<'_, WORD_COUNT>);
macro_rules! bitblock_dot {
($bitblock_type:ty) => {
bitblock_dot_refs!(BitBlock<WORD_COUNT>, $bitblock_type);
bitblock_dot_refs!(&BitBlock<WORD_COUNT>, $bitblock_type);
bitblock_dot_refs!(&mut BitBlock<WORD_COUNT>, $bitblock_type);
};
}
bitblock_dot!(BitBlock<WORD_COUNT>);
bitblock_dot!(&BitBlock<WORD_COUNT>);
bitblock_dot!(&mut BitBlock<WORD_COUNT>);
// Standard traits
impl<const WORD_COUNT: usize> FromIterator<bool> for BitVec<WORD_COUNT> {
fn from_iter<Iterator: IntoIterator<Item = bool>>(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<const WORD_COUNT: usize> PartialEq<$vec_bool> for $vec_type {
blocks_partial_eq_body_bool!($vec_bool);
}
impl<const WORD_COUNT: usize> PartialEq<$vec_type> for $vec_bool {
blocks_partial_eq_body_bool!($vec_type);
}
};
}
macro_rules! blocks_partial_eq {
($vec_type:ty) => {
impl<const WORD_COUNT: usize> PartialEq<BitVec<WORD_COUNT>> for $vec_type {
blocks_partial_eq_body!(BitVec<WORD_COUNT>);
}
impl<const WORD_COUNT: usize> PartialEq<MutableBitView<'_, WORD_COUNT>> for $vec_type {
blocks_partial_eq_body!(MutableBitView<'_, WORD_COUNT>);
}
impl<const WORD_COUNT: usize> PartialEq<BitView<'_, WORD_COUNT>> for $vec_type {
blocks_partial_eq_body!(BitView<'_, WORD_COUNT>);
}
impl<const WORD_COUNT: usize> PartialEq<IndexSet> for $vec_type {
blocks_partial_eq_body_bool!(IndexSet);
}
blocks_partial_eq_vec_bool!(Vec<bool>, $vec_type);
blocks_partial_eq_vec_bool!(&[bool], $vec_type);
blocks_partial_eq_vec_bool!(&mut [bool], $vec_type);
};
}
blocks_partial_eq!(BitVec<WORD_COUNT>);
blocks_partial_eq!(MutableBitView<'_, WORD_COUNT>);
blocks_partial_eq!(BitView<'_, WORD_COUNT>);
macro_rules! bitblocks_partial_eq {
($vec_type:ty) => {
impl<const WORD_COUNT: usize> PartialEq<IndexSet> for $vec_type {
blocks_partial_eq_body_bool!(IndexSet);
}
blocks_partial_eq_vec_bool!(Vec<bool>, $vec_type);
blocks_partial_eq_vec_bool!(&[bool], $vec_type);
blocks_partial_eq_vec_bool!(&mut [bool], $vec_type);
};
}
bitblocks_partial_eq!(BitBlock<WORD_COUNT>);
bitblocks_partial_eq!(&mut BitBlock<WORD_COUNT>);
bitblocks_partial_eq!(&BitBlock<WORD_COUNT>);
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<WORD_COUNT> {
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<const WORD_COUNT: usize> BitVec<WORD_COUNT> {
#[must_use]
pub fn iter(&self) -> BitIterator<'_> {
<&Self as IntoIterator>::into_iter(self)
}
}
impl<const WORD_COUNT: usize> BitView<'_, WORD_COUNT> {
#[must_use]
pub fn iter(&self) -> BitIterator<'_> {
<&Self as IntoIterator>::into_iter(self)
}
}
impl<const WORD_COUNT: usize> MutableBitView<'_, WORD_COUNT> {
#[must_use]
pub fn iter(&self) -> BitIterator<'_> {
<&Self as IntoIterator>::into_iter(self)
}
}
impl<
Other: BorrowAsBitIterator + Bitwise,
T: NeutralElement<NeutralElementType = Self> + IndexAssignable + BorrowAsBitIterator,
> FromBits<Other> 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
}
}microsoft/qdk
Publicmirrored from https://github.com/microsoft/qdkAvailable
source/paulimer/src/bits/bitvec.rs
527lines · modepreview