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