use std::ops;
use vob::Vob;
use rand;
use rand::Rng;
use friendly::binary_matrix::BinMatrix;
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BinVector {
vec: Vob,
}
impl ops::Deref for BinVector {
type Target = Vob;
#[inline]
fn deref(&self) -> &Self::Target {
&self.vec
}
}
impl From<Vob> for BinVector {
fn from(v: Vob) -> BinVector {
BinVector::from(v)
}
}
impl ops::DerefMut for BinVector {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.vec
}
}
impl BinVector {
#[inline]
pub fn new() -> Self {
BinVector::from(Vob::new())
}
#[inline]
pub fn from(vec: Vob) -> Self {
BinVector { vec }
}
#[inline]
pub fn from_elem(len: usize, elem: bool) -> Self {
BinVector::from(Vob::from_elem(len, elem))
}
#[inline]
pub fn from_bools(bools: &[bool]) -> BinVector {
let vec = bools.iter().cloned().collect::<Vob>();
BinVector { vec }
}
#[inline]
pub fn from_function(len: usize, f: fn(usize) -> bool) -> BinVector {
let mut vob = Vob::with_capacity(len);
for i in 0..len {
vob.push(f(i));
}
BinVector::from(vob)
}
#[inline]
pub fn random(len: usize) -> BinVector {
let mut rng = rand::thread_rng();
let mut vob = Vob::with_capacity(len);
for _ in 0..len {
vob.push(rng.gen());
}
BinVector::from(vob)
}
#[inline]
pub fn with_capacity(len: usize) -> Self {
BinVector::from(Vob::with_capacity(len))
}
#[inline]
pub fn from_bytes(bytes: &[u8]) -> BinVector {
let vec: Vob = Vob::from_bytes(bytes);
BinVector { vec }
}
#[inline]
pub fn count_ones(&self) -> u32 {
self.iter_storage()
.fold(0u32, |acc, block| acc + block.count_ones())
}
#[inline]
pub fn extend_from_binvec(&mut self, other: &BinVector) {
self.vec.extend_from_vob(&other.vec);
}
#[inline]
pub fn into_vob(self) -> Vob {
self.vec
}
pub fn as_matrix(&self) -> BinMatrix {
BinMatrix::new(vec![self.clone()] )
}
pub fn as_column_matrix(&self) -> BinMatrix {
self.as_matrix().transposed()
}
pub fn as_u32(&self) -> u32 {
assert!(self.len() < 32, "Can't convert this to a >32 bit number");
self.iter_storage()
.next()
.expect("Can't convert None to a number") as u32
}
pub fn as_u64(&self) -> u64 {
assert!(self.len() < 64, "Can't convert this to a >32 bit number");
self.iter_storage()
.next()
.expect("Can't convert None to a number") as u64
}
}
impl<'a> ops::Add<&'a BinVector> for &'a BinVector {
type Output = BinVector;
#[inline]
fn add(self, other: &BinVector) -> Self::Output {
let mut new = self.clone();
new += other;
new
}
}
impl ops::Add<BinVector> for BinVector {
type Output = BinVector;
#[inline]
fn add(self, other: BinVector) -> Self::Output {
assert_eq!(self.len(), other.len(), "unequal length vectors");
let mut new = self.clone();
new += other;
new
}
}
impl<'a> ops::AddAssign<&'a BinVector> for BinVector {
#[inline]
fn add_assign(&mut self, other: &BinVector) {
assert_eq!(self.len(), other.len(), "unequal length vectors");
self.xor(&*other);
}
}
impl ops::AddAssign<BinVector> for BinVector {
#[inline]
fn add_assign(&mut self, other: BinVector) {
assert_eq!(self.len(), other.len(), "unequal length vectors");
self.xor(&*other);
}
}
impl<'a> ops::Mul<&'a BinVector> for &'a BinVector {
type Output = bool;
#[inline]
fn mul(self, other: &BinVector) -> Self::Output {
let mut vec = self.clone();
vec.and(&other);
vec.count_ones() % 2 == 1
}
}
impl ops::Mul<BinVector> for BinVector {
type Output = bool;
#[inline]
fn mul(self, other: BinVector) -> Self::Output {
let mut vec = self.clone();
vec.and(&other);
vec.count_ones() % 2 == 1
}
}
#[cfg(test)]
mod test {
use super::*;
use vob::Vob;
#[test]
fn init() {
let b = Vob::from_elem(10, false);
let b = BinVector::from(b);
assert_eq!(b.len(), 10);
}
#[test]
fn from_bytes() {
let b = BinVector::from_bytes(&[0b1111_1111]);
assert_eq!(b.len(), 8);
let b = BinVector::from_bytes(&[0b1000_0000]);
assert_eq!(b.get(0), Some(true));
assert_eq!(b.get(1), Some(false));
}
#[test]
fn add() {
let a = BinVector::from(Vob::from_elem(10, false));
let b = BinVector::from(Vob::from_elem(10, false));
let c = &a + &b;
assert_eq!(c.len(), 10, "length incorrect");
assert_eq!(Vob::from_elem(10, false), *c);
assert_eq!(c, a + b);
}
#[test]
fn mul() {
let a = BinVector::from(Vob::from_elem(10, true));
let b = BinVector::from(Vob::from_elem(10, false));
let c = &a * &b;
assert_eq!(false, c);
assert_eq!(c, a * b);
}
#[test]
fn as_matrix() {
let a = BinVector::random(10);
let amat = a.as_matrix();
assert_eq!(amat.ncols(), 10);
assert_eq!(amat.nrows(), 1);
assert_eq!(amat.as_vector(), a);
}
#[test]
fn as_column_matrix() {
let a = BinVector::random(10);
let amat = a.as_column_matrix();
assert_eq!(amat.ncols(), 1);
assert_eq!(amat.nrows(), 10);
assert_eq!(amat.as_vector(), a);
}
#[test]
fn count_ones() {
let a = BinVector::from_elem(10, true);
let b = BinVector::from_elem(10, false);
assert_eq!(a.count_ones(), 10);
assert_eq!(b.count_ones(), 0);
assert_eq!(BinVector::from_bytes(&[0b1010_1000]).count_ones(), 3);
}
}