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 /// 
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 /// 
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 /// 
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 /// 
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 /// 
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}