20 #include <xmmintrin.h>
34 static constexpr
float detEpsilon = 1E-10;
40 template <std::
size_t N>
41 static T
det(
const T (&m)[N][N]) {
42 throw std::runtime_error(
"Not implemented!");
46 static T
det(
const T (&m)[2][2]) {
47 return m[0][0] * m[1][1] - m[0][1] * m[1][0];
51 static T
det(
const T (&m)[3][3]) {
52 return m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0]
53 + m[0][2] * m[1][0] * m[2][1] - m[0][2] * m[1][1] * m[2][0]
54 - m[0][1] * m[1][0] * m[2][2] - m[0][0] * m[1][2] * m[2][1];
58 static T
det(
const T (&m)[4][4]) {
59 float s0 = m[0][0] * m[1][1] - m[1][0] * m[0][1];
60 float s1 = m[0][0] * m[1][2] - m[1][0] * m[0][2];
61 float s2 = m[0][0] * m[1][3] - m[1][0] * m[0][3];
62 float s3 = m[0][1] * m[1][2] - m[1][1] * m[0][2];
63 float s4 = m[0][1] * m[1][3] - m[1][1] * m[0][3];
64 float s5 = m[0][2] * m[1][3] - m[1][2] * m[0][3];
66 float c5 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
67 float c4 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
68 float c3 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
69 float c2 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
70 float c1 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
71 float c0 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
73 return (s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0);
82 template <std::
size_t N>
83 static void invert(
const T (&m)[N][N], T (&out)[N][N]) {
84 throw std::runtime_error(
"Not implemented!");
88 static void invert(
const T (&m)[2][2], T (&out)[2][2]) {
90 if(fabs(det) < detEpsilon) {
91 throw std::runtime_error(
"Matrix is not invertable: Determinant is "
92 "smaller than epsilon");
95 float invdet = 1.f /
det;
97 out[0][0] = m[1][1] * invdet;
98 out[0][1] = -m[0][1] * invdet;
99 out[1][0] = -m[1][0] * invdet;
100 out[1][1] = m[0][0] * invdet;
104 static void invert(
const T (&m)[3][3], T (&out)[3][3]) {
106 if(fabs(det) < detEpsilon) {
107 throw std::runtime_error(
"Matrix is not invertable: Determinant is "
108 "smaller than epsilon");
111 float invdet = 1.f /
det;
113 out[0][0] = (m[1][1] * m[2][2] - m[1][2] * m[2][1]) * invdet;
114 out[0][1] = (m[0][2] * m[2][1] - m[0][1] * m[2][2]) * invdet;
115 out[0][2] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * invdet;
117 out[1][0] = (m[1][2] * m[2][0] - m[1][0] * m[2][2]) * invdet;
118 out[1][1] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * invdet;
119 out[1][2] = (m[0][2] * m[1][0] - m[0][0] * m[1][2]) * invdet;
121 out[2][0] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]) * invdet;
122 out[2][1] = (m[0][1] * m[2][0] - m[0][0] * m[2][1]) * invdet;
123 out[2][2] = (m[0][0] * m[1][1] - m[0][1] * m[1][0]) * invdet;
127 static void invert(
const T (&m)[4][4], T (&out)[4][4]) {
128 float s0 = m[0][0] * m[1][1] - m[1][0] * m[0][1];
129 float s1 = m[0][0] * m[1][2] - m[1][0] * m[0][2];
130 float s2 = m[0][0] * m[1][3] - m[1][0] * m[0][3];
131 float s3 = m[0][1] * m[1][2] - m[1][1] * m[0][2];
132 float s4 = m[0][1] * m[1][3] - m[1][1] * m[0][3];
133 float s5 = m[0][2] * m[1][3] - m[1][2] * m[0][3];
135 float c5 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
136 float c4 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
137 float c3 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
138 float c2 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
139 float c1 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
140 float c0 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
142 float det = (s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0);
143 if(fabs(det) < detEpsilon) {
144 throw std::runtime_error(
"Matrix is not invertable: Determinant is "
145 "smaller than epsilon");
148 float invdet = 1.f /
det;
150 out[0][0] = ( m[1][1] * c5 - m[1][2] * c4 + m[1][3] * c3) * invdet;
151 out[0][1] = (-m[0][1] * c5 + m[0][2] * c4 - m[0][3] * c3) * invdet;
152 out[0][2] = ( m[3][1] * s5 - m[3][2] * s4 + m[3][3] * s3) * invdet;
153 out[0][3] = (-m[2][1] * s5 + m[2][2] * s4 - m[2][3] * s3) * invdet;
155 out[1][0] = (-m[1][0] * c5 + m[1][2] * c2 - m[1][3] * c1) * invdet;
156 out[1][1] = ( m[0][0] * c5 - m[0][2] * c2 + m[0][3] * c1) * invdet;
157 out[1][2] = (-m[3][0] * s5 + m[3][2] * s2 - m[3][3] * s1) * invdet;
158 out[1][3] = ( m[2][0] * s5 - m[2][2] * s2 + m[2][3] * s1) * invdet;
160 out[2][0] = ( m[1][0] * c4 - m[1][1] * c2 + m[1][3] * c0) * invdet;
161 out[2][1] = (-m[0][0] * c4 + m[0][1] * c2 - m[0][3] * c0) * invdet;
162 out[2][2] = ( m[3][0] * s4 - m[3][1] * s2 + m[3][3] * s0) * invdet;
163 out[2][3] = (-m[2][0] * s4 + m[2][1] * s2 - m[2][3] * s0) * invdet;
165 out[3][0] = (-m[1][0] * c3 + m[1][1] * c1 - m[1][2] * c0) * invdet;
166 out[3][1] = ( m[0][0] * c3 - m[0][1] * c1 + m[0][2] * c0) * invdet;
167 out[3][2] = (-m[3][0] * s3 + m[3][1] * s1 - m[3][2] * s0) * invdet;
168 out[3][3] = ( m[2][0] * s3 - m[2][1] * s1 + m[2][2] * s0) * invdet;
174 template <std::
size_t R, std::
size_t C>
175 static void transpose(
const T (&m)[R][C],
const T (&out)[C][R]) {
176 for(
int i = 0; i< R; ++i) {
177 for(
int j = 0; j < C; ++j) {
192 template <
typename Ta,
197 inline void matrixMultiply(
const Ta (&lh)[Ra][CR],
198 const Tb (&rh)[CR][Cb],
199 decltype(Ta(0) * Tb(0)) (&out)[Ra][Cb]) {
200 for(
int i = 0; i < Ra; ++i) {
201 for(
int j = 0; j < Cb; ++j) {
203 for(
int k = 0; k < CR; ++k) {
204 out[i][j] += lh[i][k] * rh[k][j];
211 inline void matrixMultiply(
const float (&lh)[2][2],
212 const float (&rh)[2][2],
213 float (&out)[2][2]) {
214 out[0][0] = lh[0][0]*rh[0][0] + lh[0][1]*rh[1][0];
215 out[0][1] = lh[0][0]*rh[0][1] + lh[0][1]*rh[1][1];
216 out[1][0] = lh[1][0]*rh[0][0] + lh[1][1]*rh[1][0];
217 out[1][1] = lh[1][0]*rh[0][1] + lh[1][1]*rh[1][1];
221 inline void matrixMultiply(
const float (&lh)[3][3],
222 const float (&rh)[3][3],
223 float (&out)[3][3]) {
224 for(
int i = 0; i < 3; ++i) {
225 for(
int j = 0; j < 3; ++j) {
226 out[i][j] = lh[i][0] * rh[0][j] + lh[i][1] * rh[1][j] + lh[i][2]
233 inline void matrixMultiply(
const float (&lh)[4][4],
234 const float (&rh)[4][4],
235 float (&out)[4][4]) {
236 const __m128 a = _mm_loadu_ps(rh[0]);
237 const __m128 b = _mm_loadu_ps(rh[1]);
238 const __m128 c = _mm_loadu_ps(rh[2]);
239 const __m128 d = _mm_loadu_ps(rh[3]);
242 t1 = _mm_set_ps1(lh[0][0]);
243 t2 = _mm_mul_ps(a, t1);
244 t1 = _mm_set_ps1(lh[0][1]);
245 t2 = _mm_add_ps(_mm_mul_ps(b, t1), t2);
246 t1 = _mm_set_ps1(lh[0][2]);
247 t2 = _mm_add_ps(_mm_mul_ps(c, t1), t2);
248 t1 = _mm_set_ps1(lh[0][3]);
249 t2 = _mm_add_ps(_mm_mul_ps(d, t1), t2);
250 _mm_storeu_ps(out[0], t2);
252 t1 = _mm_set_ps1(lh[1][0]);
253 t2 = _mm_mul_ps(a, t1);
254 t1 = _mm_set_ps1(lh[1][1]);
255 t2 = _mm_add_ps(_mm_mul_ps(b, t1), t2);
256 t1 = _mm_set_ps1(lh[1][2]);
257 t2 = _mm_add_ps(_mm_mul_ps(c, t1), t2);
258 t1 = _mm_set_ps1(lh[1][3]);
259 t2 = _mm_add_ps(_mm_mul_ps(d, t1), t2);
260 _mm_storeu_ps(out[1], t2);
262 t1 = _mm_set_ps1(lh[2][0]);
263 t2 = _mm_mul_ps(a, t1);
264 t1 = _mm_set_ps1(lh[2][1]);
265 t2 = _mm_add_ps(_mm_mul_ps(b, t1), t2);
266 t1 = _mm_set_ps1(lh[2][2]);
267 t2 = _mm_add_ps(_mm_mul_ps(c, t1), t2);
268 t1 = _mm_set_ps1(lh[2][3]);
269 t2 = _mm_add_ps(_mm_mul_ps(d, t1), t2);
270 _mm_storeu_ps(out[2], t2);
272 t1 = _mm_set_ps1(lh[3][0]);
273 t2 = _mm_mul_ps(a, t1);
274 t1 = _mm_set_ps1(lh[3][1]);
275 t2 = _mm_add_ps(_mm_mul_ps(b, t1), t2);
276 t1 = _mm_set_ps1(lh[3][2]);
277 t2 = _mm_add_ps(_mm_mul_ps(c, t1), t2);
278 t1 = _mm_set_ps1(lh[3][3]);
279 t2 = _mm_add_ps(_mm_mul_ps(d, t1), t2);
280 _mm_storeu_ps(out[3], t2);
287 template <
typename T, std::
size_t R, std::
size_t C>
293 static constexpr std::size_t numRows = R;
294 static constexpr std::size_t numColumns = C;
301 memset(data, 0,
sizeof(data));
306 throw std::out_of_range(
"Invalid row index");
308 for(
int i = 0; i < C; ++i) {
309 out.data[i] = data[index][i];
316 throw std::out_of_range(
"Invalid column index");
318 for(
int i = 0; i < R; ++i) {
319 out.data[i] = data[i][index];
326 throw std::out_of_range(
"Invalid row index");
327 for(
int i = 0; i < C; ++i) {
328 data[index][i] = vec.data[i];
334 throw std::out_of_range(
"Invalid column index");
335 for(
int i = 0; i < R; ++i) {
336 data[i][index] = vec.data[i];
355 template <
typename T, std::
size_t R, std::
size_t C>
365 template <
typename T, std::
size_t N>
369 for(
int i = 0; i < N; ++i) {
370 this->data[i][i] = T(1);
377 for(
int i = 0; i < N; ++i) {
378 out.data[i] = this->data[i][i];
384 for(
int i = 0; i < N; ++i) {
385 this->data[i][i] = vec.data[i];
390 T determinant()
const {
413 template <
typename T, std::
size_t R, std::
size_t C>
418 template <
typename T, std::
size_t R, std::
size_t C>
419 Matrix<T, R, C> operator-(
const Matrix<T, R, C>& m) {
434 template <
typename Ta,
typename Tb, std::
size_t R, std::
size_t C>
435 Matrix<Ta, R, C>& operator+=(Matrix<Ta, R, C>& lh,
436 const Matrix<Tb, R, C>& rh) {
437 for(
int i = 0; i < R; ++i) {
438 for(
int j = 0; j < C; ++j) {
439 lh.data[i][j] += rh.data[i][j];
446 template <
typename Ta,
typename Tb, std::
size_t R, std::
size_t C>
447 Matrix<Ta, R, C>& operator-=(Matrix<Ta, R, C>& lh,
448 const Matrix<Tb, R, C>& rh) {
449 for(
int i = 0; i < R; ++i) {
450 for(
int j = 0; j < C; ++j) {
451 lh.data[i][j] -= rh.data[i][j];
458 template <
typename Ta,
typename Tb, std::
size_t R, std::
size_t C>
459 Matrix<Ta, R, C>& operator*=(Matrix<Ta, R, C>& lh,
460 const Matrix<Tb, R, C>& rh) {
461 internal::matrixMultiply(lh.data, rh.data, lh.data);
466 template <
typename Ta,
typename Tb, std::
size_t R, std::
size_t C>
467 Matrix<Ta, R, C>& operator*=(Matrix<Ta, R, C>& lh, Tb rh) {
468 for(
int i = 0; i < R; ++i) {
469 for(
int j = 0; j < C; ++j) {
477 template <
typename Ta,
typename Tb, std::
size_t R, std::
size_t C>
478 Matrix<Ta, R, C>& operator/=(Matrix<Ta, R, C>& lh, Tb rh) {
479 for(
int i = 0; i < R; ++i) {
480 for(
int j = 0; j < C; ++j) {
490 template <
typename Ta,
typename Tb, std::
size_t R, std::
size_t C>
491 auto operator*(
const Matrix<Ta, R, C>& lh, Tb rh)
492 -> Matrix<decltype(Ta(0) * Tb(0)), R, C> {
493 Matrix<decltype(Ta(0) * Tb(0)), R, C> out(lh);
499 template <
typename Ta,
typename Tb, std::
size_t R, std::
size_t C>
500 auto operator*(Tb lh,
const Matrix<Ta, R, C>& rh)
501 -> Matrix<decltype(Ta(0) * Tb(0)), R, C> {
502 Matrix<decltype(Ta(0) * Tb(0)), R, C> out(rh);
508 template <
typename Ta,
typename Tb, std::
size_t R, std::
size_t C>
509 auto operator/(
const Matrix<Ta, R, C>& lh, Tb rh)
510 -> Matrix<decltype(Ta(0) / Tb(0)), R, C> {
511 Matrix<decltype(Ta(0) / Tb(0)), R, C> out(lh);
517 template <
typename Ta,
typename Tb, std::
size_t R, std::
size_t C>
518 auto operator+(
const Matrix<Ta, R, C>& lh,
const Matrix<Tb, R, C>& rh)
519 -> Matrix<decltype(Ta(0) + Tb(0)), R, C> {
520 Matrix<decltype(Ta(0) + Tb(0)), R, C> out(lh);
526 template <
typename Ta,
typename Tb, std::
size_t R, std::
size_t C>
527 auto operator-(
const Matrix<Ta, R, C>& lh,
const Matrix<Tb, R, C>& rh)
528 -> Matrix<decltype(Ta(0) - Tb(0)), R, C> {
529 Matrix<decltype(Ta(0) - Tb(0)), R, C> out(lh);
535 template <
typename Ta,
typename Tb, std::
size_t R, std::
size_t C>
536 auto operator*(
const Matrix<Ta, R, C>& lh,
const Matrix<Tb, R, C>& rh)
537 -> Matrix<decltype(Ta(0) * Tb(0)), R, C> {
538 Matrix<decltype(Ta(0) * Tb(0)), R, C> out(lh);
539 internal::matrixMultiply(lh.data, rh.data, out.data);
544 template <
typename Ta,
typename Tb, std::
size_t R, std::
size_t C>
545 auto operator*(
const Matrix<Ta, R, C>& lh, Vector<Tb, C> rh)
546 -> Vector<decltype(Ta(0) + Tb(0)), R> {
547 Vector<decltype(Ta(0) + Tb(0)), R> out;
548 internal::matrixMultiply(lh.data,
549 reinterpret_cast<Tb(&)[C][1]>(rh.data),
550 reinterpret_cast<Tb(&)[C][1]>(out.data));
555 template <
typename Ta,
typename Tb, std::
size_t R, std::
size_t C>
556 auto operator*(Vector<Tb, R> lh,
const Matrix<Ta, R, C>& rh)
557 -> Vector<decltype(Ta(0) + Tb(0)), C> {
558 Vector<decltype(Ta(0) + Tb(0)), C> out;
559 internal::matrixMultiply(
reinterpret_cast<Tb(&)[1][R]
>(lh.data),
561 reinterpret_cast<Tb(&)[1][C]>(out.data));
570 template <
typename Tdst,
typename Tsrc>
571 Tdst matrix_cast(
const Tsrc& in) {
575 for(
int i = 0; i < Tdst::numRows && i < Tsrc::numRows; ++i) {
576 for(
int j = 0; j < Tdst::numColumns && j < Tsrc::numColumns; ++j) {
577 out.data[i][j] =
static_cast<typename Tdst::type
>(in.data[i][j]);
582 for(
int i = lxMin(Tsrc::numRows, Tsrc::numColumns);
583 i < lxMin(Tdst::numRows, Tdst::numColumns);
585 out.data[i][i] =
typename Tdst::type(1);
594 template <
typename T, std::
size_t N>
595 using MatQ = Matrix<T, N, N>;
597 template <std::
size_t N>
598 using MatQf = MatQ<float, N>;
599 template <std::
size_t N>
600 using MatQi = MatQ<int, N>;
602 using Mat2f = MatQ<float, 2>;
603 using Mat2i = MatQ<int, 2>;
605 using Mat3f = MatQ<float, 3>;
606 using Mat3i = MatQ<int, 3>;
608 using Mat4f = MatQ<float, 4>;
609 using Mat4i = MatQ<int, 4>;
611 using Mat2x3f = Matrix<float, 2, 3>;
612 using Mat2x4f = Matrix<float, 2, 4>;
613 using Mat3x2f = Matrix<float, 3, 2>;
614 using Mat3x4f = Matrix<float, 3, 4>;
615 using Mat4x2f = Matrix<float, 4, 2>;
616 using Mat4x3f = Matrix<float, 4, 3>;
618 using Mat2x3i = Matrix<int, 2, 3>;
619 using Mat2x4i = Matrix<int, 2, 4>;
620 using Mat3x2i = Matrix<int, 3, 2>;
621 using Mat3x4i = Matrix<int, 3, 4>;
622 using Mat4x2i = Matrix<int, 4, 2>;
623 using Mat4x3i = Matrix<int, 4, 3>;
Represents a vector with arbitrary dimension and type of elements.
Definition: VectorCore.hpp:138
Helper struct for various algorithms.
Definition: MatrixCore.hpp:32
This file will define Vector and various vector functions.
Helper class for common Matrix stuff.
Definition: MatrixCore.hpp:288
static void invert(const T(&m)[N][N], T(&out)[N][N])
calculates the inverted matrix and writes it to out
Definition: MatrixCore.hpp:83
Definition: MatrixCore.hpp:366
static T det(const T(&m)[N][N])
calculates the determinant of the matrix
Definition: MatrixCore.hpp:41
static void transpose(const T(&m)[R][C], const T(&out)[C][R])
Transposes the matrix m and writes result into out.
Definition: MatrixCore.hpp:175
Represents a RxC matrix with elements of type T.
Definition: MatrixCore.hpp:356