MatrixXD.h

00001 //===========================================================================
00002 // GoTools - SINTEF Geometry Tools version 1.1
00003 //
00004 // GoTools module: CORE
00005 //
00006 // Copyright (C) 2000-2007 SINTEF ICT, Applied Mathematics, Norway.
00007 //
00008 // This program is free software; you can redistribute it and/or          
00009 // modify it under the terms of the GNU General Public License            
00010 // as published by the Free Software Foundation version 2 of the License. 
00011 //
00012 // This program is distributed in the hope that it will be useful,        
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of         
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          
00015 // GNU General Public License for more details.                           
00016 //
00017 // You should have received a copy of the GNU General Public License      
00018 // along with this program; if not, write to the Free Software            
00019 // Foundation, Inc.,                                                      
00020 // 59 Temple Place - Suite 330,                                           
00021 // Boston, MA  02111-1307, USA.                                           
00022 //
00023 // Contact information: E-mail: tor.dokken@sintef.no                      
00024 // SINTEF ICT, Department of Applied Mathematics,                         
00025 // P.O. Box 124 Blindern,                                                 
00026 // 0314 Oslo, Norway.                                                     
00027 //
00028 // Other licenses are also available for this software, notably licenses
00029 // for:
00030 // - Building commercial software.                                        
00031 // - Building software whose source code you wish to keep private.        
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); // Make a copy so that it gets the right size.
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         // Now, make this matrix into
00291         // uut + cos(angle)*(I-uut) + sin(angle)*S;
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 //      double alpha = p.angle(q);
00335 //      setToRotation(alpha, v[0], v[1], v[2]);
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         // Now, make this matrix into
00356         // vvt + cos(angle)*(I+vvt) + S;
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             // @@ Slow implementation...
00373             // Developing along the first coordinate (rows).
00374             T result(0);
00375             for (int i = 0; i < Dim; ++i) {
00376                 // Make the submatrix
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                 // Add or subtract the sub determinant
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     //    template<> removed by JAM
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 } // namespace Go
00449 
00450 
00451 #endif // _GOMATRIXXD_H
00452 
00453 

Generated on Mon Jun 11 14:48:18 2007 for GoTools Core Library by  doxygen 1.5.1