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