use crate::bitmatrix::BitMatrix;
use std::fmt;
use std::ops::{BitXor, BitXorAssign, Index, Mul};
#[derive(Clone, Debug)]
pub struct BitVector(BitMatrix);
impl BitVector {
#[inline]
pub fn bit(&self, i: usize) -> bool {
self.0.bit(0, i)
}
#[inline]
pub fn set_bit(&mut self, i: usize, b: bool) {
self.0.set_bit(0, i, b);
}
pub fn build(length: usize, mut f: impl FnMut(usize) -> bool) -> Self {
Self(BitMatrix::build(1, length, |_, j| f(j)))
}
pub fn from_bool_vec(data: &Vec<bool>) -> Self {
Self::build(data.len(), |i| data[i])
}
pub fn from_int_vec(data: &Vec<usize>) -> Self {
Self::build(data.len(), |i| data[i] != 0)
}
pub fn zeros(length: usize) -> Self {
Self(BitMatrix::zeros(1, length))
}
pub fn is_zero(&self) -> bool {
self.0.is_zero()
}
#[inline]
pub fn len(&self) -> usize {
self.0.cols()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn random(rng: &mut impl rand::Rng, length: usize) -> Self {
Self(BitMatrix::random(rng, 1, length))
}
#[inline]
pub fn weight(&self) -> usize {
self.0.row_weight(0)
}
#[inline]
pub fn xor_with(&mut self, other: &BitVector) {
if self.len() != other.len() {
panic!("BitVectors must have the same length for XOR");
}
self.0.add_bits_to_row(other.0.row(0), 0);
}
#[inline]
pub fn as_slice(&self) -> &crate::data::BitSlice {
self.0.row(0)
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut crate::data::BitSlice {
self.0.row_mut(0)
}
#[inline]
pub fn as_matrix(&self) -> &BitMatrix {
&self.0
}
#[inline]
pub fn as_row_vector(&self) -> &BitMatrix {
&self.0
}
}
impl fmt::Display for BitVector {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[")?;
for i in 0..self.len() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", if self[i] { 1 } else { 0 })?;
}
write!(f, "]")
}
}
impl BitXor for &BitVector {
type Output = BitVector;
fn bitxor(self, rhs: Self) -> Self::Output {
assert_eq!(
self.len(),
rhs.len(),
"BitVectors must have the same length for XOR"
);
let mut result = self.clone();
result.xor_with(rhs);
result
}
}
impl BitXor for BitVector {
type Output = BitVector;
fn bitxor(mut self, rhs: Self) -> Self::Output {
self ^= rhs;
self
}
}
impl BitXorAssign<&BitVector> for BitVector {
fn bitxor_assign(&mut self, rhs: &BitVector) {
self.xor_with(rhs);
}
}
impl BitXorAssign<BitVector> for BitVector {
fn bitxor_assign(&mut self, rhs: BitVector) {
self.xor_with(&rhs);
}
}
impl PartialEq for BitVector {
fn eq(&self, other: &Self) -> bool {
if self.len() != other.len() {
return false;
}
for i in 0..self.len() {
if self.bit(i) != other.bit(i) {
return false;
}
}
true
}
}
impl Eq for BitVector {}
impl Index<usize> for BitVector {
type Output = bool;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
if self.bit(index) {
&true
} else {
&false
}
}
}
impl From<BitVector> for BitMatrix {
fn from(vector: BitVector) -> Self {
vector.0
}
}
impl TryFrom<BitMatrix> for BitVector {
type Error = &'static str;
fn try_from(matrix: BitMatrix) -> Result<Self, Self::Error> {
if matrix.rows() != 1 {
return Err("Cannot convert BitMatrix to BitVector unless it has exactly one row");
}
Ok(BitVector(matrix))
}
}
impl Mul<&BitVector> for &BitMatrix {
type Output = BitVector;
fn mul(self, rhs: &BitVector) -> Self::Output {
self.try_mul_vector(rhs).unwrap()
}
}
#[cfg(test)]
mod tests {
use super::*;
use rand::{rngs::SmallRng, SeedableRng};
#[test]
fn test_matrix_vector_multiplication() {
let matrix = BitMatrix::from_bool_vec(&vec![
vec![true, false, true],
vec![false, true, true],
vec![true, true, false],
]);
let vector = BitVector::from_bool_vec(&vec![true, true, false]);
let result = &matrix * &vector;
assert_eq!(result.len(), 3);
assert!(result[0]); assert!(result[1]); assert!(!result[2]); }
#[test]
fn test_matrix_vector_multiplication_identity() {
let identity = BitMatrix::identity(3);
let vector = BitVector::from_bool_vec(&vec![true, false, true]);
let result = &identity * &vector;
assert_eq!(result.len(), 3);
assert_eq!(result[0], true);
assert_eq!(result[1], false);
assert_eq!(result[2], true);
}
#[test]
fn test_matrix_vector_multiplication_zeros() {
let zero_matrix = BitMatrix::zeros(2, 3);
let vector = BitVector::from_bool_vec(&vec![true, true, true]);
let result = &zero_matrix * &vector;
assert_eq!(result.len(), 2);
assert!(result.is_zero());
}
#[test]
#[should_panic(expected = "Cannot multiply matrix")]
fn test_matrix_vector_multiplication_dimension_mismatch() {
let matrix = BitMatrix::zeros(2, 3);
let vector = BitVector::zeros(2);
let _result = &matrix * &vector;
}
#[test]
fn test_matrix_vector_multiplication_random() {
let mut rng = SmallRng::seed_from_u64(123);
let matrix = BitMatrix::random(&mut rng, 5, 7);
let vector = BitVector::random(&mut rng, 7);
let result = &matrix * &vector;
assert_eq!(result.len(), 5);
let mut expected_first = false;
for j in 0..7 {
expected_first ^= matrix.bit(0, j) & vector[j];
}
assert_eq!(result[0], expected_first);
}
}