laexpr.h

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

Generated on Wed Jan 24 15:56:26 2007 for MechSys by  doxygen 1.4.7