Row.h

Go to the documentation of this file.
00001 #ifndef SimTK_SIMMATRIX_SMALLMATRIX_ROW_H_
00002 #define SimTK_SIMMATRIX_SMALLMATRIX_ROW_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                      SimTK Core: SimTK Simmatrix(tm)                       *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK Core biosimulation toolkit originating from      *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org.               *
00011  *                                                                            *
00012  * Portions copyright (c) 2005-7 Stanford University and the Authors.         *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors:                                                              *
00015  *                                                                            *
00016  * Permission is hereby granted, free of charge, to any person obtaining a    *
00017  * copy of this software and associated documentation files (the "Software"), *
00018  * to deal in the Software without restriction, including without limitation  *
00019  * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
00020  * and/or sell copies of the Software, and to permit persons to whom the      *
00021  * Software is furnished to do so, subject to the following conditions:       *
00022  *                                                                            *
00023  * The above copyright notice and this permission notice shall be included in *
00024  * all copies or substantial portions of the Software.                        *
00025  *                                                                            *
00026  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
00027  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
00028  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
00029  * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
00030  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
00031  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
00032  * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
00033  * -------------------------------------------------------------------------- */
00034 
00039 #include "SimTKcommon/internal/common.h"
00040 
00041 
00042 namespace SimTK {
00043 
00044 
00046 template <int N, class ELT, int STRIDE> class Row {
00047     typedef ELT                                 E;
00048     typedef typename CNT<E>::TNeg               ENeg;
00049     typedef typename CNT<E>::TWithoutNegator    EWithoutNegator;
00050     typedef typename CNT<E>::TReal              EReal;
00051     typedef typename CNT<E>::TImag              EImag;
00052     typedef typename CNT<E>::TComplex           EComplex;
00053     typedef typename CNT<E>::THerm              EHerm;
00054     typedef typename CNT<E>::TPosTrans          EPosTrans;
00055     typedef typename CNT<E>::TSqHermT           ESqHermT;
00056     typedef typename CNT<E>::TSqTHerm           ESqTHerm;
00057 
00058     typedef typename CNT<E>::TAbs               EAbs;
00059     typedef typename CNT<E>::TStandard          EStandard;
00060     typedef typename CNT<E>::TInvert            EInvert;
00061     typedef typename CNT<E>::TNormalize         ENormalize;
00062 
00063     typedef typename CNT<E>::Scalar             EScalar;
00064     typedef typename CNT<E>::Number             ENumber;
00065     typedef typename CNT<E>::StdNumber          EStdNumber;
00066     typedef typename CNT<E>::Precision          EPrecision;
00067     typedef typename CNT<E>::ScalarSq           EScalarSq;
00068 
00069 public:
00070 
00071     enum {
00072         NRows               = 1,
00073         NCols               = N,
00074         RowSpacing          = 1,
00075         ColSpacing          = STRIDE,
00076         NPackedElements     = N,
00077         NActualElements     = N * STRIDE,   // includes trailing gap
00078         NActualScalars      = CNT<E>::NActualScalars * NActualElements,
00079         ImagOffset          = NTraits<ENumber>::ImagOffset,
00080         RealStrideFactor    = 1, // composite types don't change size when
00081                                  // cast from complex to real or imaginary
00082         ArgDepth            = ((int)CNT<E>::ArgDepth < (int)MAX_RESOLVED_DEPTH 
00083                                 ? CNT<E>::ArgDepth + 1 
00084                                 : MAX_RESOLVED_DEPTH),
00085         IsScalar            = 0,
00086         IsNumber            = 0,
00087         IsStdNumber         = 0,
00088         IsPrecision         = 0,
00089         SignInterpretation  = CNT<E>::SignInterpretation
00090     };
00091 
00092     typedef Row<N,E,STRIDE>                 T;
00093     typedef Row<N,ENeg,STRIDE>              TNeg;
00094     typedef Row<N,EWithoutNegator,STRIDE>   TWithoutNegator;
00095 
00096     typedef Row<N,EReal,STRIDE*CNT<E>::RealStrideFactor>         
00097                                             TReal;
00098     typedef Row<N,EImag,STRIDE*CNT<E>::RealStrideFactor>         
00099                                             TImag;
00100     typedef Row<N,EComplex,STRIDE>          TComplex;
00101     typedef Vec<N,EHerm,STRIDE>             THerm;
00102     typedef Vec<N,E,STRIDE>                 TPosTrans;
00103     typedef E                               TElement;
00104     typedef Row                             TRow;
00105     typedef E                               TCol;
00106 
00107     // These are the results of calculations, so are returned in new, packed
00108     // memory. Be sure to refer to element types here which are also packed.
00109     typedef Row<N,EAbs,1>                   TAbs;       // Note stride
00110     typedef Row<N,EStandard,1>              TStandard;
00111     typedef Vec<N,EInvert,1>                TInvert;    // packed
00112     typedef Row<N,ENormalize,1>             TNormalize;
00113 
00114     typedef SymMat<N,ESqHermT>              TSqHermT;   // result of self outer product
00115     typedef EScalarSq                       TSqTHerm;   // result of self dot product
00116 
00117     // These recurse right down to the underlying scalar type no matter how
00118     // deep the elements are.
00119     typedef EScalar                         Scalar;
00120     typedef ENumber                         Number;
00121     typedef EStdNumber                      StdNumber;
00122     typedef EPrecision                      Precision;
00123     typedef EScalarSq                       ScalarSq;
00124 
00125     int size()   const  { return N; }
00126     int nrow()   const  { return 1; }
00127     int ncol()   const  { return N; }
00128 
00129 
00130     // Scalar norm square is sum( squares of all scalars )
00131     ScalarSq scalarNormSqr() const { 
00132         ScalarSq sum(0);
00133         for(int i=0;i<N;++i) sum += CNT<E>::scalarNormSqr(d[i*STRIDE]);
00134         return sum;
00135     }
00136 
00137     // abs() is elementwise absolute value; that is, the return value has the same
00138     // dimension as this Row but with each element replaced by whatever it thinks
00139     // its absolute value is.
00140     TAbs abs() const {
00141         TAbs rabs;
00142         for(int i=0;i<N;++i) rabs[i] = CNT<E>::abs(d[i*STRIDE]);
00143         return rabs;
00144     }
00145 
00146     TStandard standardize() const {
00147         TStandard rstd;
00148         for(int i=0;i<N;++i) rstd[i] = CNT<E>::standardize(d[i*STRIDE]);
00149         return rstd;
00150     }
00151 
00152     // Sum just adds up all the elements, getting rid of negators and
00153     // conjugates in the process.
00154     EStandard sum() const {
00155         E sum(0);
00156         for (int i=0;i<N;++i) sum += d[i*STRIDE];
00157         return CNT<E>::standardize(sum);
00158     }
00159 
00160     // This gives the resulting rowvector type when (v[i] op P) is applied to each element of v.
00161     // It is a row of length N, stride 1, and element types which are the regular
00162     // composite result of E op P. Typically P is a scalar type but it doesn't have to be.
00163     template <class P> struct EltResult { 
00164         typedef Row<N, typename CNT<E>::template Result<P>::Mul, 1> Mul;
00165         typedef Row<N, typename CNT<E>::template Result<P>::Dvd, 1> Dvd;
00166         typedef Row<N, typename CNT<E>::template Result<P>::Add, 1> Add;
00167         typedef Row<N, typename CNT<E>::template Result<P>::Sub, 1> Sub;
00168     };
00169 
00170     // This is the composite result for v op P where P is some kind of appropriately shaped
00171     // non-scalar type.
00172     template <class P> struct Result { 
00173         typedef MulCNTs<1,N,ArgDepth,Row,ColSpacing,RowSpacing,
00174             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00175             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> MulOp;
00176         typedef typename MulOp::Type Mul;
00177 
00178         typedef MulCNTsNonConforming<1,N,ArgDepth,Row,ColSpacing,RowSpacing,
00179             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00180             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> MulOpNonConforming;
00181         typedef typename MulOpNonConforming::Type MulNon;
00182 
00183 
00184         typedef DvdCNTs<1,N,ArgDepth,Row,ColSpacing,RowSpacing,
00185             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00186             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> DvdOp;
00187         typedef typename DvdOp::Type Dvd;
00188 
00189         typedef AddCNTs<1,N,ArgDepth,Row,ColSpacing,RowSpacing,
00190             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00191             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> AddOp;
00192         typedef typename AddOp::Type Add;
00193 
00194         typedef SubCNTs<1,N,ArgDepth,Row,ColSpacing,RowSpacing,
00195             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00196             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> SubOp;
00197         typedef typename SubOp::Type Sub;
00198     };
00199 
00200     // Shape-preserving element substitution (always packed)
00201     template <class P> struct Substitute {
00202         typedef Row<N,P> Type;
00203     };
00204 
00205     // Default construction initializes to NaN when debugging but
00206     // is left uninitialized otherwise.
00207     Row(){ 
00208     #ifndef NDEBUG
00209         setToNaN();
00210     #endif
00211     }
00212 
00213     // It's important not to use the default copy constructor or copy
00214     // assignment because the compiler doesn't understand that we may
00215     // have noncontiguous storage and will try to copy the whole array.
00216     Row(const Row& src) {
00217         for (int i=0; i<N; ++i)
00218             d[i*STRIDE] = src[i];
00219     }
00220     Row& operator=(const Row& src) {    // no harm if src and 'this' are the same
00221         for (int i=0; i<N; ++i)
00222             d[i*STRIDE] = src[i];
00223         return *this;
00224     }
00225 
00226     // We want an implicit conversion from a Row of the same length
00227     // and element type but with a different stride.
00228     template <int SS> Row(const Row<N,E,SS>& src) {
00229         for (int i=0; i<N; ++i)
00230             d[i*STRIDE] = src[i];
00231     }
00232 
00233     // We want an implicit conversion from a Row of the same length
00234     // and *negated* element type, possibly with a different stride.
00235     template <int SS> Row(const Row<N,ENeg,SS>& src) {
00236         for (int i=0; i<N; ++i)
00237             d[i*STRIDE] = src[i];
00238     }
00239 
00240     // Construct a Row from a Row of the same length, with any
00241     // stride. Works as long as the element types are compatible.
00242     template <class EE, int SS> explicit Row(const Row<N,EE,SS>& vv)
00243       { for (int i=0;i<N;++i) d[i*STRIDE]=vv[i]; }
00244 
00245     // Construction using an element assigns to each element.
00246     explicit Row(const ELT& e)
00247       { for (int i=0;i<N;++i) d[i*STRIDE]=e; }
00248 
00249     // A bevy of constructors for Rows up to length 6.
00250     Row(const E& e0,const E& e1)
00251       { assert(N==2);(*this)[0]=e0;(*this)[1]=e1; }
00252     Row(const E& e0,const E& e1,const E& e2)
00253       { assert(N==3);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2; }
00254     Row(const E& e0,const E& e1,const E& e2,const E& e3)
00255       { assert(N==4);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;(*this)[3]=e3; }
00256     Row(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4)
00257       { assert(N==5);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;
00258         (*this)[3]=e3;(*this)[4]=e4; }
00259     Row(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,const E& e5)
00260       { assert(N==6);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;
00261         (*this)[3]=e3;(*this)[4]=e4;(*this)[5]=e5; }
00262 
00263     // Construction from a pointer to anything assumes we're pointing
00264     // at an element list of the right length.
00265     template <class EE> explicit Row(const EE* p)
00266       { assert(p); for(int i=0;i<N;++i) d[i*STRIDE]=p[i]; }
00267     template <class EE> Row& operator=(const EE* p)
00268       { assert(p); for(int i=0;i<N;++i) d[i*STRIDE]=p[i]; return *this; }
00269 
00270     // Conforming assignment ops.
00271     template <class EE, int SS> Row& operator=(const Row<N,EE,SS>& vv)
00272       { for(int i=0;i<N;++i) d[i*STRIDE] = vv[i]; return *this; }
00273     template <class EE, int SS> Row& operator+=(const Row<N,EE,SS>& r)
00274       { for(int i=0;i<N;++i) d[i*STRIDE] += r[i]; return *this; }
00275     template <class EE, int SS> Row& operator+=(const Row<N,negator<EE>,SS>& r)
00276       { for(int i=0;i<N;++i) d[i*STRIDE] -= -(r[i]); return *this; }
00277     template <class EE, int SS> Row& operator-=(const Row<N,EE,SS>& r)
00278       { for(int i=0;i<N;++i) d[i*STRIDE] -= r[i]; return *this; }
00279     template <class EE, int SS> Row& operator-=(const Row<N,negator<EE>,SS>& r)
00280       { for(int i=0;i<N;++i) d[i*STRIDE] += -(r[i]); return *this; }
00281 
00282     // Conforming binary ops with 'this' on left, producing new packed result.
00283     // Cases: r=r+r, r=r-r, s=r*v r=r*m
00284     template <class EE, int SS> Row<N,typename CNT<E>::template Result<EE>::Add>
00285     conformingAdd(const Row<N,EE,SS>& r) const {
00286         Row<N,typename CNT<E>::template Result<EE>::Add> result;
00287         for (int j=0;j<N;++j) result[j] = (*this)[j] + r[j];
00288         return result;
00289     }
00290     template <class EE, int SS> Row<N,typename CNT<E>::template Result<EE>::Sub>
00291     conformingSubtract(const Row<N,EE,SS>& r) const {
00292         Row<N,typename CNT<E>::template Result<EE>::Sub> result;
00293         for (int j=0;j<N;++j) result[j] = (*this)[j] - r[j];
00294         return result;
00295     }
00296 
00297     // dot product
00298     template <class EE, int SS> typename CNT<E>::template Result<EE>::Mul
00299     conformingMultiply(const Vec<N,EE,SS>& r) const {
00300         typename CNT<E>::template Result<EE>::Mul result(0);
00301         for (int j=0;j<N;++j) result += (*this)[j]*r[j];
00302         return result;
00303     }
00304 
00305     // row=row*mat
00306     template <int MatNCol, class EE, int CS, int RS> 
00307     Row<MatNCol,typename CNT<E>::template Result<EE>::Mul>
00308     conformingMultiply(const Mat<N,MatNCol,EE,CS,RS>& m) const {
00309         Row<MatNCol,typename CNT<E>::template Result<EE>::Mul> result;
00310         for (int j=0;j<N;++j) result[j] = conformingMultiply(m(j));
00311         return result;
00312     }
00313 
00314     const E& operator[](int i) const { assert(0 <= i && i < N); return d[i*STRIDE]; }
00315     E&       operator[](int i)       { assert(0 <= i && i < N); return d[i*STRIDE]; }
00316     const E& operator()(int i) const { return (*this)[i]; }
00317     E&       operator()(int i)       { return (*this)[i]; }
00318 
00319     ScalarSq normSqr() const { return scalarNormSqr(); }
00320     ScalarSq norm()    const { return std::sqrt(scalarNormSqr()); }
00321 
00322     // If the elements of this Row are scalars, the result is what you get by
00323     // dividing each element by the norm() calculated above. If the elements are
00324     // *not* scalars, then the elements are *separately* normalized. That means
00325     // you will get a different answer from Row<2,Row3>::normalize() than you
00326     // would from a Row<6>::normalize() containing the same scalars.
00327     //
00328     // Normalize returns a row of the same dimension but in new, packed storage
00329     // and with a return type that does not include negator<> even if the original
00330     // Row<> does, because we can eliminate the negation here almost for free.
00331     // But we can't standardize (change conjugate to complex) for free, so we'll retain
00332     // conjugates if there are any.
00333     TNormalize normalize() const {
00334         if (CNT<E>::IsScalar) {
00335             return castAwayNegatorIfAny() / (SignInterpretation*norm());
00336         } else {
00337             TNormalize elementwiseNormalized;
00338             for (int j=0; j<N; ++j) 
00339                 elementwiseNormalized[j] = CNT<E>::normalize((*this)[j]);
00340             return elementwiseNormalized;
00341         }
00342     }
00343 
00344     TInvert invert() const {assert(false); return TInvert();} // TODO default inversion
00345 
00346     const Row&   operator+() const { return *this; }
00347     const TNeg&  operator-() const { return negate(); }
00348     TNeg&        operator-()       { return updNegate(); }
00349     const THerm& operator~() const { return transpose(); }
00350     THerm&       operator~()       { return updTranspose(); }
00351 
00352     const TNeg&  negate() const { return *reinterpret_cast<const TNeg*>(this); }
00353     TNeg&        updNegate()    { return *reinterpret_cast<TNeg*>(this); }
00354 
00355     const THerm& transpose()    const { return *reinterpret_cast<const THerm*>(this); }
00356     THerm&       updTranspose()       { return *reinterpret_cast<THerm*>(this); }
00357 
00358     const TPosTrans& positionalTranspose() const
00359         { return *reinterpret_cast<const TPosTrans*>(this); }
00360     TPosTrans&       updPositionalTranspose()
00361         { return *reinterpret_cast<TPosTrans*>(this); }
00362 
00363     const TReal& real() const { return *reinterpret_cast<const TReal*>(this); }
00364     TReal&       real()       { return *reinterpret_cast<      TReal*>(this); }
00365 
00366     // Had to contort these routines to get them through VC++ 7.net
00367     const TImag& imag()    const { 
00368         const int offs = ImagOffset;
00369         const EImag* p = reinterpret_cast<const EImag*>(this);
00370         return *reinterpret_cast<const TImag*>(p+offs);
00371     }
00372     TImag& imag() { 
00373         const int offs = ImagOffset;
00374         EImag* p = reinterpret_cast<EImag*>(this);
00375         return *reinterpret_cast<TImag*>(p+offs);
00376     }
00377 
00378     const TWithoutNegator& castAwayNegatorIfAny() const {return *reinterpret_cast<const TWithoutNegator*>(this);}
00379     TWithoutNegator&       updCastAwayNegatorIfAny()    {return *reinterpret_cast<TWithoutNegator*>(this);}
00380 
00381 
00382     // These are elementwise binary operators, (this op ee) by default but (ee op this) if
00383     // 'FromLeft' appears in the name. The result is a packed Row<N> but the element type
00384     // may change. These are mostly used to implement global operators.
00385 
00386     //TODO: consider converting 'e' to Standard Numbers as precalculation and changing
00387     // return type appropriately.
00388     template <class EE> Row<N, typename CNT<E>::template Result<EE>::Mul>
00389     scalarMultiply(const EE& e) const {
00390         Row<N, typename CNT<E>::template Result<EE>::Mul> result;
00391         for (int j=0; j<N; ++j) result[j] = (*this)[j] * e;
00392         return result;
00393     }
00394     template <class EE> Row<N, typename CNT<EE>::template Result<E>::Mul>
00395     scalarMultiplyFromLeft(const EE& e) const {
00396         Row<N, typename CNT<EE>::template Result<E>::Mul> result;
00397         for (int j=0; j<N; ++j) result[j] = e * (*this)[j];
00398         return result;
00399     }
00400 
00401     // TODO: should precalculate and store 1/e, while converting to Standard Numbers. Note
00402     // that return type should change appropriately.
00403     template <class EE> Row<N, typename CNT<E>::template Result<EE>::Dvd>
00404     scalarDivide(const EE& e) const {
00405         Row<N, typename CNT<E>::template Result<EE>::Dvd> result;
00406         for (int j=0; j<N; ++j) result[j] = (*this)[j] / e;
00407         return result;
00408     }
00409     template <class EE> Row<N, typename CNT<EE>::template Result<E>::Dvd>
00410     scalarDivideFromLeft(const EE& e) const {
00411         Row<N, typename CNT<EE>::template Result<E>::Dvd> result;
00412         for (int j=0; j<N; ++j) result[j] = e / (*this)[j];
00413         return result;
00414     }
00415 
00416     template <class EE> Row<N, typename CNT<E>::template Result<EE>::Add>
00417     scalarAdd(const EE& e) const {
00418         Row<N, typename CNT<E>::template Result<EE>::Add> result;
00419         for (int j=0; j<N; ++j) result[j] = (*this)[j] + e;
00420         return result;
00421     }
00422     // Add is commutative, so no 'FromLeft'.
00423 
00424     template <class EE> Row<N, typename CNT<E>::template Result<EE>::Sub>
00425     scalarSubtract(const EE& e) const {
00426         Row<N, typename CNT<E>::template Result<EE>::Sub> result;
00427         for (int j=0; j<N; ++j) result[j] = (*this)[j] - e;
00428         return result;
00429     }
00430     template <class EE> Row<N, typename CNT<EE>::template Result<E>::Sub>
00431     scalarSubtractFromLeft(const EE& e) const {
00432         Row<N, typename CNT<EE>::template Result<E>::Sub> result;
00433         for (int j=0; j<N; ++j) result[j] = e - (*this)[j];
00434         return result;
00435     }
00436 
00437     // Generic assignments for any element type not listed explicitly, including scalars.
00438     // These are done repeatedly for each element and only work if the operation can
00439     // be performed leaving the original element type.
00440     template <class EE> Row& operator =(const EE& e) {return scalarEq(e);}
00441     template <class EE> Row& operator+=(const EE& e) {return scalarPlusEq(e);}
00442     template <class EE> Row& operator-=(const EE& e) {return scalarMinusEq(e);}
00443     template <class EE> Row& operator*=(const EE& e) {return scalarTimesEq(e);}
00444     template <class EE> Row& operator/=(const EE& e) {return scalarDivideEq(e);}
00445 
00446     // Generalized scalar assignment & computed assignment methods. These will work
00447     // for any assignment-compatible element, not just scalars.
00448     template <class EE> Row& scalarEq(const EE& ee)
00449       { for(int i=0;i<N;++i) d[i*STRIDE] = ee; return *this; }
00450     template <class EE> Row& scalarPlusEq(const EE& ee)
00451       { for(int i=0;i<N;++i) d[i*STRIDE] += ee; return *this; }
00452     template <class EE> Row& scalarMinusEq(const EE& ee)
00453       { for(int i=0;i<N;++i) d[i*STRIDE] -= ee; return *this; }
00454     template <class EE> Row& scalarInverseMinusEq(const EE& ee)
00455       { for(int i=0;i<N;++i) d[i*STRIDE] = ee - d[i*STRIDE]; return *this; }
00456     template <class EE> Row& scalarTimesEq(const EE& ee)
00457       { for(int i=0;i<N;++i) d[i*STRIDE] *= ee; return *this; }
00458     template <class EE> Row& scalarDivideEq(const EE& ee)
00459       { for(int i=0;i<N;++i) d[i*STRIDE] /= ee; return *this; }
00460     template <class EE> Row& scalarInverseDivideEq(const EE& ee)
00461       { for(int i=0;i<N;++i) d[i*STRIDE] = ee / d[i*STRIDE]; return *this; }
00462 
00463     void setToNaN() {
00464         (*this) = CNT<ELT>::getNaN();
00465     }
00466 
00467     // Extract a sub-Row with size known at compile time. These have to be
00468     // called with explicit template arguments, e.g. getSubRow<3>(j).
00469     template <int NN>
00470     const Row<NN,ELT,STRIDE>& getSubRow(int j) const {
00471         assert(0 <= j && j + NN <= N);
00472         return Row<NN,ELT,STRIDE>::getAs(&(*this)[j]);
00473     }
00474     template <int NN>
00475     Row<NN,ELT,STRIDE>& updSubRow(int j) {
00476         assert(0 <= j && j + NN <= N);
00477         return Row<NN,ELT,STRIDE>::updAs(&(*this)[j]);
00478     }
00479 
00480     // Return a row one smaller than this one by dropping the element
00481     // at the indicated position p. The result is packed but has same
00482     // element type as this one.
00483     Row<N-1,ELT,1> drop1(int p) const {
00484         assert(0 <= p && p < N);
00485         Row<N-1,ELT,1> out;
00486         int nxt=0;
00487         for (int i=0; i<N-1; ++i, ++nxt) {
00488             if (nxt==p) ++nxt;  // skip the loser
00489             out[i] = (*this)[nxt];
00490         }
00491         return out;
00492     }
00493 
00494     // Return a vector one larger than this one by adding an element
00495     // to the end. The result is packed but has same element type as
00496     // this one. Works for any assignment compatible element.
00497     template <class EE> Row<N+1,ELT,1> append1(const EE& v) const {
00498         Row<N+1,ELT,1> out;
00499         Row<N,ELT,1>::updAs(&out[0]) = (*this);
00500         out[N] = v;
00501         return out;
00502     }
00503 
00504 
00505     // Return a vector one larger than this one by inserting an element
00506     // *before* the indicated one. The result is packed but has same element type as
00507     // this one. Works for any assignment compatible element. The index
00508     // can be one greater than normally allowed in which case the element
00509     // is appended.
00510     template <class EE> Row<N+1,ELT,1> insert1(int p, const EE& v) const {
00511         assert(0 <= p && p <= N);
00512         if (p==N) return append1(v);
00513         Row<N+1,ELT,1> out;
00514         int nxt=0;
00515         for (int i=0; i<N; ++i, ++nxt) {
00516             if (i==p) out[nxt++] = v;
00517             out[nxt] = (*this)[i];
00518         }
00519         return out;
00520     }
00521 
00522     // These assume we are given a pointer to d[0] of a Row<N,E,S> like this one.
00523     static const Row& getAs(const ELT* p)  {return *reinterpret_cast<const Row*>(p);}
00524     static Row&       updAs(ELT* p)        {return *reinterpret_cast<Row*>(p);}
00525 
00526     // Extract a subrow from a longer one. Element type and stride must match.
00527     template <int NN>
00528     static const Row& getSubRow(const Row<NN,ELT,STRIDE>& r, int j) {
00529         assert(0 <= j && j + N <= NN);
00530         return getAs(&r[j]);
00531     }
00532     template <int NN>
00533     static Row& updSubRow(Row<NN,ELT,STRIDE>& r, int j) {
00534         assert(0 <= j && j + N <= NN);
00535         return updAs(&r[j]);
00536     }
00537 
00538     static Row<N,ELT,1> getNaN() { return Row<N,ELT,1>(CNT<ELT>::getNaN()); }
00539 private:
00540     ELT d[NActualElements];    // data
00541 };
00542 
00544 // Global operators involving two rows.    //
00545 //   v+v, v-v, v==v, v!=v                  //
00547 
00548 // v3 = v1 + v2 where all v's have the same length N. 
00549 template <int N, class E1, int S1, class E2, int S2> inline
00550 typename Row<N,E1,S1>::template Result< Row<N,E2,S2> >::Add
00551 operator+(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r) { 
00552     return Row<N,E1,S1>::template Result< Row<N,E2,S2> >
00553         ::AddOp::perform(l,r);
00554 }
00555 
00556 // v3 = v1 - v2, similar to +
00557 template <int N, class E1, int S1, class E2, int S2> inline
00558 typename Row<N,E1,S1>::template Result< Row<N,E2,S2> >::Sub
00559 operator-(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r) { 
00560     return Row<N,E1,S1>::template Result< Row<N,E2,S2> >
00561         ::SubOp::perform(l,r);
00562 }
00563 
00564 // bool = v1 == v2, v1 and v2 have the same length M
00565 template <int N, class E1, int S1, class E2, int S2> inline bool
00566 operator==(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r) { 
00567     for (int i=0; i < N; ++i)
00568         if (l[i] != r[i]) return false;
00569     return true;
00570 }
00571 
00572 // bool = v1 != v2, v1 and v2 have the same length M
00573 template <int N, class E1, int S1, class E2, int S2> inline bool
00574 operator!=(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r) {return !(l==r);} 
00575 
00576 
00578 // Global operators involving a row and a scalar. //
00580 
00581 // I haven't been able to figure out a nice way to templatize for the
00582 // built-in reals without introducing a lot of unwanted type matches
00583 // as well. So we'll just grind them out explicitly here.
00584 
00585 // SCALAR MULTIPLY
00586 
00587 // v = v*real, real*v 
00588 template <int N, class E, int S> inline
00589 typename Row<N,E,S>::template Result<float>::Mul
00590 operator*(const Row<N,E,S>& l, const float& r)
00591   { return Row<N,E,S>::template Result<float>::MulOp::perform(l,r); }
00592 template <int N, class E, int S> inline
00593 typename Row<N,E,S>::template Result<float>::Mul
00594 operator*(const float& l, const Row<N,E,S>& r) {return r*l;}
00595 
00596 template <int N, class E, int S> inline
00597 typename Row<N,E,S>::template Result<double>::Mul
00598 operator*(const Row<N,E,S>& l, const double& r)
00599   { return Row<N,E,S>::template Result<double>::MulOp::perform(l,r); }
00600 template <int N, class E, int S> inline
00601 typename Row<N,E,S>::template Result<double>::Mul
00602 operator*(const double& l, const Row<N,E,S>& r) {return r*l;}
00603 
00604 template <int N, class E, int S> inline
00605 typename Row<N,E,S>::template Result<long double>::Mul
00606 operator*(const Row<N,E,S>& l, const long double& r)
00607   { return Row<N,E,S>::template Result<long double>::MulOp::perform(l,r); }
00608 template <int N, class E, int S> inline
00609 typename Row<N,E,S>::template Result<long double>::Mul
00610 operator*(const long double& l, const Row<N,E,S>& r) {return r*l;}
00611 
00612 // v = v*int, int*v -- just convert int to v's precision float
00613 template <int N, class E, int S> inline
00614 typename Row<N,E,S>::template Result<typename CNT<E>::Precision>::Mul
00615 operator*(const Row<N,E,S>& l, int r) {return l * (typename CNT<E>::Precision)r;}
00616 template <int N, class E, int S> inline
00617 typename Row<N,E,S>::template Result<typename CNT<E>::Precision>::Mul
00618 operator*(int l, const Row<N,E,S>& r) {return r * (typename CNT<E>::Precision)l;}
00619 
00620 // Complex, conjugate, and negator are all easy to templatize.
00621 
00622 // v = v*complex, complex*v
00623 template <int N, class E, int S, class R> inline
00624 typename Row<N,E,S>::template Result<std::complex<R> >::Mul
00625 operator*(const Row<N,E,S>& l, const std::complex<R>& r)
00626   { return Row<N,E,S>::template Result<std::complex<R> >::MulOp::perform(l,r); }
00627 template <int N, class E, int S, class R> inline
00628 typename Row<N,E,S>::template Result<std::complex<R> >::Mul
00629 operator*(const std::complex<R>& l, const Row<N,E,S>& r) {return r*l;}
00630 
00631 // v = v*conjugate, conjugate*v (convert conjugate->complex)
00632 template <int N, class E, int S, class R> inline
00633 typename Row<N,E,S>::template Result<std::complex<R> >::Mul
00634 operator*(const Row<N,E,S>& l, const conjugate<R>& r) {return l*(std::complex<R>)r;}
00635 template <int N, class E, int S, class R> inline
00636 typename Row<N,E,S>::template Result<std::complex<R> >::Mul
00637 operator*(const conjugate<R>& l, const Row<N,E,S>& r) {return r*(std::complex<R>)l;}
00638 
00639 // v = v*negator, negator*v: convert negator to standard number
00640 template <int N, class E, int S, class R> inline
00641 typename Row<N,E,S>::template Result<typename negator<R>::StdNumber>::Mul
00642 operator*(const Row<N,E,S>& l, const negator<R>& r) {return l * (typename negator<R>::StdNumber)(R)r;}
00643 template <int N, class E, int S, class R> inline
00644 typename Row<N,E,S>::template Result<typename negator<R>::StdNumber>::Mul
00645 operator*(const negator<R>& l, const Row<N,E,S>& r) {return r * (typename negator<R>::StdNumber)(R)l;}
00646 
00647 
00648 // SCALAR DIVIDE. This is a scalar operation when the scalar is on the right,
00649 // but when it is on the left it means scalar * pseudoInverse(row), which is a vec.
00650 
00651 // v = v/real, real/v 
00652 template <int N, class E, int S> inline
00653 typename Row<N,E,S>::template Result<float>::Dvd
00654 operator/(const Row<N,E,S>& l, const float& r)
00655   { return Row<N,E,S>::template Result<float>::DvdOp::perform(l,r); }
00656 template <int N, class E, int S> inline
00657 typename CNT<float>::template Result<Row<N,E,S> >::Dvd
00658 operator/(const float& l, const Row<N,E,S>& r)
00659   { return CNT<float>::template Result<Row<N,E,S> >::DvdOp::perform(l,r); }
00660 
00661 template <int N, class E, int S> inline
00662 typename Row<N,E,S>::template Result<double>::Dvd
00663 operator/(const Row<N,E,S>& l, const double& r)
00664   { return Row<N,E,S>::template Result<double>::DvdOp::perform(l,r); }
00665 template <int N, class E, int S> inline
00666 typename CNT<double>::template Result<Row<N,E,S> >::Dvd
00667 operator/(const double& l, const Row<N,E,S>& r)
00668   { return CNT<double>::template Result<Row<N,E,S> >::DvdOp::perform(l,r); }
00669 
00670 template <int N, class E, int S> inline
00671 typename Row<N,E,S>::template Result<long double>::Dvd
00672 operator/(const Row<N,E,S>& l, const long double& r)
00673   { return Row<N,E,S>::template Result<long double>::DvdOp::perform(l,r); }
00674 template <int N, class E, int S> inline
00675 typename CNT<long double>::template Result<Row<N,E,S> >::Dvd
00676 operator/(const long double& l, const Row<N,E,S>& r)
00677   { return CNT<long double>::template Result<Row<N,E,S> >::DvdOp::perform(l,r); }
00678 
00679 // v = v/int, int/v -- just convert int to v's precision float
00680 template <int N, class E, int S> inline
00681 typename Row<N,E,S>::template Result<typename CNT<E>::Precision>::Dvd
00682 operator/(const Row<N,E,S>& l, int r) {return l / (typename CNT<E>::Precision)r;}
00683 template <int N, class E, int S> inline
00684 typename CNT<typename CNT<E>::Precision>::template Result<Row<N,E,S> >::Dvd
00685 operator/(int l, const Row<N,E,S>& r) {return (typename CNT<E>::Precision)l / r;}
00686 
00687 
00688 // Complex, conjugate, and negator are all easy to templatize.
00689 
00690 // v = v/complex, complex/v
00691 template <int N, class E, int S, class R> inline
00692 typename Row<N,E,S>::template Result<std::complex<R> >::Dvd
00693 operator/(const Row<N,E,S>& l, const std::complex<R>& r)
00694   { return Row<N,E,S>::template Result<std::complex<R> >::DvdOp::perform(l,r); }
00695 template <int N, class E, int S, class R> inline
00696 typename CNT<std::complex<R> >::template Result<Row<N,E,S> >::Dvd
00697 operator/(const std::complex<R>& l, const Row<N,E,S>& r)
00698   { return CNT<std::complex<R> >::template Result<Row<N,E,S> >::DvdOp::perform(l,r); }
00699 
00700 // v = v/conjugate, conjugate/v (convert conjugate->complex)
00701 template <int N, class E, int S, class R> inline
00702 typename Row<N,E,S>::template Result<std::complex<R> >::Dvd
00703 operator/(const Row<N,E,S>& l, const conjugate<R>& r) {return l/(std::complex<R>)r;}
00704 template <int N, class E, int S, class R> inline
00705 typename CNT<std::complex<R> >::template Result<Row<N,E,S> >::Dvd
00706 operator/(const conjugate<R>& l, const Row<N,E,S>& r) {return (std::complex<R>)l/r;}
00707 
00708 // v = v/negator, negator/v: convert negator to number
00709 template <int N, class E, int S, class R> inline
00710 typename Row<N,E,S>::template Result<typename negator<R>::StdNumber>::Dvd
00711 operator/(const Row<N,E,S>& l, const negator<R>& r) {return l/(typename negator<R>::StdNumber)(R)r;}
00712 template <int N, class E, int S, class R> inline
00713 typename CNT<R>::template Result<Row<N,E,S> >::Dvd
00714 operator/(const negator<R>& l, const Row<N,E,S>& r) {return (typename negator<R>::StdNumber)(R)l/r;}
00715 
00716 
00717 // Add and subtract are odd as scalar ops. They behave as though the
00718 // scalar stands for a vector each of whose elements is that scalar,
00719 // and then a normal vector add or subtract is done.
00720 
00721 // SCALAR ADD
00722 
00723 // v = v+real, real+v 
00724 template <int N, class E, int S> inline
00725 typename Row<N,E,S>::template Result<float>::Add
00726 operator+(const Row<N,E,S>& l, const float& r)
00727   { return Row<N,E,S>::template Result<float>::AddOp::perform(l,r); }
00728 template <int N, class E, int S> inline
00729 typename Row<N,E,S>::template Result<float>::Add
00730 operator+(const float& l, const Row<N,E,S>& r) {return r+l;}
00731 
00732 template <int N, class E, int S> inline
00733 typename Row<N,E,S>::template Result<double>::Add
00734 operator+(const Row<N,E,S>& l, const double& r)
00735   { return Row<N,E,S>::template Result<double>::AddOp::perform(l,r); }
00736 template <int N, class E, int S> inline
00737 typename Row<N,E,S>::template Result<double>::Add
00738 operator+(const double& l, const Row<N,E,S>& r) {return r+l;}
00739 
00740 template <int N, class E, int S> inline
00741 typename Row<N,E,S>::template Result<long double>::Add
00742 operator+(const Row<N,E,S>& l, const long double& r)
00743   { return Row<N,E,S>::template Result<long double>::AddOp::perform(l,r); }
00744 template <int N, class E, int S> inline
00745 typename Row<N,E,S>::template Result<long double>::Add
00746 operator+(const long double& l, const Row<N,E,S>& r) {return r+l;}
00747 
00748 // v = v+int, int+v -- just convert int to v's precision float
00749 template <int N, class E, int S> inline
00750 typename Row<N,E,S>::template Result<typename CNT<E>::Precision>::Add
00751 operator+(const Row<N,E,S>& l, int r) {return l + (typename CNT<E>::Precision)r;}
00752 template <int N, class E, int S> inline
00753 typename Row<N,E,S>::template Result<typename CNT<E>::Precision>::Add
00754 operator+(int l, const Row<N,E,S>& r) {return r + (typename CNT<E>::Precision)l;}
00755 
00756 // Complex, conjugate, and negator are all easy to templatize.
00757 
00758 // v = v+complex, complex+v
00759 template <int N, class E, int S, class R> inline
00760 typename Row<N,E,S>::template Result<std::complex<R> >::Add
00761 operator+(const Row<N,E,S>& l, const std::complex<R>& r)
00762   { return Row<N,E,S>::template Result<std::complex<R> >::AddOp::perform(l,r); }
00763 template <int N, class E, int S, class R> inline
00764 typename Row<N,E,S>::template Result<std::complex<R> >::Add
00765 operator+(const std::complex<R>& l, const Row<N,E,S>& r) {return r+l;}
00766 
00767 // v = v+conjugate, conjugate+v (convert conjugate->complex)
00768 template <int N, class E, int S, class R> inline
00769 typename Row<N,E,S>::template Result<std::complex<R> >::Add
00770 operator+(const Row<N,E,S>& l, const conjugate<R>& r) {return l+(std::complex<R>)r;}
00771 template <int N, class E, int S, class R> inline
00772 typename Row<N,E,S>::template Result<std::complex<R> >::Add
00773 operator+(const conjugate<R>& l, const Row<N,E,S>& r) {return r+(std::complex<R>)l;}
00774 
00775 // v = v+negator, negator+v: convert negator to standard number
00776 template <int N, class E, int S, class R> inline
00777 typename Row<N,E,S>::template Result<typename negator<R>::StdNumber>::Add
00778 operator+(const Row<N,E,S>& l, const negator<R>& r) {return l + (typename negator<R>::StdNumber)(R)r;}
00779 template <int N, class E, int S, class R> inline
00780 typename Row<N,E,S>::template Result<typename negator<R>::StdNumber>::Add
00781 operator+(const negator<R>& l, const Row<N,E,S>& r) {return r + (typename negator<R>::StdNumber)(R)l;}
00782 
00783 // SCALAR SUBTRACT -- careful, not commutative.
00784 
00785 // v = v-real, real-v 
00786 template <int N, class E, int S> inline
00787 typename Row<N,E,S>::template Result<float>::Sub
00788 operator-(const Row<N,E,S>& l, const float& r)
00789   { return Row<N,E,S>::template Result<float>::SubOp::perform(l,r); }
00790 template <int N, class E, int S> inline
00791 typename CNT<float>::template Result<Row<N,E,S> >::Sub
00792 operator-(const float& l, const Row<N,E,S>& r)
00793   { return CNT<float>::template Result<Row<N,E,S> >::SubOp::perform(l,r); }
00794 
00795 template <int N, class E, int S> inline
00796 typename Row<N,E,S>::template Result<double>::Sub
00797 operator-(const Row<N,E,S>& l, const double& r)
00798   { return Row<N,E,S>::template Result<double>::SubOp::perform(l,r); }
00799 template <int N, class E, int S> inline
00800 typename CNT<double>::template Result<Row<N,E,S> >::Sub
00801 operator-(const double& l, const Row<N,E,S>& r)
00802   { return CNT<double>::template Result<Row<N,E,S> >::SubOp::perform(l,r); }
00803 
00804 template <int N, class E, int S> inline
00805 typename Row<N,E,S>::template Result<long double>::Sub
00806 operator-(const Row<N,E,S>& l, const long double& r)
00807   { return Row<N,E,S>::template Result<long double>::SubOp::perform(l,r); }
00808 template <int N, class E, int S> inline
00809 typename CNT<long double>::template Result<Row<N,E,S> >::Sub
00810 operator-(const long double& l, const Row<N,E,S>& r)
00811   { return CNT<long double>::template Result<Row<N,E,S> >::SubOp::perform(l,r); }
00812 
00813 // v = v-int, int-v // just convert int to v's precision float
00814 template <int N, class E, int S> inline
00815 typename Row<N,E,S>::template Result<typename CNT<E>::Precision>::Sub
00816 operator-(const Row<N,E,S>& l, int r) {return l - (typename CNT<E>::Precision)r;}
00817 template <int N, class E, int S> inline
00818 typename CNT<typename CNT<E>::Precision>::template Result<Row<N,E,S> >::Sub
00819 operator-(int l, const Row<N,E,S>& r) {return (typename CNT<E>::Precision)l - r;}
00820 
00821 
00822 // Complex, conjugate, and negator are all easy to templatize.
00823 
00824 // v = v-complex, complex-v
00825 template <int N, class E, int S, class R> inline
00826 typename Row<N,E,S>::template Result<std::complex<R> >::Sub
00827 operator-(const Row<N,E,S>& l, const std::complex<R>& r)
00828   { return Row<N,E,S>::template Result<std::complex<R> >::SubOp::perform(l,r); }
00829 template <int N, class E, int S, class R> inline
00830 typename CNT<std::complex<R> >::template Result<Row<N,E,S> >::Sub
00831 operator-(const std::complex<R>& l, const Row<N,E,S>& r)
00832   { return CNT<std::complex<R> >::template Result<Row<N,E,S> >::SubOp::perform(l,r); }
00833 
00834 // v = v-conjugate, conjugate-v (convert conjugate->complex)
00835 template <int N, class E, int S, class R> inline
00836 typename Row<N,E,S>::template Result<std::complex<R> >::Sub
00837 operator-(const Row<N,E,S>& l, const conjugate<R>& r) {return l-(std::complex<R>)r;}
00838 template <int N, class E, int S, class R> inline
00839 typename CNT<std::complex<R> >::template Result<Row<N,E,S> >::Sub
00840 operator-(const conjugate<R>& l, const Row<N,E,S>& r) {return (std::complex<R>)l-r;}
00841 
00842 // v = v-negator, negator-v: convert negator to standard number
00843 template <int N, class E, int S, class R> inline
00844 typename Row<N,E,S>::template Result<typename negator<R>::StdNumber>::Sub
00845 operator-(const Row<N,E,S>& l, const negator<R>& r) {return l-(typename negator<R>::StdNumber)(R)r;}
00846 template <int N, class E, int S, class R> inline
00847 typename CNT<R>::template Result<Row<N,E,S> >::Sub
00848 operator-(const negator<R>& l, const Row<N,E,S>& r) {return (typename negator<R>::StdNumber)(R)l-r;}
00849 
00850 
00851 // Row I/O
00852 template <int N, class E, int S, class CHAR, class TRAITS> inline
00853 std::basic_ostream<CHAR,TRAITS>&
00854 operator<<(std::basic_ostream<CHAR,TRAITS>& o, const Row<N,E,S>& v) {
00855     o << "[" << v[0]; for(int i=1;i<N;++i) o<<','<<v[i]; o<<']'; return o;
00856 }
00857 
00858 template <int N, class E, int S, class CHAR, class TRAITS> inline
00859 std::basic_istream<CHAR,TRAITS>&
00860 operator>>(std::basic_istream<CHAR,TRAITS>& is, Row<N,E,S>& v) {
00861     // TODO: not sure how to do Row input yet
00862     assert(false);
00863     return is;
00864 }
00865 
00866 } //namespace SimTK
00867 
00868 
00869 #endif //SimTK_SIMMATRIX_SMALLMATRIX_ROW_H_

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