All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SMatTDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_SMATTDMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_SMATTDMATMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
31 #include <boost/type_traits/remove_reference.hpp>
39 #include <blaze/math/shims/Reset.h>
65 #include <blaze/util/Assert.h>
66 #include <blaze/util/InvalidType.h>
68 #include <blaze/util/SelectType.h>
69 #include <blaze/util/Types.h>
70 
71 
72 namespace blaze {
73 
74 //=================================================================================================
75 //
76 // CLASS SMATTDMATMULTEXPR
77 //
78 //=================================================================================================
79 
80 //*************************************************************************************************
87 template< typename MT1 // Type of the left-hand side sparse matrix
88  , typename MT2 > // Type of the right-hand side dense matrix
89 class SMatTDMatMultExpr : public DenseMatrix< SMatTDMatMultExpr<MT1,MT2>, false >
90  , private Expression
91  , private Computation
92 {
93  private:
94  //**Type definitions****************************************************************************
95  typedef typename MT1::ResultType RT1;
96  typedef typename MT2::ResultType RT2;
97  typedef typename MT1::CompositeType CT1;
98  typedef typename MT2::CompositeType CT2;
99  //**********************************************************************************************
100 
101  public:
102  //**Type definitions****************************************************************************
105  typedef typename ResultType::OppositeType OppositeType;
106  typedef typename ResultType::TransposeType TransposeType;
107  typedef typename ResultType::ElementType ElementType;
108  typedef const ElementType ReturnType;
109  typedef const ResultType CompositeType;
110 
112  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
113 
115  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
116 
118  typedef typename SelectType< IsComputation<MT1>::value, const RT1, CT1 >::Type LT;
119 
121  typedef typename SelectType< IsComputation<MT2>::value, const RT2, CT2 >::Type RT;
122  //**********************************************************************************************
123 
124  //**Compilation flags***************************************************************************
126  enum { vectorizable = 0 };
127  //**********************************************************************************************
128 
129  //**Constructor*********************************************************************************
135  explicit inline SMatTDMatMultExpr( const MT1& lhs, const MT2& rhs )
136  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
137  , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
138  {
139  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
140  }
141  //**********************************************************************************************
142 
143  //**Access operator*****************************************************************************
150  inline ReturnType operator()( size_t i, size_t j ) const {
151  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
152  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
153 
154  typedef typename boost::remove_reference<CT1>::type::ConstIterator ConstIterator;
155 
156  ElementType tmp = ElementType();
157 
158  // Early exit
159  if( lhs_.columns() == 0UL )
160  return tmp;
161 
162  // Fast computation in case the left-hand side sparse matrix directly provides iterators
164  {
165  // Evaluation of the left-hand side sparse matrix operand
166  CT1 A( lhs_ );
167 
168  const ConstIterator end( A.end(i) );
169  ConstIterator element( A.begin(i) );
170 
171  // Early exit in case row i is empty
172  if( element == end )
173  return tmp;
174 
175  // Calculating element (i,j)
176  tmp = element->value() * rhs_(element->index(),j);
177  ++element;
178  for( ; element!=end; ++element )
179  tmp += element->value() * rhs_(element->index(),j);
180  }
181 
182  // Default computation in case the left-hand side sparse matrix doesn't provide iterators
183  else {
184  tmp = lhs_(i,0UL) * rhs_(0UL,j);
185  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
186  tmp += lhs_(i,k) * rhs_(k,j);
187  }
188  }
189 
190  return tmp;
191  }
192  //**********************************************************************************************
193 
194  //**Rows function*******************************************************************************
199  inline size_t rows() const {
200  return lhs_.rows();
201  }
202  //**********************************************************************************************
203 
204  //**Columns function****************************************************************************
209  inline size_t columns() const {
210  return rhs_.columns();
211  }
212  //**********************************************************************************************
213 
214  //**Left operand access*************************************************************************
219  inline LeftOperand leftOperand() const {
220  return lhs_;
221  }
222  //**********************************************************************************************
223 
224  //**Right operand access************************************************************************
229  inline RightOperand rightOperand() const {
230  return rhs_;
231  }
232  //**********************************************************************************************
233 
234  //**********************************************************************************************
240  template< typename T >
241  inline bool canAlias( const T* alias ) const {
242  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
243  }
244  //**********************************************************************************************
245 
246  //**********************************************************************************************
252  template< typename T >
253  inline bool isAliased( const T* alias ) const {
254  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
255  }
256  //**********************************************************************************************
257 
258  private:
259  //**Member variables****************************************************************************
262  //**********************************************************************************************
263 
264  //**Assignment to dense matrices****************************************************************
276  template< typename MT // Type of the target dense matrix
277  , bool SO > // Storage order of the target dense matrix
278  friend inline void assign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
279  {
281 
282  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
283  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
284 
285  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
286 
287  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
288  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
289 
290  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
291  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
292  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
293  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
294  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
295  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
296 
297  const size_t block( 256UL );
298 
299  BLAZE_INTERNAL_ASSERT( ( B.columns() - ( B.columns() % 4UL ) ) == ( B.columns() & size_t(-4) ), "Invalid end calculation" );
300  const size_t jend( B.columns() & size_t(-4) );
301 
302  for( size_t ii=0UL; ii<A.rows(); ii+=block ) {
303  const size_t iend( ( ii+block > A.rows() )?( A.rows() ):( ii+block ) );
304  for( size_t j=0UL; j<jend; j+=4UL ) {
305  for( size_t i=ii; i<iend; ++i ) {
306  const ConstIterator end( A.end(i) );
307  ConstIterator element( A.begin(i) );
308  if( element!=end ) {
309  (~lhs)(i,j ) = element->value() * B(element->index(),j );
310  (~lhs)(i,j+1UL) = element->value() * B(element->index(),j+1UL);
311  (~lhs)(i,j+2UL) = element->value() * B(element->index(),j+2UL);
312  (~lhs)(i,j+3UL) = element->value() * B(element->index(),j+3UL);
313  ++element;
314  for( ; element!=end; ++element ) {
315  (~lhs)(i,j ) += element->value() * B(element->index(),j );
316  (~lhs)(i,j+1UL) += element->value() * B(element->index(),j+1UL);
317  (~lhs)(i,j+2UL) += element->value() * B(element->index(),j+2UL);
318  (~lhs)(i,j+3UL) += element->value() * B(element->index(),j+3UL);
319  }
320  }
321  else {
322  reset( (~lhs)(i,j ) );
323  reset( (~lhs)(i,j+1UL) );
324  reset( (~lhs)(i,j+2UL) );
325  reset( (~lhs)(i,j+3UL) );
326  }
327  }
328  }
329  for( size_t j=jend; j<B.columns(); ++j ) {
330  for( size_t i=ii; i<iend; ++i ) {
331  const ConstIterator end( A.end(i) );
332  ConstIterator element( A.begin(i) );
333  if( element!=end ) {
334  (~lhs)(i,j) = element->value() * B(element->index(),j);
335  ++element;
336  for( ; element!=end; ++element ) {
337  (~lhs)(i,j) += element->value() * B(element->index(),j);
338  }
339  }
340  else {
341  reset( (~lhs)(i,j) );
342  }
343  }
344  }
345  }
346  }
348  //**********************************************************************************************
349 
350  //**Assignment to sparse matrices***************************************************************
362  template< typename MT // Type of the target sparse matrix
363  , bool SO > // Storage order of the target sparse matrix
364  friend inline void assign( SparseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
365  {
367 
368  typedef typename SelectType< SO, OppositeType, ResultType >::Type TmpType;
369 
375  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename TmpType::CompositeType );
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  const TmpType tmp( rhs );
381  assign( ~lhs, tmp );
382  }
384  //**********************************************************************************************
385 
386  //**Addition assignment to dense matrices*******************************************************
399  template< typename MT // Type of the target dense matrix
400  , bool SO > // Storage order of the target dense matrix
401  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
402  {
404 
405  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
406  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
407 
408  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
409 
410  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
411  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
412 
413  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
414  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
415  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
416  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
417  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
418  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
419 
420  const size_t block( 256UL );
421  BLAZE_INTERNAL_ASSERT( ( B.columns() - ( B.columns() % 4UL ) ) == ( B.columns() & size_t(-4) ), "Invalid end calculation" );
422  const size_t jend( B.columns() & size_t(-4) );
423 
424  for( size_t ii=0UL; ii<A.rows(); ii+=block ) {
425  const size_t iend( ( ii+block > A.rows() )?( A.rows() ):( ii+block ) );
426  for( size_t j=0UL; j<jend; j+=4UL ) {
427  for( size_t i=ii; i<iend; ++i ) {
428  const ConstIterator end( A.end(i) );
429  ConstIterator element( A.begin(i) );
430  for( ; element!=end; ++element ) {
431  (~lhs)(i,j ) += element->value() * B(element->index(),j );
432  (~lhs)(i,j+1UL) += element->value() * B(element->index(),j+1UL);
433  (~lhs)(i,j+2UL) += element->value() * B(element->index(),j+2UL);
434  (~lhs)(i,j+3UL) += element->value() * B(element->index(),j+3UL);
435  }
436  }
437  }
438  for( size_t j=jend; j<B.columns(); ++j ) {
439  for( size_t i=ii; i<iend; ++i ) {
440  const ConstIterator end( A.end(i) );
441  ConstIterator element( A.begin(i) );
442  for( ; element!=end; ++element ) {
443  (~lhs)(i,j) += element->value() * B(element->index(),j);
444  }
445  }
446  }
447  }
448  }
450  //**********************************************************************************************
451 
452  //**Addition assignment to sparse matrices******************************************************
453  // No special implementation for the addition assignment to sparse matrices.
454  //**********************************************************************************************
455 
456  //**Subtraction assignment to dense matrices****************************************************
469  template< typename MT // Type of the target dense matrix
470  , bool SO > // Storage order of the target dense matrix
471  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
472  {
474 
475  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
476  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
477 
478  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
479 
480  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
481  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
482 
483  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
484  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
485  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
486  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
487  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
488  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
489 
490  const size_t block( 256UL );
491  BLAZE_INTERNAL_ASSERT( ( B.columns() - ( B.columns() % 4UL ) ) == ( B.columns() & size_t(-4) ), "Invalid end calculation" );
492  const size_t jend( B.columns() & size_t(-4) );
493 
494  for( size_t ii=0UL; ii<A.rows(); ii+=block ) {
495  const size_t iend( ( ii+block > A.rows() )?( A.rows() ):( ii+block ) );
496  for( size_t j=0UL; j<jend; j+=4UL ) {
497  for( size_t i=ii; i<iend; ++i ) {
498  const ConstIterator end( A.end(i) );
499  ConstIterator element( A.begin(i) );
500  for( ; element!=end; ++element ) {
501  (~lhs)(i,j ) -= element->value() * B(element->index(),j );
502  (~lhs)(i,j+1UL) -= element->value() * B(element->index(),j+1UL);
503  (~lhs)(i,j+2UL) -= element->value() * B(element->index(),j+2UL);
504  (~lhs)(i,j+3UL) -= element->value() * B(element->index(),j+3UL);
505  }
506  }
507  }
508  for( size_t j=jend; j<B.columns(); ++j ) {
509  for( size_t i=ii; i<iend; ++i ) {
510  const ConstIterator end( A.end(i) );
511  ConstIterator element( A.begin(i) );
512  for( ; element!=end; ++element ) {
513  (~lhs)(i,j) -= element->value() * B(element->index(),j);
514  }
515  }
516  }
517  }
518  }
520  //**********************************************************************************************
521 
522  //**Subtraction assignment to sparse matrices***************************************************
523  // No special implementation for the subtraction assignment to sparse matrices.
524  //**********************************************************************************************
525 
526  //**Multiplication assignment to dense matrices*************************************************
527  // No special implementation for the multiplication assignment to dense matrices.
528  //**********************************************************************************************
529 
530  //**Multiplication assignment to sparse matrices************************************************
531  // No special implementation for the multiplication assignment to sparse matrices.
532  //**********************************************************************************************
533 
534  //**Compile time checks*************************************************************************
541  //**********************************************************************************************
542 };
543 //*************************************************************************************************
544 
545 
546 
547 
548 //=================================================================================================
549 //
550 // GLOBAL BINARY ARITHMETIC OPERATORS
551 //
552 //=================================================================================================
553 
554 //*************************************************************************************************
585 template< typename T1 // Type of the left-hand side sparse matrix
586  , typename T2 > // Type of the right-hand side dense matrix
587 inline const SMatTDMatMultExpr<T1,T2>
589 {
591 
592  if( (~lhs).columns() != (~rhs).rows() )
593  throw std::invalid_argument( "Matrix sizes do not match" );
594 
595  return SMatTDMatMultExpr<T1,T2>( ~lhs, ~rhs );
596 }
597 //*************************************************************************************************
598 
599 
600 
601 
602 //=================================================================================================
603 //
604 // GLOBAL OPERATORS
605 //
606 //=================================================================================================
607 
608 //*************************************************************************************************
621 template< typename MT1 // Type of the left-hand side sparse matrix
622  , typename MT2 > // Type of the right-hand side dense matrix
623 inline typename RowExprTrait< SMatTDMatMultExpr<MT1,MT2> >::Type
624  row( const SMatTDMatMultExpr<MT1,MT2>& dm, size_t index )
625 {
627 
628  return row( dm.leftOperand(), index ) * dm.rightOperand();
629 }
631 //*************************************************************************************************
632 
633 
634 //*************************************************************************************************
647 template< typename MT1 // Type of the left-hand side sparse matrix
648  , typename MT2 > // Type of the right-hand side dense matrix
649 inline typename ColumnExprTrait< SMatTDMatMultExpr<MT1,MT2> >::Type
650  column( const SMatTDMatMultExpr<MT1,MT2>& dm, size_t index )
651 {
653 
654  return dm.leftOperand() * column( dm.rightOperand(), index );
655 }
657 //*************************************************************************************************
658 
659 
660 
661 
662 //=================================================================================================
663 //
664 // EXPRESSION TRAIT SPECIALIZATIONS
665 //
666 //=================================================================================================
667 
668 //*************************************************************************************************
670 template< typename MT1, typename MT2, typename VT >
671 struct DMatDVecMultExprTrait< SMatTDMatMultExpr<MT1,MT2>, VT >
672 {
673  public:
674  //**********************************************************************************************
675  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
676  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
677  IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
678  , typename SMatDVecMultExprTrait< MT1, typename TDMatDVecMultExprTrait<MT2,VT>::Type >::Type
679  , INVALID_TYPE >::Type Type;
680  //**********************************************************************************************
681 };
683 //*************************************************************************************************
684 
685 
686 //*************************************************************************************************
688 template< typename MT1, typename MT2, typename VT >
689 struct DMatSVecMultExprTrait< SMatTDMatMultExpr<MT1,MT2>, VT >
690 {
691  public:
692  //**********************************************************************************************
693  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
694  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
695  IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
696  , typename SMatDVecMultExprTrait< MT1, typename TDMatSVecMultExprTrait<MT2,VT>::Type >::Type
697  , INVALID_TYPE >::Type Type;
698  //**********************************************************************************************
699 };
701 //*************************************************************************************************
702 
703 
704 //*************************************************************************************************
706 template< typename VT, typename MT1, typename MT2 >
707 struct TDVecDMatMultExprTrait< VT, SMatTDMatMultExpr<MT1,MT2> >
708 {
709  public:
710  //**********************************************************************************************
711  typedef typename SelectType< IsDenseVector<VT>::value && IsTransposeVector<VT>::value &&
712  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
713  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
714  , typename TDVecTDMatMultExprTrait< typename TDVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
715  , INVALID_TYPE >::Type Type;
716  //**********************************************************************************************
717 };
719 //*************************************************************************************************
720 
721 
722 //*************************************************************************************************
724 template< typename VT, typename MT1, typename MT2 >
725 struct TSVecDMatMultExprTrait< VT, SMatTDMatMultExpr<MT1,MT2> >
726 {
727  public:
728  //**********************************************************************************************
729  typedef typename SelectType< IsSparseVector<VT>::value && IsTransposeVector<VT>::value &&
730  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
731  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
732  , typename TSVecTDMatMultExprTrait< typename TSVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
733  , INVALID_TYPE >::Type Type;
734  //**********************************************************************************************
735 };
737 //*************************************************************************************************
738 
739 
740 //*************************************************************************************************
742 template< typename MT1, typename MT2 >
743 struct RowExprTrait< SMatTDMatMultExpr<MT1,MT2> >
744 {
745  public:
746  //**********************************************************************************************
747  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
748  //**********************************************************************************************
749 };
751 //*************************************************************************************************
752 
753 
754 //*************************************************************************************************
756 template< typename MT1, typename MT2 >
757 struct ColumnExprTrait< SMatTDMatMultExpr<MT1,MT2> >
758 {
759  public:
760  //**********************************************************************************************
761  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
762  //**********************************************************************************************
763 };
765 //*************************************************************************************************
766 
767 } // namespace blaze
768 
769 #endif