Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base/Matrix3

Go to the documentation of this file.
00001 /* **-*-c++-*-**************************************************************
00002   Copyright (C)1996 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: Matrix3 1029 2004-02-11 20:45:54Z jungd $
00019   $Revision: 1.10 $
00020   $Date: 2004-02-11 15:45:54 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022  
00023 ****************************************************************************/
00024 
00025 #ifndef _BASE_MATRIX3_
00026 #define _BASE_MATRIX3_
00027 
00028 #include <iostream>
00029 
00030 #include <base/base>
00031 #include <base/Object>
00032 #include <base/Vector3>
00033 
00034 
00035 #define MATRIX3_ACCESS(r,c) (3*(c-1)+r-1)
00036 
00037 
00038 namespace base {
00039 
00040 class Serializer;
00041 class Matrix3;
00042 
00043 // classes to help speed up common vector/matrix operations
00044 //  (not used directly by the user)
00045 
00046 struct M3V3mul {
00047   const Matrix3& m;
00048   const Vector3& v;
00049 
00050   M3V3mul(const Matrix3& mm, const Vector3& vv) : m(mm), v(vv) {}
00051 
00052   operator Vector3() const;
00053 };
00054 
00055 struct M3V3mulV3add {
00056   const Matrix3& m;
00057   const Vector3& v;
00058   const Vector3& v2;
00059 
00060   M3V3mulV3add(const M3V3mul& mv, const Vector3& vv) : m(mv.m), v(mv.v), v2(vv) {}
00061 
00062   operator Vector3() const;
00063 };
00064 
00065 
00066 //
00067 // The matrix
00068 //
00069 
00070 class Matrix3 
00071 {
00072 
00073 public:
00074   Matrix3() { setIdentity(); }
00075   Matrix3(const Matrix3& m) { this->operator=(m); }
00076   Matrix3(const Real& s) { setDiag(s); }
00077   Matrix3(Real e11, Real e12, Real e13,
00078           Real e21, Real e22, Real e23,
00079           Real e31, Real e32, Real e33)
00080   {
00081     e(1,1)=e11; e(1,2)=e12; e(1,3)=e13;
00082     e(2,1)=e21; e(2,2)=e22; e(2,3)=e23;
00083     e(3,1)=e31; e(3,2)=e32; e(3,3)=e33;
00084   }
00085   ~Matrix3() {}
00086 
00087   
00088   Matrix3& setIdentity() throw()
00089   {
00090     setDiag(Real(1)); return *this;
00091   }
00092 
00093   Matrix3& setZero() throw()
00094   {
00095     setDiag(Real(0)); return *this;
00096   }
00097 
00098 
00099   Real& e(Int row, Int col) throw()
00100   { 
00101     Assertm( !((row < 1) || (row > 3) || (col < 1) || (col > 3)), "matrix row and col within bounds (debug only check)");
00102     return m[MATRIX3_ACCESS(row,col)]; 
00103   }
00104 
00105   const Real& e(Int row, Int col) const throw()
00106   {
00107     Assertm( !((row < 1) || (row > 3) || (col < 1) || (col > 3)), "matrix row and col within bounds (debug only check)");
00108     return m[MATRIX3_ACCESS(row,col)]; 
00109   }
00110 
00111   Real& at(Int row, Int col) throw(std::out_of_range)
00112   {
00113     if ((row < 1) || (row > 3) || (col < 1) || (col > 3))
00114       throw std::out_of_range(Exception("matrix row or col out of bounds"));
00115 
00116     return m[MATRIX3_ACCESS(row,col)];
00117   }
00118 
00119   const Real& at(Int row, Int col) const throw(std::out_of_range)
00120   {
00121     if ((row < 1) || (row > 3) || (col < 1) || (col > 3))
00122       throw std::out_of_range(Exception("matrix row or col out of bounds"));
00123 
00124     return m[MATRIX3_ACCESS(row,col)];
00125   }
00126 
00127   Real& operator()(Int row, Int col) throw()
00128   {
00129 #ifdef DEBUG
00130     return at(row,col);
00131 #else
00132     return e(row,col);
00133 #endif
00134   }
00135 
00136   const Real& operator()(Int row, Int col) const throw()
00137   {
00138 #ifdef DEBUG
00139     return at(row,col);
00140 #else
00141     return e(row,col);
00142 #endif
00143   }
00144 
00145 
00146 
00147 
00148 
00149   Vector3 row(Int row) const         // extract row vector
00150   { return Vector3(e(row,1),e(row,2),e(row,3)); }
00151 
00152   Vector3 column(Int col) const      // extract column vector
00153   { return Vector3(e(1,col),e(2,col),e(3,col)); }
00154 
00155   void setRow(Int row, const Vector3& r) throw()
00156   { e(row,1)=r.x; e(row,2)=r.y; e(row,3)=r.z; }
00157 
00158   void setColumn(Int col, const Vector3& c) throw()
00159   { e(1,col)=c.x; e(2,col)=c.y; e(3,col)=c.z; }
00160 
00161   void swapColumns(Int col1, Int col2) throw(std::out_of_range)
00162   {
00163     if ((col1 < 1) || (col1 > 3) || (col2 < 1) || (col2 > 3))
00164       throw std::out_of_range(Exception("matrix col out of bounds"));
00165 
00166     Vector3 tmp(column(col1));
00167     setColumn(col1,column(col2));
00168     setColumn(col2,tmp);
00169   }
00170 
00171   void swapRows(Int row1, Int row2) throw(std::out_of_range)
00172   {
00173     if ((row1 < 1) || (row1 > 3) || (row2 < 1) || (row2 > 3))
00174       throw std::out_of_range(Exception("matrix row out of bounds"));
00175 
00176     Vector3 tmp(row(row1));
00177     setRow(row1,row(row2));
00178     setRow(row2,tmp);
00179   }
00180 
00181 
00182   Vector3 operator[](Int r) const  // row
00183   { return row(r); }
00184 
00185 
00186   int index(Int row, Int col) const throw()
00187   { return MATRIX3_ACCESS(row,col); }
00188 
00189   Matrix3& operator=(const Matrix3& src) throw()
00190   { 
00191     if (&src != this)
00192       for(int i=0; i<9; i++)
00193         m[i] = src.m[i];
00194     return *this;
00195   }
00196 
00197 
00198   bool operator==(const Matrix3& m1) const throw()
00199   {
00200     for(int i=0; i<9; i++)
00201       if (m1.m[i]!=m[i]) return false;
00202     return true;
00203   }
00204 
00205   bool equals(const Matrix3& m1, Real epsilon = consts::epsilon) const throw()
00206   {
00207     for(int i=0; i<9; i++)
00208       if (!base::equals(m1.m[i],m[i],epsilon)) return false;
00209     return true;
00210   }
00211 
00212 
00213   Matrix3& transpose();
00214   Matrix3& invert();
00215   Matrix3& negate() throw();
00216 
00217   /// sets the matrix to the right-handed orthonormal basis for vector v
00218   void setOrthonormalBasisOf(const Vector3& v);
00219   
00220   // Find LUP decomposition.  P is represented by the vector Pi, where the element
00221   //  values represent the column of P containing a 1. i.e. Pi[i]=j => P[i][j]=1
00222   void decomposeLUP(Matrix3& L, Matrix3& U, Vector3& Pi) const;
00223   
00224   /// Solve Ax=b for x, given b, where A=*this (returns x)
00225   Vector3  solve(const Vector3& b) const; 
00226 
00227   // Computes the eigen values/vectors in dout & vout resp.
00228   //  (returns the no. of iterations taken (upto max) )
00229   Int eigenJacobi(Matrix3& vout, Vector3& dout, Int maxIter=50) const;
00230 
00231   Matrix3& operator*=(const Matrix3& m2);
00232   Matrix3& operator+=(const Matrix3& m2);
00233   Matrix3& operator-=(const Matrix3& m2);
00234   Matrix3& operator*=(const Real& s);
00235   Matrix3& operator/=(const Real& s);
00236 
00237 
00238   const Real* c_array() const { return m; }
00239   Real* c_array() { return m; }
00240 
00241   /// Solve for xA = b, given LUP decomposition of A as L, U and Pi, and given b, returns x
00242   static Vector3 solveLUP(const Matrix3& L, const Matrix3& U, const Vector3& Pi, const Vector3& b);
00243 
00244   static void decomposeLUP(const Matrix3& A, Matrix3& L, Matrix3& U, Vector3& Pi)
00245   { A.decomposeLUP(L,U,Pi); }
00246 
00247   // best to use the operators than use these directly
00248   static Vector3 matrixMulVector(const Matrix3& m, const Vector3& v); // m x v
00249   static Vector3 matrixMulVectorAddVector(const Matrix3& m, const Vector3& v, const Vector3& v2); // m x v + v2
00250 
00251   void serialize(Serializer& s); ///< read or write object state to Serializer
00252 
00253 private:
00254   Real m[9];
00255   
00256   void setDiag(const Real& d)
00257   {
00258     m[0] = d;
00259     m[1] = Real(0);
00260     m[2] = Real(0);
00261     m[3] = Real(0);
00262     m[4] = d;
00263     m[5] = Real(0);
00264     m[6] = Real(0);
00265     m[7] = Real(0);
00266     m[8] = d;
00267   }
00268 
00269 };
00270 
00271 
00272 // Operations
00273 
00274 
00275 inline Matrix3 operator*(const Matrix3& m1, const Matrix3& m2) // Matrix multiplication
00276 { Matrix3 r(m1); return r *= m2; }
00277 
00278 inline Matrix3 operator+(const Matrix3& m1, const Matrix3& m2) // Addition
00279 { Matrix3 r(m1); return r += m2; }
00280 
00281 inline Matrix3 operator-(const Matrix3& m1, const Matrix3& m2) // Subtraction
00282 { Matrix3 r(m1); return r -= m2; }
00283 
00284 inline Matrix3 operator-(const Matrix3& m1) // Negation
00285 { Matrix3 r(m1); return r.negate(); }
00286 
00287 inline Matrix3 operator*(const Matrix3& m1, const Real& s) // Scalar multiplication
00288 { Matrix3 r(m1); return r *= s; }
00289 
00290 inline Matrix3 operator*(const Real& s, const Matrix3& m1) // Scalar multiplication
00291 { Matrix3 r(m1); return r *= s; }
00292 
00293 inline Matrix3 operator/(const Matrix3& m1, const Real& s) // Scalar division
00294 { Matrix3 r(m1); return r /= s; }
00295 
00296 inline Matrix3 transpose(const Matrix3& m) // Transpose
00297 { Matrix3 r(m); return r.transpose(); }
00298 
00299 inline Matrix3 inverse(const Matrix3& m) // Inverse
00300 { Matrix3 r(m); return r.invert(); }
00301 
00302 
00303 
00304 
00305 
00306 // These functions and the structs above provide closures for common vector matrix
00307 //  operations.
00308 // For example, an expression like m*v+v2 will expand to:
00309 //              Matrix3::matrixMulVectorAddVector(m,v,v2);
00310 // rather than: Vector3 r(operator*(m,v)); r.operator+=(v2), return r
00311 //   (saving a couple copies between temporaries)
00312 
00313 inline M3V3mulV3add operator+(const M3V3mul& mv, const Vector3& vv)
00314 { return M3V3mulV3add(mv,vv); }
00315 
00316 inline M3V3mul operator*(const Matrix3& mm, const Vector3& vv)
00317 { return M3V3mul(mm,vv); }
00318 
00319 inline M3V3mul::operator Vector3() const
00320 { return Matrix3::matrixMulVector(m,v); }
00321 
00322 inline M3V3mulV3add::operator Vector3() const
00323 { return Matrix3::matrixMulVectorAddVector(m,v,v2); }
00324 
00325 
00326 std::ostream& operator<<(std::ostream& out, const Matrix3& m); // Output
00327 
00328 
00329 } // base
00330 
00331 #endif
00332 

Generated on Thu Jul 29 15:56:07 2004 for OpenSim by doxygen 1.3.6