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