Simbody  3.4 (development)
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  *                       Simbody(tm): SimTKcommon                             *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK 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/home/simbody.  *
00011  *                                                                            *
00012  * Portions copyright (c) 2005-12 Stanford University and the Authors.        *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors:                                                              *
00015  *                                                                            *
00016  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
00017  * not use this file except in compliance with the License. You may obtain a  *
00018  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
00019  *                                                                            *
00020  * Unless required by applicable law or agreed to in writing, software        *
00021  * distributed under the License is distributed on an "AS IS" BASIS,          *
00022  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
00023  * See the License for the specific language governing permissions and        *
00024  * limitations under the License.                                             *
00025  * -------------------------------------------------------------------------- */
00026 
00031 #include "SimTKcommon/internal/common.h"
00032 
00033 namespace SimTK {
00034 
00051 template <int M, int N, class ELT, int CS, int RS> class Mat {
00052     typedef ELT                                 E;
00053     typedef typename CNT<E>::TNeg               ENeg;
00054     typedef typename CNT<E>::TWithoutNegator    EWithoutNegator;
00055     typedef typename CNT<E>::TReal              EReal;
00056     typedef typename CNT<E>::TImag              EImag;
00057     typedef typename CNT<E>::TComplex           EComplex;
00058     typedef typename CNT<E>::THerm              EHerm;
00059     typedef typename CNT<E>::TPosTrans          EPosTrans;
00060     typedef typename CNT<E>::TSqHermT           ESqHermT;
00061     typedef typename CNT<E>::TSqTHerm           ESqTHerm;
00062 
00063     typedef typename CNT<E>::TSqrt              ESqrt;
00064     typedef typename CNT<E>::TAbs               EAbs;
00065     typedef typename CNT<E>::TStandard          EStandard;
00066     typedef typename CNT<E>::TInvert            EInvert;
00067     typedef typename CNT<E>::TNormalize         ENormalize;
00068 
00069     typedef typename CNT<E>::Scalar             EScalar;
00070     typedef typename CNT<E>::ULessScalar        EULessScalar;
00071     typedef typename CNT<E>::Number             ENumber;
00072     typedef typename CNT<E>::StdNumber          EStdNumber;
00073     typedef typename CNT<E>::Precision          EPrecision;
00074     typedef typename CNT<E>::ScalarNormSq       EScalarNormSq;
00075 
00076 public:
00078     enum {
00079         NRows               = M,
00080         NCols               = N,
00081         MinDim              = N < M ? N : M,
00082         MaxDim              = N > M ? N : M,
00083         RowSpacing          = RS,
00084         ColSpacing          = CS,
00085         NPackedElements     = M * N,
00086         NActualElements     = (N-1)*CS + (M-1)*RS + 1,
00087         NActualScalars      = CNT<E>::NActualScalars * NActualElements,
00088         ImagOffset          = NTraits<ENumber>::ImagOffset,
00089         RealStrideFactor    = 1, // composite types don't change size when
00090                                  // cast from complex to real or imaginary
00091         ArgDepth            = ((int)CNT<E>::ArgDepth < (int)MAX_RESOLVED_DEPTH 
00092                                 ? CNT<E>::ArgDepth + 1 
00093                                 : MAX_RESOLVED_DEPTH),
00094         IsScalar            = 0,
00095         IsULessScalar       = 0,
00096         IsNumber            = 0,
00097         IsStdNumber         = 0,
00098         IsPrecision         = 0,
00099         SignInterpretation  = CNT<E>::SignInterpretation
00100     };
00101 
00102     typedef Mat<M,N,E,CS,RS>                T;
00103     typedef Mat<M,N,ENeg,CS,RS>             TNeg;
00104     typedef Mat<M,N,EWithoutNegator,CS,RS>  TWithoutNegator;
00105 
00106     typedef Mat<M,N,EReal,CS*CNT<E>::RealStrideFactor,RS*CNT<E>::RealStrideFactor>
00107                                             TReal;
00108     typedef Mat<M,N,EImag,CS*CNT<E>::RealStrideFactor,RS*CNT<E>::RealStrideFactor>
00109                                             TImag;
00110     typedef Mat<M,N,EComplex,CS,RS>         TComplex;
00111     typedef Mat<N,M,EHerm,RS,CS>            THerm;
00112     typedef Mat<N,M,E,RS,CS>                TPosTrans;
00113     typedef E                               TElement;
00114     typedef Row<N,E,CS>                     TRow;    
00115     typedef Vec<M,E,RS>                     TCol;
00116     typedef Vec<MinDim,E,RS+CS>             TDiag;
00117 
00118     // These are the results of calculations, so are returned in new, packed
00119     // memory. Be sure to refer to element types here which are also packed.
00120     typedef Mat<M,N,ESqrt,M,1>              TSqrt;      // Note strides are packed
00121     typedef Mat<M,N,EAbs,M,1>               TAbs;       // Note strides are packed
00122     typedef Mat<M,N,EStandard,M,1>          TStandard;
00123     typedef Mat<N,M,EInvert,N,1>            TInvert;    // like THerm but packed
00124     typedef Mat<M,N,ENormalize,M,1>         TNormalize;
00125 
00126     typedef SymMat<N,ESqHermT>              TSqHermT;   // ~Mat*Mat
00127     typedef SymMat<M,ESqTHerm>              TSqTHerm;   // Mat*~Mat
00128 
00129     // Here the elements are copied unchanged but the result matrix
00130     // is an ordinary packed, column order matrix.
00131     typedef Mat<M,N,E,M,1>                  TPacked;
00132     typedef Mat<M-1,N,E,M-1,1>              TDropRow;
00133     typedef Mat<M,N-1,E,M,1>                TDropCol;
00134     typedef Mat<M-1,N-1,E,M-1,1>            TDropRowCol;
00135     typedef Mat<M+1,N,E,M+1,1>              TAppendRow;
00136     typedef Mat<M,N+1,E,M,1>                TAppendCol;
00137     typedef Mat<M+1,N+1,E,M+1,1>            TAppendRowCol;
00138 
00139     typedef EScalar                         Scalar;
00140     typedef EULessScalar                    ULessScalar;
00141     typedef ENumber                         Number;
00142     typedef EStdNumber                      StdNumber;
00143     typedef EPrecision                      Precision;
00144     typedef EScalarNormSq                   ScalarNormSq;
00145 
00146     typedef THerm                           TransposeType; // TODO
00147 
00149     static int size() { return M*N; }
00152     static int nrow() { return M; }
00155     static int ncol() { return N; }
00156 
00162     ScalarNormSq scalarNormSqr() const { 
00163         ScalarNormSq sum(0);
00164         for(int j=0;j<N;++j) sum += CNT<TCol>::scalarNormSqr((*this)(j));
00165         return sum;
00166     }
00167 
00171     TSqrt sqrt() const { 
00172         TSqrt msqrt;
00173         for(int j=0;j<N;++j) msqrt(j) = (*this)(j).sqrt();
00174         return msqrt;
00175     }
00176 
00180     TAbs abs() const { 
00181         TAbs mabs;
00182         for(int j=0;j<N;++j) mabs(j) = (*this)(j).abs();
00183         return mabs;
00184     }
00185 
00186     TStandard standardize() const {
00187         TStandard mstd;
00188         for(int j=0;j<N;++j) mstd(j) = (*this)(j).standardize();
00189         return mstd;
00190     }
00191 
00192     // This gives the resulting matrix type when (m(i,j) op P) is applied to each element.
00193     // It is an MxN vector with default column and row spacing, and element types which
00194     // are the regular composite result of E op P. Typically P is a scalar type but
00195     // it doesn't have to be.
00196     template <class P> struct EltResult { 
00197         typedef Mat<M,N, typename CNT<E>::template Result<P>::Mul, M, 1> Mul;
00198         typedef Mat<M,N, typename CNT<E>::template Result<P>::Dvd, M, 1> Dvd;
00199         typedef Mat<M,N, typename CNT<E>::template Result<P>::Add, M, 1> Add;
00200         typedef Mat<M,N, typename CNT<E>::template Result<P>::Sub, M, 1> Sub;
00201     };
00202 
00203     // This is the composite result for m op P where P is some kind of appropriately shaped
00204     // non-scalar type.
00205     template <class P> struct Result { 
00206         typedef MulCNTs<M,N,ArgDepth,Mat,ColSpacing,RowSpacing,
00207             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00208             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> MulOp;
00209         typedef typename MulOp::Type Mul;
00210 
00211         typedef MulCNTsNonConforming<M,N,ArgDepth,Mat,ColSpacing,RowSpacing,
00212             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00213             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> MulOpNonConforming;
00214         typedef typename MulOpNonConforming::Type MulNon;
00215 
00216         typedef DvdCNTs<M,N,ArgDepth,Mat,ColSpacing,RowSpacing,
00217             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00218             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> DvdOp;
00219         typedef typename DvdOp::Type Dvd;
00220 
00221         typedef AddCNTs<M,N,ArgDepth,Mat,ColSpacing,RowSpacing,
00222             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00223             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> AddOp;
00224         typedef typename AddOp::Type Add;
00225 
00226         typedef SubCNTs<M,N,ArgDepth,Mat,ColSpacing,RowSpacing,
00227             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00228             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> SubOp;
00229         typedef typename SubOp::Type Sub;
00230     };
00231 
00232     // Shape-preserving element substitution (always packed)
00233     template <class P> struct Substitute {
00234         typedef Mat<M,N,P> Type;
00235     };
00236 
00239     Mat(){ 
00240     #ifndef NDEBUG
00241         setToNaN();
00242     #endif
00243     }
00244 
00245     // It's important not to use the default copy constructor or copy
00246     // assignment because the compiler doesn't understand that we may
00247     // have noncontiguous storage and will try to copy the whole array.
00248 
00251     Mat(const Mat& src) {
00252         for (int j=0; j<N; ++j)
00253             (*this)(j) = src(j);
00254     }
00258     Mat& operator=(const Mat& src) {    
00259         for (int j=0; j<N; ++j)
00260            (*this)(j) = src(j); // no harm if src and 'this' are the same
00261         return *this;
00262     }
00263 
00268     explicit Mat(const SymMat<M, ELT>& src) {
00269         updDiag() = src.diag();
00270         for (int j = 0; j < M; ++j)
00271             for (int i = j+1; i < M; ++i) {
00272                 (*this)(i, j) = src.getEltLower(i, j);
00273                 (*this)(j, i) = src.getEltUpper(j, i);
00274             }
00275     }
00276 
00281     template <int CSS, int RSS> 
00282     Mat(const Mat<M,N,E,CSS,RSS>& src) {
00283         for (int j=0; j<N; ++j)
00284             (*this)(j) = src(j);
00285     }
00286 
00292     template <int CSS, int RSS> 
00293     Mat(const Mat<M,N,ENeg,CSS,RSS>& src) {
00294         for (int j=0; j<N; ++j)
00295             (*this)(j) = src(j);
00296     }
00297 
00305     template <class EE, int CSS, int RSS> 
00306     explicit Mat(const Mat<M,N,EE,CSS,RSS>& mm)
00307       { for (int j=0;j<N;++j) (*this)(j) = mm(j);}
00308 
00312     explicit Mat(const E& e)
00313       { for (int j=0;j<N;++j) (*this)(j) = E(0); diag()=e; }
00314 
00319     explicit Mat(const ENeg& e)
00320       { for (int j=0;j<N;++j) (*this)(j) = E(0); diag()=e; }
00321 
00328     explicit Mat(int i) 
00329       { new (this) Mat(E(Precision(i))); }
00330 
00331     // A bevy of constructors from individual exact-match elements IN ROW ORDER.
00332     Mat(const E& e0,const E& e1)
00333       {assert(M*N==2);d[rIx(0)]=e0;d[rIx(1)]=e1;}
00334     Mat(const E& e0,const E& e1,const E& e2)
00335       {assert(M*N==3);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;}
00336     Mat(const E& e0,const E& e1,const E& e2,const E& e3)
00337       {assert(M*N==4);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;}
00338     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4)
00339       {assert(M*N==5);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;}
00340     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00341         const E& e5)
00342       {assert(M*N==6);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00343        d[rIx(5)]=e5;}
00344     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00345         const E& e5,const E& e6)
00346       {assert(M*N==7);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00347        d[rIx(5)]=e5;d[rIx(6)]=e6;}
00348     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00349         const E& e5,const E& e6,const E& e7)
00350       {assert(M*N==8);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;}
00352     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00353         const E& e5,const E& e6,const E& e7,const E& e8)
00354       {assert(M*N==9);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00355        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;}
00356     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00357         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9)
00358       {assert(M*N==10);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00359        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;}
00360     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00361         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9,
00362         const E& e10)
00363       {assert(M*N==11);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00364        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;}
00365     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00366         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9,
00367         const E& e10, const E& e11)
00368       {assert(M*N==12);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00369        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
00370        d[rIx(11)]=e11;}
00371     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00372         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9,
00373         const E& e10, const E& e11, const E& e12)
00374       {assert(M*N==13);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00375        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
00376        d[rIx(11)]=e11;d[rIx(12)]=e12;}
00377     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00378         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9,
00379         const E& e10, const E& e11, const E& e12, const E& e13)
00380       {assert(M*N==14);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00381        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
00382        d[rIx(11)]=e11;d[rIx(12)]=e12;d[rIx(13)]=e13;}
00383     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00384         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9,
00385         const E& e10, const E& e11, const E& e12, const E& e13, const E& e14)
00386       {assert(M*N==15);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00387        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
00388        d[rIx(11)]=e11;d[rIx(12)]=e12;d[rIx(13)]=e13;d[rIx(14)]=e14;}
00389     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00390         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9,
00391         const E& e10, const E& e11, const E& e12, const E& e13, const E& e14, 
00392         const E& e15)
00393       {assert(M*N==16);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00394        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
00395        d[rIx(11)]=e11;d[rIx(12)]=e12;d[rIx(13)]=e13;d[rIx(14)]=e14;d[rIx(15)]=e15;}
00396 
00397     // Construction from 1-6 *exact match* Rows
00398     explicit Mat(const TRow& r0)
00399       { assert(M==1); (*this)[0]=r0; }
00400     Mat(const TRow& r0,const TRow& r1)
00401       { assert(M==2);(*this)[0]=r0;(*this)[1]=r1; }
00402     Mat(const TRow& r0,const TRow& r1,const TRow& r2)
00403       { assert(M==3);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2; }
00404     Mat(const TRow& r0,const TRow& r1,const TRow& r2,
00405         const TRow& r3)
00406       { assert(M==4);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;(*this)[3]=r3; }
00407     Mat(const TRow& r0,const TRow& r1,const TRow& r2,
00408         const TRow& r3,const TRow& r4)
00409       { assert(M==5);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;
00410         (*this)[3]=r3;(*this)[4]=r4; }
00411     Mat(const TRow& r0,const TRow& r1,const TRow& r2,
00412         const TRow& r3,const TRow& r4,const TRow& r5)
00413       { assert(M==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* Rows
00417     template <class EE, int SS> explicit Mat(const Row<N,EE,SS>& r0)
00418       { assert(M==1); (*this)[0]=r0; }
00419     template <class EE, int SS> Mat(const Row<N,EE,SS>& r0,const Row<N,EE,SS>& r1)
00420       { assert(M==2);(*this)[0]=r0;(*this)[1]=r1; }
00421     template <class EE, int SS> 
00422     Mat(const Row<N,EE,SS>& r0,const Row<N,EE,SS>& r1,const Row<N,EE,SS>& r2)
00423       { assert(M==3);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2; }
00424     template <class EE, int SS> 
00425     Mat(const Row<N,EE,SS>& r0,const Row<N,EE,SS>& r1,const Row<N,EE,SS>& r2,
00426         const Row<N,EE,SS>& r3)
00427       { assert(M==4);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;(*this)[3]=r3; }
00428     template <class EE, int SS> 
00429     Mat(const Row<N,EE,SS>& r0,const Row<N,EE,SS>& r1,const Row<N,EE,SS>& r2,
00430         const Row<N,EE,SS>& r3,const Row<N,EE,SS>& r4)
00431       { assert(M==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 Row<N,EE,SS>& r0,const Row<N,EE,SS>& r1,const Row<N,EE,SS>& r2,
00435         const Row<N,EE,SS>& r3,const Row<N,EE,SS>& r4,const Row<N,EE,SS>& r5)
00436       { assert(M==6);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;
00437         (*this)[3]=r3;(*this)[4]=r4;(*this)[5]=r5; }
00438 
00439 
00440     // Construction from 1-6 *exact match* Vecs
00441     explicit Mat(const TCol& r0)
00442       { assert(N==1); (*this)(0)=r0; }
00443     Mat(const TCol& r0,const TCol& r1)
00444       { assert(N==2);(*this)(0)=r0;(*this)(1)=r1; }
00445     Mat(const TCol& r0,const TCol& r1,const TCol& r2)
00446       { assert(N==3);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2; }
00447     Mat(const TCol& r0,const TCol& r1,const TCol& r2,
00448         const TCol& r3)
00449       { assert(N==4);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;(*this)(3)=r3; }
00450     Mat(const TCol& r0,const TCol& r1,const TCol& r2,
00451         const TCol& r3,const TCol& r4)
00452       { assert(N==5);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;
00453         (*this)(3)=r3;(*this)(4)=r4; }
00454     Mat(const TCol& r0,const TCol& r1,const TCol& r2,
00455         const TCol& r3,const TCol& r4,const TCol& r5)
00456       { assert(N==6);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;
00457         (*this)(3)=r3;(*this)(4)=r4;(*this)(5)=r5; }
00458 
00459     // Construction from 1-6 *compatible* Vecs
00460     template <class EE, int SS> explicit Mat(const Vec<M,EE,SS>& r0)
00461       { assert(N==1); (*this)(0)=r0; }
00462     template <class EE, int SS> Mat(const Vec<M,EE,SS>& r0,const Vec<M,EE,SS>& r1)
00463       { assert(N==2);(*this)(0)=r0;(*this)(1)=r1; }
00464     template <class EE, int SS> 
00465     Mat(const Vec<M,EE,SS>& r0,const Vec<M,EE,SS>& r1,const Vec<M,EE,SS>& r2)
00466       { assert(N==3);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2; }
00467     template <class EE, int SS> 
00468     Mat(const Vec<M,EE,SS>& r0,const Vec<M,EE,SS>& r1,const Vec<M,EE,SS>& r2,
00469         const Vec<M,EE,SS>& r3)
00470       { assert(N==4);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;(*this)(3)=r3; }
00471     template <class EE, int SS> 
00472     Mat(const Vec<M,EE,SS>& r0,const Vec<M,EE,SS>& r1,const Vec<M,EE,SS>& r2,
00473         const Vec<M,EE,SS>& r3,const Vec<M,EE,SS>& r4)
00474       { assert(N==5);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;
00475         (*this)(3)=r3;(*this)(4)=r4; }
00476     template <class EE, int SS> 
00477     Mat(const Vec<M,EE,SS>& r0,const Vec<M,EE,SS>& r1,const Vec<M,EE,SS>& r2,
00478         const Vec<M,EE,SS>& r3,const Vec<M,EE,SS>& r4,const Vec<M,EE,SS>& r5)
00479       { assert(N==6);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;
00480         (*this)(3)=r3;(*this)(4)=r4;(*this)(5)=r5; }
00481 
00482     // Construction from a pointer to anything assumes we're pointing
00483     // at a packed element list of the right length, in row order.
00484     template <class EE> explicit Mat(const EE* p)
00485       { assert(p); for(int i=0;i<M;++i) (*this)[i]=&p[i*N]; }
00486 
00487     // Assignment works similarly to copy -- if the lengths match,
00488     // go element-by-element. Otherwise, zero and then copy to each 
00489     // diagonal element.
00490     template <class EE, int CSS, int RSS> Mat& operator=(const Mat<M,N,EE,CSS,RSS>& mm) {
00491         for (int j=0; j<N; ++j) (*this)(j) = mm(j);
00492         return *this;
00493     }
00494 
00495     template <class EE> Mat& operator=(const EE* p) {
00496         assert(p); for(int i=0;i<M;++i) (*this)[i]=&p[i*N];
00497         return *this;
00498     }
00499 
00500     // Assignment ops
00501     template <class EE, int CSS, int RSS> Mat& 
00502     operator+=(const Mat<M,N,EE,CSS,RSS>& mm) {
00503         for (int j=0; j<N; ++j) (*this)(j) += mm(j);
00504         return *this;
00505     }
00506     template <class EE, int CSS, int RSS> Mat&
00507     operator+=(const Mat<M,N,negator<EE>,CSS,RSS>& mm) {
00508         for (int j=0; j<N; ++j) (*this)(j) -= -(mm(j));
00509         return *this;
00510     }
00511 
00512     template <class EE, int CSS, int RSS> Mat&
00513     operator-=(const Mat<M,N,EE,CSS,RSS>& mm) {
00514         for (int j=0; j<N; ++j) (*this)(j) -= mm(j);
00515         return *this;
00516     }
00517     template <class EE, int CSS, int RSS> Mat&
00518     operator-=(const Mat<M,N,negator<EE>,CSS,RSS>& mm) {
00519         for (int j=0; j<N; ++j) (*this)(j) += -(mm(j));
00520         return *this;
00521     }
00522 
00523     // In place matrix multiply can only be done when the RHS matrix is square of dimension
00524     // N (i.e., number of columns), and the elements are also *= compatible.
00525     template <class EE, int CSS, int RSS> Mat&
00526     operator*=(const Mat<N,N,EE,CSS,RSS>& mm) {
00527         const Mat t(*this);
00528         for (int j=0; j<N; ++j)
00529             for (int i=0; i<M; ++i)
00530                 (*this)(i,j) = t[i] * mm(j);
00531         return *this;
00532     }
00533 
00534     // Conforming binary ops with 'this' on left, producing new packed result.
00535     // Cases: m=m+-m, m=m+-sy, m=m*m, m=m*sy, v=m*v
00536 
00537     // m= this + m
00538     template <class E2, int CS2, int RS2> 
00539     typename Result<Mat<M,N,E2,CS2,RS2> >::Add
00540     conformingAdd(const Mat<M,N,E2,CS2,RS2>& r) const {
00541         typename Result<Mat<M,N,E2,CS2,RS2> >::Add result;
00542         for (int j=0;j<N;++j) result(j) = (*this)(j) + r(j);
00543         return result;
00544     }
00545     // m= this - m
00546     template <class E2, int CS2, int RS2> 
00547     typename Result<Mat<M,N,E2,CS2,RS2> >::Sub
00548     conformingSubtract(const Mat<M,N,E2,CS2,RS2>& r) const {
00549         typename Result<Mat<M,N,E2,CS2,RS2> >::Sub result;
00550         for (int j=0;j<N;++j) result(j) = (*this)(j) - r(j);
00551         return result;
00552     }
00553     // m= m - this
00554     template <class E2, int CS2, int RS2> 
00555     typename Mat<M,N,E2,CS2,RS2>::template Result<Mat>::Sub
00556     conformingSubtractFromLeft(const Mat<M,N,E2,CS2,RS2>& l) const {
00557         return l.conformingSubtract(*this);
00558     }
00559 
00560     // m= this .* m
00561     template <class E2, int CS2, int RS2> 
00562     typename EltResult<E2>::Mul
00563     elementwiseMultiply(const Mat<M,N,E2,CS2,RS2>& r) const {
00564         typename EltResult<E2>::Mul result;
00565         for (int j=0;j<N;++j) 
00566             result(j) = (*this)(j).elementwiseMultiply(r(j));
00567         return result;
00568     }
00569 
00570     // m= this ./ m
00571     template <class E2, int CS2, int RS2> 
00572     typename EltResult<E2>::Dvd
00573     elementwiseDivide(const Mat<M,N,E2,CS2,RS2>& r) const {
00574         typename EltResult<E2>::Dvd result;
00575         for (int j=0;j<N;++j) 
00576             result(j) = (*this)(j).elementwiseDivide(r(j));
00577         return result;
00578     }
00579 
00580     // We always punt to the SymMat since it knows better what to do.
00581     // m = this + sym
00582     template <class E2, int RS2> 
00583     typename Result<SymMat<M,E2,RS2> >::Add
00584     conformingAdd(const SymMat<M,E2,RS2>& sy) const {
00585         assert(M==N);
00586         return sy.conformingAdd(*this);
00587     }
00588     // m= this - sym
00589     template <class E2, int RS2> 
00590     typename Result<SymMat<M,E2,RS2> >::Sub
00591     conformingSubtract(const SymMat<M,E2,RS2>& sy) const {
00592         assert(M==N);
00593         return sy.conformingSubtractFromLeft(*this);
00594     }
00595     // m= sym - this
00596     template <class E2, int RS2> 
00597     typename SymMat<M,E2,RS2>::template Result<Mat>::Sub
00598     conformingSubtractFromLeft(const SymMat<M,E2,RS2>& sy) const {
00599         assert(M==N);
00600         return sy.conformingSubtract(*this);
00601     }
00602 
00603     // m= this * m
00604     template <int N2, class E2, int CS2, int RS2>
00605     typename Result<Mat<N,N2,E2,CS2,RS2> >::Mul
00606     conformingMultiply(const Mat<N,N2,E2,CS2,RS2>& m) const {
00607         typename Result<Mat<N,N2,E2,CS2,RS2> >::Mul result;
00608         for (int j=0;j<N2;++j)
00609             for (int i=0;i<M;++i)
00610                 result(i,j) = (*this)[i].conformingMultiply(m(j)); // i.e., dot()
00611         return result;
00612     }
00613     // m= m * this
00614     template <int M2, class E2, int CS2, int RS2>
00615     typename Mat<M2,M,E2,CS2,RS2>::template Result<Mat>::Mul
00616     conformingMultiplyFromLeft(const Mat<M2,M,E2,CS2,RS2>& m) const {
00617         return m.conformingMultiply(*this);
00618     }
00619 
00620     // m= this / m = this * m.invert()
00621     template <int M2, class E2, int CS2, int RS2> 
00622     typename Result<Mat<M2,N,E2,CS2,RS2> >::Dvd
00623     conformingDivide(const Mat<M2,N,E2,CS2,RS2>& m) const {
00624         return conformingMultiply(m.invert());
00625     }
00626     // m= m / this = m * this.invert()
00627     template <int M2, class E2, int CS2, int RS2> 
00628     typename Mat<M2,N,E2,CS2,RS2>::template Result<Mat>::Dvd
00629     conformingDivideFromLeft(const Mat<M2,N,E2,CS2,RS2>& m) const {
00630         return m.conformingMultiply((*this).invert());
00631     }
00632     
00633     const TRow& operator[](int i) const { return row(i); }
00634     TRow&       operator[](int i)       { return row(i); }    
00635     const TCol& operator()(int j) const { return col(j); }
00636     TCol&       operator()(int j)       { return col(j); }
00637     
00638     const E& operator()(int i,int j) const { return elt(i,j); }
00639     E&       operator()(int i,int j)       { return elt(i,j); }
00640 
00641     // This is the scalar Frobenius norm.
00642     ScalarNormSq normSqr() const { return scalarNormSqr(); }
00643     typename CNT<ScalarNormSq>::TSqrt 
00644         norm() const { return CNT<ScalarNormSq>::sqrt(scalarNormSqr()); }
00645 
00646     // There is no conventional meaning for normalize() applied to a matrix. We
00647     // choose to define it as follows:
00648     // If the elements of this Mat are scalars, the result is what you get by
00649     // dividing each element by the Frobenius norm() calculated above. If the elements are
00650     // *not* scalars, then the elements are *separately* normalized. That means
00651     // you will get a different answer from Mat<2,2,Mat33>::normalize() than you
00652     // would from a Mat<6,6>::normalize() containing the same scalars.
00653     //
00654     // Normalize returns a matrix of the same dimension but in new, packed storage
00655     // and with a return type that does not include negator<> even if the original
00656     // Mat<> does, because we can eliminate the negation here almost for free.
00657     // But we can't standardize (change conjugate to complex) for free, so we'll retain
00658     // conjugates if there are any.
00659     TNormalize normalize() const {
00660         if (CNT<E>::IsScalar) {
00661             return castAwayNegatorIfAny() / (SignInterpretation*norm());
00662         } else {
00663             TNormalize elementwiseNormalized;
00664             // punt to the column Vec to deal with the elements
00665             for (int j=0; j<N; ++j) 
00666                 elementwiseNormalized(j) = (*this)(j).normalize();
00667             return elementwiseNormalized;
00668         }
00669     }
00670 
00671     // Default inversion. Assume full rank if square, otherwise return
00672     // pseudoinverse. (Mostly TODO)
00673     TInvert invert() const;
00674 
00675     const Mat&   operator+() const { return *this; }
00676     const TNeg&  operator-() const { return negate(); }
00677     TNeg&        operator-()       { return updNegate(); }
00678     const THerm& operator~() const { return transpose(); }
00679     THerm&       operator~()       { return updTranspose(); }
00680 
00681     const TNeg&  negate() const { return *reinterpret_cast<const TNeg*>(this); }
00682     TNeg&        updNegate()    { return *reinterpret_cast<TNeg*>(this); }
00683 
00684     const THerm& transpose()    const { return *reinterpret_cast<const THerm*>(this); }
00685     THerm&       updTranspose()       { return *reinterpret_cast<THerm*>(this); }
00686 
00687     const TPosTrans& positionalTranspose() const
00688         { return *reinterpret_cast<const TPosTrans*>(this); }
00689     TPosTrans&       updPositionalTranspose()
00690         { return *reinterpret_cast<TPosTrans*>(this); }
00691 
00692     // If the underlying scalars are complex or conjugate, we can return a
00693     // reference to the real part just by recasting the data to a matrix of
00694     // the same dimensions but containing real elements, with the scalar
00695     // spacing doubled.
00696     const TReal& real() const { return *reinterpret_cast<const TReal*>(this); }
00697     TReal&       real()       { return *reinterpret_cast<      TReal*>(this); }
00698 
00699     // Getting the imaginary part is almost the same as real, but we have
00700     // to shift the starting address of the returned object by 1 real-size
00701     // ("precision") scalar so that the first element is the imaginary part
00702     // of the original first element.
00703     // TODO: should blow up or return a reference to a zero matrix if called
00704     // on a real object.
00705     // Had to contort these routines to get them through VC++ 7.net
00706     const TImag& imag()    const { 
00707         const int offs = ImagOffset;
00708         const Precision* p = reinterpret_cast<const Precision*>(this);
00709         return *reinterpret_cast<const TImag*>(p+offs);
00710     }
00711     TImag& imag() { 
00712         const int offs = ImagOffset;
00713         Precision* p = reinterpret_cast<Precision*>(this);
00714         return *reinterpret_cast<TImag*>(p+offs);
00715     }
00716 
00717     const TWithoutNegator& castAwayNegatorIfAny() const {return *reinterpret_cast<const TWithoutNegator*>(this);}
00718     TWithoutNegator&       updCastAwayNegatorIfAny()    {return *reinterpret_cast<TWithoutNegator*>(this);}
00719 
00720     const TRow& row(int i) const { 
00721         SimTK_INDEXCHECK(i,M, "Mat::row[i]");
00722         return *reinterpret_cast<const TRow*>(&d[i*RS]); 
00723     }
00724     TRow& row(int i) { 
00725         SimTK_INDEXCHECK(i,M, "Mat::row[i]");
00726         return *reinterpret_cast<TRow*>(&d[i*RS]); 
00727     }
00728 
00729     const TCol& col(int j) const { 
00730         SimTK_INDEXCHECK(j,N, "Mat::col(j)");
00731         return *reinterpret_cast<const TCol*>(&d[j*CS]); 
00732     }
00733     TCol& col(int j) { 
00734         SimTK_INDEXCHECK(j,N, "Mat::col(j)");
00735         return *reinterpret_cast<TCol*>(&d[j*CS]); 
00736     }    
00737     
00738     const E& elt(int i, int j) const {
00739         SimTK_INDEXCHECK(i,M, "Mat::elt(i,j)");
00740         SimTK_INDEXCHECK(j,N, "Mat::elt(i,j)");
00741         return d[i*RS+j*CS]; 
00742     }
00743     E& elt(int i, int j) { 
00744         SimTK_INDEXCHECK(i,M, "Mat::elt(i,j)");
00745         SimTK_INDEXCHECK(j,N, "Mat::elt(i,j)");
00746         return d[i*RS+j*CS]; 
00747     }
00748 
00752     const TDiag& diag() const { return *reinterpret_cast<const TDiag*>(d); }
00756     TDiag&       updDiag()    { return *reinterpret_cast<TDiag*>(d); }
00759     TDiag&       diag()       { return *reinterpret_cast<TDiag*>(d); }
00760 
00761     EStandard trace() const {return diag().sum();}
00762 
00763     // These are elementwise binary operators, (this op ee) by default but (ee op this) if
00764     // 'FromLeft' appears in the name. The result is a packed Mat<M,N> but the element type
00765     // may change. These are mostly used to implement global operators.
00766     // We call these "scalar" operators but actually the "scalar" can be a composite type.
00767 
00768     //TODO: consider converting 'e' to Standard Numbers as precalculation and changing
00769     // return type appropriately.
00770     template <class EE> Mat<M,N, typename CNT<E>::template Result<EE>::Mul>
00771     scalarMultiply(const EE& e) const {
00772         Mat<M,N, typename CNT<E>::template Result<EE>::Mul> result;
00773         for (int j=0; j<N; ++j) result(j) = (*this)(j).scalarMultiply(e);
00774         return result;
00775     }
00776     template <class EE> Mat<M,N, typename CNT<EE>::template Result<E>::Mul>
00777     scalarMultiplyFromLeft(const EE& e) const {
00778         Mat<M,N, typename CNT<EE>::template Result<E>::Mul> result;
00779         for (int j=0; j<N; ++j) result(j) = (*this)(j).scalarMultiplyFromLeft(e);
00780         return result;
00781     }
00782 
00783     // TODO: should precalculate and store 1/e, while converting to Standard Numbers. Note
00784     // that return type should change appropriately.
00785     template <class EE> Mat<M,N, typename CNT<E>::template Result<EE>::Dvd>
00786     scalarDivide(const EE& e) const {
00787         Mat<M,N, typename CNT<E>::template Result<EE>::Dvd> result;
00788         for (int j=0; j<N; ++j) result(j) = (*this)(j).scalarDivide(e);
00789         return result;
00790     }
00791     template <class EE> Mat<M,N, typename CNT<EE>::template Result<E>::Dvd>
00792     scalarDivideFromLeft(const EE& e) const {
00793         Mat<M,N, typename CNT<EE>::template Result<E>::Dvd> result;
00794         for (int j=0; j<N; ++j) result(j) = (*this)(j).scalarDivideFromLeft(e);
00795         return result;
00796     }
00797 
00798     // Additive operators for scalars operate only on the diagonal.
00799     template <class EE> Mat<M,N, typename CNT<E>::template Result<EE>::Add>
00800     scalarAdd(const EE& e) const {
00801         Mat<M,N, typename CNT<E>::template Result<EE>::Add> result(*this);
00802         result.diag() += e;
00803         return result;
00804     }
00805     // Add is commutative, so no 'FromLeft'.
00806 
00807     template <class EE> Mat<M,N, typename CNT<E>::template Result<EE>::Sub>
00808     scalarSubtract(const EE& e) const {
00809         Mat<M,N, typename CNT<E>::template Result<EE>::Sub> result(*this);
00810         result.diag() -= e;
00811         return result;
00812     }
00813     // Should probably do something clever with negation here (s - m)
00814     template <class EE> Mat<M,N, typename CNT<EE>::template Result<E>::Sub>
00815     scalarSubtractFromLeft(const EE& e) const {
00816         Mat<M,N, typename CNT<EE>::template Result<E>::Sub> result(-(*this));
00817         result.diag() += e; // yes, add
00818         return result;
00819     }
00820 
00821     // Generic assignments for any element type not listed explicitly, including scalars.
00822     // These are done repeatedly for each element and only work if the operation can
00823     // be performed leaving the original element type.
00824     template <class EE> Mat& operator =(const EE& e) {return scalarEq(e);}
00825     template <class EE> Mat& operator+=(const EE& e) {return scalarPlusEq(e);}
00826     template <class EE> Mat& operator-=(const EE& e) {return scalarMinusEq(e);}
00827     template <class EE> Mat& operator*=(const EE& e) {return scalarTimesEq(e);}
00828     template <class EE> Mat& operator/=(const EE& e) {return scalarDivideEq(e);}
00829 
00830     // Generalized scalar assignment & computed assignment methods. These will work
00831     // for any assignment-compatible element, not just scalars.
00832     template <class EE> Mat& scalarEq(const EE& ee)
00833       { for(int j=0; j<N; ++j) (*this)(j).scalarEq(EE(0)); 
00834         diag().scalarEq(ee); 
00835         return *this; }
00836 
00837     template <class EE> Mat& scalarPlusEq(const EE& ee)
00838       { diag().scalarPlusEq(ee); return *this; }
00839 
00840     template <class EE> Mat& scalarMinusEq(const EE& ee)
00841       { diag().scalarMinusEq(ee); return *this; }
00842     // m = s - m; negate m, then add s
00843     template <class EE> Mat& scalarMinusEqFromLeft(const EE& ee)
00844       { scalarTimesEq(E(-1)); diag().scalarAdd(ee); return *this; }
00845 
00846     template <class EE> Mat& scalarTimesEq(const EE& ee)
00847       { for(int j=0; j<N; ++j) (*this)(j).scalarTimesEq(ee); return *this; }
00848     template <class EE> Mat& scalarTimesEqFromLeft(const EE& ee)
00849       { for(int j=0; j<N; ++j) (*this)(j).scalarTimesEqFromLeft(ee); return *this; } 
00850 
00851     template <class EE> Mat& scalarDivideEq(const EE& ee)
00852       { for(int j=0; j<N; ++j) (*this)(j).scalarDivideEq(ee); return *this; }
00853     template <class EE> Mat& scalarDivideEqFromLeft(const EE& ee)
00854       { for(int j=0; j<N; ++j) (*this)(j).scalarDivideEqFromLeft(ee); return *this; } 
00855 
00856     void setToNaN() {
00857         for (int j=0; j<N; ++j)
00858             (*this)(j).setToNaN();
00859     }
00860 
00861     void setToZero() {
00862         for (int j=0; j<N; ++j)
00863             (*this)(j).setToZero();
00864     }
00865 
00866     // Extract a sub-Mat with size known at compile time. These have to be
00867     // called with explicit template arguments, e.g. getSubMat<3,4>(i,j).
00868 
00869     template <int MM, int NN> struct SubMat {
00870         typedef Mat<MM,NN,ELT,CS,RS> Type;
00871     };
00872 
00873     template <int MM, int NN>
00874     const typename SubMat<MM,NN>::Type& getSubMat(int i, int j) const {
00875         assert(0 <= i && i + MM <= M);
00876         assert(0 <= j && j + NN <= N);
00877         return SubMat<MM,NN>::Type::getAs(&(*this)(i,j));
00878     }
00879     template <int MM, int NN>
00880     typename SubMat<MM,NN>::Type& updSubMat(int i, int j) {
00881         assert(0 <= i && i + MM <= M);
00882         assert(0 <= j && j + NN <= N);
00883         return SubMat<MM,NN>::Type::updAs(&(*this)(i,j));
00884     }
00885     template <int MM, int NN>
00886     void setSubMat(int i, int j, const typename SubMat<MM,NN>::Type& value) {
00887         assert(0 <= i && i + MM <= M);
00888         assert(0 <= j && j + NN <= N);
00889         SubMat<MM,NN>::Type::updAs(&(*this)(i,j)) = value;
00890     }
00891 
00894     TDropRow dropRow(int i) const {
00895         assert(0 <= i && i < M);
00896         TDropRow out;
00897         for (int r=0, nxt=0; r<M-1; ++r, ++nxt) {
00898             if (nxt==i) ++nxt;  // skip the loser
00899             out[r] = (*this)[nxt];
00900         }
00901         return out;
00902     }
00903 
00906     TDropCol dropCol(int j) const {
00907         assert(0 <= j && j < N);
00908         TDropCol out;
00909         for (int c=0, nxt=0; c<N-1; ++c, ++nxt) {
00910             if (nxt==j) ++nxt;  // skip the loser
00911             out(c) = (*this)(nxt);
00912         }
00913         return out;
00914     }
00915 
00919     TDropRowCol dropRowCol(int i, int j) const {
00920         assert(0 <= i && i < M);
00921         assert(0 <= j && j < N);
00922         TDropRowCol out;
00923         for (int c=0, nxtc=0; c<N-1; ++c, ++nxtc) { 
00924             if (nxtc==j) ++nxtc;
00925             for (int r=0, nxtr=0; r<M-1; ++r, ++nxtr) {
00926                 if (nxtr==i) ++nxtr;
00927                 out(r,c) = (*this)(nxtr,nxtc);
00928             }
00929         }
00930         return out;
00931     }
00932 
00936     template <class EE, int SS> 
00937     TAppendRow appendRow(const Row<N,EE,SS>& row) const {
00938         TAppendRow out;
00939         out.template updSubMat<M,N>(0,0) = (*this);
00940         out[M] = row;
00941         return out;
00942     }
00943 
00947     template <class EE, int SS> 
00948     TAppendCol appendCol(const Vec<M,EE,SS>& col) const {
00949         TAppendCol out;
00950         out.template updSubMat<M,N>(0,0) = (*this);
00951         out(N) = col;
00952         return out;
00953     }
00954 
00961     template <class ER, int SR, class EC, int SC> 
00962     TAppendRowCol appendRowCol(const Row<N+1,ER,SR>& row,
00963                                const Vec<M+1,EC,SC>& col) const 
00964     {
00965         TAppendRowCol out;
00966         out.template updSubMat<M,N>(0,0) = (*this);
00967         out[M].template updSubRow<N>(0) = 
00968             row.template getSubRow<N>(0); // ignore last element
00969         out(N) = col;
00970         return out;
00971     }
00972 
00978     template <class EE, int SS> 
00979     TAppendRow insertRow(int i, const Row<N,EE,SS>& row) const {
00980         assert(0 <= i && i <= M);
00981         if (i==M) return appendRow(row);
00982         TAppendRow out;
00983         for (int r=0, nxt=0; r<M; ++r, ++nxt) {
00984             if (nxt==i) out[nxt++] = row;
00985             out[nxt] = (*this)[r];
00986         }
00987         return out;
00988     }
00989 
00995     template <class EE, int SS> 
00996     TAppendCol insertCol(int j, const Vec<M,EE,SS>& col) const {
00997         assert(0 <= j && j <= N);
00998         if (j==N) return appendCol(col);
00999         TAppendCol out;
01000         for (int c=0, nxt=0; c<N; ++c, ++nxt) {
01001             if (nxt==j) out(nxt++) = col;
01002             out(nxt) = (*this)(c);
01003         }
01004         return out;
01005     }
01006 
01014     template <class ER, int SR, class EC, int SC>
01015     TAppendRowCol insertRowCol(int i, int j, const Row<N+1,ER,SR>& row,
01016                                              const Vec<M+1,EC,SC>& col) const {
01017         assert(0 <= i && i <= M);
01018         assert(0 <= j && j <= N);
01019         TAppendRowCol out;
01020         for (int c=0, nxtc=0; c<N; ++c, ++nxtc) { 
01021             if (nxtc==j) ++nxtc;   // leave room
01022             for (int r=0, nxtr=0; r<M; ++r, ++nxtr) {
01023                 if (nxtr==i) ++nxtr;
01024                 out(nxtr,nxtc) = (*this)(r,c);
01025             }
01026         }
01027         out[i] = row;
01028         out(j) = col; // overwrites row's j'th element
01029         return out;
01030     }
01031 
01032     // These assume we are given a pointer to d[0] of a Mat<M,N,E,CS,RS> like this one.
01033     static const Mat& getAs(const ELT* p)  {return *reinterpret_cast<const Mat*>(p);}
01034     static Mat&       updAs(ELT* p)        {return *reinterpret_cast<Mat*>(p);}
01035 
01036     // Note packed spacing
01037     static Mat<M,N,ELT,M,1> getNaN() { 
01038         Mat<M,N,ELT,M,1> m;
01039         m.setToNaN();
01040         return m;
01041     }
01042 
01044     bool isNaN() const {
01045         for (int j=0; j<N; ++j)
01046             if (this->col(j).isNaN())
01047                 return true;
01048         return false;
01049     }
01050 
01053     bool isInf() const {
01054         bool seenInf = false;
01055         for (int j=0; j<N; ++j) {
01056             if (!this->col(j).isFinite()) {
01057                 if (!this->col(j).isInf()) 
01058                     return false; // something bad was found
01059                 seenInf = true; 
01060             }
01061         }
01062         return seenInf;
01063     }
01064 
01066     bool isFinite() const {
01067         for (int j=0; j<N; ++j)
01068             if (!this->col(j).isFinite())
01069                 return false;
01070         return true;
01071     }
01072 
01075     static double getDefaultTolerance() {return MinDim*CNT<ELT>::getDefaultTolerance();}
01076 
01079     template <class E2, int CS2, int RS2>
01080     bool isNumericallyEqual(const Mat<M,N,E2,CS2,RS2>& m, double tol) const {
01081         for (int j=0; j < N; ++j)
01082             if (!(*this)(j).isNumericallyEqual(m(j), tol))
01083                 return false;
01084         return true;
01085     }
01086 
01090     template <class E2, int CS2, int RS2>
01091     bool isNumericallyEqual(const Mat<M,N,E2,CS2,RS2>& m) const {
01092         const double tol = std::max(getDefaultTolerance(),m.getDefaultTolerance());
01093         return isNumericallyEqual(m, tol);
01094     }
01095 
01101     bool isNumericallyEqual
01102        (const ELT& e,
01103         double     tol = getDefaultTolerance()) const 
01104     {
01105         for (int i=0; i<M; ++i)
01106             for (int j=0; j<N; ++j) {
01107                 if (i==j) {
01108                     if (!CNT<ELT>::isNumericallyEqual((*this)(i,i), e, tol))
01109                         return false;
01110                 } else {
01111                     // off-diagonals must be zero
01112                     if (!CNT<ELT>::isNumericallyEqual((*this)(i,j), ELT(0), tol))
01113                         return false;
01114                 }
01115             }
01116         return true;
01117     }
01118 
01126     bool isNumericallySymmetric(double tol = getDefaultTolerance()) const {
01127         if (M != N) return false; // handled at compile time
01128         for (int j=0; j<M; ++j)
01129             for (int i=j; i<M; ++i)
01130                 if (!CNT<ELT>::isNumericallyEqual(elt(j,i), CNT<ELT>::transpose(elt(i,j)), tol))
01131                     return false;
01132         return true;
01133     }
01134 
01141     bool isExactlySymmetric() const {
01142         if (M != N) return false; // handled at compile time
01143         for (int j=0; j<M; ++j)
01144             for (int i=j; i<M; ++i)
01145                 if (elt(j,i) != CNT<ELT>::transpose(elt(i,j)))
01146                     return false;
01147         return true;
01148     }
01149     
01151     TRow colSum() const {
01152         TRow temp;
01153         for (int j = 0; j < N; ++j)
01154             temp[j] = col(j).sum();
01155         return temp;
01156     }
01159     TRow sum() const {return colSum();}
01160 
01162     TCol rowSum() const {
01163         TCol temp;
01164         for (int i = 0; i < M; ++i)
01165             temp[i] = row(i).sum();
01166         return temp;
01167     }
01168 
01169     // Functions to be used for Scripting in MATLAB and languages that do not support operator overloading
01171     std::string toString() const {
01172         std::stringstream stream;
01173         stream <<  (*this) ;
01174         return stream.str(); 
01175     }
01177     const ELT& get(int i,int j) const { return elt(i,j); }
01179     void       set(int i,int j, const ELT& value)       { elt(i,j)=value; }
01180 
01181 private:
01182     E d[NActualElements];
01183 
01184     // This permits running through d as though it were stored
01185     // in row order with packed elements. Pass in the k'th value
01186     // of the row ordering and get back the index into d where
01187     // that element is stored.
01188     int rIx(int k) const {
01189         const int row = k / N;
01190         const int col = k % N; // that's modulus, not cross product!
01191         return row*RS + col*CS;
01192     }
01193 };
01194 
01196 // Global operators involving two matrices. //
01197 //   m+m, m-m, m*m, m==m, m!=m              //
01199 
01200 template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline 
01201 typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >::Add
01202 operator+(const Mat<M,N,EL,CSL,RSL>& l, const Mat<M,N,ER,CSR,RSR>& r) { 
01203     return Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >
01204         ::AddOp::perform(l,r);
01205 }
01206 
01207 template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline
01208 typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >::Sub
01209 operator-(const Mat<M,N,EL,CSL,RSL>& l, const Mat<M,N,ER,CSR,RSR>& r) { 
01210     return Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >
01211         ::SubOp::perform(l,r);
01212 }
01213 
01214 // Matrix multiply of an MxN by NxP to produce a packed MxP.
01215 template <int M, int N, class EL, int CSL, int RSL, int P, class ER, int CSR, int RSR> inline
01216 typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<N,P,ER,CSR,RSR> >::Mul
01217 operator*(const Mat<M,N,EL,CSL,RSL>& l, const Mat<N,P,ER,CSR,RSR>& r) { 
01218     return Mat<M,N,EL,CSL,RSL>::template Result<Mat<N,P,ER,CSR,RSR> >
01219         ::MulOp::perform(l,r);
01220 }
01221 
01222 // Non-conforming matrix multiply of an MxN by MMxNN; will be a scalar multiply if one
01223 // has scalar elements and the other has composite elements.
01224 template <int M, int N, class EL, int CSL, int RSL, int MM, int NN, class ER, int CSR, int RSR> inline
01225 typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<MM,NN,ER,CSR,RSR> >::MulNon
01226 operator*(const Mat<M,N,EL,CSL,RSL>& l, const Mat<MM,NN,ER,CSR,RSR>& r) { 
01227     return Mat<M,N,EL,CSL,RSL>::template Result<Mat<MM,NN,ER,CSR,RSR> >
01228                 ::MulOpNonConforming::perform(l,r);
01229 }
01230 
01231 template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline
01232 bool operator==(const Mat<M,N,EL,CSL,RSL>& l, const Mat<M,N,ER,CSR,RSR>& r) { 
01233     for (int j=0; j<N; ++j)
01234         if (l(j) != r(j)) return false;
01235     return true;
01236 }
01237 template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline
01238 bool operator!=(const Mat<M,N,EL,CSL,RSL>& l, const Mat<M,N,ER,CSR,RSR>& r) { 
01239     return !(l==r);
01240 }
01241 
01242 
01244 // Global operators involving a matrix and a scalar. //
01246 
01247 // SCALAR MULTIPLY
01248 
01249 // m = m*real, real*m 
01250 template <int M, int N, class E, int CS, int RS> inline
01251 typename Mat<M,N,E,CS,RS>::template Result<float>::Mul
01252 operator*(const Mat<M,N,E,CS,RS>& l, const float& r)
01253   { return Mat<M,N,E,CS,RS>::template Result<float>::MulOp::perform(l,r); }
01254 template <int M, int N, class E, int CS, int RS> inline
01255 typename Mat<M,N,E,CS,RS>::template Result<float>::Mul
01256 operator*(const float& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
01257 
01258 template <int M, int N, class E, int CS, int RS> inline
01259 typename Mat<M,N,E,CS,RS>::template Result<double>::Mul
01260 operator*(const Mat<M,N,E,CS,RS>& l, const double& r)
01261   { return Mat<M,N,E,CS,RS>::template Result<double>::MulOp::perform(l,r); }
01262 template <int M, int N, class E, int CS, int RS> inline
01263 typename Mat<M,N,E,CS,RS>::template Result<double>::Mul
01264 operator*(const double& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
01265 
01266 template <int M, int N, class E, int CS, int RS> inline
01267 typename Mat<M,N,E,CS,RS>::template Result<long double>::Mul
01268 operator*(const Mat<M,N,E,CS,RS>& l, const long double& r)
01269   { return Mat<M,N,E,CS,RS>::template Result<long double>::MulOp::perform(l,r); }
01270 template <int M, int N, class E, int CS, int RS> inline
01271 typename Mat<M,N,E,CS,RS>::template Result<long double>::Mul
01272 operator*(const long double& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
01273 
01274 // m = m*int, int*m -- just convert int to m's precision float
01275 template <int M, int N, class E, int CS, int RS> inline
01276 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Mul
01277 operator*(const Mat<M,N,E,CS,RS>& l, int r) {return l * (typename CNT<E>::Precision)r;}
01278 template <int M, int N, class E, int CS, int RS> inline
01279 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Mul
01280 operator*(int l, const Mat<M,N,E,CS,RS>& r) {return r * (typename CNT<E>::Precision)l;}
01281 
01282 // Complex, conjugate, and negator are all easy to templatize.
01283 
01284 // m = m*complex, complex*m
01285 template <int M, int N, class E, int CS, int RS, class R> inline
01286 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
01287 operator*(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
01288   { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::MulOp::perform(l,r); }
01289 template <int M, int N, class E, int CS, int RS, class R> inline
01290 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
01291 operator*(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
01292 
01293 // m = m*conjugate, conjugate*m (convert conjugate->complex)
01294 template <int M, int N, class E, int CS, int RS, class R> inline
01295 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
01296 operator*(const Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l*(std::complex<R>)r;}
01297 template <int M, int N, class E, int CS, int RS, class R> inline
01298 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
01299 operator*(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return r*(std::complex<R>)l;}
01300 
01301 // m = m*negator, negator*m: convert negator to standard number
01302 template <int M, int N, class E, int CS, int RS, class R> inline
01303 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Mul
01304 operator*(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l * (typename negator<R>::StdNumber)(R)r;}
01305 template <int M, int N, class E, int CS, int RS, class R> inline
01306 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Mul
01307 operator*(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return r * (typename negator<R>::StdNumber)(R)l;}
01308 
01309 
01310 // SCALAR DIVIDE. This is a scalar operation when the scalar is on the right,
01311 // but when it is on the left it means scalar * pseudoInverse(mat), 
01312 // which is a matrix whose type is like the matrix's Hermitian transpose.
01313 // TODO: for now it is just going to call mat.invert() which will fail on
01314 // singular matrices.
01315 
01316 // m = m/real, real/m 
01317 template <int M, int N, class E, int CS, int RS> inline
01318 typename Mat<M,N,E,CS,RS>::template Result<float>::Dvd
01319 operator/(const Mat<M,N,E,CS,RS>& l, const float& r)
01320 {   return Mat<M,N,E,CS,RS>::template Result<float>::DvdOp::perform(l,r); }
01321 
01322 template <int M, int N, class E, int CS, int RS> inline
01323 typename CNT<float>::template Result<Mat<M,N,E,CS,RS> >::Dvd
01324 operator/(const float& l, const Mat<M,N,E,CS,RS>& r)
01325 {   return l * r.invert(); }
01326 
01327 template <int M, int N, class E, int CS, int RS> inline
01328 typename Mat<M,N,E,CS,RS>::template Result<double>::Dvd
01329 operator/(const Mat<M,N,E,CS,RS>& l, const double& r)
01330 {   return Mat<M,N,E,CS,RS>::template Result<double>::DvdOp::perform(l,r); }
01331 
01332 template <int M, int N, class E, int CS, int RS> inline
01333 typename CNT<double>::template Result<Mat<M,N,E,CS,RS> >::Dvd
01334 operator/(const double& l, const Mat<M,N,E,CS,RS>& r)
01335 {   return l * r.invert(); }
01336 
01337 template <int M, int N, class E, int CS, int RS> inline
01338 typename Mat<M,N,E,CS,RS>::template Result<long double>::Dvd
01339 operator/(const Mat<M,N,E,CS,RS>& l, const long double& r)
01340 {   return Mat<M,N,E,CS,RS>::template Result<long double>::DvdOp::perform(l,r); }
01341 
01342 template <int M, int N, class E, int CS, int RS> inline
01343 typename CNT<long double>::template Result<Mat<M,N,E,CS,RS> >::Dvd
01344 operator/(const long double& l, const Mat<M,N,E,CS,RS>& r)
01345 {   return l * r.invert(); }
01346 
01347 // m = m/int, int/m -- just convert int to m's precision float
01348 template <int M, int N, class E, int CS, int RS> inline
01349 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Dvd
01350 operator/(const Mat<M,N,E,CS,RS>& l, int r) 
01351 {   return l / (typename CNT<E>::Precision)r; }
01352 
01353 template <int M, int N, class E, int CS, int RS> inline
01354 typename CNT<typename CNT<E>::Precision>::template Result<Mat<M,N,E,CS,RS> >::Dvd
01355 operator/(int l, const Mat<M,N,E,CS,RS>& r) 
01356 {   return (typename CNT<E>::Precision)l / r; }
01357 
01358 
01359 // Complex, conjugate, and negator are all easy to templatize.
01360 
01361 // m = m/complex, complex/m
01362 template <int M, int N, class E, int CS, int RS, class R> inline
01363 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Dvd
01364 operator/(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
01365   { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::DvdOp::perform(l,r); }
01366 template <int M, int N, class E, int CS, int RS, class R> inline
01367 typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Dvd
01368 operator/(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r)
01369   { return CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::DvdOp::perform(l,r); }
01370 
01371 // m = m/conjugate, conjugate/m (convert conjugate->complex)
01372 template <int M, int N, class E, int CS, int RS, class R> inline
01373 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Dvd
01374 operator/(const Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l/(std::complex<R>)r;}
01375 template <int M, int N, class E, int CS, int RS, class R> inline
01376 typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Dvd
01377 operator/(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return (std::complex<R>)l/r;}
01378 
01379 // m = m/negator, negator/m: convert negator to a standard number
01380 template <int M, int N, class E, int CS, int RS, class R> inline
01381 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Dvd
01382 operator/(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l/(typename negator<R>::StdNumber)(R)r;}
01383 template <int M, int N, class E, int CS, int RS, class R> inline
01384 typename CNT<R>::template Result<Mat<M,N,E,CS,RS> >::Dvd
01385 operator/(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return (typename negator<R>::StdNumber)(R)l/r;}
01386 
01387 
01388 // Add and subtract are odd as scalar ops. They behave as though the
01389 // scalar stands for a conforming matrix whose diagonal elements are that,
01390 // scalar and then a normal matrix add or subtract is done.
01391 
01392 // SCALAR ADD
01393 
01394 // m = m+real, real+m 
01395 template <int M, int N, class E, int CS, int RS> inline
01396 typename Mat<M,N,E,CS,RS>::template Result<float>::Add
01397 operator+(const Mat<M,N,E,CS,RS>& l, const float& r)
01398   { return Mat<M,N,E,CS,RS>::template Result<float>::AddOp::perform(l,r); }
01399 template <int M, int N, class E, int CS, int RS> inline
01400 typename Mat<M,N,E,CS,RS>::template Result<float>::Add
01401 operator+(const float& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
01402 
01403 template <int M, int N, class E, int CS, int RS> inline
01404 typename Mat<M,N,E,CS,RS>::template Result<double>::Add
01405 operator+(const Mat<M,N,E,CS,RS>& l, const double& r)
01406   { return Mat<M,N,E,CS,RS>::template Result<double>::AddOp::perform(l,r); }
01407 template <int M, int N, class E, int CS, int RS> inline
01408 typename Mat<M,N,E,CS,RS>::template Result<double>::Add
01409 operator+(const double& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
01410 
01411 template <int M, int N, class E, int CS, int RS> inline
01412 typename Mat<M,N,E,CS,RS>::template Result<long double>::Add
01413 operator+(const Mat<M,N,E,CS,RS>& l, const long double& r)
01414   { return Mat<M,N,E,CS,RS>::template Result<long double>::AddOp::perform(l,r); }
01415 template <int M, int N, class E, int CS, int RS> inline
01416 typename Mat<M,N,E,CS,RS>::template Result<long double>::Add
01417 operator+(const long double& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
01418 
01419 // m = m+int, int+m -- just convert int to m's precision float
01420 template <int M, int N, class E, int CS, int RS> inline
01421 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Add
01422 operator+(const Mat<M,N,E,CS,RS>& l, int r) {return l + (typename CNT<E>::Precision)r;}
01423 template <int M, int N, class E, int CS, int RS> inline
01424 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Add
01425 operator+(int l, const Mat<M,N,E,CS,RS>& r) {return r + (typename CNT<E>::Precision)l;}
01426 
01427 // Complex, conjugate, and negator are all easy to templatize.
01428 
01429 // m = m+complex, complex+m
01430 template <int M, int N, class E, int CS, int RS, class R> inline
01431 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
01432 operator+(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
01433   { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::AddOp::perform(l,r); }
01434 template <int M, int N, class E, int CS, int RS, class R> inline
01435 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
01436 operator+(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
01437 
01438 // m = m+conjugate, conjugate+m (convert conjugate->complex)
01439 template <int M, int N, class E, int CS, int RS, class R> inline
01440 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
01441 operator+(const Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l+(std::complex<R>)r;}
01442 template <int M, int N, class E, int CS, int RS, class R> inline
01443 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
01444 operator+(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return r+(std::complex<R>)l;}
01445 
01446 // m = m+negator, negator+m: convert negator to standard number
01447 template <int M, int N, class E, int CS, int RS, class R> inline
01448 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Add
01449 operator+(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l + (typename negator<R>::StdNumber)(R)r;}
01450 template <int M, int N, class E, int CS, int RS, class R> inline
01451 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Add
01452 operator+(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return r + (typename negator<R>::StdNumber)(R)l;}
01453 
01454 // SCALAR SUBTRACT -- careful, not commutative.
01455 
01456 // m = m-real, real-m 
01457 template <int M, int N, class E, int CS, int RS> inline
01458 typename Mat<M,N,E,CS,RS>::template Result<float>::Sub
01459 operator-(const Mat<M,N,E,CS,RS>& l, const float& r)
01460   { return Mat<M,N,E,CS,RS>::template Result<float>::SubOp::perform(l,r); }
01461 template <int M, int N, class E, int CS, int RS> inline
01462 typename CNT<float>::template Result<Mat<M,N,E,CS,RS> >::Sub
01463 operator-(const float& l, const Mat<M,N,E,CS,RS>& r)
01464   { return CNT<float>::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
01465 
01466 template <int M, int N, class E, int CS, int RS> inline
01467 typename Mat<M,N,E,CS,RS>::template Result<double>::Sub
01468 operator-(const Mat<M,N,E,CS,RS>& l, const double& r)
01469   { return Mat<M,N,E,CS,RS>::template Result<double>::SubOp::perform(l,r); }
01470 template <int M, int N, class E, int CS, int RS> inline
01471 typename CNT<double>::template Result<Mat<M,N,E,CS,RS> >::Sub
01472 operator-(const double& l, const Mat<M,N,E,CS,RS>& r)
01473   { return CNT<double>::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
01474 
01475 template <int M, int N, class E, int CS, int RS> inline
01476 typename Mat<M,N,E,CS,RS>::template Result<long double>::Sub
01477 operator-(const Mat<M,N,E,CS,RS>& l, const long double& r)
01478   { return Mat<M,N,E,CS,RS>::template Result<long double>::SubOp::perform(l,r); }
01479 template <int M, int N, class E, int CS, int RS> inline
01480 typename CNT<long double>::template Result<Mat<M,N,E,CS,RS> >::Sub
01481 operator-(const long double& l, const Mat<M,N,E,CS,RS>& r)
01482   { return CNT<long double>::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
01483 
01484 // m = m-int, int-m // just convert int to m's precision float
01485 template <int M, int N, class E, int CS, int RS> inline
01486 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Sub
01487 operator-(const Mat<M,N,E,CS,RS>& l, int r) {return l - (typename CNT<E>::Precision)r;}
01488 template <int M, int N, class E, int CS, int RS> inline
01489 typename CNT<typename CNT<E>::Precision>::template Result<Mat<M,N,E,CS,RS> >::Sub
01490 operator-(int l, const Mat<M,N,E,CS,RS>& r) {return (typename CNT<E>::Precision)l - r;}
01491 
01492 
01493 // Complex, conjugate, and negator are all easy to templatize.
01494 
01495 // m = m-complex, complex-m
01496 template <int M, int N, class E, int CS, int RS, class R> inline
01497 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Sub
01498 operator-(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
01499   { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::SubOp::perform(l,r); }
01500 template <int M, int N, class E, int CS, int RS, class R> inline
01501 typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Sub
01502 operator-(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r)
01503   { return CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
01504 
01505 // m = m-conjugate, conjugate-m (convert conjugate->complex)
01506 template <int M, int N, class E, int CS, int RS, class R> inline
01507 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Sub
01508 operator-(const Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l-(std::complex<R>)r;}
01509 template <int M, int N, class E, int CS, int RS, class R> inline
01510 typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Sub
01511 operator-(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return (std::complex<R>)l-r;}
01512 
01513 // m = m-negator, negator-m: convert negator to standard number
01514 template <int M, int N, class E, int CS, int RS, class R> inline
01515 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Sub
01516 operator-(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l-(typename negator<R>::StdNumber)(R)r;}
01517 template <int M, int N, class E, int CS, int RS, class R> inline
01518 typename CNT<R>::template Result<Mat<M,N,E,CS,RS> >::Sub
01519 operator-(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return (typename negator<R>::StdNumber)(R)l-r;}
01520 
01521 
01522 // Mat I/O
01523 template <int M, int N, class E, int CS, int RS, class CHAR, class TRAITS> inline
01524 std::basic_ostream<CHAR,TRAITS>&
01525 operator<<(std::basic_ostream<CHAR,TRAITS>& o, const Mat<M,N,E,CS,RS>& m) {
01526     for (int i=0;i<M;++i) {
01527         o << std::endl << "[";
01528         for (int j=0;j<N;++j)         
01529             o << (j>0?",":"") << m(i,j);
01530         o << "]";
01531     }
01532     if (M) o << std::endl;
01533     return o; 
01534 }
01535 
01536 template <int M, int N, class E, int CS, int RS, class CHAR, class TRAITS> inline
01537 std::basic_istream<CHAR,TRAITS>&
01538 operator>>(std::basic_istream<CHAR,TRAITS>& is, Mat<M,N,E,CS,RS>& m) {
01539     // TODO: not sure how to do Vec input yet
01540     assert(false);
01541     return is;
01542 }
01543 
01544 } //namespace SimTK
01545 
01546 
01547 #endif //SimTK_SIMMATRIX_SMALLMATRIX_MAT_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines