lin_algebra 0.4.0

A linear algebra package to compute image, kernel and rank of linear applications.
Documentation
use crate::gf2_matrix::GF2Matrix;
use crate::matrix::{Matrix, Number};
use crate::packed_gf2_matrix::{BitOrder, PackedGF2Matrix};

impl<T: Number> From<&PackedGF2Matrix<T>> for GF2Matrix {
    fn from(int_matrix: &PackedGF2Matrix<T>) -> Self {
        int_matrix.from_int_matrix_to_gf2_matrix(BitOrder::MSB)
    }
}

impl<T: Number> From<PackedGF2Matrix<T>> for GF2Matrix {
    fn from(int_matrix: PackedGF2Matrix<T>) -> Self {
        int_matrix.from_int_matrix_to_gf2_matrix(BitOrder::MSB)
    }
}

impl<T: Number> Matrix<T>
where
    T: Number + From<usize>,
{
    pub fn from_vec_to_int_msb(v: &[u8]) -> T {
        let mut x = 0usize;
        let n = v.len();

        for (i, &bit) in v.iter().enumerate() {
            assert!(bit == 0 || bit == 1);
            if bit == 1 {
                x |= 1 << (n - 1 - i);
            }
        }

        T::from(x)
    }
}

impl<T: Number> From<GF2Matrix> for PackedGF2Matrix<T>
where
    T: Number + From<usize>,
{
    fn from(gf2_matrix: GF2Matrix) -> Self {
        let ve: Vec<T> = gf2_matrix
            .elements
            .iter()
            .map(|row| Matrix::<T>::from_vec_to_int_msb(&row))
            .collect();
        Self::from_vec(ve)
    }
}

impl<T: Number> From<&GF2Matrix> for PackedGF2Matrix<T>
where
    T: Number + From<usize>,
{
    fn from(gf2_matrix: &GF2Matrix) -> Self {
        let ve: Vec<T> = gf2_matrix
            .elements
            .iter()
            .map(|row| Matrix::<T>::from_vec_to_int_msb(&row))
            .collect();
        Self::from_vec(ve)
    }
}

impl<T: Number> From<Vec<T>> for PackedGF2Matrix<T> {
    fn from(value: Vec<T>) -> Self {
        Self::from_vec(value)
    }
}

impl<T: Number> From<&Vec<T>> for PackedGF2Matrix<T> {
    fn from(value: &Vec<T>) -> Self {
        Self::from_vec_referenced(value)
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn test_int_mtrix_to_gf2_matrix_convertion() {
        let elements = vec![0, 1, 2, 4, 8];
        let int_matrix = PackedGF2Matrix::<u8>::new(elements.clone(), 4);
        let gf2_matrix = GF2Matrix::from(int_matrix);
        let expected = vec![
            vec![0, 0, 0, 0],
            vec![0, 0, 0, 1],
            vec![0, 0, 1, 0],
            vec![0, 1, 0, 0],
            vec![1, 0, 0, 0],
        ];
        assert_eq!(gf2_matrix.elements, expected);

        let int_matrix = PackedGF2Matrix::<u8>::new(elements.clone(), 4);
        let gf2_matrix: GF2Matrix = int_matrix.into();
        assert_eq!(gf2_matrix.elements, expected);
    }

    #[test]
    fn test_int_mtrix_to_gf2_matrix_convertion_by_ref() {
        let elements = vec![0, 1, 2, 4, 8];
        let int_matrix = PackedGF2Matrix::<u8>::new(elements.clone(), 4);
        let gf2_matrix = GF2Matrix::from(&int_matrix);
        let expected = vec![
            vec![0, 0, 0, 0],
            vec![0, 0, 0, 1],
            vec![0, 0, 1, 0],
            vec![0, 1, 0, 0],
            vec![1, 0, 0, 0],
        ];
        assert_eq!(gf2_matrix.elements, expected);

        let int_matrix = PackedGF2Matrix::<u8>::new(elements.clone(), 4);
        let gf2_matrix: GF2Matrix = (&int_matrix).into();
        assert_eq!(gf2_matrix.elements, expected);
    }
}