00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef RTC_SMAT_H
00020 #define RTC_SMAT_H
00021
00022
00023 #include "rtc/rtcMath.h"
00024 #include "rtc/rtcVec.h"
00025 #include "rtc/rtcMat.h"
00026
00027
00028 namespace rtc {
00029
00030
00031 template <class T, int M> class Vec;
00032 template <class T, int M, int N> class Mat;
00033 template <class T, int M> class SMat;
00034
00041 template <class T, int M>
00042 class SMat: public Mat<T,M,M> {
00043 public:
00044
00045 using Mat<T,M,M>::x;
00046 using Mat<T,M,M>::set;
00047
00048
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
00056 template <class U> SMat(const Mat<U,M,M>& m);
00057
00058
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
00065 Vec<T,M> getDiag();
00066
00067
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
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
00085
00086
00087
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
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
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
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
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
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 }
00411
00412 #endif // RTC_SMAT_H defined
00413