Lugdunum  0.1.0
Matrix.inl
Go to the documentation of this file.
1 template <uint8_t Rows, uint8_t Columns, typename T>
2 inline Matrix<Rows, Columns, T>::Matrix(T value) : _values(Rows * Columns) {
3  static_assert(std::is_arithmetic<T>::value, "Can't construct matrix with non integral type");
4 
5  for (uint8_t row = 0; row < Rows; ++row) {
6  for (uint8_t col = 0; col < Columns; ++col) {
7  (*this)(row, col) = value;
8  }
9  }
10 }
11 
12 template <uint8_t Rows, uint8_t Columns, typename T>
13 inline Matrix<Rows, Columns, T>::Matrix(const Values& values) : _values{values} {
14  LUG_ASSERT(values.size() == Rows * Columns, "Matrix construct with bad size initializer list");
15 }
16 
17 template <uint8_t Rows, uint8_t Columns, typename T>
18 inline Matrix<Rows, Columns, T>::Matrix(std::initializer_list<T> list) {
19  LUG_ASSERT(list.size() == Rows * Columns, "Matrix construct with bad size initializer list");
20 
21  auto it = std::begin(list);
22  for (uint8_t row = 0; row < Rows; ++row) {
23  for (uint8_t col = 0; col < Columns; ++col) {
24  (*this)(row, col) = *it;
25  it++;
26  }
27  }
28 }
29 
30 
31 template <uint8_t Rows, uint8_t Columns, typename T>
32 inline constexpr uint8_t Matrix<Rows, Columns, T>::getRows() const {
33  return Rows;
34 }
35 
36 template <uint8_t Rows, uint8_t Columns, typename T>
37 inline constexpr uint8_t Matrix<Rows, Columns, T>::getColumns() const {
38  return Columns;
39 }
40 
41 template <uint8_t Rows, uint8_t Columns, typename T>
43  return _values;
44 }
45 
46 template <uint8_t Rows, uint8_t Columns, typename T>
48  return _values;
49 }
50 
51 template <uint8_t Rows, uint8_t Columns, typename T>
52 inline T& Matrix<Rows, Columns, T>::operator()(uint8_t row, uint8_t col) {
53  return _values[col * Rows + row];
54 }
55 
56 template <uint8_t Rows, uint8_t Columns, typename T>
57 inline constexpr const T& Matrix<Rows, Columns, T>::operator()(uint8_t row, uint8_t col) const {
58  return _values[col * Rows + row];
59 }
60 
61 
62 // Matrix/Scalar operations
63 template <uint8_t Rows, uint8_t Columns, typename T>
65  _values += rhs;
66  return *this;
67 }
68 
69 template <uint8_t Rows, uint8_t Columns, typename T>
71  _values -= rhs;
72  return *this;
73 }
74 
75 template <uint8_t Rows, uint8_t Columns, typename T>
77  _values *= rhs;
78  return *this;
79 }
80 
81 template <uint8_t Rows, uint8_t Columns, typename T>
83  _values /= rhs;
84  return *this;
85 }
86 
87 
88 // Matrix/Matrix operations
89 template <uint8_t Rows, uint8_t Columns, typename T>
91  _values += rhs._values;
92  return *this;
93 }
94 
95 template <uint8_t Rows, uint8_t Columns, typename T>
97  _values -= rhs._values;
98  return *this;
99 }
100 
101 template <uint8_t Rows, uint8_t Columns, typename T>
102 #if defined(LUG_COMPILER_MSVC)
103 template <typename>
105 #else
106 template <bool EnableBool>
107 inline typename std::enable_if<(Rows == Columns) && EnableBool, Matrix<Rows, Columns, T>>::type& Matrix<Rows, Columns, T>::operator*=(const Matrix<Rows, Columns, T>& rhs)
108 #endif
109 {
110  static_assert(Rows == Columns, "Operator *= is only available for square matrices");
111 
112  *this = *this * rhs;
113 
114  return *this;
115 }
116 
117 template <uint8_t Rows, uint8_t Columns, typename T>
118 #if defined(LUG_COMPILER_MSVC)
119 template <typename>
121 #else
122 template <bool EnableBool>
123 inline typename std::enable_if<(Rows == Columns) && EnableBool, Matrix<Rows, Columns, T>>::type& Matrix<Rows, Columns, T>::operator/=(const Matrix<Rows, Columns, T>& rhs)
124 #endif
125 {
126  static_assert(Rows == Columns, "Operator /= is only available for square matrices");
127 
128  *this *= rhs.inverse();
129 
130  return *this;
131 }
132 
133 template <uint8_t Rows, uint8_t Columns, typename T>
134 #if defined(LUG_COMPILER_MSVC)
135 template <typename>
137 #else
138 template <bool EnableBool>
139 inline typename std::enable_if<(Rows == 1) && EnableBool, Matrix<Rows, Columns, T>>::type Matrix<Rows, Columns, T>::inverse() const
140 #endif
141 {
142  static_assert(Rows == Columns, "The matrix has to be a square matrix to calculate the inverse");
143  return Matrix<Rows, Columns, T>(*this);
144 }
145 
146 template <uint8_t Rows, uint8_t Columns, typename T>
147 #if defined(LUG_COMPILER_MSVC)
148 template <typename, typename>
150 #else
151 template <bool EnableBool>
152 inline typename std::enable_if<(Rows == 2) && EnableBool, Matrix<Rows, Columns, T>>::type Matrix<Rows, Columns, T>::inverse() const
153 #endif
154 {
155  static_assert(Rows == Columns, "The matrix has to be a square matrix to calculate the inverse");
156  return (1 / det()) * Matrix<Rows, Columns, T>{
157  (*this)(1, 1),
158  -(*this)(0, 1),
159  -(*this)(1, 0),
160  (*this)(0, 0)
161  };
162 }
163 
164 template <uint8_t Rows, uint8_t Columns, typename T>
165 #if defined(LUG_COMPILER_MSVC)
166 template <typename, typename, typename>
168 #else
169 template <bool EnableBool>
170 inline typename std::enable_if<(Rows == 3) && EnableBool, Matrix<Rows, Columns, T>>::type Matrix<Rows, Columns, T>::inverse() const
171 #endif
172 {
173  static_assert(Rows == Columns, "The matrix has to be a square matrix to calculate the inverse");
174  return (1 / det()) * Matrix<Rows, Columns, T>{
175  (*this)(1, 1) * (*this)(2, 2) - (*this)(1, 2) * (*this)(2, 1),
176  (*this)(0, 2) * (*this)(2, 1) - (*this)(0, 1) * (*this)(2, 2),
177  (*this)(0, 1) * (*this)(1, 2) - (*this)(0, 2) * (*this)(1, 1),
178 
179  (*this)(1, 2) * (*this)(2, 0) - (*this)(1, 0) * (*this)(2, 2),
180  (*this)(0, 0) * (*this)(2, 2) - (*this)(0, 2) * (*this)(2, 0),
181  (*this)(0, 2) * (*this)(1, 0) - (*this)(0, 0) * (*this)(1, 2),
182 
183  (*this)(1, 0) * (*this)(2, 1) - (*this)(1, 1) * (*this)(2, 0),
184  (*this)(0, 1) * (*this)(2, 0) - (*this)(0, 0) * (*this)(2, 1),
185  (*this)(0, 0) * (*this)(1, 1) - (*this)(0, 1) * (*this)(1, 0)
186  };
187 }
188 
189 template <uint8_t Rows, uint8_t Columns, typename T>
190 #if defined(LUG_COMPILER_MSVC)
191 template <typename, typename, typename, typename>
193 #else
194 template <bool EnableBool>
195 inline typename std::enable_if<(Rows == 4) && EnableBool, Matrix<Rows, Columns, T>>::type Matrix<Rows, Columns, T>::inverse() const
196 #endif
197 {
198  static_assert(Rows == Columns, "The matrix has to be a square matrix to calculate the inverse");
199  return (1 / det()) * Matrix<Rows, Columns, T>{
200  // 11
201  (*this)(1, 1) * (*this)(2, 2) * (*this)(3, 3)
202  + (*this)(1, 2) * (*this)(2, 3) * (*this)(3, 1)
203  + (*this)(1, 3) * (*this)(2, 1) * (*this)(3, 2)
204  - (*this)(1, 1) * (*this)(2, 3) * (*this)(3, 2)
205  - (*this)(1, 2) * (*this)(2, 1) * (*this)(3, 3)
206  - (*this)(1, 3) * (*this)(2, 2) * (*this)(3, 1),
207 
208  // 12
209  (*this)(0, 1) * (*this)(2, 3) * (*this)(3, 2)
210  + (*this)(0, 2) * (*this)(2, 1) * (*this)(3, 3)
211  + (*this)(0, 3) * (*this)(2, 2) * (*this)(3, 1)
212  - (*this)(0, 1) * (*this)(2, 2) * (*this)(3, 3)
213  - (*this)(0, 2) * (*this)(2, 3) * (*this)(3, 1)
214  - (*this)(0, 3) * (*this)(2, 1) * (*this)(3, 2),
215 
216  // 13
217  (*this)(0, 1) * (*this)(1, 2) * (*this)(3, 3)
218  + (*this)(0, 2) * (*this)(1, 3) * (*this)(3, 1)
219  + (*this)(0, 3) * (*this)(1, 1) * (*this)(3, 2)
220  - (*this)(0, 1) * (*this)(1, 3) * (*this)(3, 2)
221  - (*this)(0, 2) * (*this)(1, 1) * (*this)(3, 3)
222  - (*this)(0, 3) * (*this)(1, 2) * (*this)(3, 1),
223 
224  // 14
225  (*this)(0, 1) * (*this)(1, 3) * (*this)(2, 2)
226  + (*this)(0, 2) * (*this)(1, 1) * (*this)(2, 3)
227  + (*this)(0, 3) * (*this)(1, 2) * (*this)(2, 1)
228  - (*this)(0, 1) * (*this)(1, 2) * (*this)(2, 3)
229  - (*this)(0, 2) * (*this)(1, 3) * (*this)(2, 1)
230  - (*this)(0, 3) * (*this)(1, 1) * (*this)(2, 2),
231 
232  // 21
233  (*this)(1, 0) * (*this)(2, 3) * (*this)(3, 2)
234  + (*this)(1, 2) * (*this)(2, 0) * (*this)(3, 3)
235  + (*this)(1, 3) * (*this)(2, 2) * (*this)(3, 0)
236  - (*this)(1, 0) * (*this)(2, 2) * (*this)(3, 3)
237  - (*this)(1, 2) * (*this)(2, 3) * (*this)(3, 0)
238  - (*this)(1, 3) * (*this)(2, 0) * (*this)(3, 2),
239 
240  // 22
241  (*this)(0, 0) * (*this)(2, 2) * (*this)(3, 3)
242  + (*this)(0, 2) * (*this)(2, 3) * (*this)(3, 0)
243  + (*this)(0, 3) * (*this)(2, 0) * (*this)(3, 2)
244  - (*this)(0, 0) * (*this)(2, 3) * (*this)(3, 2)
245  - (*this)(0, 2) * (*this)(2, 0) * (*this)(3, 3)
246  - (*this)(0, 3) * (*this)(2, 2) * (*this)(3, 0),
247 
248  // 23
249  (*this)(0, 0) * (*this)(1, 3) * (*this)(3, 2)
250  + (*this)(0, 2) * (*this)(1, 0) * (*this)(3, 3)
251  + (*this)(0, 3) * (*this)(1, 2) * (*this)(3, 0)
252  - (*this)(0, 0) * (*this)(1, 2) * (*this)(3, 3)
253  - (*this)(0, 2) * (*this)(1, 3) * (*this)(3, 0)
254  - (*this)(0, 3) * (*this)(1, 0) * (*this)(3, 2),
255 
256  // 24
257  (*this)(0, 0) * (*this)(1, 2) * (*this)(2, 3)
258  + (*this)(0, 2) * (*this)(1, 3) * (*this)(2, 0)
259  + (*this)(0, 3) * (*this)(1, 0) * (*this)(2, 2)
260  - (*this)(0, 0) * (*this)(1, 3) * (*this)(2, 2)
261  - (*this)(0, 2) * (*this)(1, 0) * (*this)(2, 3)
262  - (*this)(0, 3) * (*this)(1, 2) * (*this)(2, 0),
263 
264  // 31
265  (*this)(1, 0) * (*this)(2, 1) * (*this)(3, 3)
266  + (*this)(1, 1) * (*this)(2, 3) * (*this)(3, 0)
267  + (*this)(1, 3) * (*this)(2, 0) * (*this)(3, 1)
268  - (*this)(1, 0) * (*this)(2, 3) * (*this)(3, 1)
269  - (*this)(1, 1) * (*this)(2, 0) * (*this)(3, 3)
270  - (*this)(1, 3) * (*this)(2, 1) * (*this)(3, 0),
271 
272  // 32
273  (*this)(0, 0) * (*this)(2, 3) * (*this)(3, 1)
274  + (*this)(0, 1) * (*this)(2, 0) * (*this)(3, 3)
275  + (*this)(0, 3) * (*this)(2, 1) * (*this)(3, 0)
276  - (*this)(0, 0) * (*this)(2, 1) * (*this)(3, 3)
277  - (*this)(0, 1) * (*this)(2, 3) * (*this)(3, 0)
278  - (*this)(0, 3) * (*this)(2, 0) * (*this)(3, 1),
279 
280  // 33
281  (*this)(0, 0) * (*this)(1, 1) * (*this)(3, 3)
282  + (*this)(0, 1) * (*this)(1, 3) * (*this)(3, 0)
283  + (*this)(0, 3) * (*this)(1, 0) * (*this)(3, 1)
284  - (*this)(0, 0) * (*this)(1, 3) * (*this)(3, 1)
285  - (*this)(0, 1) * (*this)(1, 0) * (*this)(3, 3)
286  - (*this)(0, 3) * (*this)(1, 1) * (*this)(3, 0),
287 
288  // 34
289  (*this)(0, 0) * (*this)(1, 3) * (*this)(2, 1)
290  + (*this)(0, 1) * (*this)(1, 0) * (*this)(2, 3)
291  + (*this)(0, 3) * (*this)(1, 1) * (*this)(2, 0)
292  - (*this)(0, 0) * (*this)(1, 1) * (*this)(2, 3)
293  - (*this)(0, 1) * (*this)(1, 3) * (*this)(2, 0)
294  - (*this)(0, 3) * (*this)(1, 0) * (*this)(2, 1),
295 
296  // 41
297  (*this)(1, 0) * (*this)(2, 2) * (*this)(3, 1)
298  + (*this)(1, 1) * (*this)(2, 0) * (*this)(3, 2)
299  + (*this)(1, 2) * (*this)(2, 1) * (*this)(3, 0)
300  - (*this)(1, 0) * (*this)(2, 1) * (*this)(3, 2)
301  - (*this)(1, 1) * (*this)(2, 2) * (*this)(3, 0)
302  - (*this)(1, 2) * (*this)(2, 0) * (*this)(3, 1),
303 
304  // 42
305  (*this)(0, 0) * (*this)(2, 1) * (*this)(3, 2)
306  + (*this)(0, 1) * (*this)(2, 2) * (*this)(3, 0)
307  + (*this)(0, 2) * (*this)(2, 0) * (*this)(3, 1)
308  - (*this)(0, 0) * (*this)(2, 2) * (*this)(3, 1)
309  - (*this)(0, 1) * (*this)(2, 0) * (*this)(3, 2)
310  - (*this)(0, 2) * (*this)(2, 1) * (*this)(3, 0),
311 
312  // 43
313  (*this)(0, 0) * (*this)(1, 2) * (*this)(3, 1)
314  + (*this)(0, 1) * (*this)(1, 0) * (*this)(3, 2)
315  + (*this)(0, 2) * (*this)(1, 1) * (*this)(3, 0)
316  - (*this)(0, 0) * (*this)(1, 1) * (*this)(3, 2)
317  - (*this)(0, 1) * (*this)(1, 2) * (*this)(3, 0)
318  - (*this)(0, 2) * (*this)(1, 0) * (*this)(3, 1),
319 
320  // 44
321  (*this)(0, 0) * (*this)(1, 1) * (*this)(2, 2)
322  + (*this)(0, 1) * (*this)(1, 2) * (*this)(2, 0)
323  + (*this)(0, 2) * (*this)(1, 0) * (*this)(2, 1)
324  - (*this)(0, 0) * (*this)(1, 2) * (*this)(2, 1)
325  - (*this)(0, 1) * (*this)(1, 0) * (*this)(2, 2)
326  - (*this)(0, 2) * (*this)(1, 1) * (*this)(2, 0)
327  };
328 }
329 
330 template <uint8_t Rows, uint8_t Columns, typename T>
332  Matrix<Columns, Rows, T> transposeMatrix(0);
333 
334  for (uint8_t row = 0; row < Rows; ++row) {
335  for (uint8_t col = 0; col < Columns; ++col) {
336  transposeMatrix(col, row) = (*this)(row, col);
337  }
338  }
339 
340  return transposeMatrix;
341 }
342 
343 
344 template <uint8_t Rows, uint8_t Columns, typename T>
345 #if defined(LUG_COMPILER_MSVC)
346 template <typename>
347 inline T Matrix<Rows, Columns, T>::det() const
348 #else
349 template <bool EnableBool>
350 inline typename std::enable_if<(Rows == 1) && EnableBool, T>::type Matrix<Rows, Columns, T>::det() const
351 #endif
352 {
353  static_assert(Rows == Columns, "The matrix has to be a square matrix to calculate the determinant");
354  return (*this)(0, 0);
355 }
356 
357 template <uint8_t Rows, uint8_t Columns, typename T>
358 #if defined(LUG_COMPILER_MSVC)
359 template <typename, typename>
360 inline T Matrix<Rows, Columns, T>::det() const
361 #else
362 template <bool EnableBool>
363 inline typename std::enable_if<(Rows == 2) && EnableBool, T>::type Matrix<Rows, Columns, T>::det() const
364 #endif
365 {
366  static_assert(Rows == Columns, "The matrix has to be a square matrix to calculate the determinant");
367  return (
368  (*this)(0, 0) * (*this)(1, 1)
369  - (*this)(0, 1) * (*this)(1, 0)
370  );
371 }
372 
373 template <uint8_t Rows, uint8_t Columns, typename T>
374 #if defined(LUG_COMPILER_MSVC)
375 template <typename, typename, typename>
376 inline T Matrix<Rows, Columns, T>::det() const
377 #else
378 template <bool EnableBool>
379 inline typename std::enable_if<(Rows == 3) && EnableBool, T>::type Matrix<Rows, Columns, T>::det() const
380 #endif
381 {
382  static_assert(Rows == Columns, "The matrix has to be a square matrix to calculate the determinant");
383  return (
384  (*this)(0, 0) * (*this)(1, 1) * (*this)(2, 2)
385  + (*this)(1, 0) * (*this)(2, 1) * (*this)(0, 2)
386  + (*this)(2, 0) * (*this)(0, 1) * (*this)(1, 2)
387  - (*this)(0, 0) * (*this)(2, 1) * (*this)(1, 2)
388  - (*this)(2, 0) * (*this)(1, 1) * (*this)(0, 2)
389  - (*this)(1, 0) * (*this)(0, 1) * (*this)(2, 2)
390  );
391 }
392 
393 template <uint8_t Rows, uint8_t Columns, typename T>
394 #if defined(LUG_COMPILER_MSVC)
395 template <typename, typename, typename, typename>
396 inline T Matrix<Rows, Columns, T>::det() const
397 #else
398 template <bool EnableBool>
399 inline typename std::enable_if<(Rows == 4) && EnableBool, T>::type Matrix<Rows, Columns, T>::det() const
400 #endif
401 {
402  static_assert(Rows == Columns, "The matrix has to be a square matrix to calculate the determinant");
403  return (
404  (*this)(0, 0) * (*this)(1, 1) * (*this)(2, 2) * (*this)(3, 3)
405  + (*this)(0, 0) * (*this)(1, 2) * (*this)(2, 3) * (*this)(3, 1)
406  + (*this)(0, 0) * (*this)(1, 3) * (*this)(2, 1) * (*this)(3, 2)
407 
408  + (*this)(0, 1) * (*this)(1, 0) * (*this)(2, 3) * (*this)(3, 2)
409  + (*this)(0, 1) * (*this)(1, 2) * (*this)(2, 0) * (*this)(3, 3)
410  + (*this)(0, 1) * (*this)(1, 3) * (*this)(2, 2) * (*this)(3, 0)
411 
412  + (*this)(0, 2) * (*this)(1, 0) * (*this)(2, 1) * (*this)(3, 3)
413  + (*this)(0, 2) * (*this)(1, 1) * (*this)(2, 3) * (*this)(3, 0)
414  + (*this)(0, 2) * (*this)(1, 3) * (*this)(2, 0) * (*this)(3, 1)
415 
416  + (*this)(0, 3) * (*this)(1, 0) * (*this)(2, 2) * (*this)(3, 1)
417  + (*this)(0, 3) * (*this)(1, 1) * (*this)(2, 0) * (*this)(3, 2)
418  + (*this)(0, 3) * (*this)(1, 2) * (*this)(2, 1) * (*this)(3, 0)
419 
420  - (*this)(0, 0) * (*this)(1, 1) * (*this)(2, 3) * (*this)(3, 2)
421  - (*this)(0, 0) * (*this)(1, 2) * (*this)(2, 1) * (*this)(3, 3)
422  - (*this)(0, 0) * (*this)(1, 3) * (*this)(2, 2) * (*this)(3, 1)
423 
424  - (*this)(0, 1) * (*this)(1, 0) * (*this)(2, 2) * (*this)(3, 3)
425  - (*this)(0, 1) * (*this)(1, 2) * (*this)(2, 3) * (*this)(3, 0)
426  - (*this)(0, 1) * (*this)(1, 3) * (*this)(2, 0) * (*this)(3, 2)
427 
428  - (*this)(0, 2) * (*this)(1, 0) * (*this)(2, 3) * (*this)(3, 1)
429  - (*this)(0, 2) * (*this)(1, 1) * (*this)(2, 0) * (*this)(3, 3)
430  - (*this)(0, 2) * (*this)(1, 3) * (*this)(2, 1) * (*this)(3, 0)
431 
432  - (*this)(0, 3) * (*this)(1, 0) * (*this)(2, 1) * (*this)(3, 2)
433  - (*this)(0, 3) * (*this)(1, 1) * (*this)(2, 2) * (*this)(3, 0)
434  - (*this)(0, 3) * (*this)(1, 2) * (*this)(2, 0) * (*this)(3, 1)
435  );
436 }
437 
438 template <uint8_t Rows, uint8_t Columns, typename T>
439 #if defined(LUG_COMPILER_MSVC)
440 template <typename, typename, typename, typename, typename>
442 #else
443 template <bool EnableBool>
444 typename std::enable_if<(Rows > 4) && EnableBool, T>::type Matrix<Rows, Columns, T>::det() const
445 #endif
446 {
447  static_assert(Rows == Columns, "The matrix has to be a square matrix to calculate the determinant");
448 
449  T determinant = 0;
450  Matrix<Rows - 1, Columns - 1, T> minorMatrix(0);
451 
452  constexpr uint8_t k = 0;
453  for (uint8_t i = 0; i < Rows; ++i) {
454  for (uint8_t row = 0; row < Rows; ++row) {
455  if (row == k) {
456  continue;
457  }
458 
459  const uint8_t indexRow = row + (row > k ? -1 : 0);
460  for (uint8_t column = 0; column < Columns; ++column) {
461  if (column == i) {
462  continue;
463  }
464 
465  const uint8_t indexColumn = column + (column > i ? -1 : 0);
466  minorMatrix(indexRow, indexColumn) = (*this)(row, column);
467  }
468  }
469 
470  determinant += (*this)(i, k) * ((i + k) % 2 ? 1 : -1) * minorMatrix.det();
471  }
472 
473  return determinant;
474 }
475 
476 
477 template <uint8_t Rows, uint8_t Columns, typename T>
478 #if defined(LUG_COMPILER_MSVC)
479 template <typename>
481 #else
482 template <bool EnableBool>
483 inline typename std::enable_if<(Rows == Columns) && EnableBool, Matrix<Rows, Columns, T>>::type Matrix<Rows, Columns, T>::identity()
484 #endif
485 {
486  static_assert(Rows == Columns, "The identity matrix has to be a square matrix");
487 
488  Matrix<Rows, Columns, T> matrix(0);
489 
490  for (uint8_t i = 0; i < Rows; ++i) {
491  matrix(i, i) = 1;
492  }
493 
494  return matrix;
495 }
496 
497 // Unary operations
498 template <uint8_t Rows, uint8_t Columns, typename T>
499 Matrix<Rows, Columns, T> operator-(const Matrix<Rows, Columns, T>& lhs) {
500  return T(0) - lhs;
501 }
502 
503 // Matrix/Scalar operations
504 template <uint8_t Rows, uint8_t Columns, typename T>
505 inline Matrix<Rows, Columns, T> operator+(const Matrix<Rows, Columns, T>& lhs, T rhs) {
506  return Matrix<Rows, Columns, T>(lhs.getValues() + rhs);
507 }
508 
509 template <uint8_t Rows, uint8_t Columns, typename T>
510 inline Matrix<Rows, Columns, T> operator-(const Matrix<Rows, Columns, T>& lhs, T rhs) {
511  return Matrix<Rows, Columns, T>(lhs.getValues() - rhs);
512 }
513 
514 template <uint8_t Rows, uint8_t Columns, typename T>
515 inline Matrix<Rows, Columns, T> operator*(const Matrix<Rows, Columns, T>& lhs, T rhs) {
516  return Matrix<Rows, Columns, T>(lhs.getValues() * rhs);
517 }
518 
519 template <uint8_t Rows, uint8_t Columns, typename T>
520 inline Matrix<Rows, Columns, T> operator/(const Matrix<Rows, Columns, T>& lhs, T rhs) {
521  return Matrix<Rows, Columns, T>(lhs.getValues() / rhs);
522 }
523 
524 template <uint8_t Rows, uint8_t Columns, typename T>
525 inline Matrix<Rows, Columns, T> operator+(T lhs, const Matrix<Rows, Columns, T>& rhs) {
526  return Matrix<Rows, Columns, T>(lhs + rhs.getValues());
527 }
528 
529 template <uint8_t Rows, uint8_t Columns, typename T>
530 inline Matrix<Rows, Columns, T> operator-(T lhs, const Matrix<Rows, Columns, T>& rhs) {
531  return Matrix<Rows, Columns, T>(lhs - rhs.getValues());
532 }
533 
534 template <uint8_t Rows, uint8_t Columns, typename T>
535 inline Matrix<Rows, Columns, T> operator*(T lhs, const Matrix<Rows, Columns, T>& rhs) {
536  return Matrix<Rows, Columns, T>(lhs * rhs.getValues());
537 }
538 
539 template <uint8_t Rows, uint8_t Columns, typename T>
540 inline Matrix<Rows, Columns, T> operator/(T lhs, const Matrix<Rows, Columns, T>& rhs) {
541  return Matrix<Rows, Columns, T>(lhs / rhs.getValues());
542 }
543 
544 // Matrix/Matrix operations
545 template <uint8_t Rows, uint8_t Columns, typename T>
546 inline Matrix<Rows, Columns, T> operator+(const Matrix<Rows, Columns, T>& lhs, const Matrix<Rows, Columns, T>& rhs) {
547  Matrix<Rows, Columns, T> matrix{lhs};
548 
549  matrix += rhs;
550 
551  return matrix;
552 }
553 
554 template <uint8_t Rows, uint8_t Columns, typename T>
555 inline Matrix<Rows, Columns, T> operator-(const Matrix<Rows, Columns, T>& lhs, const Matrix<Rows, Columns, T>& rhs) {
556  Matrix<Rows, Columns, T> matrix{lhs};
557 
558  matrix -= rhs;
559 
560  return matrix;
561 }
562 
563 template <uint8_t RowsLeft, uint8_t ColumnsLeft, uint8_t RowsRight, uint8_t ColumnsRight, typename T>
564 inline Matrix<RowsLeft, ColumnsRight, T> operator*(const Matrix<RowsLeft, ColumnsLeft, T>& lhs, const Matrix<RowsRight, ColumnsRight, T>& rhs) {
565  static_assert(ColumnsLeft == RowsRight, "Columns of the right operand and Rows of the left operand must be of the same size to multiply matrices");
566 
567  Matrix<RowsLeft, ColumnsRight, T> matrix(0);
568 
569  for (uint8_t i = 0; i < RowsLeft; ++i) {
570  for (uint8_t j = 0; j < ColumnsRight; ++j) {
571  for (uint8_t k = 0; k < RowsRight; ++k) {
572  matrix(i, j) += lhs(i, k) * rhs(k, j);
573  }
574  }
575  }
576 
577  return matrix;
578 }
579 
580 template <uint8_t RowsLeft, uint8_t ColumnsLeft, uint8_t RowsRight, uint8_t ColumnsRight, typename T>
581 inline Matrix<RowsLeft, ColumnsRight, T> operator/(const Matrix<RowsLeft, ColumnsLeft, T>& lhs, const Matrix<RowsRight, ColumnsRight, T>& rhs) {
582  static_assert(RowsLeft == ColumnsLeft, "Matrix division can only happen with square matrix");
583  static_assert(RowsRight == ColumnsRight, "Matrix division can only happen with square matrix");
584  static_assert(RowsLeft == RowsRight, "Matrix division can only happen with matrices of the same size");
585 
586  return lhs * rhs.inverse();
587 }
588 
589 
590 // Comparaison operators
591 template <uint8_t Rows, uint8_t Columns, typename T>
592 inline bool operator==(const Matrix<Rows, Columns, T>& lhs, const Matrix<Rows, Columns, T>& rhs) {
593  return (lhs.getValues() == rhs.getValues());
594 }
595 
596 template <uint8_t Rows, uint8_t Columns, typename T>
597 inline bool operator!=(const Matrix<Rows, Columns, T>& lhs, const Matrix<Rows, Columns, T>& rhs) {
598  return (lhs.getValues() != rhs.getValues());
599 }
600 
601 // TODO: Handle alignment of values
602 template <uint8_t Rows, uint8_t Columns, typename T>
603 std::ostream& operator<<(std::ostream& os, const Matrix<Rows, Columns, T>& matrix) {
604  os << "{\n";
605 
606  for (uint8_t i = 0; i < Rows; ++i) {
607  os << " ";
608 
609  for (uint8_t j = 0; j < Columns; ++j) {
610  if (j != 0) {
611  os << ", ";
612  }
613 
614  os << matrix(i, j);
615  }
616 
617  os << "\n";
618  }
619 
620  os << "}";
621 
622  return os;
623 }
Quaternion< T > inverse(const Quaternion< T > &lhs)
Definition: Quaternion.inl:187
#define LUG_ASSERT(assertion, message)
Definition: Debug.hpp:38
bool operator!=(const Matrix< Rows, Columns, T > &lhs, const Matrix< Rows, Columns, T > &rhs)
Definition: Matrix.inl:597
bool operator==(const Matrix< Rows, Columns, T > &lhs, const Matrix< Rows, Columns, T > &rhs)
Definition: Matrix.inl:592
Matrix< Rows, Columns, T > operator-(const Matrix< Rows, Columns, T > &lhs)
Definition: Matrix.inl:499
Matrix< Rows, Columns, T > operator*(const Matrix< Rows, Columns, T > &lhs, T rhs)
Definition: Matrix.inl:515
std::enable_if<(Rows==1) &&EnableBool, Matrix< Rows, Columns, T > >::type inverse() const
Matrix< Rows, Columns, T > operator/(const Matrix< Rows, Columns, T > &lhs, T rhs)
Definition: Matrix.inl:520
Matrix< Rows, Columns, T > operator+(const Matrix< Rows, Columns, T > &lhs, T rhs)
Definition: Matrix.inl:505