Simbody  3.4 (development)
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  *                       Simbody(tm): SimTKcommon                             *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK biosimulation toolkit originating from           *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
00011  *                                                                            *
00012  * Portions copyright (c) 2005-12 Stanford University and the Authors.        *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors: Peter Eastman                                                *
00015  *                                                                            *
00016  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
00017  * not use this file except in compliance with the License. You may obtain a  *
00018  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
00019  *                                                                            *
00020  * Unless required by applicable law or agreed to in writing, software        *
00021  * distributed under the License is distributed on an "AS IS" BASIS,          *
00022  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
00023  * See the License for the specific language governing permissions and        *
00024  * limitations under the License.                                             *
00025  * -------------------------------------------------------------------------- */
00026 
00031 #include "SimTKcommon/internal/common.h"
00032 
00033 namespace SimTK {
00034 
00035 
00036 // The following functions are used internally by Vec.
00037 
00038 // Hide from Doxygen.
00040 namespace Impl {
00041 
00042 // For those wimpy compilers that don't unroll short, constant-limit loops, 
00043 // Peter Eastman added these recursive template implementations of 
00044 // elementwise add, subtract, and copy. Sherm added multiply and divide.
00045 
00046 template <class E1, int S1, class E2, int S2> void
00047 conformingAdd(const Vec<1,E1,S1>& r1, const Vec<1,E2,S2>& r2, 
00048               Vec<1,typename CNT<E1>::template Result<E2>::Add>& result) {
00049     result[0] = r1[0] + r2[0];
00050 }
00051 template <int N, class E1, int S1, class E2, int S2> void
00052 conformingAdd(const Vec<N,E1,S1>& r1, const Vec<N,E2,S2>& r2, 
00053               Vec<N,typename CNT<E1>::template Result<E2>::Add>& result) {
00054     conformingAdd(reinterpret_cast<const Vec<N-1,E1,S1>&>(r1), 
00055                   reinterpret_cast<const Vec<N-1,E2,S2>&>(r2), 
00056                   reinterpret_cast<Vec<N-1,typename CNT<E1>::
00057                               template Result<E2>::Add>&>(result));
00058     result[N-1] = r1[N-1] + r2[N-1];
00059 }
00060 
00061 template <class E1, int S1, class E2, int S2> void
00062 conformingSubtract(const Vec<1,E1,S1>& r1, const Vec<1,E2,S2>& r2, 
00063                    Vec<1,typename CNT<E1>::template Result<E2>::Sub>& result) {
00064     result[0] = r1[0] - r2[0];
00065 }
00066 template <int N, class E1, int S1, class E2, int S2> void
00067 conformingSubtract(const Vec<N,E1,S1>& r1, const Vec<N,E2,S2>& r2, 
00068                    Vec<N,typename CNT<E1>::template Result<E2>::Sub>& result) {
00069     conformingSubtract(reinterpret_cast<const Vec<N-1,E1,S1>&>(r1), 
00070                        reinterpret_cast<const Vec<N-1,E2,S2>&>(r2), 
00071                        reinterpret_cast<Vec<N-1,typename CNT<E1>::
00072                                    template Result<E2>::Sub>&>(result));
00073     result[N-1] = r1[N-1] - r2[N-1];
00074 }
00075 
00076 template <class E1, int S1, class E2, int S2> void
00077 elementwiseMultiply(const Vec<1,E1,S1>& r1, const Vec<1,E2,S2>& r2, 
00078               Vec<1,typename CNT<E1>::template Result<E2>::Mul>& result) {
00079     result[0] = r1[0] * r2[0];
00080 }
00081 template <int N, class E1, int S1, class E2, int S2> void
00082 elementwiseMultiply(const Vec<N,E1,S1>& r1, const Vec<N,E2,S2>& r2, 
00083               Vec<N,typename CNT<E1>::template Result<E2>::Mul>& result) {
00084     elementwiseMultiply(reinterpret_cast<const Vec<N-1,E1,S1>&>(r1), 
00085                         reinterpret_cast<const Vec<N-1,E2,S2>&>(r2), 
00086                         reinterpret_cast<Vec<N-1,typename CNT<E1>::
00087                                     template Result<E2>::Mul>&>(result));
00088     result[N-1] = r1[N-1] * r2[N-1];
00089 }
00090 
00091 template <class E1, int S1, class E2, int S2> void
00092 elementwiseDivide(const Vec<1,E1,S1>& r1, const Vec<1,E2,S2>& r2, 
00093               Vec<1,typename CNT<E1>::template Result<E2>::Dvd>& result) {
00094     result[0] = r1[0] / r2[0];
00095 }
00096 template <int N, class E1, int S1, class E2, int S2> void
00097 elementwiseDivide(const Vec<N,E1,S1>& r1, const Vec<N,E2,S2>& r2, 
00098               Vec<N,typename CNT<E1>::template Result<E2>::Dvd>& result) {
00099     elementwiseDivide(reinterpret_cast<const Vec<N-1,E1,S1>&>(r1), 
00100                       reinterpret_cast<const Vec<N-1,E2,S2>&>(r2), 
00101                       reinterpret_cast<Vec<N-1,typename CNT<E1>::
00102                                   template Result<E2>::Dvd>&>(result));
00103     result[N-1] = r1[N-1] / r2[N-1];
00104 }
00105 
00106 template <class E1, int S1, class E2, int S2> void
00107 copy(Vec<1,E1,S1>& r1, const Vec<1,E2,S2>& r2) {
00108     r1[0] = r2[0];
00109 }
00110 template <int N, class E1, int S1, class E2, int S2> void
00111 copy(Vec<N,E1,S1>& r1, const Vec<N,E2,S2>& r2) {
00112     copy(reinterpret_cast<Vec<N-1,E1,S1>&>(r1), 
00113          reinterpret_cast<const Vec<N-1,E2,S2>&>(r2));
00114     r1[N-1] = r2[N-1];
00115 }
00116 
00117 }
00130 template <int M, class ELT, int STRIDE>
00131 class Vec {
00132 public:
00138     typedef ELT                                 E;
00140     typedef typename CNT<E>::TNeg               ENeg;
00142     typedef typename CNT<E>::TWithoutNegator    EWithoutNegator;
00145     typedef typename CNT<E>::TReal              EReal;
00149     typedef typename CNT<E>::TImag              EImag;
00152     typedef typename CNT<E>::TComplex           EComplex;
00154     typedef typename CNT<E>::THerm              EHerm;
00156     typedef typename CNT<E>::TPosTrans          EPosTrans;
00159     typedef typename CNT<E>::TSqHermT           ESqHermT;
00161     typedef typename CNT<E>::TSqTHerm           ESqTHerm;
00163     typedef typename CNT<E>::TSqrt              ESqrt;
00165     typedef typename CNT<E>::TAbs               EAbs;
00168     typedef typename CNT<E>::TStandard          EStandard;
00171     typedef typename CNT<E>::TInvert            EInvert;
00173     typedef typename CNT<E>::TNormalize         ENormalize;
00174 
00175     typedef typename CNT<E>::Scalar             EScalar;
00176     typedef typename CNT<E>::ULessScalar        EULessScalar;
00177     typedef typename CNT<E>::Number             ENumber;
00178     typedef typename CNT<E>::StdNumber          EStdNumber;
00179     typedef typename CNT<E>::Precision          EPrecision;
00180     typedef typename CNT<E>::ScalarNormSq       EScalarNormSq;
00181 
00184     enum {
00185         NRows               = M,
00186         NCols               = 1,
00187         NPackedElements     = M,
00188         NActualElements     = M * STRIDE,   // includes trailing gap
00189         NActualScalars      = CNT<E>::NActualScalars * NActualElements,
00190         RowSpacing          = STRIDE,
00191         ColSpacing          = NActualElements,
00192         ImagOffset          = NTraits<ENumber>::ImagOffset,
00193         RealStrideFactor    = 1, // composite types don't change size when
00194                                  // cast from complex to real or imaginary
00195         ArgDepth            = ((int)CNT<E>::ArgDepth < (int)MAX_RESOLVED_DEPTH 
00196                                 ? CNT<E>::ArgDepth + 1 
00197                                 : MAX_RESOLVED_DEPTH),
00198         IsScalar            = 0,
00199         IsULessScalar       = 0,
00200         IsNumber            = 0,
00201         IsStdNumber         = 0,
00202         IsPrecision         = 0,
00203         SignInterpretation  = CNT<E>::SignInterpretation
00204     };
00205 
00206     // These are reinterpretations of the current data, so have the
00207     // same packing (stride).
00208 
00210     typedef Vec<M,E,STRIDE>                 T;
00213     typedef Vec<M,ENeg,STRIDE>              TNeg;
00216     typedef Vec<M,EWithoutNegator,STRIDE>   TWithoutNegator;
00219     typedef Vec<M,EReal,STRIDE*CNT<E>::RealStrideFactor>         
00220                                             TReal;
00223     typedef Vec<M,EImag,STRIDE*CNT<E>::RealStrideFactor>         
00224                                             TImag;
00225     typedef Vec<M,EComplex,STRIDE>          TComplex;
00229     typedef Row<M,EHerm,STRIDE>             THerm;
00232     typedef Row<M,E,STRIDE>                 TPosTrans;
00234     typedef E                               TElement;
00236     typedef E                               TRow;
00238     typedef Vec                             TCol;
00239 
00240     // These are the results of calculations, so are returned in new, packed
00241     // memory. Be sure to refer to element types here which are also packed.
00242     typedef Vec<M,ESqrt,1>                  TSqrt;      // Note stride
00243     typedef Vec<M,EAbs,1>                   TAbs;       // Note stride
00244     typedef Vec<M,EStandard,1>              TStandard;
00245     typedef Row<M,EInvert,1>                TInvert;
00246     typedef Vec<M,ENormalize,1>             TNormalize;
00247 
00248     typedef ESqHermT                        TSqHermT;   // result of self dot product
00249     typedef SymMat<M,ESqTHerm>              TSqTHerm;   // result of self outer product
00250 
00251     // These recurse right down to the underlying scalar type no matter how
00252     // deep the elements are.
00253     typedef EScalar                         Scalar;
00254     typedef EULessScalar                    ULessScalar;
00255     typedef ENumber                         Number;
00256     typedef EStdNumber                      StdNumber;
00257     typedef EPrecision                      Precision;
00258     typedef EScalarNormSq                   ScalarNormSq;
00263     static int size() { return M; }
00265     static int nrow() { return M; }
00267     static int ncol() { return 1; }
00268 
00269 
00272     ScalarNormSq scalarNormSqr() const { 
00273         ScalarNormSq sum(0);
00274         for(int i=0;i<M;++i) sum += CNT<E>::scalarNormSqr(d[i*STRIDE]);
00275         return sum;
00276     }
00277 
00282     TSqrt sqrt() const {
00283         TSqrt vsqrt;
00284         for(int i=0;i<M;++i) vsqrt[i] = CNT<E>::sqrt(d[i*STRIDE]);
00285         return vsqrt;
00286     }
00287 
00292     TAbs abs() const {
00293         TAbs vabs;
00294         for(int i=0;i<M;++i) vabs[i] = CNT<E>::abs(d[i*STRIDE]);
00295         return vabs;
00296     }
00297 
00302     TStandard standardize() const {
00303         TStandard vstd;
00304         for(int i=0;i<M;++i) vstd[i] = CNT<E>::standardize(d[i*STRIDE]);
00305         return vstd;
00306     }
00307 
00311     EStandard sum() const {
00312         E sum(0);
00313         for (int i=0;i<M;++i) sum += d[i*STRIDE];
00314         return CNT<E>::standardize(sum);
00315     }
00316 
00317 
00318     // This gives the resulting vector type when (v[i] op P) is applied to 
00319     // each element of v. It is a vector of length M, stride 1, and element 
00320     // types which are the regular composite result of E op P. Typically P is 
00321     // a scalar type but it doesn't have to be.
00322     template <class P> struct EltResult { 
00323         typedef Vec<M, typename CNT<E>::template Result<P>::Mul, 1> Mul;
00324         typedef Vec<M, typename CNT<E>::template Result<P>::Dvd, 1> Dvd;
00325         typedef Vec<M, typename CNT<E>::template Result<P>::Add, 1> Add;
00326         typedef Vec<M, typename CNT<E>::template Result<P>::Sub, 1> Sub;
00327     };
00328 
00329     // This is the composite result for v op P where P is some kind of 
00330     // appropriately shaped non-scalar type.
00331     template <class P> struct Result { 
00332         typedef MulCNTs<M,1,ArgDepth,Vec,ColSpacing,RowSpacing,
00333             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00334             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> MulOp;
00335         typedef typename MulOp::Type Mul;
00336 
00337         typedef MulCNTsNonConforming<M,1,ArgDepth,Vec,ColSpacing,RowSpacing,
00338             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00339             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> MulOpNonConforming;
00340         typedef typename MulOpNonConforming::Type MulNon;
00341 
00342         typedef DvdCNTs<M,1,ArgDepth,Vec,ColSpacing,RowSpacing,
00343             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00344             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> DvdOp;
00345         typedef typename DvdOp::Type Dvd;
00346 
00347         typedef AddCNTs<M,1,ArgDepth,Vec,ColSpacing,RowSpacing,
00348             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00349             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> AddOp;
00350         typedef typename AddOp::Type Add;
00351 
00352         typedef SubCNTs<M,1,ArgDepth,Vec,ColSpacing,RowSpacing,
00353             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00354             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> SubOp;
00355         typedef typename SubOp::Type Sub;
00356     };
00357 
00363     template <class P> struct Substitute {
00364         typedef Vec<M,P> Type;
00365     };
00366 
00370     Vec(){ 
00371     #ifndef NDEBUG
00372         setToNaN();
00373     #endif
00374     }
00375 
00376     // It's important not to use the default copy constructor or copy
00377     // assignment because the compiler doesn't understand that we may
00378     // have noncontiguous storage and will try to copy the whole array.
00379 
00383     Vec(const Vec& src) {
00384         Impl::copy(*this, src);
00385     }
00390     Vec& operator=(const Vec& src) {    
00391         Impl::copy(*this, src);
00392         return *this;
00393     }
00394 
00397     template <int SS> Vec(const Vec<M,E,SS>& src) {
00398         Impl::copy(*this, src);
00399     }
00400 
00403     template <int SS> Vec(const Vec<M,ENeg,SS>& src) {
00404         Impl::copy(*this, src);
00405     }
00406 
00409     template <class EE, int SS> explicit Vec(const Vec<M,EE,SS>& src) {
00410         Impl::copy(*this, src);
00411     }
00412 
00415     explicit Vec(const E& e) {for (int i=0;i<M;++i) d[i*STRIDE]=e;}
00416 
00421     explicit Vec(const ENeg& ne) {
00422         const E e = ne; // requires floating point negation
00423         for (int i=0;i<M;++i) d[i*STRIDE]=e;
00424     }
00425 
00430     explicit Vec(int i) {new (this) Vec(E(Precision(i)));}
00431 
00432     // A bevy of constructors for Vecs up to length 9.
00433 
00435     Vec(const E& e0,const E& e1)
00436       { assert(M==2);(*this)[0]=e0;(*this)[1]=e1; }
00437     Vec(const E& e0,const E& e1,const E& e2)
00438       { assert(M==3);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2; }
00439     Vec(const E& e0,const E& e1,const E& e2,const E& e3)
00440       { assert(M==4);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;(*this)[3]=e3; }
00441     Vec(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4)
00442       { assert(M==5);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;
00443         (*this)[3]=e3;(*this)[4]=e4; }
00444     Vec(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,const E& e5)
00445       { assert(M==6);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;
00446         (*this)[3]=e3;(*this)[4]=e4;(*this)[5]=e5; }
00447     Vec(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,const E& e5, const E& e6)
00448       { assert(M==7);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;
00449         (*this)[3]=e3;(*this)[4]=e4;(*this)[5]=e5;(*this)[6]=e6; }
00450     Vec(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,const E& e5, const E& e6, const E& e7)
00451       { assert(M==8);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;
00452         (*this)[3]=e3;(*this)[4]=e4;(*this)[5]=e5;(*this)[6]=e6;(*this)[7]=e7; }
00453     Vec(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,const E& e5, const E& e6, const E& e7, const E& e8)
00454       { assert(M==9);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;
00455         (*this)[3]=e3;(*this)[4]=e4;(*this)[5]=e5;(*this)[6]=e6;(*this)[7]=e7;(*this)[8]=e8; }
00456 
00461     template <class EE> explicit Vec(const EE* p)
00462     {   assert(p); for(int i=0;i<M;++i) d[i*STRIDE]=p[i]; }
00463 
00468     template <class EE> Vec& operator=(const EE* p)
00469     {   assert(p); for(int i=0;i<M;++i) d[i*STRIDE]=p[i]; return *this; }
00470 
00473     template <class EE, int SS> Vec& operator=(const Vec<M,EE,SS>& vv) 
00474     {   Impl::copy(*this, vv); return *this; }
00475 
00478     template <class EE, int SS> Vec& operator+=(const Vec<M,EE,SS>& r)
00479     {   for(int i=0;i<M;++i) d[i*STRIDE] += r[i]; return *this; }
00483     template <class EE, int SS> Vec& operator+=(const Vec<M,negator<EE>,SS>& r)
00484     {   for(int i=0;i<M;++i) d[i*STRIDE] -= -(r[i]); return *this; }
00485 
00488     template <class EE, int SS> Vec& operator-=(const Vec<M,EE,SS>& r)
00489     {   for(int i=0;i<M;++i) d[i*STRIDE] -= r[i]; return *this; }
00493     template <class EE, int SS> Vec& operator-=(const Vec<M,negator<EE>,SS>& r)
00494     {   for(int i=0;i<M;++i) d[i*STRIDE] += -(r[i]); return *this; }
00495 
00496     // Conforming binary ops with 'this' on left, producing new packed result.
00497     // Cases: v=v+v, v=v-v, m=v*r
00498 
00500     template <class EE, int SS> Vec<M,typename CNT<E>::template Result<EE>::Add>
00501     conformingAdd(const Vec<M,EE,SS>& r) const {
00502         Vec<M,typename CNT<E>::template Result<EE>::Add> result;
00503         Impl::conformingAdd(*this, r, result);
00504         return result;
00505     }
00507     template <class EE, int SS> Vec<M,typename CNT<E>::template Result<EE>::Sub>
00508     conformingSubtract(const Vec<M,EE,SS>& r) const {
00509         Vec<M,typename CNT<E>::template Result<EE>::Sub> result;
00510         Impl::conformingSubtract(*this, r, result);
00511         return result;
00512     }
00513 
00516     template <class EE, int SS> Mat<M,M,typename CNT<E>::template Result<EE>::Mul>
00517     conformingMultiply(const Row<M,EE,SS>& r) const {
00518         Mat<M,M,typename CNT<E>::template Result<EE>::Mul> result;
00519         for (int j=0;j<M;++j) result(j) = scalarMultiply(r(j));
00520         return result;
00521     }
00522 
00524     template <class EE, int SS> Vec<M,typename CNT<E>::template Result<EE>::Mul>
00525     elementwiseMultiply(const Vec<M,EE,SS>& r) const {
00526         Vec<M,typename CNT<E>::template Result<EE>::Mul> result;
00527         Impl::elementwiseMultiply(*this, r, result);
00528         return result;
00529     }
00531     template <class EE, int SS> Vec<M,typename CNT<E>::template Result<EE>::Dvd>
00532     elementwiseDivide(const Vec<M,EE,SS>& r) const {
00533         Vec<M,typename CNT<E>::template Result<EE>::Dvd> result;
00534         Impl::elementwiseDivide(*this, r, result);
00535         return result;
00536     }
00537 
00541     const E& operator[](int i) const 
00542     {   assert(0 <= i && i < M); return d[i*STRIDE]; }
00544     const E& operator()(int i) const {return (*this)[i];}
00545 
00549     E& operator[](int i) {assert(0 <= i && i < M); return d[i*STRIDE];}
00551     E& operator()(int i) {return (*this)[i];}
00552 
00553     ScalarNormSq normSqr() const { return scalarNormSqr(); }
00554     typename CNT<ScalarNormSq>::TSqrt 
00555         norm() const { return CNT<ScalarNormSq>::sqrt(scalarNormSqr()); }
00556 
00568     TNormalize normalize() const {
00569         if (CNT<E>::IsScalar) {
00570             return castAwayNegatorIfAny() / (SignInterpretation*norm());
00571         } else {
00572             TNormalize elementwiseNormalized;
00573             for (int i=0; i<M; ++i) 
00574                 elementwiseNormalized[i] = CNT<E>::normalize((*this)[i]);
00575             return elementwiseNormalized;
00576         }
00577     }
00578 
00580     TInvert invert() const {assert(false); return TInvert();} // TODO default inversion
00581 
00583     const Vec&   operator+() const { return *this; }
00587     const TNeg&  operator-() const { return negate(); }
00590     TNeg&        operator-()       { return updNegate(); }
00594     const THerm& operator~() const { return transpose(); }
00598     THerm&       operator~()       { return updTranspose(); }
00599 
00601     const TNeg&  negate() const { return *reinterpret_cast<const TNeg*>(this); }
00604     TNeg&        updNegate()    { return *reinterpret_cast<      TNeg*>(this); }
00605 
00607     const THerm& transpose()    const { return *reinterpret_cast<const THerm*>(this); }
00610     THerm&       updTranspose()       { return *reinterpret_cast<      THerm*>(this); }
00611 
00616     const TPosTrans& positionalTranspose() const
00617         { return *reinterpret_cast<const TPosTrans*>(this); }
00619     TPosTrans&       updPositionalTranspose()
00620         { return *reinterpret_cast<TPosTrans*>(this); }
00621 
00626     const TReal& real() const { return *reinterpret_cast<const TReal*>(this); }
00629     TReal&       real()       { return *reinterpret_cast<      TReal*>(this); }
00630 
00631     // Had to contort these next two routines to get them through VC++ 7.net
00632 
00637     const TImag& imag()    const { 
00638         const int offs = ImagOffset;
00639         const EImag* p = reinterpret_cast<const EImag*>(this);
00640         return *reinterpret_cast<const TImag*>(p+offs);
00641     }
00644     TImag& imag() { 
00645         const int offs = ImagOffset;
00646         EImag* p = reinterpret_cast<EImag*>(this);
00647         return *reinterpret_cast<TImag*>(p+offs);
00648     }
00649 
00653     const TWithoutNegator& castAwayNegatorIfAny() const 
00654     {   return *reinterpret_cast<const TWithoutNegator*>(this); }
00657     TWithoutNegator&       updCastAwayNegatorIfAny()    
00658     {   return *reinterpret_cast<TWithoutNegator*>(this); }
00659 
00660     // These are elementwise binary operators, (this op ee) by default but 
00661     // (ee op this) if 'FromLeft' appears in the name. The result is a packed 
00662     // Vec<M> but the element type may change. These are mostly used to 
00663     // implement global operators. We call these "scalar" operators but 
00664     // actually the "scalar" can be a composite type.
00665 
00666     //TODO: consider converting 'e' to Standard Numbers as precalculation and 
00667     // changing return type appropriately.
00668     template <class EE> Vec<M, typename CNT<E>::template Result<EE>::Mul>
00669     scalarMultiply(const EE& e) const {
00670         Vec<M, typename CNT<E>::template Result<EE>::Mul> result;
00671         for (int i=0; i<M; ++i) result[i] = (*this)[i] * e;
00672         return result;
00673     }
00674     template <class EE> Vec<M, typename CNT<EE>::template Result<E>::Mul>
00675     scalarMultiplyFromLeft(const EE& e) const {
00676         Vec<M, typename CNT<EE>::template Result<E>::Mul> result;
00677         for (int i=0; i<M; ++i) result[i] = e * (*this)[i];
00678         return result;
00679     }
00680 
00681     // TODO: should precalculate and store 1/e, while converting to Standard 
00682     // Numbers. Note that return type should change appropriately.
00683     template <class EE> Vec<M, typename CNT<E>::template Result<EE>::Dvd>
00684     scalarDivide(const EE& e) const {
00685         Vec<M, typename CNT<E>::template Result<EE>::Dvd> result;
00686         for (int i=0; i<M; ++i) result[i] = (*this)[i] / e;
00687         return result;
00688     }
00689     template <class EE> Vec<M, typename CNT<EE>::template Result<E>::Dvd>
00690     scalarDivideFromLeft(const EE& e) const {
00691         Vec<M, typename CNT<EE>::template Result<E>::Dvd> result;
00692         for (int i=0; i<M; ++i) result[i] = e / (*this)[i];
00693         return result;
00694     }
00695 
00696     template <class EE> Vec<M, typename CNT<E>::template Result<EE>::Add>
00697     scalarAdd(const EE& e) const {
00698         Vec<M, typename CNT<E>::template Result<EE>::Add> result;
00699         for (int i=0; i<M; ++i) result[i] = (*this)[i] + e;
00700         return result;
00701     }
00702     // Add is commutative, so no 'FromLeft'.
00703 
00704     template <class EE> Vec<M, typename CNT<E>::template Result<EE>::Sub>
00705     scalarSubtract(const EE& e) const {
00706         Vec<M, typename CNT<E>::template Result<EE>::Sub> result;
00707         for (int i=0; i<M; ++i) result[i] = (*this)[i] - e;
00708         return result;
00709     }
00710     template <class EE> Vec<M, typename CNT<EE>::template Result<E>::Sub>
00711     scalarSubtractFromLeft(const EE& e) const {
00712         Vec<M, typename CNT<EE>::template Result<E>::Sub> result;
00713         for (int i=0; i<M; ++i) result[i] = e - (*this)[i];
00714         return result;
00715     }
00716 
00717     // Generic assignments for any element type not listed explicitly, including scalars.
00718     // These are done repeatedly for each element and only work if the operation can
00719     // be performed leaving the original element type.
00720     template <class EE> Vec& operator =(const EE& e) {return scalarEq(e);}
00721     template <class EE> Vec& operator+=(const EE& e) {return scalarPlusEq(e);}
00722     template <class EE> Vec& operator-=(const EE& e) {return scalarMinusEq(e);}
00723     template <class EE> Vec& operator*=(const EE& e) {return scalarTimesEq(e);}
00724     template <class EE> Vec& operator/=(const EE& e) {return scalarDivideEq(e);}
00725 
00726     // Generalized element assignment & computed assignment methods. These will work
00727     // for any assignment-compatible element, not just scalars.
00728     template <class EE> Vec& scalarEq(const EE& ee)
00729       { for(int i=0;i<M;++i) d[i*STRIDE] = ee; return *this; }
00730     template <class EE> Vec& scalarPlusEq(const EE& ee)
00731       { for(int i=0;i<M;++i) d[i*STRIDE] += ee; return *this; }
00732     template <class EE> Vec& scalarMinusEq(const EE& ee)
00733       { for(int i=0;i<M;++i) d[i*STRIDE] -= ee; return *this; }
00734     template <class EE> Vec& scalarMinusEqFromLeft(const EE& ee)
00735       { for(int i=0;i<M;++i) d[i*STRIDE] = ee - d[i*STRIDE]; return *this; }
00736     template <class EE> Vec& scalarTimesEq(const EE& ee)
00737       { for(int i=0;i<M;++i) d[i*STRIDE] *= ee; return *this; }
00738     template <class EE> Vec& scalarTimesEqFromLeft(const EE& ee)
00739       { for(int i=0;i<M;++i) d[i*STRIDE] = ee * d[i*STRIDE]; return *this; }
00740     template <class EE> Vec& scalarDivideEq(const EE& ee)
00741       { for(int i=0;i<M;++i) d[i*STRIDE] /= ee; return *this; }
00742     template <class EE> Vec& scalarDivideEqFromLeft(const EE& ee)
00743       { for(int i=0;i<M;++i) d[i*STRIDE] = ee / d[i*STRIDE]; return *this; }
00744 
00745     // Specialize for int to avoid warnings and ambiguities.
00746     Vec& scalarEq(int ee)       {return scalarEq(Precision(ee));}
00747     Vec& scalarPlusEq(int ee)   {return scalarPlusEq(Precision(ee));}
00748     Vec& scalarMinusEq(int ee)  {return scalarMinusEq(Precision(ee));}
00749     Vec& scalarTimesEq(int ee)  {return scalarTimesEq(Precision(ee));}
00750     Vec& scalarDivideEq(int ee) {return scalarDivideEq(Precision(ee));}
00751     Vec& scalarMinusEqFromLeft(int ee)  {return scalarMinusEqFromLeft(Precision(ee));}
00752     Vec& scalarTimesEqFromLeft(int ee)  {return scalarTimesEqFromLeft(Precision(ee));}
00753     Vec& scalarDivideEqFromLeft(int ee) {return scalarDivideEqFromLeft(Precision(ee));}
00754 
00757     void setToNaN() {
00758         (*this) = CNT<ELT>::getNaN();
00759     }
00760 
00762     void setToZero() {
00763         (*this) = ELT(0);
00764     }
00765 
00771     template <int MM>
00772     const Vec<MM,ELT,STRIDE>& getSubVec(int i) const {
00773         assert(0 <= i && i + MM <= M);
00774         return Vec<MM,ELT,STRIDE>::getAs(&(*this)[i]);
00775     }
00781     template <int MM>
00782     Vec<MM,ELT,STRIDE>& updSubVec(int i) {
00783         assert(0 <= i && i + MM <= M);
00784         return Vec<MM,ELT,STRIDE>::updAs(&(*this)[i]);
00785     }
00786 
00787 
00791     template <int MM>
00792     static const Vec& getSubVec(const Vec<MM,ELT,STRIDE>& v, int i) {
00793         assert(0 <= i && i + M <= MM);
00794         return getAs(&v[i]);
00795     }
00799     template <int MM>
00800     static Vec& updSubVec(Vec<MM,ELT,STRIDE>& v, int i) {
00801         assert(0 <= i && i + M <= MM);
00802         return updAs(&v[i]);
00803     }
00804 
00808     Vec<M-1,ELT,1> drop1(int p) const {
00809         assert(0 <= p && p < M);
00810         Vec<M-1,ELT,1> out;
00811         int nxt=0;
00812         for (int i=0; i<M-1; ++i, ++nxt) {
00813             if (nxt==p) ++nxt;  // skip the loser
00814             out[i] = (*this)[nxt];
00815         }
00816         return out;
00817     }
00818 
00822     template <class EE> Vec<M+1,ELT,1> append1(const EE& v) const {
00823         Vec<M+1,ELT,1> out;
00824         Vec<M,ELT,1>::updAs(&out[0]) = (*this);
00825         out[M] = v;
00826         return out;
00827     }
00828 
00829 
00835     template <class EE> Vec<M+1,ELT,1> insert1(int p, const EE& v) const {
00836         assert(0 <= p && p <= M);
00837         if (p==M) return append1(v);
00838         Vec<M+1,ELT,1> out;
00839         int nxt=0;
00840         for (int i=0; i<M; ++i, ++nxt) {
00841             if (i==p) out[nxt++] = v;
00842             out[nxt] = (*this)[i];
00843         }
00844         return out;
00845     }
00846             
00849     static const Vec& getAs(const ELT* p)  
00850     {   return *reinterpret_cast<const Vec*>(p); }
00853     static Vec&       updAs(ELT* p)
00854     {   return *reinterpret_cast<Vec*>(p); }
00855 
00856 
00860     static Vec<M,ELT,1> getNaN() { return Vec<M,ELT,1>(CNT<ELT>::getNaN()); }
00861 
00863     bool isNaN() const {
00864         for (int i=0; i<M; ++i)
00865             if (CNT<ELT>::isNaN((*this)[i]))
00866                 return true;
00867         return false;
00868     }
00869 
00872     bool isInf() const {
00873         bool seenInf = false;
00874         for (int i=0; i<M; ++i) {
00875             const ELT& e = (*this)[i];
00876             if (!CNT<ELT>::isFinite(e)) {
00877                 if (!CNT<ELT>::isInf(e)) 
00878                     return false; // something bad was found
00879                 seenInf = true; 
00880             }
00881         }
00882         return seenInf;
00883     }
00884 
00887     bool isFinite() const {
00888         for (int i=0; i<M; ++i)
00889             if (!CNT<ELT>::isFinite((*this)[i]))
00890                 return false;
00891         return true;
00892     }
00893 
00896     static double getDefaultTolerance() {return CNT<ELT>::getDefaultTolerance();}
00897 
00900     template <class E2, int RS2>
00901     bool isNumericallyEqual(const Vec<M,E2,RS2>& v, double tol) const {
00902         for (int i=0; i<M; ++i)
00903             if (!CNT<ELT>::isNumericallyEqual((*this)[i], v[i], tol))
00904                 return false;
00905         return true;
00906     }
00907 
00911     template <class E2, int RS2>
00912     bool isNumericallyEqual(const Vec<M,E2,RS2>& v) const {
00913         const double tol = std::max(getDefaultTolerance(),v.getDefaultTolerance());
00914         return isNumericallyEqual(v, tol);
00915     }
00916 
00921     bool isNumericallyEqual
00922        (const ELT& e,
00923         double     tol = getDefaultTolerance()) const 
00924     {
00925         for (int i=0; i<M; ++i)
00926             if (!CNT<ELT>::isNumericallyEqual((*this)[i], e, tol))
00927                 return false;
00928         return true;
00929     }
00930 
00931     // Functions to be used for Scripting in MATLAB and languages that do not support operator overloading
00933     std::string toString() const {
00934         std::stringstream stream;
00935         stream <<  (*this);
00936         return stream.str(); 
00937     }
00938 
00940     void set(int i, const E& value)  
00941     {   (*this)[i] = value; }
00942 
00944     const E& get(int i) const 
00945     {   return operator[](i); }
00946 
00947 private:
00948     // TODO: should be an array of scalars rather than elements to control
00949     // packing more carefully.
00950     ELT d[NActualElements];    // data
00951 };
00952 
00954 // Global operators involving two vectors. //
00955 //   v+v, v-v, v==v, v!=v                  //
00957 
00958 // v3 = v1 + v2 where all v's have the same length M. 
00959 template <int M, class E1, int S1, class E2, int S2> inline
00960 typename Vec<M,E1,S1>::template Result< Vec<M,E2,S2> >::Add
00961 operator+(const Vec<M,E1,S1>& l, const Vec<M,E2,S2>& r) {
00962     return Vec<M,E1,S1>::template Result< Vec<M,E2,S2> >
00963         ::AddOp::perform(l,r);
00964 }
00965 
00966 // v3 = v1 - v2, similar to +
00967 template <int M, class E1, int S1, class E2, int S2> inline
00968 typename Vec<M,E1,S1>::template Result< Vec<M,E2,S2> >::Sub
00969 operator-(const Vec<M,E1,S1>& l, const Vec<M,E2,S2>& r) { 
00970     return Vec<M,E1,S1>::template Result< Vec<M,E2,S2> >
00971         ::SubOp::perform(l,r);
00972 }
00973 
00975 template <int M, class E1, int S1, class E2, int S2> inline bool
00976 operator==(const Vec<M,E1,S1>& l, const Vec<M,E2,S2>& r) 
00977 {   for (int i=0; i < M; ++i) if (l[i] != r[i]) return false;
00978     return true; }
00980 template <int M, class E1, int S1, class E2, int S2> inline bool
00981 operator!=(const Vec<M,E1,S1>& l, const Vec<M,E2,S2>& r) {return !(l==r);} 
00982 
00984 template <int M, class E1, int S1, class E2> inline bool
00985 operator==(const Vec<M,E1,S1>& v, const E2& e) 
00986 {   for (int i=0; i < M; ++i) if (v[i] != e) return false;
00987     return true; }
00989 template <int M, class E1, int S1, class E2> inline bool
00990 operator!=(const Vec<M,E1,S1>& v, const E2& e) {return !(v==e);} 
00991 
00993 template <int M, class E1, int S1, class E2, int S2> inline bool
00994 operator<(const Vec<M,E1,S1>& l, const Vec<M,E2,S2>& r) 
00995 {   for (int i=0; i < M; ++i) if (l[i] >= r[i]) return false;
00996     return true; }
00998 template <int M, class E1, int S1, class E2> inline bool
00999 operator<(const Vec<M,E1,S1>& v, const E2& e) 
01000 {   for (int i=0; i < M; ++i) if (v[i] >= e) return false;
01001     return true; }
01002 
01004 template <int M, class E1, int S1, class E2, int S2> inline bool
01005 operator>(const Vec<M,E1,S1>& l, const Vec<M,E2,S2>& r) 
01006 {   for (int i=0; i < M; ++i) if (l[i] <= r[i]) return false;
01007     return true; }
01009 template <int M, class E1, int S1, class E2> inline bool
01010 operator>(const Vec<M,E1,S1>& v, const E2& e) 
01011 {   for (int i=0; i < M; ++i) if (v[i] <= e) return false;
01012     return true; }
01013 
01016 template <int M, class E1, int S1, class E2, int S2> inline bool
01017 operator<=(const Vec<M,E1,S1>& l, const Vec<M,E2,S2>& r) 
01018 {   for (int i=0; i < M; ++i) if (l[i] > r[i]) return false;
01019     return true; }
01022 template <int M, class E1, int S1, class E2> inline bool
01023 operator<=(const Vec<M,E1,S1>& v, const E2& e) 
01024 {   for (int i=0; i < M; ++i) if (v[i] > e) return false;
01025     return true; }
01026 
01029 template <int M, class E1, int S1, class E2, int S2> inline bool
01030 operator>=(const Vec<M,E1,S1>& l, const Vec<M,E2,S2>& r) 
01031 {   for (int i=0; i < M; ++i) if (l[i] < r[i]) return false;
01032     return true; }
01035 template <int M, class E1, int S1, class E2> inline bool
01036 operator>=(const Vec<M,E1,S1>& v, const E2& e) 
01037 {   for (int i=0; i < M; ++i) if (v[i] < e) return false;
01038     return true; }
01039 
01041 // Global operators involving a vector and a scalar. //
01043 
01044 // I haven't been able to figure out a nice way to templatize for the
01045 // built-in reals without introducing a lot of unwanted type matches
01046 // as well. So we'll just grind them out explicitly here.
01047 
01048 // SCALAR MULTIPLY
01049 
01050 // v = v*real, real*v 
01051 template <int M, class E, int S> inline
01052 typename Vec<M,E,S>::template Result<float>::Mul
01053 operator*(const Vec<M,E,S>& l, const float& r)
01054   { return Vec<M,E,S>::template Result<float>::MulOp::perform(l,r); }
01055 template <int M, class E, int S> inline
01056 typename Vec<M,E,S>::template Result<float>::Mul
01057 operator*(const float& l, const Vec<M,E,S>& r) {return r*l;}
01058 
01059 template <int M, class E, int S> inline
01060 typename Vec<M,E,S>::template Result<double>::Mul
01061 operator*(const Vec<M,E,S>& l, const double& r)
01062   { return Vec<M,E,S>::template Result<double>::MulOp::perform(l,r); }
01063 template <int M, class E, int S> inline
01064 typename Vec<M,E,S>::template Result<double>::Mul
01065 operator*(const double& l, const Vec<M,E,S>& r) {return r*l;}
01066 
01067 template <int M, class E, int S> inline
01068 typename Vec<M,E,S>::template Result<long double>::Mul
01069 operator*(const Vec<M,E,S>& l, const long double& r)
01070   { return Vec<M,E,S>::template Result<long double>::MulOp::perform(l,r); }
01071 template <int M, class E, int S> inline
01072 typename Vec<M,E,S>::template Result<long double>::Mul
01073 operator*(const long double& l, const Vec<M,E,S>& r) {return r*l;}
01074 
01075 // v = v*int, int*v -- just convert int to v's precision float
01076 template <int M, class E, int S> inline
01077 typename Vec<M,E,S>::template Result<typename CNT<E>::Precision>::Mul
01078 operator*(const Vec<M,E,S>& l, int r) {return l * (typename CNT<E>::Precision)r;}
01079 template <int M, class E, int S> inline
01080 typename Vec<M,E,S>::template Result<typename CNT<E>::Precision>::Mul
01081 operator*(int l, const Vec<M,E,S>& r) {return r * (typename CNT<E>::Precision)l;}
01082 
01083 // Complex, conjugate, and negator are all easy to templatize.
01084 
01085 // v = v*complex, complex*v
01086 template <int M, class E, int S, class R> inline
01087 typename Vec<M,E,S>::template Result<std::complex<R> >::Mul
01088 operator*(const Vec<M,E,S>& l, const std::complex<R>& r)
01089   { return Vec<M,E,S>::template Result<std::complex<R> >::MulOp::perform(l,r); }
01090 template <int M, class E, int S, class R> inline
01091 typename Vec<M,E,S>::template Result<std::complex<R> >::Mul
01092 operator*(const std::complex<R>& l, const Vec<M,E,S>& r) {return r*l;}
01093 
01094 // v = v*conjugate, conjugate*v (convert conjugate->complex)
01095 template <int M, class E, int S, class R> inline
01096 typename Vec<M,E,S>::template Result<std::complex<R> >::Mul
01097 operator*(const Vec<M,E,S>& l, const conjugate<R>& r) {return l*(std::complex<R>)r;}
01098 template <int M, class E, int S, class R> inline
01099 typename Vec<M,E,S>::template Result<std::complex<R> >::Mul
01100 operator*(const conjugate<R>& l, const Vec<M,E,S>& r) {return r*(std::complex<R>)l;}
01101 
01102 // v = v*negator, negator*v: convert negator to standard number
01103 template <int M, class E, int S, class R> inline
01104 typename Vec<M,E,S>::template Result<typename negator<R>::StdNumber>::Mul
01105 operator*(const Vec<M,E,S>& l, const negator<R>& r) {return l * (typename negator<R>::StdNumber)(R)r;}
01106 template <int M, class E, int S, class R> inline
01107 typename Vec<M,E,S>::template Result<typename negator<R>::StdNumber>::Mul
01108 operator*(const negator<R>& l, const Vec<M,E,S>& r) {return r * (typename negator<R>::StdNumber)(R)l;}
01109 
01110 
01111 // SCALAR DIVIDE. This is a scalar operation when the scalar is on the right,
01112 // but when it is on the left it means scalar * pseudoInverse(vec), which is 
01113 // a row.
01114 
01115 // v = v/real, real/v 
01116 template <int M, class E, int S> inline
01117 typename Vec<M,E,S>::template Result<float>::Dvd
01118 operator/(const Vec<M,E,S>& l, const float& r)
01119   { return Vec<M,E,S>::template Result<float>::DvdOp::perform(l,r); }
01120 template <int M, class E, int S> inline
01121 typename CNT<float>::template Result<Vec<M,E,S> >::Dvd
01122 operator/(const float& l, const Vec<M,E,S>& r)
01123   { return CNT<float>::template Result<Vec<M,E,S> >::DvdOp::perform(l,r); }
01124 
01125 template <int M, class E, int S> inline
01126 typename Vec<M,E,S>::template Result<double>::Dvd
01127 operator/(const Vec<M,E,S>& l, const double& r)
01128   { return Vec<M,E,S>::template Result<double>::DvdOp::perform(l,r); }
01129 template <int M, class E, int S> inline
01130 typename CNT<double>::template Result<Vec<M,E,S> >::Dvd
01131 operator/(const double& l, const Vec<M,E,S>& r)
01132   { return CNT<double>::template Result<Vec<M,E,S> >::DvdOp::perform(l,r); }
01133 
01134 template <int M, class E, int S> inline
01135 typename Vec<M,E,S>::template Result<long double>::Dvd
01136 operator/(const Vec<M,E,S>& l, const long double& r)
01137   { return Vec<M,E,S>::template Result<long double>::DvdOp::perform(l,r); }
01138 template <int M, class E, int S> inline
01139 typename CNT<long double>::template Result<Vec<M,E,S> >::Dvd
01140 operator/(const long double& l, const Vec<M,E,S>& r)
01141   { return CNT<long double>::template Result<Vec<M,E,S> >::DvdOp::perform(l,r); }
01142 
01143 // v = v/int, int/v -- just convert int to v's precision float
01144 template <int M, class E, int S> inline
01145 typename Vec<M,E,S>::template Result<typename CNT<E>::Precision>::Dvd
01146 operator/(const Vec<M,E,S>& l, int r) {return l / (typename CNT<E>::Precision)r;}
01147 template <int M, class E, int S> inline
01148 typename CNT<typename CNT<E>::Precision>::template Result<Vec<M,E,S> >::Dvd
01149 operator/(int l, const Vec<M,E,S>& r) {return (typename CNT<E>::Precision)l / r;}
01150 
01151 
01152 // Complex, conjugate, and negator are all easy to templatize.
01153 
01154 // v = v/complex, complex/v
01155 template <int M, class E, int S, class R> inline
01156 typename Vec<M,E,S>::template Result<std::complex<R> >::Dvd
01157 operator/(const Vec<M,E,S>& l, const std::complex<R>& r)
01158   { return Vec<M,E,S>::template Result<std::complex<R> >::DvdOp::perform(l,r); }
01159 template <int M, class E, int S, class R> inline
01160 typename CNT<std::complex<R> >::template Result<Vec<M,E,S> >::Dvd
01161 operator/(const std::complex<R>& l, const Vec<M,E,S>& r)
01162   { return CNT<std::complex<R> >::template Result<Vec<M,E,S> >::DvdOp::perform(l,r); }
01163 
01164 // v = v/conjugate, conjugate/v (convert conjugate->complex)
01165 template <int M, class E, int S, class R> inline
01166 typename Vec<M,E,S>::template Result<std::complex<R> >::Dvd
01167 operator/(const Vec<M,E,S>& l, const conjugate<R>& r) {return l/(std::complex<R>)r;}
01168 template <int M, class E, int S, class R> inline
01169 typename CNT<std::complex<R> >::template Result<Vec<M,E,S> >::Dvd
01170 operator/(const conjugate<R>& l, const Vec<M,E,S>& r) {return (std::complex<R>)l/r;}
01171 
01172 // v = v/negator, negator/v: convert negator to number
01173 template <int M, class E, int S, class R> inline
01174 typename Vec<M,E,S>::template Result<typename negator<R>::StdNumber>::Dvd
01175 operator/(const Vec<M,E,S>& l, const negator<R>& r) {return l/(typename negator<R>::StdNumber)(R)r;}
01176 template <int M, class E, int S, class R> inline
01177 typename CNT<R>::template Result<Vec<M,E,S> >::Dvd
01178 operator/(const negator<R>& l, const Vec<M,E,S>& r) {return (typename negator<R>::StdNumber)(R)l/r;}
01179 
01180 
01181 // Add and subtract are odd as scalar ops. They behave as though the
01182 // scalar stands for a vector each of whose elements is that scalar,
01183 // and then a normal vector add or subtract is done.
01184 
01185 // SCALAR ADD
01186 
01187 // v = v+real, real+v 
01188 template <int M, class E, int S> inline
01189 typename Vec<M,E,S>::template Result<float>::Add
01190 operator+(const Vec<M,E,S>& l, const float& r)
01191   { return Vec<M,E,S>::template Result<float>::AddOp::perform(l,r); }
01192 template <int M, class E, int S> inline
01193 typename Vec<M,E,S>::template Result<float>::Add
01194 operator+(const float& l, const Vec<M,E,S>& r) {return r+l;}
01195 
01196 template <int M, class E, int S> inline
01197 typename Vec<M,E,S>::template Result<double>::Add
01198 operator+(const Vec<M,E,S>& l, const double& r)
01199   { return Vec<M,E,S>::template Result<double>::AddOp::perform(l,r); }
01200 template <int M, class E, int S> inline
01201 typename Vec<M,E,S>::template Result<double>::Add
01202 operator+(const double& l, const Vec<M,E,S>& r) {return r+l;}
01203 
01204 template <int M, class E, int S> inline
01205 typename Vec<M,E,S>::template Result<long double>::Add
01206 operator+(const Vec<M,E,S>& l, const long double& r)
01207   { return Vec<M,E,S>::template Result<long double>::AddOp::perform(l,r); }
01208 template <int M, class E, int S> inline
01209 typename Vec<M,E,S>::template Result<long double>::Add
01210 operator+(const long double& l, const Vec<M,E,S>& r) {return r+l;}
01211 
01212 // v = v+int, int+v -- just convert int to v's precision float
01213 template <int M, class E, int S> inline
01214 typename Vec<M,E,S>::template Result<typename CNT<E>::Precision>::Add
01215 operator+(const Vec<M,E,S>& l, int r) {return l + (typename CNT<E>::Precision)r;}
01216 template <int M, class E, int S> inline
01217 typename Vec<M,E,S>::template Result<typename CNT<E>::Precision>::Add
01218 operator+(int l, const Vec<M,E,S>& r) {return r + (typename CNT<E>::Precision)l;}
01219 
01220 // Complex, conjugate, and negator are all easy to templatize.
01221 
01222 // v = v+complex, complex+v
01223 template <int M, class E, int S, class R> inline
01224 typename Vec<M,E,S>::template Result<std::complex<R> >::Add
01225 operator+(const Vec<M,E,S>& l, const std::complex<R>& r)
01226   { return Vec<M,E,S>::template Result<std::complex<R> >::AddOp::perform(l,r); }
01227 template <int M, class E, int S, class R> inline
01228 typename Vec<M,E,S>::template Result<std::complex<R> >::Add
01229 operator+(const std::complex<R>& l, const Vec<M,E,S>& r) {return r+l;}
01230 
01231 // v = v+conjugate, conjugate+v (convert conjugate->complex)
01232 template <int M, class E, int S, class R> inline
01233 typename Vec<M,E,S>::template Result<std::complex<R> >::Add
01234 operator+(const Vec<M,E,S>& l, const conjugate<R>& r) {return l+(std::complex<R>)r;}
01235 template <int M, class E, int S, class R> inline
01236 typename Vec<M,E,S>::template Result<std::complex<R> >::Add
01237 operator+(const conjugate<R>& l, const Vec<M,E,S>& r) {return r+(std::complex<R>)l;}
01238 
01239 // v = v+negator, negator+v: convert negator to standard number
01240 template <int M, class E, int S, class R> inline
01241 typename Vec<M,E,S>::template Result<typename negator<R>::StdNumber>::Add
01242 operator+(const Vec<M,E,S>& l, const negator<R>& r) {return l + (typename negator<R>::StdNumber)(R)r;}
01243 template <int M, class E, int S, class R> inline
01244 typename Vec<M,E,S>::template Result<typename negator<R>::StdNumber>::Add
01245 operator+(const negator<R>& l, const Vec<M,E,S>& r) {return r + (typename negator<R>::StdNumber)(R)l;}
01246 
01247 // SCALAR SUBTRACT -- careful, not commutative.
01248 
01249 // v = v-real, real-v 
01250 template <int M, class E, int S> inline
01251 typename Vec<M,E,S>::template Result<float>::Sub
01252 operator-(const Vec<M,E,S>& l, const float& r)
01253   { return Vec<M,E,S>::template Result<float>::SubOp::perform(l,r); }
01254 template <int M, class E, int S> inline
01255 typename CNT<float>::template Result<Vec<M,E,S> >::Sub
01256 operator-(const float& l, const Vec<M,E,S>& r)
01257   { return CNT<float>::template Result<Vec<M,E,S> >::SubOp::perform(l,r); }
01258 
01259 template <int M, class E, int S> inline
01260 typename Vec<M,E,S>::template Result<double>::Sub
01261 operator-(const Vec<M,E,S>& l, const double& r)
01262   { return Vec<M,E,S>::template Result<double>::SubOp::perform(l,r); }
01263 template <int M, class E, int S> inline
01264 typename CNT<double>::template Result<Vec<M,E,S> >::Sub
01265 operator-(const double& l, const Vec<M,E,S>& r)
01266   { return CNT<double>::template Result<Vec<M,E,S> >::SubOp::perform(l,r); }
01267 
01268 template <int M, class E, int S> inline
01269 typename Vec<M,E,S>::template Result<long double>::Sub
01270 operator-(const Vec<M,E,S>& l, const long double& r)
01271   { return Vec<M,E,S>::template Result<long double>::SubOp::perform(l,r); }
01272 template <int M, class E, int S> inline
01273 typename CNT<long double>::template Result<Vec<M,E,S> >::Sub
01274 operator-(const long double& l, const Vec<M,E,S>& r)
01275   { return CNT<long double>::template Result<Vec<M,E,S> >::SubOp::perform(l,r); }
01276 
01277 // v = v-int, int-v // just convert int to v's precision float
01278 template <int M, class E, int S> inline
01279 typename Vec<M,E,S>::template Result<typename CNT<E>::Precision>::Sub
01280 operator-(const Vec<M,E,S>& l, int r) {return l - (typename CNT<E>::Precision)r;}
01281 template <int M, class E, int S> inline
01282 typename CNT<typename CNT<E>::Precision>::template Result<Vec<M,E,S> >::Sub
01283 operator-(int l, const Vec<M,E,S>& r) {return (typename CNT<E>::Precision)l - r;}
01284 
01285 
01286 // Complex, conjugate, and negator are all easy to templatize.
01287 
01288 // v = v-complex, complex-v
01289 template <int M, class E, int S, class R> inline
01290 typename Vec<M,E,S>::template Result<std::complex<R> >::Sub
01291 operator-(const Vec<M,E,S>& l, const std::complex<R>& r)
01292   { return Vec<M,E,S>::template Result<std::complex<R> >::SubOp::perform(l,r); }
01293 template <int M, class E, int S, class R> inline
01294 typename CNT<std::complex<R> >::template Result<Vec<M,E,S> >::Sub
01295 operator-(const std::complex<R>& l, const Vec<M,E,S>& r)
01296   { return CNT<std::complex<R> >::template Result<Vec<M,E,S> >::SubOp::perform(l,r); }
01297 
01298 // v = v-conjugate, conjugate-v (convert conjugate->complex)
01299 template <int M, class E, int S, class R> inline
01300 typename Vec<M,E,S>::template Result<std::complex<R> >::Sub
01301 operator-(const Vec<M,E,S>& l, const conjugate<R>& r) {return l-(std::complex<R>)r;}
01302 template <int M, class E, int S, class R> inline
01303 typename CNT<std::complex<R> >::template Result<Vec<M,E,S> >::Sub
01304 operator-(const conjugate<R>& l, const Vec<M,E,S>& r) {return (std::complex<R>)l-r;}
01305 
01306 // v = v-negator, negator-v: convert negator to standard number
01307 template <int M, class E, int S, class R> inline
01308 typename Vec<M,E,S>::template Result<typename negator<R>::StdNumber>::Sub
01309 operator-(const Vec<M,E,S>& l, const negator<R>& r) {return l-(typename negator<R>::StdNumber)(R)r;}
01310 template <int M, class E, int S, class R> inline
01311 typename CNT<R>::template Result<Vec<M,E,S> >::Sub
01312 operator-(const negator<R>& l, const Vec<M,E,S>& r) {return (typename negator<R>::StdNumber)(R)l-r;}
01313 
01314 // Vec I/O
01315 template <int M, class E, int S, class CHAR, class TRAITS> inline
01316 std::basic_ostream<CHAR,TRAITS>&
01317 operator<<(std::basic_ostream<CHAR,TRAITS>& o, const Vec<M,E,S>& v) {
01318     o << "~[" << v[0]; for(int i=1;i<M;++i) o<<','<<v[i]; o<<']'; return o;
01319 }
01320 
01323 template <int M, class E, int S, class CHAR, class TRAITS> inline
01324 std::basic_istream<CHAR,TRAITS>&
01325 operator>>(std::basic_istream<CHAR,TRAITS>& is, Vec<M,E,S>& v) {
01326     CHAR tilde;
01327     is >> tilde; if (is.fail()) return is;
01328     if (tilde != CHAR('~')) {
01329         tilde = CHAR(0);
01330         is.unget(); if (is.fail()) return is;
01331     }
01332 
01333     CHAR openBracket, closeBracket;
01334     is >> openBracket; if (is.fail()) return is;
01335     if (openBracket==CHAR('('))
01336         closeBracket = CHAR(')');
01337     else if (openBracket==CHAR('['))
01338         closeBracket = CHAR(']');
01339     else {
01340         closeBracket = CHAR(0);
01341         is.unget(); if (is.fail()) return is;
01342     }
01343 
01344     // If we saw a "~" but then we didn't see any brackets, that's an
01345     // error. Set the fail bit and return.
01346     if (tilde != CHAR(0) && closeBracket == CHAR(0)) {
01347         is.setstate( std::ios::failbit );
01348         return is;
01349     }
01350 
01351     for (int i=0; i < M; ++i) {
01352         is >> v[i];
01353         if (is.fail()) return is;
01354         if (i != M-1) {
01355             CHAR c; is >> c; if (is.fail()) return is;
01356             if (c != ',') is.unget();
01357             if (is.fail()) return is;
01358         }
01359     }
01360 
01361     // Get the closing bracket if there was an opening one. If we don't
01362     // see the expected character we'll set the fail bit in the istream.
01363     if (closeBracket != CHAR(0)) {
01364         CHAR closer; is >> closer; if (is.fail()) return is;
01365         if (closer != closeBracket) {
01366             is.unget(); if (is.fail()) return is;
01367             is.setstate( std::ios::failbit );
01368         }
01369     }
01370 
01371     return is;
01372 }
01373 
01374 } //namespace SimTK
01375 
01376 
01377 #endif //SimTK_SIMMATRIX_SMALLMATRIX_VEC_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines