TooN: internal/operators.hh Source File

TooN 2.0.0-beta8

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List

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 }