All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TSMatSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TSMATSMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TSMATSMATMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
31 #include <vector>
32 #include <boost/type_traits/remove_reference.hpp>
44 #include <blaze/math/shims/Reset.h>
67 #include <blaze/util/Assert.h>
68 #include <blaze/util/DisableIf.h>
69 #include <blaze/util/EnableIf.h>
70 #include <blaze/util/InvalidType.h>
72 #include <blaze/util/SelectType.h>
73 #include <blaze/util/Types.h>
74 #include <blaze/util/Unused.h>
75 
76 
77 namespace blaze {
78 
79 //=================================================================================================
80 //
81 // CLASS TSMATSMATMULTEXPR
82 //
83 //=================================================================================================
84 
85 //*************************************************************************************************
92 template< typename MT1 // Type of the left-hand side sparse matrix
93  , typename MT2 > // Type of the right-hand side sparse matrix
94 class TSMatSMatMultExpr : public SparseMatrix< TSMatSMatMultExpr<MT1,MT2>, true >
95  , private Expression
96  , private Computation
97 {
98  private:
99  //**Type definitions****************************************************************************
100  typedef typename MT1::ResultType RT1;
101  typedef typename MT2::ResultType RT2;
102  typedef typename MT1::CompositeType CT1;
103  typedef typename MT2::CompositeType CT2;
104  //**********************************************************************************************
105 
106  public:
107  //**Type definitions****************************************************************************
110  typedef typename ResultType::OppositeType OppositeType;
111  typedef typename ResultType::TransposeType TransposeType;
112  typedef typename ResultType::ElementType ElementType;
113  typedef const ElementType ReturnType;
114  typedef const ResultType CompositeType;
115 
117  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
118 
120  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
121  //**********************************************************************************************
122 
123  //**Constructor*********************************************************************************
129  explicit inline TSMatSMatMultExpr( const MT1& lhs, const MT2& rhs )
130  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
131  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
132  {
133  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
134  }
135  //**********************************************************************************************
136 
137  //**Access operator*****************************************************************************
144  inline ReturnType operator()( size_t i, size_t j ) const {
145  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
146  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
147 
148  ElementType tmp = ElementType();
149 
150  if( lhs_.columns() != 0UL ) {
151  tmp = lhs_(i,0UL) * rhs_(0UL,j);
152  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
153  tmp += lhs_(i,k) * rhs_(k,j);
154  }
155  }
156 
157  return tmp;
158  }
159  //**********************************************************************************************
160 
161  //**Rows function*******************************************************************************
166  inline size_t rows() const {
167  return lhs_.rows();
168  }
169  //**********************************************************************************************
170 
171  //**Columns function****************************************************************************
176  inline size_t columns() const {
177  return rhs_.columns();
178  }
179  //**********************************************************************************************
180 
181  //**NonZeros function***************************************************************************
186  inline size_t nonZeros() const {
187  return 0UL;
188  }
189  //**********************************************************************************************
190 
191  //**NonZeros function***************************************************************************
197  inline size_t nonZeros( size_t i ) const {
198  UNUSED_PARAMETER( i );
199  return 0UL;
200  }
201  //**********************************************************************************************
202 
203  //**Left operand access*************************************************************************
208  inline LeftOperand leftOperand() const {
209  return lhs_;
210  }
211  //**********************************************************************************************
212 
213  //**Right operand access************************************************************************
218  inline RightOperand rightOperand() const {
219  return rhs_;
220  }
221  //**********************************************************************************************
222 
223  //**********************************************************************************************
229  template< typename T >
230  inline bool canAlias( const T* alias ) const {
231  return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
232  }
233  //**********************************************************************************************
234 
235  //**********************************************************************************************
241  template< typename T >
242  inline bool isAliased( const T* alias ) const {
243  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
244  }
245  //**********************************************************************************************
246 
247  private:
248  //**Member variables****************************************************************************
251  //**********************************************************************************************
252 
253  //**Default assignment to dense matrices********************************************************
267  template< typename MT // Type of the target dense matrix
268  , bool SO > // Storage order of the target dense matrix
269  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
270  assign( DenseMatrix<MT,SO>& lhs, const TSMatSMatMultExpr& rhs )
271  {
273 
274  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
275  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
276 
277  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
278  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
279 
280  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
281  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
282 
283  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
284  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
285  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
286  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
287  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
288  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
289 
290  for( size_t j=0UL; j<A.columns(); ++j ) {
291  const LeftIterator lend( A.end(j) );
292  for( LeftIterator lelem=A.begin(j); lelem!=lend; ++lelem ) {
293  const RightIterator rend( B.end(j) );
294  for( RightIterator relem=B.begin(j); relem!=rend; ++relem )
295  {
296  if( isDefault( (~lhs)(lelem->index(),relem->index()) ) ) {
297  (~lhs)(lelem->index(),relem->index()) = lelem->value() * relem->value();
298  }
299  else {
300  (~lhs)(lelem->index(),relem->index()) += lelem->value() * relem->value();
301  }
302  }
303  }
304  }
305  }
307  //**********************************************************************************************
308 
309  //**Optimized assignment to dense matrices******************************************************
323  template< typename MT // Type of the target dense matrix
324  , bool SO > // Storage order of the target dense matrix
325  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
326  assign( DenseMatrix<MT,SO>& lhs, const TSMatSMatMultExpr& rhs )
327  {
329 
330  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
331  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
332 
333  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
334  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
335 
336  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
337  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
338 
339  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
340  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
341  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
342  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
343  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
344  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
345 
346  for( size_t j=0UL; j<A.columns(); ++j ) {
347  const LeftIterator lend( A.end(j) );
348  for( LeftIterator lelem=A.begin(j); lelem!=lend; ++lelem ) {
349  const RightIterator rend( B.end(j) );
350  for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
351  (~lhs)(lelem->index(),relem->index()) += lelem->value() * relem->value();
352  }
353  }
354  }
355  }
357  //**********************************************************************************************
358 
359  //**Assignment to row-major sparse matrices*****************************************************
372  template< typename MT > // Type of the target sparse matrix
373  friend inline void assign( SparseMatrix<MT,false>& lhs, const TSMatSMatMultExpr& rhs )
374  {
376 
377  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
378  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
379 
380  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( typename MT1::OppositeType );
381 
382  const typename MT1::OppositeType tmp( rhs.lhs_ );
383  assign( ~lhs, tmp * rhs.rhs_ );
384  }
386  //**********************************************************************************************
387 
388  //**Assignment to column-major sparse matrices**************************************************
401  template< typename MT > // Type of the target sparse matrix
402  friend inline void assign( SparseMatrix<MT,true>& lhs, const TSMatSMatMultExpr& rhs )
403  {
405 
406  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
407  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
408 
409  BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( typename MT2::OppositeType );
410 
411  const typename MT2::OppositeType tmp( rhs.rhs_ );
412  assign( ~lhs, rhs.lhs_ * tmp );
413  }
415  //**********************************************************************************************
416 
417  //**Addition assignment to dense matrices*******************************************************
430  template< typename MT // Type of the target dense matrix
431  , bool SO > // Storage order of the target dense matarix
432  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const TSMatSMatMultExpr& rhs )
433  {
435 
436  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
437  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
438 
439  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
440  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
441 
442  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
443  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
444 
445  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
446  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
447  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
448  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
449  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
450  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
451 
452  for( size_t j=0UL; j<A.columns(); ++j ) {
453  const LeftIterator lend( A.end(j) );
454  for( LeftIterator lelem=A.begin(j); lelem!=lend; ++lelem ) {
455  const RightIterator rend( B.end(j) );
456  for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
457  (~lhs)(lelem->index(),relem->index()) += lelem->value() * relem->value();
458  }
459  }
460  }
461  }
463  //**********************************************************************************************
464 
465  //**Addition assignment to sparse matrices******************************************************
466  // No special implementation for the addition assignment to sparse matrices.
467  //**********************************************************************************************
468 
469  //**Subtraction assignment to dense matrices****************************************************
482  template< typename MT // Type of the target dense matrix
483  , bool SO > // Storage order of the target dense matrix
484  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TSMatSMatMultExpr& rhs )
485  {
487 
488  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
489  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
490 
491  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
492  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
493 
494  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
495  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
496 
497  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
498  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
499  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
500  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
501  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
502  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
503 
504  for( size_t j=0UL; j<A.columns(); ++j ) {
505  const LeftIterator lend( A.end(j) );
506  for( LeftIterator lelem=A.begin(j); lelem!=lend; ++lelem ) {
507  const RightIterator rend( B.end(j) );
508  for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
509  (~lhs)(lelem->index(),relem->index()) -= lelem->value() * relem->value();
510  }
511  }
512  }
513  }
515  //**********************************************************************************************
516 
517  //**Subtraction assignment to sparse matrices***************************************************
518  // No special implementation for the subtraction assignment to sparse matrices.
519  //**********************************************************************************************
520 
521  //**Multiplication assignment to dense matrices*************************************************
522  // No special implementation for the multiplication assignment to dense matrices.
523  //**********************************************************************************************
524 
525  //**Multiplication assignment to sparse matrices************************************************
526  // No special implementation for the multiplication assignment to sparse matrices.
527  //**********************************************************************************************
528 
529  //**Compile time checks*************************************************************************
536  //**********************************************************************************************
537 };
538 //*************************************************************************************************
539 
540 
541 
542 
543 //=================================================================================================
544 //
545 // GLOBAL BINARY ARITHMETIC OPERATORS
546 //
547 //=================================================================================================
548 
549 //*************************************************************************************************
579 template< typename T1 // Type of the left-hand side sparse matrix
580  , typename T2 > // Type of the right-hand side sparse matrix
581 inline const TSMatSMatMultExpr<T1,T2>
583 {
585 
586  if( (~lhs).columns() != (~rhs).rows() )
587  throw std::invalid_argument( "Matrix sizes do not match" );
588 
589  return TSMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
590 }
591 //*************************************************************************************************
592 
593 
594 
595 
596 //=================================================================================================
597 //
598 // GLOBAL OPERATORS
599 //
600 //=================================================================================================
601 
602 //*************************************************************************************************
615 template< typename T1 // Type of the left-hand side sparse matrix
616  , typename T2 > // Type of the right-hand side sparse matrix
617 inline typename RowExprTrait< TSMatSMatMultExpr<T1,T2> >::Type
618  row( const TSMatSMatMultExpr<T1,T2>& sm, size_t index )
619 {
621 
622  return row( sm.leftOperand(), index ) * sm.rightOperand();
623 }
625 //*************************************************************************************************
626 
627 
628 //*************************************************************************************************
641 template< typename T1 // Type of the left-hand side sparse matrix
642  , typename T2 > // Type of the right-hand side sparse matrix
643 inline typename ColumnExprTrait< TSMatSMatMultExpr<T1,T2> >::Type
644  column( const TSMatSMatMultExpr<T1,T2>& sm, size_t index )
645 {
647 
648  return sm.leftOperand() * column( sm.rightOperand(), index );
649 }
651 //*************************************************************************************************
652 
653 
654 
655 
656 //=================================================================================================
657 //
658 // EXPRESSION TRAIT SPECIALIZATIONS
659 //
660 //=================================================================================================
661 
662 //*************************************************************************************************
664 template< typename MT1, typename MT2, typename VT >
665 struct TSMatDVecMultExprTrait< TSMatSMatMultExpr<MT1,MT2>, VT >
666 {
667  public:
668  //**********************************************************************************************
669  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
670  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
671  IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
672  , typename TSMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
673  , INVALID_TYPE >::Type Type;
674  //**********************************************************************************************
675 };
677 //*************************************************************************************************
678 
679 
680 //*************************************************************************************************
682 template< typename MT1, typename MT2, typename VT >
683 struct TSMatSVecMultExprTrait< TSMatSMatMultExpr<MT1,MT2>, VT >
684 {
685  public:
686  //**********************************************************************************************
687  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
688  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
689  IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
690  , typename TSMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
691  , INVALID_TYPE >::Type Type;
692  //**********************************************************************************************
693 };
695 //*************************************************************************************************
696 
697 
698 //*************************************************************************************************
700 template< typename VT, typename MT1, typename MT2 >
701 struct TDVecTSMatMultExprTrait< VT, TSMatSMatMultExpr<MT1,MT2> >
702 {
703  public:
704  //**********************************************************************************************
705  typedef typename SelectType< IsDenseVector<VT>::value && IsTransposeVector<VT>::value &&
706  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
707  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
708  , typename TDVecSMatMultExprTrait< typename TDVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
709  , INVALID_TYPE >::Type Type;
710  //**********************************************************************************************
711 };
713 //*************************************************************************************************
714 
715 
716 //*************************************************************************************************
718 template< typename VT, typename MT1, typename MT2 >
719 struct TSVecTSMatMultExprTrait< VT, TSMatSMatMultExpr<MT1,MT2> >
720 {
721  public:
722  //**********************************************************************************************
723  typedef typename SelectType< IsSparseVector<VT>::value && IsTransposeVector<VT>::value &&
724  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
725  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
726  , typename TDVecSMatMultExprTrait< typename TDVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
727  , INVALID_TYPE >::Type Type;
728  //**********************************************************************************************
729 };
731 //*************************************************************************************************
732 
733 
734 //*************************************************************************************************
736 template< typename MT1, typename MT2 >
737 struct RowExprTrait< TSMatSMatMultExpr<MT1,MT2> >
738 {
739  public:
740  //**********************************************************************************************
741  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
742  //**********************************************************************************************
743 };
745 //*************************************************************************************************
746 
747 
748 //*************************************************************************************************
750 template< typename MT1, typename MT2 >
751 struct ColumnExprTrait< TSMatSMatMultExpr<MT1,MT2> >
752 {
753  public:
754  //**********************************************************************************************
755  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
756  //**********************************************************************************************
757 };
759 //*************************************************************************************************
760 
761 } // namespace blaze
762 
763 #endif