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-7 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 
00055     typedef typename CNT<E>::TAbs               EAbs;
00056     typedef typename CNT<E>::TStandard          EStandard;
00057     typedef typename CNT<E>::TInvert            EInvert;
00058     typedef typename CNT<E>::TNormalize         ENormalize;
00059     typedef typename CNT<E>::TSqHermT           ESqHermT;
00060     typedef typename CNT<E>::TSqTHerm           ESqTHerm;
00061 
00062     typedef typename CNT<E>::Scalar             EScalar;
00063     typedef typename CNT<E>::Number             ENumber;
00064     typedef typename CNT<E>::StdNumber          EStdNumber;
00065     typedef typename CNT<E>::Precision          EPrecision;
00066     typedef typename CNT<E>::ScalarSq           EScalarSq;
00067 
00068 public:
00069 
00070     enum {
00071         NRows               = M,
00072         NCols               = N,
00073         MinDim              = N < M ? N : M,
00074         MaxDim              = N > M ? N : M,
00075         RowSpacing          = RS,
00076         ColSpacing          = CS,
00077         NPackedElements     = M * N,
00078         NActualElements     = (N-1)*CS + (M-1)*RS + 1,
00079         NActualScalars      = CNT<E>::NActualScalars * NActualElements,
00080         ImagOffset          = NTraits<ENumber>::ImagOffset,
00081         RealStrideFactor    = 1, // composite types don't change size when
00082                                  // cast from complex to real or imaginary
00083         ArgDepth            = ((int)CNT<E>::ArgDepth < (int)MAX_RESOLVED_DEPTH 
00084                                 ? CNT<E>::ArgDepth + 1 
00085                                 : MAX_RESOLVED_DEPTH),
00086         IsScalar            = 0,
00087         IsNumber            = 0,
00088         IsStdNumber         = 0,
00089         IsPrecision         = 0,
00090         SignInterpretation  = CNT<E>::SignInterpretation
00091     };
00092 
00093     typedef Mat<M,N,E,CS,RS>                T;
00094     typedef Mat<M,N,ENeg,CS,RS>             TNeg;
00095     typedef Mat<M,N,EWithoutNegator,CS,RS>  TWithoutNegator;
00096 
00097     typedef Mat<M,N,EReal,CS*CNT<E>::RealStrideFactor,RS*CNT<E>::RealStrideFactor>
00098                                             TReal;
00099     typedef Mat<M,N,EImag,CS*CNT<E>::RealStrideFactor,RS*CNT<E>::RealStrideFactor>
00100                                             TImag;
00101     typedef Mat<M,N,EComplex,CS,RS>         TComplex;
00102     typedef Mat<N,M,EHerm,RS,CS>            THerm;
00103     typedef Mat<N,M,E,RS,CS>                TPosTrans;
00104     typedef E                               TElement;
00105     typedef Row<N,E,CS>                     TRow;    
00106     typedef Vec<M,E,RS>                     TCol;
00107     typedef Vec<MinDim,E,RS+CS>             TDiag;
00108 
00109     // These are the results of calculations, so are returned in new, packed
00110     // memory. Be sure to refer to element types here which are also packed.
00111     typedef Mat<M,N,EAbs,M,1>               TAbs;       // Note strides are packed
00112     typedef Mat<M,N,EStandard,M,1>          TStandard;
00113     typedef Mat<N,M,EInvert,N,1>            TInvert;    // like THerm but packed
00114     typedef Mat<M,N,ENormalize,M,1>         TNormalize;
00115     typedef SymMat<N,ESqHermT>              TSqHermT;   // ~Mat*Mat
00116     typedef SymMat<M,ESqTHerm>              TSqTHerm;   // Mat*~Mat
00117 
00118     typedef EScalar                         Scalar;
00119     typedef ENumber                         Number;
00120     typedef EStdNumber                      StdNumber;
00121     typedef EPrecision                      Precision;
00122     typedef EScalarSq                       ScalarSq;
00123 
00124     typedef THerm                           TransposeType; // TODO
00125 
00126     int size() const { return M*N; }
00127     int nrow() const { return M; }
00128     int ncol() const { return N; }
00129 
00130     // Scalar norm square is sum( squares of all scalars )
00131     ScalarSq scalarNormSqr() const { 
00132         ScalarSq sum(0);
00133         for(int j=0;j<N;++j) sum += CNT<TCol>::scalarNormSqr((*this)(j));
00134         return sum;
00135     }
00136 
00137     // abs() is elementwise absolute value; that is, the return value has the same
00138     // dimension as this Mat but with each element replaced by whatever it thinks
00139     // its absolute value is.
00140     TAbs abs() const { 
00141         TAbs mabs;
00142         for(int j=0;j<N;++j) mabs(j) = (*this)(j).abs();
00143         return mabs;
00144     }
00145 
00146     TStandard standardize() const {
00147         TStandard mstd;
00148         for(int j=0;j<N;++j) mstd(j) = (*this)(j).standardize();
00149         return mstd;
00150     }
00151 
00152     // This gives the resulting matrix type when (m(i,j) op P) is applied to each element.
00153     // It is an MxN vector with default column and row spacing, and element types which
00154     // are the regular composite result of E op P. Typically P is a scalar type but
00155     // it doesn't have to be.
00156     template <class P> struct EltResult { 
00157         typedef Mat<M,N, typename CNT<E>::template Result<P>::Mul, M, 1> Mul;
00158         typedef Mat<M,N, typename CNT<E>::template Result<P>::Dvd, M, 1> Dvd;
00159         typedef Mat<M,N, typename CNT<E>::template Result<P>::Add, M, 1> Add;
00160         typedef Mat<M,N, typename CNT<E>::template Result<P>::Sub, M, 1> Sub;
00161     };
00162 
00163     // This is the composite result for m op P where P is some kind of appropriately shaped
00164     // non-scalar type.
00165     template <class P> struct Result { 
00166         typedef MulCNTs<M,N,ArgDepth,Mat,ColSpacing,RowSpacing,
00167             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00168             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> MulOp;
00169         typedef typename MulOp::Type Mul;
00170 
00171         typedef MulCNTsNonConforming<M,N,ArgDepth,Mat,ColSpacing,RowSpacing,
00172             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00173             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> MulOpNonConforming;
00174         typedef typename MulOpNonConforming::Type MulNon;
00175 
00176         typedef DvdCNTs<M,N,ArgDepth,Mat,ColSpacing,RowSpacing,
00177             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00178             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> DvdOp;
00179         typedef typename DvdOp::Type Dvd;
00180 
00181         typedef AddCNTs<M,N,ArgDepth,Mat,ColSpacing,RowSpacing,
00182             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00183             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> AddOp;
00184         typedef typename AddOp::Type Add;
00185 
00186         typedef SubCNTs<M,N,ArgDepth,Mat,ColSpacing,RowSpacing,
00187             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00188             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> SubOp;
00189         typedef typename SubOp::Type Sub;
00190     };
00191 
00192     // Shape-preserving element substitution (always packed)
00193     template <class P> struct Substitute {
00194         typedef Mat<M,N,P> Type;
00195     };
00196 
00197     // Default construction initializes to NaN when debugging but
00198     // is left uninitialized otherwise.
00199     Mat(){ 
00200     #ifndef NDEBUG
00201         setToNaN();
00202     #endif
00203     }
00204 
00205     // It's important not to use the default copy constructor or copy
00206     // assignment because the compiler doesn't understand that we may
00207     // have noncontiguous storage and will try to copy the whole array.
00208     Mat(const Mat& src) {
00209         for (int j=0; j<N; ++j)
00210             (*this)(j) = src(j);
00211     }
00212     Mat& operator=(const Mat& src) {    // no harm if src and 'this' are the same
00213         for (int j=0; j<N; ++j)
00214            (*this)(j) = src(j);
00215         return *this;
00216     }
00217     // Convert a SymMat to a Mat.
00218     explicit Mat(const SymMat<M, ELT>& src) {
00219         for (int i = 0; i < M; ++i)
00220             for (int j = 0; j <= i; ++j) {
00221                 (*this)(i, j) = src(i, j);
00222                 (*this)(j, i) = src(i, j);
00223             }
00224     }
00225 
00226     // We want an implicit conversion from a Mat of the same length
00227     // and element type but with different spacings.
00228     template <int CSS, int RSS> Mat(const Mat<M,N,E,CSS,RSS>& src) {
00229         for (int j=0; j<N; ++j)
00230             (*this)(j) = src(j);
00231     }
00232 
00233     // We want an implicit conversion from a Mat of the same length
00234     // and *negated* element type, possibly with different spacings.
00235     template <int CSS, int RSS> Mat(const Mat<M,N,ENeg,CSS,RSS>& src) {
00236         for (int j=0; j<N; ++j)
00237             (*this)(j) = src(j);
00238     }
00239 
00240     // Construct a Mat from a Mat of the same dimensions, with any
00241     // spacings. Works as long as the element types are assignment compatible.
00242     template <class EE, int CSS, int RSS> explicit Mat(const Mat<M,N,EE,CSS,RSS>& mm)
00243       { for (int j=0;j<N;++j) (*this)(j) = mm(j);}
00244 
00245     // Construction using an element repeats that element on the diagonal
00246     // but sets the rest of the matrix to zero.
00247     explicit Mat(const E& e)
00248       { for (int j=0;j<N;++j) (*this)(j) = E(0); diag()=e; }
00249 
00250     // A bevy of constructors from individual exact-match elements IN ROW ORDER.
00251     Mat(const E& e0,const E& e1)
00252       {assert(M*N==2);d[rIx(0)]=e0;d[rIx(1)]=e1;}
00253     Mat(const E& e0,const E& e1,const E& e2)
00254       {assert(M*N==3);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;}
00255     Mat(const E& e0,const E& e1,const E& e2,const E& e3)
00256       {assert(M*N==4);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;}
00257     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4)
00258       {assert(M*N==5);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;}
00259     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00260         const E& e5)
00261       {assert(M*N==6);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00262        d[rIx(5)]=e5;}
00263     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00264         const E& e5,const E& e6)
00265       {assert(M*N==7);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00266        d[rIx(5)]=e5;d[rIx(6)]=e6;}
00267     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00268         const E& e5,const E& e6,const E& e7)
00269       {assert(M*N==8);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00270        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;}
00271     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00272         const E& e5,const E& e6,const E& e7,const E& e8)
00273       {assert(M*N==9);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00274        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;}
00275     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00276         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9)
00277       {assert(M*N==10);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00278        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;}
00279     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00280         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9,
00281         const E& e10)
00282       {assert(M*N==11);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00283        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;}
00284     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00285         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9,
00286         const E& e10, const E& e11)
00287       {assert(M*N==12);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00288        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
00289        d[rIx(11)]=e11;}
00290     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00291         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9,
00292         const E& e10, const E& e11, const E& e12)
00293       {assert(M*N==13);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00294        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
00295        d[rIx(11)]=e11;d[rIx(12)]=e12;}
00296     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00297         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9,
00298         const E& e10, const E& e11, const E& e12, const E& e13)
00299       {assert(M*N==14);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;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
00301        d[rIx(11)]=e11;d[rIx(12)]=e12;d[rIx(13)]=e13;}
00302     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00303         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9,
00304         const E& e10, const E& e11, const E& e12, const E& e13, const E& e14)
00305       {assert(M*N==15);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00306        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
00307        d[rIx(11)]=e11;d[rIx(12)]=e12;d[rIx(13)]=e13;d[rIx(14)]=e14;}
00308     Mat(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,
00309         const E& e5,const E& e6,const E& e7,const E& e8,const E& e9,
00310         const E& e10, const E& e11, const E& e12, const E& e13, const E& e14, 
00311         const E& e15)
00312       {assert(M*N==16);d[rIx(0)]=e0;d[rIx(1)]=e1;d[rIx(2)]=e2;d[rIx(3)]=e3;d[rIx(4)]=e4;
00313        d[rIx(5)]=e5;d[rIx(6)]=e6;d[rIx(7)]=e7;d[rIx(8)]=e8;d[rIx(9)]=e9;d[rIx(10)]=e10;
00314        d[rIx(11)]=e11;d[rIx(12)]=e12;d[rIx(13)]=e13;d[rIx(14)]=e14;d[rIx(15)]=e15;}
00315 
00316     // Construction from 1-6 *exact match* Rows
00317     explicit Mat(const TRow& r0)
00318       { assert(M==1); (*this)[0]=r0; }
00319     Mat(const TRow& r0,const TRow& r1)
00320       { assert(M==2);(*this)[0]=r0;(*this)[1]=r1; }
00321     Mat(const TRow& r0,const TRow& r1,const TRow& r2)
00322       { assert(M==3);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2; }
00323     Mat(const TRow& r0,const TRow& r1,const TRow& r2,
00324         const TRow& r3)
00325       { assert(M==4);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;(*this)[3]=r3; }
00326     Mat(const TRow& r0,const TRow& r1,const TRow& r2,
00327         const TRow& r3,const TRow& r4)
00328       { assert(M==5);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;
00329         (*this)[3]=r3;(*this)[4]=r4; }
00330     Mat(const TRow& r0,const TRow& r1,const TRow& r2,
00331         const TRow& r3,const TRow& r4,const TRow& r5)
00332       { assert(M==6);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;
00333         (*this)[3]=r3;(*this)[4]=r4;(*this)[5]=r5; }
00334 
00335     // Construction from 1-6 *compatible* Rows
00336     template <class EE, int SS> explicit Mat(const Row<N,EE,SS>& r0)
00337       { assert(M==1); (*this)[0]=r0; }
00338     template <class EE, int SS> Mat(const Row<N,EE,SS>& r0,const Row<N,EE,SS>& r1)
00339       { assert(M==2);(*this)[0]=r0;(*this)[1]=r1; }
00340     template <class EE, int SS> 
00341     Mat(const Row<N,EE,SS>& r0,const Row<N,EE,SS>& r1,const Row<N,EE,SS>& r2)
00342       { assert(M==3);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2; }
00343     template <class EE, int SS> 
00344     Mat(const Row<N,EE,SS>& r0,const Row<N,EE,SS>& r1,const Row<N,EE,SS>& r2,
00345         const Row<N,EE,SS>& r3)
00346       { assert(M==4);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;(*this)[3]=r3; }
00347     template <class EE, int SS> 
00348     Mat(const Row<N,EE,SS>& r0,const Row<N,EE,SS>& r1,const Row<N,EE,SS>& r2,
00349         const Row<N,EE,SS>& r3,const Row<N,EE,SS>& r4)
00350       { assert(M==5);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;
00351         (*this)[3]=r3;(*this)[4]=r4; }
00352     template <class EE, int SS> 
00353     Mat(const Row<N,EE,SS>& r0,const Row<N,EE,SS>& r1,const Row<N,EE,SS>& r2,
00354         const Row<N,EE,SS>& r3,const Row<N,EE,SS>& r4,const Row<N,EE,SS>& r5)
00355       { assert(M==6);(*this)[0]=r0;(*this)[1]=r1;(*this)[2]=r2;
00356         (*this)[3]=r3;(*this)[4]=r4;(*this)[5]=r5; }
00357 
00358 
00359     // Construction from 1-6 *exact match* Vecs
00360     explicit Mat(const TCol& r0)
00361       { assert(N==1); (*this)(0)=r0; }
00362     Mat(const TCol& r0,const TCol& r1)
00363       { assert(N==2);(*this)(0)=r0;(*this)(1)=r1; }
00364     Mat(const TCol& r0,const TCol& r1,const TCol& r2)
00365       { assert(N==3);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2; }
00366     Mat(const TCol& r0,const TCol& r1,const TCol& r2,
00367         const TCol& r3)
00368       { assert(N==4);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;(*this)(3)=r3; }
00369     Mat(const TCol& r0,const TCol& r1,const TCol& r2,
00370         const TCol& r3,const TCol& r4)
00371       { assert(N==5);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;
00372         (*this)(3)=r3;(*this)(4)=r4; }
00373     Mat(const TCol& r0,const TCol& r1,const TCol& r2,
00374         const TCol& r3,const TCol& r4,const TCol& r5)
00375       { assert(N==6);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;
00376         (*this)(3)=r3;(*this)(4)=r4;(*this)(5)=r5; }
00377 
00378     // Construction from 1-6 *compatible* Vecs
00379     template <class EE, int SS> explicit Mat(const Vec<M,EE,SS>& r0)
00380       { assert(N==1); (*this)(0)=r0; }
00381     template <class EE, int SS> Mat(const Vec<M,EE,SS>& r0,const Vec<M,EE,SS>& r1)
00382       { assert(N==2);(*this)(0)=r0;(*this)(1)=r1; }
00383     template <class EE, int SS> 
00384     Mat(const Vec<M,EE,SS>& r0,const Vec<M,EE,SS>& r1,const Vec<M,EE,SS>& r2)
00385       { assert(N==3);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2; }
00386     template <class EE, int SS> 
00387     Mat(const Vec<M,EE,SS>& r0,const Vec<M,EE,SS>& r1,const Vec<M,EE,SS>& r2,
00388         const Vec<M,EE,SS>& r3)
00389       { assert(N==4);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;(*this)(3)=r3; }
00390     template <class EE, int SS> 
00391     Mat(const Vec<M,EE,SS>& r0,const Vec<M,EE,SS>& r1,const Vec<M,EE,SS>& r2,
00392         const Vec<M,EE,SS>& r3,const Vec<M,EE,SS>& r4)
00393       { assert(N==5);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;
00394         (*this)(3)=r3;(*this)(4)=r4; }
00395     template <class EE, int SS> 
00396     Mat(const Vec<M,EE,SS>& r0,const Vec<M,EE,SS>& r1,const Vec<M,EE,SS>& r2,
00397         const Vec<M,EE,SS>& r3,const Vec<M,EE,SS>& r4,const Vec<M,EE,SS>& r5)
00398       { assert(N==6);(*this)(0)=r0;(*this)(1)=r1;(*this)(2)=r2;
00399         (*this)(3)=r3;(*this)(4)=r4;(*this)(5)=r5; }
00400 
00401     // Construction from a pointer to anything assumes we're pointing
00402     // at a packed element list of the right length, in row order.
00403     template <class EE> explicit Mat(const EE* p)
00404       { assert(p); for(int i=0;i<M;++i) (*this)[i]=&p[i*N]; }
00405 
00406     // Assignment works similarly to copy -- if the lengths match,
00407     // go element-by-element. Otherwise, zero and then copy to each 
00408     // diagonal element.
00409     template <class EE, int CSS, int RSS> Mat& operator=(const Mat<M,N,EE,CSS,RSS>& mm) {
00410         for (int j=0; j<N; ++j) (*this)(j) = mm(j);
00411         return *this;
00412     }
00413 
00414     template <class EE> Mat& operator=(const EE* p) {
00415         assert(p); for(int i=0;i<M;++i) (*this)[i]=&p[i*N];
00416         return *this;
00417     }
00418 
00419     // Assignment ops
00420     template <class EE, int CSS, int RSS> Mat& 
00421     operator+=(const Mat<M,N,EE,CSS,RSS>& mm) {
00422         for (int j=0; j<N; ++j) (*this)(j) += mm(j);
00423         return *this;
00424     }
00425     template <class EE, int CSS, int RSS> Mat&
00426     operator+=(const Mat<M,N,negator<EE>,CSS,RSS>& mm) {
00427         for (int j=0; j<N; ++j) (*this)(j) -= -(mm(j));
00428         return *this;
00429     }
00430 
00431     template <class EE, int CSS, int RSS> Mat&
00432     operator-=(const Mat<M,N,EE,CSS,RSS>& mm) {
00433         for (int j=0; j<N; ++j) (*this)(j) -= mm(j);
00434         return *this;
00435     }
00436     template <class EE, int CSS, int RSS> Mat&
00437     operator-=(const Mat<M,N,negator<EE>,CSS,RSS>& mm) {
00438         for (int j=0; j<N; ++j) (*this)(j) += -(mm(j));
00439         return *this;
00440     }
00441 
00442     // In place matrix multiply can only be done when the RHS matrix is square of dimension
00443     // N (i.e., number of columns), and the elements are also *= compatible.
00444     template <class EE, int CSS, int RSS> Mat&
00445     operator*=(const Mat<N,N,EE,CSS,RSS>& mm) {
00446         const Mat t(*this);
00447         for (int j=0; j<N; ++j)
00448             for (int i=0; i<M; ++i)
00449                 (*this)(i,j) = t[i] * mm(j);
00450         return *this;
00451     }
00452 
00453     // Conforming binary ops with 'this' on left, producing new packed result.
00454     // Cases: m=m+-m, m=m+-sy, m=m*m, m=m*sy, v=m*v
00455 
00456     // m= this + m
00457     template <class E2, int CS2, int RS2> 
00458     typename Result<Mat<M,N,E2,CS2,RS2> >::Add
00459     conformingAdd(const Mat<M,N,E2,CS2,RS2>& r) const {
00460         typename Result<Mat<M,N,E2,CS2,RS2> >::Add result;
00461         for (int j=0;j<N;++j) result(j) = (*this)(j) + r(j);
00462         return result;
00463     }
00464     // m= this - m
00465     template <class E2, int CS2, int RS2> 
00466     typename Result<Mat<M,N,E2,CS2,RS2> >::Sub
00467     conformingSubtract(const Mat<M,N,E2,CS2,RS2>& r) const {
00468         typename Result<Mat<M,N,E2,CS2,RS2> >::Sub result;
00469         for (int j=0;j<N;++j) result(j) = (*this)(j) - r(j);
00470         return result;
00471     }
00472     // m= m - this
00473     template <class E2, int CS2, int RS2> 
00474     typename Mat<M,N,E2,CS2,RS2>::template Result<Mat>::Sub
00475     conformingSubtractFromLeft(const Mat<M,N,E2,CS2,RS2>& l) const {
00476         return l.conformingSubtract(*this);
00477     }
00478 
00479     // We always punt to the SymMat since it knows better what to do.
00480     // m = this + sym
00481     template <class E2, int RS2> 
00482     typename Result<SymMat<M,E2,RS2> >::Add
00483     conformingAdd(const SymMat<M,E2,RS2>& sy) const {
00484         assert(M==N);
00485         return sy.conformingAdd(*this);
00486     }
00487     // m= this - sym
00488     template <class E2, int RS2> 
00489     typename Result<SymMat<M,E2,RS2> >::Sub
00490     conformingSubtract(const SymMat<M,E2,RS2>& sy) const {
00491         assert(M==N);
00492         return sy.conformingSubtractFromLeft(*this);
00493     }
00494     // m= sym - this
00495     template <class E2, int RS2> 
00496     typename SymMat<M,E2,RS2>::template Result<Mat>::Sub
00497     conformingSubtractFromLeft(const SymMat<M,E2,RS2>& sy) const {
00498         assert(M==N);
00499         return sy.conformingSubtract(*this);
00500     }
00501 
00502     // m= this * m
00503     template <int N2, class E2, int CS2, int RS2>
00504     typename Result<Mat<N,N2,E2,CS2,RS2> >::Mul
00505     conformingMultiply(const Mat<N,N2,E2,CS2,RS2>& m) const {
00506         typename Result<Mat<N,N2,E2,CS2,RS2> >::Mul result;
00507         for (int j=0;j<N2;++j)
00508             for (int i=0;i<M;++i)
00509                 result(i,j) = (*this)[i].conformingMultiply(m(j)); // i.e., dot()
00510         return result;
00511     }
00512     // m= m * this
00513     template <int M2, class E2, int CS2, int RS2>
00514     typename Mat<M2,M,E2,CS2,RS2>::template Result<Mat>::Mul
00515     conformingMultiplyFromLeft(const Mat<M2,M,E2,CS2,RS2>& m) const {
00516         return m.conformingMultiply(*this);
00517     }
00518 
00519     // m= this / m = this * m.invert()
00520     template <int M2, class E2, int CS2, int RS2> 
00521     typename Result<Mat<M2,N,E2,CS2,RS2> >::Dvd
00522     conformingDivide(const Mat<M2,N,E2,CS2,RS2>& m) const {
00523         return conformingMultiply(m.invert());
00524     }
00525     // m= m / this = m * this.invert()
00526     template <int M2, class E2, int CS2, int RS2> 
00527     typename Mat<M2,N,E2,CS2,RS2>::template Result<Mat>::Dvd
00528     conformingDivideFromLeft(const Mat<M2,N,E2,CS2,RS2>& m) const {
00529         return m.conformingMultiply((*this).invert());
00530     }
00531     
00532     const TRow& operator[](int i) const { return row(i); }
00533     TRow&       operator[](int i)       { return row(i); }    
00534     const TCol& operator()(int j) const { return col(j); }
00535     TCol&       operator()(int j)       { return col(j); }
00536     
00537     const E& operator()(int i,int j) const { return d[i*RS+j*CS]; }
00538     E&       operator()(int i,int j)       { return d[i*RS+j*CS]; }
00539 
00540     // This is the scalar Frobenius norm.
00541     ScalarSq normSqr() const { return scalarNormSqr(); }
00542     ScalarSq norm()    const { return std::sqrt(scalarNormSqr()); }
00543 
00544     // There is no conventional meaning for normalize() applied to a matrix. We
00545     // choose to define it as follows:
00546     // If the elements of this Mat are scalars, the result is what you get by
00547     // dividing each element by the Frobenius norm() calculated above. If the elements are
00548     // *not* scalars, then the elements are *separately* normalized. That means
00549     // you will get a different answer from Mat<2,2,Mat33>::normalize() than you
00550     // would from a Mat<6,6>::normalize() containing the same scalars.
00551     //
00552     // Normalize returns a matrix of the same dimension but in new, packed storage
00553     // and with a return type that does not include negator<> even if the original
00554     // Mat<> does, because we can eliminate the negation here almost for free.
00555     // But we can't standardize (change conjugate to complex) for free, so we'll retain
00556     // conjugates if there are any.
00557     TNormalize normalize() const {
00558         if (CNT<E>::IsScalar) {
00559             return castAwayNegatorIfAny() / (SignInterpretation*norm());
00560         } else {
00561             TNormalize elementwiseNormalized;
00562             // punt to the column Vec to deal with the elements
00563             for (int j=0; j<N; ++j) 
00564                 elementwiseNormalized(j) = (*this)(j).normalize();
00565             return elementwiseNormalized;
00566         }
00567     }
00568 
00569     // Default inversion. Assume full rank if square, otherwise return
00570     // pseudoinverse. (Mostly TODO)
00571     TInvert invert() const;
00572 
00573     const Mat&   operator+() const { return *this; }
00574     const TNeg&  operator-() const { return negate(); }
00575     TNeg&        operator-()       { return updNegate(); }
00576     const THerm& operator~() const { return transpose(); }
00577     THerm&       operator~()       { return updTranspose(); }
00578 
00579     const TNeg&  negate() const { return *reinterpret_cast<const TNeg*>(this); }
00580     TNeg&        updNegate()    { return *reinterpret_cast<TNeg*>(this); }
00581 
00582     const THerm& transpose()    const { return *reinterpret_cast<const THerm*>(this); }
00583     THerm&       updTranspose()       { return *reinterpret_cast<THerm*>(this); }
00584 
00585     const TPosTrans& positionalTranspose() const
00586         { return *reinterpret_cast<const TPosTrans*>(this); }
00587     TPosTrans&       updPositionalTranspose()
00588         { return *reinterpret_cast<TPosTrans*>(this); }
00589 
00590     // If the underlying scalars are complex or conjugate, we can return a
00591     // reference to the real part just by recasting the data to a matrix of
00592     // the same dimensions but containing real elements, with the scalar
00593     // spacing doubled.
00594     const TReal& real() const { return *reinterpret_cast<const TReal*>(this); }
00595     TReal&       real()       { return *reinterpret_cast<      TReal*>(this); }
00596 
00597     // Getting the imaginary part is almost the same as real, but we have
00598     // to shift the starting address of the returned object by 1 real-size
00599     // ("precision") scalar so that the first element is the imaginary part
00600     // of the original first element.
00601     // TODO: should blow up or return a reference to a zero matrix if called
00602     // on a real object.
00603     // Had to contort these routines to get them through VC++ 7.net
00604     const TImag& imag()    const { 
00605         const int offs = ImagOffset;
00606         const Precision* p = reinterpret_cast<const Precision*>(this);
00607         return *reinterpret_cast<const TImag*>(p+offs);
00608     }
00609     TImag& imag() { 
00610         const int offs = ImagOffset;
00611         Precision* p = reinterpret_cast<Precision*>(this);
00612         return *reinterpret_cast<TImag*>(p+offs);
00613     }
00614 
00615     const TWithoutNegator& castAwayNegatorIfAny() const {return *reinterpret_cast<const TWithoutNegator*>(this);}
00616     TWithoutNegator&       updCastAwayNegatorIfAny()    {return *reinterpret_cast<TWithoutNegator*>(this);}
00617 
00618     const TRow& row(int i) const 
00619       { assert(0<=i&&i<M); return *reinterpret_cast<const TRow*>(&d[i*RS]); }
00620     TRow&       row(int i)       
00621       { assert(0<=i&&i<M); return *reinterpret_cast<      TRow*>(&d[i*RS]); }
00622 
00623     const TCol& col(int j) const 
00624       { assert(0<=j&&j<N); return *reinterpret_cast<const TCol*>(&d[j*CS]); }
00625     TCol&       col(int j)       
00626       { assert(0<=j&&j<N); return *reinterpret_cast<      TCol*>(&d[j*CS]); }    
00627 
00628 
00629     const TDiag& diag() const { return *reinterpret_cast<const TDiag*>(d); }
00630     TDiag&       diag()       { return *reinterpret_cast<TDiag*>(d); }
00631 
00632     StdNumber trace() const {return diag().sum();}
00633 
00634     // These are elementwise binary operators, (this op ee) by default but (ee op this) if
00635     // 'FromLeft' appears in the name. The result is a packed Mat<M,N> but the element type
00636     // may change. These are mostly used to implement global operators.
00637     // We call these "scalar" operators but actually the "scalar" can be a composite type.
00638 
00639     //TODO: consider converting 'e' to Standard Numbers as precalculation and changing
00640     // return type appropriately.
00641     template <class EE> Mat<M,N, typename CNT<E>::template Result<EE>::Mul>
00642     scalarMultiply(const EE& e) const {
00643         Mat<M,N, typename CNT<E>::template Result<EE>::Mul> result;
00644         for (int j=0; j<N; ++j) result(j) = (*this)(j).scalarMultiply(e);
00645         return result;
00646     }
00647     template <class EE> Mat<M,N, typename CNT<EE>::template Result<E>::Mul>
00648     scalarMultiplyFromLeft(const EE& e) const {
00649         Mat<M,N, typename CNT<EE>::template Result<E>::Mul> result;
00650         for (int j=0; j<N; ++j) result(j) = (*this)(j).scalarMultiplyFromLeft(e);
00651         return result;
00652     }
00653 
00654     // TODO: should precalculate and store 1/e, while converting to Standard Numbers. Note
00655     // that return type should change appropriately.
00656     template <class EE> Mat<M,N, typename CNT<E>::template Result<EE>::Dvd>
00657     scalarDivide(const EE& e) const {
00658         Mat<M,N, typename CNT<E>::template Result<EE>::Dvd> result;
00659         for (int j=0; j<N; ++j) result(j) = (*this)(j).scalarDivide(e);
00660         return result;
00661     }
00662     template <class EE> Mat<M,N, typename CNT<EE>::template Result<E>::Dvd>
00663     scalarDivideFromLeft(const EE& e) const {
00664         Mat<M,N, typename CNT<EE>::template Result<E>::Dvd> result;
00665         for (int j=0; j<N; ++j) result(j) = (*this)(j).scalarDivideFromLeft(e);
00666         return result;
00667     }
00668 
00669     // Additive operators for scalars operate only on the diagonal.
00670     template <class EE> Mat<M,N, typename CNT<E>::template Result<EE>::Add>
00671     scalarAdd(const EE& e) const {
00672         Mat<M,N, typename CNT<E>::template Result<EE>::Add> result(*this);
00673         result.diag() += e;
00674         return result;
00675     }
00676     // Add is commutative, so no 'FromLeft'.
00677 
00678     template <class EE> Mat<M,N, typename CNT<E>::template Result<EE>::Sub>
00679     scalarSubtract(const EE& e) const {
00680         Mat<M,N, typename CNT<E>::template Result<EE>::Sub> result(*this);
00681         result.diag() -= e;
00682         return result;
00683     }
00684     // Should probably do something clever with negation here (s - m)
00685     template <class EE> Mat<M,N, typename CNT<EE>::template Result<E>::Sub>
00686     scalarSubtractFromLeft(const EE& e) const {
00687         Mat<M,N, typename CNT<EE>::template Result<E>::Sub> result(-(*this));
00688         result.diag() += e; // yes, add
00689         return result;
00690     }
00691 
00692     // Generic assignments for any element type not listed explicitly, including scalars.
00693     // These are done repeatedly for each element and only work if the operation can
00694     // be performed leaving the original element type.
00695     template <class EE> Mat& operator =(const EE& e) {return scalarEq(e);}
00696     template <class EE> Mat& operator+=(const EE& e) {return scalarPlusEq(e);}
00697     template <class EE> Mat& operator-=(const EE& e) {return scalarMinusEq(e);}
00698     template <class EE> Mat& operator*=(const EE& e) {return scalarTimesEq(e);}
00699     template <class EE> Mat& operator/=(const EE& e) {return scalarDivideEq(e);}
00700 
00701     // Generalized scalar assignment & computed assignment methods. These will work
00702     // for any assignment-compatible element, not just scalars.
00703     template <class EE> Mat& scalarEq(const EE& ee)
00704       { for(int j=0; j<N; ++j) (*this)(j).scalarEq(EE(0)); 
00705         diag().scalarEq(ee); 
00706         return *this; }
00707 
00708     template <class EE> Mat& scalarPlusEq(const EE& ee)
00709       { diag().scalarPlusEq(ee); return *this; }
00710 
00711     template <class EE> Mat& scalarMinusEq(const EE& ee)
00712       { diag().scalarMinusEq(ee); return *this; }
00713     // m = s - m; negate m, then add s
00714     template <class EE> Mat& scalarMinusEqFromLeft(const EE& ee)
00715       { scalarTimesEq(E(-1)); diag().scalarAdd(ee); return *this; }
00716 
00717     template <class EE> Mat& scalarTimesEq(const EE& ee)
00718       { for(int j=0; j<N; ++j) (*this)(j).scalarTimesEq(ee); return *this; }
00719     template <class EE> Mat& scalarTimesEqFromLeft(const EE& ee)
00720       { for(int j=0; j<N; ++j) (*this)(j).scalarTimesEqFromLeft(ee); return *this; } 
00721 
00722     template <class EE> Mat& scalarDivideEq(const EE& ee)
00723       { for(int j=0; j<N; ++j) (*this)(j).scalarDivideEq(ee); return *this; }
00724     template <class EE> Mat& scalarDivideEqFromLeft(const EE& ee)
00725       { for(int j=0; j<N; ++j) (*this)(j).scalarDivideEqFromLeft(ee); return *this; } 
00726 
00727     void setToNaN() {
00728         for (int j=0; j<N; ++j)
00729             (*this)(j).setToNaN();
00730     }
00731 
00732     // Extract a sub-Mat with size known at compile time. These have to be
00733     // called with explicit template arguments, e.g. getSubMat<3,4>(i,j).
00734 
00735     template <int MM, int NN> struct SubMat {
00736         typedef Mat<MM,NN,ELT,CS,RS> Type;
00737     };
00738 
00739     template <int MM, int NN>
00740     const typename SubMat<MM,NN>::Type& getSubMat(int i, int j) const {
00741         assert(0 <= i && i + MM <= M);
00742         assert(0 <= j && j + NN <= N);
00743         return SubMat<MM,NN>::Type::getAs(&(*this)(i,j));
00744     }
00745     template <int MM, int NN>
00746     typename SubMat<MM,NN>::Type& updSubMat(int i, int j) {
00747         assert(0 <= i && i + MM <= M);
00748         assert(0 <= j && j + NN <= N);
00749         return SubMat<MM,NN>::Type::updAs(&(*this)(i,j));
00750     }
00751 
00752     // These assume we are given a pointer to d[0] of a Mat<M,N,E,CS,RS> like this one.
00753     static const Mat& getAs(const ELT* p)  {return *reinterpret_cast<const Mat*>(p);}
00754     static Mat&       updAs(ELT* p)        {return *reinterpret_cast<Mat*>(p);}
00755 
00756     // Note packed spacing
00757     static Mat<M,N,ELT,M,1> getNaN() { 
00758         Mat<M,N,ELT,M,1> m;
00759         m.setToNaN();
00760         return m;
00761     }
00762     
00763     TRow sum() const {
00764         TRow temp;
00765         for (int i = 0; i < N; ++i)
00766             temp[i] = col(i).sum();
00767         return temp;
00768     }
00769 
00770 private:
00771     E d[NActualElements];
00772 
00773     // This permits running through d as though it were stored
00774     // in row order with packed elements. Pass in the k'th value
00775     // of the row ordering and get back the index into d where
00776     // that element is stored.
00777     int rIx(int k) const {
00778         const int row = k / N;
00779         const int col = k % N; // that's modulus, not cross product!
00780         return row*RS + col*CS;
00781     }
00782 };
00783 
00785 // Global operators involving two matrices. //
00786 //   m+m, m-m, m*m, m==m, m!=m              //
00788 
00789 template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline 
00790 typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >::Add
00791 operator+(const Mat<M,N,EL,CSL,RSL>& l, const Mat<M,N,ER,CSR,RSR>& r) { 
00792     return Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >
00793         ::AddOp::perform(l,r);
00794 }
00795 
00796 template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline
00797 typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >::Sub
00798 operator-(const Mat<M,N,EL,CSL,RSL>& l, const Mat<M,N,ER,CSR,RSR>& r) { 
00799     return Mat<M,N,EL,CSL,RSL>::template Result<Mat<M,N,ER,CSR,RSR> >
00800         ::SubOp::perform(l,r);
00801 }
00802 
00803 // Matrix multiply of an MxN by NxP to produce a packed MxP.
00804 template <int M, int N, class EL, int CSL, int RSL, int P, class ER, int CSR, int RSR> inline
00805 typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<N,P,ER,CSR,RSR> >::Mul
00806 operator*(const Mat<M,N,EL,CSL,RSL>& l, const Mat<N,P,ER,CSR,RSR>& r) { 
00807     return Mat<M,N,EL,CSL,RSL>::template Result<Mat<N,P,ER,CSR,RSR> >
00808         ::MulOp::perform(l,r);
00809 }
00810 
00811 // Non-conforming matrix multiply of an MxN by MMxNN; will be a scalar multiply if one
00812 // has scalar elements and the other has composite elements.
00813 template <int M, int N, class EL, int CSL, int RSL, int MM, int NN, class ER, int CSR, int RSR> inline
00814 typename Mat<M,N,EL,CSL,RSL>::template Result<Mat<MM,NN,ER,CSR,RSR> >::MulNon
00815 operator*(const Mat<M,N,EL,CSL,RSL>& l, const Mat<MM,NN,ER,CSR,RSR>& r) { 
00816     return Mat<M,N,EL,CSL,RSL>::template Result<Mat<MM,NN,ER,CSR,RSR> >
00817                 ::MulOpNonConforming::perform(l,r);
00818 }
00819 
00820 template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline
00821 bool operator==(const Mat<M,N,EL,CSL,RSL>& l, const Mat<M,N,ER,CSR,RSR>& r) { 
00822     for (int j=0; j<N; ++j)
00823         if (l(j) != r(j)) return false;
00824     return true;
00825 }
00826 template <int M, int N, class EL, int CSL, int RSL, class ER, int CSR, int RSR> inline
00827 bool operator!=(const Mat<M,N,EL,CSL,RSL>& l, const Mat<M,N,ER,CSR,RSR>& r) { 
00828     return !(l==r);
00829 }
00830 
00831 
00833 // Global operators involving a matrix and a scalar. //
00835 
00836 // SCALAR MULTIPLY
00837 
00838 // m = m*real, real*m 
00839 template <int M, int N, class E, int CS, int RS> inline
00840 typename Mat<M,N,E,CS,RS>::template Result<float>::Mul
00841 operator*(const Mat<M,N,E,CS,RS>& l, const float& r)
00842   { return Mat<M,N,E,CS,RS>::template Result<float>::MulOp::perform(l,r); }
00843 template <int M, int N, class E, int CS, int RS> inline
00844 typename Mat<M,N,E,CS,RS>::template Result<float>::Mul
00845 operator*(const float& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
00846 
00847 template <int M, int N, class E, int CS, int RS> inline
00848 typename Mat<M,N,E,CS,RS>::template Result<double>::Mul
00849 operator*(const Mat<M,N,E,CS,RS>& l, const double& r)
00850   { return Mat<M,N,E,CS,RS>::template Result<double>::MulOp::perform(l,r); }
00851 template <int M, int N, class E, int CS, int RS> inline
00852 typename Mat<M,N,E,CS,RS>::template Result<double>::Mul
00853 operator*(const double& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
00854 
00855 template <int M, int N, class E, int CS, int RS> inline
00856 typename Mat<M,N,E,CS,RS>::template Result<long double>::Mul
00857 operator*(const Mat<M,N,E,CS,RS>& l, const long double& r)
00858   { return Mat<M,N,E,CS,RS>::template Result<long double>::MulOp::perform(l,r); }
00859 template <int M, int N, class E, int CS, int RS> inline
00860 typename Mat<M,N,E,CS,RS>::template Result<long double>::Mul
00861 operator*(const long double& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
00862 
00863 // m = m*int, int*m -- just convert int to m's precision float
00864 template <int M, int N, class E, int CS, int RS> inline
00865 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Mul
00866 operator*(const Mat<M,N,E,CS,RS>& l, int r) {return l * (typename CNT<E>::Precision)r;}
00867 template <int M, int N, class E, int CS, int RS> inline
00868 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Mul
00869 operator*(int l, const Mat<M,N,E,CS,RS>& r) {return r * (typename CNT<E>::Precision)l;}
00870 
00871 // Complex, conjugate, and negator are all easy to templatize.
00872 
00873 // m = m*complex, complex*m
00874 template <int M, int N, class E, int CS, int RS, class R> inline
00875 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
00876 operator*(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
00877   { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::MulOp::perform(l,r); }
00878 template <int M, int N, class E, int CS, int RS, class R> inline
00879 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
00880 operator*(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r) {return r*l;}
00881 
00882 // m = m*conjugate, conjugate*m (convert conjugate->complex)
00883 template <int M, int N, class E, int CS, int RS, class R> inline
00884 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
00885 operator*(const Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l*(std::complex<R>)r;}
00886 template <int M, int N, class E, int CS, int RS, class R> inline
00887 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Mul
00888 operator*(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return r*(std::complex<R>)l;}
00889 
00890 // m = m*negator, negator*m: convert negator to standard number
00891 template <int M, int N, class E, int CS, int RS, class R> inline
00892 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Mul
00893 operator*(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l * (typename negator<R>::StdNumber)(R)r;}
00894 template <int M, int N, class E, int CS, int RS, class R> inline
00895 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Mul
00896 operator*(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return r * (typename negator<R>::StdNumber)(R)l;}
00897 
00898 
00899 // SCALAR DIVIDE. This is a scalar operation when the scalar is on the right,
00900 // but when it is on the left it means scalar * pseudoInverse(mat), 
00901 // which is a matrix whose type is like the matrix's Hermitian transpose.
00902 
00903 // m = m/real, real/m 
00904 template <int M, int N, class E, int CS, int RS> inline
00905 typename Mat<M,N,E,CS,RS>::template Result<float>::Dvd
00906 operator/(const Mat<M,N,E,CS,RS>& l, const float& r)
00907   { return Mat<M,N,E,CS,RS>::template Result<float>::DvdOp::perform(l,r); }
00908 template <int M, int N, class E, int CS, int RS> inline
00909 typename CNT<float>::template Result<Mat<M,N,E,CS,RS> >::Dvd
00910 operator/(const float& l, const Mat<M,N,E,CS,RS>& r)
00911   { return CNT<float>::template Result<Mat<M,N,E,CS,RS> >::DvdOp::perform(l,r); }
00912 
00913 template <int M, int N, class E, int CS, int RS> inline
00914 typename Mat<M,N,E,CS,RS>::template Result<double>::Dvd
00915 operator/(const Mat<M,N,E,CS,RS>& l, const double& r)
00916   { return Mat<M,N,E,CS,RS>::template Result<double>::DvdOp::perform(l,r); }
00917 template <int M, int N, class E, int CS, int RS> inline
00918 typename CNT<double>::template Result<Mat<M,N,E,CS,RS> >::Dvd
00919 operator/(const double& l, const Mat<M,N,E,CS,RS>& r)
00920   { return CNT<double>::template Result<Mat<M,N,E,CS,RS> >::DvdOp::perform(l,r); }
00921 
00922 template <int M, int N, class E, int CS, int RS> inline
00923 typename Mat<M,N,E,CS,RS>::template Result<long double>::Dvd
00924 operator/(const Mat<M,N,E,CS,RS>& l, const long double& r)
00925   { return Mat<M,N,E,CS,RS>::template Result<long double>::DvdOp::perform(l,r); }
00926 template <int M, int N, class E, int CS, int RS> inline
00927 typename CNT<long double>::template Result<Mat<M,N,E,CS,RS> >::Dvd
00928 operator/(const long double& l, const Mat<M,N,E,CS,RS>& r)
00929   { return CNT<long double>::template Result<Mat<M,N,E,CS,RS> >::DvdOp::perform(l,r); }
00930 
00931 // m = m/int, int/m -- just convert int to m's precision float
00932 template <int M, int N, class E, int CS, int RS> inline
00933 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Dvd
00934 operator/(const Mat<M,N,E,CS,RS>& l, int r) {return l / (typename CNT<E>::Precision)r;}
00935 template <int M, int N, class E, int CS, int RS> inline
00936 typename CNT<typename CNT<E>::Precision>::template Result<Mat<M,N,E,CS,RS> >::Dvd
00937 operator/(int l, const Mat<M,N,E,CS,RS>& r) {return (typename CNT<E>::Precision)l / r;}
00938 
00939 
00940 // Complex, conjugate, and negator are all easy to templatize.
00941 
00942 // m = m/complex, complex/m
00943 template <int M, int N, class E, int CS, int RS, class R> inline
00944 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Dvd
00945 operator/(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
00946   { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::DvdOp::perform(l,r); }
00947 template <int M, int N, class E, int CS, int RS, class R> inline
00948 typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Dvd
00949 operator/(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r)
00950   { return CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::DvdOp::perform(l,r); }
00951 
00952 // m = m/conjugate, conjugate/m (convert conjugate->complex)
00953 template <int M, int N, class E, int CS, int RS, class R> inline
00954 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Dvd
00955 operator/(const Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l/(std::complex<R>)r;}
00956 template <int M, int N, class E, int CS, int RS, class R> inline
00957 typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Dvd
00958 operator/(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return (std::complex<R>)l/r;}
00959 
00960 // m = m/negator, negator/m: convert negator to a standard number
00961 template <int M, int N, class E, int CS, int RS, class R> inline
00962 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Dvd
00963 operator/(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l/(typename negator<R>::StdNumber)(R)r;}
00964 template <int M, int N, class E, int CS, int RS, class R> inline
00965 typename CNT<R>::template Result<Mat<M,N,E,CS,RS> >::Dvd
00966 operator/(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return (typename negator<R>::StdNumber)(R)l/r;}
00967 
00968 
00969 // Add and subtract are odd as scalar ops. They behave as though the
00970 // scalar stands for a conforming matrix whose diagonal elements are that,
00971 // scalar and then a normal matrix add or subtract is done.
00972 
00973 // SCALAR ADD
00974 
00975 // m = m+real, real+m 
00976 template <int M, int N, class E, int CS, int RS> inline
00977 typename Mat<M,N,E,CS,RS>::template Result<float>::Add
00978 operator+(const Mat<M,N,E,CS,RS>& l, const float& r)
00979   { return Mat<M,N,E,CS,RS>::template Result<float>::AddOp::perform(l,r); }
00980 template <int M, int N, class E, int CS, int RS> inline
00981 typename Mat<M,N,E,CS,RS>::template Result<float>::Add
00982 operator+(const float& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
00983 
00984 template <int M, int N, class E, int CS, int RS> inline
00985 typename Mat<M,N,E,CS,RS>::template Result<double>::Add
00986 operator+(const Mat<M,N,E,CS,RS>& l, const double& r)
00987   { return Mat<M,N,E,CS,RS>::template Result<double>::AddOp::perform(l,r); }
00988 template <int M, int N, class E, int CS, int RS> inline
00989 typename Mat<M,N,E,CS,RS>::template Result<double>::Add
00990 operator+(const double& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
00991 
00992 template <int M, int N, class E, int CS, int RS> inline
00993 typename Mat<M,N,E,CS,RS>::template Result<long double>::Add
00994 operator+(const Mat<M,N,E,CS,RS>& l, const long double& r)
00995   { return Mat<M,N,E,CS,RS>::template Result<long double>::AddOp::perform(l,r); }
00996 template <int M, int N, class E, int CS, int RS> inline
00997 typename Mat<M,N,E,CS,RS>::template Result<long double>::Add
00998 operator+(const long double& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
00999 
01000 // m = m+int, int+m -- just convert int to m's precision float
01001 template <int M, int N, class E, int CS, int RS> inline
01002 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Add
01003 operator+(const Mat<M,N,E,CS,RS>& l, int r) {return l + (typename CNT<E>::Precision)r;}
01004 template <int M, int N, class E, int CS, int RS> inline
01005 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Add
01006 operator+(int l, const Mat<M,N,E,CS,RS>& r) {return r + (typename CNT<E>::Precision)l;}
01007 
01008 // Complex, conjugate, and negator are all easy to templatize.
01009 
01010 // m = m+complex, complex+m
01011 template <int M, int N, class E, int CS, int RS, class R> inline
01012 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
01013 operator+(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
01014   { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::AddOp::perform(l,r); }
01015 template <int M, int N, class E, int CS, int RS, class R> inline
01016 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
01017 operator+(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r) {return r+l;}
01018 
01019 // m = m+conjugate, conjugate+m (convert conjugate->complex)
01020 template <int M, int N, class E, int CS, int RS, class R> inline
01021 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
01022 operator+(const Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l+(std::complex<R>)r;}
01023 template <int M, int N, class E, int CS, int RS, class R> inline
01024 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Add
01025 operator+(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return r+(std::complex<R>)l;}
01026 
01027 // m = m+negator, negator+m: convert negator to standard number
01028 template <int M, int N, class E, int CS, int RS, class R> inline
01029 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Add
01030 operator+(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l + (typename negator<R>::StdNumber)(R)r;}
01031 template <int M, int N, class E, int CS, int RS, class R> inline
01032 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Add
01033 operator+(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return r + (typename negator<R>::StdNumber)(R)l;}
01034 
01035 // SCALAR SUBTRACT -- careful, not commutative.
01036 
01037 // m = m-real, real-m 
01038 template <int M, int N, class E, int CS, int RS> inline
01039 typename Mat<M,N,E,CS,RS>::template Result<float>::Sub
01040 operator-(const Mat<M,N,E,CS,RS>& l, const float& r)
01041   { return Mat<M,N,E,CS,RS>::template Result<float>::SubOp::perform(l,r); }
01042 template <int M, int N, class E, int CS, int RS> inline
01043 typename CNT<float>::template Result<Mat<M,N,E,CS,RS> >::Sub
01044 operator-(const float& l, const Mat<M,N,E,CS,RS>& r)
01045   { return CNT<float>::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
01046 
01047 template <int M, int N, class E, int CS, int RS> inline
01048 typename Mat<M,N,E,CS,RS>::template Result<double>::Sub
01049 operator-(const Mat<M,N,E,CS,RS>& l, const double& r)
01050   { return Mat<M,N,E,CS,RS>::template Result<double>::SubOp::perform(l,r); }
01051 template <int M, int N, class E, int CS, int RS> inline
01052 typename CNT<double>::template Result<Mat<M,N,E,CS,RS> >::Sub
01053 operator-(const double& l, const Mat<M,N,E,CS,RS>& r)
01054   { return CNT<double>::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
01055 
01056 template <int M, int N, class E, int CS, int RS> inline
01057 typename Mat<M,N,E,CS,RS>::template Result<long double>::Sub
01058 operator-(const Mat<M,N,E,CS,RS>& l, const long double& r)
01059   { return Mat<M,N,E,CS,RS>::template Result<long double>::SubOp::perform(l,r); }
01060 template <int M, int N, class E, int CS, int RS> inline
01061 typename CNT<long double>::template Result<Mat<M,N,E,CS,RS> >::Sub
01062 operator-(const long double& l, const Mat<M,N,E,CS,RS>& r)
01063   { return CNT<long double>::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
01064 
01065 // m = m-int, int-m // just convert int to m's precision float
01066 template <int M, int N, class E, int CS, int RS> inline
01067 typename Mat<M,N,E,CS,RS>::template Result<typename CNT<E>::Precision>::Sub
01068 operator-(const Mat<M,N,E,CS,RS>& l, int r) {return l - (typename CNT<E>::Precision)r;}
01069 template <int M, int N, class E, int CS, int RS> inline
01070 typename CNT<typename CNT<E>::Precision>::template Result<Mat<M,N,E,CS,RS> >::Sub
01071 operator-(int l, const Mat<M,N,E,CS,RS>& r) {return (typename CNT<E>::Precision)l - r;}
01072 
01073 
01074 // Complex, conjugate, and negator are all easy to templatize.
01075 
01076 // m = m-complex, complex-m
01077 template <int M, int N, class E, int CS, int RS, class R> inline
01078 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Sub
01079 operator-(const Mat<M,N,E,CS,RS>& l, const std::complex<R>& r)
01080   { return Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::SubOp::perform(l,r); }
01081 template <int M, int N, class E, int CS, int RS, class R> inline
01082 typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Sub
01083 operator-(const std::complex<R>& l, const Mat<M,N,E,CS,RS>& r)
01084   { return CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::SubOp::perform(l,r); }
01085 
01086 // m = m-conjugate, conjugate-m (convert conjugate->complex)
01087 template <int M, int N, class E, int CS, int RS, class R> inline
01088 typename Mat<M,N,E,CS,RS>::template Result<std::complex<R> >::Sub
01089 operator-(const Mat<M,N,E,CS,RS>& l, const conjugate<R>& r) {return l-(std::complex<R>)r;}
01090 template <int M, int N, class E, int CS, int RS, class R> inline
01091 typename CNT<std::complex<R> >::template Result<Mat<M,N,E,CS,RS> >::Sub
01092 operator-(const conjugate<R>& l, const Mat<M,N,E,CS,RS>& r) {return (std::complex<R>)l-r;}
01093 
01094 // m = m-negator, negator-m: convert negator to standard number
01095 template <int M, int N, class E, int CS, int RS, class R> inline
01096 typename Mat<M,N,E,CS,RS>::template Result<typename negator<R>::StdNumber>::Sub
01097 operator-(const Mat<M,N,E,CS,RS>& l, const negator<R>& r) {return l-(typename negator<R>::StdNumber)(R)r;}
01098 template <int M, int N, class E, int CS, int RS, class R> inline
01099 typename CNT<R>::template Result<Mat<M,N,E,CS,RS> >::Sub
01100 operator-(const negator<R>& l, const Mat<M,N,E,CS,RS>& r) {return (typename negator<R>::StdNumber)(R)l-r;}
01101 
01102 
01103 // Mat I/O
01104 template <int M, int N, class E, int CS, int RS, class CHAR, class TRAITS> inline
01105 std::basic_ostream<CHAR,TRAITS>&
01106 operator<<(std::basic_ostream<CHAR,TRAITS>& o, const Mat<M,N,E,CS,RS>& m) {
01107     for (int i=0;i<M;++i) {
01108         o << std::endl << "[";
01109         for (int j=0;j<N;++j)         
01110             o << (j>0?",":"") << m(i,j);
01111         o << "]";
01112     }
01113     if (M) o << std::endl;
01114     return o; 
01115 }
01116 
01117 template <int M, int N, class E, int CS, int RS, class CHAR, class TRAITS> inline
01118 std::basic_istream<CHAR,TRAITS>&
01119 operator>>(std::basic_istream<CHAR,TRAITS>& is, Mat<M,N,E,CS,RS>& m) {
01120     // TODO: not sure how to do Vec input yet
01121     assert(false);
01122     return is;
01123 }
01124 
01125 } //namespace SimTK
01126 
01127 
01128 #endif //SimTK_SIMMATRIX_SMALLMATRIX_MAT_H_

Generated on Thu Feb 28 01:34:30 2008 for SimTKcommon by  doxygen 1.4.7