![]() |
MechSys
1.0
Computing library for simulations in continuum and discrete mechanics
|
00001 /************************************************************************ 00002 * MechSys - Open Library for Mechanical Systems * 00003 * Copyright (C) 2005 Dorival M. Pedroso, Raúl D. D. Farfan * 00004 * * 00005 * This program is free software: you can redistribute it and/or modify * 00006 * it under the terms of the GNU General Public License as published by * 00007 * the Free Software Foundation, either version 3 of the License, or * 00008 * any later version. * 00009 * * 00010 * This program is distributed in the hope that it will be useful, * 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00013 * GNU General Public License for more details. * 00014 * * 00015 * You should have received a copy of the GNU General Public License * 00016 * along with this program. If not, see <http://www.gnu.org/licenses/> * 00017 ************************************************************************/ 00018 00019 /* Expression template evaluation for matrices */ 00020 00021 #ifndef MECHSYS_LINALG_LAEXPR_H 00022 #define MECHSYS_LINALG_LAEXPR_H 00023 00024 // STL 00025 #include <iostream> 00026 #include <sstream> 00027 00028 // MechSys 00029 #include <mechsys/linalg/matrix.h> 00030 #include <mechsys/linalg/vector.h> 00031 #include <mechsys/util/fatal.h> 00032 00033 extern "C" 00034 { 00035 // BLAS 00036 double ddot_(int const *N, double const *X, int const *incX, double const *Y, int const *incY); 00037 00038 void dgemv_(char const *TransA , int const *M , int const *N , double const *alpha , 00039 double const *A , int const *lda , double const *X , int const *incX , 00040 double const *beta , double *Y , int const *incY); 00041 00042 void dgemm_(char const *TransA , char const *TransB , int const *M , int const *N , 00043 int const *K , double const *alpha , double const *A , int const *lda , 00044 double const *B , int const *ldb , double const *beta , double *C , int const *ldc); 00045 } 00046 00047 namespace LinAlg 00048 { 00049 00050 00051 // LAPACK wrapper ////////////////////////////////////////////////////////////////////////////////////////////// 00052 00053 00055 inline double Dot(Vector<double> const & X, Vector<double> const & Y) 00056 { 00057 #ifndef DNDEBUG 00058 if (Y.Size()!=X.Size()) throw new Fatal("LinAlg::Axpy: The size (%d) of vector Y must be equal to the size (%d) of vector X",Y.Size(),X.Size()); 00059 #endif 00060 int N = X.Size(); 00061 int incX = 1; 00062 int incY = 1; 00063 return ddot_(&N,X.GetPtr(),&incX,Y.GetPtr(),&incY); 00064 } 00065 00067 inline void Gemv(double const a, Matrix<double> const & A, Vector<double> const & X, double const b, Vector<double> & Y) 00068 { 00069 /* {Y} <- a*[A]*{X} + b*{Y} 00070 _ _ / 0 \ 00071 / 0 \ | 00 01 02 03 04 ... 0N | | 1 | / 0 \ 00072 | 1 | | 10 11 12 13 14 ... 1N | | 2 | | 1 | 00073 | 2 | = a*| 20 21 22 23 24 ... 2N |*| 3 | + b*| 2 | 00074 |...| | ... | | 4 | |...| 00075 \ M / |_ M0 M1 M2 M3 M4 ... MN _| |...| \ M / 00076 \ N / 00077 00078 This function preserves [A] matrix after multplication 00079 */ 00080 #ifndef DNDEBUG 00081 if (X.Size()!=A.Cols()) throw new Fatal("LinAlg::Gemv: The size (%d) of vector X must be equal to the number of columns (%d) of matrix A",X.Size(),A.Cols()); 00082 if (Y.Size()!=A.Rows()) throw new Fatal("LinAlg::Gemv: The size (%d) of vector Y must be equal to the number of rows (%d) of matrix A",Y.Size(),A.Rows()); 00083 #endif 00084 int M = A.Rows(); 00085 int N = A.Cols(); 00086 char TransA = 'N'; 00087 int incX = 1; 00088 int incY = 1; 00089 dgemv_(&TransA, // CBLAS_TRANSPOSE A 00090 &M, // M 00091 &N, // N 00092 &a, // Alpha 00093 A.GetPtr(), // const double * A 00094 &M, // LDA 00095 X.GetPtr(), // const double * X 00096 &incX, // incX 00097 &b, // Beta 00098 Y.GetPtr(), // double * Y 00099 &incY); // incY 00100 } 00101 00103 inline void Gemm(double const a, Matrix<double> const & A, Matrix<double> const & B, double const b, Matrix<double> & C) 00104 { 00105 /* [C] <- a*[A]*[B] + b*[C] 00106 _ _ _ _ / 00 . 0N \ _ _ 00107 | 00 . 0N | | 00 01 02 03 04 ... 0K | | 10 . 1N | | 00 . 0N | 00108 | 10 . 1N | | 10 11 12 13 14 ... 1K | | 20 . 2N | | 10 . 1N | 00109 | 20 . 2N | = a*| 20 21 22 23 24 ... 2K |*| 30 . 3N | + b*| 20 . 2N | 00110 | ... | | ... | | 40 . 4N | | ... | 00111 |_ M0 . MN _| |_ M0 M1 M2 M3 M4 ... MK _| | ... | |_ M0 . MN _| 00112 \ K0 . KN / 00113 */ 00114 #ifndef DNDEBUG 00115 if (B.Rows()!=A.Cols()) throw new Fatal("LinAlg::Gemm: The number of rows (%d) of matrix B must be equal to the number of columns (%d) of matrix A",B.Rows(),A.Cols()); 00116 if (C.Rows()!=A.Rows()) throw new Fatal("LinAlg::Gemm: The number of rows (%d) of matrix C must be equal to the number of rows (%d) of matrix A",C.Rows(),A.Rows()); 00117 if (C.Cols()!=B.Cols()) throw new Fatal("LinAlg::Gemm: The number of columns (%d) of matrix C must be equal to the number of columns (%d) of matrix B",C.Cols(),B.Cols()); 00118 #endif 00119 int M = A.Rows(); 00120 int K = A.Cols(); 00121 int N = B.Cols(); 00122 char TransA = 'N'; 00123 char TransB = 'N'; 00124 dgemm_(&TransA, // CBLAS_TRANSPOSE A 00125 &TransB, // CBLAS_TRANSPOSE B 00126 &M, // M 00127 &N, // N 00128 &K, // K 00129 &a, // Alpha 00130 A.GetPtr(), // const double * A 00131 &M, // LDA 00132 B.GetPtr(), // const double * B 00133 &K, // LDB 00134 &b, // Beta 00135 C.GetPtr(), // double * C 00136 &M); // LDC 00137 } 00138 00140 inline void Gemtm(double const a, Matrix<double> const & A, Matrix<double> const & B, double const b, Matrix<double> & C) 00141 { 00142 #ifndef DNDEBUG 00143 if (B.Rows()!=A.Rows()) throw new Fatal("LinAlg::Gemtm: The number of rows (%d) of matrix B must be equal to the number of rows (%d) of matrix A",B.Rows(),A.Rows()); 00144 if (C.Rows()!=A.Cols()) throw new Fatal("LinAlg::Gemtm: The number of rows (%d) of matrix C must be equal to the number of columns (%d) of matrix A",C.Rows(),A.Cols()); 00145 if (C.Cols()!=B.Cols()) throw new Fatal("LinAlg::Gemtm: The number of columns (%d) of matrix C must be equal to the number of columns (%d) of matrix B",C.Cols(),B.Cols()); 00146 #endif 00147 int K = A.Rows(); 00148 int M = A.Cols(); 00149 int N = B.Cols(); 00150 char TransA = 'T'; 00151 char TransB = 'N'; 00152 dgemm_(&TransA, // CBLAS_TRANSPOSE A 00153 &TransB, // CBLAS_TRANSPOSE B 00154 &M, // M 00155 &N, // N 00156 &K, // K 00157 &a, // Alpha 00158 A.GetPtr(), // const double * A 00159 &K, // LDA 00160 B.GetPtr(), // const double * B 00161 &K, // LDB 00162 &b, // Beta 00163 C.GetPtr(), // double * C 00164 &M); // LDC 00165 } 00166 00168 inline void Gemmt(double const a, Matrix<double> const & A, Matrix<double> const & B, double const b, Matrix<double> & C) 00169 { 00170 #ifndef DNDEBUG 00171 if (B.Cols()!=A.Cols()) throw new Fatal("LinAlg::Gemmt: The number of columns (%d) of matrix B must be equal to the number of columns (%d) of matrix A",B.Cols(),A.Cols()); 00172 if (C.Rows()!=A.Rows()) throw new Fatal("LinAlg::Gemmt: The number of rows (%d) of matrix C must be equal to the number of rows (%d) of matrix A",C.Rows(),A.Rows()); 00173 if (C.Cols()!=B.Rows()) throw new Fatal("LinAlg::Gemmt: The number of columns (%d) of matrix C must be equal to the number of rows (%d) of matrix B",C.Cols(),B.Rows()); 00174 #endif 00175 int M = A.Rows(); 00176 int K = A.Cols(); 00177 int N = B.Rows(); 00178 char TransA = 'N'; 00179 char TransB = 'T'; 00180 dgemm_(&TransA, // CBLAS_TRANSPOSE A 00181 &TransB, // CBLAS_TRANSPOSE B 00182 &M, // M 00183 &N, // N 00184 &K, // K 00185 &a, // Alpha 00186 A.GetPtr(), // const double * A 00187 &M, // LDA 00188 B.GetPtr(), // const double * B 00189 &N, // LDB 00190 &b, // Beta 00191 C.GetPtr(), // double * C 00192 &M); // LDC 00193 } 00194 00196 inline void Gemtmt(double const a, Matrix<double> const & A, Matrix<double> const & B, double const b, Matrix<double> & C) 00197 { 00198 #ifndef DNDEBUG 00199 if (B.Cols()!=A.Rows()) throw new Fatal("LinAlg::Gemmt: The number of columns (%d) of matrix B must be equal to the number of rows (%d) of matrix A",B.Cols(),A.Rows()); 00200 if (C.Rows()!=A.Cols()) throw new Fatal("LinAlg::Gemmt: The number of rows (%d) of matrix C must be equal to the number of columns (%d) of matrix A",C.Rows(),A.Cols()); 00201 if (C.Cols()!=B.Rows()) throw new Fatal("LinAlg::Gemmt: The number of columns (%d) of matrix C must be equal to the number of rows (%d) of matrix B",C.Cols(),B.Rows()); 00202 #endif 00203 int K = A.Rows(); 00204 int M = A.Cols(); 00205 int N = B.Rows(); 00206 char TransA = 'T'; 00207 char TransB = 'T'; 00208 dgemm_(&TransA, // CBLAS_TRANSPOSE A 00209 &TransB, // CBLAS_TRANSPOSE B 00210 &M, // M 00211 &N, // N 00212 &K, // K 00213 &a, // Alpha 00214 A.GetPtr(), // const double * A 00215 &K, // LDA 00216 B.GetPtr(), // const double * B 00217 &N, // LDB 00218 &b, // Beta 00219 C.GetPtr(), // double * C 00220 &M); // LDC 00221 } 00222 00223 00224 // Implementation of basic operations ////////////////////////////////////////////////////////////////////////// 00225 00226 00227 // returns: Y <- a*X 00228 template <typename type> 00229 inline 00230 void _scale(size_t n, 00231 type a, 00232 type const * ptrX, 00233 type * ptrY) 00234 { 00235 size_t ll = n % 4; 00236 for (size_t i = 0; i<ll; ++i) ptrY[i] = a*ptrX[i]; 00237 for (size_t i = ll; i<n; i += 4) 00238 { 00239 ptrY[i] = a*ptrX[i ]; 00240 ptrY[i+1] = a*ptrX[i+1]; 00241 ptrY[i+2] = a*ptrX[i+2]; 00242 ptrY[i+3] = a*ptrX[i+3]; 00243 } 00244 } 00245 00246 // returns: Y <- a*X + b*W 00247 template <typename type> 00248 inline 00249 void _scale(size_t n, 00250 type a, 00251 type const * ptrX, 00252 type b, 00253 type const * ptrW, 00254 type * ptrY) 00255 { 00256 size_t ll = n % 4; 00257 for (size_t i = 0; i<ll; ++i) ptrY[i] = a*ptrX[i] + b*ptrW[i]; 00258 for (size_t i = ll; i<n; i += 4) 00259 { 00260 ptrY[i] = a*ptrX[i ] + b*ptrW[i ]; 00261 ptrY[i+1] = a*ptrX[i+1] + b*ptrW[i+1]; 00262 ptrY[i+2] = a*ptrX[i+2] + b*ptrW[i+2]; 00263 ptrY[i+3] = a*ptrX[i+3] + b*ptrW[i+3]; 00264 } 00265 } 00266 00267 00268 // Scale function for Vector and Matrix //////////////////////////////////////////////////////////////////////// 00269 00270 00271 // returns: Y <- a*X 00272 template <typename type> 00273 inline 00274 void scale(type a, 00275 Vector<type> const & X, 00276 Vector<type> & Y) 00277 { 00278 size_t n = X.Size(); 00279 Y.Resize(n); 00280 type const * ptrX = X.GetPtr(); 00281 type * ptrY = Y.GetPtr(); 00282 _scale(n, a, ptrX, ptrY); 00283 } 00284 00285 // returns: Y <- a*X + b*W 00286 template <typename type> 00287 inline 00288 void scale(type a, 00289 Vector<type> const & X, 00290 type b, 00291 Vector<type> const & W, 00292 Vector<type> & Y) 00293 { 00294 int n = X.Size(); 00295 if (W.Size()!=n) throw new Fatal("Internal Error: laexpr.h::scale: W.Size()==%d must be equal to %d",W.Size(),n); 00296 Y.Resize(n); 00297 type const * ptrX = X.GetPtr(); 00298 type const * ptrW = W.GetPtr(); 00299 type * ptrY = Y.GetPtr(); 00300 _scale(n, a, ptrX, b, ptrW, ptrY); 00301 } 00302 00303 // returns: Y <- a*X 00304 template <typename type> 00305 inline 00306 void scale(type a, 00307 Matrix<type> const & X, 00308 Matrix<type> & Y) 00309 { 00310 size_t n = X.Rows()*X.Cols(); 00311 Y.Resize(X.Rows(), X.Cols()); 00312 type const * ptrX = X.GetPtr(); 00313 type * ptrY = Y.GetPtr(); 00314 _scale(n, a, ptrX, ptrY); 00315 } 00316 00317 // returns: Y <- a*X + b*W 00318 template <typename type> 00319 inline 00320 void scale(type a, 00321 Matrix<type> const & X, 00322 type b, 00323 Matrix<type> const & W, 00324 Matrix<type> & Y) 00325 { 00326 if (!(X.Rows()==W.Rows() && X.Cols()==W.Cols())) throw new Fatal("Internal Error: laexpr.h::scale: X.Rows==%d must be equal to W.Rows==%d and X.Cols==%d must be equal to W.Cols==%d",X.Rows(),W.Rows(),X.Cols(),W.Cols()); 00327 size_t n = X.Rows()*X.Cols(); 00328 Y.Resize(X.Rows(), X.Cols()); 00329 type const * ptrX = X.GetPtr(); 00330 type const * ptrW = W.GetPtr(); 00331 type * ptrY = Y.GetPtr(); 00332 _scale(n, a, ptrX, b, ptrW, ptrY); 00333 } 00334 00335 // returns: B <- a*trn(A); 00336 template <typename type> 00337 inline 00338 void scalet(type a, 00339 Vector<type> const & A, 00340 Matrix<type> & B) 00341 { 00342 size_t n = A.Size(); 00343 B.Resize(1, n); 00344 type const * ptrA = A.GetPtr(); 00345 type * ptrB = B.GetPtr(); 00346 _scale(n, a, ptrA, ptrB); 00347 } 00348 00349 // returns: B <- a*trn(A); 00350 template <typename type> 00351 inline 00352 void scalet(type a, 00353 Matrix<type> const & A, 00354 Matrix<type> & B) // n x m (col major) 00355 { 00356 size_t m = A.Rows(); 00357 size_t n = A.Cols(); 00358 type const * ptrA; 00359 ptrA = A.GetPtr(); 00360 00361 B.Resize(n, m); 00362 type * ptrB = B.GetPtr(); 00363 00364 type rowA[n]; 00365 for (size_t i=0; i<m; ++i) //in rows of A 00366 { 00367 for (size_t k = 0; k<n; k++) //in cols of A 00368 rowA[k] = ptrA[i + k*m]; 00369 type * colB = &ptrB[i*n]; 00370 _scale(n, a, rowA, colB); 00371 } 00372 } 00373 00374 00375 // Function operations ///////////////////////////////////////////////////////////////////////////////////////// 00376 00377 00378 // Vector function operators 00379 00380 // Vector + Vector 00381 template <typename type> 00382 inline 00383 Vector<type> & _add(Vector<type> const & A, Vector<type> const & B, Vector<type> & R) 00384 { 00385 scale(static_cast<type>(1), A, static_cast<type>(1), B, R); 00386 return R; 00387 } 00388 00389 // Vector - Vector 00390 template <typename type> 00391 inline 00392 Vector<type> & _minus(Vector<type> const & A, Vector<type> const & B, Vector<type> & R) 00393 { 00394 scale(static_cast<type>(1), A, static_cast<type>(-1), B, R); 00395 return R; 00396 } 00397 00398 // scalar * Vector 00399 template <class type, class t_num1> 00400 inline 00401 Vector<type> & _prod(t_num1 const & a, Vector<type> const & A, Vector<type> & R) 00402 { 00403 //scale(static_cast<type>(a), A, R); 00404 R.Resize(A.Size()); 00405 _scale(A.Size(), static_cast<type>(a), A.GetPtr(), R.GetPtr()); 00406 return R; 00407 } 00408 00409 // vector transpose 00410 template <typename type> 00411 inline 00412 Matrix<type> & _trn(Vector<type> const & A, Matrix<type> & R) 00413 { 00414 scalet(static_cast<type>(1), A, R); 00415 return R; 00416 } 00417 00418 // Matrix + Matrix 00419 template <typename type> 00420 inline 00421 Matrix<type> & _add(Matrix<type> const & A, Matrix<type> const & B, Matrix<type> & R) 00422 { 00423 scale(static_cast<type>(1), A, static_cast<type>(1), B, R); 00424 return R; 00425 } 00426 00427 // Matrix - Matrix 00428 template <typename type> 00429 inline 00430 Matrix<type> & _minus(Matrix<type> const & A, Matrix<type> const & B, Matrix<type> & R) 00431 { 00432 scale(static_cast<type>(1), A, static_cast<type>(-1), B, R); 00433 return R; 00434 } 00435 00436 // Matrix * Vector 00437 template <class type> 00438 inline 00439 Vector<type> & _prod(Matrix<type> const & A, Vector<type> const & B, Vector<type> & R) 00440 { 00441 R.Resize(A.Rows()); 00442 if (A.Cols()!=B.Size()) throw new Fatal("Internal Error: laexpr.h::_prod: A.Cols==%d must be equal to B.Size==%d",A.Cols(),B.Size()); 00443 Gemv(static_cast<type>(1), A, B, static_cast<type>(0), R); 00444 return R; 00445 } 00446 00447 // Vector * Matrix 00448 template <class type> 00449 inline 00450 Matrix<type> & _prod(Vector<type> const & A, Matrix<type> const & B, Matrix<type> & R) 00451 { 00452 // this operation is appropriate only when B is a row matrix 00453 size_t m = A.Size(); 00454 size_t n = B.Cols(); 00455 if (B.Rows()!=1) throw new Fatal("Internal Error: laexpr.h::_prod: B.Rows==%d must be equal to 1",B.Rows()); 00456 R.Resize(m, n); 00457 type const * ptrA = A.GetPtr(); 00458 type const * ptrB = B.GetPtr(); 00459 type * ptrR = R.GetPtr(); 00460 00461 for (size_t i=0; i<m; i++) 00462 for (size_t j=0; j<n; j++) 00463 ptrR[i+j*m] = ptrA[i]*ptrB[j]; 00464 00465 return R; 00466 } 00467 00468 // Matrix * Matrix 00469 template <class type> 00470 inline 00471 Matrix<type> & _prod(Matrix<type> const & A, Matrix<type> const & B, Matrix<type> & R) 00472 { 00473 R.Resize(A.Rows(), B.Cols()); 00474 Gemm(static_cast<type>(1), A, B, static_cast<type>(0), R); 00475 return R; 00476 } 00477 00478 // scalar * Matrix 00479 template <class type, class t_scalar> 00480 inline 00481 Matrix<type> & _prod(t_scalar const & A, Matrix<type> const & B, Matrix<type> & R) 00482 { 00483 scale(static_cast<type const &>(A), B, R); 00484 return R; 00485 } 00486 00487 // trn(Matrix) 00488 template <typename type> 00489 inline 00490 Matrix<type> & _trn(Matrix<type> const & A, Matrix<type> & R) 00491 { 00492 scalet(static_cast<type>(1), A, R); 00493 return R; 00494 } 00495 00496 // trn(Matrix) * Matrix 00497 template <class type> 00498 inline 00499 Matrix<type> & _prodt(Matrix<type> const & A, Matrix<type> const & B, Matrix<type> & R) 00500 { 00501 R.Resize(A.Cols(), B.Cols()); 00502 Gemtm(static_cast<type>(1), A, B, static_cast<type>(0), R); 00503 return R; 00504 } 00505 00506 // Matrix * trn(Matrix) 00507 template <class type> 00508 inline 00509 Matrix<type> & _prod_t(Matrix<type> const & A, Matrix<type> const & B, Matrix<type> & R) 00510 { 00511 R.Resize(A.Rows(), B.Rows()); 00512 Gemmt(static_cast<type>(1), A, B, static_cast<type>(0), R); 00513 return R; 00514 } 00515 00516 // Vector * trn(Vector) 00517 template <class type> 00518 inline 00519 Matrix<type> & _prod_t(Vector<type> const & A, Vector<type> const & B, Matrix<type> & R) 00520 { 00521 size_t m = A.Size(); 00522 size_t n = B.Size(); 00523 R.Resize(m, n); 00524 type const * ptrA = A.GetPtr(); 00525 type const * ptrB = B.GetPtr(); 00526 type * ptrR = R.GetPtr(); 00527 for (size_t i=0; i<m; ++i) 00528 for (size_t j=0; j<n; ++j) 00529 ptrR[i+j*m] = ptrA[i]*ptrB[j]; 00530 return R; 00531 } 00532 00533 // trn(Vector) * Vector 00534 template <class type> 00535 inline 00536 type & _prodt(Vector<type> const & A, Vector<type> const & B, type & R) 00537 { 00538 if (A.Size()!=B.Size()) throw new Fatal("Internal Error: laexpr.h::_prodt: A.Size==%d must be equal to B.Size==%d",A.Size(),B.Size()); 00539 R = Dot(A, B); 00540 return R; 00541 } 00542 00543 // trn(Matrix) * trn(Matrix) 00544 template <class type> 00545 inline 00546 Matrix<type> & _prodtt(Matrix<type> const & A, Matrix<type> const & B, Matrix<type> & R) 00547 { 00548 R.Resize(A.Cols(), B.Rows()); 00549 Gemtmt(static_cast<type>(1), A, B, static_cast<type>(0), R); 00550 return R; 00551 } 00552 00553 00554 // Expression classes ////////////////////////////////////////////////////////////////////////////////////////// 00555 00556 00557 // Base expression class 00558 template <class t_exp, class t_res> 00559 class expression 00560 { 00561 public: 00562 operator t_res () const { return static_cast<t_exp const &>(*this).operator t_res(); } 00563 // Functions for external usage 00564 void Apply (t_res & result) const { static_cast<t_exp const &>(*this).Apply (result); } 00565 void Apply_pe(t_res & result) const { static_cast<t_exp const &>(*this).Apply_pe(result); } 00566 void Apply_me(t_res & result) const { static_cast<t_exp const &>(*this).Apply_me(result); } 00567 protected: 00568 expression(){ }; // private constructor to avoid accidental constructions 00569 }; 00570 00571 // Output for expressions 00572 template <class t_exp, class t_res> 00573 std::ostream & operator << (std::ostream & os, expression<t_exp, t_res> const & expr) 00574 { 00575 os << expr.operator t_res(); 00576 return os; 00577 } 00578 00579 // Expression class for unary operators 00580 template <class t_exp1, class t_op, class t_res> 00581 class exp_un:public expression<exp_un<t_exp1, t_op, t_res>, t_res> 00582 { 00583 public: 00584 typedef t_exp1 T_exp1; 00585 typedef t_op T_op; 00586 typedef t_res T_res; 00587 explicit exp_un(t_exp1 const & A):Arg(A){ } // explicit to avoid constructors ambiguity by default conversions 00588 operator t_res () const { t_res result; return t_op::template Apply(Arg, result); } 00589 void Apply(t_res & result) const 00590 { 00591 void const * ptr_arg = static_cast<void const*>(&Arg); 00592 void const * ptr_result = static_cast<void const*>(&result); 00593 if (ptr_arg != ptr_result) t_op::template Apply(Arg, result); 00594 else result = operator t_res(); 00595 } 00596 void Apply_pe(t_res & result) const { result = result + *this; } 00597 void Apply_me(t_res & result) const { result = result - *this; } 00598 t_exp1 const & Arg; 00599 private: 00600 exp_un() { }; // private constructor to avoid accidental constructions 00601 }; 00602 00603 // Expression class for binary operators 00604 template <class t_exp1, class t_exp2, class t_op, class t_res> 00605 class exp_bin:public expression<exp_bin<t_exp1, t_exp2, t_op, t_res>, t_res> 00606 { 00607 public: 00608 typedef t_exp1 T_exp1; 00609 typedef t_exp2 T_exp2; 00610 typedef t_op T_op; 00611 typedef t_res T_res; 00612 exp_bin(t_exp1 const & A, t_exp2 const & B):Arg1(A),Arg2(B){} 00613 operator t_res () const { t_res result; return t_op::template Apply(Arg1, Arg2, result); } 00614 void Apply(t_res & result) const 00615 { 00616 void const * ptr_arg1 = static_cast<void const*>(&Arg1); 00617 void const * ptr_arg2 = static_cast<void const*>(&Arg2); 00618 void const * ptr_result = static_cast<void const*>(&result); 00619 if (ptr_arg1 != ptr_result && ptr_arg2 != ptr_result) 00620 t_op::template Apply(Arg1, Arg2, result); 00621 else 00622 result = operator t_res (); 00623 } 00624 void Apply_pe(t_res & result) const { result = result + *this; } 00625 void Apply_me(t_res & result) const { result = result - *this; } 00626 t_exp1 const & Arg1; 00627 t_exp2 const & Arg2; 00628 private: 00629 exp_bin() { }; 00630 }; 00631 00632 // Expression class for ternary operators 00633 template <class t_exp1, class t_exp2, class t_exp3, class t_op, class t_res> 00634 class exp_ter:public expression<exp_ter<t_exp1, t_exp2, t_exp3, t_op, t_res>, t_res> 00635 { 00636 public: 00637 typedef t_exp1 T_exp1; 00638 typedef t_exp2 T_exp2; 00639 typedef t_exp3 T_exp3; 00640 typedef t_op T_op; 00641 typedef t_res T_res; 00642 exp_ter(t_exp1 const & A, t_exp2 const & B):Arg1(A),Arg2(B) { } 00643 operator t_res () const { t_res result; return t_op::template Apply(Arg1, Arg2, Arg3, result); } 00644 void Apply(t_res & result) const 00645 { 00646 void const * ptr_arg1 = static_cast<void const*>(&Arg1); 00647 void const * ptr_arg2 = static_cast<void const*>(&Arg2); 00648 void const * ptr_arg3 = static_cast<void const*>(&Arg3); 00649 void const * ptr_result = static_cast<void const*>(&result); 00650 if (ptr_arg1 != ptr_result && ptr_arg2 != ptr_result && ptr_arg3 != ptr_result) 00651 t_op::template Apply(Arg1, Arg2, Arg3, result); 00652 else 00653 result = operator t_res (); 00654 } 00655 void Apply_pe(t_res & result) const { result = result + *this; } 00656 void Apply_me(t_res & result) const { result = result - *this; } 00657 t_exp1 const & Arg1; 00658 t_exp2 const & Arg2; 00659 t_exp3 const & Arg3; 00660 private: 00661 exp_ter() { }; 00662 }; 00663 00664 00665 // Identification of expression result type //////////////////////////////////////////////////////////////////// 00666 00667 00668 // for simple objects 00669 template<class t_exp, class t_exp_again = t_exp> 00670 struct res_type 00671 { 00672 typedef t_exp T_res; 00673 }; 00674 00675 // for unary expressions 00676 template<class t_exp> 00677 struct res_type<t_exp, exp_un< typename t_exp::T_exp1, typename t_exp::T_op, typename t_exp::T_res> > 00678 { 00679 typedef typename t_exp::T_res T_res; 00680 }; 00681 00682 // for binary expressions 00683 template<class t_exp> 00684 struct res_type<t_exp, exp_bin< typename t_exp::T_exp1, typename t_exp::T_exp2, typename t_exp::T_op, typename t_exp::T_res> > 00685 { 00686 typedef typename t_exp::T_res T_res; 00687 }; 00688 00689 00690 // Operator classes //////////////////////////////////////////////////////////////////////////////////////////// 00691 00692 00693 // class operator for addition 00694 class op_add 00695 { 00696 public: 00697 template <class t_exp1, class t_exp2, class t_res> 00698 static t_res & Apply(t_exp1 const & A, t_exp2 const & B, t_res & R) 00699 { 00700 typedef typename res_type<t_exp1>::T_res t_res1; 00701 typedef typename res_type<t_exp2>::T_res t_res2; 00702 return _add( static_cast<t_res1 const &>(A), static_cast<t_res2 const &>(B), R); 00703 } 00704 }; 00705 00706 // class operator for subtraction 00707 class op_minus 00708 { 00709 public: 00710 template <class t_exp1, class t_exp2, class t_res> 00711 static t_res & Apply(t_exp1 const & A, t_exp2 const & B, t_res & R) 00712 { 00713 typedef typename res_type<t_exp1>::T_res t_res1; 00714 typedef typename res_type<t_exp2>::T_res t_res2; 00715 return _minus(static_cast<t_res1 const &>(A), static_cast<t_res2 const &>(B), R); 00716 } 00717 }; 00718 00719 // class operator for unary minus 00720 class op_minus_un 00721 { 00722 public: 00723 template <class t_exp1, class t_res> 00724 static t_res & Apply(t_exp1 const & A, t_res & R) 00725 { 00726 return _prod(-1.0, static_cast<t_res const &>(A), R); 00727 } 00728 }; 00729 00730 // class operator for multiplication 00731 class op_prod 00732 { 00733 public: 00734 template <class t_exp1, class t_exp2, class t_res> 00735 static t_res & Apply(t_exp1 const & A, t_exp2 const & B, t_res & R) 00736 { 00737 typedef typename res_type<t_exp1>::T_res t_res1; 00738 typedef typename res_type<t_exp2>::T_res t_res2; 00739 return _prod( static_cast<t_res1 const &>(A), static_cast<t_res2 const &>(B), R); 00740 } 00741 }; 00742 00743 class op_div_sc; //prototype for class operator that performs division by scalar 00744 00745 // class operator for multiplication by scalar 00746 class op_prod_sc 00747 { 00748 public: 00749 template <class t_sc, class t_exp, class t_res> 00750 static t_res & Apply(t_sc const & A, t_exp const & B, t_res & R) 00751 { 00752 return _prod(A, static_cast<t_res const &>(B), R); 00753 } 00754 00755 // Overloading of apply functions to perform fast multiplication by multiple scalars: 00756 00757 // scalar * exp_bin<op_prod_sc> 00758 template <class t_sc1, class t_sc2, class t_exp, class t_res> 00759 static t_res & Apply(t_sc1 const & A, exp_bin<t_sc2, t_exp, op_prod_sc, t_res > const & B, t_res & R) 00760 { 00761 return _prod(A*B.Arg1, static_cast<t_res const &>(B.Arg2), R); 00762 } 00763 00764 // scalar * exp_bin<op_div_sc> 00765 template <class t_sc1, class t_sc2, class t_exp, class t_res> 00766 static t_res & Apply(t_sc1 const & A, exp_bin<t_sc2, t_exp, op_div_sc, t_res > const & B, t_res & R) 00767 { 00768 return _prod(A/B.Arg1, static_cast<t_res const &>(B.Arg2), R); 00769 } 00770 }; 00771 00772 // class operator for division by scalar 00773 class op_div_sc 00774 { 00775 public: 00776 template <class t_sc, class t_exp, class t_res> 00777 static t_res & Apply(t_sc const & A, t_exp const & B, t_res & R) 00778 { 00779 return _prod(1.0/A, static_cast<t_res const &>(B), R); 00780 } 00781 00782 // Overloading of apply functions to perform fast multiplication by multiple scalars: 00783 00784 // exp_bin<op_prod_sc> / scalar 00785 template <class t_sc1, class t_sc2, class t_exp, class t_res> 00786 static t_res & Apply(t_sc1 const & A, exp_bin<t_sc2, t_exp, op_prod_sc, t_res > const & B, t_res & R) 00787 { 00788 return _prod(B.Arg1/A, static_cast<t_res const &>(B.Arg2), R); 00789 } 00790 00791 // exp_bin<op_div_sc> / scalar 00792 template <class t_sc1, class t_sc2, class t_exp, class t_res> 00793 static t_res & Apply(t_sc1 const & A, exp_bin<t_sc2, t_exp, op_div_sc, t_res > const & B, t_res & R) 00794 { 00795 return _prod(1.0/(A*B.Arg1), static_cast<t_res const &>(B.Arg2), R); 00796 } 00797 }; 00798 00799 // class operator for transposition 00800 class op_trn 00801 { 00802 public: 00803 template <class t_exp1, class t_res> 00804 static t_res & Apply(t_exp1 const & A, t_res & R) 00805 { 00806 typedef typename res_type<t_exp1>::T_res t_res1; 00807 return _trn(static_cast<t_res1 const &>(A), R); 00808 } 00809 }; 00810 00811 class op_oto // object transposed by object 00812 { 00813 public: 00814 template <class t_exp1, class t_exp2, class t_res> 00815 static t_res & Apply(t_exp1 const & A, t_exp2 const & B, t_res & R) 00816 { 00817 typedef typename res_type<t_exp1>::T_res t_res1; 00818 typedef typename res_type<t_exp2>::T_res t_res2; 00819 _prodt(A, B, R); 00820 return R; 00821 } 00822 }; 00823 00824 class op_oot // object by object transposed 00825 { 00826 public: 00827 template <class t_exp1, class t_exp2, class t_res> 00828 static t_res & Apply(t_exp1 const & A, t_exp2 const & B, t_res & R) 00829 { 00830 typedef typename res_type<t_exp1>::T_res t_res1; 00831 typedef typename res_type<t_exp2>::T_res t_res2; 00832 _prod_t(A, B, R); 00833 return R; 00834 } 00835 }; 00836 00837 class op_otot // object transposed by object transposed 00838 { 00839 public: 00840 template <class t_exp1, class t_exp2, class t_res> 00841 static t_res & Apply(t_exp1 const & A, t_exp2 const & B, t_res & R) 00842 { 00843 typedef typename res_type<t_exp1>::T_res t_res1; 00844 typedef typename res_type<t_exp2>::T_res t_res2; 00845 _prodtt(A, B, R); 00846 return R; 00847 } 00848 }; 00849 00850 00851 // Expression & object operations ////////////////////////////////////////////////////////////////////////////// 00852 00853 00854 // macro for scalar operations 00855 #define DECLARE_OP_WITH_SCALAR(MACRO) \ 00856 MACRO(short); \ 00857 MACRO(int); \ 00858 MACRO(long int); \ 00859 MACRO(size_t); \ 00860 MACRO(float); \ 00861 MACRO(double); \ 00862 MACRO(long double); 00863 00864 // - expression (unary) 00865 template <class t_exp, class t_res> 00866 inline 00867 exp_un< t_exp, op_minus_un, t_res > 00868 operator-(expression<t_exp, t_res> const & A) 00869 { 00870 return exp_un< t_exp, op_minus_un, t_res >(static_cast<t_exp const &>(A)); 00871 } 00872 00873 // + expression (unary) 00874 template <class t_exp, class t_res> 00875 inline 00876 expression<t_exp, t_res> 00877 operator+(expression<t_exp, t_res> const & A) 00878 { 00879 return A; 00880 } 00881 00882 // expression + obj 00883 template <class t_obj, class t_exp1> 00884 inline 00885 exp_bin< t_exp1, t_obj, op_add, t_obj > 00886 operator+(expression<t_exp1, t_obj> const & A, t_obj const & B) 00887 { 00888 return exp_bin< t_exp1 , t_obj, op_add, t_obj >(static_cast<t_exp1 const &>(A),B); 00889 } 00890 00891 // obj + expression 00892 template <class t_obj, class t_exp1 > 00893 inline 00894 exp_bin< t_obj, t_exp1, op_add, t_obj > 00895 operator+(t_obj const & A, expression<t_exp1,t_obj> const & B) 00896 { 00897 return exp_bin<t_obj, t_exp1, op_add, t_obj >(A,static_cast<t_exp1 const &>(B)); 00898 } 00899 00900 // exp + exp 00901 template <class t_obj, class t_exp1, class t_exp2> 00902 inline 00903 exp_bin< t_exp1, t_exp2, op_add, t_obj > 00904 operator+(expression<t_exp1, t_obj > const & A, expression<t_exp2, t_obj > const & B) 00905 { 00906 return exp_bin<t_exp1 ,t_exp2, op_add, t_obj >(static_cast<t_exp1 const &>(A), static_cast<t_exp2 const &>(B)); 00907 } 00908 00909 // exp - exp 00910 template <class t_obj, class t_exp1, class t_exp2> 00911 inline 00912 exp_bin< t_exp1, t_exp2, op_minus, t_obj > 00913 operator-(expression<t_exp1, t_obj > const & A, expression<t_exp2, t_obj > const & B) 00914 { 00915 return exp_bin<t_exp1 ,t_exp2, op_minus, t_obj >(static_cast<t_exp1 const &>(A), static_cast<t_exp2 const &>(B)); 00916 } 00917 00918 // expression - obj 00919 template <class t_obj, class t_exp1> 00920 inline 00921 exp_bin< t_exp1, t_obj, op_minus, t_obj > 00922 operator-(expression<t_exp1, t_obj> const & A, t_obj const & B) 00923 { 00924 return exp_bin< t_exp1 , t_obj, op_minus, t_obj >(static_cast<t_exp1 const &>(A),B); 00925 } 00926 00927 // obj - expression 00928 template <class t_obj, class t_exp1 > 00929 inline 00930 exp_bin< t_obj, t_exp1, op_minus, t_obj > 00931 operator-(t_obj const & A, expression<t_exp1,t_obj> const & B) 00932 { 00933 return exp_bin<t_obj, t_exp1, op_minus, t_obj >(A,static_cast<t_exp1 const &>(B)); 00934 } 00935 00936 // scalar * expression && expression * scalar 00937 #define EXPR_MULT_SCALAR(T) \ 00938 template <class t_obj, class t_exp1> \ 00939 inline exp_bin<T, t_exp1, op_prod_sc, t_obj > \ 00940 operator*(T const & A, expression<t_exp1, t_obj > const & B) \ 00941 { \ 00942 return exp_bin<T, t_exp1, op_prod_sc, t_obj >(A, static_cast<t_exp1 const &>(B)); \ 00943 } \ 00944 template <class t_obj, class t_exp1> \ 00945 inline exp_bin<T, t_exp1, op_prod_sc, t_obj > \ 00946 operator*(expression<t_exp1, t_obj > const & A, T const & B) \ 00947 { \ 00948 return exp_bin<T, t_exp1, op_prod_sc, t_obj >(B, static_cast<t_exp1 const &>(A)); \ 00949 } 00950 00951 DECLARE_OP_WITH_SCALAR(EXPR_MULT_SCALAR); 00952 00953 // expression * scalar 00954 #define EXPR_DIV_SCALAR(T) \ 00955 template <class t_obj, class t_exp1> \ 00956 inline exp_bin<T, t_exp1, op_div_sc, t_obj > \ 00957 operator/(expression<t_exp1, t_obj > const & A, T const & B) \ 00958 { \ 00959 return exp_bin<T, t_exp1, op_div_sc, t_obj >(B, static_cast<t_exp1 const &>(A)); \ 00960 } 00961 00962 DECLARE_OP_WITH_SCALAR(EXPR_DIV_SCALAR); 00963 00964 00965 // Vector operations /////////////////////////////////////////////////////////////////////////////////////////// 00966 00967 00968 // - Vector 00969 template <class type> 00970 inline 00971 exp_un< Vector<type>, op_minus_un, Vector<type> > 00972 operator-(Vector<type> const & A) 00973 { 00974 return exp_un< Vector<type>, op_minus_un, Vector<type> > (A); 00975 } 00976 00977 // + Vector 00978 template <class type> 00979 inline 00980 Vector<type> 00981 operator+(Vector<type> const & A) 00982 { 00983 return A; 00984 } 00985 00986 // Vector + Vector 00987 template <typename type> 00988 inline 00989 exp_bin<Vector<type>, Vector<type>, op_add, Vector<type> > 00990 operator + (Vector<type> const & A, Vector<type> const & B) 00991 { 00992 return exp_bin<Vector<type>, Vector<type>, op_add, Vector<type> >(A,B); 00993 } 00994 00995 // Vector - Vector 00996 template <typename type> 00997 inline 00998 exp_bin<Vector<type>, Vector<type>, op_minus, Vector<type> > 00999 operator - (Vector<type> const & A, Vector<type> const & B) 01000 { 01001 return exp_bin<Vector<type>, Vector<type>, op_minus, Vector<type> >(A,B); 01002 } 01003 01004 // trn(Vector) 01005 template <typename type> 01006 inline 01007 exp_un<Vector<type>, op_trn, Matrix<type> > 01008 trn (Vector<type> const & A) 01009 { 01010 return exp_un<Vector<type>, op_trn, Matrix<type> >(A); 01011 } 01012 01013 // trn(exp) 01014 template <class type, class t_exp1> 01015 inline 01016 exp_un< t_exp1, op_trn, Matrix<type> > 01017 trn (expression<t_exp1, Vector<type> > const & A) 01018 { 01019 return exp_un<t_exp1, op_trn, Matrix<type> >(static_cast<t_exp1 const &>(A)); 01020 } 01021 01022 // scalar * Vector && Vector * scalar 01023 #define VECTOR_MULT_SCALAR(T) \ 01024 template <class type> \ 01025 inline \ 01026 exp_bin< T, Vector<type>, op_prod_sc, Vector<type> > \ 01027 operator * ( T const & A, Vector<type> const & B) \ 01028 { \ 01029 return exp_bin< T, Vector<type>, op_prod_sc, Vector<type> >(A,B); \ 01030 } \ 01031 template <class type> \ 01032 inline \ 01033 exp_bin<T, Vector<type>, op_prod_sc, Vector<type> > \ 01034 operator * (Vector<type> const & A, T const & B) \ 01035 { \ 01036 return exp_bin<T, Vector<type>, op_prod_sc, Vector<type> >(B,A); \ 01037 } 01038 01039 DECLARE_OP_WITH_SCALAR(VECTOR_MULT_SCALAR); 01040 01041 // Vector / scalar 01042 #define VECTOR_DIV_SCALAR(T) \ 01043 template <class type> \ 01044 inline \ 01045 exp_bin<T, Vector<type>, op_div_sc, Vector<type> > \ 01046 operator / (Vector<type> const & A, T const & B) \ 01047 { \ 01048 return exp_bin<T, Vector<type>, op_div_sc, Vector<type> >(B,A); \ 01049 } 01050 01051 DECLARE_OP_WITH_SCALAR(VECTOR_DIV_SCALAR); 01052 01053 01054 // Matrix operations /////////////////////////////////////////////////////////////////////////////////////////// 01055 01056 01057 // - Matrix 01058 template <class type> 01059 inline 01060 exp_un< Matrix<type>, op_minus_un, Matrix<type> > 01061 operator-(Matrix<type> const & A) 01062 { 01063 return exp_un< Matrix<type>, op_minus_un, Matrix<type> > (A); 01064 } 01065 01066 // + Matrix 01067 template <class type> 01068 inline 01069 Matrix<type> 01070 operator+(Matrix<type> const & A) 01071 { 01072 return A; 01073 } 01074 01075 // Matrix + Matrix 01076 template <typename type> 01077 inline 01078 exp_bin<Matrix<type>, Matrix<type>, op_add, Matrix<type> > 01079 operator + (Matrix<type> const & A, Matrix<type> const & B) 01080 { 01081 return exp_bin<Matrix<type>, Matrix<type>, op_add, Matrix<type> >(A,B); 01082 } 01083 01084 // Matrix - Matrix 01085 template <typename type> 01086 inline 01087 exp_bin<Matrix<type>, Matrix<type>, op_minus, Matrix<type> > 01088 operator - (Matrix<type> const & A, Matrix<type> const & B) 01089 { 01090 return exp_bin<Matrix<type>, Matrix<type>, op_minus, Matrix<type> >(A,B); 01091 } 01092 01093 // Matrix * Matrix 01094 template <typename type> 01095 inline 01096 exp_bin<Matrix<type>, Matrix<type>, op_prod, Matrix<type> > 01097 operator * (Matrix<type> const & A, Matrix<type> const & B) 01098 { 01099 return exp_bin<Matrix<type>, Matrix<type>, op_prod, Matrix<type> >(A,B); 01100 } 01101 01102 // trn(Matrix) 01103 template <typename type> 01104 inline 01105 exp_un<Matrix<type>, op_trn, Matrix<type> > 01106 trn (Matrix<type> const & A) 01107 { 01108 return exp_un<Matrix<type>, op_trn, Matrix<type> >(A); 01109 } 01110 01111 // trn(exp) 01112 template <class type, class t_exp1> 01113 inline 01114 exp_un< t_exp1, op_trn, Matrix<type> > 01115 trn (expression<t_exp1, Matrix<type> > const & A) 01116 { 01117 return exp_un<t_exp1, op_trn, Matrix<type> >(static_cast<t_exp1 const &>(A)); 01118 } 01119 01120 // trans(Matrix) 01121 template <typename type> 01122 inline 01123 exp_un<Matrix<type>, op_trn, Matrix<type> > 01124 trans (Matrix<type> const & A) 01125 { 01126 return exp_un<Matrix<type>, op_trn, Matrix<type> >(A); 01127 } 01128 01129 // trans(exp) 01130 template <class type, class t_exp1> 01131 inline 01132 exp_un< t_exp1, op_trn, Matrix<type> > 01133 trans (expression<t_exp1, Matrix<type> > const & A) 01134 { 01135 return exp_un<t_exp1, op_trn, Matrix<type> >(static_cast<t_exp1 const &>(A)); 01136 } 01137 01138 // scalar * Matrix && Matrix * scalar 01139 #define MATRIX_MULT_SCALAR(T) \ 01140 template <class type> \ 01141 inline exp_bin< T ,Matrix <type>, op_prod_sc,Matrix <type> > \ 01142 operator * (T const & A, Matrix <type> const & B) \ 01143 { \ 01144 return exp_bin< T,Matrix <type>, op_prod_sc,Matrix <type> >(A,B); \ 01145 } \ 01146 template <class type> \ 01147 inline exp_bin<T, Matrix <type>, op_prod_sc,Matrix <type> > \ 01148 operator * (Matrix <type> const & A, T const & B) \ 01149 { \ 01150 return exp_bin<T, Matrix <type>, op_prod_sc,Matrix <type> >(B,A); \ 01151 } 01152 01153 DECLARE_OP_WITH_SCALAR(MATRIX_MULT_SCALAR); 01154 01155 // Matrix / scalar 01156 #define MATRIX_DIV_SCALAR(T) \ 01157 template <class type> \ 01158 inline exp_bin<T, Matrix <type>, op_div_sc,Matrix <type> > \ 01159 operator / (Matrix <type> const & A, T const & B) \ 01160 { \ 01161 return exp_bin<T, Matrix <type>, op_div_sc,Matrix <type> >(B,A); \ 01162 } 01163 01164 DECLARE_OP_WITH_SCALAR(MATRIX_DIV_SCALAR); 01165 01166 01167 // Matrix & Vector operations ////////////////////////////////////////////////////////////////////////////////// 01168 01169 01170 // Vector * Matrix 01171 template <class type> 01172 inline 01173 exp_bin<Vector<type>, Matrix<type>, op_prod, Matrix<type> > 01174 operator * (Vector<type> const & A, Matrix<type> const & B) 01175 { 01176 return exp_bin<Vector<type>, Matrix<type>, op_prod, Matrix<type> >(A,B); 01177 } 01178 01179 // Matrix * Vector 01180 template <typename type> 01181 inline 01182 exp_bin<Matrix<type>, Vector<type>, op_prod, Vector<type> > 01183 operator * (Matrix<type> const & A, Vector<type> const & B) 01184 { 01185 return exp_bin<Matrix<type>, Vector<type>, op_prod, Vector<type> >(A,B); 01186 } 01187 01188 // expression * Vector 01189 template <class type, class t_exp1> 01190 inline 01191 exp_bin< t_exp1, Vector<type>, op_prod, Vector<type> > 01192 operator*(expression<t_exp1, Matrix<type> > const & A, Vector<type> const & B) 01193 { 01194 return exp_bin< t_exp1 , Vector<type>, op_prod, Vector<type> >(static_cast<t_exp1 const &>(A),B); 01195 } 01196 01197 // expression * Matrix 01198 template <class type, class t_exp1> 01199 inline 01200 exp_bin< t_exp1, Matrix<type>, op_prod, Matrix<type> > 01201 operator*(expression<t_exp1, Matrix<type> > const & A, Matrix<type> const & B) 01202 { 01203 return exp_bin< t_exp1, Matrix<type>, op_prod, Matrix<type> >(static_cast<t_exp1 const &>(A),B); 01204 } 01205 01206 // Matrix * expression 01207 template <class type, class t_exp1> 01208 inline 01209 exp_bin<Matrix<type>, t_exp1, op_prod, Matrix<type> > 01210 operator*(Matrix<type> const & A, expression<t_exp1, Matrix<type> > const & B) 01211 { 01212 return exp_bin< Matrix<type>, t_exp1, op_prod, Matrix<type> >(A,static_cast<t_exp1 const &>(B)); 01213 } 01214 01215 // expression * expression (1) 01216 template <class type, class t_exp1, class t_exp2> 01217 inline 01218 exp_bin< t_exp1, t_exp2, op_prod, Matrix<type> > 01219 operator*(expression<t_exp1, Matrix<type> > const & A, expression<t_exp2, Matrix<type> > const & B) 01220 { 01221 return exp_bin< t_exp1, t_exp2, op_prod, Matrix<type> >(static_cast<t_exp1 const &>(A),static_cast<t_exp2 const &>(B)); 01222 } 01223 01224 // expression * expression (2) 01225 template <class type, class t_exp1, class t_exp2> 01226 inline 01227 exp_bin< t_exp1, t_exp2, op_prod, Vector<type> > 01228 operator*(expression<t_exp1, Matrix<type> > const & A, expression<t_exp2, Vector<type> > const & B) 01229 { 01230 return exp_bin< t_exp1, t_exp2, op_prod, Vector<type> >(static_cast<t_exp1 const &>(A),static_cast<t_exp2 const &>(B)); 01231 } 01232 01233 // expression * expression (3) 01234 template <class type, class t_exp1, class t_exp2> 01235 inline 01236 exp_bin< t_exp1, t_exp2, op_prod, Matrix<type> > 01237 operator*(expression<t_exp1, Vector<type> > const & A, expression<t_exp2, Matrix<type> > const & B) 01238 { 01239 return exp_bin< t_exp1, t_exp2, op_prod, Matrix<type> >(static_cast<t_exp1 const &>(A),static_cast<t_exp2 const &>(B)); 01240 } 01241 01242 01243 // Matrix, Vector combinations with transposition ////////////////////////////////////////////////////////////// 01244 01245 01246 // trn(Vector) * Vector 01247 template <class type> 01248 inline 01249 exp_bin<Vector<type>, Vector<type>, op_oto, type > 01250 operator * (exp_un< Vector<type>, op_trn, Matrix<type> > const & A, Vector<type> const & B) 01251 { 01252 return exp_bin<Vector<type>, Vector<type>, op_oto, type >(A.Arg, B); 01253 } 01254 01255 // Vector * trn(Vector) 01256 template <class type> 01257 inline 01258 exp_bin<Vector<type>,Vector<type>, op_oot, Matrix<type> > 01259 operator * (Vector<type> const & A, exp_un< Vector<type>, op_trn, Matrix<type> > const & B) 01260 { 01261 return exp_bin<Vector<type>,Vector<type>, op_oot, Matrix<type> >(A, B.Arg); 01262 } 01263 01264 // trn(Matrix) * Matrix 01265 template <class type> 01266 inline 01267 exp_bin<Matrix<type>, Matrix<type>, op_oto, Matrix<type> > 01268 operator * (exp_un<Matrix<type>, op_trn, Matrix<type> > const & A, Matrix<type> const & B) 01269 { 01270 return exp_bin<Matrix<type>, Matrix<type>, op_oto, Matrix<type> >(A.Arg, B); 01271 } 01272 01273 // Matrix * trn(Matrix) 01274 template <class type> 01275 inline 01276 exp_bin<Matrix<type>, Matrix<type>, op_oot, Matrix<type> > 01277 operator * (Matrix<type> const & A, exp_un<Matrix<type>, op_trn, Matrix<type> > const & B) 01278 { 01279 return exp_bin<Matrix<type>, Matrix<type>, op_oot, Matrix<type> >(A, B.Arg); 01280 } 01281 01282 // trn(Matrix) * trn(Matrix) 01283 template <class type> 01284 inline 01285 exp_bin<Matrix<type>, Matrix<type>, op_otot, Matrix<type> > 01286 operator * (exp_un<Matrix<type>, op_trn, Matrix<type> > const & A, exp_un<Matrix<type>, op_trn, Matrix<type> > const & B) 01287 { 01288 return exp_bin<Matrix<type>, Matrix<type>, op_otot, Matrix<type> >(A.Arg, B.Arg); 01289 } 01290 01291 }; // namespace LinAlg 01292 01293 #endif // MECHSYS_LINALG_LAEXPR_H