All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SMatTSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_SMATTSMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_SMATTSMATMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
58 #include <blaze/util/Assert.h>
59 #include <blaze/util/InvalidType.h>
61 #include <blaze/util/SelectType.h>
62 #include <blaze/util/Types.h>
64 #include <blaze/util/Unused.h>
65 
66 
67 namespace blaze {
68 
69 //=================================================================================================
70 //
71 // CLASS SMATTSMATMULTEXPR
72 //
73 //=================================================================================================
74 
75 //*************************************************************************************************
82 template< typename MT1 // Type of the left-hand side sparse matrix
83  , typename MT2 > // Type of the right-hand side sparse matrix
84 class SMatTSMatMultExpr : public SparseMatrix< SMatTSMatMultExpr<MT1,MT2>, false >
85  , private MatMatMultExpr
86  , private Computation
87 {
88  private:
89  //**Type definitions****************************************************************************
90  typedef typename MT1::ResultType RT1;
91  typedef typename MT2::ResultType RT2;
92  typedef typename MT1::CompositeType CT1;
93  typedef typename MT2::CompositeType CT2;
94  //**********************************************************************************************
95 
96  public:
97  //**Type definitions****************************************************************************
100  typedef typename ResultType::OppositeType OppositeType;
101  typedef typename ResultType::TransposeType TransposeType;
102  typedef typename ResultType::ElementType ElementType;
103  typedef const ElementType ReturnType;
104  typedef const ResultType CompositeType;
105 
107  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
108 
110  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
111  //**********************************************************************************************
112 
113  //**Constructor*********************************************************************************
119  explicit inline SMatTSMatMultExpr( const MT1& lhs, const MT2& rhs )
120  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
121  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
122  {
123  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
124  }
125  //**********************************************************************************************
126 
127  //**Access operator*****************************************************************************
134  inline ReturnType operator()( size_t i, size_t j ) const {
135  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
136  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
137 
138  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
139  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
140 
141  ElementType tmp = ElementType();
142 
143  // Early exit
144  if( lhs_.columns() == 0UL )
145  return tmp;
146 
147  // Fast computation in case both the left-hand side and the right-hand side
148  // sparse matrices directly provide iterators
150  {
151  // Evaluation of the left-hand side sparse matrix operand
152  CT1 A( lhs_ );
153 
154  const LeftIterator lend( A.end(i) );
155  LeftIterator lelem( A.begin(i) );
156 
157  // Evaluation of the right-hand side sparse matrix operand
158  CT2 B( rhs_ );
159 
160  const RightIterator rend( B.end(j) );
161  RightIterator relem( B.begin(j) );
162 
163  // Early exit in case row i or column j are empty
164  if( lelem == lend || relem == rend )
165  return tmp;
166 
167  // Calculating element (i,j)
168  while( true ) {
169  if( lelem->index() < relem->index() ) {
170  ++lelem;
171  if( lelem == lend ) break;
172  }
173  else if( relem->index() < lelem->index() ) {
174  ++relem;
175  if( relem == rend ) break;
176  }
177  else {
178  tmp = lelem->value() * relem->value();
179  ++lelem;
180  ++relem;
181  break;
182  }
183  }
184 
185  if( lelem != lend && relem != rend )
186  {
187  while( true ) {
188  if( lelem->index() < relem->index() ) {
189  ++lelem;
190  if( lelem == lend ) break;
191  }
192  else if( relem->index() < lelem->index() ) {
193  ++relem;
194  if( relem == rend ) break;
195  }
196  else {
197  tmp += lelem->value() * relem->value();
198  ++lelem;
199  if( lelem == lend ) break;
200  ++relem;
201  if( relem == rend ) break;
202  }
203  }
204  }
205  }
206 
207  // Optimized computation in case the left-hand side sparse matrix directly provides iterators
209  {
210  // Evaluation of the left-hand side sparse matrix operand
211  CT1 A( lhs_ );
212 
213  const LeftIterator end( A.end(i) );
214  LeftIterator element( A.begin(i) );
215 
216  // Early exit in case row i is empty
217  if( element == end )
218  return tmp;
219 
220  // Calculating element (i,j)
221  tmp = element->value() * rhs_(element->index(),j);
222  ++element;
223  for( ; element!=end; ++element )
224  tmp += element->value() * rhs_(element->index(),j);
225  }
226 
227  // Optimized computation in case the right-hand side sparse matrix directly provides iterators
229  {
230  // Evaluation of the right-hand side sparse matrix operand
231  CT2 B( rhs_ );
232 
233  const RightIterator end( B.end(j) );
234  RightIterator element( B.begin(j) );
235 
236  // Early exit in case row i is empty
237  if( element == end )
238  return tmp;
239 
240  // Calculating element (i,j)
241  tmp = lhs_(i,element->index()) * element->value();
242  ++element;
243  for( ; element!=end; ++element )
244  tmp += lhs_(i,element->index()) * element->value();
245  }
246 
247  // Default computation in case both sparse matrices don't provide iterators
248  else {
249  tmp = lhs_(i,0UL) * rhs_(0UL,j);
250  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
251  tmp += lhs_(i,k) * rhs_(k,j);
252  }
253  }
254 
255  return tmp;
256  }
257  //**********************************************************************************************
258 
259  //**Rows function*******************************************************************************
264  inline size_t rows() const {
265  return lhs_.rows();
266  }
267  //**********************************************************************************************
268 
269  //**Columns function****************************************************************************
274  inline size_t columns() const {
275  return rhs_.columns();
276  }
277  //**********************************************************************************************
278 
279  //**NonZeros function***************************************************************************
284  inline size_t nonZeros() const {
285  return 0UL;
286  }
287  //**********************************************************************************************
288 
289  //**NonZeros function***************************************************************************
295  inline size_t nonZeros( size_t i ) const {
296  UNUSED_PARAMETER( i );
297  return 0UL;
298  }
299  //**********************************************************************************************
300 
301  //**Left operand access*************************************************************************
306  inline LeftOperand leftOperand() const {
307  return lhs_;
308  }
309  //**********************************************************************************************
310 
311  //**Right operand access************************************************************************
316  inline RightOperand rightOperand() const {
317  return rhs_;
318  }
319  //**********************************************************************************************
320 
321  //**********************************************************************************************
327  template< typename T >
328  inline bool canAlias( const T* alias ) const {
329  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
330  }
331  //**********************************************************************************************
332 
333  //**********************************************************************************************
339  template< typename T >
340  inline bool isAliased( const T* alias ) const {
341  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
342  }
343  //**********************************************************************************************
344 
345  private:
346  //**Member variables****************************************************************************
349  //**********************************************************************************************
350 
351  //**Assignment to row-major dense matrices******************************************************
364  template< typename MT > // Type of the target dense matrix
365  friend inline void assign( DenseMatrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
366  {
368 
369  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
370  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
371 
372  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( typename MT2::OppositeType );
373 
374  const typename MT2::OppositeType tmp( rhs.rhs_ );
375  assign( ~lhs, rhs.lhs_ * tmp );
376  }
378  //**********************************************************************************************
379 
380  //**Assignment to column-major dense matrices***************************************************
393  template< typename MT > // Type of the target dense matrix
394  friend inline void assign( DenseMatrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
395  {
397 
398  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
399  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
400 
401  BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( typename MT1::OppositeType );
402 
403  const typename MT1::OppositeType tmp( rhs.lhs_ );
404  assign( ~lhs, tmp * rhs.rhs_ );
405  }
407  //**********************************************************************************************
408 
409  //**Assignment to row-major sparse matrices*****************************************************
422  template< typename MT > // Type of the target sparse matrix
423  friend inline void assign( SparseMatrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
424  {
426 
427  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
428  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
429 
430  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( typename MT2::OppositeType );
431 
432  const typename MT2::OppositeType tmp( rhs.rhs_ );
433  assign( ~lhs, rhs.lhs_ * tmp );
434  }
436  //**********************************************************************************************
437 
438  //**Assignment to column-major sparse matrices**************************************************
451  template< typename MT > // Type of the target sparse matrix
452  friend inline void assign( SparseMatrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
453  {
455 
456  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
457  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
458 
459  BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( typename MT1::OppositeType );
460 
461  const typename MT1::OppositeType tmp( rhs.lhs_ );
462  assign( ~lhs, tmp * rhs.rhs_ );
463  }
465  //**********************************************************************************************
466 
467  //**Addition assignment to row-major dense matrices*********************************************
480  template< typename MT > // Type of the target dense matrix
481  friend inline void addAssign( DenseMatrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
482  {
484 
485  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
486  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
487 
488  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( typename MT2::OppositeType );
489 
490  const typename MT2::OppositeType tmp( rhs.rhs_ );
491  addAssign( ~lhs, rhs.lhs_ * tmp );
492  }
494  //**********************************************************************************************
495 
496  //**Addition assignment to column-major dense matrices******************************************
509  template< typename MT > // Type of the target dense matrix
510  friend inline void addAssign( DenseMatrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
511  {
513 
514  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
515  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
516 
517  BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( typename MT1::OppositeType );
518 
519  const typename MT1::OppositeType tmp( rhs.lhs_ );
520  addAssign( ~lhs, tmp * rhs.rhs_ );
521  }
523  //**********************************************************************************************
524 
525  //**Addition assignment to sparse matrices******************************************************
526  // No special implementation for the addition assignment to sparse matrices.
527  //**********************************************************************************************
528 
529  //**Subtraction assignment to row-major dense matrices******************************************
542  template< typename MT > // Type of the target dense matrix
543  friend inline void subAssign( DenseMatrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
544  {
546 
547  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
548  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
549 
550  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( typename MT2::OppositeType );
551 
552  const typename MT2::OppositeType tmp( rhs.rhs_ );
553  subAssign( ~lhs, rhs.lhs_ * tmp );
554  }
556  //**********************************************************************************************
557 
558  //**Subtraction assignment to column-major dense matrices***************************************
571  template< typename MT > // Type of the target dense matrix
572  friend inline void subAssign( DenseMatrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
573  {
575 
576  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
577  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
578 
579  BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( typename MT1::OppositeType );
580 
581  const typename MT1::OppositeType tmp( rhs.lhs_ );
582  subAssign( ~lhs, tmp * rhs.rhs_ );
583  }
585  //**********************************************************************************************
586 
587  //**Subtraction assignment to sparse matrices***************************************************
588  // No special implementation for the subtraction assignment to sparse matrices.
589  //**********************************************************************************************
590 
591  //**Multiplication assignment to dense matrices*************************************************
592  // No special implementation for the multiplication assignment to dense matrices.
593  //**********************************************************************************************
594 
595  //**Multiplication assignment to sparse matrices************************************************
596  // No special implementation for the multiplication assignment to sparse matrices.
597  //**********************************************************************************************
598 
599  //**Compile time checks*************************************************************************
606  //**********************************************************************************************
607 };
608 //*************************************************************************************************
609 
610 
611 
612 
613 //=================================================================================================
614 //
615 // GLOBAL BINARY ARITHMETIC OPERATORS
616 //
617 //=================================================================================================
618 
619 //*************************************************************************************************
649 template< typename T1 // Type of the left-hand side sparse matrix
650  , typename T2 > // Type of the right-hand side sparse matrix
651 inline const SMatTSMatMultExpr<T1,T2>
653 {
655 
656  if( (~lhs).columns() != (~rhs).rows() )
657  throw std::invalid_argument( "Matrix sizes do not match" );
658 
659  return SMatTSMatMultExpr<T1,T2>( ~lhs, ~rhs );
660 }
661 //*************************************************************************************************
662 
663 
664 
665 
666 //=================================================================================================
667 //
668 // EXPRESSION TRAIT SPECIALIZATIONS
669 //
670 //=================================================================================================
671 
672 //*************************************************************************************************
674 template< typename MT1, typename MT2, typename VT >
675 struct SMatDVecMultExprTrait< SMatTSMatMultExpr<MT1,MT2>, VT >
676 {
677  public:
678  //**********************************************************************************************
679  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
680  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
681  IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
682  , typename SMatDVecMultExprTrait< MT1, typename TSMatDVecMultExprTrait<MT2,VT>::Type >::Type
683  , INVALID_TYPE >::Type Type;
684  //**********************************************************************************************
685 };
687 //*************************************************************************************************
688 
689 
690 //*************************************************************************************************
692 template< typename MT1, typename MT2, typename VT >
693 struct SMatSVecMultExprTrait< SMatTSMatMultExpr<MT1,MT2>, VT >
694 {
695  public:
696  //**********************************************************************************************
697  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
698  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
699  IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
700  , typename SMatSVecMultExprTrait< MT1, typename TSMatSVecMultExprTrait<MT2,VT>::Type >::Type
701  , INVALID_TYPE >::Type Type;
702  //**********************************************************************************************
703 };
705 //*************************************************************************************************
706 
707 
708 //*************************************************************************************************
710 template< typename VT, typename MT1, typename MT2 >
711 struct TDVecSMatMultExprTrait< VT, SMatTSMatMultExpr<MT1,MT2> >
712 {
713  public:
714  //**********************************************************************************************
715  typedef typename SelectType< IsDenseVector<VT>::value && IsTransposeVector<VT>::value &&
716  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
717  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
718  , typename TDVecTSMatMultExprTrait< typename TDVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
719  , INVALID_TYPE >::Type Type;
720  //**********************************************************************************************
721 };
723 //*************************************************************************************************
724 
725 
726 //*************************************************************************************************
728 template< typename VT, typename MT1, typename MT2 >
729 struct TSVecSMatMultExprTrait< VT, SMatTSMatMultExpr<MT1,MT2> >
730 {
731  public:
732  //**********************************************************************************************
733  typedef typename SelectType< IsSparseVector<VT>::value && IsTransposeVector<VT>::value &&
734  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
735  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
736  , typename TDVecTSMatMultExprTrait< typename TDVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
737  , INVALID_TYPE >::Type Type;
738  //**********************************************************************************************
739 };
741 //*************************************************************************************************
742 
743 
744 //*************************************************************************************************
746 template< typename MT1, typename MT2 >
747 struct RowExprTrait< SMatTSMatMultExpr<MT1,MT2> >
748 {
749  public:
750  //**********************************************************************************************
751  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
752  //**********************************************************************************************
753 };
755 //*************************************************************************************************
756 
757 
758 //*************************************************************************************************
760 template< typename MT1, typename MT2 >
761 struct ColumnExprTrait< SMatTSMatMultExpr<MT1,MT2> >
762 {
763  public:
764  //**********************************************************************************************
765  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
766  //**********************************************************************************************
767 };
769 //*************************************************************************************************
770 
771 } // namespace blaze
772 
773 #endif