TooN
operators.hh
1 //-*- c++ -*-
2 
3 // Copyright (C) 2009 Tom Drummond (twd20@cam.ac.uk),
4 // Ed Rosten (er258@cam.ac.uk)
5 
6 //All rights reserved.
7 //
8 //Redistribution and use in source and binary forms, with or without
9 //modification, are permitted provided that the following conditions
10 //are met:
11 //1. Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //2. Redistributions in binary form must reproduce the above copyright
14 // notice, this list of conditions and the following disclaimer in the
15 // documentation and/or other materials provided with the distribution.
16 //
17 //THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
18 //AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 //IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 //ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
21 //LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 //CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 //SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 //INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 //CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 //ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 //POSSIBILITY OF SUCH DAMAGE.
28 
29 namespace TooN {
30 
32 // Type and size computation for scalar operations used in this file
34 
39 template<class L, class R> struct Field
40 {
42  static const int is = IsField<L>::value & IsField<R>::value;
43 };
44 
45 namespace Internal {
46 
47  //Automatic type deduction of return types
51  template<class C> C gettype();
52 
53 
54  template<class C> struct Clean
55  {
56  typedef C type;
57  };
58 
59  template<class C> struct Clean<const C>
60  {
61  typedef C type;
62  };
63 
64  template<class C> struct Clean<const C&>
65  {
66  typedef C type;
67  };
68 
69  template<class C> struct Clean<C&>
70  {
71  typedef C type;
72  };
73 
74  template<class L, class R> struct CField
75  {
76  static const int is = TooN::Field<typename Clean<L>::type, typename Clean<R>::type>::is;
77  };
78 
79 
80  //We have to use the traits here because it is not possible to
81  //check for the existence of a valid operator *, especially
82  //in the presence of builtin operators. Therefore, the type is
83  //only deduced if both of the input types are fields.
84  template<class L, class R, int F = CField<L,R>::is> struct AddType { typedef decltype (gettype<L>()+gettype<R>()) type;};
85  template<class L, class R, int F = CField<L,R>::is> struct SubtractType { typedef decltype (gettype<L>()-gettype<R>()) type;};
86  template<class L, class R, int F = CField<L,R>::is> struct MultiplyType { typedef decltype (gettype<L>()*gettype<R>()) type;};
87  template<class L, class R, int F = CField<L,R>::is> struct DivideType { typedef decltype (gettype<L>()/gettype<R>()) type;};
88 
89  template<class L, class R> struct AddType<L, R, 0> { typedef These_Types_Do_Not_Form_A_Field<L, R> type;};
90  template<class L, class R> struct SubtractType<L, R, 0> { typedef These_Types_Do_Not_Form_A_Field<L, R> type;};
91  template<class L, class R> struct MultiplyType<L, R, 0> { typedef These_Types_Do_Not_Form_A_Field<L, R> type;};
92  template<class L, class R> struct DivideType<L, R, 0> { typedef These_Types_Do_Not_Form_A_Field<L, R> type;};
93 
94 
95  //Mini operators for passing to Pairwise, etc
96  struct Add{
97  template<class A, class B, class C> static A op(const B& b, const C& c){return b+c;}
98  template<class P1, class P2> struct Return { typedef typename AddType<P1,P2>::type Type;};
99  };
100  struct Subtract{
101  template<class A, class B, class C> static A op(const B& b, const C& c){return b-c;}
102  template<class P1, class P2> struct Return { typedef typename SubtractType<P1,P2>::type Type;};
103  };
104  struct Multiply{
105  template<class A, class B, class C> static A op(const B& b, const C& c){return b*c;}
106  template<class P1, class P2> struct Return { typedef typename MultiplyType<P1,P2>::type Type;};
107  };
108  struct Divide{
109  template<class A, class B, class C> static A op(const B& b, const C& c){return b/c;}
110  template<class P1, class P2> struct Return { typedef typename DivideType<P1,P2>::type Type;};
111  };
112 
113 };
114 
116 // Operators
118 
119 template<class Op> struct Operator{};
120 
121 
123 // Vector <op> Vector
125 
126 namespace Internal {
127  template<typename Op, // the operation
128  int S1, typename P1, typename B1, // lhs vector
129  int S2, typename P2, typename B2> // rhs vector
130  struct VPairwise;
131 
132  template <int S, typename P, typename A> // input vector
133  struct VNegate;
134 };
135 
136 template<typename Op, // the operation
137  int S1, typename P1, typename B1, // lhs vector
138  int S2, typename P2, typename B2> // rhs vector
139 struct Operator<Internal::VPairwise<Op, S1, P1, B1, S2, P2, B2> > {
140  const Vector<S1, P1, B1> & lhs;
141  const Vector<S2, P2, B2> & rhs;
142 
143  Operator(const Vector<S1, P1, B1> & lhs_in, const Vector<S2, P2, B2> & rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
144 
145  template<int S0, typename P0, typename Ba0>
146  void eval(Vector<S0, P0, Ba0>& res) const
147  {
148  for(int i=0; i < res.size(); ++i)
149  res[i] = Op::template op<P0,P1, P2>(lhs[i],rhs[i]);
150  }
151  int size() const {return lhs.size();}
152 };
153 
154 // Addition Vector + Vector
155 template<int S1, int S2, typename P1, typename P2, typename B1, typename B2>
157 operator+(const Vector<S1, P1, B1>& v1, const Vector<S2, P2, B2>& v2)
158 {
159  SizeMismatch<S1, S2>:: test(v1.size(),v2.size());
161 }
162 
163 // Subtraction Vector - Vector
164 template<int S1, int S2, typename P1, typename P2, typename B1, typename B2>
165 Vector<Internal::Sizer<S1,S2>::size, typename Internal::SubtractType<P1, P2>::type> operator-(const Vector<S1, P1, B1>& v1, const Vector<S2, P2, B2>& v2)
166 {
167  SizeMismatch<S1, S2>:: test(v1.size(),v2.size());
169 }
170 
171 // diagmult Vector, Vector
172 template <int S1, int S2, typename P1, typename P2, typename B1, typename B2>
173 Vector<Internal::Sizer<S1,S2>::size, typename Internal::MultiplyType<P1,P2>::type> diagmult(const Vector<S1,P1,B1>& v1, const Vector<S2,P2,B2>& v2)
174 {
175  SizeMismatch<S1,S2>::test(v1.size(),v2.size());
177 }
178 
179 template<int S, typename P, typename A>
180 struct Operator<Internal::VNegate<S, P, A> > {
181  const Vector<S, P, A> & input;
182  Operator( const Vector<S, P, A> & in ) : input(in) {}
183 
184  template<int S0, typename P0, typename A0>
185  void eval(Vector<S0, P0, A0> & res) const
186  {
187  res = input * -1;
188  }
189  int size() const { return input.size(); }
190 };
191 
192 // Negation -Vector
193 template <int S, typename P, typename A>
194 Vector<S, P> operator-(const Vector<S,P,A> & v){
196 }
197 
198 // Dot product Vector * Vector
199 template<int Size1, typename Precision1, typename Base1, int Size2, typename Precision2, typename Base2>
201  SizeMismatch<Size1, Size2>:: test(v1.size(),v2.size());
202  const int s=v1.size();
204  for(int i=0; i<s; i++){
205  result+=v1[i]*v2[i];
206  }
207  return result;
208 }
209 
210 template <typename P1, typename P2, typename B1, typename B2>
212  // assume the result of adding two restypes is also a restype
213  typedef typename Internal::MultiplyType<P1,P2>::type restype;
214 
215  Vector<3, restype> result;
216 
217  result[0] = v1[1]*v2[2] - v1[2]*v2[1];
218  result[1] = v1[2]*v2[0] - v1[0]*v2[2];
219  result[2] = v1[0]*v2[1] - v1[1]*v2[0];
220 
221  return result;
222 }
223 
224 
225 
226 
228 // Matrix <op> Matrix
230 
231 namespace Internal {
232  template<typename Op, // the operation
233  int R1, int C1, typename P1, typename B1, // lhs matrix
234  int R2, int C2, typename P2, typename B2> // rhs matrix
235  struct MPairwise;
236 
237  template<int R1, int C1, typename P1, typename B1, // lhs matrix
238  int R2, int C2, typename P2, typename B2> // rhs matrix
240 
241  template<int R, int C, typename P, typename A> // input matrix
242  struct MNegate;
243 };
244 
245 template<typename Op, // the operation
246  int R1, int C1, typename P1, typename B1, // lhs matrix
247  int R2, int C2, typename P2, typename B2> // rhs matrix
248 struct Operator<Internal::MPairwise<Op, R1, C1, P1, B1, R2, C2, P2, B2> > {
249  const Matrix<R1, C1, P1, B1> & lhs;
250  const Matrix<R2, C2, P2, B2> & rhs;
251 
252  Operator(const Matrix<R1, C1, P1, B1> & lhs_in, const Matrix<R2, C2, P2, B2> & rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
253 
254  template<int R0, int C0, typename P0, typename Ba0>
255  void eval(Matrix<R0, C0, P0, Ba0>& res) const
256  {
257  for(int r=0; r < res.num_rows(); ++r){
258  for(int c=0; c < res.num_cols(); ++c){
259  res(r,c) = Op::template op<P0,P1, P2>(lhs(r,c),rhs(r,c));
260  }
261  }
262  }
263  int num_rows() const {return lhs.num_rows();}
264  int num_cols() const {return lhs.num_cols();}
265 };
266 
267 // Addition Matrix + Matrix
268 template<int R1, int R2, int C1, int C2, typename P1, typename P2, typename B1, typename B2>
270 operator+(const Matrix<R1, C1, P1, B1>& m1, const Matrix<R2, C2, P2, B2>& m2)
271 {
272  SizeMismatch<R1, R2>:: test(m1.num_rows(),m2.num_rows());
273  SizeMismatch<C1, C2>:: test(m1.num_cols(),m2.num_cols());
275 }
276 
277 // Subtraction Matrix - Matrix
278 template<int R1, int R2, int C1, int C2, typename P1, typename P2, typename B1, typename B2>
279 Matrix<Internal::Sizer<R1,R2>::size, Internal::Sizer<C1,C2>::size, typename Internal::SubtractType<P1, P2>::type>
280 operator-(const Matrix<R1, C1, P1, B1>& m1, const Matrix<R2, C2, P2, B2>& m2)
281 {
282  SizeMismatch<R1, R2>:: test(m1.num_rows(),m2.num_rows());
283  SizeMismatch<C1, C2>:: test(m1.num_cols(),m2.num_cols());
285 }
286 
287 template<int R, int C, typename P, typename A>
288 struct Operator<Internal::MNegate<R,C, P, A> > {
289  const Matrix<R,C,P,A> & input;
290  Operator( const Matrix<R,C,P,A> & in ) : input(in) {}
291 
292  template<int R0, int C0, typename P0, typename A0>
293  void eval(Matrix<R0,C0,P0,A0> & res) const
294  {
295  res = input * -1;
296  }
297  int num_rows() const { return input.num_rows(); }
298  int num_cols() const { return input.num_cols(); }
299 };
300 
301 // Negation -Matrix
302 template <int R, int C, typename P, typename A>
303 Matrix<R, C, P> operator-(const Matrix<R,C,P,A> & v){
305 }
306 
307 template<int R1, int C1, typename P1, typename B1, // lhs matrix
308  int R2, int C2, typename P2, typename B2> // rhs matrix
309 struct Operator<Internal::MatrixMultiply<R1, C1, P1, B1, R2, C2, P2, B2> > {
310  const Matrix<R1, C1, P1, B1> & lhs;
311  const Matrix<R2, C2, P2, B2> & rhs;
312 
313  Operator(const Matrix<R1, C1, P1, B1> & lhs_in, const Matrix<R2, C2, P2, B2> & rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
314 
315  template<int R0, int C0, typename P0, typename Ba0>
316  void eval(Matrix<R0, C0, P0, Ba0>& res) const
317  {
318 
319  for(int r=0; r < res.num_rows(); ++r) {
320  for(int c=0; c < res.num_cols(); ++c) {
321  res(r,c) = lhs[r] * (rhs.T()[c]);
322  }
323  }
324  }
325  int num_rows() const {return lhs.num_rows();}
326  int num_cols() const {return rhs.num_cols();}
327 };
328 
329 
330 
331 
332 // Matrix multiplication Matrix * Matrix
333 
334 template<int R1, int C1, int R2, int C2, typename P1, typename P2, typename B1, typename B2>
336 {
337  SizeMismatch<C1, R2>:: test(m1.num_cols(),m2.num_rows());
339 }
340 
342 // matrix <op> vector and vv.
344 
345 
346 namespace Internal {
347  // dummy struct for Vector * Matrix
348  template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2>
350 
351  // this is distinct to cater for non commuting precision types
352  template<int Size, typename P1, typename B1, int R, int C, typename P2, typename B2>
354 
355  // dummy struct for Vector * Matrix
356  template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2>
358 
359  // this is distinct to cater for non commuting precision types
360  template<int Size, typename P1, typename B1, int R, int C, typename P2, typename B2>
362 
363 };
364 
365 // Matrix Vector multiplication Matrix * Vector
366 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2>
367 struct Operator<Internal::MatrixVectorMultiply<R,C,P1,B1,Size,P2,B2> > {
368  const Matrix<R,C,P1,B1>& lhs;
369  const Vector<Size,P2,B2>& rhs;
370 
371  Operator(const Matrix<R,C,P1,B1>& lhs_in, const Vector<Size,P2,B2>& rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
372 
373  int size() const {return lhs.num_rows();}
374 
375  template<int Sout, typename Pout, typename Bout>
376  void eval(Vector<Sout, Pout, Bout>& res) const {
377  for(int i=0; i < res.size(); ++i){
378  res[i] = lhs[i] * rhs;
379  }
380  }
381 };
382 
383 template<int R, int C, int Size, typename P1, typename P2, typename B1, typename B2>
385 {
386  SizeMismatch<C,Size>::test(m.num_cols(), v.size());
388 }
389 
390 // Vector Matrix multiplication Vector * Matrix
391 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2>
392 struct Operator<Internal::VectorMatrixMultiply<Size,P1,B1,R,C,P2,B2> > {
393  const Vector<Size,P1,B1>& lhs;
394  const Matrix<R,C,P2,B2>& rhs;
395 
396  Operator(const Vector<Size,P1,B1>& lhs_in, const Matrix<R,C,P2,B2>& rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
397 
398  int size() const {return rhs.num_cols();}
399 
400  template<int Sout, typename Pout, typename Bout>
401  void eval(Vector<Sout, Pout, Bout>& res) const {
402  for(int i=0; i < res.size(); ++i){
403  res[i] = lhs * rhs.T()[i];
404  }
405  }
406 };
407 
408 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2>
410  const Matrix<R,C,P2,B2>& m)
411 {
412  SizeMismatch<R,Size>::test(m.num_rows(), v.size());
414 }
415 
416 
417 // Matrix Vector diagonal multiplication Matrix * Vector
418 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2>
419 struct Operator<Internal::MatrixVectorDiagMultiply<R,C,P1,B1,Size,P2,B2> > {
420  const Matrix<R,C,P1,B1>& lhs;
421  const Vector<Size,P2,B2>& rhs;
422 
423  Operator(const Matrix<R,C,P1,B1>& lhs_in, const Vector<Size,P2,B2>& rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
424 
425  int num_rows() const {return lhs.num_rows();}
426  int num_cols() const {return lhs.num_cols();}
427 
428  template<int Rout, int Cout, typename Pout, typename Bout>
429  void eval(Matrix<Rout, Cout, Pout, Bout>& res) const {
430  for(int c=0; c < res.num_cols(); ++c) {
431  P2 temp = rhs[c];
432  for(int r=0; r < res.num_rows(); ++r) {
433  res(r,c) = lhs(r,c)*temp;
434  }
435  }
436  }
437 };
438 
439 template<int R, int C, int Size, typename P1, typename P2, typename B1, typename B2>
441 {
442  SizeMismatch<C,Size>::test(m.num_cols(), v.size());
444 }
445 
446 // Vector Matrix diagonal multiplication Vector * Matrix
447 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2>
448 struct Operator<Internal::VectorMatrixDiagMultiply<Size,P1,B1,R,C,P2,B2> > {
449  const Vector<Size,P1,B1>& lhs;
450  const Matrix<R,C,P2,B2>& rhs;
451 
452  Operator(const Vector<Size,P1,B1>& lhs_in, const Matrix<R,C,P2,B2>& rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
453 
454  int num_rows() const {return rhs.num_rows();}
455  int num_cols() const {return rhs.num_cols();}
456 
457  template<int Rout, int Cout, typename Pout, typename Bout>
458  void eval(Matrix<Rout, Cout, Pout, Bout>& res) const {
459  for(int r=0; r < res.num_rows(); ++r){
460  const P1 temp = lhs[r];
461  for(int c=0; c<res.num_cols(); ++c){
462  res(r,c) = temp * rhs(r,c);
463  }
464  }
465  }
466 };
467 
468 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2>
470  const Matrix<R,C,P2,B2>& m)
471 {
472  SizeMismatch<R,Size>::test(m.num_rows(), v.size());
474 }
475 
476 
478 //
479 // vector <op> scalar
480 // scalar <op> vector
481 // matrix <op> scalar
482 // scalar <op> matrix
483 //
484 // Except <scalar> / <matrix|vector> does not exist
485 
486 namespace Internal {
487  template<int Size, typename P1, typename B1, typename P2, typename Op>
488  struct ApplyScalarV;
489 
490  template<int Size, typename P1, typename B1, typename P2, typename Op>
492 
493  template<int R, int C, typename P1, typename B1, typename P2, typename Op>
494  struct ApplyScalarM;
495 
496  template<int R, int C, typename P1, typename B1, typename P2, typename Op>
498 };
499 
500 template<int Size, typename P1, typename B1, typename P2, typename Op>
501 struct Operator<Internal::ApplyScalarV<Size,P1,B1,P2,Op> > {
502  const Vector<Size,P1,B1>& lhs;
503  const P2& rhs;
504 
505  Operator(const Vector<Size,P1,B1>& v, const P2& s) : lhs(v), rhs(s) {}
506 
507  template<int S0, typename P0, typename Ba0>
508  void eval(Vector<S0,P0,Ba0>& v) const {
509  for(int i=0; i<v.size(); i++){
510  v[i]= Op::template op<P0,P1,P2> (lhs[i],rhs);
511  }
512  }
513 
514  int size() const {
515  return lhs.size();
516  }
517 };
518 
519 template <int Size, typename P1, typename B1, typename P2>
522 }
523 template <int Size, typename P1, typename B1, typename P2>
526 }
527 
528 template<int Size, typename P1, typename B1, typename P2, typename Op>
529 struct Operator<Internal::ApplyScalarVL<Size,P1,B1,P2,Op> > {
530  const P2& lhs;
531  const Vector<Size,P1,B1>& rhs;
532 
533  Operator(const P2& s, const Vector<Size,P1,B1>& v) : lhs(s), rhs(v) {}
534 
535  template<int S0, typename P0, typename Ba0>
536  void eval(Vector<S0,P0,Ba0>& v) const {
537  for(int i=0; i<v.size(); i++){
538  v[i]= Op::template op<P0,P2,P1> (lhs,rhs[i]);
539  }
540  }
541 
542  int size() const {
543  return rhs.size();
544  }
545 };
546 template <int Size, typename P1, typename B1, typename P2>
549 }
550 // no left division
551 
552 
554 
555 template<int R, int C, typename P1, typename B1, typename P2, typename Op>
556 struct Operator<Internal::ApplyScalarM<R,C,P1,B1,P2,Op> > {
557  const Matrix<R,C,P1,B1>& lhs;
558  const P2& rhs;
559 
560  Operator(const Matrix<R,C,P1,B1>& m, const P2& s) : lhs(m), rhs(s) {}
561 
562  template<int R0, int C0, typename P0, typename Ba0>
563  void eval(Matrix<R0,C0,P0,Ba0>& m) const {
564  for(int r=0; r<m.num_rows(); r++){
565  for(int c=0; c<m.num_cols(); c++){
566  m(r,c)= Op::template op<P0,P1,P2> (lhs(r,c),rhs);
567  }
568  }
569  }
570 
571  int num_rows() const {
572  return lhs.num_rows();
573  }
574  int num_cols() const {
575  return lhs.num_cols();
576  }
577 };
578 
579 template <int R, int C, typename P1, typename B1, typename P2>
582 }
583 template <int R, int C, typename P1, typename B1, typename P2>
586 }
587 
588 template<int R, int C, typename P1, typename B1, typename P2, typename Op>
589 struct Operator<Internal::ApplyScalarML<R,C,P1,B1,P2,Op> > {
590  const P2& lhs;
591  const Matrix<R,C,P1,B1>& rhs;
592 
593  Operator( const P2& s,const Matrix<R,C,P1,B1>& m) : lhs(s), rhs(m) {}
594 
595  template<int R0, int C0, typename P0, typename Ba0>
596  void eval(Matrix<R0,C0,P0,Ba0>& m) const {
597  for(int r=0; r<m.num_rows(); r++){
598  for(int c=0; c<m.num_cols(); c++){
599  m(r,c)= Op::template op<P0,P1,P2> (lhs,rhs(r,c));
600  }
601  }
602  }
603 
604  int num_rows() const {
605  return rhs.num_rows();
606  }
607  int num_cols() const {
608  return rhs.num_cols();
609  }
610 };
611 
612 template <int R, int C, typename P1, typename B1, typename P2>
615 }
616 
618 //
619 // Addition of operators
620 //
621 template <int Size, typename P1, typename B1, typename Op>
623  return op.add(v);
624 }
625 
626 template <int Size, typename P1, typename B1, typename Op>
628  return op.add(v);
629 }
630 
631 template <int Rows, int Cols, typename P1, typename B1, typename Op>
633  return op.add(m);
634 }
635 
636 template <int Rows, int Cols, typename P1, typename B1, typename Op>
638  return op.add(m);
639 }
640 
641 
642 
643 
644 template <int Size, typename P1, typename B1, typename Op>
646  return op.rsubtract(v);
647 }
648 
649 template <int Size, typename P1, typename B1, typename Op>
651  return op.lsubtract(v);
652 }
653 
654 template <int Rows, int Cols, typename P1, typename B1, typename Op>
656  return op.rsubtract(m);
657 }
658 
659 template <int Rows, int Cols, typename P1, typename B1, typename Op>
661  return op.lsubtract(m);
662 }
664 //
665 // Stream I/O operators
666 //
667 
668 // output operator <<
669 template <int Size, typename Precision, typename Base>
670 inline std::ostream& operator<< (std::ostream& os, const Vector<Size,Precision,Base>& v){
671  std::streamsize fw = os.width();
672  for(int i=0; i<v.size(); i++){
673  os.width(fw);
674  os << v[i] << " ";
675  }
676  return os;
677 }
678 
679 // operator istream& >>
680 template <int Size, typename Precision, typename Base>
681 std::istream& operator >> (std::istream& is, Vector<Size, Precision, Base>& v){
682  for (int i=0; i<v.size(); i++){
683  is >> v[i];
684  }
685  return is;
686 }
687 
688 template<int Rows, int Cols, typename Precision, class Base>
689 inline std::ostream& operator<< (std::ostream& os, const Matrix<Rows, Cols, Precision, Base>& m){
690  std::streamsize fw = os.width();
691  for(int i=0; i < m.num_rows(); i++)
692  {
693  for(int j=0; j < m.num_cols(); j++)
694  {
695  if(j != 0)
696  os << " ";
697  os.width(fw);
698  os << m(i,j);
699  }
700  os << std::endl;
701  }
702  return os;
703 }
704 
705 // operator istream& >>
706 template <int Rows, int Cols, typename Precision, typename Base>
707 std::istream& operator >> (std::istream& is, Matrix<Rows, Cols, Precision, Base>& m){
708  for(int r=0; r<m.num_rows(); r++){
709  for(int c=0; c < m.num_cols(); c++){
710  is >> m(r,c);
711  }
712  }
713  return is;
714 }
715 
716 
717 //Overloads of swap
718 namespace Internal
719 {
720  TOON_CREATE_METHOD_DETECTOR(swap);
721  template<class V1, class V2, bool has_swap = Has_swap_Method<V1>::Has>
722  struct Swap
723  {
724  static void swap(V1& v1, V2& v2)
725  {
726  using std::swap;
728  for(int i=0; i < v1.size(); i++)
729  swap(v1[i], v2[i]);
730  }
731  };
732 
733  template<class V>
734  struct Swap<V, V, true>
735  {
736  static void swap(V& v1, V& v2)
737  {
738  v1.swap(v2);
739  }
740  };
741 
742 };
743 
744 
745 template<int S1, class P1, class B1, int S2, class P2, class B2>
746 void swap(Vector<S1, P1, B1>& v1, Vector<S2, P2, B2>& v2)
747 {
749 }
750 
751 
752 template<int S1, class P1, class B1>
753 void swap(Vector<S1, P1, B1>& v1, Vector<S1, P1, B1>& v2)
754 {
756 }
757 
758 }
Definition: operators.hh:96
Definition: operators.hh:497
Definition: operators.hh:130
Definition: operators.hh:242
Definition: operators.hh:357
Definition: TooN.h:300
Pretty generic SFINAE introspection generator.
Definition: vec_test.cc:21
Is a number a field? i.e., +, -, *, / defined.
Definition: TooN.h:113
Definition: operators.hh:110
Definition: operators.hh:361
Definition: operators.hh:119
Definition: operators.hh:102
Definition: operators.hh:86
Definition: operators.hh:85
Definition: operators.hh:98
Determine if two classes are in the same field.
Definition: operators.hh:39
Definition: operators.hh:106
Definition: operators.hh:87
Definition: operators.hh:108
Definition: operators.hh:74
Definition: operators.hh:104
Definition: operators.hh:54
Definition: operators.hh:353
Definition: operators.hh:349
Definition: size_mismatch.hh:103
Definition: operators.hh:239
Definition: operators.hh:100
Definition: operators.hh:84
Definition: operators.hh:491
Definition: operators.hh:133
Definition: operators.hh:494
Definition: operators.hh:488
Definition: operators.hh:235
Definition: operators.hh:722
static const int is
<Set to 1 if the two classes are in the same field.
Definition: operators.hh:42