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 
00814 
00817     TDropRow dropRow(int i) const {
00818         assert(0 <= i && i < M);
00819         TDropRow out;
00820         for (int r=0, nxt=0; r<M-1; ++r, ++nxt) {
00821             if (nxt==i) ++nxt;  // skip the loser
00822             out[r] = (*this)[nxt];
00823         }
00824         return out;
00825     }
00826 
00829     TDropCol dropCol(int j) const {
00830         assert(0 <= j && j < N);
00831         TDropCol out;
00832         for (int c=0, nxt=0; c<N-1; ++c, ++nxt) {
00833             if (nxt==j) ++nxt;  // skip the loser
00834             out(c) = (*this)(nxt);
00835         }
00836         return out;
00837     }
00838 
00842     TDropRowCol dropRowCol(int i, int j) const {
00843         assert(0 <= i && i < M);
00844         assert(0 <= j && j < N);
00845         TDropRowCol out;
00846         for (int c=0, nxtc=0; c<N-1; ++c, ++nxtc) { 
00847             if (nxtc==j) ++nxtc;
00848             for (int r=0, nxtr=0; r<M-1; ++r, ++nxtr) {
00849                 if (nxtr==i) ++nxtr;
00850                 out(r,c) = (*this)(nxtr,nxtc);
00851             }
00852         }
00853         return out;
00854     }
00855 
00859     template <class EE, int SS> 
00860     TAppendRow appendRow(const Row<N,EE,SS>& row) const {
00861         TAppendRow out;
00862         out.updSubMat<M,N>(0,0) = (*this);
00863         out[M] = row;
00864         return out;
00865     }
00866 
00870     template <class EE, int SS> 
00871     TAppendCol appendCol(const Vec<M,EE,SS>& col) const {
00872         TAppendCol out;
00873         out.updSubMat<M,N>(0,0) = (*this);
00874         out(N) = col;
00875         return out;
00876     }
00877 
00884     template <class ER, int SR, class EC, int SC> 
00885     TAppendRowCol appendRowCol(const Row<N+1,ER,SR>& row,
00886                                const Vec<M+1,EC,SC>& col) const 
00887     {
00888         TAppendRowCol out;
00889         out.updSubMat<M,N>(0,0) = (*this);
00890         out[M].updSubRow<N>(0) = row.updSubRow<N>(0); // ignore last element
00891         out(N) = col;
00892         return out;
00893     }
00894 
00900     template <class EE, int SS> 
00901     TAppendRow insertRow(int i, const Row<N,EE,SS>& row) const {
00902         assert(0 <= i && i <= M);
00903         if (i==M) return appendRow(row);
00904         TAppendRow out;
00905         for (int r=0, nxt=0; r<M; ++r, ++nxt) {
00906             if (nxt==i) out[nxt++] = row;
00907             out[nxt] = (*this)[r];
00908         }
00909         return out;
00910     }
00911 
00917     template <class EE, int SS> 
00918     TAppendCol insertCol(int j, const Vec<M,EE,SS>& col) const {
00919         assert(0 <= j && j <= N);
00920         if (j==N) return appendCol(col);
00921         TAppendCol out;
00922         for (int c=0, nxt=0; c<N; ++c, ++nxt) {
00923             if (nxt==j) out(nxt++) = col;
00924             out(nxt) = (*this)(c);
00925         }
00926         return out;
00927     }
00928 
00936     template <class ER, int SR, class EC, int SC>
00937     TAppendRowCol insertRowCol(int i, int j, const Row<N+1,ER,SR>& row,
00938                                              const Vec<M+1,EC,SC>& col) const {
00939         assert(0 <= i && i <= M);
00940         assert(0 <= j && j <= N);
00941         TAppendRowCol out;
00942         for (int c=0, nxtc=0; c<N; ++c, ++nxtc) { 
00943             if (nxtc==i) ++nxtc;   // leave room
00944             for (int r=0, nxtr=0; r<M; ++r, ++nxtr) {
00945                 if (nxtr==i) ++nxtr;
00946                 out(nxtr,nxtc) = (*this)(r,c);
00947             }
00948         }
00949         out[i] = row;
00950         out(j) = col; // overwrites row's j'th element
00951         return out;
00952     }
00953 
00954     // These assume we are given a pointer to d[0] of a Mat<M,N,E,CS,RS> like this one.
00955     static const Mat& getAs(const ELT* p)  {return *reinterpret_cast<const Mat*>(p);}
00956     static Mat&       updAs(ELT* p)        {return *reinterpret_cast<Mat*>(p);}
00957 
00958     // Note packed spacing
00959     static Mat<M,N,ELT,M,1> getNaN() { 
00960         Mat<M,N,ELT,M,1> m;
00961         m.setToNaN();
00962         return m;
00963     }
00964 
00966     bool isNaN() const {
00967         for (int j=0; j<N; ++j)
00968             if (this->col(j).isNaN())
00969                 return true;
00970         return false;
00971     }
00972 
00975     bool isInf() const {
00976         bool seenInf = false;
00977         for (int j=0; j<N; ++j) {
00978             if (!this->col(j).isFinite()) {
00979                 if (!this->col(j).isInf()) 
00980                     return false; // something bad was found
00981                 seenInf = true; 
00982             }
00983         }
00984         return seenInf;
00985     }
00986 
00988     bool isFinite() const {
00989         for (int j=0; j<N; ++j)
00990             if (!this->col(j).isFinite())
00991                 return false;
00992         return true;
00993     }
00994 
00997     static double getDefaultTolerance() {return MinDim*CNT<ELT>::getDefaultTolerance();}
00998 
01001     template <class E2, int CS2, int RS2>
01002     bool isNumericallyEqual(const Mat<M,N,E2,CS2,RS2>& m, double tol) const {
01003         for (int j=0; j < N; ++j)
01004             if (!(*this)(j).isNumericallyEqual(m(j), tol))
01005                 return false;
01006         return true;
01007     }
01008 
01012     template <class E2, int CS2, int RS2>
01013     bool isNumericallyEqual(const Mat<M,N,E2,CS2,RS2>& m) const {
01014         const double tol = std::max(getDefaultTolerance(),m.getDefaultTolerance());
01015         return isNumericallyEqual(m, tol);
01016     }
01017 
01023     bool isNumericallyEqual
01024        (const ELT& e,
01025         double     tol = getDefaultTolerance()) const 
01026     {
01027         for (int i=0; i<M; ++i)
01028             for (int j=0; j<N; ++j) {
01029                 if (i==j) {
01030                     if (!CNT<ELT>::isNumericallyEqual((*this)(i,i), e, tol))
01031                         return false;
01032                 } else {
01033                     // off-diagonals must be zero
01034                     if (!CNT<ELT>::isNumericallyEqual((*this)(i,j), ELT(0), tol))
01035                         return false;
01036                 }
01037             }
01038         return true;
01039     }
01040 
01048     bool isNumericallySymmetric(double tol = getDefaultTolerance()) const {
01049         if (M != N) return false; // handled at compile time
01050         for (int j=0; j<M; ++j)
01051             for (int i=j; i<M; ++i)
01052                 if (!CNT<ELT>::isNumericallyEqual(elt(j,i), CNT<ELT>::transpose(elt(i,j)), tol))
01053                     return false;
01054         return true;
01055     }
01056 
01063     bool isExactlySymmetric() const {
01064         if (M != N) return false; // handled at compile time
01065         for (int j=0; j<M; ++j)
01066             for (int i=j; i<M; ++i)
01067                 if (elt(j,i) != CNT<ELT>::transpose(elt(i,j)))
01068                     return false;
01069         return true;
01070     }
01071     
01072     TRow sum() const {
01073         TRow temp;
01074         for (int j = 0; j < N; ++j)
01075             temp[j] = col(j).sum();
01076         return temp;
01077     }
01078 
01079 private:
01080     E d[NActualElements];
01081 
01082     // This permits running through d as though it were stored
01083     // in row order with packed elements. Pass in the k'th value
01084     // of the row ordering and get back the index into d where
01085     // that element is stored.
01086     int rIx(int k) const {
01087         const int row = k / N;
01088         const int col = k % N; // that's modulus, not cross product!
01089         return row*RS + col*CS;
01090     }
01091 };
01092 
01094 // Global operators involving two matrices. //
01095 //   m+m, m-m, m*m, m==m, m!=m              //
01097 
01098 template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline 
01099 typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >::Add
01100 operator+(const Mat<M,N,EL,CSL,RSL>& l, const Mat<M,N,ER,CSR,RSR>& r) { 
01101     return Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >
01102         ::AddOp::perform(l,r);
01103 }
01104 
01105 template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline
01106 typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >::Sub
01107 operator-(const Mat<M,N,EL,CSL,RSL>& l, const Mat<M,N,ER,CSR,RSR>& r) { 
01108     return Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >
01109         ::SubOp::perform(l,r);
01110 }
01111 
01112 // Matrix multiply of an MxN by NxP to produce a packed MxP.
01113 template <int M, int N, class EL, int CSL, int RSL, int P, class ER, int CSR, int RSR> inline
01114 typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<N,P,ER,CSR,RSR> >::Mul
01115 operator*(const Mat<M,N,EL,CSL,RSL>& l, const Mat<N,P,ER,CSR,RSR>& r) { 
01116     return Mat<M,N,EL,CSL,RSL>::template Result<Mat<N,P,ER,CSR,RSR> >
01117         ::MulOp::perform(l,r);
01118 }
01119 
01120 // Non-conforming matrix multiply of an MxN by MMxNN; will be a scalar multiply if one
01121 // has scalar elements and the other has composite elements.
01122 template <int M, int N, class EL, int CSL, int RSL, int MM, int NN, class ER, int CSR, int RSR> inline
01123 typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<MM,NN,ER,CSR,RSR> >::MulNon
01124 operator*(const Mat<M,N,EL,CSL,RSL>& l, const Mat<MM,NN,ER,CSR,RSR>& r) { 
01125     return Mat<M,N,EL,CSL,RSL>::template Result<Mat<MM,NN,ER,CSR,RSR> >
01126                 ::MulOpNonConforming::perform(l,r);
01127 }
01128 
01129 template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline
01130 bool operator==(const Mat<M,N,EL,CSL,RSL>& l, const Mat<M,N,ER,CSR,RSR>& r) { 
01131     for (int j=0; j<N; ++j)
01132         if (l(j) != r(j)) return false;
01133     return true;
01134 }
01135 template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline
01136 bool operator!=(const Mat<M,N,EL,CSL,RSL>& l, const Mat<M,N,ER,CSR,RSR>& r) { 
01137     return !(l==r);
01138 }
01139 
01140 
01142 // Global operators involving a matrix and a scalar. //
01144 
01145 // SCALAR MULTIPLY
01146 
01147 // m = m*real, real*m 
01148 template <int M, int N, class E, int CS, int RS> inline
01149 typename Mat<M,N,E,CS,RS>::template Result<float>::Mul
01150 operator*(const Mat<M,N,E,CS,RS>& l, const float& r)
01151   { return Mat<M,N,E,CS,RS>::template Result<float>::MulOp::perform(l,r); }
01152 template <int M, int N, class E, int CS, int RS> inline
01153 typename Mat<M,N,E,CS,RS>::template Result<float>::Mul
01154 operator*(const float& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
01155 
01156 template <int M, int N, class E, int CS, int RS> inline
01157 typename Mat<M,N,E,CS,RS>::template Result<double>::Mul
01158 operator*(const Mat<M,N,E,CS,RS>& l, const double& r)
01159   { return Mat<M,N,E,CS,RS>::template Result<double>::MulOp::perform(l,r); }
01160 template <int M, int N, class E, int CS, int RS> inline
01161 typename Mat<M,N,E,CS,RS>::template Result<double>::Mul
01162 operator*(const double& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
01163 
01164 template <int M, int N, class E, int CS, int RS> inline
01165 typename Mat<M,N,E,CS,RS>::template Result<long double>::Mul
01166 operator*(const Mat<M,N,E,CS,RS>& l, const long double& r)
01167   { return Mat<M,N,E,CS,RS>::template Result<long double>::MulOp::perform(l,r); }
01168 template <int M, int N, class E, int CS, int RS> inline
01169 typename Mat<M,N,E,CS,RS>::template Result<long double>::Mul
01170 operator*(const long double& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
01171 
01172 // m = m*int, int*m -- just convert int to m's precision float
01173 template <int M, int N, class E, int CS, int RS> inline
01174 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Mul
01175 operator*(const Mat<M,N,E,CS,RS>& l, int r) {return l * (typename CNT<E>::Precision)r;}
01176 template <int M, int N, class E, int CS, int RS> inline
01177 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Mul
01178 operator*(int l, const Mat<M,N,E,CS,RS>& r) {return r * (typename CNT<E>::Precision)l;}
01179 
01180 // Complex, conjugate, and negator are all easy to templatize.
01181 
01182 // m = m*complex, complex*m
01183 template <int M, int N, class E, int CS, int RS, class R> inline
01184 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
01185 operator*(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
01186   { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::MulOp::perform(l,r); }
01187 template <int M, int N, class E, int CS, int RS, class R> inline
01188 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
01189 operator*(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
01190 
01191 // m = m*conjugate, conjugate*m (convert conjugate->complex)
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 Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l*(std::complex<R>)r;}
01195 template <int M, int N, class E, int CS, int RS, class R> inline
01196 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
01197 operator*(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return r*(std::complex<R>)l;}
01198 
01199 // m = m*negator, negator*m: convert negator to standard number
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<typename negator<R>::StdNumber>::Mul
01202 operator*(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l * (typename negator<R>::StdNumber)(R)r;}
01203 template <int M, int N, class E, int CS, int RS, class R> inline
01204 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Mul
01205 operator*(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return r * (typename negator<R>::StdNumber)(R)l;}
01206 
01207 
01208 // SCALAR DIVIDE. This is a scalar operation when the scalar is on the right,
01209 // but when it is on the left it means scalar * pseudoInverse(mat), 
01210 // which is a matrix whose type is like the matrix's Hermitian transpose.
01211 // TODO: for now it is just going to call mat.invert() which will fail on
01212 // singular matrices.
01213 
01214 // m = m/real, real/m 
01215 template <int M, int N, class E, int CS, int RS> inline
01216 typename Mat<M,N,E,CS,RS>::template Result<float>::Dvd
01217 operator/(const Mat<M,N,E,CS,RS>& l, const float& r)
01218 {   return Mat<M,N,E,CS,RS>::template Result<float>::DvdOp::perform(l,r); }
01219 
01220 template <int M, int N, class E, int CS, int RS> inline
01221 typename CNT<float>::template Result<Mat<M,N,E,CS,RS> >::Dvd
01222 operator/(const float& l, const Mat<M,N,E,CS,RS>& r)
01223 {   return l * r.invert(); }
01224 
01225 template <int M, int N, class E, int CS, int RS> inline
01226 typename Mat<M,N,E,CS,RS>::template Result<double>::Dvd
01227 operator/(const Mat<M,N,E,CS,RS>& l, const double& r)
01228 {   return Mat<M,N,E,CS,RS>::template Result<double>::DvdOp::perform(l,r); }
01229 
01230 template <int M, int N, class E, int CS, int RS> inline
01231 typename CNT<double>::template Result<Mat<M,N,E,CS,RS> >::Dvd
01232 operator/(const double& l, const Mat<M,N,E,CS,RS>& r)
01233 {   return l * r.invert(); }
01234 
01235 template <int M, int N, class E, int CS, int RS> inline
01236 typename Mat<M,N,E,CS,RS>::template Result<long double>::Dvd
01237 operator/(const Mat<M,N,E,CS,RS>& l, const long double& r)
01238 {   return Mat<M,N,E,CS,RS>::template Result<long double>::DvdOp::perform(l,r); }
01239 
01240 template <int M, int N, class E, int CS, int RS> inline
01241 typename CNT<long double>::template Result<Mat<M,N,E,CS,RS> >::Dvd
01242 operator/(const long double& l, const Mat<M,N,E,CS,RS>& r)
01243 {   return l * r.invert(); }
01244 
01245 // m = m/int, int/m -- just convert int to m's precision float
01246 template <int M, int N, class E, int CS, int RS> inline
01247 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Dvd
01248 operator/(const Mat<M,N,E,CS,RS>& l, int r) 
01249 {   return l / (typename CNT<E>::Precision)r; }
01250 
01251 template <int M, int N, class E, int CS, int RS> inline
01252 typename CNT<typename CNT<E>::Precision>::template Result<Mat<M,N,E,CS,RS> >::Dvd
01253 operator/(int l, const Mat<M,N,E,CS,RS>& r) 
01254 {   return (typename CNT<E>::Precision)l / r; }
01255 
01256 
01257 // Complex, conjugate, and negator are all easy to templatize.
01258 
01259 // m = m/complex, complex/m
01260 template <int M, int N, class E, int CS, int RS, class R> inline
01261 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Dvd
01262 operator/(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
01263   { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::DvdOp::perform(l,r); }
01264 template <int M, int N, class E, int CS, int RS, class R> inline
01265 typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Dvd
01266 operator/(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r)
01267   { return CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::DvdOp::perform(l,r); }
01268 
01269 // m = m/conjugate, conjugate/m (convert conjugate->complex)
01270 template <int M, int N, class E, int CS, int RS, class R> inline
01271 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Dvd
01272 operator/(const Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l/(std::complex<R>)r;}
01273 template <int M, int N, class E, int CS, int RS, class R> inline
01274 typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Dvd
01275 operator/(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return (std::complex<R>)l/r;}
01276 
01277 // m = m/negator, negator/m: convert negator to a standard number
01278 template <int M, int N, class E, int CS, int RS, class R> inline
01279 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Dvd
01280 operator/(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l/(typename negator<R>::StdNumber)(R)r;}
01281 template <int M, int N, class E, int CS, int RS, class R> inline
01282 typename CNT<R>::template Result<Mat<M,N,E,CS,RS> >::Dvd
01283 operator/(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return (typename negator<R>::StdNumber)(R)l/r;}
01284 
01285 
01286 // Add and subtract are odd as scalar ops. They behave as though the
01287 // scalar stands for a conforming matrix whose diagonal elements are that,
01288 // scalar and then a normal matrix add or subtract is done.
01289 
01290 // SCALAR ADD
01291 
01292 // m = m+real, real+m 
01293 template <int M, int N, class E, int CS, int RS> inline
01294 typename Mat<M,N,E,CS,RS>::template Result<float>::Add
01295 operator+(const Mat<M,N,E,CS,RS>& l, const float& r)
01296   { return Mat<M,N,E,CS,RS>::template Result<float>::AddOp::perform(l,r); }
01297 template <int M, int N, class E, int CS, int RS> inline
01298 typename Mat<M,N,E,CS,RS>::template Result<float>::Add
01299 operator+(const float& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
01300 
01301 template <int M, int N, class E, int CS, int RS> inline
01302 typename Mat<M,N,E,CS,RS>::template Result<double>::Add
01303 operator+(const Mat<M,N,E,CS,RS>& l, const double& r)
01304   { return Mat<M,N,E,CS,RS>::template Result<double>::AddOp::perform(l,r); }
01305 template <int M, int N, class E, int CS, int RS> inline
01306 typename Mat<M,N,E,CS,RS>::template Result<double>::Add
01307 operator+(const double& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
01308 
01309 template <int M, int N, class E, int CS, int RS> inline
01310 typename Mat<M,N,E,CS,RS>::template Result<long double>::Add
01311 operator+(const Mat<M,N,E,CS,RS>& l, const long double& r)
01312   { return Mat<M,N,E,CS,RS>::template Result<long double>::AddOp::perform(l,r); }
01313 template <int M, int N, class E, int CS, int RS> inline
01314 typename Mat<M,N,E,CS,RS>::template Result<long double>::Add
01315 operator+(const long double& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
01316 
01317 // m = m+int, int+m -- just convert int to m's precision float
01318 template <int M, int N, class E, int CS, int RS> inline
01319 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Add
01320 operator+(const Mat<M,N,E,CS,RS>& l, int r) {return l + (typename CNT<E>::Precision)r;}
01321 template <int M, int N, class E, int CS, int RS> inline
01322 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Add
01323 operator+(int l, const Mat<M,N,E,CS,RS>& r) {return r + (typename CNT<E>::Precision)l;}
01324 
01325 // Complex, conjugate, and negator are all easy to templatize.
01326 
01327 // m = m+complex, complex+m
01328 template <int M, int N, class E, int CS, int RS, class R> inline
01329 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
01330 operator+(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
01331   { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::AddOp::perform(l,r); }
01332 template <int M, int N, class E, int CS, int RS, class R> inline
01333 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
01334 operator+(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
01335 
01336 // m = m+conjugate, conjugate+m (convert conjugate->complex)
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 Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l+(std::complex<R>)r;}
01340 template <int M, int N, class E, int CS, int RS, class R> inline
01341 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
01342 operator+(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return r+(std::complex<R>)l;}
01343 
01344 // m = m+negator, negator+m: convert negator to standard number
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<typename negator<R>::StdNumber>::Add
01347 operator+(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l + (typename negator<R>::StdNumber)(R)r;}
01348 template <int M, int N, class E, int CS, int RS, class R> inline
01349 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Add
01350 operator+(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return r + (typename negator<R>::StdNumber)(R)l;}
01351 
01352 // SCALAR SUBTRACT -- careful, not commutative.
01353 
01354 // m = m-real, real-m 
01355 template <int M, int N, class E, int CS, int RS> inline
01356 typename Mat<M,N,E,CS,RS>::template Result<float>::Sub
01357 operator-(const Mat<M,N,E,CS,RS>& l, const float& r)
01358   { return Mat<M,N,E,CS,RS>::template Result<float>::SubOp::perform(l,r); }
01359 template <int M, int N, class E, int CS, int RS> inline
01360 typename CNT<float>::template Result<Mat<M,N,E,CS,RS> >::Sub
01361 operator-(const float& l, const Mat<M,N,E,CS,RS>& r)
01362   { return CNT<float>::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
01363 
01364 template <int M, int N, class E, int CS, int RS> inline
01365 typename Mat<M,N,E,CS,RS>::template Result<double>::Sub
01366 operator-(const Mat<M,N,E,CS,RS>& l, const double& r)
01367   { return Mat<M,N,E,CS,RS>::template Result<double>::SubOp::perform(l,r); }
01368 template <int M, int N, class E, int CS, int RS> inline
01369 typename CNT<double>::template Result<Mat<M,N,E,CS,RS> >::Sub
01370 operator-(const double& l, const Mat<M,N,E,CS,RS>& r)
01371   { return CNT<double>::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
01372 
01373 template <int M, int N, class E, int CS, int RS> inline
01374 typename Mat<M,N,E,CS,RS>::template Result<long double>::Sub
01375 operator-(const Mat<M,N,E,CS,RS>& l, const long double& r)
01376   { return Mat<M,N,E,CS,RS>::template Result<long double>::SubOp::perform(l,r); }
01377 template <int M, int N, class E, int CS, int RS> inline
01378 typename CNT<long double>::template Result<Mat<M,N,E,CS,RS> >::Sub
01379 operator-(const long double& l, const Mat<M,N,E,CS,RS>& r)
01380   { return CNT<long double>::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
01381 
01382 // m = m-int, int-m // just convert int to m's precision float
01383 template <int M, int N, class E, int CS, int RS> inline
01384 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Sub
01385 operator-(const Mat<M,N,E,CS,RS>& l, int r) {return l - (typename CNT<E>::Precision)r;}
01386 template <int M, int N, class E, int CS, int RS> inline
01387 typename CNT<typename CNT<E>::Precision>::template Result<Mat<M,N,E,CS,RS> >::Sub
01388 operator-(int l, const Mat<M,N,E,CS,RS>& r) {return (typename CNT<E>::Precision)l - r;}
01389 
01390 
01391 // Complex, conjugate, and negator are all easy to templatize.
01392 
01393 // m = m-complex, complex-m
01394 template <int M, int N, class E, int CS, int RS, class R> inline
01395 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Sub
01396 operator-(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
01397   { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::SubOp::perform(l,r); }
01398 template <int M, int N, class E, int CS, int RS, class R> inline
01399 typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Sub
01400 operator-(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r)
01401   { return CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
01402 
01403 // m = m-conjugate, conjugate-m (convert conjugate->complex)
01404 template <int M, int N, class E, int CS, int RS, class R> inline
01405 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Sub
01406 operator-(const Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l-(std::complex<R>)r;}
01407 template <int M, int N, class E, int CS, int RS, class R> inline
01408 typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Sub
01409 operator-(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return (std::complex<R>)l-r;}
01410 
01411 // m = m-negator, negator-m: convert negator to standard number
01412 template <int M, int N, class E, int CS, int RS, class R> inline
01413 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Sub
01414 operator-(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l-(typename negator<R>::StdNumber)(R)r;}
01415 template <int M, int N, class E, int CS, int RS, class R> inline
01416 typename CNT<R>::template Result<Mat<M,N,E,CS,RS> >::Sub
01417 operator-(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return (typename negator<R>::StdNumber)(R)l-r;}
01418 
01419 
01420 // Mat I/O
01421 template <int M, int N, class E, int CS, int RS, class CHAR, class TRAITS> inline
01422 std::basic_ostream<CHAR,TRAITS>&
01423 operator<<(std::basic_ostream<CHAR,TRAITS>& o, const Mat<M,N,E,CS,RS>& m) {
01424     for (int i=0;i<M;++i) {
01425         o << std::endl << "[";
01426         for (int j=0;j<N;++j)         
01427             o << (j>0?",":"") << m(i,j);
01428         o << "]";
01429     }
01430     if (M) o << std::endl;
01431     return o; 
01432 }
01433 
01434 template <int M, int N, class E, int CS, int RS, class CHAR, class TRAITS> inline
01435 std::basic_istream<CHAR,TRAITS>&
01436 operator>>(std::basic_istream<CHAR,TRAITS>& is, Mat<M,N,E,CS,RS>& m) {
01437     // TODO: not sure how to do Vec input yet
01438     assert(false);
01439     return is;
01440 }
01441 
01442 } //namespace SimTK
01443 
01444 
01445 #endif //SimTK_SIMMATRIX_SMALLMATRIX_MAT_H_

Generated on Thu Aug 12 16:37:11 2010 for SimTKcore by  doxygen 1.6.1