TooN 2.0.0-beta8
|
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 }