use crate::bit::bitwise_for_slice as slice;
use crate::bit::bitwise_via_borrow as borrow;
use crate::bit::unsigned_integers::BitIterator;
use crate::{BitLength, Bitwise, BitwiseMut, BitwisePair, BitwisePairMut, IntoBitIterator};
use std::borrow::{Borrow, BorrowMut};
use std::ops::{Deref, DerefMut};
pub const BIT_BLOCK_WORD_COUNT: usize = 8usize;
pub type Word = u64;
pub type BitBlockInnerArray = [Word; BIT_BLOCK_WORD_COUNT];
#[repr(C, align(64))]
#[derive(Eq, Clone, Debug, Hash, PartialEq, Default)]
pub struct BitBlock {
pub blocks: BitBlockInnerArray,
}
impl Borrow<BitBlockInnerArray> for BitBlock {
fn borrow(&self) -> &BitBlockInnerArray {
&self.blocks
}
}
impl BorrowMut<BitBlockInnerArray> for BitBlock {
fn borrow_mut(&mut self) -> &mut BitBlockInnerArray {
&mut self.blocks
}
}
impl Deref for BitBlock {
type Target = BitBlockInnerArray;
fn deref(&self) -> &Self::Target {
&self.blocks
}
}
impl DerefMut for BitBlock {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.blocks
}
}
impl BitLength for BitBlock {
fn bit_len(&self) -> usize {
Self::BLOCK_BIT_LEN
}
const BLOCK_BIT_LEN: usize = 8 * size_of::<BitBlockInnerArray>();
}
delegate_bitwise!(BitBlock, borrow::BitwiseViaBorrow<BitBlockInnerArray>);
delegate_bitwise_mut!(BitBlock, borrow::BitwiseMutViaBorrow<BitBlockInnerArray>);
delegate_bitwise_pair!(BitBlock, BitBlock, borrow::BitwisePairViaBorrow<BitBlockInnerArray, BitBlockInnerArray>);
delegate_bitwise_pair_mut!(BitBlock, BitBlock, borrow::BitwisePairMutViaBorrow<BitBlockInnerArray, BitBlockInnerArray>);
impl From<BitBlockInnerArray> for BitBlock {
fn from(blocks: BitBlockInnerArray) -> Self {
Self { blocks }
}
}
impl IntoBitIterator for BitBlock {
type BitIterator = <BitBlockInnerArray as IntoBitIterator>::BitIterator;
fn iter_bits(self) -> Self::BitIterator {
self.blocks.iter_bits()
}
}
impl<'life> IntoBitIterator for &'life BitBlock {
type BitIterator = <&'life BitBlockInnerArray as IntoBitIterator>::BitIterator;
fn iter_bits(self) -> Self::BitIterator {
<BitBlock as Borrow<BitBlockInnerArray>>::borrow(self).iter_bits()
}
}
impl<'life> IntoIterator for &'life BitBlock {
type Item = bool;
type IntoIter = BitIterator<'life>;
fn into_iter(self) -> Self::IntoIter {
self.iter_bits()
}
}
impl BitBlock {
#[must_use]
pub fn iter(&self) -> BitIterator<'_> {
<&Self as IntoIterator>::into_iter(self)
}
}
impl FromIterator<bool> for BitBlock {
fn from_iter<Iterator: IntoIterator<Item = bool>>(iterator: Iterator) -> Self {
let mut res: BitBlock = BitBlock::default();
for (index, bit) in iterator.into_iter().enumerate() {
res.assign_index(index, bit);
}
res
}
}
delegate_bitwise!([BitBlock], slice::BitwiseForSlice<BitBlock>);
delegate_bitwise_mut!([BitBlock], slice::BitwiseMutForSlice<BitBlock>);
delegate_bitwise_pair!([BitBlock], [BitBlock], slice::BitwisePairForSlice<BitBlock>);
delegate_bitwise_pair_mut!([BitBlock], [BitBlock], slice::BitwisePairMutForSlice<BitBlock>);
impl<'life> IntoBitIterator for &'life [BitBlock] {
type BitIterator = <Self as slice::IntoBitIteratorForSlice<'life, BitBlock>>::BitIterator;
fn iter_bits(self) -> Self::BitIterator {
<Self as slice::IntoBitIteratorForSlice<BitBlock>>::iter_bits(self)
}
}
impl BitLength for [BitBlock] {
fn bit_len(&self) -> usize {
self.len() * BitBlock::BLOCK_BIT_LEN
}
const BLOCK_BIT_LEN: usize = BitBlock::BLOCK_BIT_LEN;
}
impl BitBlock {
#[must_use]
pub fn ones() -> Self {
[u64::MAX; BIT_BLOCK_WORD_COUNT].into()
}
pub fn clear(&mut self) {
self.blocks.fill(0);
}
}
#[must_use]
#[derive(Clone, Debug, Hash, PartialEq)]
pub struct BitAccessor {
word_index: usize,
bitmask: Word,
}
impl BitAccessor {
pub fn for_index<T>(index: usize) -> Self
where
T: BitLength,
{
assert!(index < T::BLOCK_BIT_LEN);
unsafe { Self::for_index_unchecked(index) }
}
pub unsafe fn for_index_unchecked(index: usize) -> Self {
let word_index = index / (Word::BITS as usize);
let bit_index = index % (Word::BITS as usize);
Self {
word_index,
bitmask: 1 << bit_index,
}
}
#[must_use]
pub fn array_value_of<const SIZE: usize>(&self, block: &[Word; SIZE]) -> bool {
let word = unsafe { block.get_unchecked(self.word_index) };
(*word & self.bitmask) != 0
}
pub fn array_bitxor<const SIZE: usize>(&self, block: &mut [Word; SIZE]) {
let word: &mut Word = unsafe { block.get_unchecked_mut(self.word_index) };
*word ^= self.bitmask;
}
pub fn array_set_value_of<const SIZE: usize>(&self, block: &mut [Word; SIZE], to: bool) {
let word = unsafe { block.get_unchecked_mut(self.word_index) };
if to {
*word |= self.bitmask;
} else {
*word &= !self.bitmask;
}
}
}