Easy3D 2.6.1
Loading...
Searching...
No Matches
mat.h
1/********************************************************************
2 * Copyright (C) 2015 Liangliang Nan <liangliang.nan@gmail.com>
3 * https://3d.bk.tudelft.nl/liangliang/
4 *
5 * This file is part of Easy3D. If it is useful in your research/work,
6 * I would be grateful if you show your appreciation by citing it:
7 * ------------------------------------------------------------------
8 * Liangliang Nan.
9 * Easy3D: a lightweight, easy-to-use, and efficient C++ library
10 * for processing and rendering 3D data.
11 * Journal of Open Source Software, 6(64), 3255, 2021.
12 * ------------------------------------------------------------------
13 *
14 * Easy3D is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License Version 3
16 * as published by the Free Software Foundation.
17 *
18 * Easy3D is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 ********************************************************************/
26
27#ifndef EASY3D_CORE_MAT_H
28#define EASY3D_CORE_MAT_H
29
30#include <iostream>
31#include <iomanip>
32
33#include <easy3d/core/vec.h>
34#include <easy3d/core/constant.h>
35#include <easy3d/util/logging.h>
36
37
38namespace easy3d {
39
40
44 //#define MATRIX_ROW_MAJOR
45
46 template <typename T> class Mat2;
47 template <typename T> class Mat3;
48 template <typename T> class Mat4;
49
50
62 template <size_t N, size_t M, typename T>
63 class Mat
64 {
65 public:
66 // ----------------- constructor and destructor -------------------
67
74 Mat() = default;
75
80 explicit Mat(T s);
81
90 template <size_t rN, size_t rM>
91 explicit Mat(const Mat<rN, rM, T> &rhs);
92
97 explicit Mat(const T *m);
98
105
106 // ------------------- size query ---------------------
107
112 static size_t num_rows() { return N; }
113
118 static size_t num_columns() { return M; }
119
120 // --------------------- access -----------------------
121
127 Vec<M, T> row(size_t row) const;
128
134 Vec<N, T> col(size_t col) const;
135
142 const T& operator()(size_t row, size_t col) const;
143
150 T& operator()(size_t row, size_t col);
151
156 operator const T*() const;
157
162 operator T*();
163
164 // --------------------- modification ------------------
165
169 void load_zero();
170
175 void load_identity(T s = T(1));
176
184 template <size_t vN>
185 void set_row(size_t row, const Vec<vN, T> &v);
186
194 template <size_t vN>
195 void set_col(size_t col, const Vec<vN, T> &v);
196
202 void swap_rows(size_t a, size_t b);
203
209 void swap_cols(size_t a, size_t b);
210
211 // ------- matrix-matrix arithmetic operators --------
212
218 bool operator==(const Mat<N, M, T> &rhs) const;
219
225 bool operator!=(const Mat<N, M, T> &rhs) const;
226
233 template <size_t rM>
235
242
249
255
256 // ------- matrix-vector arithmetic operators --------
257
263 Vec<N, T> operator*(const Vec<M, T> &rhs) const;
264
265 // ------- matrix-scalar arithmetic operators --------
266
279
280 // ------- matrix-matrix assignment operators --------
281
288
295
302
303 // ------- matrix-scalar assignment operators --------
304
311
318
325
332
333 protected:
335 T m_[N * M];
336 };
337
338
339 // ------- global scalar-matrix arithmetic operators --------
340
350 template <size_t N, size_t M, typename T>
351 Mat<N, M, T> operator*(T lhs, const Mat<N, M, T> &rhs);
352
353 // ------- global matrix-matrix multiplication operators --------
354
362 template <typename T>
363 Mat2<T> operator*(const Mat2<T> &lhs, const Mat2<T> &rhs);
364
372 template <typename T>
373 Mat3<T> operator*(const Mat3<T> &lhs, const Mat3<T> &rhs);
374
382 template <typename T>
383 Mat4<T> operator*(const Mat4<T> &lhs, const Mat4<T> &rhs);
384
385 // ------- global matrix-vector arithmetic operators --------
386
394 template <typename T>
395 Vec<3, T> operator*(const Mat4<T> &lhs, const Vec<3, T> &rhs);
396
404 template <typename T>
405 Vec<2, T> operator*(const Mat3<T> &lhs, const Vec<2, T> &rhs);
406
414 template <typename T>
415 Vec<2, T> operator*(const Mat2<T> &lhs, const Vec<2, T> &rhs);
416
424 template <typename T>
425 Vec<3, T> operator*(const Mat3<T> &lhs, const Vec<3, T> &rhs);
426
434 template <typename T>
435 Vec<4, T> operator*(const Mat4<T> &lhs, const Vec<4, T> &rhs);
436
437 // -------------- global matrix related function ---------------
438
446 template <size_t N, typename T>
447 T trace(const Mat<N, N, T> &m);
448
458 template <size_t N, typename T>
459 T determinant(const Mat<N, N, T> &m);
460
469 template <size_t N, size_t M, typename T>
471
481 template <size_t N, typename T>
483
494 template <size_t M, size_t N, typename T>
495 Mat<N, M, T> tensor(const Vec<M, T> &u, const Vec<N, T> &v);
496
509 template<size_t N, size_t M, typename T>
511
527 template<size_t N, typename T>
528 bool lu_decomposition(const Mat<N, N, T> &a, Mat<N, N, T> *alu, Vec<N, T> *rowp, T *d);
529
589 template <size_t N, typename T>
590 void lu_back_substitution(const Mat<N, N, T> &alu, const Vec<N, T> &rowp, const Vec<N, T> &b, Vec<N, T> *x);
591
604 template<size_t N, typename FT>
606
615 template <size_t N, typename FT>
616 void cholesky_solve(const Mat<N, N, FT> &L, const Vec<N, FT> &b, Vec<N, FT>& x);
617
628 template<size_t N, size_t M, typename T>
629 void cholesky_solve(const Mat<N, N, T> &L, const Mat<N, M, T> &B, Mat<N, M, T>& X);
630
640 template <size_t N, size_t M, typename T>
641 std::ostream& operator<< (std::ostream& output, const Mat<N, M, T>& m);
642
652 template <size_t N, size_t M, typename T>
653 std::istream& operator>> (std::istream& input, Mat<N, M, T>& m);
654
655
656 /*******************************************************************************
657
658 IMPLEMENTATION:
659
660 *******************************************************************************/
661
662 /*----------------------------------------------------------------------------*/
663 template <size_t N, size_t M, typename T>
665 for (size_t i = 0; i < N; ++i) {
666 for (size_t j = 0; j < M; ++j)
667 if (i == j)
668 (*this)(i, j) = T(s);
669 else
670 (*this)(i, j) = T(0);
671 }
672 }
673
674 /*----------------------------------------------------------------------------*/
675 template <size_t N, size_t M, typename T>
676 template <size_t rN, size_t rM>
678 assert(rN >= N);
679 assert(rM >= M);
680
681 for (size_t i = 0; i < N; ++i)
682 for (size_t j = 0; j < M; ++j)
683 (*this)(i, j) = rhs(i, j);
684 }
685
686 /*----------------------------------------------------------------------------*/
687 template <size_t N, size_t M, typename T>
688 Mat<N, M, T>::Mat(const T *m) {
689 assert(m != nullptr);
690
691 for (size_t i = 0; i < N * M; ++i)
692 m_[i] = m[i];
693 }
694
695 /*----------------------------------------------------------------------------*/
696 template <size_t N, size_t M, typename T>
698 Mat<N, M, T> result;
699 for (size_t i = 0; i < N; ++i) {
700 for (size_t j = 0; j < M; ++j)
701 if (i == j)
702 result(i, j) = T(1);
703 else
704 result(i, j) = T(0);
705 }
706 return result;
707 }
708
709
710 /*----------------------------------------------------------------------------*/
711 template <size_t N, size_t M, typename T>
712 Vec<M, T> Mat<N, M, T>::row(size_t r) const {
713 assert(r < N);
714
715 Vec<M, T> result;
716 for (size_t i = 0; i < M; ++i)
717 result[i] = (*this)(r, i);
718 return result;
719 }
720
721 /*----------------------------------------------------------------------------*/
722 template <size_t N, size_t M, typename T>
723 Vec<N, T> Mat<N, M, T>::col(size_t c) const {
724 assert(c < M);
725
726 Vec<N, T> result;
727 for (size_t i = 0; i < N; ++i)
728 result[i] = (*this)(i, c);
729 return result;
730 }
731
732 /*----------------------------------------------------------------------------*/
733 template <size_t N, size_t M, typename T>
734 template <size_t vN>
735 void Mat<N, M, T>::set_row(size_t r, const Vec<vN, T> &v) {
736 assert(r < N);
737 assert(vN >= M);
738
739 for (size_t i = 0; i < M; ++i)
740 (*this)(r, i) = v[i];
741 }
742
743 /*----------------------------------------------------------------------------*/
744 template <size_t N, size_t M, typename T>
745 template <size_t vN>
746 void Mat<N, M, T>::set_col(size_t c, const Vec<vN, T> &v) {
747 assert(c < M);
748 assert(vN >= N);
749
750 for (size_t i = 0; i < N; ++i)
751 (*this)(i, c) = v[i];
752 }
753
754 /*----------------------------------------------------------------------------*/
755 template <size_t N, size_t M, typename T>
756 void Mat<N, M, T>::swap_rows(size_t a, size_t b) {
757 assert(a < N);
758 assert(b < N);
759
760 for (size_t i = 0; i < M; ++i) {
761 T tmp = (*this)(a, i);
762 (*this)(a, i) = (*this)(b, i);
763 (*this)(b, i) = tmp;
764 }
765 }
766
767 /*----------------------------------------------------------------------------*/
768 template <size_t N, size_t M, typename T>
770 size_t size = N * M;
771 for (size_t i = 0; i < size; ++i)
772 m_[i] = T(0);
773 }
774
775 /*----------------------------------------------------------------------------*/
776 template <size_t N, size_t M, typename T>
777 void Mat<N, M, T>::load_identity(T s /* = T(1)*/) {
778 for (size_t i = 0; i < N; ++i) {
779 for (size_t j = 0; j < M; ++j)
780 if (i == j)
781 (*this)(i, j) = T(s);
782 else
783 (*this)(i, j) = T(0);
784 }
785 }
786
787 /*----------------------------------------------------------------------------*/
788 template <size_t N, size_t M, typename T>
789 void Mat<N, M, T>::swap_cols(size_t a, size_t b) {
790 assert(a < M);
791 assert(b < M);
792
793 for (size_t i = 0; i < N; ++i) {
794 T tmp = (*this)(i, a);
795 (*this)(i, a) = (*this)(i, b);
796 (*this)(i, b) = tmp;
797 }
798 }
799
800 /*----------------------------------------------------------------------------*/
801 template <size_t N, size_t M, typename T>
802 Mat<N, M, T>::operator const T*() const {
803 return m_;
804 }
805
806 /*----------------------------------------------------------------------------*/
807 template <size_t N, size_t M, typename T>
809 return m_;
810 }
811
812 /*----------------------------------------------------------------------------*/
813 template <size_t N, size_t M, typename T>
814 const T& Mat<N, M, T>::operator()(size_t row, size_t col) const {
815 assert(row < N);
816 assert(col < M);
817
818 #ifdef MATRIX_ROW_MAJOR
819 return m_[row * M + col]; // row-major
820 #else
821 return m_[col * N + row]; // column-major
822 #endif
823 }
824
825 /*----------------------------------------------------------------------------*/
826 template <size_t N, size_t M, typename T>
827 T& Mat<N, M, T>::operator()(size_t row, size_t col) {
828 assert(row < N);
829 assert(col < M);
830
831 #ifdef MATRIX_ROW_MAJOR
832 return m_[row * M + col]; // row-major
833 #else
834 return m_[col * N + row]; // column-major
835 #endif
836 }
837
838 /*----------------------------------------------------------------------------*/
839 template <size_t N, size_t M, typename T>
840 bool Mat<N, M, T>::operator==(const Mat<N, M, T> &rhs) const {
841 bool result = true;
842 for (size_t i = 0; i < N * M; ++i)
843 result &= epsilon_equal(m_[i], rhs[i], T(0));
844 return result;
845 }
846
847 /*----------------------------------------------------------------------------*/
848 template <size_t N, size_t M, typename T>
849 bool Mat<N, M, T>::operator!=(const Mat<N, M, T> &rhs) const {
850 return !(*this == rhs);
851 }
852
853
854 /*----------------------------------------------------------------------------*/
855 template <size_t N, size_t M, typename T>
856 template <size_t rM>
858 Mat<N, rM, T> result;
859 for (size_t i = 0; i < N; ++i) {
860 for (size_t j = 0; j < rM; ++j) {
861 result(i, j) = T(0);
862 for (size_t k = 0; k < M; ++k) {
863 result(i, j) += (*this)(i, k) * rhs(k, j);
864 }
865 }
866 }
867 return result;
868 }
869
870 /*----------------------------------------------------------------------------*/
871 template <size_t N, size_t M, typename T>
873 Mat<N, M, T> result;
874 for (size_t i = 0; i < N * M; ++i)
875 result[i] = m_[i] + rhs[i];
876 return result;
877 }
878
879 /*----------------------------------------------------------------------------*/
880 template <size_t N, size_t M, typename T>
882 Mat<N, M, T> result;
883 for (size_t i = 0; i < N * M; ++i)
884 result[i] = m_[i] - rhs[i];
885 return result;
886 }
887
888 /*----------------------------------------------------------------------------*/
889 template <size_t N, size_t M, typename T>
891 Mat<N, M, T> result;
892 for (size_t i = 0; i < N * M; ++i)
893 result[i] = -m_[i];
894 return result;
895 }
896
897
898 // MATRIX-VECTOR ARITHMETIC OPERATORS:
899
900 /*----------------------------------------------------------------------------*/
901 template <size_t N, size_t M, typename T>
903 Vec<N, T> result;
904 for (size_t i = 0; i < N; ++i) {
905 result[i] = 0;
906 for (size_t j = 0; j < M; ++j) {
907 result[i] += (*this)(i, j) * rhs[j];
908 }
909 }
910 return result;
911 }
912
913
914 // MATRIX-SCALAR ARITHMETIC OPERATORS:
915
916 /*----------------------------------------------------------------------------*/
917 template <size_t N, size_t M, typename T>
919 Mat<N, M, T> result;
920 for (size_t i = 0; i < N * M; ++i)
921 result[i] = m_[i] * rhs;
922 return result;
923 }
924
925 /*----------------------------------------------------------------------------*/
926 template <size_t N, size_t M, typename T>
928 Mat<N, M, T> result;
929 for (size_t i = 0; i < N * M; ++i)
930 result[i] = m_[i] / rhs;
931 return result;
932 }
933
934 // MATRIX-MATRIX ASSIGNMENT OPERATORS:
935
936 /*----------------------------------------------------------------------------*/
937 template <size_t N, size_t M, typename T>
939 Mat<N, M, T> tmp = *this * rhs;
940 *this = tmp;
941 return *this;
942 }
943
944 /*----------------------------------------------------------------------------*/
945 template <size_t N, size_t M, typename T>
947 for (size_t i = 0; i < N * M; ++i)
948 m_[i] += rhs[i];
949 return *this;
950 }
951
952 /*----------------------------------------------------------------------------*/
953 template <size_t N, size_t M, typename T>
955 for (size_t i = 0; i < N * M; ++i)
956 m_[i] -= rhs[i];
957 return *this;
958 }
959
960
961 // MATRIX-SCALAR ASSIGNMENT OPERATORS:
962
963 /*----------------------------------------------------------------------------*/
964 template <size_t N, size_t M, typename T>
966 for (size_t i = 0; i < N * M; ++i)
967 m_[i] *= rhs;
968 return *this;
969 }
970
971 /*----------------------------------------------------------------------------*/
972 template <size_t N, size_t M, typename T>
974 for (size_t i = 0; i < N * M; ++i)
975 m_[i] /= rhs;
976 return *this;
977 }
978
979 /*----------------------------------------------------------------------------*/
980 template <size_t N, size_t M, typename T>
982 for (size_t i = 0; i < N * M; ++i)
983 m_[i] += rhs;
984 return *this;
985 }
986
987 /*----------------------------------------------------------------------------*/
988 template <size_t N, size_t M, typename T>
990 for (size_t i = 0; i < N * M; ++i)
991 m_[i] -= rhs;
992 return *this;
993 }
994
995
996 // GLOBAL SCALAR-MATRIX ARITHMETIC OPERATORS:
997
998 /*----------------------------------------------------------------------------*/
999 template <size_t N, size_t M, typename T>
1001 Mat<N, M, T> result;
1002 for (size_t i = 0; i < N * M; ++i)
1003 result[i] = lhs * rhs[i];
1004 return result;
1005 }
1006
1007
1008 // ------- global matrix-matrix multiplication operators --------
1009
1010 template <typename T>
1011 Mat2<T> operator*(const Mat2<T> &lhs, const Mat2<T> &rhs) {
1012 Mat2<T> result;
1013 for (size_t i = 0; i < 2; ++i) {
1014 for (size_t j = 0; j < 2; ++j) {
1015 result(i, j) = T(0);
1016 for (size_t k = 0; k < 2; ++k) {
1017 result(i, j) += lhs(i, k) * rhs(k, j);
1018 }
1019 }
1020 }
1021 return result;
1022 }
1023
1024 template <typename T>
1025 Mat3<T> operator*(const Mat3<T> &lhs, const Mat3<T> &rhs) {
1026 Mat3<T> result;
1027 for (size_t i = 0; i < 3; ++i) {
1028 for (size_t j = 0; j < 3; ++j) {
1029 result(i, j) = T(0);
1030 for (size_t k = 0; k < 3; ++k) {
1031 result(i, j) += lhs(i, k) * rhs(k, j);
1032 }
1033 }
1034 }
1035 return result;
1036 }
1037
1038 template <typename T>
1039 Mat4<T> operator*(const Mat4<T> &lhs, const Mat4<T> &rhs) {
1040 Mat4<T> result;
1041 for (size_t i = 0; i < 4; ++i) {
1042 for (size_t j = 0; j < 4; ++j) {
1043 result(i, j) = T(0);
1044 for (size_t k = 0; k < 4; ++k) {
1045 result(i, j) += lhs(i, k) * rhs(k, j);
1046 }
1047 }
1048 }
1049 return result;
1050 }
1051
1052 // GLOBAL MATRIX-VECTOR ARITHMETIC OPERATORS:
1053
1054 /*----------------------------- homogeneous version --------------------------*/
1055 template <typename T>
1056 Vec<3, T> operator*(const Mat4<T> &lhs, const Vec<3, T> &rhs) {
1057 Vec<4, T> tmp(rhs, T(1));
1058 Vec<4, T> result = lhs * tmp;
1059 result /= result[3];
1060 return Vec<3, T>((T*)result);
1061 }
1062
1063 /*----------------------------- homogeneous version --------------------------*/
1064 template <typename T>
1065 Vec<2, T> operator*(const Mat3<T> &lhs, const Vec<2, T> &rhs) {
1066 Vec<3, T> tmp(rhs, T(1));
1067 Vec<3, T> result = lhs * tmp;
1068 result /= result[2];
1069 return Vec<2, T>((T*)result);
1070 }
1071
1072
1073 /*--------------------------- non-homogeneous version ------------------------*/
1074 template <typename T>
1075 Vec<2, T> operator*(const Mat2<T> &lhs, const Vec<2, T> &rhs) {
1076 Vec<2, T> result;
1077 for (size_t i = 0; i < 2; ++i) {
1078 result[i] = 0;
1079 for (size_t j = 0; j < 2; ++j) {
1080 result[i] += lhs(i, j) * rhs[j];
1081 }
1082 }
1083 return result;
1084 }
1085
1086 /*--------------------------- non-homogeneous version ------------------------*/
1088 template <typename T>
1089 Vec<3, T> operator*(const Mat3<T> &lhs, const Vec<3, T> &rhs) {
1090 Vec<3, T> result;
1091 for (size_t i = 0; i < 3; ++i) {
1092 result[i] = 0;
1093 for (size_t j = 0; j < 3; ++j) {
1094 result[i] += lhs(i, j) * rhs[j];
1095 }
1096 }
1097 return result;
1098 }
1099
1100 /*--------------------------- non-homogeneous version ------------------------*/
1102 template <typename T>
1103 Vec<4, T> operator*(const Mat4<T> &lhs, const Vec<4, T> &rhs) {
1104 Vec<4, T> result;
1105 for (size_t i = 0; i < 4; ++i) {
1106 result[i] = 0;
1107 for (size_t j = 0; j < 4; ++j) {
1108 result[i] += lhs(i, j) * rhs[j];
1109 }
1110 }
1111 return result;
1112 }
1113
1114
1115
1116 // GLOBAL SERVICES:
1117
1118 /*----------------------------------------------------------------------------*/
1119 template <size_t N, size_t M, typename T>
1121 Mat<M, N, T> result;
1122 for (size_t i = 0; i < N; ++i) {
1123 for (size_t j = 0; j < M; ++j) {
1124 result(j, i) = m(i, j);
1125 }
1126 }
1127 return result;
1128 }
1129
1130 /*----------------------------------------------------------------------------*/
1132 template <size_t D, typename T>
1133 T trace(const Mat<D, D, T> &m) {
1134 T result = m(0, 0);
1135 for (size_t i = 1; i < D; ++i)
1136 result += m(i, i);
1137 return result;
1138 }
1139
1140 /*----------------------------------------------------------------------------*/
1142 template <size_t N, typename T>
1144 /* Use LU decomposition to find the determinant. */
1145 Mat<N, N, T> tmp;
1146 Vec<N, T> rowp;
1147 T result;
1148 lu_decomposition(m, &tmp, &rowp, &result);
1149 for (size_t i = 0; i < N; ++i)
1150 result *= tmp(i, i);
1151 return result;
1152 }
1153
1155 template <typename T>
1156 T determinant(const Mat2<T> &m) {
1157 return m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0);
1158 }
1159
1161 template <typename T>
1162 T determinant(const Mat3<T> &m) {
1163 return
1164 m(0, 0) * (m(1, 1) * m(2, 2) - m(2, 1) * m(1, 2)) +
1165 m(0, 1) * (m(2, 0) * m(1, 2) - m(1, 0) * m(2, 2)) +
1166 m(0, 2) * (m(1, 0) * m(2, 1) - m(2, 0) * m(1, 1));
1167 }
1168
1170 template <typename T>
1171 T determinant(const Mat4<T> &m) {
1172 return
1173 m(0, 3) * m(1, 2) * m(2, 1) * m(3, 0) - m(0, 2) * m(1, 3) * m(2, 1) * m(3, 0) -
1174 m(0, 3) * m(1, 1) * m(2, 2) * m(3, 0) + m(0, 1) * m(1, 3) * m(2, 2) * m(3, 0) +
1175 m(0, 2) * m(1, 1) * m(2, 3) * m(3, 0) - m(0, 1) * m(1, 2) * m(2, 3) * m(3, 0) -
1176 m(0, 3) * m(1, 2) * m(2, 0) * m(3, 1) + m(0, 2) * m(1, 3) * m(2, 0) * m(3, 1) +
1177 m(0, 3) * m(1, 0) * m(2, 2) * m(3, 1) - m(0, 0) * m(1, 3) * m(2, 2) * m(3, 1) -
1178 m(0, 2) * m(1, 0) * m(2, 3) * m(3, 1) + m(0, 0) * m(1, 2) * m(2, 3) * m(3, 1) +
1179 m(0, 3) * m(1, 1) * m(2, 0) * m(3, 2) - m(0, 1) * m(1, 3) * m(2, 0) * m(3, 2) -
1180 m(0, 3) * m(1, 0) * m(2, 1) * m(3, 2) + m(0, 0) * m(1, 3) * m(2, 1) * m(3, 2) +
1181 m(0, 1) * m(1, 0) * m(2, 3) * m(3, 2) - m(0, 0) * m(1, 1) * m(2, 3) * m(3, 2) -
1182 m(0, 2) * m(1, 1) * m(2, 0) * m(3, 3) + m(0, 1) * m(1, 2) * m(2, 0) * m(3, 3) +
1183 m(0, 2) * m(1, 0) * m(2, 1) * m(3, 3) - m(0, 0) * m(1, 2) * m(2, 1) * m(3, 3) -
1184 m(0, 1) * m(1, 0) * m(2, 2) * m(3, 3) + m(0, 0) * m(1, 1) * m(2, 2) * m(3, 3);
1185 }
1186
1187 /*----------------------------------------------------------------------------*/
1189 template <size_t N, typename T>
1191 // Use Gauss-Jordan elimination to find inverse. This uses less memory than the LU decomposition method.
1192 // See lu_back_substitution() for an example of computing inverse using LU decomposition.
1193 size_t indxc[N], indxr[N], ipiv[N];
1194
1195 Mat<N, N, T> result = m;
1196
1197 for (size_t i = 0; i < N; ++i)
1198 ipiv[i] = 0;
1199
1200 for (size_t i = 0; i < N; ++i) { // for each column
1201 T max = T(0);
1202 size_t maxc, maxr;
1203 for (size_t j = 0; j < N; ++j) { // search for pivot
1204 if (ipiv[j] != 1) {
1205 for (size_t k = 0; k < N; ++k) { // for each column
1206 if (ipiv[k] == 0) {
1207 T element = std::abs(result(j, k));
1208 if (element > max) {
1209 max = element;
1210 maxr = j;
1211 maxc = k;
1212 }
1213 }
1214 }
1215 }
1216 }
1217 ++ipiv[maxc];
1218
1219 if (maxr != maxc)
1220 result.swap_rows(maxr, maxc);
1221
1222 indxr[i] = maxr;
1223 indxc[i] = maxc;
1224
1225 // check for singular matrix:
1226 if (std::abs(result(maxc, maxc)) < epsilon<T>()) {
1227 LOG(ERROR) << "input matrix is singular";
1228 return result; // return partial result
1229 }
1230
1231 // multiply row by 1/pivot:
1232 T rpivot = T(1) / result(maxc, maxc);
1233 result(maxc, maxc) = T(1);
1234 result.set_row(maxc, result.row(maxc) * rpivot);
1235
1236 // reduce rows (except pivot):
1237 for (size_t j = 0; j < N; ++j) {
1238 if (j != maxc) {
1239 T dum = result(j, maxc);
1240 result(j, maxc) = T(0);
1241 for (size_t k = 0; k < N; ++k)
1242 result(j, k) -= result(maxc, k) * dum;
1243 }
1244 }
1245 }
1246
1247 // undo column swap:
1248 size_t i = N;
1249 do {
1250 --i;
1251 if (indxr[i] != indxc[i]) // if swap occurred
1252 result.swap_cols(indxr[i], indxc[i]);
1253 } while (i != 0);
1254
1255 return result;
1256 }
1257
1259 template <typename T>
1261 Mat2<T> result;
1262 result(0, 0) = m(1, 1);
1263 result(0, 1) = -m(0, 1);
1264 result(1, 0) = -m(1, 0);
1265 result(1, 1) = m(0, 0);
1266
1267 T det = determinant(m);
1268 det = T(1) / det;
1269 result *= det;
1270
1271 return result;
1272 }
1273
1275 template <typename T>
1277 Mat3<T> result;
1278 result(0, 0) = (m(1, 1) * m(2, 2) - m(2, 1) * m(1, 2));
1279 result(0, 1) = -(m(0, 1) * m(2, 2) - m(0, 2) * m(2, 1));
1280 result(0, 2) = (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1));
1281 result(1, 0) = -(m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0));
1282 result(1, 1) = (m(0, 0) * m(2, 2) - m(0, 2) * m(2, 0));
1283 result(1, 2) = -(m(0, 0) * m(1, 2) - m(1, 0) * m(0, 2));
1284 result(2, 0) = (m(1, 0) * m(2, 1) - m(2, 0) * m(1, 1));
1285 result(2, 1) = -(m(0, 0) * m(2, 1) - m(2, 0) * m(0, 1));
1286 result(2, 2) = (m(0, 0) * m(1, 1) - m(1, 0) * m(0, 1));
1287
1288 T det = determinant(m);
1289 det = T(1) / det;
1290 result *= det;
1291
1292 return result;
1293 }
1294
1296 template <typename T>
1298 Mat4<T> result;
1299 result(0, 0) = m(1, 2) * m(2, 3) * m(3, 1) - m(1, 3) * m(2, 2) * m(3, 1) + m(1, 3) * m(2, 1) * m(3, 2) - m(1, 1) * m(2, 3) * m(3, 2) - m(1, 2) * m(2, 1) * m(3, 3) + m(1, 1) * m(2, 2) * m(3, 3);
1300 result(0, 1) = m(0, 3) * m(2, 2) * m(3, 1) - m(0, 2) * m(2, 3) * m(3, 1) - m(0, 3) * m(2, 1) * m(3, 2) + m(0, 1) * m(2, 3) * m(3, 2) + m(0, 2) * m(2, 1) * m(3, 3) - m(0, 1) * m(2, 2) * m(3, 3);
1301 result(0, 2) = m(0, 2) * m(1, 3) * m(3, 1) - m(0, 3) * m(1, 2) * m(3, 1) + m(0, 3) * m(1, 1) * m(3, 2) - m(0, 1) * m(1, 3) * m(3, 2) - m(0, 2) * m(1, 1) * m(3, 3) + m(0, 1) * m(1, 2) * m(3, 3);
1302 result(0, 3) = m(0, 3) * m(1, 2) * m(2, 1) - m(0, 2) * m(1, 3) * m(2, 1) - m(0, 3) * m(1, 1) * m(2, 2) + m(0, 1) * m(1, 3) * m(2, 2) + m(0, 2) * m(1, 1) * m(2, 3) - m(0, 1) * m(1, 2) * m(2, 3);
1303 result(1, 0) = m(1, 3) * m(2, 2) * m(3, 0) - m(1, 2) * m(2, 3) * m(3, 0) - m(1, 3) * m(2, 0) * m(3, 2) + m(1, 0) * m(2, 3) * m(3, 2) + m(1, 2) * m(2, 0) * m(3, 3) - m(1, 0) * m(2, 2) * m(3, 3);
1304 result(1, 1) = m(0, 2) * m(2, 3) * m(3, 0) - m(0, 3) * m(2, 2) * m(3, 0) + m(0, 3) * m(2, 0) * m(3, 2) - m(0, 0) * m(2, 3) * m(3, 2) - m(0, 2) * m(2, 0) * m(3, 3) + m(0, 0) * m(2, 2) * m(3, 3);
1305 result(1, 2) = m(0, 3) * m(1, 2) * m(3, 0) - m(0, 2) * m(1, 3) * m(3, 0) - m(0, 3) * m(1, 0) * m(3, 2) + m(0, 0) * m(1, 3) * m(3, 2) + m(0, 2) * m(1, 0) * m(3, 3) - m(0, 0) * m(1, 2) * m(3, 3);
1306 result(1, 3) = m(0, 2) * m(1, 3) * m(2, 0) - m(0, 3) * m(1, 2) * m(2, 0) + m(0, 3) * m(1, 0) * m(2, 2) - m(0, 0) * m(1, 3) * m(2, 2) - m(0, 2) * m(1, 0) * m(2, 3) + m(0, 0) * m(1, 2) * m(2, 3);
1307 result(2, 0) = m(1, 1) * m(2, 3) * m(3, 0) - m(1, 3) * m(2, 1) * m(3, 0) + m(1, 3) * m(2, 0) * m(3, 1) - m(1, 0) * m(2, 3) * m(3, 1) - m(1, 1) * m(2, 0) * m(3, 3) + m(1, 0) * m(2, 1) * m(3, 3);
1308 result(2, 1) = m(0, 3) * m(2, 1) * m(3, 0) - m(0, 1) * m(2, 3) * m(3, 0) - m(0, 3) * m(2, 0) * m(3, 1) + m(0, 0) * m(2, 3) * m(3, 1) + m(0, 1) * m(2, 0) * m(3, 3) - m(0, 0) * m(2, 1) * m(3, 3);
1309 result(2, 2) = m(0, 1) * m(1, 3) * m(3, 0) - m(0, 3) * m(1, 1) * m(3, 0) + m(0, 3) * m(1, 0) * m(3, 1) - m(0, 0) * m(1, 3) * m(3, 1) - m(0, 1) * m(1, 0) * m(3, 3) + m(0, 0) * m(1, 1) * m(3, 3);
1310 result(2, 3) = m(0, 3) * m(1, 1) * m(2, 0) - m(0, 1) * m(1, 3) * m(2, 0) - m(0, 3) * m(1, 0) * m(2, 1) + m(0, 0) * m(1, 3) * m(2, 1) + m(0, 1) * m(1, 0) * m(2, 3) - m(0, 0) * m(1, 1) * m(2, 3);
1311 result(3, 0) = m(1, 2) * m(2, 1) * m(3, 0) - m(1, 1) * m(2, 2) * m(3, 0) - m(1, 2) * m(2, 0) * m(3, 1) + m(1, 0) * m(2, 2) * m(3, 1) + m(1, 1) * m(2, 0) * m(3, 2) - m(1, 0) * m(2, 1) * m(3, 2);
1312 result(3, 1) = m(0, 1) * m(2, 2) * m(3, 0) - m(0, 2) * m(2, 1) * m(3, 0) + m(0, 2) * m(2, 0) * m(3, 1) - m(0, 0) * m(2, 2) * m(3, 1) - m(0, 1) * m(2, 0) * m(3, 2) + m(0, 0) * m(2, 1) * m(3, 2);
1313 result(3, 2) = m(0, 2) * m(1, 1) * m(3, 0) - m(0, 1) * m(1, 2) * m(3, 0) - m(0, 2) * m(1, 0) * m(3, 1) + m(0, 0) * m(1, 2) * m(3, 1) + m(0, 1) * m(1, 0) * m(3, 2) - m(0, 0) * m(1, 1) * m(3, 2);
1314 result(3, 3) = m(0, 1) * m(1, 2) * m(2, 0) - m(0, 2) * m(1, 1) * m(2, 0) + m(0, 2) * m(1, 0) * m(2, 1) - m(0, 0) * m(1, 2) * m(2, 1) - m(0, 1) * m(1, 0) * m(2, 2) + m(0, 0) * m(1, 1) * m(2, 2);
1315
1316 T det = determinant(m);
1317 det = T(1) / det;
1318 result *= det;
1319
1320 return result;
1321 }
1322
1323 /*----------------------------------------------------------------------------*/
1324 template <size_t M, size_t N, typename T>
1326 Mat<N, 1, T> mu(u); // column vector u
1327 Mat<1, M, T> mv(v); // row vector v
1328 return mu * mv; // use matrix multiplication
1329 }
1330
1331 /*----------------------------------------------------------------------------*/
1332 /* Adapted from "Numerical Recipes in C" (Press et al.) */
1333 template <size_t N, size_t M, typename T>
1335 const Mat<N, N, T> &a,
1336 const Mat<N, M, T> &b,
1337 Mat<N, N, T> *ainv,
1338 Mat<N, M, T> *x) {
1339
1340 size_t indxc[N], indxr[N], ipiv[N];
1341
1342 Mat<N, N, T> &amat = *ainv;
1343 amat = a; // copy A
1344 Mat<N, M, T> &bmat = *x;
1345 bmat = b; // copy B
1346
1347 for (size_t i = 0; i < N; ++i)
1348 ipiv[i] = 0;
1349
1350 for (size_t i = 0; i < N; ++i) { // for each column
1351 T max = T(0);
1352 size_t maxc, maxr;
1353 for (size_t j = 0; j < N; ++j) { // search for pivot
1354 if (ipiv[j] != 1) {
1355 for (size_t k = 0; k < N; ++k) { // for each column
1356 if (ipiv[k] == 0) {
1357 T element = std::abs(amat(j, k));
1358 if (element > max) {
1359 max = element;
1360 maxr = j;
1361 maxc = k;
1362 }
1363 }
1364 }
1365 }
1366 }
1367 ++ipiv[maxc];
1368
1369 if (maxr != maxc) {
1370 amat.swap_rows(maxr, maxc);
1371 bmat.swap_rows(maxr, maxc);
1372 }
1373
1374 indxr[i] = maxr;
1375 indxc[i] = maxc;
1376
1377 // check for singular matrix:
1378 if (std::abs(amat(maxc, maxc)) < epsilon<T>())
1379 return false;
1380
1381 // multiply row by 1/pivot:
1382 T rpivot = T(1) / amat(maxc, maxc);
1383 amat(maxc, maxc) = T(1);
1384 amat.set_row(maxc, amat.row(maxc) * rpivot);
1385 bmat.set_row(maxc, bmat.row(maxc) * rpivot);
1386
1387 // reduce rows (except pivot):
1388 for (size_t j = 0; j < N; ++j) {
1389 if (j != maxc) {
1390 T dum = amat(j, maxc);
1391 amat(j, maxc) = T(0);
1392 for (size_t k = 0; k < N; ++k)
1393 amat(j, k) -= amat(maxc, k) * dum;
1394 for (size_t k = 0; k < M; ++k)
1395 bmat(j, k) -= bmat(maxc, k) * dum;
1396 }
1397 }
1398 }
1399
1400 // unscramble a by interchanging columns:
1401 size_t i = N;
1402 do {
1403 --i;
1404 if (indxr[i] != indxc[i]) // if swap occurred
1405 amat.swap_cols(indxr[i], indxc[i]);
1406 } while (i != 0);
1407
1408 return true;
1409 }
1410
1411 /*----------------------------------------------------------------------------*/
1412 /* Adapted from "Numerical Recipes in C" (Press et al.) */
1413 template <size_t N, typename T>
1415 const Mat<N, N, T> &a,
1416 Mat<N, N, T> *alu,
1417 Vec<N, T> *rowp,
1418 T *d) {
1419
1420 Vec<N, T> scalev; // stores implicit scaling of each row
1421 *d = T(1); // no rows changed
1422 Mat<N, N, T> &amat = *alu;
1423 amat = a; // copy a
1424
1425 for (size_t i = 0; i < N; ++i) { // for each row
1426 // get implicit scaling:
1427 T max = T(0);
1428 for (size_t j = 0; j < N; ++j) {
1429 T element = std::abs(amat(i, j));
1430 if (element > max)
1431 max = element;
1432 }
1433
1434 // check for singular matrix:
1435 if (std::abs(max) < min<T>())
1436 return false;
1437
1438 scalev[i] = T(1) / max; // save scaling factor
1439 }
1440
1441 for (size_t j = 0; j < N; ++j) { // for each column
1442 for (size_t i = 0; i < j; ++i) {
1443 T sum = amat(i, j);
1444 for (size_t k = 0; k < i; ++k)
1445 sum -= amat(i, k) * amat(k, j);
1446 amat(i, j) = sum;
1447 }
1448
1449 T max = T(0);
1450 size_t imax;
1451 for (size_t i = j; i < N; ++i) {
1452 T sum = amat(i, j);
1453 for (size_t k = 0; k < j; ++k)
1454 sum -= amat(i, k) * amat(k, j);
1455 amat(i, j) = sum;
1456
1457 T dum = scalev[i] * std::abs(sum);
1458 if (dum >= max) {
1459 max = dum;
1460 imax = i;
1461 }
1462 }
1463
1464 if (j != imax) { // if we need to swap rows
1465 amat.swap_rows(imax, j);
1466 scalev[imax] = scalev[j]; // also swap scale factor
1467 *d = -(*d); // change parity of d
1468 }
1469 (*rowp)[j] = static_cast<T>(imax);
1470
1471 // check for singular matrix:
1472 if (std::abs(amat(j, j)) < epsilon<T>())
1473 return false;
1474
1475 // divide by the pivot element:
1476 if (j != N) {
1477 T dum = T(1) / amat(j, j);
1478 for (size_t i = j + 1; i < N; ++i)
1479 amat(i, j) *= dum;
1480 }
1481
1482 }
1483
1484 return true;
1485 }
1486
1487 /*----------------------------------------------------------------------------*/
1488 /* Adapted from "Numerical Recipes in C" (Press et al.) */
1489 template <size_t N, typename T>
1491 const Mat<N, N, T> &alu,
1492 const Vec<N, T> &rowp,
1493 const Vec<N, T> &b,
1494 Vec<N, T> *x
1495 )
1496 {
1497 Vec<N, T> &result = *x;
1498 result = b; // copy b to result
1499
1500 size_t ii = 0;
1501 for (size_t i = 0; i < N; ++i) {
1502 auto ip = static_cast<size_t>(rowp[i]);
1503 assert(ip < N);
1504
1505 T sum = result[ip];
1506 result[ip] = result[i];
1507 if (ii != 0) {
1508 for (size_t j = ii - 1; j < i; ++j)
1509 sum -= alu(i, j) * result[j];
1510 }
1511 else if (std::abs(sum) > epsilon<T>()) {
1512 ii = i + 1;
1513 }
1514 result[i] = sum;
1515 }
1516
1517 size_t i = N;
1518 do {
1519 --i;
1520 T sum = result[i];
1521 for (size_t j = i + 1; j < N; ++j)
1522 sum -= alu(i, j) * result[j];
1523 result[i] = sum / alu(i, i);
1524 } while (i != 0);
1525 }
1526
1527
1528 /*----------------------------------------------------------------------------*/
1529 // Adapted from Template Numerical Toolkit.
1530 template<size_t N, typename FT>
1532 bool spd = true;
1533 for (size_t j = 0; j < N; ++j) {
1534 FT d = 0;
1535 for (size_t k = 0; k < j; ++k) {
1536 FT s = 0;
1537 for (size_t i = 0; i < k; ++i)
1538 s += L(k, i) * L(j, i);
1539
1540 L(j, k) = s = (A(j, k) - s) / L(k, k);
1541 d = d + s * s;
1542 spd = spd && (A(k, j) == A(j, k));
1543 }
1544
1545 d = A(j, j) - d;
1546 spd = spd && (d > 0);
1547
1548 L(j, j) = std::sqrt(d > 0 ? d : 0);
1549 for (size_t k = j + 1; k < N; ++k)
1550 L(j, k) = 0;
1551 }
1552 return spd;
1553 }
1554
1555 /*----------------------------------------------------------------------------*/
1556 // Adapted from Template Numerical Toolkit.
1557 template <size_t N, typename FT>
1558 void cholesky_solve(const Mat<N, N, FT> &L, const Vec<N, FT> &b, Vec<N, FT>& x) {
1559 x = b;
1560 // solve L*y = b
1561 for (size_t k = 0; k < N; ++k) {
1562 for (size_t i = 0; i < k; ++i)
1563 x[k] -= x[i] * L(k, i);
1564 x[k] /= L(k, k);
1565 }
1566
1567 // solve L'*x = y
1568 for (int k = N - 1; k >= 0; --k) { // attention: size_t will not work
1569 for (size_t i = k + 1; i < N; ++i)
1570 x[k] -= x[i] * L(i, k);
1571 x[k] /= L(k, k);
1572 }
1573 }
1574
1575 template<size_t N, size_t M, typename T>
1577 X = B;
1578 // solve L_*Y = B
1579 for (size_t j = 0; j < M; ++j) {
1580 for (size_t k = 0; k < N; ++k) {
1581 for (size_t i = 0; i < k; ++i)
1582 X(k, j) -= X(i, j) * L(k, i);
1583
1584 X(k, j) /= L(k, k);
1585 }
1586 }
1587
1588 // solve L'*X = Y
1589 for (size_t j = 0; j < M; ++j) {
1590 for (int k = N - 1; k >= 0; --k) { // attention: size_t will not work
1591 for (size_t i = k + 1; i < N; ++i)
1592 X(k, j) -= X(i, j) * L(i, k);
1593
1594 X(k, j) /= L(k, k);
1595 }
1596 }
1597 }
1598
1599 /*----------------------------------------------------------------------------*/
1600
1602 template <size_t N, size_t M, typename T> inline
1603 std::ostream& operator<< (std::ostream& output, const Mat<N, M, T>& m) {
1604 output << std::fixed << std::setprecision(8);
1605 const char sep = ' ';
1606 for (int i = 0; i < N; i++) {
1607 for (int j = 0; j < M; j++) {
1608 output << sep << std::setw(7) << m(i, j);
1609 }
1610 output << std::endl;
1611 }
1612 output << std::resetiosflags(std::ios_base::fixed | std::ios_base::floatfield);
1613 return output;
1614 }
1615
1616 /*----------------------------------------------------------------------------*/
1618 template <size_t N, size_t M, typename T>
1619 std::istream& operator>> (std::istream& input, Mat<N, M, T>& m) {
1620 for (int i = 0; i < N; i++) {
1621 for (int j = 0; j < M; j++) {
1622 input >> m(i, j);
1623 }
1624 }
1625 return input;
1626 }
1627
1628
1629 /*----------------------------------------------------------------------------*/
1630
1632 template<size_t N, typename FT>
1634 return Mat<N, 1, FT>(v.data());
1635 }
1636
1637
1639 template<size_t N, typename FT>
1641 return Mat<1, N, FT>(v.data());
1642 }
1643
1644 /*----------------------------------------------------------------------------*/
1645
1647 template <size_t N, size_t M, typename T>
1648 bool has_nan(const Mat<N, M, T>& m) {
1649 for (int i = 0; i < N; i++) {
1650 for (int j = 0; j < M; j++) {
1651 if (std::isnan(m(i, j)) || std::isinf(m(i, j)))
1652 return true;
1653 }
1654 }
1655 return false;
1656 }
1657
1658
1659 /*******************************************************************************
1660
1661 -------------------------------- 2x2 matrix ----------------------------------
1662
1663 *******************************************************************************/
1664
1671 template <typename T>
1672 class Mat2 : public Mat<2, 2, T>
1673 {
1674 public:
1681 Mat2() = default;
1682
1687 explicit Mat2(T s);
1688
1690 Mat2(const Mat<2, 2, T> &rhs);
1691
1696 explicit Mat2(const Mat<3, 3, T> &rhs);
1697
1703 T s00, T s01,
1704 T s10, T s11
1705 );
1706
1708 explicit Mat2(const T *m);
1709
1715 const Vec<2, T> &x,
1716 const Vec<2, T> &y
1717 );
1718
1724 static Mat2<T> rotation(T angle);
1725
1730 static Mat2<T> scale(T s);
1731
1737 static Mat2<T> scale(T x, T y);
1738
1739 }; // class Mat2
1740
1741 /*----------------------------------------------------------------------------*/
1742 template <typename T>
1744 for (size_t i = 0; i < 2; ++i) {
1745 for (size_t j = 0; j < 2; ++j)
1746 if (i == j)
1747 (*this)(i, j) = T(s);
1748 else
1749 (*this)(i, j) = T(0);
1750 }
1751 }
1752
1753 /*----------------------------------------------------------------------------*/
1754 template <typename T>
1756 for (size_t i = 0; i < 4; ++i)
1757 (*this).m_[i] = rhs[i];
1758 }
1759
1760 /*----------------------------------------------------------------------------*/
1761 template <typename T>
1763 (*this)(0, 0) = rhs(0, 0); (*this)(0, 1) = rhs(0, 1);
1764 (*this)(1, 0) = rhs(1, 0); (*this)(1, 1) = rhs(1, 1);
1765 }
1766
1767 /*----------------------------------------------------------------------------*/
1768 template <typename T>
1770 T s00, T s01,
1771 T s10, T s11
1772 ) {
1773 (*this)(0, 0) = s00; (*this)(0, 1) = s01;
1774 (*this)(1, 0) = s10; (*this)(1, 1) = s11;
1775 }
1776
1777 /*----------------------------------------------------------------------------*/
1778 template <typename T>
1779 Mat2<T>::Mat2(const T *m) {
1780 assert(m != nullptr);
1781
1782 #ifdef MATRIX_ROW_MAJOR
1783 (*this)(0, 0) = m[0]; (*this)(0, 1) = m[1];
1784 (*this)(1, 0) = m[2]; (*this)(1, 1) = m[3];
1785 #else
1786 (*this)(0, 0) = m[0]; (*this)(0, 1) = m[2];
1787 (*this)(1, 0) = m[1]; (*this)(1, 1) = m[3];
1788 #endif
1789 }
1790
1791 /*----------------------------------------------------------------------------*/
1792 template <typename T>
1793 Mat2<T>::Mat2(const Vec<2, T> &x, const Vec<2, T> &y) {
1794 #ifdef MATRIX_ROW_MAJOR
1795 (*this).set_row(0, x);
1796 (*this).set_row(1, y);
1797 #else
1798 (*this).set_col(0, x);
1799 (*this).set_col(1, y);
1800 #endif
1801 }
1802
1803 /*----------------------------------------------------------------------------*/
1804 template <typename T>
1806 return Mat2<T>(
1807 std::cos(angle), -std::sin(angle),
1808 std::sin(angle), std::cos(angle)
1809 );
1810 }
1811
1812 /*----------------------------------------------------------------------------*/
1813 template <typename T>
1815 return Mat2<T>(
1816 s, T(0),
1817 T(0), s
1818 );
1819 }
1820
1821 /*----------------------------------------------------------------------------*/
1822 template <typename T>
1824 return Mat2<T>(
1825 x, T(0),
1826 T(0), y
1827 );
1828 }
1829
1830 /*******************************************************************************
1831
1832 -------------------------------- 3x3 matrix ----------------------------------
1833
1834 *******************************************************************************/
1835
1836 template <typename T> class Quat;
1837
1843 template <typename T>
1844 class Mat3 : public Mat<3, 3, T> {
1845 public:
1852 Mat3() = default;
1853
1858 explicit Mat3(T s);
1859
1861 Mat3(const Mat<3, 3, T> &rhs);
1862
1867 explicit Mat3(const Mat<4, 4, T> &rhs);
1868
1874 T s00, T s01, T s02,
1875 T s10, T s11, T s12,
1876 T s20, T s21, T s22
1877 );
1878
1880 explicit Mat3(const T *m);
1881
1887 const Vec<3, T> &x,
1888 const Vec<3, T> &y,
1889 const Vec<3, T> &z
1890 );
1891
1896 explicit Mat3(const Mat<2, 2, T> &rhs);
1897
1903 explicit Mat3(const Quat<T> &q);
1904
1906 Mat2<T> sub() const;
1907
1912 static Mat3<T> scale(T s);
1913
1920 static Mat3<T> scale(T x, T y, T z);
1921
1930 static Mat3<T> rotation(const Vec<3, T> &axis, T angle);
1931
1940 static Mat3<T> rotation(const Vec<3, T> &axis_angle);
1941
1945 static Mat3<T> rotation(const Quat<T> &q);
1946
1954 static Mat3<T> rotation(T x, T y, T z, int order = 312);
1955
1956 }; // class Mat3
1957
1958
1959 /*******************************************************************************
1960
1961 IMPLEMENTATION:
1962
1963 *******************************************************************************/
1964
1965 /*----------------------------------------------------------------------------*/
1966 template <typename T>
1968 for (size_t i = 0; i < 3; ++i) {
1969 for (size_t j = 0; j < 3; ++j)
1970 if (i == j)
1971 (*this)(i, j) = T(s);
1972 else
1973 (*this)(i, j) = T(0);
1974 }
1975 }
1976
1977 /*----------------------------------------------------------------------------*/
1978 template <typename T>
1980 for (size_t i = 0; i < 9; ++i)
1981 (*this).m_[i] = rhs[i];
1982 }
1983
1984 /*----------------------------------------------------------------------------*/
1985 template <typename T>
1987 (*this)(0, 0) = rhs(0, 0); (*this)(0, 1) = rhs(0, 1); (*this)(0, 2) = rhs(0, 2);
1988 (*this)(1, 0) = rhs(1, 0); (*this)(1, 1) = rhs(1, 1); (*this)(1, 2) = rhs(1, 2);
1989 (*this)(2, 0) = rhs(2, 0); (*this)(2, 1) = rhs(2, 1); (*this)(2, 2) = rhs(2, 2);
1990 }
1991
1992 /*----------------------------------------------------------------------------*/
1993 template <typename T>
1995 T s00, T s01, T s02,
1996 T s10, T s11, T s12,
1997 T s20, T s21, T s22
1998 ) {
1999 (*this)(0, 0) = s00; (*this)(0, 1) = s01; (*this)(0, 2) = s02;
2000 (*this)(1, 0) = s10; (*this)(1, 1) = s11; (*this)(1, 2) = s12;
2001 (*this)(2, 0) = s20; (*this)(2, 1) = s21; (*this)(2, 2) = s22;
2002 }
2003
2004 /*----------------------------------------------------------------------------*/
2005 template <typename T>
2006 Mat3<T>::Mat3(const T *m) {
2007 assert(m != nullptr);
2008
2009 #ifdef MATRIX_ROW_MAJOR
2010 (*this)(0, 0) = m[0]; (*this)(0, 1) = m[1]; (*this)(0, 2) = m[2];
2011 (*this)(1, 0) = m[3]; (*this)(1, 1) = m[4]; (*this)(1, 2) = m[5];
2012 (*this)(2, 0) = m[6]; (*this)(2, 1) = m[7]; (*this)(2, 2) = m[8];
2013 #else
2014 (*this)(0, 0) = m[0]; (*this)(0, 1) = m[3]; (*this)(0, 2) = m[6];
2015 (*this)(1, 0) = m[1]; (*this)(1, 1) = m[4]; (*this)(1, 2) = m[7];
2016 (*this)(2, 0) = m[2]; (*this)(2, 1) = m[5]; (*this)(2, 2) = m[8];
2017 #endif
2018 }
2019
2020 /*----------------------------------------------------------------------------*/
2021 template <typename T>
2022 Mat3<T>::Mat3(const Vec<3, T> &x, const Vec<3, T> &y, const Vec<3, T> &z) {
2023 #ifdef MATRIX_ROW_MAJOR
2024 (*this).set_row(0, x);
2025 (*this).set_row(1, y);
2026 (*this).set_row(2, z);
2027 #else
2028 (*this).set_col(0, x);
2029 (*this).set_col(1, y);
2030 (*this).set_col(2, z);
2031 #endif
2032 }
2033
2034 /*----------------------------------------------------------------------------*/
2035 template <typename T>
2037 (*this)(0, 0) = rhs(0, 1); (*this)(0, 0) = rhs(0, 1); (*this)(0, 2) = T(0);
2038 (*this)(1, 0) = rhs(1, 1); (*this)(1, 0) = rhs(1, 1); (*this)(1, 2) = T(0);
2039 (*this)(2, 0) = T(0); (*this)(2, 0) = T(0); (*this)(2, 2) = T(1);
2040 }
2041
2042 /*----------------------------------------------------------------------------*/
2043 template <typename T>
2045 // input must be unit quaternion
2046 assert(std::abs(q.length() - 1) < epsilon<T>());
2047 const T x = q.x;
2048 const T y = q.y;
2049 const T z = q.z;
2050 const T w = q.w;
2051 (*this)(0, 0) = 1.0 - 2.0 * (y*y + z*z); (*this)(0, 1) = 2.0 * (x*y - w*z); (*this)(0, 2) = 2.0 * (x*z + w*y);
2052 (*this)(1, 0) = 2.0 * (x*y + w*z); (*this)(1, 1) = 1.0 - 2.0 * (x*x + z*z); (*this)(1, 2) = 2.0 * (y*z - w*x);
2053 (*this)(2, 0) = 2.0 * (x*z - w*y); (*this)(2, 1) = 2.0 * (y*z + w*x); (*this)(2, 2) = 1.0 - 2.0 * (x*x + y*y);
2054 }
2055
2056 /*----------------------------------------------------------------------------*/
2057 template <typename T>
2059 Mat2<T> mat;
2060 for (size_t i = 0; i < 2; i++) {
2061 for (size_t j = 0; j < 2; j++) {
2062 mat(i, j) = (*this)(i, j);
2063 }
2064 }
2065 return mat;
2066 }
2067
2068 /*----------------------------------------------------------------------------*/
2069 template <typename T>
2071 return Mat3<T>(
2072 s, T(0), T(0),
2073 T(0), s, T(0),
2074 T(0), T(0), s
2075 );
2076 }
2077
2078 /*----------------------------------------------------------------------------*/
2079 template <typename T>
2080 Mat3<T> Mat3<T>::scale(T x, T y, T z) {
2081 return Mat3<T>(
2082 x, T(0), T(0),
2083 T(0), y, T(0),
2084 T(0), T(0), z
2085 );
2086 }
2087
2088 /*----------------------------------------------------------------------------*/
2089 template <typename T>
2090 Mat3<T> Mat3<T>::rotation(const Vec<3, T> &axis, T angle) {
2091 assert(std::abs(axis.length() - 1) < epsilon<T>());
2092
2093 // cross-product matrix of axis:
2094 const Mat3<T> cpm(
2095 T(0), -axis[2], axis[1],
2096 axis[2], T(0), -axis[0],
2097 -axis[1], axis[0], T(0)
2098 );
2099
2100 // axis-axis tensor product:
2101 const Mat3<T> tpm = tensor(axis, axis);
2102
2103 // trig coefficients:
2104 const T c = std::cos(angle);
2105 const T rc = T(1) - c;
2106 const T s = std::sin(angle);
2107
2108 return Mat3<T>::identity() * c + cpm * s + tpm * rc;
2109 }
2110
2111 /*----------------------------------------------------------------------------*/
2112 template <typename T>
2114 const T len = axis_angle.length();
2115 return rotation(axis_angle/len, len);
2116 }
2117
2118 /*----------------------------------------------------------------------------*/
2119 template <typename T>
2121 // input must be unit quaternion
2122 assert(std::abs(q.length() - 1) < epsilon<T>());
2123 const T x = q.x;
2124 const T y = q.y;
2125 const T z = q.z;
2126 const T w = q.w;
2127 Mat3<T> m;
2128 m(0, 0) = 1.0 - 2.0 * (y*y + z*z); m(0, 1) = 2.0 * (x*y - w*z); m(0, 2) = 2.0 * (x*z + w*y);
2129 m(1, 0) = 2.0 * (x*y + w*z); m(1, 1) = 1.0 - 2.0 * (x*x + z*z); m(1, 2) = 2.0 * (y*z - w*x);
2130 m(2, 0) = 2.0 * (x*z - w*y); m(2, 1) = 2.0 * (y*z + w*x); m(2, 2) = 1.0 - 2.0 * (x*x + y*y);
2131 return m;
2132 }
2133
2134 /*----------------------------------------------------------------------------*/
2135 template <typename T>
2136 Mat3<T> Mat3<T>::rotation(T x, T y, T z, int order) {
2137 // The code is not optimized. The final matrix can be directly derived.
2138 // http://www.songho.ca/opengl/gl_anglestoaxes.html
2139 // http://inside.mines.edu/fs_home/gmurray/ArbitraryAxisRotation/
2140 Mat3<T> rx; // Rotation about X-axis (Pitch)
2141 rx(0, 0) = T(1); rx(0, 1) = T(0); rx(0, 2) = T(0);
2142 rx(1, 0) = T(0); rx(1, 1) = std::cos(x); rx(1, 2) = -std::sin(x);
2143 rx(2, 0) = T(0); rx(2, 1) = std::sin(x); rx(2, 2) = std::cos(x);
2144
2145 Mat3<T> ry; // Rotation about Y-axis (Yaw, Heading)
2146 ry(0, 0) = std::cos(y); ry(0, 1) = T(0); ry(0, 2) = std::sin(y);
2147 ry(1, 0) = T(0); ry(1, 1) = T(1); ry(1, 2) = T(0);
2148 ry(2, 0) = -std::sin(y); ry(2, 1) = T(0); ry(2, 2) = std::cos(y);
2149
2150 Mat3<T> rz; // Rotation about Z-axis (Roll)
2151 rz(0, 0) = std::cos(z); rz(0, 1) = -std::sin(z); rz(0, 2) = T(0);
2152 rz(1, 0) = std::sin(z); rz(1, 1) = std::cos(z); rz(1, 2) = T(0);
2153 rz(2, 0) = T(0); rz(2, 1) = T(0); rz(2, 2) = T(1);
2154
2155 switch (order) {
2156 case 123: return rz * ry * rx;
2157 case 132: return ry * rz * rx;
2158 case 213: return rz * rx * ry;
2159 case 231: return rx * rz * ry;
2160 case 312: return ry * rx * rz;
2161 case 321: return rx * ry * rz;
2162 default:
2163 LOG(ERROR) << "invalid rotation order";
2164 return rx * rz * ry;
2165 }
2166 }
2167
2168 /*******************************************************************************
2169
2170 -------------------------------- 4x4 matrix ----------------------------------
2171
2172 *******************************************************************************/
2173
2179 template <typename T>
2180 class Mat4 : public Mat<4, 4, T> {
2181 public:
2188 Mat4() = default;
2189
2194 explicit Mat4(T s);
2195
2197 Mat4(const Mat<4, 4, T> &rhs);
2198
2204 T s00, T s01, T s02, T s03,
2205 T s10, T s11, T s12, T s13,
2206 T s20, T s21, T s22, T s23,
2207 T s30, T s31, T s32, T s33
2208 );
2209
2211 explicit Mat4(const T *m);
2212
2218 const Vec<4, T> &x,
2219 const Vec<4, T> &y,
2220 const Vec<4, T> &z,
2221 const Vec<4, T> &w
2222 );
2223
2228 explicit Mat4(const Mat<3, 3, T> &rhs);
2229
2234 Mat4(const Vec<3, T> &s, const Quat<T> &r, const Vec<3, T> &t);
2235
2237 Mat3<T> sub() const;
2238
2244 static Mat4<T> scale(T s);
2245
2251 static Mat4<T> scale(const Vec<4, T>& s); // set w to 1 for 3D scaling
2260 static Mat4<T> scale(T x, T y, T z, T w); // set w to 1 for 3D scaling
2261
2270 static Mat4<T> rotation(const Vec<3, T> &axis, T angle);
2271
2280 static Mat4<T> rotation(const Vec<3, T> &axis_angle);
2281
2286 static Mat4<T> rotation(const Quat<T> &q);
2287
2296 static Mat4<T> rotation(T x, T y, T z, int order = 312);
2297
2309 static Mat4<T> translation(T x, T y, T z);
2310
2311 }; // class Mat4
2312
2313
2314 /*******************************************************************************
2315
2316 IMPLEMENTATION:
2317
2318 *******************************************************************************/
2319
2320 /*----------------------------------------------------------------------------*/
2321 template <typename T>
2323 for (size_t i = 0; i < 4; ++i) {
2324 for (size_t j = 0; j < 4; ++j)
2325 if (i == j)
2326 (*this)(i, j) = T(s);
2327 else
2328 (*this)(i, j) = T(0);
2329 }
2330 }
2331
2332 /*----------------------------------------------------------------------------*/
2333 template <typename T>
2335 for (size_t i = 0; i < 16; ++i)
2336 (*this).m_[i] = rhs[i];
2337 }
2338
2339 /*----------------------------------------------------------------------------*/
2340 template <typename T>
2342 T s00, T s01, T s02, T s03,
2343 T s10, T s11, T s12, T s13,
2344 T s20, T s21, T s22, T s23,
2345 T s30, T s31, T s32, T s33
2346 ) {
2347 (*this)(0, 0) = s00; (*this)(0, 1) = s01; (*this)(0, 2) = s02; (*this)(0, 3) = s03;
2348 (*this)(1, 0) = s10; (*this)(1, 1) = s11; (*this)(1, 2) = s12; (*this)(1, 3) = s13;
2349 (*this)(2, 0) = s20; (*this)(2, 1) = s21; (*this)(2, 2) = s22; (*this)(2, 3) = s23;
2350 (*this)(3, 0) = s30; (*this)(3, 1) = s31; (*this)(3, 2) = s32; (*this)(3, 3) = s33;
2351 }
2352
2353 /*----------------------------------------------------------------------------*/
2354 template <typename T>
2355 Mat4<T>::Mat4(const T *m) {
2356 assert(m != nullptr);
2357
2358 #ifdef MATRIX_ROW_MAJOR
2359 (*this)(0, 0) = m[0]; (*this)(0, 1) = m[1]; (*this)(0, 2) = m[2]; (*this)(0, 3) = m[3];
2360 (*this)(1, 0) = m[4]; (*this)(1, 1) = m[5]; (*this)(1, 2) = m[6]; (*this)(1, 3) = m[7];
2361 (*this)(2, 0) = m[8]; (*this)(2, 1) = m[9]; (*this)(2, 2) = m[10]; (*this)(2, 3) = m[11];
2362 (*this)(3, 0) = m[12]; (*this)(3, 1) = m[13]; (*this)(3, 2) = m[14]; (*this)(3, 3) = m[15];
2363 #else
2364 (*this)(0, 0) = m[0]; (*this)(0, 1) = m[4]; (*this)(0, 2) = m[8]; (*this)(0, 3) = m[12];
2365 (*this)(1, 0) = m[1]; (*this)(1, 1) = m[5]; (*this)(1, 2) = m[9]; (*this)(1, 3) = m[13];
2366 (*this)(2, 0) = m[2]; (*this)(2, 1) = m[6]; (*this)(2, 2) = m[10]; (*this)(2, 3) = m[14];
2367 (*this)(3, 0) = m[3]; (*this)(3, 1) = m[7]; (*this)(3, 2) = m[11]; (*this)(3, 3) = m[15];
2368 #endif
2369 }
2370
2371 /*----------------------------------------------------------------------------*/
2372 template <typename T>
2374 const Vec<4, T> &x,
2375 const Vec<4, T> &y,
2376 const Vec<4, T> &z,
2377 const Vec<4, T> &w
2378 ) {
2379
2380 #ifdef MATRIX_ROW_MAJOR
2381 (*this).set_row(0, x);
2382 (*this).set_row(1, y);
2383 (*this).set_row(2, z);
2384 (*this).set_row(3, w);
2385 #else
2386 (*this).set_col(0, x);
2387 (*this).set_col(1, y);
2388 (*this).set_col(2, z);
2389 (*this).set_col(3, w);
2390 #endif
2391 }
2392
2393 /*----------------------------------------------------------------------------*/
2394 template <typename T>
2396 (*this)(0, 0) = rhs(0, 0); (*this)(0, 1) = rhs(0, 1); (*this)(0, 2) = rhs(0, 2); (*this)(0, 3) = T(0);
2397 (*this)(1, 0) = rhs(1, 0); (*this)(1, 1) = rhs(1, 1); (*this)(1, 2) = rhs(1, 2); (*this)(1, 3) = T(0);
2398 (*this)(2, 0) = rhs(2, 0); (*this)(2, 1) = rhs(2, 1); (*this)(2, 2) = rhs(2, 2); (*this)(2, 3) = T(0);
2399 (*this)(3, 0) = T(0); (*this)(3, 1) = T(0); (*this)(3, 2) = T(0); (*this)(3, 3) = T(1);
2400 }
2401
2402 /*----------------------------------------------------------------------------*/
2403 template <typename T>
2405 Mat3<T> mat;
2406 for (size_t i = 0; i < 3; i++) {
2407 for (size_t j = 0; j < 3; j++) {
2408 mat(i, j) = (*this)(i, j);
2409 }
2410 }
2411 return mat;
2412 }
2413
2414 /*----------------------------------------------------------------------------*/
2415 template <typename T>
2416 Mat4<T>::Mat4(const Vec<3, T> &s, const Quat<T> &rot, const Vec<3, T> &t) {
2417 assert(std::abs(rot.length() - 1) < epsilon<T>());
2418
2419 // get rotation matrix from quaternion:
2420 Mat3<T> r(rot);
2421
2422 // incorporate scale (cheaper than a matrix multiply):
2423 r(0, 0) = r(0, 0) * s[0]; r(0, 1) = r(0, 1) * s[1]; r(0, 2) = r(0, 2) * s[2];
2424 r(1, 0) = r(1, 0) * s[0]; r(1, 1) = r(1, 1) * s[1]; r(1, 2) = r(1, 2) * s[2];
2425 r(2, 0) = r(2, 0) * s[0]; r(2, 1) = r(2, 1) * s[1]; r(2, 2) = r(2, 2) * s[2];
2426
2427 // combine rotation matrix, scale and translation:
2428 (*this)(0, 0) = r(0, 0); (*this)(0, 1) = r(0, 1); (*this)(0, 2) = r(0, 2); (*this)(0, 3) = t[0];
2429 (*this)(1, 0) = r(1, 0); (*this)(1, 1) = r(1, 1); (*this)(1, 2) = r(1, 2); (*this)(1, 3) = t[1];
2430 (*this)(2, 0) = r(2, 0); (*this)(2, 1) = r(2, 1); (*this)(2, 2) = r(2, 2); (*this)(2, 3) = t[2];
2431 (*this)(3, 0) = T(0); (*this)(3, 1) = T(0); (*this)(3, 2) = T(0); (*this)(3, 3) = T(1);
2432 }
2433
2434 /*----------------------------------------------------------------------------*/
2435 template <typename T>
2437 return Mat4<T>(
2438 s, T(0), T(0), T(0),
2439 T(0), s, T(0), T(0),
2440 T(0), T(0), s, T(0),
2441 T(0), T(0), T(0), T(1)
2442 );
2443 }
2444
2445 /*----------------------------------------------------------------------------*/
2446 template <typename T>
2447 Mat4<T> Mat4<T>::scale(T x, T y, T z, T w) {
2448 return Mat4<T>(
2449 x, T(0), T(0), T(0),
2450 T(0), y, T(0), T(0),
2451 T(0), T(0), z, T(0),
2452 T(0), T(0), T(0), w
2453 );
2454 }
2455
2456 /*----------------------------------------------------------------------------*/
2457 template <typename T>
2459 return Mat4<T>(
2460 s.x, T(0), T(0), T(0),
2461 T(0), s.y, T(0), T(0),
2462 T(0), T(0), s.z, T(0),
2463 T(0), T(0), T(0), s.w
2464 );
2465 }
2466
2467 /*----------------------------------------------------------------------------*/
2468
2469 template <typename T>
2470 Mat4<T> Mat4<T>::rotation(const Vec<3, T> &axis, T angle) {
2471 assert(std::abs(axis.length() - 1) < epsilon<T>());
2472 return Mat4<T>(Mat3<T>::rotation(axis, angle)); // gen 3x3 rotation matrix as arg to Mat4 constructor
2473 }
2474
2475 /*----------------------------------------------------------------------------*/
2476
2477 template <typename T>
2479 const T len = axis_angle.length();
2480 return Mat4<T>(Mat3<T>::rotation(axis_angle/len, len));
2481 }
2482
2483 /*----------------------------------------------------------------------------*/
2484 template <typename T>
2486 // input must be unit quaternion
2487 assert(std::abs(q.length() - 1) < epsilon<T>());
2488 const T x = q.x;
2489 const T y = q.y;
2490 const T z = q.z;
2491 const T w = q.w;
2492 Mat4<T> m;
2493 m(0, 0) = 1.0 - 2.0 * (y*y + z*z); m(0, 1) = 2.0 * (x*y - w*z); m(0, 2) = 2.0 * (x*z + w*y); m(0, 3) = 0.0;
2494 m(1, 0) = 2.0 * (x*y + w*z); m(1, 1) = 1.0 - 2.0 * (x*x + z*z); m(1, 2) = 2.0 * (y*z - w*x); m(1, 3) = 0.0;
2495 m(2, 0) = 2.0 * (x*z - w*y); m(2, 1) = 2.0 * (y*z + w*x); m(2, 2) = 1.0 - 2.0 * (x*x + y*y); m(2, 3) = 0.0;
2496 m(3, 0) = 0.0; m(3, 1) = 0.0; m(3, 2) = 0.0; m(3, 3) = 1.0;
2497 return m;
2498 }
2499
2500 /*----------------------------------------------------------------------------*/
2501 template <typename T>
2502 Mat4<T> Mat4<T>::rotation(T x, T y, T z, int order) {
2503 // The code is not optimized. The final matrix can be directly derived.
2504 // http://www.songho.ca/opengl/gl_anglestoaxes.html
2505 // http://inside.mines.edu/fs_home/gmurray/ArbitraryAxisRotation/
2506 Mat4<T> rx; // Rotation about X-axis (Pitch)
2507 rx(0, 0) = T(1); rx(0, 1) = T(0); rx(0, 2) = T(0); rx(0, 3) = T(0);
2508 rx(1, 0) = T(0); rx(1, 1) = std::cos(x); rx(1, 2) = -std::sin(x); rx(1, 3) = T(0);
2509 rx(2, 0) = T(0); rx(2, 1) = std::sin(x); rx(2, 2) = std::cos(x); rx(2, 3) = T(0);
2510 rx(3, 0) = T(0); rx(3, 1) = T(0); rx(3, 2) = T(0); rx(3, 3) = T(1);
2511
2512 Mat4<T> ry; // Rotation about Y-axis (Yaw, Heading)
2513 ry(0, 0) = std::cos(y); ry(0, 1) = T(0); ry(0, 2) = std::sin(y); ry(0, 3) = T(0);
2514 ry(1, 0) = T(0); ry(1, 1) = T(1); ry(1, 2) = T(0); ry(1, 3) = T(0);
2515 ry(2, 0) = -std::sin(y); ry(2, 1) = T(0); ry(2, 2) = std::cos(y); ry(2, 3) = T(0);
2516 ry(3, 0) = T(0); ry(3, 1) = T(0); ry(3, 2) = T(0); ry(3, 3) = T(1);
2517
2518 Mat4<T> rz; // Rotation about Z-axis (Roll)
2519 rz(0, 0) = std::cos(z); rz(0, 1) = -std::sin(z); rz(0, 2) = T(0); rz(0, 3) = T(0);
2520 rz(1, 0) = std::sin(z); rz(1, 1) = std::cos(z); rz(1, 2) = T(0); rz(1, 3) = T(0);
2521 rz(2, 0) = T(0); rz(2, 1) = T(0); rz(2, 2) = T(1); rz(2, 3) = T(0);
2522 rz(3, 0) = T(0); rz(3, 1) = T(0); rz(3, 2) = T(0); rz(3, 3) = T(1);
2523
2524 switch (order) {
2525 case 123: return rz * ry * rx;
2526 case 132: return ry * rz * rx;
2527 case 213: return rz * rx * ry;
2528 case 231: return rx * rz * ry;
2529 case 312: return ry * rx * rz;
2530 case 321: return rx * ry * rz;
2531 default:
2532 LOG(ERROR) << "invalid rotation order";
2533 return rx * rz * ry;
2534 }
2535 }
2536
2537 /*----------------------------------------------------------------------------*/
2538 template <typename T>
2540 return Mat4<T>(
2541 T(1), T(0), T(0), t[0],
2542 T(0), T(1), T(0), t[1],
2543 T(0), T(0), T(1), t[2],
2544 T(0), T(0), T(0), T(1)
2545 );
2546 }
2547
2548 /*----------------------------------------------------------------------------*/
2549 template <typename T>
2551 return Mat4<T>(
2552 T(1), T(0), T(0), x,
2553 T(0), T(1), T(0), y,
2554 T(0), T(0), T(1), z,
2555 T(0), T(0), T(0), T(1)
2556 );
2557 }
2558
2559}
2560
2561#endif // EASY3D_CORE_MAT_H
2 by 2 matrix. Extends Mat with 2D-specific functionality and constructors.
Definition mat.h:1673
static Mat2< T > scale(T s)
Static constructor return a 2D uniform scale matrix.
Definition mat.h:1814
static Mat2< T > rotation(T angle)
Static constructor return a 2D rotation matrix.
Definition mat.h:1805
Mat2(T s)
Constructor that initializes diagonal elements to a scalar value and others zeros.
Definition mat.h:1743
Mat2(const T *m)
Initialize elements from an array of type T.
Definition mat.h:1779
static Mat2< T > scale(T x, T y)
Static constructor return a 2D non-uniform scale matrix.
Definition mat.h:1823
Mat2()=default
Default constructor.
Mat2(const Mat< 3, 3, T > &rhs)
Copies the top-left corner of rhs. This provides compatibility with generic operations implemented by...
Definition mat.h:1762
Mat2(T s00, T s01, T s10, T s11)
Initialize elements from individual scalars. The digits following s in the parameter names indicate t...
Definition mat.h:1769
Mat2(const Vec< 2, T > &x, const Vec< 2, T > &y)
Initialize elements from two vectors. If MATRIX_ROW_MAJOR is defined, x and y specify rows of the mat...
Definition mat.h:1793
Mat2(const Mat< 2, 2, T > &rhs)
Copy constructor. This provides compatibility with generic operations implemented by Mat.
Definition mat.h:1755
3 by 3 matrix. Extends Mat with 3D-specific functionality and constructors.
Definition mat.h:1844
static Mat3< T > rotation(T x, T y, T z, int order=312)
Static constructor returning a 3D rotation matrix defined by Euler angles. The three rotations are ap...
Definition mat.h:2136
Mat3(T s)
Constructor that initializes diagonal elements to a scalar value and others zeros.
Definition mat.h:1967
Mat3()=default
Default constructor.
static Mat3< T > rotation(const Vec< 3, T > &axis_angle)
Static constructor returning a 3D rotation matrix defined by the axis–angle representation....
Definition mat.h:2113
static Mat3< T > rotation(const Vec< 3, T > &axis, T angle)
Static constructor returning a 3D rotation matrix defined by its axis and angle.
Definition mat.h:2090
Mat3(const Quat< T > &q)
Definition mat.h:2044
Mat2< T > sub() const
the upper-left 2x2 sub-matrix.
Definition mat.h:2058
Mat3(const Mat< 4, 4, T > &rhs)
Copies the top-left corner of rhs. This provides compatibility with generic operations implemented by...
Definition mat.h:1986
Mat3(const Mat< 3, 3, T > &rhs)
Copy constructor. This provides compatibility with generic operations implemented by Mat.
Definition mat.h:1979
Mat3(const T *m)
Definition mat.h:2006
static Mat3< T > scale(T x, T y, T z)
Static constructor returning a 3D non-uniform scale matrix.
Definition mat.h:2080
Mat3(T s00, T s01, T s02, T s10, T s11, T s12, T s20, T s21, T s22)
Initialize elements from individual scalars. The digits following s in the parameter names indicate t...
Definition mat.h:1994
static Mat3< T > rotation(const Quat< T > &q)
Static constructor return a 3D rotation matrix defined by a quaternion.
Definition mat.h:2120
Mat3(const Mat< 2, 2, T > &rhs)
Definition mat.h:2036
Mat3(const Vec< 3, T > &x, const Vec< 3, T > &y, const Vec< 3, T > &z)
Initialize elements from three vectors. If MATRIX_ROW_MAJOR is defined, x, y and z specify rows of th...
Definition mat.h:2022
static Mat3< T > scale(T s)
Static constructor returning a 3D uniform scale matrix.
Definition mat.h:2070
4 by 4 matrix. Extends Mat with 4D-specific functionality and constructors.
Definition mat.h:2180
Mat4(const T *m)
Initialize elements from an array of type T.
Definition mat.h:2355
Mat4()=default
Default constructor.
static Mat4< T > scale(const Vec< 4, T > &s)
Static constructor returning a 4D non-uniform scale matrix,.
Definition mat.h:2458
Mat4(T s)
Constructor that initializes diagonal elements to a scalar value and others zeros.
Definition mat.h:2322
static Mat4< T > rotation(const Quat< T > &q)
Static constructor returning a 3D rotation matrix defined by a quaternion.
Definition mat.h:2485
static Mat4< T > scale(T s)
Static constructor returning a 4D uniform scale matrix.
Definition mat.h:2436
static Mat4< T > rotation(const Vec< 3, T > &axis, T angle)
Static constructor returning a 3D rotation matrix defined by its axis and angle.
Definition mat.h:2470
Mat4(const Mat< 4, 4, T > &rhs)
Copy constructor. This provides compatibility with generic operations implemented by Mat.
Definition mat.h:2334
static Mat4< T > translation(T x, T y, T z)
Static constructor return a 3D translation matrix (as a 4D affine transformation).
Definition mat.h:2550
Mat4(const Mat< 3, 3, T > &rhs)
Initialize from a 3D matrix. rhs forms the upper-left 3x3 sub-matrix, other elements are initialized ...
Definition mat.h:2395
static Mat4< T > scale(T x, T y, T z, T w)
Static constructor returning a 4D non-uniform scale matrix,.
Definition mat.h:2447
static Mat4< T > translation(const Vec< 3, T > &t)
Static constructor return a 3D translation matrix (as a 4D affine transformation).
Definition mat.h:2539
Mat4(const Vec< 4, T > &x, const Vec< 4, T > &y, const Vec< 4, T > &z, const Vec< 4, T > &w)
Initialize elements from four vectors. If MATRIX_ROW_MAJOR is defined, x, y, z and w specify rows of ...
Definition mat.h:2373
static Mat4< T > rotation(const Vec< 3, T > &axis_angle)
Static constructor returning a 3D rotation matrix defined by the axis–angle representation....
Definition mat.h:2478
Mat4(const Vec< 3, T > &s, const Quat< T > &r, const Vec< 3, T > &t)
Initialize from scale/rotation/translation. The order of the transformations is scale,...
Definition mat.h:2416
Mat3< T > sub() const
Return the upper-left 3x3 sub-matrix.
Definition mat.h:2404
static Mat4< T > rotation(T x, T y, T z, int order=312)
Static constructor returning a 3D rotation matrix defined by Euler angles. The three rotations are ap...
Definition mat.h:2502
Mat4(T s00, T s01, T s02, T s03, T s10, T s11, T s12, T s13, T s20, T s21, T s22, T s23, T s30, T s31, T s32, T s33)
Initialize elements from individual scalars. The digits following s in the parameter names indicate t...
Definition mat.h:2341
Base class for matrix types.
Definition mat.h:64
Vec< N, T > col(size_t col) const
Returns the specified column as a vector.
Definition mat.h:723
Mat< N, M, T > & operator*=(T rhs)
Multiplies the matrix by a scalar and assigns the result to the matrix.
Definition mat.h:965
void swap_cols(size_t a, size_t b)
Swaps the specified columns.
Definition mat.h:789
void set_row(size_t row, const Vec< vN, T > &v)
Sets the specified row from a vector.
Definition mat.h:735
Vec< M, T > row(size_t row) const
Returns the specified row as a vector.
Definition mat.h:712
static Mat< N, M, T > identity()
Returns an identity matrix.
Definition mat.h:697
Mat()=default
Default constructor.
Mat(const Mat< rN, rM, T > &rhs)
Copy constructor for matrices with different dimensions (rN >= N, rM >= M).
Definition mat.h:677
Mat(T s)
Constructs a matrix with diagonal elements set to s and other elements set to zero.
Definition mat.h:664
Mat< N, M, T > & operator-=(const Mat< N, M, T > &rhs)
Subtracts another matrix from the matrix and assigns the result to the matrix.
Definition mat.h:954
Mat< N, M, T > & operator*=(const Mat< N, M, T > &rhs)
Multiplies the matrix by another matrix and assigns the result to the matrix.
Definition mat.h:938
Mat(const T *m)
Constructs a matrix from an array of elements.
Definition mat.h:688
void set_col(size_t col, const Vec< vN, T > &v)
Sets the specified column from a vector.
Definition mat.h:746
Mat< N, M, T > & operator-=(T rhs)
Subtracts a scalar from the matrix and assigns the result to the matrix.
Definition mat.h:989
Mat< N, M, T > operator*(T rhs) const
Multiplies the matrix by a scalar.
Definition mat.h:918
T & operator()(size_t row, size_t col)
Returns a reference to the element at the specified row and column.
Definition mat.h:827
void swap_rows(size_t a, size_t b)
Swaps the specified rows.
Definition mat.h:756
void load_zero()
Sets all elements to zero.
Definition mat.h:769
void load_identity(T s=T(1))
Sets the diagonal elements to s and other elements to zero.
Definition mat.h:777
Mat< N, M, T > operator-(const Mat< N, M, T > &rhs) const
Subtracts another matrix from the matrix. Component-wise matrix-matrix subtraction.
Definition mat.h:881
static size_t num_columns()
Returns the number of columns in the matrix.
Definition mat.h:118
bool operator!=(const Mat< N, M, T > &rhs) const
Checks if the matrix is not equal to another matrix.
Definition mat.h:849
Mat< N, M, T > & operator/=(T rhs)
Divides the matrix by a scalar and assigns the result to the matrix.
Definition mat.h:973
Mat< N, M, T > & operator+=(const Mat< N, M, T > &rhs)
Adds another matrix to the matrix and assigns the result to the matrix.
Definition mat.h:946
static size_t num_rows()
Returns the number of rows in the matrix.
Definition mat.h:112
const T & operator()(size_t row, size_t col) const
Returns a constant reference to the element at the specified row and column.
Definition mat.h:814
Vec< N, T > operator*(const Vec< M, T > &rhs) const
Multiplies the matrix by a vector.
Definition mat.h:902
Mat< N, M, T > operator/(T rhs) const
Divides the matrix by a scalar.
Definition mat.h:927
Mat< N, M, T > & operator+=(T rhs)
Adds a scalar to the matrix and assigns the result to the matrix.
Definition mat.h:981
Mat< N, rM, T > operator*(const Mat< M, rM, T > &rhs) const
Multiplies the matrix by another matrix.
Definition mat.h:857
bool operator==(const Mat< N, M, T > &rhs) const
Checks if the matrix is equal to another matrix.
Definition mat.h:840
Mat< N, M, T > operator-() const
Negates the matrix. Component-wise matrix negation.
Definition mat.h:890
Mat< N, M, T > operator+(const Mat< N, M, T > &rhs) const
Adds the matrix to another matrix. Component-wise matrix-matrix addition.
Definition mat.h:872
The Quaternion class represents 3D rotations and orientations.
Definition quat.h:107
FT length() const
Return the length of the quaternion.
Definition quat.h:285
Base class for vector types. It provides generic functionality for N dimensional vectors.
Definition vec.h:30
T length() const
Returns the length of this vector.
Definition vec.h:115
T * data()
Returns the memory address of the vector.
Definition vec.h:82
Definition collider.cpp:182
T trace(const Mat< N, N, T > &m)
Returns the trace (sum of elements on the main diagonal) of an N x N (square) matrix.
Mat< M, N, T > transpose(const Mat< N, M, T > &m)
Transposes a matrix.
Definition mat.h:1120
FT min()
Function returning minimum representable value for a given type.
T determinant(const Mat< N, N, T > &m)
Computes the determinant of a square matrix.
Definition mat.h:1143
FT epsilon()
Function returning the epsilon value for a given type.
bool cholesky_decompose(const Mat< N, N, FT > &A, Mat< N, N, FT > &L)
Perform Cholesky decomposition of a symmetric, positive-definite matrix.
Definition mat.h:1531
bool epsilon_equal(FT const &x, FT const &y, FT const &eps)
Tests if two values are Epsilon equal.
Definition constant.h:134
std::ostream & operator<<(std::ostream &os, Graph::Vertex v)
Output stream support for Graph::Vertex.
Definition graph.h:1300
void lu_back_substitution(const Mat< N, N, T > &alu, const Vec< N, T > &rowp, const Vec< N, T > &b, Vec< N, T > *x)
Solve a set of linear equations using outputs from lu_decomposition() as inputs.
Definition mat.h:1490
FT max()
Function returning maximum representable value for a given type.
T det(const Vec< 2, T > &v1, const Vec< 2, T > &v2)
Compute the determinant of the 2x2 matrix formed by the two 2D vectors as the two rows.
Definition vec.h:481
bool lu_decomposition(const Mat< N, N, T > &a, Mat< N, N, T > *alu, Vec< N, T > *rowp, T *d)
Perform LU decomposition of a square matrix.
Definition mat.h:1414
Mat< N, N, T > inverse(const Mat< N, N, T > &m)
Returns the inverse of an N x N (square) matrix.
Definition mat.h:1190
std::istream & operator>>(std::istream &is, GenericLine< DIM, FT > &line)
Input stream support for GenericLine.
Definition line.h:183
Mat< N, 1, FT > to_matrix(const Vec< N, FT > &v)
Convert a N-dimensional vector into a N by 1 matrix.
Definition mat.h:1633
bool has_nan(const GenericBox< DIM, FT > &box)
Check if the representation of a box has NaN.
Definition box.h:373
std::vector< FT > sum(const Matrix< FT > &)
Definition matrix.h:1485
bool gauss_jordan_elimination(const Mat< N, N, T > &a, const Mat< N, M, T > &b, Mat< N, N, T > *ainv, Mat< N, M, T > *x)
Perform Gauss-Jordan elimination to solve a set of linear equations and additionally compute the inve...
Definition mat.h:1334
void cholesky_solve(const Mat< N, N, FT > &L, const Vec< N, FT > &b, Vec< N, FT > &x)
Solve a set of linear equations using outputs from cholesky_decompose() as inputs.
Definition mat.h:1558
Mat< N, M, T > operator*(T lhs, const Mat< N, M, T > &rhs)
Multiplies a scalar by a matrix.
Definition mat.h:1000
Mat< N, M, T > tensor(const Vec< M, T > &u, const Vec< N, T > &v)
Returns the tensor product (outer product) of vectors u and v, where u is treated as a column vector ...
Definition mat.h:1325