use super::api::BitSliceIndex;
use crate::{
access::BitAccess,
indices::Indexable,
order::BitOrder,
slice::BitSlice,
store::BitStore,
};
use either::Either;
use core::{
ops::{
AddAssign,
BitAndAssign,
BitOrAssign,
BitXorAssign,
Index,
IndexMut,
Neg,
Not,
Range,
RangeFrom,
RangeFull,
RangeInclusive,
RangeTo,
RangeToInclusive,
ShlAssign,
ShrAssign,
},
ptr,
};
impl<O, T, I> AddAssign<I> for BitSlice<O, T>
where O: BitOrder, T: BitStore,
I: IntoIterator<Item=bool>, I::IntoIter: DoubleEndedIterator {
#[allow(clippy::many_single_char_names)]
fn add_assign(&mut self, addend: I) {
use core::iter::repeat;
let mut c = false;
let addend_iter = addend.into_iter().rev().chain(repeat(false));
for (i, b) in (0 .. self.len()).rev().zip(addend_iter) {
let a = unsafe { *self.get_unchecked(i) };
let (y, z) = crate::rca1(a, b, c);
unsafe { self.set_unchecked(i, y); }
c = z;
}
}
}
impl<O, T, I> BitAndAssign<I> for BitSlice<O, T>
where O: BitOrder, T: BitStore, I: IntoIterator<Item=bool> {
fn bitand_assign(&mut self, rhs: I) {
use core::iter;
rhs.into_iter()
.chain(iter::repeat(false))
.enumerate()
.take(self.len())
.for_each(|(idx, bit)| unsafe {
let val = *self.get_unchecked(idx);
self.set_unchecked(idx, val & bit);
});
}
}
impl<O, T, I> BitOrAssign<I> for BitSlice<O, T>
where O: BitOrder, T: BitStore, I: IntoIterator<Item=bool> {
fn bitor_assign(&mut self, rhs: I) {
rhs.into_iter()
.enumerate()
.take(self.len())
.for_each(|(idx, bit)| unsafe {
let val = *self.get_unchecked(idx);
self.set_unchecked(idx, val | bit);
});
}
}
impl<O, T, I> BitXorAssign<I> for BitSlice<O, T>
where O: BitOrder, T: BitStore, I: IntoIterator<Item=bool> {
fn bitxor_assign(&mut self, rhs: I) {
rhs.into_iter()
.enumerate()
.take(self.len())
.for_each(|(idx, bit)| unsafe {
let val = *self.get_unchecked(idx);
self.set_unchecked(idx, val ^ bit);
})
}
}
impl<O, T> Index<usize> for BitSlice<O, T>
where O: BitOrder, T: BitStore {
type Output = bool;
fn index(&self, place: usize) -> &Self::Output {
place.index(self)
}
}
impl<O, T> Index<Range<usize>> for BitSlice<O, T>
where O: BitOrder, T: BitStore {
type Output = Self;
fn index(&self, range: Range<usize>) -> &Self {
range.index(self)
}
}
impl<O, T> IndexMut<Range<usize>> for BitSlice<O, T>
where O: BitOrder, T: BitStore {
fn index_mut(&mut self, range: Range<usize>) -> &mut Self {
range.index_mut(self)
}
}
impl<O, T> Index<RangeInclusive<usize>> for BitSlice<O, T>
where O: BitOrder, T: BitStore {
type Output = Self;
fn index(&self, range: RangeInclusive<usize>) -> &Self {
range.index(self)
}
}
impl<O, T> IndexMut<RangeInclusive<usize>> for BitSlice<O, T>
where O: BitOrder, T: BitStore {
fn index_mut(&mut self, range: RangeInclusive<usize>) -> &mut Self {
range.index_mut(self)
}
}
impl<O, T> Index<RangeFrom<usize>> for BitSlice<O, T>
where O: BitOrder, T: BitStore {
type Output = Self;
fn index(&self, range: RangeFrom<usize>) -> &Self {
range.index(self)
}
}
impl<O, T> IndexMut<RangeFrom<usize>> for BitSlice<O, T>
where O: BitOrder, T: BitStore {
fn index_mut(&mut self, range: RangeFrom<usize>) -> &mut Self {
range.index_mut(self)
}
}
impl<O, T> Index<RangeFull> for BitSlice<O, T>
where O: BitOrder, T: BitStore {
type Output = Self;
fn index(&self, _: RangeFull) -> &Self {
self
}
}
impl<O, T> IndexMut<RangeFull> for BitSlice<O, T>
where O: BitOrder, T: BitStore {
fn index_mut(&mut self, _: RangeFull) -> &mut Self {
self
}
}
impl<O, T> Index<RangeTo<usize>> for BitSlice<O, T>
where O: BitOrder, T: BitStore {
type Output = Self;
fn index(&self, range: RangeTo<usize>) -> &Self {
range.index(self)
}
}
impl<O, T> IndexMut<RangeTo<usize>> for BitSlice<O, T>
where O: BitOrder, T: BitStore {
fn index_mut(&mut self, range: RangeTo<usize>) -> &mut Self {
range.index_mut(self)
}
}
impl<O, T> Index<RangeToInclusive<usize>> for BitSlice<O, T>
where O: BitOrder, T: BitStore {
type Output = Self;
fn index(&self, range: RangeToInclusive<usize>) -> &Self {
range.index(self)
}
}
impl<O, T> IndexMut<RangeToInclusive<usize>> for BitSlice<O, T>
where O: BitOrder, T: BitStore {
fn index_mut(&mut self, range: RangeToInclusive<usize>) -> &mut Self {
range.index_mut(self)
}
}
impl<'a, O, T> Neg for &'a mut BitSlice<O, T>
where O: BitOrder, T: 'a + BitStore {
type Output = Self;
fn neg(self) -> Self::Output {
if self.is_empty() || self.not_any() {
return self;
}
if unsafe { *self.get_unchecked(0) } {
unsafe { self.set_unchecked(0, false); }
if self.not_any() {
return self;
}
unsafe { self.set_unchecked(0, true); }
}
let this = !self;
*this += core::iter::once(true);
this
}
}
impl<'a, O, T> Not for &'a mut BitSlice<O, T>
where O: BitOrder, T: 'a + BitStore {
type Output = Self;
fn not(self) -> Self::Output {
match self.bitptr().domain().splat() {
Either::Right((h, e, t)) => for n in *h .. *t {
e.invert_bit::<O>(n.idx());
},
Either::Left((h, b, t)) => {
if let Some((h, head)) = h {
for n in *h .. T::BITS {
head.invert_bit::<O>(n.idx())
}
}
if let Some(body) = b {
for elt in body {
elt.store(!elt.load());
}
}
if let Some((tail, t)) = t {
for n in 0 .. *t {
tail.invert_bit::<O>(n.idx())
}
}
},
}
self
}
}
__bitslice_shift!(u8, u16, u32, u64, i8, i16, i32, i64);
impl<O, T> ShlAssign<usize> for BitSlice<O, T>
where O: BitOrder, T: BitStore {
#[allow(clippy::suspicious_op_assign_impl)] fn shl_assign(&mut self, shamt: usize) {
if shamt == 0 {
return;
}
let len = self.len();
if shamt >= len {
self.set_all(false);
return;
}
if self.bitptr().domain().is_spanning() {
let offset = shamt >> T::INDX;
let rem = self.bitptr().elements() - offset;
let to: *mut T = self.as_mut_ptr();
let from: *const T = &self.as_slice()[offset];
let tail: *mut T = &mut self.as_mut_slice()[rem];
unsafe {
ptr::copy(from, to, rem);
ptr::write_bytes(tail, 0, offset);
}
self[.. rem << T::INDX] <<= shamt & T::INDX as usize;
return;
}
for (to, from) in (shamt .. len).enumerate() {
unsafe { self.copy_unchecked(from, to); }
}
self[len - shamt ..].set_all(false);
}
}
impl<O, T> ShrAssign<usize> for BitSlice<O, T>
where O: BitOrder, T: BitStore {
#[allow(clippy::suspicious_op_assign_impl)] fn shr_assign(&mut self, shamt: usize) {
if shamt == 0 {
return;
}
let len = self.len();
if shamt >= len {
self.set_all(false);
return;
}
if self.bitptr().domain().is_spanning() {
let offset = shamt >> T::INDX;
let rem = self.bitptr().elements() - offset;
let from: *mut T = self.as_mut_ptr();
let to: *mut T = &mut self.as_mut_slice()[offset];
unsafe {
ptr::copy(from, to, rem);
ptr::write_bytes(from, 0, offset);
}
self[offset << T::INDX ..] >>= shamt & T::INDX as usize;
return;
}
for (from, to) in (shamt .. len).enumerate().rev() {
unsafe { self.copy_unchecked(from, to); }
}
self[.. shamt].set_all(false);
}
}