TooN 2.1
internal/operators.hh
00001 //-*- c++ -*-
00002 
00003 // Copyright (C) 2009 Tom Drummond (twd20@cam.ac.uk),
00004 // Ed Rosten (er258@cam.ac.uk)
00005 //
00006 // This file is part of the TooN Library.  This library is free
00007 // software; you can redistribute it and/or modify it under the
00008 // terms of the GNU General Public License as published by the
00009 // Free Software Foundation; either version 2, or (at your option)
00010 // any later version.
00011 
00012 // This library is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 
00017 // You should have received a copy of the GNU General Public License along
00018 // with this library; see the file COPYING.  If not, write to the Free
00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00020 // USA.
00021 
00022 // As a special exception, you may use this file as part of a free software
00023 // library without restriction.  Specifically, if other files instantiate
00024 // templates or use macros or inline functions from this file, or you compile
00025 // this file and link it with other files to produce an executable, this
00026 // file does not by itself cause the resulting executable to be covered by
00027 // the GNU General Public License.  This exception does not however
00028 // invalidate any other reasons why the executable file might be covered by
00029 // the GNU General Public License.
00030 
00031 namespace TooN {
00032 
00033 //////////////////////////////////////////////////////////////////////////////////////////////
00034 //             Type  and size computation for scalar operations used in this file
00035 //////////////////////////////////////////////////////////////////////////////////////////////
00036 
00037 ///Determine if two classes are in the same field. For the purposes of
00038 ///%TooN \c float and \c int are in the same field, since operator
00039 ///+,-,*,/ are defined for any combination of \c float and \c int. 
00040 ///Combinations of builtin types are dea;t with by IsField.
00041 template<class L, class R> struct Field
00042 {   
00043     ///<Set to 1 if the two classes are in the same field.
00044     static const int is = IsField<L>::value & IsField<R>::value;
00045 };
00046 
00047 namespace Internal {
00048 
00049     //Automatic type deduction of return types
00050     ///@internal
00051     ///This function offers to return a value of type C. This function
00052     ///is not implemented anywhere, the result is used for type deduction.
00053     template<class C> C gettype();
00054     
00055     
00056     template<class C> struct Clean
00057     {
00058         typedef C type;
00059     };
00060     
00061     template<class C> struct Clean<const C>
00062     {
00063         typedef C type;
00064     };
00065 
00066     template<class C> struct Clean<const C&>
00067     {
00068         typedef C type;
00069     };
00070 
00071     template<class C> struct Clean<C&>
00072     {
00073         typedef C type;
00074     };
00075 
00076     template<class L, class R> struct CField
00077     {
00078         static const int is = TooN::Field<typename Clean<L>::type, typename Clean<R>::type>::is;
00079     };
00080 
00081 
00082     //We have to use the traits here because it is not possible to 
00083     //check for the existence of a valid operator *, especially
00084     //in the presence of builtin operators. Therefore, the type is
00085     //only deduced if both of the input types are fields.
00086     template<class L, class R, int F = CField<L,R>::is> struct AddType      { typedef TOON_TYPEOF(gettype<L>()+gettype<R>()) type;};
00087     template<class L, class R, int F = CField<L,R>::is> struct SubtractType { typedef TOON_TYPEOF(gettype<L>()-gettype<R>()) type;};
00088     template<class L, class R, int F = CField<L,R>::is> struct MultiplyType { typedef TOON_TYPEOF(gettype<L>()*gettype<R>()) type;};
00089     template<class L, class R, int F = CField<L,R>::is> struct DivideType   { typedef TOON_TYPEOF(gettype<L>()/gettype<R>()) type;};
00090 
00091     template<class L, class R> struct AddType<L, R, 0>         { typedef These_Types_Do_Not_Form_A_Field<L, R> type;};
00092     template<class L, class R> struct SubtractType<L, R, 0>    { typedef These_Types_Do_Not_Form_A_Field<L, R> type;};
00093     template<class L, class R> struct MultiplyType<L, R, 0>    { typedef These_Types_Do_Not_Form_A_Field<L, R> type;};
00094     template<class L, class R> struct DivideType<L, R, 0>      { typedef These_Types_Do_Not_Form_A_Field<L, R> type;};
00095 
00096 
00097     //Mini operators for passing to Pairwise, etc
00098     struct Add{
00099         template<class A, class B, class C>      static A op(const B& b, const C& c){return b+c;}
00100         template<class P1, class P2> struct Return { typedef typename AddType<P1,P2>::type Type;};
00101     };
00102     struct Subtract{
00103         template<class A, class B, class C> static A op(const B& b, const C& c){return b-c;}
00104         template<class P1, class P2> struct Return { typedef typename SubtractType<P1,P2>::type Type;};
00105     };
00106     struct Multiply{
00107         template<class A, class B, class C> static A op(const B& b, const C& c){return b*c;}
00108         template<class P1, class P2> struct Return { typedef typename MultiplyType<P1,P2>::type Type;};
00109     };
00110     struct Divide{
00111         template<class A, class B, class C>   static A op(const B& b, const C& c){return b/c;}
00112         template<class P1, class P2> struct Return { typedef typename DivideType<P1,P2>::type Type;};
00113     };
00114 
00115 };
00116 
00117 //////////////////////////////////////////////////////////////////////////////////////////////
00118 //                                       Operators
00119 //////////////////////////////////////////////////////////////////////////////////////////////
00120 
00121 template<class Op> struct Operator{};
00122 
00123 
00124 //////////////////////////////////////////////////////////////////////////////////
00125 //                         Vector <op> Vector
00126 //////////////////////////////////////////////////////////////////////////////////
00127 
00128 namespace Internal {
00129     template<typename Op,                           // the operation
00130              int S1, typename P1, typename B1,      // lhs vector
00131              int S2, typename P2, typename B2>      // rhs vector
00132     struct VPairwise;
00133 
00134     template <int S, typename P, typename A>        // input vector
00135     struct VNegate;
00136 };
00137 
00138 template<typename Op,                           // the operation
00139          int S1, typename P1, typename B1,      // lhs vector
00140          int S2, typename P2, typename B2>      // rhs vector
00141 struct Operator<Internal::VPairwise<Op, S1, P1, B1, S2, P2, B2> > {
00142     const Vector<S1, P1, B1> & lhs;
00143     const Vector<S2, P2, B2> & rhs;
00144 
00145     Operator(const Vector<S1, P1, B1> & lhs_in, const Vector<S2, P2, B2> & rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
00146 
00147     template<int S0, typename P0, typename Ba0>
00148     void eval(Vector<S0, P0, Ba0>& res) const
00149     {
00150         for(int i=0; i < res.size(); ++i)
00151             res[i] = Op::template op<P0,P1, P2>(lhs[i],rhs[i]);
00152     }
00153     int size() const {return lhs.size();}
00154 };
00155 
00156 // Addition Vector + Vector
00157 template<int S1, int S2, typename P1, typename P2, typename B1, typename B2> 
00158 Vector<Internal::Sizer<S1,S2>::size, typename Internal::AddType<P1, P2>::type> 
00159 operator+(const Vector<S1, P1, B1>& v1, const Vector<S2, P2, B2>& v2)
00160 {
00161     SizeMismatch<S1, S2>:: test(v1.size(),v2.size());
00162     return Operator<Internal::VPairwise<Internal::Add,S1,P1,B1,S2,P2,B2> >(v1,v2);
00163 }
00164 
00165 // Subtraction Vector - Vector
00166 template<int S1, int S2, typename P1, typename P2, typename B1, typename B2> 
00167 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)
00168 {
00169     SizeMismatch<S1, S2>:: test(v1.size(),v2.size());
00170     return Operator<Internal::VPairwise<Internal::Subtract,S1,P1,B1,S2,P2,B2> >(v1,v2);
00171 }
00172 
00173 // diagmult Vector, Vector
00174 template <int S1, int S2, typename P1, typename P2, typename B1, typename B2>
00175 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)
00176 {
00177     SizeMismatch<S1,S2>::test(v1.size(),v2.size());
00178     return Operator<Internal::VPairwise<Internal::Multiply,S1,P1,B1,S2,P2,B2> >(v1,v2);
00179 }
00180 
00181 template<int S, typename P, typename A>
00182 struct Operator<Internal::VNegate<S, P, A> > {
00183     const Vector<S, P, A> & input;
00184     Operator( const Vector<S, P, A> & in ) : input(in) {}
00185     
00186     template<int S0, typename P0, typename A0>
00187     void eval(Vector<S0, P0, A0> & res) const
00188     {
00189         res = input * -1;
00190     }
00191     int size() const { return input.size(); }
00192 };
00193 
00194 // Negation -Vector
00195 template <int S, typename P, typename A>
00196 Vector<S, P> operator-(const Vector<S,P,A> & v){
00197     return Operator<Internal::VNegate<S,P,A> >(v);
00198 }
00199 
00200 // Dot product Vector * Vector
00201 template<int Size1, typename Precision1, typename Base1, int Size2, typename Precision2, typename Base2>
00202 typename Internal::MultiplyType<Precision1, Precision2>::type operator*(const Vector<Size1, Precision1, Base1>& v1, const Vector<Size2, Precision2, Base2>& v2){
00203   SizeMismatch<Size1, Size2>:: test(v1.size(),v2.size());
00204   const int s=v1.size();
00205   typename Internal::MultiplyType<Precision1, Precision2>::type result=0;
00206   for(int i=0; i<s; i++){
00207     result+=v1[i]*v2[i];
00208   }
00209   return result;
00210 }
00211 
00212 template <typename P1, typename P2, typename B1, typename B2>
00213 Vector<3, typename Internal::MultiplyType<P1,P2>::type> operator^(const Vector<3,P1,B1>& v1, const Vector<3,P2,B2>& v2){
00214     // assume the result of adding two restypes is also a restype
00215     typedef typename Internal::MultiplyType<P1,P2>::type restype;
00216 
00217     Vector<3, restype> result;
00218 
00219     result[0] = v1[1]*v2[2] - v1[2]*v2[1];
00220     result[1] = v1[2]*v2[0] - v1[0]*v2[2];
00221     result[2] = v1[0]*v2[1] - v1[1]*v2[0];
00222 
00223     return result;
00224 }
00225 
00226 
00227 
00228 
00229 //////////////////////////////////////////////////////////////////////////////////
00230 //                            Matrix <op> Matrix
00231 //////////////////////////////////////////////////////////////////////////////////
00232 
00233 namespace Internal {
00234     template<typename Op,                           // the operation
00235              int R1, int C1, typename P1, typename B1,      // lhs matrix
00236              int R2, int C2, typename P2, typename B2>      // rhs matrix
00237     struct MPairwise;
00238 
00239     template<int R1, int C1, typename P1, typename B1,      // lhs matrix
00240              int R2, int C2, typename P2, typename B2>      // rhs matrix
00241     struct MatrixMultiply;
00242 
00243     template<int R, int C, typename P, typename A>         // input matrix
00244     struct MNegate;
00245 };
00246 
00247 template<typename Op,                           // the operation
00248          int R1, int C1, typename P1, typename B1,      // lhs matrix
00249          int R2, int C2, typename P2, typename B2>      // rhs matrix
00250 struct Operator<Internal::MPairwise<Op, R1, C1, P1, B1, R2, C2, P2, B2> > {
00251     const Matrix<R1, C1, P1, B1> & lhs;
00252     const Matrix<R2, C2, P2, B2> & rhs;
00253 
00254     Operator(const Matrix<R1, C1, P1, B1> & lhs_in, const Matrix<R2, C2, P2, B2> & rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
00255 
00256     template<int R0, int C0, typename P0, typename Ba0>
00257     void eval(Matrix<R0, C0, P0, Ba0>& res) const
00258     {
00259         for(int r=0; r < res.num_rows(); ++r){
00260             for(int c=0; c < res.num_cols(); ++c){
00261                 res(r,c) = Op::template op<P0,P1, P2>(lhs(r,c),rhs(r,c));
00262             }
00263         }
00264     }
00265     int num_rows() const {return lhs.num_rows();}
00266     int num_cols() const {return lhs.num_cols();}
00267 };
00268 
00269 // Addition Matrix + Matrix
00270 template<int R1, int R2, int C1, int C2, typename P1, typename P2, typename B1, typename B2> 
00271 Matrix<Internal::Sizer<R1,R2>::size, Internal::Sizer<C1,C2>::size, typename Internal::AddType<P1, P2>::type> 
00272 operator+(const Matrix<R1, C1, P1, B1>& m1, const Matrix<R2, C2, P2, B2>& m2)
00273 {
00274     SizeMismatch<R1, R2>:: test(m1.num_rows(),m2.num_rows());
00275     SizeMismatch<C1, C2>:: test(m1.num_cols(),m2.num_cols());
00276     return Operator<Internal::MPairwise<Internal::Add,R1,C1,P1,B1,R2,C2,P2,B2> >(m1,m2);
00277 }
00278 
00279 // Subtraction Matrix - Matrix
00280 template<int R1, int R2, int C1, int C2, typename P1, typename P2, typename B1, typename B2> 
00281 Matrix<Internal::Sizer<R1,R2>::size, Internal::Sizer<C1,C2>::size, typename Internal::SubtractType<P1, P2>::type> 
00282 operator-(const Matrix<R1, C1, P1, B1>& m1, const Matrix<R2, C2, P2, B2>& m2)
00283 {
00284     SizeMismatch<R1, R2>:: test(m1.num_rows(),m2.num_rows());
00285     SizeMismatch<C1, C2>:: test(m1.num_cols(),m2.num_cols());
00286     return Operator<Internal::MPairwise<Internal::Subtract,R1,C1,P1,B1,R2,C2,P2,B2> >(m1,m2);
00287 }
00288 
00289 template<int R, int C, typename P, typename A>
00290 struct Operator<Internal::MNegate<R,C, P, A> > {
00291     const Matrix<R,C,P,A> & input;
00292     Operator( const Matrix<R,C,P,A> & in ) : input(in) {}
00293     
00294     template<int R0, int C0, typename P0, typename A0>
00295     void eval(Matrix<R0,C0,P0,A0> & res) const
00296     {
00297         res = input * -1;
00298     }
00299     int num_rows() const { return input.num_rows(); }
00300     int num_cols() const { return input.num_cols(); }
00301 };
00302 
00303 // Negation -Matrix
00304 template <int R, int C, typename P, typename A>
00305 Matrix<R, C, P> operator-(const Matrix<R,C,P,A> & v){
00306     return Operator<Internal::MNegate<R,C,P,A> >(v);
00307 }
00308 
00309 template<int R1, int C1, typename P1, typename B1,      // lhs matrix
00310          int R2, int C2, typename P2, typename B2>      // rhs matrix
00311 struct Operator<Internal::MatrixMultiply<R1, C1, P1, B1, R2, C2, P2, B2> > {
00312     const Matrix<R1, C1, P1, B1> & lhs;
00313     const Matrix<R2, C2, P2, B2> & rhs;
00314 
00315     Operator(const Matrix<R1, C1, P1, B1> & lhs_in, const Matrix<R2, C2, P2, B2> & rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
00316 
00317     template<int R0, int C0, typename P0, typename Ba0>
00318     void eval(Matrix<R0, C0, P0, Ba0>& res) const
00319     {
00320 
00321         for(int r=0; r < res.num_rows(); ++r) {
00322             for(int c=0; c < res.num_cols(); ++c) {
00323                 res(r,c) = lhs[r] * (rhs.T()[c]);
00324             }
00325         }
00326     }
00327     int num_rows() const {return lhs.num_rows();}
00328     int num_cols() const {return rhs.num_cols();}
00329 };
00330 
00331 
00332 
00333 
00334 // Matrix multiplication Matrix * Matrix
00335 
00336 template<int R1, int C1, int R2, int C2, typename P1, typename P2, typename B1, typename B2> 
00337 Matrix<R1, C2, typename Internal::MultiplyType<P1, P2>::type> operator*(const Matrix<R1, C1, P1, B1>& m1, const Matrix<R2, C2, P2, B2>& m2)
00338 {
00339     SizeMismatch<C1, R2>:: test(m1.num_cols(),m2.num_rows());
00340     return Operator<Internal::MatrixMultiply<R1,C1,P1,B1,R2,C2,P2,B2> >(m1,m2);
00341 }
00342 
00343 //////////////////////////////////////////////////////////////////////////////////
00344 //                 matrix <op> vector and vv.
00345 //////////////////////////////////////////////////////////////////////////////////
00346 
00347 
00348 namespace Internal {
00349     // dummy struct for Vector * Matrix
00350     template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2>
00351     struct MatrixVectorMultiply;
00352 
00353     // this is distinct to cater for non commuting precision types
00354     template<int Size, typename P1, typename B1, int R, int C, typename P2, typename B2>
00355     struct VectorMatrixMultiply;
00356 
00357     // dummy struct for Vector * Matrix
00358     template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2>
00359     struct MatrixVectorDiagMultiply;
00360 
00361     // this is distinct to cater for non commuting precision types
00362     template<int Size, typename P1, typename B1, int R, int C, typename P2, typename B2>
00363     struct VectorMatrixDiagMultiply;
00364 
00365 };
00366 
00367 // Matrix Vector multiplication Matrix * Vector
00368 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2> 
00369 struct Operator<Internal::MatrixVectorMultiply<R,C,P1,B1,Size,P2,B2> > {
00370     const Matrix<R,C,P1,B1>& lhs;
00371     const Vector<Size,P2,B2>& rhs;
00372 
00373     Operator(const Matrix<R,C,P1,B1>& lhs_in, const Vector<Size,P2,B2>& rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
00374 
00375     int size() const {return lhs.num_rows();}
00376 
00377     template<int Sout, typename Pout, typename Bout>
00378     void eval(Vector<Sout, Pout, Bout>& res) const {
00379         for(int i=0; i < res.size(); ++i){
00380             res[i] = lhs[i] * rhs;
00381         }
00382     }
00383 };
00384 
00385 template<int R, int C, int Size, typename P1, typename P2, typename B1, typename B2>
00386 Vector<R, typename Internal::MultiplyType<P1,P2>::type> operator*(const Matrix<R, C, P1, B1>& m, const Vector<Size, P2, B2>& v)
00387 {
00388     SizeMismatch<C,Size>::test(m.num_cols(), v.size());
00389     return Operator<Internal::MatrixVectorMultiply<R,C,P1,B1,Size,P2,B2> >(m,v);
00390 }
00391                                                                     
00392 // Vector Matrix multiplication Vector * Matrix
00393 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2> 
00394 struct Operator<Internal::VectorMatrixMultiply<Size,P1,B1,R,C,P2,B2> > {
00395     const Vector<Size,P1,B1>& lhs;
00396     const Matrix<R,C,P2,B2>& rhs;
00397 
00398     Operator(const Vector<Size,P1,B1>& lhs_in, const Matrix<R,C,P2,B2>& rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
00399 
00400     int size() const {return rhs.num_cols();}
00401 
00402     template<int Sout, typename Pout, typename Bout>
00403     void eval(Vector<Sout, Pout, Bout>& res) const {
00404         for(int i=0; i < res.size(); ++i){
00405             res[i] = lhs * rhs.T()[i];
00406         }
00407     }
00408 };
00409 
00410 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2> 
00411 Vector<C, typename Internal::MultiplyType<P1,P2>::type> operator*(const Vector<Size,P1,B1>& v,
00412                                                                   const Matrix<R,C,P2,B2>& m)
00413 {
00414     SizeMismatch<R,Size>::test(m.num_rows(), v.size());
00415     return Operator<Internal::VectorMatrixMultiply<Size,P1,B1,R,C,P2,B2> >(v,m);
00416 }
00417 
00418 
00419 // Matrix Vector diagonal multiplication Matrix * Vector
00420 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2> 
00421 struct Operator<Internal::MatrixVectorDiagMultiply<R,C,P1,B1,Size,P2,B2> > {
00422     const Matrix<R,C,P1,B1>& lhs;
00423     const Vector<Size,P2,B2>& rhs;
00424 
00425     Operator(const Matrix<R,C,P1,B1>& lhs_in, const Vector<Size,P2,B2>& rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
00426 
00427     int num_rows() const {return lhs.num_rows();}
00428     int num_cols() const {return lhs.num_cols();}
00429 
00430     template<int Rout, int Cout, typename Pout, typename Bout>
00431     void eval(Matrix<Rout, Cout, Pout, Bout>& res) const {
00432         for(int c=0; c < res.num_cols(); ++c) {
00433             P2 temp = rhs[c];
00434             for(int r=0; r < res.num_rows(); ++r) {
00435                 res(r,c) = lhs(r,c)*temp;
00436             }
00437         }
00438     }
00439 };
00440 
00441 template<int R, int C, int Size, typename P1, typename P2, typename B1, typename B2>
00442 Matrix<R, C, typename Internal::MultiplyType<P1,P2>::type> diagmult(const Matrix<R, C, P1, B1>& m, const Vector<Size, P2, B2>& v)
00443 {
00444     SizeMismatch<C,Size>::test(m.num_cols(), v.size());
00445     return Operator<Internal::MatrixVectorDiagMultiply<R,C,P1,B1,Size,P2,B2> >(m,v);
00446 }
00447                                                                     
00448 // Vector Matrix diagonal multiplication Vector * Matrix
00449 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2> 
00450 struct Operator<Internal::VectorMatrixDiagMultiply<Size,P1,B1,R,C,P2,B2> > {
00451     const Vector<Size,P1,B1>& lhs;
00452     const Matrix<R,C,P2,B2>& rhs;
00453 
00454     Operator(const Vector<Size,P1,B1>& lhs_in, const Matrix<R,C,P2,B2>& rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
00455 
00456     int num_rows() const {return rhs.num_rows();}
00457     int num_cols() const {return rhs.num_cols();}
00458 
00459     template<int Rout, int Cout, typename Pout, typename Bout>
00460     void eval(Matrix<Rout, Cout, Pout, Bout>& res) const {
00461         for(int r=0; r < res.num_rows(); ++r){
00462             const P1 temp = lhs[r];
00463             for(int c=0; c<res.num_cols(); ++c){
00464                 res(r,c) = temp * rhs(r,c);
00465             }
00466         }
00467     }
00468 };
00469 
00470 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2> 
00471 Matrix<R, C, typename Internal::MultiplyType<P1,P2>::type> diagmult(const Vector<Size,P1,B1>& v,
00472                                                                  const Matrix<R,C,P2,B2>& m)
00473 {
00474     SizeMismatch<R,Size>::test(m.num_rows(), v.size());
00475     return Operator<Internal::VectorMatrixDiagMultiply<Size,P1,B1,R,C,P2,B2> >(v,m);
00476 }
00477 
00478 
00479 ////////////////////////////////////////////////////////////////////////////////
00480 //
00481 // vector <op> scalar 
00482 // scalar <op> vector 
00483 // matrix <op> scalar 
00484 // scalar <op> matrix 
00485 //
00486 // Except <scalar> / <matrix|vector> does not exist
00487 
00488 namespace Internal {
00489     template<int Size, typename P1, typename B1, typename P2, typename Op>
00490     struct ApplyScalarV;
00491 
00492     template<int Size, typename P1, typename B1, typename P2, typename Op>
00493     struct ApplyScalarVL;
00494 
00495     template<int R, int C, typename P1, typename B1, typename P2, typename Op>
00496     struct ApplyScalarM;
00497 
00498     template<int R, int C, typename P1, typename B1, typename P2, typename Op>
00499     struct ApplyScalarML;
00500 };
00501 
00502 template<int Size, typename P1, typename B1, typename P2, typename Op>
00503 struct Operator<Internal::ApplyScalarV<Size,P1,B1,P2,Op> > {
00504     const Vector<Size,P1,B1>& lhs;
00505     const P2& rhs;
00506 
00507     Operator(const Vector<Size,P1,B1>& v, const P2& s) : lhs(v), rhs(s) {}
00508         
00509     template<int S0, typename P0, typename Ba0>
00510     void eval(Vector<S0,P0,Ba0>& v) const {
00511         for(int i=0; i<v.size(); i++){
00512             v[i]= Op::template op<P0,P1,P2> (lhs[i],rhs);
00513         }
00514     }
00515 
00516     int size() const {
00517         return lhs.size();
00518     }
00519 };
00520 
00521 template <int Size, typename P1, typename B1, typename P2>
00522 Vector<Size, typename Internal::Multiply::Return<P1,P2>::Type> operator*(const Vector<Size, P1, B1>& v, const P2& s){
00523     return Operator<Internal::ApplyScalarV<Size,P1,B1,P2,Internal::Multiply> > (v,s);
00524 }
00525 template <int Size, typename P1, typename B1, typename P2>
00526 Vector<Size, typename Internal::Divide::Return<P1,P2>::Type> operator/(const Vector<Size, P1, B1>& v, const P2& s){
00527     return Operator<Internal::ApplyScalarV<Size,P1,B1,P2,Internal::Divide> > (v,s);
00528 }
00529 
00530 template<int Size, typename P1, typename B1, typename P2, typename Op>
00531 struct Operator<Internal::ApplyScalarVL<Size,P1,B1,P2,Op> > {
00532     const P2& lhs;
00533     const Vector<Size,P1,B1>& rhs;
00534 
00535     Operator(const P2& s, const Vector<Size,P1,B1>& v) : lhs(s), rhs(v) {}
00536         
00537     template<int S0, typename P0, typename Ba0>
00538     void eval(Vector<S0,P0,Ba0>& v) const {
00539         for(int i=0; i<v.size(); i++){
00540             v[i]= Op::template op<P0,P2,P1> (lhs,rhs[i]);
00541         }
00542     }
00543 
00544     int size() const {
00545         return rhs.size();
00546     }
00547 };
00548 template <int Size, typename P1, typename B1, typename P2>
00549 Vector<Size, typename Internal::Multiply::Return<P2,P1>::Type> operator*(const P2& s, const Vector<Size, P1, B1>& v){
00550     return Operator<Internal::ApplyScalarVL<Size,P1,B1,P2,Internal::Multiply> > (s,v);
00551 }
00552 // no left division
00553 
00554 
00555 ///////  Matrix scalar operators
00556 
00557 template<int R, int C, typename P1, typename B1, typename P2, typename Op>
00558 struct Operator<Internal::ApplyScalarM<R,C,P1,B1,P2,Op> > {
00559     const Matrix<R,C,P1,B1>& lhs;
00560     const P2& rhs;
00561 
00562     Operator(const Matrix<R,C,P1,B1>& m, const P2& s) : lhs(m), rhs(s) {}
00563         
00564     template<int R0, int C0, typename P0, typename Ba0>
00565     void eval(Matrix<R0,C0,P0,Ba0>& m) const {
00566         for(int r=0; r<m.num_rows(); r++){
00567             for(int c=0; c<m.num_cols(); c++){
00568                 m(r,c)= Op::template op<P0,P1,P2> (lhs(r,c),rhs);
00569             }
00570         }
00571     }
00572 
00573     int num_rows() const {
00574         return lhs.num_rows();
00575     }
00576     int num_cols() const {
00577         return lhs.num_cols();
00578     }
00579 };
00580 
00581 template <int R, int C, typename P1, typename B1, typename P2>
00582 Matrix<R,C, typename Internal::Multiply::Return<P1,P2>::Type> operator*(const Matrix<R,C, P1, B1>& m, const P2& s){
00583     return Operator<Internal::ApplyScalarM<R,C,P1,B1,P2,Internal::Multiply> > (m,s);
00584 }
00585 template <int R, int C, typename P1, typename B1, typename P2>
00586 Matrix<R,C, typename Internal::Divide::Return<P1,P2>::Type> operator/(const Matrix<R,C, P1, B1>& m, const P2& s){
00587     return Operator<Internal::ApplyScalarM<R,C,P1,B1,P2,Internal::Divide> > (m,s);
00588 }
00589 
00590 template<int R, int C, typename P1, typename B1, typename P2, typename Op>
00591 struct Operator<Internal::ApplyScalarML<R,C,P1,B1,P2,Op> > {
00592     const P2& lhs;
00593     const Matrix<R,C,P1,B1>& rhs;
00594 
00595     Operator( const P2& s,const Matrix<R,C,P1,B1>& m) : lhs(s), rhs(m) {}
00596         
00597     template<int R0, int C0, typename P0, typename Ba0>
00598     void eval(Matrix<R0,C0,P0,Ba0>& m) const {
00599         for(int r=0; r<m.num_rows(); r++){
00600             for(int c=0; c<m.num_cols(); c++){
00601                 m(r,c)= Op::template op<P0,P1,P2> (lhs,rhs(r,c));
00602             }
00603         }
00604     }
00605 
00606     int num_rows() const {
00607         return rhs.num_rows();
00608     }
00609     int num_cols() const {
00610         return rhs.num_cols();
00611     }
00612 };
00613 
00614 template <int R, int C, typename P1, typename B1, typename P2>
00615 Matrix<R,C, typename Internal::Multiply::Return<P2,P1>::Type> operator*(const P2& s, const Matrix<R,C, P1, B1>& m){
00616     return Operator<Internal::ApplyScalarML<R,C,P1,B1,P2,Internal::Multiply> > (s,m);
00617 }
00618 
00619 ////////////////////////////////////////////////////////////////////////////////
00620 //
00621 // Addition of operators
00622 //
00623 template <int Size, typename P1, typename B1, typename Op>
00624 Vector<Size, typename Internal::Add::Return<P1,typename Operator<Op>::Precision>::Type> operator+(const Vector<Size, P1, B1>& v, const Operator<Op>& op){
00625     return op.add(v);
00626 }
00627 
00628 template <int Size, typename P1, typename B1, typename Op>
00629 Vector<Size, typename Internal::Add::Return<typename Operator<Op>::Precision, P1>::Type> operator+(const Operator<Op>& op, const Vector<Size, P1, B1>& v){
00630     return op.add(v);
00631 }
00632 
00633 template <int Rows, int Cols, typename P1, typename B1, typename Op>
00634 Matrix<Rows, Cols, typename Internal::Add::Return<P1,typename Operator<Op>::Precision>::Type> operator+(const Matrix<Rows, Cols, P1, B1>& m, const Operator<Op>& op){
00635     return op.add(m);
00636 }
00637 
00638 template <int Rows, int Cols, typename P1, typename B1, typename Op>
00639 Matrix<Rows, Cols, typename Internal::Add::Return<typename Operator<Op>::Precision,P1>::Type> operator+(const Operator<Op>& op, const Matrix<Rows, Cols, P1, B1>& m){
00640     return op.add(m);
00641 }
00642 
00643 
00644 
00645 
00646 template <int Size, typename P1, typename B1, typename Op>
00647 Vector<Size, typename Internal::Subtract::Return<P1,typename Operator<Op>::Precision>::Type> operator-(const Vector<Size, P1, B1>& v, const Operator<Op>& op){
00648     return op.rsubtract(v);
00649 }
00650 
00651 template <int Size, typename P1, typename B1, typename Op>
00652 Vector<Size, typename Internal::Subtract::Return<typename Operator<Op>::Precision, P1>::Type> operator-(const Operator<Op>& op, const Vector<Size, P1, B1>& v){
00653     return op.lsubtract(v);
00654 }
00655 
00656 template <int Rows, int Cols, typename P1, typename B1, typename Op>
00657 Matrix<Rows, Cols, typename Internal::Subtract::Return<P1,typename Operator<Op>::Precision>::Type> operator-(const Matrix<Rows, Cols, P1, B1>& m, const Operator<Op>& op){
00658     return op.rsubtract(m);
00659 }
00660 
00661 template <int Rows, int Cols, typename P1, typename B1, typename Op>
00662 Matrix<Rows, Cols, typename Internal::Subtract::Return<typename Operator<Op>::Precision,P1>::Type> operator-(const Operator<Op>& op, const Matrix<Rows, Cols, P1, B1>& m){
00663     return op.lsubtract(m);
00664 }
00665 ////////////////////////////////////////////////////////////////////////////////
00666 //
00667 // Stream I/O operators
00668 //
00669 
00670 // output operator <<
00671 template <int Size, typename Precision, typename Base>
00672 inline std::ostream& operator<< (std::ostream& os, const Vector<Size,Precision,Base>& v){
00673   std::streamsize fw = os.width();
00674   for(int i=0; i<v.size(); i++){
00675     os.width(fw);
00676     os << v[i] << " ";
00677   }
00678   return os;
00679 }
00680 
00681 // operator istream& >>
00682 template <int Size, typename Precision, typename Base>
00683 std::istream& operator >> (std::istream& is, Vector<Size, Precision, Base>& v){
00684     for (int i=0; i<v.size(); i++){
00685         is >>  v[i];
00686     }
00687     return is;
00688 }
00689 
00690 template<int Rows, int Cols, typename Precision, class Base>
00691 inline std::ostream& operator<< (std::ostream& os, const Matrix<Rows, Cols, Precision, Base>& m){
00692     std::streamsize fw = os.width();
00693     for(int i=0; i < m.num_rows(); i++)
00694     {
00695         for(int j=0; j < m.num_cols(); j++)
00696         {
00697             if(j != 0)
00698                 os << " ";
00699             os.width(fw);
00700             os << m(i,j);
00701         }
00702         os << std::endl;
00703     }
00704     return os;
00705 }
00706 
00707 // operator istream& >>
00708 template <int Rows, int Cols, typename Precision, typename Base>
00709 std::istream& operator >> (std::istream& is, Matrix<Rows, Cols, Precision, Base>& m){
00710     for(int r=0; r<m.num_rows(); r++){
00711         for(int c=0; c < m.num_cols(); c++){
00712             is >> m(r,c);
00713         }
00714     }
00715     return is;
00716 }
00717 
00718 
00719 //Overloads of swap
00720 namespace Internal
00721 {
00722     TOON_CREATE_METHOD_DETECTOR(swap);
00723     template<class V1, class V2, bool has_swap = Has_swap_Method<V1>::Has>
00724     struct Swap
00725     {
00726         static void swap(V1& v1, V2& v2)
00727         {
00728             using std::swap;
00729             SizeMismatch<V1::SizeParameter,V2::SizeParameter>::test(v1.size(), v2.size());
00730             for(int i=0; i < v1.size(); i++)
00731                 swap(v1[i], v2[i]);
00732         }
00733     };
00734     
00735     template<class V>
00736     struct Swap<V, V, true>
00737     {
00738         static void swap(V& v1, V& v2)
00739         {
00740             v1.swap(v2);
00741         }
00742     };
00743 
00744 };
00745 
00746 
00747 template<int S1, class P1, class B1, int S2, class P2, class B2>
00748 void swap(Vector<S1, P1, B1>& v1, Vector<S2, P2, B2>& v2)
00749 {
00750     Internal::Swap<Vector<S1, P1, B1>, Vector<S2, P2, B2> >::swap(v1, v2);
00751 }
00752 
00753 
00754 template<int S1, class P1, class B1>
00755 void swap(Vector<S1, P1, B1>& v1, Vector<S1, P1, B1>& v2)
00756 {
00757     Internal::Swap<Vector<S1, P1, B1>, Vector<S1, P1, B1> >::swap(v1, v2);
00758 }
00759 
00760 }