Vec.h

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

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