Simbody

Row.h

Go to the documentation of this file.
00001 #ifndef SimTK_SIMMATRIX_SMALLMATRIX_ROW_H_
00002 #define SimTK_SIMMATRIX_SMALLMATRIX_ROW_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                      SimTK Core: SimTK Simmatrix(tm)                       *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK Core biosimulation toolkit originating from      *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org.               *
00011  *                                                                            *
00012  * Portions copyright (c) 2005-10 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 
00042 namespace SimTK {
00043 
00044 // The following functions are used internally by Row.
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 Row<1,E1,S1>& r1, const Row<1,E2,S2>& r2, Row<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 Row<N,E1,S1>& r1, const Row<N,E2,S2>& r2, Row<N,typename CNT<E1>::template Result<E2>::Add>& result) {
00057     conformingAdd(reinterpret_cast<const Row<N-1,E1,S1>&>(r1), reinterpret_cast<const Row<N-1,E2,S2>&>(r2), reinterpret_cast<Row<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 Row<1,E1,S1>& r1, const Row<1,E2,S2>& r2, Row<1,typename CNT<E1>::template Result<E2>::Sub>& 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 Row<N,E1,S1>& r1, const Row<N,E2,S2>& r2, Row<N,typename CNT<E1>::template Result<E2>::Sub>& result) {
00066     conformingSubtract(reinterpret_cast<const Row<N-1,E1,S1>&>(r1), reinterpret_cast<const Row<N-1,E2,S2>&>(r2), reinterpret_cast<Row<N-1,typename CNT<E1>::template Result<E2>::Sub>&>(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(Row<1,E1,S1>& r1, const Row<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(Row<N,E1,S1>& r1, const Row<N,E2,S2>& r2) {
00075     copy(reinterpret_cast<Row<N-1,E1,S1>&>(r1), reinterpret_cast<const Row<N-1,E2,S2>&>(r2));
00076     r1[N-1] = r2[N-1];
00077 }
00078 
00079 }
00080 
00082 template <int N, class ELT, int STRIDE> class Row {
00083     typedef ELT                                 E;
00084     typedef typename CNT<E>::TNeg               ENeg;
00085     typedef typename CNT<E>::TWithoutNegator    EWithoutNegator;
00086     typedef typename CNT<E>::TReal              EReal;
00087     typedef typename CNT<E>::TImag              EImag;
00088     typedef typename CNT<E>::TComplex           EComplex;
00089     typedef typename CNT<E>::THerm              EHerm;
00090     typedef typename CNT<E>::TPosTrans          EPosTrans;
00091     typedef typename CNT<E>::TSqHermT           ESqHermT;
00092     typedef typename CNT<E>::TSqTHerm           ESqTHerm;
00093 
00094     typedef typename CNT<E>::TSqrt              ESqrt;
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>::ULessScalar        EULessScalar;
00102     typedef typename CNT<E>::Number             ENumber;
00103     typedef typename CNT<E>::StdNumber          EStdNumber;
00104     typedef typename CNT<E>::Precision          EPrecision;
00105     typedef typename CNT<E>::ScalarNormSq       EScalarNormSq;
00106 
00107 public:
00108 
00109     enum {
00110         NRows               = 1,
00111         NCols               = N,
00112         NPackedElements     = N,
00113         NActualElements     = N * STRIDE,   // includes trailing gap
00114         NActualScalars      = CNT<E>::NActualScalars * NActualElements,
00115         RowSpacing          = NActualElements,
00116         ColSpacing          = STRIDE,
00117         ImagOffset          = NTraits<ENumber>::ImagOffset,
00118         RealStrideFactor    = 1, // composite types don't change size when
00119                                  // cast from complex to real or imaginary
00120         ArgDepth            = ((int)CNT<E>::ArgDepth < (int)MAX_RESOLVED_DEPTH 
00121                                 ? CNT<E>::ArgDepth + 1 
00122                                 : MAX_RESOLVED_DEPTH),
00123         IsScalar            = 0,
00124         IsULessScalar       = 0,
00125         IsNumber            = 0,
00126         IsStdNumber         = 0,
00127         IsPrecision         = 0,
00128         SignInterpretation  = CNT<E>::SignInterpretation
00129     };
00130 
00131     typedef Row<N,E,STRIDE>                 T;
00132     typedef Row<N,ENeg,STRIDE>              TNeg;
00133     typedef Row<N,EWithoutNegator,STRIDE>   TWithoutNegator;
00134 
00135     typedef Row<N,EReal,STRIDE*CNT<E>::RealStrideFactor>         
00136                                             TReal;
00137     typedef Row<N,EImag,STRIDE*CNT<E>::RealStrideFactor>         
00138                                             TImag;
00139     typedef Row<N,EComplex,STRIDE>          TComplex;
00140     typedef Vec<N,EHerm,STRIDE>             THerm;
00141     typedef Vec<N,E,STRIDE>                 TPosTrans;
00142     typedef E                               TElement;
00143     typedef Row                             TRow;
00144     typedef E                               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<N,ESqrt,1>                  TSqrt;      // Note stride
00149     typedef Row<N,EAbs,1>                   TAbs;       // Note stride
00150     typedef Row<N,EStandard,1>              TStandard;
00151     typedef Vec<N,EInvert,1>                TInvert;    // packed
00152     typedef Row<N,ENormalize,1>             TNormalize;
00153 
00154     typedef SymMat<N,ESqHermT>              TSqHermT;   // result of self outer product
00155     typedef EScalarNormSq                   TSqTHerm;   // result of self dot product
00156 
00157     // These recurse right down to the underlying scalar type no matter how
00158     // deep the elements are.
00159     typedef EScalar                         Scalar;
00160     typedef EULessScalar                    ULessScalar;
00161     typedef ENumber                         Number;
00162     typedef EStdNumber                      StdNumber;
00163     typedef EPrecision                      Precision;
00164     typedef EScalarNormSq                   ScalarNormSq;
00165 
00166     int size()   const  { return N; }
00167     int nrow()   const  { return 1; }
00168     int ncol()   const  { return N; }
00169 
00170 
00171     // Scalar norm square is sum( conjugate squares of all scalars )
00172     ScalarNormSq scalarNormSqr() const { 
00173         ScalarNormSq sum(0);
00174         for(int i=0;i<N;++i) sum += CNT<E>::scalarNormSqr(d[i*STRIDE]);
00175         return sum;
00176     }
00177 
00178     // sqrt() is elementwise square root; that is, the return value has the same
00179     // dimension as this Vec but with each element replaced by whatever it thinks
00180     // its square root is.
00181     TSqrt sqrt() const {
00182         TSqrt rsqrt;
00183         for(int i=0;i<N;++i) rsqrt[i] = CNT<E>::sqrt(d[i*STRIDE]);
00184         return rsqrt;
00185     }
00186 
00187     // abs() is elementwise absolute value; that is, the return value has the same
00188     // dimension as this Row but with each element replaced by whatever it thinks
00189     // its absolute value is.
00190     TAbs abs() const {
00191         TAbs rabs;
00192         for(int i=0;i<N;++i) rabs[i] = CNT<E>::abs(d[i*STRIDE]);
00193         return rabs;
00194     }
00195 
00196     TStandard standardize() const {
00197         TStandard rstd;
00198         for(int i=0;i<N;++i) rstd[i] = CNT<E>::standardize(d[i*STRIDE]);
00199         return rstd;
00200     }
00201 
00202     // Sum just adds up all the elements, getting rid of negators and
00203     // conjugates in the process.
00204     EStandard sum() const {
00205         E sum(0);
00206         for (int i=0;i<N;++i) sum += d[i*STRIDE];
00207         return CNT<E>::standardize(sum);
00208     }
00209 
00210     // This gives the resulting rowvector type when (v[i] op P) is applied to each element of v.
00211     // It is a row of length N, stride 1, and element types which are the regular
00212     // composite result of E op P. Typically P is a scalar type but it doesn't have to be.
00213     template <class P> struct EltResult { 
00214         typedef Row<N, typename CNT<E>::template Result<P>::Mul, 1> Mul;
00215         typedef Row<N, typename CNT<E>::template Result<P>::Dvd, 1> Dvd;
00216         typedef Row<N, typename CNT<E>::template Result<P>::Add, 1> Add;
00217         typedef Row<N, typename CNT<E>::template Result<P>::Sub, 1> Sub;
00218     };
00219 
00220     // This is the composite result for v op P where P is some kind of appropriately shaped
00221     // non-scalar type.
00222     template <class P> struct Result { 
00223         typedef MulCNTs<1,N,ArgDepth,Row,ColSpacing,RowSpacing,
00224             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00225             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> MulOp;
00226         typedef typename MulOp::Type Mul;
00227 
00228         typedef MulCNTsNonConforming<1,N,ArgDepth,Row,ColSpacing,RowSpacing,
00229             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00230             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> MulOpNonConforming;
00231         typedef typename MulOpNonConforming::Type MulNon;
00232 
00233 
00234         typedef DvdCNTs<1,N,ArgDepth,Row,ColSpacing,RowSpacing,
00235             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00236             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> DvdOp;
00237         typedef typename DvdOp::Type Dvd;
00238 
00239         typedef AddCNTs<1,N,ArgDepth,Row,ColSpacing,RowSpacing,
00240             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00241             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> AddOp;
00242         typedef typename AddOp::Type Add;
00243 
00244         typedef SubCNTs<1,N,ArgDepth,Row,ColSpacing,RowSpacing,
00245             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
00246             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> SubOp;
00247         typedef typename SubOp::Type Sub;
00248     };
00249 
00250     // Shape-preserving element substitution (always packed)
00251     template <class P> struct Substitute {
00252         typedef Row<N,P> Type;
00253     };
00254 
00255     // Default construction initializes to NaN when debugging but
00256     // is left uninitialized otherwise.
00257     Row(){ 
00258     #ifndef NDEBUG
00259         setToNaN();
00260     #endif
00261     }
00262 
00263     // It's important not to use the default copy constructor or copy
00264     // assignment because the compiler doesn't understand that we may
00265     // have noncontiguous storage and will try to copy the whole array.
00266     Row(const Row& src) {
00267         Impl::copy(*this, src);
00268     }
00269     Row& operator=(const Row& src) {    // no harm if src and 'this' are the same
00270         Impl::copy(*this, src);
00271         return *this;
00272     }
00273 
00274     // We want an implicit conversion from a Row of the same length
00275     // and element type but with a different stride.
00276     template <int SS> Row(const Row<N,E,SS>& src) {
00277         Impl::copy(*this, src);
00278     }
00279 
00280     // We want an implicit conversion from a Row of the same length
00281     // and *negated* element type, possibly with a different stride.
00282     template <int SS> Row(const Row<N,ENeg,SS>& src) {
00283         Impl::copy(*this, src);
00284     }
00285 
00286     // Construct a Row from a Row of the same length, with any
00287     // stride. Works as long as the element types are compatible.
00288     template <class EE, int SS> explicit Row(const Row<N,EE,SS>& vv) {
00289         Impl::copy(*this, vv);
00290     }
00291 
00292     // Construction using an element assigns to each element.
00293     explicit Row(const E& e)
00294       { for (int i=0;i<N;++i) d[i*STRIDE]=e; }
00295 
00296     // Construction using a negated element assigns to each element.
00297     explicit Row(const ENeg& ne)
00298       { for (int i=0;i<N;++i) d[i*STRIDE]=ne; }
00299 
00300     // Given an int, turn it into a suitable floating point number
00301     // and then feed that to the above single-element constructor.
00302     explicit Row(int i) 
00303       { new (this) Row(E(Precision(i))); }
00304 
00305     // A bevy of constructors for Rows up to length 6.
00306     Row(const E& e0,const E& e1)
00307       { assert(N==2);(*this)[0]=e0;(*this)[1]=e1; }
00308     Row(const E& e0,const E& e1,const E& e2)
00309       { assert(N==3);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2; }
00310     Row(const E& e0,const E& e1,const E& e2,const E& e3)
00311       { assert(N==4);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;(*this)[3]=e3; }
00312     Row(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4)
00313       { assert(N==5);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;
00314         (*this)[3]=e3;(*this)[4]=e4; }
00315     Row(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,const E& e5)
00316       { assert(N==6);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;
00317         (*this)[3]=e3;(*this)[4]=e4;(*this)[5]=e5; }
00318     Row(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,const E& e5,const E& e6)
00319       { assert(N==7);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;
00320         (*this)[3]=e3;(*this)[4]=e4;(*this)[5]=e5;(*this)[6]=e6; }
00321     Row(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,const E& e5,const E& e6,const E& e7)
00322       { assert(N==8);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;
00323         (*this)[3]=e3;(*this)[4]=e4;(*this)[5]=e5;(*this)[6]=e6;(*this)[7]=e7; }
00324     Row(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)
00325       { assert(N==9);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;
00326         (*this)[3]=e3;(*this)[4]=e4;(*this)[5]=e5;(*this)[6]=e6;(*this)[7]=e7;(*this)[8]=e8; }
00327 
00328     // Construction from a pointer to anything assumes we're pointing
00329     // at an element list of the right length.
00330     template <class EE> explicit Row(const EE* p)
00331       { assert(p); for(int i=0;i<N;++i) d[i*STRIDE]=p[i]; }
00332     template <class EE> Row& operator=(const EE* p)
00333       { assert(p); for(int i=0;i<N;++i) d[i*STRIDE]=p[i]; return *this; }
00334 
00335     // Conforming assignment ops.
00336     template <class EE, int SS> Row& operator=(const Row<N,EE,SS>& vv) {
00337         Impl::copy(*this, vv);
00338         return *this;
00339     }
00340     template <class EE, int SS> Row& operator+=(const Row<N,EE,SS>& r)
00341       { for(int i=0;i<N;++i) d[i*STRIDE] += r[i]; return *this; }
00342     template <class EE, int SS> Row& operator+=(const Row<N,negator<EE>,SS>& r)
00343       { for(int i=0;i<N;++i) d[i*STRIDE] -= -(r[i]); return *this; }
00344     template <class EE, int SS> Row& operator-=(const Row<N,EE,SS>& r)
00345       { for(int i=0;i<N;++i) d[i*STRIDE] -= r[i]; return *this; }
00346     template <class EE, int SS> Row& operator-=(const Row<N,negator<EE>,SS>& r)
00347       { for(int i=0;i<N;++i) d[i*STRIDE] += -(r[i]); return *this; }
00348 
00349     // Conforming binary ops with 'this' on left, producing new packed result.
00350     // Cases: r=r+r, r=r-r, s=r*v r=r*m
00351     template <class EE, int SS> Row<N,typename CNT<E>::template Result<EE>::Add>
00352     conformingAdd(const Row<N,EE,SS>& r) const {
00353         Row<N,typename CNT<E>::template Result<EE>::Add> result;
00354         Impl::conformingAdd(*this, r, result);
00355         return result;
00356     }
00357     template <class EE, int SS> Row<N,typename CNT<E>::template Result<EE>::Sub>
00358     conformingSubtract(const Row<N,EE,SS>& r) const {
00359         Row<N,typename CNT<E>::template Result<EE>::Sub> result;
00360         Impl::conformingSubtract(*this, r, result);
00361         return result;
00362     }
00363 
00364     // dot product (s = row*col)
00365     template <class EE, int SS> typename CNT<E>::template Result<EE>::Mul
00366     conformingMultiply(const Vec<N,EE,SS>& r) const {
00367         return (*this)*r;
00368     }
00369 
00370     // row=row*mat
00371     template <int MatNCol, class EE, int CS, int RS> 
00372     Row<MatNCol,typename CNT<E>::template Result<EE>::Mul>
00373     conformingMultiply(const Mat<N,MatNCol,EE,CS,RS>& m) const {
00374         Row<MatNCol,typename CNT<E>::template Result<EE>::Mul> result;
00375         for (int j=0;j<N;++j) result[j] = conformingMultiply(m(j));
00376         return result;
00377     }
00378 
00379     const E& operator[](int i) const { assert(0 <= i && i < N); return d[i*STRIDE]; }
00380     E&       operator[](int i)       { assert(0 <= i && i < N); return d[i*STRIDE]; }
00381     const E& operator()(int i) const { return (*this)[i]; }
00382     E&       operator()(int i)       { return (*this)[i]; }
00383 
00384     ScalarNormSq normSqr() const { return scalarNormSqr(); }
00385     typename CNT<ScalarNormSq>::TSqrt 
00386         norm() const { return CNT<ScalarNormSq>::sqrt(scalarNormSqr()); }
00387 
00388     // If the elements of this Row are scalars, the result is what you get by
00389     // dividing each element by the norm() calculated above. If the elements are
00390     // *not* scalars, then the elements are *separately* normalized. That means
00391     // you will get a different answer from Row<2,Row3>::normalize() than you
00392     // would from a Row<6>::normalize() containing the same scalars.
00393     //
00394     // Normalize returns a row of the same dimension but in new, packed storage
00395     // and with a return type that does not include negator<> even if the original
00396     // Row<> does, because we can eliminate the negation here almost for free.
00397     // But we can't standardize (change conjugate to complex) for free, so we'll retain
00398     // conjugates if there are any.
00399     TNormalize normalize() const {
00400         if (CNT<E>::IsScalar) {
00401             return castAwayNegatorIfAny() / (SignInterpretation*norm());
00402         } else {
00403             TNormalize elementwiseNormalized;
00404             for (int j=0; j<N; ++j) 
00405                 elementwiseNormalized[j] = CNT<E>::normalize((*this)[j]);
00406             return elementwiseNormalized;
00407         }
00408     }
00409 
00410     TInvert invert() const {assert(false); return TInvert();} // TODO default inversion
00411 
00412     const Row&   operator+() const { return *this; }
00413     const TNeg&  operator-() const { return negate(); }
00414     TNeg&        operator-()       { return updNegate(); }
00415     const THerm& operator~() const { return transpose(); }
00416     THerm&       operator~()       { return updTranspose(); }
00417 
00418     const TNeg&  negate() const { return *reinterpret_cast<const TNeg*>(this); }
00419     TNeg&        updNegate()    { return *reinterpret_cast<TNeg*>(this); }
00420 
00421     const THerm& transpose()    const { return *reinterpret_cast<const THerm*>(this); }
00422     THerm&       updTranspose()       { return *reinterpret_cast<THerm*>(this); }
00423 
00424     const TPosTrans& positionalTranspose() const
00425         { return *reinterpret_cast<const TPosTrans*>(this); }
00426     TPosTrans&       updPositionalTranspose()
00427         { return *reinterpret_cast<TPosTrans*>(this); }
00428 
00429     const TReal& real() const { return *reinterpret_cast<const TReal*>(this); }
00430     TReal&       real()       { return *reinterpret_cast<      TReal*>(this); }
00431 
00432     // Had to contort these routines to get them through VC++ 7.net
00433     const TImag& imag()    const { 
00434         const int offs = ImagOffset;
00435         const EImag* p = reinterpret_cast<const EImag*>(this);
00436         return *reinterpret_cast<const TImag*>(p+offs);
00437     }
00438     TImag& imag() { 
00439         const int offs = ImagOffset;
00440         EImag* p = reinterpret_cast<EImag*>(this);
00441         return *reinterpret_cast<TImag*>(p+offs);
00442     }
00443 
00444     const TWithoutNegator& castAwayNegatorIfAny() const {return *reinterpret_cast<const TWithoutNegator*>(this);}
00445     TWithoutNegator&       updCastAwayNegatorIfAny()    {return *reinterpret_cast<TWithoutNegator*>(this);}
00446 
00447 
00448     // These are elementwise binary operators, (this op ee) by default but 
00449     // (ee op this) if 'FromLeft' appears in the name. The result is a packed 
00450     // Row<N> but the element type may change. These are mostly used to 
00451     // implement global operators. We call these "scalar" operators but 
00452     // actually the "scalar" can be a composite type.
00453 
00454     //TODO: consider converting 'e' to Standard Numbers as precalculation and 
00455     // changing return type appropriately.
00456     template <class EE> Row<N, typename CNT<E>::template Result<EE>::Mul>
00457     scalarMultiply(const EE& e) const {
00458         Row<N, typename CNT<E>::template Result<EE>::Mul> result;
00459         for (int j=0; j<N; ++j) result[j] = (*this)[j] * e;
00460         return result;
00461     }
00462     template <class EE> Row<N, typename CNT<EE>::template Result<E>::Mul>
00463     scalarMultiplyFromLeft(const EE& e) const {
00464         Row<N, typename CNT<EE>::template Result<E>::Mul> result;
00465         for (int j=0; j<N; ++j) result[j] = e * (*this)[j];
00466         return result;
00467     }
00468 
00469     // TODO: should precalculate and store 1/e, while converting to Standard 
00470     // Numbers. Note that return type should change appropriately.
00471     template <class EE> Row<N, typename CNT<E>::template Result<EE>::Dvd>
00472     scalarDivide(const EE& e) const {
00473         Row<N, typename CNT<E>::template Result<EE>::Dvd> result;
00474         for (int j=0; j<N; ++j) result[j] = (*this)[j] / e;
00475         return result;
00476     }
00477     template <class EE> Row<N, typename CNT<EE>::template Result<E>::Dvd>
00478     scalarDivideFromLeft(const EE& e) const {
00479         Row<N, typename CNT<EE>::template Result<E>::Dvd> result;
00480         for (int j=0; j<N; ++j) result[j] = e / (*this)[j];
00481         return result;
00482     }
00483 
00484     template <class EE> Row<N, typename CNT<E>::template Result<EE>::Add>
00485     scalarAdd(const EE& e) const {
00486         Row<N, typename CNT<E>::template Result<EE>::Add> result;
00487         for (int j=0; j<N; ++j) result[j] = (*this)[j] + e;
00488         return result;
00489     }
00490     // Add is commutative, so no 'FromLeft'.
00491 
00492     template <class EE> Row<N, typename CNT<E>::template Result<EE>::Sub>
00493     scalarSubtract(const EE& e) const {
00494         Row<N, typename CNT<E>::template Result<EE>::Sub> result;
00495         for (int j=0; j<N; ++j) result[j] = (*this)[j] - e;
00496         return result;
00497     }
00498     template <class EE> Row<N, typename CNT<EE>::template Result<E>::Sub>
00499     scalarSubtractFromLeft(const EE& e) const {
00500         Row<N, typename CNT<EE>::template Result<E>::Sub> result;
00501         for (int j=0; j<N; ++j) result[j] = e - (*this)[j];
00502         return result;
00503     }
00504 
00505     // Generic assignments for any element type not listed explicitly, including scalars.
00506     // These are done repeatedly for each element and only work if the operation can
00507     // be performed leaving the original element type.
00508     template <class EE> Row& operator =(const EE& e) {return scalarEq(e);}
00509     template <class EE> Row& operator+=(const EE& e) {return scalarPlusEq(e);}
00510     template <class EE> Row& operator-=(const EE& e) {return scalarMinusEq(e);}
00511     template <class EE> Row& operator*=(const EE& e) {return scalarTimesEq(e);}
00512     template <class EE> Row& operator/=(const EE& e) {return scalarDivideEq(e);}
00513 
00514     // Generalized scalar assignment & computed assignment methods. These will work
00515     // for any assignment-compatible element, not just scalars.
00516     template <class EE> Row& scalarEq(const EE& ee)
00517       { for(int i=0;i<N;++i) d[i*STRIDE] = ee; return *this; }
00518     template <class EE> Row& scalarPlusEq(const EE& ee)
00519       { for(int i=0;i<N;++i) d[i*STRIDE] += ee; return *this; }
00520     template <class EE> Row& scalarMinusEq(const EE& ee)
00521       { for(int i=0;i<N;++i) d[i*STRIDE] -= ee; return *this; }
00522     template <class EE> Row& scalarMinusEqFromLeft(const EE& ee)
00523       { for(int i=0;i<N;++i) d[i*STRIDE] = ee - d[i*STRIDE]; return *this; }
00524     template <class EE> Row& scalarTimesEq(const EE& ee)
00525       { for(int i=0;i<N;++i) d[i*STRIDE] *= ee; return *this; }
00526     template <class EE> Row& scalarTimesEqFromLeft(const EE& ee)
00527       { for(int i=0;i<N;++i) d[i*STRIDE] = ee * d[i*STRIDE]; return *this; }
00528     template <class EE> Row& scalarDivideEq(const EE& ee)
00529       { for(int i=0;i<N;++i) d[i*STRIDE] /= ee; return *this; }
00530     template <class EE> Row& scalarDivideEqFromLeft(const EE& ee)
00531       { for(int i=0;i<N;++i) d[i*STRIDE] = ee / d[i*STRIDE]; return *this; }
00532 
00533     void setToNaN() {
00534         (*this) = CNT<ELT>::getNaN();
00535     }
00536 
00537     void setToZero() {
00538         (*this) = ELT(0);
00539     }
00540 
00541     // Extract a sub-Row with size known at compile time. These have to be
00542     // called with explicit template arguments, e.g. getSubRow<3>(j).
00543     template <int NN>
00544     const Row<NN,ELT,STRIDE>& getSubRow(int j) const {
00545         assert(0 <= j && j + NN <= N);
00546         return Row<NN,ELT,STRIDE>::getAs(&(*this)[j]);
00547     }
00548     template <int NN>
00549     Row<NN,ELT,STRIDE>& updSubRow(int j) {
00550         assert(0 <= j && j + NN <= N);
00551         return Row<NN,ELT,STRIDE>::updAs(&(*this)[j]);
00552     }
00553 
00554     // Return a row one smaller than this one by dropping the element
00555     // at the indicated position p. The result is packed but has same
00556     // element type as this one.
00557     Row<N-1,ELT,1> drop1(int p) const {
00558         assert(0 <= p && p < N);
00559         Row<N-1,ELT,1> out;
00560         int nxt=0;
00561         for (int i=0; i<N-1; ++i, ++nxt) {
00562             if (nxt==p) ++nxt;  // skip the loser
00563             out[i] = (*this)[nxt];
00564         }
00565         return out;
00566     }
00567 
00568     // Return a vector one larger than this one by adding an element
00569     // to the end. The result is packed but has same element type as
00570     // this one. Works for any assignment compatible element.
00571     template <class EE> Row<N+1,ELT,1> append1(const EE& v) const {
00572         Row<N+1,ELT,1> out;
00573         Row<N,ELT,1>::updAs(&out[0]) = (*this);
00574         out[N] = v;
00575         return out;
00576     }
00577 
00578 
00579     // Return a vector one larger than this one by inserting an element
00580     // *before* the indicated one. The result is packed but has same element type as
00581     // this one. Works for any assignment compatible element. The index
00582     // can be one greater than normally allowed in which case the element
00583     // is appended.
00584     template <class EE> Row<N+1,ELT,1> insert1(int p, const EE& v) const {
00585         assert(0 <= p && p <= N);
00586         if (p==N) return append1(v);
00587         Row<N+1,ELT,1> out;
00588         int nxt=0;
00589         for (int i=0; i<N; ++i, ++nxt) {
00590             if (i==p) out[nxt++] = v;
00591             out[nxt] = (*this)[i];
00592         }
00593         return out;
00594     }
00595 
00596     // These assume we are given a pointer to d[0] of a Row<N,E,S> like this one.
00597     static const Row& getAs(const ELT* p)  {return *reinterpret_cast<const Row*>(p);}
00598     static Row&       updAs(ELT* p)        {return *reinterpret_cast<Row*>(p);}
00599 
00600     // Extract a subrow from a longer one. Element type and stride must match.
00601     template <int NN>
00602     static const Row& getSubRow(const Row<NN,ELT,STRIDE>& r, int j) {
00603         assert(0 <= j && j + N <= NN);
00604         return getAs(&r[j]);
00605     }
00606     template <int NN>
00607     static Row& updSubRow(Row<NN,ELT,STRIDE>& r, int j) {
00608         assert(0 <= j && j + N <= NN);
00609         return updAs(&r[j]);
00610     }
00611 
00612     static Row<N,ELT,1> getNaN() { return Row<N,ELT,1>(CNT<ELT>::getNaN()); }
00613 
00615     bool isNaN() const {
00616         for (int j=0; j<N; ++j)
00617             if (CNT<ELT>::isNaN((*this)[j]))
00618                 return true;
00619         return false;
00620     }
00621 
00624     bool isInf() const {
00625         bool seenInf = false;
00626         for (int j=0; j<N; ++j) {
00627             const ELT& e = (*this)[j];
00628             if (!CNT<ELT>::isFinite(e)) {
00629                 if (!CNT<ELT>::isInf(e)) 
00630                     return false; // something bad was found
00631                 seenInf = true; 
00632             }
00633         }
00634         return seenInf;
00635     }
00636 
00638     bool isFinite() const {
00639         for (int j=0; j<N; ++j)
00640             if (!CNT<ELT>::isFinite((*this)[j]))
00641                 return false;
00642         return true;
00643     }
00644 
00647     static double getDefaultTolerance() {return CNT<ELT>::getDefaultTolerance();}
00648 
00651     template <class E2, int CS2>
00652     bool isNumericallyEqual(const Row<N,E2,CS2>& r, double tol) const {
00653         for (int j=0; j<N; ++j)
00654             if (!CNT<ELT>::isNumericallyEqual((*this)(j), r(j), tol))
00655                 return false;
00656         return true;
00657     }
00658 
00662     template <class E2, int CS2>
00663     bool isNumericallyEqual(const Row<N,E2,CS2>& r) const {
00664         const double tol = std::max(getDefaultTolerance(),r.getDefaultTolerance());
00665         return isNumericallyEqual(r, tol);
00666     }
00667 
00672     bool isNumericallyEqual
00673        (const ELT& e,
00674         double     tol = getDefaultTolerance()) const 
00675     {
00676         for (int j=0; j<N; ++j)
00677             if (!CNT<ELT>::isNumericallyEqual((*this)(j), e, tol))
00678                 return false;
00679         return true;
00680     }
00681 private:
00682     ELT d[NActualElements];    // data
00683 };
00684 
00686 // Global operators involving two rows.    //
00687 //   v+v, v-v, v==v, v!=v                  //
00689 
00690 // v3 = v1 + v2 where all v's have the same length N. 
00691 template <int N, class E1, int S1, class E2, int S2> inline
00692 typename Row<N,E1,S1>::template Result< Row<N,E2,S2> >::Add
00693 operator+(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r) { 
00694     return Row<N,E1,S1>::template Result< Row<N,E2,S2> >
00695         ::AddOp::perform(l,r);
00696 }
00697 
00698 // v3 = v1 - v2, similar to +
00699 template <int N, class E1, int S1, class E2, int S2> inline
00700 typename Row<N,E1,S1>::template Result< Row<N,E2,S2> >::Sub
00701 operator-(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r) { 
00702     return Row<N,E1,S1>::template Result< Row<N,E2,S2> >
00703         ::SubOp::perform(l,r);
00704 }
00705 
00707 template <int N, class E1, int S1, class E2, int S2> inline bool
00708 operator==(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r) { 
00709     for (int i=0; i < N; ++i) if (l[i] != r[i]) return false;
00710     return true;
00711 }
00713 template <int N, class E1, int S1, class E2, int S2> inline bool
00714 operator!=(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r) {return !(l==r);} 
00715 
00717 template <int N, class E1, int S1, class E2, int S2> inline bool
00718 operator<(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r) 
00719 {   for (int i=0; i < N; ++i) if (l[i] >= r[i]) return false;
00720     return true; }
00722 template <int N, class E1, int S1, class E2> inline bool
00723 operator<(const Row<N,E1,S1>& v, const E2& e) 
00724 {   for (int i=0; i < N; ++i) if (v[i] >= e) return false;
00725     return true; }
00726 
00728 template <int N, class E1, int S1, class E2, int S2> inline bool
00729 operator>(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r) 
00730 {   for (int i=0; i < N; ++i) if (l[i] <= r[i]) return false;
00731     return true; }
00733 template <int N, class E1, int S1, class E2> inline bool
00734 operator>(const Row<N,E1,S1>& v, const E2& e) 
00735 {   for (int i=0; i < N; ++i) if (v[i] <= e) return false;
00736     return true; }
00737 
00740 template <int N, class E1, int S1, class E2, int S2> inline bool
00741 operator<=(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r) 
00742 {   for (int i=0; i < N; ++i) if (l[i] > r[i]) return false;
00743     return true; }
00746 template <int N, class E1, int S1, class E2> inline bool
00747 operator<=(const Row<N,E1,S1>& v, const E2& e) 
00748 {   for (int i=0; i < N; ++i) if (v[i] > e) return false;
00749     return true; }
00750 
00753 template <int N, class E1, int S1, class E2, int S2> inline bool
00754 operator>=(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r) 
00755 {   for (int i=0; i < N; ++i) if (l[i] < r[i]) return false;
00756     return true; }
00759 template <int N, class E1, int S1, class E2> inline bool
00760 operator>=(const Row<N,E1,S1>& v, const E2& e) 
00761 {   for (int i=0; i < N; ++i) if (v[i] < e) return false;
00762     return true; }
00763 
00765 // Global operators involving a row and a scalar. //
00767 
00768 // I haven't been able to figure out a nice way to templatize for the
00769 // built-in reals without introducing a lot of unwanted type matches
00770 // as well. So we'll just grind them out explicitly here.
00771 
00772 // SCALAR MULTIPLY
00773 
00774 // v = v*real, real*v 
00775 template <int N, class E, int S> inline
00776 typename Row<N,E,S>::template Result<float>::Mul
00777 operator*(const Row<N,E,S>& l, const float& r)
00778   { return Row<N,E,S>::template Result<float>::MulOp::perform(l,r); }
00779 template <int N, class E, int S> inline
00780 typename Row<N,E,S>::template Result<float>::Mul
00781 operator*(const float& l, const Row<N,E,S>& r) {return r*l;}
00782 
00783 template <int N, class E, int S> inline
00784 typename Row<N,E,S>::template Result<double>::Mul
00785 operator*(const Row<N,E,S>& l, const double& r)
00786   { return Row<N,E,S>::template Result<double>::MulOp::perform(l,r); }
00787 template <int N, class E, int S> inline
00788 typename Row<N,E,S>::template Result<double>::Mul
00789 operator*(const double& l, const Row<N,E,S>& r) {return r*l;}
00790 
00791 template <int N, class E, int S> inline
00792 typename Row<N,E,S>::template Result<long double>::Mul
00793 operator*(const Row<N,E,S>& l, const long double& r)
00794   { return Row<N,E,S>::template Result<long double>::MulOp::perform(l,r); }
00795 template <int N, class E, int S> inline
00796 typename Row<N,E,S>::template Result<long double>::Mul
00797 operator*(const long double& l, const Row<N,E,S>& r) {return r*l;}
00798 
00799 // v = v*int, int*v -- just convert int to v's precision float
00800 template <int N, class E, int S> inline
00801 typename Row<N,E,S>::template Result<typename CNT<E>::Precision>::Mul
00802 operator*(const Row<N,E,S>& l, int r) {return l * (typename CNT<E>::Precision)r;}
00803 template <int N, class E, int S> inline
00804 typename Row<N,E,S>::template Result<typename CNT<E>::Precision>::Mul
00805 operator*(int l, const Row<N,E,S>& r) {return r * (typename CNT<E>::Precision)l;}
00806 
00807 // Complex, conjugate, and negator are all easy to templatize.
00808 
00809 // v = v*complex, complex*v
00810 template <int N, class E, int S, class R> inline
00811 typename Row<N,E,S>::template Result<std::complex<R> >::Mul
00812 operator*(const Row<N,E,S>& l, const std::complex<R>& r)
00813   { return Row<N,E,S>::template Result<std::complex<R> >::MulOp::perform(l,r); }
00814 template <int N, class E, int S, class R> inline
00815 typename Row<N,E,S>::template Result<std::complex<R> >::Mul
00816 operator*(const std::complex<R>& l, const Row<N,E,S>& r) {return r*l;}
00817 
00818 // v = v*conjugate, conjugate*v (convert conjugate->complex)
00819 template <int N, class E, int S, class R> inline
00820 typename Row<N,E,S>::template Result<std::complex<R> >::Mul
00821 operator*(const Row<N,E,S>& l, const conjugate<R>& r) {return l*(std::complex<R>)r;}
00822 template <int N, class E, int S, class R> inline
00823 typename Row<N,E,S>::template Result<std::complex<R> >::Mul
00824 operator*(const conjugate<R>& l, const Row<N,E,S>& r) {return r*(std::complex<R>)l;}
00825 
00826 // v = v*negator, negator*v: convert negator to standard number
00827 template <int N, class E, int S, class R> inline
00828 typename Row<N,E,S>::template Result<typename negator<R>::StdNumber>::Mul
00829 operator*(const Row<N,E,S>& l, const negator<R>& r) {return l * (typename negator<R>::StdNumber)(R)r;}
00830 template <int N, class E, int S, class R> inline
00831 typename Row<N,E,S>::template Result<typename negator<R>::StdNumber>::Mul
00832 operator*(const negator<R>& l, const Row<N,E,S>& r) {return r * (typename negator<R>::StdNumber)(R)l;}
00833 
00834 
00835 // SCALAR DIVIDE. This is a scalar operation when the scalar is on the right,
00836 // but when it is on the left it means scalar * pseudoInverse(row), which is 
00837 // a vec.
00838 
00839 // v = v/real, real/v 
00840 template <int N, class E, int S> inline
00841 typename Row<N,E,S>::template Result<float>::Dvd
00842 operator/(const Row<N,E,S>& l, const float& r)
00843   { return Row<N,E,S>::template Result<float>::DvdOp::perform(l,r); }
00844 template <int N, class E, int S> inline
00845 typename CNT<float>::template Result<Row<N,E,S> >::Dvd
00846 operator/(const float& l, const Row<N,E,S>& r)
00847   { return CNT<float>::template Result<Row<N,E,S> >::DvdOp::perform(l,r); }
00848 
00849 template <int N, class E, int S> inline
00850 typename Row<N,E,S>::template Result<double>::Dvd
00851 operator/(const Row<N,E,S>& l, const double& r)
00852   { return Row<N,E,S>::template Result<double>::DvdOp::perform(l,r); }
00853 template <int N, class E, int S> inline
00854 typename CNT<double>::template Result<Row<N,E,S> >::Dvd
00855 operator/(const double& l, const Row<N,E,S>& r)
00856   { return CNT<double>::template Result<Row<N,E,S> >::DvdOp::perform(l,r); }
00857 
00858 template <int N, class E, int S> inline
00859 typename Row<N,E,S>::template Result<long double>::Dvd
00860 operator/(const Row<N,E,S>& l, const long double& r)
00861   { return Row<N,E,S>::template Result<long double>::DvdOp::perform(l,r); }
00862 template <int N, class E, int S> inline
00863 typename CNT<long double>::template Result<Row<N,E,S> >::Dvd
00864 operator/(const long double& l, const Row<N,E,S>& r)
00865   { return CNT<long double>::template Result<Row<N,E,S> >::DvdOp::perform(l,r); }
00866 
00867 // v = v/int, int/v -- just convert int to v's precision float
00868 template <int N, class E, int S> inline
00869 typename Row<N,E,S>::template Result<typename CNT<E>::Precision>::Dvd
00870 operator/(const Row<N,E,S>& l, int r) {return l / (typename CNT<E>::Precision)r;}
00871 template <int N, class E, int S> inline
00872 typename CNT<typename CNT<E>::Precision>::template Result<Row<N,E,S> >::Dvd
00873 operator/(int l, const Row<N,E,S>& r) {return (typename CNT<E>::Precision)l / r;}
00874 
00875 
00876 // Complex, conjugate, and negator are all easy to templatize.
00877 
00878 // v = v/complex, complex/v
00879 template <int N, class E, int S, class R> inline
00880 typename Row<N,E,S>::template Result<std::complex<R> >::Dvd
00881 operator/(const Row<N,E,S>& l, const std::complex<R>& r)
00882   { return Row<N,E,S>::template Result<std::complex<R> >::DvdOp::perform(l,r); }
00883 template <int N, class E, int S, class R> inline
00884 typename CNT<std::complex<R> >::template Result<Row<N,E,S> >::Dvd
00885 operator/(const std::complex<R>& l, const Row<N,E,S>& r)
00886   { return CNT<std::complex<R> >::template Result<Row<N,E,S> >::DvdOp::perform(l,r); }
00887 
00888 // v = v/conjugate, conjugate/v (convert conjugate->complex)
00889 template <int N, class E, int S, class R> inline
00890 typename Row<N,E,S>::template Result<std::complex<R> >::Dvd
00891 operator/(const Row<N,E,S>& l, const conjugate<R>& r) {return l/(std::complex<R>)r;}
00892 template <int N, class E, int S, class R> inline
00893 typename CNT<std::complex<R> >::template Result<Row<N,E,S> >::Dvd
00894 operator/(const conjugate<R>& l, const Row<N,E,S>& r) {return (std::complex<R>)l/r;}
00895 
00896 // v = v/negator, negator/v: convert negator to number
00897 template <int N, class E, int S, class R> inline
00898 typename Row<N,E,S>::template Result<typename negator<R>::StdNumber>::Dvd
00899 operator/(const Row<N,E,S>& l, const negator<R>& r) {return l/(typename negator<R>::StdNumber)(R)r;}
00900 template <int N, class E, int S, class R> inline
00901 typename CNT<R>::template Result<Row<N,E,S> >::Dvd
00902 operator/(const negator<R>& l, const Row<N,E,S>& r) {return (typename negator<R>::StdNumber)(R)l/r;}
00903 
00904 
00905 // Add and subtract are odd as scalar ops. They behave as though the
00906 // scalar stands for a vector each of whose elements is that scalar,
00907 // and then a normal vector add or subtract is done.
00908 
00909 // SCALAR ADD
00910 
00911 // v = v+real, real+v 
00912 template <int N, class E, int S> inline
00913 typename Row<N,E,S>::template Result<float>::Add
00914 operator+(const Row<N,E,S>& l, const float& r)
00915   { return Row<N,E,S>::template Result<float>::AddOp::perform(l,r); }
00916 template <int N, class E, int S> inline
00917 typename Row<N,E,S>::template Result<float>::Add
00918 operator+(const float& l, const Row<N,E,S>& r) {return r+l;}
00919 
00920 template <int N, class E, int S> inline
00921 typename Row<N,E,S>::template Result<double>::Add
00922 operator+(const Row<N,E,S>& l, const double& r)
00923   { return Row<N,E,S>::template Result<double>::AddOp::perform(l,r); }
00924 template <int N, class E, int S> inline
00925 typename Row<N,E,S>::template Result<double>::Add
00926 operator+(const double& l, const Row<N,E,S>& r) {return r+l;}
00927 
00928 template <int N, class E, int S> inline
00929 typename Row<N,E,S>::template Result<long double>::Add
00930 operator+(const Row<N,E,S>& l, const long double& r)
00931   { return Row<N,E,S>::template Result<long double>::AddOp::perform(l,r); }
00932 template <int N, class E, int S> inline
00933 typename Row<N,E,S>::template Result<long double>::Add
00934 operator+(const long double& l, const Row<N,E,S>& r) {return r+l;}
00935 
00936 // v = v+int, int+v -- just convert int to v's precision float
00937 template <int N, class E, int S> inline
00938 typename Row<N,E,S>::template Result<typename CNT<E>::Precision>::Add
00939 operator+(const Row<N,E,S>& l, int r) {return l + (typename CNT<E>::Precision)r;}
00940 template <int N, class E, int S> inline
00941 typename Row<N,E,S>::template Result<typename CNT<E>::Precision>::Add
00942 operator+(int l, const Row<N,E,S>& r) {return r + (typename CNT<E>::Precision)l;}
00943 
00944 // Complex, conjugate, and negator are all easy to templatize.
00945 
00946 // v = v+complex, complex+v
00947 template <int N, class E, int S, class R> inline
00948 typename Row<N,E,S>::template Result<std::complex<R> >::Add
00949 operator+(const Row<N,E,S>& l, const std::complex<R>& r)
00950   { return Row<N,E,S>::template Result<std::complex<R> >::AddOp::perform(l,r); }
00951 template <int N, class E, int S, class R> inline
00952 typename Row<N,E,S>::template Result<std::complex<R> >::Add
00953 operator+(const std::complex<R>& l, const Row<N,E,S>& r) {return r+l;}
00954 
00955 // v = v+conjugate, conjugate+v (convert conjugate->complex)
00956 template <int N, class E, int S, class R> inline
00957 typename Row<N,E,S>::template Result<std::complex<R> >::Add
00958 operator+(const Row<N,E,S>& l, const conjugate<R>& r) {return l+(std::complex<R>)r;}
00959 template <int N, class E, int S, class R> inline
00960 typename Row<N,E,S>::template Result<std::complex<R> >::Add
00961 operator+(const conjugate<R>& l, const Row<N,E,S>& r) {return r+(std::complex<R>)l;}
00962 
00963 // v = v+negator, negator+v: convert negator to standard number
00964 template <int N, class E, int S, class R> inline
00965 typename Row<N,E,S>::template Result<typename negator<R>::StdNumber>::Add
00966 operator+(const Row<N,E,S>& l, const negator<R>& r) {return l + (typename negator<R>::StdNumber)(R)r;}
00967 template <int N, class E, int S, class R> inline
00968 typename Row<N,E,S>::template Result<typename negator<R>::StdNumber>::Add
00969 operator+(const negator<R>& l, const Row<N,E,S>& r) {return r + (typename negator<R>::StdNumber)(R)l;}
00970 
00971 // SCALAR SUBTRACT -- careful, not commutative.
00972 
00973 // v = v-real, real-v 
00974 template <int N, class E, int S> inline
00975 typename Row<N,E,S>::template Result<float>::Sub
00976 operator-(const Row<N,E,S>& l, const float& r)
00977   { return Row<N,E,S>::template Result<float>::SubOp::perform(l,r); }
00978 template <int N, class E, int S> inline
00979 typename CNT<float>::template Result<Row<N,E,S> >::Sub
00980 operator-(const float& l, const Row<N,E,S>& r)
00981   { return CNT<float>::template Result<Row<N,E,S> >::SubOp::perform(l,r); }
00982 
00983 template <int N, class E, int S> inline
00984 typename Row<N,E,S>::template Result<double>::Sub
00985 operator-(const Row<N,E,S>& l, const double& r)
00986   { return Row<N,E,S>::template Result<double>::SubOp::perform(l,r); }
00987 template <int N, class E, int S> inline
00988 typename CNT<double>::template Result<Row<N,E,S> >::Sub
00989 operator-(const double& l, const Row<N,E,S>& r)
00990   { return CNT<double>::template Result<Row<N,E,S> >::SubOp::perform(l,r); }
00991 
00992 template <int N, class E, int S> inline
00993 typename Row<N,E,S>::template Result<long double>::Sub
00994 operator-(const Row<N,E,S>& l, const long double& r)
00995   { return Row<N,E,S>::template Result<long double>::SubOp::perform(l,r); }
00996 template <int N, class E, int S> inline
00997 typename CNT<long double>::template Result<Row<N,E,S> >::Sub
00998 operator-(const long double& l, const Row<N,E,S>& r)
00999   { return CNT<long double>::template Result<Row<N,E,S> >::SubOp::perform(l,r); }
01000 
01001 // v = v-int, int-v // just convert int to v's precision float
01002 template <int N, class E, int S> inline
01003 typename Row<N,E,S>::template Result<typename CNT<E>::Precision>::Sub
01004 operator-(const Row<N,E,S>& l, int r) {return l - (typename CNT<E>::Precision)r;}
01005 template <int N, class E, int S> inline
01006 typename CNT<typename CNT<E>::Precision>::template Result<Row<N,E,S> >::Sub
01007 operator-(int l, const Row<N,E,S>& r) {return (typename CNT<E>::Precision)l - r;}
01008 
01009 
01010 // Complex, conjugate, and negator are all easy to templatize.
01011 
01012 // v = v-complex, complex-v
01013 template <int N, class E, int S, class R> inline
01014 typename Row<N,E,S>::template Result<std::complex<R> >::Sub
01015 operator-(const Row<N,E,S>& l, const std::complex<R>& r)
01016   { return Row<N,E,S>::template Result<std::complex<R> >::SubOp::perform(l,r); }
01017 template <int N, class E, int S, class R> inline
01018 typename CNT<std::complex<R> >::template Result<Row<N,E,S> >::Sub
01019 operator-(const std::complex<R>& l, const Row<N,E,S>& r)
01020   { return CNT<std::complex<R> >::template Result<Row<N,E,S> >::SubOp::perform(l,r); }
01021 
01022 // v = v-conjugate, conjugate-v (convert conjugate->complex)
01023 template <int N, class E, int S, class R> inline
01024 typename Row<N,E,S>::template Result<std::complex<R> >::Sub
01025 operator-(const Row<N,E,S>& l, const conjugate<R>& r) {return l-(std::complex<R>)r;}
01026 template <int N, class E, int S, class R> inline
01027 typename CNT<std::complex<R> >::template Result<Row<N,E,S> >::Sub
01028 operator-(const conjugate<R>& l, const Row<N,E,S>& r) {return (std::complex<R>)l-r;}
01029 
01030 // v = v-negator, negator-v: convert negator to standard number
01031 template <int N, class E, int S, class R> inline
01032 typename Row<N,E,S>::template Result<typename negator<R>::StdNumber>::Sub
01033 operator-(const Row<N,E,S>& l, const negator<R>& r) {return l-(typename negator<R>::StdNumber)(R)r;}
01034 template <int N, class E, int S, class R> inline
01035 typename CNT<R>::template Result<Row<N,E,S> >::Sub
01036 operator-(const negator<R>& l, const Row<N,E,S>& r) {return (typename negator<R>::StdNumber)(R)l-r;}
01037 
01038 
01039 // Row I/O
01040 template <int N, class E, int S, class CHAR, class TRAITS> inline
01041 std::basic_ostream<CHAR,TRAITS>&
01042 operator<<(std::basic_ostream<CHAR,TRAITS>& o, const Row<N,E,S>& v) {
01043     o << "[" << v[0]; for(int i=1;i<N;++i) o<<','<<v[i]; o<<']'; return o;
01044 }
01045 
01048 template <int N, class E, int S, class CHAR, class TRAITS> inline
01049 std::basic_istream<CHAR,TRAITS>&
01050 operator>>(std::basic_istream<CHAR,TRAITS>& is, Row<N,E,S>& v) {
01051     CHAR openBracket, closeBracket;
01052     is >> openBracket; if (is.fail()) return is;
01053     if (openBracket==CHAR('('))
01054         closeBracket = CHAR(')');
01055     else if (openBracket==CHAR('['))
01056         closeBracket = CHAR(']');
01057     else {
01058         closeBracket = CHAR(0);
01059         is.unget(); if (is.fail()) return is;
01060     }
01061 
01062     for (int i=0; i < N; ++i) {
01063         is >> v[i];
01064         if (is.fail()) return is;
01065         if (i != N-1) {
01066             CHAR c; is >> c; if (is.fail()) return is;
01067             if (c != ',') is.unget();
01068             if (is.fail()) return is;
01069         }
01070     }
01071 
01072     // Get the closing bracket if there was an opening one. If we don't
01073     // see the expected character we'll set the fail bit in the istream.
01074     if (closeBracket != CHAR(0)) {
01075         CHAR closer; is >> closer; if (is.fail()) return is;
01076         if (closer != closeBracket) {
01077             is.unget(); if (is.fail()) return is;
01078             is.setstate( std::ios::failbit );
01079         }
01080     }
01081 
01082     return is;
01083 }
01084 
01085 } //namespace SimTK
01086 
01087 
01088 #endif //SimTK_SIMMATRIX_SMALLMATRIX_ROW_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines