// @(#)root/smatrix:$Id$ // Authors: J. Palacios 2006 #ifndef ROOT_Math_HelperOps #define ROOT_Math_HelperOps 1 // Include files /** @class HelperOps HelperOps.h Math/HelperOps.h * * * @author Juan PALACIOS * @date 2006-01-11 * * Specialised helper classes for binary operators =, +=, -= * between SMatrices and Expressions with arbitrary representations. * Specialisations at the moment only for Symmetric LHS and Generic RHS * and used to throw static assert. */ #include "Math/StaticCheck.h" #include // required by std::copy #include namespace ROOT { namespace Math { template class SMatrix; template class Expr; template class MatRepSym; template class MatRepStd; //========================================================================= /** Structure to assign from an expression based to general matrix to general matrix */ template struct Assign { /** Evaluate the expression from general to general matrices. If the matrix to assign the value is in use in the expression, a temporary object is created to store the value (case A = B * A) */ static void Evaluate(SMatrix& lhs, const Expr& rhs) { if (! rhs.IsInUse(lhs.begin() ) ) { unsigned int l = 0; for(unsigned int i=0; i struct Assign, MatRepSym > { /** Evaluate the expression from symmetric to symmetric matrices. If the matrix to assign the value is in use in the expression, a temporary object is created to store the value (case A = B * A) */ static void Evaluate(SMatrix >& lhs, const Expr >& rhs) { if (! rhs.IsInUse(lhs.begin() ) ) { unsigned int l = 0; for(unsigned int i=0; i::kSize]; unsigned int l = 0; for(unsigned int i=0; i::kSize; ++i) lhs.fRep.Array()[i] = tmp[i]; } } }; /** Dummy Structure which flags an error to avoid assigment from expression based on a general matrix to a symmetric matrix */ template struct Assign, MatRepStd > { static void Evaluate(SMatrix >&, const Expr >&) { STATIC_CHECK(0==1, Cannot_assign_general_to_symmetric_matrix); } }; // struct Assign /** Force Expression evaluation from general to symmetric. To be used when is known (like in similarity products) that the result is symmetric Note this is function used in the simmilarity product: no check for temporary is done since in that case is not needed */ struct AssignSym { /// assign a symmetric matrix from an expression template static void Evaluate(SMatrix >& lhs, const Expr& rhs) { //for(unsigned int i=0; i static void Evaluate(SMatrix >& lhs, const SMatrix& rhs) { //for(unsigned int i=0; i struct PlusEquals { static void Evaluate(SMatrix& lhs, const Expr& rhs) { if (! rhs.IsInUse(lhs.begin() ) ) { unsigned int l = 0; for(unsigned int i=0; i struct PlusEquals, MatRepSym > { static void Evaluate(SMatrix >& lhs, const Expr >& rhs) { if (! rhs.IsInUse(lhs.begin() ) ) { unsigned int l = 0; // l span storage of sym matrices for(unsigned int i=0; i::kSize]; unsigned int l = 0; for(unsigned int i=0; i::kSize; ++i) lhs.fRep.Array()[i] += tmp[i]; } } }; /** Specialization for symmetrix += general : NOT Allowed operation */ template struct PlusEquals, MatRepStd > { static void Evaluate(SMatrix >&, const Expr >&) { STATIC_CHECK(0==1, Cannot_plusEqual_general_to_symmetric_matrix); } }; // struct PlusEquals //========================================================================= /** Evaluate the expression performing a -= operation Need to check whether creating a temporary object with the expression result (like in op: A -= A * B ) */ template struct MinusEquals { static void Evaluate(SMatrix& lhs, const Expr& rhs) { if (! rhs.IsInUse(lhs.begin() ) ) { unsigned int l = 0; for(unsigned int i=0; i struct MinusEquals, MatRepSym > { static void Evaluate(SMatrix >& lhs, const Expr >& rhs) { if (! rhs.IsInUse(lhs.begin() ) ) { unsigned int l = 0; // l span storage of sym matrices for(unsigned int i=0; i::kSize]; unsigned int l = 0; for(unsigned int i=0; i::kSize; ++i) lhs.fRep.Array()[i] -= tmp[i]; } } }; /** Specialization for symmetrix -= general : NOT Allowed operation */ template struct MinusEquals, MatRepStd > { static void Evaluate(SMatrix >&, const Expr >&) { STATIC_CHECK(0==1, Cannot_minusEqual_general_to_symmetric_matrix); } }; // struct MinusEquals /** Structure to deal when a submatrix is placed in a matrix. We have different cases according to the matrix representation */ template struct PlaceMatrix { static void Evaluate(SMatrix& lhs, const SMatrix& rhs, unsigned int row, unsigned int col) { assert(row+D3 <= D1 && col+D4 <= D2); const unsigned int offset = row*D2+col; for(unsigned int i=0; i struct PlaceExpr { static void Evaluate(SMatrix& lhs, const Expr& rhs, unsigned int row, unsigned int col) { assert(row+D3 <= D1 && col+D4 <= D2); const unsigned int offset = row*D2+col; for(unsigned int i=0; i struct PlaceMatrix, MatRepStd > { static void Evaluate(SMatrix >& , const SMatrix >& , unsigned int , unsigned int ) { STATIC_CHECK(0==1, Cannot_Place_Matrix_general_in_symmetric_matrix); } }; // struct PlaceMatrix // specialization for general expression in symmetric matrices template struct PlaceExpr, MatRepStd > { static void Evaluate(SMatrix >& , const Expr >& , unsigned int , unsigned int ) { STATIC_CHECK(0==1, Cannot_Place_Matrix_general_in_symmetric_matrix); } }; // struct PlaceExpr // specialization for symmetric matrix in symmetric matrices template struct PlaceMatrix, MatRepSym > { static void Evaluate(SMatrix >& lhs, const SMatrix >& rhs, unsigned int row, unsigned int col ) { // can work only if placed on the diagonal assert(row == col); for(unsigned int i=0; i struct PlaceExpr, MatRepSym > { static void Evaluate(SMatrix >& lhs, const Expr >& rhs, unsigned int row, unsigned int col ) { // can work only if placed on the diagonal assert(row == col); for(unsigned int i=0; i struct RetrieveMatrix { static void Evaluate(SMatrix& lhs, const SMatrix& rhs, unsigned int row, unsigned int col) { STATIC_CHECK( D1 <= D3,Smatrix_nrows_too_small); STATIC_CHECK( D2 <= D4,Smatrix_ncols_too_small); assert(row + D1 <= D3); assert(col + D2 <= D4); for(unsigned int i=0; i struct RetrieveMatrix, MatRepStd > { static void Evaluate(SMatrix >& , const SMatrix >& , unsigned int , unsigned int ) { STATIC_CHECK(0==1, Cannot_Sub_Matrix_symmetric_in_general_matrix); } }; // struct RetrieveMatrix // specialization for getting symmetric matrices from symmetric matrices (OK if row == col) template struct RetrieveMatrix, MatRepSym > { static void Evaluate(SMatrix >& lhs, const SMatrix >& rhs, unsigned int row, unsigned int col ) { STATIC_CHECK( D1 <= D3,Smatrix_dimension1_too_small); // can work only if placed on the diagonal assert(row == col); assert(row + D1 <= D3); for(unsigned int i=0; i struct AssignItr { template static void Evaluate(SMatrix& lhs, Iterator begin, Iterator end, bool triang, bool lower,bool check=true) { // require size match exactly (better) if (triang) { Iterator itr = begin; if (lower) { for (unsigned int i = 0; i < D1; ++i) for (unsigned int j =0; j <= i; ++j) { // we assume iterator is well bounded within matrix lhs.fRep[i*D2+j] = *itr++; } } else { // upper for (unsigned int i = 0; i < D1; ++i) for (unsigned int j = i; j struct AssignItr > { template static void Evaluate(SMatrix >& lhs, Iterator begin, Iterator end, bool , bool lower, bool check = true) { if (lower) { if (check) { assert(begin+ static_cast< int>( MatRepSym::kSize) == end); } std::copy(begin, end, lhs.fRep.Array() ); } else { Iterator itr = begin; for (unsigned int i = 0; i < D1; ++i) for (unsigned int j = i; j