use crate::{BitMatrix, BitVec};
#[derive(Debug, Clone, PartialEq)]
pub struct AffineMap {
matrix: BitMatrix,
shift: BitVec,
}
impl AffineMap {
#[must_use]
pub fn affine(matrix: BitMatrix, shift: BitVec) -> Self {
assert_eq!(matrix.row_count(), shift.len());
Self { matrix, shift }
}
#[must_use]
pub fn linear(matrix: BitMatrix) -> Self {
let shift = BitVec::zeros(matrix.row_count());
Self { matrix, shift }
}
#[must_use]
pub fn translation(shift: BitVec) -> Self {
let matrix = BitMatrix::identity(shift.len());
Self { matrix, shift }
}
#[must_use]
pub fn zero(input_dimension: usize, output_dimension: usize) -> Self {
let matrix = BitMatrix::zeros(output_dimension, input_dimension);
let shift = BitVec::zeros(output_dimension);
Self { matrix, shift }
}
pub fn apply(&self, input: &BitVec) -> BitVec {
&self.matrix * &input.as_view() + &self.shift
}
#[must_use]
pub fn dot(&self, other: &AffineMap) -> AffineMap {
assert_eq!(self.input_dimension(), other.output_dimension());
let matrix = &self.matrix * &other.matrix;
let shift = &self.matrix * &other.shift.as_view() + &self.shift;
AffineMap::affine(matrix, shift)
}
#[must_use]
pub fn input_dimension(&self) -> usize {
self.matrix.column_count()
}
#[must_use]
pub fn output_dimension(&self) -> usize {
self.matrix.row_count()
}
pub fn matrix(&self) -> &BitMatrix {
&self.matrix
}
pub fn matrix_mut(&mut self) -> &mut BitMatrix {
&mut self.matrix
}
pub fn shift(&self) -> &BitVec {
&self.shift
}
pub fn shift_mut(&mut self) -> &mut BitVec {
&mut self.shift
}
}