m4ri_rust/friendly/
binary_vector.rs

1/// Implement binary vectors to help implement functions on matrices
2///
3/// Wraps the `vob` crate.
4use std::ops;
5use vob::Vob;
6
7use rand;
8use rand::Rng;
9
10use friendly::binary_matrix::BinMatrix;
11
12/// Wrapper around vob::Vob
13#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
14#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
15pub struct BinVector {
16    vec: Vob,
17}
18
19impl ops::Deref for BinVector {
20    type Target = Vob;
21
22    #[inline]
23    fn deref(&self) -> &Self::Target {
24        &self.vec
25    }
26}
27
28impl From<Vob> for BinVector {
29    fn from(v: Vob) -> BinVector {
30        BinVector::from(v)
31    }
32}
33
34impl ops::DerefMut for BinVector {
35    #[inline]
36    fn deref_mut(&mut self) -> &mut Self::Target {
37        &mut self.vec
38    }
39}
40
41impl BinVector {
42    /// Create a new BinVector
43    #[inline]
44    pub fn new() -> Self {
45        BinVector::from(Vob::new())
46    }
47
48    //// Construct directly from a vec
49    #[inline]
50    pub fn from(vec: Vob) -> Self {
51        BinVector { vec }
52    }
53
54    /// Create with a certain length and all the same element
55    #[inline]
56    pub fn from_elem(len: usize, elem: bool) -> Self {
57        BinVector::from(Vob::from_elem(len, elem))
58    }
59
60    /// Set it up from bools
61    #[inline]
62    pub fn from_bools(bools: &[bool]) -> BinVector {
63        let vec = bools.iter().cloned().collect::<Vob>();
64        BinVector { vec }
65    }
66
67    /// Construct the BinVector from the result of a function
68    ///
69    /// # Example
70    /// ```
71    /// # use m4ri_rust::friendly::BinVector;
72    /// let v = BinVector::from_function(4, |i| i % 2 == 0);
73    /// assert_eq!(v.get(0), Some(true));
74    /// assert_eq!(v.get(1), Some(false));
75    /// ```
76    #[inline]
77    pub fn from_function(len: usize, f: fn(usize) -> bool) -> BinVector {
78        let mut vob = Vob::with_capacity(len);
79        for i in 0..len {
80            vob.push(f(i));
81        }
82        BinVector::from(vob)
83    }
84
85    /// Randomized
86    #[inline]
87    pub fn random(len: usize) -> BinVector {
88        let mut rng = rand::thread_rng();
89        let mut vob = Vob::with_capacity(len);
90        for _ in 0..len {
91            vob.push(rng.gen());
92        }
93        BinVector::from(vob)
94    }
95
96    /// initialise with a set capacity
97    #[inline]
98    pub fn with_capacity(len: usize) -> Self {
99        BinVector::from(Vob::with_capacity(len))
100    }
101
102    /// Create a new BinVector from an `&[u8]`.
103    #[inline]
104    pub fn from_bytes(bytes: &[u8]) -> BinVector {
105        let vec: Vob = Vob::from_bytes(bytes);
106
107        BinVector { vec }
108    }
109
110    /// Get the hamming weight
111    #[inline]
112    pub fn count_ones(&self) -> u32 {
113        self.iter_storage()
114            .fold(0u32, |acc, block| acc + block.count_ones())
115    }
116
117    /// Extend from a binary vector
118    #[inline]
119    pub fn extend_from_binvec(&mut self, other: &BinVector) {
120        self.vec.extend_from_vob(&other.vec);
121    }
122
123    /// Obtain the inner Vob
124    #[inline]
125    pub fn into_vob(self) -> Vob {
126        self.vec
127    }
128
129    /// Obtain this as a row matrix
130    pub fn as_matrix(&self) -> BinMatrix {
131        BinMatrix::new(vec![self.clone()] )
132    }
133
134    /// Obtain this as a column matrix
135    pub fn as_column_matrix(&self) -> BinMatrix {
136        self.as_matrix().transposed()
137    }
138
139    /// Get an u32 in the order as it's stored
140    pub fn as_u32(&self) -> u32 {
141        assert!(self.len() < 32, "Can't convert this to a >32 bit number");
142        self.iter_storage()
143            .next()
144            .expect("Can't convert None to a number") as u32
145    }
146
147    /// Get an u64 in the order as it's stored
148    pub fn as_u64(&self) -> u64 {
149        assert!(self.len() < 64, "Can't convert this to a >32 bit number");
150        self.iter_storage()
151            .next()
152            .expect("Can't convert None to a number") as u64
153    }
154}
155
156impl<'a> ops::Add<&'a BinVector> for &'a BinVector {
157    type Output = BinVector;
158    #[inline]
159    fn add(self, other: &BinVector) -> Self::Output {
160        let mut new = self.clone();
161        new += other;
162        new
163    }
164}
165
166impl ops::Add<BinVector> for BinVector {
167    type Output = BinVector;
168
169    #[inline]
170    fn add(self, other: BinVector) -> Self::Output {
171        assert_eq!(self.len(), other.len(), "unequal length vectors");
172        let mut new = self.clone();
173        new += other;
174        new
175    }
176}
177
178impl<'a> ops::AddAssign<&'a BinVector> for BinVector {
179    #[inline]
180    fn add_assign(&mut self, other: &BinVector) {
181        assert_eq!(self.len(), other.len(), "unequal length vectors");
182        self.xor(&*other);
183    }
184}
185
186impl ops::AddAssign<BinVector> for BinVector {
187    #[inline]
188    fn add_assign(&mut self, other: BinVector) {
189        assert_eq!(self.len(), other.len(), "unequal length vectors");
190        self.xor(&*other);
191    }
192}
193
194impl<'a> ops::Mul<&'a BinVector> for &'a BinVector {
195    type Output = bool;
196
197    #[inline]
198    fn mul(self, other: &BinVector) -> Self::Output {
199        let mut vec = self.clone();
200        vec.and(&other);
201        vec.count_ones() % 2 == 1
202    }
203}
204
205impl ops::Mul<BinVector> for BinVector {
206    type Output = bool;
207
208    #[inline]
209    /// Compute the inner product between two vectors
210    fn mul(self, other: BinVector) -> Self::Output {
211        let mut vec = self.clone();
212        vec.and(&other);
213        vec.count_ones() % 2 == 1
214    }
215}
216
217#[cfg(test)]
218mod test {
219    use super::*;
220    use vob::Vob;
221
222    #[test]
223    fn init() {
224        let b = Vob::from_elem(10, false);
225        let b = BinVector::from(b);
226        assert_eq!(b.len(), 10);
227    }
228
229    #[test]
230    fn from_bytes() {
231        let b = BinVector::from_bytes(&[0b1111_1111]);
232        assert_eq!(b.len(), 8);
233
234        let b = BinVector::from_bytes(&[0b1000_0000]);
235        assert_eq!(b.get(0), Some(true));
236        assert_eq!(b.get(1), Some(false));
237    }
238
239    #[test]
240    fn add() {
241        let a = BinVector::from(Vob::from_elem(10, false));
242        let b = BinVector::from(Vob::from_elem(10, false));
243
244        let c = &a + &b;
245
246        assert_eq!(c.len(), 10, "length incorrect");
247        assert_eq!(Vob::from_elem(10, false), *c);
248        assert_eq!(c, a + b);
249    }
250
251    #[test]
252    fn mul() {
253        let a = BinVector::from(Vob::from_elem(10, true));
254        let b = BinVector::from(Vob::from_elem(10, false));
255
256        let c = &a * &b;
257
258        assert_eq!(false, c);
259        assert_eq!(c, a * b);
260    }
261
262    #[test]
263    fn as_matrix() {
264        let a = BinVector::random(10);
265        let amat = a.as_matrix();
266        assert_eq!(amat.ncols(), 10);
267        assert_eq!(amat.nrows(), 1);
268        assert_eq!(amat.as_vector(), a);
269    }
270
271    #[test]
272    fn as_column_matrix() {
273        let a = BinVector::random(10);
274        let amat = a.as_column_matrix();
275        assert_eq!(amat.ncols(), 1);
276        assert_eq!(amat.nrows(), 10);
277        assert_eq!(amat.as_vector(), a);
278    }
279
280    #[test]
281    fn count_ones() {
282        let a = BinVector::from_elem(10, true);
283        let b = BinVector::from_elem(10, false);
284        assert_eq!(a.count_ones(), 10);
285        assert_eq!(b.count_ones(), 0);
286        assert_eq!(BinVector::from_bytes(&[0b1010_1000]).count_ones(), 3);
287    }
288}