matrix_calc/
matrix.rs

1use std::ops::{Add, Mul, Sub};
2
3/// An alias represents matrix row.
4pub type Row = Vec<f32>;
5
6#[derive(Debug)]
7/// Matrix Metadata Storage
8struct MatrixMeta {
9    /// Row count
10    row_count: usize,
11    /// Column count
12    column_count: usize,
13}
14
15#[derive(Debug)]
16/// Matrix itself
17pub struct Matrix {
18    /// The matrix metadata. This meta will be generated automatically.
19    meta: MatrixMeta,
20    /// The matrix data
21    data: Vec<Row>,
22}
23
24impl Matrix {
25    /// Return a new matrix with metadata generated.
26    ///
27    /// # Arguments
28    ///
29    /// * `data` - A vector that stores multiple `Row`s.
30    ///
31    /// # Notes
32    ///
33    /// Try to use macros `create_matrix!()`.
34    /// ```
35    /// use matrix::{create_matrix, create_matrix_row};
36    ///
37    /// let matrix = create_matrix!(
38    ///     create_matrix_row!(1.0,2.0),
39    ///     create_matrix_row!(3.0,4.0)
40    /// );
41    pub fn new(data: Vec<Row>) -> Matrix {
42        let meta = MatrixMeta {
43            row_count: data.len(),
44            column_count: data.get(0).unwrap().len(),
45        };
46
47        for row_index in 0..data.len() {
48            if data.get(row_index).unwrap().len() != meta.column_count {
49                panic!(
50                    "Column counts not match in row {}. (Found {}, Expected {})",
51                    row_index,
52                    data.get(row_index).unwrap().len(),
53                    meta.column_count,
54                );
55            }
56        }
57
58        Matrix { meta, data }
59    }
60}
61
62impl PartialEq<Matrix> for Matrix {
63    /// Compare two matrices with same structure and data.
64    fn eq(&self, other: &Matrix) -> bool {
65        self.meta.row_count == other.meta.row_count
66            && self.meta.column_count == other.meta.column_count
67            && self.data == other.data
68    }
69}
70
71impl Add<Matrix> for Matrix {
72    /// A new matrix object will be returned.
73    type Output = Self;
74
75    /// Perform additions between two matrices and return a result matrix.
76    ///
77    /// ![additions](https://latex.codecogs.com/png.image?%5Cinline%20%5Clarge%20%5Cdpi%7B110%7D%5Cbg%7Bwhite%7D%5Cbegin%7Bbmatrix%7D1%20&%205%5C%5C-4%20&%203%5Cend%7Bbmatrix%7D&plus;%5Cbegin%7Bbmatrix%7D2%20&%20-1%20%5C%5C4%20&%20-1%5Cend%7Bbmatrix%7D=%5Cbegin%7Bbmatrix%7D3%20&%204%20%5C%5C%200%20&%202%5Cend%7Bbmatrix%7D)
78    ///
79    /// # Example
80    /// ```
81    ///   use matrix::{create_matrix, create_matrix_row};
82    ///
83    ///   let lhs = create_matrix!(create_matrix_row!(1.0, 5.0), create_matrix_row!(-4.0, 3.0));
84    ///   let rhs = create_matrix!(create_matrix_row!(2.0, -1.0), create_matrix_row!(4.0, -1.0));
85    ///   let returning_result = create_matrix!(create_matrix_row!(3.0, 4.0), create_matrix_row!(0.0, 2.0));
86    /// ```
87    fn add(self, rhs: Self) -> Self::Output {
88        if self.meta.row_count != rhs.meta.row_count
89            || self.meta.column_count != rhs.meta.column_count
90        {
91            panic!("These two matrices cannot be added.");
92        } else {
93            let mut matrix_vec = vec![];
94            for row_index in 0..self.meta.row_count {
95                let mut matrix_column_vec = vec![];
96                for column_index in 0..self.meta.column_count {
97                    matrix_column_vec.push(
98                        self.data.get(row_index).unwrap().get(column_index).unwrap()
99                            + rhs.data.get(row_index).unwrap().get(column_index).unwrap(),
100                    );
101                }
102                matrix_vec.push(matrix_column_vec);
103            }
104
105            Matrix::new(matrix_vec)
106        }
107    }
108}
109
110/// Perform substraction between two matrices and return a result matrix.
111impl Sub<Matrix> for Matrix {
112    /// A new matrix object will be returned.
113    type Output = Self;
114
115    /// Perform substraction between two matrices and return a result matrix.
116    ///
117    /// ![substraction](https://latex.codecogs.com/png.image?%5Cinline%20%5Clarge%20%5Cdpi%7B110%7D%5Cbg%7Bwhite%7D%5Cbegin%7Bbmatrix%7D4%20&%205%20&%206%5C%5C2%20&%203%20&%204%5Cend%7Bbmatrix%7D-%5Cbegin%7Bbmatrix%7D2%20&%204%20&%206%20%5C%5C1%20&%202%20&%203%5Cend%7Bbmatrix%7D=%5Cbegin%7Bbmatrix%7D2%20&%201%20&%200%20%5C%5C%201%20&%201%20&%201%5Cend%7Bbmatrix%7D)
118    ///
119    /// # Example
120    /// ```
121    /// use matrix::{create_matrix, create_matrix_row};
122    ///
123    /// let lhs = create_matrix!(create_matrix_row!(4.0, 5.0, 6.0), create_matrix_row!(2.0, 3.0, 4.0));
124    /// let rhs = create_matrix!(create_matrix_row!(2.0, 4.0, 6.0), create_matrix_row!(1.0, 2.0, 3.0));
125    /// let returning_result = create_matrix!(create_matrix_row!(2.0, 1.0, 0.0), create_matrix_row!(1.0, 1.0, 1.0));
126    /// ```
127    fn sub(self, rhs: Self) -> Self::Output {
128        if self.meta.row_count != rhs.meta.row_count
129            || self.meta.column_count != rhs.meta.column_count
130        {
131            panic!("These two matrices cannot be substracted.");
132        } else {
133            let mut matrix_vec = vec![];
134            for row_index in 0..self.meta.row_count {
135                let mut matrix_column_vec = vec![];
136                for column_index in 0..self.meta.column_count {
137                    matrix_column_vec.push(
138                        self.data.get(row_index).unwrap().get(column_index).unwrap()
139                            - rhs.data.get(row_index).unwrap().get(column_index).unwrap(),
140                    );
141                }
142                matrix_vec.push(matrix_column_vec);
143            }
144
145            Matrix::new(matrix_vec)
146        }
147    }
148}
149
150impl Mul<Matrix> for Matrix {
151    /// A new matrix object will be returned.
152    type Output = Self;
153
154    /// Perform multiplication between two matrices and return a result matrix.
155    ///
156    /// ![multiplication_1](https://latex.codecogs.com/png.image?%5Cinline%20%5Clarge%20%5Cdpi%7B110%7D%5Cbg%7Bwhite%7D%5Cbegin%7Bbmatrix%7D1%20&%202%20&%203%5C%5C4%20&%205%20&%206%5Cend%7Bbmatrix%7D*%5Cbegin%7Bbmatrix%7D7%20&%208%20%5C%5C9%20&%2010%5C%5C%2011%20&%2012%5Cend%7Bbmatrix%7D=%5Cbegin%7Bbmatrix%7D58%20&%2064%20%5C%5C%20139%20&%20154%5Cend%7Bbmatrix%7D)
157    ///
158    /// # Example 1
159    /// ```
160    /// use matrix::{create_matrix, create_matrix_row};
161    ///
162    /// let lhs = create_matrix!(create_matrix_row!(1.0, 2.0, 3.0), create_matrix_row!(4.0, 5.0, 6.0));
163    /// let rhs = create_matrix!(create_matrix_row!(7.0, 8.0), create_matrix_row!(9.0, 10.0), create_matrix_row!(11.0, 12.0));
164    /// let returning_result = create_matrix!(create_matrix_row!(58.0, 64.0), create_matrix_row!(139.0, 154.0));
165    /// ```
166    ///
167    /// ![multiplication_2](https://latex.codecogs.com/png.image?%5Cinline%20%5Clarge%20%5Cdpi%7B110%7D%5Cbg%7Bwhite%7D%5Cbegin%7Bbmatrix%7D1%20&%202%20&%203%5Cend%7Bbmatrix%7D*%5Cbegin%7Bbmatrix%7D4%20%5C%5C5%20%5C%5C%206%5Cend%7Bbmatrix%7D=%5Cbegin%7Bbmatrix%7D32%5Cend%7Bbmatrix%7D)
168    ///
169    /// # Example 2
170    /// ```
171    /// use matrix::{create_matrix, create_matrix_row};
172    ///
173    /// let lhs = create_matrix!(create_matrix_row!(1.0, 2.0, 3.0));
174    /// let rhs = create_matrix!(create_matrix_row!(4.0), create_matrix_row!(5.0), create_matrix_row!(6.0));
175    /// let return_result = create_matrix!(create_matrix_row!(32.0));
176    /// ```
177    ///
178    /// ![multiplication_3](https://latex.codecogs.com/png.image?%5Cinline%20%5Clarge%20%5Cdpi%7B110%7D%5Cbg%7Bwhite%7D%5Cbegin%7Bbmatrix%7D4%20%5C%5C5%20%5C%5C%206%5Cend%7Bbmatrix%7D*%5Cbegin%7Bbmatrix%7D1%20&%202%20&%203%5Cend%7Bbmatrix%7D=%5Cbegin%7Bbmatrix%7D4%20&%208%20&%2012%20%5C%5C%205%20&%2010%20&%2015%20%5C%5C%206%20&%2012%20&%2018%20%5Cend%7Bbmatrix%7D)
179    ///
180    /// # Example 3
181    /// ```
182    /// use matrix::{create_matrix, create_matrix_row};
183    ///
184    /// let lhs = create_matrix!(create_matrix_row!(4.0), create_matrix_row!(5.0), create_matrix_row!(6.0));
185    /// let rhs = create_matrix!(create_matrix_row!(1.0, 2.0, 3.0));
186    /// let return_result = create_matrix!(
187    ///     create_matrix_row!(4.0, 8.0, 12.0),
188    ///     create_matrix_row!(5.0, 10.0, 15.0),
189    ///     create_matrix_row!(6.0, 12.0, 18.0)
190    /// );
191    /// ```
192    fn mul(self, rhs: Self) -> Self::Output {
193        if self.meta.column_count != rhs.meta.row_count {
194            panic!("These two matrices cannot be multiplied.");
195        } else {
196            let mut matrix_vec = vec![];
197            for row_index in 0..self.meta.row_count {
198                let mut matrix_column_vec = vec![];
199                for column_index in 0..rhs.meta.column_count {
200                    let mut result: f32 = 0.0;
201                    for (index, value) in self.data.get(row_index).unwrap().iter().enumerate() {
202                        result += value * rhs.data.get(index).unwrap().get(column_index).unwrap();
203                    }
204
205                    matrix_column_vec.push(result);
206                }
207                matrix_vec.push(matrix_column_vec);
208            }
209
210            Matrix::new(matrix_vec)
211        }
212    }
213}
214
215impl Mul<Matrix> for f32 {
216    /// A new matrix object will be returned.
217    type Output = Matrix;
218
219    /// Perform multiplication between a matrix and a float number, then return a result matrix.
220    fn mul(self, matrix: Matrix) -> Self::Output {
221        let mut matrix_vec = vec![];
222        for row_index in 0..matrix.meta.row_count {
223            let mut matrix_column_vec = vec![];
224            for column_index in 0..matrix.meta.column_count {
225                matrix_column_vec.push(
226                    self * matrix
227                        .data
228                        .get(row_index)
229                        .unwrap()
230                        .get(column_index)
231                        .unwrap(),
232                );
233            }
234            matrix_vec.push(matrix_column_vec);
235        }
236
237        Matrix::new(matrix_vec)
238    }
239}
240
241#[macro_export]
242/// Macro the create a matrix row.
243///
244/// # Examples
245///
246/// ```
247/// use matrix::{create_matrix, create_matrix_row};
248///
249/// // This matrix contains two rows and each row contains two columns
250/// let matrix = create_matrix!(
251///     create_matrix_row!(1.0,2.0),
252///     create_matrix_row!(3.0,4.0)
253/// );
254macro_rules! create_matrix {
255    ($($x:expr), *) => (
256        {
257            let mut matrix = Vec::new();
258            $(
259                matrix.push($x);
260            )*
261            matrix::matrix::Matrix::new(matrix)
262        }
263    );
264}
265
266#[macro_export]
267/// Macro the create a matrix row.
268///
269/// # Examples
270///
271/// ```
272/// use matrix::create_matrix_row;
273///
274/// // This row contains two columns
275/// let row = create_matrix_row!(1.0, 2.0);
276/// ```
277macro_rules! create_matrix_row {
278    ($($x:expr), *) => (
279        {
280            let mut row = matrix::matrix::Row::new();
281            $(
282                row.push($x);
283            )*
284            row
285        }
286    );
287}