Simbody

Mat.h

Go to the documentation of this file.
00001 #ifndef SimTK_SIMMATRIX_SMALLMATRIX_MAT_H_
00002 #define SimTK_SIMMATRIX_SMALLMATRIX_MAT_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                      SimTK Core: SimTK Simmatrix(tm)                       *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK Core biosimulation toolkit originating from      *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org.               *
00011  *                                                                            *
00012  * Portions copyright (c) 2005-10 Stanford University and the Authors.        *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors:                                                              *
00015  *                                                                            *
00016  * Permission is hereby granted, free of charge, to any person obtaining a    *
00017  * copy of this software and associated documentation files (the "Software"), *
00018  * to deal in the Software without restriction, including without limitation  *
00019  * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
00020  * and/or sell copies of the Software, and to permit persons to whom the      *
00021  * Software is furnished to do so, subject to the following conditions:       *
00022  *                                                                            *
00023  * The above copyright notice and this permission notice shall be included in *
00024  * all copies or substantial portions of the Software.                        *
00025  *                                                                            *
00026  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
00027  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
00028  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
00029  * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
00030  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
00031  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
00032  * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
00033  * -------------------------------------------------------------------------- */
00034 
00039 #include "SimTKcommon/internal/common.h"
00040 
00041 namespace SimTK {
00042 
00045 template <int M, int N, class ELT, int CS, int RS> class Mat {
00046     typedef ELT                                 E;
00047     typedef typename CNT<E>::TNeg               ENeg;
00048     typedef typename CNT<E>::TWithoutNegator    EWithoutNegator;
00049     typedef typename CNT<E>::TReal              EReal;
00050     typedef typename CNT<E>::TImag              EImag;
00051     typedef typename CNT<E>::TComplex           EComplex;
00052     typedef typename CNT<E>::THerm              EHerm;
00053     typedef typename CNT<E>::TPosTrans          EPosTrans;
00054     typedef typename CNT<E>::TSqHermT           ESqHermT;
00055     typedef typename CNT<E>::TSqTHerm           ESqTHerm;
00056 
00057     typedef typename CNT<E>::TSqrt              ESqrt;
00058     typedef typename CNT<E>::TAbs               EAbs;
00059     typedef typename CNT<E>::TStandard          EStandard;
00060     typedef typename CNT<E>::TInvert            EInvert;
00061     typedef typename CNT<E>::TNormalize         ENormalize;
00062 
00063     typedef typename CNT<E>::Scalar             EScalar;
00064     typedef typename CNT<E>::ULessScalar        EULessScalar;
00065     typedef typename CNT<E>::Number             ENumber;
00066     typedef typename CNT<E>::StdNumber          EStdNumber;
00067     typedef typename CNT<E>::Precision          EPrecision;
00068     typedef typename CNT<E>::ScalarNormSq       EScalarNormSq;
00069 
00070 public:
00071 
00072     enum {
00073         NRows               = M,
00074         NCols               = N,
00075         MinDim              = N < M ? N : M,
00076         MaxDim              = N > M ? N : M,
00077         RowSpacing          = RS,
00078         ColSpacing          = CS,
00079         NPackedElements     = M * N,
00080         NActualElements     = (N-1)*CS + (M-1)*RS + 1,
00081         NActualScalars      = CNT<E>::NActualScalars * NActualElements,
00082         ImagOffset          = NTraits<ENumber>::ImagOffset,
00083         RealStrideFactor    = 1, // composite types don't change size when
00084                                  // cast from complex to real or imaginary
00085         ArgDepth            = ((int)CNT<E>::ArgDepth < (int)MAX_RESOLVED_DEPTH 
00086                                 ? CNT<E>::ArgDepth + 1 
00087                                 : MAX_RESOLVED_DEPTH),
00088         IsScalar            = 0,
00089         IsULessScalar       = 0,
00090         IsNumber            = 0,
00091         IsStdNumber         = 0,
00092         IsPrecision         = 0,
00093         SignInterpretation  = CNT<E>::SignInterpretation
00094     };
00095 
00096     typedef Mat<M,N,E,CS,RS>                T;
00097     typedef Mat<M,N,ENeg,CS,RS>             TNeg;
00098     typedef Mat<M,N,EWithoutNegator,CS,RS>  TWithoutNegator;
00099 
00100     typedef Mat<M,N,EReal,CS*CNT<E>::RealStrideFactor,RS*CNT<E>::RealStrideFactor>
00101                                             TReal;
00102     typedef Mat<M,N,EImag,CS*CNT<E>::RealStrideFactor,RS*CNT<E>::RealStrideFactor>
00103                                             TImag;
00104     typedef Mat<M,N,EComplex,CS,RS>         TComplex;
00105     typedef Mat<N,M,EHerm,RS,CS>            THerm;
00106     typedef Mat<N,M,E,RS,CS>                TPosTrans;
00107     typedef E                               TElement;
00108     typedef Row<N,E,CS>                     TRow;    
00109     typedef Vec<M,E,RS>                     TCol;
00110     typedef Vec<MinDim,E,RS+CS>             TDiag;
00111 
00112     // These are the results of calculations, so are returned in new, packed
00113     // memory. Be sure to refer to element types here which are also packed.
00114     typedef Mat<M,N,ESqrt,M,1>              TSqrt;      // Note strides are packed
00115     typedef Mat<M,N,EAbs,M,1>               TAbs;       // Note strides are packed
00116     typedef Mat<M,N,EStandard,M,1>          TStandard;
00117     typedef Mat<N,M,EInvert,N,1>            TInvert;    // like THerm but packed
00118     typedef Mat<M,N,ENormalize,M,1>         TNormalize;
00119 
00120     typedef SymMat<N,ESqHermT>              TSqHermT;   // ~Mat*Mat
00121     typedef SymMat<M,ESqTHerm>              TSqTHerm;   // Mat*~Mat
00122 
00123     // Here the elements are passed through unchanged but the result matrix
00124     // is an ordinary packed, column order matrix.
00125     typedef Mat<M,N,E,M,1>                  TPacked;
00126     typedef Mat<M-1,N,E,M,1>                TDropRow;
00127     typedef Mat<M,N-1,E,M,1>                TDropCol;
00128     typedef Mat<M-1,N-1,E,M,1>              TDropRowCol;
00129     typedef Mat<M+1,N,E,M,1>                TAppendRow;
00130     typedef Mat<M,N+1,E,M,1>                TAppendCol;
00131     typedef Mat<M+1,N+1,E,M,1>              TAppendRowCol;
00132 
00133     typedef EScalar                         Scalar;
00134     typedef EULessScalar                    ULessScalar;
00135     typedef ENumber                         Number;
00136     typedef EStdNumber                      StdNumber;
00137     typedef EPrecision                      Precision;
00138     typedef EScalarNormSq                   ScalarNormSq;
00139 
00140     typedef THerm                           TransposeType; // TODO
00141 
00142     int size() const { return M*N; }
00143     int nrow() const { return M; }
00144     int ncol() const { return N; }
00145 
00146     // Scalar norm square is sum( squares of all scalars )
00147     ScalarNormSq scalarNormSqr() const { 
00148         ScalarNormSq sum(0);
00149         for(int j=0;j<N;++j) sum += CNT<TCol>::scalarNormSqr((*this)(j));
00150         return sum;
00151     }
00152 
00153     // sqrt() is elementwise square root; that is, the return value has the same
00154     // dimension as this Mat but with each element replaced by whatever it thinks
00155     // its square root is.
00156     TSqrt sqrt() const { 
00157         TSqrt msqrt;
00158         for(int j=0;j<N;++j) msqrt(j) = (*this)(j).sqrt();
00159         return msqrt;
00160     }
00161 
00162     // abs() is elementwise absolute value; that is, the return value has the same
00163     // dimension as this Mat but with each element replaced by whatever it thinks
00164     // its absolute value is.
00165     TAbs abs() const { 
00166         TAbs mabs;
00167         for(int j=0;j<N;++j) mabs(j) = (*this)(j).abs();
00168         return mabs;
00169     }
00170 
00171     TStandard standardize() const {
00172         TStandard mstd;
00173         for(int j=0;j<N;++j) mstd(j) = (*this)(j).standardize();
00174         return mstd;
00175     }
00176 
00177     // This gives the resulting matrix type when (m(i,j) op P) is applied to each element.
00178     // It is an MxN vector with default column and row spacing, and element types which
00179     // are the regular composite result of E op P. Typically P is a scalar type but
00180     // it doesn't have to be.
00181     template <class P> struct EltResult { 
00182         typedef Mat<M,N, typename CNT<E>::template Result<P>::Mul, M, 1> Mul;
00183         typedef Mat<M,N, typename CNT<E>::template Result<P>::Dvd, M, 1> Dvd;
00184         typedef Mat<M,N, typename CNT<E>::template Result<P>::Add, M, 1> Add;
00185         typedef Mat<M,N, typename CNT<E>::template Result<P>::Sub, M, 1> Sub;
00186     };
00187 
00188     // This is the composite result for m op P where P is some kind of appropriately shaped
00189     // non-scalar type.
00190     template <class P> struct Result { 
00191         typedef MulCNTs<M,N,ArgDepth,Mat,ColSpacing,RowSpacing,
00192             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00193             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> MulOp;
00194         typedef typename MulOp::Type Mul;
00195 
00196         typedef MulCNTsNonConforming<M,N,ArgDepth,Mat,ColSpacing,RowSpacing,
00197             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00198             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> MulOpNonConforming;
00199         typedef typename MulOpNonConforming::Type MulNon;
00200 
00201         typedef DvdCNTs<M,N,ArgDepth,Mat,ColSpacing,RowSpacing,
00202             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00203             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> DvdOp;
00204         typedef typename DvdOp::Type Dvd;
00205 
00206         typedef AddCNTs<M,N,ArgDepth,Mat,ColSpacing,RowSpacing,
00207             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00208             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> AddOp;
00209         typedef typename AddOp::Type Add;
00210 
00211         typedef SubCNTs<M,N,ArgDepth,Mat,ColSpacing,RowSpacing,
00212             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00213             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> SubOp;
00214         typedef typename SubOp::Type Sub;
00215     };
00216 
00217     // Shape-preserving element substitution (always packed)
00218     template <class P> struct Substitute {
00219         typedef Mat<M,N,P> Type;
00220     };
00221 
00222     // Default construction initializes to NaN when debugging but
00223     // is left uninitialized otherwise.
00224     Mat(){ 
00225     #ifndef NDEBUG
00226         setToNaN();
00227     #endif
00228     }
00229 
00230     // It's important not to use the default copy constructor or copy
00231     // assignment because the compiler doesn't understand that we may
00232     // have noncontiguous storage and will try to copy the whole array.
00233     Mat(const Mat& src) {
00234         for (int j=0; j<N; ++j)
00235             (*this)(j) = src(j);
00236     }
00237     Mat& operator=(const Mat& src) {    // no harm if src and 'this' are the same
00238         for (int j=0; j<N; ++j)
00239            (*this)(j) = src(j);
00240         return *this;
00241     }
00242 
00243     // Convert a SymMat to a Mat. Caution: with complex elements the
00244     // upper triangle values are conjugates of the lower triangle ones.
00245     explicit Mat(const SymMat<M, ELT>& src) {
00246         diag() = src.diag();
00247         for (int j = 0; j < M; ++j)
00248             for (int i = j+1; i < M; ++i) {
00249                 (*this)(i, j) = src.getEltLower(i, j);
00250                 (*this)(j, i) = src.getEltUpper(j, i);
00251             }
00252     }
00253 
00254     // We want an implicit conversion from a Mat of the same length
00255     // and element type but with different spacings.
00256     template <int CSS, int RSS> Mat(const Mat<M,N,E,CSS,RSS>& src) {
00257         for (int j=0; j<N; ++j)
00258             (*this)(j) = src(j);
00259     }
00260 
00261     // We want an implicit conversion from a Mat of the same length
00262     // and *negated* element type, possibly with different spacings.
00263     template <int CSS, int RSS> Mat(const Mat<M,N,ENeg,CSS,RSS>& src) {
00264         for (int j=0; j<N; ++j)
00265             (*this)(j) = src(j);
00266     }
00267 
00268     // Construct a Mat from a Mat of the same dimensions, with any
00269     // spacings. Works as long as the element types are assignment compatible.
00270     template <class EE, int CSS, int RSS> explicit Mat(const Mat<M,N,EE,CSS,RSS>& mm)
00271       { for (int j=0;j<N;++j) (*this)(j) = mm(j);}
00272 
00273     // Construction using an element repeats that element on the diagonal
00274     // but sets the rest of the matrix to zero.
00275     explicit Mat(const E& e)
00276       { for (int j=0;j<N;++j) (*this)(j) = E(0); diag()=e; }
00277 
00278     // Construction using a negated element is just like construction from
00279     // the element.
00280     explicit Mat(const ENeg& e)
00281       { for (int j=0;j<N;++j) (*this)(j) = E(0); diag()=e; }
00282 
00283     // Given an int, turn it into a suitable floating point number
00284     // and then feed that to the above single-element constructor.
00285     explicit Mat(int i) 
00286       { new (this) Mat(E(Precision(i))); }
00287 
00288     // A bevy of constructors from individual exact-match elements IN ROW ORDER.
00289     Mat(const E& e0,const E& e1)
00290       {assert(M*N==2);d[rIx(0)]=e0;d[rIx(1)]=e1;}
00291     Mat(const E& e0,const E& e1,const E& e2)
00292       {assert(M*N==3);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;}
00293     Mat(const E& e0,const E& e1,const E& e2,const E& e3)
00294       {assert(M*N==4);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;}
00295     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4)
00296       {assert(M*N==5);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;}
00297     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00298         const E& e5)
00299       {assert(M*N==6);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00300        d[rIx(5)]=e5;}
00301     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00302         const E& e5,const E& e6)
00303       {assert(M*N==7);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00304        d[rIx(5)]=e5;d[rIx(6)]=e6;}
00305     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00306         const E& e5,const E& e6,const E& e7)
00307       {assert(M*N==8);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00308        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;}
00309     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00310         const E& e5,const E& e6,const E& e7,const E& e8)
00311       {assert(M*N==9);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00312        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;}
00313     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00314         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9)
00315       {assert(M*N==10);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00316        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;}
00317     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00318         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9,
00319         const E& e10)
00320       {assert(M*N==11);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00321        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;}
00322     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00323         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9,
00324         const E& e10, const E& e11)
00325       {assert(M*N==12);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00326        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
00327        d[rIx(11)]=e11;}
00328     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00329         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9,
00330         const E& e10, const E& e11, const E& e12)
00331       {assert(M*N==13);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00332        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
00333        d[rIx(11)]=e11;d[rIx(12)]=e12;}
00334     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00335         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9,
00336         const E& e10, const E& e11, const E& e12, const E& e13)
00337       {assert(M*N==14);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00338        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
00339        d[rIx(11)]=e11;d[rIx(12)]=e12;d[rIx(13)]=e13;}
00340     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00341         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9,
00342         const E& e10, const E& e11, const E& e12, const E& e13, const E& e14)
00343       {assert(M*N==15);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00344        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
00345        d[rIx(11)]=e11;d[rIx(12)]=e12;d[rIx(13)]=e13;d[rIx(14)]=e14;}
00346     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00347         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9,
00348         const E& e10, const E& e11, const E& e12, const E& e13, const E& e14, 
00349         const E& e15)
00350       {assert(M*N==16);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00351        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
00352        d[rIx(11)]=e11;d[rIx(12)]=e12;d[rIx(13)]=e13;d[rIx(14)]=e14;d[rIx(15)]=e15;}
00353 
00354     // Construction from 1-6 *exact match* Rows
00355     explicit Mat(const TRow& r0)
00356       { assert(M==1); (*this)[0]=r0; }
00357     Mat(const TRow& r0,const TRow& r1)
00358       { assert(M==2);(*this)[0]=r0;(*this)[1]=r1; }
00359     Mat(const TRow& r0,const TRow& r1,const TRow& r2)
00360       { assert(M==3);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2; }
00361     Mat(const TRow& r0,const TRow& r1,const TRow& r2,
00362         const TRow& r3)
00363       { assert(M==4);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;(*this)[3]=r3; }
00364     Mat(const TRow& r0,const TRow& r1,const TRow& r2,
00365         const TRow& r3,const TRow& r4)
00366       { assert(M==5);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;
00367         (*this)[3]=r3;(*this)[4]=r4; }
00368     Mat(const TRow& r0,const TRow& r1,const TRow& r2,
00369         const TRow& r3,const TRow& r4,const TRow& r5)
00370       { assert(M==6);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;
00371         (*this)[3]=r3;(*this)[4]=r4;(*this)[5]=r5; }
00372 
00373     // Construction from 1-6 *compatible* Rows
00374     template <class EE, int SS> explicit Mat(const Row<N,EE,SS>& r0)
00375       { assert(M==1); (*this)[0]=r0; }
00376     template <class EE, int SS> Mat(const Row<N,EE,SS>& r0,const Row<N,EE,SS>& r1)
00377       { assert(M==2);(*this)[0]=r0;(*this)[1]=r1; }
00378     template <class EE, int SS> 
00379     Mat(const Row<N,EE,SS>& r0,const Row<N,EE,SS>& r1,const Row<N,EE,SS>& r2)
00380       { assert(M==3);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2; }
00381     template <class EE, int SS> 
00382     Mat(const Row<N,EE,SS>& r0,const Row<N,EE,SS>& r1,const Row<N,EE,SS>& r2,
00383         const Row<N,EE,SS>& r3)
00384       { assert(M==4);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;(*this)[3]=r3; }
00385     template <class EE, int SS> 
00386     Mat(const Row<N,EE,SS>& r0,const Row<N,EE,SS>& r1,const Row<N,EE,SS>& r2,
00387         const Row<N,EE,SS>& r3,const Row<N,EE,SS>& r4)
00388       { assert(M==5);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;
00389         (*this)[3]=r3;(*this)[4]=r4; }
00390     template <class EE, int SS> 
00391     Mat(const Row<N,EE,SS>& r0,const Row<N,EE,SS>& r1,const Row<N,EE,SS>& r2,
00392         const Row<N,EE,SS>& r3,const Row<N,EE,SS>& r4,const Row<N,EE,SS>& r5)
00393       { assert(M==6);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;
00394         (*this)[3]=r3;(*this)[4]=r4;(*this)[5]=r5; }
00395 
00396 
00397     // Construction from 1-6 *exact match* Vecs
00398     explicit Mat(const TCol& r0)
00399       { assert(N==1); (*this)(0)=r0; }
00400     Mat(const TCol& r0,const TCol& r1)
00401       { assert(N==2);(*this)(0)=r0;(*this)(1)=r1; }
00402     Mat(const TCol& r0,const TCol& r1,const TCol& r2)
00403       { assert(N==3);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2; }
00404     Mat(const TCol& r0,const TCol& r1,const TCol& r2,
00405         const TCol& r3)
00406       { assert(N==4);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;(*this)(3)=r3; }
00407     Mat(const TCol& r0,const TCol& r1,const TCol& r2,
00408         const TCol& r3,const TCol& r4)
00409       { assert(N==5);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;
00410         (*this)(3)=r3;(*this)(4)=r4; }
00411     Mat(const TCol& r0,const TCol& r1,const TCol& r2,
00412         const TCol& r3,const TCol& r4,const TCol& r5)
00413       { assert(N==6);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;
00414         (*this)(3)=r3;(*this)(4)=r4;(*this)(5)=r5; }
00415 
00416     // Construction from 1-6 *compatible* Vecs
00417     template <class EE, int SS> explicit Mat(const Vec<M,EE,SS>& r0)
00418       { assert(N==1); (*this)(0)=r0; }
00419     template <class EE, int SS> Mat(const Vec<M,EE,SS>& r0,const Vec<M,EE,SS>& r1)
00420       { assert(N==2);(*this)(0)=r0;(*this)(1)=r1; }
00421     template <class EE, int SS> 
00422     Mat(const Vec<M,EE,SS>& r0,const Vec<M,EE,SS>& r1,const Vec<M,EE,SS>& r2)
00423       { assert(N==3);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2; }
00424     template <class EE, int SS> 
00425     Mat(const Vec<M,EE,SS>& r0,const Vec<M,EE,SS>& r1,const Vec<M,EE,SS>& r2,
00426         const Vec<M,EE,SS>& r3)
00427       { assert(N==4);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;(*this)(3)=r3; }
00428     template <class EE, int SS> 
00429     Mat(const Vec<M,EE,SS>& r0,const Vec<M,EE,SS>& r1,const Vec<M,EE,SS>& r2,
00430         const Vec<M,EE,SS>& r3,const Vec<M,EE,SS>& r4)
00431       { assert(N==5);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;
00432         (*this)(3)=r3;(*this)(4)=r4; }
00433     template <class EE, int SS> 
00434     Mat(const Vec<M,EE,SS>& r0,const Vec<M,EE,SS>& r1,const Vec<M,EE,SS>& r2,
00435         const Vec<M,EE,SS>& r3,const Vec<M,EE,SS>& r4,const Vec<M,EE,SS>& r5)
00436       { assert(N==6);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;
00437         (*this)(3)=r3;(*this)(4)=r4;(*this)(5)=r5; }
00438 
00439     // Construction from a pointer to anything assumes we're pointing
00440     // at a packed element list of the right length, in row order.
00441     template <class EE> explicit Mat(const EE* p)
00442       { assert(p); for(int i=0;i<M;++i) (*this)[i]=&p[i*N]; }
00443 
00444     // Assignment works similarly to copy -- if the lengths match,
00445     // go element-by-element. Otherwise, zero and then copy to each 
00446     // diagonal element.
00447     template <class EE, int CSS, int RSS> Mat& operator=(const Mat<M,N,EE,CSS,RSS>& mm) {
00448         for (int j=0; j<N; ++j) (*this)(j) = mm(j);
00449         return *this;
00450     }
00451 
00452     template <class EE> Mat& operator=(const EE* p) {
00453         assert(p); for(int i=0;i<M;++i) (*this)[i]=&p[i*N];
00454         return *this;
00455     }
00456 
00457     // Assignment ops
00458     template <class EE, int CSS, int RSS> Mat& 
00459     operator+=(const Mat<M,N,EE,CSS,RSS>& mm) {
00460         for (int j=0; j<N; ++j) (*this)(j) += mm(j);
00461         return *this;
00462     }
00463     template <class EE, int CSS, int RSS> Mat&
00464     operator+=(const Mat<M,N,negator<EE>,CSS,RSS>& mm) {
00465         for (int j=0; j<N; ++j) (*this)(j) -= -(mm(j));
00466         return *this;
00467     }
00468 
00469     template <class EE, int CSS, int RSS> Mat&
00470     operator-=(const Mat<M,N,EE,CSS,RSS>& mm) {
00471         for (int j=0; j<N; ++j) (*this)(j) -= mm(j);
00472         return *this;
00473     }
00474     template <class EE, int CSS, int RSS> Mat&
00475     operator-=(const Mat<M,N,negator<EE>,CSS,RSS>& mm) {
00476         for (int j=0; j<N; ++j) (*this)(j) += -(mm(j));
00477         return *this;
00478     }
00479 
00480     // In place matrix multiply can only be done when the RHS matrix is square of dimension
00481     // N (i.e., number of columns), and the elements are also *= compatible.
00482     template <class EE, int CSS, int RSS> Mat&
00483     operator*=(const Mat<N,N,EE,CSS,RSS>& mm) {
00484         const Mat t(*this);
00485         for (int j=0; j<N; ++j)
00486             for (int i=0; i<M; ++i)
00487                 (*this)(i,j) = t[i] * mm(j);
00488         return *this;
00489     }
00490 
00491     // Conforming binary ops with 'this' on left, producing new packed result.
00492     // Cases: m=m+-m, m=m+-sy, m=m*m, m=m*sy, v=m*v
00493 
00494     // m= this + m
00495     template <class E2, int CS2, int RS2> 
00496     typename Result<Mat<M,N,E2,CS2,RS2> >::Add
00497     conformingAdd(const Mat<M,N,E2,CS2,RS2>& r) const {
00498         typename Result<Mat<M,N,E2,CS2,RS2> >::Add result;
00499         for (int j=0;j<N;++j) result(j) = (*this)(j) + r(j);
00500         return result;
00501     }
00502     // m= this - m
00503     template <class E2, int CS2, int RS2> 
00504     typename Result<Mat<M,N,E2,CS2,RS2> >::Sub
00505     conformingSubtract(const Mat<M,N,E2,CS2,RS2>& r) const {
00506         typename Result<Mat<M,N,E2,CS2,RS2> >::Sub result;
00507         for (int j=0;j<N;++j) result(j) = (*this)(j) - r(j);
00508         return result;
00509     }
00510     // m= m - this
00511     template <class E2, int CS2, int RS2> 
00512     typename Mat<M,N,E2,CS2,RS2>::template Result<Mat>::Sub
00513     conformingSubtractFromLeft(const Mat<M,N,E2,CS2,RS2>& l) const {
00514         return l.conformingSubtract(*this);
00515     }
00516 
00517     // We always punt to the SymMat since it knows better what to do.
00518     // m = this + sym
00519     template <class E2, int RS2> 
00520     typename Result<SymMat<M,E2,RS2> >::Add
00521     conformingAdd(const SymMat<M,E2,RS2>& sy) const {
00522         assert(M==N);
00523         return sy.conformingAdd(*this);
00524     }
00525     // m= this - sym
00526     template <class E2, int RS2> 
00527     typename Result<SymMat<M,E2,RS2> >::Sub
00528     conformingSubtract(const SymMat<M,E2,RS2>& sy) const {
00529         assert(M==N);
00530         return sy.conformingSubtractFromLeft(*this);
00531     }
00532     // m= sym - this
00533     template <class E2, int RS2> 
00534     typename SymMat<M,E2,RS2>::template Result<Mat>::Sub
00535     conformingSubtractFromLeft(const SymMat<M,E2,RS2>& sy) const {
00536         assert(M==N);
00537         return sy.conformingSubtract(*this);
00538     }
00539 
00540     // m= this * m
00541     template <int N2, class E2, int CS2, int RS2>
00542     typename Result<Mat<N,N2,E2,CS2,RS2> >::Mul
00543     conformingMultiply(const Mat<N,N2,E2,CS2,RS2>& m) const {
00544         typename Result<Mat<N,N2,E2,CS2,RS2> >::Mul result;
00545         for (int j=0;j<N2;++j)
00546             for (int i=0;i<M;++i)
00547                 result(i,j) = (*this)[i].conformingMultiply(m(j)); // i.e., dot()
00548         return result;
00549     }
00550     // m= m * this
00551     template <int M2, class E2, int CS2, int RS2>
00552     typename Mat<M2,M,E2,CS2,RS2>::template Result<Mat>::Mul
00553     conformingMultiplyFromLeft(const Mat<M2,M,E2,CS2,RS2>& m) const {
00554         return m.conformingMultiply(*this);
00555     }
00556 
00557     // m= this / m = this * m.invert()
00558     template <int M2, class E2, int CS2, int RS2> 
00559     typename Result<Mat<M2,N,E2,CS2,RS2> >::Dvd
00560     conformingDivide(const Mat<M2,N,E2,CS2,RS2>& m) const {
00561         return conformingMultiply(m.invert());
00562     }
00563     // m= m / this = m * this.invert()
00564     template <int M2, class E2, int CS2, int RS2> 
00565     typename Mat<M2,N,E2,CS2,RS2>::template Result<Mat>::Dvd
00566     conformingDivideFromLeft(const Mat<M2,N,E2,CS2,RS2>& m) const {
00567         return m.conformingMultiply((*this).invert());
00568     }
00569     
00570     const TRow& operator[](int i) const { return row(i); }
00571     TRow&       operator[](int i)       { return row(i); }    
00572     const TCol& operator()(int j) const { return col(j); }
00573     TCol&       operator()(int j)       { return col(j); }
00574     
00575     const E& operator()(int i,int j) const { return elt(i,j); }
00576     E&       operator()(int i,int j)       { return elt(i,j); }
00577 
00578     // This is the scalar Frobenius norm.
00579     ScalarNormSq normSqr() const { return scalarNormSqr(); }
00580     typename CNT<ScalarNormSq>::TSqrt 
00581         norm() const { return CNT<ScalarNormSq>::sqrt(scalarNormSqr()); }
00582 
00583     // There is no conventional meaning for normalize() applied to a matrix. We
00584     // choose to define it as follows:
00585     // If the elements of this Mat are scalars, the result is what you get by
00586     // dividing each element by the Frobenius norm() calculated above. If the elements are
00587     // *not* scalars, then the elements are *separately* normalized. That means
00588     // you will get a different answer from Mat<2,2,Mat33>::normalize() than you
00589     // would from a Mat<6,6>::normalize() containing the same scalars.
00590     //
00591     // Normalize returns a matrix of the same dimension but in new, packed storage
00592     // and with a return type that does not include negator<> even if the original
00593     // Mat<> does, because we can eliminate the negation here almost for free.
00594     // But we can't standardize (change conjugate to complex) for free, so we'll retain
00595     // conjugates if there are any.
00596     TNormalize normalize() const {
00597         if (CNT<E>::IsScalar) {
00598             return castAwayNegatorIfAny() / (SignInterpretation*norm());
00599         } else {
00600             TNormalize elementwiseNormalized;
00601             // punt to the column Vec to deal with the elements
00602             for (int j=0; j<N; ++j) 
00603                 elementwiseNormalized(j) = (*this)(j).normalize();
00604             return elementwiseNormalized;
00605         }
00606     }
00607 
00608     // Default inversion. Assume full rank if square, otherwise return
00609     // pseudoinverse. (Mostly TODO)
00610     TInvert invert() const;
00611 
00612     const Mat&   operator+() const { return *this; }
00613     const TNeg&  operator-() const { return negate(); }
00614     TNeg&        operator-()       { return updNegate(); }
00615     const THerm& operator~() const { return transpose(); }
00616     THerm&       operator~()       { return updTranspose(); }
00617 
00618     const TNeg&  negate() const { return *reinterpret_cast<const TNeg*>(this); }
00619     TNeg&        updNegate()    { return *reinterpret_cast<TNeg*>(this); }
00620 
00621     const THerm& transpose()    const { return *reinterpret_cast<const THerm*>(this); }
00622     THerm&       updTranspose()       { return *reinterpret_cast<THerm*>(this); }
00623 
00624     const TPosTrans& positionalTranspose() const
00625         { return *reinterpret_cast<const TPosTrans*>(this); }
00626     TPosTrans&       updPositionalTranspose()
00627         { return *reinterpret_cast<TPosTrans*>(this); }
00628 
00629     // If the underlying scalars are complex or conjugate, we can return a
00630     // reference to the real part just by recasting the data to a matrix of
00631     // the same dimensions but containing real elements, with the scalar
00632     // spacing doubled.
00633     const TReal& real() const { return *reinterpret_cast<const TReal*>(this); }
00634     TReal&       real()       { return *reinterpret_cast<      TReal*>(this); }
00635 
00636     // Getting the imaginary part is almost the same as real, but we have
00637     // to shift the starting address of the returned object by 1 real-size
00638     // ("precision") scalar so that the first element is the imaginary part
00639     // of the original first element.
00640     // TODO: should blow up or return a reference to a zero matrix if called
00641     // on a real object.
00642     // Had to contort these routines to get them through VC++ 7.net
00643     const TImag& imag()    const { 
00644         const int offs = ImagOffset;
00645         const Precision* p = reinterpret_cast<const Precision*>(this);
00646         return *reinterpret_cast<const TImag*>(p+offs);
00647     }
00648     TImag& imag() { 
00649         const int offs = ImagOffset;
00650         Precision* p = reinterpret_cast<Precision*>(this);
00651         return *reinterpret_cast<TImag*>(p+offs);
00652     }
00653 
00654     const TWithoutNegator& castAwayNegatorIfAny() const {return *reinterpret_cast<const TWithoutNegator*>(this);}
00655     TWithoutNegator&       updCastAwayNegatorIfAny()    {return *reinterpret_cast<TWithoutNegator*>(this);}
00656 
00657     const TRow& row(int i) const { 
00658         SimTK_INDEXCHECK(i,M, "Mat::row[i]");
00659         return *reinterpret_cast<const TRow*>(&d[i*RS]); 
00660     }
00661     TRow& row(int i) { 
00662         SimTK_INDEXCHECK(i,M, "Mat::row[i]");
00663         return *reinterpret_cast<TRow*>(&d[i*RS]); 
00664     }
00665 
00666     const TCol& col(int j) const { 
00667         SimTK_INDEXCHECK(j,N, "Mat::col(j)");
00668         return *reinterpret_cast<const TCol*>(&d[j*CS]); 
00669     }
00670     TCol& col(int j) { 
00671         SimTK_INDEXCHECK(j,N, "Mat::col(j)");
00672         return *reinterpret_cast<TCol*>(&d[j*CS]); 
00673     }    
00674     
00675     const E& elt(int i, int j) const {
00676         SimTK_INDEXCHECK(i,M, "Mat::elt(i,j)");
00677         SimTK_INDEXCHECK(j,N, "Mat::elt(i,j)");
00678         return d[i*RS+j*CS]; 
00679     }
00680     E& elt(int i, int j) { 
00681         SimTK_INDEXCHECK(i,M, "Mat::elt(i,j)");
00682         SimTK_INDEXCHECK(j,N, "Mat::elt(i,j)");
00683         return d[i*RS+j*CS]; 
00684     }
00685 
00686     const TDiag& diag() const { return *reinterpret_cast<const TDiag*>(d); }
00687     TDiag&       diag()       { return *reinterpret_cast<TDiag*>(d); }
00688 
00689     EStandard trace() const {return diag().sum();}
00690 
00691     // These are elementwise binary operators, (this op ee) by default but (ee op this) if
00692     // 'FromLeft' appears in the name. The result is a packed Mat<M,N> but the element type
00693     // may change. These are mostly used to implement global operators.
00694     // We call these "scalar" operators but actually the "scalar" can be a composite type.
00695 
00696     //TODO: consider converting 'e' to Standard Numbers as precalculation and changing
00697     // return type appropriately.
00698     template <class EE> Mat<M,N, typename CNT<E>::template Result<EE>::Mul>
00699     scalarMultiply(const EE& e) const {
00700         Mat<M,N, typename CNT<E>::template Result<EE>::Mul> result;
00701         for (int j=0; j<N; ++j) result(j) = (*this)(j).scalarMultiply(e);
00702         return result;
00703     }
00704     template <class EE> Mat<M,N, typename CNT<EE>::template Result<E>::Mul>
00705     scalarMultiplyFromLeft(const EE& e) const {
00706         Mat<M,N, typename CNT<EE>::template Result<E>::Mul> result;
00707         for (int j=0; j<N; ++j) result(j) = (*this)(j).scalarMultiplyFromLeft(e);
00708         return result;
00709     }
00710 
00711     // TODO: should precalculate and store 1/e, while converting to Standard Numbers. Note
00712     // that return type should change appropriately.
00713     template <class EE> Mat<M,N, typename CNT<E>::template Result<EE>::Dvd>
00714     scalarDivide(const EE& e) const {
00715         Mat<M,N, typename CNT<E>::template Result<EE>::Dvd> result;
00716         for (int j=0; j<N; ++j) result(j) = (*this)(j).scalarDivide(e);
00717         return result;
00718     }
00719     template <class EE> Mat<M,N, typename CNT<EE>::template Result<E>::Dvd>
00720     scalarDivideFromLeft(const EE& e) const {
00721         Mat<M,N, typename CNT<EE>::template Result<E>::Dvd> result;
00722         for (int j=0; j<N; ++j) result(j) = (*this)(j).scalarDivideFromLeft(e);
00723         return result;
00724     }
00725 
00726     // Additive operators for scalars operate only on the diagonal.
00727     template <class EE> Mat<M,N, typename CNT<E>::template Result<EE>::Add>
00728     scalarAdd(const EE& e) const {
00729         Mat<M,N, typename CNT<E>::template Result<EE>::Add> result(*this);
00730         result.diag() += e;
00731         return result;
00732     }
00733     // Add is commutative, so no 'FromLeft'.
00734 
00735     template <class EE> Mat<M,N, typename CNT<E>::template Result<EE>::Sub>
00736     scalarSubtract(const EE& e) const {
00737         Mat<M,N, typename CNT<E>::template Result<EE>::Sub> result(*this);
00738         result.diag() -= e;
00739         return result;
00740     }
00741     // Should probably do something clever with negation here (s - m)
00742     template <class EE> Mat<M,N, typename CNT<EE>::template Result<E>::Sub>
00743     scalarSubtractFromLeft(const EE& e) const {
00744         Mat<M,N, typename CNT<EE>::template Result<E>::Sub> result(-(*this));
00745         result.diag() += e; // yes, add
00746         return result;
00747     }
00748 
00749     // Generic assignments for any element type not listed explicitly, including scalars.
00750     // These are done repeatedly for each element and only work if the operation can
00751     // be performed leaving the original element type.
00752     template <class EE> Mat& operator =(const EE& e) {return scalarEq(e);}
00753     template <class EE> Mat& operator+=(const EE& e) {return scalarPlusEq(e);}
00754     template <class EE> Mat& operator-=(const EE& e) {return scalarMinusEq(e);}
00755     template <class EE> Mat& operator*=(const EE& e) {return scalarTimesEq(e);}
00756     template <class EE> Mat& operator/=(const EE& e) {return scalarDivideEq(e);}
00757 
00758     // Generalized scalar assignment & computed assignment methods. These will work
00759     // for any assignment-compatible element, not just scalars.
00760     template <class EE> Mat& scalarEq(const EE& ee)
00761       { for(int j=0; j<N; ++j) (*this)(j).scalarEq(EE(0)); 
00762         diag().scalarEq(ee); 
00763         return *this; }
00764 
00765     template <class EE> Mat& scalarPlusEq(const EE& ee)
00766       { diag().scalarPlusEq(ee); return *this; }
00767 
00768     template <class EE> Mat& scalarMinusEq(const EE& ee)
00769       { diag().scalarMinusEq(ee); return *this; }
00770     // m = s - m; negate m, then add s
00771     template <class EE> Mat& scalarMinusEqFromLeft(const EE& ee)
00772       { scalarTimesEq(E(-1)); diag().scalarAdd(ee); return *this; }
00773 
00774     template <class EE> Mat& scalarTimesEq(const EE& ee)
00775       { for(int j=0; j<N; ++j) (*this)(j).scalarTimesEq(ee); return *this; }
00776     template <class EE> Mat& scalarTimesEqFromLeft(const EE& ee)
00777       { for(int j=0; j<N; ++j) (*this)(j).scalarTimesEqFromLeft(ee); return *this; } 
00778 
00779     template <class EE> Mat& scalarDivideEq(const EE& ee)
00780       { for(int j=0; j<N; ++j) (*this)(j).scalarDivideEq(ee); return *this; }
00781     template <class EE> Mat& scalarDivideEqFromLeft(const EE& ee)
00782       { for(int j=0; j<N; ++j) (*this)(j).scalarDivideEqFromLeft(ee); return *this; } 
00783 
00784     void setToNaN() {
00785         for (int j=0; j<N; ++j)
00786             (*this)(j).setToNaN();
00787     }
00788 
00789     void setToZero() {
00790         for (int j=0; j<N; ++j)
00791             (*this)(j).setToZero();
00792     }
00793 
00794     // Extract a sub-Mat with size known at compile time. These have to be
00795     // called with explicit template arguments, e.g. getSubMat<3,4>(i,j).
00796 
00797     template <int MM, int NN> struct SubMat {
00798         typedef Mat<MM,NN,ELT,CS,RS> Type;
00799     };
00800 
00801     template <int MM, int NN>
00802     const typename SubMat<MM,NN>::Type& getSubMat(int i, int j) const {
00803         assert(0 <= i && i + MM <= M);
00804         assert(0 <= j && j + NN <= N);
00805         return SubMat<MM,NN>::Type::getAs(&(*this)(i,j));
00806     }
00807     template <int MM, int NN>
00808     typename SubMat<MM,NN>::Type& updSubMat(int i, int j) {
00809         assert(0 <= i && i + MM <= M);
00810         assert(0 <= j && j + NN <= N);
00811         return SubMat<MM,NN>::Type::updAs(&(*this)(i,j));
00812     }
00813     template <int MM, int NN>
00814     void setSubMat(int i, int j, const typename SubMat<MM,NN>::Type& value) {
00815         assert(0 <= i && i + MM <= M);
00816         assert(0 <= j && j + NN <= N);
00817         SubMat<MM,NN>::Type::updAs(&(*this)(i,j)) = value;
00818     }
00819 
00822     TDropRow dropRow(int i) const {
00823         assert(0 <= i && i < M);
00824         TDropRow out;
00825         for (int r=0, nxt=0; r<M-1; ++r, ++nxt) {
00826             if (nxt==i) ++nxt;  // skip the loser
00827             out[r] = (*this)[nxt];
00828         }
00829         return out;
00830     }
00831 
00834     TDropCol dropCol(int j) const {
00835         assert(0 <= j && j < N);
00836         TDropCol out;
00837         for (int c=0, nxt=0; c<N-1; ++c, ++nxt) {
00838             if (nxt==j) ++nxt;  // skip the loser
00839             out(c) = (*this)(nxt);
00840         }
00841         return out;
00842     }
00843 
00847     TDropRowCol dropRowCol(int i, int j) const {
00848         assert(0 <= i && i < M);
00849         assert(0 <= j && j < N);
00850         TDropRowCol out;
00851         for (int c=0, nxtc=0; c<N-1; ++c, ++nxtc) { 
00852             if (nxtc==j) ++nxtc;
00853             for (int r=0, nxtr=0; r<M-1; ++r, ++nxtr) {
00854                 if (nxtr==i) ++nxtr;
00855                 out(r,c) = (*this)(nxtr,nxtc);
00856             }
00857         }
00858         return out;
00859     }
00860 
00864     template <class EE, int SS> 
00865     TAppendRow appendRow(const Row<N,EE,SS>& row) const {
00866         TAppendRow out;
00867         out.updSubMat<M,N>(0,0) = (*this);
00868         out[M] = row;
00869         return out;
00870     }
00871 
00875     template <class EE, int SS> 
00876     TAppendCol appendCol(const Vec<M,EE,SS>& col) const {
00877         TAppendCol out;
00878         out.updSubMat<M,N>(0,0) = (*this);
00879         out(N) = col;
00880         return out;
00881     }
00882 
00889     template <class ER, int SR, class EC, int SC> 
00890     TAppendRowCol appendRowCol(const Row<N+1,ER,SR>& row,
00891                                const Vec<M+1,EC,SC>& col) const 
00892     {
00893         TAppendRowCol out;
00894         out.updSubMat<M,N>(0,0) = (*this);
00895         out[M].updSubRow<N>(0) = row.updSubRow<N>(0); // ignore last element
00896         out(N) = col;
00897         return out;
00898     }
00899 
00905     template <class EE, int SS> 
00906     TAppendRow insertRow(int i, const Row<N,EE,SS>& row) const {
00907         assert(0 <= i && i <= M);
00908         if (i==M) return appendRow(row);
00909         TAppendRow out;
00910         for (int r=0, nxt=0; r<M; ++r, ++nxt) {
00911             if (nxt==i) out[nxt++] = row;
00912             out[nxt] = (*this)[r];
00913         }
00914         return out;
00915     }
00916 
00922     template <class EE, int SS> 
00923     TAppendCol insertCol(int j, const Vec<M,EE,SS>& col) const {
00924         assert(0 <= j && j <= N);
00925         if (j==N) return appendCol(col);
00926         TAppendCol out;
00927         for (int c=0, nxt=0; c<N; ++c, ++nxt) {
00928             if (nxt==j) out(nxt++) = col;
00929             out(nxt) = (*this)(c);
00930         }
00931         return out;
00932     }
00933 
00941     template <class ER, int SR, class EC, int SC>
00942     TAppendRowCol insertRowCol(int i, int j, const Row<N+1,ER,SR>& row,
00943                                              const Vec<M+1,EC,SC>& col) const {
00944         assert(0 <= i && i <= M);
00945         assert(0 <= j && j <= N);
00946         TAppendRowCol out;
00947         for (int c=0, nxtc=0; c<N; ++c, ++nxtc) { 
00948             if (nxtc==i) ++nxtc;   // leave room
00949             for (int r=0, nxtr=0; r<M; ++r, ++nxtr) {
00950                 if (nxtr==i) ++nxtr;
00951                 out(nxtr,nxtc) = (*this)(r,c);
00952             }
00953         }
00954         out[i] = row;
00955         out(j) = col; // overwrites row's j'th element
00956         return out;
00957     }
00958 
00959     // These assume we are given a pointer to d[0] of a Mat<M,N,E,CS,RS> like this one.
00960     static const Mat& getAs(const ELT* p)  {return *reinterpret_cast<const Mat*>(p);}
00961     static Mat&       updAs(ELT* p)        {return *reinterpret_cast<Mat*>(p);}
00962 
00963     // Note packed spacing
00964     static Mat<M,N,ELT,M,1> getNaN() { 
00965         Mat<M,N,ELT,M,1> m;
00966         m.setToNaN();
00967         return m;
00968     }
00969 
00971     bool isNaN() const {
00972         for (int j=0; j<N; ++j)
00973             if (this->col(j).isNaN())
00974                 return true;
00975         return false;
00976     }
00977 
00980     bool isInf() const {
00981         bool seenInf = false;
00982         for (int j=0; j<N; ++j) {
00983             if (!this->col(j).isFinite()) {
00984                 if (!this->col(j).isInf()) 
00985                     return false; // something bad was found
00986                 seenInf = true; 
00987             }
00988         }
00989         return seenInf;
00990     }
00991 
00993     bool isFinite() const {
00994         for (int j=0; j<N; ++j)
00995             if (!this->col(j).isFinite())
00996                 return false;
00997         return true;
00998     }
00999 
01002     static double getDefaultTolerance() {return MinDim*CNT<ELT>::getDefaultTolerance();}
01003 
01006     template <class E2, int CS2, int RS2>
01007     bool isNumericallyEqual(const Mat<M,N,E2,CS2,RS2>& m, double tol) const {
01008         for (int j=0; j < N; ++j)
01009             if (!(*this)(j).isNumericallyEqual(m(j), tol))
01010                 return false;
01011         return true;
01012     }
01013 
01017     template <class E2, int CS2, int RS2>
01018     bool isNumericallyEqual(const Mat<M,N,E2,CS2,RS2>& m) const {
01019         const double tol = std::max(getDefaultTolerance(),m.getDefaultTolerance());
01020         return isNumericallyEqual(m, tol);
01021     }
01022 
01028     bool isNumericallyEqual
01029        (const ELT& e,
01030         double     tol = getDefaultTolerance()) const 
01031     {
01032         for (int i=0; i<M; ++i)
01033             for (int j=0; j<N; ++j) {
01034                 if (i==j) {
01035                     if (!CNT<ELT>::isNumericallyEqual((*this)(i,i), e, tol))
01036                         return false;
01037                 } else {
01038                     // off-diagonals must be zero
01039                     if (!CNT<ELT>::isNumericallyEqual((*this)(i,j), ELT(0), tol))
01040                         return false;
01041                 }
01042             }
01043         return true;
01044     }
01045 
01053     bool isNumericallySymmetric(double tol = getDefaultTolerance()) const {
01054         if (M != N) return false; // handled at compile time
01055         for (int j=0; j<M; ++j)
01056             for (int i=j; i<M; ++i)
01057                 if (!CNT<ELT>::isNumericallyEqual(elt(j,i), CNT<ELT>::transpose(elt(i,j)), tol))
01058                     return false;
01059         return true;
01060     }
01061 
01068     bool isExactlySymmetric() const {
01069         if (M != N) return false; // handled at compile time
01070         for (int j=0; j<M; ++j)
01071             for (int i=j; i<M; ++i)
01072                 if (elt(j,i) != CNT<ELT>::transpose(elt(i,j)))
01073                     return false;
01074         return true;
01075     }
01076     
01077     TRow sum() const {
01078         TRow temp;
01079         for (int j = 0; j < N; ++j)
01080             temp[j] = col(j).sum();
01081         return temp;
01082     }
01083 
01084 private:
01085     E d[NActualElements];
01086 
01087     // This permits running through d as though it were stored
01088     // in row order with packed elements. Pass in the k'th value
01089     // of the row ordering and get back the index into d where
01090     // that element is stored.
01091     int rIx(int k) const {
01092         const int row = k / N;
01093         const int col = k % N; // that's modulus, not cross product!
01094         return row*RS + col*CS;
01095     }
01096 };
01097 
01099 // Global operators involving two matrices. //
01100 //   m+m, m-m, m*m, m==m, m!=m              //
01102 
01103 template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline 
01104 typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >::Add
01105 operator+(const Mat<M,N,EL,CSL,RSL>& l, const Mat<M,N,ER,CSR,RSR>& r) { 
01106     return Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >
01107         ::AddOp::perform(l,r);
01108 }
01109 
01110 template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline
01111 typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >::Sub
01112 operator-(const Mat<M,N,EL,CSL,RSL>& l, const Mat<M,N,ER,CSR,RSR>& r) { 
01113     return Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >
01114         ::SubOp::perform(l,r);
01115 }
01116 
01117 // Matrix multiply of an MxN by NxP to produce a packed MxP.
01118 template <int M, int N, class EL, int CSL, int RSL, int P, class ER, int CSR, int RSR> inline
01119 typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<N,P,ER,CSR,RSR> >::Mul
01120 operator*(const Mat<M,N,EL,CSL,RSL>& l, const Mat<N,P,ER,CSR,RSR>& r) { 
01121     return Mat<M,N,EL,CSL,RSL>::template Result<Mat<N,P,ER,CSR,RSR> >
01122         ::MulOp::perform(l,r);
01123 }
01124 
01125 // Non-conforming matrix multiply of an MxN by MMxNN; will be a scalar multiply if one
01126 // has scalar elements and the other has composite elements.
01127 template <int M, int N, class EL, int CSL, int RSL, int MM, int NN, class ER, int CSR, int RSR> inline
01128 typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<MM,NN,ER,CSR,RSR> >::MulNon
01129 operator*(const Mat<M,N,EL,CSL,RSL>& l, const Mat<MM,NN,ER,CSR,RSR>& r) { 
01130     return Mat<M,N,EL,CSL,RSL>::template Result<Mat<MM,NN,ER,CSR,RSR> >
01131                 ::MulOpNonConforming::perform(l,r);
01132 }
01133 
01134 template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline
01135 bool operator==(const Mat<M,N,EL,CSL,RSL>& l, const Mat<M,N,ER,CSR,RSR>& r) { 
01136     for (int j=0; j<N; ++j)
01137         if (l(j) != r(j)) return false;
01138     return true;
01139 }
01140 template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline
01141 bool operator!=(const Mat<M,N,EL,CSL,RSL>& l, const Mat<M,N,ER,CSR,RSR>& r) { 
01142     return !(l==r);
01143 }
01144 
01145 
01147 // Global operators involving a matrix and a scalar. //
01149 
01150 // SCALAR MULTIPLY
01151 
01152 // m = m*real, real*m 
01153 template <int M, int N, class E, int CS, int RS> inline
01154 typename Mat<M,N,E,CS,RS>::template Result<float>::Mul
01155 operator*(const Mat<M,N,E,CS,RS>& l, const float& r)
01156   { return Mat<M,N,E,CS,RS>::template Result<float>::MulOp::perform(l,r); }
01157 template <int M, int N, class E, int CS, int RS> inline
01158 typename Mat<M,N,E,CS,RS>::template Result<float>::Mul
01159 operator*(const float& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
01160 
01161 template <int M, int N, class E, int CS, int RS> inline
01162 typename Mat<M,N,E,CS,RS>::template Result<double>::Mul
01163 operator*(const Mat<M,N,E,CS,RS>& l, const double& r)
01164   { return Mat<M,N,E,CS,RS>::template Result<double>::MulOp::perform(l,r); }
01165 template <int M, int N, class E, int CS, int RS> inline
01166 typename Mat<M,N,E,CS,RS>::template Result<double>::Mul
01167 operator*(const double& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
01168 
01169 template <int M, int N, class E, int CS, int RS> inline
01170 typename Mat<M,N,E,CS,RS>::template Result<long double>::Mul
01171 operator*(const Mat<M,N,E,CS,RS>& l, const long double& r)
01172   { return Mat<M,N,E,CS,RS>::template Result<long double>::MulOp::perform(l,r); }
01173 template <int M, int N, class E, int CS, int RS> inline
01174 typename Mat<M,N,E,CS,RS>::template Result<long double>::Mul
01175 operator*(const long double& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
01176 
01177 // m = m*int, int*m -- just convert int to m's precision float
01178 template <int M, int N, class E, int CS, int RS> inline
01179 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Mul
01180 operator*(const Mat<M,N,E,CS,RS>& l, int r) {return l * (typename CNT<E>::Precision)r;}
01181 template <int M, int N, class E, int CS, int RS> inline
01182 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Mul
01183 operator*(int l, const Mat<M,N,E,CS,RS>& r) {return r * (typename CNT<E>::Precision)l;}
01184 
01185 // Complex, conjugate, and negator are all easy to templatize.
01186 
01187 // m = m*complex, complex*m
01188 template <int M, int N, class E, int CS, int RS, class R> inline
01189 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
01190 operator*(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
01191   { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::MulOp::perform(l,r); }
01192 template <int M, int N, class E, int CS, int RS, class R> inline
01193 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
01194 operator*(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
01195 
01196 // m = m*conjugate, conjugate*m (convert conjugate->complex)
01197 template <int M, int N, class E, int CS, int RS, class R> inline
01198 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
01199 operator*(const Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l*(std::complex<R>)r;}
01200 template <int M, int N, class E, int CS, int RS, class R> inline
01201 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
01202 operator*(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return r*(std::complex<R>)l;}
01203 
01204 // m = m*negator, negator*m: convert negator to standard number
01205 template <int M, int N, class E, int CS, int RS, class R> inline
01206 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Mul
01207 operator*(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l * (typename negator<R>::StdNumber)(R)r;}
01208 template <int M, int N, class E, int CS, int RS, class R> inline
01209 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Mul
01210 operator*(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return r * (typename negator<R>::StdNumber)(R)l;}
01211 
01212 
01213 // SCALAR DIVIDE. This is a scalar operation when the scalar is on the right,
01214 // but when it is on the left it means scalar * pseudoInverse(mat), 
01215 // which is a matrix whose type is like the matrix's Hermitian transpose.
01216 // TODO: for now it is just going to call mat.invert() which will fail on
01217 // singular matrices.
01218 
01219 // m = m/real, real/m 
01220 template <int M, int N, class E, int CS, int RS> inline
01221 typename Mat<M,N,E,CS,RS>::template Result<float>::Dvd
01222 operator/(const Mat<M,N,E,CS,RS>& l, const float& r)
01223 {   return Mat<M,N,E,CS,RS>::template Result<float>::DvdOp::perform(l,r); }
01224 
01225 template <int M, int N, class E, int CS, int RS> inline
01226 typename CNT<float>::template Result<Mat<M,N,E,CS,RS> >::Dvd
01227 operator/(const float& l, const Mat<M,N,E,CS,RS>& r)
01228 {   return l * r.invert(); }
01229 
01230 template <int M, int N, class E, int CS, int RS> inline
01231 typename Mat<M,N,E,CS,RS>::template Result<double>::Dvd
01232 operator/(const Mat<M,N,E,CS,RS>& l, const double& r)
01233 {   return Mat<M,N,E,CS,RS>::template Result<double>::DvdOp::perform(l,r); }
01234 
01235 template <int M, int N, class E, int CS, int RS> inline
01236 typename CNT<double>::template Result<Mat<M,N,E,CS,RS> >::Dvd
01237 operator/(const double& l, const Mat<M,N,E,CS,RS>& r)
01238 {   return l * r.invert(); }
01239 
01240 template <int M, int N, class E, int CS, int RS> inline
01241 typename Mat<M,N,E,CS,RS>::template Result<long double>::Dvd
01242 operator/(const Mat<M,N,E,CS,RS>& l, const long double& r)
01243 {   return Mat<M,N,E,CS,RS>::template Result<long double>::DvdOp::perform(l,r); }
01244 
01245 template <int M, int N, class E, int CS, int RS> inline
01246 typename CNT<long double>::template Result<Mat<M,N,E,CS,RS> >::Dvd
01247 operator/(const long double& l, const Mat<M,N,E,CS,RS>& r)
01248 {   return l * r.invert(); }
01249 
01250 // m = m/int, int/m -- just convert int to m's precision float
01251 template <int M, int N, class E, int CS, int RS> inline
01252 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Dvd
01253 operator/(const Mat<M,N,E,CS,RS>& l, int r) 
01254 {   return l / (typename CNT<E>::Precision)r; }
01255 
01256 template <int M, int N, class E, int CS, int RS> inline
01257 typename CNT<typename CNT<E>::Precision>::template Result<Mat<M,N,E,CS,RS> >::Dvd
01258 operator/(int l, const Mat<M,N,E,CS,RS>& r) 
01259 {   return (typename CNT<E>::Precision)l / r; }
01260 
01261 
01262 // Complex, conjugate, and negator are all easy to templatize.
01263 
01264 // m = m/complex, complex/m
01265 template <int M, int N, class E, int CS, int RS, class R> inline
01266 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Dvd
01267 operator/(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
01268   { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::DvdOp::perform(l,r); }
01269 template <int M, int N, class E, int CS, int RS, class R> inline
01270 typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Dvd
01271 operator/(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r)
01272   { return CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::DvdOp::perform(l,r); }
01273 
01274 // m = m/conjugate, conjugate/m (convert conjugate->complex)
01275 template <int M, int N, class E, int CS, int RS, class R> inline
01276 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Dvd
01277 operator/(const Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l/(std::complex<R>)r;}
01278 template <int M, int N, class E, int CS, int RS, class R> inline
01279 typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Dvd
01280 operator/(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return (std::complex<R>)l/r;}
01281 
01282 // m = m/negator, negator/m: convert negator to a standard number
01283 template <int M, int N, class E, int CS, int RS, class R> inline
01284 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Dvd
01285 operator/(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l/(typename negator<R>::StdNumber)(R)r;}
01286 template <int M, int N, class E, int CS, int RS, class R> inline
01287 typename CNT<R>::template Result<Mat<M,N,E,CS,RS> >::Dvd
01288 operator/(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return (typename negator<R>::StdNumber)(R)l/r;}
01289 
01290 
01291 // Add and subtract are odd as scalar ops. They behave as though the
01292 // scalar stands for a conforming matrix whose diagonal elements are that,
01293 // scalar and then a normal matrix add or subtract is done.
01294 
01295 // SCALAR ADD
01296 
01297 // m = m+real, real+m 
01298 template <int M, int N, class E, int CS, int RS> inline
01299 typename Mat<M,N,E,CS,RS>::template Result<float>::Add
01300 operator+(const Mat<M,N,E,CS,RS>& l, const float& r)
01301   { return Mat<M,N,E,CS,RS>::template Result<float>::AddOp::perform(l,r); }
01302 template <int M, int N, class E, int CS, int RS> inline
01303 typename Mat<M,N,E,CS,RS>::template Result<float>::Add
01304 operator+(const float& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
01305 
01306 template <int M, int N, class E, int CS, int RS> inline
01307 typename Mat<M,N,E,CS,RS>::template Result<double>::Add
01308 operator+(const Mat<M,N,E,CS,RS>& l, const double& r)
01309   { return Mat<M,N,E,CS,RS>::template Result<double>::AddOp::perform(l,r); }
01310 template <int M, int N, class E, int CS, int RS> inline
01311 typename Mat<M,N,E,CS,RS>::template Result<double>::Add
01312 operator+(const double& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
01313 
01314 template <int M, int N, class E, int CS, int RS> inline
01315 typename Mat<M,N,E,CS,RS>::template Result<long double>::Add
01316 operator+(const Mat<M,N,E,CS,RS>& l, const long double& r)
01317   { return Mat<M,N,E,CS,RS>::template Result<long double>::AddOp::perform(l,r); }
01318 template <int M, int N, class E, int CS, int RS> inline
01319 typename Mat<M,N,E,CS,RS>::template Result<long double>::Add
01320 operator+(const long double& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
01321 
01322 // m = m+int, int+m -- just convert int to m's precision float
01323 template <int M, int N, class E, int CS, int RS> inline
01324 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Add
01325 operator+(const Mat<M,N,E,CS,RS>& l, int r) {return l + (typename CNT<E>::Precision)r;}
01326 template <int M, int N, class E, int CS, int RS> inline
01327 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Add
01328 operator+(int l, const Mat<M,N,E,CS,RS>& r) {return r + (typename CNT<E>::Precision)l;}
01329 
01330 // Complex, conjugate, and negator are all easy to templatize.
01331 
01332 // m = m+complex, complex+m
01333 template <int M, int N, class E, int CS, int RS, class R> inline
01334 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
01335 operator+(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
01336   { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::AddOp::perform(l,r); }
01337 template <int M, int N, class E, int CS, int RS, class R> inline
01338 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
01339 operator+(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
01340 
01341 // m = m+conjugate, conjugate+m (convert conjugate->complex)
01342 template <int M, int N, class E, int CS, int RS, class R> inline
01343 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
01344 operator+(const Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l+(std::complex<R>)r;}
01345 template <int M, int N, class E, int CS, int RS, class R> inline
01346 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
01347 operator+(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return r+(std::complex<R>)l;}
01348 
01349 // m = m+negator, negator+m: convert negator to standard number
01350 template <int M, int N, class E, int CS, int RS, class R> inline
01351 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Add
01352 operator+(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l + (typename negator<R>::StdNumber)(R)r;}
01353 template <int M, int N, class E, int CS, int RS, class R> inline
01354 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Add
01355 operator+(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return r + (typename negator<R>::StdNumber)(R)l;}
01356 
01357 // SCALAR SUBTRACT -- careful, not commutative.
01358 
01359 // m = m-real, real-m 
01360 template <int M, int N, class E, int CS, int RS> inline
01361 typename Mat<M,N,E,CS,RS>::template Result<float>::Sub
01362 operator-(const Mat<M,N,E,CS,RS>& l, const float& r)
01363   { return Mat<M,N,E,CS,RS>::template Result<float>::SubOp::perform(l,r); }
01364 template <int M, int N, class E, int CS, int RS> inline
01365 typename CNT<float>::template Result<Mat<M,N,E,CS,RS> >::Sub
01366 operator-(const float& l, const Mat<M,N,E,CS,RS>& r)
01367   { return CNT<float>::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
01368 
01369 template <int M, int N, class E, int CS, int RS> inline
01370 typename Mat<M,N,E,CS,RS>::template Result<double>::Sub
01371 operator-(const Mat<M,N,E,CS,RS>& l, const double& r)
01372   { return Mat<M,N,E,CS,RS>::template Result<double>::SubOp::perform(l,r); }
01373 template <int M, int N, class E, int CS, int RS> inline
01374 typename CNT<double>::template Result<Mat<M,N,E,CS,RS> >::Sub
01375 operator-(const double& l, const Mat<M,N,E,CS,RS>& r)
01376   { return CNT<double>::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
01377 
01378 template <int M, int N, class E, int CS, int RS> inline
01379 typename Mat<M,N,E,CS,RS>::template Result<long double>::Sub
01380 operator-(const Mat<M,N,E,CS,RS>& l, const long double& r)
01381   { return Mat<M,N,E,CS,RS>::template Result<long double>::SubOp::perform(l,r); }
01382 template <int M, int N, class E, int CS, int RS> inline
01383 typename CNT<long double>::template Result<Mat<M,N,E,CS,RS> >::Sub
01384 operator-(const long double& l, const Mat<M,N,E,CS,RS>& r)
01385   { return CNT<long double>::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
01386 
01387 // m = m-int, int-m // just convert int to m's precision float
01388 template <int M, int N, class E, int CS, int RS> inline
01389 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Sub
01390 operator-(const Mat<M,N,E,CS,RS>& l, int r) {return l - (typename CNT<E>::Precision)r;}
01391 template <int M, int N, class E, int CS, int RS> inline
01392 typename CNT<typename CNT<E>::Precision>::template Result<Mat<M,N,E,CS,RS> >::Sub
01393 operator-(int l, const Mat<M,N,E,CS,RS>& r) {return (typename CNT<E>::Precision)l - r;}
01394 
01395 
01396 // Complex, conjugate, and negator are all easy to templatize.
01397 
01398 // m = m-complex, complex-m
01399 template <int M, int N, class E, int CS, int RS, class R> inline
01400 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Sub
01401 operator-(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
01402   { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::SubOp::perform(l,r); }
01403 template <int M, int N, class E, int CS, int RS, class R> inline
01404 typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Sub
01405 operator-(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r)
01406   { return CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
01407 
01408 // m = m-conjugate, conjugate-m (convert conjugate->complex)
01409 template <int M, int N, class E, int CS, int RS, class R> inline
01410 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Sub
01411 operator-(const Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l-(std::complex<R>)r;}
01412 template <int M, int N, class E, int CS, int RS, class R> inline
01413 typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Sub
01414 operator-(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return (std::complex<R>)l-r;}
01415 
01416 // m = m-negator, negator-m: convert negator to standard number
01417 template <int M, int N, class E, int CS, int RS, class R> inline
01418 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Sub
01419 operator-(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l-(typename negator<R>::StdNumber)(R)r;}
01420 template <int M, int N, class E, int CS, int RS, class R> inline
01421 typename CNT<R>::template Result<Mat<M,N,E,CS,RS> >::Sub
01422 operator-(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return (typename negator<R>::StdNumber)(R)l-r;}
01423 
01424 
01425 // Mat I/O
01426 template <int M, int N, class E, int CS, int RS, class CHAR, class TRAITS> inline
01427 std::basic_ostream<CHAR,TRAITS>&
01428 operator<<(std::basic_ostream<CHAR,TRAITS>& o, const Mat<M,N,E,CS,RS>& m) {
01429     for (int i=0;i<M;++i) {
01430         o << std::endl << "[";
01431         for (int j=0;j<N;++j)         
01432             o << (j>0?",":"") << m(i,j);
01433         o << "]";
01434     }
01435     if (M) o << std::endl;
01436     return o; 
01437 }
01438 
01439 template <int M, int N, class E, int CS, int RS, class CHAR, class TRAITS> inline
01440 std::basic_istream<CHAR,TRAITS>&
01441 operator>>(std::basic_istream<CHAR,TRAITS>& is, Mat<M,N,E,CS,RS>& m) {
01442     // TODO: not sure how to do Vec input yet
01443     assert(false);
01444     return is;
01445 }
01446 
01447 } //namespace SimTK
01448 
01449 
01450 #endif //SimTK_SIMMATRIX_SMALLMATRIX_MAT_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines