TooN 2.0.0-beta8
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 namespace Internal {
00038 
00039     //Automatic type deduction of return types
00040     ///@internal
00041     ///This function offers to return a value of type C. This function
00042     ///is not implemented anywhere, the result is used for type deduction.
00043     template<class C> C gettype();
00044     
00045     ///@internal
00046     ///Determine if two classes are in the same field. For the purposes of
00047     ///%TooN \c float and \c int are in the same field, since operator
00048     ///+,-,*,/ are defined for any combination of \c float and \c int.
00049     template<class L, class R> struct Field
00050     {   
00051         ///<Set to 1 if the two classes are in the same field.
00052         static const int is = IsField<L>::value & IsField<R>::value;
00053     };
00054     
00055 
00056     //We have to use the traits here because it is not possible to 
00057     //check for the existence of a valid operator *, especially
00058     //in the presence of builtin operators. Therefore, the type is
00059     //only deduced if both of the input types are fields.
00060     template<class L, class R, int F = Field<L,R>::is> struct AddType      { typedef TOON_TYPEOF(gettype<L>()+gettype<R>()) type;};
00061     template<class L, class R, int F = Field<L,R>::is> struct SubtractType { typedef TOON_TYPEOF(gettype<L>()-gettype<R>()) type;};
00062     template<class L, class R, int F = Field<L,R>::is> struct MultiplyType { typedef TOON_TYPEOF(gettype<L>()*gettype<R>()) type;};
00063     template<class L, class R, int F = Field<L,R>::is> struct DivideType   { typedef TOON_TYPEOF(gettype<L>()/gettype<R>()) type;};
00064 
00065     template<class L, class R> struct AddType<L, R, 0>         { typedef These_Types_Do_Not_Form_A_Field<L, R> type;};
00066     template<class L, class R> struct SubtractType<L, R, 0>    { typedef These_Types_Do_Not_Form_A_Field<L, R> type;};
00067     template<class L, class R> struct MultiplyType<L, R, 0>    { typedef These_Types_Do_Not_Form_A_Field<L, R> type;};
00068     template<class L, class R> struct DivideType<L, R, 0>      { typedef These_Types_Do_Not_Form_A_Field<L, R> type;};
00069 
00070 
00071     //Mini operators for passing to Pairwise, etc
00072     struct Add{
00073         template<class A, class B, class C>      static A op(const B& b, const C& c){return b+c;}
00074         template<class P1, class P2> struct Return { typedef typename AddType<P1,P2>::type Type;};
00075     };
00076     struct Subtract{
00077         template<class A, class B, class C> static A op(const B& b, const C& c){return b-c;}
00078         template<class P1, class P2> struct Return { typedef typename SubtractType<P1,P2>::type Type;};
00079     };
00080     struct Multiply{
00081         template<class A, class B, class C> static A op(const B& b, const C& c){return b*c;}
00082         template<class P1, class P2> struct Return { typedef typename MultiplyType<P1,P2>::type Type;};
00083     };
00084     struct Divide{
00085         template<class A, class B, class C>   static A op(const B& b, const C& c){return b/c;}
00086         template<class P1, class P2> struct Return { typedef typename DivideType<P1,P2>::type Type;};
00087     };
00088 
00089 };
00090 
00091 //////////////////////////////////////////////////////////////////////////////////////////////
00092 //                                       Operators
00093 //////////////////////////////////////////////////////////////////////////////////////////////
00094 
00095 template<class Op> struct Operator{};
00096 
00097 
00098 //////////////////////////////////////////////////////////////////////////////////
00099 //                         Vector <op> Vector
00100 //////////////////////////////////////////////////////////////////////////////////
00101 
00102 namespace Internal {
00103     template<typename Op,                           // the operation
00104              int S1, typename P1, typename B1,      // lhs vector
00105              int S2, typename P2, typename B2>      // rhs vector
00106     struct VPairwise;
00107 
00108     template <int S, typename P, typename A>        // input vector
00109     struct VNegate;
00110 };
00111 
00112 template<typename Op,                           // the operation
00113          int S1, typename P1, typename B1,      // lhs vector
00114          int S2, typename P2, typename B2>      // rhs vector
00115 struct Operator<Internal::VPairwise<Op, S1, P1, B1, S2, P2, B2> > {
00116     const Vector<S1, P1, B1> & lhs;
00117     const Vector<S2, P2, B2> & rhs;
00118 
00119     Operator(const Vector<S1, P1, B1> & lhs_in, const Vector<S2, P2, B2> & rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
00120 
00121     template<int S0, typename P0, typename Ba0>
00122     void eval(Vector<S0, P0, Ba0>& res) const
00123     {
00124         for(int i=0; i < res.size(); ++i)
00125             res[i] = Op::template op<P0,P1, P2>(lhs[i],rhs[i]);
00126     }
00127     int size() const {return lhs.size();}
00128 };
00129 
00130 // Addition Vector + Vector
00131 template<int S1, int S2, typename P1, typename P2, typename B1, typename B2> 
00132 Vector<Internal::Sizer<S1,S2>::size, typename Internal::AddType<P1, P2>::type> 
00133 operator+(const Vector<S1, P1, B1>& v1, const Vector<S2, P2, B2>& v2)
00134 {
00135     SizeMismatch<S1, S2>:: test(v1.size(),v2.size());
00136     return Operator<Internal::VPairwise<Internal::Add,S1,P1,B1,S2,P2,B2> >(v1,v2);
00137 }
00138 
00139 // Subtraction Vector - Vector
00140 template<int S1, int S2, typename P1, typename P2, typename B1, typename B2> 
00141 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)
00142 {
00143     SizeMismatch<S1, S2>:: test(v1.size(),v2.size());
00144     return Operator<Internal::VPairwise<Internal::Subtract,S1,P1,B1,S2,P2,B2> >(v1,v2);
00145 }
00146 
00147 // diagmult Vector, Vector
00148 template <int S1, int S2, typename P1, typename P2, typename B1, typename B2>
00149 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)
00150 {
00151     SizeMismatch<S1,S2>::test(v1.size(),v2.size());
00152     return Operator<Internal::VPairwise<Internal::Multiply,S1,P1,B1,S2,P2,B2> >(v1,v2);
00153 }
00154 
00155 template<int S, typename P, typename A>
00156 struct Operator<Internal::VNegate<S, P, A> > {
00157     const Vector<S, P, A> & input;
00158     Operator( const Vector<S, P, A> & in ) : input(in) {}
00159     
00160     template<int S0, typename P0, typename A0>
00161     void eval(Vector<S0, P0, A0> & res) const
00162     {
00163         res = input * -1;
00164     }
00165     int size() const { return input.size(); }
00166 };
00167 
00168 // Negation -Vector
00169 template <int S, typename P, typename A>
00170 Vector<S, P> operator-(const Vector<S,P,A> & v){
00171     return Operator<Internal::VNegate<S,P,A> >(v);
00172 }
00173 
00174 // Dot product Vector * Vector
00175 template<int Size1, typename Precision1, typename Base1, int Size2, typename Precision2, typename Base2>
00176 typename Internal::MultiplyType<Precision1, Precision2>::type operator*(const Vector<Size1, Precision1, Base1>& v1, const Vector<Size2, Precision2, Base2>& v2){
00177   SizeMismatch<Size1, Size2>:: test(v1.size(),v2.size());
00178   const int s=v1.size();
00179   typename Internal::MultiplyType<Precision1, Precision2>::type result=0;
00180   for(int i=0; i<s; i++){
00181     result+=v1[i]*v2[i];
00182   }
00183   return result;
00184 }
00185 
00186 template <typename P1, typename P2, typename B1, typename B2>
00187 Vector<3, typename Internal::MultiplyType<P1,P2>::type> operator^(const Vector<3,P1,B1>& v1, const Vector<3,P2,B2>& v2){
00188     // assume the result of adding two restypes is also a restype
00189     typedef typename Internal::MultiplyType<P1,P2>::type restype;
00190 
00191     Vector<3, restype> result;
00192 
00193     result[0] = v1[1]*v2[2] - v1[2]*v2[1];
00194     result[1] = v1[2]*v2[0] - v1[0]*v2[2];
00195     result[2] = v1[0]*v2[1] - v1[1]*v2[0];
00196 
00197     return result;
00198 }
00199 
00200 
00201 
00202 
00203 //////////////////////////////////////////////////////////////////////////////////
00204 //                            Matrix <op> Matrix
00205 //////////////////////////////////////////////////////////////////////////////////
00206 
00207 namespace Internal {
00208     template<typename Op,                           // the operation
00209              int R1, int C1, typename P1, typename B1,      // lhs matrix
00210              int R2, int C2, typename P2, typename B2>      // rhs matrix
00211     struct MPairwise;
00212 
00213     template<int R1, int C1, typename P1, typename B1,      // lhs matrix
00214              int R2, int C2, typename P2, typename B2>      // rhs matrix
00215     struct MatrixMultiply;
00216 
00217     template<int R, int C, typename P, typename A>         // input matrix
00218     struct MNegate;
00219 };
00220 
00221 template<typename Op,                           // the operation
00222          int R1, int C1, typename P1, typename B1,      // lhs matrix
00223          int R2, int C2, typename P2, typename B2>      // rhs matrix
00224 struct Operator<Internal::MPairwise<Op, R1, C1, P1, B1, R2, C2, P2, B2> > {
00225     const Matrix<R1, C1, P1, B1> & lhs;
00226     const Matrix<R2, C2, P2, B2> & rhs;
00227 
00228     Operator(const Matrix<R1, C1, P1, B1> & lhs_in, const Matrix<R2, C2, P2, B2> & rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
00229 
00230     template<int R0, int C0, typename P0, typename Ba0>
00231     void eval(Matrix<R0, C0, P0, Ba0>& res) const
00232     {
00233         for(int r=0; r < res.num_rows(); ++r){
00234             for(int c=0; c < res.num_cols(); ++c){
00235                 res(r,c) = Op::template op<P0,P1, P2>(lhs(r,c),rhs(r,c));
00236             }
00237         }
00238     }
00239     int num_rows() const {return lhs.num_rows();}
00240     int num_cols() const {return lhs.num_cols();}
00241 };
00242 
00243 // Addition Matrix + Matrix
00244 template<int R1, int R2, int C1, int C2, typename P1, typename P2, typename B1, typename B2> 
00245 Matrix<Internal::Sizer<R1,R2>::size, Internal::Sizer<C1,C2>::size, typename Internal::AddType<P1, P2>::type> 
00246 operator+(const Matrix<R1, C1, P1, B1>& m1, const Matrix<R2, C2, P2, B2>& m2)
00247 {
00248     SizeMismatch<R1, R2>:: test(m1.num_rows(),m2.num_rows());
00249     SizeMismatch<C1, C2>:: test(m1.num_cols(),m2.num_cols());
00250     return Operator<Internal::MPairwise<Internal::Add,R1,C1,P1,B1,R2,C2,P2,B2> >(m1,m2);
00251 }
00252 
00253 // Subtraction Matrix - Matrix
00254 template<int R1, int R2, int C1, int C2, typename P1, typename P2, typename B1, typename B2> 
00255 Matrix<Internal::Sizer<R1,R2>::size, Internal::Sizer<C1,C2>::size, typename Internal::SubtractType<P1, P2>::type> 
00256 operator-(const Matrix<R1, C1, P1, B1>& m1, const Matrix<R2, C2, P2, B2>& m2)
00257 {
00258     SizeMismatch<R1, R2>:: test(m1.num_rows(),m2.num_rows());
00259     SizeMismatch<C1, C2>:: test(m1.num_cols(),m2.num_cols());
00260     return Operator<Internal::MPairwise<Internal::Subtract,R1,C1,P1,B1,R2,C2,P2,B2> >(m1,m2);
00261 }
00262 
00263 template<int R, int C, typename P, typename A>
00264 struct Operator<Internal::MNegate<R,C, P, A> > {
00265     const Matrix<R,C,P,A> & input;
00266     Operator( const Matrix<R,C,P,A> & in ) : input(in) {}
00267     
00268     template<int R0, int C0, typename P0, typename A0>
00269     void eval(Matrix<R0,C0,P0,A0> & res) const
00270     {
00271         res = input * -1;
00272     }
00273     int num_rows() const { return input.num_rows(); }
00274     int num_cols() const { return input.num_cols(); }
00275 };
00276 
00277 // Negation -Matrix
00278 template <int R, int C, typename P, typename A>
00279 Matrix<R, C, P> operator-(const Matrix<R,C,P,A> & v){
00280     return Operator<Internal::MNegate<R,C,P,A> >(v);
00281 }
00282 
00283 template<int R1, int C1, typename P1, typename B1,      // lhs matrix
00284          int R2, int C2, typename P2, typename B2>      // rhs matrix
00285 struct Operator<Internal::MatrixMultiply<R1, C1, P1, B1, R2, C2, P2, B2> > {
00286     const Matrix<R1, C1, P1, B1> & lhs;
00287     const Matrix<R2, C2, P2, B2> & rhs;
00288 
00289     Operator(const Matrix<R1, C1, P1, B1> & lhs_in, const Matrix<R2, C2, P2, B2> & rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
00290 
00291     template<int R0, int C0, typename P0, typename Ba0>
00292     void eval(Matrix<R0, C0, P0, Ba0>& res) const
00293     {
00294 
00295         for(int r=0; r < res.num_rows(); ++r) {
00296             for(int c=0; c < res.num_cols(); ++c) {
00297                 res(r,c) = lhs[r] * (rhs.T()[c]);
00298             }
00299         }
00300     }
00301     int num_rows() const {return lhs.num_rows();}
00302     int num_cols() const {return rhs.num_cols();}
00303 };
00304 
00305 
00306 
00307 
00308 // Matrix multiplication Matrix * Matrix
00309 
00310 template<int R1, int C1, int R2, int C2, typename P1, typename P2, typename B1, typename B2> 
00311 Matrix<R1, C2, typename Internal::MultiplyType<P1, P2>::type> operator*(const Matrix<R1, C1, P1, B1>& m1, const Matrix<R2, C2, P2, B2>& m2)
00312 {
00313     SizeMismatch<C1, R2>:: test(m1.num_cols(),m2.num_rows());
00314     return Operator<Internal::MatrixMultiply<R1,C1,P1,B1,R2,C2,P2,B2> >(m1,m2);
00315 }
00316 
00317 //////////////////////////////////////////////////////////////////////////////////
00318 //                 matrix <op> vector and vv.
00319 //////////////////////////////////////////////////////////////////////////////////
00320 
00321 
00322 namespace Internal {
00323     // dummy struct for Vector * Matrix
00324     template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2>
00325     struct MatrixVectorMultiply;
00326 
00327     // this is distinct to cater for non commuting precision types
00328     template<int Size, typename P1, typename B1, int R, int C, typename P2, typename B2>
00329     struct VectorMatrixMultiply;
00330 
00331     // dummy struct for Vector * Matrix
00332     template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2>
00333     struct MatrixVectorDiagMultiply;
00334 
00335     // this is distinct to cater for non commuting precision types
00336     template<int Size, typename P1, typename B1, int R, int C, typename P2, typename B2>
00337     struct VectorMatrixDiagMultiply;
00338 
00339 };
00340 
00341 // Matrix Vector multiplication Matrix * Vector
00342 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2> 
00343 struct Operator<Internal::MatrixVectorMultiply<R,C,P1,B1,Size,P2,B2> > {
00344     const Matrix<R,C,P1,B1>& lhs;
00345     const Vector<Size,P2,B2>& rhs;
00346 
00347     Operator(const Matrix<R,C,P1,B1>& lhs_in, const Vector<Size,P2,B2>& rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
00348 
00349     int size() const {return lhs.num_rows();}
00350 
00351     template<int Sout, typename Pout, typename Bout>
00352     void eval(Vector<Sout, Pout, Bout>& res) const {
00353         for(int i=0; i < res.size(); ++i){
00354             res[i] = lhs[i] * rhs;
00355         }
00356     }
00357 };
00358 
00359 template<int R, int C, int Size, typename P1, typename P2, typename B1, typename B2>
00360 Vector<R, typename Internal::MultiplyType<P1,P2>::type> operator*(const Matrix<R, C, P1, B1>& m, const Vector<Size, P2, B2>& v)
00361 {
00362     SizeMismatch<C,Size>::test(m.num_cols(), v.size());
00363     return Operator<Internal::MatrixVectorMultiply<R,C,P1,B1,Size,P2,B2> >(m,v);
00364 }
00365                                                                     
00366 // Vector Matrix multiplication Vector * Matrix
00367 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2> 
00368 struct Operator<Internal::VectorMatrixMultiply<Size,P1,B1,R,C,P2,B2> > {
00369     const Vector<Size,P1,B1>& lhs;
00370     const Matrix<R,C,P2,B2>& rhs;
00371 
00372     Operator(const Vector<Size,P1,B1>& lhs_in, const Matrix<R,C,P2,B2>& rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
00373 
00374     int size() const {return rhs.num_cols();}
00375 
00376     template<int Sout, typename Pout, typename Bout>
00377     void eval(Vector<Sout, Pout, Bout>& res) const {
00378         for(int i=0; i < res.size(); ++i){
00379             res[i] = lhs * rhs.T()[i];
00380         }
00381     }
00382 };
00383 
00384 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2> 
00385 Vector<C, typename Internal::MultiplyType<P1,P2>::type> operator*(const Vector<Size,P1,B1>& v,
00386                                                                   const Matrix<R,C,P2,B2>& m)
00387 {
00388     SizeMismatch<R,Size>::test(m.num_rows(), v.size());
00389     return Operator<Internal::VectorMatrixMultiply<Size,P1,B1,R,C,P2,B2> >(v,m);
00390 }
00391 
00392 
00393 // Matrix Vector diagonal multiplication Matrix * Vector
00394 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2> 
00395 struct Operator<Internal::MatrixVectorDiagMultiply<R,C,P1,B1,Size,P2,B2> > {
00396     const Matrix<R,C,P1,B1>& lhs;
00397     const Vector<Size,P2,B2>& rhs;
00398 
00399     Operator(const Matrix<R,C,P1,B1>& lhs_in, const Vector<Size,P2,B2>& rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
00400 
00401     int num_rows() const {return lhs.num_rows();}
00402     int num_cols() const {return lhs.num_cols();}
00403 
00404     template<int Rout, int Cout, typename Pout, typename Bout>
00405     void eval(Matrix<Rout, Cout, Pout, Bout>& res) const {
00406         for(int c=0; c < res.num_cols(); ++c) {
00407             P2 temp = rhs[c];
00408             for(int r=0; r < res.num_rows(); ++r) {
00409                 res(r,c) = lhs(r,c)*temp;
00410             }
00411         }
00412     }
00413 };
00414 
00415 template<int R, int C, int Size, typename P1, typename P2, typename B1, typename B2>
00416 Matrix<R, C, typename Internal::MultiplyType<P1,P2>::type> diagmult(const Matrix<R, C, P1, B1>& m, const Vector<Size, P2, B2>& v)
00417 {
00418     SizeMismatch<C,Size>::test(m.num_cols(), v.size());
00419     return Operator<Internal::MatrixVectorDiagMultiply<R,C,P1,B1,Size,P2,B2> >(m,v);
00420 }
00421                                                                     
00422 // Vector Matrix diagonal multiplication Vector * Matrix
00423 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2> 
00424 struct Operator<Internal::VectorMatrixDiagMultiply<Size,P1,B1,R,C,P2,B2> > {
00425     const Vector<Size,P1,B1>& lhs;
00426     const Matrix<R,C,P2,B2>& rhs;
00427 
00428     Operator(const Vector<Size,P1,B1>& lhs_in, const Matrix<R,C,P2,B2>& rhs_in) : lhs(lhs_in), rhs(rhs_in) {}
00429 
00430     int num_rows() const {return rhs.num_rows();}
00431     int num_cols() const {return rhs.num_cols();}
00432 
00433     template<int Rout, int Cout, typename Pout, typename Bout>
00434     void eval(Matrix<Rout, Cout, Pout, Bout>& res) const {
00435         for(int r=0; r < res.num_rows(); ++r){
00436             const P1 temp = lhs[r];
00437             for(int c=0; c<res.num_cols(); ++c){
00438                 res(r,c) = temp * rhs(r,c);
00439             }
00440         }
00441     }
00442 };
00443 
00444 template<int R, int C, typename P1, typename B1, int Size, typename P2, typename B2> 
00445 Matrix<R, C, typename Internal::MultiplyType<P1,P2>::type> diagmult(const Vector<Size,P1,B1>& v,
00446                                                                  const Matrix<R,C,P2,B2>& m)
00447 {
00448     SizeMismatch<R,Size>::test(m.num_rows(), v.size());
00449     return Operator<Internal::VectorMatrixDiagMultiply<Size,P1,B1,R,C,P2,B2> >(v,m);
00450 }
00451 
00452 
00453 ////////////////////////////////////////////////////////////////////////////////
00454 //
00455 // vector <op> scalar 
00456 // scalar <op> vector 
00457 // matrix <op> scalar 
00458 // scalar <op> matrix 
00459 //
00460 // Except <scalar> / <matrix|vector> does not exist
00461 
00462 namespace Internal {
00463     template<int Size, typename P1, typename B1, typename P2, typename Op>
00464     struct ApplyScalarV;
00465 
00466     template<int Size, typename P1, typename B1, typename P2, typename Op>
00467     struct ApplyScalarVL;
00468 
00469     template<int R, int C, typename P1, typename B1, typename P2, typename Op>
00470     struct ApplyScalarM;
00471 
00472     template<int R, int C, typename P1, typename B1, typename P2, typename Op>
00473     struct ApplyScalarML;
00474 };
00475 
00476 template<int Size, typename P1, typename B1, typename P2, typename Op>
00477 struct Operator<Internal::ApplyScalarV<Size,P1,B1,P2,Op> > {
00478     const Vector<Size,P1,B1>& lhs;
00479     const P2& rhs;
00480 
00481     Operator(const Vector<Size,P1,B1>& v, const P2& s) : lhs(v), rhs(s) {}
00482         
00483     template<int S0, typename P0, typename Ba0>
00484     void eval(Vector<S0,P0,Ba0>& v) const {
00485         for(int i=0; i<v.size(); i++){
00486             v[i]= Op::template op<P0,P1,P2> (lhs[i],rhs);
00487         }
00488     }
00489 
00490     int size() const {
00491         return lhs.size();
00492     }
00493 };
00494 
00495 template <int Size, typename P1, typename B1, typename P2>
00496 Vector<Size, typename Internal::Multiply::Return<P1,P2>::Type> operator*(const Vector<Size, P1, B1>& v, const P2& s){
00497     return Operator<Internal::ApplyScalarV<Size,P1,B1,P2,Internal::Multiply> > (v,s);
00498 }
00499 template <int Size, typename P1, typename B1, typename P2>
00500 Vector<Size, typename Internal::Divide::Return<P1,P2>::Type> operator/(const Vector<Size, P1, B1>& v, const P2& s){
00501     return Operator<Internal::ApplyScalarV<Size,P1,B1,P2,Internal::Divide> > (v,s);
00502 }
00503 
00504 template<int Size, typename P1, typename B1, typename P2, typename Op>
00505 struct Operator<Internal::ApplyScalarVL<Size,P1,B1,P2,Op> > {
00506     const P2& lhs;
00507     const Vector<Size,P1,B1>& rhs;
00508 
00509     Operator(const P2& s, const Vector<Size,P1,B1>& v) : lhs(s), rhs(v) {}
00510         
00511     template<int S0, typename P0, typename Ba0>
00512     void eval(Vector<S0,P0,Ba0>& v) const {
00513         for(int i=0; i<v.size(); i++){
00514             v[i]= Op::template op<P0,P2,P1> (lhs,rhs[i]);
00515         }
00516     }
00517 
00518     int size() const {
00519         return rhs.size();
00520     }
00521 };
00522 template <int Size, typename P1, typename B1, typename P2>
00523 Vector<Size, typename Internal::Multiply::Return<P2,P1>::Type> operator*(const P2& s, const Vector<Size, P1, B1>& v){
00524     return Operator<Internal::ApplyScalarVL<Size,P1,B1,P2,Internal::Multiply> > (s,v);
00525 }
00526 // no left division
00527 
00528 
00529 ///////  Matrix scalar operators
00530 
00531 template<int R, int C, typename P1, typename B1, typename P2, typename Op>
00532 struct Operator<Internal::ApplyScalarM<R,C,P1,B1,P2,Op> > {
00533     const Matrix<R,C,P1,B1>& lhs;
00534     const P2& rhs;
00535 
00536     Operator(const Matrix<R,C,P1,B1>& m, const P2& s) : lhs(m), rhs(s) {}
00537         
00538     template<int R0, int C0, typename P0, typename Ba0>
00539     void eval(Matrix<R0,C0,P0,Ba0>& m) const {
00540         for(int r=0; r<m.num_rows(); r++){
00541             for(int c=0; c<m.num_cols(); c++){
00542                 m(r,c)= Op::template op<P0,P1,P2> (lhs(r,c),rhs);
00543             }
00544         }
00545     }
00546 
00547     int num_rows() const {
00548         return lhs.num_rows();
00549     }
00550     int num_cols() const {
00551         return lhs.num_cols();
00552     }
00553 };
00554 
00555 template <int R, int C, typename P1, typename B1, typename P2>
00556 Matrix<R,C, typename Internal::Multiply::Return<P1,P2>::Type> operator*(const Matrix<R,C, P1, B1>& m, const P2& s){
00557     return Operator<Internal::ApplyScalarM<R,C,P1,B1,P2,Internal::Multiply> > (m,s);
00558 }
00559 template <int R, int C, typename P1, typename B1, typename P2>
00560 Matrix<R,C, typename Internal::Divide::Return<P1,P2>::Type> operator/(const Matrix<R,C, P1, B1>& m, const P2& s){
00561     return Operator<Internal::ApplyScalarM<R,C,P1,B1,P2,Internal::Divide> > (m,s);
00562 }
00563 
00564 template<int R, int C, typename P1, typename B1, typename P2, typename Op>
00565 struct Operator<Internal::ApplyScalarML<R,C,P1,B1,P2,Op> > {
00566     const P2& lhs;
00567     const Matrix<R,C,P1,B1>& rhs;
00568 
00569     Operator( const P2& s,const Matrix<R,C,P1,B1>& m) : lhs(s), rhs(m) {}
00570         
00571     template<int R0, int C0, typename P0, typename Ba0>
00572     void eval(Matrix<R0,C0,P0,Ba0>& m) const {
00573         for(int r=0; r<m.num_rows(); r++){
00574             for(int c=0; c<m.num_cols(); c++){
00575                 m(r,c)= Op::template op<P0,P1,P2> (lhs,rhs(r,c));
00576             }
00577         }
00578     }
00579 
00580     int num_rows() const {
00581         return rhs.num_rows();
00582     }
00583     int num_cols() const {
00584         return rhs.num_cols();
00585     }
00586 };
00587 
00588 template <int R, int C, typename P1, typename B1, typename P2>
00589 Matrix<R,C, typename Internal::Multiply::Return<P2,P1>::Type> operator*(const P2& s, const Matrix<R,C, P1, B1>& m){
00590     return Operator<Internal::ApplyScalarML<R,C,P1,B1,P2,Internal::Multiply> > (s,m);
00591 }
00592 
00593 ////////////////////////////////////////////////////////////////////////////////
00594 //
00595 // Addition of operators
00596 //
00597 template <int Size, typename P1, typename B1, typename Op>
00598 Vector<Size, typename Internal::Add::Return<P1,typename Operator<Op>::Precision>::Type> operator+(const Vector<Size, P1, B1>& v, const Operator<Op>& op){
00599     return op.add(v);
00600 }
00601 
00602 template <int Size, typename P1, typename B1, typename Op>
00603 Vector<Size, typename Internal::Add::Return<typename Operator<Op>::Precision, P1>::Type> operator+(const Operator<Op>& op, const Vector<Size, P1, B1>& v){
00604     return op.add(v);
00605 }
00606 
00607 template <int Rows, int Cols, typename P1, typename B1, typename Op>
00608 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){
00609     return op.add(m);
00610 }
00611 
00612 template <int Rows, int Cols, typename P1, typename B1, typename Op>
00613 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){
00614     return op.add(m);
00615 }
00616 
00617 
00618 
00619 
00620 template <int Size, typename P1, typename B1, typename Op>
00621 Vector<Size, typename Internal::Subtract::Return<P1,typename Operator<Op>::Precision>::Type> operator-(const Vector<Size, P1, B1>& v, const Operator<Op>& op){
00622     return op.rsubtract(v);
00623 }
00624 
00625 template <int Size, typename P1, typename B1, typename Op>
00626 Vector<Size, typename Internal::Subtract::Return<typename Operator<Op>::Precision, P1>::Type> operator-(const Operator<Op>& op, const Vector<Size, P1, B1>& v){
00627     return op.lsubtract(v);
00628 }
00629 
00630 template <int Rows, int Cols, typename P1, typename B1, typename Op>
00631 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){
00632     return op.rsubtract(m);
00633 }
00634 
00635 template <int Rows, int Cols, typename P1, typename B1, typename Op>
00636 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){
00637     return op.lsubtract(m);
00638 }
00639 ////////////////////////////////////////////////////////////////////////////////
00640 //
00641 // Stream I/O operators
00642 //
00643 
00644 // output operator <<
00645 template <int Size, typename Precision, typename Base>
00646 inline std::ostream& operator<< (std::ostream& os, const Vector<Size,Precision,Base>& v){
00647   std::streamsize fw = os.width();
00648   for(int i=0; i<v.size(); i++){
00649     os.width(fw);
00650     os << v[i] << " ";
00651   }
00652   return os;
00653 }
00654 
00655 // operator istream& >>
00656 template <int Size, typename Precision, typename Base>
00657 std::istream& operator >> (std::istream& is, Vector<Size, Precision, Base>& v){
00658     for (int i=0; i<v.size(); i++){
00659         is >>  v[i];
00660     }
00661     return is;
00662 }
00663 
00664 template<int Rows, int Cols, typename Precision, class Base>
00665 inline std::ostream& operator<< (std::ostream& os, const Matrix<Rows, Cols, Precision, Base>& m){
00666     std::streamsize fw = os.width();
00667     for(int i=0; i < m.num_rows(); i++)
00668     {
00669         for(int j=0; j < m.num_cols(); j++)
00670         {
00671             if(j != 0)
00672                 os << " ";
00673             os.width(fw);
00674             os << m(i,j);
00675         }
00676         os << std::endl;
00677     }
00678     return os;
00679 }
00680 
00681 // operator istream& >>
00682 template <int Rows, int Cols, typename Precision, typename Base>
00683 std::istream& operator >> (std::istream& is, Matrix<Rows, Cols, Precision, Base>& m){
00684     for(int r=0; r<m.num_rows(); r++){
00685         for(int c=0; c < m.num_cols(); c++){
00686             is >> m(r,c);
00687         }
00688     }
00689     return is;
00690 }
00691 
00692 }