Simbody  3.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SymMat.h
Go to the documentation of this file.
1 #ifndef SimTK_SIMMATRIX_SMALLMATRIX_SYMMAT_H_
2 #define SimTK_SIMMATRIX_SMALLMATRIX_SYMMAT_H_
3 
4 /* -------------------------------------------------------------------------- *
5  * Simbody(tm): SimTKcommon *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from *
8  * Simbios, the NIH National Center for Physics-Based Simulation of *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11  * *
12  * Portions copyright (c) 2005-12 Stanford University and the Authors. *
13  * Authors: Michael Sherman *
14  * Contributors: *
15  * *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may *
17  * not use this file except in compliance with the License. You may obtain a *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
19  * *
20  * Unless required by applicable law or agreed to in writing, software *
21  * distributed under the License is distributed on an "AS IS" BASIS, *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
23  * See the License for the specific language governing permissions and *
24  * limitations under the License. *
25  * -------------------------------------------------------------------------- */
26 
67 
68 namespace SimTK {
69 
71 template <int M, class ELT, int RS> class SymMat {
72  typedef ELT E;
73  typedef typename CNT<E>::TNeg ENeg;
74  typedef typename CNT<E>::TWithoutNegator EWithoutNegator;
75  typedef typename CNT<E>::TReal EReal;
76  typedef typename CNT<E>::TImag EImag;
77  typedef typename CNT<E>::TComplex EComplex;
78  typedef typename CNT<E>::THerm EHerm;
79  typedef typename CNT<E>::TPosTrans EPosTrans;
80  typedef typename CNT<E>::TSqHermT ESqHermT;
81  typedef typename CNT<E>::TSqTHerm ESqTHerm;
82 
83  typedef typename CNT<E>::TSqrt ESqrt;
84  typedef typename CNT<E>::TAbs EAbs;
85  typedef typename CNT<E>::TStandard EStandard;
86  typedef typename CNT<E>::TInvert EInvert;
87  typedef typename CNT<E>::TNormalize ENormalize;
88 
89  typedef typename CNT<E>::Scalar EScalar;
90  typedef typename CNT<E>::ULessScalar EULessScalar;
91  typedef typename CNT<E>::Number ENumber;
92  typedef typename CNT<E>::StdNumber EStdNumber;
93  typedef typename CNT<E>::Precision EPrecision;
94  typedef typename CNT<E>::ScalarNormSq EScalarNormSq;
95 
96 public:
97 
98  enum {
99  NRows = M,
100  NCols = M,
102  NLowerElements = (M*(M-1))/2,
109  RealStrideFactor = 1, // composite types don't change size when
110  // cast from complex to real or imaginary
112  ? CNT<E>::ArgDepth + 1
114  IsScalar = 0,
116  IsNumber = 0,
120  };
121 
122  typedef SymMat<M,E,RS> T;
125 
131  typedef T THerm; // These two are opposite of what you might expect
133  typedef E TElement;
134  typedef Vec<M,E,RS> TDiag; // storage type for the diagonal elements
135  typedef Vec<(M*(M-1))/2,E,RS> TLower; // storage type for the below-diag elements
136  typedef Vec<(M*(M-1))/2,EHerm,RS> TUpper; // cast TLower to this for upper elements
137  typedef Vec<(M*(M+1))/2,E,RS> TAsVec; // the whole SymMat as a single Vec
138 
139  // These are the results of calculations, so are returned in new, packed
140  // memory. Be sure to refer to element types here which are also packed.
141  typedef Row<M,E,1> TRow; // packed since we have to copy
142  typedef Vec<M,E,1> TCol;
148  typedef SymMat<M,ESqHermT,1> TSqHermT; // ~Mat*Mat
149  typedef SymMat<M,ESqTHerm,1> TSqTHerm; // Mat*~Mat
150  typedef SymMat<M,E,1> TPacked; // no extra row spacing for new data
151 
152  typedef EScalar Scalar;
153  typedef EULessScalar ULessScalar;
154  typedef ENumber Number;
155  typedef EStdNumber StdNumber;
156  typedef EPrecision Precision;
157  typedef EScalarNormSq ScalarNormSq;
158 
159  static int size() { return (M*(M+1))/2; }
160  static int nrow() { return M; }
161  static int ncol() { return M; }
162 
163  // Scalar norm square is sum( squares of all scalars ). The off-diagonals
164  // come up twice.
165  ScalarNormSq scalarNormSqr() const {
166  return getDiag().scalarNormSqr() + 2.*getLower().scalarNormSqr();
167  }
168 
169  // sqrt() is elementwise square root; that is, the return value has the same
170  // dimension as this SymMat but with each element replaced by whatever it thinks
171  // its square root is.
172  TSqrt sqrt() const {
173  return TSqrt(getAsVec().sqrt());
174  }
175 
176  // abs() is elementwise absolute value; that is, the return value has the same
177  // dimension as this SymMat but with each element replaced by whatever it thinks
178  // its absolute value is.
179  TAbs abs() const {
180  return TAbs(getAsVec().abs());
181  }
182 
183  TStandard standardize() const {
184  return TStandard(getAsVec().standardize());
185  }
186 
187  EStandard trace() const {return getDiag().sum();}
188 
189  // This gives the resulting SymMat type when (m[i] op P) is applied to each element of m.
190  // It is a SymMat of dimension M, spacing 1, and element types which are the regular
191  // composite result of E op P. Typically P is a scalar type but it doesn't have to be.
192  template <class P> struct EltResult {
197  };
198 
199  // This is the composite result for m op P where P is some kind of appropriately shaped
200  // non-scalar type.
201  template <class P> struct Result {
202  typedef MulCNTs<M,M,ArgDepth,SymMat,ColSpacing,RowSpacing,
205  typedef typename MulOp::Type Mul;
206 
207  typedef MulCNTsNonConforming<M,M,ArgDepth,SymMat,ColSpacing,RowSpacing,
210  typedef typename MulOpNonConforming::Type MulNon;
211 
212 
213  typedef DvdCNTs<M,M,ArgDepth,SymMat,ColSpacing,RowSpacing,
216  typedef typename DvdOp::Type Dvd;
217 
218  typedef AddCNTs<M,M,ArgDepth,SymMat,ColSpacing,RowSpacing,
221  typedef typename AddOp::Type Add;
222 
223  typedef SubCNTs<M,M,ArgDepth,SymMat,ColSpacing,RowSpacing,
226  typedef typename SubOp::Type Sub;
227  };
228 
229  // Shape-preserving element substitution (always packed)
230  template <class P> struct Substitute {
231  typedef SymMat<M,P> Type;
232  };
233 
236  SymMat(){
237  #ifndef NDEBUG
238  setToNaN();
239  #endif
240  }
241 
243  SymMat(const SymMat& src) {
244  updAsVec() = src.getAsVec();
245  }
246 
248  SymMat& operator=(const SymMat& src) {
249  updAsVec() = src.getAsVec();
250  return *this;
251  }
252 
263  template <class EE, int CSS, int RSS>
264  explicit SymMat(const Mat<M,M,EE,CSS,RSS>& m)
265  { setFromSymmetric(m); }
266 
270  template <class EE, int CSS, int RSS>
272  this->updDiag() = m.diag().real();
273  for (int j=0; j<M; ++j)
274  for (int i=j+1; i<M; ++i)
275  this->updEltLower(i,j) = m(i,j);
276  return *this;
277  }
278 
286  template <class EE, int CSS, int RSS>
288  this->updDiag() = m.diag().real();
289  for (int j=0; j<M; ++j)
290  for (int i=j+1; i<M; ++i)
291  this->updEltLower(i,j) = m(j,i);
292  return *this;
293  }
294 
300  template <class EE, int CSS, int RSS>
302  SimTK_ERRCHK1(m.isNumericallySymmetric(), "SymMat::setFromSymmetric()",
303  "The allegedly symmetric source matrix was not symmetric to within "
304  "a tolerance of %g.", m.getDefaultTolerance());
305  this->updDiag() = m.diag().real();
306  for (int j=0; j<M; ++j)
307  for (int i=j+1; i<M; ++i)
308  this->updEltLower(i,j) =
309  (m(i,j) + CNT<EE>::transpose(m(j,i)))/2;
310  return *this;
311  }
312 
315  template <int RSS> SymMat(const SymMat<M,E,RSS>& src)
316  { updAsVec() = src.getAsVec(); }
317 
320  template <int RSS> SymMat(const SymMat<M,ENeg,RSS>& src)
321  { updAsVec() = src.getAsVec(); }
322 
326  template <class EE, int RSS> explicit SymMat(const SymMat<M,EE,RSS>& src)
327  { updAsVec() = src.getAsVec(); }
328 
329  // Construction using an element repeats that element on the diagonal
330  // but sets the rest of the matrix to zero.
331  explicit SymMat(const E& e) {
332  updDiag() = CNT<E>::real(e);
333  for (int i=0; i < NLowerElements; ++i) updlowerE(i) = E(0);
334  }
335 
336  // Construction using a negated element is just like construction from
337  // the element.
338  explicit SymMat(const ENeg& e) {
339  updDiag() = CNT<ENeg>::real(e);
340  for (int i=0; i < NLowerElements; ++i) updlowerE(i) = E(0);
341  }
342 
343  // Given an int, turn it into a suitable floating point number
344  // and then feed that to the above single-element constructor.
345  explicit SymMat(int i)
346  { new (this) SymMat(E(Precision(i))); }
347 
361 
362  SymMat(const E& e0,
363  const E& e1,const E& e2)
364  { assert(M==2); TDiag& d=updDiag(); TLower& l=updLower();
365  d[0]=CNT<E>::real(e0); d[1]=CNT<E>::real(e2);
366  l[0]=e1; }
367 
368  SymMat(const E& e0,
369  const E& e1,const E& e2,
370  const E& e3,const E& e4, const E& e5)
371  { assert(M==3); TDiag& d=updDiag(); TLower& l=updLower();
372  d[0]=CNT<E>::real(e0);d[1]=CNT<E>::real(e2);d[2]=CNT<E>::real(e5);
373  l[0]=e1;l[1]=e3;
374  l[2]=e4; }
375 
376  SymMat(const E& e0,
377  const E& e1,const E& e2,
378  const E& e3,const E& e4, const E& e5,
379  const E& e6,const E& e7, const E& e8, const E& e9)
380  { assert(M==4); TDiag& d=updDiag(); TLower& l=updLower();
381  d[0]=CNT<E>::real(e0);d[1]=CNT<E>::real(e2);d[2]=CNT<E>::real(e5);d[3]=CNT<E>::real(e9);
382  l[0]=e1;l[1]=e3;l[2]=e6;
383  l[3]=e4;l[4]=e7;
384  l[5]=e8; }
385 
386  SymMat(const E& e0,
387  const E& e1, const E& e2,
388  const E& e3, const E& e4, const E& e5,
389  const E& e6, const E& e7, const E& e8, const E& e9,
390  const E& e10,const E& e11, const E& e12, const E& e13, const E& e14)
391  { assert(M==5); TDiag& d=updDiag(); TLower& l=updLower();
392  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);
393  l[0]=e1;l[1]=e3;l[2]=e6;l[3]=e10;
394  l[4]=e4;l[5]=e7;l[6]=e11;
395  l[7]=e8;l[8]=e12;
396  l[9]=e13; }
397 
398  SymMat(const E& e0,
399  const E& e1, const E& e2,
400  const E& e3, const E& e4, const E& e5,
401  const E& e6, const E& e7, const E& e8, const E& e9,
402  const E& e10,const E& e11, const E& e12, const E& e13, const E& e14,
403  const E& e15,const E& e16, const E& e17, const E& e18, const E& e19, const E& e20)
404  { assert(M==6); TDiag& d=updDiag(); TLower& l=updLower();
405  d[0]=CNT<E>::real(e0);d[1]=CNT<E>::real(e2);d[2]=CNT<E>::real(e5);
406  d[3]=CNT<E>::real(e9);d[4]=CNT<E>::real(e14);d[5]=CNT<E>::real(e20);
407  l[0] =e1; l[1] =e3; l[2] =e6; l[3]=e10; l[4]=e15;
408  l[5] =e4; l[6] =e7; l[7] =e11; l[8]=e16;
409  l[9] =e8; l[10]=e12;l[11]=e17;
410  l[12]=e13;l[13]=e18;
411  l[14]=e19; }
412 
413  // Construction from a pointer to anything assumes we're pointing
414  // at a packed element list of the right length, providing the
415  // lower triangle in row order, so a b c d e f means
416  // a
417  // b c
418  // d e f
419  // g h i j
420  // This has to be mapped to our diagonal/lower layout, which in
421  // the above example will be:
422  // [a c f j][b d g e h i]
423  //
424  // In the input layout, the i'th row begins at element i(i+1)/2,
425  // so diagonals are at i(i+1)/2 + i, while lower
426  // elements (i,j; i>j) are at i(i+1)/2 + j.
427  template <class EE> explicit SymMat(const EE* p) {
428  assert(p);
429  for (int i=0; i<M; ++i) {
430  const int rowStart = (i*(i+1))/2;
431  updDiag()[i] = CNT<EE>::real(p[rowStart + i]);
432  for (int j=0; j<i; ++j)
433  updEltLower(i,j) = p[rowStart + j];
434  }
435  }
436 
437  // This is the same thing except as an assignment to pointer rather
438  // than a constructor from pointer.
439  template <class EE> SymMat& operator=(const EE* p) {
440  assert(p);
441  for (int i=0; i<M; ++i) {
442  const int rowStart = (i*(i+1))/2;
443  updDiag()[i] = CNT<EE>::real(p[rowStart + i]);
444  for (int j=0; j<i; ++j)
445  updEltLower(i,j) = p[rowStart + j];
446  }
447  return *this;
448  }
449 
450  // Assignment works similarly to copy -- if the lengths match,
451  // go element-by-element. Otherwise, zero and then copy to each
452  // diagonal element.
453  template <class EE, int RSS> SymMat& operator=(const SymMat<M,EE,RSS>& mm) {
454  updAsVec() = mm.getAsVec();
455  return *this;
456  }
457 
458 
459  // Conforming assignment ops
460  template <class EE, int RSS> SymMat&
462  updAsVec() += mm.getAsVec();
463  return *this;
464  }
465  template <class EE, int RSS> SymMat&
466  operator+=(const SymMat<M,negator<EE>,RSS>& mm) {
467  updAsVec() -= -mm.getAsVec(); // negation of negator is free
468  return *this;
469  }
470 
471  template <class EE, int RSS> SymMat&
473  updAsVec() -= mm.getAsVec();
474  return *this;
475  }
476  template <class EE, int RSS> SymMat&
477  operator-=(const SymMat<M,negator<EE>,RSS>& mm) {
478  updAsVec() += -mm.getAsVec(); // negation of negator is free
479  return *this;
480  }
481 
482  // In place matrix multiply can only be done when the RHS matrix is the same
483  // size and the elements are also *= compatible.
484  template <class EE, int RSS> SymMat&
486  assert(false); // TODO
487  return *this;
488  }
489 
490  // Conforming binary ops with 'this' on left, producing new packed result.
491  // Cases: sy=sy+-sy, m=sy+-m, m=sy*sy, m=sy*m, v=sy*v
492 
493  // sy= this + sy
494  template <class E2, int RS2>
495  typename Result<SymMat<M,E2,RS2> >::Add
496  conformingAdd(const SymMat<M,E2,RS2>& r) const {
497  return typename Result<SymMat<M,E2,RS2> >::Add
499  }
500  // m= this - m
501  template <class E2, int RS2>
502  typename Result<SymMat<M,E2,RS2> >::Sub
504  return typename Result<SymMat<M,E2,RS2> >::Sub
506  }
507 
508  // symmetric * symmetric produces a full result
509  // m= this * s
510  // TODO: this is not a good implementation
511  template <class E2, int RS2>
512  typename Result<SymMat<M,E2,RS2> >::Mul
514  typename Result<SymMat<M,E2,RS2> >::Mul result;
515  for (int j=0;j<M;++j)
516  for (int i=0;i<M;++i)
517  result(i,j) = (*this)[i] * s(j);
518  return result;
519  }
520 
521  // sy= this .* sy
522  template <class E2, int RS2>
523  typename EltResult<E2>::Mul
525  return typename EltResult<E2>::Mul
527  }
528 
529  // sy= this ./ sy
530  template <class E2, int RS2>
531  typename EltResult<E2>::Dvd
533  return typename EltResult<E2>::Dvd
535  }
536 
537  // TODO: need the rest of the SymMat operators
538 
539  // Must be i >= j.
540  const E& operator()(int i,int j) const
541  { return i==j ? getDiag()[i] : getEltLower(i,j); }
542  E& operator()(int i,int j)
543  { return i==j ? updDiag()[i] : updEltLower(i,j); }
544 
545  // These are slow for a symmetric matrix, requiring copying and
546  // possibly floating point operations for conjugation.
547  TRow operator[](int i) const {return row(i);}
548  TCol operator()(int j) const {return col(j);}
549 
550 
551  // This is the scalar Frobenius norm.
552  ScalarNormSq normSqr() const { return scalarNormSqr(); }
553  typename CNT<ScalarNormSq>::TSqrt
555 
567  TNormalize normalize() const {
568  if (CNT<E>::IsScalar) {
570  } else {
571  TNormalize elementwiseNormalized;
572  // punt to the equivalent Vec to get the elements normalized
573  elementwiseNormalized.updAsVec() = getAsVec().normalize();
574  return elementwiseNormalized;
575  }
576  }
577 
578  TInvert invert() const {assert(false); return TInvert();} // TODO default inversion
579 
580  const SymMat& operator+() const { return *this; }
581  const TNeg& operator-() const { return negate(); }
582  TNeg& operator-() { return updNegate(); }
583  const THerm& operator~() const { return transpose(); }
584  THerm& operator~() { return updTranspose(); }
585 
586  const TNeg& negate() const { return *reinterpret_cast<const TNeg*>(this); }
587  TNeg& updNegate() { return *reinterpret_cast<TNeg*>(this); }
588 
589  const THerm& transpose() const { return *reinterpret_cast<const THerm*>(this); }
590  THerm& updTranspose() { return *reinterpret_cast<THerm*>(this); }
591 
593  { return *reinterpret_cast<const TPosTrans*>(this); }
595  { return *reinterpret_cast<TPosTrans*>(this); }
596 
597  const TReal& real() const { return *reinterpret_cast<const TReal*>(this); }
598  TReal& real() { return *reinterpret_cast< TReal*>(this); }
599 
600  // Had to contort these routines to get them through VC++ 7.net
601  const TImag& imag() const {
602  const int offs = ImagOffset;
603  const EImag* p = reinterpret_cast<const EImag*>(this);
604  return *reinterpret_cast<const TImag*>(p+offs);
605  }
606  TImag& imag() {
607  const int offs = ImagOffset;
608  EImag* p = reinterpret_cast<EImag*>(this);
609  return *reinterpret_cast<TImag*>(p+offs);
610  }
611 
612  const TWithoutNegator& castAwayNegatorIfAny() const {return *reinterpret_cast<const TWithoutNegator*>(this);}
613  TWithoutNegator& updCastAwayNegatorIfAny() {return *reinterpret_cast<TWithoutNegator*>(this);}
614 
615  // These are elementwise binary operators, (this op ee) by default but (ee op this) if
616  // 'FromLeft' appears in the name. The result is a packed SymMat<M> but the element type
617  // may change. These are mostly used to implement global operators.
618  // We call these "scalar" operators but actually the "scalar" can be a composite type.
619 
620  //TODO: consider converting 'e' to Standard Numbers as precalculation and changing
621  // return type appropriately.
622  template <class EE> SymMat<M, typename CNT<E>::template Result<EE>::Mul>
623  scalarMultiply(const EE& e) const {
624  SymMat<M, typename CNT<E>::template Result<EE>::Mul> result;
625  result.updAsVec() = getAsVec().scalarMultiply(e);
626  return result;
627  }
628  template <class EE> SymMat<M, typename CNT<EE>::template Result<E>::Mul>
629  scalarMultiplyFromLeft(const EE& e) const {
630  SymMat<M, typename CNT<EE>::template Result<E>::Mul> result;
631  result.updAsVec() = getAsVec().scalarMultiplyFromLeft(e);
632  return result;
633  }
634 
635  // TODO: should precalculate and store 1/e, while converting to Standard Numbers. Note
636  // that return type should change appropriately.
637  template <class EE> SymMat<M, typename CNT<E>::template Result<EE>::Dvd>
638  scalarDivide(const EE& e) const {
639  SymMat<M, typename CNT<E>::template Result<EE>::Dvd> result;
640  result.updAsVec() = getAsVec().scalarDivide(e);
641  return result;
642  }
643  template <class EE> SymMat<M, typename CNT<EE>::template Result<E>::Dvd>
644  scalarDivideFromLeft(const EE& e) const {
645  SymMat<M, typename CNT<EE>::template Result<E>::Dvd> result;
646  result.updAsVec() = getAsVec().scalarDivideFromLeft(e);
647  return result;
648  }
649 
650  // Additive ops involving a scalar update only the diagonal
651  template <class EE> SymMat<M, typename CNT<E>::template Result<EE>::Add>
652  scalarAdd(const EE& e) const {
653  SymMat<M, typename CNT<E>::template Result<EE>::Add> result(*this);
654  result.updDiag() += e;
655  return result;
656  }
657  // Add is commutative, so no 'FromLeft'.
658 
659  template <class EE> SymMat<M, typename CNT<E>::template Result<EE>::Sub>
660  scalarSubtract(const EE& e) const {
661  SymMat<M, typename CNT<E>::template Result<EE>::Sub> result(*this);
662  result.diag() -= e;
663  return result;
664  }
665  // This is s-m; negate m and add s to diagonal
666  // TODO: Should do something clever with negation here.
667  template <class EE> SymMat<M, typename CNT<EE>::template Result<E>::Sub>
668  scalarSubtractFromLeft(const EE& e) const {
669  SymMat<M, typename CNT<EE>::template Result<E>::Sub> result(-(*this));
670  result.diag() += e;
671  return result;
672  }
673 
674  // Generic assignments for any element type not listed explicitly, including scalars.
675  // These are done repeatedly for each element and only work if the operation can
676  // be performed leaving the original element type.
677  template <class EE> SymMat& operator =(const EE& e) {return scalarEq(e);}
678  template <class EE> SymMat& operator+=(const EE& e) {return scalarPlusEq(e);}
679  template <class EE> SymMat& operator-=(const EE& e) {return scalarMinusEq(e);}
680  template <class EE> SymMat& operator*=(const EE& e) {return scalarTimesEq(e);}
681  template <class EE> SymMat& operator/=(const EE& e) {return scalarDivideEq(e);}
682 
683  // Generalized scalar assignment & computed assignment methods. These will work
684  // for any assignment-compatible element, not just scalars.
685  template <class EE> SymMat& scalarEq(const EE& ee)
686  { updDiag() = ee; updLower() = E(0); return *this; }
687  template <class EE> SymMat& scalarPlusEq(const EE& ee)
688  { updDiag() += ee; return *this; }
689  template <class EE> SymMat& scalarMinusEq(const EE& ee)
690  { updDiag() -= ee; return *this; }
691 
692  // this is m = s-m; negate off diagonal, do d=s-d for each diagonal element d
693  template <class EE> SymMat& scalarMinusEqFromLeft(const EE& ee)
694  { updLower() *= E(-1); updDiag().scalarMinusEqFromLeft(ee); return *this; }
695 
696  template <class EE> SymMat& scalarTimesEq(const EE& ee)
697  { updAsVec() *= ee; return *this; }
698  template <class EE> SymMat& scalarTimesEqFromLeft(const EE& ee)
699  { updAsVec().scalarTimesEqFromLeft(ee); return *this; }
700  template <class EE> SymMat& scalarDivideEq(const EE& ee)
701  { updAsVec() /= ee; return *this; }
702  template <class EE> SymMat& scalarDivideEqFromLeft(const EE& ee)
703  { updAsVec().scalarDivideEqFromLeft(ee); return *this; }
704 
705  void setToNaN() { updAsVec().setToNaN(); }
706  void setToZero() { updAsVec().setToZero(); }
707 
708  // These assume we are given a pointer to d[0] of a SymMat<M,E,RS> like this one.
709  static const SymMat& getAs(const ELT* p) {return *reinterpret_cast<const SymMat*>(p);}
710  static SymMat& updAs(ELT* p) {return *reinterpret_cast<SymMat*>(p);}
711 
712  // Note packed spacing
713  static TPacked getNaN() {
716  }
717 
719  bool isNaN() const {return getAsVec().isNaN();}
720 
723  bool isInf() const {return getAsVec().isInf();}
724 
726  bool isFinite() const {return getAsVec().isFinite();}
727 
731 
734  template <class E2, int RS2>
735  bool isNumericallyEqual(const SymMat<M,E2,RS2>& m, double tol) const {
736  return getAsVec().isNumericallyEqual(m.getAsVec(), tol);
737  }
738 
742  template <class E2, int RS2>
743  bool isNumericallyEqual(const SymMat<M,E2,RS2>& m) const {
744  const double tol = std::max(getDefaultTolerance(),m.getDefaultTolerance());
745  return isNumericallyEqual(m, tol);
746  }
747 
753  bool isNumericallyEqual
754  (const ELT& e,
755  double tol = getDefaultTolerance()) const
756  {
757  if (!diag().isNumericallyEqual(e, tol))
758  return false;
759  return getLower().isNumericallyEqual(ELT(0), tol);
760  }
761 
762  // Rows and columns have to be copied and Hermitian elements have to
763  // be conjugated at a floating point cost. This isn't the best way
764  // to work with a symmetric matrix.
765  TRow row(int i) const {
766  SimTK_INDEXCHECK(i,M,"SymMat::row[i]");
767  TRow rowi;
768  // Columns left of diagonal are lower.
769  for (int j=0; j<i; ++j)
770  rowi[j] = getEltLower(i,j);
771  rowi[i] = getEltDiag(i);
772  for (int j=i+1; j<M; ++j)
773  rowi[j] = getEltUpper(i,j); // conversion from EHerm to E may cost flops
774  return rowi;
775  }
776 
777  TCol col(int j) const {
778  SimTK_INDEXCHECK(j,M,"SymMat::col(j)");
779  TCol colj;
780  // Rows above diagonal are upper (with conjugated elements).
781  for (int i=0; i<j; ++i)
782  colj[i] = getEltUpper(i,j); // conversion from EHerm to E may cost flops
783  colj[j] = getEltDiag(j);
784  for (int i=j+1; i<M; ++i)
785  colj[i] = getEltLower(i,j);
786  return colj;
787  }
788 
794  E elt(int i, int j) const {
795  SimTK_INDEXCHECK(i,M,"SymMat::elt(i,j)");
796  SimTK_INDEXCHECK(j,M,"SymMat::elt(i,j)");
797  if (i>j) return getEltLower(i,j); // copy element
798  else if (i==j) return getEltDiag(i); // copy element
799  else return getEltUpper(i,j); // conversion from EHerm to E may cost flops
800  }
801 
802  const TDiag& getDiag() const {return TDiag::getAs(d);}
803  TDiag& updDiag() {return TDiag::updAs(d);}
804 
805  // Conventional synonym
806  const TDiag& diag() const {return getDiag();}
807  TDiag& diag() {return updDiag();}
808 
809  const TLower& getLower() const {return TLower::getAs(&d[M*RS]);}
810  TLower& updLower() {return TLower::updAs(&d[M*RS]);}
811 
812  const TUpper& getUpper() const {return reinterpret_cast<const TUpper&>(getLower());}
813  TUpper& updUpper() {return reinterpret_cast< TUpper&>(updLower());}
814 
815  const TAsVec& getAsVec() const {return TAsVec::getAs(d);}
816  TAsVec& updAsVec() {return TAsVec::updAs(d);}
817 
818  const E& getEltDiag(int i) const {return getDiag()[i];}
819  E& updEltDiag(int i) {return updDiag()[i];}
820 
821  // must be i > j
822  const E& getEltLower(int i, int j) const {return getLower()[lowerIx(i,j)];}
823  E& updEltLower(int i, int j) {return updLower()[lowerIx(i,j)];}
824 
825  // must be i < j
826  const EHerm& getEltUpper(int i, int j) const {return getUpper()[lowerIx(j,i)];}
827  EHerm& updEltUpper(int i, int j) {return updUpper()[lowerIx(j,i)];}
828 
830  TRow colSum() const {
831  TRow temp(~getDiag());
832  for (int i = 1; i < M; ++i)
833  for (int j = 0; j < i; ++j) {
834  const E& value = getEltLower(i, j);;
835  temp[j] += value;
836  temp[i] += E(reinterpret_cast<const EHerm&>(value));
837  }
838  return temp;
839  }
842  TRow sum() const {return colSum();}
843 
846  TCol rowSum() const {
847  TCol temp(getDiag());
848  for (int i = 1; i < M; ++i)
849  for (int j = 0; j < i; ++j) {
850  const E& value = getEltLower(i, j);;
851  temp[i] += value;
852  temp[j] += E(reinterpret_cast<const EHerm&>(value));
853  }
854  return temp;
855  }
856 private:
857  E d[NActualElements];
858 
859  // This utility doesn't turn lower or upper into a Vec which could turn
860  // out to have zero length if this is a 1x1 matrix.
861  const E& getlowerE(int i) const {return d[(M+i)*RS];}
862  E& updlowerE(int i) {return d[(M+i)*RS];}
863 
864  SymMat(const TDiag& di, const TLower& low) {
865  updDiag() = di; updLower() = low;
866  }
867 
868  explicit SymMat(const TAsVec& v) {
869  TAsVec::updAs(d) = v;
870  }
871 
872  // Convert i,j with i>j to an index in "lower". This also gives the
873  // right index for "upper" with i and j reversed.
874  static int lowerIx(int i, int j) {
875  assert(0 <= j && j < i && i < M);
876  return (i-j-1) + j*(M-1) - (j*(j-1))/2;
877  }
878 
879  template <int MM, class EE, int RSS> friend class SymMat;
880 };
881 
883 // Global operators involving two symmetric matrices. //
884 // sy=sy+sy, sy=sy-sy, m=sy*sy, sy==sy, sy!=sy //
886 
887 // m3 = m1 + m2 where all m's have the same dimension M.
888 template <int M, class E1, int S1, class E2, int S2> inline
889 typename SymMat<M,E1,S1>::template Result< SymMat<M,E2,S2> >::Add
891  return SymMat<M,E1,S1>::template Result< SymMat<M,E2,S2> >
892  ::AddOp::perform(l,r);
893 }
894 
895 // m3 = m1 - m2 where all m's have the same dimension M.
896 template <int M, class E1, int S1, class E2, int S2> inline
897 typename SymMat<M,E1,S1>::template Result< SymMat<M,E2,S2> >::Sub
899  return SymMat<M,E1,S1>::template Result< SymMat<M,E2,S2> >
900  ::SubOp::perform(l,r);
901 }
902 
903 // m3 = m1 * m2 where all m's have the same dimension M.
904 // The result will not be symmetric.
905 template <int M, class E1, int S1, class E2, int S2> inline
906 typename SymMat<M,E1,S1>::template Result< SymMat<M,E2,S2> >::Mul
908  return SymMat<M,E1,S1>::template Result< SymMat<M,E2,S2> >
909  ::MulOp::perform(l,r);
910 }
911 
912 // bool = m1 == m2, m1 and m2 have the same dimension M
913 template <int M, class E1, int S1, class E2, int S2> inline bool
915  return l.getAsVec() == r.getAsVec();
916 }
917 
918 // bool = m1 == m2, m1 and m2 have the same dimension M
919 template <int M, class E1, int S1, class E2, int S2> inline bool
920 operator!=(const SymMat<M,E1,S1>& l, const SymMat<M,E2,S2>& r) {return !(l==r);}
921 
923 // Global operators involving a SymMat and a scalar. //
925 
926 // SCALAR MULTIPLY
927 
928 // m = m*real, real*m
929 template <int M, class E, int S> inline
930 typename SymMat<M,E,S>::template Result<float>::Mul
931 operator*(const SymMat<M,E,S>& l, const float& r)
932  { return SymMat<M,E,S>::template Result<float>::MulOp::perform(l,r); }
933 template <int M, class E, int S> inline
934 typename SymMat<M,E,S>::template Result<float>::Mul
935 operator*(const float& l, const SymMat<M,E,S>& r) {return r*l;}
936 
937 template <int M, class E, int S> inline
938 typename SymMat<M,E,S>::template Result<double>::Mul
939 operator*(const SymMat<M,E,S>& l, const double& r)
940  { return SymMat<M,E,S>::template Result<double>::MulOp::perform(l,r); }
941 template <int M, class E, int S> inline
942 typename SymMat<M,E,S>::template Result<double>::Mul
943 operator*(const double& l, const SymMat<M,E,S>& r) {return r*l;}
944 
945 template <int M, class E, int S> inline
946 typename SymMat<M,E,S>::template Result<long double>::Mul
947 operator*(const SymMat<M,E,S>& l, const long double& r)
948  { return SymMat<M,E,S>::template Result<long double>::MulOp::perform(l,r); }
949 template <int M, class E, int S> inline
950 typename SymMat<M,E,S>::template Result<long double>::Mul
951 operator*(const long double& l, const SymMat<M,E,S>& r) {return r*l;}
952 
953 // m = m*int, int*m -- just convert int to m's precision float
954 template <int M, class E, int S> inline
955 typename SymMat<M,E,S>::template Result<typename CNT<E>::Precision>::Mul
956 operator*(const SymMat<M,E,S>& l, int r) {return l * (typename CNT<E>::Precision)r;}
957 template <int M, class E, int S> inline
958 typename SymMat<M,E,S>::template Result<typename CNT<E>::Precision>::Mul
959 operator*(int l, const SymMat<M,E,S>& r) {return r * (typename CNT<E>::Precision)l;}
960 
961 // Complex, conjugate, and negator are all easy to templatize.
962 
963 // m = m*complex, complex*m
964 template <int M, class E, int S, class R> inline
965 typename SymMat<M,E,S>::template Result<std::complex<R> >::Mul
966 operator*(const SymMat<M,E,S>& l, const std::complex<R>& r)
967  { return SymMat<M,E,S>::template Result<std::complex<R> >::MulOp::perform(l,r); }
968 template <int M, class E, int S, class R> inline
969 typename SymMat<M,E,S>::template Result<std::complex<R> >::Mul
970 operator*(const std::complex<R>& l, const SymMat<M,E,S>& r) {return r*l;}
971 
972 // m = m*conjugate, conjugate*m (convert conjugate->complex)
973 template <int M, class E, int S, class R> inline
974 typename SymMat<M,E,S>::template Result<std::complex<R> >::Mul
975 operator*(const SymMat<M,E,S>& l, const conjugate<R>& r) {return l*(std::complex<R>)r;}
976 template <int M, class E, int S, class R> inline
977 typename SymMat<M,E,S>::template Result<std::complex<R> >::Mul
978 operator*(const conjugate<R>& l, const SymMat<M,E,S>& r) {return r*(std::complex<R>)l;}
979 
980 // m = m*negator, negator*m: convert negator to standard number
981 template <int M, class E, int S, class R> inline
982 typename SymMat<M,E,S>::template Result<typename negator<R>::StdNumber>::Mul
983 operator*(const SymMat<M,E,S>& l, const negator<R>& r) {return l * (typename negator<R>::StdNumber)(R)r;}
984 template <int M, class E, int S, class R> inline
985 typename SymMat<M,E,S>::template Result<typename negator<R>::StdNumber>::Mul
986 operator*(const negator<R>& l, const SymMat<M,E,S>& r) {return r * (typename negator<R>::StdNumber)(R)l;}
987 
988 
989 // SCALAR DIVIDE. This is a scalar operation when the scalar is on the right,
990 // but when it is on the left it means scalar * pseudoInverse(mat), which is
991 // a similar symmetric matrix.
992 
993 // m = m/real, real/m
994 template <int M, class E, int S> inline
995 typename SymMat<M,E,S>::template Result<float>::Dvd
996 operator/(const SymMat<M,E,S>& l, const float& r)
997  { return SymMat<M,E,S>::template Result<float>::DvdOp::perform(l,r); }
998 template <int M, class E, int S> inline
999 typename CNT<float>::template Result<SymMat<M,E,S> >::Dvd
1000 operator/(const float& l, const SymMat<M,E,S>& r)
1001  { return CNT<float>::template Result<SymMat<M,E,S> >::DvdOp::perform(l,r); }
1002 
1003 template <int M, class E, int S> inline
1004 typename SymMat<M,E,S>::template Result<double>::Dvd
1005 operator/(const SymMat<M,E,S>& l, const double& r)
1006  { return SymMat<M,E,S>::template Result<double>::DvdOp::perform(l,r); }
1007 template <int M, class E, int S> inline
1008 typename CNT<double>::template Result<SymMat<M,E,S> >::Dvd
1009 operator/(const double& l, const SymMat<M,E,S>& r)
1010  { return CNT<double>::template Result<SymMat<M,E,S> >::DvdOp::perform(l,r); }
1011 
1012 template <int M, class E, int S> inline
1013 typename SymMat<M,E,S>::template Result<long double>::Dvd
1014 operator/(const SymMat<M,E,S>& l, const long double& r)
1015  { return SymMat<M,E,S>::template Result<long double>::DvdOp::perform(l,r); }
1016 template <int M, class E, int S> inline
1017 typename CNT<long double>::template Result<SymMat<M,E,S> >::Dvd
1018 operator/(const long double& l, const SymMat<M,E,S>& r)
1019  { return CNT<long double>::template Result<SymMat<M,E,S> >::DvdOp::perform(l,r); }
1020 
1021 // m = m/int, int/m -- just convert int to m's precision float
1022 template <int M, class E, int S> inline
1023 typename SymMat<M,E,S>::template Result<typename CNT<E>::Precision>::Dvd
1024 operator/(const SymMat<M,E,S>& l, int r) {return l / (typename CNT<E>::Precision)r;}
1025 template <int M, class E, int S> inline
1026 typename CNT<typename CNT<E>::Precision>::template Result<SymMat<M,E,S> >::Dvd
1027 operator/(int l, const SymMat<M,E,S>& r) {return (typename CNT<E>::Precision)l / r;}
1028 
1029 
1030 // Complex, conjugate, and negator are all easy to templatize.
1031 
1032 // m = m/complex, complex/m
1033 template <int M, class E, int S, class R> inline
1034 typename SymMat<M,E,S>::template Result<std::complex<R> >::Dvd
1035 operator/(const SymMat<M,E,S>& l, const std::complex<R>& r)
1036  { return SymMat<M,E,S>::template Result<std::complex<R> >::DvdOp::perform(l,r); }
1037 template <int M, class E, int S, class R> inline
1038 typename CNT<std::complex<R> >::template Result<SymMat<M,E,S> >::Dvd
1039 operator/(const std::complex<R>& l, const SymMat<M,E,S>& r)
1040  { return CNT<std::complex<R> >::template Result<SymMat<M,E,S> >::DvdOp::perform(l,r); }
1041 
1042 // m = m/conjugate, conjugate/m (convert conjugate->complex)
1043 template <int M, class E, int S, class R> inline
1044 typename SymMat<M,E,S>::template Result<std::complex<R> >::Dvd
1045 operator/(const SymMat<M,E,S>& l, const conjugate<R>& r) {return l/(std::complex<R>)r;}
1046 template <int M, class E, int S, class R> inline
1047 typename CNT<std::complex<R> >::template Result<SymMat<M,E,S> >::Dvd
1048 operator/(const conjugate<R>& l, const SymMat<M,E,S>& r) {return (std::complex<R>)l/r;}
1049 
1050 // m = m/negator, negator/m: convert negator to number
1051 template <int M, class E, int S, class R> inline
1052 typename SymMat<M,E,S>::template Result<typename negator<R>::StdNumber>::Dvd
1053 operator/(const SymMat<M,E,S>& l, const negator<R>& r) {return l/(typename negator<R>::StdNumber)(R)r;}
1054 template <int M, class E, int S, class R> inline
1055 typename CNT<R>::template Result<SymMat<M,E,S> >::Dvd
1056 operator/(const negator<R>& l, const SymMat<M,E,S>& r) {return (typename negator<R>::StdNumber)(R)l/r;}
1057 
1058 
1059 // Add and subtract are odd as scalar ops. They behave as though the
1060 // scalar stands for a conforming matrix whose diagonal elements are that,
1061 // scalar and then a normal matrix add or subtract is done.
1062 
1063 // SCALAR ADD
1064 
1065 // m = m+real, real+m
1066 template <int M, class E, int S> inline
1067 typename SymMat<M,E,S>::template Result<float>::Add
1068 operator+(const SymMat<M,E,S>& l, const float& r)
1069  { return SymMat<M,E,S>::template Result<float>::AddOp::perform(l,r); }
1070 template <int M, class E, int S> inline
1071 typename SymMat<M,E,S>::template Result<float>::Add
1072 operator+(const float& l, const SymMat<M,E,S>& r) {return r+l;}
1073 
1074 template <int M, class E, int S> inline
1075 typename SymMat<M,E,S>::template Result<double>::Add
1076 operator+(const SymMat<M,E,S>& l, const double& r)
1077  { return SymMat<M,E,S>::template Result<double>::AddOp::perform(l,r); }
1078 template <int M, class E, int S> inline
1079 typename SymMat<M,E,S>::template Result<double>::Add
1080 operator+(const double& l, const SymMat<M,E,S>& r) {return r+l;}
1081 
1082 template <int M, class E, int S> inline
1083 typename SymMat<M,E,S>::template Result<long double>::Add
1084 operator+(const SymMat<M,E,S>& l, const long double& r)
1085  { return SymMat<M,E,S>::template Result<long double>::AddOp::perform(l,r); }
1086 template <int M, class E, int S> inline
1087 typename SymMat<M,E,S>::template Result<long double>::Add
1088 operator+(const long double& l, const SymMat<M,E,S>& r) {return r+l;}
1089 
1090 // m = m+int, int+m -- just convert int to m's precision float
1091 template <int M, class E, int S> inline
1092 typename SymMat<M,E,S>::template Result<typename CNT<E>::Precision>::Add
1093 operator+(const SymMat<M,E,S>& l, int r) {return l + (typename CNT<E>::Precision)r;}
1094 template <int M, class E, int S> inline
1095 typename SymMat<M,E,S>::template Result<typename CNT<E>::Precision>::Add
1096 operator+(int l, const SymMat<M,E,S>& r) {return r + (typename CNT<E>::Precision)l;}
1097 
1098 // Complex, conjugate, and negator are all easy to templatize.
1099 
1100 // m = m+complex, complex+m
1101 template <int M, class E, int S, class R> inline
1102 typename SymMat<M,E,S>::template Result<std::complex<R> >::Add
1103 operator+(const SymMat<M,E,S>& l, const std::complex<R>& r)
1104  { return SymMat<M,E,S>::template Result<std::complex<R> >::AddOp::perform(l,r); }
1105 template <int M, class E, int S, class R> inline
1106 typename SymMat<M,E,S>::template Result<std::complex<R> >::Add
1107 operator+(const std::complex<R>& l, const SymMat<M,E,S>& r) {return r+l;}
1108 
1109 // m = m+conjugate, conjugate+m (convert conjugate->complex)
1110 template <int M, class E, int S, class R> inline
1111 typename SymMat<M,E,S>::template Result<std::complex<R> >::Add
1112 operator+(const SymMat<M,E,S>& l, const conjugate<R>& r) {return l+(std::complex<R>)r;}
1113 template <int M, class E, int S, class R> inline
1114 typename SymMat<M,E,S>::template Result<std::complex<R> >::Add
1115 operator+(const conjugate<R>& l, const SymMat<M,E,S>& r) {return r+(std::complex<R>)l;}
1116 
1117 // m = m+negator, negator+m: convert negator to standard number
1118 template <int M, class E, int S, class R> inline
1119 typename SymMat<M,E,S>::template Result<typename negator<R>::StdNumber>::Add
1120 operator+(const SymMat<M,E,S>& l, const negator<R>& r) {return l + (typename negator<R>::StdNumber)(R)r;}
1121 template <int M, class E, int S, class R> inline
1122 typename SymMat<M,E,S>::template Result<typename negator<R>::StdNumber>::Add
1123 operator+(const negator<R>& l, const SymMat<M,E,S>& r) {return r + (typename negator<R>::StdNumber)(R)l;}
1124 
1125 // SCALAR SUBTRACT -- careful, not commutative.
1126 
1127 // m = m-real, real-m
1128 template <int M, class E, int S> inline
1129 typename SymMat<M,E,S>::template Result<float>::Sub
1130 operator-(const SymMat<M,E,S>& l, const float& r)
1131  { return SymMat<M,E,S>::template Result<float>::SubOp::perform(l,r); }
1132 template <int M, class E, int S> inline
1133 typename CNT<float>::template Result<SymMat<M,E,S> >::Sub
1134 operator-(const float& l, const SymMat<M,E,S>& r)
1135  { return CNT<float>::template Result<SymMat<M,E,S> >::SubOp::perform(l,r); }
1136 
1137 template <int M, class E, int S> inline
1138 typename SymMat<M,E,S>::template Result<double>::Sub
1139 operator-(const SymMat<M,E,S>& l, const double& r)
1140  { return SymMat<M,E,S>::template Result<double>::SubOp::perform(l,r); }
1141 template <int M, class E, int S> inline
1142 typename CNT<double>::template Result<SymMat<M,E,S> >::Sub
1143 operator-(const double& l, const SymMat<M,E,S>& r)
1144  { return CNT<double>::template Result<SymMat<M,E,S> >::SubOp::perform(l,r); }
1145 
1146 template <int M, class E, int S> inline
1147 typename SymMat<M,E,S>::template Result<long double>::Sub
1148 operator-(const SymMat<M,E,S>& l, const long double& r)
1149  { return SymMat<M,E,S>::template Result<long double>::SubOp::perform(l,r); }
1150 template <int M, class E, int S> inline
1151 typename CNT<long double>::template Result<SymMat<M,E,S> >::Sub
1152 operator-(const long double& l, const SymMat<M,E,S>& r)
1153  { return CNT<long double>::template Result<SymMat<M,E,S> >::SubOp::perform(l,r); }
1154 
1155 // m = m-int, int-m // just convert int to m's precision float
1156 template <int M, class E, int S> inline
1157 typename SymMat<M,E,S>::template Result<typename CNT<E>::Precision>::Sub
1158 operator-(const SymMat<M,E,S>& l, int r) {return l - (typename CNT<E>::Precision)r;}
1159 template <int M, class E, int S> inline
1160 typename CNT<typename CNT<E>::Precision>::template Result<SymMat<M,E,S> >::Sub
1161 operator-(int l, const SymMat<M,E,S>& r) {return (typename CNT<E>::Precision)l - r;}
1162 
1163 
1164 // Complex, conjugate, and negator are all easy to templatize.
1165 
1166 // m = m-complex, complex-m
1167 template <int M, class E, int S, class R> inline
1168 typename SymMat<M,E,S>::template Result<std::complex<R> >::Sub
1169 operator-(const SymMat<M,E,S>& l, const std::complex<R>& r)
1170  { return SymMat<M,E,S>::template Result<std::complex<R> >::SubOp::perform(l,r); }
1171 template <int M, class E, int S, class R> inline
1172 typename CNT<std::complex<R> >::template Result<SymMat<M,E,S> >::Sub
1173 operator-(const std::complex<R>& l, const SymMat<M,E,S>& r)
1174  { return CNT<std::complex<R> >::template Result<SymMat<M,E,S> >::SubOp::perform(l,r); }
1175 
1176 // m = m-conjugate, conjugate-m (convert conjugate->complex)
1177 template <int M, class E, int S, class R> inline
1178 typename SymMat<M,E,S>::template Result<std::complex<R> >::Sub
1179 operator-(const SymMat<M,E,S>& l, const conjugate<R>& r) {return l-(std::complex<R>)r;}
1180 template <int M, class E, int S, class R> inline
1181 typename CNT<std::complex<R> >::template Result<SymMat<M,E,S> >::Sub
1182 operator-(const conjugate<R>& l, const SymMat<M,E,S>& r) {return (std::complex<R>)l-r;}
1183 
1184 // m = m-negator, negator-m: convert negator to standard number
1185 template <int M, class E, int S, class R> inline
1186 typename SymMat<M,E,S>::template Result<typename negator<R>::StdNumber>::Sub
1187 operator-(const SymMat<M,E,S>& l, const negator<R>& r) {return l-(typename negator<R>::StdNumber)(R)r;}
1188 template <int M, class E, int S, class R> inline
1189 typename CNT<R>::template Result<SymMat<M,E,S> >::Sub
1190 operator-(const negator<R>& l, const SymMat<M,E,S>& r) {return (typename negator<R>::StdNumber)(R)l-r;}
1191 
1192 
1193 // SymMat I/O
1194 template <int M, class E, int RS, class CHAR, class TRAITS> inline
1195 std::basic_ostream<CHAR,TRAITS>&
1196 operator<<(std::basic_ostream<CHAR,TRAITS>& o, const SymMat<M,E,RS>& m) {
1197  for (int i=0;i<M;++i) {
1198  o << std::endl << "[";
1199  for (int j=0; j<=i; ++j)
1200  o << (j>0?" ":"") << m(i,j);
1201  for (int j=i+1; j<M; ++j)
1202  o << " *";
1203  o << "]";
1204  }
1205  if (M) o << std::endl;
1206  return o;
1207 }
1208 
1209 template <int M, class E, int RS, class CHAR, class TRAITS> inline
1210 std::basic_istream<CHAR,TRAITS>&
1211 operator>>(std::basic_istream<CHAR,TRAITS>& is, SymMat<M,E,RS>& m) {
1212  // TODO: not sure how to do input yet
1213  assert(false);
1214  return is;
1215 }
1216 
1217 } //namespace SimTK
1218 
1219 
1220 #endif //SimTK_SIMMATRIX_SMALLMATRIX_SYMMAT_H_
Matrix_< E > operator/(const MatrixBase< E > &l, const typename CNT< E >::StdNumber &r)
Definition: BigMatrix.h:2693
SymMat(const E &e)
Definition: SymMat.h:331
bool isNumericallySymmetric(double tol=getDefaultTolerance()) const
A Matrix is symmetric (actually Hermitian) if it is square and each element (i,j) is the Hermitian tr...
Definition: Mat.h:1126
SymMat(const E &e0, const E &e1, const E &e2, const E &e3, const E &e4, const E &e5, const E &e6, const E &e7, const E &e8, const E &e9)
Definition: SymMat.h:376
SymMat & scalarPlusEq(const EE &ee)
Definition: SymMat.h:687
TCol rowSum() const
Returns a column vector (Vec) containing the row sums of this matrix.
Definition: SymMat.h:846
const TReal & real() const
Definition: SymMat.h:597
SymMat< M, ESqTHerm, 1 > TSqTHerm
Definition: SymMat.h:149
bool isFinite() const
Return true if no element of this Vec contains an Infinity or a NaN anywhere.
Definition: Vec.h:887
Vec<(M *(M+1))/2, E, RS > TAsVec
Definition: SymMat.h:137
TNeg & operator-()
Definition: SymMat.h:582
K::ScalarNormSq ScalarNormSq
Definition: CompositeNumericalTypes.h:166
const TDiag & getDiag() const
Definition: SymMat.h:802
Definition: SymMat.h:107
Definition: SymMat.h:116
SymMat & operator*=(const EE &e)
Definition: SymMat.h:680
SymMat(int i)
Definition: SymMat.h:345
K::ULessScalar ULessScalar
Definition: CompositeNumericalTypes.h:161
Definition: SymMat.h:192
SymMat< M, E, 1 > TPacked
Definition: SymMat.h:150
SymMat< M, typename CNT< EE >::template Result< E >::Dvd > scalarDivideFromLeft(const EE &e) const
Definition: SymMat.h:644
K::TReal TReal
Definition: CompositeNumericalTypes.h:141
SymMat< M, typename CNT< EE >::template Result< E >::Mul > scalarMultiplyFromLeft(const EE &e) const
Definition: SymMat.h:629
SymMat & operator=(const EE *p)
Definition: SymMat.h:439
Result< SymMat< M, E2, RS2 > >::Sub conformingSubtract(const SymMat< M, E2, RS2 > &r) const
Definition: SymMat.h:503
Vec< M, E, RS > TDiag
Definition: SymMat.h:134
SymMat & operator+=(const SymMat< M, EE, RSS > &mm)
Definition: SymMat.h:461
ScalarNormSq scalarNormSqr() const
Scalar norm square is sum( conjugate squares of all underlying scalars ), where conjugate square of s...
Definition: Vec.h:272
DvdOp::Type Dvd
Definition: SymMat.h:216
const E & getEltLower(int i, int j) const
Definition: SymMat.h:822
const TLower & getLower() const
Definition: SymMat.h:809
RS is total spacing between rows in memory (default 1)
Definition: SymMat.h:71
SymMat & scalarMinusEqFromLeft(const EE &ee)
Definition: SymMat.h:693
SymMat & scalarDivideEqFromLeft(const EE &ee)
Definition: SymMat.h:702
E TElement
Definition: SymMat.h:133
static const THerm & transpose(const K &t)
Definition: CompositeNumericalTypes.h:216
const TNeg & negate() const
Definition: SymMat.h:586
const TWithoutNegator & castAwayNegatorIfAny() const
Definition: SymMat.h:612
bool isNaN() const
Return true if any element of this Vec contains a NaN anywhere.
Definition: Vec.h:863
SimTK::conjugate<R> should be instantiated only for float, double, long double.
Definition: String.h:45
const SymMat & operator+() const
Definition: SymMat.h:580
K::TSqrt TSqrt
Definition: CompositeNumericalTypes.h:154
const TNeg & operator-() const
Definition: SymMat.h:581
const TUpper & getUpper() const
Definition: SymMat.h:812
SymMat & scalarTimesEq(const EE &ee)
Definition: SymMat.h:696
static TSqrt sqrt(const K &t)
Definition: CompositeNumericalTypes.h:239
static Vec & updAs(ELT *p)
Recast a writable ordinary C++ array E[] to a writable Vec<M,E,S>; assumes compatible length...
Definition: Vec.h:853
K::Scalar Scalar
Definition: CompositeNumericalTypes.h:160
K::TNormalize TNormalize
Definition: CompositeNumericalTypes.h:158
EULessScalar ULessScalar
Definition: SymMat.h:153
Vec< M, typename CNT< EE >::template Result< E >::Mul > scalarMultiplyFromLeft(const EE &e) const
Definition: Vec.h:675
Definition: SymMat.h:104
TDiag & diag()
Definition: SymMat.h:807
SymMat & scalarTimesEqFromLeft(const EE &ee)
Definition: SymMat.h:698
TAsVec & updAsVec()
Definition: SymMat.h:816
SymMat & setFromSymmetric(const Mat< M, M, EE, CSS, RSS > &m)
Create a new SymMat of this type from a square Mat of the right size, that is expected to be symmetri...
Definition: SymMat.h:301
#define SimTK_ERRCHK1(cond, whereChecked, fmt, a1)
Definition: ExceptionMacros.h:326
E & updEltLower(int i, int j)
Definition: SymMat.h:823
K::TImag TImag
Definition: CompositeNumericalTypes.h:142
T THerm
Definition: SymMat.h:131
MulOp::Type Mul
Definition: SymMat.h:205
EPrecision Precision
Definition: SymMat.h:156
SymMat< M, typename CNT< E >::template Result< EE >::Add > scalarAdd(const EE &e) const
Definition: SymMat.h:652
Vec<(M *(M-1))/2, E, RS > TLower
Definition: SymMat.h:135
Definition: SymMat.h:230
std::basic_istream< CHAR, TRAITS > & operator>>(std::basic_istream< CHAR, TRAITS > &is, conjugate< R > &c)
Definition: conjugate.h:800
Definition: SymMat.h:100
void setToZero()
Definition: SymMat.h:706
negator<N>, where N is a number type (real, complex, conjugate), is represented in memory identically...
Definition: String.h:44
Definition: CompositeNumericalTypes.h:120
SymMat(const SymMat< M, ENeg, RSS > &src)
This is an implicit conversion from a SymMat of the same length and negated element type...
Definition: SymMat.h:320
SymMat< M, EWithoutNegator, RS > TWithoutNegator
Definition: SymMat.h:124
bool isFinite() const
Return true if no element contains an Infinity or a NaN.
Definition: SymMat.h:726
static double getDefaultTolerance()
Definition: CompositeNumericalTypes.h:269
const THerm & transpose() const
Definition: SymMat.h:589
SymMat< M, typename CNT< E >::template Result< P >::Sub, 1 > Sub
Definition: SymMat.h:196
TDiag & updDiag()
Definition: SymMat.h:803
AddCNTs< M, M, ArgDepth, SymMat, ColSpacing, RowSpacing, CNT< P >::NRows, CNT< P >::NCols, CNT< P >::ArgDepth, P, CNT< P >::ColSpacing, CNT< P >::RowSpacing > AddOp
Definition: SymMat.h:220
SymMat< M, typename CNT< E >::template Result< P >::Add, 1 > Add
Definition: SymMat.h:195
const THerm & operator~() const
Definition: SymMat.h:583
SymMat< M, typename CNT< EE >::template Result< E >::Sub > scalarSubtractFromLeft(const EE &e) const
Definition: SymMat.h:668
bool operator==(const PhiMatrix &p1, const PhiMatrix &p2)
Definition: SpatialAlgebra.h:774
SymMat(const E &e0, const E &e1, const E &e2, const E &e3, const E &e4, const E &e5, const E &e6, const E &e7, const E &e8, const E &e9, const E &e10, const E &e11, const E &e12, const E &e13, const E &e14)
Definition: SymMat.h:386
Definition: SymMat.h:117
E & operator()(int i, int j)
Definition: SymMat.h:542
Definition: SymMat.h:105
SymMat(const Mat< M, M, EE, CSS, RSS > &m)
This is an explicit conversion from square Mat of right size, assuming that the source matrix is symm...
Definition: SymMat.h:264
SymMat(const SymMat< M, E, RSS > &src)
This is an implicit conversion from a SymMat of the same length and element type but with different s...
Definition: SymMat.h:315
TCol col(int j) const
Definition: SymMat.h:777
Definition: SymMat.h:115
TSqrt sqrt() const
Definition: SymMat.h:172
Definition: SymMat.h:106
SymMat & operator=(const SymMat< M, EE, RSS > &mm)
Definition: SymMat.h:453
TImag & imag()
Definition: SymMat.h:606
SymMat & scalarMinusEq(const EE &ee)
Definition: SymMat.h:689
SymMat< M, typename CNT< E >::template Result< EE >::Sub > scalarSubtract(const EE &e) const
Definition: SymMat.h:660
SubOp::Type Sub
Definition: SymMat.h:226
Row< M, E, 1 > TRow
Definition: SymMat.h:141
SymMat(const SymMat< M, EE, RSS > &src)
Construct a SymMat from a SymMat of the same dimensions, with any element type and spacing...
Definition: SymMat.h:326
SymMat & scalarDivideEq(const EE &ee)
Definition: SymMat.h:700
Definition: SymMat.h:114
TInvert invert() const
Definition: SymMat.h:578
K::TSqTHerm TSqTHerm
Definition: CompositeNumericalTypes.h:147
SymMat(const SymMat &src)
Copy constructor.
Definition: SymMat.h:243
void setToNaN()
Definition: SymMat.h:705
TReal & real()
Definition: SymMat.h:598
bool isNumericallyEqual(const SymMat< M, E2, RS2 > &m) const
Test whether this matrix is numerically equal to some other matrix with the same shape, using a default tolerance which is the looser of the default tolerances of the two objects being compared.
Definition: SymMat.h:743
THerm & updTranspose()
Definition: SymMat.h:590
TRow row(int i) const
Definition: SymMat.h:765
EStandard sum() const
Sum just adds up all the elements into a single return element that is the same type as this Vec's el...
Definition: Vec.h:311
Definition: SymMat.h:119
SymMat< M, ESqrt, 1 > TSqrt
Definition: SymMat.h:143
SymMat & operator*=(const SymMat< M, EE, RSS > &mm)
Definition: SymMat.h:485
This is a fixed length column vector designed for no-overhead inline computation. ...
Definition: Vec.h:131
Result< SymMat< M, E2, RS2 > >::Add conformingAdd(const SymMat< M, E2, RS2 > &r) const
Definition: SymMat.h:496
SymMat & operator-=(const SymMat< M, negator< EE >, RSS > &mm)
Definition: SymMat.h:477
EltResult< E2 >::Mul elementwiseMultiply(const SymMat< M, E2, RS2 > &r) const
Definition: SymMat.h:524
const TReal & real() const
Return a reference to the real portion of this Vec if it has complex elements; otherwise the type doe...
Definition: Vec.h:626
Vec< M, typename CNT< E >::template Result< EE >::Mul > scalarMultiply(const EE &e) const
Definition: Vec.h:669
SymMat & setFromUpper(const Mat< M, M, EE, CSS, RSS > &m)
Create a new SymMat of this type from a square Mat of the right size, looking only at upper elements ...
Definition: SymMat.h:287
K::Precision Precision
Definition: CompositeNumericalTypes.h:164
TRow sum() const
This is an alternate name for colSum(); behaves like the Matlab function of the same name...
Definition: SymMat.h:842
MulCNTs< M, M, ArgDepth, SymMat, ColSpacing, RowSpacing, CNT< P >::NRows, CNT< P >::NCols, CNT< P >::ArgDepth, P, CNT< P >::ColSpacing, CNT< P >::RowSpacing > MulOp
Definition: SymMat.h:204
void setToNaN()
Set every scalar in this Vec to NaN; this is the default initial value in Debug builds, but not in Release.
Definition: Vec.h:757
Matrix_< E > operator*(const MatrixBase< E > &l, const typename CNT< E >::StdNumber &r)
Definition: BigMatrix.h:2685
const TAsVec & getAsVec() const
Definition: SymMat.h:815
void setToZero()
Set every scalar in this Vec to zero.
Definition: Vec.h:762
const TDiag & diag() const
Select main diagonal (of largest leading square if rectangular) and return it as a read-only view (as...
Definition: Mat.h:752
Definition: SymMat.h:111
K::TInvert TInvert
Definition: CompositeNumericalTypes.h:157
bool isNumericallyEqual(const Vec< M, E2, RS2 > &v, double tol) const
Test whether this vector is numerically equal to some other vector with the same shape, using a specified tolerance.
Definition: Vec.h:901
SymMat< M, typename CNT< E >::template Result< P >::Mul, 1 > Mul
Definition: SymMat.h:193
THerm & operator~()
Definition: SymMat.h:584
SymMat & operator-=(const EE &e)
Definition: SymMat.h:679
bool isInf() const
Return true if any element of this SymMat contains a +Inf or -Inf somewhere but no element contains a...
Definition: SymMat.h:723
SymMat(const EE *p)
Definition: SymMat.h:427
SymMat()
Default construction initializes to NaN when debugging but is left uninitialized otherwise.
Definition: SymMat.h:236
SymMat< M, E, RS > T
Definition: SymMat.h:122
E & updEltDiag(int i)
Definition: SymMat.h:819
ELEM max(const VectorBase< ELEM > &v)
Definition: VectorMath.h:251
SymMat & scalarEq(const EE &ee)
Definition: SymMat.h:685
NTraits< N >::StdNumber StdNumber
Definition: negator.h:107
static const SymMat & getAs(const ELT *p)
Definition: SymMat.h:709
TRow operator[](int i) const
Definition: SymMat.h:547
SymMat< M, EHerm, RS > TPosTrans
Definition: SymMat.h:132
E elt(int i, int j) const
Return a value for any element of a symmetric matrix, even those in the upper triangle which aren't a...
Definition: SymMat.h:794
SymMat< M, typename CNT< E >::template Result< EE >::Dvd > scalarDivide(const EE &e) const
Definition: SymMat.h:638
SubCNTs< M, M, ArgDepth, SymMat, ColSpacing, RowSpacing, CNT< P >::NRows, CNT< P >::NCols, CNT< P >::ArgDepth, P, CNT< P >::ColSpacing, CNT< P >::RowSpacing > SubOp
Definition: SymMat.h:225
TNormalize normalize() const
If the elements of this Vec are scalars, the result is what you get by dividing each element by the n...
Definition: Vec.h:568
K::TPosTrans TPosTrans
Definition: CompositeNumericalTypes.h:145
SymMat & operator+=(const SymMat< M, negator< EE >, RSS > &mm)
Definition: SymMat.h:466
SymMat & setFromLower(const Mat< M, M, EE, CSS, RSS > &m)
Create a new SymMat of this type from a square Mat of the right size, looking only at lower elements ...
Definition: SymMat.h:271
SymMat(const E &e0, const E &e1, const E &e2, const E &e3, const E &e4, const E &e5, const E &e6, const E &e7, const E &e8, const E &e9, const E &e10, const E &e11, const E &e12, const E &e13, const E &e14, const E &e15, const E &e16, const E &e17, const E &e18, const E &e19, const E &e20)
Definition: SymMat.h:398
SymMat & operator=(const SymMat &src)
Copy assignment; no harm if source and this are the same matrix.
Definition: SymMat.h:248
TLower & updLower()
Definition: SymMat.h:810
EScalar Scalar
Definition: SymMat.h:152
static TPacked getNaN()
Definition: SymMat.h:713
SymMat< M, EStandard, 1 > TStandard
Definition: SymMat.h:145
EHerm & updEltUpper(int i, int j)
Definition: SymMat.h:827
SymMat< M, EImag, RS *CNT< E >::RealStrideFactor > TImag
Definition: SymMat.h:129
SymMat(const E &e0, const E &e1, const E &e2, const E &e3, const E &e4, const E &e5)
Definition: SymMat.h:368
K::StdNumber StdNumber
Definition: CompositeNumericalTypes.h:163
TCol operator()(int j) const
Definition: SymMat.h:548
Vec & scalarTimesEqFromLeft(const EE &ee)
Definition: Vec.h:738
bool operator!=(const conjugate< R > &a, const float &b)
Definition: conjugate.h:859
Definition: SymMat.h:99
Vec< M, E, 1 > TCol
Definition: SymMat.h:142
Specialized information about Composite Numerical Types which allows us to define appropriate templat...
Definition: CompositeNumericalTypes.h:136
Vec<(M *(M-1))/2, EHerm, RS > TUpper
Definition: SymMat.h:136
SymMat & operator-=(const SymMat< M, EE, RSS > &mm)
Definition: SymMat.h:472
SymMat< M, ESqHermT, 1 > TSqHermT
Definition: SymMat.h:148
const E & operator()(int i, int j) const
Definition: SymMat.h:540
SymMat< M, EInvert, 1 > TInvert
Definition: SymMat.h:146
Generic Row.
Definition: Row.h:118
TNeg & updNegate()
Definition: SymMat.h:587
const TDiag & diag() const
Definition: SymMat.h:806
EStandard trace() const
Definition: SymMat.h:187
Vec & scalarMinusEqFromLeft(const EE &ee)
Definition: Vec.h:734
Mandatory first inclusion for any Simbody source or header file.
static double getDefaultTolerance()
For approximate comparisions, the default tolerance to use for a matrix is its shortest dimension tim...
Definition: SymMat.h:730
EScalarNormSq ScalarNormSq
Definition: SymMat.h:157
K::TNeg TNeg
Definition: CompositeNumericalTypes.h:139
TAbs abs() const
Definition: SymMat.h:179
static SymMat & updAs(ELT *p)
Definition: SymMat.h:710
static double getDefaultTolerance()
For approximate comparisions, the default tolerance to use for a matrix is its shortest dimension tim...
Definition: Mat.h:1075
ENumber Number
Definition: SymMat.h:154
K::TStandard TStandard
Definition: CompositeNumericalTypes.h:156
Definition: SymMat.h:201
#define SimTK_INDEXCHECK(ix, ub, where)
Definition: ExceptionMacros.h:145
EStdNumber StdNumber
Definition: SymMat.h:155
K::TWithoutNegator TWithoutNegator
Definition: CompositeNumericalTypes.h:140
const EHerm & getEltUpper(int i, int j) const
Definition: SymMat.h:826
bool isNumericallyEqual(const SymMat< M, E2, RS2 > &m, double tol) const
Test whether this matrix is numerically equal to some other matrix with the same shape, using a specified tolerance.
Definition: SymMat.h:735
static int size()
Definition: SymMat.h:159
AddOp::Type Add
Definition: SymMat.h:221
SymMat(const E &e0, const E &e1, const E &e2)
A bevy of constructors from individual exact-match elements IN ROW ORDER, giving the LOWER TRIANGLE...
Definition: SymMat.h:362
Definition: SymMat.h:101
DvdCNTs< M, M, ArgDepth, SymMat, ColSpacing, RowSpacing, CNT< P >::NRows, CNT< P >::NCols, CNT< P >::ArgDepth, P, CNT< P >::ColSpacing, CNT< P >::RowSpacing > DvdOp
Definition: SymMat.h:215
Definition: SymMat.h:109
TPosTrans & updPositionalTranspose()
Definition: SymMat.h:594
SymMat< M, P > Type
Definition: SymMat.h:231
SymMat< M, EComplex, RS > TComplex
Definition: SymMat.h:130
SymMat< M, typename CNT< E >::template Result< P >::Dvd, 1 > Dvd
Definition: SymMat.h:194
bool isNaN() const
Return true if any element of this SymMat contains a NaN anywhere.
Definition: SymMat.h:719
MulCNTsNonConforming< M, M, ArgDepth, SymMat, ColSpacing, RowSpacing, CNT< P >::NRows, CNT< P >::NCols, CNT< P >::ArgDepth, P, CNT< P >::ColSpacing, CNT< P >::RowSpacing > MulOpNonConforming
Definition: SymMat.h:209
This class represents a small matrix whose size is known at compile time, containing elements of any ...
Definition: Mat.h:51
CNT< ScalarNormSq >::TSqrt norm() const
Definition: SymMat.h:554
K::TComplex TComplex
Definition: CompositeNumericalTypes.h:143
TNormalize normalize() const
There is no conventional meaning for normalize() applied to a matrix.
Definition: SymMat.h:567
SymMat< M, EAbs, 1 > TAbs
Definition: SymMat.h:144
K::Number Number
Definition: CompositeNumericalTypes.h:162
Definition: SymMat.h:102
bool isInf() const
Return true if any element of this Vec contains a +Infinity or -Infinity somewhere but no element con...
Definition: Vec.h:872
TWithoutNegator & updCastAwayNegatorIfAny()
Definition: SymMat.h:613
TStandard standardize() const
Definition: SymMat.h:183
Definition: SymMat.h:103
Definition: SymMat.h:118
SymMat< M, typename CNT< E >::template Result< EE >::Mul > scalarMultiply(const EE &e) const
Definition: SymMat.h:623
EltResult< E2 >::Dvd elementwiseDivide(const SymMat< M, E2, RS2 > &r) const
Definition: SymMat.h:532
MulOpNonConforming::Type MulNon
Definition: SymMat.h:210
const TPosTrans & positionalTranspose() const
Definition: SymMat.h:592
SymMat< M, EReal, RS *CNT< E >::RealStrideFactor > TReal
Definition: SymMat.h:127
ScalarNormSq scalarNormSqr() const
Definition: SymMat.h:165
K::TSqHermT TSqHermT
Definition: CompositeNumericalTypes.h:146
ScalarNormSq normSqr() const
Definition: SymMat.h:552
static int nrow()
Definition: SymMat.h:160
const TImag & imag() const
Definition: SymMat.h:601
SymMat(const ENeg &e)
Definition: SymMat.h:338
static const TReal & real(const T &t)
Definition: CompositeNumericalTypes.h:203
K::THerm THerm
Definition: CompositeNumericalTypes.h:144
Result< SymMat< M, E2, RS2 > >::Mul conformingMultiply(const SymMat< M, E2, RS2 > &s) const
Definition: SymMat.h:513
SymMat< M, ENormalize, 1 > TNormalize
Definition: SymMat.h:147
static int ncol()
Definition: SymMat.h:161
Vec< M, typename CNT< E >::template Result< EE >::Dvd > scalarDivide(const EE &e) const
Definition: Vec.h:684
Definition: negator.h:64
TUpper & updUpper()
Definition: SymMat.h:813
Vec & scalarDivideEqFromLeft(const EE &ee)
Definition: Vec.h:742
TRow colSum() const
Returns a row vector (Row) containing the column sums of this matrix.
Definition: SymMat.h:830
Definition: SymMat.h:108
Vec< M, typename CNT< EE >::template Result< E >::Dvd > scalarDivideFromLeft(const EE &e) const
Definition: Vec.h:690
const E & getEltDiag(int i) const
Definition: SymMat.h:818
static const Vec & getAs(const ELT *p)
Recast an ordinary C++ array E[] to a const Vec<M,E,S>; assumes compatible length, stride, and packing.
Definition: Vec.h:849
SymMat & operator+=(const EE &e)
Definition: SymMat.h:678
SymMat & operator/=(const EE &e)
Definition: SymMat.h:681
K::TAbs TAbs
Definition: CompositeNumericalTypes.h:155
SymMat< M, ENeg, RS > TNeg
Definition: SymMat.h:123