use core::util::indexer::Indexer;
use std::ops::{BitAnd, BitOr, Index, IndexMut, Not};
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct BoolVec<I: Indexer> {
data: Vec<bool>,
indexer: I,
}
impl<I: Indexer> Index<I::Index> for BoolVec<I> {
type Output = bool;
fn index(&self, i: I::Index) -> &Self::Output {
&self.data[self.indexer.to_num(i)]
}
}
impl<I: Indexer> IndexMut<I::Index> for BoolVec<I> {
fn index_mut(&mut self, i: I::Index) -> &mut Self::Output {
&mut self.data[self.indexer.to_num(i)]
}
}
impl<I> BoolVec<I>
where
I: Indexer,
{
pub fn from_data(data: Vec<bool>, indexer: I) -> BoolVec<I> {
assert_eq!(data.len(), indexer.range());
BoolVec { data, indexer }
}
pub fn falses(indexer: I) -> Self {
let size = indexer.range();
let data = vec![false; size];
BoolVec { data, indexer }
}
pub fn trues(indexer: I) -> Self {
let size = indexer.range();
let data = vec![true; size];
BoolVec { data, indexer }
}
fn bit_map_unary<F: Fn(bool) -> bool>(&self, op: F) -> Self {
let indexer = self.indexer.clone();
let size = self.data.len();
let mut data = Vec::with_capacity(size);
for i in 0..size {
data.push(op(self.data[i]));
}
BoolVec { data, indexer }
}
fn bit_map_binary<F: Fn(bool, bool) -> bool>(
&self,
other: &Self,
op: F,
) -> Self {
assert_eq!(self.indexer, other.indexer);
let indexer = self.indexer.clone();
let size = self.data.len();
let mut data = Vec::with_capacity(size);
for i in 0..size {
data.push(op(self.data[i], other.data[i]));
}
BoolVec { data, indexer }
}
pub fn intersection(&self, other: &Self) -> Self {
self & other
}
pub fn union(&self, other: &Self) -> Self {
self | other
}
pub fn complement(&self) -> Self {
!self
}
pub fn reindex<J>(self, indexer: J) -> BoolVec<J>
where
J: Indexer,
{
assert_eq!(self.indexer.range(), indexer.range());
let data = self.data;
BoolVec { indexer, data }
}
pub fn indexer(&self) -> &I {
&self.indexer
}
}
impl<'now, I> BitAnd for &'now BoolVec<I>
where
I: Indexer,
{
type Output = BoolVec<I>;
fn bitand(self, other: Self) -> Self::Output {
BoolVec::bit_map_binary(self, other, BitAnd::bitand)
}
}
impl<'now, I> BitOr for &'now BoolVec<I>
where
I: Indexer,
{
type Output = BoolVec<I>;
fn bitor(self, other: Self) -> Self::Output {
BoolVec::bit_map_binary(self, other, BitOr::bitor)
}
}
impl<'now, I> Not for &'now BoolVec<I>
where
I: Indexer,
{
type Output = BoolVec<I>;
fn not(self) -> Self::Output {
BoolVec::bit_map_unary(self, Not::not)
}
}
#[cfg(test)]
mod tests {
use super::BoolVec;
use core::util::indexer;
#[test]
fn doc_tests() {
let indexer = 17;
let falses = BoolVec::falses(indexer);
for i in 0..17 {
assert_eq!(falses[i], false);
}
let indexer = 23;
let trues = BoolVec::trues(indexer);
for i in 0..23 {
assert_eq!(trues[i], true);
}
let indexer = 3;
let a = BoolVec::from_data(vec![true, true, false], indexer);
let b = BoolVec::from_data(vec![false, true, true], indexer);
let c = BoolVec::from_data(vec![false, true, false], indexer);
assert_eq!(a.intersection(&b), c);
let indexer = 3;
let a = BoolVec::from_data(vec![false, true, false], indexer);
let b = BoolVec::from_data(vec![false, false, true], indexer);
let c = BoolVec::from_data(vec![false, true, true], indexer);
assert_eq!(a.union(&b), c);
let indexer = 3;
let a = BoolVec::from_data(vec![true, true, false], indexer);
let b = BoolVec::from_data(vec![false, false, true], indexer);
assert_eq!(a.complement(), b);
let rect = indexer::Rect::new(2, 3);
let num = 6;
let vec_rect = BoolVec::falses(rect);
let vec_num = BoolVec::falses(num);
assert_eq!(vec_num, vec_rect.reindex(num));
}
}