use self::indexer::Indexer;
use core::util::bool_vec::BoolVec;
use core::util::indexer;
use std::ops::{Index, IndexMut, Mul};
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct BoolMat<J: Indexer, K: Indexer> {
rows: J,
columns: K,
contents: BoolVec<indexer::Rect>,
}
impl<J, K> Index<(J::Index, K::Index)> for BoolMat<J, K>
where
J: Indexer,
K: Indexer,
{
type Output = bool;
fn index(&self, (j, k): (J::Index, K::Index)) -> &Self::Output {
let i = (self.rows.to_num(j), self.columns.to_num(k));
&self.contents[i]
}
}
impl<J, K> IndexMut<(J::Index, K::Index)> for BoolMat<J, K>
where
J: Indexer,
K: Indexer,
{
fn index_mut(
&mut self,
(j, k): (J::Index, K::Index),
) -> &mut Self::Output {
let i = (self.rows.to_num(j), self.columns.to_num(k));
&mut self.contents[i]
}
}
impl<J, K> BoolMat<J, K>
where
J: Indexer,
K: Indexer,
{
pub fn falses(rows: J, columns: K) -> Self {
let rect = indexer::Rect::new(rows.range(), columns.range());
let contents = BoolVec::falses(rect);
BoolMat {
rows,
columns,
contents,
}
}
pub fn trues(rows: J, columns: K) -> Self {
let rect = indexer::Rect::new(rows.range(), columns.range());
let contents = BoolVec::trues(rect);
BoolMat {
rows,
columns,
contents,
}
}
pub fn eval(&self, v: &BoolVec<K>) -> BoolVec<J> {
let matrix = self * BoolMat::column(v);
let indexer = matrix.rows;
matrix.contents.reindex(indexer)
}
}
impl<I> BoolMat<I, ()>
where
I: Indexer,
{
fn column(vec: &BoolVec<I>) -> Self {
let rows = vec.indexer().clone();
let columns = ();
let rect = indexer::Rect::new(rows.range(), 1);
let contents = vec.clone().reindex(rect);
BoolMat {
rows,
columns,
contents,
}
}
}
impl<I> BoolMat<I, I>
where
I: Indexer,
{
pub fn from_diag(diag: &BoolVec<I>) -> Self {
let indexer = diag.indexer();
let rows = indexer.clone();
let columns = indexer.clone();
let mut res = BoolMat::falses(rows, columns);
let len = indexer.range();
for i in 0..len {
res.contents[(i, i)] = diag[indexer.to_index(i)];
}
res
}
pub fn id_matrix(indexer: I) -> Self {
BoolMat::from_diag(&BoolVec::trues(indexer))
}
}
impl<'now, J, K, L> Mul<&'now BoolMat<K, L>> for &'now BoolMat<J, K>
where
J: Indexer,
K: Indexer,
L: Indexer,
{
type Output = BoolMat<J, L>;
fn mul(self, other: &BoolMat<K, L>) -> Self::Output {
assert_eq!(self.columns, other.rows);
let len = self.columns.range();
let rows = self.rows.clone();
let columns = other.columns.clone();
let height = rows.range();
let width = columns.range();
let entry = |j, l| {
(0..len).map(|k| {
self.contents[(j, k)] & other.contents[(k, l)]
}).any(|b| b)
};
let mut data = Vec::with_capacity(height * width);
for j in 0..height {
for l in 0..width {
data.push(entry(j, l));
}
}
let rect = indexer::Rect::new(height, width);
let contents = BoolVec::from_data(data, rect);
BoolMat {
rows,
columns,
contents,
}
}
}
impl<'now, J, K, L> Mul<BoolMat<K, L>> for &'now BoolMat<J, K>
where
J: Indexer,
K: Indexer,
L: Indexer,
{
type Output = BoolMat<J, L>;
fn mul(self, other: BoolMat<K, L>) -> Self::Output {
self * &other
}
}
impl<'now, J, K, L> Mul<&'now BoolMat<K, L>> for BoolMat<J, K>
where
J: Indexer,
K: Indexer,
L: Indexer,
{
type Output = BoolMat<J, L>;
fn mul(self, other: &'now BoolMat<K, L>) -> Self::Output {
&self * other
}
}
impl<J, K, L> Mul<BoolMat<K, L>> for BoolMat<J, K>
where
J: Indexer,
K: Indexer,
L: Indexer,
{
type Output = BoolMat<J, L>;
fn mul(self, other: BoolMat<K, L>) -> Self::Output {
&self * &other
}
}