MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/linalg/laexpr.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines