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

base/Matrix3.cpp

Go to the documentation of this file.
00001 /****************************************************************************
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.cpp 1029 2004-02-11 20:45:54Z jungd $
00019   $Revision: 1.5 $
00020   $Date: 2004-02-11 15:45:54 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022  
00023 ****************************************************************************/
00024 
00025 #include <base/Matrix3>
00026 
00027 #include <base/Math>
00028 #include <base/Serializer>
00029 
00030 
00031 using base::Math;
00032 using base::Matrix3;
00033 using base::Vector3;
00034 
00035 using std::ostream;
00036 
00037 
00038 inline static void exchange(Real& a, Real& b)
00039 {
00040   Real t(a);
00041   a = b;
00042   b = t;
00043 }
00044 
00045 // row, col element exchange
00046 inline static void rcswap3(Real m[], Int r, Int c) 
00047 {
00048   Real* rcp = &m[MATRIX3_ACCESS(r,c)];
00049   Real* crp = &m[MATRIX3_ACCESS(c,r)];
00050   exchange(*rcp, *crp);
00051 }
00052 
00053 
00054 Matrix3& Matrix3::transpose()
00055 {
00056   rcswap3(m,1,2); rcswap3(m,1,3);
00057   rcswap3(m,2,3);
00058 
00059   return *this;
00060 }
00061 
00062 
00063 Matrix3& Matrix3::invert()
00064 {
00065   // Solve AX = I by solving 3 eqns: Ax = e (for each e a col of I)
00066   Matrix3 I; // identity
00067   Matrix3 X, A(*this);
00068   Vector3 x;
00069   
00070   Matrix3 L,U;
00071   Vector3 Pi;
00072   
00073   A.decomposeLUP(L,U,Pi);
00074   
00075   for(int c=1; c<=3; c++) {
00076     x = solveLUP(L,U,Pi,I.column(c));
00077     for(int r=1; r<=3; r++) X.e(r,c) = x[r];
00078   }
00079   
00080   return (*this = X);
00081 
00082 }
00083 
00084 
00085 
00086 void Matrix3::setOrthonormalBasisOf(const Vector3& v)
00087 {
00088   Vector3 n(v); n.normalize();
00089   setRow(3, n);
00090   
00091   Vector3 u;
00092   if (Math::abs(n.x) >= Math::abs(n.y)) {
00093     // n.x or n.z is the largest magnitude component, swap them
00094     Real invLength = 1.0 / Math::sqrt(Math::sqr(n.x) + Math::sqr(n.z));
00095     u = Vector3(-n.z * invLength, 0, n.x * invLength);
00096   }
00097   else {
00098     // n.y or n.z is the largest magnitude component, swap them
00099     Real invLength = 1.0/Math::sqrt(Math::sqr(n.y) + Math::sqr(n.z));
00100     u = Vector3(0, n.z * invLength, n.y * invLength);
00101   }
00102   
00103   setRow(1, u);
00104   setRow(2, cross(n,u));
00105 }
00106 
00107 
00108 void Matrix3::decomposeLUP(Matrix3& L, Matrix3& U, Vector3& Pi) const
00109 {
00110   Real p,a;
00111   int kp,i,j,k;
00112   Matrix3 AA(*this);
00113 
00114   for(i=1; i<=3; i++) Pi[i] = i;
00115   for(k=1; k<=3-1; k++) {
00116     p = Real(0); kp = 1;
00117     for(i=k; i<=3; i++) {
00118       a = Real(Math::abs(AA.e(i,k)));
00119       if ( a > p ) {
00120         p = a;
00121         kp = i;
00122       }
00123     }
00124     if (p == Real(0))
00125       throw std::invalid_argument(Exception("matrix is singular"));
00126     
00127     exchange(Pi[k],Pi[kp]);
00128     for(i=1; i<=3;i++) exchange(AA.e(k,i),AA.e(kp,i));
00129     
00130     for(i=k+1; i<=3;i++) {
00131       AA.e(i,k) /= AA.e(k,k);
00132       for(j=k+1; j<=3; j++)
00133         AA.e(i,j) -= AA.e(i,k)*AA.e(k,j);
00134     }
00135   }
00136   
00137   for(i=1;i<=3;i++) {
00138     for(j=1;j<=3;j++)
00139       if (i>j) {
00140         L.e(i,j) = AA.e(i,j); U.e(i,j) = Real(0);
00141       }
00142       else {
00143         U.e(i,j) = AA.e(i,j); L.e(i,j) = Real(0);
00144       }
00145     L.e(i,i) = Real(1);
00146     
00147   }
00148 
00149 }
00150 
00151 
00152 Vector3 Matrix3::solve(const Vector3& b) const
00153 {
00154   Matrix3 L,U;
00155   Vector3 Pi;
00156 
00157   decomposeLUP(L,U,Pi);
00158   return solveLUP(L,U,Pi,b);
00159 }
00160 
00161 
00162 Matrix3& Matrix3::negate() throw()
00163 {
00164   for(int i=0; i<9; i++)
00165     m[i]=-m[i];
00166   return *this;
00167 }
00168 
00169 
00170 // Operators
00171 
00172 // multiplication
00173 Matrix3& Matrix3::operator*=(const Matrix3& m2)
00174 {
00175   Matrix3 tmp;
00176 
00177   for(int row=1; row<=3; row++)
00178     for(int col=1; col<=3; col++)
00179       tmp.e(row,col) =  (e(row,1) * m2.e(1,col)) + (e(row,2) * m2.e(2,col))
00180                                                   + (e(row,3) * m2.e(3,col)); 
00181  
00182   return (*this = tmp);
00183 }
00184 
00185 // addition
00186 Matrix3& Matrix3::operator+=(const Matrix3& m2)
00187 {
00188   for(int i=0; i<9; i++)
00189     m[i] += m2.m[i];
00190   return (*this);
00191 }
00192 
00193 // subtration
00194 Matrix3& Matrix3::operator-=(const Matrix3& m2)
00195 {
00196   for(int i=0; i<9; i++)
00197     m[i] -= m2.m[i];
00198   return (*this);
00199 }
00200 
00201 // Scalar multiplication
00202 Matrix3& Matrix3::operator*=(const Real& s)
00203 {
00204   for(int i=0; i<9; i++)
00205     m[i] *= s;
00206   return *this;
00207 }
00208 
00209 // Scalar division
00210 Matrix3& Matrix3::operator/=(const Real& s)
00211 {
00212   for(int i=0; i<9; i++)
00213     m[i] /= s;
00214   return *this;
00215 }
00216 
00217 
00218 
00219 Vector3 Matrix3::matrixMulVector(const Matrix3& m, const Vector3& v) 
00220 { return Vector3(m.m[0]*v.x+m.m[3]*v.y+m.m[6]*v.z,
00221                  m.m[1]*v.x+m.m[4]*v.y+m.m[7]*v.z,
00222                  m.m[2]*v.x+m.m[5]*v.y+m.m[8]*v.z);
00223 }
00224 
00225 /* above is equivelent to: (which is slower but easier to read)
00226 Vector4 Matrix4::matrixMulVector(const Matrix4& m, const Vector4& v) 
00227 { return Vector4(m.e(1,1)*v.x+m.e(1,2)*v.y+m.e(1,3)*v.z,
00228                  m.e(2,1)*v.x+m.e(2,2)*v.y+m.e(2,3)*v.z,
00229                  m.e(3,1)*v.x+m.e(3,2)*v.y+m.e(3,3)*v.z)
00230 }
00231 */
00232 
00233 
00234 Vector3 Matrix3::matrixMulVectorAddVector(const Matrix3& m, const Vector3& v, const Vector3& v2) 
00235 { return Vector3(m.m[0]*v.x+m.m[3]*v.y+m.m[6]*v.z+v2.x,
00236                  m.m[1]*v.x+m.m[4]*v.y+m.m[7]*v.z+v2.y,
00237                  m.m[2]*v.x+m.m[5]*v.y+m.m[8]*v.z+v2.z);
00238 }
00239 
00240 
00241 /// Solve for Ax = b, given LUP decomposition of A as L, U and Pi, and given b, returns x
00242 Vector3 Matrix3::solveLUP(const Matrix3& L, const Matrix3& U, const Vector3& Pi, const Vector3& b)
00243 {
00244   int i,j;
00245   Vector3 y, x;
00246   Real s;
00247   // forward subst.
00248   for(i=1;i<=3;i++) {
00249     s = Real(0);
00250     for(j=1;j<=i-1;j++) s += L.e(i,j)*y[j];
00251     y[i] = b[int(Pi[i])] - s;
00252   }
00253   // backward subst.
00254   for(i=3;i>=1;i--) {
00255     s = Real(0);
00256     for(j=i+1;j<=3;j++) s += U.e(i,j)*x[j];
00257     x[i] = (y[i] - s)/(U.e(i,i));
00258   }
00259   return x;
00260 }
00261 
00262 
00263 // eigenJacobi helper
00264 //  (do we really need to pass g & h??)
00265 inline void rotate(Matrix3& a, Real& g, Real& h, Real s, Real tau, Int i, Int j, Int k, Int l) {
00266   g=a.e(i,j); h=a.e(k,l); 
00267   a.e(i,j) = g-s*(h+g*tau);
00268   a.e(k,l) = h+s*(g-h*tau);
00269 }
00270 
00271 
00272 /// Computes the eigen values/vectors in dout & vout resp.
00273 /** (returns the no. of iterations taken (max 50) )
00274  * see Numerical Recipies in C pp467 (Ch.11).
00275  */
00276 Int Matrix3::eigenJacobi(Matrix3& vout, Vector3& dout, Int maxIter) const
00277 {
00278   Int i;
00279   Real tresh,theta,tau,t,sm,s,h,g,c;
00280   Vector3 b,z,d;
00281   Matrix3 v;
00282   Matrix3 a(*this);
00283   
00284   b.x = a.e(1,1);
00285   b.y = a.e(2,2);
00286   b.z = a.e(3,3);
00287   d = b;
00288   z.setZero();
00289   
00290   Int nrot = 0;
00291   
00292   for(i=0; i<maxIter; i++) {
00293     
00294     sm=0.0; sm+=Math::abs(a.e(1,2)); sm+=Math::abs(a.e(1,3)); sm+=Math::abs(a.e(2,3));
00295     if (sm == 0.0) { 
00296       vout = v;
00297       dout = d;
00298       return i;
00299     }
00300     
00301     if (i < 3) tresh=0.2*sm/(3.0*3.0); else tresh=0.0;
00302     
00303     // loop unrolled
00304     {
00305       g = 100.0*Math::abs(a.e(1,2));  
00306       if (i>3 && Math::abs(d.x)+g==Math::abs(d.x) && Math::abs(d.y)+g==Math::abs(d.y))
00307         a.e(1,2)=0.0;
00308       else if (Math::abs(a.e(1,2))>tresh)
00309         {
00310           h = d.y-d.x;
00311           if (Math::abs(h)+g == Math::abs(h)) 
00312             t=(a.e(1,2))/h;
00313           else {
00314             theta=0.5*h/(a.e(1,2));
00315             t=1.0/(Math::abs(theta)+Math::sqrt(1.0+theta*theta));
00316             if (theta < 0.0) t = -t;
00317           }
00318           c=1.0/Math::sqrt(1.0+t*t); s=t*c; tau=s/(1.0+c); h=t*a.e(1,2);
00319           z.x -= h; z.y += h; d.x -= h; d.y += h;
00320           a.e(1,2)=0.0;
00321           rotate(a,g,h,s,tau,1,3,2,3);
00322           rotate(v,g,h,s,tau,1,1,1,2);
00323           rotate(v,g,h,s,tau,2,1,2,2);
00324           rotate(v,g,h,s,tau,3,1,3,2); 
00325           nrot++;
00326         }
00327     }
00328     
00329     {
00330       g = 100.0*Math::abs(a.e(1,3));
00331       if (i>3 && Math::abs(d.x)+g==Math::abs(d.x) && Math::abs(d.z)+g==Math::abs(d.z))
00332         a.e(1,3)=0.0;
00333       else if (Math::abs(a.e(1,3))>tresh)
00334         {
00335           h = d.z-d.x;
00336           if (Math::abs(h)+g == Math::abs(h)) t=(a.e(1,3))/h;
00337           else
00338             {
00339               theta=0.5*h/(a.e(1,3));
00340               t=1.0/(Math::abs(theta)+Math::sqrt(1.0+theta*theta));
00341               if (theta < 0.0) t = -t;
00342             }
00343           c=1.0/Math::sqrt(1+t*t); s=t*c; tau=s/(1.0+c); h=t*a.e(1,3);
00344           z.x -= h; z.z += h; d.x -= h; d.z += h;
00345           a.e(1,3)=0.0;
00346           rotate(a,g,h,s,tau,1,2,2,3);
00347           rotate(v,g,h,s,tau,1,1,1,3);
00348           rotate(v,g,h,s,tau,2,1,2,3);
00349           rotate(v,g,h,s,tau,3,1,3,3); 
00350           nrot++;
00351         }
00352     }
00353     
00354     
00355     {
00356       g = 100.0*Math::abs(a.e(2,3));
00357       if (i>3 && Math::abs(d.y)+g==Math::abs(d.y) && Math::abs(d.z)+g==Math::abs(d.z))
00358         a.e(2,3)=0.0;
00359       else if (Math::abs(a.e(2,3))>tresh)
00360         {
00361           h = d.z-d.y;
00362           if (Math::abs(h)+g == Math::abs(h)) t=(a.e(2,3))/h;
00363           else
00364             {
00365               theta=0.5*h/(a.e(2,3));
00366               t=1.0/(Math::abs(theta)+Math::sqrt(1.0+theta*theta));
00367               if (theta < 0.0) t = -t;
00368             }
00369           c=1.0/Math::sqrt(1+t*t); s=t*c; tau=s/(1.0+c); h=t*a.e(2,3);
00370           z.y -= h; z.z += h; d.y -= h; d.z += h;
00371           a.e(2,3)=0.0;
00372           rotate(a,g,h,s,tau,1,2,1,3); 
00373           rotate(v,g,h,s,tau,1,2,1,3); 
00374           rotate(v,g,h,s,tau,2,2,2,3);
00375           rotate(v,g,h,s,tau,3,2,3,3); 
00376           nrot++;
00377         }
00378     }
00379     
00380     b += z; d = b; z.setZero();
00381     
00382   } // for i
00383   
00384   return i;
00385 }
00386 
00387 
00388 void Matrix3::serialize(Serializer& s)
00389 {
00390   for(Int i=0; i<9; i++) 
00391     s(m[i]);
00392 }
00393 
00394 
00395 
00396 // output
00397 ostream& base::operator<<(ostream& out, const Matrix3& m)
00398 {
00399   return out << m.e(1,1) << " " << m.e(1,2) << " " << m.e(1,3) << std::endl
00400              << m.e(2,1) << " " << m.e(2,2) << " " << m.e(2,3) << std::endl
00401              << m.e(3,1) << " " << m.e(3,2) << " " << m.e(3,3) << std::endl;
00402 }
00403 
00404 
00405 
00406 
00407 
00408 
00409 

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