00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef VRS_MAT_H
00019 #define VRS_MAT_H
00020
00021 #include <vrs/vec.h>
00022
00023 namespace VRS {
00024
00027 template<unsigned int DIM, typename T>
00028 class Mat {
00029 public:
00031 typedef T value_type;
00032
00033 public:
00035 explicit Mat(T diag = T(1)) { for(size_t i = 0; i < DIM; ++i) { m_columns[i][i] = diag; } }
00037 explicit Mat(Vec<DIM, T> const& diag) { for(size_t i = 0; i < DIM; ++i) { m_columns[i][i] = diag[i]; } }
00038
00039 public:
00041 Mat(Vec<4, T> const& column0, Vec<4, T> const& column1, Vec<4, T> const& column2, Vec<4, T> const& column3) {
00042 m_columns[0] = column0; m_columns[1] = column1; m_columns[2] = column2; m_columns[3] = column3;
00043 VRS_STATIC_ASSERT(DIM == 4);
00044 }
00045
00047 Mat(
00048 T c0r0, T c0r1, T c0r2, T c0r3,
00049 T c1r0, T c1r1, T c1r2, T c1r3,
00050 T c2r0, T c2r1, T c2r2, T c2r3,
00051 T c3r0, T c3r1, T c3r2, T c3r3
00052 ) {
00053 m_columns[0] = Vec<4, T>(c0r0, c0r1, c0r2, c0r3);
00054 m_columns[1] = Vec<4, T>(c1r0, c1r1, c1r2, c1r3);
00055 m_columns[2] = Vec<4, T>(c2r0, c2r1, c2r2, c2r3);
00056 m_columns[3] = Vec<4, T>(c3r0, c3r1, c3r2, c3r3);
00057 VRS_STATIC_ASSERT(DIM == 4);
00058 }
00059
00060 public:
00062 Mat(Vec<3, T> const& column0, Vec<3, T> const& column1, Vec<3, T> const& column2) {
00063 m_columns[0] = column0; m_columns[1] = column1; m_columns[2] = column2;
00064 VRS_STATIC_ASSERT(DIM == 3);
00065 }
00066
00068 Mat(
00069 T c0r0, T c0r1, T c0r2,
00070 T c1r0, T c1r1, T c1r2,
00071 T c2r0, T c2r1, T c2r2
00072 ) {
00073 m_columns[0] = Vec<3, T>(c0r0, c0r1, c0r2);
00074 m_columns[1] = Vec<3, T>(c1r0, c1r1, c1r2);
00075 m_columns[2] = Vec<3, T>(c2r0, c2r1, c2r2);
00076 VRS_STATIC_ASSERT(DIM == 3);
00077 }
00078
00079 public:
00081 Mat(Vec<2, T> const& column0, Vec<2, T> const& column1) {
00082 m_columns[0] = column0; m_columns[1] = column1;
00083 VRS_STATIC_ASSERT(DIM == 2);
00084 }
00085
00087 Mat(
00088 T c0r0, T c0r1,
00089 T c1r0, T c1r1
00090 ) {
00091 m_columns[0] = Vec<2, T>(c0r0, c0r1);
00092 m_columns[1] = Vec<2, T>(c1r0, c1r1);
00093 VRS_STATIC_ASSERT(DIM == 2);
00094 }
00095
00096 public:
00099 template<unsigned int DIM2, typename S>
00100 explicit Mat(Mat<DIM2, S> const& other) {
00101 for(size_t i = 0; i < DIM; ++i) {
00102 for(size_t j = 0; j < DIM; ++j) {
00103 if((i < DIM2) && (j < DIM2)) {
00104 m_columns[i][j] = other[i][j];
00105 } else {
00106 m_columns[i][j] = (i == j) ? T(1) : T(0);
00107 }
00108 }
00109 }
00110 }
00111
00112 public:
00114 Vec<DIM, T> const& operator[](size_t column) const { assert(column < DIM); return m_columns[column]; }
00116 Vec<DIM, T> & operator[](size_t column) { assert(column < DIM); return m_columns[column]; }
00117
00119 T element(size_t column, size_t row) const { assert(column < DIM); assert(row < DIM); return m_columns[column][row]; }
00121 T& element(size_t column, size_t row) { assert(column < DIM); assert(row < DIM); return m_columns[column][row]; }
00122
00124 Vec<DIM, T> const& column(size_t column) const { assert(column < DIM); return m_columns[column]; }
00126 Vec<DIM, T> row(size_t row) const { assert(row < DIM); Vec<DIM, T> result; for(size_t i = 0; i < DIM; ++i) { result[i] = m_columns[i][row]; } return result; }
00127
00129 Mat<DIM - 1, T> minor(size_t column, size_t row) const { assert(column < DIM); assert(row < DIM); Mat<DIM - 1, T> result; for(size_t i = 0; i < DIM - 1; ++i) { for(size_t j = 0; j < DIM - 1; ++j) { result[i][j] = m_columns[(i < column) ? i : i+1][(j < row) ? j : j+1]; } } return result; }
00130
00131 public:
00133 bool operator==(Mat<DIM, T> const& other) const { for(size_t i = 0; i < DIM; ++i) { if(m_columns[i] != other[i]) { return false; } } return true; }
00135 bool operator<(Mat<DIM, T> const& other) const { for(size_t i = 0; i < DIM; ++i) { if(m_columns[i] < other[i]) { return true; } if(m_columns[i] > other[i]) { return false; } } return false; }
00136
00137 public:
00139 Mat<DIM, T>& operator+=(Mat<DIM, T> const& other) { for(size_t i = 0; i < DIM; ++i) { m_columns[i] += other[i]; } return *this; }
00141 Mat<DIM, T>& operator-=(Mat<DIM, T> const& other) { for(size_t i = 0; i < DIM; ++i) { m_columns[i] -= other[i]; } return *this; }
00143 Mat<DIM, T>& operator*=(Mat<DIM, T> const& mat) { return operator=(*this * mat); }
00144
00145 private:
00146 Vec<DIM, T> m_columns[DIM];
00147 };
00148
00150 template<unsigned int DIM, typename T>
00151 inline std::ostream& operator<<(std::ostream& out, const Mat<DIM, T>& mat) {
00152 for(size_t i = 0; i < DIM; ++i) {
00153 out << ((i > 0) ? ", " : "") << mat[i];
00154 }
00155 return out;
00156 }
00157
00159 template<unsigned int DIM, typename T>
00160 bool operator!=(Mat<DIM, T> const& m0, Mat<DIM, T> const& m1) { return !(m0 == m1); }
00161
00163 template<unsigned int DIM, typename T>
00164 bool operator>(Mat<DIM, T> const& m0, Mat<DIM, T> const& m1) { return (m1 < m0); }
00166 template<unsigned int DIM, typename T>
00167 bool operator<=(Mat<DIM, T> const& m0, Mat<DIM, T> const& m1) { return !(m0 > m1); }
00169 template<unsigned int DIM, typename T>
00170 bool operator>=(Mat<DIM, T> const& m0, Mat<DIM, T> const& m1) { return !(m0 < m1); }
00171
00173 template<unsigned int DIM, typename T>
00174 inline Mat<DIM, T> operator+(Mat<DIM, T> const& m0, Mat<DIM, T> const& m1) { Mat<DIM, T> result = m0; return (result += m1); }
00176 template<unsigned int DIM, typename T>
00177 inline Mat<DIM, T> operator-(Mat<DIM, T> const& m0, Mat<DIM, T> const& m1) { Mat<DIM, T> result = m0; return (result -= m1); }
00179 template<unsigned int DIM, typename T>
00180 inline Mat<DIM, T> operator*(Mat<DIM, T> const& m0, Mat<DIM, T> const& m1) {
00181 Mat<DIM, T> result;
00182 for(size_t j = 0; j < DIM; ++j) {
00183 const Vec<DIM, T> m0rowJ(m0.row(j));
00184 for(size_t i = 0; i < DIM; ++i) {
00185 result[i][j] = dot(m0rowJ, m1.column(i));
00186 }
00187 }
00188 return result;
00189 }
00190
00192 template<unsigned int DIM, typename T>
00193 inline Mat<DIM, T> operator+(Mat<DIM, T> const& m0, T s1) { Mat<DIM, T> result; for(size_t i = 0; i < DIM; ++i) { for(size_t j = 0; j < DIM; ++j) { result[i][j] = m0[i][j] + s1; } } return result; }
00195 template<unsigned int DIM, typename T>
00196 inline Mat<DIM, T> operator-(Mat<DIM, T> const& m0, T s1) { Mat<DIM, T> result; for(size_t i = 0; i < DIM; ++i) { for(size_t j = 0; j < DIM; ++j) { result[i][j] = m0[i][j] - s1; } } return result; }
00198 template<unsigned int DIM, typename T>
00199 inline Mat<DIM, T> operator*(Mat<DIM, T> const& m0, T s1) { Mat<DIM, T> result; for(size_t i = 0; i < DIM; ++i) { for(size_t j = 0; j < DIM; ++j) { result[i][j] = m0[i][j] * s1; } } return result; }
00200
00202 template<unsigned int DIM, typename T>
00203 inline Mat<DIM, T> operator+(T s0, Mat<DIM, T> const& m1) { Mat<DIM, T> result; for(size_t i = 0; i < DIM; ++i) { for(size_t j = 0; j < DIM; ++j) { result[i][j] = s0 + m1[i][j]; } } return result; }
00205 template<unsigned int DIM, typename T>
00206 inline Mat<DIM, T> operator-(T s0, Mat<DIM, T> const& m1) { Mat<DIM, T> result; for(size_t i = 0; i < DIM; ++i) { for(size_t j = 0; j < DIM; ++j) { result[i][j] = s0 - m1[i][j]; } } return result; }
00208 template<unsigned int DIM, typename T>
00209 inline Mat<DIM, T> operator*(T s0, Mat<DIM, T> const& m1) { Mat<DIM, T> result; for(size_t i = 0; i < DIM; ++i) { for(size_t j = 0; j < DIM; ++j) { result[i][j] = s0 * m1[i][j]; } } return result; }
00210
00212 template<unsigned int DIM, typename T>
00213 inline Mat<DIM, T> operator*(Mat<DIM, T> const& mat) { Mat<DIM, T> result; for(size_t i = 0; i < DIM; ++i) { for(size_t j = 0; j < DIM; ++j) { result[i][j] = -mat[i][j]; } } return result; }
00214
00216 template<unsigned int DIM, typename T>
00217 inline Mat<DIM, T>& operator++(Mat<DIM, T>& v) { return (v += T(1)); }
00219 template<unsigned int DIM, typename T>
00220 inline Mat<DIM, T> operator++(Mat<DIM, T>& v, int) { const Mat<DIM, T> result = v; v += T(1); return result; }
00222 template<unsigned int DIM, typename T>
00223 inline Mat<DIM, T>& operator--(Mat<DIM, T>& v) { return (v -= T(1)); }
00225 template<unsigned int DIM, typename T>
00226 inline Mat<DIM, T> operator--(Mat<DIM, T>& v, int) { const Mat<DIM, T> result = v; v -= T(1); return result; }
00227
00229 template<unsigned int DIM, typename T>
00230 inline Mat<DIM, T> transpose(Mat<DIM, T> const& x) { Mat<DIM, T> result; for(size_t i = 0; i < DIM; ++i) { for(size_t j = 0; j < DIM; ++j) { result[i][j] = x[j][i]; } } return result; }
00231
00234 template<typename T>
00235 inline T det(Mat<1, T> const& x) { return x[0][0]; }
00236
00239 template<typename T>
00240 inline T det(Mat<2, T> const& x) { return (x[0][0]*x[1][1] - x[1][0]*x[0][1]); }
00241
00244 template<typename T>
00245 inline T det(Mat<3, T> const& x) { return (x[0][0]*x[1][1]*x[2][2] - x[0][0]*x[2][1]*x[1][2] - x[1][0]*x[0][1]*x[2][2] - x[1][0]*x[2][1]*x[0][2] - x[2][0]*x[0][1]*x[1][2] - x[2][0]*x[1][1]*x[0][2]); }
00246
00249 template<unsigned int DIM, typename T>
00250 inline T det(Mat<DIM, T> const& x) {
00251 T result = T(0);
00252 for(size_t i = 0; i < DIM; ++i) {
00253 const T d = x[i][0] * det(x.minor(i, 0));
00254 result += ((i % 2) == 0) ? d : -d;
00255 }
00256 return result;
00257 VRS_STATIC_ASSERT(DIM >= 4);
00258 }
00259
00262 template<typename T>
00263 inline Mat<1, T> inverse(Mat<1, T> const& x) {
00264 if(x[0][0] == T(0)) { return Mat<1, T>(T(0)); }
00265 return Mat<1, T>(T(1) / x[0][0]);
00266 }
00267
00270 template<typename T>
00271 inline Mat<2, T> inverse(Mat<2, T> const& x) {
00272 const T d = det(x);
00273 if(d == T(0)) { return Mat<2, T>(T(0)); }
00274 const T invD = T(1) / d;
00275 return Mat<2, T>(invD * x[1][1], -invD * x[0][1], -invD * x[1][0], invD * x[0][0]);
00276 }
00277
00280 template<unsigned int DIM, typename T>
00281 inline Mat<DIM, T> inverse(Mat<DIM, T> const& x) {
00282 Mat<DIM, T> inv;
00283 Mat<DIM, T> xx(x);
00284
00285
00286 for(size_t i = 0; i < DIM; ++i) {
00287
00288 T temp = T(0);
00289 size_t pivot = DIM;
00290 for(size_t j = i; j < DIM; ++j) {
00291 const T temp2 = fabs(xx[j][i]);
00292 if(temp2 > temp) {
00293 temp = temp2;
00294 pivot = j;
00295 }
00296 }
00297 if(pivot == DIM) {
00298
00299 return Mat<DIM, T>(T(0));
00300 }
00301
00302 if(pivot != i) {
00303
00304 std::swap(inv[i], inv[pivot]);
00305 std::swap(xx[i], xx[pivot]);
00306 }
00307
00308
00309 const T div = T(1) / xx[i][i];
00310 inv[i] *= div;
00311 xx[i] *= div;
00312
00313
00314 for(size_t j = 0; j < DIM; ++j) {
00315 if(i == j) { continue; }
00316 const Vec<DIM, T> temp2 = xx[j][i] * xx[i];
00317 inv[j] -= temp2;
00318 xx[j] -= temp2;
00319 }
00320 }
00321
00322 return inv;
00323 VRS_STATIC_ASSERT(DIM >= 3);
00324 }
00325
00327 template<unsigned int DIM, typename T>
00328 inline Mat<DIM + 1, T> scaling(Vec<DIM, T> const& x) {
00329 return Mat<DIM + 1, T>(Vec<DIM + 1, T>(x, T(1)));
00330 }
00331
00333 template<unsigned int DIM, typename T>
00334 inline Mat<DIM + 1, T> translation(Vec<DIM, T> const& x) {
00335 Mat<DIM + 1, T> result;
00336 result[DIM] = Vec<DIM + 1, T>(x, T(1));
00337 return result;
00338 }
00339
00340 }
00341
00342 #include <vrs/vec_mat_ops.h>
00343
00344 #endif // VRS_MAT_H