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

Generated on Thu May 7 20:28:40 2009 for TooN by  doxygen 1.5.3