matrix 0.22.0

The package provides a matrix laboratory.
Documentation
use format::compressed::Variant;
use format::{Compressed, Conventional, Diagonal};
use {Element, Size};

impl<'l, T: Element> From<&'l Conventional<T>> for Compressed<T> {
    fn from(conventional: &'l Conventional<T>) -> Self {
        let (rows, columns) = conventional.dimensions();
        let mut matrix = Compressed::new((rows, columns), Variant::Column);
        for (k, &value) in conventional.values.iter().enumerate() {
            if !value.is_zero() {
                matrix.set((k % rows, k / rows), value);
            }
        }
        matrix
    }
}

impl<T: Element> From<Conventional<T>> for Compressed<T> {
    #[inline]
    fn from(matrix: Conventional<T>) -> Self {
        (&matrix).into()
    }
}

impl<'l, T: Element> From<&'l Compressed<T>> for Conventional<T> {
    fn from(matrix: &'l Compressed<T>) -> Self {
        let &Compressed {
            rows,
            columns,
            variant,
            ref values,
            ref indices,
            ref offsets,
            ..
        } = validate!(matrix);
        let mut matrix = Conventional::new((rows, columns));
        match variant {
            Variant::Row => {
                for i in 0..rows {
                    for k in offsets[i]..offsets[i + 1] {
                        matrix.values[indices[k] * rows + i] = values[k];
                    }
                }
            }
            Variant::Column => {
                for j in 0..columns {
                    for k in offsets[j]..offsets[j + 1] {
                        matrix.values[j * rows + indices[k]] = values[k];
                    }
                }
            }
        }
        matrix
    }
}

impl<T: Element> From<Compressed<T>> for Conventional<T> {
    #[inline]
    fn from(matrix: Compressed<T>) -> Self {
        (&matrix).into()
    }
}

impl<'l, T: Element> From<&'l Diagonal<T>> for Compressed<T> {
    #[inline]
    fn from(matrix: &'l Diagonal<T>) -> Self {
        matrix.clone().into()
    }
}

impl<T: Element> From<Diagonal<T>> for Compressed<T> {
    fn from(matrix: Diagonal<T>) -> Self {
        let Diagonal {
            rows,
            columns,
            values,
        } = validate!(matrix);
        let nonzeros = values.len();
        let indices = (0..nonzeros).collect();
        let offsets = (0..(columns + 1))
            .map(|i| if i < nonzeros { i } else { nonzeros })
            .collect();
        new!(
            rows,
            columns,
            nonzeros,
            Variant::Column,
            values,
            indices,
            offsets
        )
    }
}

#[cfg(test)]
mod tests {
    use format::compressed::Variant;
    use prelude::*;

    #[test]
    fn from_conventional() {
        let matrix = Conventional::from_vec(
            (5, 3),
            matrix![
                0.0, 0.0, 0.0;
                1.0, 0.0, 0.0;
                0.0, 0.0, 0.0;
                0.0, 2.0, 0.0;
                0.0, 3.0, 4.0;
            ],
        );
        let matrix = Compressed::from(matrix);
        assert_eq!(
            matrix,
            new!(
                5,
                3,
                4,
                Variant::Column,
                vec![1.0, 2.0, 3.0, 4.0],
                vec![1, 3, 4, 4],
                vec![0, 1, 3, 4]
            )
        );
    }

    #[test]
    fn from_diagonal_tall() {
        let matrix = Compressed::from(Diagonal::from_vec((5, 3), vec![1.0, 2.0, 0.0]));
        assert_eq!(
            matrix,
            new!(
                5,
                3,
                3,
                Variant::Column,
                vec![1.0, 2.0, 0.0],
                vec![0, 1, 2],
                vec![0, 1, 2, 3]
            )
        );
    }

    #[test]
    fn from_diagonal_wide() {
        let matrix = Compressed::from(Diagonal::from_vec((3, 5), vec![1.0, 0.0, 3.0]));
        assert_eq!(
            matrix,
            new!(
                3,
                5,
                3,
                Variant::Column,
                vec![1.0, 0.0, 3.0],
                vec![0, 1, 2],
                vec![0, 1, 2, 3, 3, 3]
            )
        );
    }

    #[test]
    fn into_conventional() {
        let matrix = new!(
            5,
            3,
            3,
            Variant::Column,
            vec![1.0, 2.0, 3.0],
            vec![0, 1, 2],
            vec![0, 1, 2, 3]
        );
        let matrix = Conventional::from(matrix);
        assert_eq!(
            &*matrix,
            &*matrix![
                1.0, 0.0, 0.0;
                0.0, 2.0, 0.0;
                0.0, 0.0, 3.0;
                0.0, 0.0, 0.0;
                0.0, 0.0, 0.0;
            ]
        );
    }
}