Leonetienne/Eule
Homemade math library, mainly targetted towards computer graphics
Matrix4x4.cpp
Go to the documentation of this file.
1 #include "Matrix4x4.h"
2 #include "Vector3.h"
3 #include "Math.h"
4 
5 //#define _EULE_NO_INTRINSICS_
6 #ifndef _EULE_NO_INTRINSICS_
7 #include <immintrin.h>
8 #endif
9 
10 using namespace Eule;
11 
13 {
14  // Create identity matrix
15  for (std::size_t i = 0; i < 4; i++)
16  for (std::size_t j = 0; j < 4; j++)
17  v[i][j] = double(i == j);
18 
19  return;
20 }
21 
23 {
24  v = other.v;
25  return;
26 }
27 
29 {
30  v = std::move(other.v);
31  return;
32 }
33 
35 {
36  Matrix4x4 newMatrix;
37  newMatrix.p = 1;
38 
39  #ifndef _EULE_NO_INTRINSICS_
40 
41 
42  /* <= Matrix3x3 multiplication => */
43 
44  // Load matrix components
45  __m256d __va1 = _mm256_set_pd(v[0][0], v[0][0], v[0][0], v[1][0]);
46  __m256d __va2 = _mm256_set_pd(v[1][0], v[1][0], v[2][0], v[2][0]);
47 
48  __m256d __oa1 = _mm256_set_pd(other[0][0], other[0][1], other[0][2], other[0][0]);
49  __m256d __oa2 = _mm256_set_pd(other[0][1], other[0][2], other[0][0], other[0][1]);
50 
51  __m256d __vb1 = _mm256_set_pd(v[0][1], v[0][1], v[0][1], v[1][1]);
52  __m256d __vb2 = _mm256_set_pd(v[1][1], v[1][1], v[2][1], v[2][1]);
53 
54  __m256d __ob1 = _mm256_set_pd(other[1][0], other[1][1], other[1][2], other[1][0]);
55  __m256d __ob2 = _mm256_set_pd(other[1][1], other[1][2], other[1][0], other[1][1]);
56 
57  __m256d __vc1 = _mm256_set_pd(v[0][2], v[0][2], v[0][2], v[1][2]);
58  __m256d __vc2 = _mm256_set_pd(v[1][2], v[1][2], v[2][2], v[2][2]);
59 
60  __m256d __oc1 = _mm256_set_pd(other[2][0], other[2][1], other[2][2], other[2][0]);
61  __m256d __oc2 = _mm256_set_pd(other[2][1], other[2][2], other[2][0], other[2][1]);
62 
63  // Initialize sums
64  __m256d __sum1 = _mm256_set1_pd(0);
65  __m256d __sum2 = _mm256_set1_pd(0);
66 
67  // Let's multiply-add them together
68  // First, the first block
69  __sum1 = _mm256_fmadd_pd(__va1, __oa1, __sum1);
70  __sum1 = _mm256_fmadd_pd(__vb1, __ob1, __sum1);
71  __sum1 = _mm256_fmadd_pd(__vc1, __oc1, __sum1);
72 
73  // Then the second block
74  __sum2 = _mm256_fmadd_pd(__va2, __oa2, __sum2);
75  __sum2 = _mm256_fmadd_pd(__vb2, __ob2, __sum2);
76  __sum2 = _mm256_fmadd_pd(__vc2, __oc2, __sum2);
77 
78  // Retrieve results
79  double sum1[4];
80  double sum2[4];
81 
82  _mm256_storeu_pd(sum1, __sum1);
83  _mm256_storeu_pd(sum2, __sum2);
84 
85  // Apply results
86  // Block 1
87  newMatrix[0][0] = sum1[3];
88  newMatrix[0][1] = sum1[2];
89  newMatrix[0][2] = sum1[1];
90  newMatrix[1][0] = sum1[0];
91 
92  // Block 2
93  newMatrix[1][1] = sum2[3];
94  newMatrix[1][2] = sum2[2];
95  newMatrix[2][0] = sum2[1];
96  newMatrix[2][1] = sum2[0];
97 
98  // Does not fit in the intrinsic calculation. Might just calculate 'by hand'.
99  newMatrix[2][2] = (v[2][0] * other[0][2]) + (v[2][1] * other[1][2]) + (v[2][2] * other[2][2]);
100 
101 
102  /* <= Translation component => */
103 
104  // Load translation components into registers
105  __m256d __transSelf = _mm256_set_pd(0, l, h, d);
106  __m256d __transOther = _mm256_set_pd(0, other.l, other.h, other.d);
107 
108  // Let's add them
109  __m256d __sum = _mm256_add_pd(__transSelf, __transOther);
110 
111  // Retrieve results
112  double sum[4];
113  _mm256_storeu_pd(sum, __sum);
114 
115  // Apply them
116  newMatrix.d = sum[0];
117  newMatrix.h = sum[1];
118  newMatrix.l = sum[2];
119 
120  #else
121 
122 
123  // Rotation, Scaling
124  newMatrix[0][0] = (v[0][0] * other[0][0]) + (v[0][1] * other[1][0]) + (v[0][2] * other[2][0]);
125  newMatrix[0][1] = (v[0][0] * other[0][1]) + (v[0][1] * other[1][1]) + (v[0][2] * other[2][1]);
126  newMatrix[0][2] = (v[0][0] * other[0][2]) + (v[0][1] * other[1][2]) + (v[0][2] * other[2][2]);
127 
128  newMatrix[1][0] = (v[1][0] * other[0][0]) + (v[1][1] * other[1][0]) + (v[1][2] * other[2][0]);
129  newMatrix[1][1] = (v[1][0] * other[0][1]) + (v[1][1] * other[1][1]) + (v[1][2] * other[2][1]);
130  newMatrix[1][2] = (v[1][0] * other[0][2]) + (v[1][1] * other[1][2]) + (v[1][2] * other[2][2]);
131 
132  newMatrix[2][0] = (v[2][0] * other[0][0]) + (v[2][1] * other[1][0]) + (v[2][2] * other[2][0]);
133  newMatrix[2][1] = (v[2][0] * other[0][1]) + (v[2][1] * other[1][1]) + (v[2][2] * other[2][1]);
134  newMatrix[2][2] = (v[2][0] * other[0][2]) + (v[2][1] * other[1][2]) + (v[2][2] * other[2][2]);
135 
136 
137  // Translation
138  newMatrix[0][3] = v[0][3] + other[0][3];
139  newMatrix[1][3] = v[1][3] + other[1][3];
140  newMatrix[2][3] = v[2][3] + other[2][3];
141 
142  #endif
143 
144  return newMatrix;
145 }
146 
148 {
149  *this = *this * other;
150  return;
151 }
152 
154 {
155  return *this * other.Inverse3x3();
156 }
157 
159 {
160  *this = *this * other.Inverse3x3();
161  return;
162 }
163 
164 Matrix4x4 Matrix4x4::operator*(const double scalar) const
165 {
166  Matrix4x4 m;
167 
168  #ifndef _EULE_NO_INTRINSICS_
169 
170  // Load matrix rows
171  __m256d __row0 = _mm256_set_pd(v[0][3], v[0][2], v[0][1], v[0][0]);
172  __m256d __row1 = _mm256_set_pd(v[1][3], v[1][2], v[1][1], v[1][0]);
173  __m256d __row2 = _mm256_set_pd(v[2][3], v[2][2], v[2][1], v[2][0]);
174  __m256d __row3 = _mm256_set_pd(v[3][3], v[3][2], v[3][1], v[3][0]);
175 
176  // Load scalar
177  __m256d __scalar = _mm256_set1_pd(scalar);
178 
179  // Scale values
180  __m256d __sr0 = _mm256_mul_pd(__row0, __scalar);
181  __m256d __sr1 = _mm256_mul_pd(__row1, __scalar);
182  __m256d __sr2 = _mm256_mul_pd(__row2, __scalar);
183  __m256d __sr3 = _mm256_mul_pd(__row3, __scalar);
184 
185  // Extract results
186  _mm256_storeu_pd(m.v[0].data(), __sr0);
187  _mm256_storeu_pd(m.v[1].data(), __sr1);
188  _mm256_storeu_pd(m.v[2].data(), __sr2);
189  _mm256_storeu_pd(m.v[3].data(), __sr3);
190 
191  #else
192 
193  for (std::size_t x = 0; x < 4; x++)
194  for (std::size_t y = 0; y < 4; y++)
195  m[x][y] = v[x][y] * scalar;
196 
197  #endif
198 
199  return m;
200 }
201 
202 void Matrix4x4::operator*=(const double scalar)
203 {
204  *this = *this * scalar;
205  return;
206 }
207 
208 Matrix4x4 Matrix4x4::operator/(const double denominator) const
209 {
210  const double precomputeDivision = 1.0 / denominator;
211 
212  return *this * precomputeDivision;
213 }
214 
215 void Matrix4x4::operator/=(const double denominator)
216 {
217  *this = *this / denominator;
218  return;
219 }
220 
222 {
223  Matrix4x4 m;
224 
225  #ifndef _EULE_NO_INTRINSICS_
226 
227  // Load matrix rows
228  __m256d __row0a = _mm256_set_pd(v[0][3], v[0][2], v[0][1], v[0][0]);
229  __m256d __row1a = _mm256_set_pd(v[1][3], v[1][2], v[1][1], v[1][0]);
230  __m256d __row2a = _mm256_set_pd(v[2][3], v[2][2], v[2][1], v[2][0]);
231  __m256d __row3a = _mm256_set_pd(v[3][3], v[3][2], v[3][1], v[3][0]);
232 
233  __m256d __row0b = _mm256_set_pd(other[0][3], other[0][2], other[0][1], other[0][0]);
234  __m256d __row1b = _mm256_set_pd(other[1][3], other[1][2], other[1][1], other[1][0]);
235  __m256d __row2b = _mm256_set_pd(other[2][3], other[2][2], other[2][1], other[2][0]);
236  __m256d __row3b = _mm256_set_pd(other[3][3], other[3][2], other[3][1], other[3][0]);
237 
238  // Add rows
239  __m256d __sr0 = _mm256_add_pd(__row0a, __row0b);
240  __m256d __sr1 = _mm256_add_pd(__row1a, __row1b);
241  __m256d __sr2 = _mm256_add_pd(__row2a, __row2b);
242  __m256d __sr3 = _mm256_add_pd(__row3a, __row3b);
243 
244  // Extract results
245  _mm256_storeu_pd(m.v[0].data(), __sr0);
246  _mm256_storeu_pd(m.v[1].data(), __sr1);
247  _mm256_storeu_pd(m.v[2].data(), __sr2);
248  _mm256_storeu_pd(m.v[3].data(), __sr3);
249 
250  #else
251 
252  for (std::size_t x = 0; x < 4; x++)
253  for (std::size_t y = 0; y < 4; y++)
254  m[x][y] = v[x][y] + other[x][y];
255 
256  #endif
257 
258  return m;
259 }
260 
262 {
263  #ifndef _EULE_NO_INTRINSICS_
264  // Doing it again is a tad directer, and thus faster. We avoid an intermittent Matrix4x4 instance
265 
266  // Load matrix rows
267  __m256d __row0a = _mm256_set_pd(v[0][3], v[0][2], v[0][1], v[0][0]);
268  __m256d __row1a = _mm256_set_pd(v[1][3], v[1][2], v[1][1], v[1][0]);
269  __m256d __row2a = _mm256_set_pd(v[2][3], v[2][2], v[2][1], v[2][0]);
270  __m256d __row3a = _mm256_set_pd(v[3][3], v[3][2], v[3][1], v[3][0]);
271 
272  __m256d __row0b = _mm256_set_pd(other[0][3], other[0][2], other[0][1], other[0][0]);
273  __m256d __row1b = _mm256_set_pd(other[1][3], other[1][2], other[1][1], other[1][0]);
274  __m256d __row2b = _mm256_set_pd(other[2][3], other[2][2], other[2][1], other[2][0]);
275  __m256d __row3b = _mm256_set_pd(other[3][3], other[3][2], other[3][1], other[3][0]);
276 
277  // Add rows
278  __m256d __sr0 = _mm256_add_pd(__row0a, __row0b);
279  __m256d __sr1 = _mm256_add_pd(__row1a, __row1b);
280  __m256d __sr2 = _mm256_add_pd(__row2a, __row2b);
281  __m256d __sr3 = _mm256_add_pd(__row3a, __row3b);
282 
283  // Extract results
284  _mm256_storeu_pd(v[0].data(), __sr0);
285  _mm256_storeu_pd(v[1].data(), __sr1);
286  _mm256_storeu_pd(v[2].data(), __sr2);
287  _mm256_storeu_pd(v[3].data(), __sr3);
288 
289  #else
290 
291  *this = *this + other;
292 
293  #endif
294 
295  return;
296 }
297 
299 {
300  Matrix4x4 m;
301 
302  #ifndef _EULE_NO_INTRINSICS_
303 
304  // Load matrix rows
305  __m256d __row0a = _mm256_set_pd(v[0][3], v[0][2], v[0][1], v[0][0]);
306  __m256d __row1a = _mm256_set_pd(v[1][3], v[1][2], v[1][1], v[1][0]);
307  __m256d __row2a = _mm256_set_pd(v[2][3], v[2][2], v[2][1], v[2][0]);
308  __m256d __row3a = _mm256_set_pd(v[3][3], v[3][2], v[3][1], v[3][0]);
309 
310  __m256d __row0b = _mm256_set_pd(other[0][3], other[0][2], other[0][1], other[0][0]);
311  __m256d __row1b = _mm256_set_pd(other[1][3], other[1][2], other[1][1], other[1][0]);
312  __m256d __row2b = _mm256_set_pd(other[2][3], other[2][2], other[2][1], other[2][0]);
313  __m256d __row3b = _mm256_set_pd(other[3][3], other[3][2], other[3][1], other[3][0]);
314 
315  // Subtract rows
316  __m256d __sr0 = _mm256_sub_pd(__row0a, __row0b);
317  __m256d __sr1 = _mm256_sub_pd(__row1a, __row1b);
318  __m256d __sr2 = _mm256_sub_pd(__row2a, __row2b);
319  __m256d __sr3 = _mm256_sub_pd(__row3a, __row3b);
320 
321  // Extract results
322  _mm256_storeu_pd(m.v[0].data(), __sr0);
323  _mm256_storeu_pd(m.v[1].data(), __sr1);
324  _mm256_storeu_pd(m.v[2].data(), __sr2);
325  _mm256_storeu_pd(m.v[3].data(), __sr3);
326 
327  #else
328 
329  for (std::size_t x = 0; x < 4; x++)
330  for (std::size_t y = 0; y < 4; y++)
331  m[x][y] = v[x][y] - other[x][y];
332 
333  #endif
334 
335  return m;
336 }
337 
339 {
340  #ifndef _EULE_NO_INTRINSICS_
341  // Doing it again is a tad directer, and thus faster. We avoid an intermittent Matrix4x4 instance
342 
343  // Load matrix rows
344  __m256d __row0a = _mm256_set_pd(v[0][3], v[0][2], v[0][1], v[0][0]);
345  __m256d __row1a = _mm256_set_pd(v[1][3], v[1][2], v[1][1], v[1][0]);
346  __m256d __row2a = _mm256_set_pd(v[2][3], v[2][2], v[2][1], v[2][0]);
347  __m256d __row3a = _mm256_set_pd(v[3][3], v[3][2], v[3][1], v[3][0]);
348 
349  __m256d __row0b = _mm256_set_pd(other[0][3], other[0][2], other[0][1], other[0][0]);
350  __m256d __row1b = _mm256_set_pd(other[1][3], other[1][2], other[1][1], other[1][0]);
351  __m256d __row2b = _mm256_set_pd(other[2][3], other[2][2], other[2][1], other[2][0]);
352  __m256d __row3b = _mm256_set_pd(other[3][3], other[3][2], other[3][1], other[3][0]);
353 
354  // Subtract rows
355  __m256d __sr0 = _mm256_sub_pd(__row0a, __row0b);
356  __m256d __sr1 = _mm256_sub_pd(__row1a, __row1b);
357  __m256d __sr2 = _mm256_sub_pd(__row2a, __row2b);
358  __m256d __sr3 = _mm256_sub_pd(__row3a, __row3b);
359 
360  // Extract results
361  _mm256_storeu_pd(v[0].data(), __sr0);
362  _mm256_storeu_pd(v[1].data(), __sr1);
363  _mm256_storeu_pd(v[2].data(), __sr2);
364  _mm256_storeu_pd(v[3].data(), __sr3);
365 
366  #else
367 
368  * this = *this - other;
369 
370  #endif
371 
372  return;
373 }
374 
375 std::array<double, 4>& Matrix4x4::operator[](std::size_t y)
376 {
377  return v[y];
378 }
379 
380 const std::array<double, 4>& Matrix4x4::operator[](std::size_t y) const
381 {
382  return v[y];
383 }
384 
385 void Matrix4x4::operator=(const Matrix4x4& other)
386 {
387  v = other.v;
388  return;
389 }
390 
391 void Matrix4x4::operator=(Matrix4x4&& other) noexcept
392 {
393  v = std::move(other.v);
394  return;
395 }
396 
398 {
399  return v == other.v;
400 }
401 
403 {
404  return !operator==(other);
405 }
406 
408 {
409  return Vector3d(d, h, l);
410 }
411 
413 {
414  d = trans.x;
415  h = trans.y;
416  l = trans.z;
417  return;
418 }
419 
421 {
422  Matrix4x4 m(*this);
423  m.d = 0;
424  m.h = 0;
425  m.l = 0;
426  return m;
427 }
428 
430 {
431  Matrix4x4 trans(*this); // Keep other cells
432 
433  for (std::size_t i = 0; i < 3; i++)
434  for (std::size_t j = 0; j < 3; j++)
435  trans[j][i] = v[i][j];
436 
437  return trans;
438 }
439 
441 {
442  Matrix4x4 trans;
443 
444  for (std::size_t i = 0; i < 4; i++)
445  for (std::size_t j = 0; j < 4; j++)
446  trans[j][i] = v[i][j];
447 
448  return trans;
449 }
450 
452 {
453  Matrix4x4 m;
454 
455  m[0][0] = (v[0][0]*o[0][0]) + (v[0][1]*o[1][0]) + (v[0][2]*o[2][0]) + (v[0][3]*o[3][0]);
456  m[0][1] = (v[0][0]*o[0][1]) + (v[0][1]*o[1][1]) + (v[0][2]*o[2][1]) + (v[0][3]*o[3][1]);
457  m[0][2] = (v[0][0]*o[0][2]) + (v[0][1]*o[1][2]) + (v[0][2]*o[2][2]) + (v[0][3]*o[3][2]);
458  m[0][3] = (v[0][0]*o[0][3]) + (v[0][1]*o[1][3]) + (v[0][2]*o[2][3]) + (v[0][3]*o[3][3]);
459 
460  m[1][0] = (v[1][0]*o[0][0]) + (v[1][1]*o[1][0]) + (v[1][2]*o[2][0]) + (v[1][3]*o[3][0]);
461  m[1][1] = (v[1][0]*o[0][1]) + (v[1][1]*o[1][1]) + (v[1][2]*o[2][1]) + (v[1][3]*o[3][1]);
462  m[1][2] = (v[1][0]*o[0][2]) + (v[1][1]*o[1][2]) + (v[1][2]*o[2][2]) + (v[1][3]*o[3][2]);
463  m[1][3] = (v[1][0]*o[0][3]) + (v[1][1]*o[1][3]) + (v[1][2]*o[2][3]) + (v[1][3]*o[3][3]);
464 
465  m[2][0] = (v[2][0]*o[0][0]) + (v[2][1]*o[1][0]) + (v[2][2]*o[2][0]) + (v[2][3]*o[3][0]);
466  m[2][1] = (v[2][0]*o[0][1]) + (v[2][1]*o[1][1]) + (v[2][2]*o[2][1]) + (v[2][3]*o[3][1]);
467  m[2][2] = (v[2][0]*o[0][2]) + (v[2][1]*o[1][2]) + (v[2][2]*o[2][2]) + (v[2][3]*o[3][2]);
468  m[2][3] = (v[2][0]*o[0][3]) + (v[2][1]*o[1][3]) + (v[2][2]*o[2][3]) + (v[2][3]*o[3][3]);
469 
470  m[3][0] = (v[3][0]*o[0][0]) + (v[3][1]*o[1][0]) + (v[3][2]*o[2][0]) + (v[3][3]*o[3][0]);
471  m[3][1] = (v[3][0]*o[0][1]) + (v[3][1]*o[1][1]) + (v[3][2]*o[2][1]) + (v[3][3]*o[3][1]);
472  m[3][2] = (v[3][0]*o[0][2]) + (v[3][1]*o[1][2]) + (v[3][2]*o[2][2]) + (v[3][3]*o[3][2]);
473  m[3][3] = (v[3][0]*o[0][3]) + (v[3][1]*o[1][3]) + (v[3][2]*o[2][3]) + (v[3][3]*o[3][3]);
474 
475  return m;
476 }
477 
478 Matrix4x4 Matrix4x4::GetCofactors(std::size_t p, std::size_t q, std::size_t n) const
479 {
480  if (n > 4)
481  throw std::runtime_error("Dimension out of range! 0 <= n <= 4");
482 
483  Matrix4x4 cofs;
484 
485  std::size_t i = 0;
486  std::size_t j = 0;
487 
488  for (std::size_t y = 0; y < n; y++)
489  for (std::size_t x = 0; x < n; x++)
490  {
491  if ((y != p) && (x != q))
492  {
493  cofs[i][j] = v[y][x];
494  j++;
495  }
496 
497  if (j == n - 1)
498  {
499  j = 0;
500  i++;
501  }
502  }
503 
504  return cofs;
505 }
506 
507 /*
508 * BEGIN_REF
509 * https://www.geeksforgeeks.org/adjoint-inverse-matrix/
510 */
511 double Matrix4x4::Determinant(std::size_t n) const
512 {
513  if (n > 4)
514  throw std::runtime_error("Dimension out of range! 0 <= n <= 4");
515 
516  double d = 0;
517  double sign = 1;
518 
519  if (n == 1)
520  return v[0][0];
521 
522  for (std::size_t x = 0; x < n; x++)
523  {
524  Matrix4x4 cofs = GetCofactors(0, x, n);
525 
526  d += sign * v[0][x] * cofs.Determinant(n - 1);
527  sign = -sign;
528  }
529 
530  return d;
531 }
532 
533 Matrix4x4 Matrix4x4::Adjoint(std::size_t n) const
534 {
535  if (n > 4)
536  throw std::runtime_error("Dimension out of range! 0 <= n <= 4");
537 
538  Matrix4x4 adj;
539  double sign = 1;
540 
541  for (std::size_t i = 0; i < n; i++)
542  for (std::size_t j = 0; j < n; j++)
543  {
544  Matrix4x4 cofs = GetCofactors(i, j, n);
545 
546  // sign of adj[j][i] positive if sum of row
547  // and column indexes is even.
548  sign = ((i + j) % 2 == 0) ? 1 : -1;
549 
550  // Interchanging rows and columns to get the
551  // transpose of the cofactor matrix
552  adj[j][i] = sign * (cofs.Determinant(n - 1));
553  }
554 
555  return adj;
556 }
557 
559 {
560  Matrix4x4 inv;
561 
562  double det = Determinant(3);
563  if (det == 0.0)
564  throw std::runtime_error("Matrix3x3 not inversible!");
565 
566  Matrix4x4 adj = Adjoint(3);
567 
568  for (std::size_t i = 0; i < 3; i++)
569  for (std::size_t j = 0; j < 3; j++)
570  inv[i][j] = adj[i][j] / det;
571 
573 
574  return inv;
575 }
576 
578 {
579  Matrix4x4 inv;
580 
581  double det = Determinant(4);
582  if (det == 0.0)
583  throw std::runtime_error("Matrix4x4 not inversible!");
584 
585  Matrix4x4 adj = Adjoint(4);
586 
587  for (std::size_t i = 0; i < 4; i++)
588  for (std::size_t j = 0; j < 4; j++)
589  inv[i][j] = adj[i][j] / det;
590 
591  return inv;
592 }
593 
594 /*
595 * END REF
596 */
597 
599 {
600  return (Determinant(3) != 0);
601 }
602 
604 {
605  return (Determinant(4) != 0);
606 }
607 
608 bool Matrix4x4::Similar(const Matrix4x4& other, double epsilon) const
609 {
610  for (std::size_t i = 0; i < 4; i++)
611  for (std::size_t j = 0; j < 4; j++)
612  if (!Math::Similar(v[i][j], other[i][j], epsilon))
613  return false;
614 
615  return true;
616 }
617 
618 namespace Eule
619 {
620  std::ostream& operator<<(std::ostream& os, const Matrix4x4& m)
621  {
622  os << std::endl;
623 
624  for (std::size_t y = 0; y < 4; y++)
625  {
626  for (std::size_t x = 0; x < 4; x++)
627  os << " | " << m[y][x];
628 
629  os << " |" << std::endl;
630  }
631 
632  return os;
633  }
634 
635  std::wostream& operator<<(std::wostream& os, const Matrix4x4& m)
636  {
637  os << std::endl;
638 
639  for (std::size_t y = 0; y < 4; y++)
640  {
641  for (std::size_t x = 0; x < 4; x++)
642  os << L" | " << m[y][x];
643 
644  os << L" |" << std::endl;
645  }
646 
647  return os;
648  }
649 }
Eule::Matrix4x4::j
double & j
Definition: Matrix4x4.h:137
Eule::Matrix4x4::Inverse4x4
Matrix4x4 Inverse4x4() const
Will return the full 4x4-inverse of this matrix.
Definition: Matrix4x4.cpp:577
Eule::Matrix4x4::Adjoint
Matrix4x4 Adjoint(std::size_t n) const
Will return the adjoint of this matrix, by dimension n.
Definition: Matrix4x4.cpp:533
Eule::Matrix4x4::operator==
bool operator==(const Matrix4x4 &other)
Definition: Matrix4x4.cpp:397
Eule::Matrix4x4::operator+
Matrix4x4 operator+(const Matrix4x4 &other) const
Cellwise addition.
Definition: Matrix4x4.cpp:221
Eule::Matrix4x4::i
double & i
Definition: Matrix4x4.h:136
Eule::Matrix4x4::operator-=
void operator-=(const Matrix4x4 &other)
Cellwise subtraction.
Definition: Matrix4x4.cpp:338
Eule::Matrix4x4::Transpose4x4
Matrix4x4 Transpose4x4() const
Will return the 4x4 transpose of this matrix.
Definition: Matrix4x4.cpp:440
Eule::Matrix4x4::operator!=
bool operator!=(const Matrix4x4 &other)
Definition: Matrix4x4.cpp:402
Eule::Vector3< double >
Eule::Matrix4x4::operator[]
std::array< double, 4 > & operator[](std::size_t y)
Definition: Matrix4x4.cpp:375
Eule::Matrix4x4::DropTranslationComponents
Matrix4x4 DropTranslationComponents() const
Will return this Matrix4x4 with d,h,l being set to 0.
Definition: Matrix4x4.cpp:420
Eule::Matrix4x4::operator*=
void operator*=(const Matrix4x4 &other)
Definition: Matrix4x4.cpp:147
Eule::Matrix4x4::Inverse3x3
Matrix4x4 Inverse3x3() const
Will return the 3x3-inverse of this matrix.
Definition: Matrix4x4.cpp:558
Eule::Matrix4x4::operator/
Matrix4x4 operator/(const Matrix4x4 &other) const
Definition: Matrix4x4.cpp:153
Eule::Matrix4x4::v
std::array< std::array< double, 4 >, 4 > v
Array holding the matrices values.
Definition: Matrix4x4.h:44
Eule::Matrix4x4::operator*
Matrix4x4 operator*(const Matrix4x4 &other) const
Definition: Matrix4x4.cpp:34
Math.h
Eule::Vector3d
Vector3< double > Vector3d
Definition: Matrix4x4.h:9
Matrix4x4.h
Eule::Matrix4x4::operator=
void operator=(const Matrix4x4 &other)
Definition: Matrix4x4.cpp:385
Eule::Vector3::z
T z
Definition: Vector3.h:96
Eule::Matrix4x4
A matrix 4x4 class representing a 3d transformation.
Definition: Matrix4x4.h:36
Eule::Matrix4x4::IsInversible4x4
bool IsInversible4x4() const
Will check if the entire matrix is inversible.
Definition: Matrix4x4.cpp:603
Eule::Matrix4x4::Similar
bool Similar(const Matrix4x4 &other, double epsilon=0.00001) const
Will compare if two matrices are similar to a certain epsilon value.
Definition: Matrix4x4.cpp:608
Eule::Matrix4x4::operator/=
void operator/=(const Matrix4x4 &other)
Definition: Matrix4x4.cpp:158
Eule::Vector3::x
T x
Definition: Vector3.h:94
Eule::Matrix4x4::p
double & p
Definition: Matrix4x4.h:143
Eule::Matrix4x4::IsInversible3x3
bool IsInversible3x3() const
Will check if the 3x3-component is inversible.
Definition: Matrix4x4.cpp:598
Eule::Matrix4x4::Transpose3x3
Matrix4x4 Transpose3x3() const
Will return the 3x3 transpose of this matrix.
Definition: Matrix4x4.cpp:429
Eule::operator<<
std::ostream & operator<<(std::ostream &os, const Matrix4x4 &m)
Definition: Matrix4x4.cpp:620
Eule::Matrix4x4::l
double & l
Definition: Matrix4x4.h:139
Eule::Matrix4x4::operator-
Matrix4x4 operator-(const Matrix4x4 &other) const
Cellwise subtraction.
Definition: Matrix4x4.cpp:298
Eule::Matrix4x4::Determinant
double Determinant(std::size_t n) const
Will return the determinant, by dimension n.
Definition: Matrix4x4.cpp:511
Vector3.h
Eule::Math::Similar
static constexpr bool Similar(const double a, const double b, const double epsilon=0.00001)
Compares two double values with a given accuracy.
Eule::Matrix4x4::operator+=
void operator+=(const Matrix4x4 &other)
Cellwise addition.
Definition: Matrix4x4.cpp:261
Eule::Matrix4x4::Matrix4x4
Matrix4x4()
Definition: Matrix4x4.cpp:12
Eule::Matrix4x4::SetTranslationComponent
void SetTranslationComponent(const Vector3d &trans)
Will set d,h,l from a Vector3d(x,y,z)
Definition: Matrix4x4.cpp:412
Eule::Matrix4x4::Multiply4x4
Matrix4x4 Multiply4x4(const Matrix4x4 &o) const
Will return the Matrix4x4 of an actual 4x4 multiplication. operator* only does a 3x3.
Definition: Matrix4x4.cpp:451
Eule::Matrix4x4::o
double & o
Definition: Matrix4x4.h:142
Eule::Matrix4x4::m
double & m
Definition: Matrix4x4.h:140
Eule::Matrix4x4::GetCofactors
Matrix4x4 GetCofactors(std::size_t p, std::size_t q, std::size_t n) const
Will return the cofactors of this matrix, by dimension n.
Definition: Matrix4x4.cpp:478
Eule::Matrix4x4::GetTranslationComponent
const Vector3d GetTranslationComponent() const
Will return d,h,l as a Vector3d(x,y,z)
Definition: Matrix4x4.cpp:407
Eule::Matrix4x4::n
double & n
Definition: Matrix4x4.h:141
Eule::Matrix4x4::h
double & h
Definition: Matrix4x4.h:135
Eule
Definition: Collider.h:4
Eule::Matrix4x4::d
double & d
Definition: Matrix4x4.h:131
Eule::Vector3::y
T y
Definition: Vector3.h:95