matrix/format/conventional/
mod.rs

1//! The conventional format.
2//!
3//! The format is suitable for dense matrices.
4
5use std::ops::{Deref, DerefMut, Index, IndexMut};
6use std::ptr;
7
8use {Element, Matrix, Position, Size};
9
10/// A conventional matrix.
11#[derive(Clone, Debug, PartialEq)]
12pub struct Conventional<T: Element> {
13    /// The number of rows.
14    pub rows: usize,
15    /// The number of columns.
16    pub columns: usize,
17    /// The values stored in the column-major order.
18    pub values: Vec<T>,
19}
20
21macro_rules! new(
22    ($rows:expr, $columns:expr, $values:expr) => (
23        Conventional {
24            rows: $rows,
25            columns: $columns,
26            values: $values,
27        }
28    );
29);
30
31mod convert;
32mod decomposition;
33mod operation;
34
35size!(Conventional);
36
37impl<T: Element> Conventional<T> {
38    /// Create a zero matrix.
39    pub fn new<S: Size>(size: S) -> Self {
40        let (rows, columns) = size.dimensions();
41        new!(rows, columns, vec![T::zero(); rows * columns])
42    }
43
44    /// Create a matrix from a slice.
45    pub fn from_slice<S: Size>(size: S, values: &[T]) -> Self {
46        let (rows, columns) = size.dimensions();
47        debug_assert_eq!(values.len(), rows * columns);
48        new!(rows, columns, values.to_vec())
49    }
50
51    /// Create a matrix from a vector.
52    pub fn from_vec<S: Size>(size: S, values: Vec<T>) -> Self {
53        let (rows, columns) = size.dimensions();
54        debug_assert_eq!(values.len(), rows * columns);
55        new!(rows, columns, values)
56    }
57
58    /// Create a matrix with uninitialized elements.
59    pub unsafe fn with_uninitialized<S: Size>(size: S) -> Self {
60        let (rows, columns) = size.dimensions();
61        new!(rows, columns, buffer!(rows * columns))
62    }
63
64    /// Zero out the content.
65    ///
66    /// The function should only be used when it is safe to overwrite `T` with
67    /// zero bytes.
68    #[inline]
69    pub unsafe fn erase(&mut self) {
70        ptr::write_bytes(self.values.as_mut_ptr(), 0, self.values.len())
71    }
72
73    /// Resize.
74    pub fn resize<S: Size>(&mut self, size: S) {
75        let (rows, columns) = size.dimensions();
76        if self.rows == rows {
77            if self.columns > columns {
78                self.values.truncate(rows * columns);
79            } else {
80                self.values
81                    .extend(vec![T::zero(); rows * (columns - self.columns)]);
82            }
83            self.columns = columns;
84        } else {
85            let mut matrix = Conventional::zero(size);
86            let rows = min!(self.rows, rows);
87            let columns = min!(self.columns, columns);
88            for j in 0..columns {
89                for i in 0..rows {
90                    matrix[(i, j)] = self[(i, j)];
91                }
92            }
93            *self = matrix;
94        }
95    }
96}
97
98impl<T: Element> Matrix for Conventional<T> {
99    type Element = T;
100
101    fn nonzeros(&self) -> usize {
102        self.values
103            .iter()
104            .fold(0, |sum, &value| if value.is_zero() { sum } else { sum + 1 })
105    }
106
107    #[inline]
108    fn zero<S: Size>(size: S) -> Self {
109        Conventional::new(size)
110    }
111}
112
113impl<T: Element, P: Position> Index<P> for Conventional<T> {
114    type Output = T;
115
116    #[inline(always)]
117    fn index(&self, index: P) -> &Self::Output {
118        let (i, j) = index.coordinates();
119        &self.values[j * self.rows + i]
120    }
121}
122
123impl<T: Element, P: Position> IndexMut<P> for Conventional<T> {
124    #[inline(always)]
125    fn index_mut(&mut self, index: P) -> &mut Self::Output {
126        let (i, j) = index.coordinates();
127        &mut self.values[j * self.rows + i]
128    }
129}
130
131impl<T: Element> Deref for Conventional<T> {
132    type Target = [T];
133
134    #[inline]
135    fn deref(&self) -> &Self::Target {
136        self.values.deref()
137    }
138}
139
140impl<T: Element> DerefMut for Conventional<T> {
141    #[inline]
142    fn deref_mut(&mut self) -> &mut Self::Target {
143        self.values.deref_mut()
144    }
145}
146
147#[cfg(test)]
148mod tests {
149    use prelude::*;
150
151    #[test]
152    fn erase() {
153        let mut matrix = Conventional::from_vec(10, vec![42.0; 10 * 10]);
154        unsafe { matrix.erase() };
155        assert!(matrix.iter().all(|&value| value == 0.0));
156    }
157
158    #[test]
159    fn resize_fewer_columns() {
160        let mut matrix = Conventional::from_vec((2, 3), vec![1.0, 4.0, 2.0, 5.0, 3.0, 6.0]);
161        matrix.resize((2, 2));
162        assert_eq!(
163            matrix,
164            Conventional::from_vec(
165                (2, 2),
166                matrix![
167                    1.0, 2.0;
168                    4.0, 5.0;
169                ],
170            )
171        );
172    }
173
174    #[test]
175    fn resize_fewer_rows() {
176        let mut matrix = Conventional::from_vec((2, 3), vec![1.0, 4.0, 2.0, 5.0, 3.0, 6.0]);
177        matrix.resize((1, 3));
178        assert_eq!(
179            matrix,
180            Conventional::from_vec(
181                (1, 3),
182                matrix![
183                    1.0, 2.0, 3.0;
184                ],
185            )
186        );
187    }
188
189    #[test]
190    fn resize_more_columns() {
191        let mut matrix = Conventional::from_vec((2, 3), vec![1.0, 4.0, 2.0, 5.0, 3.0, 6.0]);
192        matrix.resize((2, 4));
193        assert_eq!(
194            matrix,
195            Conventional::from_vec(
196                (2, 4),
197                matrix![
198                    1.0, 2.0, 3.0, 0.0;
199                    4.0, 5.0, 6.0, 0.0;
200                ],
201            )
202        );
203    }
204
205    #[test]
206    fn resize_more_rows() {
207        let mut matrix = Conventional::from_vec((2, 3), vec![1.0, 4.0, 2.0, 5.0, 3.0, 6.0]);
208        matrix.resize((3, 3));
209        assert_eq!(
210            matrix,
211            Conventional::from_vec(
212                (3, 3),
213                matrix![
214                    1.0, 2.0, 3.0;
215                    4.0, 5.0, 6.0;
216                    0.0, 0.0, 0.0;
217                ],
218            )
219        );
220    }
221
222    #[test]
223    fn resize_more_columns_rows() {
224        let mut matrix = Conventional::from_vec((2, 3), vec![1.0, 4.0, 2.0, 5.0, 3.0, 6.0]);
225        matrix.resize((3, 4));
226        assert_eq!(
227            matrix,
228            Conventional::from_vec(
229                (3, 4),
230                matrix![
231                    1.0, 2.0, 3.0, 0.0;
232                    4.0, 5.0, 6.0, 0.0;
233                    0.0, 0.0, 0.0, 0.0;
234                ],
235            )
236        );
237    }
238
239    #[test]
240    fn nonzeros() {
241        let matrix = Conventional::from_vec(2, vec![1.0, 2.0, 3.0, 0.0]);
242        assert_eq!(matrix.nonzeros(), 3);
243    }
244}