All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TSMatDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TSMATDMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TSMATDMATMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
38 #include <blaze/math/shims/Reset.h>
64 #include <blaze/util/Assert.h>
65 #include <blaze/util/DisableIf.h>
66 #include <blaze/util/EnableIf.h>
67 #include <blaze/util/InvalidType.h>
69 #include <blaze/util/SelectType.h>
70 #include <blaze/util/Types.h>
72 
73 
74 namespace blaze {
75 
76 //=================================================================================================
77 //
78 // CLASS SMATDMATMULTEXPR
79 //
80 //=================================================================================================
81 
82 //*************************************************************************************************
89 template< typename MT1 // Type of the left-hand side dense matrix
90  , typename MT2 > // Type of the right-hand side sparse matrix
91 class TSMatDMatMultExpr : public DenseMatrix< TSMatDMatMultExpr<MT1,MT2>, true >
92  , private MatMatMultExpr
93  , private Computation
94 {
95  private:
96  //**Type definitions****************************************************************************
97  typedef typename MT1::ResultType RT1;
98  typedef typename MT2::ResultType RT2;
99  typedef typename MT1::ElementType ET1;
100  typedef typename MT2::ElementType ET2;
101  typedef typename MT1::CompositeType CT1;
102  typedef typename MT2::CompositeType CT2;
103  //**********************************************************************************************
104 
105  public:
106  //**Type definitions****************************************************************************
109  typedef typename ResultType::OppositeType OppositeType;
110  typedef typename ResultType::TransposeType TransposeType;
111  typedef typename ResultType::ElementType ElementType;
112  typedef const ElementType ReturnType;
113  typedef const ResultType CompositeType;
114 
116  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
117 
119  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
120 
122  typedef typename SelectType< IsComputation<MT1>::value, const RT1, CT1 >::Type LT;
123 
125  typedef typename SelectType< IsComputation<MT2>::value, const RT2, CT2 >::Type RT;
126  //**********************************************************************************************
127 
128  //**Compilation flags***************************************************************************
130  enum { vectorizable = 0 };
131  //**********************************************************************************************
132 
133  //**Constructor*********************************************************************************
139  explicit inline TSMatDMatMultExpr( const MT1& lhs, const MT2& rhs )
140  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
141  , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
142  {
143  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
144  }
145  //**********************************************************************************************
146 
147  //**Access operator*****************************************************************************
154  inline ReturnType operator()( size_t i, size_t j ) const {
155  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
156  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
157 
158  ElementType tmp;
159 
160  if( lhs_.columns() != 0UL ) {
161  tmp = lhs_(i,0UL) * rhs_(0UL,j);
162  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
163  tmp += lhs_(i,k) * rhs_(k,j);
164  }
165  }
166  else {
167  reset( tmp );
168  }
169 
170  return tmp;
171  }
172  //**********************************************************************************************
173 
174  //**Rows function*******************************************************************************
179  inline size_t rows() const {
180  return lhs_.rows();
181  }
182  //**********************************************************************************************
183 
184  //**Columns function****************************************************************************
189  inline size_t columns() const {
190  return rhs_.columns();
191  }
192  //**********************************************************************************************
193 
194  //**Left operand access*************************************************************************
199  inline LeftOperand leftOperand() const {
200  return lhs_;
201  }
202  //**********************************************************************************************
203 
204  //**Right operand access************************************************************************
209  inline RightOperand rightOperand() const {
210  return rhs_;
211  }
212  //**********************************************************************************************
213 
214  //**********************************************************************************************
220  template< typename T >
221  inline bool canAlias( const T* alias ) const {
222  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
223  }
224  //**********************************************************************************************
225 
226  //**********************************************************************************************
232  template< typename T >
233  inline bool isAliased( const T* alias ) const {
234  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
235  }
236  //**********************************************************************************************
237 
238  private:
239  //**Member variables****************************************************************************
242  //**********************************************************************************************
243 
244  //**Default assignment to dense matrices********************************************************
258  template< typename MT // Type of the target dense matrix
259  , bool SO > // Storage order of the target dense matrix
260  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
261  assign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
262  {
264 
265  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
266  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
267 
268  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
269 
270  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
271  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
272 
273  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
274  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
275  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
276  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
277  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
278  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
279 
280  reset( ~lhs );
281 
282  const size_t block( SO ? 8UL : 256UL );
283 
284  for( size_t jj=0UL; jj<B.columns(); jj+=block ) {
285  const size_t jend( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
286  for( size_t i=0UL; i<A.columns(); ++i ) {
287  const ConstIterator end( A.end(i) );
288  ConstIterator element( A.begin(i) );
289  for( ; element!=end; ++element ) {
290  for( size_t j=jj; j<jend; ++j ) {
291  if( isDefault( (~lhs)(element->index(),j) ) )
292  (~lhs)(element->index(),j) = element->value() * B(i,j);
293  else
294  (~lhs)(element->index(),j) += element->value() * B(i,j);
295  }
296  }
297  }
298  }
299  }
301  //**********************************************************************************************
302 
303  //**Optimized assignment to dense matrices******************************************************
317  template< typename MT // Type of the target dense matrix
318  , bool SO > // Storage order of the target dense matrix
319  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
320  assign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
321  {
323 
324  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
325  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
326 
327  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
328 
329  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
330  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
331 
332  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
333  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
334  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
335  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
336  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
337  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
338 
339  const size_t block( SO ? 8UL : 256UL );
340 
341  for( size_t jj=0UL; jj<B.columns(); jj+=block ) {
342  const size_t jend( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
343  for( size_t i=0UL; i<A.rows(); ++i ) {
344  for( size_t j=jj; j<jend; ++j ) {
345  reset( (~lhs)(i,j) );
346  }
347  }
348  for( size_t i=0UL; i<A.columns(); ++i )
349  {
350  const ConstIterator end( A.end(i) );
351  ConstIterator element( A.begin(i) );
352 
353  const size_t nonzeros( A.nonZeros(i) );
354 
355  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == ( nonzeros & size_t(-4) ), "Invalid end calculation" );
356  const size_t kend( nonzeros & size_t(-4) );
357 
358  for( size_t k=0UL; k<kend; k+=4UL ) {
359  const size_t i1( element->index() );
360  const ET1 v1( element->value() );
361  ++element;
362  const size_t i2( element->index() );
363  const ET1 v2( element->value() );
364  ++element;
365  const size_t i3( element->index() );
366  const ET1 v3( element->value() );
367  ++element;
368  const size_t i4( element->index() );
369  const ET1 v4( element->value() );
370  ++element;
371 
372  for( size_t j=jj; j<jend; ++j ) {
373  (~lhs)(i1,j) += v1 * B(i,j);
374  (~lhs)(i2,j) += v2 * B(i,j);
375  (~lhs)(i3,j) += v3 * B(i,j);
376  (~lhs)(i4,j) += v4 * B(i,j);
377  }
378  }
379 
380  for( ; element!=end; ++element ) {
381  for( size_t j=jj; j<jend; ++j ) {
382  (~lhs)(element->index(),j) += element->value() * B(i,j);
383  }
384  }
385  }
386  }
387  }
389  //**********************************************************************************************
390 
391  //**Assignment to sparse matrices***************************************************************
403  template< typename MT // Type of the target sparse matrix
404  , bool SO > // Storage order of the target sparse matrix
405  friend inline void assign( SparseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
406  {
408 
409  typedef typename SelectType< SO, ResultType, OppositeType >::Type TmpType;
410 
416  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename TmpType::CompositeType );
417 
418  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
419  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
420 
421  const TmpType tmp( rhs );
422  assign( ~lhs, tmp );
423  }
425  //**********************************************************************************************
426 
427  //**Addition assignment to dense matrices*******************************************************
440  template< typename MT // Type of the target dense matrix
441  , bool SO > // Storage order of the target dense matrix
442  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
443  {
445 
446  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
447  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
448 
449  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
450 
451  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
452  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
453 
454  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
455  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
456  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
457  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
458  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
459  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
460 
461  const size_t block( SO ? 8UL : 256UL );
462 
463  for( size_t jj=0UL; jj<B.columns(); jj+=block ) {
464  const size_t jend( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
465  for( size_t i=0UL; i<A.columns(); ++i )
466  {
467  const ConstIterator end( A.end(i) );
468  ConstIterator element( A.begin(i) );
469 
470  const size_t nonzeros( A.nonZeros(i) );
471 
472  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == ( nonzeros & size_t(-4) ), "Invalid end calculation" );
473  const size_t kend( nonzeros & size_t(-4) );
474 
475  for( size_t k=0UL; k<kend; k+=4UL ) {
476  const size_t i1( element->index() );
477  const ET1 v1( element->value() );
478  ++element;
479  const size_t i2( element->index() );
480  const ET1 v2( element->value() );
481  ++element;
482  const size_t i3( element->index() );
483  const ET1 v3( element->value() );
484  ++element;
485  const size_t i4( element->index() );
486  const ET1 v4( element->value() );
487  ++element;
488 
489  for( size_t j=jj; j<jend; ++j ) {
490  (~lhs)(i1,j) += v1 * B(i,j);
491  (~lhs)(i2,j) += v2 * B(i,j);
492  (~lhs)(i3,j) += v3 * B(i,j);
493  (~lhs)(i4,j) += v4 * B(i,j);
494  }
495  }
496 
497  for( ; element!=end; ++element ) {
498  for( size_t j=jj; j<jend; ++j ) {
499  (~lhs)(element->index(),j) += element->value() * B(i,j);
500  }
501  }
502  }
503  }
504  }
506  //**********************************************************************************************
507 
508  //**Addition assignment to sparse matrices******************************************************
509  // No special implementation for the addition assignment to sparse matrices.
510  //**********************************************************************************************
511 
512  //**Subtraction assignment to dense matrices****************************************************
525  template< typename MT // Type of the target dense matrix
526  , bool SO > // Storage order of the target dense matrix
527  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
528  {
530 
531  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
532  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
533 
534  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
535 
536  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
537  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
538 
539  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
540  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
541  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
542  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
543  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
544  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
545 
546  const size_t block( SO ? 8UL : 256UL );
547 
548  for( size_t jj=0UL; jj<B.columns(); jj+=block ) {
549  const size_t jend( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
550  for( size_t i=0UL; i<A.columns(); ++i )
551  {
552  const ConstIterator end( A.end(i) );
553  ConstIterator element( A.begin(i) );
554 
555  const size_t nonzeros( A.nonZeros(i) );
556 
557  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == ( nonzeros & size_t(-4) ), "Invalid end calculation" );
558  const size_t kend( nonzeros & size_t(-4) );
559 
560  for( size_t k=0UL; k<kend; k+=4UL ) {
561  const size_t i1( element->index() );
562  const ET1 v1( element->value() );
563  ++element;
564  const size_t i2( element->index() );
565  const ET1 v2( element->value() );
566  ++element;
567  const size_t i3( element->index() );
568  const ET1 v3( element->value() );
569  ++element;
570  const size_t i4( element->index() );
571  const ET1 v4( element->value() );
572  ++element;
573 
574  for( size_t j=jj; j<jend; ++j ) {
575  (~lhs)(i1,j) -= v1 * B(i,j);
576  (~lhs)(i2,j) -= v2 * B(i,j);
577  (~lhs)(i3,j) -= v3 * B(i,j);
578  (~lhs)(i4,j) -= v4 * B(i,j);
579  }
580  }
581 
582  for( ; element!=end; ++element ) {
583  for( size_t j=jj; j<jend; ++j ) {
584  (~lhs)(element->index(),j) -= element->value() * B(i,j);
585  }
586  }
587  }
588  }
589  }
591  //**********************************************************************************************
592 
593  //**Subtraction assignment to sparse matrices***************************************************
594  // No special implementation for the subtraction assignment to sparse matrices.
595  //**********************************************************************************************
596 
597  //**Multiplication assignment to dense matrices*************************************************
598  // No special implementation for the multiplication assignment to dense matrices.
599  //**********************************************************************************************
600 
601  //**Multiplication assignment to sparse matrices************************************************
602  // No special implementation for the multiplication assignment to sparse matrices.
603  //**********************************************************************************************
604 
605  //**Compile time checks*************************************************************************
612  //**********************************************************************************************
613 };
614 //*************************************************************************************************
615 
616 
617 
618 
619 //=================================================================================================
620 //
621 // GLOBAL BINARY ARITHMETIC OPERATORS
622 //
623 //=================================================================================================
624 
625 //*************************************************************************************************
656 template< typename T1 // Type of the left-hand side sparse matrix
657  , typename T2 > // Type of the right-hand side dense matrix
658 inline const TSMatDMatMultExpr<T1,T2>
660 {
662 
663  if( (~lhs).columns() != (~rhs).rows() )
664  throw std::invalid_argument( "Matrix sizes do not match" );
665 
666  return TSMatDMatMultExpr<T1,T2>( ~lhs, ~rhs );
667 }
668 //*************************************************************************************************
669 
670 
671 
672 
673 //=================================================================================================
674 //
675 // EXPRESSION TRAIT SPECIALIZATIONS
676 //
677 //=================================================================================================
678 
679 //*************************************************************************************************
681 template< typename MT1, typename MT2, typename VT >
682 struct TDMatDVecMultExprTrait< TSMatDMatMultExpr<MT1,MT2>, VT >
683 {
684  public:
685  //**********************************************************************************************
686  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
687  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
688  IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
689  , typename TSMatDVecMultExprTrait< MT1, typename DMatDVecMultExprTrait<MT2,VT>::Type >::Type
690  , INVALID_TYPE >::Type Type;
691  //**********************************************************************************************
692 };
694 //*************************************************************************************************
695 
696 
697 //*************************************************************************************************
699 template< typename MT1, typename MT2, typename VT >
700 struct TDMatSVecMultExprTrait< TSMatDMatMultExpr<MT1,MT2>, VT >
701 {
702  public:
703  //**********************************************************************************************
704  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
705  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
706  IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
707  , typename TSMatDVecMultExprTrait< MT1, typename DMatSVecMultExprTrait<MT2,VT>::Type >::Type
708  , INVALID_TYPE >::Type Type;
709  //**********************************************************************************************
710 };
712 //*************************************************************************************************
713 
714 
715 //*************************************************************************************************
717 template< typename VT, typename MT1, typename MT2 >
718 struct TDVecTDMatMultExprTrait< VT, TSMatDMatMultExpr<MT1,MT2> >
719 {
720  public:
721  //**********************************************************************************************
722  typedef typename SelectType< IsDenseVector<VT>::value && IsTransposeVector<VT>::value &&
723  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
724  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
725  , typename TDVecDMatMultExprTrait< typename TDVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
726  , INVALID_TYPE >::Type Type;
727  //**********************************************************************************************
728 };
730 //*************************************************************************************************
731 
732 
733 //*************************************************************************************************
735 template< typename VT, typename MT1, typename MT2 >
736 struct TSVecTDMatMultExprTrait< VT, TSMatDMatMultExpr<MT1,MT2> >
737 {
738  public:
739  //**********************************************************************************************
740  typedef typename SelectType< IsSparseVector<VT>::value && IsTransposeVector<VT>::value &&
741  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
742  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
743  , typename TDVecDMatMultExprTrait< typename TDVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
744  , INVALID_TYPE >::Type Type;
745  //**********************************************************************************************
746 };
748 //*************************************************************************************************
749 
750 
751 //*************************************************************************************************
753 template< typename MT1, typename MT2 >
754 struct RowExprTrait< TSMatDMatMultExpr<MT1,MT2> >
755 {
756  public:
757  //**********************************************************************************************
758  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
759  //**********************************************************************************************
760 };
762 //*************************************************************************************************
763 
764 
765 //*************************************************************************************************
767 template< typename MT1, typename MT2 >
768 struct ColumnExprTrait< TSMatDMatMultExpr<MT1,MT2> >
769 {
770  public:
771  //**********************************************************************************************
772  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
773  //**********************************************************************************************
774 };
776 //*************************************************************************************************
777 
778 } // namespace blaze
779 
780 #endif