$search
00001 /* 00002 * Copyright (C) 2009 00003 * Robert Bosch LLC 00004 * Research and Technology Center North America 00005 * Palo Alto, California 00006 * 00007 * All rights reserved. 00008 * 00009 *------------------------------------------------------------------------------ 00010 * project ....: Autonomous Technologies 00011 * file .......: rtcSMat.h 00012 * authors ....: Benjamin Pitzer 00013 * organization: Robert Bosch LLC 00014 * creation ...: 08/16/2006 00015 * modified ...: $Date: 2009-01-21 18:19:16 -0800 (Wed, 21 Jan 2009) $ 00016 * changed by .: $Author: benjaminpitzer $ 00017 * revision ...: $Revision: 14 $ 00018 */ 00019 #ifndef RTC_SMAT_H 00020 #define RTC_SMAT_H 00021 00022 //== INCLUDES ================================================================== 00023 #include "rtc/rtcMath.h" 00024 #include "rtc/rtcVec.h" 00025 #include "rtc/rtcMat.h" 00026 00027 //== NAMESPACES ================================================================ 00028 namespace rtc { 00029 00030 // Forward declarations 00031 template <class T, int M> class Vec; // M-d vector 00032 template <class T, int M, int N> class Mat; // MxN Matrix 00033 template <class T, int M> class SMat; // MxM Square Matrix 00034 00041 template <class T, int M> 00042 class SMat: public Mat<T,M,M> { 00043 public: 00044 // Data 00045 using Mat<T,M,M>::x; 00046 using Mat<T,M,M>::set; 00047 00048 // Constructors 00049 SMat(); 00050 SMat(const T* d); 00051 SMat(const T diagVal); 00052 SMat(const Vec<T,M>& diagVec); 00053 SMat(const Mat<T,M,M>& m); 00054 00055 // Casting Operation 00056 template <class U> SMat(const Mat<U,M,M>& m); 00057 00058 // Mutators 00059 void setIdentity(); 00060 void setDiag(const T a); 00061 void setDiag(const Vec<T,M>& diagVec); 00062 SMat<T,M>& leftMultiply(const SMat<T,M>& m); 00063 00064 // Accessors 00065 Vec<T,M> getDiag(); 00066 00067 // Basic square matrix functions 00068 T trace() const; 00069 void transpose(); 00070 SMat<T,M-1> minorMat(const int ip, const int jp) const; 00071 T det() const; 00072 SMat<T,M> inverted() const; 00073 int invert(); 00074 00075 // Decompositions 00076 int luDecomp(Vec<int,M>& indx, T* d = NULL); 00077 void luSolve(const Vec<int,M>& indx, Vec<T,M>& b); 00078 int choleskyDecomp(); 00079 int choleskyDecomp(SMat<T,M>& r); 00080 void choleskySolve(Vec<T,M>& b); 00081 }; 00082 00083 //============================================================================== 00084 // SMat<T,M> 00085 //============================================================================== 00086 00087 // Constructors 00088 00091 template <class T, int M> 00092 inline SMat<T,M>::SMat() {} 00093 00097 template <class T, int M> 00098 inline SMat<T,M>::SMat(const T* d) : Mat<T,M,M>(d) {} 00099 00103 template <class T, int M> 00104 inline SMat<T,M>::SMat(const T diagVal) { 00105 set(T(0)); 00106 setDiag(diagVal); 00107 } 00108 00112 template <class T, int M> 00113 inline SMat<T,M>::SMat(const Vec<T,M>& diagVec) { 00114 set(T(0)); 00115 setDiag(diagVec); 00116 } 00117 00120 template <class T, int M> 00121 inline SMat<T,M>::SMat(const Mat<T,M,M>& m) : Mat<T,M,M>(m) {} 00122 00123 // Casting Operation 00124 00127 template <class T, int M> template <class U> 00128 inline SMat<T,M>::SMat(const Mat<U,M,M>& m) : Mat<T,M,M>(m) {} 00129 00130 // Mutators 00131 00135 template <class T, int M> 00136 inline void SMat<T,M>::setIdentity() { 00137 set(T(0)); 00138 setDiag(T(1)); 00139 } 00140 00144 template <class T, int M> 00145 inline void SMat<T,M>::setDiag(const T diagVal) { 00146 for (int i=0,k=0;i<M;i++,k+=(M+1)) 00147 x[k] = diagVal; 00148 } 00149 00154 template <class T, int M> 00155 inline void SMat<T,M>::setDiag(const Vec<T,M>& diagVec) { 00156 for (int i=0,k=0;i<M;i++,k+=(M+1)) 00157 x[k] = diagVec.x[i]; 00158 } 00159 00162 template <class T, int M> 00163 inline SMat<T,M>& SMat<T,M>::leftMultiply(const SMat<T,M>& m) { 00164 (*this) = m*(*this); 00165 return *this; 00166 } 00167 00168 // Accessors 00169 00173 template <class T, int M> 00174 inline Vec<T,M> SMat<T,M>::getDiag() { 00175 Vec<T,M> v; 00176 for (int i=0,k=0;i<M;i++,k+=(M+1)) v.x[i] = x[k]; 00177 return v; 00178 } 00179 00180 // Some basic square matrix functions 00181 00184 template <class T, int M> 00185 inline T SMat<T,M>::trace() const { 00186 T sum = T(0); 00187 for (int i=0,k=0;i<M;i++,k+=(M+1)) sum += x[k]; 00188 return sum; 00189 } 00190 00193 template <class T, int M> 00194 inline void SMat<T,M>::transpose() { 00195 for (int i=0;i<M;i++) for (int j=i+1;j<M;j++) rtc_swap(x[i*M+j],x[j*M+i]); 00196 } 00197 00200 template <class T, int M> 00201 inline SMat<T,M-1> SMat<T,M>::minorMat(const int ip, const int jp) const { 00202 #if MATMATH_CHECK_BOUNDS 00203 if (ip<0 || ip>M || jp<0 || jp>M) { 00204 std::stringstream ss; 00205 ss << "SMat<" << M << ">::minorMat(" << ip; 00206 ss << ", " << jp << "): index out of range\n"; 00207 ss << std::flush; 00208 throw Exception(ss.str()); 00209 } 00210 #endif 00211 SMat<T,M-1> m; 00212 for (int i=0,k=0;i<M;++i) if (i != ip) { 00213 for (int j=0,l=0;j<M;++j) if (j != jp) { 00214 m.x[k*(M-1)+l] = x[i*M+j]; 00215 ++l; 00216 } 00217 ++k; 00218 } 00219 return m; 00220 } 00221 00226 template <class T, int M> 00227 inline T SMat<T,M>::det() const { 00228 SMat<T,M> tmp(*this); 00229 Vec<int,M> indx; T d; 00230 tmp.luDecomp(indx,&d); 00231 return d*tmp.getDiag().prod(); 00232 } 00233 00237 template <class T, int M> 00238 inline SMat<T,M> SMat<T,M>::inverted() const { 00239 SMat<T,M> tmp(*this); 00240 Vec<int,M> indx; T d; 00241 if (tmp.luDecomp(indx,&d)) { 00242 throw Exception("SMat::inverted(): error, can't take the inverse of a singular matrix."); 00243 } 00244 SMat<T,M> inv; 00245 for (int i=0;i<M;i++) { 00246 Vec<T,M> col(T(0)); 00247 col(i) = T(1); 00248 tmp.luSolve(indx,col); 00249 inv.setCol(i,col); 00250 } 00251 return inv; 00252 } 00253 00257 template <class T, int M> 00258 inline int SMat<T,M>::invert() { 00259 SMat<T,M> tmp(*this); 00260 Vec<int,M> indx; T d; 00261 if (tmp.luDecomp(indx,&d)) 00262 throw Exception("SMat::invert(): error, can't take the inverse of a singular matrix."); 00263 00264 for (int i=0;i<M;i++) { 00265 Vec<T,M> col(T(0)); 00266 col(i) = T(1); 00267 tmp.luSolve(indx,col); 00268 this->setCol(i,col); 00269 } 00270 return 0; 00271 } 00272 00273 // Decomposition and Solve Routines (compliments of Numerical Recipes in C) 00274 00282 template <class T, int M> 00283 inline int SMat<T,M>::luDecomp(Vec<int,M>& indx, T* d) 00284 { 00285 int i,imax=0,j,k; 00286 T big,dum,sum,temp; 00287 Vec<T,M> vv; 00288 00289 if (d) *d=1.0; 00290 for (i=0;i<M;i++) { 00291 big=0.0; 00292 for (j=0;j<M;j++) if ((temp=fabs(x[i*M+j])) > big) big=temp; 00293 if (big == 0.0) return 1; 00294 vv(i)=T(1)/big; 00295 } 00296 for (j=0;j<M;j++) { 00297 for (i=0;i<j;i++) { 00298 sum=x[i*M+j]; 00299 for (k=0;k<i;k++) sum -= x[i*M+k]*x[k*M+j]; 00300 x[i*M+j]=sum; 00301 } 00302 big=0.0; 00303 for (i=j;i<M;i++) { 00304 sum=x[i*M+j]; 00305 for (k=0;k<j;k++) sum -= x[i*M+k]*x[k*M+j]; 00306 x[i*M+j]=sum; 00307 if ((dum=vv(i)*fabs(sum)) >= big) { 00308 big=dum; 00309 imax=i; 00310 } 00311 } 00312 if (j != imax) { 00313 for (k=0;k<M;k++) { 00314 dum=x[imax*M+k]; 00315 x[imax*M+k]=x[j*M+k]; 00316 x[j*M+k]=dum; 00317 } 00318 if (d) *d = -(*d); 00319 vv(imax)=vv(j); 00320 } 00321 indx.x[j]=imax; 00322 if (x[j*M+j] == 0.0) x[j*M+j] = T(1e-20); 00323 if (j != M-1) { 00324 dum=T(1)/(x[j*M+j]); 00325 for (i=j+1;i<M;i++) x[i*M+j] *= dum; 00326 } 00327 } 00328 return 0; 00329 } 00330 00337 template <class T, int M> 00338 inline void SMat<T,M>::luSolve(const Vec<int,M>& indx, Vec<T,M>& b) 00339 { 00340 int i,ii=-1,ip,j; 00341 float sum; 00342 for (i=0;i<M;i++) { 00343 ip=indx.x[i]; sum=b.x[ip]; b.x[ip]=b.x[i]; 00344 if (ii>=0) for (j=ii;j<i;j++) sum -= x[i*M+j]*b.x[j]; 00345 else if (sum) ii=i; 00346 b.x[i]=sum; 00347 } 00348 for (i=(M-1);i>=0;i--) { 00349 sum=b.x[i]; 00350 for (j=i+1;j<M;j++) sum -= x[i*M+j]*b.x[j]; 00351 b.x[i]=sum/x[i*M+i]; 00352 } 00353 } 00354 00360 template <class T, int M> 00361 inline int SMat<T,M>::choleskyDecomp() 00362 { 00363 T sum; T p[M]; 00364 for (int i=0;i<M;i++) for (int j=i,k;j<M;j++) { 00365 for (sum=x[i*M+j],k=i-1;k>=0;k--) sum -= x[i*M+k]*x[j*M+k]; 00366 if (i == j) { 00367 if (sum <= T(0)) return 1; 00368 p[i] = sqrt(double(sum)); 00369 } else x[j*M+i] = sum/p[i]; 00370 } 00371 for (int i=0;i<M;i++) x[i*M+i] = p[i]; 00372 return 0; 00373 } 00374 00378 template <class T, int M> 00379 inline int SMat<T,M>::choleskyDecomp(SMat<T,M>& r) 00380 { 00381 r.set(*this); 00382 r.choleskyDecomp(); 00383 for (int i=0;i<M-1;i++) 00384 for (int j=i+1;j<M;j++) 00385 r.x[i*M+j]=T(0); 00386 r.transpose(); 00387 return 0; 00388 } 00389 00395 template <class T, int M> 00396 inline void SMat<T,M>::choleskySolve(Vec<T,M>& b) 00397 { 00398 T sum; 00399 for (int i=0,k;i<M;i++) { 00400 for (sum=b.x[i],k=i-1;k>=0;k--) sum -= x[i*M+k]*b.x[k]; 00401 b.x[i] = sum/x[i*M+i]; 00402 } 00403 for (int i=M-1,k;i>=0;i--) { 00404 for (sum=b.x[i],k=i+1;k<M;k++) sum -= x[k*M+i]*b.x[k]; 00405 b.x[i] = sum/x[i*M+i]; 00406 } 00407 } 00408 00409 //============================================================================== 00410 } // namespace rtc 00411 //============================================================================== 00412 #endif // RTC_SMAT_H defined 00413 //==============================================================================