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

Generated on Fri Sep 26 07:44:19 2008 for SimTKcore by  doxygen 1.5.6