Simbody
|
00001 #ifndef SimTK_SIMMATRIX_BIGMATRIX_H_ 00002 #define SimTK_SIMMATRIX_BIGMATRIX_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-9 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 00167 // TODO: matrix expression templates for delaying operator execution. 00168 00169 #include "SimTKcommon/Scalar.h" 00170 #include "SimTKcommon/SmallMatrix.h" 00171 00172 #include "SimTKcommon/internal/MatrixHelper.h" 00173 #include "SimTKcommon/internal/MatrixCharacteristics.h" 00174 00175 #include <iostream> 00176 #include <cassert> 00177 #include <complex> 00178 #include <cstddef> 00179 #include <limits> 00180 00181 namespace SimTK { 00182 00183 template <class ELT> class MatrixBase; 00184 template <class ELT> class VectorBase; 00185 template <class ELT> class RowVectorBase; 00186 00187 template <class T=Real> class MatrixView_; 00188 template <class T=Real> class DeadMatrixView_; 00189 template <class T=Real> class Matrix_; 00190 template <class T=Real> class DeadMatrix_; 00191 00192 template <class T=Real> class VectorView_; 00193 template <class T=Real> class DeadVectorView_; 00194 template <class T=Real> class Vector_; 00195 template <class T=Real> class DeadVector_; 00196 00197 template <class T=Real> class RowVectorView_; 00198 template <class T=Real> class DeadRowVectorView_; 00199 template <class T=Real> class RowVector_; 00200 template <class T=Real> class DeadRowVector_; 00201 00202 template <class ELT, class VECTOR_CLASS> class VectorIterator; 00203 00204 // -------------------------------- MatrixBase -------------------------------- 00226 // ---------------------------------------------------------------------------- 00227 template <class ELT> class MatrixBase { 00228 public: 00229 // These typedefs are handy, but despite appearances you cannot 00230 // treat a MatrixBase as a composite numerical type. That is, 00231 // CNT<MatrixBase> will not compile, or if it does it won't be 00232 // meaningful. 00233 00234 typedef ELT E; 00235 typedef typename CNT<E>::TNeg ENeg; 00236 typedef typename CNT<E>::TWithoutNegator EWithoutNegator; 00237 typedef typename CNT<E>::TReal EReal; 00238 typedef typename CNT<E>::TImag EImag; 00239 typedef typename CNT<E>::TComplex EComplex; 00240 typedef typename CNT<E>::THerm EHerm; 00241 typedef typename CNT<E>::TPosTrans EPosTrans; 00242 00243 typedef typename CNT<E>::TAbs EAbs; 00244 typedef typename CNT<E>::TStandard EStandard; 00245 typedef typename CNT<E>::TInvert EInvert; 00246 typedef typename CNT<E>::TNormalize ENormalize; 00247 typedef typename CNT<E>::TSqHermT ESqHermT; 00248 typedef typename CNT<E>::TSqTHerm ESqTHerm; 00249 00250 typedef typename CNT<E>::Scalar EScalar; 00251 typedef typename CNT<E>::Number ENumber; 00252 typedef typename CNT<E>::StdNumber EStdNumber; 00253 typedef typename CNT<E>::Precision EPrecision; 00254 typedef typename CNT<E>::ScalarNormSq EScalarNormSq; 00255 00256 typedef EScalar Scalar; // the underlying Scalar type 00257 typedef ENumber Number; // negator removed from Scalar 00258 typedef EStdNumber StdNumber; // conjugate goes to complex 00259 typedef EPrecision Precision; // complex removed from StdNumber 00260 typedef EScalarNormSq ScalarNormSq; // type of scalar^2 00261 00262 typedef MatrixBase<E> T; 00263 typedef MatrixBase<ENeg> TNeg; 00264 typedef MatrixBase<EWithoutNegator> TWithoutNegator; 00265 typedef MatrixBase<EReal> TReal; 00266 typedef MatrixBase<EImag> TImag; 00267 typedef MatrixBase<EComplex> TComplex; 00268 typedef MatrixBase<EHerm> THerm; 00269 typedef MatrixBase<E> TPosTrans; 00270 00271 typedef MatrixBase<EAbs> TAbs; 00272 typedef MatrixBase<EStandard> TStandard; 00273 typedef MatrixBase<EInvert> TInvert; 00274 typedef MatrixBase<ENormalize> TNormalize; 00275 typedef MatrixBase<ESqHermT> TSqHermT; // ~Mat*Mat 00276 typedef MatrixBase<ESqTHerm> TSqTHerm; // Mat*~Mat 00277 00278 const MatrixCommitment& getCharacterCommitment() const {return helper.getCharacterCommitment();} 00279 const MatrixCharacter& getMatrixCharacter() const {return helper.getMatrixCharacter();} 00280 00283 void commitTo(const MatrixCommitment& mc) 00284 { helper.commitTo(mc); } 00285 00286 // This gives the resulting matrix type when (m(i,j) op P) is applied to each element. 00287 // It will have element types which are the regular composite result of E op P. 00288 template <class P> struct EltResult { 00289 typedef MatrixBase<typename CNT<E>::template Result<P>::Mul> Mul; 00290 typedef MatrixBase<typename CNT<E>::template Result<P>::Dvd> Dvd; 00291 typedef MatrixBase<typename CNT<E>::template Result<P>::Add> Add; 00292 typedef MatrixBase<typename CNT<E>::template Result<P>::Sub> Sub; 00293 }; 00294 00296 int nrow() const {return helper.nrow();} 00298 int ncol() const {return helper.ncol();} 00299 00307 ptrdiff_t nelt() const {return helper.nelt();} 00308 00310 bool isResizeable() const {return getCharacterCommitment().isResizeable();} 00311 00312 enum { 00313 NScalarsPerElement = CNT<E>::NActualScalars, 00314 CppNScalarsPerElement = sizeof(E) / sizeof(Scalar) 00315 }; 00316 00320 MatrixBase() : helper(NScalarsPerElement,CppNScalarsPerElement) {} 00321 00324 MatrixBase(int m, int n) 00325 : helper(NScalarsPerElement,CppNScalarsPerElement,MatrixCommitment(),m,n) {} 00326 00332 explicit MatrixBase(const MatrixCommitment& commitment) 00333 : helper(NScalarsPerElement,CppNScalarsPerElement,commitment) {} 00334 00335 00340 MatrixBase(const MatrixCommitment& commitment, int m, int n) 00341 : helper(NScalarsPerElement,CppNScalarsPerElement,commitment,m,n) {} 00342 00344 MatrixBase(const MatrixBase& b) 00345 : helper(b.helper.getCharacterCommitment(), 00346 b.helper, typename MatrixHelper<Scalar>::DeepCopy()) { } 00347 00350 MatrixBase(const TNeg& b) 00351 : helper(b.helper.getCharacterCommitment(), 00352 b.helper, typename MatrixHelper<Scalar>::DeepCopy()) { } 00353 00356 MatrixBase& copyAssign(const MatrixBase& b) { 00357 helper.copyAssign(b.helper); 00358 return *this; 00359 } 00360 MatrixBase& operator=(const MatrixBase& b) { return copyAssign(b); } 00361 00362 00371 MatrixBase& viewAssign(const MatrixBase& src) { 00372 helper.writableViewAssign(const_cast<MatrixHelper<Scalar>&>(src.helper)); 00373 return *this; 00374 } 00375 00376 // default destructor 00377 00384 MatrixBase(const MatrixCommitment& commitment, int m, int n, const ELT& initialValue) 00385 : helper(NScalarsPerElement, CppNScalarsPerElement, commitment, m, n) 00386 { helper.fillWith(reinterpret_cast<const Scalar*>(&initialValue)); } 00387 00398 MatrixBase(const MatrixCommitment& commitment, int m, int n, 00399 const ELT* cppInitialValuesByRow) 00400 : helper(NScalarsPerElement, CppNScalarsPerElement, commitment, m, n) 00401 { helper.copyInByRowsFromCpp(reinterpret_cast<const Scalar*>(cppInitialValuesByRow)); } 00402 00414 00416 MatrixBase(const MatrixCommitment& commitment, 00417 const MatrixCharacter& character, 00418 int spacing, const Scalar* data) // read only data 00419 : helper(NScalarsPerElement, CppNScalarsPerElement, 00420 commitment, character, spacing, data) {} 00421 00423 MatrixBase(const MatrixCommitment& commitment, 00424 const MatrixCharacter& character, 00425 int spacing, Scalar* data) // writable data 00426 : helper(NScalarsPerElement, CppNScalarsPerElement, 00427 commitment, character, spacing, data) {} 00429 00430 // Create a new MatrixBase from an existing helper. Both shallow and deep copies are possible. 00431 MatrixBase(const MatrixCommitment& commitment, 00432 MatrixHelper<Scalar>& source, 00433 const typename MatrixHelper<Scalar>::ShallowCopy& shallow) 00434 : helper(commitment, source, shallow) {} 00435 MatrixBase(const MatrixCommitment& commitment, 00436 const MatrixHelper<Scalar>& source, 00437 const typename MatrixHelper<Scalar>::ShallowCopy& shallow) 00438 : helper(commitment, source, shallow) {} 00439 MatrixBase(const MatrixCommitment& commitment, 00440 const MatrixHelper<Scalar>& source, 00441 const typename MatrixHelper<Scalar>::DeepCopy& deep) 00442 : helper(commitment, source, deep) {} 00443 00447 void clear() {helper.clear();} 00448 00449 MatrixBase& operator*=(const StdNumber& t) { helper.scaleBy(t); return *this; } 00450 MatrixBase& operator/=(const StdNumber& t) { helper.scaleBy(StdNumber(1)/t); return *this; } 00451 MatrixBase& operator+=(const MatrixBase& r) { helper.addIn(r.helper); return *this; } 00452 MatrixBase& operator-=(const MatrixBase& r) { helper.subIn(r.helper); return *this; } 00453 00454 template <class EE> MatrixBase(const MatrixBase<EE>& b) 00455 : helper(MatrixCommitment(),b.helper, typename MatrixHelper<Scalar>::DeepCopy()) { } 00456 00457 template <class EE> MatrixBase& operator=(const MatrixBase<EE>& b) 00458 { helper = b.helper; return *this; } 00459 template <class EE> MatrixBase& operator+=(const MatrixBase<EE>& b) 00460 { helper.addIn(b.helper); return *this; } 00461 template <class EE> MatrixBase& operator-=(const MatrixBase<EE>& b) 00462 { helper.subIn(b.helper); return *this; } 00463 00474 MatrixBase& operator=(const ELT& t) { 00475 setToZero(); updDiag().setTo(t); 00476 return *this; 00477 } 00478 00484 template <class S> inline MatrixBase& 00485 scalarAssign(const S& s) { 00486 setToZero(); updDiag().setTo(s); 00487 return *this; 00488 } 00489 00493 template <class S> inline MatrixBase& 00494 scalarAddInPlace(const S& s) { 00495 updDiag().elementwiseAddScalarInPlace(s); 00496 } 00497 00498 00502 template <class S> inline MatrixBase& 00503 scalarSubtractInPlace(const S& s) { 00504 updDiag().elementwiseSubtractScalarInPlace(s); 00505 } 00506 00509 template <class S> inline MatrixBase& 00510 scalarSubtractFromLeftInPlace(const S& s) { 00511 negateInPlace(); 00512 updDiag().elementwiseAddScalarInPlace(s); // yes, add 00513 } 00514 00521 template <class S> inline MatrixBase& 00522 scalarMultiplyInPlace(const S&); 00523 00527 template <class S> inline MatrixBase& 00528 scalarMultiplyFromLeftInPlace(const S&); 00529 00536 template <class S> inline MatrixBase& 00537 scalarDivideInPlace(const S&); 00538 00542 template <class S> inline MatrixBase& 00543 scalarDivideFromLeftInPlace(const S&); 00544 00545 00548 template <class EE> inline MatrixBase& 00549 rowScaleInPlace(const VectorBase<EE>&); 00550 00553 template <class EE> inline void 00554 rowScale(const VectorBase<EE>& r, typename EltResult<EE>::Mul& out) const; 00555 00556 template <class EE> inline typename EltResult<EE>::Mul 00557 rowScale(const VectorBase<EE>& r) const { 00558 typename EltResult<EE>::Mul out(nrow(), ncol()); rowScale(r,out); return out; 00559 } 00560 00563 template <class EE> inline MatrixBase& 00564 colScaleInPlace(const VectorBase<EE>&); 00565 00566 template <class EE> inline void 00567 colScale(const VectorBase<EE>& c, typename EltResult<EE>::Mul& out) const; 00568 00569 template <class EE> inline typename EltResult<EE>::Mul 00570 colScale(const VectorBase<EE>& c) const { 00571 typename EltResult<EE>::Mul out(nrow(), ncol()); colScale(c,out); return out; 00572 } 00573 00574 00579 template <class ER, class EC> inline MatrixBase& 00580 rowAndColScaleInPlace(const VectorBase<ER>& r, const VectorBase<EC>& c); 00581 00582 template <class ER, class EC> inline void 00583 rowAndColScale(const VectorBase<ER>& r, const VectorBase<EC>& c, 00584 typename EltResult<typename VectorBase<ER>::template EltResult<EC>::Mul>::Mul& out) const; 00585 00586 template <class ER, class EC> inline typename EltResult<typename VectorBase<ER>::template EltResult<EC>::Mul>::Mul 00587 rowAndColScale(const VectorBase<ER>& r, const VectorBase<EC>& c) const { 00588 typename EltResult<typename VectorBase<ER>::template EltResult<EC>::Mul>::Mul 00589 out(nrow(), ncol()); 00590 rowAndColScale(r,c,out); return out; 00591 } 00592 00600 template <class S> inline MatrixBase& 00601 elementwiseAssign(const S& s); 00602 00604 MatrixBase& elementwiseInvertInPlace(); 00605 00606 void elementwiseInvert(MatrixBase<typename CNT<E>::TInvert>& out) const; 00607 00608 MatrixBase<typename CNT<E>::TInvert> elementwiseInvert() const { 00609 MatrixBase<typename CNT<E>::TInvert> out(nrow(), ncol()); 00610 elementwiseInvert(out); 00611 return out; 00612 } 00613 00621 template <class S> inline MatrixBase& 00622 elementwiseAddScalarInPlace(const S& s); 00623 00624 template <class S> inline void 00625 elementwiseAddScalar(const S& s, typename EltResult<S>::Add&) const; 00626 00627 template <class S> inline typename EltResult<S>::Add 00628 elementwiseAddScalar(const S& s) const { 00629 typename EltResult<S>::Add out(nrow(), ncol()); 00630 elementwiseAddScalar(s,out); 00631 return out; 00632 } 00633 00641 template <class S> inline MatrixBase& 00642 elementwiseSubtractScalarInPlace(const S& s); 00643 00644 template <class S> inline void 00645 elementwiseSubtractScalar(const S& s, typename EltResult<S>::Sub&) const; 00646 00647 template <class S> inline typename EltResult<S>::Sub 00648 elementwiseSubtractScalar(const S& s) const { 00649 typename EltResult<S>::Sub out(nrow(), ncol()); 00650 elementwiseSubtractScalar(s,out); 00651 return out; 00652 } 00653 00662 template <class S> inline MatrixBase& 00663 elementwiseSubtractFromScalarInPlace(const S& s); 00664 00665 template <class S> inline void 00666 elementwiseSubtractFromScalar( 00667 const S&, 00668 typename MatrixBase<S>::template EltResult<E>::Sub&) const; 00669 00670 template <class S> inline typename MatrixBase<S>::template EltResult<E>::Sub 00671 elementwiseSubtractFromScalar(const S& s) const { 00672 typename MatrixBase<S>::template EltResult<E>::Sub out(nrow(), ncol()); 00673 elementwiseSubtractFromScalar<S>(s,out); 00674 return out; 00675 } 00676 00678 template <class EE> inline MatrixBase& 00679 elementwiseMultiplyInPlace(const MatrixBase<EE>&); 00680 00681 template <class EE> inline void 00682 elementwiseMultiply(const MatrixBase<EE>&, typename EltResult<EE>::Mul&) const; 00683 00684 template <class EE> inline typename EltResult<EE>::Mul 00685 elementwiseMultiply(const MatrixBase<EE>& m) const { 00686 typename EltResult<EE>::Mul out(nrow(), ncol()); 00687 elementwiseMultiply<EE>(m,out); 00688 return out; 00689 } 00690 00692 template <class EE> inline MatrixBase& 00693 elementwiseMultiplyFromLeftInPlace(const MatrixBase<EE>&); 00694 00695 template <class EE> inline void 00696 elementwiseMultiplyFromLeft( 00697 const MatrixBase<EE>&, 00698 typename MatrixBase<EE>::template EltResult<E>::Mul&) const; 00699 00700 template <class EE> inline typename MatrixBase<EE>::template EltResult<E>::Mul 00701 elementwiseMultiplyFromLeft(const MatrixBase<EE>& m) const { 00702 typename EltResult<EE>::Mul out(nrow(), ncol()); 00703 elementwiseMultiplyFromLeft<EE>(m,out); 00704 return out; 00705 } 00706 00708 template <class EE> inline MatrixBase& 00709 elementwiseDivideInPlace(const MatrixBase<EE>&); 00710 00711 template <class EE> inline void 00712 elementwiseDivide(const MatrixBase<EE>&, typename EltResult<EE>::Dvd&) const; 00713 00714 template <class EE> inline typename EltResult<EE>::Dvd 00715 elementwiseDivide(const MatrixBase<EE>& m) const { 00716 typename EltResult<EE>::Dvd out(nrow(), ncol()); 00717 elementwiseDivide<EE>(m,out); 00718 return out; 00719 } 00720 00722 template <class EE> inline MatrixBase& 00723 elementwiseDivideFromLeftInPlace(const MatrixBase<EE>&); 00724 00725 template <class EE> inline void 00726 elementwiseDivideFromLeft( 00727 const MatrixBase<EE>&, 00728 typename MatrixBase<EE>::template EltResult<E>::Dvd&) const; 00729 00730 template <class EE> inline typename MatrixBase<EE>::template EltResult<EE>::Dvd 00731 elementwiseDivideFromLeft(const MatrixBase<EE>& m) const { 00732 typename MatrixBase<EE>::template EltResult<E>::Dvd out(nrow(), ncol()); 00733 elementwiseDivideFromLeft<EE>(m,out); 00734 return out; 00735 } 00736 00738 MatrixBase& setTo(const ELT& t) {helper.fillWith(reinterpret_cast<const Scalar*>(&t)); return *this;} 00739 MatrixBase& setToNaN() {helper.fillWithScalar(CNT<StdNumber>::getNaN()); return *this;} 00740 MatrixBase& setToZero() {helper.fillWithScalar(StdNumber(0)); return *this;} 00741 00742 // View creating operators. TODO: these should be DeadMatrixViews 00743 inline RowVectorView_<ELT> row(int i) const; // select a row 00744 inline RowVectorView_<ELT> updRow(int i); 00745 inline VectorView_<ELT> col(int j) const; // select a column 00746 inline VectorView_<ELT> updCol(int j); 00747 00748 RowVectorView_<ELT> operator[](int i) const {return row(i);} 00749 RowVectorView_<ELT> operator[](int i) {return updRow(i);} 00750 VectorView_<ELT> operator()(int j) const {return col(j);} 00751 VectorView_<ELT> operator()(int j) {return updCol(j);} 00752 00753 // Select a block. 00754 inline MatrixView_<ELT> block(int i, int j, int m, int n) const; 00755 inline MatrixView_<ELT> updBlock(int i, int j, int m, int n); 00756 00757 MatrixView_<ELT> operator()(int i, int j, int m, int n) const 00758 { return block(i,j,m,n); } 00759 MatrixView_<ELT> operator()(int i, int j, int m, int n) 00760 { return updBlock(i,j,m,n); } 00761 00762 // Hermitian transpose. 00763 inline MatrixView_<EHerm> transpose() const; 00764 inline MatrixView_<EHerm> updTranspose(); 00765 00766 MatrixView_<EHerm> operator~() const {return transpose();} 00767 MatrixView_<EHerm> operator~() {return updTranspose();} 00768 00769 // Select matrix diagonal (of largest leading square if rectangular). 00770 inline VectorView_<ELT> diag() const; 00771 inline VectorView_<ELT> updDiag(); 00772 00773 // Create a view of the real or imaginary elements. TODO 00774 //inline MatrixView_<EReal> real() const; 00775 //inline MatrixView_<EReal> updReal(); 00776 //inline MatrixView_<EImag> imag() const; 00777 //inline MatrixView_<EImag> updImag(); 00778 00779 // Overload "real" and "imag" for both read and write as a nod to convention. TODO 00780 //MatrixView_<EReal> real() {return updReal();} 00781 //MatrixView_<EReal> imag() {return updImag();} 00782 00783 // TODO: this routine seems ill-advised but I need it for the IVM port at the moment 00784 TInvert invert() const { // return a newly-allocated inverse; dump negator 00785 TInvert m(*this); 00786 m.helper.invertInPlace(); 00787 return m; // TODO - bad: makes an extra copy 00788 } 00789 00790 void invertInPlace() {helper.invertInPlace();} 00791 00793 void dump(const char* msg=0) const { 00794 helper.dump(msg); 00795 } 00796 00797 00798 // This routine is useful for implementing friendlier Matrix expressions and operators. 00799 // It maps closely to the Level-3 BLAS family of pxxmm() routines like sgemm(). The 00800 // operation performed assumes that "this" is the result, and that "this" has 00801 // already been sized correctly to receive the result. We'll compute 00802 // this = beta*this + alpha*A*B 00803 // If beta is 0 then "this" can be uninitialized. If alpha is 0 we promise not 00804 // to look at A or B. The routine can work efficiently even if A and/or B are transposed 00805 // by their views, so an expression like 00806 // C += s * ~A * ~B 00807 // can be performed with the single equivalent call 00808 // C.matmul(1., s, Tr(A), Tr(B)) 00809 // where Tr(A) indicates a transposed view of the original A. 00810 // The ultimate efficiency of this call depends on the data layout and views which 00811 // are used for the three matrices. 00812 // NOTE: neither A nor B can be the same matrix as 'this', nor views of the same data 00813 // which would expose elements of 'this' that will be modified by this operation. 00814 template <class ELT_A, class ELT_B> 00815 MatrixBase& matmul(const StdNumber& beta, // applied to 'this' 00816 const StdNumber& alpha, const MatrixBase<ELT_A>& A, const MatrixBase<ELT_B>& B) 00817 { 00818 helper.matmul(beta,alpha,A.helper,B.helper); 00819 return *this; 00820 } 00821 00830 const ELT& getElt(int i, int j) const { return *reinterpret_cast<const ELT*>(helper.getElt(i,j)); } 00831 ELT& updElt(int i, int j) { return *reinterpret_cast< ELT*>(helper.updElt(i,j)); } 00832 00833 const ELT& operator()(int i, int j) const {return getElt(i,j);} 00834 ELT& operator()(int i, int j) {return updElt(i,j);} 00835 00840 void getAnyElt(int i, int j, ELT& value) const 00841 { helper.getAnyElt(i,j,reinterpret_cast<Scalar*>(&value)); } 00842 ELT getAnyElt(int i, int j) const {ELT e; getAnyElt(i,j,e); return e;} 00843 00846 // TODO: very slow! Should be optimized at least for the case 00847 // where ELT is a Scalar. 00848 ScalarNormSq scalarNormSqr() const { 00849 const int nr=nrow(), nc=ncol(); 00850 ScalarNormSq sum(0); 00851 for(int j=0;j<nc;++j) 00852 for (int i=0; i<nr; ++i) 00853 sum += CNT<E>::scalarNormSqr((*this)(i,j)); 00854 return sum; 00855 } 00856 00860 // TODO: very slow! Should be optimized at least for the case 00861 // where ELT is a Scalar. 00862 void abs(TAbs& mabs) const { 00863 const int nr=nrow(), nc=ncol(); 00864 mabs.resize(nr,nc); 00865 for(int j=0;j<nc;++j) 00866 for (int i=0; i<nr; ++i) 00867 mabs(i,j) = CNT<E>::abs((*this)(i,j)); 00868 } 00869 00872 TAbs abs() const { TAbs mabs; abs(mabs); return mabs; } 00873 00884 TStandard standardize() const { 00885 const int nr=nrow(), nc=ncol(); 00886 TStandard mstd(nr, nc); 00887 for(int j=0;j<nc;++j) 00888 for (int i=0; i<nr; ++i) 00889 mstd(i,j) = CNT<E>::standardize((*this)(i,j)); 00890 return mstd; 00891 } 00892 00895 ScalarNormSq normSqr() const { return scalarNormSqr(); } 00896 // TODO -- not good; unnecessary overflow 00897 typename CNT<ScalarNormSq>::TSqrt 00898 norm() const { return CNT<ScalarNormSq>::sqrt(scalarNormSqr()); } 00899 00902 typename CNT<ScalarNormSq>::TSqrt 00903 normRMS() const { 00904 if (!CNT<ELT>::IsScalar) 00905 SimTK_THROW1(Exception::Cant, "normRMS() only defined for scalar elements"); 00906 if (nelt() == 0) 00907 return typename CNT<ScalarNormSq>::TSqrt(0); 00908 return CNT<ScalarNormSq>::sqrt(scalarNormSqr()/nelt()); 00909 } 00910 00912 RowVectorBase<ELT> sum() const { 00913 const int cols = ncol(); 00914 RowVectorBase<ELT> row(cols); 00915 for (int i = 0; i < cols; ++i) 00916 helper.colSum(i, reinterpret_cast<Scalar*>(&row[i])); 00917 return row; 00918 } 00919 00920 //TODO: make unary +/- return a self-view so they won't reallocate? 00921 const MatrixBase& operator+() const {return *this; } 00922 const TNeg& negate() const {return *reinterpret_cast<const TNeg*>(this); } 00923 TNeg& updNegate() {return *reinterpret_cast<TNeg*>(this); } 00924 00925 const TNeg& operator-() const {return negate();} 00926 TNeg& operator-() {return updNegate();} 00927 00928 MatrixBase& negateInPlace() {(*this) *= EPrecision(-1); return *this;} 00929 00934 MatrixBase& resize(int m, int n) { helper.resize(m,n); return *this; } 00940 MatrixBase& resizeKeep(int m, int n) { helper.resizeKeep(m,n); return *this; } 00941 00942 // This prevents shape changes in a Matrix that would otherwise allow it. No harm if is 00943 // are called on a Matrix that is locked already; it always succeeds. 00944 void lockShape() {helper.lockShape();} 00945 00946 // This allows shape changes again for a Matrix which was constructed to allow them 00947 // but had them locked with the above routine. No harm if this is called on a Matrix 00948 // that is already unlocked, but it is not allowed to call this on a Matrix which 00949 // *never* allowed resizing. An exception will be thrown in that case. 00950 void unlockShape() {helper.unlockShape();} 00951 00952 // An assortment of handy conversions 00953 const MatrixView_<ELT>& getAsMatrixView() const { return *reinterpret_cast<const MatrixView_<ELT>*>(this); } 00954 MatrixView_<ELT>& updAsMatrixView() { return *reinterpret_cast< MatrixView_<ELT>*>(this); } 00955 const Matrix_<ELT>& getAsMatrix() const { return *reinterpret_cast<const Matrix_<ELT>*>(this); } 00956 Matrix_<ELT>& updAsMatrix() { return *reinterpret_cast< Matrix_<ELT>*>(this); } 00957 00958 const VectorView_<ELT>& getAsVectorView() const 00959 { assert(ncol()==1); return *reinterpret_cast<const VectorView_<ELT>*>(this); } 00960 VectorView_<ELT>& updAsVectorView() 00961 { assert(ncol()==1); return *reinterpret_cast< VectorView_<ELT>*>(this); } 00962 const Vector_<ELT>& getAsVector() const 00963 { assert(ncol()==1); return *reinterpret_cast<const Vector_<ELT>*>(this); } 00964 Vector_<ELT>& updAsVector() 00965 { assert(ncol()==1); return *reinterpret_cast< Vector_<ELT>*>(this); } 00966 const VectorBase<ELT>& getAsVectorBase() const 00967 { assert(ncol()==1); return *reinterpret_cast<const VectorBase<ELT>*>(this); } 00968 VectorBase<ELT>& updAsVectorBase() 00969 { assert(ncol()==1); return *reinterpret_cast< VectorBase<ELT>*>(this); } 00970 00971 const RowVectorView_<ELT>& getAsRowVectorView() const 00972 { assert(nrow()==1); return *reinterpret_cast<const RowVectorView_<ELT>*>(this); } 00973 RowVectorView_<ELT>& updAsRowVectorView() 00974 { assert(nrow()==1); return *reinterpret_cast< RowVectorView_<ELT>*>(this); } 00975 const RowVector_<ELT>& getAsRowVector() const 00976 { assert(nrow()==1); return *reinterpret_cast<const RowVector_<ELT>*>(this); } 00977 RowVector_<ELT>& updAsRowVector() 00978 { assert(nrow()==1); return *reinterpret_cast< RowVector_<ELT>*>(this); } 00979 const RowVectorBase<ELT>& getAsRowVectorBase() const 00980 { assert(nrow()==1); return *reinterpret_cast<const RowVectorBase<ELT>*>(this); } 00981 RowVectorBase<ELT>& updAsRowVectorBase() 00982 { assert(nrow()==1); return *reinterpret_cast< RowVectorBase<ELT>*>(this); } 00983 00984 // Access to raw data. We have to return the raw data 00985 // pointer as pointer-to-scalar because we may pack the elements tighter 00986 // than a C++ array would. 00987 00991 int getNScalarsPerElement() const {return NScalarsPerElement;} 00992 00996 int getPackedSizeofElement() const {return NScalarsPerElement*sizeof(Scalar);} 00997 00998 bool hasContiguousData() const {return helper.hasContiguousData();} 00999 ptrdiff_t getContiguousScalarDataLength() const { 01000 return helper.getContiguousDataLength(); 01001 } 01002 const Scalar* getContiguousScalarData() const { 01003 return helper.getContiguousData(); 01004 } 01005 Scalar* updContiguousScalarData() { 01006 return helper.updContiguousData(); 01007 } 01008 void replaceContiguousScalarData(Scalar* newData, ptrdiff_t length, bool takeOwnership) { 01009 helper.replaceContiguousData(newData,length,takeOwnership); 01010 } 01011 void replaceContiguousScalarData(const Scalar* newData, ptrdiff_t length) { 01012 helper.replaceContiguousData(newData,length); 01013 } 01014 void swapOwnedContiguousScalarData(Scalar* newData, ptrdiff_t length, Scalar*& oldData) { 01015 helper.swapOwnedContiguousData(newData,length,oldData); 01016 } 01017 01022 explicit MatrixBase(MatrixHelperRep<Scalar>* hrep) : helper(hrep) {} 01023 01024 protected: 01025 const MatrixHelper<Scalar>& getHelper() const {return helper;} 01026 MatrixHelper<Scalar>& updHelper() {return helper;} 01027 01028 private: 01029 MatrixHelper<Scalar> helper; // this is just one pointer 01030 01031 template <class EE> friend class MatrixBase; 01032 }; 01033 01034 01035 01036 // -------------------------------- VectorBase -------------------------------- 01040 // ---------------------------------------------------------------------------- 01041 template <class ELT> class VectorBase : public MatrixBase<ELT> { 01042 typedef MatrixBase<ELT> Base; 01043 typedef typename CNT<ELT>::Scalar Scalar; 01044 typedef typename CNT<ELT>::Number Number; 01045 typedef typename CNT<ELT>::StdNumber StdNumber; 01046 typedef VectorBase<ELT> T; 01047 typedef VectorBase<typename CNT<ELT>::TAbs> TAbs; 01048 typedef VectorBase<typename CNT<ELT>::TNeg> TNeg; 01049 typedef RowVectorView_<typename CNT<ELT>::THerm> THerm; 01050 public: 01051 // ------------------------------------------------------------------------ 01061 01064 explicit VectorBase(int m=0) : Base(MatrixCommitment::Vector(), m, 1) {} 01065 01069 VectorBase(const VectorBase& source) : Base(source) {} 01070 01072 VectorBase(const TNeg& source) : Base(source) {} 01073 01076 VectorBase(int m, const ELT& initialValue) 01077 : Base(MatrixCommitment::Vector(),m,1,initialValue) {} 01078 01083 VectorBase(int m, const ELT* cppInitialValues) 01084 : Base(MatrixCommitment::Vector(),m,1,cppInitialValues) {} 01086 01087 // ------------------------------------------------------------------------ 01096 01098 VectorBase(int m, int stride, const Scalar* s) 01099 : Base(MatrixCommitment::Vector(m), MatrixCharacter::Vector(m),stride,s) { } 01101 VectorBase(int m, int stride, Scalar* s) 01102 : Base(MatrixCommitment::Vector(m), MatrixCharacter::Vector(m),stride,s) { } 01104 01105 // ------------------------------------------------------------------------ 01112 01114 VectorBase(MatrixHelper<Scalar>& h, const typename MatrixHelper<Scalar>::ShallowCopy& s) 01115 : Base(MatrixCommitment::Vector(), h,s) { } 01117 VectorBase(const MatrixHelper<Scalar>& h, const typename MatrixHelper<Scalar>::ShallowCopy& s) 01118 : Base(MatrixCommitment::Vector(), h,s) { } 01120 VectorBase(const MatrixHelper<Scalar>& h, const typename MatrixHelper<Scalar>::DeepCopy& d) 01121 : Base(MatrixCommitment::Vector(), h,d) { } 01123 01124 // This gives the resulting vector type when (v[i] op P) is applied to each element. 01125 // It will have element types which are the regular composite result of ELT op P. 01126 template <class P> struct EltResult { 01127 typedef VectorBase<typename CNT<ELT>::template Result<P>::Mul> Mul; 01128 typedef VectorBase<typename CNT<ELT>::template Result<P>::Dvd> Dvd; 01129 typedef VectorBase<typename CNT<ELT>::template Result<P>::Add> Add; 01130 typedef VectorBase<typename CNT<ELT>::template Result<P>::Sub> Sub; 01131 }; 01132 01135 VectorBase& operator=(const VectorBase& b) { 01136 Base::operator=(b); return *this; 01137 } 01138 01139 // default destructor 01140 01141 01142 VectorBase& operator*=(const StdNumber& t) { Base::operator*=(t); return *this; } 01143 VectorBase& operator/=(const StdNumber& t) { Base::operator/=(t); return *this; } 01144 VectorBase& operator+=(const VectorBase& r) { Base::operator+=(r); return *this; } 01145 VectorBase& operator-=(const VectorBase& r) { Base::operator-=(r); return *this; } 01146 01147 01148 template <class EE> VectorBase& operator=(const VectorBase<EE>& b) 01149 { Base::operator=(b); return *this; } 01150 template <class EE> VectorBase& operator+=(const VectorBase<EE>& b) 01151 { Base::operator+=(b); return *this; } 01152 template <class EE> VectorBase& operator-=(const VectorBase<EE>& b) 01153 { Base::operator-=(b); return *this; } 01154 01155 01159 VectorBase& operator=(const ELT& t) { Base::setTo(t); return *this; } 01160 01165 template <class EE> VectorBase& rowScaleInPlace(const VectorBase<EE>& v) 01166 { Base::template rowScaleInPlace<EE>(v); return *this; } 01167 template <class EE> inline void rowScale(const VectorBase<EE>& v, typename EltResult<EE>::Mul& out) const 01168 { Base::rowScale(v,out); } 01169 template <class EE> inline typename EltResult<EE>::Mul rowScale(const VectorBase<EE>& v) const 01170 { typename EltResult<EE>::Mul out(nrow()); Base::rowScale(v,out); return out; } 01171 01173 VectorBase& elementwiseInvertInPlace() { 01174 Base::elementwiseInvertInPlace(); 01175 return *this; 01176 } 01177 01179 void elementwiseInvert(VectorBase<typename CNT<ELT>::TInvert>& out) const { 01180 Base::elementwiseInvert(out); 01181 } 01182 01184 VectorBase<typename CNT<ELT>::TInvert> elementwiseInvert() const { 01185 VectorBase<typename CNT<ELT>::TInvert> out(nrow()); 01186 Base::elementwiseInvert(out); 01187 return out; 01188 } 01189 01190 // elementwise multiply 01191 template <class EE> VectorBase& elementwiseMultiplyInPlace(const VectorBase<EE>& r) 01192 { Base::template elementwiseMultiplyInPlace<EE>(r); return *this; } 01193 template <class EE> inline void elementwiseMultiply(const VectorBase<EE>& v, typename EltResult<EE>::Mul& out) const 01194 { Base::template elementwiseMultiply<EE>(v,out); } 01195 template <class EE> inline typename EltResult<EE>::Mul elementwiseMultiply(const VectorBase<EE>& v) const 01196 { typename EltResult<EE>::Mul out(nrow()); Base::template elementwiseMultiply<EE>(v,out); return out; } 01197 01198 // elementwise multiply from left 01199 template <class EE> VectorBase& elementwiseMultiplyFromLeftInPlace(const VectorBase<EE>& r) 01200 { Base::template elementwiseMultiplyFromLeftInPlace<EE>(r); return *this; } 01201 template <class EE> inline void 01202 elementwiseMultiplyFromLeft( 01203 const VectorBase<EE>& v, 01204 typename VectorBase<EE>::template EltResult<ELT>::Mul& out) const 01205 { 01206 Base::template elementwiseMultiplyFromLeft<EE>(v,out); 01207 } 01208 template <class EE> inline typename VectorBase<EE>::template EltResult<ELT>::Mul 01209 elementwiseMultiplyFromLeft(const VectorBase<EE>& v) const 01210 { 01211 typename VectorBase<EE>::template EltResult<ELT>::Mul out(nrow()); 01212 Base::template elementwiseMultiplyFromLeft<EE>(v,out); 01213 return out; 01214 } 01215 01216 // elementwise divide 01217 template <class EE> VectorBase& elementwiseDivideInPlace(const VectorBase<EE>& r) 01218 { Base::template elementwiseDivideInPlace<EE>(r); return *this; } 01219 template <class EE> inline void elementwiseDivide(const VectorBase<EE>& v, typename EltResult<EE>::Dvd& out) const 01220 { Base::template elementwiseDivide<EE>(v,out); } 01221 template <class EE> inline typename EltResult<EE>::Dvd elementwiseDivide(const VectorBase<EE>& v) const 01222 { typename EltResult<EE>::Dvd out(nrow()); Base::template elementwiseDivide<EE>(v,out); return out; } 01223 01224 // elementwise divide from left 01225 template <class EE> VectorBase& elementwiseDivideFromLeftInPlace(const VectorBase<EE>& r) 01226 { Base::template elementwiseDivideFromLeftInPlace<EE>(r); return *this; } 01227 template <class EE> inline void 01228 elementwiseDivideFromLeft( 01229 const VectorBase<EE>& v, 01230 typename VectorBase<EE>::template EltResult<ELT>::Dvd& out) const 01231 { 01232 Base::template elementwiseDivideFromLeft<EE>(v,out); 01233 } 01234 template <class EE> inline typename VectorBase<EE>::template EltResult<ELT>::Dvd 01235 elementwiseDivideFromLeft(const VectorBase<EE>& v) const 01236 { 01237 typename VectorBase<EE>::template EltResult<ELT>::Dvd out(nrow()); 01238 Base::template elementwiseDivideFromLeft<EE>(v,out); 01239 return out; 01240 } 01241 01242 // Implicit conversions are allowed to Vector or Matrix, but not to RowVector. 01243 operator const Vector_<ELT>&() const { return *reinterpret_cast<const Vector_<ELT>*>(this); } 01244 operator Vector_<ELT>&() { return *reinterpret_cast< Vector_<ELT>*>(this); } 01245 operator const VectorView_<ELT>&() const { return *reinterpret_cast<const VectorView_<ELT>*>(this); } 01246 operator VectorView_<ELT>&() { return *reinterpret_cast< VectorView_<ELT>*>(this); } 01247 01248 operator const Matrix_<ELT>&() const { return *reinterpret_cast<const Matrix_<ELT>*>(this); } 01249 operator Matrix_<ELT>&() { return *reinterpret_cast< Matrix_<ELT>*>(this); } 01250 operator const MatrixView_<ELT>&() const { return *reinterpret_cast<const MatrixView_<ELT>*>(this); } 01251 operator MatrixView_<ELT>&() { return *reinterpret_cast< MatrixView_<ELT>*>(this); } 01252 01253 01254 // size() for Vectors is Base::nelt() but returns int instead of ptrdiff_t. 01255 int size() const { 01256 assert(Base::nelt() <= (ptrdiff_t)std::numeric_limits<int>::max()); 01257 assert(Base::ncol()==1); 01258 return (int)Base::nelt(); 01259 } 01260 int nrow() const {assert(Base::ncol()==1); return Base::nrow();} 01261 int ncol() const {assert(Base::ncol()==1); return Base::ncol();} 01262 ptrdiff_t nelt() const {assert(Base::ncol()==1); return Base::nelt();} 01263 01264 // Override MatrixBase operators to return the right shape 01265 TAbs abs() const {TAbs result; Base::abs(result); return result;} 01266 01267 // Override MatrixBase indexing operators 01268 const ELT& operator[](int i) const {return *reinterpret_cast<const ELT*>(Base::getHelper().getElt(i));} 01269 ELT& operator[](int i) {return *reinterpret_cast<ELT*> (Base::updHelper().updElt(i));} 01270 const ELT& operator()(int i) const {return *reinterpret_cast<const ELT*>(Base::getHelper().getElt(i));} 01271 ELT& operator()(int i) {return *reinterpret_cast<ELT*> (Base::updHelper().updElt(i));} 01272 01273 // Block (contiguous subvector) view creation 01274 VectorView_<ELT> operator()(int i, int m) const {return Base::operator()(i,0,m,1).getAsVectorView();} 01275 VectorView_<ELT> operator()(int i, int m) {return Base::operator()(i,0,m,1).updAsVectorView();} 01276 01277 // Indexed view creation (arbitrary subvector). Indices must be monotonically increasing. 01278 VectorView_<ELT> index(const Array_<int>& indices) const { 01279 MatrixHelper<Scalar> h(Base::getHelper().getCharacterCommitment(), Base::getHelper(), indices); 01280 return VectorView_<ELT>(h); 01281 } 01282 VectorView_<ELT> updIndex(const Array_<int>& indices) { 01283 MatrixHelper<Scalar> h(Base::getHelper().getCharacterCommitment(), Base::updHelper(), indices); 01284 return VectorView_<ELT>(h); 01285 } 01286 01287 VectorView_<ELT> operator()(const Array_<int>& indices) const {return index(indices);} 01288 VectorView_<ELT> operator()(const Array_<int>& indices) {return updIndex(indices);} 01289 01290 // Hermitian transpose. 01291 THerm transpose() const {return Base::transpose().getAsRowVectorView();} 01292 THerm updTranspose() {return Base::updTranspose().updAsRowVectorView();} 01293 01294 THerm operator~() const {return transpose();} 01295 THerm operator~() {return updTranspose();} 01296 01297 const VectorBase& operator+() const {return *this; } 01298 01299 // Negation 01300 01301 const TNeg& negate() const {return *reinterpret_cast<const TNeg*>(this); } 01302 TNeg& updNegate() {return *reinterpret_cast<TNeg*>(this); } 01303 01304 const TNeg& operator-() const {return negate();} 01305 TNeg& operator-() {return updNegate();} 01306 01307 VectorBase& resize(int m) {Base::resize(m,1); return *this;} 01308 VectorBase& resizeKeep(int m) {Base::resizeKeep(m,1); return *this;} 01309 01310 //TODO: this is not re-locking the number of columns at 1. 01311 void clear() {Base::clear(); Base::resize(0,1);} 01312 01313 ELT sum() const {ELT s; Base::getHelper().sum(reinterpret_cast<Scalar*>(&s)); return s; } // add all the elements 01314 VectorIterator<ELT, VectorBase<ELT> > begin() { 01315 return VectorIterator<ELT, VectorBase<ELT> >(*this, 0); 01316 } 01317 VectorIterator<ELT, VectorBase<ELT> > end() { 01318 return VectorIterator<ELT, VectorBase<ELT> >(*this, size()); 01319 } 01320 01321 protected: 01322 // Create a VectorBase handle using a given helper rep. 01323 explicit VectorBase(MatrixHelperRep<Scalar>* hrep) : Base(hrep) {} 01324 01325 private: 01326 // NO DATA MEMBERS ALLOWED 01327 }; 01328 01329 01330 01331 // ------------------------------- RowVectorBase ------------------------------ 01335 // ---------------------------------------------------------------------------- 01336 template <class ELT> class RowVectorBase : public MatrixBase<ELT> { 01337 typedef MatrixBase<ELT> Base; 01338 typedef typename CNT<ELT>::Scalar Scalar; 01339 typedef typename CNT<ELT>::Number Number; 01340 typedef typename CNT<ELT>::StdNumber StdNumber; 01341 typedef RowVectorBase<ELT> T; 01342 typedef RowVectorBase<typename CNT<ELT>::TAbs> TAbs; 01343 typedef RowVectorBase<typename CNT<ELT>::TNeg> TNeg; 01344 typedef VectorView_<typename CNT<ELT>::THerm> THerm; 01345 public: 01346 // ------------------------------------------------------------------------ 01356 01359 explicit RowVectorBase(int n=0) : Base(MatrixCommitment::RowVector(), 1, n) {} 01360 01364 RowVectorBase(const RowVectorBase& source) : Base(source) {} 01365 01367 RowVectorBase(const TNeg& source) : Base(source) {} 01368 01371 RowVectorBase(int n, const ELT& initialValue) 01372 : Base(MatrixCommitment::RowVector(),1,n,initialValue) {} 01373 01378 RowVectorBase(int n, const ELT* cppInitialValues) 01379 : Base(MatrixCommitment::RowVector(),1,n,cppInitialValues) {} 01381 01382 // ------------------------------------------------------------------------ 01391 01393 RowVectorBase(int n, int stride, const Scalar* s) 01394 : Base(MatrixCommitment::RowVector(n), MatrixCharacter::RowVector(n),stride,s) { } 01396 RowVectorBase(int n, int stride, Scalar* s) 01397 : Base(MatrixCommitment::RowVector(n), MatrixCharacter::RowVector(n),stride,s) { } 01399 01400 // ------------------------------------------------------------------------ 01407 01409 RowVectorBase(MatrixHelper<Scalar>& h, const typename MatrixHelper<Scalar>::ShallowCopy& s) 01410 : Base(MatrixCommitment::RowVector(), h,s) { } 01412 RowVectorBase(const MatrixHelper<Scalar>& h, const typename MatrixHelper<Scalar>::ShallowCopy& s) 01413 : Base(MatrixCommitment::RowVector(), h,s) { } 01415 RowVectorBase(const MatrixHelper<Scalar>& h, const typename MatrixHelper<Scalar>::DeepCopy& d) 01416 : Base(MatrixCommitment::RowVector(), h,d) { } 01418 01419 // This gives the resulting rowvector type when (r(i) op P) is applied to each element. 01420 // It will have element types which are the regular composite result of ELT op P. 01421 template <class P> struct EltResult { 01422 typedef RowVectorBase<typename CNT<ELT>::template Result<P>::Mul> Mul; 01423 typedef RowVectorBase<typename CNT<ELT>::template Result<P>::Dvd> Dvd; 01424 typedef RowVectorBase<typename CNT<ELT>::template Result<P>::Add> Add; 01425 typedef RowVectorBase<typename CNT<ELT>::template Result<P>::Sub> Sub; 01426 }; 01427 01430 RowVectorBase& operator=(const RowVectorBase& b) { 01431 Base::operator=(b); return *this; 01432 } 01433 01434 // default destructor 01435 01436 RowVectorBase& operator*=(const StdNumber& t) {Base::operator*=(t); return *this;} 01437 RowVectorBase& operator/=(const StdNumber& t) {Base::operator/=(t); return *this;} 01438 RowVectorBase& operator+=(const RowVectorBase& r) {Base::operator+=(r); return *this;} 01439 RowVectorBase& operator-=(const RowVectorBase& r) {Base::operator-=(r); return *this;} 01440 01441 template <class EE> RowVectorBase& operator=(const RowVectorBase<EE>& b) 01442 { Base::operator=(b); return *this; } 01443 template <class EE> RowVectorBase& operator+=(const RowVectorBase<EE>& b) 01444 { Base::operator+=(b); return *this; } 01445 template <class EE> RowVectorBase& operator-=(const RowVectorBase<EE>& b) 01446 { Base::operator-=(b); return *this; } 01447 01448 // default destructor 01449 01453 RowVectorBase& operator=(const ELT& t) { Base::setTo(t); return *this; } 01454 01459 template <class EE> RowVectorBase& colScaleInPlace(const VectorBase<EE>& v) 01460 { Base::template colScaleInPlace<EE>(v); return *this; } 01461 template <class EE> inline void colScale(const VectorBase<EE>& v, typename EltResult<EE>::Mul& out) const 01462 { return Base::template colScale<EE>(v,out); } 01463 template <class EE> inline typename EltResult<EE>::Mul colScale(const VectorBase<EE>& v) const 01464 { typename EltResult<EE>::Mul out(ncol()); Base::template colScale<EE>(v,out); return out; } 01465 01466 01467 // elementwise multiply 01468 template <class EE> RowVectorBase& elementwiseMultiplyInPlace(const RowVectorBase<EE>& r) 01469 { Base::template elementwiseMultiplyInPlace<EE>(r); return *this; } 01470 template <class EE> inline void elementwiseMultiply(const RowVectorBase<EE>& v, typename EltResult<EE>::Mul& out) const 01471 { Base::template elementwiseMultiply<EE>(v,out); } 01472 template <class EE> inline typename EltResult<EE>::Mul elementwiseMultiply(const RowVectorBase<EE>& v) const 01473 { typename EltResult<EE>::Mul out(nrow()); Base::template elementwiseMultiply<EE>(v,out); return out; } 01474 01475 // elementwise multiply from left 01476 template <class EE> RowVectorBase& elementwiseMultiplyFromLeftInPlace(const RowVectorBase<EE>& r) 01477 { Base::template elementwiseMultiplyFromLeftInPlace<EE>(r); return *this; } 01478 template <class EE> inline void 01479 elementwiseMultiplyFromLeft( 01480 const RowVectorBase<EE>& v, 01481 typename RowVectorBase<EE>::template EltResult<ELT>::Mul& out) const 01482 { 01483 Base::template elementwiseMultiplyFromLeft<EE>(v,out); 01484 } 01485 template <class EE> inline typename RowVectorBase<EE>::template EltResult<ELT>::Mul 01486 elementwiseMultiplyFromLeft(const RowVectorBase<EE>& v) const 01487 { 01488 typename RowVectorBase<EE>::template EltResult<ELT>::Mul out(nrow()); 01489 Base::template elementwiseMultiplyFromLeft<EE>(v,out); 01490 return out; 01491 } 01492 01493 // elementwise divide 01494 template <class EE> RowVectorBase& elementwiseDivideInPlace(const RowVectorBase<EE>& r) 01495 { Base::template elementwiseDivideInPlace<EE>(r); return *this; } 01496 template <class EE> inline void elementwiseDivide(const RowVectorBase<EE>& v, typename EltResult<EE>::Dvd& out) const 01497 { Base::template elementwiseDivide<EE>(v,out); } 01498 template <class EE> inline typename EltResult<EE>::Dvd elementwiseDivide(const RowVectorBase<EE>& v) const 01499 { typename EltResult<EE>::Dvd out(nrow()); Base::template elementwiseDivide<EE>(v,out); return out; } 01500 01501 // elementwise divide from left 01502 template <class EE> RowVectorBase& elementwiseDivideFromLeftInPlace(const RowVectorBase<EE>& r) 01503 { Base::template elementwiseDivideFromLeftInPlace<EE>(r); return *this; } 01504 template <class EE> inline void 01505 elementwiseDivideFromLeft( 01506 const RowVectorBase<EE>& v, 01507 typename RowVectorBase<EE>::template EltResult<ELT>::Dvd& out) const 01508 { 01509 Base::template elementwiseDivideFromLeft<EE>(v,out); 01510 } 01511 template <class EE> inline typename RowVectorBase<EE>::template EltResult<ELT>::Dvd 01512 elementwiseDivideFromLeft(const RowVectorBase<EE>& v) const 01513 { 01514 typename RowVectorBase<EE>::template EltResult<ELT>::Dvd out(nrow()); 01515 Base::template elementwiseDivideFromLeft<EE>(v,out); 01516 return out; 01517 } 01518 01519 // Implicit conversions are allowed to RowVector or Matrix, but not to Vector. 01520 operator const RowVector_<ELT>&() const {return *reinterpret_cast<const RowVector_<ELT>*>(this);} 01521 operator RowVector_<ELT>&() {return *reinterpret_cast< RowVector_<ELT>*>(this);} 01522 operator const RowVectorView_<ELT>&() const {return *reinterpret_cast<const RowVectorView_<ELT>*>(this);} 01523 operator RowVectorView_<ELT>&() {return *reinterpret_cast< RowVectorView_<ELT>*>(this);} 01524 01525 operator const Matrix_<ELT>&() const {return *reinterpret_cast<const Matrix_<ELT>*>(this);} 01526 operator Matrix_<ELT>&() {return *reinterpret_cast< Matrix_<ELT>*>(this);} 01527 operator const MatrixView_<ELT>&() const {return *reinterpret_cast<const MatrixView_<ELT>*>(this);} 01528 operator MatrixView_<ELT>&() {return *reinterpret_cast< MatrixView_<ELT>*>(this);} 01529 01530 01531 // size() for RowVectors is Base::nelt() but returns int instead of ptrdiff_t. 01532 int size() const { 01533 assert(Base::nelt() <= (ptrdiff_t)std::numeric_limits<int>::max()); 01534 assert(Base::nrow()==1); 01535 return (int)Base::nelt(); 01536 } 01537 int nrow() const {assert(Base::nrow()==1); return Base::nrow();} 01538 int ncol() const {assert(Base::nrow()==1); return Base::ncol();} 01539 ptrdiff_t nelt() const {assert(Base::nrow()==1); return Base::nelt();} 01540 01541 // Override MatrixBase operators to return the right shape 01542 TAbs abs() const { 01543 TAbs result; Base::abs(result); return result; 01544 } 01545 01546 // Override MatrixBase indexing operators 01547 const ELT& operator[](int j) const {return *reinterpret_cast<const ELT*>(Base::getHelper().getElt(j));} 01548 ELT& operator[](int j) {return *reinterpret_cast<ELT*> (Base::updHelper().updElt(j));} 01549 const ELT& operator()(int j) const {return *reinterpret_cast<const ELT*>(Base::getHelper().getElt(j));} 01550 ELT& operator()(int j) {return *reinterpret_cast<ELT*> (Base::updHelper().updElt(j));} 01551 01552 // Block (contiguous subvector) creation 01553 RowVectorView_<ELT> operator()(int j, int n) const {return Base::operator()(0,j,1,n).getAsRowVectorView();} 01554 RowVectorView_<ELT> operator()(int j, int n) {return Base::operator()(0,j,1,n).updAsRowVectorView();} 01555 01556 // Indexed view creation (arbitrary subvector). Indices must be monotonically increasing. 01557 RowVectorView_<ELT> index(const Array_<int>& indices) const { 01558 MatrixHelper<Scalar> h(Base::getHelper().getCharacterCommitment(), Base::getHelper(), indices); 01559 return RowVectorView_<ELT>(h); 01560 } 01561 RowVectorView_<ELT> updIndex(const Array_<int>& indices) { 01562 MatrixHelper<Scalar> h(Base::getHelper().getCharacterCommitment(), Base::updHelper(), indices); 01563 return RowVectorView_<ELT>(h); 01564 } 01565 01566 RowVectorView_<ELT> operator()(const Array_<int>& indices) const {return index(indices);} 01567 RowVectorView_<ELT> operator()(const Array_<int>& indices) {return updIndex(indices);} 01568 01569 // Hermitian transpose. 01570 THerm transpose() const {return Base::transpose().getAsVectorView();} 01571 THerm updTranspose() {return Base::updTranspose().updAsVectorView();} 01572 01573 THerm operator~() const {return transpose();} 01574 THerm operator~() {return updTranspose();} 01575 01576 const RowVectorBase& operator+() const {return *this; } 01577 01578 // Negation 01579 01580 const TNeg& negate() const {return *reinterpret_cast<const TNeg*>(this); } 01581 TNeg& updNegate() {return *reinterpret_cast<TNeg*>(this); } 01582 01583 const TNeg& operator-() const {return negate();} 01584 TNeg& operator-() {return updNegate();} 01585 01586 RowVectorBase& resize(int n) {Base::resize(1,n); return *this;} 01587 RowVectorBase& resizeKeep(int n) {Base::resizeKeep(1,n); return *this;} 01588 01589 //TODO: this is not re-locking the number of rows at 1. 01590 void clear() {Base::clear(); Base::resize(1,0);} 01591 01592 ELT sum() const {ELT s; Base::getHelper().sum(reinterpret_cast<Scalar*>(&s)); return s; } // add all the elements 01593 VectorIterator<ELT, RowVectorBase<ELT> > begin() { 01594 return VectorIterator<ELT, RowVectorBase<ELT> >(*this, 0); 01595 } 01596 VectorIterator<ELT, RowVectorBase<ELT> > end() { 01597 return VectorIterator<ELT, RowVectorBase<ELT> >(*this, size()); 01598 } 01599 01600 protected: 01601 // Create a RowVectorBase handle using a given helper rep. 01602 explicit RowVectorBase(MatrixHelperRep<Scalar>* hrep) : Base(hrep) {} 01603 01604 private: 01605 // NO DATA MEMBERS ALLOWED 01606 }; 01607 01608 01609 01610 // ------------------------------- MatrixView_ -------------------------------- 01616 // ---------------------------------------------------------------------------- 01617 template <class ELT> class MatrixView_ : public MatrixBase<ELT> { 01618 typedef MatrixBase<ELT> Base; 01619 typedef typename CNT<ELT>::Scalar S; 01620 typedef typename CNT<ELT>::StdNumber StdNumber; 01621 public: 01622 // Default construction is suppressed. 01623 // Uses default destructor. 01624 01625 // Create a MatrixView_ handle using a given helper rep. 01626 explicit MatrixView_(MatrixHelperRep<S>* hrep) : Base(hrep) {} 01627 01628 // Copy constructor is shallow. CAUTION: despite const argument, this preserves writability 01629 // if it was present in the source. This is necessary to allow temporary views to be 01630 // created and used as lvalues. 01631 MatrixView_(const MatrixView_& m) 01632 : Base(MatrixCommitment(), 01633 const_cast<MatrixHelper<S>&>(m.getHelper()), 01634 typename MatrixHelper<S>::ShallowCopy()) {} 01635 01636 // Copy assignment is deep but not reallocating. 01637 MatrixView_& operator=(const MatrixView_& m) { 01638 Base::operator=(m); return *this; 01639 } 01640 01641 // Copy construction and copy assignment from a DeadMatrixView steals the helper. 01642 MatrixView_(DeadMatrixView_<ELT>&); 01643 MatrixView_& operator=(DeadMatrixView_<ELT>&); 01644 01645 // Ask for shallow copy 01646 MatrixView_(const MatrixHelper<S>& h) : Base(MatrixCommitment(), h, typename MatrixHelper<S>::ShallowCopy()) { } 01647 MatrixView_(MatrixHelper<S>& h) : Base(MatrixCommitment(), h, typename MatrixHelper<S>::ShallowCopy()) { } 01648 01649 MatrixView_& operator=(const Matrix_<ELT>& v) { Base::operator=(v); return *this; } 01650 MatrixView_& operator=(const ELT& e) { Base::operator=(e); return *this; } 01651 01652 template <class EE> MatrixView_& operator=(const MatrixBase<EE>& m) 01653 { Base::operator=(m); return *this; } 01654 template <class EE> MatrixView_& operator+=(const MatrixBase<EE>& m) 01655 { Base::operator+=(m); return *this; } 01656 template <class EE> MatrixView_& operator-=(const MatrixBase<EE>& m) 01657 { Base::operator-=(m); return *this; } 01658 01659 MatrixView_& operator*=(const StdNumber& t) { Base::operator*=(t); return *this; } 01660 MatrixView_& operator/=(const StdNumber& t) { Base::operator/=(t); return *this; } 01661 MatrixView_& operator+=(const ELT& r) { this->updDiag() += r; return *this; } 01662 MatrixView_& operator-=(const ELT& r) { this->updDiag() -= r; return *this; } 01663 01664 operator const Matrix_<ELT>&() const { return *reinterpret_cast<const Matrix_<ELT>*>(this); } 01665 operator Matrix_<ELT>&() { return *reinterpret_cast<Matrix_<ELT>*>(this); } 01666 01667 private: 01668 // NO DATA MEMBERS ALLOWED 01669 MatrixView_(); // default constructor suppressed (what's it a view of?) 01670 }; 01671 01672 01673 01674 // ----------------------------- DeadMatrixView_ ------------------------------ 01678 // ---------------------------------------------------------------------------- 01679 template <class ELT> class DeadMatrixView_ : public MatrixView_<ELT> { 01680 typedef MatrixView_<ELT> Base; 01681 typedef typename CNT<ELT>::Scalar S; 01682 typedef typename CNT<ELT>::StdNumber StdNumber; 01683 public: 01684 // Default construction is suppressed. 01685 // Uses default destructor. 01686 01687 // All functionality is passed through to MatrixView_. 01688 explicit DeadMatrixView_(MatrixHelperRep<S>* hrep) : Base(hrep) {} 01689 DeadMatrixView_(const Base& m) : Base(m) {} 01690 DeadMatrixView_& operator=(const Base& m) { 01691 Base::operator=(m); return *this; 01692 } 01693 01694 // Ask for shallow copy 01695 DeadMatrixView_(const MatrixHelper<S>& h) : Base(h) {} 01696 DeadMatrixView_(MatrixHelper<S>& h) : Base(h) {} 01697 01698 DeadMatrixView_& operator=(const Matrix_<ELT>& v) { Base::operator=(v); return *this; } 01699 DeadMatrixView_& operator=(const ELT& e) { Base::operator=(e); return *this; } 01700 01701 template <class EE> DeadMatrixView_& operator=(const MatrixBase<EE>& m) 01702 { Base::operator=(m); return *this; } 01703 template <class EE> DeadMatrixView_& operator+=(const MatrixBase<EE>& m) 01704 { Base::operator+=(m); return *this; } 01705 template <class EE> DeadMatrixView_& operator-=(const MatrixBase<EE>& m) 01706 { Base::operator-=(m); return *this; } 01707 01708 DeadMatrixView_& operator*=(const StdNumber& t) { Base::operator*=(t); return *this; } 01709 DeadMatrixView_& operator/=(const StdNumber& t) { Base::operator/=(t); return *this; } 01710 DeadMatrixView_& operator+=(const ELT& r) { this->updDiag() += r; return *this; } 01711 DeadMatrixView_& operator-=(const ELT& r) { this->updDiag() -= r; return *this; } 01712 01713 private: 01714 // NO DATA MEMBERS ALLOWED 01715 DeadMatrixView_(); // default constructor suppressed (what's it a view of?) 01716 }; 01717 01718 template <class ELT> inline 01719 MatrixView_<ELT>::MatrixView_(DeadMatrixView_<ELT>& dead) 01720 : Base(dead.updHelper().stealRep()) {} 01721 01722 template <class ELT> inline MatrixView_<ELT>& 01723 MatrixView_<ELT>::operator=(DeadMatrixView_<ELT>& dead) { 01724 if (Base::getHelper().getCharacterCommitment().isSatisfiedBy(dead.getMatrixCharacter())) 01725 Base::updHelper().replaceRep(dead.updHelper().stealRep()); 01726 else 01727 Base::operator=(dead); 01728 return *this; 01729 } 01730 01731 01732 // ---------------------------------- Matrix_ --------------------------------- 01735 // ---------------------------------------------------------------------------- 01736 template <class ELT> class Matrix_ : public MatrixBase<ELT> { 01737 typedef typename CNT<ELT>::Scalar S; 01738 typedef typename CNT<ELT>::Number Number; 01739 typedef typename CNT<ELT>::StdNumber StdNumber; 01740 01741 typedef typename CNT<ELT>::TNeg ENeg; 01742 typedef typename CNT<ELT>::THerm EHerm; 01743 01744 typedef MatrixBase<ELT> Base; 01745 typedef MatrixBase<ENeg> BaseNeg; 01746 typedef MatrixBase<EHerm> BaseHerm; 01747 01748 typedef Matrix_<ELT> T; 01749 typedef MatrixView_<ELT> TView; 01750 typedef Matrix_<ENeg> TNeg; 01751 01752 public: 01753 Matrix_() : Base() { } 01754 Matrix_(const MatrixCommitment& mc) : Base(mc) {} 01755 01756 // Copy constructor is deep. 01757 Matrix_(const Matrix_& src) : Base(src) { } 01758 01759 // Assignment is a deep copy and will also allow reallocation if this Matrix 01760 // doesn't have a view. 01761 Matrix_& operator=(const Matrix_& src) { 01762 Base::operator=(src); return *this; 01763 } 01764 01765 // Force a deep copy of the view or whatever this is. 01766 // Note that this is an implicit conversion. 01767 Matrix_(const Base& v) : Base(v) {} // e.g., MatrixView 01768 01769 // Allow implicit conversion from a source matrix that 01770 // has a negated version of ELT. 01771 Matrix_(const BaseNeg& v) : Base(v) {} 01772 01773 // TODO: implicit conversion from conjugate. This is trickier 01774 // since real elements are their own conjugate so you'll get 01775 // duplicate methods defined from Matrix_(BaseHerm) and Matrix_(Base). 01776 01777 Matrix_(int m, int n) : Base(MatrixCommitment(), m, n) {} 01778 01779 Matrix_(int m, int n, const ELT* cppInitialValuesByRow) 01780 : Base(MatrixCommitment(), m, n, cppInitialValuesByRow) {} 01781 Matrix_(int m, int n, const ELT& initialValue) 01782 : Base(MatrixCommitment(), m, n, initialValue) {} 01783 01784 Matrix_(int m, int n, int leadingDim, const S* data) // read only 01785 : Base(MatrixCommitment(), MatrixCharacter::LapackFull(m,n), 01786 leadingDim, data) {} 01787 Matrix_(int m, int n, int leadingDim, S* data) // writable 01788 : Base(MatrixCommitment(), MatrixCharacter::LapackFull(m,n), 01789 leadingDim, data) {} 01790 01792 template <int M, int N, int CS, int RS> 01793 explicit Matrix_(const Mat<M,N,ELT,CS,RS>& mat) 01794 : Base(MatrixCommitment(), M, N) 01795 { for (int i = 0; i < M; ++i) 01796 for (int j = 0; j < N; ++j) 01797 this->updElt(i, j) = mat(i, j); } 01798 01799 Matrix_& operator=(const ELT& v) { Base::operator=(v); return *this; } 01800 01801 template <class EE> Matrix_& operator=(const MatrixBase<EE>& m) 01802 { Base::operator=(m); return*this; } 01803 template <class EE> Matrix_& operator+=(const MatrixBase<EE>& m) 01804 { Base::operator+=(m); return*this; } 01805 template <class EE> Matrix_& operator-=(const MatrixBase<EE>& m) 01806 { Base::operator-=(m); return*this; } 01807 01808 Matrix_& operator*=(const StdNumber& t) { Base::operator*=(t); return *this; } 01809 Matrix_& operator/=(const StdNumber& t) { Base::operator/=(t); return *this; } 01810 Matrix_& operator+=(const ELT& r) { this->updDiag() += r; return *this; } 01811 Matrix_& operator-=(const ELT& r) { this->updDiag() -= r; return *this; } 01812 01813 const TNeg& negate() const {return *reinterpret_cast<const TNeg*>(this); } 01814 TNeg& updNegate() {return *reinterpret_cast<TNeg*>(this); } 01815 01816 const TNeg& operator-() const {return negate();} 01817 TNeg& operator-() {return updNegate();} 01818 01819 private: 01820 // NO DATA MEMBERS ALLOWED 01821 }; 01822 01823 01824 01825 // -------------------------------- VectorView_ ------------------------------- 01831 // ---------------------------------------------------------------------------- 01832 template <class ELT> class VectorView_ : public VectorBase<ELT> { 01833 typedef VectorBase<ELT> Base; 01834 typedef typename CNT<ELT>::Scalar S; 01835 typedef typename CNT<ELT>::Number Number; 01836 typedef typename CNT<ELT>::StdNumber StdNumber; 01837 typedef VectorView_<ELT> T; 01838 typedef VectorView_< typename CNT<ELT>::TNeg > TNeg; 01839 typedef RowVectorView_< typename CNT<ELT>::THerm > THerm; 01840 public: 01841 // Default construction is suppressed. 01842 // Uses default destructor. 01843 01844 // Create a VectorView_ handle using a given helper rep. 01845 explicit VectorView_(MatrixHelperRep<S>* hrep) : Base(hrep) {} 01846 01847 // Copy constructor is shallow. CAUTION: despite const argument, this preserves writability 01848 // if it was present in the source. This is necessary to allow temporary views to be 01849 // created and used as lvalues. 01850 VectorView_(const VectorView_& v) 01851 : Base(const_cast<MatrixHelper<S>&>(v.getHelper()), typename MatrixHelper<S>::ShallowCopy()) { } 01852 01853 // Copy assignment is deep but not reallocating. 01854 VectorView_& operator=(const VectorView_& v) { 01855 Base::operator=(v); return *this; 01856 } 01857 01858 // Ask for shallow copy 01859 explicit VectorView_(const MatrixHelper<S>& h) : Base(h, typename MatrixHelper<S>::ShallowCopy()) { } 01860 explicit VectorView_(MatrixHelper<S>& h) : Base(h, typename MatrixHelper<S>::ShallowCopy()) { } 01861 01862 VectorView_& operator=(const Base& b) { Base::operator=(b); return *this; } 01863 01864 VectorView_& operator=(const ELT& v) { Base::operator=(v); return *this; } 01865 01866 template <class EE> VectorView_& operator=(const VectorBase<EE>& m) 01867 { Base::operator=(m); return*this; } 01868 template <class EE> VectorView_& operator+=(const VectorBase<EE>& m) 01869 { Base::operator+=(m); return*this; } 01870 template <class EE> VectorView_& operator-=(const VectorBase<EE>& m) 01871 { Base::operator-=(m); return*this; } 01872 01873 VectorView_& operator*=(const StdNumber& t) { Base::operator*=(t); return *this; } 01874 VectorView_& operator/=(const StdNumber& t) { Base::operator/=(t); return *this; } 01875 VectorView_& operator+=(const ELT& b) { elementwiseAddScalarInPlace(b); return *this; } 01876 VectorView_& operator-=(const ELT& b) { elementwiseSubtractScalarInPlace(b); return *this; } 01877 01878 private: 01879 // NO DATA MEMBERS ALLOWED 01880 VectorView_(); // default construction suppressed (what's it a View of?) 01881 }; 01882 01883 01884 01885 // ---------------------------------- Vector_ --------------------------------- 01889 // ---------------------------------------------------------------------------- 01890 template <class ELT> class Vector_ : public VectorBase<ELT> { 01891 typedef typename CNT<ELT>::Scalar S; 01892 typedef typename CNT<ELT>::Number Number; 01893 typedef typename CNT<ELT>::StdNumber StdNumber; 01894 typedef typename CNT<ELT>::TNeg ENeg; 01895 typedef VectorBase<ELT> Base; 01896 typedef VectorBase<ENeg> BaseNeg; 01897 public: 01898 Vector_() : Base() {} // 0x1 reallocatable 01899 // Uses default destructor. 01900 01901 // Copy constructor is deep. 01902 Vector_(const Vector_& src) : Base(src) {} 01903 01904 // Implicit conversions. 01905 Vector_(const Base& src) : Base(src) {} // e.g., VectorView 01906 Vector_(const BaseNeg& src) : Base(src) {} 01907 01908 // Copy assignment is deep and can be reallocating if this Vector 01909 // has no View. 01910 Vector_& operator=(const Vector_& src) { 01911 Base::operator=(src); return*this; 01912 } 01913 01914 01915 explicit Vector_(int m) : Base(m) { } 01916 Vector_(int m, const ELT* cppInitialValues) : Base(m, cppInitialValues) {} 01917 Vector_(int m, const ELT& initialValue) : Base(m, initialValue) {} 01918 01923 Vector_(int m, const S* cppData, bool): Base(m, Base::CppNScalarsPerElement, cppData) {} 01924 Vector_(int m, S* cppData, bool): Base(m, Base::CppNScalarsPerElement, cppData) {} 01925 01929 Vector_(int m, int stride, const S* data, bool) : Base(m, stride, data) {} 01930 Vector_(int m, int stride, S* data, bool) : Base(m, stride, data) {} 01931 01933 template <int M> 01934 explicit Vector_(const Vec<M,ELT>& v) : Base(M) { 01935 for (int i = 0; i < M; ++i) 01936 this->updElt(i, 0) = v(i); 01937 } 01938 01939 Vector_& operator=(const ELT& v) { Base::operator=(v); return *this; } 01940 01941 template <class EE> Vector_& operator=(const VectorBase<EE>& m) 01942 { Base::operator=(m); return*this; } 01943 template <class EE> Vector_& operator+=(const VectorBase<EE>& m) 01944 { Base::operator+=(m); return*this; } 01945 template <class EE> Vector_& operator-=(const VectorBase<EE>& m) 01946 { Base::operator-=(m); return*this; } 01947 01948 Vector_& operator*=(const StdNumber& t) { Base::operator*=(t); return *this; } 01949 Vector_& operator/=(const StdNumber& t) { Base::operator/=(t); return *this; } 01950 Vector_& operator+=(const ELT& b) { elementwiseAddScalarInPlace(b); return *this; } 01951 Vector_& operator-=(const ELT& b) { elementwiseSubtractScalarInPlace(b); return *this; } 01952 01953 private: 01954 // NO DATA MEMBERS ALLOWED 01955 }; 01956 01957 01958 01959 // ------------------------------ RowVectorView_ ------------------------------ 01965 // ---------------------------------------------------------------------------- 01966 template <class ELT> class RowVectorView_ : public RowVectorBase<ELT> { 01967 typedef RowVectorBase<ELT> Base; 01968 typedef typename CNT<ELT>::Scalar S; 01969 typedef typename CNT<ELT>::Number Number; 01970 typedef typename CNT<ELT>::StdNumber StdNumber; 01971 typedef RowVectorView_<ELT> T; 01972 typedef RowVectorView_< typename CNT<ELT>::TNeg > TNeg; 01973 typedef VectorView_< typename CNT<ELT>::THerm > THerm; 01974 public: 01975 // Default construction is suppressed. 01976 // Uses default destructor. 01977 01978 // Create a RowVectorView_ handle using a given helper rep. 01979 explicit RowVectorView_(MatrixHelperRep<S>* hrep) : Base(hrep) {} 01980 01981 // Copy constructor is shallow. CAUTION: despite const argument, this preserves writability 01982 // if it was present in the source. This is necessary to allow temporary views to be 01983 // created and used as lvalues. 01984 RowVectorView_(const RowVectorView_& r) 01985 : Base(const_cast<MatrixHelper<S>&>(r.getHelper()), typename MatrixHelper<S>::ShallowCopy()) { } 01986 01987 // Copy assignment is deep but not reallocating. 01988 RowVectorView_& operator=(const RowVectorView_& r) { 01989 Base::operator=(r); return *this; 01990 } 01991 01992 // Ask for shallow copy 01993 explicit RowVectorView_(const MatrixHelper<S>& h) : Base(h, typename MatrixHelper<S>::ShallowCopy()) { } 01994 explicit RowVectorView_(MatrixHelper<S>& h) : Base(h, typename MatrixHelper<S>::ShallowCopy()) { } 01995 01996 RowVectorView_& operator=(const Base& b) { Base::operator=(b); return *this; } 01997 01998 RowVectorView_& operator=(const ELT& v) { Base::operator=(v); return *this; } 01999 02000 template <class EE> RowVectorView_& operator=(const RowVectorBase<EE>& m) 02001 { Base::operator=(m); return*this; } 02002 template <class EE> RowVectorView_& operator+=(const RowVectorBase<EE>& m) 02003 { Base::operator+=(m); return*this; } 02004 template <class EE> RowVectorView_& operator-=(const RowVectorBase<EE>& m) 02005 { Base::operator-=(m); return*this; } 02006 02007 RowVectorView_& operator*=(const StdNumber& t) { Base::operator*=(t); return *this; } 02008 RowVectorView_& operator/=(const StdNumber& t) { Base::operator/=(t); return *this; } 02009 RowVectorView_& operator+=(const ELT& b) { elementwiseAddScalarInPlace(b); return *this; } 02010 RowVectorView_& operator-=(const ELT& b) { elementwiseSubtractScalarInPlace(b); return *this; } 02011 02012 private: 02013 // NO DATA MEMBERS ALLOWED 02014 RowVectorView_(); // default construction suppressed (what is it a view of?) 02015 }; 02016 02017 02018 02019 // -------------------------------- RowVector_ -------------------------------- 02024 // ---------------------------------------------------------------------------- 02025 template <class ELT> class RowVector_ : public RowVectorBase<ELT> { 02026 typedef typename CNT<ELT>::Scalar S; 02027 typedef typename CNT<ELT>::Number Number; 02028 typedef typename CNT<ELT>::StdNumber StdNumber; 02029 typedef typename CNT<ELT>::TNeg ENeg; 02030 02031 typedef RowVectorBase<ELT> Base; 02032 typedef RowVectorBase<ENeg> BaseNeg; 02033 public: 02034 RowVector_() : Base() {} // 1x0 reallocatable 02035 // Uses default destructor. 02036 02037 // Copy constructor is deep. 02038 RowVector_(const RowVector_& src) : Base(src) {} 02039 02040 // Implicit conversions. 02041 RowVector_(const Base& src) : Base(src) {} // e.g., RowVectorView 02042 RowVector_(const BaseNeg& src) : Base(src) {} 02043 02044 // Copy assignment is deep and can be reallocating if this RowVector 02045 // has no View. 02046 RowVector_& operator=(const RowVector_& src) { 02047 Base::operator=(src); return*this; 02048 } 02049 02050 02051 explicit RowVector_(int n) : Base(n) { } 02052 RowVector_(int n, const ELT* cppInitialValues) : Base(n, cppInitialValues) {} 02053 RowVector_(int n, const ELT& initialValue) : Base(n, initialValue) {} 02054 02059 RowVector_(int n, const S* cppData, bool): Base(n, Base::CppNScalarsPerElement, cppData) {} 02060 RowVector_(int n, S* cppData, bool): Base(n, Base::CppNScalarsPerElement, cppData) {} 02061 02065 RowVector_(int n, int stride, const S* data, bool) : Base(n, stride, data) {} 02066 RowVector_(int n, int stride, S* data, bool) : Base(n, stride, data) {} 02067 02069 template <int M> 02070 explicit RowVector_(const Row<M,ELT>& v) : Base(M) { 02071 for (int i = 0; i < M; ++i) 02072 this->updElt(0, i) = v(i); 02073 } 02074 02075 RowVector_& operator=(const ELT& v) { Base::operator=(v); return *this; } 02076 02077 template <class EE> RowVector_& operator=(const RowVectorBase<EE>& b) 02078 { Base::operator=(b); return*this; } 02079 template <class EE> RowVector_& operator+=(const RowVectorBase<EE>& b) 02080 { Base::operator+=(b); return*this; } 02081 template <class EE> RowVector_& operator-=(const RowVectorBase<EE>& b) 02082 { Base::operator-=(b); return*this; } 02083 02084 RowVector_& operator*=(const StdNumber& t) { Base::operator*=(t); return *this; } 02085 RowVector_& operator/=(const StdNumber& t) { Base::operator/=(t); return *this; } 02086 RowVector_& operator+=(const ELT& b) { elementwiseAddScalarInPlace(b); return *this; } 02087 RowVector_& operator-=(const ELT& b) { elementwiseSubtractScalarInPlace(b); return *this; } 02088 02089 private: 02090 // NO DATA MEMBERS ALLOWED 02091 }; 02092 02093 02094 02095 // ------------------------ MatrixBase definitions ---------------------------- 02096 02097 template <class ELT> inline MatrixView_<ELT> 02098 MatrixBase<ELT>::block(int i, int j, int m, int n) const { 02099 SimTK_INDEXCHECK(i,nrow()+1,"MatrixBase::block()"); 02100 SimTK_INDEXCHECK(j,ncol()+1,"MatrixBase::block()"); 02101 SimTK_SIZECHECK(i+m,nrow(),"MatrixBase::block()"); 02102 SimTK_SIZECHECK(j+n,ncol(),"MatrixBase::block()"); 02103 02104 MatrixHelper<Scalar> h(MatrixCommitment(),helper,i,j,m,n); 02105 return MatrixView_<ELT>(h.stealRep()); 02106 } 02107 02108 template <class ELT> inline MatrixView_<ELT> 02109 MatrixBase<ELT>::updBlock(int i, int j, int m, int n) { 02110 SimTK_INDEXCHECK(i,nrow()+1,"MatrixBase::updBlock()"); 02111 SimTK_INDEXCHECK(j,ncol()+1,"MatrixBase::updBlock()"); 02112 SimTK_SIZECHECK(i+m,nrow(),"MatrixBase::updBlock()"); 02113 SimTK_SIZECHECK(j+n,ncol(),"MatrixBase::updBlock()"); 02114 02115 MatrixHelper<Scalar> h(MatrixCommitment(),helper,i,j,m,n); 02116 return MatrixView_<ELT>(h.stealRep()); 02117 } 02118 02119 template <class E> inline MatrixView_<typename CNT<E>::THerm> 02120 MatrixBase<E>::transpose() const { 02121 MatrixHelper<typename CNT<Scalar>::THerm> 02122 h(MatrixCommitment(), 02123 helper, typename MatrixHelper<typename CNT<Scalar>::THerm>::TransposeView()); 02124 return MatrixView_<typename CNT<E>::THerm>(h.stealRep()); 02125 } 02126 02127 template <class E> inline MatrixView_<typename CNT<E>::THerm> 02128 MatrixBase<E>::updTranspose() { 02129 MatrixHelper<typename CNT<Scalar>::THerm> 02130 h(MatrixCommitment(), 02131 helper, typename MatrixHelper<typename CNT<Scalar>::THerm>::TransposeView()); 02132 return MatrixView_<typename CNT<E>::THerm>(h.stealRep()); 02133 } 02134 02135 template <class E> inline VectorView_<E> 02136 MatrixBase<E>::diag() const { 02137 MatrixHelper<Scalar> h(MatrixCommitment::Vector(), 02138 helper, typename MatrixHelper<Scalar>::DiagonalView()); 02139 return VectorView_<E>(h.stealRep()); 02140 } 02141 02142 template <class E> inline VectorView_<E> 02143 MatrixBase<E>::updDiag() { 02144 MatrixHelper<Scalar> h(MatrixCommitment::Vector(), 02145 helper, typename MatrixHelper<Scalar>::DiagonalView()); 02146 return VectorView_<E>(h.stealRep()); 02147 } 02148 02149 template <class ELT> inline VectorView_<ELT> 02150 MatrixBase<ELT>::col(int j) const { 02151 SimTK_INDEXCHECK(j,ncol(),"MatrixBase::col()"); 02152 02153 MatrixHelper<Scalar> h(MatrixCommitment::Vector(), 02154 helper,0,j,nrow(),1); 02155 return VectorView_<ELT>(h.stealRep()); 02156 } 02157 02158 template <class ELT> inline VectorView_<ELT> 02159 MatrixBase<ELT>::updCol(int j) { 02160 SimTK_INDEXCHECK(j,ncol(),"MatrixBase::updCol()"); 02161 02162 MatrixHelper<Scalar> h(MatrixCommitment::Vector(), 02163 helper,0,j,nrow(),1); 02164 return VectorView_<ELT>(h.stealRep()); 02165 } 02166 02167 template <class ELT> inline RowVectorView_<ELT> 02168 MatrixBase<ELT>::row(int i) const { 02169 SimTK_INDEXCHECK(i,nrow(),"MatrixBase::row()"); 02170 02171 MatrixHelper<Scalar> h(MatrixCommitment::RowVector(), 02172 helper,i,0,1,ncol()); 02173 return RowVectorView_<ELT>(h.stealRep()); 02174 } 02175 02176 template <class ELT> inline RowVectorView_<ELT> 02177 MatrixBase<ELT>::updRow(int i) { 02178 SimTK_INDEXCHECK(i,nrow(),"MatrixBase::updRow()"); 02179 02180 MatrixHelper<Scalar> h(MatrixCommitment::RowVector(), 02181 helper,i,0,1,ncol()); 02182 return RowVectorView_<ELT>(h.stealRep()); 02183 } 02184 02185 // M = diag(v) * M; v must have nrow() elements. 02186 // That is, M[i] *= v[i]. 02187 template <class ELT> template <class EE> inline MatrixBase<ELT>& 02188 MatrixBase<ELT>::rowScaleInPlace(const VectorBase<EE>& v) { 02189 assert(v.nrow() == nrow()); 02190 for (int i=0; i < nrow(); ++i) 02191 (*this)[i] *= v[i]; 02192 return *this; 02193 } 02194 02195 template <class ELT> template <class EE> inline void 02196 MatrixBase<ELT>::rowScale(const VectorBase<EE>& v, typename MatrixBase<ELT>::template EltResult<EE>::Mul& out) const { 02197 assert(v.nrow() == nrow()); 02198 out.resize(nrow(), ncol()); 02199 for (int j=0; j<ncol(); ++j) 02200 for (int i=0; i<nrow(); ++i) 02201 out(i,j) = (*this)(i,j) * v[i]; 02202 } 02203 02204 // M = M * diag(v); v must have ncol() elements 02205 // That is, M(i) *= v[i] 02206 template <class ELT> template <class EE> inline MatrixBase<ELT>& 02207 MatrixBase<ELT>::colScaleInPlace(const VectorBase<EE>& v) { 02208 assert(v.nrow() == ncol()); 02209 for (int j=0; j < ncol(); ++j) 02210 (*this)(j) *= v[j]; 02211 return *this; 02212 } 02213 02214 template <class ELT> template <class EE> inline void 02215 MatrixBase<ELT>::colScale(const VectorBase<EE>& v, typename MatrixBase<ELT>::template EltResult<EE>::Mul& out) const { 02216 assert(v.nrow() == ncol()); 02217 out.resize(nrow(), ncol()); 02218 for (int j=0; j<ncol(); ++j) 02219 for (int i=0; i<nrow(); ++i) 02220 out(i,j) = (*this)(i,j) * v[j]; 02221 } 02222 02223 02224 // M(i,j) *= r[i]*c[j]; r must have nrow() elements; c must have ncol() elements 02225 template <class ELT> template <class ER, class EC> inline MatrixBase<ELT>& 02226 MatrixBase<ELT>::rowAndColScaleInPlace(const VectorBase<ER>& r, const VectorBase<EC>& c) { 02227 assert(r.nrow()==nrow() && c.nrow()==ncol()); 02228 for (int j=0; j<ncol(); ++j) 02229 for (int i=0; i<nrow(); ++i) 02230 (*this)(i,j) *= (r[i]*c[j]); 02231 return *this; 02232 } 02233 02234 template <class ELT> template <class ER, class EC> inline void 02235 MatrixBase<ELT>::rowAndColScale( 02236 const VectorBase<ER>& r, 02237 const VectorBase<EC>& c, 02238 typename EltResult<typename VectorBase<ER>::template EltResult<EC>::Mul>::Mul& 02239 out) const 02240 { 02241 assert(r.nrow()==nrow() && c.nrow()==ncol()); 02242 out.resize(nrow(), ncol()); 02243 for (int j=0; j<ncol(); ++j) 02244 for (int i=0; i<nrow(); ++i) 02245 out(i,j) = (*this)(i,j) * (r[i]*c[j]); 02246 } 02247 02248 02249 // Set M(i,j) = M(i,j)^-1. 02250 template <class ELT> inline MatrixBase<ELT>& 02251 MatrixBase<ELT>::elementwiseInvertInPlace() { 02252 const int nr=nrow(), nc=ncol(); 02253 for (int j=0; j<nc; ++j) 02254 for (int i=0; i<nr; ++i) { 02255 ELT& e = updElt(i,j); 02256 e = CNT<ELT>::invert(e); 02257 } 02258 return *this; 02259 } 02260 02261 template <class ELT> inline void 02262 MatrixBase<ELT>::elementwiseInvert(MatrixBase<typename CNT<E>::TInvert>& out) const { 02263 const int nr=nrow(), nc=ncol(); 02264 out.resize(nr,nc); 02265 for (int j=0; j<nc; ++j) 02266 for (int i=0; i<nr; ++i) 02267 out(i,j) = CNT<ELT>::invert((*this)(i,j)); 02268 } 02269 02270 // M(i,j) += s 02271 template <class ELT> template <class S> inline MatrixBase<ELT>& 02272 MatrixBase<ELT>::elementwiseAddScalarInPlace(const S& s) { 02273 for (int j=0; j<ncol(); ++j) 02274 for (int i=0; i<nrow(); ++i) 02275 (*this)(i,j) += s; 02276 return *this; 02277 } 02278 02279 template <class ELT> template <class S> inline void 02280 MatrixBase<ELT>::elementwiseAddScalar( 02281 const S& s, 02282 typename MatrixBase<ELT>::template EltResult<S>::Add& out) const 02283 { 02284 const int nr=nrow(), nc=ncol(); 02285 out.resize(nr,nc); 02286 for (int j=0; j<nc; ++j) 02287 for (int i=0; i<nr; ++i) 02288 out(i,j) = (*this)(i,j) + s; 02289 } 02290 02291 // M(i,j) -= s 02292 template <class ELT> template <class S> inline MatrixBase<ELT>& 02293 MatrixBase<ELT>::elementwiseSubtractScalarInPlace(const S& s) { 02294 for (int j=0; j<ncol(); ++j) 02295 for (int i=0; i<nrow(); ++i) 02296 (*this)(i,j) -= s; 02297 return *this; 02298 } 02299 02300 template <class ELT> template <class S> inline void 02301 MatrixBase<ELT>::elementwiseSubtractScalar( 02302 const S& s, 02303 typename MatrixBase<ELT>::template EltResult<S>::Sub& out) const 02304 { 02305 const int nr=nrow(), nc=ncol(); 02306 out.resize(nr,nc); 02307 for (int j=0; j<nc; ++j) 02308 for (int i=0; i<nr; ++i) 02309 out(i,j) = (*this)(i,j) - s; 02310 } 02311 02312 // M(i,j) = s - M(i,j) 02313 template <class ELT> template <class S> inline MatrixBase<ELT>& 02314 MatrixBase<ELT>::elementwiseSubtractFromScalarInPlace(const S& s) { 02315 const int nr=nrow(), nc=ncol(); 02316 for (int j=0; j<nc; ++j) 02317 for (int i=0; i<nr; ++i) { 02318 ELT& e = updElt(i,j); 02319 e = s - e; 02320 } 02321 return *this; 02322 } 02323 02324 template <class ELT> template <class S> inline void 02325 MatrixBase<ELT>::elementwiseSubtractFromScalar( 02326 const S& s, 02327 typename MatrixBase<S>::template EltResult<ELT>::Sub& out) const 02328 { 02329 const int nr=nrow(), nc=ncol(); 02330 out.resize(nr,nc); 02331 for (int j=0; j<nc; ++j) 02332 for (int i=0; i<nr; ++i) 02333 out(i,j) = s - (*this)(i,j); 02334 } 02335 02336 // M(i,j) *= R(i,j); R must have same dimensions as this 02337 template <class ELT> template <class EE> inline MatrixBase<ELT>& 02338 MatrixBase<ELT>::elementwiseMultiplyInPlace(const MatrixBase<EE>& r) { 02339 const int nr=nrow(), nc=ncol(); 02340 assert(r.nrow()==nr && r.ncol()==nc); 02341 for (int j=0; j<nc; ++j) 02342 for (int i=0; i<nr; ++i) 02343 (*this)(i,j) *= r(i,j); 02344 return *this; 02345 } 02346 02347 template <class ELT> template <class EE> inline void 02348 MatrixBase<ELT>::elementwiseMultiply( 02349 const MatrixBase<EE>& r, 02350 typename MatrixBase<ELT>::template EltResult<EE>::Mul& out) const 02351 { 02352 const int nr=nrow(), nc=ncol(); 02353 assert(r.nrow()==nr && r.ncol()==nc); 02354 out.resize(nr,nc); 02355 for (int j=0; j<nc; ++j) 02356 for (int i=0; i<nr; ++i) 02357 out(i,j) = (*this)(i,j) * r(i,j); 02358 } 02359 02360 // M(i,j) = R(i,j) * M(i,j); R must have same dimensions as this 02361 template <class ELT> template <class EE> inline MatrixBase<ELT>& 02362 MatrixBase<ELT>::elementwiseMultiplyFromLeftInPlace(const MatrixBase<EE>& r) { 02363 const int nr=nrow(), nc=ncol(); 02364 assert(r.nrow()==nr && r.ncol()==nc); 02365 for (int j=0; j<nc; ++j) 02366 for (int i=0; i<nr; ++i) { 02367 ELT& e = updElt(i,j); 02368 e = r(i,j) * e; 02369 } 02370 return *this; 02371 } 02372 02373 template <class ELT> template <class EE> inline void 02374 MatrixBase<ELT>::elementwiseMultiplyFromLeft( 02375 const MatrixBase<EE>& r, 02376 typename MatrixBase<EE>::template EltResult<ELT>::Mul& out) const 02377 { 02378 const int nr=nrow(), nc=ncol(); 02379 assert(r.nrow()==nr && r.ncol()==nc); 02380 out.resize(nr,nc); 02381 for (int j=0; j<nc; ++j) 02382 for (int i=0; i<nr; ++i) 02383 out(i,j) = r(i,j) * (*this)(i,j); 02384 } 02385 02386 // M(i,j) /= R(i,j); R must have same dimensions as this 02387 template <class ELT> template <class EE> inline MatrixBase<ELT>& 02388 MatrixBase<ELT>::elementwiseDivideInPlace(const MatrixBase<EE>& r) { 02389 const int nr=nrow(), nc=ncol(); 02390 assert(r.nrow()==nr && r.ncol()==nc); 02391 for (int j=0; j<nc; ++j) 02392 for (int i=0; i<nr; ++i) 02393 (*this)(i,j) /= r(i,j); 02394 return *this; 02395 } 02396 02397 template <class ELT> template <class EE> inline void 02398 MatrixBase<ELT>::elementwiseDivide( 02399 const MatrixBase<EE>& r, 02400 typename MatrixBase<ELT>::template EltResult<EE>::Dvd& out) const 02401 { 02402 const int nr=nrow(), nc=ncol(); 02403 assert(r.nrow()==nr && r.ncol()==nc); 02404 out.resize(nr,nc); 02405 for (int j=0; j<nc; ++j) 02406 for (int i=0; i<nr; ++i) 02407 out(i,j) = (*this)(i,j) / r(i,j); 02408 } 02409 // M(i,j) = R(i,j) / M(i,j); R must have same dimensions as this 02410 template <class ELT> template <class EE> inline MatrixBase<ELT>& 02411 MatrixBase<ELT>::elementwiseDivideFromLeftInPlace(const MatrixBase<EE>& r) { 02412 const int nr=nrow(), nc=ncol(); 02413 assert(r.nrow()==nr && r.ncol()==nc); 02414 for (int j=0; j<nc; ++j) 02415 for (int i=0; i<nr; ++i) { 02416 ELT& e = updElt(i,j); 02417 e = r(i,j) / e; 02418 } 02419 return *this; 02420 } 02421 02422 template <class ELT> template <class EE> inline void 02423 MatrixBase<ELT>::elementwiseDivideFromLeft( 02424 const MatrixBase<EE>& r, 02425 typename MatrixBase<EE>::template EltResult<ELT>::Dvd& out) const 02426 { 02427 const int nr=nrow(), nc=ncol(); 02428 assert(r.nrow()==nr && r.ncol()==nc); 02429 out.resize(nr,nc); 02430 for (int j=0; j<nc; ++j) 02431 for (int i=0; i<nr; ++i) 02432 out(i,j) = r(i,j) / (*this)(i,j); 02433 } 02434 02435 /* 02436 template <class ELT> inline MatrixView_< typename CNT<ELT>::TReal > 02437 MatrixBase<ELT>::real() const { 02438 if (!CNT<ELT>::IsComplex) { // known at compile time 02439 return MatrixView_< typename CNT<ELT>::TReal >( // this is just ELT 02440 MatrixHelper(helper,0,0,nrow(),ncol())); // a view of the whole matrix 02441 } 02442 // Elements are complex -- helper uses underlying precision (real) type. 02443 MatrixHelper<Precision> h(helper,typename MatrixHelper<Precision>::RealView); 02444 return MatrixView_< typename CNT<ELT>::TReal >(h); 02445 } 02446 */ 02447 02448 02449 // ---------------------------------------------------------------------------- 02453 02454 // + and - allow mixed element types, but will fail to compile if the elements aren't 02455 // compatible. At run time these will fail if the dimensions are incompatible. 02456 template <class E1, class E2> 02457 Matrix_<typename CNT<E1>::template Result<E2>::Add> 02458 operator+(const MatrixBase<E1>& l, const MatrixBase<E2>& r) { 02459 return Matrix_<typename CNT<E1>::template Result<E2>::Add>(l) += r; 02460 } 02461 02462 template <class E> 02463 Matrix_<E> operator+(const MatrixBase<E>& l, const typename CNT<E>::T& r) { 02464 return Matrix_<E>(l) += r; 02465 } 02466 02467 template <class E> 02468 Matrix_<E> operator+(const typename CNT<E>::T& l, const MatrixBase<E>& r) { 02469 return Matrix_<E>(r) += l; 02470 } 02471 02472 template <class E1, class E2> 02473 Matrix_<typename CNT<E1>::template Result<E2>::Sub> 02474 operator-(const MatrixBase<E1>& l, const MatrixBase<E2>& r) { 02475 return Matrix_<typename CNT<E1>::template Result<E2>::Sub>(l) -= r; 02476 } 02477 02478 template <class E> 02479 Matrix_<E> operator-(const MatrixBase<E>& l, const typename CNT<E>::T& r) { 02480 return Matrix_<E>(l) -= r; 02481 } 02482 02483 template <class E> 02484 Matrix_<E> operator-(const typename CNT<E>::T& l, const MatrixBase<E>& r) { 02485 Matrix_<E> temp(r.nrow(), r.ncol()); 02486 temp = l; 02487 return (temp -= r); 02488 } 02489 02490 // Scalar multiply and divide. You might wish the scalar could be 02491 // a templatized type "E2", but that would create horrible ambiguities since 02492 // E2 would match not only scalar types but everything else including 02493 // matrices. 02494 template <class E> Matrix_<E> 02495 operator*(const MatrixBase<E>& l, const typename CNT<E>::StdNumber& r) 02496 { return Matrix_<E>(l)*=r; } 02497 02498 template <class E> Matrix_<E> 02499 operator*(const typename CNT<E>::StdNumber& l, const MatrixBase<E>& r) 02500 { return Matrix_<E>(r)*=l; } 02501 02502 template <class E> Matrix_<E> 02503 operator/(const MatrixBase<E>& l, const typename CNT<E>::StdNumber& r) 02504 { return Matrix_<E>(l)/=r; } 02505 02506 // Handle ints explicitly. 02507 template <class E> Matrix_<E> 02508 operator*(const MatrixBase<E>& l, int r) 02509 { return Matrix_<E>(l)*= typename CNT<E>::StdNumber(r); } 02510 02511 template <class E> Matrix_<E> 02512 operator*(int l, const MatrixBase<E>& r) 02513 { return Matrix_<E>(r)*= typename CNT<E>::StdNumber(l); } 02514 02515 template <class E> Matrix_<E> 02516 operator/(const MatrixBase<E>& l, int r) 02517 { return Matrix_<E>(l)/= typename CNT<E>::StdNumber(r); } 02518 02520 02524 02525 template <class E1, class E2> 02526 Vector_<typename CNT<E1>::template Result<E2>::Add> 02527 operator+(const VectorBase<E1>& l, const VectorBase<E2>& r) { 02528 return Vector_<typename CNT<E1>::template Result<E2>::Add>(l) += r; 02529 } 02530 template <class E> 02531 Vector_<E> operator+(const VectorBase<E>& l, const typename CNT<E>::T& r) { 02532 return Vector_<E>(l) += r; 02533 } 02534 template <class E> 02535 Vector_<E> operator+(const typename CNT<E>::T& l, const VectorBase<E>& r) { 02536 return Vector_<E>(r) += l; 02537 } 02538 template <class E1, class E2> 02539 Vector_<typename CNT<E1>::template Result<E2>::Sub> 02540 operator-(const VectorBase<E1>& l, const VectorBase<E2>& r) { 02541 return Vector_<typename CNT<E1>::template Result<E2>::Sub>(l) -= r; 02542 } 02543 template <class E> 02544 Vector_<E> operator-(const VectorBase<E>& l, const typename CNT<E>::T& r) { 02545 return Vector_<E>(l) -= r; 02546 } 02547 template <class E> 02548 Vector_<E> operator-(const typename CNT<E>::T& l, const VectorBase<E>& r) { 02549 Vector_<E> temp(r.size()); 02550 temp = l; 02551 return (temp -= r); 02552 } 02553 02554 template <class E> Vector_<E> 02555 operator*(const VectorBase<E>& l, const typename CNT<E>::StdNumber& r) 02556 { return Vector_<E>(l)*=r; } 02557 02558 template <class E> Vector_<E> 02559 operator*(const typename CNT<E>::StdNumber& l, const VectorBase<E>& r) 02560 { return Vector_<E>(r)*=l; } 02561 02562 template <class E> Vector_<E> 02563 operator/(const VectorBase<E>& l, const typename CNT<E>::StdNumber& r) 02564 { return Vector_<E>(l)/=r; } 02565 02566 // Handle ints explicitly 02567 template <class E> Vector_<E> 02568 operator*(const VectorBase<E>& l, int r) 02569 { return Vector_<E>(l)*= typename CNT<E>::StdNumber(r); } 02570 02571 template <class E> Vector_<E> 02572 operator*(int l, const VectorBase<E>& r) 02573 { return Vector_<E>(r)*= typename CNT<E>::StdNumber(l); } 02574 02575 template <class E> Vector_<E> 02576 operator/(const VectorBase<E>& l, int r) 02577 { return Vector_<E>(l)/= typename CNT<E>::StdNumber(r); } 02578 02580 02584 02585 template <class E1, class E2> 02586 RowVector_<typename CNT<E1>::template Result<E2>::Add> 02587 operator+(const RowVectorBase<E1>& l, const RowVectorBase<E2>& r) { 02588 return RowVector_<typename CNT<E1>::template Result<E2>::Add>(l) += r; 02589 } 02590 template <class E> 02591 RowVector_<E> operator+(const RowVectorBase<E>& l, const typename CNT<E>::T& r) { 02592 return RowVector_<E>(l) += r; 02593 } 02594 template <class E> 02595 RowVector_<E> operator+(const typename CNT<E>::T& l, const RowVectorBase<E>& r) { 02596 return RowVector_<E>(r) += l; 02597 } 02598 template <class E1, class E2> 02599 RowVector_<typename CNT<E1>::template Result<E2>::Sub> 02600 operator-(const RowVectorBase<E1>& l, const RowVectorBase<E2>& r) { 02601 return RowVector_<typename CNT<E1>::template Result<E2>::Sub>(l) -= r; 02602 } 02603 template <class E> 02604 RowVector_<E> operator-(const RowVectorBase<E>& l, const typename CNT<E>::T& r) { 02605 return RowVector_<E>(l) -= r; 02606 } 02607 template <class E> 02608 RowVector_<E> operator-(const typename CNT<E>::T& l, const RowVectorBase<E>& r) { 02609 RowVector_<E> temp(r.size()); 02610 temp = l; 02611 return (temp -= r); 02612 } 02613 02614 template <class E> RowVector_<E> 02615 operator*(const RowVectorBase<E>& l, const typename CNT<E>::StdNumber& r) 02616 { return RowVector_<E>(l)*=r; } 02617 02618 template <class E> RowVector_<E> 02619 operator*(const typename CNT<E>::StdNumber& l, const RowVectorBase<E>& r) 02620 { return RowVector_<E>(r)*=l; } 02621 02622 template <class E> RowVector_<E> 02623 operator/(const RowVectorBase<E>& l, const typename CNT<E>::StdNumber& r) 02624 { return RowVector_<E>(l)/=r; } 02625 02626 // Handle ints explicitly. 02627 template <class E> RowVector_<E> 02628 operator*(const RowVectorBase<E>& l, int r) 02629 { return RowVector_<E>(l)*= typename CNT<E>::StdNumber(r); } 02630 02631 template <class E> RowVector_<E> 02632 operator*(int l, const RowVectorBase<E>& r) 02633 { return RowVector_<E>(r)*= typename CNT<E>::StdNumber(l); } 02634 02635 template <class E> RowVector_<E> 02636 operator/(const RowVectorBase<E>& l, int r) 02637 { return RowVector_<E>(l)/= typename CNT<E>::StdNumber(r); } 02638 02640 02641 02646 02647 // TODO: these should use LAPACK! 02648 02649 // Dot product 02650 template <class E1, class E2> 02651 typename CNT<E1>::template Result<E2>::Mul 02652 operator*(const RowVectorBase<E1>& r, const VectorBase<E2>& v) { 02653 assert(r.ncol() == v.nrow()); 02654 typename CNT<E1>::template Result<E2>::Mul sum(0); 02655 for (int j=0; j < r.ncol(); ++j) 02656 sum += r(j) * v[j]; 02657 return sum; 02658 } 02659 02660 template <class E1, class E2> 02661 Vector_<typename CNT<E1>::template Result<E2>::Mul> 02662 operator*(const MatrixBase<E1>& m, const VectorBase<E2>& v) { 02663 assert(m.ncol() == v.nrow()); 02664 Vector_<typename CNT<E1>::template Result<E2>::Mul> res(m.nrow()); 02665 for (int i=0; i< m.nrow(); ++i) 02666 res[i] = m[i]*v; 02667 return res; 02668 } 02669 02670 template <class E1, class E2> 02671 Matrix_<typename CNT<E1>::template Result<E2>::Mul> 02672 operator*(const MatrixBase<E1>& m1, const MatrixBase<E2>& m2) { 02673 assert(m1.ncol() == m2.nrow()); 02674 Matrix_<typename CNT<E1>::template Result<E2>::Mul> 02675 res(m1.nrow(),m2.ncol()); 02676 02677 for (int j=0; j < res.ncol(); ++j) 02678 for (int i=0; i < res.nrow(); ++i) 02679 res(i,j) = m1[i] * m2(j); 02680 02681 return res; 02682 } 02683 02685 02686 // This "private" static method is used to implement VectorView's 02687 // fillVectorViewFromStream() and Vector's readVectorFromStream() 02688 // namespace-scope static methods, which are in turn used to implement 02689 // VectorView's and 02690 // Vector's stream extraction operators ">>". This method has to be in the 02691 // header file so that we don't need to pass streams through the API, but it 02692 // is not intended for use by users and has no Doxygen presence, unlike 02693 // fillArrayFromStream() and readArrayFromStream() and (more commonly) 02694 // the extraction operators. 02695 template <class T> static inline 02696 std::istream& readVectorFromStreamHelper 02697 (std::istream& in, bool isFixedSize, Vector_<T>& out) 02698 { 02699 // If already failed, bad, or eof, set failed bit and return without 02700 // touching the Vector. 02701 if (!in.good()) {in.setstate(std::ios::failbit); return in;} 02702 02703 // If the passed-in Vector isn't resizeable, then we have to treat it as 02704 // a fixed size VectorView regardless of the setting of the isFixedSize 02705 // argument. 02706 if (!out.isResizeable()) 02707 isFixedSize = true; // might be overriding the argument here 02708 02709 // numRequired will be ignored unless isFixedSize==true. 02710 const int numRequired = isFixedSize ? out.size() : 0; 02711 02712 if (!isFixedSize) 02713 out.clear(); // We're going to replace the entire contents of the Array. 02714 02715 // Skip initial whitespace. If that results in eof this may be a successful 02716 // read of a 0-length, unbracketed Vector. That is OK for either a 02717 // variable-length Vector or a fixed-length VectorView of length zero. 02718 std::ws(in); if (in.fail()) return in; 02719 if (in.eof()) { 02720 if (isFixedSize && numRequired != 0) 02721 in.setstate(std::ios_base::failbit); // zero elements not OK 02722 return in; 02723 } 02724 02725 // Here the stream is good and the next character is non-white. 02726 assert(in.good()); 02727 02728 // Use this for raw i/o (peeks and gets). 02729 typename std::iostream::int_type ch; 02730 const typename std::iostream::int_type EOFch = 02731 std::iostream::traits_type::eof(); 02732 02733 // First we'll look for the optional "~". If found, the brackets become 02734 // required. 02735 bool tildeFound = false; 02736 ch = in.peek(); if (in.fail()) return in; 02737 assert(ch != EOFch); // we already checked above 02738 if ((char)ch == '~') { 02739 tildeFound = true; 02740 in.get(); // absorb the tilde 02741 // Eat whitespace after the tilde to see what's next. 02742 if (in.good()) std::ws(in); 02743 // If we hit eof after the tilde we don't like the formatting. 02744 if (!in.good()) {in.setstate(std::ios_base::failbit); return in;} 02745 } 02746 02747 // Here the stream is good, the next character is non-white, and we 02748 // might have seen a tilde. 02749 assert(in.good()); 02750 02751 // Now see if the sequence is bare or surrounded by (), or []. 02752 bool lookForCloser = true; 02753 char openBracket, closeBracket; 02754 ch = in.peek(); if (in.fail()) return in; 02755 assert(ch != EOFch); // we already checked above 02756 02757 openBracket = (char)ch; 02758 if (openBracket=='(') {in.get(); closeBracket = ')';} 02759 else if (openBracket=='[') {in.get(); closeBracket = ']';} 02760 else lookForCloser = false; 02761 02762 // If we found a tilde, the opening bracket was mandatory. If we didn't 02763 // find one then we reject the formatting. 02764 if (tildeFound && !lookForCloser) 02765 { in.setstate(std::ios_base::failbit); return in;} 02766 02767 // If lookForCloser is true, then closeBracket contains the terminating 02768 // delimiter, otherwise we're not going to quit until eof. 02769 02770 // Eat whitespace after the opening bracket to see what's next. 02771 if (in.good()) std::ws(in); 02772 02773 // If we're at eof now it must be because the open bracket was the 02774 // last non-white character in the stream, which is an error. 02775 if (!in.good()) { 02776 if (in.eof()) { 02777 assert(lookForCloser); // or we haven't read anything that could eof 02778 in.setstate(std::ios::failbit); 02779 } 02780 return in; 02781 } 02782 02783 // istream is good and next character is non-white; ready to read first 02784 // value or terminator. 02785 02786 // We need to figure out whether the elements are space- or comma- 02787 // separated and then insist on consistency. 02788 bool commaOK = true, commaRequired = false; 02789 bool terminatorSeen = false; 02790 int nextIndex = 0; 02791 while (true) { 02792 char c; 02793 02794 // Here at the top of this loop, we have already successfully read 02795 // n=nextIndex values of type T. For fixed-size reads, it might be 02796 // the case that n==numRequired already, but we still may need to 02797 // look for a closing bracket before we can declare victory. 02798 // The stream is good() (not at eof) but it might be the case that 02799 // there is nothing but white space left; we don't know yet because 02800 // if we have satisfied the fixed-size count and are not expecting 02801 // a terminator then we should quit without absorbing the trailing 02802 // white space. 02803 assert(in.good()); 02804 02805 // Look for closing bracket before trying to read value. 02806 if (lookForCloser) { 02807 // Eat white space to find the closing bracket. 02808 std::ws(in); if (!in.good()) break; // eof? 02809 ch = in.peek(); assert(ch != EOFch); 02810 if (!in.good()) break; 02811 c = (char)ch; 02812 if (c == closeBracket) { 02813 in.get(); // absorb the closing bracket 02814 terminatorSeen = true; 02815 break; 02816 } 02817 // next char not a closing bracket; fall through 02818 } 02819 02820 // We didn't look or didn't find a closing bracket. The istream is good 02821 // but we might be looking at white space. 02822 02823 // If we already got all the elements we want, break for final checks. 02824 if (isFixedSize && (nextIndex == numRequired)) 02825 break; // that's a full count. 02826 02827 // Look for comma before value, except the first time. 02828 if (commaOK && nextIndex != 0) { 02829 // Eat white space to find the comma. 02830 std::ws(in); if (!in.good()) break; // eof? 02831 ch = in.peek(); assert(ch != EOFch); 02832 if (!in.good()) break; 02833 c = (char)ch; 02834 if (c == ',') { 02835 in.get(); // absorb comma 02836 commaRequired = true; // all commas from now on 02837 } else { // next char not a comma 02838 if (commaRequired) // bad, e.g.: v1, v2, v3 v4 02839 { in.setstate(std::ios::failbit); break; } 02840 else commaOK = false; // saw: v1 v2 (no commas now) 02841 } 02842 if (!in.good()) break; // might be eof 02843 } 02844 02845 // No closing bracket yet; don't have enough elements; skipped comma 02846 // if any; istream is good; might be looking at white space. 02847 assert(in.good()); 02848 02849 // Now read in an element of type T. 02850 // The extractor T::operator>>() will ignore leading white space. 02851 if (!isFixedSize) 02852 out.resizeKeep(out.size()+1); // grow by one (default consructed) 02853 in >> out[nextIndex]; if (in.fail()) break; 02854 ++nextIndex; 02855 02856 if (!in.good()) break; // might be eof 02857 } 02858 02859 // We will get here under a number of circumstances: 02860 // - the fail bit is set in the istream, or 02861 // - we reached eof 02862 // - we saw a closing brace 02863 // - we got all the elements we wanted (for a fixed-size read) 02864 // Note that it is possible that we consumed everything except some 02865 // trailing white space (meaning we're not technically at eof), but 02866 // for consistency with built-in operator>>()'s we won't try to absorb 02867 // that trailing white space. 02868 02869 if (!in.fail()) { 02870 if (lookForCloser && !terminatorSeen) 02871 in.setstate(std::ios::failbit); // missing terminator 02872 02873 if (isFixedSize && nextIndex != numRequired) 02874 in.setstate(std::ios::failbit); // wrong number of values 02875 } 02876 02877 return in; 02878 } 02879 02880 02881 02882 //------------------------------------------------------------------------------ 02883 // RELATED GLOBAL OPERATORS 02884 //------------------------------------------------------------------------------ 02885 // These are logically part of the Matrix_<T> class but are not actually 02886 // class members; that is, they are in the SimTK namespace. 02887 02895 02902 template <class T> inline std::ostream& 02903 operator<<(std::ostream& o, const VectorBase<T>& v) 02904 { o << "~["; for(int i=0;i<v.size();++i) o<<(i>0?" ":"")<<v[i]; 02905 return o << "]"; } 02906 02913 template <class T> inline std::ostream& 02914 operator<<(std::ostream& o, const RowVectorBase<T>& v) 02915 { o << "["; for(int i=0;i<v.size();++i) o<<(i>0?" ":"")<<v[i]; 02916 return o << "]"; } 02917 02925 template <class T> inline std::ostream& 02926 operator<<(std::ostream& o, const MatrixBase<T>& m) { 02927 for (int i=0;i<m.nrow();++i) 02928 o << std::endl << m[i]; 02929 if (m.nrow()) o << std::endl; 02930 return o; 02931 } 02932 02933 02965 template <class T> static inline 02966 std::istream& readVectorFromStream(std::istream& in, Vector_<T>& out) 02967 { return readVectorFromStreamHelper<T>(in, false /*variable sizez*/, out); } 02968 02969 02970 02995 template <class T> static inline 02996 std::istream& fillVectorFromStream(std::istream& in, Vector_<T>& out) 02997 { return readVectorFromStreamHelper<T>(in, true /*fixed size*/, out); } 02998 03003 template <class T> static inline 03004 std::istream& fillVectorViewFromStream(std::istream& in, VectorView_<T>& out) 03005 { return readVectorFromStreamHelper<T>(in, true /*fixed size*/, out); } 03006 03007 03017 template <class T> inline 03018 std::istream& operator>>(std::istream& in, Vector_<T>& out) 03019 { return readVectorFromStream<T>(in, out); } 03020 03028 template <class T> inline 03029 std::istream& operator>>(std::istream& in, VectorView_<T>& out) 03030 { return fillVectorViewFromStream<T>(in, out); } 03031 03034 // Friendly abbreviations for vectors and matrices with scalar elements. 03035 03036 typedef Vector_<Real> Vector; 03037 typedef Vector_<float> fVector; 03038 typedef Vector_<double> dVector; 03039 typedef Vector_<Complex> ComplexVector; 03040 typedef Vector_<fComplex> fComplexVector; 03041 typedef Vector_<dComplex> dComplexVector; 03042 03043 typedef VectorView_<Real> VectorView; 03044 typedef VectorView_<float> fVectorView; 03045 typedef VectorView_<double> dVectorView; 03046 typedef VectorView_<Complex> ComplexVectorView; 03047 typedef VectorView_<fComplex> fComplexVectorView; 03048 typedef VectorView_<dComplex> dComplexVectorView; 03049 03050 typedef RowVector_<Real> RowVector; 03051 typedef RowVector_<float> fRowVector; 03052 typedef RowVector_<double> dRowVector; 03053 typedef RowVector_<Complex> ComplexRowVector; 03054 typedef RowVector_<fComplex> fComplexRowVector; 03055 typedef RowVector_<dComplex> dComplexRowVector; 03056 03057 typedef RowVectorView_<Real> RowVectorView; 03058 typedef RowVectorView_<float> fRowVectorView; 03059 typedef RowVectorView_<double> dRowVectorView; 03060 typedef RowVectorView_<Complex> ComplexRowVectorView; 03061 typedef RowVectorView_<fComplex> fComplexRowVectorView; 03062 typedef RowVectorView_<dComplex> dComplexRowVectorView; 03063 03064 typedef Matrix_<Real> Matrix; 03065 typedef Matrix_<float> fMatrix; 03066 typedef Matrix_<double> dMatrix; 03067 typedef Matrix_<Complex> ComplexMatrix; 03068 typedef Matrix_<fComplex> fComplexMatrix; 03069 typedef Matrix_<dComplex> dComplexMatrix; 03070 03071 typedef MatrixView_<Real> MatrixView; 03072 typedef MatrixView_<float> fMatrixView; 03073 typedef MatrixView_<double> dMatrixView; 03074 typedef MatrixView_<Complex> ComplexMatrixView; 03075 typedef MatrixView_<fComplex> fComplexMatrixView; 03076 typedef MatrixView_<dComplex> dComplexMatrixView; 03077 03078 03083 template <class ELT, class VECTOR_CLASS> 03084 class VectorIterator { 03085 public: 03086 typedef ELT value_type; 03087 typedef int difference_type; 03088 typedef ELT& reference; 03089 typedef ELT* pointer; 03090 typedef std::random_access_iterator_tag iterator_category; 03091 VectorIterator(VECTOR_CLASS& vector, int index) : vector(vector), index(index) { 03092 } 03093 VectorIterator(const VectorIterator& iter) : vector(iter.vector), index(iter.index) { 03094 } 03095 VectorIterator& operator=(const VectorIterator& iter) { 03096 vector = iter.vector; 03097 index = iter.index; 03098 return *this; 03099 } 03100 ELT& operator*() { 03101 assert (index >= 0 && index < vector.size()); 03102 return vector[index]; 03103 } 03104 ELT& operator[](int i) { 03105 assert (i >= 0 && i < vector.size()); 03106 return vector[i]; 03107 } 03108 VectorIterator operator++() { 03109 assert (index < vector.size()); 03110 ++index; 03111 return *this; 03112 } 03113 VectorIterator operator++(int) { 03114 assert (index < vector.size()); 03115 VectorIterator current = *this; 03116 ++index; 03117 return current; 03118 } 03119 VectorIterator operator--() { 03120 assert (index > 0); 03121 --index; 03122 return *this; 03123 } 03124 VectorIterator operator--(int) { 03125 assert (index > 0); 03126 VectorIterator current = *this; 03127 --index; 03128 return current; 03129 } 03130 bool operator<(VectorIterator iter) const { 03131 return (index < iter.index); 03132 } 03133 bool operator>(VectorIterator iter) const { 03134 return (index > iter.index); 03135 } 03136 bool operator<=(VectorIterator iter) const { 03137 return (index <= iter.index); 03138 } 03139 bool operator>=(VectorIterator iter) const { 03140 return (index >= iter.index); 03141 } 03142 int operator-(VectorIterator iter) const { 03143 return (index - iter.index); 03144 } 03145 VectorIterator operator-(int n) const { 03146 return VectorIterator(vector, index-n); 03147 } 03148 VectorIterator operator+(int n) const { 03149 return VectorIterator(vector, index+n); 03150 } 03151 bool operator==(VectorIterator iter) const { 03152 return (index == iter.index); 03153 } 03154 bool operator!=(VectorIterator iter) const { 03155 return (index != iter.index); 03156 } 03157 private: 03158 VECTOR_CLASS& vector; 03159 int index; 03160 }; 03161 03162 } //namespace SimTK 03163 03164 #endif //SimTK_SIMMATRIX_BIGMATRIX_H_