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