Simbody 3.9
Loading...
Searching...
No Matches
Mat.h
Go to the documentation of this file.
1#ifndef SimTK_SIMMATRIX_SMALLMATRIX_MAT_H_
2#define SimTK_SIMMATRIX_SMALLMATRIX_MAT_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
32
33#include <tuple>
34#include <type_traits>
35
36namespace SimTK {
37
100template <int M, int N, class ELT, int CS, int RS> class Mat {
101public:
102 typedef ELT E;
103 typedef typename CNT<E>::TNeg ENeg;
105 typedef typename CNT<E>::TReal EReal;
106 typedef typename CNT<E>::TImag EImag;
107 typedef typename CNT<E>::TComplex EComplex;
108 typedef typename CNT<E>::THerm EHerm;
109 typedef typename CNT<E>::TPosTrans EPosTrans;
110 typedef typename CNT<E>::TSqHermT ESqHermT;
111 typedef typename CNT<E>::TSqTHerm ESqTHerm;
112
113 typedef typename CNT<E>::TSqrt ESqrt;
114 typedef typename CNT<E>::TAbs EAbs;
115 typedef typename CNT<E>::TStandard EStandard;
116 typedef typename CNT<E>::TInvert EInvert;
118
119 typedef typename CNT<E>::Scalar EScalar;
121 typedef typename CNT<E>::Number ENumber;
125
127 #ifndef SWIG
128 enum {
129 NRows = M,
130 NCols = N,
131 MinDim = N < M ? N : M,
132 MaxDim = N > M ? N : M,
136 NActualElements = (N-1)*CS + (M-1)*RS + 1,
139 RealStrideFactor = 1, // composite types don't change size when
140 // cast from complex to real or imaginary
142 ? CNT<E>::ArgDepth + 1
150 };
151 #endif
152
156
164 typedef E TElement;
168
169 // These are the results of calculations, so are returned in new, packed
170 // memory. Be sure to refer to element types here which are also packed.
171 typedef Mat<M,N,ESqrt,M,1> TSqrt; // Note strides are packed
172 typedef Mat<M,N,EAbs,M,1> TAbs; // Note strides are packed
174 typedef Mat<N,M,EInvert,N,1> TInvert; // like THerm but packed
176
177 typedef SymMat<N,ESqHermT> TSqHermT; // ~Mat*Mat
178 typedef SymMat<M,ESqTHerm> TSqTHerm; // Mat*~Mat
179
180 // Here the elements are copied unchanged but the result matrix
181 // is an ordinary packed, column order matrix.
183 typedef Mat<M-1,N,E,M-1,1> TDropRow;
184 typedef Mat<M,N-1,E,M,1> TDropCol;
185 typedef Mat<M-1,N-1,E,M-1,1> TDropRowCol;
189
196
197 typedef THerm TransposeType; // TODO
198
200 static int size() { return M*N; }
203 static int nrow() { return M; }
206 static int ncol() { return N; }
207
214 ScalarNormSq sum(0);
215 for(int j=0;j<N;++j) sum += CNT<TCol>::scalarNormSqr((*this)(j));
216 return sum;
217 }
218
222 TSqrt sqrt() const {
223 TSqrt msqrt;
224 for(int j=0;j<N;++j) msqrt(j) = (*this)(j).sqrt();
225 return msqrt;
226 }
227
232 TAbs mabs;
233 for(int j=0;j<N;++j) mabs(j) = (*this)(j).abs();
234 return mabs;
235 }
236
239 for(int j=0;j<N;++j) mstd(j) = (*this)(j).standardize();
240 return mstd;
241 }
242
243 // This gives the resulting matrix type when (m(i,j) op P) is applied to each element.
244 // It is an MxN vector with default column and row spacing, and element types which
245 // are the regular composite result of E op P. Typically P is a scalar type but
246 // it doesn't have to be.
253
254 // This is the composite result for m op P where P is some kind of appropriately shaped
255 // non-scalar type.
282
283 // Shape-preserving element substitution (always packed)
284 template <class P> struct Substitute {
286 };
287
290 Mat(){
291 #ifndef NDEBUG
292 setToNaN();
293 #endif
294 }
295
296 // It's important not to use the default copy constructor or copy
297 // assignment because the compiler doesn't understand that we may
298 // have noncontiguous storage and will try to copy the whole array.
299
302 Mat(const Mat& src) {
303 for (int j=0; j<N; ++j)
304 (*this)(j) = src(j);
305 }
309 Mat& operator=(const Mat& src) {
310 for (int j=0; j<N; ++j)
311 (*this)(j) = src(j); // no harm if src and 'this' are the same
312 return *this;
313 }
314
319 explicit Mat(const SymMat<M, ELT>& src) {
320 updDiag() = src.diag();
321 for (int j = 0; j < M; ++j)
322 for (int i = j+1; i < M; ++i) {
323 (*this)(i, j) = src.getEltLower(i, j);
324 (*this)(j, i) = src.getEltUpper(j, i);
325 }
326 }
327
332 template <int CSS, int RSS>
334 for (int j=0; j<N; ++j)
335 (*this)(j) = src(j);
336 }
337
343 template <int CSS, int RSS>
345 for (int j=0; j<N; ++j)
346 (*this)(j) = src(j);
347 }
348
356 template <class EE, int CSS, int RSS>
357 explicit Mat(const Mat<M,N,EE,CSS,RSS>& mm)
358 { for (int j=0;j<N;++j) (*this)(j) = mm(j);}
359
363 explicit Mat(const E& e)
364 { for (int j=0;j<N;++j) (*this)(j) = E(0); diag()=e; }
365
370 explicit Mat(const ENeg& e)
371 { for (int j=0;j<N;++j) (*this)(j) = E(0); diag()=e; }
372
379 explicit Mat(int i)
380 { new (this) Mat(E(Precision(i))); }
381
382 // Constructs a `Mat` from individual exact-match elements IN ROW ORDER.
383 template<
384 typename... Elements,
385 typename = std::enable_if_t<
386 (M*N==sizeof...(Elements)) &&
387 (std::is_convertible_v<Elements&&, const E&> && ...)
388 >
389 >
391 {
392 assignDataRowByRow(
393 std::forward_as_tuple(elementsRowByRow...),
394 std::make_integer_sequence<int, sizeof...(Elements)>{}
395 );
396 }
397
398 // Construction from 1-6 *exact match* Rows
399 explicit Mat(const TRow& r0)
400 { assert(M==1); (*this)[0]=r0; }
401 Mat(const TRow& r0,const TRow& r1)
402 { assert(M==2);(*this)[0]=r0;(*this)[1]=r1; }
403 Mat(const TRow& r0,const TRow& r1,const TRow& r2)
404 { assert(M==3);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2; }
405 Mat(const TRow& r0,const TRow& r1,const TRow& r2,
406 const TRow& r3)
407 { assert(M==4);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;(*this)[3]=r3; }
408 Mat(const TRow& r0,const TRow& r1,const TRow& r2,
409 const TRow& r3,const TRow& r4)
410 { assert(M==5);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;
411 (*this)[3]=r3;(*this)[4]=r4; }
412 Mat(const TRow& r0,const TRow& r1,const TRow& r2,
413 const TRow& r3,const TRow& r4,const TRow& r5)
414 { assert(M==6);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;
415 (*this)[3]=r3;(*this)[4]=r4;(*this)[5]=r5; }
416
417 // Construction from 1-6 *compatible* Rows
418 template <class EE, int SS> explicit Mat(const Row<N,EE,SS>& r0)
419 { assert(M==1); (*this)[0]=r0; }
420 template <class EE, int SS> Mat(const Row<N,EE,SS>& r0,const Row<N,EE,SS>& r1)
421 { assert(M==2);(*this)[0]=r0;(*this)[1]=r1; }
422 template <class EE, int SS>
424 { assert(M==3);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2; }
425 template <class EE, int SS>
427 const Row<N,EE,SS>& r3)
428 { assert(M==4);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;(*this)[3]=r3; }
429 template <class EE, int SS>
431 const Row<N,EE,SS>& r3,const Row<N,EE,SS>& r4)
432 { assert(M==5);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;
433 (*this)[3]=r3;(*this)[4]=r4; }
434 template <class EE, int SS>
436 const Row<N,EE,SS>& r3,const Row<N,EE,SS>& r4,const Row<N,EE,SS>& r5)
437 { assert(M==6);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;
438 (*this)[3]=r3;(*this)[4]=r4;(*this)[5]=r5; }
439
440
441 // Construction from 1-6 *exact match* Vecs
442 explicit Mat(const TCol& r0)
443 { assert(N==1); (*this)(0)=r0; }
444 Mat(const TCol& r0,const TCol& r1)
445 { assert(N==2);(*this)(0)=r0;(*this)(1)=r1; }
446 Mat(const TCol& r0,const TCol& r1,const TCol& r2)
447 { assert(N==3);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2; }
448 Mat(const TCol& r0,const TCol& r1,const TCol& r2,
449 const TCol& r3)
450 { assert(N==4);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;(*this)(3)=r3; }
451 Mat(const TCol& r0,const TCol& r1,const TCol& r2,
452 const TCol& r3,const TCol& r4)
453 { assert(N==5);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;
454 (*this)(3)=r3;(*this)(4)=r4; }
455 Mat(const TCol& r0,const TCol& r1,const TCol& r2,
456 const TCol& r3,const TCol& r4,const TCol& r5)
457 { assert(N==6);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;
458 (*this)(3)=r3;(*this)(4)=r4;(*this)(5)=r5; }
459
460 // Construction from 1-6 *compatible* Vecs
461 template <class EE, int SS> explicit Mat(const Vec<M,EE,SS>& r0)
462 { assert(N==1); (*this)(0)=r0; }
463 template <class EE, int SS> Mat(const Vec<M,EE,SS>& r0,const Vec<M,EE,SS>& r1)
464 { assert(N==2);(*this)(0)=r0;(*this)(1)=r1; }
465 template <class EE, int SS>
467 { assert(N==3);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2; }
468 template <class EE, int SS>
470 const Vec<M,EE,SS>& r3)
471 { assert(N==4);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;(*this)(3)=r3; }
472 template <class EE, int SS>
474 const Vec<M,EE,SS>& r3,const Vec<M,EE,SS>& r4)
475 { assert(N==5);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;
476 (*this)(3)=r3;(*this)(4)=r4; }
477 template <class EE, int SS>
479 const Vec<M,EE,SS>& r3,const Vec<M,EE,SS>& r4,const Vec<M,EE,SS>& r5)
480 { assert(N==6);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;
481 (*this)(3)=r3;(*this)(4)=r4;(*this)(5)=r5; }
482
483 // Construction from a pointer to anything assumes we're pointing
484 // at a packed element list of the right length, in row order.
485 template <class EE> explicit Mat(const EE* p)
486 { assert(p); for(int i=0;i<M;++i) (*this)[i]=&p[i*N]; }
487
488 // Assignment works similarly to copy -- if the lengths match,
489 // go element-by-element. Otherwise, zero and then copy to each
490 // diagonal element.
491 template <class EE, int CSS, int RSS> Mat& operator=(const Mat<M,N,EE,CSS,RSS>& mm) {
492 for (int j=0; j<N; ++j) (*this)(j) = mm(j);
493 return *this;
494 }
495
496 template <class EE> Mat& operator=(const EE* p) {
497 assert(p); for(int i=0;i<M;++i) (*this)[i]=&p[i*N];
498 return *this;
499 }
500
501 // Assignment ops
502 template <class EE, int CSS, int RSS> Mat&
504 for (int j=0; j<N; ++j) (*this)(j) += mm(j);
505 return *this;
506 }
507 template <class EE, int CSS, int RSS> Mat&
509 for (int j=0; j<N; ++j) (*this)(j) -= -(mm(j));
510 return *this;
511 }
512
513 template <class EE, int CSS, int RSS> Mat&
515 for (int j=0; j<N; ++j) (*this)(j) -= mm(j);
516 return *this;
517 }
518 template <class EE, int CSS, int RSS> Mat&
520 for (int j=0; j<N; ++j) (*this)(j) += -(mm(j));
521 return *this;
522 }
523
524 // In place matrix multiply can only be done when the RHS matrix is square of dimension
525 // N (i.e., number of columns), and the elements are also *= compatible.
526 template <class EE, int CSS, int RSS> Mat&
528 const Mat t(*this);
529 for (int j=0; j<N; ++j)
530 for (int i=0; i<M; ++i)
531 (*this)(i,j) = t[i] * mm(j);
532 return *this;
533 }
534
535 // Conforming binary ops with 'this' on left, producing new packed result.
536 // Cases: m=m+-m, m=m+-sy, m=m*m, m=m*sy, v=m*v
537
538 // m= this + m
539 template <class E2, int CS2, int RS2>
540 typename Result<Mat<M,N,E2,CS2,RS2> >::Add
542 typename Result<Mat<M,N,E2,CS2,RS2> >::Add result;
543 for (int j=0;j<N;++j) result(j) = (*this)(j) + r(j);
544 return result;
545 }
546 // m= this - m
547 template <class E2, int CS2, int RS2>
548 typename Result<Mat<M,N,E2,CS2,RS2> >::Sub
550 typename Result<Mat<M,N,E2,CS2,RS2> >::Sub result;
551 for (int j=0;j<N;++j) result(j) = (*this)(j) - r(j);
552 return result;
553 }
554 // m= m - this
555 template <class E2, int CS2, int RS2>
558 return l.conformingSubtract(*this);
559 }
560
561 // m= this .* m
562 template <class E2, int CS2, int RS2>
563 typename EltResult<E2>::Mul
565 typename EltResult<E2>::Mul result;
566 for (int j=0;j<N;++j)
567 result(j) = (*this)(j).elementwiseMultiply(r(j));
568 return result;
569 }
570
571 // m= this ./ m
572 template <class E2, int CS2, int RS2>
573 typename EltResult<E2>::Dvd
575 typename EltResult<E2>::Dvd result;
576 for (int j=0;j<N;++j)
577 result(j) = (*this)(j).elementwiseDivide(r(j));
578 return result;
579 }
580
581 // We always punt to the SymMat since it knows better what to do.
582 // m = this + sym
583 template <class E2, int RS2>
584 typename Result<SymMat<M,E2,RS2> >::Add
586 assert(M==N);
587 return sy.conformingAdd(*this);
588 }
589 // m= this - sym
590 template <class E2, int RS2>
591 typename Result<SymMat<M,E2,RS2> >::Sub
593 assert(M==N);
594 return sy.conformingSubtractFromLeft(*this);
595 }
596 // m= sym - this
597 template <class E2, int RS2>
600 assert(M==N);
601 return sy.conformingSubtract(*this);
602 }
603
604 // m= this * m
605 template <int N2, class E2, int CS2, int RS2>
606 typename Result<Mat<N,N2,E2,CS2,RS2> >::Mul
608 typename Result<Mat<N,N2,E2,CS2,RS2> >::Mul result;
609 for (int j=0;j<N2;++j)
610 for (int i=0;i<M;++i)
611 result(i,j) = (*this)[i].conformingMultiply(m(j)); // i.e., dot()
612 return result;
613 }
614 // m= m * this
615 template <int M2, class E2, int CS2, int RS2>
618 return m.conformingMultiply(*this);
619 }
620
621 // m= this / m = this * m.invert()
622 template <int M2, class E2, int CS2, int RS2>
623 typename Result<Mat<M2,N,E2,CS2,RS2> >::Dvd
625 return conformingMultiply(m.invert());
626 }
627 // m= m / this = m * this.invert()
628 template <int M2, class E2, int CS2, int RS2>
631 return m.conformingMultiply((*this).invert());
632 }
633
634 const TRow& operator[](int i) const { return row(i); }
635 TRow& operator[](int i) { return row(i); }
636 const TCol& operator()(int j) const { return col(j); }
637 TCol& operator()(int j) { return col(j); }
638
639 const E& operator()(int i,int j) const { return elt(i,j); }
640 E& operator()(int i,int j) { return elt(i,j); }
641
642 // This is the scalar Frobenius norm.
643 ScalarNormSq normSqr() const { return scalarNormSqr(); }
646
647 // There is no conventional meaning for normalize() applied to a matrix. We
648 // choose to define it as follows:
649 // If the elements of this Mat are scalars, the result is what you get by
650 // dividing each element by the Frobenius norm() calculated above. If the elements are
651 // *not* scalars, then the elements are *separately* normalized. That means
652 // you will get a different answer from Mat<2,2,Mat33>::normalize() than you
653 // would from a Mat<6,6>::normalize() containing the same scalars.
654 //
655 // Normalize returns a matrix of the same dimension but in new, packed storage
656 // and with a return type that does not include negator<> even if the original
657 // Mat<> does, because we can eliminate the negation here almost for free.
658 // But we can't standardize (change conjugate to complex) for free, so we'll retain
659 // conjugates if there are any.
661 if (CNT<E>::IsScalar) {
663 } else {
665 // punt to the column Vec to deal with the elements
666 for (int j=0; j<N; ++j)
667 elementwiseNormalized(j) = (*this)(j).normalize();
669 }
670 }
671
672 // Default inversion. Assume full rank if square, otherwise return
673 // pseudoinverse. (Mostly TODO)
675
676 const Mat& operator+() const { return *this; }
677 const TNeg& operator-() const { return negate(); }
678 TNeg& operator-() { return updNegate(); }
679 const THerm& operator~() const { return transpose(); }
680 THerm& operator~() { return updTranspose(); }
681
682 SimTK_NODISCARD const TNeg& negate() const { return *reinterpret_cast<const TNeg*>(this); }
683 TNeg& updNegate() { return *reinterpret_cast<TNeg*>(this); }
684
685 SimTK_NODISCARD const THerm& transpose() const { return *reinterpret_cast<const THerm*>(this); }
686 THerm& updTranspose() { return *reinterpret_cast<THerm*>(this); }
687
689 { return *reinterpret_cast<const TPosTrans*>(this); }
691 { return *reinterpret_cast<TPosTrans*>(this); }
692
693 // If the underlying scalars are complex or conjugate, we can return a
694 // reference to the real part just by recasting the data to a matrix of
695 // the same dimensions but containing real elements, with the scalar
696 // spacing doubled.
697 const TReal& real() const { return *reinterpret_cast<const TReal*>(this); }
698 TReal& real() { return *reinterpret_cast< TReal*>(this); }
699
700 // Getting the imaginary part is almost the same as real, but we have
701 // to shift the starting address of the returned object by 1 real-size
702 // ("precision") scalar so that the first element is the imaginary part
703 // of the original first element.
704 // TODO: should blow up or return a reference to a zero matrix if called
705 // on a real object.
706 // Had to contort these routines to get them through VC++ 7.net
707 const TImag& imag() const {
708 const int offs = ImagOffset;
709 const Precision* p = reinterpret_cast<const Precision*>(this);
710 return *reinterpret_cast<const TImag*>(p+offs);
711 }
713 const int offs = ImagOffset;
714 Precision* p = reinterpret_cast<Precision*>(this);
715 return *reinterpret_cast<TImag*>(p+offs);
716 }
717
718 const TWithoutNegator& castAwayNegatorIfAny() const {return *reinterpret_cast<const TWithoutNegator*>(this);}
719 TWithoutNegator& updCastAwayNegatorIfAny() {return *reinterpret_cast<TWithoutNegator*>(this);}
720
721 const TRow& row(int i) const {
722 SimTK_INDEXCHECK(i,M, "Mat::row[i]");
723 return *reinterpret_cast<const TRow*>(&d[i*RS]);
724 }
725 TRow& row(int i) {
726 SimTK_INDEXCHECK(i,M, "Mat::row[i]");
727 return *reinterpret_cast<TRow*>(&d[i*RS]);
728 }
729
730 const TCol& col(int j) const {
731 SimTK_INDEXCHECK(j,N, "Mat::col(j)");
732 return *reinterpret_cast<const TCol*>(&d[j*CS]);
733 }
734 TCol& col(int j) {
735 SimTK_INDEXCHECK(j,N, "Mat::col(j)");
736 return *reinterpret_cast<TCol*>(&d[j*CS]);
737 }
738
739 const E& elt(int i, int j) const {
740 SimTK_INDEXCHECK(i,M, "Mat::elt(i,j)");
741 SimTK_INDEXCHECK(j,N, "Mat::elt(i,j)");
742 return d[i*RS+j*CS];
743 }
744 E& elt(int i, int j) {
745 SimTK_INDEXCHECK(i,M, "Mat::elt(i,j)");
746 SimTK_INDEXCHECK(j,N, "Mat::elt(i,j)");
747 return d[i*RS+j*CS];
748 }
749
753 const TDiag& diag() const { return *reinterpret_cast<const TDiag*>(d); }
757 TDiag& updDiag() { return *reinterpret_cast<TDiag*>(d); }
760 TDiag& diag() { return *reinterpret_cast<TDiag*>(d); }
761
762 EStandard trace() const {return diag().sum();}
763
764 // These are elementwise binary operators, (this op ee) by default but (ee op this) if
765 // 'FromLeft' appears in the name. The result is a packed Mat<M,N> but the element type
766 // may change. These are mostly used to implement global operators.
767 // We call these "scalar" operators but actually the "scalar" can be a composite type.
768
769 //TODO: consider converting 'e' to Standard Numbers as precalculation and changing
770 // return type appropriately.
772 scalarMultiply(const EE& e) const {
774 for (int j=0; j<N; ++j) result(j) = (*this)(j).scalarMultiply(e);
775 return result;
776 }
778 scalarMultiplyFromLeft(const EE& e) const {
780 for (int j=0; j<N; ++j) result(j) = (*this)(j).scalarMultiplyFromLeft(e);
781 return result;
782 }
783
784 // TODO: should precalculate and store 1/e, while converting to Standard Numbers. Note
785 // that return type should change appropriately.
787 scalarDivide(const EE& e) const {
789 for (int j=0; j<N; ++j) result(j) = (*this)(j).scalarDivide(e);
790 return result;
791 }
793 scalarDivideFromLeft(const EE& e) const {
795 for (int j=0; j<N; ++j) result(j) = (*this)(j).scalarDivideFromLeft(e);
796 return result;
797 }
798
799 // Additive operators for scalars operate only on the diagonal.
801 scalarAdd(const EE& e) const {
803 result.diag() += e;
804 return result;
805 }
806 // Add is commutative, so no 'FromLeft'.
807
809 scalarSubtract(const EE& e) const {
811 result.diag() -= e;
812 return result;
813 }
814 // Should probably do something clever with negation here (s - m)
816 scalarSubtractFromLeft(const EE& e) const {
818 result.diag() += e; // yes, add
819 return result;
820 }
821
822 // Generic assignments for any element type not listed explicitly, including scalars.
823 // These are done repeatedly for each element and only work if the operation can
824 // be performed leaving the original element type.
825 template <class EE> Mat& operator =(const EE& e) {return scalarEq(e);}
826 template <class EE> Mat& operator+=(const EE& e) {return scalarPlusEq(e);}
827 template <class EE> Mat& operator-=(const EE& e) {return scalarMinusEq(e);}
828 template <class EE> Mat& operator*=(const EE& e) {return scalarTimesEq(e);}
829 template <class EE> Mat& operator/=(const EE& e) {return scalarDivideEq(e);}
830
831 // Generalized scalar assignment & computed assignment methods. These will work
832 // for any assignment-compatible element, not just scalars.
833 template <class EE> Mat& scalarEq(const EE& ee)
834 { for(int j=0; j<N; ++j) (*this)(j).scalarEq(EE(0));
835 diag().scalarEq(ee);
836 return *this; }
837
838 template <class EE> Mat& scalarPlusEq(const EE& ee)
839 { diag().scalarPlusEq(ee); return *this; }
840
841 template <class EE> Mat& scalarMinusEq(const EE& ee)
842 { diag().scalarMinusEq(ee); return *this; }
843 // m = s - m; negate m, then add s
844 template <class EE> Mat& scalarMinusEqFromLeft(const EE& ee)
845 { scalarTimesEq(E(-1)); diag().scalarAdd(ee); return *this; }
846
847 template <class EE> Mat& scalarTimesEq(const EE& ee)
848 { for(int j=0; j<N; ++j) (*this)(j).scalarTimesEq(ee); return *this; }
849 template <class EE> Mat& scalarTimesEqFromLeft(const EE& ee)
850 { for(int j=0; j<N; ++j) (*this)(j).scalarTimesEqFromLeft(ee); return *this; }
851
852 template <class EE> Mat& scalarDivideEq(const EE& ee)
853 { for(int j=0; j<N; ++j) (*this)(j).scalarDivideEq(ee); return *this; }
854 template <class EE> Mat& scalarDivideEqFromLeft(const EE& ee)
855 { for(int j=0; j<N; ++j) (*this)(j).scalarDivideEqFromLeft(ee); return *this; }
856
857 void setToNaN() {
858 for (int j=0; j<N; ++j)
859 (*this)(j).setToNaN();
860 }
861
862 void setToZero() {
863 for (int j=0; j<N; ++j)
864 (*this)(j).setToZero();
865 }
866
867 // Extract a sub-Mat with size known at compile time. These have to be
868 // called with explicit template arguments, e.g. getSubMat<3,4>(i,j).
869
870 template <int MM, int NN> struct SubMat {
872 };
873
874 template <int MM, int NN>
875 const typename SubMat<MM,NN>::Type& getSubMat(int i, int j) const {
876 assert(0 <= i && i + MM <= M);
877 assert(0 <= j && j + NN <= N);
878 return SubMat<MM,NN>::Type::getAs(&(*this)(i,j));
879 }
880 template <int MM, int NN>
881 typename SubMat<MM,NN>::Type& updSubMat(int i, int j) {
882 assert(0 <= i && i + MM <= M);
883 assert(0 <= j && j + NN <= N);
884 return SubMat<MM,NN>::Type::updAs(&(*this)(i,j));
885 }
886 template <int MM, int NN>
887 void setSubMat(int i, int j, const typename SubMat<MM,NN>::Type& value) {
888 assert(0 <= i && i + MM <= M);
889 assert(0 <= j && j + NN <= N);
890 SubMat<MM,NN>::Type::updAs(&(*this)(i,j)) = value;
891 }
892
895 TDropRow dropRow(int i) const {
896 assert(0 <= i && i < M);
898 for (int r=0, nxt=0; r<M-1; ++r, ++nxt) {
899 if (nxt==i) ++nxt; // skip the loser
900 out[r] = (*this)[nxt];
901 }
902 return out;
903 }
904
907 TDropCol dropCol(int j) const {
908 assert(0 <= j && j < N);
910 for (int c=0, nxt=0; c<N-1; ++c, ++nxt) {
911 if (nxt==j) ++nxt; // skip the loser
912 out(c) = (*this)(nxt);
913 }
914 return out;
915 }
916
920 TDropRowCol dropRowCol(int i, int j) const {
921 assert(0 <= i && i < M);
922 assert(0 <= j && j < N);
924 for (int c=0, nxtc=0; c<N-1; ++c, ++nxtc) {
925 if (nxtc==j) ++nxtc;
926 for (int r=0, nxtr=0; r<M-1; ++r, ++nxtr) {
927 if (nxtr==i) ++nxtr;
928 out(r,c) = (*this)(nxtr,nxtc);
929 }
930 }
931 return out;
932 }
933
937 template <class EE, int SS>
940 out.template updSubMat<M,N>(0,0) = (*this);
941 out[M] = row;
942 return out;
943 }
944
948 template <class EE, int SS>
951 out.template updSubMat<M,N>(0,0) = (*this);
952 out(N) = col;
953 return out;
954 }
955
962 template <class ER, int SR, class EC, int SC>
964 const Vec<M+1,EC,SC>& col) const
965 {
967 out.template updSubMat<M,N>(0,0) = (*this);
968 out[M].template updSubRow<N>(0) =
969 row.template getSubRow<N>(0); // ignore last element
970 out(N) = col;
971 return out;
972 }
973
979 template <class EE, int SS>
980 TAppendRow insertRow(int i, const Row<N,EE,SS>& row) const {
981 assert(0 <= i && i <= M);
982 if (i==M) return appendRow(row);
984 for (int r=0, nxt=0; r<M; ++r, ++nxt) {
985 if (nxt==i) out[nxt++] = row;
986 out[nxt] = (*this)[r];
987 }
988 return out;
989 }
990
996 template <class EE, int SS>
997 TAppendCol insertCol(int j, const Vec<M,EE,SS>& col) const {
998 assert(0 <= j && j <= N);
999 if (j==N) return appendCol(col);
1001 for (int c=0, nxt=0; c<N; ++c, ++nxt) {
1002 if (nxt==j) out(nxt++) = col;
1003 out(nxt) = (*this)(c);
1004 }
1005 return out;
1006 }
1007
1015 template <class ER, int SR, class EC, int SC>
1017 const Vec<M+1,EC,SC>& col) const {
1018 assert(0 <= i && i <= M);
1019 assert(0 <= j && j <= N);
1021 for (int c=0, nxtc=0; c<N; ++c, ++nxtc) {
1022 if (nxtc==j) ++nxtc; // leave room
1023 for (int r=0, nxtr=0; r<M; ++r, ++nxtr) {
1024 if (nxtr==i) ++nxtr;
1025 out(nxtr,nxtc) = (*this)(r,c);
1026 }
1027 }
1028 out[i] = row;
1029 out(j) = col; // overwrites row's j'th element
1030 return out;
1031 }
1032
1033 // These assume we are given a pointer to d[0] of a Mat<M,N,E,CS,RS> like this one.
1034 static const Mat& getAs(const ELT* p) {return *reinterpret_cast<const Mat*>(p);}
1035 static Mat& updAs(ELT* p) {return *reinterpret_cast<Mat*>(p);}
1036
1037 // Note packed spacing
1040 m.setToNaN();
1041 return m;
1042 }
1043
1045 bool isNaN() const {
1046 for (int j=0; j<N; ++j)
1047 if (this->col(j).isNaN())
1048 return true;
1049 return false;
1050 }
1051
1054 bool isInf() const {
1055 bool seenInf = false;
1056 for (int j=0; j<N; ++j) {
1057 if (!this->col(j).isFinite()) {
1058 if (!this->col(j).isInf())
1059 return false; // something bad was found
1060 seenInf = true;
1061 }
1062 }
1063 return seenInf;
1064 }
1065
1067 bool isFinite() const {
1068 for (int j=0; j<N; ++j)
1069 if (!this->col(j).isFinite())
1070 return false;
1071 return true;
1072 }
1073
1076 static double getDefaultTolerance() {return int(MinDim)*CNT<ELT>::getDefaultTolerance();}
1077
1080 template <class E2, int CS2, int RS2>
1081 bool isNumericallyEqual(const Mat<M,N,E2,CS2,RS2>& m, double tol) const {
1082 for (int j=0; j < N; ++j)
1083 if (!(*this)(j).isNumericallyEqual(m(j), tol))
1084 return false;
1085 return true;
1086 }
1087
1091 template <class E2, int CS2, int RS2>
1093 const double tol = std::max(getDefaultTolerance(),m.getDefaultTolerance());
1094 return isNumericallyEqual(m, tol);
1095 }
1096
1103 (const ELT& e,
1104 double tol = getDefaultTolerance()) const
1105 {
1106 for (int i=0; i<M; ++i)
1107 for (int j=0; j<N; ++j) {
1108 if (i==j) {
1109 if (!CNT<ELT>::isNumericallyEqual((*this)(i,i), e, tol))
1110 return false;
1111 } else {
1112 // off-diagonals must be zero
1113 if (!CNT<ELT>::isNumericallyEqual((*this)(i,j), ELT(0), tol))
1114 return false;
1115 }
1116 }
1117 return true;
1118 }
1119
1128 if (M != N) return false; // handled at compile time
1129 for (int j=0; j<M; ++j)
1130 for (int i=j; i<M; ++i)
1132 return false;
1133 return true;
1134 }
1135
1142 bool isExactlySymmetric() const {
1143 if (M != N) return false; // handled at compile time
1144 for (int j=0; j<M; ++j)
1145 for (int i=j; i<M; ++i)
1146 if (elt(j,i) != CNT<ELT>::transpose(elt(i,j)))
1147 return false;
1148 return true;
1149 }
1150
1152 TRow colSum() const {
1153 TRow temp;
1154 for (int j = 0; j < N; ++j)
1155 temp[j] = col(j).sum();
1156 return temp;
1157 }
1160 TRow sum() const {return colSum();}
1161
1163 TCol rowSum() const {
1164 TCol temp;
1165 for (int i = 0; i < M; ++i)
1166 temp[i] = row(i).sum();
1167 return temp;
1168 }
1169
1170 // Functions to be used for Scripting in MATLAB and languages that do not support operator overloading
1172 std::string toString() const {
1173 std::stringstream stream;
1174 stream << (*this) ;
1175 return stream.str();
1176 }
1178 const ELT& get(int i,int j) const { return elt(i,j); }
1180 void set(int i,int j, const ELT& value) { elt(i,j)=value; }
1181
1182private:
1183 E d[NActualElements];
1184
1185 // This permits running through d as though it were stored
1186 // in row order with packed elements. Pass in the k'th value
1187 // of the row ordering and get back the index into d where
1188 // that element is stored.
1189 int rIx(int k) const {
1190 const int row = k / N;
1191 const int col = k % N; // that's modulus, not cross product!
1192 return row*RS + col*CS;
1193 }
1194
1195 template<typename ElementsRowByRowTuple, int... Idx>
1196 void assignDataRowByRow(ElementsRowByRowTuple&& els, std::integer_sequence<int, Idx...>)
1197 {
1198 ((d[rIx(Idx)] = std::get<Idx>(els)) , ...);
1199 }
1200};
1201
1203// Global operators involving two matrices. //
1204// m+m, m-m, m*m, m==m, m!=m //
1206
1207template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline
1208typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >::Add
1210 return Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >
1211 ::AddOp::perform(l,r);
1212}
1213
1214template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline
1215typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >::Sub
1217 return Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >
1218 ::SubOp::perform(l,r);
1219}
1220
1221// Matrix multiply of an MxN by NxP to produce a packed MxP.
1222template <int M, int N, class EL, int CSL, int RSL, int P, class ER, int CSR, int RSR> inline
1223typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<N,P,ER,CSR,RSR> >::Mul
1225 return Mat<M,N,EL,CSL,RSL>::template Result<Mat<N,P,ER,CSR,RSR> >
1226 ::MulOp::perform(l,r);
1227}
1228
1229// Non-conforming matrix multiply of an MxN by MMxNN; will be a scalar multiply if one
1230// has scalar elements and the other has composite elements.
1231template <int M, int N, class EL, int CSL, int RSL, int MM, int NN, class ER, int CSR, int RSR> inline
1232typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<MM,NN,ER,CSR,RSR> >::MulNon
1234 return Mat<M,N,EL,CSL,RSL>::template Result<Mat<MM,NN,ER,CSR,RSR> >
1235 ::MulOpNonConforming::perform(l,r);
1236}
1237
1238template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline
1240 for (int j=0; j<N; ++j)
1241 if (l(j) != r(j)) return false;
1242 return true;
1243}
1244template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline
1246 return !(l==r);
1247}
1248
1249
1251// Global operators involving a matrix and a scalar. //
1253
1254// SCALAR MULTIPLY
1255
1256// m = m*real, real*m
1257template <int M, int N, class E, int CS, int RS> inline
1258typename Mat<M,N,E,CS,RS>::template Result<float>::Mul
1259operator*(const Mat<M,N,E,CS,RS>& l, const float& r)
1260 { return Mat<M,N,E,CS,RS>::template Result<float>::MulOp::perform(l,r); }
1261template <int M, int N, class E, int CS, int RS> inline
1262typename Mat<M,N,E,CS,RS>::template Result<float>::Mul
1263operator*(const float& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
1264
1265template <int M, int N, class E, int CS, int RS> inline
1266typename Mat<M,N,E,CS,RS>::template Result<double>::Mul
1267operator*(const Mat<M,N,E,CS,RS>& l, const double& r)
1268 { return Mat<M,N,E,CS,RS>::template Result<double>::MulOp::perform(l,r); }
1269template <int M, int N, class E, int CS, int RS> inline
1270typename Mat<M,N,E,CS,RS>::template Result<double>::Mul
1271operator*(const double& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
1272
1273// m = m*int, int*m -- just convert int to m's precision float
1274template <int M, int N, class E, int CS, int RS> inline
1275typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Mul
1276operator*(const Mat<M,N,E,CS,RS>& l, int r) {return l * (typename CNT<E>::Precision)r;}
1277template <int M, int N, class E, int CS, int RS> inline
1278typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Mul
1279operator*(int l, const Mat<M,N,E,CS,RS>& r) {return r * (typename CNT<E>::Precision)l;}
1280
1281// Complex, conjugate, and negator are all easy to templatize.
1282
1283// m = m*complex, complex*m
1284template <int M, int N, class E, int CS, int RS, class R> inline
1285typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
1286operator*(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
1287 { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::MulOp::perform(l,r); }
1288template <int M, int N, class E, int CS, int RS, class R> inline
1289typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
1290operator*(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
1291
1292// m = m*conjugate, conjugate*m (convert conjugate->complex)
1293template <int M, int N, class E, int CS, int RS, class R> inline
1294typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
1295operator*(const Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l*(std::complex<R>)r;}
1296template <int M, int N, class E, int CS, int RS, class R> inline
1297typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
1298operator*(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return r*(std::complex<R>)l;}
1299
1300// m = m*negator, negator*m: convert negator to standard number
1301template <int M, int N, class E, int CS, int RS, class R> inline
1302typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Mul
1303operator*(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l * (typename negator<R>::StdNumber)(R)r;}
1304template <int M, int N, class E, int CS, int RS, class R> inline
1305typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Mul
1306operator*(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return r * (typename negator<R>::StdNumber)(R)l;}
1307
1308
1309// SCALAR DIVIDE. This is a scalar operation when the scalar is on the right,
1310// but when it is on the left it means scalar * pseudoInverse(mat),
1311// which is a matrix whose type is like the matrix's Hermitian transpose.
1312// TODO: for now it is just going to call mat.invert() which will fail on
1313// singular matrices.
1314
1315// m = m/real, real/m
1316template <int M, int N, class E, int CS, int RS> inline
1317typename Mat<M,N,E,CS,RS>::template Result<float>::Dvd
1318operator/(const Mat<M,N,E,CS,RS>& l, const float& r)
1319{ return Mat<M,N,E,CS,RS>::template Result<float>::DvdOp::perform(l,r); }
1320
1321template <int M, int N, class E, int CS, int RS> inline
1322typename CNT<float>::template Result<Mat<M,N,E,CS,RS> >::Dvd
1323operator/(const float& l, const Mat<M,N,E,CS,RS>& r)
1324{ return l * r.invert(); }
1325
1326template <int M, int N, class E, int CS, int RS> inline
1327typename Mat<M,N,E,CS,RS>::template Result<double>::Dvd
1328operator/(const Mat<M,N,E,CS,RS>& l, const double& r)
1329{ return Mat<M,N,E,CS,RS>::template Result<double>::DvdOp::perform(l,r); }
1330
1331template <int M, int N, class E, int CS, int RS> inline
1332typename CNT<double>::template Result<Mat<M,N,E,CS,RS> >::Dvd
1333operator/(const double& l, const Mat<M,N,E,CS,RS>& r)
1334{ return l * r.invert(); }
1335
1336// m = m/int, int/m -- just convert int to m's precision float
1337template <int M, int N, class E, int CS, int RS> inline
1338typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Dvd
1340{ return l / (typename CNT<E>::Precision)r; }
1341
1342template <int M, int N, class E, int CS, int RS> inline
1343typename CNT<typename CNT<E>::Precision>::template Result<Mat<M,N,E,CS,RS> >::Dvd
1345{ return (typename CNT<E>::Precision)l / r; }
1346
1347
1348// Complex, conjugate, and negator are all easy to templatize.
1349
1350// m = m/complex, complex/m
1351template <int M, int N, class E, int CS, int RS, class R> inline
1352typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Dvd
1353operator/(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
1354 { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::DvdOp::perform(l,r); }
1355template <int M, int N, class E, int CS, int RS, class R> inline
1356typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Dvd
1357operator/(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r)
1358 { return CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::DvdOp::perform(l,r); }
1359
1360// m = m/conjugate, conjugate/m (convert conjugate->complex)
1361template <int M, int N, class E, int CS, int RS, class R> inline
1362typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Dvd
1363operator/(const Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l/(std::complex<R>)r;}
1364template <int M, int N, class E, int CS, int RS, class R> inline
1365typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Dvd
1366operator/(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return (std::complex<R>)l/r;}
1367
1368// m = m/negator, negator/m: convert negator to a standard number
1369template <int M, int N, class E, int CS, int RS, class R> inline
1370typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Dvd
1371operator/(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l/(typename negator<R>::StdNumber)(R)r;}
1372template <int M, int N, class E, int CS, int RS, class R> inline
1373typename CNT<R>::template Result<Mat<M,N,E,CS,RS> >::Dvd
1374operator/(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return (typename negator<R>::StdNumber)(R)l/r;}
1375
1376
1377// Add and subtract are odd as scalar ops. They behave as though the
1378// scalar stands for a conforming matrix whose diagonal elements are that,
1379// scalar and then a normal matrix add or subtract is done.
1380
1381// SCALAR ADD
1382
1383// m = m+real, real+m
1384template <int M, int N, class E, int CS, int RS> inline
1385typename Mat<M,N,E,CS,RS>::template Result<float>::Add
1386operator+(const Mat<M,N,E,CS,RS>& l, const float& r)
1387 { return Mat<M,N,E,CS,RS>::template Result<float>::AddOp::perform(l,r); }
1388template <int M, int N, class E, int CS, int RS> inline
1389typename Mat<M,N,E,CS,RS>::template Result<float>::Add
1390operator+(const float& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
1391
1392template <int M, int N, class E, int CS, int RS> inline
1393typename Mat<M,N,E,CS,RS>::template Result<double>::Add
1394operator+(const Mat<M,N,E,CS,RS>& l, const double& r)
1395 { return Mat<M,N,E,CS,RS>::template Result<double>::AddOp::perform(l,r); }
1396template <int M, int N, class E, int CS, int RS> inline
1397typename Mat<M,N,E,CS,RS>::template Result<double>::Add
1398operator+(const double& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
1399
1400// m = m+int, int+m -- just convert int to m's precision float
1401template <int M, int N, class E, int CS, int RS> inline
1402typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Add
1403operator+(const Mat<M,N,E,CS,RS>& l, int r) {return l + (typename CNT<E>::Precision)r;}
1404template <int M, int N, class E, int CS, int RS> inline
1405typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Add
1406operator+(int l, const Mat<M,N,E,CS,RS>& r) {return r + (typename CNT<E>::Precision)l;}
1407
1408// Complex, conjugate, and negator are all easy to templatize.
1409
1410// m = m+complex, complex+m
1411template <int M, int N, class E, int CS, int RS, class R> inline
1412typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
1413operator+(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
1414 { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::AddOp::perform(l,r); }
1415template <int M, int N, class E, int CS, int RS, class R> inline
1416typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
1417operator+(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
1418
1419// m = m+conjugate, conjugate+m (convert conjugate->complex)
1420template <int M, int N, class E, int CS, int RS, class R> inline
1421typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
1422operator+(const Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l+(std::complex<R>)r;}
1423template <int M, int N, class E, int CS, int RS, class R> inline
1424typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
1425operator+(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return r+(std::complex<R>)l;}
1426
1427// m = m+negator, negator+m: convert negator to standard number
1428template <int M, int N, class E, int CS, int RS, class R> inline
1429typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Add
1430operator+(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l + (typename negator<R>::StdNumber)(R)r;}
1431template <int M, int N, class E, int CS, int RS, class R> inline
1432typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Add
1433operator+(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return r + (typename negator<R>::StdNumber)(R)l;}
1434
1435// SCALAR SUBTRACT -- careful, not commutative.
1436
1437// m = m-real, real-m
1438template <int M, int N, class E, int CS, int RS> inline
1439typename Mat<M,N,E,CS,RS>::template Result<float>::Sub
1440operator-(const Mat<M,N,E,CS,RS>& l, const float& r)
1441 { return Mat<M,N,E,CS,RS>::template Result<float>::SubOp::perform(l,r); }
1442template <int M, int N, class E, int CS, int RS> inline
1443typename CNT<float>::template Result<Mat<M,N,E,CS,RS> >::Sub
1444operator-(const float& l, const Mat<M,N,E,CS,RS>& r)
1445 { return CNT<float>::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
1446
1447template <int M, int N, class E, int CS, int RS> inline
1448typename Mat<M,N,E,CS,RS>::template Result<double>::Sub
1449operator-(const Mat<M,N,E,CS,RS>& l, const double& r)
1450 { return Mat<M,N,E,CS,RS>::template Result<double>::SubOp::perform(l,r); }
1451template <int M, int N, class E, int CS, int RS> inline
1452typename CNT<double>::template Result<Mat<M,N,E,CS,RS> >::Sub
1453operator-(const double& l, const Mat<M,N,E,CS,RS>& r)
1454 { return CNT<double>::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
1455
1456// m = m-int, int-m // just convert int to m's precision float
1457template <int M, int N, class E, int CS, int RS> inline
1458typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Sub
1459operator-(const Mat<M,N,E,CS,RS>& l, int r) {return l - (typename CNT<E>::Precision)r;}
1460template <int M, int N, class E, int CS, int RS> inline
1461typename CNT<typename CNT<E>::Precision>::template Result<Mat<M,N,E,CS,RS> >::Sub
1462operator-(int l, const Mat<M,N,E,CS,RS>& r) {return (typename CNT<E>::Precision)l - r;}
1463
1464
1465// Complex, conjugate, and negator are all easy to templatize.
1466
1467// m = m-complex, complex-m
1468template <int M, int N, class E, int CS, int RS, class R> inline
1469typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Sub
1470operator-(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
1471 { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::SubOp::perform(l,r); }
1472template <int M, int N, class E, int CS, int RS, class R> inline
1473typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Sub
1474operator-(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r)
1475 { return CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
1476
1477// m = m-conjugate, conjugate-m (convert conjugate->complex)
1478template <int M, int N, class E, int CS, int RS, class R> inline
1479typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Sub
1480operator-(const Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l-(std::complex<R>)r;}
1481template <int M, int N, class E, int CS, int RS, class R> inline
1482typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Sub
1483operator-(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return (std::complex<R>)l-r;}
1484
1485// m = m-negator, negator-m: convert negator to standard number
1486template <int M, int N, class E, int CS, int RS, class R> inline
1487typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Sub
1488operator-(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l-(typename negator<R>::StdNumber)(R)r;}
1489template <int M, int N, class E, int CS, int RS, class R> inline
1490typename CNT<R>::template Result<Mat<M,N,E,CS,RS> >::Sub
1491operator-(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return (typename negator<R>::StdNumber)(R)l-r;}
1492
1493
1494// Mat I/O
1495template <int M, int N, class E, int CS, int RS, class CHAR, class TRAITS> inline
1496std::basic_ostream<CHAR,TRAITS>&
1497operator<<(std::basic_ostream<CHAR,TRAITS>& o, const Mat<M,N,E,CS,RS>& m) {
1498 for (int i=0;i<M;++i) {
1499 o << std::endl << "[";
1500 for (int j=0;j<N;++j)
1501 o << (j>0?",":"") << m(i,j);
1502 o << "]";
1503 }
1504 if (M) o << std::endl;
1505 return o;
1506}
1507
1508template <int M, int N, class E, int CS, int RS, class CHAR, class TRAITS> inline
1509std::basic_istream<CHAR,TRAITS>&
1510operator>>(std::basic_istream<CHAR,TRAITS>& is, Mat<M,N,E,CS,RS>& m) {
1511 // TODO: not sure how to do Vec input yet
1512 assert(false);
1513 return is;
1514}
1515
1516} //namespace SimTK
1517
1518
1519#endif //SimTK_SIMMATRIX_SMALLMATRIX_MAT_H_
#define SimTK_INDEXCHECK(ix, ub, where)
Definition ExceptionMacros.h:145
Mandatory first inclusion for any Simbody source or header file.
#define SimTK_NODISCARD
Warn if a caller fails to capture or use the return value of a method.
Definition SimTKcommon/include/SimTKcommon/internal/common.h:315
Specialized information about Composite Numerical Types which allows us to define appropriate templat...
Definition CompositeNumericalTypes.h:136
K::ULessScalar ULessScalar
Definition CompositeNumericalTypes.h:161
static double getDefaultTolerance()
Definition CompositeNumericalTypes.h:269
K::ScalarNormSq ScalarNormSq
Definition CompositeNumericalTypes.h:166
K::StdNumber StdNumber
Definition CompositeNumericalTypes.h:163
static TSqrt sqrt(const K &t)
Definition CompositeNumericalTypes.h:239
K::TSqHermT TSqHermT
Definition CompositeNumericalTypes.h:146
K::TSqrt TSqrt
Definition CompositeNumericalTypes.h:154
K::TInvert TInvert
Definition CompositeNumericalTypes.h:157
K::TNormalize TNormalize
Definition CompositeNumericalTypes.h:158
K::TWithoutNegator TWithoutNegator
Definition CompositeNumericalTypes.h:140
K::TReal TReal
Definition CompositeNumericalTypes.h:141
K::THerm THerm
Definition CompositeNumericalTypes.h:144
K::TPosTrans TPosTrans
Definition CompositeNumericalTypes.h:145
K::TNeg TNeg
Definition CompositeNumericalTypes.h:139
K::TStandard TStandard
Definition CompositeNumericalTypes.h:156
K::TComplex TComplex
Definition CompositeNumericalTypes.h:143
K::TSqTHerm TSqTHerm
Definition CompositeNumericalTypes.h:147
K::TImag TImag
Definition CompositeNumericalTypes.h:142
K::Precision Precision
Definition CompositeNumericalTypes.h:164
K::Scalar Scalar
Definition CompositeNumericalTypes.h:160
K::TAbs TAbs
Definition CompositeNumericalTypes.h:155
K::Number Number
Definition CompositeNumericalTypes.h:162
This class represents a small matrix whose size is known at compile time, containing elements of any ...
Definition Mat.h:100
Mat()
Default construction initializes to NaN when debugging but is left uninitialized otherwise to ensure ...
Definition Mat.h:290
CNT< E >::TImag EImag
Definition Mat.h:106
SubMat< MM, NN >::Type & updSubMat(int i, int j)
Definition Mat.h:881
Mat< M, N, E2, CS2, RS2 >::template Result< Mat >::Sub conformingSubtractFromLeft(const Mat< M, N, E2, CS2, RS2 > &l) const
Definition Mat.h:557
Mat(const SymMat< M, ELT > &src)
Explicit construction of a Mat from a SymMat (symmetric/Hermitian matrix).
Definition Mat.h:319
const E & elt(int i, int j) const
Definition Mat.h:739
void setSubMat(int i, int j, const typename SubMat< MM, NN >::Type &value)
Definition Mat.h:887
Result< SymMat< M, E2, RS2 > >::Sub conformingSubtract(const SymMat< M, E2, RS2 > &sy) const
Definition Mat.h:592
TAppendRowCol appendRowCol(const Row< N+1, ER, SR > &row, const Vec< M+1, EC, SC > &col) const
Return a matrix one row and one column larger than this one by adding a row to the bottom and a colum...
Definition Mat.h:963
Result< Mat< N, N2, E2, CS2, RS2 > >::Mul conformingMultiply(const Mat< N, N2, E2, CS2, RS2 > &m) const
Definition Mat.h:607
Mat< M, N, typename CNT< EE >::template Result< E >::Dvd > scalarDivideFromLeft(const EE &e) const
Definition Mat.h:793
EltResult< E2 >::Dvd elementwiseDivide(const Mat< M, N, E2, CS2, RS2 > &r) const
Definition Mat.h:574
Mat & scalarTimesEqFromLeft(const EE &ee)
Definition Mat.h:849
TWithoutNegator & updCastAwayNegatorIfAny()
Definition Mat.h:719
Mat< M-1, N-1, E, M-1, 1 > TDropRowCol
Definition Mat.h:185
Mat< M, N+1, E, M, 1 > TAppendCol
Definition Mat.h:187
Mat(const TCol &r0, const TCol &r1, const TCol &r2, const TCol &r3)
Definition Mat.h:448
static int nrow()
Return the number of rows in this Mat, echoing the value supplied for the template parameter M.
Definition Mat.h:203
const TReal & real() const
Definition Mat.h:697
Mat(const TCol &r0)
Definition Mat.h:442
const TCol & operator()(int j) const
Definition Mat.h:636
CNT< E >::TComplex EComplex
Definition Mat.h:107
CNT< E >::TStandard EStandard
Definition Mat.h:115
EStdNumber StdNumber
Definition Mat.h:193
Mat< M, N, ENeg, CS, RS > TNeg
Definition Mat.h:154
void setToNaN()
Definition Mat.h:857
E & elt(int i, int j)
Definition Mat.h:744
TInvert invert() const
Definition SmallMatrixMixed.h:1004
THerm TransposeType
Definition Mat.h:197
Mat(const TRow &r0, const TRow &r1, const TRow &r2, const TRow &r3, const TRow &r4)
Definition Mat.h:408
Mat & scalarDivideEqFromLeft(const EE &ee)
Definition Mat.h:854
static double getDefaultTolerance()
For approximate comparisons, the default tolerance to use for a matrix is its shortest dimension time...
Definition Mat.h:1076
TRow & operator[](int i)
Definition Mat.h:635
Mat(const Row< N, EE, SS > &r0, const Row< N, EE, SS > &r1, const Row< N, EE, SS > &r2, const Row< N, EE, SS > &r3, const Row< N, EE, SS > &r4)
Definition Mat.h:430
Mat< M, N, EAbs, M, 1 > TAbs
Definition Mat.h:172
TRow sum() const
This is an alternate name for colSum(); behaves like the Matlab function of the same name.
Definition Mat.h:1160
bool isNumericallyEqual(const Mat< M, N, E2, CS2, RS2 > &m, double tol) const
Test whether this matrix is numerically equal to some other matrix with the same shape,...
Definition Mat.h:1081
CNT< E >::TWithoutNegator EWithoutNegator
Definition Mat.h:104
CNT< E >::TSqHermT ESqHermT
Definition Mat.h:110
Mat< M, N, typename CNT< EE >::template Result< E >::Mul > scalarMultiplyFromLeft(const EE &e) const
Definition Mat.h:778
Mat< M, N, EStandard, M, 1 > TStandard
Definition Mat.h:173
Result< Mat< M2, N, E2, CS2, RS2 > >::Dvd conformingDivide(const Mat< M2, N, E2, CS2, RS2 > &m) const
Definition Mat.h:624
TDropRow dropRow(int i) const
Return a matrix one row smaller than this one by dropping row i.
Definition Mat.h:895
CNT< E >::Number ENumber
Definition Mat.h:121
Mat(const Row< N, EE, SS > &r0, const Row< N, EE, SS > &r1)
Definition Mat.h:420
Mat(Elements &&... elementsRowByRow)
Definition Mat.h:390
const THerm & transpose() const
Definition Mat.h:685
ScalarNormSq normSqr() const
Definition Mat.h:643
SymMat< N, ESqHermT > TSqHermT
Definition Mat.h:177
Mat(const Row< N, EE, SS > &r0)
Definition Mat.h:418
Mat & scalarMinusEqFromLeft(const EE &ee)
Definition Mat.h:844
EScalar Scalar
Definition Mat.h:190
Mat(const Vec< M, EE, SS > &r0, const Vec< M, EE, SS > &r1, const Vec< M, EE, SS > &r2, const Vec< M, EE, SS > &r3)
Definition Mat.h:469
TStandard standardize() const
Definition Mat.h:237
EScalarNormSq ScalarNormSq
Definition Mat.h:195
TReal & real()
Definition Mat.h:698
static const Mat & getAs(const ELT *p)
Definition Mat.h:1034
EStandard trace() const
Definition Mat.h:762
CNT< E >::TAbs EAbs
Definition Mat.h:114
ScalarNormSq scalarNormSqr() const
Scalar norm square is the sum of squares of all the scalars that comprise the value of this Mat.
Definition Mat.h:213
CNT< ScalarNormSq >::TSqrt norm() const
Definition Mat.h:645
Mat< M, N, typename CNT< E >::template Result< EE >::Sub > scalarSubtract(const EE &e) const
Definition Mat.h:809
Mat & operator-=(const Mat< M, N, negator< EE >, CSS, RSS > &mm)
Definition Mat.h:519
Mat(const TCol &r0, const TCol &r1, const TCol &r2, const TCol &r3, const TCol &r4, const TCol &r5)
Definition Mat.h:455
Mat< M, N, E, M, 1 > TPacked
Definition Mat.h:182
Vec< M, E, RS > TCol
Definition Mat.h:166
EltResult< E2 >::Mul elementwiseMultiply(const Mat< M, N, E2, CS2, RS2 > &r) const
Definition Mat.h:564
const TRow & operator[](int i) const
Definition Mat.h:634
Mat(const Vec< M, EE, SS > &r0)
Definition Mat.h:461
TAbs abs() const
Elementwise absolute value; that is, the return value has the same dimensions as this Mat but with ea...
Definition Mat.h:231
TPosTrans & updPositionalTranspose()
Definition Mat.h:690
const E & operator()(int i, int j) const
Definition Mat.h:639
CNT< E >::ScalarNormSq EScalarNormSq
Definition Mat.h:124
Mat< N, M, E, RS, CS > TPosTrans
Definition Mat.h:163
ELT E
Definition Mat.h:102
static int ncol()
Return the number of columns in this Mat, echoing the value supplied for the template parameter N.
Definition Mat.h:206
Mat< M2, N, E2, CS2, RS2 >::template Result< Mat >::Dvd conformingDivideFromLeft(const Mat< M2, N, E2, CS2, RS2 > &m) const
Definition Mat.h:630
Mat(const Row< N, EE, SS > &r0, const Row< N, EE, SS > &r1, const Row< N, EE, SS > &r2)
Definition Mat.h:423
bool isExactlySymmetric() const
A Matrix is symmetric (actually Hermitian) if it is square and each element (i,j) is the Hermitian (c...
Definition Mat.h:1142
CNT< E >::Precision EPrecision
Definition Mat.h:123
Mat< M, N, typename CNT< EE >::template Result< E >::Sub > scalarSubtractFromLeft(const EE &e) const
Definition Mat.h:816
CNT< E >::TPosTrans EPosTrans
Definition Mat.h:109
Mat & scalarPlusEq(const EE &ee)
Definition Mat.h:838
CNT< E >::TNormalize ENormalize
Definition Mat.h:117
const TPosTrans & positionalTranspose() const
Definition Mat.h:688
SymMat< M, ESqTHerm > TSqTHerm
Definition Mat.h:178
Mat & scalarDivideEq(const EE &ee)
Definition Mat.h:852
Row< N, E, CS > TRow
Definition Mat.h:165
Mat< M, N, E, CS, RS > T
Definition Mat.h:153
Mat(const TRow &r0, const TRow &r1, const TRow &r2)
Definition Mat.h:403
Mat< M, N, ENormalize, M, 1 > TNormalize
Definition Mat.h:175
Mat & operator+=(const Mat< M, N, EE, CSS, RSS > &mm)
Definition Mat.h:503
Mat(const TCol &r0, const TCol &r1, const TCol &r2, const TCol &r3, const TCol &r4)
Definition Mat.h:451
const TRow & row(int i) const
Definition Mat.h:721
TRow colSum() const
Returns a row vector (Row) containing the column sums of this matrix.
Definition Mat.h:1152
TCol & col(int j)
Definition Mat.h:734
Mat(const Mat &src)
Copy constructor copies only the elements that are present and does not touch any unused memory space...
Definition Mat.h:302
Mat(const TRow &r0, const TRow &r1, const TRow &r2, const TRow &r3, const TRow &r4, const TRow &r5)
Definition Mat.h:412
Mat & scalarEq(const EE &ee)
Definition Mat.h:833
Result< Mat< M, N, E2, CS2, RS2 > >::Add conformingAdd(const Mat< M, N, E2, CS2, RS2 > &r) const
Definition Mat.h:541
TRow & row(int i)
Definition Mat.h:725
TNeg & updNegate()
Definition Mat.h:683
CNT< E >::TSqrt ESqrt
Definition Mat.h:113
Mat< M, N, typename CNT< E >::template Result< EE >::Mul > scalarMultiply(const EE &e) const
Definition Mat.h:772
Mat & operator*=(const Mat< N, N, EE, CSS, RSS > &mm)
Definition Mat.h:527
ENumber Number
Definition Mat.h:192
TNormalize normalize() const
Definition Mat.h:660
static int size()
Return the total number of elements M*N contained in this Mat.
Definition Mat.h:200
TAppendCol insertCol(int j, const Vec< M, EE, SS > &col) const
Return a matrix one column larger than this one by inserting a column before column j.
Definition Mat.h:997
Mat & operator=(const Mat< M, N, EE, CSS, RSS > &mm)
Definition Mat.h:491
Mat(const Mat< M, N, E, CSS, RSS > &src)
This provides an implicit conversion from a Mat of the same dimensions and element type but with diff...
Definition Mat.h:333
CNT< E >::TInvert EInvert
Definition Mat.h:116
const TNeg & negate() const
Definition Mat.h:682
void set(int i, int j, const ELT &value)
Variant of indexing operator that's scripting friendly to set entry (i, j)
Definition Mat.h:1180
E & operator()(int i, int j)
Definition Mat.h:640
Mat & operator-=(const EE &e)
Definition Mat.h:827
Mat< M+1, N, E, M+1, 1 > TAppendRow
Definition Mat.h:186
CNT< E >::Scalar EScalar
Definition Mat.h:119
bool isFinite() const
Return true if no element contains an Infinity or a NaN.
Definition Mat.h:1067
Vec< MinDim, E, RS+CS > TDiag
Definition Mat.h:167
Mat< M2, M, E2, CS2, RS2 >::template Result< Mat >::Mul conformingMultiplyFromLeft(const Mat< M2, M, E2, CS2, RS2 > &m) const
Definition Mat.h:617
TSqrt sqrt() const
Elementwise square root; that is, the return value has the same dimensions as this Mat but with each ...
Definition Mat.h:222
CNT< E >::TReal EReal
Definition Mat.h:105
TDiag & diag()
This non-const version of diag() is an alternate name for updDiag() available for historical reasons.
Definition Mat.h:760
bool isNumericallyEqual(const ELT &e, double tol=getDefaultTolerance()) const
Test whether this is numerically a "scalar" matrix, meaning that it is a diagonal matrix in which eac...
Definition Mat.h:1103
@ NPackedElements
Definition Mat.h:135
@ ImagOffset
Definition Mat.h:138
@ ArgDepth
Definition Mat.h:141
@ NCols
Definition Mat.h:130
@ RowSpacing
Definition Mat.h:133
@ RealStrideFactor
Definition Mat.h:139
@ NActualElements
Definition Mat.h:136
@ IsPrecision
Definition Mat.h:148
@ IsScalar
Definition Mat.h:144
@ IsNumber
Definition Mat.h:146
@ ColSpacing
Definition Mat.h:134
@ SignInterpretation
Definition Mat.h:149
@ IsStdNumber
Definition Mat.h:147
@ NActualScalars
Definition Mat.h:137
@ NRows
Definition Mat.h:129
@ MinDim
Definition Mat.h:131
@ IsULessScalar
Definition Mat.h:145
Result< SymMat< M, E2, RS2 > >::Add conformingAdd(const SymMat< M, E2, RS2 > &sy) const
Definition Mat.h:585
const SubMat< MM, NN >::Type & getSubMat(int i, int j) const
Definition Mat.h:875
TNeg & operator-()
Definition Mat.h:678
Mat(const EE *p)
Definition Mat.h:485
static Mat & updAs(ELT *p)
Definition Mat.h:1035
TAppendRowCol insertRowCol(int i, int j, const Row< N+1, ER, SR > &row, const Vec< M+1, EC, SC > &col) const
Return a matrix one row and one column larger than this one by inserting a row before row i and a col...
Definition Mat.h:1016
TAppendRow appendRow(const Row< N, EE, SS > &row) const
Return a matrix one row larger than this one by adding a row to the end.
Definition Mat.h:938
static Mat< M, N, ELT, M, 1 > getNaN()
Definition Mat.h:1038
Mat< M-1, N, E, M-1, 1 > TDropRow
Definition Mat.h:183
THerm & updTranspose()
Definition Mat.h:686
Mat(const E &e)
Explicit construction from a single element e of this Mat's element type E sets all the main diagonal...
Definition Mat.h:363
const ELT & get(int i, int j) const
Variant of indexing operator that's scripting friendly to get entry (i, j)
Definition Mat.h:1178
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:753
CNT< E >::TNeg ENeg
Definition Mat.h:103
Mat(int i)
Explicit construction from an int value means we convert the int into an object of this Mat's element...
Definition Mat.h:379
Mat< N, M, EInvert, N, 1 > TInvert
Definition Mat.h:174
CNT< E >::THerm EHerm
Definition Mat.h:108
Mat(const Row< N, EE, SS > &r0, const Row< N, EE, SS > &r1, const Row< N, EE, SS > &r2, const Row< N, EE, SS > &r3)
Definition Mat.h:426
const TCol & col(int j) const
Definition Mat.h:730
std::string toString() const
toString() returns a string representation of the Mat.
Definition Mat.h:1172
bool isNaN() const
Return true if any element of this Mat contains a NaN anywhere.
Definition Mat.h:1045
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:1127
TCol rowSum() const
Returns a column vector (Vec) containing the row sums of this matrix.
Definition Mat.h:1163
TAppendCol appendCol(const Vec< M, EE, SS > &col) const
Return a matrix one column larger than this one by adding a column to the end.
Definition Mat.h:949
EULessScalar ULessScalar
Definition Mat.h:191
Mat & operator+=(const EE &e)
Definition Mat.h:826
bool isInf() const
Return true if any element of this Mat contains a +Inf or -Inf somewhere but no element contains a Na...
Definition Mat.h:1054
Mat< M, N-1, E, M, 1 > TDropCol
Definition Mat.h:184
Mat & operator*=(const EE &e)
Definition Mat.h:828
Mat< M, N, EReal, CS *CNT< E >::RealStrideFactor, RS *CNT< E >::RealStrideFactor > TReal
Definition Mat.h:158
Mat< M, N, ESqrt, M, 1 > TSqrt
Definition Mat.h:171
SymMat< M, E2, RS2 >::template Result< Mat >::Sub conformingSubtractFromLeft(const SymMat< M, E2, RS2 > &sy) const
Definition Mat.h:599
const THerm & operator~() const
Definition Mat.h:679
Mat & operator/=(const EE &e)
Definition Mat.h:829
TDropCol dropCol(int j) const
Return a matrix one column smaller than this one by dropping column j.
Definition Mat.h:907
TAppendRow insertRow(int i, const Row< N, EE, SS > &row) const
Return a matrix one row larger than this one by inserting a row before row i.
Definition Mat.h:980
const TWithoutNegator & castAwayNegatorIfAny() const
Definition Mat.h:718
Mat< M+1, N+1, E, M+1, 1 > TAppendRowCol
Definition Mat.h:188
Mat< M, N, EComplex, CS, RS > TComplex
Definition Mat.h:161
CNT< E >::ULessScalar EULessScalar
Definition Mat.h:120
TDiag & updDiag()
Select main diagonal (of largest leading square if rectangular) and return it as a writable view (as ...
Definition Mat.h:757
Mat(const TCol &r0, const TCol &r1, const TCol &r2)
Definition Mat.h:446
Result< Mat< M, N, E2, CS2, RS2 > >::Sub conformingSubtract(const Mat< M, N, E2, CS2, RS2 > &r) const
Definition Mat.h:549
const Mat & operator+() const
Definition Mat.h:676
Mat(const Vec< M, EE, SS > &r0, const Vec< M, EE, SS > &r1, const Vec< M, EE, SS > &r2, const Vec< M, EE, SS > &r3, const Vec< M, EE, SS > &r4)
Definition Mat.h:473
Mat(const Mat< M, N, EE, CSS, RSS > &mm)
Explicit construction of a Mat from a source Mat of the same dimensions and an assignment-compatible ...
Definition Mat.h:357
Mat(const TRow &r0)
Definition Mat.h:399
Mat & operator-=(const Mat< M, N, EE, CSS, RSS > &mm)
Definition Mat.h:514
Mat(const TRow &r0, const TRow &r1)
Definition Mat.h:401
Mat(const Mat< M, N, ENeg, CSS, RSS > &src)
This provides an implicit conversion from a Mat of the same dimensions and negated element type,...
Definition Mat.h:344
CNT< E >::StdNumber EStdNumber
Definition Mat.h:122
Mat(const ENeg &e)
Explicit construction from a single element e whose type is negator<E> (abbreviated ENeg here) where ...
Definition Mat.h:370
Mat< M, N, EImag, CS *CNT< E >::RealStrideFactor, RS *CNT< E >::RealStrideFactor > TImag
Definition Mat.h:160
Mat(const TCol &r0, const TCol &r1)
Definition Mat.h:444
TImag & imag()
Definition Mat.h:712
const TImag & imag() const
Definition Mat.h:707
Mat & scalarTimesEq(const EE &ee)
Definition Mat.h:847
Mat(const Vec< M, EE, SS > &r0, const Vec< M, EE, SS > &r1, const Vec< M, EE, SS > &r2, const Vec< M, EE, SS > &r3, const Vec< M, EE, SS > &r4, const Vec< M, EE, SS > &r5)
Definition Mat.h:478
Mat & scalarMinusEq(const EE &ee)
Definition Mat.h:841
Mat< M, N, EWithoutNegator, CS, RS > TWithoutNegator
Definition Mat.h:155
Mat & operator=(const Mat &src)
Copy assignment copies only the elements that are present and does not touch any unused memory space ...
Definition Mat.h:309
Mat & operator+=(const Mat< M, N, negator< EE >, CSS, RSS > &mm)
Definition Mat.h:508
void setToZero()
Definition Mat.h:862
Mat(const Vec< M, EE, SS > &r0, const Vec< M, EE, SS > &r1)
Definition Mat.h:463
Mat< M, N, typename CNT< E >::template Result< EE >::Add > scalarAdd(const EE &e) const
Definition Mat.h:801
Mat< N, M, EHerm, RS, CS > THerm
Definition Mat.h:162
Mat(const Vec< M, EE, SS > &r0, const Vec< M, EE, SS > &r1, const Vec< M, EE, SS > &r2)
Definition Mat.h:466
EPrecision Precision
Definition Mat.h:194
E TElement
Definition Mat.h:164
TCol & operator()(int j)
Definition Mat.h:637
TDropRowCol dropRowCol(int i, int j) const
Return a matrix one row and one column smaller than this one by dropping row i and column j.
Definition Mat.h:920
Mat & operator=(const EE *p)
Definition Mat.h:496
const TNeg & operator-() const
Definition Mat.h:677
Mat< M, N, typename CNT< E >::template Result< EE >::Dvd > scalarDivide(const EE &e) const
Definition Mat.h:787
Mat(const TRow &r0, const TRow &r1, const TRow &r2, const TRow &r3)
Definition Mat.h:405
THerm & operator~()
Definition Mat.h:680
Mat(const Row< N, EE, SS > &r0, const Row< N, EE, SS > &r1, const Row< N, EE, SS > &r2, const Row< N, EE, SS > &r3, const Row< N, EE, SS > &r4, const Row< N, EE, SS > &r5)
Definition Mat.h:435
CNT< E >::TSqTHerm ESqTHerm
Definition Mat.h:111
bool isNumericallyEqual(const Mat< M, N, E2, CS2, RS2 > &m) const
Test whether this matrix is numerically equal to some other matrix with the same shape,...
Definition Mat.h:1092
Definition NTraits.h:486
This is a fixed-length row vector designed for no-overhead inline computation.
Definition Row.h:132
EStandard sum() const
Definition Row.h:254
This is a small, fixed-size symmetric or Hermitian matrix designed for no-overhead inline computation...
Definition SymMat.h:87
This is a fixed-length column vector designed for no-overhead inline computation.
Definition Vec.h:186
Vec & scalarMinusEq(const EE &ee)
Definition Vec.h:837
Vec & scalarPlusEq(const EE &ee)
Definition Vec.h:835
Vec< M, typename CNT< E >::template Result< EE >::Add > scalarAdd(const EE &e) const
Definition Vec.h:802
Vec & scalarEq(const EE &ee)
Definition Vec.h:833
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:368
SimTK::conjugate<R> should be instantiated only for float, double.
Definition conjugate.h:178
negator<N>, where N is a number type (real, complex, conjugate), is represented in memory identically...
Definition negator.h:75
NTraits< N >::StdNumber StdNumber
Definition negator.h:107
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition Assembler.h:37
Matrix_< E > operator*(const MatrixBase< E > &l, const typename CNT< E >::StdNumber &r)
Definition BigMatrix.h:605
Matrix_< E > operator/(const MatrixBase< E > &l, const typename CNT< E >::StdNumber &r)
Definition BigMatrix.h:613
std::basic_istream< CHAR, TRAITS > & operator>>(std::basic_istream< CHAR, TRAITS > &is, conjugate< R > &c)
Definition conjugate.h:505
@ MAX_RESOLVED_DEPTH
Definition CompositeNumericalTypes.h:120
Matrix_< typename CNT< E1 >::template Result< E2 >::Add > operator+(const MatrixBase< E1 > &l, const MatrixBase< E2 > &r)
Definition BigMatrix.h:568
std::ostream & operator<<(std::ostream &o, const ContactForce &f)
Definition CompliantContactSubsystem.h:387
Matrix_< typename CNT< E1 >::template Result< E2 >::Sub > operator-(const MatrixBase< E1 > &l, const MatrixBase< E2 > &r)
Definition BigMatrix.h:584
bool operator==(const PhiMatrix &p1, const PhiMatrix &p2)
Definition SpatialAlgebra.h:791
bool operator!=(const L &left, const R &right)
Definition SimTKcommon/include/SimTKcommon/internal/common.h:664
Definition Mat.h:247
Mat< M, N, typename CNT< E >::template Result< P >::Add, M, 1 > Add
Definition Mat.h:250
Mat< M, N, typename CNT< E >::template Result< P >::Sub, M, 1 > Sub
Definition Mat.h:251
Mat< M, N, typename CNT< E >::template Result< P >::Mul, M, 1 > Mul
Definition Mat.h:248
Mat< M, N, typename CNT< E >::template Result< P >::Dvd, M, 1 > Dvd
Definition Mat.h:249
Definition Mat.h:256
MulCNTs< M, N, ArgDepth, Mat, ColSpacing, RowSpacing, CNT< P >::NRows, CNT< P >::NCols, CNT< P >::ArgDepth, P, CNT< P >::ColSpacing, CNT< P >::RowSpacing > MulOp
Definition Mat.h:259
DvdOp::Type Dvd
Definition Mat.h:270
MulOpNonConforming::Type MulNon
Definition Mat.h:265
SubCNTs< M, N, ArgDepth, Mat, ColSpacing, RowSpacing, CNT< P >::NRows, CNT< P >::NCols, CNT< P >::ArgDepth, P, CNT< P >::ColSpacing, CNT< P >::RowSpacing > SubOp
Definition Mat.h:279
MulOp::Type Mul
Definition Mat.h:260
MulCNTsNonConforming< M, N, ArgDepth, Mat, ColSpacing, RowSpacing, CNT< P >::NRows, CNT< P >::NCols, CNT< P >::ArgDepth, P, CNT< P >::ColSpacing, CNT< P >::RowSpacing > MulOpNonConforming
Definition Mat.h:264
SubOp::Type Sub
Definition Mat.h:280
AddOp::Type Add
Definition Mat.h:275
DvdCNTs< M, N, ArgDepth, Mat, ColSpacing, RowSpacing, CNT< P >::NRows, CNT< P >::NCols, CNT< P >::ArgDepth, P, CNT< P >::ColSpacing, CNT< P >::RowSpacing > DvdOp
Definition Mat.h:269
AddCNTs< M, N, ArgDepth, Mat, ColSpacing, RowSpacing, CNT< P >::NRows, CNT< P >::NCols, CNT< P >::ArgDepth, P, CNT< P >::ColSpacing, CNT< P >::RowSpacing > AddOp
Definition Mat.h:274
Definition Mat.h:870
Mat< MM, NN, ELT, CS, RS > Type
Definition Mat.h:871
Definition Mat.h:284
Mat< M, N, P > Type
Definition Mat.h:285