00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef _GOMATRIXXD_H
00034 #define _GOMATRIXXD_H
00035
00036 #include "Array.h"
00037 #include <boost/static_assert.hpp>
00038 #include <algorithm>
00039 #include <iostream>
00040 #include <cmath>
00041
00042
00043 namespace Go
00044 {
00047
00048
00053 template <typename T, int Dim>
00054 class MatrixXD
00055 {
00056 public:
00058 MatrixXD() {}
00059
00061 ~MatrixXD() {}
00062
00064 T& operator()(int row, int col)
00065 {
00066 return m_[row][col];
00067 }
00068
00070 T** get() {return m_;}
00071
00073 const T& operator()(int row, int col) const
00074 {
00075 return m_[row][col];
00076 }
00077
00079 void zero()
00080 {
00081 for (int i = 0; i < Dim; ++i) {
00082 for (int j = 0; j < Dim; ++j) {
00083 m_[i][j] = 0;
00084 }
00085 }
00086 }
00087
00089 void identity()
00090 {
00091 zero();
00092 for (int i = 0; i < Dim; ++i) {
00093 m_[i][i] = 1;
00094 }
00095 }
00096
00098 void transpose()
00099 {
00100 for (int i = 0; i < Dim; ++i) {
00101 for (int j = 0; j < Dim; ++j) {
00102 std::swap(m_[i][j], m_[j][i]);
00103 }
00104 }
00105 }
00106
00111 void setToRotation(T angle, T x, T y, T z);
00112
00117 void setToRotation(const Vector3D& p, const Vector3D& q);
00118
00120 MatrixXD operator * (const MatrixXD& other) const
00121 {
00122 MatrixXD res;
00123 T inner;
00124 for (int i = 0; i < Dim; ++i) {
00125 for (int j = 0; j < Dim; ++j) {
00126 inner = 0;
00127 for (int k = 0; k < Dim; ++k) {
00128 inner += m_[i][k] * other.m_[k][j];
00129 }
00130 res.m_[i][j] = inner;
00131 }
00132 }
00133 return res;
00134 }
00135
00137 MatrixXD& operator *= (const MatrixXD& other)
00138 {
00139 (*this) = (*this) * other;
00140 return *this;
00141 }
00142
00144 MatrixXD operator * (T scalar) const
00145 {
00146 MatrixXD dup(*this);
00147 dup *= scalar;
00148 return dup;
00149 }
00150
00152 MatrixXD& operator *= (T scalar)
00153 {
00154 for (int i = 0; i < Dim; ++i) {
00155 for (int j = 0; j < Dim; ++j) {
00156 m_[i][j] *= scalar;
00157 }
00158 }
00159 return *this;
00160 }
00161
00163 MatrixXD operator + (const MatrixXD& other) const
00164 {
00165 MatrixXD dup(*this);
00166 dup += other;
00167 return dup;
00168 }
00169
00171 MatrixXD& operator += (const MatrixXD& other)
00172 {
00173 for (int i = 0; i < Dim; ++i) {
00174 for (int j = 0; j < Dim; ++j) {
00175 m_[i][j] += other.m_[i][j];
00176 }
00177 }
00178 return *this;
00179 }
00180
00182 MatrixXD operator - () const
00183 {
00184 MatrixXD dup(*this);
00185 for (int i = 0; i < Dim; ++i) {
00186 for (int j = 0; j < Dim; ++j) {
00187 dup.m_[i][j] = -m_[i][j];
00188 }
00189 }
00190 return dup;
00191 }
00192
00194 template <class VectorType>
00195 VectorType operator * (const VectorType& vec) const
00196 {
00197 VectorType res(vec);
00198 T inner;
00199 for (int i = 0; i < Dim; ++i) {
00200 inner = 0;
00201 for (int k = 0; k < Dim; ++k) {
00202 inner += m_[i][k] * vec[k];
00203 }
00204 res[i] = inner;
00205 }
00206 return res;
00207 }
00208
00210 T det() const;
00211
00213 T trace() const
00214 {
00215 T tr(0.0);
00216 for (int i = 0; i < Dim ; ++i) {
00217 for (int j = 0; j < Dim ; ++j) {
00218 tr +=m_[i][j];
00219 }
00220 }
00221 return tr;
00222 }
00223
00225 T frobeniusNorm() const
00226 {
00227 T fn(0.0);
00228 for (int i = 0; i < Dim ; ++i) {
00229 for (int j = 0; j < Dim ; ++j) {
00230 fn +=m_[i][j]*m_[i][j];
00231 }
00232 }
00233 fn = std::sqrt(fn);
00234 return fn;
00235 }
00236
00238 MatrixXD<T, Dim-1> submatrix(int r, int c) const
00239 {
00240 MatrixXD<T, Dim-1> subm;
00241 for (int j = 0; j < Dim; ++j) {
00242 if (j == r) continue;
00243 int joff = 0;
00244 if (j > r) joff = -1;
00245 for (int k = 0; k < Dim; ++k) {
00246 if (k == c) continue;
00247 int koff = 0;
00248 if (k > c) koff = -1;
00249 subm(j + joff, k + koff) = m_[j][k];
00250 }
00251 }
00252 return subm;
00253 }
00254
00255 private:
00256 T m_[Dim][Dim];
00257 };
00258
00259
00260 template <typename T, int Dim>
00261 inline void MatrixXD<T,Dim>::setToRotation(T angle, T x, T y, T z)
00262 {
00263 BOOST_STATIC_ASSERT(Dim == 3 || Dim == 4);
00264 THROW("This code should never be entered!");
00265 }
00266
00267 template <>
00268 inline void MatrixXD<double,3>::setToRotation(double angle, double x, double y, double z)
00269 {
00270 Array<double, 3> u(x, y, z);
00271 u.normalize();
00272 MatrixXD<double,3> S;
00273 S(0,0) = S(1,1) = S(2,2) = 0.0;
00274 S(0,1) = -u[2];
00275 S(1,0) = u[2];
00276 S(0,2) = u[1];
00277 S(2,0) = -u[1];
00278 S(1,2) = -u[0];
00279 S(2,1) = u[0];
00280 MatrixXD<double,3> uut;
00281 uut(0,0) = u[0]*u[0];
00282 uut(0,1) = u[0]*u[1];
00283 uut(0,2) = u[0]*u[2];
00284 uut(1,0) = u[1]*u[0];
00285 uut(1,1) = u[1]*u[1];
00286 uut(1,2) = u[1]*u[2];
00287 uut(2,0) = u[2]*u[0];
00288 uut(2,1) = u[2]*u[1];
00289 uut(2,2) = u[2]*u[2];
00290
00291
00292 double cosang = std::cos(angle);
00293 double sinang = std::sin(angle);
00294 uut *= (double(1.0) - cosang);
00295 S *= sinang;
00296 identity();
00297 (*this) *= cosang;
00298 (*this) += uut;
00299 (*this) += S;
00300 }
00301
00302
00303 template <>
00304 inline void MatrixXD<double,4>::setToRotation(double angle, double x, double y, double z)
00305 {
00306 identity();
00307 MatrixXD<double,3> r;
00308 r.setToRotation(angle, x, y, z);
00309 m_[0][0] = r(0,0);
00310 m_[0][1] = r(0,1);
00311 m_[0][2] = r(0,2);
00312 m_[1][0] = r(1,0);
00313 m_[1][1] = r(1,1);
00314 m_[1][2] = r(1,2);
00315 m_[2][0] = r(2,0);
00316 m_[2][1] = r(2,1);
00317 m_[2][2] = r(2,2);
00318 }
00319
00320 template <typename T, int Dim>
00321 inline void MatrixXD<T,Dim>::setToRotation(const Vector3D& p,
00322 const Vector3D& q)
00323 {
00324 BOOST_STATIC_ASSERT(Dim == 3);
00325 THROW("This code should never be entered!");
00326 }
00327
00328 template <>
00329 inline void MatrixXD<double, 3>::setToRotation(const Vector3D& p,
00330 const Vector3D& q)
00331 {
00332 Vector3D v = p % q;
00333
00334
00335
00336
00337 MatrixXD<double,3> S;
00338 S(0,0) = S(1,1) = S(2,2) = 0.0;
00339 S(0,1) = -v[2];
00340 S(1,0) = v[2];
00341 S(0,2) = v[1];
00342 S(2,0) = -v[1];
00343 S(1,2) = -v[0];
00344 S(2,1) = v[0];
00345 MatrixXD<double,3> vvt;
00346 vvt(0,0) = v[0]*v[0];
00347 vvt(0,1) = v[0]*v[1];
00348 vvt(0,2) = v[0]*v[2];
00349 vvt(1,0) = v[1]*v[0];
00350 vvt(1,1) = v[1]*v[1];
00351 vvt(1,2) = v[1]*v[2];
00352 vvt(2,0) = v[2]*v[0];
00353 vvt(2,1) = v[2]*v[1];
00354 vvt(2,2) = v[2]*v[2];
00355
00356
00357 double cosang = p*q;
00358 vvt *= 1.0/(1.0 + cosang);
00359 identity();
00360 (*this) *= cosang;
00361 (*this) += vvt;
00362 (*this) += S;
00363 }
00364
00366 template <typename T, int Dim>
00367 class DetComp
00368 {
00369 public:
00370 T det(const T m[Dim][Dim])
00371 {
00372
00373
00374 T result(0);
00375 for (int i = 0; i < Dim; ++i) {
00376
00377 MatrixXD<T, Dim-1> subm;
00378 for (int j = 1; j < Dim; ++j) {
00379 for (int k = 0; k < Dim; ++k) {
00380 if (k == i) continue;
00381 int koff = 0;
00382 if (k > i) koff = -1;
00383 subm(j - 1, k + koff) = m[j][k];
00384 }
00385 }
00386
00387 if (i/2 == (i+1)/2) {
00388 result += subm.det()*m[0][i];
00389 } else {
00390 result -= subm.det()*m[0][i];
00391 }
00392 }
00393 return result;
00394 }
00395 };
00397
00400
00402 template<typename T>
00403 class DetComp<T,1>
00404 {
00405 public:
00406 T det(const T m[1][1])
00407 {
00408 return m[0][0];
00409 }
00410 };
00411
00413 template <typename T, int Dim>
00414 inline T MatrixXD<T,Dim>::det() const
00415 {
00416 DetComp<T,Dim> dc;
00417 return dc.det(m_);
00418 }
00419
00421 template <typename T, int Dim>
00422 inline std::istream& operator>> (std::istream& is, MatrixXD<T, Dim>& m)
00423 {
00424 for (int i = 0; i < Dim; ++i) {
00425 for (int j = 0; j < Dim; ++j) {
00426 is >> m(i,j);
00427 }
00428 }
00429 return is;
00430 }
00432
00434 template <typename T, int Dim>
00435 inline std::ostream& operator<< (std::ostream& os, const MatrixXD<T, Dim>& m)
00436 {
00437 for (int i = 0; i < Dim; ++i) {
00438 for (int j = 0; j < Dim; ++j) {
00439 os << m(i,j) << ' ';
00440 }
00441 os << '\n';
00442 }
00443 return os;
00444 }
00445
00446
00448 }
00449
00450
00451 #endif // _GOMATRIXXD_H
00452
00453