Simbody
|
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_