All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TSMatTDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TSMATTDMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TSMATTDMATMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
38 #include <blaze/math/shims/Reset.h>
59 #include <blaze/util/Assert.h>
60 #include <blaze/util/EnableIf.h>
61 #include <blaze/util/DisableIf.h>
62 #include <blaze/util/InvalidType.h>
64 #include <blaze/util/SelectType.h>
65 #include <blaze/util/Types.h>
67 
68 
69 namespace blaze {
70 
71 //=================================================================================================
72 //
73 // CLASS SMATDMATMULTEXPR
74 //
75 //=================================================================================================
76 
77 //*************************************************************************************************
84 template< typename MT1 // Type of the left-hand side dense matrix
85  , typename MT2 > // Type of the right-hand side sparse matrix
86 class TSMatTDMatMultExpr : public DenseMatrix< TSMatTDMatMultExpr<MT1,MT2>, true >
87  , private MatMatMultExpr
88  , private Computation
89 {
90  private:
91  //**Type definitions****************************************************************************
92  typedef typename MT1::ResultType RT1;
93  typedef typename MT2::ResultType RT2;
94  typedef typename MT1::ElementType ET1;
95  typedef typename MT2::ElementType ET2;
96  typedef typename MT1::CompositeType CT1;
97  typedef typename MT2::CompositeType CT2;
98  //**********************************************************************************************
99 
100  public:
101  //**Type definitions****************************************************************************
104  typedef typename ResultType::OppositeType OppositeType;
105  typedef typename ResultType::TransposeType TransposeType;
106  typedef typename ResultType::ElementType ElementType;
107  typedef const ElementType ReturnType;
108  typedef const ResultType CompositeType;
109 
111  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
112 
114  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
115 
117  typedef typename SelectType< IsComputation<MT1>::value, const RT1, CT1 >::Type LT;
118 
120  typedef typename SelectType< IsComputation<MT2>::value, const RT2, CT2 >::Type RT;
121  //**********************************************************************************************
122 
123  //**Compilation flags***************************************************************************
125  enum { vectorizable = 0 };
126  //**********************************************************************************************
127 
128  //**Constructor*********************************************************************************
134  explicit inline TSMatTDMatMultExpr( const MT1& lhs, const MT2& rhs )
135  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
136  , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
137  {
138  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
139  }
140  //**********************************************************************************************
141 
142  //**Access operator*****************************************************************************
149  inline ReturnType operator()( size_t i, size_t j ) const {
150  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
151  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
152 
153  ElementType tmp;
154 
155  if( lhs_.columns() != 0UL ) {
156  tmp = lhs_(i,0UL) * rhs_(0UL,j);
157  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
158  tmp += lhs_(i,k) * rhs_(k,j);
159  }
160  }
161  else {
162  reset( tmp );
163  }
164 
165  return tmp;
166  }
167  //**********************************************************************************************
168 
169  //**Rows function*******************************************************************************
174  inline size_t rows() const {
175  return lhs_.rows();
176  }
177  //**********************************************************************************************
178 
179  //**Columns function****************************************************************************
184  inline size_t columns() const {
185  return rhs_.columns();
186  }
187  //**********************************************************************************************
188 
189  //**Left operand access*************************************************************************
194  inline LeftOperand leftOperand() const {
195  return lhs_;
196  }
197  //**********************************************************************************************
198 
199  //**Right operand access************************************************************************
204  inline RightOperand rightOperand() const {
205  return rhs_;
206  }
207  //**********************************************************************************************
208 
209  //**********************************************************************************************
215  template< typename T >
216  inline bool canAlias( const T* alias ) const {
217  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
218  }
219  //**********************************************************************************************
220 
221  //**********************************************************************************************
227  template< typename T >
228  inline bool isAliased( const T* alias ) const {
229  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
230  }
231  //**********************************************************************************************
232 
233  private:
234  //**Member variables****************************************************************************
237  //**********************************************************************************************
238 
239  //**Default assignment to dense matrices********************************************************
253  template< typename MT // Type of the target dense matrix
254  , bool SO > // Storage order of the target dense matrix
255  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
256  assign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
257  {
259 
260  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
261  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
262 
263  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
264 
265  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
266  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
267 
268  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
269  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
270  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
271  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
272  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
273  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
274 
275  reset( ~lhs );
276 
277  const size_t block( 64UL );
278 
279  for( size_t jj=0UL; jj<B.columns(); jj+=block ) {
280  const size_t jend( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
281  for( size_t i=0UL; i<A.columns(); ++i ) {
282  const ConstIterator end( A.end(i) );
283  ConstIterator element( A.begin(i) );
284  for( ; element!=end; ++element ) {
285  for( size_t j=jj; j<jend; ++j ) {
286  if( isDefault( (~lhs)(element->index(),j) ) )
287  (~lhs)(element->index(),j) = element->value() * B(i,j);
288  else
289  (~lhs)(element->index(),j) += element->value() * B(i,j);
290  }
291  }
292  }
293  }
294  }
296  //**********************************************************************************************
297 
298  //**Optimized assignment to dense matrices******************************************************
312  template< typename MT // Type of the target dense matrix
313  , bool SO > // Storage order of the target dense matrix
314  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
315  assign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
316  {
318 
319  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
320  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
321 
322  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
323 
324  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
325  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
326 
327  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
328  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
329  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
330  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
331  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
332  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
333 
334  const size_t block( SO ? 64UL : 128UL );
335 
336  for( size_t jj=0UL; jj<B.columns(); jj+=block ) {
337  const size_t jend( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
338  for( size_t i=0UL; i<A.rows(); ++i ) {
339  for( size_t j=jj; j<jend; ++j ) {
340  reset( (~lhs)(i,j) );
341  }
342  }
343  for( size_t i=0UL; i<A.columns(); ++i )
344  {
345  const ConstIterator end( A.end(i) );
346  ConstIterator element( A.begin(i) );
347 
348  const size_t nonzeros( A.nonZeros(i) );
349 
350  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == ( nonzeros & size_t(-4) ), "Invalid end calculation" );
351  const size_t kend( nonzeros & size_t(-4) );
352 
353  for( size_t k=0UL; k<kend; k+=4UL ) {
354  const size_t i1( element->index() );
355  const ET1 v1( element->value() );
356  ++element;
357  const size_t i2( element->index() );
358  const ET1 v2( element->value() );
359  ++element;
360  const size_t i3( element->index() );
361  const ET1 v3( element->value() );
362  ++element;
363  const size_t i4( element->index() );
364  const ET1 v4( element->value() );
365  ++element;
366 
367  for( size_t j=jj; j<jend; ++j ) {
368  (~lhs)(i1,j) += v1 * B(i,j);
369  (~lhs)(i2,j) += v2 * B(i,j);
370  (~lhs)(i3,j) += v3 * B(i,j);
371  (~lhs)(i4,j) += v4 * B(i,j);
372  }
373  }
374 
375  for( ; element!=end; ++element ) {
376  for( size_t j=jj; j<jend; ++j ) {
377  (~lhs)(element->index(),j) += element->value() * B(i,j);
378  }
379  }
380  }
381  }
382  }
384  //**********************************************************************************************
385 
386  //**Assignment to sparse matrices***************************************************************
399  template< typename MT // Type of the target sparse matrix
400  , bool SO > // Storage order of the target sparse matrix
401  friend inline void assign( SparseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
402  {
404 
405  typedef typename SelectType< SO, ResultType, OppositeType >::Type TmpType;
406 
412  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename TmpType::CompositeType );
413 
414  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
415  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
416 
417  const TmpType tmp( rhs );
418  assign( ~lhs, tmp );
419  }
421  //**********************************************************************************************
422 
423  //**Addition assignment to dense matrices*******************************************************
436  template< typename MT // Type of the target dense matrix
437  , bool SO > // Storage order of the target dense matrix
438  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
439  {
441 
442  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
443  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
444 
445  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
446 
447  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
448  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
449 
450  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
451  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
452  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
453  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
454  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
455  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
456 
457  const size_t block( SO ? 64UL : 128UL );
458 
459  for( size_t jj=0UL; jj<B.columns(); jj+=block ) {
460  const size_t jend( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
461  for( size_t i=0UL; i<A.columns(); ++i )
462  {
463  const ConstIterator end( A.end(i) );
464  ConstIterator element( A.begin(i) );
465 
466  const size_t nonzeros( A.nonZeros(i) );
467 
468  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == ( nonzeros & size_t(-4) ), "Invalid end calculation" );
469  const size_t kend( nonzeros & size_t(-4) );
470 
471  for( size_t k=0UL; k<kend; k+=4UL ) {
472  const size_t i1( element->index() );
473  const ET1 v1( element->value() );
474  ++element;
475  const size_t i2( element->index() );
476  const ET1 v2( element->value() );
477  ++element;
478  const size_t i3( element->index() );
479  const ET1 v3( element->value() );
480  ++element;
481  const size_t i4( element->index() );
482  const ET1 v4( element->value() );
483  ++element;
484 
485  for( size_t j=jj; j<jend; ++j ) {
486  (~lhs)(i1,j) += v1 * B(i,j);
487  (~lhs)(i2,j) += v2 * B(i,j);
488  (~lhs)(i3,j) += v3 * B(i,j);
489  (~lhs)(i4,j) += v4 * B(i,j);
490  }
491  }
492 
493  for( ; element!=end; ++element ) {
494  for( size_t j=jj; j<jend; ++j ) {
495  (~lhs)(element->index(),j) += element->value() * B(i,j);
496  }
497  }
498  }
499  }
500  }
502  //**********************************************************************************************
503 
504  //**Addition assignment to sparse matrices******************************************************
505  // No special implementation for the addition assignment to sparse matrices.
506  //**********************************************************************************************
507 
508  //**Subtraction assignment to dense matrices****************************************************
521  template< typename MT // Type of the target dense matrix
522  , bool SO > // Storage order of the target dense matrix
523  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
524  {
526 
527  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
528  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
529 
530  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
531 
532  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
533  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
534 
535  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
536  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
537  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
538  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
539  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
540  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
541 
542  const size_t block( SO ? 64UL : 128UL );
543 
544  for( size_t jj=0UL; jj<B.columns(); jj+=block ) {
545  const size_t jend( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
546  for( size_t i=0UL; i<A.columns(); ++i )
547  {
548  const ConstIterator end( A.end(i) );
549  ConstIterator element( A.begin(i) );
550 
551  const size_t nonzeros( A.nonZeros(i) );
552 
553  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == ( nonzeros & size_t(-4) ), "Invalid end calculation" );
554  const size_t kend( nonzeros & size_t(-4) );
555 
556  for( size_t k=0UL; k<kend; k+=4UL ) {
557  const size_t i1( element->index() );
558  const ET1 v1( element->value() );
559  ++element;
560  const size_t i2( element->index() );
561  const ET1 v2( element->value() );
562  ++element;
563  const size_t i3( element->index() );
564  const ET1 v3( element->value() );
565  ++element;
566  const size_t i4( element->index() );
567  const ET1 v4( element->value() );
568  ++element;
569 
570  for( size_t j=jj; j<jend; ++j ) {
571  (~lhs)(i1,j) -= v1 * B(i,j);
572  (~lhs)(i2,j) -= v2 * B(i,j);
573  (~lhs)(i3,j) -= v3 * B(i,j);
574  (~lhs)(i4,j) -= v4 * B(i,j);
575  }
576  }
577 
578  for( ; element!=end; ++element ) {
579  for( size_t j=jj; j<jend; ++j ) {
580  (~lhs)(element->index(),j) -= element->value() * B(i,j);
581  }
582  }
583  }
584  }
585  }
587  //**********************************************************************************************
588 
589  //**Subtraction assignment to sparse matrices***************************************************
590  // No special implementation for the subtraction assignment to sparse matrices.
591  //**********************************************************************************************
592 
593  //**Multiplication assignment to dense matrices*************************************************
594  // No special implementation for the multiplication assignment to dense matrices.
595  //**********************************************************************************************
596 
597  //**Multiplication assignment to sparse matrices************************************************
598  // No special implementation for the multiplication assignment to sparse matrices.
599  //**********************************************************************************************
600 
601  //**Compile time checks*************************************************************************
608  //**********************************************************************************************
609 };
610 //*************************************************************************************************
611 
612 
613 
614 
615 //=================================================================================================
616 //
617 // GLOBAL BINARY ARITHMETIC OPERATORS
618 //
619 //=================================================================================================
620 
621 //*************************************************************************************************
650 template< typename T1 // Type of the left-hand side sparse matrix
651  , typename T2 > // Type of the right-hand side dense matrix
652 inline const TSMatTDMatMultExpr<T1,T2>
654 {
656 
657  if( (~lhs).columns() != (~rhs).rows() )
658  throw std::invalid_argument( "Matrix sizes do not match" );
659 
660  return TSMatTDMatMultExpr<T1,T2>( ~lhs, ~rhs );
661 }
662 //*************************************************************************************************
663 
664 
665 
666 
667 //=================================================================================================
668 //
669 // EXPRESSION TRAIT SPECIALIZATIONS
670 //
671 //=================================================================================================
672 
673 //*************************************************************************************************
675 template< typename MT1, typename MT2, typename VT >
676 struct TDMatDVecMultExprTrait< TSMatTDMatMultExpr<MT1,MT2>, VT >
677 {
678  public:
679  //**********************************************************************************************
680  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
681  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
682  IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
683  , typename TSMatDVecMultExprTrait< MT1, typename TDMatDVecMultExprTrait<MT2,VT>::Type >::Type
684  , INVALID_TYPE >::Type Type;
685  //**********************************************************************************************
686 };
688 //*************************************************************************************************
689 
690 
691 //*************************************************************************************************
693 template< typename MT1, typename MT2, typename VT >
694 struct TDMatSVecMultExprTrait< TSMatTDMatMultExpr<MT1,MT2>, VT >
695 {
696  public:
697  //**********************************************************************************************
698  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
699  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
700  IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
701  , typename TSMatDVecMultExprTrait< MT1, typename TDMatSVecMultExprTrait<MT2,VT>::Type >::Type
702  , INVALID_TYPE >::Type Type;
703  //**********************************************************************************************
704 };
706 //*************************************************************************************************
707 
708 
709 //*************************************************************************************************
711 template< typename VT, typename MT1, typename MT2 >
712 struct TDVecTDMatMultExprTrait< VT, TSMatTDMatMultExpr<MT1,MT2> >
713 {
714  public:
715  //**********************************************************************************************
716  typedef typename SelectType< IsDenseVector<VT>::value && !IsTransposeVector<VT>::value &&
717  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
718  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
719  , typename TDVecTDMatMultExprTrait< typename TDVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
720  , INVALID_TYPE >::Type Type;
721  //**********************************************************************************************
722 };
724 //*************************************************************************************************
725 
726 
727 //*************************************************************************************************
729 template< typename VT, typename MT1, typename MT2 >
730 struct TSVecTDMatMultExprTrait< VT, TSMatTDMatMultExpr<MT1,MT2> >
731 {
732  public:
733  //**********************************************************************************************
734  typedef typename SelectType< IsSparseVector<VT>::value && !IsTransposeVector<VT>::value &&
735  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
736  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
737  , typename TSVecTDMatMultExprTrait< typename TSVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
738  , INVALID_TYPE >::Type Type;
739  //**********************************************************************************************
740 };
742 //*************************************************************************************************
743 
744 
745 //*************************************************************************************************
747 template< typename MT1, typename MT2 >
748 struct RowExprTrait< TSMatTDMatMultExpr<MT1,MT2> >
749 {
750  public:
751  //**********************************************************************************************
752  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
753  //**********************************************************************************************
754 };
756 //*************************************************************************************************
757 
758 
759 //*************************************************************************************************
761 template< typename MT1, typename MT2 >
762 struct ColumnExprTrait< TSMatTDMatMultExpr<MT1,MT2> >
763 {
764  public:
765  //**********************************************************************************************
766  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
767  //**********************************************************************************************
768 };
770 //*************************************************************************************************
771 
772 } // namespace blaze
773 
774 #endif