00001 #ifndef OPENTISSUE_CORE_MATH_MATH_MATRIX3X3_H
00002 #define OPENTISSUE_CORE_MATH_MATH_MATRIX3X3_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/math_vector3.h>
00013 #include <OpenTissue/core/math/math_value_traits.h>
00014 #include <OpenTissue/core/math/math_eigen_system_decomposition.h>
00015
00016 #include <cmath>
00017 #include <cassert>
00018 #include <iosfwd>
00019
00020
00021 namespace OpenTissue
00022 {
00023
00024 namespace math
00025 {
00026
00027 template <typename > class Quaternion;
00028
00029 template<
00030 typename value_type_
00031
00032 >
00033 class Matrix3x3
00034 {
00035 protected:
00036
00037 typedef typename math::ValueTraits<value_type_> value_traits_ ;
00038
00039 public:
00040
00041 typedef value_traits_ value_traits;
00042 typedef value_type_ value_type;
00043 typedef Vector3<value_type> vector3_type;
00044 typedef Quaternion<value_type> quaternion_type;
00045 typedef size_t index_type;
00046
00047 protected:
00048
00049
00050 vector3_type m_row0;
00051 vector3_type m_row1;
00052 vector3_type m_row2;
00053
00054 public:
00055
00056 Matrix3x3()
00057 : m_row0(value_traits::zero() ,value_traits::zero() ,value_traits::zero() )
00058 , m_row1(value_traits::zero() ,value_traits::zero() ,value_traits::zero() )
00059 , m_row2(value_traits::zero() ,value_traits::zero() ,value_traits::zero() )
00060 {}
00061
00062 ~Matrix3x3(){}
00063
00064 explicit Matrix3x3(
00065 value_type const & m00 , value_type const & m01 , value_type const & m02
00066 , value_type const & m10 , value_type const & m11 , value_type const & m12
00067 , value_type const & m20 , value_type const & m21 , value_type const & m22
00068 )
00069 : m_row0(m00,m01,m02)
00070 , m_row1(m10,m11,m12)
00071 , m_row2(m20,m21,m22)
00072 {}
00073
00074
00075 explicit Matrix3x3(vector3_type const & row0, vector3_type const & row1, vector3_type const & row2)
00076 : m_row0(row0)
00077 , m_row1(row1)
00078 , m_row2(row2)
00079 {}
00080
00081 explicit Matrix3x3(quaternion_type const & q) { *this = q; }
00082
00083 Matrix3x3(Matrix3x3 const & M)
00084 : m_row0(M.m_row0)
00085 , m_row1(M.m_row1)
00086 , m_row2(M.m_row2)
00087 {}
00088
00089 public:
00090
00091 value_type & operator()(index_type i, index_type j)
00092 {
00093 assert( ( i>=0 && i<3 ) || !"Matrix3x3::(i,j) i must be in range [0..2]");
00094 assert( ( j>=0 && j<3 ) || !"Matrix3x3::(i,j) j must be in range [0..2]");
00095 return (*(&m_row0+i))(j);
00096 }
00097
00098 value_type const & operator()(index_type i, index_type j) const
00099 {
00100 assert( ( i>=0 && i<3 ) || !"Matrix3x3::(i,j) i must be in range [0..2]");
00101 assert( ( j>=0 && j<3 ) || !"Matrix3x3::(i,j) j must be in range [0..2]");
00102 return (*(&m_row0+i))(j);
00103 }
00104
00105 vector3_type & operator[](index_type i)
00106 {
00107 assert( ( i>=0 && i<3 ) || !"Matrix3x3::(i,j) i must be in range [0..2]");
00108 return *(&m_row0+i);
00109 }
00110
00111 vector3_type const & operator[](index_type i) const
00112 {
00113 assert( ( i>=0 && i<3 ) || !"Matrix3x3::(i,j) i must be in range [0..2]");
00114 return *(&m_row0+i);
00115 }
00116
00117 Matrix3x3 & operator=( Matrix3x3 const & cpy )
00118 {
00119 m_row0=cpy.m_row0;
00120 m_row1=cpy.m_row1;
00121 m_row2=cpy.m_row2;
00122 return *this;
00123 }
00124
00125
00126 bool operator==(Matrix3x3 const & cmp ) const
00127 {
00128 return (m_row0==cmp.m_row0) && (m_row1==cmp.m_row1) && (m_row2==cmp.m_row2);
00129 }
00130
00131 bool operator!=( Matrix3x3 const & cmp ) const
00132 {
00133 return !(*this==cmp);
00134 }
00135
00136 Matrix3x3 operator+ ( Matrix3x3 const & m ) const { return Matrix3x3( m_row0+m.m_row0, m_row1+m.m_row1, m_row2+m.m_row2); }
00137 Matrix3x3 operator- ( Matrix3x3 const & m ) const { return Matrix3x3( m_row0-m.m_row0, m_row1-m.m_row1, m_row2-m.m_row2); }
00138 Matrix3x3 & operator+= ( Matrix3x3 const & m ) { m_row0+=m.m_row0; m_row1+=m.m_row1; m_row2+=m.m_row2; return *this; }
00139 Matrix3x3 & operator-= ( Matrix3x3 const & m ) { m_row0-=m.m_row0; m_row1-=m.m_row1; m_row2-=m.m_row2; return *this; }
00140 Matrix3x3 & operator*= ( value_type const & s ) {m_row0*=s;m_row1*=s;m_row2*=s;return *this;}
00141
00142 Matrix3x3 & operator/= ( value_type const & s )
00143 {
00144 assert(s || !"Matrix3x3/=(): division by zero");
00145 m_row0/=s;
00146 m_row1/=s;
00147 m_row2/=s;
00148 return *this;
00149 }
00150
00151 vector3_type operator*(vector3_type const &v) const { return vector3_type(m_row0*v, m_row1*v, m_row2*v); }
00152 Matrix3x3 operator-() const { return Matrix3x3(-m_row0,-m_row1,-m_row2); }
00153
00154 size_t size1() const { return 3u; }
00155 size_t size2() const { return 3u; }
00156
00163 Matrix3x3 & operator=(quaternion_type const & q)
00164 {
00165 m_row0(0) = value_traits::one() - value_traits::two() * ( (q.v()(1)*q.v()(1)) + (q.v()(2)*q.v()(2)));
00166 m_row1(1) = value_traits::one() - value_traits::two() * ( (q.v()(0)*q.v()(0)) + (q.v()(2)*q.v()(2)));
00167 m_row2(2) = value_traits::one() - value_traits::two() * ( (q.v()(1)*q.v()(1)) + (q.v()(0)*q.v()(0)));
00168 m_row1(0) = value_traits::two() * ( (q.v()(0)*q.v()(1)) + (q.s()*q.v()(2)));
00169 m_row0(1) = value_traits::two() * ( (q.v()(0)*q.v()(1)) - (q.s()*q.v()(2)));
00170 m_row2(0) = value_traits::two() * (-(q.s()*q.v()(1)) + (q.v()(0)*q.v()(2)));
00171 m_row0(2) = value_traits::two() * ( (q.s()*q.v()(1)) + (q.v()(0)*q.v()(2)));
00172 m_row2(1) = value_traits::two() * ( (q.v()(2)*q.v()(1)) + (q.s()*q.v()(0)));
00173 m_row1(2) = value_traits::two() * ( (q.v()(2)*q.v()(1)) - (q.s()*q.v()(0)));
00174 return *this;
00175 }
00176
00177 void clear()
00178 {
00179 m_row0.clear();
00180 m_row1.clear();
00181 m_row2.clear();
00182 }
00183
00184 public:
00185
00186 friend Matrix3x3 fabs(Matrix3x3 const & A)
00187 {
00188 using std::fabs;
00189
00190 return Matrix3x3(
00191 fabs(A(0,0)), fabs(A(0,1)), fabs(A(0,2)),
00192 fabs(A(1,0)), fabs(A(1,1)), fabs(A(1,2)),
00193 fabs(A(2,0)), fabs(A(2,1)), fabs(A(2,2))
00194 );
00195 }
00196
00197 public:
00198
00199 vector3_type column(index_type i) const
00200 {
00201 assert((i>=0 && i<3) || !"Matrix3x3::column(): index must be in range [0..2]");
00202
00203 return vector3_type(m_row0(i), m_row1(i), m_row2(i));
00204 }
00205
00206 void set_column(index_type i, vector3_type const & column)
00207 {
00208 assert((i>=0 && i<3) || !"Matrix3x3::set_column(): index must be in range [0..2]");
00209
00210 m_row0(i) = column(0);
00211 m_row1(i) = column(1);
00212 m_row2(i) = column(2);
00213 }
00214
00215 vector3_type & row(index_type i) { return (*this)[i]; }
00216 vector3_type const & row(index_type i) const { return (*this)[i]; }
00217
00218 };
00219
00220
00221 template<typename T>
00222 inline void random(Matrix3x3<T> & m )
00223 {
00224 random(m.row(0));
00225 random(m.row(1));
00226 random(m.row(2));
00227 }
00228
00229 template<typename T>
00230 inline Matrix3x3<T> operator*( Matrix3x3<T> const & m, T const &s )
00231 {
00232 return Matrix3x3<T>(m.row(0)*s, m.row(1)*s, m.row(2)*s);
00233 }
00234
00235 template<typename T>
00236 inline Matrix3x3<T> operator*( T const & s, Matrix3x3<T> const & m )
00237 {
00238 return Matrix3x3<T>(m.row(0)*s, m.row(1)*s, m.row(2)*s);
00239 }
00240
00241 template<typename T>
00242 inline Matrix3x3<T> operator/( Matrix3x3<T> const & m, T const & s )
00243 {
00244 return Matrix3x3<T>(m.row(0)/s, m.row(1)/s, m.row(2)/s);
00245 }
00246
00247 template<typename T>
00248 inline Matrix3x3<T> operator/( T const & s, Matrix3x3<T> const & m )
00249 {
00250 return Matrix3x3<T>(m.row(0)/s, m.row(1)/s, m.row(2)/s);
00251 }
00252
00253 template<typename T>
00254 inline Matrix3x3<T> operator*(Matrix3x3<T> const & A,Matrix3x3<T> const & B)
00255 {
00256 typedef typename Matrix3x3<T>::value_traits value_traits;
00257 Matrix3x3<T> C;
00258
00259 for (int c=0; c<3; ++c)
00260 for (int r=0; r<3; ++r){
00261 C(r,c) = value_traits::zero();
00262 for(int i=0; i<3; ++i){
00263 C(r,c) += A(r,i) * B(i,c);
00264 }
00265 }
00266 return C;
00267 }
00268
00276 template<typename T>
00277 inline Matrix3x3<T> Rx(T const & radians)
00278 {
00279 typedef typename Matrix3x3<T>::value_traits value_traits;
00280
00281 using std::cos;
00282 using std::sin;
00283
00284 T cosinus = boost::numeric_cast<T>( cos(radians) );
00285 T sinus = boost::numeric_cast<T>( sin(radians) );
00286
00287 return Matrix3x3<T>(
00288 value_traits::one(), value_traits::zero(), value_traits::zero(),
00289 value_traits::zero(), cosinus, -sinus,
00290 value_traits::zero(), sinus, cosinus
00291 );
00292 }
00293
00301 template<typename T>
00302 inline Matrix3x3<T> Ry(T const & radians)
00303 {
00304 typedef typename Matrix3x3<T>::value_traits value_traits;
00305
00306 using std::cos;
00307 using std::sin;
00308
00309 T cosinus = boost::numeric_cast<T>( cos(radians) );
00310 T sinus = boost::numeric_cast<T>( sin(radians) );
00311 return Matrix3x3<T>(
00312 cosinus, value_traits::zero(), sinus,
00313 value_traits::zero(), value_traits::one(), value_traits::zero(),
00314 -sinus, value_traits::zero(), cosinus
00315 );
00316 }
00317
00324 template<typename T>
00325 inline Matrix3x3<T> Rz(T const & radians)
00326 {
00327 typedef typename Matrix3x3<T>::value_traits value_traits;
00328
00329 using std::cos;
00330 using std::sin;
00331
00332 T cosinus = boost::numeric_cast<T>( cos(radians) );
00333 T sinus = boost::numeric_cast<T>( sin(radians) );
00334
00335 return Matrix3x3<T>(
00336 cosinus, -sinus, value_traits::zero(),
00337 sinus, cosinus, value_traits::zero(),
00338 value_traits::zero(), value_traits::zero(), value_traits::one()
00339 );
00340 }
00341
00349 template<typename T>
00350 inline Matrix3x3<T> Ru(T const & radians, Vector3<T> const & axis)
00351 {
00352 typedef typename Matrix3x3<T>::value_traits value_traits;
00353
00354 using std::cos;
00355 using std::sin;
00356
00357 T cosinus = boost::numeric_cast<T>( cos(radians) );
00358 T sinus = boost::numeric_cast<T>( sin(radians) );
00359 Vector3<T> u = unit(axis);
00360
00361
00362 return Matrix3x3<T>(
00363 u(0)*u(0) + cosinus*(value_traits::one() - u(0)*u(0)), u(0)*u(1)*(value_traits::one()-cosinus) - sinus*u(2), u(0)*u(2)*(value_traits::one()-cosinus) + sinus*u(1),
00364 u(0)*u(1)*(value_traits::one()-cosinus) + sinus*u(2), u(1)*u(1) + cosinus*(value_traits::one() - u(1)*u(1)), u(1)*u(2)*(value_traits::one()-cosinus) - sinus*u(0),
00365 u(0)*u(2)*(value_traits::one()-cosinus) - sinus*u(1), u(1)*u(2)*(value_traits::one()-cosinus) + sinus*u(0), u(2)*u(2) + cosinus*(value_traits::one() - u(2)*u(2))
00366 );
00367 }
00368
00374 template<typename T>
00375 inline Matrix3x3<T> z_dof(Vector3<T> const & k)
00376 {
00377 Vector3<T> i,j;
00378 orthonormal_vectors(i,j,unit(k));
00379 return Matrix3x3<T>(
00380 i(0) , j(0), k(0)
00381 , i(1) , j(1), k(1)
00382 , i(2) , j(2), k(2)
00383 );
00384 }
00385
00386 template<typename T>
00387 inline bool is_orthonormal(Matrix3x3<T> const & M,T const & threshold)
00388 {
00389 typedef typename Matrix3x3<T>::value_traits value_traits;
00390
00391 using std::fabs;
00392
00393 assert(threshold>=value_traits::zero() || !"is_orthonormal(): threshold must be non-negative");
00394
00395 T dot01 = M.m_row0*M.m_row1;
00396 T dot02 = M.m_row0*M.m_row2;
00397 T dot12 = M.m_row1*M.m_row2;
00398 if(fabs(dot01)>threshold) return false;
00399 if(fabs(dot02)>threshold) return false;
00400 if(fabs(dot12)>threshold) return false;
00401 T dot00 = M.m_row0*M.m_row0;
00402 T dot11 = M.m_row1*M.m_row1;
00403 T dot22 = M.m_row2*M.m_row2;
00404 if((dot00-value_traits::one())>threshold) return false;
00405 if((dot11-value_traits::one())>threshold) return false;
00406 if((dot22-value_traits::one())>threshold) return false;
00407 return true;
00408 }
00409
00410 template<typename T>
00411 inline bool is_orthonormal(Matrix3x3<T> const & M)
00412 {
00413 typedef typename Matrix3x3<T>::value_traits value_traits;
00414
00415 return is_orthonormal(M, value_traits::zero());
00416 }
00417
00418 template<typename T>
00419 inline bool is_zero(Matrix3x3<T> M, T const & threshold)
00420 {
00421 typedef typename Matrix3x3<T>::value_traits value_traits;
00422
00423 using std::fabs;
00424
00425 assert(threshold>=value_traits::zero() || !"is_zero(): threshold must be non-negative");
00426
00427 if(fabs(M(0,0))>threshold) return false;
00428 if(fabs(M(0,1))>threshold) return false;
00429 if(fabs(M(0,2))>threshold) return false;
00430 if(fabs(M(1,0))>threshold) return false;
00431 if(fabs(M(1,1))>threshold) return false;
00432 if(fabs(M(1,2))>threshold) return false;
00433 if(fabs(M(2,0))>threshold) return false;
00434 if(fabs(M(2,1))>threshold) return false;
00435 if(fabs(M(2,2))>threshold) return false;
00436 return true;
00437 }
00438
00439 template<typename T>
00440 inline bool is_zero(Matrix3x3<T> const & M)
00441 {
00442 typedef typename Matrix3x3<T>::value_traits value_traits;
00443
00444 return is_zero(M, value_traits::zero());
00445 }
00446
00447 template<typename T>
00448 inline bool is_symmetric(Matrix3x3<T> M, T const & threshold)
00449 {
00450 typedef typename Matrix3x3<T>::value_traits value_traits;
00451
00452 using std::fabs;
00453
00454 assert(threshold>=value_traits::zero() || !"is_symmetric(): threshold must be non-negative");
00455
00456 if(fabs(M(0,1)-M(1,0))>threshold) return false;
00457 if(fabs(M(0,2)-M(2,0))>threshold) return false;
00458 if(fabs(M(1,2)-M(2,1))>threshold) return false;
00459 return true;
00460 }
00461
00462 template<typename T>
00463 inline bool is_symmetric(Matrix3x3<T> const & M)
00464 {
00465 typedef typename Matrix3x3<T>::value_traits value_traits;
00466
00467 return is_symmetric(M, value_traits::zero());
00468 }
00469
00470 template<typename T>
00471 inline bool is_diagonal(Matrix3x3<T> M, T const & threshold)
00472 {
00473 typedef typename Matrix3x3<T>::value_traits value_traits;
00474
00475 using std::fabs;
00476
00477 assert(threshold>=value_traits::zero() || !"is_diagonal(): threshold must be non-negative");
00478
00479 if(fabs(M(0,1))>threshold) return false;
00480 if(fabs(M(0,2))>threshold) return false;
00481 if(fabs(M(1,0))>threshold) return false;
00482 if(fabs(M(1,2))>threshold) return false;
00483 if(fabs(M(2,0))>threshold) return false;
00484 if(fabs(M(2,1))>threshold) return false;
00485 return true;
00486 }
00487
00488 template<typename T>
00489 inline bool is_diagonal(Matrix3x3<T> const & M)
00490 {
00491 typedef typename Matrix3x3<T>::value_traits value_traits;
00492
00493 return is_diagonal(M, value_traits::zero());
00494 }
00495
00496 template<typename T>
00497 inline bool is_identity(Matrix3x3<T> M, T const & threshold)
00498 {
00499 typedef typename Matrix3x3<T>::value_traits value_traits;
00500
00501 using std::fabs;
00502
00503 assert(threshold>=value_traits::zero() || !"is_identity(): threshold must be non-negative");
00504
00505 if(fabs(M(0,0)-value_traits::one())>threshold) return false;
00506 if(fabs(M(0,1))>threshold) return false;
00507 if(fabs(M(0,2))>threshold) return false;
00508 if(fabs(M(1,0))>threshold) return false;
00509 if(fabs(M(1,1)-value_traits::one())>threshold) return false;
00510 if(fabs(M(1,2))>threshold) return false;
00511 if(fabs(M(2,0))>threshold) return false;
00512 if(fabs(M(2,1))>threshold) return false;
00513 if(fabs(M(2,2)-value_traits::one())>threshold) return false;
00514 return true;
00515 }
00516
00517 template<typename T>
00518 inline bool is_identity(Matrix3x3<T> const & M)
00519 {
00520 typedef typename Matrix3x3<T>::value_traits value_traits;
00521
00522 return is_identity(M, value_traits::zero());
00523 }
00524
00525 template <typename T>
00526 inline Matrix3x3<T> outer_prod( Vector3<T> const & v1, Vector3<T> const & v2 )
00527 {
00528 return Matrix3x3<T>(
00529 ( v1( 0 ) * v2( 0 ) ), ( v1( 0 ) * v2( 1 ) ), ( v1( 0 ) * v2( 2 ) ),
00530 ( v1( 1 ) * v2( 0 ) ), ( v1( 1 ) * v2( 1 ) ), ( v1( 1 ) * v2( 2 ) ),
00531 ( v1( 2 ) * v2( 0 ) ), ( v1( 2 ) * v2( 1 ) ), ( v1( 2 ) * v2( 2 ) )
00532 );
00533 }
00534
00535 template<typename T>
00536 inline Matrix3x3<T> ortonormalize(Matrix3x3<T> const & A)
00537 {
00538 typedef typename Matrix3x3<T>::vector3_type vector3_type;
00539
00540 vector3_type row0(A(0,0),A(0,1),A(0,2));
00541 vector3_type row1(A(1,0),A(1,1),A(1,2));
00542 vector3_type row2(A(2,0),A(2,1),A(2,2));
00543
00544 T const l0 = length(row0);
00545 if(l0) row0 /= l0;
00546
00547 row1 -= row0 * dot(row0 , row1);
00548 T const l1 = length(row1);
00549 if(l1) row1 /= l1;
00550
00551 row2 = cross( row0 , row1);
00552
00553 return Matrix3x3<T>(
00554 row0(0), row0(1), row0(2),
00555 row1(0), row1(1), row1(2),
00556 row2(0), row2(1), row2(2)
00557 );
00558 }
00559
00560 template<typename T>
00561 inline Matrix3x3<T> trans(Matrix3x3<T> const & M)
00562 {
00563 return Matrix3x3<T>(
00564 M(0,0), M(1,0), M(2,0),
00565 M(0,1), M(1,1), M(2,1),
00566 M(0,2), M(1,2), M(2,2)
00567 );
00568 }
00569
00570
00571 template<typename T>
00572 inline Matrix3x3<T> diag(T const & d0,T const & d1,T const & d2 )
00573 {
00574 typedef typename Matrix3x3<T>::value_traits value_traits;
00575
00576 return Matrix3x3<T>(
00577 d0, value_traits::zero(), value_traits::zero(),
00578 value_traits::zero(), d1, value_traits::zero(),
00579 value_traits::zero(), value_traits::zero(), d2
00580 );
00581 }
00582
00583 template<typename T>
00584 inline Matrix3x3<T> diag(Vector3<T> const & d) { return diag( d(0), d(1), d(2)); }
00585
00586 template<typename T>
00587 inline Matrix3x3<T> diag(T const & d ) { return diag(d,d,d); }
00588
00589 template<typename T>
00590 inline Matrix3x3<T> inverse(Matrix3x3<T> const & A)
00591 {
00592 typedef typename Matrix3x3<T>::value_traits value_traits;
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613 Matrix3x3<T> adj;
00614 adj(0,0) = A(1,1)*A(2,2) - A(2,1)*A(1,2);
00615 adj(1,1) = A(0,0)*A(2,2) - A(2,0)*A(0,2);
00616 adj(2,2) = A(0,0)*A(1,1) - A(1,0)*A(0,1);
00617 adj(0,1) = A(1,0)*A(2,2) - A(2,0)*A(1,2);
00618 adj(0,2) = A(1,0)*A(2,1) - A(2,0)*A(1,1);
00619 adj(1,0) = A(0,1)*A(2,2) - A(2,1)*A(0,2);
00620 adj(1,2) = A(0,0)*A(2,1) - A(2,0)*A(0,1);
00621 adj(2,0) = A(0,1)*A(1,2) - A(1,1)*A(0,2);
00622 adj(2,1) = A(0,0)*A(1,2) - A(1,0)*A(0,2);
00623 T det = A(0,0)*adj(0,0) - A(0,1)*adj(0,1) + A(0,2)*adj(0,2);
00624 if(det)
00625 {
00626 adj(0,1) = -adj(0,1);
00627 adj(1,0) = -adj(1,0);
00628 adj(1,2) = -adj(1,2);
00629 adj(2,1) = -adj(2,1);
00630 return trans(adj)/det;
00631 }
00632
00633 return diag(value_traits::one());
00634 }
00635
00636 template<typename T>
00637 inline T max_value(Matrix3x3<T> const & A)
00638 {
00639 using std::max;
00640
00641 return max(A(0,0), max( A(0,1), max( A(0,2), max ( A(1,0), max ( A(1,1), max ( A(1,2), max (A(2,0), max ( A(2,1) , A(2,2) ) ) ) ) ) ) ) );
00642 }
00643
00644 template<typename T>
00645 inline T min_value(Matrix3x3<T> const & A)
00646 {
00647 using std::min;
00648
00649 return min(A(0,0), min( A(0,1), min( A(0,2), min ( A(1,0), min ( A(1,1), min ( A(1,2), min (A(2,0), min ( A(2,1) , A(2,2) ) ) ) ) ) ) ) );
00650 }
00651
00652 template<typename T>
00653 inline T det(Matrix3x3<T> const & A)
00654 {
00655 return A(0,0)*(A(1,1)*A(2,2) - A(2,1)*A(1,2)) - A(0,1)*(A(1,0)*A(2,2) - A(2,0)*A(1,2)) + A(0,2)*(A(1,0)*A(2,1) - A(2,0)*A(1,1));
00656 }
00657
00658 template<typename T>
00659 inline T trace(Matrix3x3<T> const & A)
00660 {
00661 return (A(0,0) + A(1,1) + A(2,2));
00662 }
00663
00664 template<typename T>
00665 inline T norm_1(Matrix3x3<T> const & A)
00666 {
00667 using std::fabs;
00668 using std::max;
00669
00670 T r0 = fabs(A(0,0)) + fabs(A(0,1)) + fabs(A(0,2));
00671 T r1 = fabs(A(1,0)) + fabs(A(1,1)) + fabs(A(1,2));
00672 T r2 = fabs(A(2,0)) + fabs(A(2,1)) + fabs(A(2,2));
00673
00674 return max ( r0, max( r1, r2 ) );
00675 }
00676
00677 template<typename T>
00678 inline T norm_2(Matrix3x3<T> const & A)
00679 {
00680 using std::fabs;
00681 using std::max;
00682 using std::sqrt;
00683
00684 Matrix3x3<T> V;
00685 typename Matrix3x3<T>::vector3_type d;
00686 math::eigen(A,V,d);
00687
00688 T lambda = max( fabs(d(0)), max( fabs(d(1)) , fabs(d(2)) ));
00689 return sqrt( lambda );
00690 }
00691
00692 template<typename T>
00693 inline T norm_inf(Matrix3x3<T> const & A)
00694 {
00695 using std::fabs;
00696 using std::max;
00697
00698 T c0 = fabs(A(0,0)) + fabs(A(1,0)) + fabs(A(2,0));
00699 T c1 = fabs(A(0,1)) + fabs(A(1,1)) + fabs(A(2,1));
00700 T c2 = fabs(A(0,2)) + fabs(A(1,2)) + fabs(A(2,2));
00701 return max ( c0, max( c1, c2 ) );
00702 }
00703
00704 template<typename T>
00705 inline Matrix3x3<T> truncate(Matrix3x3<T> const & A,T const & epsilon)
00706 {
00707 typedef typename Matrix3x3<T>::value_traits value_traits;
00708
00709 using std::fabs;
00710
00711 assert(epsilon>value_traits::zero() || !"truncate(Matrix3x3,epsilon): epsilon must be positive");
00712
00713 return Matrix3x3<T>(
00714 fabs(A(0,0))<epsilon?value_traits::zero():A(0,0),
00715 fabs(A(0,1))<epsilon?value_traits::zero():A(0,1),
00716 fabs(A(0,2))<epsilon?value_traits::zero():A(0,2),
00717
00718 fabs(A(1,0))<epsilon?value_traits::zero():A(1,0),
00719 fabs(A(1,1))<epsilon?value_traits::zero():A(1,1),
00720 fabs(A(1,2))<epsilon?value_traits::zero():A(1,2),
00721
00722 fabs(A(2,0))<epsilon?value_traits::zero():A(2,0),
00723 fabs(A(2,1))<epsilon?value_traits::zero():A(2,1),
00724 fabs(A(2,2))<epsilon?value_traits::zero():A(2,2)
00725 );
00726 }
00727
00734 template<typename T>
00735 inline Matrix3x3<T> star(Vector3<T> const & v)
00736 {
00737 typedef typename Matrix3x3<T>::value_traits value_traits;
00738
00739
00740
00741
00742 return Matrix3x3<T>(
00743 value_traits::zero(), -v(2), v(1),
00744 v(2), value_traits::zero(), -v(0),
00745 -v(1), v(0), value_traits::zero()
00746 );
00747 }
00748
00749 template<typename T>
00750 inline std::ostream & operator<< (std::ostream & o,Matrix3x3<T> const & A)
00751 {
00752 o << "[" << A(0,0)
00753 << "," << A(0,1)
00754 << "," << A(0,2)
00755 << ";" << A(1,0)
00756 << "," << A(1,1)
00757 << "," << A(1,2)
00758 << ";" << A(2,0)
00759 << "," << A(2,1)
00760 << "," << A(2,2)
00761 << "]";
00762 return o;
00763 }
00764
00765 template<typename T>
00766 inline std::istream & operator>>(std::istream & i,Matrix3x3<T> & A)
00767 {
00768 char dummy;
00769 i >> dummy;
00770 i >> A(0,0);
00771 i >> dummy;
00772 i >> A(0,1);
00773 i >> dummy;
00774 i >> A(0,2);
00775 i >> dummy;
00776 i >> A(1,0);
00777 i >> dummy;
00778 i >> A(1,1);
00779 i >> dummy;
00780 i >> A(1,2);
00781 i >> dummy;
00782 i >> A(2,0);
00783 i >> dummy;
00784 i >> A(2,1);
00785 i >> dummy;
00786 i >> A(2,2);
00787 i >> dummy;
00788 return i;
00789 }
00790
00791 }
00792
00793 }
00794
00795
00796 #endif