extern crate num_traits;
use num_traits::PrimInt;
pub fn matrix_mul<I, O>(word: I, mat: &[I]) -> O where
I: PrimInt,
O: PrimInt + From<u8>,
{
accum_rows(word, O::zero(), mat)
}
pub fn matrix_mul_systematic<I, O>(word: I, mat: &[I]) -> O where
I: PrimInt + Into<O>,
O: PrimInt + From<u8>,
{
accum_rows(word, word.into(), mat)
}
fn accum_rows<I, O>(word: I, init: O, mat: &[I]) -> O where
I: PrimInt,
O: PrimInt + From<u8>,
{
mat.iter().fold(init, |accum, &row| {
let bit = ((word & row).count_ones() & 1) as u8;
accum << 1 | bit.into()
})
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_mul() {
let w: u16 = matrix_mul(0b0110011, &[
0b1010101,
0b0110011,
0b0001111,
]);
assert_eq!(w, 0b000);
let w: u16 = matrix_mul(0b0110111, &[
0b1010101,
0b0110011,
0b0001111,
]);
assert_eq!(w, 0b101);
}
#[test]
fn test_mul_sys() {
let w: u16 = matrix_mul_systematic(0u16, &[
0b11111110000,
0b11110001110,
0b11001101101,
0b10101011011,
]);
assert_eq!(w, 0);
let w: u16 = matrix_mul_systematic(0b11111111111u16, &[
0b11111110000,
0b11110001110,
0b11001101101,
0b10101011011,
]);
assert_eq!(w, 0b11111111111_1111);
let w: u16 = matrix_mul_systematic(0b11111111101u16, &[
0b11111110000,
0b11110001110,
0b11001101101,
0b10101011011,
]);
assert_eq!(w, 0b11111111101_1010);
}
}