1 #ifndef SimTK_SIMMATRIX_SMALLMATRIX_ROW_H_
2 #define SimTK_SIMMATRIX_SMALLMATRIX_ROW_H_
3 
4 /* -------------------------------------------------------------------------- *
5  *                       Simbody(tm): SimTKcommon                             *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from           *
8  * Simbios, the NIH National Center for Physics-Based Simulation of           *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
11  *                                                                            *
12  * Portions copyright (c) 2005-12 Stanford University and the Authors.        *
13  * Authors: Michael Sherman                                                   *
14  * Contributors: Peter Eastman                                                *
15  *                                                                            *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
17  * not use this file except in compliance with the License. You may obtain a  *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
19  *                                                                            *
20  * Unless required by applicable law or agreed to in writing, software        *
21  * distributed under the License is distributed on an "AS IS" BASIS,          *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
23  * See the License for the specific language governing permissions and        *
24  * limitations under the License.                                             *
25  * -------------------------------------------------------------------------- */
26 
27 /**@file
28  * This file declares class Row<NCOLS, ELEMENT_TYPE, STRIDE>.
29  */
30 
31 #include "SimTKcommon/internal/common.h"
32 
33 
34 namespace SimTK {
35 
36 // The following functions are used internally by Row.
37 
38 namespace Impl {
39 
40 // For those wimpy compilers that don't unroll short, constant-limit loops,
41 // Peter Eastman added these recursive template implementations of
42 // elementwise add, subtract, and copy. Sherm added multiply and divide.
43 
44 template <class E1, int S1, class E2, int S2> void
conformingAdd(const Row<1,E1,S1> & r1,const Row<1,E2,S2> & r2,Row<1,typename CNT<E1>::template Result<E2>::Add> & result)45 conformingAdd(const Row<1,E1,S1>& r1, const Row<1,E2,S2>& r2,
46               Row<1,typename CNT<E1>::template Result<E2>::Add>& result) {
47     result[0] = r1[0] + r2[0];
48 }
49 template <int N, class E1, int S1, class E2, int S2> void
conformingAdd(const Row<N,E1,S1> & r1,const Row<N,E2,S2> & r2,Row<N,typename CNT<E1>::template Result<E2>::Add> & result)50 conformingAdd(const Row<N,E1,S1>& r1, const Row<N,E2,S2>& r2,
51               Row<N,typename CNT<E1>::template Result<E2>::Add>& result) {
52     conformingAdd(reinterpret_cast<const Row<N-1,E1,S1>&>(r1),
53                   reinterpret_cast<const Row<N-1,E2,S2>&>(r2),
54                   reinterpret_cast<Row<N-1,typename CNT<E1>::
55                               template Result<E2>::Add>&>(result));
56     result[N-1] = r1[N-1] + r2[N-1];
57 }
58 
59 template <class E1, int S1, class E2, int S2> void
conformingSubtract(const Row<1,E1,S1> & r1,const Row<1,E2,S2> & r2,Row<1,typename CNT<E1>::template Result<E2>::Sub> & result)60 conformingSubtract(const Row<1,E1,S1>& r1, const Row<1,E2,S2>& r2,
61                    Row<1,typename CNT<E1>::template Result<E2>::Sub>& result) {
62     result[0] = r1[0] - r2[0];
63 }
64 template <int N, class E1, int S1, class E2, int S2> void
conformingSubtract(const Row<N,E1,S1> & r1,const Row<N,E2,S2> & r2,Row<N,typename CNT<E1>::template Result<E2>::Sub> & result)65 conformingSubtract(const Row<N,E1,S1>& r1, const Row<N,E2,S2>& r2,
66                    Row<N,typename CNT<E1>::template Result<E2>::Sub>& result) {
67     conformingSubtract(reinterpret_cast<const Row<N-1,E1,S1>&>(r1),
68                        reinterpret_cast<const Row<N-1,E2,S2>&>(r2),
69                        reinterpret_cast<Row<N-1,typename CNT<E1>::
70                                    template Result<E2>::Sub>&>(result));
71     result[N-1] = r1[N-1] - r2[N-1];
72 }
73 
74 template <class E1, int S1, class E2, int S2> void
elementwiseMultiply(const Row<1,E1,S1> & r1,const Row<1,E2,S2> & r2,Row<1,typename CNT<E1>::template Result<E2>::Mul> & result)75 elementwiseMultiply(const Row<1,E1,S1>& r1, const Row<1,E2,S2>& r2,
76               Row<1,typename CNT<E1>::template Result<E2>::Mul>& result) {
77     result[0] = r1[0] * r2[0];
78 }
79 template <int N, class E1, int S1, class E2, int S2> void
elementwiseMultiply(const Row<N,E1,S1> & r1,const Row<N,E2,S2> & r2,Row<N,typename CNT<E1>::template Result<E2>::Mul> & result)80 elementwiseMultiply(const Row<N,E1,S1>& r1, const Row<N,E2,S2>& r2,
81               Row<N,typename CNT<E1>::template Result<E2>::Mul>& result) {
82     elementwiseMultiply(reinterpret_cast<const Row<N-1,E1,S1>&>(r1),
83                         reinterpret_cast<const Row<N-1,E2,S2>&>(r2),
84                         reinterpret_cast<Row<N-1,typename CNT<E1>::
85                                     template Result<E2>::Mul>&>(result));
86     result[N-1] = r1[N-1] * r2[N-1];
87 }
88 
89 template <class E1, int S1, class E2, int S2> void
elementwiseDivide(const Row<1,E1,S1> & r1,const Row<1,E2,S2> & r2,Row<1,typename CNT<E1>::template Result<E2>::Dvd> & result)90 elementwiseDivide(const Row<1,E1,S1>& r1, const Row<1,E2,S2>& r2,
91               Row<1,typename CNT<E1>::template Result<E2>::Dvd>& result) {
92     result[0] = r1[0] / r2[0];
93 }
94 template <int N, class E1, int S1, class E2, int S2> void
elementwiseDivide(const Row<N,E1,S1> & r1,const Row<N,E2,S2> & r2,Row<N,typename CNT<E1>::template Result<E2>::Dvd> & result)95 elementwiseDivide(const Row<N,E1,S1>& r1, const Row<N,E2,S2>& r2,
96               Row<N,typename CNT<E1>::template Result<E2>::Dvd>& result) {
97     elementwiseDivide(reinterpret_cast<const Row<N-1,E1,S1>&>(r1),
98                         reinterpret_cast<const Row<N-1,E2,S2>&>(r2),
99                         reinterpret_cast<Row<N-1,typename CNT<E1>::
100                                     template Result<E2>::Dvd>&>(result));
101     result[N-1] = r1[N-1] / r2[N-1];
102 }
103 
104 template <class E1, int S1, class E2, int S2> void
copy(Row<1,E1,S1> & r1,const Row<1,E2,S2> & r2)105 copy(Row<1,E1,S1>& r1, const Row<1,E2,S2>& r2) {
106     r1[0] = r2[0];
107 }
108 template <int N, class E1, int S1, class E2, int S2> void
copy(Row<N,E1,S1> & r1,const Row<N,E2,S2> & r2)109 copy(Row<N,E1,S1>& r1, const Row<N,E2,S2>& r2) {
110     copy(reinterpret_cast<Row<N-1,E1,S1>&>(r1),
111          reinterpret_cast<const Row<N-1,E2,S2>&>(r2));
112     r1[N-1] = r2[N-1];
113 }
114 
115 }
116 
117 /** @brief This is a fixed-length row vector designed for no-overhead inline
118 computation.
119 
120 @ingroup MatVecUtilities
121 
122 The %Row type is not commonly used in Simbody user programs; the column vector
123 class Vec is much more common. Typically %Row objects arise either from
124 transposing a Vec or selecting rows from a Mat.
125 
126 @tparam     N       The number of columns in the row vector.
127 @tparam     ELT     The element type. Must be a composite numerical type (CNT).
128 The default is ELT=Real.
129 @tparam     STRIDE  The spacing from one element to the next in memory, as an
130 integer number of elements of type ELT. The default is STRIDE=1.
131 **/
132 template <int N, class ELT, int STRIDE> class Row {
133     typedef ELT                                 E;
134     typedef typename CNT<E>::TNeg               ENeg;
135     typedef typename CNT<E>::TWithoutNegator    EWithoutNegator;
136     typedef typename CNT<E>::TReal              EReal;
137     typedef typename CNT<E>::TImag              EImag;
138     typedef typename CNT<E>::TComplex           EComplex;
139     typedef typename CNT<E>::THerm              EHerm;
140     typedef typename CNT<E>::TPosTrans          EPosTrans;
141     typedef typename CNT<E>::TSqHermT           ESqHermT;
142     typedef typename CNT<E>::TSqTHerm           ESqTHerm;
143 
144     typedef typename CNT<E>::TSqrt              ESqrt;
145     typedef typename CNT<E>::TAbs               EAbs;
146     typedef typename CNT<E>::TStandard          EStandard;
147     typedef typename CNT<E>::TInvert            EInvert;
148     typedef typename CNT<E>::TNormalize         ENormalize;
149 
150     typedef typename CNT<E>::Scalar             EScalar;
151     typedef typename CNT<E>::ULessScalar        EULessScalar;
152     typedef typename CNT<E>::Number             ENumber;
153     typedef typename CNT<E>::StdNumber          EStdNumber;
154     typedef typename CNT<E>::Precision          EPrecision;
155     typedef typename CNT<E>::ScalarNormSq       EScalarNormSq;
156 
157 public:
158 
159     enum {
160         NRows               = 1,
161         NCols               = N,
162         NPackedElements     = N,
163         NActualElements     = N * STRIDE,   // includes trailing gap
164         NActualScalars      = CNT<E>::NActualScalars * NActualElements,
165         RowSpacing          = NActualElements,
166         ColSpacing          = STRIDE,
167         ImagOffset          = NTraits<ENumber>::ImagOffset,
168         RealStrideFactor    = 1, // composite types don't change size when
169                                  // cast from complex to real or imaginary
170         ArgDepth            = ((int)CNT<E>::ArgDepth < (int)MAX_RESOLVED_DEPTH
171                                 ? CNT<E>::ArgDepth + 1
172                                 : MAX_RESOLVED_DEPTH),
173         IsScalar            = 0,
174         IsULessScalar       = 0,
175         IsNumber            = 0,
176         IsStdNumber         = 0,
177         IsPrecision         = 0,
178         SignInterpretation  = CNT<E>::SignInterpretation
179     };
180 
181     typedef Row<N,E,STRIDE>                 T;
182     typedef Row<N,ENeg,STRIDE>              TNeg;
183     typedef Row<N,EWithoutNegator,STRIDE>   TWithoutNegator;
184 
185     typedef Row<N,EReal,STRIDE*CNT<E>::RealStrideFactor>
186                                             TReal;
187     typedef Row<N,EImag,STRIDE*CNT<E>::RealStrideFactor>
188                                             TImag;
189     typedef Row<N,EComplex,STRIDE>          TComplex;
190     typedef Vec<N,EHerm,STRIDE>             THerm;
191     typedef Vec<N,E,STRIDE>                 TPosTrans;
192     typedef E                               TElement;
193     typedef Row                             TRow;
194     typedef E                               TCol;
195 
196     // These are the results of calculations, so are returned in new, packed
197     // memory. Be sure to refer to element types here which are also packed.
198     typedef Vec<N,ESqrt,1>                  TSqrt;      // Note stride
199     typedef Row<N,EAbs,1>                   TAbs;       // Note stride
200     typedef Row<N,EStandard,1>              TStandard;
201     typedef Vec<N,EInvert,1>                TInvert;    // packed
202     typedef Row<N,ENormalize,1>             TNormalize;
203 
204     typedef SymMat<N,ESqHermT>              TSqHermT;   // result of self outer product
205     typedef EScalarNormSq                   TSqTHerm;   // result of self dot product
206 
207     // These recurse right down to the underlying scalar type no matter how
208     // deep the elements are.
209     typedef EScalar                         Scalar;
210     typedef EULessScalar                    ULessScalar;
211     typedef ENumber                         Number;
212     typedef EStdNumber                      StdNumber;
213     typedef EPrecision                      Precision;
214     typedef EScalarNormSq                   ScalarNormSq;
215 
size()216     static int size() { return N; }
nrow()217     static int nrow() { return 1; }
ncol()218     static int ncol() { return N; }
219 
220 
221     // Scalar norm square is sum( conjugate squares of all scalars )
scalarNormSqr()222     ScalarNormSq scalarNormSqr() const {
223         ScalarNormSq sum(0);
224         for(int i=0;i<N;++i) sum += CNT<E>::scalarNormSqr(d[i*STRIDE]);
225         return sum;
226     }
227 
228     // sqrt() is elementwise square root; that is, the return value has the same
229     // dimension as this Vec but with each element replaced by whatever it thinks
230     // its square root is.
sqrt()231     TSqrt sqrt() const {
232         TSqrt rsqrt;
233         for(int i=0;i<N;++i) rsqrt[i] = CNT<E>::sqrt(d[i*STRIDE]);
234         return rsqrt;
235     }
236 
237     // abs() is elementwise absolute value; that is, the return value has the same
238     // dimension as this Row but with each element replaced by whatever it thinks
239     // its absolute value is.
abs()240     TAbs abs() const {
241         TAbs rabs;
242         for(int i=0;i<N;++i) rabs[i] = CNT<E>::abs(d[i*STRIDE]);
243         return rabs;
244     }
245 
standardize()246     TStandard standardize() const {
247         TStandard rstd;
248         for(int i=0;i<N;++i) rstd[i] = CNT<E>::standardize(d[i*STRIDE]);
249         return rstd;
250     }
251 
252     // Sum just adds up all the elements, getting rid of negators and
253     // conjugates in the process.
sum()254     EStandard sum() const {
255         E sum(0);
256         for (int i=0;i<N;++i) sum += d[i*STRIDE];
257         return CNT<E>::standardize(sum);
258     }
259 
260     // This gives the resulting rowvector type when (v[i] op P) is applied to each element of v.
261     // It is a row of length N, stride 1, and element types which are the regular
262     // composite result of E op P. Typically P is a scalar type but it doesn't have to be.
263     template <class P> struct EltResult {
264         typedef Row<N, typename CNT<E>::template Result<P>::Mul, 1> Mul;
265         typedef Row<N, typename CNT<E>::template Result<P>::Dvd, 1> Dvd;
266         typedef Row<N, typename CNT<E>::template Result<P>::Add, 1> Add;
267         typedef Row<N, typename CNT<E>::template Result<P>::Sub, 1> Sub;
268     };
269 
270     // This is the composite result for v op P where P is some kind of appropriately shaped
271     // non-scalar type.
272     template <class P> struct Result {
273         typedef MulCNTs<1,N,ArgDepth,Row,ColSpacing,RowSpacing,
274             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
275             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> MulOp;
276         typedef typename MulOp::Type Mul;
277 
278         typedef MulCNTsNonConforming<1,N,ArgDepth,Row,ColSpacing,RowSpacing,
279             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
280             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> MulOpNonConforming;
281         typedef typename MulOpNonConforming::Type MulNon;
282 
283 
284         typedef DvdCNTs<1,N,ArgDepth,Row,ColSpacing,RowSpacing,
285             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
286             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> DvdOp;
287         typedef typename DvdOp::Type Dvd;
288 
289         typedef AddCNTs<1,N,ArgDepth,Row,ColSpacing,RowSpacing,
290             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
291             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> AddOp;
292         typedef typename AddOp::Type Add;
293 
294         typedef SubCNTs<1,N,ArgDepth,Row,ColSpacing,RowSpacing,
295             CNT<P>::NRows, CNT<P>::NCols, CNT<P>::ArgDepth,
296             P, CNT<P>::ColSpacing, CNT<P>::RowSpacing> SubOp;
297         typedef typename SubOp::Type Sub;
298     };
299 
300     // Shape-preserving element substitution (always packed)
301     template <class P> struct Substitute {
302         typedef Row<N,P> Type;
303     };
304 
305     // Default construction initializes to NaN when debugging but
306     // is left uninitialized otherwise.
Row()307     Row(){
308     #ifndef NDEBUG
309         setToNaN();
310     #endif
311     }
312 
313     // It's important not to use the default copy constructor or copy
314     // assignment because the compiler doesn't understand that we may
315     // have noncontiguous storage and will try to copy the whole array.
Row(const Row & src)316     Row(const Row& src) {
317         Impl::copy(*this, src);
318     }
319     Row& operator=(const Row& src) {    // no harm if src and 'this' are the same
320         Impl::copy(*this, src);
321         return *this;
322     }
323 
324     // We want an implicit conversion from a Row of the same length
325     // and element type but with a different stride.
Row(const Row<N,E,SS> & src)326     template <int SS> Row(const Row<N,E,SS>& src) {
327         Impl::copy(*this, src);
328     }
329 
330     // We want an implicit conversion from a Row of the same length
331     // and *negated* element type, possibly with a different stride.
Row(const Row<N,ENeg,SS> & src)332     template <int SS> Row(const Row<N,ENeg,SS>& src) {
333         Impl::copy(*this, src);
334     }
335 
336     // Construct a Row from a Row of the same length, with any
337     // stride. Works as long as the element types are compatible.
Row(const Row<N,EE,SS> & vv)338     template <class EE, int SS> explicit Row(const Row<N,EE,SS>& vv) {
339         Impl::copy(*this, vv);
340     }
341 
342     // Construction using an element assigns to each element.
Row(const E & e)343     explicit Row(const E& e)
344       { for (int i=0;i<N;++i) d[i*STRIDE]=e; }
345 
346     // Construction using a negated element assigns to each element.
Row(const ENeg & ne)347     explicit Row(const ENeg& ne)
348       { for (int i=0;i<N;++i) d[i*STRIDE]=ne; }
349 
350     // Given an int, turn it into a suitable floating point number
351     // and then feed that to the above single-element constructor.
Row(int i)352     explicit Row(int i)
353       { new (this) Row(E(Precision(i))); }
354 
355     // A bevy of constructors for Rows up to length 6.
Row(const E & e0,const E & e1)356     Row(const E& e0,const E& e1)
357       { assert(N==2);(*this)[0]=e0;(*this)[1]=e1; }
Row(const E & e0,const E & e1,const E & e2)358     Row(const E& e0,const E& e1,const E& e2)
359       { assert(N==3);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2; }
Row(const E & e0,const E & e1,const E & e2,const E & e3)360     Row(const E& e0,const E& e1,const E& e2,const E& e3)
361       { assert(N==4);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;(*this)[3]=e3; }
Row(const E & e0,const E & e1,const E & e2,const E & e3,const E & e4)362     Row(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4)
363       { assert(N==5);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;
364         (*this)[3]=e3;(*this)[4]=e4; }
Row(const E & e0,const E & e1,const E & e2,const E & e3,const E & e4,const E & e5)365     Row(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,const E& e5)
366       { assert(N==6);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;
367         (*this)[3]=e3;(*this)[4]=e4;(*this)[5]=e5; }
Row(const E & e0,const E & e1,const E & e2,const E & e3,const E & e4,const E & e5,const E & e6)368     Row(const E& e0,const E& e1,const E& e2,const E& e3,const E& e4,const E& e5,const E& e6)
369       { assert(N==7);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;
370         (*this)[3]=e3;(*this)[4]=e4;(*this)[5]=e5;(*this)[6]=e6; }
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)371     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)
372       { assert(N==8);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;
373         (*this)[3]=e3;(*this)[4]=e4;(*this)[5]=e5;(*this)[6]=e6;(*this)[7]=e7; }
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)374     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)
375       { assert(N==9);(*this)[0]=e0;(*this)[1]=e1;(*this)[2]=e2;
376         (*this)[3]=e3;(*this)[4]=e4;(*this)[5]=e5;(*this)[6]=e6;(*this)[7]=e7;(*this)[8]=e8; }
377 
378     // Construction from a pointer to anything assumes we're pointing
379     // at an element list of the right length.
Row(const EE * p)380     template <class EE> explicit Row(const EE* p)
381       { assert(p); for(int i=0;i<N;++i) d[i*STRIDE]=p[i]; }
382     template <class EE> Row& operator=(const EE* p)
383       { assert(p); for(int i=0;i<N;++i) d[i*STRIDE]=p[i]; return *this; }
384 
385     // Conforming assignment ops.
386     template <class EE, int SS> Row& operator=(const Row<N,EE,SS>& vv) {
387         Impl::copy(*this, vv);
388         return *this;
389     }
390     template <class EE, int SS> Row& operator+=(const Row<N,EE,SS>& r)
391       { for(int i=0;i<N;++i) d[i*STRIDE] += r[i]; return *this; }
392     template <class EE, int SS> Row& operator+=(const Row<N,negator<EE>,SS>& r)
393       { for(int i=0;i<N;++i) d[i*STRIDE] -= -(r[i]); return *this; }
394     template <class EE, int SS> Row& operator-=(const Row<N,EE,SS>& r)
395       { for(int i=0;i<N;++i) d[i*STRIDE] -= r[i]; return *this; }
396     template <class EE, int SS> Row& operator-=(const Row<N,negator<EE>,SS>& r)
397       { for(int i=0;i<N;++i) d[i*STRIDE] += -(r[i]); return *this; }
398 
399     // Conforming binary ops with 'this' on left, producing new packed result.
400     // Cases: r=r+r, r=r-r, s=r*v r=r*m
401 
402     /** Vector addition -- use operator+ instead. **/
403     template <class EE, int SS> Row<N,typename CNT<E>::template Result<EE>::Add>
conformingAdd(const Row<N,EE,SS> & r)404     conformingAdd(const Row<N,EE,SS>& r) const {
405         Row<N,typename CNT<E>::template Result<EE>::Add> result;
406         Impl::conformingAdd(*this, r, result);
407         return result;
408     }
409 
410     /** Vector subtraction -- use operator- instead. **/
411     template <class EE, int SS> Row<N,typename CNT<E>::template Result<EE>::Sub>
conformingSubtract(const Row<N,EE,SS> & r)412     conformingSubtract(const Row<N,EE,SS>& r) const {
413         Row<N,typename CNT<E>::template Result<EE>::Sub> result;
414         Impl::conformingSubtract(*this, r, result);
415         return result;
416     }
417 
418     /** Same as dot product (s = row*col) -- use operator* or dot() instead. **/
419     template <class EE, int SS> typename CNT<E>::template Result<EE>::Mul
conformingMultiply(const Vec<N,EE,SS> & r)420     conformingMultiply(const Vec<N,EE,SS>& r) const {
421         return (*this)*r;
422     }
423 
424     /** Row times a conforming matrix, row=row*mat -- use operator* instead. **/
425     template <int MatNCol, class EE, int CS, int RS>
426     Row<MatNCol,typename CNT<E>::template Result<EE>::Mul>
conformingMultiply(const Mat<N,MatNCol,EE,CS,RS> & m)427     conformingMultiply(const Mat<N,MatNCol,EE,CS,RS>& m) const {
428         Row<MatNCol,typename CNT<E>::template Result<EE>::Mul> result;
429         for (int j=0;j<N;++j) result[j] = conformingMultiply(m(j));
430         return result;
431     }
432 
433     /** Elementwise multiply (Matlab .* operator). **/
434     template <class EE, int SS> Row<N,typename CNT<E>::template Result<EE>::Mul>
elementwiseMultiply(const Row<N,EE,SS> & r)435     elementwiseMultiply(const Row<N,EE,SS>& r) const {
436         Row<N,typename CNT<E>::template Result<EE>::Mul> result;
437         Impl::elementwiseMultiply(*this, r, result);
438         return result;
439     }
440 
441     /** Elementwise divide (Matlab ./ operator). **/
442     template <class EE, int SS> Row<N,typename CNT<E>::template Result<EE>::Dvd>
elementwiseDivide(const Row<N,EE,SS> & r)443     elementwiseDivide(const Row<N,EE,SS>& r) const {
444         Row<N,typename CNT<E>::template Result<EE>::Dvd> result;
445         Impl::elementwiseDivide(*this, r, result);
446         return result;
447     }
448 
449     const E& operator[](int i) const { assert(0 <= i && i < N); return d[i*STRIDE]; }
450     E&       operator[](int i)         { assert(0 <= i && i < N); return d[i*STRIDE]; }
operator()451     const E& operator()(int i) const { return (*this)[i]; }
operator()452     E&       operator()(int i)         { return (*this)[i]; }
453 
normSqr()454     ScalarNormSq normSqr() const { return scalarNormSqr(); }
455     typename CNT<ScalarNormSq>::TSqrt
norm()456         norm() const { return CNT<ScalarNormSq>::sqrt(scalarNormSqr()); }
457 
458     // If the elements of this Row are scalars, the result is what you get by
459     // dividing each element by the norm() calculated above. If the elements are
460     // *not* scalars, then the elements are *separately* normalized. That means
461     // you will get a different answer from Row<2,Row3>::normalize() than you
462     // would from a Row<6>::normalize() containing the same scalars.
463     //
464     // Normalize returns a row of the same dimension but in new, packed storage
465     // and with a return type that does not include negator<> even if the original
466     // Row<> does, because we can eliminate the negation here almost for free.
467     // But we can't standardize (change conjugate to complex) for free, so we'll retain
468     // conjugates if there are any.
normalize()469     TNormalize normalize() const {
470         if (CNT<E>::IsScalar) {
471             return castAwayNegatorIfAny() / (SignInterpretation*norm());
472         } else {
473             TNormalize elementwiseNormalized;
474             for (int j=0; j<N; ++j)
475                 elementwiseNormalized[j] = CNT<E>::normalize((*this)[j]);
476             return elementwiseNormalized;
477         }
478     }
479 
invert()480     TInvert invert() const {assert(false); return TInvert();} // TODO default inversion
481 
482     const Row&   operator+() const { return *this; }
483     const TNeg&  operator-() const { return negate(); }
484     TNeg&        operator-()       { return updNegate(); }
485     const THerm& operator~() const { return transpose(); }
486     THerm&       operator~()       { return updTranspose(); }
487 
negate()488     const TNeg&  negate() const { return *reinterpret_cast<const TNeg*>(this); }
updNegate()489     TNeg&        updNegate()    { return *reinterpret_cast<TNeg*>(this); }
490 
transpose()491     const THerm& transpose()    const { return *reinterpret_cast<const THerm*>(this); }
updTranspose()492     THerm&       updTranspose()       { return *reinterpret_cast<THerm*>(this); }
493 
positionalTranspose()494     const TPosTrans& positionalTranspose() const
495         { return *reinterpret_cast<const TPosTrans*>(this); }
updPositionalTranspose()496     TPosTrans&       updPositionalTranspose()
497         { return *reinterpret_cast<TPosTrans*>(this); }
498 
real()499     const TReal& real() const { return *reinterpret_cast<const TReal*>(this); }
real()500     TReal&       real()       { return *reinterpret_cast<      TReal*>(this); }
501 
502     // Had to contort these routines to get them through VC++ 7.net
imag()503     const TImag& imag()    const {
504         const int offs = ImagOffset;
505         const EImag* p = reinterpret_cast<const EImag*>(this);
506         return *reinterpret_cast<const TImag*>(p+offs);
507     }
imag()508     TImag& imag() {
509         const int offs = ImagOffset;
510         EImag* p = reinterpret_cast<EImag*>(this);
511         return *reinterpret_cast<TImag*>(p+offs);
512     }
513 
castAwayNegatorIfAny()514     const TWithoutNegator& castAwayNegatorIfAny() const {return *reinterpret_cast<const TWithoutNegator*>(this);}
updCastAwayNegatorIfAny()515     TWithoutNegator&       updCastAwayNegatorIfAny()    {return *reinterpret_cast<TWithoutNegator*>(this);}
516 
517 
518     // These are elementwise binary operators, (this op ee) by default but
519     // (ee op this) if 'FromLeft' appears in the name. The result is a packed
520     // Row<N> but the element type may change. These are mostly used to
521     // implement global operators. We call these "scalar" operators but
522     // actually the "scalar" can be a composite type.
523 
524     //TODO: consider converting 'e' to Standard Numbers as precalculation and
525     // changing return type appropriately.
526     template <class EE> Row<N, typename CNT<E>::template Result<EE>::Mul>
scalarMultiply(const EE & e)527     scalarMultiply(const EE& e) const {
528         Row<N, typename CNT<E>::template Result<EE>::Mul> result;
529         for (int j=0; j<N; ++j) result[j] = (*this)[j] * e;
530         return result;
531     }
532     template <class EE> Row<N, typename CNT<EE>::template Result<E>::Mul>
scalarMultiplyFromLeft(const EE & e)533     scalarMultiplyFromLeft(const EE& e) const {
534         Row<N, typename CNT<EE>::template Result<E>::Mul> result;
535         for (int j=0; j<N; ++j) result[j] = e * (*this)[j];
536         return result;
537     }
538 
539     // TODO: should precalculate and store 1/e, while converting to Standard
540     // Numbers. Note that return type should change appropriately.
541     template <class EE> Row<N, typename CNT<E>::template Result<EE>::Dvd>
scalarDivide(const EE & e)542     scalarDivide(const EE& e) const {
543         Row<N, typename CNT<E>::template Result<EE>::Dvd> result;
544         for (int j=0; j<N; ++j) result[j] = (*this)[j] / e;
545         return result;
546     }
547     template <class EE> Row<N, typename CNT<EE>::template Result<E>::Dvd>
scalarDivideFromLeft(const EE & e)548     scalarDivideFromLeft(const EE& e) const {
549         Row<N, typename CNT<EE>::template Result<E>::Dvd> result;
550         for (int j=0; j<N; ++j) result[j] = e / (*this)[j];
551         return result;
552     }
553 
554     template <class EE> Row<N, typename CNT<E>::template Result<EE>::Add>
scalarAdd(const EE & e)555     scalarAdd(const EE& e) const {
556         Row<N, typename CNT<E>::template Result<EE>::Add> result;
557         for (int j=0; j<N; ++j) result[j] = (*this)[j] + e;
558         return result;
559     }
560     // Add is commutative, so no 'FromLeft'.
561 
562     template <class EE> Row<N, typename CNT<E>::template Result<EE>::Sub>
scalarSubtract(const EE & e)563     scalarSubtract(const EE& e) const {
564         Row<N, typename CNT<E>::template Result<EE>::Sub> result;
565         for (int j=0; j<N; ++j) result[j] = (*this)[j] - e;
566         return result;
567     }
568     template <class EE> Row<N, typename CNT<EE>::template Result<E>::Sub>
scalarSubtractFromLeft(const EE & e)569     scalarSubtractFromLeft(const EE& e) const {
570         Row<N, typename CNT<EE>::template Result<E>::Sub> result;
571         for (int j=0; j<N; ++j) result[j] = e - (*this)[j];
572         return result;
573     }
574 
575     // Generic assignments for any element type not listed explicitly, including scalars.
576     // These are done repeatedly for each element and only work if the operation can
577     // be performed leaving the original element type.
578     template <class EE> Row& operator =(const EE& e) {return scalarEq(e);}
579     template <class EE> Row& operator+=(const EE& e) {return scalarPlusEq(e);}
580     template <class EE> Row& operator-=(const EE& e) {return scalarMinusEq(e);}
581     template <class EE> Row& operator*=(const EE& e) {return scalarTimesEq(e);}
582     template <class EE> Row& operator/=(const EE& e) {return scalarDivideEq(e);}
583 
584     // Generalized scalar assignment & computed assignment methods. These will work
585     // for any assignment-compatible element, not just scalars.
scalarEq(const EE & ee)586     template <class EE> Row& scalarEq(const EE& ee)
587       { for(int i=0;i<N;++i) d[i*STRIDE] = ee; return *this; }
scalarPlusEq(const EE & ee)588     template <class EE> Row& scalarPlusEq(const EE& ee)
589       { for(int i=0;i<N;++i) d[i*STRIDE] += ee; return *this; }
scalarMinusEq(const EE & ee)590     template <class EE> Row& scalarMinusEq(const EE& ee)
591       { for(int i=0;i<N;++i) d[i*STRIDE] -= ee; return *this; }
scalarMinusEqFromLeft(const EE & ee)592     template <class EE> Row& scalarMinusEqFromLeft(const EE& ee)
593       { for(int i=0;i<N;++i) d[i*STRIDE] = ee - d[i*STRIDE]; return *this; }
scalarTimesEq(const EE & ee)594     template <class EE> Row& scalarTimesEq(const EE& ee)
595       { for(int i=0;i<N;++i) d[i*STRIDE] *= ee; return *this; }
scalarTimesEqFromLeft(const EE & ee)596     template <class EE> Row& scalarTimesEqFromLeft(const EE& ee)
597       { for(int i=0;i<N;++i) d[i*STRIDE] = ee * d[i*STRIDE]; return *this; }
scalarDivideEq(const EE & ee)598     template <class EE> Row& scalarDivideEq(const EE& ee)
599       { for(int i=0;i<N;++i) d[i*STRIDE] /= ee; return *this; }
scalarDivideEqFromLeft(const EE & ee)600     template <class EE> Row& scalarDivideEqFromLeft(const EE& ee)
601       { for(int i=0;i<N;++i) d[i*STRIDE] = ee / d[i*STRIDE]; return *this; }
602 
603 
604     // Specialize for int to avoid warnings and ambiguities.
scalarEq(int ee)605     Row& scalarEq(int ee)       {return scalarEq(Precision(ee));}
scalarPlusEq(int ee)606     Row& scalarPlusEq(int ee)   {return scalarPlusEq(Precision(ee));}
scalarMinusEq(int ee)607     Row& scalarMinusEq(int ee)  {return scalarMinusEq(Precision(ee));}
scalarTimesEq(int ee)608     Row& scalarTimesEq(int ee)  {return scalarTimesEq(Precision(ee));}
scalarDivideEq(int ee)609     Row& scalarDivideEq(int ee) {return scalarDivideEq(Precision(ee));}
scalarMinusEqFromLeft(int ee)610     Row& scalarMinusEqFromLeft(int ee)  {return scalarMinusEqFromLeft(Precision(ee));}
scalarTimesEqFromLeft(int ee)611     Row& scalarTimesEqFromLeft(int ee)  {return scalarTimesEqFromLeft(Precision(ee));}
scalarDivideEqFromLeft(int ee)612     Row& scalarDivideEqFromLeft(int ee) {return scalarDivideEqFromLeft(Precision(ee));}
613 
614     /** Set every scalar in this %Row to NaN; this is the default initial
615     value in Debug builds, but not in Release. **/
setToNaN()616     void setToNaN() {
617         (*this) = CNT<ELT>::getNaN();
618     }
619 
620     /** Set every scalar in this %Row to zero. **/
setToZero()621     void setToZero() {
622         (*this) = ELT(0);
623     }
624 
625     /** Extract a const reference to a sub-Row with size known at compile time.
626     This must be called with an explicit template argument for the size, for
627     example, getSubRow<3>(j). This is only a recast; no copying or computation
628     is performed. The size and index are range checked in Debug builds but
629     not in Release builds. **/
630     template <int NN>
getSubRow(int j)631     const Row<NN,ELT,STRIDE>& getSubRow(int j) const {
632         assert(0 <= j && j + NN <= N);
633         return Row<NN,ELT,STRIDE>::getAs(&(*this)[j]);
634     }
635     /** Extract a writable reference to a sub-Row with size known at compile time.
636     This must be called with an explicit template argument for the size, for
637     example, updSubRow<3>(j). This is only a recast; no copying or computation
638     is performed. The size and index are range checked in Debug builds but
639     not in Release builds. **/
640     template <int NN>
updSubRow(int j)641     Row<NN,ELT,STRIDE>& updSubRow(int j) {
642         assert(0 <= j && j + NN <= N);
643         return Row<NN,ELT,STRIDE>::updAs(&(*this)[j]);
644     }
645 
646     /** Extract a subvector of type %Row from a longer one that has the same
647     element type and stride, and return a const reference to the selected
648     subsequence. **/
649     template <int NN>
getSubRow(const Row<NN,ELT,STRIDE> & r,int j)650     static const Row& getSubRow(const Row<NN,ELT,STRIDE>& r, int j) {
651         assert(0 <= j && j + N <= NN);
652         return getAs(&r[j]);
653     }
654     /** Extract a subvector of type %Row from a longer one that has the same
655     element type and stride, and return a writable reference to the selected
656     subsequence. **/
657     template <int NN>
updSubRow(Row<NN,ELT,STRIDE> & r,int j)658     static Row& updSubRow(Row<NN,ELT,STRIDE>& r, int j) {
659         assert(0 <= j && j + N <= NN);
660         return updAs(&r[j]);
661     }
662 
663     /** Return a row one smaller than this one by dropping the element
664     at the indicated position p. The result is a packed copy with the same
665     element type as this one. **/
drop1(int p)666     Row<N-1,ELT,1> drop1(int p) const {
667         assert(0 <= p && p < N);
668         Row<N-1,ELT,1> out;
669         int nxt=0;
670         for (int i=0; i<N-1; ++i, ++nxt) {
671             if (nxt==p) ++nxt;  // skip the loser
672             out[i] = (*this)[nxt];
673         }
674         return out;
675     }
676 
677     /** Return a row one larger than this one by adding an element
678     to the end. The result is a packed copy with the same element type as
679     this one. Works for any assignment compatible element. **/
append1(const EE & v)680     template <class EE> Row<N+1,ELT,1> append1(const EE& v) const {
681         Row<N+1,ELT,1> out;
682         Row<N,ELT,1>::updAs(&out[0]) = (*this);
683         out[N] = v;
684         return out;
685     }
686 
687 
688     /** Return a row one larger than this one by inserting an element
689     \e before the indicated one. The result is a packed copy with the same
690     element type as this one. Works for any assignment compatible element. The
691     index can be one greater than normally allowed in which case the element
692     is appended (but use append1() if you know you're appending). **/
insert1(int p,const EE & v)693     template <class EE> Row<N+1,ELT,1> insert1(int p, const EE& v) const {
694         assert(0 <= p && p <= N);
695         if (p==N) return append1(v);
696         Row<N+1,ELT,1> out;
697         int nxt=0;
698         for (int i=0; i<N; ++i, ++nxt) {
699             if (i==p) out[nxt++] = v;
700             out[nxt] = (*this)[i];
701         }
702         return out;
703     }
704 
705     /** Recast an ordinary C++ array E[] to a const %Row<N,E,S>; assumes
706     compatible length, stride, and packing. **/
getAs(const ELT * p)707     static const Row& getAs(const ELT* p)  {return *reinterpret_cast<const Row*>(p);}
708     /** Recast a writable ordinary C++ array E[] to a writable %Row<N,E,S>;
709     assumes compatible length, stride, and packing. **/
updAs(ELT * p)710     static Row&       updAs(ELT* p)        {return *reinterpret_cast<Row*>(p);}
711 
712     /** Return a %Row of the same length and element type as this one but
713     with all elements set to NaN. The result is packed (stride==1) regardless
714     of the stride of this %Row. **/
getNaN()715     static Row<N,ELT,1> getNaN() { return Row<N,ELT,1>(CNT<ELT>::getNaN()); }
716 
717     /** Return true if any element of this Row contains a NaN anywhere. **/
isNaN()718     bool isNaN() const {
719         for (int j=0; j<N; ++j)
720             if (CNT<ELT>::isNaN((*this)[j]))
721                 return true;
722         return false;
723     }
724 
725     /** Return true if any element of this Row contains a +Infinity
726     or -Infinity somewhere but no element contains a NaN anywhere. **/
isInf()727     bool isInf() const {
728         bool seenInf = false;
729         for (int j=0; j<N; ++j) {
730             const ELT& e = (*this)[j];
731             if (!CNT<ELT>::isFinite(e)) {
732                 if (!CNT<ELT>::isInf(e))
733                     return false; // something bad was found
734                 seenInf = true;
735             }
736         }
737         return seenInf;
738     }
739 
740     /** Return true if no element of this %Row contains an Infinity or a NaN
741     anywhere. **/
isFinite()742     bool isFinite() const {
743         for (int j=0; j<N; ++j)
744             if (!CNT<ELT>::isFinite((*this)[j]))
745                 return false;
746         return true;
747     }
748 
749     /** For approximate comparisons, the default tolerance to use for a vector is
750     the same as its elements' default tolerance. **/
getDefaultTolerance()751     static double getDefaultTolerance() {return CNT<ELT>::getDefaultTolerance();}
752 
753     /** %Test whether this row is numerically equal to some other row with
754     the same shape, using a specified tolerance. **/
755     template <class E2, int CS2>
isNumericallyEqual(const Row<N,E2,CS2> & r,double tol)756     bool isNumericallyEqual(const Row<N,E2,CS2>& r, double tol) const {
757         for (int j=0; j<N; ++j)
758             if (!CNT<ELT>::isNumericallyEqual((*this)(j), r(j), tol))
759                 return false;
760         return true;
761     }
762 
763     /** %Test whether this row vector is numerically equal to some other row with
764     the same shape, using a default tolerance which is the looser of the
765     default tolerances of the two objects being compared. **/
766     template <class E2, int CS2>
isNumericallyEqual(const Row<N,E2,CS2> & r)767     bool isNumericallyEqual(const Row<N,E2,CS2>& r) const {
768         const double tol = std::max(getDefaultTolerance(),r.getDefaultTolerance());
769         return isNumericallyEqual(r, tol);
770     }
771 
772     /** %Test whether every element of this row vector is numerically equal to
773     the given element, using either a specified tolerance or the row's
774     default tolerance (which is always the same or looser than the default
775     tolerance for one of its elements). **/
776     bool isNumericallyEqual
777        (const ELT& e,
778         double     tol = getDefaultTolerance()) const
779     {
780         for (int j=0; j<N; ++j)
781             if (!CNT<ELT>::isNumericallyEqual((*this)(j), e, tol))
782                 return false;
783         return true;
784     }
785 private:
786     ELT d[NActualElements];    // data
787 };
788 
789 /////////////////////////////////////////////
790 // Global operators involving two rows.    //
791 //   v+v, v-v, v==v, v!=v                  //
792 /////////////////////////////////////////////
793 
794 // v3 = v1 + v2 where all v's have the same length N.
795 template <int N, class E1, int S1, class E2, int S2> inline
796 typename Row<N,E1,S1>::template Result< Row<N,E2,S2> >::Add
797 operator+(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r) {
798     return Row<N,E1,S1>::template Result< Row<N,E2,S2> >
799         ::AddOp::perform(l,r);
800 }
801 
802 // v3 = v1 - v2, similar to +
803 template <int N, class E1, int S1, class E2, int S2> inline
804 typename Row<N,E1,S1>::template Result< Row<N,E2,S2> >::Sub
805 operator-(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r) {
806     return Row<N,E1,S1>::template Result< Row<N,E2,S2> >
807         ::SubOp::perform(l,r);
808 }
809 
810 /// bool = v1[i] == v2[i], for all elements i
811 template <int N, class E1, int S1, class E2, int S2> inline bool
812 operator==(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r) {
813     for (int i=0; i < N; ++i) if (l[i] != r[i]) return false;
814     return true;
815 }
816 /// bool = v1[i] != v2[i], for any element i
817 template <int N, class E1, int S1, class E2, int S2> inline bool
818 operator!=(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r) {return !(l==r);}
819 
820 /// bool = v1[i] < v2[i], for all elements i
821 template <int N, class E1, int S1, class E2, int S2> inline bool
822 operator<(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r)
823 {   for (int i=0; i < N; ++i) if (l[i] >= r[i]) return false;
824     return true; }
825 /// bool = v[i] < e, for all elements v[i] and element e
826 template <int N, class E1, int S1, class E2> inline bool
827 operator<(const Row<N,E1,S1>& v, const E2& e)
828 {   for (int i=0; i < N; ++i) if (v[i] >= e) return false;
829     return true; }
830 
831 /// bool = v1[i] > v2[i], for all elements i
832 template <int N, class E1, int S1, class E2, int S2> inline bool
833 operator>(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r)
834 {   for (int i=0; i < N; ++i) if (l[i] <= r[i]) return false;
835     return true; }
836 /// bool = v[i] > e, for all elements v[i] and element e
837 template <int N, class E1, int S1, class E2> inline bool
838 operator>(const Row<N,E1,S1>& v, const E2& e)
839 {   for (int i=0; i < N; ++i) if (v[i] <= e) return false;
840     return true; }
841 
842 /// bool = v1[i] <= v2[i], for all elements i.
843 /// This is not the same as !(v1>v2).
844 template <int N, class E1, int S1, class E2, int S2> inline bool
845 operator<=(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r)
846 {   for (int i=0; i < N; ++i) if (l[i] > r[i]) return false;
847     return true; }
848 /// bool = v[i] <= e, for all elements v[i] and element e.
849 /// This is not the same as !(v1>e).
850 template <int N, class E1, int S1, class E2> inline bool
851 operator<=(const Row<N,E1,S1>& v, const E2& e)
852 {   for (int i=0; i < N; ++i) if (v[i] > e) return false;
853     return true; }
854 
855 /// bool = v1[i] >= v2[i], for all elements i
856 /// This is not the same as !(v1<v2).
857 template <int N, class E1, int S1, class E2, int S2> inline bool
858 operator>=(const Row<N,E1,S1>& l, const Row<N,E2,S2>& r)
859 {   for (int i=0; i < N; ++i) if (l[i] < r[i]) return false;
860     return true; }
861 /// bool = v[i] >= e, for all elements v[i] and element e.
862 /// This is not the same as !(v1<e).
863 template <int N, class E1, int S1, class E2> inline bool
864 operator>=(const Row<N,E1,S1>& v, const E2& e)
865 {   for (int i=0; i < N; ++i) if (v[i] < e) return false;
866     return true; }
867 
868 ////////////////////////////////////////////////////
869 // Global operators involving a row and a scalar. //
870 ////////////////////////////////////////////////////
871 
872 // I haven't been able to figure out a nice way to templatize for the
873 // built-in reals without introducing a lot of unwanted type matches
874 // as well. So we'll just grind them out explicitly here.
875 
876 // SCALAR MULTIPLY
877 
878 // v = v*real, real*v
879 template <int N, class E, int S> inline
880 typename Row<N,E,S>::template Result<float>::Mul
881 operator*(const Row<N,E,S>& l, const float& r)
882   { return Row<N,E,S>::template Result<float>::MulOp::perform(l,r); }
883 template <int N, class E, int S> inline
884 typename Row<N,E,S>::template Result<float>::Mul
885 operator*(const float& l, const Row<N,E,S>& r) {return r*l;}
886 
887 template <int N, class E, int S> inline
888 typename Row<N,E,S>::template Result<double>::Mul
889 operator*(const Row<N,E,S>& l, const double& r)
890   { return Row<N,E,S>::template Result<double>::MulOp::perform(l,r); }
891 template <int N, class E, int S> inline
892 typename Row<N,E,S>::template Result<double>::Mul
893 operator*(const double& l, const Row<N,E,S>& r) {return r*l;}
894 
895 // v = v*int, int*v -- just convert int to v's precision float
896 template <int N, class E, int S> inline
897 typename Row<N,E,S>::template Result<typename CNT<E>::Precision>::Mul
898 operator*(const Row<N,E,S>& l, int r) {return l * (typename CNT<E>::Precision)r;}
899 template <int N, class E, int S> inline
900 typename Row<N,E,S>::template Result<typename CNT<E>::Precision>::Mul
901 operator*(int l, const Row<N,E,S>& r) {return r * (typename CNT<E>::Precision)l;}
902 
903 // Complex, conjugate, and negator are all easy to templatize.
904 
905 // v = v*complex, complex*v
906 template <int N, class E, int S, class R> inline
907 typename Row<N,E,S>::template Result<std::complex<R> >::Mul
908 operator*(const Row<N,E,S>& l, const std::complex<R>& r)
909   { return Row<N,E,S>::template Result<std::complex<R> >::MulOp::perform(l,r); }
910 template <int N, class E, int S, class R> inline
911 typename Row<N,E,S>::template Result<std::complex<R> >::Mul
912 operator*(const std::complex<R>& l, const Row<N,E,S>& r) {return r*l;}
913 
914 // v = v*conjugate, conjugate*v (convert conjugate->complex)
915 template <int N, class E, int S, class R> inline
916 typename Row<N,E,S>::template Result<std::complex<R> >::Mul
917 operator*(const Row<N,E,S>& l, const conjugate<R>& r) {return l*(std::complex<R>)r;}
918 template <int N, class E, int S, class R> inline
919 typename Row<N,E,S>::template Result<std::complex<R> >::Mul
920 operator*(const conjugate<R>& l, const Row<N,E,S>& r) {return r*(std::complex<R>)l;}
921 
922 // v = v*negator, negator*v: convert negator to standard number
923 template <int N, class E, int S, class R> inline
924 typename Row<N,E,S>::template Result<typename negator<R>::StdNumber>::Mul
925 operator*(const Row<N,E,S>& l, const negator<R>& r) {return l * (typename negator<R>::StdNumber)(R)r;}
926 template <int N, class E, int S, class R> inline
927 typename Row<N,E,S>::template Result<typename negator<R>::StdNumber>::Mul
928 operator*(const negator<R>& l, const Row<N,E,S>& r) {return r * (typename negator<R>::StdNumber)(R)l;}
929 
930 
931 // SCALAR DIVIDE. This is a scalar operation when the scalar is on the right,
932 // but when it is on the left it means scalar * pseudoInverse(row), which is
933 // a vec.
934 
935 // v = v/real, real/v
936 template <int N, class E, int S> inline
937 typename Row<N,E,S>::template Result<float>::Dvd
938 operator/(const Row<N,E,S>& l, const float& r)
939   { return Row<N,E,S>::template Result<float>::DvdOp::perform(l,r); }
940 template <int N, class E, int S> inline
941 typename CNT<float>::template Result<Row<N,E,S> >::Dvd
942 operator/(const float& l, const Row<N,E,S>& r)
943   { return CNT<float>::template Result<Row<N,E,S> >::DvdOp::perform(l,r); }
944 
945 template <int N, class E, int S> inline
946 typename Row<N,E,S>::template Result<double>::Dvd
947 operator/(const Row<N,E,S>& l, const double& r)
948   { return Row<N,E,S>::template Result<double>::DvdOp::perform(l,r); }
949 template <int N, class E, int S> inline
950 typename CNT<double>::template Result<Row<N,E,S> >::Dvd
951 operator/(const double& l, const Row<N,E,S>& r)
952   { return CNT<double>::template Result<Row<N,E,S> >::DvdOp::perform(l,r); }
953 
954 // v = v/int, int/v -- just convert int to v's precision float
955 template <int N, class E, int S> inline
956 typename Row<N,E,S>::template Result<typename CNT<E>::Precision>::Dvd
957 operator/(const Row<N,E,S>& l, int r) {return l / (typename CNT<E>::Precision)r;}
958 template <int N, class E, int S> inline
959 typename CNT<typename CNT<E>::Precision>::template Result<Row<N,E,S> >::Dvd
960 operator/(int l, const Row<N,E,S>& r) {return (typename CNT<E>::Precision)l / r;}
961 
962 
963 // Complex, conjugate, and negator are all easy to templatize.
964 
965 // v = v/complex, complex/v
966 template <int N, class E, int S, class R> inline
967 typename Row<N,E,S>::template Result<std::complex<R> >::Dvd
968 operator/(const Row<N,E,S>& l, const std::complex<R>& r)
969   { return Row<N,E,S>::template Result<std::complex<R> >::DvdOp::perform(l,r); }
970 template <int N, class E, int S, class R> inline
971 typename CNT<std::complex<R> >::template Result<Row<N,E,S> >::Dvd
972 operator/(const std::complex<R>& l, const Row<N,E,S>& r)
973   { return CNT<std::complex<R> >::template Result<Row<N,E,S> >::DvdOp::perform(l,r); }
974 
975 // v = v/conjugate, conjugate/v (convert conjugate->complex)
976 template <int N, class E, int S, class R> inline
977 typename Row<N,E,S>::template Result<std::complex<R> >::Dvd
978 operator/(const Row<N,E,S>& l, const conjugate<R>& r) {return l/(std::complex<R>)r;}
979 template <int N, class E, int S, class R> inline
980 typename CNT<std::complex<R> >::template Result<Row<N,E,S> >::Dvd
981 operator/(const conjugate<R>& l, const Row<N,E,S>& r) {return (std::complex<R>)l/r;}
982 
983 // v = v/negator, negator/v: convert negator to number
984 template <int N, class E, int S, class R> inline
985 typename Row<N,E,S>::template Result<typename negator<R>::StdNumber>::Dvd
986 operator/(const Row<N,E,S>& l, const negator<R>& r) {return l/(typename negator<R>::StdNumber)(R)r;}
987 template <int N, class E, int S, class R> inline
988 typename CNT<R>::template Result<Row<N,E,S> >::Dvd
989 operator/(const negator<R>& l, const Row<N,E,S>& r) {return (typename negator<R>::StdNumber)(R)l/r;}
990 
991 
992 // Add and subtract are odd as scalar ops. They behave as though the
993 // scalar stands for a vector each of whose elements is that scalar,
994 // and then a normal vector add or subtract is done.
995 
996 // SCALAR ADD
997 
998 // v = v+real, real+v
999 template <int N, class E, int S> inline
1000 typename Row<N,E,S>::template Result<float>::Add
1001 operator+(const Row<N,E,S>& l, const float& r)
1002   { return Row<N,E,S>::template Result<float>::AddOp::perform(l,r); }
1003 template <int N, class E, int S> inline
1004 typename Row<N,E,S>::template Result<float>::Add
1005 operator+(const float& l, const Row<N,E,S>& r) {return r+l;}
1006 
1007 template <int N, class E, int S> inline
1008 typename Row<N,E,S>::template Result<double>::Add
1009 operator+(const Row<N,E,S>& l, const double& r)
1010   { return Row<N,E,S>::template Result<double>::AddOp::perform(l,r); }
1011 template <int N, class E, int S> inline
1012 typename Row<N,E,S>::template Result<double>::Add
1013 operator+(const double& l, const Row<N,E,S>& r) {return r+l;}
1014 
1015 // v = v+int, int+v -- just convert int to v's precision float
1016 template <int N, class E, int S> inline
1017 typename Row<N,E,S>::template Result<typename CNT<E>::Precision>::Add
1018 operator+(const Row<N,E,S>& l, int r) {return l + (typename CNT<E>::Precision)r;}
1019 template <int N, class E, int S> inline
1020 typename Row<N,E,S>::template Result<typename CNT<E>::Precision>::Add
1021 operator+(int l, const Row<N,E,S>& r) {return r + (typename CNT<E>::Precision)l;}
1022 
1023 // Complex, conjugate, and negator are all easy to templatize.
1024 
1025 // v = v+complex, complex+v
1026 template <int N, class E, int S, class R> inline
1027 typename Row<N,E,S>::template Result<std::complex<R> >::Add
1028 operator+(const Row<N,E,S>& l, const std::complex<R>& r)
1029   { return Row<N,E,S>::template Result<std::complex<R> >::AddOp::perform(l,r); }
1030 template <int N, class E, int S, class R> inline
1031 typename Row<N,E,S>::template Result<std::complex<R> >::Add
1032 operator+(const std::complex<R>& l, const Row<N,E,S>& r) {return r+l;}
1033 
1034 // v = v+conjugate, conjugate+v (convert conjugate->complex)
1035 template <int N, class E, int S, class R> inline
1036 typename Row<N,E,S>::template Result<std::complex<R> >::Add
1037 operator+(const Row<N,E,S>& l, const conjugate<R>& r) {return l+(std::complex<R>)r;}
1038 template <int N, class E, int S, class R> inline
1039 typename Row<N,E,S>::template Result<std::complex<R> >::Add
1040 operator+(const conjugate<R>& l, const Row<N,E,S>& r) {return r+(std::complex<R>)l;}
1041 
1042 // v = v+negator, negator+v: convert negator to standard number
1043 template <int N, class E, int S, class R> inline
1044 typename Row<N,E,S>::template Result<typename negator<R>::StdNumber>::Add
1045 operator+(const Row<N,E,S>& l, const negator<R>& r) {return l + (typename negator<R>::StdNumber)(R)r;}
1046 template <int N, class E, int S, class R> inline
1047 typename Row<N,E,S>::template Result<typename negator<R>::StdNumber>::Add
1048 operator+(const negator<R>& l, const Row<N,E,S>& r) {return r + (typename negator<R>::StdNumber)(R)l;}
1049 
1050 // SCALAR SUBTRACT -- careful, not commutative.
1051 
1052 // v = v-real, real-v
1053 template <int N, class E, int S> inline
1054 typename Row<N,E,S>::template Result<float>::Sub
1055 operator-(const Row<N,E,S>& l, const float& r)
1056   { return Row<N,E,S>::template Result<float>::SubOp::perform(l,r); }
1057 template <int N, class E, int S> inline
1058 typename CNT<float>::template Result<Row<N,E,S> >::Sub
1059 operator-(const float& l, const Row<N,E,S>& r)
1060   { return CNT<float>::template Result<Row<N,E,S> >::SubOp::perform(l,r); }
1061 
1062 template <int N, class E, int S> inline
1063 typename Row<N,E,S>::template Result<double>::Sub
1064 operator-(const Row<N,E,S>& l, const double& r)
1065   { return Row<N,E,S>::template Result<double>::SubOp::perform(l,r); }
1066 template <int N, class E, int S> inline
1067 typename CNT<double>::template Result<Row<N,E,S> >::Sub
1068 operator-(const double& l, const Row<N,E,S>& r)
1069   { return CNT<double>::template Result<Row<N,E,S> >::SubOp::perform(l,r); }
1070 
1071 // v = v-int, int-v // just convert int to v's precision float
1072 template <int N, class E, int S> inline
1073 typename Row<N,E,S>::template Result<typename CNT<E>::Precision>::Sub
1074 operator-(const Row<N,E,S>& l, int r) {return l - (typename CNT<E>::Precision)r;}
1075 template <int N, class E, int S> inline
1076 typename CNT<typename CNT<E>::Precision>::template Result<Row<N,E,S> >::Sub
1077 operator-(int l, const Row<N,E,S>& r) {return (typename CNT<E>::Precision)l - r;}
1078 
1079 
1080 // Complex, conjugate, and negator are all easy to templatize.
1081 
1082 // v = v-complex, complex-v
1083 template <int N, class E, int S, class R> inline
1084 typename Row<N,E,S>::template Result<std::complex<R> >::Sub
1085 operator-(const Row<N,E,S>& l, const std::complex<R>& r)
1086   { return Row<N,E,S>::template Result<std::complex<R> >::SubOp::perform(l,r); }
1087 template <int N, class E, int S, class R> inline
1088 typename CNT<std::complex<R> >::template Result<Row<N,E,S> >::Sub
1089 operator-(const std::complex<R>& l, const Row<N,E,S>& r)
1090   { return CNT<std::complex<R> >::template Result<Row<N,E,S> >::SubOp::perform(l,r); }
1091 
1092 // v = v-conjugate, conjugate-v (convert conjugate->complex)
1093 template <int N, class E, int S, class R> inline
1094 typename Row<N,E,S>::template Result<std::complex<R> >::Sub
1095 operator-(const Row<N,E,S>& l, const conjugate<R>& r) {return l-(std::complex<R>)r;}
1096 template <int N, class E, int S, class R> inline
1097 typename CNT<std::complex<R> >::template Result<Row<N,E,S> >::Sub
1098 operator-(const conjugate<R>& l, const Row<N,E,S>& r) {return (std::complex<R>)l-r;}
1099 
1100 // v = v-negator, negator-v: convert negator to standard number
1101 template <int N, class E, int S, class R> inline
1102 typename Row<N,E,S>::template Result<typename negator<R>::StdNumber>::Sub
1103 operator-(const Row<N,E,S>& l, const negator<R>& r) {return l-(typename negator<R>::StdNumber)(R)r;}
1104 template <int N, class E, int S, class R> inline
1105 typename CNT<R>::template Result<Row<N,E,S> >::Sub
1106 operator-(const negator<R>& l, const Row<N,E,S>& r) {return (typename negator<R>::StdNumber)(R)l-r;}
1107 
1108 
1109 // Row I/O
1110 template <int N, class E, int S, class CHAR, class TRAITS> inline
1111 std::basic_ostream<CHAR,TRAITS>&
1112 operator<<(std::basic_ostream<CHAR,TRAITS>& o, const Row<N,E,S>& v) {
1113     o << "[" << v[0]; for(int i=1;i<N;++i) o<<','<<v[i]; o<<']'; return o;
1114 }
1115 
1116 /** Read a Row from a stream as M elements separated by white space or
1117 by commas, optionally enclosed in () or [] (but no leading "~"). **/
1118 template <int N, class E, int S, class CHAR, class TRAITS> inline
1119 std::basic_istream<CHAR,TRAITS>&
1120 operator>>(std::basic_istream<CHAR,TRAITS>& is, Row<N,E,S>& v) {
1121     CHAR openBracket, closeBracket;
1122     is >> openBracket; if (is.fail()) return is;
1123     if (openBracket==CHAR('('))
1124         closeBracket = CHAR(')');
1125     else if (openBracket==CHAR('['))
1126         closeBracket = CHAR(']');
1127     else {
1128         closeBracket = CHAR(0);
1129         is.unget(); if (is.fail()) return is;
1130     }
1131 
1132     for (int i=0; i < N; ++i) {
1133         is >> v[i];
1134         if (is.fail()) return is;
1135         if (i != N-1) {
1136             CHAR c; is >> c; if (is.fail()) return is;
1137             if (c != ',') is.unget();
1138             if (is.fail()) return is;
1139         }
1140     }
1141 
1142     // Get the closing bracket if there was an opening one. If we don't
1143     // see the expected character we'll set the fail bit in the istream.
1144     if (closeBracket != CHAR(0)) {
1145         CHAR closer; is >> closer; if (is.fail()) return is;
1146         if (closer != closeBracket) {
1147             is.unget(); if (is.fail()) return is;
1148             is.setstate( std::ios::failbit );
1149         }
1150     }
1151 
1152     return is;
1153 }
1154 
1155 } //namespace SimTK
1156 
1157 
1158 #endif //SimTK_SIMMATRIX_SMALLMATRIX_ROW_H_
1159