00001 #ifndef SimTK_SIMMATRIX_SMALLMATRIX_SYMMAT_H_
00002 #define SimTK_SIMMATRIX_SMALLMATRIX_SYMMAT_H_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00074 #include "SimTKcommon/internal/common.h"
00075
00076 namespace SimTK {
00077
00079 template <int M, class ELT, int RS> class SymMat {
00080 typedef ELT E;
00081 typedef typename CNT<E>::TNeg ENeg;
00082 typedef typename CNT<E>::TWithoutNegator EWithoutNegator;
00083 typedef typename CNT<E>::TReal EReal;
00084 typedef typename CNT<E>::TImag EImag;
00085 typedef typename CNT<E>::TComplex EComplex;
00086 typedef typename CNT<E>::THerm EHerm;
00087 typedef typename CNT<E>::TPosTrans EPosTrans;
00088 typedef typename CNT<E>::TSqHermT ESqHermT;
00089 typedef typename CNT<E>::TSqTHerm ESqTHerm;
00090
00091 typedef typename CNT<E>::TSqrt ESqrt;
00092 typedef typename CNT<E>::TAbs EAbs;
00093 typedef typename CNT<E>::TStandard EStandard;
00094 typedef typename CNT<E>::TInvert EInvert;
00095 typedef typename CNT<E>::TNormalize ENormalize;
00096
00097 typedef typename CNT<E>::Scalar EScalar;
00098 typedef typename CNT<E>::ULessScalar EULessScalar;
00099 typedef typename CNT<E>::Number ENumber;
00100 typedef typename CNT<E>::StdNumber EStdNumber;
00101 typedef typename CNT<E>::Precision EPrecision;
00102 typedef typename CNT<E>::ScalarNormSq EScalarNormSq;
00103
00104 public:
00105
00106 enum {
00107 NRows = M,
00108 NCols = M,
00109 NDiagElements = M,
00110 NLowerElements = (M*(M-1))/2,
00111 NPackedElements = NDiagElements+NLowerElements,
00112 NActualElements = RS * NPackedElements,
00113 NActualScalars = CNT<E>::NActualScalars * NActualElements,
00114 RowSpacing = RS,
00115 ColSpacing = NActualElements,
00116 ImagOffset = NTraits<ENumber>::ImagOffset,
00117 RealStrideFactor = 1,
00118
00119 ArgDepth = ((int)CNT<E>::ArgDepth < (int)MAX_RESOLVED_DEPTH
00120 ? CNT<E>::ArgDepth + 1
00121 : MAX_RESOLVED_DEPTH),
00122 IsScalar = 0,
00123 IsULessScalar = 0,
00124 IsNumber = 0,
00125 IsStdNumber = 0,
00126 IsPrecision = 0,
00127 SignInterpretation = CNT<E>::SignInterpretation
00128 };
00129
00130 typedef SymMat<M,E,RS> T;
00131 typedef SymMat<M,ENeg,RS> TNeg;
00132 typedef SymMat<M,EWithoutNegator,RS> TWithoutNegator;
00133
00134 typedef SymMat<M,EReal,RS*CNT<E>::RealStrideFactor>
00135 TReal;
00136 typedef SymMat<M,EImag,RS*CNT<E>::RealStrideFactor>
00137 TImag;
00138 typedef SymMat<M,EComplex,RS> TComplex;
00139 typedef T THerm;
00140 typedef SymMat<M,EHerm,RS> TPosTrans;
00141 typedef E TElement;
00142 typedef Vec<M,E,RS> TDiag;
00143 typedef Vec<(M*(M-1))/2,E,RS> TLower;
00144 typedef Vec<(M*(M-1))/2,EHerm,RS> TUpper;
00145 typedef Vec<(M*(M+1))/2,E,RS> TAsVec;
00146
00147
00148
00149 typedef Row<M,E,1> TRow;
00150 typedef Vec<M,E,1> TCol;
00151 typedef SymMat<M,ESqrt,1> TSqrt;
00152 typedef SymMat<M,EAbs,1> TAbs;
00153 typedef SymMat<M,EStandard,1> TStandard;
00154 typedef SymMat<M,EInvert,1> TInvert;
00155 typedef SymMat<M,ENormalize,1> TNormalize;
00156 typedef SymMat<M,ESqHermT,1> TSqHermT;
00157 typedef SymMat<M,ESqTHerm,1> TSqTHerm;
00158 typedef SymMat<M,E,1> TPacked;
00159
00160 typedef EScalar Scalar;
00161 typedef EULessScalar ULessScalar;
00162 typedef ENumber Number;
00163 typedef EStdNumber StdNumber;
00164 typedef EPrecision Precision;
00165 typedef EScalarNormSq ScalarNormSq;
00166
00167 int size() const { return (M*(M+1))/2; }
00168 int nrow() const { return M; }
00169 int ncol() const { return M; }
00170
00171
00172
00173 ScalarNormSq scalarNormSqr() const {
00174 return getDiag().scalarNormSqr() + 2.*getLower().scalarNormSqr();
00175 }
00176
00177
00178
00179
00180 TSqrt sqrt() const {
00181 return TSqrt(getAsVec().sqrt());
00182 }
00183
00184
00185
00186
00187 TAbs abs() const {
00188 return TAbs(getAsVec().abs());
00189 }
00190
00191 TStandard standardize() const {
00192 return TStandard(getAsVec().standardize());
00193 }
00194
00195 EStandard trace() const {return getDiag().sum();}
00196
00197
00198
00199
00200 template <class P> struct EltResult {
00201 typedef SymMat<M, typename CNT<E>::template Result<P>::Mul, 1> Mul;
00202 typedef SymMat<M, typename CNT<E>::template Result<P>::Dvd, 1> Dvd;
00203 typedef SymMat<M, typename CNT<E>::template Result<P>::Add, 1> Add;
00204 typedef SymMat<M, typename CNT<E>::template Result<P>::Sub, 1> Sub;
00205 };
00206
00207
00208
00209 template <class P> struct Result {
00210 typedef MulCNTs<M,M,ArgDepth,SymMat,ColSpacing,RowSpacing,
00211 CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00212 P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> MulOp;
00213 typedef typename MulOp::Type Mul;
00214
00215 typedef MulCNTsNonConforming<M,M,ArgDepth,SymMat,ColSpacing,RowSpacing,
00216 CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00217 P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> MulOpNonConforming;
00218 typedef typename MulOpNonConforming::Type MulNon;
00219
00220
00221 typedef DvdCNTs<M,M,ArgDepth,SymMat,ColSpacing,RowSpacing,
00222 CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00223 P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> DvdOp;
00224 typedef typename DvdOp::Type Dvd;
00225
00226 typedef AddCNTs<M,M,ArgDepth,SymMat,ColSpacing,RowSpacing,
00227 CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00228 P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> AddOp;
00229 typedef typename AddOp::Type Add;
00230
00231 typedef SubCNTs<M,M,ArgDepth,SymMat,ColSpacing,RowSpacing,
00232 CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00233 P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> SubOp;
00234 typedef typename SubOp::Type Sub;
00235 };
00236
00237
00238 template <class P> struct Substitute {
00239 typedef SymMat<M,P> Type;
00240 };
00241
00244 SymMat(){
00245 #ifndef NDEBUG
00246 setToNaN();
00247 #endif
00248 }
00249
00251 SymMat(const SymMat& src) {
00252 updAsVec() = src.getAsVec();
00253 }
00254
00256 SymMat& operator=(const SymMat& src) {
00257 updAsVec() = src.getAsVec();
00258 return *this;
00259 }
00260
00271 template <class EE, int CSS, int RSS>
00272 explicit SymMat(const Mat<M,M,EE,CSS,RSS>& m)
00273 { setFromSymmetric(m); }
00274
00278 template <class EE, int CSS, int RSS>
00279 SymMat& setFromLower(const Mat<M,M,EE,CSS,RSS>& m) {
00280 this->updDiag() = m.diag().real();
00281 for (int j=0; j<M; ++j)
00282 for (int i=j+1; i<M; ++i)
00283 this->updEltLower(i,j) = m(i,j);
00284 return *this;
00285 }
00286
00294 template <class EE, int CSS, int RSS>
00295 SymMat& setFromUpper(const Mat<M,M,EE,CSS,RSS>& m) {
00296 this->updDiag() = m.diag().real();
00297 for (int j=0; j<M; ++j)
00298 for (int i=j+1; i<M; ++i)
00299 this->updEltLower(i,j) = m(j,i);
00300 return *this;
00301 }
00302
00308 template <class EE, int CSS, int RSS>
00309 SymMat& setFromSymmetric(const Mat<M,M,EE,CSS,RSS>& m) {
00310 SimTK_ERRCHK1(m.isNumericallySymmetric(), "SymMat::setFromSymmetric()",
00311 "The allegedly symmetric source matrix was not symmetric to within "
00312 "a tolerance of %g.", m.getDefaultTolerance());
00313 this->updDiag() = m.diag().real();
00314 for (int j=0; j<M; ++j)
00315 for (int i=j+1; i<M; ++i)
00316 this->updEltLower(i,j) =
00317 (m(i,j) + CNT<EE>::transpose(m(j,i)))/2;
00318 return *this;
00319 }
00320
00323 template <int RSS> SymMat(const SymMat<M,E,RSS>& src)
00324 { updAsVec() = src.getAsVec(); }
00325
00328 template <int RSS> SymMat(const SymMat<M,ENeg,RSS>& src)
00329 { updAsVec() = src.getAsVec(); }
00330
00334 template <class EE, int RSS> explicit SymMat(const SymMat<M,EE,RSS>& src)
00335 { updAsVec() = src.getAsVec(); }
00336
00337
00338
00339 explicit SymMat(const E& e) {
00340 updDiag() = CNT<E>::real(e);
00341 for (int i=0; i < NLowerElements; ++i) updlowerE(i) = E(0);
00342 }
00343
00344
00345
00346 explicit SymMat(const ENeg& e) {
00347 updDiag() = CNT<ENeg>::real(e);
00348 for (int i=0; i < NLowerElements; ++i) updlowerE(i) = E(0);
00349 }
00350
00351
00352
00353 explicit SymMat(int i)
00354 { new (this) SymMat(E(Precision(i))); }
00355
00369
00370 SymMat(const E& e0,
00371 const E& e1,const E& e2)
00372 { assert(M==2); TDiag& d=updDiag(); TLower& l=updLower();
00373 d[0]=CNT<E>::real(e0); d[1]=CNT<E>::real(e2);
00374 l[0]=e1; }
00375
00376 SymMat(const E& e0,
00377 const E& e1,const E& e2,
00378 const E& e3,const E& e4, const E& e5)
00379 { assert(M==3); TDiag& d=updDiag(); TLower& l=updLower();
00380 d[0]=CNT<E>::real(e0);d[1]=CNT<E>::real(e2);d[2]=CNT<E>::real(e5);
00381 l[0]=e1;l[1]=e3;
00382 l[2]=e4; }
00383
00384 SymMat(const E& e0,
00385 const E& e1,const E& e2,
00386 const E& e3,const E& e4, const E& e5,
00387 const E& e6,const E& e7, const E& e8, const E& e9)
00388 { assert(M==4); TDiag& d=updDiag(); TLower& l=updLower();
00389 d[0]=CNT<E>::real(e0);d[1]=CNT<E>::real(e2);d[2]=CNT<E>::real(e5);d[3]=CNT<E>::real(e9);
00390 l[0]=e1;l[1]=e3;l[2]=e6;
00391 l[3]=e4;l[4]=e7;
00392 l[5]=e8; }
00393
00394 SymMat(const E& e0,
00395 const E& e1, const E& e2,
00396 const E& e3, const E& e4, const E& e5,
00397 const E& e6, const E& e7, const E& e8, const E& e9,
00398 const E& e10,const E& e11, const E& e12, const E& e13, const E& e14)
00399 { assert(M==5); TDiag& d=updDiag(); TLower& l=updLower();
00400 d[0]=CNT<E>::real(e0);d[1]=CNT<E>::real(e2);d[2]=CNT<E>::real(e5);d[3]=CNT<E>::real(e9);d[4]=CNT<E>::real(e14);
00401 l[0]=e1;l[1]=e3;l[2]=e6;l[3]=e10;
00402 l[4]=e4;l[5]=e7;l[6]=e11;
00403 l[7]=e8;l[8]=e12;
00404 l[9]=e13; }
00405
00406 SymMat(const E& e0,
00407 const E& e1, const E& e2,
00408 const E& e3, const E& e4, const E& e5,
00409 const E& e6, const E& e7, const E& e8, const E& e9,
00410 const E& e10,const E& e11, const E& e12, const E& e13, const E& e14,
00411 const E& e15,const E& e16, const E& e17, const E& e18, const E& e19, const E& e20)
00412 { assert(M==6); TDiag& d=updDiag(); TLower& l=updLower();
00413 d[0]=CNT<E>::real(e0);d[1]=CNT<E>::real(e2);d[2]=CNT<E>::real(e5);
00414 d[3]=CNT<E>::real(e9);d[4]=CNT<E>::real(e14);d[5]=CNT<E>::real(e20);
00415 l[0] =e1; l[1] =e3; l[2] =e6; l[3]=e10; l[4]=e15;
00416 l[5] =e4; l[6] =e7; l[7] =e11; l[8]=e16;
00417 l[9] =e8; l[10]=e12;l[11]=e17;
00418 l[12]=e13;l[13]=e18;
00419 l[14]=e19; }
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 template <class EE> explicit SymMat(const EE* p) {
00436 assert(p);
00437 for (int i=0; i<M; ++i) {
00438 const int rowStart = (i*(i+1))/2;
00439 updDiag()[i] = CNT<EE>::real(p[rowStart + i]);
00440 for (int j=0; j<i; ++j)
00441 updEltLower(i,j) = p[rowStart + j];
00442 }
00443 }
00444
00445
00446
00447 template <class EE> SymMat& operator=(const EE* p) {
00448 assert(p);
00449 for (int i=0; i<M; ++i) {
00450 const int rowStart = (i*(i+1))/2;
00451 updDiag()[i] = CNT<EE>::real(p[rowStart + i]);
00452 for (int j=0; j<i; ++j)
00453 updEltLower(i,j) = p[rowStart + j];
00454 }
00455 return *this;
00456 }
00457
00458
00459
00460
00461 template <class EE, int RSS> SymMat& operator=(const SymMat<M,EE,RSS>& mm) {
00462 updAsVec() = mm.getAsVec();
00463 return *this;
00464 }
00465
00466
00467
00468 template <class EE, int RSS> SymMat&
00469 operator+=(const SymMat<M,EE,RSS>& mm) {
00470 updAsVec() += mm.getAsVec();
00471 return *this;
00472 }
00473 template <class EE, int RSS> SymMat&
00474 operator+=(const SymMat<M,negator<EE>,RSS>& mm) {
00475 updAsVec() -= -mm.getAsVec();
00476 return *this;
00477 }
00478
00479 template <class EE, int RSS> SymMat&
00480 operator-=(const SymMat<M,EE,RSS>& mm) {
00481 updAsVec() -= mm.getAsVec();
00482 return *this;
00483 }
00484 template <class EE, int RSS> SymMat&
00485 operator-=(const SymMat<M,negator<EE>,RSS>& mm) {
00486 updAsVec() += -mm.getAsVec();
00487 return *this;
00488 }
00489
00490
00491
00492 template <class EE, int RSS> SymMat&
00493 operator*=(const SymMat<M,EE,RSS>& mm) {
00494 assert(false);
00495 return *this;
00496 }
00497
00498
00499
00500
00501
00502 template <class E2, int RS2>
00503 typename Result<SymMat<M,E2,RS2> >::Add
00504 conformingAdd(const SymMat<M,E2,RS2>& r) const {
00505 return typename Result<SymMat<M,E2,RS2> >::Add
00506 (getAsVec().conformingAdd(r.getAsVec()));
00507 }
00508
00509 template <class E2, int RS2>
00510 typename Result<SymMat<M,E2,RS2> >::Sub
00511 conformingSubtract(const SymMat<M,E2,RS2>& r) const {
00512 return typename Result<SymMat<M,E2,RS2> >::Sub
00513 (getAsVec().conformingSubtract(r.getAsVec()));
00514 }
00515
00516
00517
00518
00519 template <class E2, int RS2>
00520 typename Result<SymMat<M,E2,RS2> >::Mul
00521 conformingMultiply(const SymMat<M,E2,RS2>& s) const {
00522 typename Result<SymMat<M,E2,RS2> >::Mul result;
00523 for (int j=0;j<M;++j)
00524 for (int i=0;i<M;++i)
00525 result(i,j) = (*this)[i] * s(j);
00526 return result;
00527 }
00528
00529
00530
00531
00532 const E& operator()(int i,int j) const
00533 { return i==j ? getDiag()[i] : getEltLower(i,j); }
00534 E& operator()(int i,int j)
00535 { return i==j ? updDiag()[i] : updEltLower(i,j); }
00536
00537
00538
00539 TRow operator[](int i) const {return row(i);}
00540 TCol operator()(int j) const {return col(j);}
00541
00542
00543
00544 ScalarNormSq normSqr() const { return scalarNormSqr(); }
00545 typename CNT<ScalarNormSq>::TSqrt
00546 norm() const { return CNT<ScalarNormSq>::sqrt(scalarNormSqr()); }
00547
00559 TNormalize normalize() const {
00560 if (CNT<E>::IsScalar) {
00561 return castAwayNegatorIfAny() / (SignInterpretation*norm());
00562 } else {
00563 TNormalize elementwiseNormalized;
00564
00565 elementwiseNormalized.updAsVec() = getAsVec().normalize();
00566 return elementwiseNormalized;
00567 }
00568 }
00569
00570 TInvert invert() const {assert(false); return TInvert();}
00571
00572 const SymMat& operator+() const { return *this; }
00573 const TNeg& operator-() const { return negate(); }
00574 TNeg& operator-() { return updNegate(); }
00575 const THerm& operator~() const { return transpose(); }
00576 THerm& operator~() { return updTranspose(); }
00577
00578 const TNeg& negate() const { return *reinterpret_cast<const TNeg*>(this); }
00579 TNeg& updNegate() { return *reinterpret_cast<TNeg*>(this); }
00580
00581 const THerm& transpose() const { return *reinterpret_cast<const THerm*>(this); }
00582 THerm& updTranspose() { return *reinterpret_cast<THerm*>(this); }
00583
00584 const TPosTrans& positionalTranspose() const
00585 { return *reinterpret_cast<const TPosTrans*>(this); }
00586 TPosTrans& updPositionalTranspose()
00587 { return *reinterpret_cast<TPosTrans*>(this); }
00588
00589 const TReal& real() const { return *reinterpret_cast<const TReal*>(this); }
00590 TReal& real() { return *reinterpret_cast< TReal*>(this); }
00591
00592
00593 const TImag& imag() const {
00594 const int offs = ImagOffset;
00595 const EImag* p = reinterpret_cast<const EImag*>(this);
00596 return *reinterpret_cast<const TImag*>(p+offs);
00597 }
00598 TImag& imag() {
00599 const int offs = ImagOffset;
00600 EImag* p = reinterpret_cast<EImag*>(this);
00601 return *reinterpret_cast<TImag*>(p+offs);
00602 }
00603
00604 const TWithoutNegator& castAwayNegatorIfAny() const {return *reinterpret_cast<const TWithoutNegator*>(this);}
00605 TWithoutNegator& updCastAwayNegatorIfAny() {return *reinterpret_cast<TWithoutNegator*>(this);}
00606
00607
00608
00609
00610
00611
00612
00613
00614 template <class EE> SymMat<M, typename CNT<E>::template Result<EE>::Mul>
00615 scalarMultiply(const EE& e) const {
00616 SymMat<M, typename CNT<E>::template Result<EE>::Mul> result;
00617 result.updAsVec() = getAsVec().scalarMultiply(e);
00618 return result;
00619 }
00620 template <class EE> SymMat<M, typename CNT<EE>::template Result<E>::Mul>
00621 scalarMultiplyFromLeft(const EE& e) const {
00622 SymMat<M, typename CNT<EE>::template Result<E>::Mul> result;
00623 result.updAsVec() = getAsVec().scalarMultiplyFromLeft(e);
00624 return result;
00625 }
00626
00627
00628
00629 template <class EE> SymMat<M, typename CNT<E>::template Result<EE>::Dvd>
00630 scalarDivide(const EE& e) const {
00631 SymMat<M, typename CNT<E>::template Result<EE>::Dvd> result;
00632 result.updAsVec() = getAsVec().scalarDivide(e);
00633 return result;
00634 }
00635 template <class EE> SymMat<M, typename CNT<EE>::template Result<E>::Dvd>
00636 scalarDivideFromLeft(const EE& e) const {
00637 SymMat<M, typename CNT<EE>::template Result<E>::Dvd> result;
00638 result.updAsVec() = getAsVec().scalarDivideFromLeft(e);
00639 return result;
00640 }
00641
00642
00643 template <class EE> SymMat<M, typename CNT<E>::template Result<EE>::Add>
00644 scalarAdd(const EE& e) const {
00645 SymMat<M, typename CNT<E>::template Result<EE>::Add> result(*this);
00646 result.updDiag() += e;
00647 return result;
00648 }
00649
00650
00651 template <class EE> SymMat<M, typename CNT<E>::template Result<EE>::Sub>
00652 scalarSubtract(const EE& e) const {
00653 SymMat<M, typename CNT<E>::template Result<EE>::Sub> result(*this);
00654 result.diag() -= e;
00655 return result;
00656 }
00657
00658
00659 template <class EE> SymMat<M, typename CNT<EE>::template Result<E>::Sub>
00660 scalarSubtractFromLeft(const EE& e) const {
00661 SymMat<M, typename CNT<EE>::template Result<E>::Sub> result(-(*this));
00662 result.diag() += e;
00663 return result;
00664 }
00665
00666
00667
00668
00669 template <class EE> SymMat& operator =(const EE& e) {return scalarEq(e);}
00670 template <class EE> SymMat& operator+=(const EE& e) {return scalarPlusEq(e);}
00671 template <class EE> SymMat& operator-=(const EE& e) {return scalarMinusEq(e);}
00672 template <class EE> SymMat& operator*=(const EE& e) {return scalarTimesEq(e);}
00673 template <class EE> SymMat& operator/=(const EE& e) {return scalarDivideEq(e);}
00674
00675
00676
00677 template <class EE> SymMat& scalarEq(const EE& ee)
00678 { updDiag() = ee; updLower() = E(0); return *this; }
00679 template <class EE> SymMat& scalarPlusEq(const EE& ee)
00680 { updDiag() += ee; return *this; }
00681 template <class EE> SymMat& scalarMinusEq(const EE& ee)
00682 { updDiag() -= ee; return *this; }
00683
00684
00685 template <class EE> SymMat& scalarMinusEqFromLeft(const EE& ee)
00686 { updLower() *= E(-1); updDiag().scalarMinusEqFromLeft(ee); return *this; }
00687
00688 template <class EE> SymMat& scalarTimesEq(const EE& ee)
00689 { updAsVec() *= ee; return *this; }
00690 template <class EE> SymMat& scalarTimesEqFromLeft(const EE& ee)
00691 { updAsVec().scalarTimesEqFromLeft(ee); return *this; }
00692 template <class EE> SymMat& scalarDivideEq(const EE& ee)
00693 { updAsVec() /= ee; return *this; }
00694 template <class EE> SymMat& scalarDivideEqFromLeft(const EE& ee)
00695 { updAsVec().scalarDivideEqFromLeft(ee); return *this; }
00696
00697 void setToNaN() { updAsVec().setToNaN(); }
00698 void setToZero() { updAsVec().setToZero(); }
00699
00700
00701 static const SymMat& getAs(const ELT* p) {return *reinterpret_cast<const SymMat*>(p);}
00702 static SymMat& updAs(ELT* p) {return *reinterpret_cast<SymMat*>(p);}
00703
00704
00705 static TPacked getNaN() {
00706 return TPacked(CNT<typename TPacked::TDiag>::getNaN(),
00707 CNT<typename TPacked::TLower>::getNaN());
00708 }
00709
00711 bool isNaN() const {return getAsVec().isNaN();}
00712
00715 bool isInf() const {return getAsVec().isInf();}
00716
00718 bool isFinite() const {return getAsVec().isFinite();}
00719
00722 static double getDefaultTolerance() {return M*CNT<ELT>::getDefaultTolerance();}
00723
00726 template <class E2, int RS2>
00727 bool isNumericallyEqual(const SymMat<M,E2,RS2>& m, double tol) const {
00728 return getAsVec().isNumericallyEqual(m.getAsVec(), tol);
00729 }
00730
00734 template <class E2, int RS2>
00735 bool isNumericallyEqual(const SymMat<M,E2,RS2>& m) const {
00736 const double tol = std::max(getDefaultTolerance(),m.getDefaultTolerance());
00737 return isNumericallyEqual(m, tol);
00738 }
00739
00745 bool isNumericallyEqual
00746 (const ELT& e,
00747 double tol = getDefaultTolerance()) const
00748 {
00749 if (!diag().isNumericallyEqual(e, tol))
00750 return false;
00751 return getLower().isNumericallyEqual(ELT(0), tol);
00752 }
00753
00754
00755
00756
00757 TRow row(int i) const {
00758 SimTK_INDEXCHECK(i,M,"SymMat::row[i]");
00759 TRow rowi;
00760
00761 for (int j=0; j<i; ++j)
00762 rowi[j] = getEltLower(i,j);
00763 rowi[i] = getEltDiag(i);
00764 for (int j=i+1; j<M; ++j)
00765 rowi[j] = getEltUpper(i,j);
00766 return rowi;
00767 }
00768
00769 TCol col(int j) const {
00770 SimTK_INDEXCHECK(j,M,"SymMat::col(j)");
00771 TCol colj;
00772
00773 for (int i=0; i<j; ++i)
00774 colj[i] = getEltUpper(i,j);
00775 colj[j] = getEltDiag(j);
00776 for (int i=j+1; i<M; ++i)
00777 colj[i] = getEltLower(i,j);
00778 return colj;
00779 }
00780
00786 E elt(int i, int j) const {
00787 SimTK_INDEXCHECK(i,M,"SymMat::elt(i,j)");
00788 SimTK_INDEXCHECK(j,M,"SymMat::elt(i,j)");
00789 if (i>j) return getEltLower(i,j);
00790 else if (i==j) return getEltDiag(i);
00791 else return getEltUpper(i,j);
00792 }
00793
00794 const TDiag& getDiag() const {return TDiag::getAs(d);}
00795 TDiag& updDiag() {return TDiag::updAs(d);}
00796
00797
00798 const TDiag& diag() const {return getDiag();}
00799 TDiag& diag() {return updDiag();}
00800
00801 const TLower& getLower() const {return TLower::getAs(&d[M*RS]);}
00802 TLower& updLower() {return TLower::updAs(&d[M*RS]);}
00803
00804 const TUpper& getUpper() const {return reinterpret_cast<const TUpper&>(getLower());}
00805 TUpper& updUpper() {return reinterpret_cast< TUpper&>(updLower());}
00806
00807 const TAsVec& getAsVec() const {return TAsVec::getAs(d);}
00808 TAsVec& updAsVec() {return TAsVec::updAs(d);}
00809
00810 const E& getEltDiag(int i) const {return getDiag()[i];}
00811 E& updEltDiag(int i) {return updDiag()[i];}
00812
00813
00814 const E& getEltLower(int i, int j) const {return getLower()[lowerIx(i,j)];}
00815 E& updEltLower(int i, int j) {return updLower()[lowerIx(i,j)];}
00816
00817
00818 const EHerm& getEltUpper(int i, int j) const {return getUpper()[lowerIx(j,i)];}
00819 EHerm& updEltUpper(int i, int j) {return updUpper()[lowerIx(j,i)];}
00820
00821 TRow sum() const {
00822 TRow temp(~getDiag());
00823 for (int i = 1; i < M; ++i)
00824 for (int j = 0; j < i; ++j) {
00825 const E& value = getEltLower(i, j);;
00826 temp[i] += value;
00827 temp[j] += E(reinterpret_cast<const EHerm&>(value));
00828 }
00829 return temp;
00830 }
00831
00832 private:
00833 E d[NActualElements];
00834
00835
00836
00837 const E& getlowerE(int i) const {return d[(M+i)*RS];}
00838 E& updlowerE(int i) {return d[(M+i)*RS];}
00839
00840 SymMat(const TDiag& di, const TLower& low) {
00841 updDiag() = di; updLower() = low;
00842 }
00843
00844 explicit SymMat(const TAsVec& v) {
00845 TAsVec::updAs(d) = v;
00846 }
00847
00848
00849
00850 static int lowerIx(int i, int j) {
00851 assert(0 <= j && j < i && i < M);
00852 return (i-j-1) + j*(M-1) - (j*(j-1))/2;
00853 }
00854
00855 template <int MM, class EE, int RSS> friend class SymMat;
00856 };
00857
00859
00860
00862
00863
00864 template <int M, class E1, int S1, class E2, int S2> inline
00865 typename SymMat<M,E1,S1>::template Result< SymMat<M,E2,S2> >::Add
00866 operator+(const SymMat<M,E1,S1>& l, const SymMat<M,E2,S2>& r) {
00867 return SymMat<M,E1,S1>::template Result< SymMat<M,E2,S2> >
00868 ::AddOp::perform(l,r);
00869 }
00870
00871
00872 template <int M, class E1, int S1, class E2, int S2> inline
00873 typename SymMat<M,E1,S1>::template Result< SymMat<M,E2,S2> >::Sub
00874 operator-(const SymMat<M,E1,S1>& l, const SymMat<M,E2,S2>& r) {
00875 return SymMat<M,E1,S1>::template Result< SymMat<M,E2,S2> >
00876 ::SubOp::perform(l,r);
00877 }
00878
00879
00880
00881 template <int M, class E1, int S1, class E2, int S2> inline
00882 typename SymMat<M,E1,S1>::template Result< SymMat<M,E2,S2> >::Mul
00883 operator*(const SymMat<M,E1,S1>& l, const SymMat<M,E2,S2>& r) {
00884 return SymMat<M,E1,S1>::template Result< SymMat<M,E2,S2> >
00885 ::MulOp::perform(l,r);
00886 }
00887
00888
00889 template <int M, class E1, int S1, class E2, int S2> inline bool
00890 operator==(const SymMat<M,E1,S1>& l, const SymMat<M,E2,S2>& r) {
00891 return l.getAsVec() == r.getAsVec();
00892 }
00893
00894
00895 template <int M, class E1, int S1, class E2, int S2> inline bool
00896 operator!=(const SymMat<M,E1,S1>& l, const SymMat<M,E2,S2>& r) {return !(l==r);}
00897
00899
00901
00902
00903
00904
00905 template <int M, class E, int S> inline
00906 typename SymMat<M,E,S>::template Result<float>::Mul
00907 operator*(const SymMat<M,E,S>& l, const float& r)
00908 { return SymMat<M,E,S>::template Result<float>::MulOp::perform(l,r); }
00909 template <int M, class E, int S> inline
00910 typename SymMat<M,E,S>::template Result<float>::Mul
00911 operator*(const float& l, const SymMat<M,E,S>& r) {return r*l;}
00912
00913 template <int M, class E, int S> inline
00914 typename SymMat<M,E,S>::template Result<double>::Mul
00915 operator*(const SymMat<M,E,S>& l, const double& r)
00916 { return SymMat<M,E,S>::template Result<double>::MulOp::perform(l,r); }
00917 template <int M, class E, int S> inline
00918 typename SymMat<M,E,S>::template Result<double>::Mul
00919 operator*(const double& l, const SymMat<M,E,S>& r) {return r*l;}
00920
00921 template <int M, class E, int S> inline
00922 typename SymMat<M,E,S>::template Result<long double>::Mul
00923 operator*(const SymMat<M,E,S>& l, const long double& r)
00924 { return SymMat<M,E,S>::template Result<long double>::MulOp::perform(l,r); }
00925 template <int M, class E, int S> inline
00926 typename SymMat<M,E,S>::template Result<long double>::Mul
00927 operator*(const long double& l, const SymMat<M,E,S>& r) {return r*l;}
00928
00929
00930 template <int M, class E, int S> inline
00931 typename SymMat<M,E,S>::template Result<typename CNT<E>::Precision>::Mul
00932 operator*(const SymMat<M,E,S>& l, int r) {return l * (typename CNT<E>::Precision)r;}
00933 template <int M, class E, int S> inline
00934 typename SymMat<M,E,S>::template Result<typename CNT<E>::Precision>::Mul
00935 operator*(int l, const SymMat<M,E,S>& r) {return r * (typename CNT<E>::Precision)l;}
00936
00937
00938
00939
00940 template <int M, class E, int S, class R> inline
00941 typename SymMat<M,E,S>::template Result<std::complex<R> >::Mul
00942 operator*(const SymMat<M,E,S>& l, const std::complex<R>& r)
00943 { return SymMat<M,E,S>::template Result<std::complex<R> >::MulOp::perform(l,r); }
00944 template <int M, class E, int S, class R> inline
00945 typename SymMat<M,E,S>::template Result<std::complex<R> >::Mul
00946 operator*(const std::complex<R>& l, const SymMat<M,E,S>& r) {return r*l;}
00947
00948
00949 template <int M, class E, int S, class R> inline
00950 typename SymMat<M,E,S>::template Result<std::complex<R> >::Mul
00951 operator*(const SymMat<M,E,S>& l, const conjugate<R>& r) {return l*(std::complex<R>)r;}
00952 template <int M, class E, int S, class R> inline
00953 typename SymMat<M,E,S>::template Result<std::complex<R> >::Mul
00954 operator*(const conjugate<R>& l, const SymMat<M,E,S>& r) {return r*(std::complex<R>)l;}
00955
00956
00957 template <int M, class E, int S, class R> inline
00958 typename SymMat<M,E,S>::template Result<typename negator<R>::StdNumber>::Mul
00959 operator*(const SymMat<M,E,S>& l, const negator<R>& r) {return l * (typename negator<R>::StdNumber)(R)r;}
00960 template <int M, class E, int S, class R> inline
00961 typename SymMat<M,E,S>::template Result<typename negator<R>::StdNumber>::Mul
00962 operator*(const negator<R>& l, const SymMat<M,E,S>& r) {return r * (typename negator<R>::StdNumber)(R)l;}
00963
00964
00965
00966
00967
00968
00969
00970 template <int M, class E, int S> inline
00971 typename SymMat<M,E,S>::template Result<float>::Dvd
00972 operator/(const SymMat<M,E,S>& l, const float& r)
00973 { return SymMat<M,E,S>::template Result<float>::DvdOp::perform(l,r); }
00974 template <int M, class E, int S> inline
00975 typename CNT<float>::template Result<SymMat<M,E,S> >::Dvd
00976 operator/(const float& l, const SymMat<M,E,S>& r)
00977 { return CNT<float>::template Result<SymMat<M,E,S> >::DvdOp::perform(l,r); }
00978
00979 template <int M, class E, int S> inline
00980 typename SymMat<M,E,S>::template Result<double>::Dvd
00981 operator/(const SymMat<M,E,S>& l, const double& r)
00982 { return SymMat<M,E,S>::template Result<double>::DvdOp::perform(l,r); }
00983 template <int M, class E, int S> inline
00984 typename CNT<double>::template Result<SymMat<M,E,S> >::Dvd
00985 operator/(const double& l, const SymMat<M,E,S>& r)
00986 { return CNT<double>::template Result<SymMat<M,E,S> >::DvdOp::perform(l,r); }
00987
00988 template <int M, class E, int S> inline
00989 typename SymMat<M,E,S>::template Result<long double>::Dvd
00990 operator/(const SymMat<M,E,S>& l, const long double& r)
00991 { return SymMat<M,E,S>::template Result<long double>::DvdOp::perform(l,r); }
00992 template <int M, class E, int S> inline
00993 typename CNT<long double>::template Result<SymMat<M,E,S> >::Dvd
00994 operator/(const long double& l, const SymMat<M,E,S>& r)
00995 { return CNT<long double>::template Result<SymMat<M,E,S> >::DvdOp::perform(l,r); }
00996
00997
00998 template <int M, class E, int S> inline
00999 typename SymMat<M,E,S>::template Result<typename CNT<E>::Precision>::Dvd
01000 operator/(const SymMat<M,E,S>& l, int r) {return l / (typename CNT<E>::Precision)r;}
01001 template <int M, class E, int S> inline
01002 typename CNT<typename CNT<E>::Precision>::template Result<SymMat<M,E,S> >::Dvd
01003 operator/(int l, const SymMat<M,E,S>& r) {return (typename CNT<E>::Precision)l / r;}
01004
01005
01006
01007
01008
01009 template <int M, class E, int S, class R> inline
01010 typename SymMat<M,E,S>::template Result<std::complex<R> >::Dvd
01011 operator/(const SymMat<M,E,S>& l, const std::complex<R>& r)
01012 { return SymMat<M,E,S>::template Result<std::complex<R> >::DvdOp::perform(l,r); }
01013 template <int M, class E, int S, class R> inline
01014 typename CNT<std::complex<R> >::template Result<SymMat<M,E,S> >::Dvd
01015 operator/(const std::complex<R>& l, const SymMat<M,E,S>& r)
01016 { return CNT<std::complex<R> >::template Result<SymMat<M,E,S> >::DvdOp::perform(l,r); }
01017
01018
01019 template <int M, class E, int S, class R> inline
01020 typename SymMat<M,E,S>::template Result<std::complex<R> >::Dvd
01021 operator/(const SymMat<M,E,S>& l, const conjugate<R>& r) {return l/(std::complex<R>)r;}
01022 template <int M, class E, int S, class R> inline
01023 typename CNT<std::complex<R> >::template Result<SymMat<M,E,S> >::Dvd
01024 operator/(const conjugate<R>& l, const SymMat<M,E,S>& r) {return (std::complex<R>)l/r;}
01025
01026
01027 template <int M, class E, int S, class R> inline
01028 typename SymMat<M,E,S>::template Result<typename negator<R>::StdNumber>::Dvd
01029 operator/(const SymMat<M,E,S>& l, const negator<R>& r) {return l/(typename negator<R>::StdNumber)(R)r;}
01030 template <int M, class E, int S, class R> inline
01031 typename CNT<R>::template Result<SymMat<M,E,S> >::Dvd
01032 operator/(const negator<R>& l, const SymMat<M,E,S>& r) {return (typename negator<R>::StdNumber)(R)l/r;}
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042 template <int M, class E, int S> inline
01043 typename SymMat<M,E,S>::template Result<float>::Add
01044 operator+(const SymMat<M,E,S>& l, const float& r)
01045 { return SymMat<M,E,S>::template Result<float>::AddOp::perform(l,r); }
01046 template <int M, class E, int S> inline
01047 typename SymMat<M,E,S>::template Result<float>::Add
01048 operator+(const float& l, const SymMat<M,E,S>& r) {return r+l;}
01049
01050 template <int M, class E, int S> inline
01051 typename SymMat<M,E,S>::template Result<double>::Add
01052 operator+(const SymMat<M,E,S>& l, const double& r)
01053 { return SymMat<M,E,S>::template Result<double>::AddOp::perform(l,r); }
01054 template <int M, class E, int S> inline
01055 typename SymMat<M,E,S>::template Result<double>::Add
01056 operator+(const double& l, const SymMat<M,E,S>& r) {return r+l;}
01057
01058 template <int M, class E, int S> inline
01059 typename SymMat<M,E,S>::template Result<long double>::Add
01060 operator+(const SymMat<M,E,S>& l, const long double& r)
01061 { return SymMat<M,E,S>::template Result<long double>::AddOp::perform(l,r); }
01062 template <int M, class E, int S> inline
01063 typename SymMat<M,E,S>::template Result<long double>::Add
01064 operator+(const long double& l, const SymMat<M,E,S>& r) {return r+l;}
01065
01066
01067 template <int M, class E, int S> inline
01068 typename SymMat<M,E,S>::template Result<typename CNT<E>::Precision>::Add
01069 operator+(const SymMat<M,E,S>& l, int r) {return l + (typename CNT<E>::Precision)r;}
01070 template <int M, class E, int S> inline
01071 typename SymMat<M,E,S>::template Result<typename CNT<E>::Precision>::Add
01072 operator+(int l, const SymMat<M,E,S>& r) {return r + (typename CNT<E>::Precision)l;}
01073
01074
01075
01076
01077 template <int M, class E, int S, class R> inline
01078 typename SymMat<M,E,S>::template Result<std::complex<R> >::Add
01079 operator+(const SymMat<M,E,S>& l, const std::complex<R>& r)
01080 { return SymMat<M,E,S>::template Result<std::complex<R> >::AddOp::perform(l,r); }
01081 template <int M, class E, int S, class R> inline
01082 typename SymMat<M,E,S>::template Result<std::complex<R> >::Add
01083 operator+(const std::complex<R>& l, const SymMat<M,E,S>& r) {return r+l;}
01084
01085
01086 template <int M, class E, int S, class R> inline
01087 typename SymMat<M,E,S>::template Result<std::complex<R> >::Add
01088 operator+(const SymMat<M,E,S>& l, const conjugate<R>& r) {return l+(std::complex<R>)r;}
01089 template <int M, class E, int S, class R> inline
01090 typename SymMat<M,E,S>::template Result<std::complex<R> >::Add
01091 operator+(const conjugate<R>& l, const SymMat<M,E,S>& r) {return r+(std::complex<R>)l;}
01092
01093
01094 template <int M, class E, int S, class R> inline
01095 typename SymMat<M,E,S>::template Result<typename negator<R>::StdNumber>::Add
01096 operator+(const SymMat<M,E,S>& l, const negator<R>& r) {return l + (typename negator<R>::StdNumber)(R)r;}
01097 template <int M, class E, int S, class R> inline
01098 typename SymMat<M,E,S>::template Result<typename negator<R>::StdNumber>::Add
01099 operator+(const negator<R>& l, const SymMat<M,E,S>& r) {return r + (typename negator<R>::StdNumber)(R)l;}
01100
01101
01102
01103
01104 template <int M, class E, int S> inline
01105 typename SymMat<M,E,S>::template Result<float>::Sub
01106 operator-(const SymMat<M,E,S>& l, const float& r)
01107 { return SymMat<M,E,S>::template Result<float>::SubOp::perform(l,r); }
01108 template <int M, class E, int S> inline
01109 typename CNT<float>::template Result<SymMat<M,E,S> >::Sub
01110 operator-(const float& l, const SymMat<M,E,S>& r)
01111 { return CNT<float>::template Result<SymMat<M,E,S> >::SubOp::perform(l,r); }
01112
01113 template <int M, class E, int S> inline
01114 typename SymMat<M,E,S>::template Result<double>::Sub
01115 operator-(const SymMat<M,E,S>& l, const double& r)
01116 { return SymMat<M,E,S>::template Result<double>::SubOp::perform(l,r); }
01117 template <int M, class E, int S> inline
01118 typename CNT<double>::template Result<SymMat<M,E,S> >::Sub
01119 operator-(const double& l, const SymMat<M,E,S>& r)
01120 { return CNT<double>::template Result<SymMat<M,E,S> >::SubOp::perform(l,r); }
01121
01122 template <int M, class E, int S> inline
01123 typename SymMat<M,E,S>::template Result<long double>::Sub
01124 operator-(const SymMat<M,E,S>& l, const long double& r)
01125 { return SymMat<M,E,S>::template Result<long double>::SubOp::perform(l,r); }
01126 template <int M, class E, int S> inline
01127 typename CNT<long double>::template Result<SymMat<M,E,S> >::Sub
01128 operator-(const long double& l, const SymMat<M,E,S>& r)
01129 { return CNT<long double>::template Result<SymMat<M,E,S> >::SubOp::perform(l,r); }
01130
01131
01132 template <int M, class E, int S> inline
01133 typename SymMat<M,E,S>::template Result<typename CNT<E>::Precision>::Sub
01134 operator-(const SymMat<M,E,S>& l, int r) {return l - (typename CNT<E>::Precision)r;}
01135 template <int M, class E, int S> inline
01136 typename CNT<typename CNT<E>::Precision>::template Result<SymMat<M,E,S> >::Sub
01137 operator-(int l, const SymMat<M,E,S>& r) {return (typename CNT<E>::Precision)l - r;}
01138
01139
01140
01141
01142
01143 template <int M, class E, int S, class R> inline
01144 typename SymMat<M,E,S>::template Result<std::complex<R> >::Sub
01145 operator-(const SymMat<M,E,S>& l, const std::complex<R>& r)
01146 { return SymMat<M,E,S>::template Result<std::complex<R> >::SubOp::perform(l,r); }
01147 template <int M, class E, int S, class R> inline
01148 typename CNT<std::complex<R> >::template Result<SymMat<M,E,S> >::Sub
01149 operator-(const std::complex<R>& l, const SymMat<M,E,S>& r)
01150 { return CNT<std::complex<R> >::template Result<SymMat<M,E,S> >::SubOp::perform(l,r); }
01151
01152
01153 template <int M, class E, int S, class R> inline
01154 typename SymMat<M,E,S>::template Result<std::complex<R> >::Sub
01155 operator-(const SymMat<M,E,S>& l, const conjugate<R>& r) {return l-(std::complex<R>)r;}
01156 template <int M, class E, int S, class R> inline
01157 typename CNT<std::complex<R> >::template Result<SymMat<M,E,S> >::Sub
01158 operator-(const conjugate<R>& l, const SymMat<M,E,S>& r) {return (std::complex<R>)l-r;}
01159
01160
01161 template <int M, class E, int S, class R> inline
01162 typename SymMat<M,E,S>::template Result<typename negator<R>::StdNumber>::Sub
01163 operator-(const SymMat<M,E,S>& l, const negator<R>& r) {return l-(typename negator<R>::StdNumber)(R)r;}
01164 template <int M, class E, int S, class R> inline
01165 typename CNT<R>::template Result<SymMat<M,E,S> >::Sub
01166 operator-(const negator<R>& l, const SymMat<M,E,S>& r) {return (typename negator<R>::StdNumber)(R)l-r;}
01167
01168
01169
01170 template <int M, class E, int RS, class CHAR, class TRAITS> inline
01171 std::basic_ostream<CHAR,TRAITS>&
01172 operator<<(std::basic_ostream<CHAR,TRAITS>& o, const SymMat<M,E,RS>& m) {
01173 for (int i=0;i<M;++i) {
01174 o << std::endl << "[";
01175 for (int j=0; j<=i; ++j)
01176 o << (j>0?" ":"") << m(i,j);
01177 for (int j=i+1; j<M; ++j)
01178 o << " *";
01179 o << "]";
01180 }
01181 if (M) o << std::endl;
01182 return o;
01183 }
01184
01185 template <int M, class E, int RS, class CHAR, class TRAITS> inline
01186 std::basic_istream<CHAR,TRAITS>&
01187 operator>>(std::basic_istream<CHAR,TRAITS>& is, SymMat<M,E,RS>& m) {
01188
01189 assert(false);
01190 return is;
01191 }
01192
01193 }
01194
01195
01196 #endif //SimTK_SIMMATRIX_SMALLMATRIX_SYMMAT_H_