// @(#)root/smatrix:$Name: $:$Id: MatrixFunctions.h,v 1.5 2006/02/27 18:41:58 moneta Exp $ // Authors: T. Glebe, L. Moneta 2005 #ifndef ROOT_Math_MatrixFunctions #define ROOT_Math_MatrixFunctions // ******************************************************************** // // source: // // type: source code // // created: 20. Mar 2001 // // author: Thorsten Glebe // HERA-B Collaboration // Max-Planck-Institut fuer Kernphysik // Saupfercheckweg 1 // 69117 Heidelberg // Germany // E-mail: T.Glebe@mpi-hd.mpg.de // // Description: Functions/Operators special to Matrix // // changes: // 20 Mar 2001 (TG) creation // 20 Mar 2001 (TG) Added Matrix * Vector multiplication // 21 Mar 2001 (TG) Added transpose, product // 11 Apr 2001 (TG) transpose() speed improvment by removing rows(), cols() // through static members of Matrix and Expr class // // ******************************************************************** #include "Math/BinaryOpPolicy.h" namespace ROOT { namespace Math { #ifdef XXX //============================================================================== // SMatrix * SVector //============================================================================== template SVector operator*(const SMatrix& rhs, const SVector& lhs) { SVector tmp; for(unsigned int i=0; i struct meta_row_dot { template static inline typename A::value_type f(const A& lhs, const B& rhs, const unsigned int offset) { return lhs.apply(offset+I) * rhs.apply(I) + meta_row_dot::f(lhs,rhs,offset); } }; //============================================================================== // meta_row_dot<0> //============================================================================== template <> struct meta_row_dot<0> { template static inline typename A::value_type f(const A& lhs, const B& rhs, const unsigned int offset) { return lhs.apply(offset) * rhs.apply(0); } }; //============================================================================== // VectorMatrixRowOp //============================================================================== template class VectorMatrixRowOp { public: /// VectorMatrixRowOp(const Matrix& lhs, const Vector& rhs) : lhs_(lhs), rhs_(rhs) {} /// ~VectorMatrixRowOp() {} /// calc $\sum_{j} a_{ij} * v_j$ inline typename Matrix::value_type apply(unsigned int i) const { return meta_row_dot::f(lhs_, rhs_, i*D2); } protected: const Matrix& lhs_; const Vector& rhs_; }; //============================================================================== // meta_col_dot //============================================================================== template struct meta_col_dot { template static inline typename Matrix::value_type f(const Matrix& lhs, const Vector& rhs, const unsigned int offset) { return lhs.apply(Matrix::kCols*I+offset) * rhs.apply(I) + meta_col_dot::f(lhs,rhs,offset); } }; //============================================================================== // meta_col_dot<0> //============================================================================== template <> struct meta_col_dot<0> { template static inline typename Matrix::value_type f(const Matrix& lhs, const Vector& rhs, const unsigned int offset) { return lhs.apply(offset) * rhs.apply(0); } }; //============================================================================== // VectorMatrixColOp //============================================================================== template class VectorMatrixColOp { public: /// VectorMatrixColOp(const Vector& lhs, const Matrix& rhs) : lhs_(lhs), rhs_(rhs) {} /// ~VectorMatrixColOp() {} /// calc $\sum_{j} a_{ij} * v_j$ inline typename Matrix::value_type apply(unsigned int i) const { return meta_col_dot::f(rhs_, lhs_, i); } protected: const Vector& lhs_; const Matrix& rhs_; }; //============================================================================== // operator*: SMatrix * SVector //============================================================================== template inline VecExpr,SVector, D2>, T, D1> operator*(const SMatrix& lhs, const SVector& rhs) { typedef VectorMatrixRowOp,SVector, D2> VMOp; return VecExpr(VMOp(lhs,rhs)); } //============================================================================== // operator*: SMatrix * Expr //============================================================================== template inline VecExpr, VecExpr, D2>, T, D1> operator*(const SMatrix& lhs, const VecExpr& rhs) { typedef VectorMatrixRowOp,VecExpr, D2> VMOp; return VecExpr(VMOp(lhs,rhs)); } //============================================================================== // operator*: Expr * SVector //============================================================================== template inline VecExpr, SVector, D2>, T, D1> operator*(const Expr& lhs, const SVector& rhs) { typedef VectorMatrixRowOp,SVector, D2> VMOp; return VecExpr(VMOp(lhs,rhs)); } //============================================================================== // operator*: Expr * VecExpr //============================================================================== template inline VecExpr, VecExpr, D2>, T, D1> operator*(const Expr& lhs, const VecExpr& rhs) { typedef VectorMatrixRowOp,VecExpr, D2> VMOp; return VecExpr(VMOp(lhs,rhs)); } //============================================================================== // operator*: SVector * SMatrix //============================================================================== template inline VecExpr, SMatrix, D1>, T, D2> operator*(const SVector& lhs, const SMatrix& rhs) { typedef VectorMatrixColOp, SMatrix, D1> VMOp; return VecExpr(VMOp(lhs,rhs)); } //============================================================================== // operator*: SVector * Expr //============================================================================== template inline VecExpr, Expr, D1>, T, D2> operator*(const SVector& lhs, const Expr& rhs) { typedef VectorMatrixColOp, Expr, D1> VMOp; return VecExpr(VMOp(lhs,rhs)); } //============================================================================== // operator*: VecExpr * SMatrix //============================================================================== template inline VecExpr, SMatrix, D1>, T, D2> operator*(const VecExpr& lhs, const SMatrix& rhs) { typedef VectorMatrixColOp, SMatrix, D1> VMOp; return VecExpr(VMOp(lhs,rhs)); } //============================================================================== // operator*: VecExpr * Expr //============================================================================== template inline VecExpr, Expr, D1>, T, D2> operator*(const VecExpr& lhs, const Expr& rhs) { typedef VectorMatrixColOp, Expr, D1> VMOp; return VecExpr(VMOp(lhs,rhs)); } //============================================================================== // meta_matrix_dot //============================================================================== template struct meta_matrix_dot { template static inline typename MatrixA::value_type f(const MatrixA& lhs, const MatrixB& rhs, const unsigned int offset) { return lhs.apply(offset/MatrixB::kCols*MatrixA::kCols + I) * rhs.apply(MatrixB::kCols*I + offset%MatrixB::kCols) + meta_matrix_dot::f(lhs,rhs,offset); } }; //============================================================================== // meta_matrix_dot<0> //============================================================================== template <> struct meta_matrix_dot<0> { template static inline typename MatrixA::value_type f(const MatrixA& lhs, const MatrixB& rhs, const unsigned int offset) { return lhs.apply(offset/MatrixB::kCols*MatrixA::kCols) * rhs.apply(offset%MatrixB::kCols); } }; //============================================================================== // MatrixMulOp //============================================================================== template class MatrixMulOp { public: /// MatrixMulOp(const MatrixA& lhs, const MatrixB& rhs) : lhs_(lhs), rhs_(rhs) {} /// ~MatrixMulOp() {} /// calc $\sum_{j} a_{ik} * b_{kj}$ inline T apply(unsigned int i) const { return meta_matrix_dot::f(lhs_, rhs_, i); } protected: const MatrixA& lhs_; const MatrixB& rhs_; }; //============================================================================== // operator* (SMatrix * SMatrix, binary) //============================================================================== template < class T, unsigned int D1, unsigned int D, unsigned int D2, class R1, class R2> inline Expr, SMatrix,T,D>, T, D1, D2, typename MultPolicy::RepType> operator*(const SMatrix& lhs, const SMatrix& rhs) { typedef MatrixMulOp, SMatrix, T,D> MatMulOp; return Expr::RepType>(MatMulOp(lhs,rhs)); } //============================================================================== // operator* (SMatrix * Expr, binary) //============================================================================== template inline Expr, Expr,T,D>, T, D1, D2, typename MultPolicy::RepType> operator*(const SMatrix& lhs, const Expr& rhs) { typedef MatrixMulOp, Expr,T,D> MatMulOp; return Expr::RepType>(MatMulOp(lhs,rhs)); } //============================================================================== // operator* (Expr * SMatrix, binary) //============================================================================== template inline Expr, SMatrix,T,D>, T, D1, D2, typename MultPolicy::RepType> operator*(const Expr& lhs, const SMatrix& rhs) { typedef MatrixMulOp, SMatrix,T,D> MatMulOp; return Expr::RepType>(MatMulOp(lhs,rhs)); } //============================================================================== // operator* (Expr * Expr, binary) //============================================================================== template inline Expr, Expr,T,D>, T, D1, D2, typename MultPolicy::RepType> operator*(const Expr& lhs, const Expr& rhs) { typedef MatrixMulOp, Expr, T,D> MatMulOp; return Expr::RepType>(MatMulOp(lhs,rhs)); } #ifdef XXX //============================================================================== // MatrixMulOp //============================================================================== template class MatrixMulOp { public: /// MatrixMulOp(const MatrixA& lhs, const MatrixB& rhs) : lhs_(lhs), rhs_(rhs) {} /// ~MatrixMulOp() {} /// calc $\sum_{j} a_{ik} * b_{kj}$ inline typename MatrixA::value_type apply(unsigned int i) const { return meta_matrix_dot::f(lhs_, rhs_, i); } protected: const MatrixA& lhs_; const MatrixB& rhs_; }; //============================================================================== // operator* (SMatrix * SMatrix, binary) //============================================================================== template < class T, unsigned int D1, unsigned int D, unsigned int D2, class R1, class R2> inline Expr, SMatrix, D>, T, D1, D2, typename MultPolicy::RepType> operator*(const SMatrix& lhs, const SMatrix& rhs) { typedef MatrixMulOp, SMatrix, D> MatMulOp; return Expr::RepType>(MatMulOp(lhs,rhs)); } //============================================================================== // operator* (SMatrix * Expr, binary) //============================================================================== template inline Expr, Expr, D>, T, D1, D2, typename MultPolicy::RepType> operator*(const SMatrix& lhs, const Expr& rhs) { typedef MatrixMulOp, Expr, D> MatMulOp; return Expr::RepType>(MatMulOp(lhs,rhs)); } //============================================================================== // operator* (Expr * SMatrix, binary) //============================================================================== template inline Expr, SMatrix, D>, T, D1, D2, typename MultPolicy::RepType> operator*(const Expr& lhs, const SMatrix& rhs) { typedef MatrixMulOp, SMatrix, D> MatMulOp; return Expr::RepType>(MatMulOp(lhs,rhs)); } //============================================================================= // operator* (Expr * Expr, binary) //============================================================================= template inline Expr, Expr, D>, T, D1, D2, typename MultPolicy::RepType> operator*(const Expr& lhs, const Expr& rhs) { typedef MatrixMulOp, Expr, D> MatMulOp; return Expr::RepType>(MatMulOp(lhs,rhs)); } #endif //============================================================================== // TransposeOp //============================================================================== template class TransposeOp { public: /// TransposeOp( const Matrix& rhs) : rhs_(rhs) {} /// ~TransposeOp() {} /// inline T apply(unsigned int i) const { return rhs_.apply( (i%D1)*D2 + i/D1); } protected: const Matrix& rhs_; }; //============================================================================== // transpose //============================================================================== template inline Expr,T,D1,D2>, T, D2, D1, R> Transpose(const SMatrix& rhs) { typedef TransposeOp,T,D1,D2> MatTrOp; return Expr(MatTrOp(rhs)); } //============================================================================== // transpose //============================================================================== template inline Expr,T,D1,D2>, T, D2, D1,R> Transpose(const Expr& rhs) { typedef TransposeOp,T,D1,D2> MatTrOp; return Expr(MatTrOp(rhs)); } #ifdef OLD //============================================================================== // product: SMatrix/SVector calculate v^T * A * v //============================================================================== template inline T Product(const SMatrix& lhs, const SVector& rhs) { return Dot(rhs, lhs * rhs); } //============================================================================== // product: SVector/SMatrix calculate v^T * A * v //============================================================================== template inline T Product(const SVector& lhs, const SMatrix& rhs) { return Dot(lhs, rhs * lhs); } //============================================================================== // product: SMatrix/Expr calculate v^T * A * v //============================================================================== template inline T Product(const SMatrix& lhs, const VecExpr& rhs) { return Dot(rhs, lhs * rhs); } //============================================================================== // product: Expr/SMatrix calculate v^T * A * v //============================================================================== template inline T Product(const VecExpr& lhs, const SMatrix& rhs) { return Dot(lhs, rhs * lhs); } //============================================================================== // product: SVector/Expr calculate v^T * A * v //============================================================================== template inline T Product(const SVector& lhs, const Expr& rhs) { return Dot(lhs, rhs * lhs); } //============================================================================== // product: Expr/SVector calculate v^T * A * v //============================================================================== template inline T Product(const Expr& lhs, const SVector& rhs) { return Dot(rhs, lhs * rhs); } //============================================================================== // product: Expr/Expr calculate v^T * A * v //============================================================================== template inline T Product(const Expr& lhs, const VecExpr& rhs) { return Dot(rhs, lhs * rhs); } //============================================================================== // product: Expr/Expr calculate v^T * A * v //============================================================================== template inline T Product(const VecExpr& lhs, const Expr& rhs) { return Dot(lhs, rhs * lhs); } #endif //--------------------------------------------------------------------------- //Similarity (for vector equaal to product) //--------------------------------------------------------------------------- //============================================================================== // product: SMatrix/SVector calculate v^T * A * v //============================================================================== template inline T Similarity(const SMatrix& lhs, const SVector& rhs) { return Dot(rhs, lhs * rhs); } //============================================================================== // product: SVector/SMatrix calculate v^T * A * v //============================================================================== template inline T Similarity(const SVector& lhs, const SMatrix& rhs) { return Dot(lhs, rhs * lhs); } //============================================================================== // product: SMatrix/Expr calculate v^T * A * v //============================================================================== template inline T Similarity(const SMatrix& lhs, const VecExpr& rhs) { return Dot(rhs, lhs * rhs); } //============================================================================== // product: Expr/SMatrix calculate v^T * A * v //============================================================================== template inline T Similarity(const VecExpr& lhs, const SMatrix& rhs) { return Dot(lhs, rhs * lhs); } //============================================================================== // product: SVector/Expr calculate v^T * A * v //============================================================================== template inline T Similarity(const SVector& lhs, const Expr& rhs) { return Dot(lhs, rhs * lhs); } //============================================================================== // product: Expr/SVector calculate v^T * A * v //============================================================================== template inline T Similarity(const Expr& lhs, const SVector& rhs) { return Dot(rhs, lhs * rhs); } //============================================================================== // product: Expr/Expr calculate v^T * A * v //============================================================================== template inline T Similarity(const Expr& lhs, const VecExpr& rhs) { return Dot(rhs, lhs * rhs); } //============================================================================== // product: Expr/Expr calculate v^T * A * v //============================================================================== template inline T Similarity(const VecExpr& lhs, const Expr& rhs) { return Dot(lhs, rhs * lhs); } //============================================================================== // product: SMatrix/SMatrix calculate M * A * M^T where A is a symmetric matrix // return matrix will be nrows M x nrows M //============================================================================== template inline SMatrix > Similarity(const SMatrix& lhs, const SMatrix >& rhs) { SMatrix > tmp = lhs * rhs; SMatrix > tmp2 = tmp * Transpose(lhs); typedef SMatrix > SMatrixSym; typedef MatRepSym RSym; // not very efficient but is OK for now SMatrixSym mret; //std::cout << R::kSize << " " << RSym::kSize << std::endl; for(unsigned int i=0; i vtmp2 = tmp2.UpperBlock(); // #else // // for solaris problem // SVector vtmp2 = tmp2.UpperBlock< SVector > (); // #endif // SMatrixSym mret(vtmp2); return mret; } //============================================================================== // product: SMatrix/SMatrix calculate M * A * M^T where A is a symmetric matrix // return matrix will be nrowsM x nrows M // M is a matrix expression //============================================================================== template inline SMatrix > Similarity(const Expr& lhs, const SMatrix >& rhs) { SMatrix > tmp = lhs * rhs; SMatrix > tmp2 = tmp * Transpose(lhs); typedef SMatrix > SMatrixSym; SMatrixSym mret; // not very efficient but is OK for now for(unsigned int i=0; i inline SMatrix > SimilarityT(const SMatrix& lhs, const SMatrix >& rhs) { SMatrix > tmp = rhs * lhs; SMatrix > tmp2 = Transpose(lhs) * tmp; typedef SMatrix > SMatrixSym; SMatrixSym mret; // not very efficient but is OK for now for(unsigned int i=0; i inline SMatrix > SimilarityT(const Expr& lhs, const SMatrix >& rhs) { SMatrix > tmp = rhs * lhs; SMatrix > tmp2 = Transpose(lhs) * tmp; typedef SMatrix > SMatrixSym; SMatrixSym mret; // not very efficient but is OK for now for(unsigned int i=0; i