DMatSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_DMATSMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_DMATSMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <blaze/math/Aliases.h>
51 #include <blaze/math/Exception.h>
56 #include <blaze/math/Functions.h>
58 #include <blaze/math/shims/Reset.h>
97 #include <blaze/util/Assert.h>
99 #include <blaze/util/DisableIf.h>
100 #include <blaze/util/EnableIf.h>
102 #include <blaze/util/InvalidType.h>
104 #include <blaze/util/mpl/And.h>
105 #include <blaze/util/mpl/If.h>
106 #include <blaze/util/mpl/Or.h>
107 #include <blaze/util/Types.h>
108 
109 
110 namespace blaze {
111 
112 //=================================================================================================
113 //
114 // CLASS DMATSMATMULTEXPR
115 //
116 //=================================================================================================
117 
118 //*************************************************************************************************
125 template< typename MT1 // Type of the left-hand side dense matrix
126  , typename MT2 > // Type of the right-hand side sparse matrix
127 class DMatSMatMultExpr : public DenseMatrix< DMatSMatMultExpr<MT1,MT2>, false >
128  , private MatMatMultExpr
129  , private Computation
130 {
131  private:
132  //**Type definitions****************************************************************************
139  //**********************************************************************************************
140 
141  //**********************************************************************************************
143  enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
144  //**********************************************************************************************
145 
146  //**********************************************************************************************
148  enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
149  //**********************************************************************************************
150 
151  //**********************************************************************************************
153 
158  template< typename T1, typename T2, typename T3 >
159  struct CanExploitSymmetry {
160  enum : bool { value = ( IsSymmetric<T2>::value || IsSymmetric<T3>::value ) };
161  };
163  //**********************************************************************************************
164 
165  //**********************************************************************************************
167 
171  template< typename T1, typename T2, typename T3 >
172  struct IsEvaluationRequired {
173  enum : bool { value = ( evaluateLeft || evaluateRight ) &&
174  !CanExploitSymmetry<T1,T2,T3>::value };
175  };
177  //**********************************************************************************************
178 
179  //**********************************************************************************************
181 
184  template< typename T1, typename T2, typename T3 >
185  struct UseOptimizedKernel {
186  enum : bool { value = useOptimizedKernels &&
187  !IsDiagonal<T2>::value &&
188  !IsResizable< ElementType_<T1> >::value };
189  };
191  //**********************************************************************************************
192 
193  //**********************************************************************************************
195 
198  template< typename T1, typename T2, typename T3 >
199  struct UseDefaultKernel {
200  enum : bool { value = !UseOptimizedKernel<T1,T2,T3>::value };
201  };
203  //**********************************************************************************************
204 
205  public:
206  //**Type definitions****************************************************************************
212  typedef const ElementType ReturnType;
213  typedef const ResultType CompositeType;
214 
216  typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
217 
219  typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
220 
223 
226  //**********************************************************************************************
227 
228  //**Compilation flags***************************************************************************
230  enum : bool { simdEnabled = false };
231 
233  enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
234  !evaluateRight && MT2::smpAssignable };
235  //**********************************************************************************************
236 
237  //**Constructor*********************************************************************************
243  explicit inline DMatSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
244  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
245  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
246  {
247  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
248  }
249  //**********************************************************************************************
250 
251  //**Access operator*****************************************************************************
258  inline ReturnType operator()( size_t i, size_t j ) const {
259  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
260  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
261 
262  if( IsDiagonal<MT1>::value ) {
263  return lhs_(i,i) * rhs_(i,j);
264  }
265  else if( IsDiagonal<MT2>::value ) {
266  return lhs_(i,j) * rhs_(j,j);
267  }
269  const size_t begin( ( IsUpper<MT1>::value )
270  ?( ( IsLower<MT2>::value )
271  ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
272  , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
273  :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
274  :( ( IsLower<MT2>::value )
275  ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
276  :( 0UL ) ) );
277  const size_t end( ( IsLower<MT1>::value )
278  ?( ( IsUpper<MT2>::value )
279  ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
280  , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
281  :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
282  :( ( IsUpper<MT2>::value )
283  ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
284  :( lhs_.columns() ) ) );
285 
286  if( begin >= end ) return ElementType();
287 
288  const size_t n( end - begin );
289 
290  return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
291  }
292  else {
293  return row( lhs_, i ) * column( rhs_, j );
294  }
295  }
296  //**********************************************************************************************
297 
298  //**At function*********************************************************************************
306  inline ReturnType at( size_t i, size_t j ) const {
307  if( i >= lhs_.rows() ) {
308  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
309  }
310  if( j >= rhs_.columns() ) {
311  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
312  }
313  return (*this)(i,j);
314  }
315  //**********************************************************************************************
316 
317  //**Rows function*******************************************************************************
322  inline size_t rows() const noexcept {
323  return lhs_.rows();
324  }
325  //**********************************************************************************************
326 
327  //**Columns function****************************************************************************
332  inline size_t columns() const noexcept {
333  return rhs_.columns();
334  }
335  //**********************************************************************************************
336 
337  //**Left operand access*************************************************************************
342  inline LeftOperand leftOperand() const noexcept {
343  return lhs_;
344  }
345  //**********************************************************************************************
346 
347  //**Right operand access************************************************************************
352  inline RightOperand rightOperand() const noexcept {
353  return rhs_;
354  }
355  //**********************************************************************************************
356 
357  //**********************************************************************************************
363  template< typename T >
364  inline bool canAlias( const T* alias ) const noexcept {
365  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
366  }
367  //**********************************************************************************************
368 
369  //**********************************************************************************************
375  template< typename T >
376  inline bool isAliased( const T* alias ) const noexcept {
377  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
378  }
379  //**********************************************************************************************
380 
381  //**********************************************************************************************
386  inline bool isAligned() const noexcept {
387  return lhs_.isAligned();
388  }
389  //**********************************************************************************************
390 
391  //**********************************************************************************************
396  inline bool canSMPAssign() const noexcept {
397  return ( rows() * columns() >= SMP_DMATSMATMULT_THRESHOLD );
398  }
399  //**********************************************************************************************
400 
401  private:
402  //**Member variables****************************************************************************
403  LeftOperand lhs_;
404  RightOperand rhs_;
405  //**********************************************************************************************
406 
407  //**Assignment to dense matrices****************************************************************
420  template< typename MT // Type of the target dense matrix
421  , bool SO > // Storage order of the target dense matrix
423  assign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& 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  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
431  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
432 
433  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
434  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
435  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
436  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
437  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
438  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
439 
440  DMatSMatMultExpr::selectAssignKernel( ~lhs, A, B );
441  }
443  //**********************************************************************************************
444 
445  //**Assignment to dense matrices (kernel selection)*********************************************
456  template< typename MT3 // Type of the left-hand side target matrix
457  , typename MT4 // Type of the left-hand side matrix operand
458  , typename MT5 > // Type of the right-hand side matrix operand
459  static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
460  {
461  if( C.rows() * C.columns() < DMATSMATMULT_THRESHOLD )
462  selectSmallAssignKernel( C, A, B );
463  else
464  selectLargeAssignKernel( C, A, B );
465  }
467  //**********************************************************************************************
468 
469  //**Default assignment to dense matrices********************************************************
483  template< typename MT3 // Type of the left-hand side target matrix
484  , typename MT4 // Type of the left-hand side matrix operand
485  , typename MT5 > // Type of the right-hand side matrix operand
486  static inline void selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
487  {
488  typedef ConstIterator_<MT5> ConstIterator;
489 
490  reset( C );
491 
492  for( size_t j=0UL; j<B.rows(); ++j )
493  {
494  if( IsDiagonal<MT4>::value )
495  {
496  ConstIterator element( B.begin(j) );
497  const ConstIterator end( B.end(j) );
498 
499  for( ; element!=end; ++element ) {
500  C(j,element->index()) = A(j,j) * element->value();
501  }
502  }
503  else
504  {
505  const size_t iibegin( ( IsLower<MT4>::value )
506  ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
507  :( 0UL ) );
508  const size_t iiend( ( IsUpper<MT4>::value )
509  ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
510  :( A.rows() ) );
511  BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
512 
513  for( size_t ii=iibegin; ii<iiend; ii+=8UL )
514  {
515  ConstIterator element( B.begin(j) );
516  const ConstIterator end( B.end(j) );
517  const size_t iend( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
518 
519  for( ; element!=end; ++element ) {
520  for( size_t i=ii; i<iend; ++i ) {
521  if( isDefault( C(i,element->index()) ) )
522  C(i,element->index()) = A(i,j) * element->value();
523  else
524  C(i,element->index()) += A(i,j) * element->value();
525  }
526  }
527  }
528  }
529  }
530  }
532  //**********************************************************************************************
533 
534  //**Default assignment to dense matrices (small matrices)***************************************
547  template< typename MT3 // Type of the left-hand side target matrix
548  , typename MT4 // Type of the left-hand side matrix operand
549  , typename MT5 > // Type of the right-hand side matrix operand
550  static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
551  selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
552  {
553  selectDefaultAssignKernel( C, A, B );
554  }
556  //**********************************************************************************************
557 
558  //**Optimized assignment to dense matrices (small matrices)*************************************
573  template< typename MT3 // Type of the left-hand side target matrix
574  , typename MT4 // Type of the left-hand side matrix operand
575  , typename MT5 > // Type of the right-hand side matrix operand
576  static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
577  selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
578  {
579  typedef ConstIterator_<MT5> ConstIterator;
580 
581  reset( C );
582 
583  for( size_t j=0UL; j<B.rows(); ++j )
584  {
585  const size_t iibegin( ( IsLower<MT4>::value )
586  ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
587  :( 0UL ) );
588  const size_t iiend( ( IsUpper<MT4>::value )
589  ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
590  :( A.rows() ) );
591  BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
592 
593  for( size_t ii=iibegin; ii<iiend; ii+=8UL )
594  {
595  ConstIterator element( B.begin(j) );
596  const ConstIterator end( B.end(j) );
597  const size_t iend( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
598 
599  for( ; element!=end; ++element ) {
600  for( size_t i=ii; i<iend; ++i ) {
601  C(i,element->index()) += A(i,j) * element->value();
602  }
603  }
604  }
605  }
606  }
608  //**********************************************************************************************
609 
610  //**Default assignment to dense matrices (large matrices)***************************************
623  template< typename MT3 // Type of the left-hand side target matrix
624  , typename MT4 // Type of the left-hand side matrix operand
625  , typename MT5 > // Type of the right-hand side matrix operand
626  static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
627  selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
628  {
629  selectDefaultAssignKernel( C, A, B );
630  }
632  //**********************************************************************************************
633 
634  //**Optimized assignment to dense matrices (large matrices)*************************************
649  template< typename MT3 // Type of the left-hand side target matrix
650  , typename MT4 // Type of the left-hand side matrix operand
651  , typename MT5 > // Type of the right-hand side matrix operand
652  static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
653  selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
654  {
656 
657  const OppositeType_<MT5> tmp( serial( B ) );
658  assign( C, A * tmp );
659  }
661  //**********************************************************************************************
662 
663  //**Assignment to sparse matrices***************************************************************
676  template< typename MT // Type of the target sparse matrix
677  , bool SO > // Storage order of the target sparse matrix
678  friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
679  assign( SparseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
680  {
682 
683  typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
684 
690  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
691 
692  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
693  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
694 
695  const TmpType tmp( serial( rhs ) );
696  assign( ~lhs, tmp );
697  }
699  //**********************************************************************************************
700 
701  //**Restructuring assignment********************************************************************
716  template< typename MT // Type of the target matrix
717  , bool SO > // Storage order of the target matrix
718  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
719  assign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
720  {
722 
724 
725  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
726  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
727 
728  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
729  assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
730  else if( IsSymmetric<MT1>::value )
731  assign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
732  else
733  assign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
734  }
736  //**********************************************************************************************
737 
738  //**Addition assignment to dense matrices*******************************************************
751  template< typename MT // Type of the target dense matrix
752  , bool SO > // Storage order of the target dense matrix
753  friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
754  addAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
755  {
757 
758  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
759  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
760 
761  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
762  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
763 
764  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
765  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
766  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
767  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
768  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
769  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
770 
771  DMatSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
772  }
774  //**********************************************************************************************
775 
776  //**Addition assignment to dense matrices (kernel selection)************************************
787  template< typename MT3 // Type of the left-hand side target matrix
788  , typename MT4 // Type of the left-hand side matrix operand
789  , typename MT5 > // Type of the right-hand side matrix operand
790  static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
791  {
792  if( C.rows() * C.columns() < DMATSMATMULT_THRESHOLD )
793  selectSmallAddAssignKernel( C, A, B );
794  else
795  selectLargeAddAssignKernel( C, A, B );
796  }
798  //**********************************************************************************************
799 
800  //**Optimized addition assignment to dense matrices (small matrices)****************************
814  template< typename MT3 // Type of the left-hand side target matrix
815  , typename MT4 // Type of the left-hand side matrix operand
816  , typename MT5 > // Type of the right-hand side matrix operand
817  static inline void selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
818  {
819  typedef ConstIterator_<MT5> ConstIterator;
820 
821  for( size_t j=0UL; j<B.rows(); ++j )
822  {
823  if( IsDiagonal<MT4>::value )
824  {
825  ConstIterator element( B.begin(j) );
826  const ConstIterator end( B.end(j) );
827 
828  for( ; element!=end; ++element ) {
829  C(j,element->index()) += A(j,j) * element->value();
830  }
831  }
832  else
833  {
834  const size_t iibegin( ( IsLower<MT4>::value )
835  ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
836  :( 0UL ) );
837  const size_t iiend( ( IsUpper<MT4>::value )
838  ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
839  :( A.rows() ) );
840  BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
841 
842  for( size_t ii=iibegin; ii<iiend; ii+=8UL )
843  {
844  ConstIterator element( B.begin(j) );
845  const ConstIterator end( B.end(j) );
846  const size_t iend( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
847 
848  for( ; element!=end; ++element ) {
849  for( size_t i=ii; i<iend; ++i ) {
850  C(i,element->index()) += A(i,j) * element->value();
851  }
852  }
853  }
854  }
855  }
856  }
858  //**********************************************************************************************
859 
860  //**Optimized addition assignment to dense matrices (large matrices)****************************
874  template< typename MT3 // Type of the left-hand side target matrix
875  , typename MT4 // Type of the left-hand side matrix operand
876  , typename MT5 > // Type of the right-hand side matrix operand
877  static inline void selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
878  {
880 
881  const OppositeType_<MT5> tmp( serial( B ) );
882  addAssign( C, A * tmp );
883  }
885  //**********************************************************************************************
886 
887  //**Restructuring addition assignment***********************************************************
902  template< typename MT // Type of the target matrix
903  , bool SO > // Storage order of the target matrix
904  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
905  addAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
906  {
908 
910 
911  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
912  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
913 
914  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
915  addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
916  else if( IsSymmetric<MT1>::value )
917  addAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
918  else
919  addAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
920  }
922  //**********************************************************************************************
923 
924  //**Addition assignment to sparse matrices******************************************************
925  // No special implementation for the addition assignment to sparse matrices.
926  //**********************************************************************************************
927 
928  //**Subtraction assignment to dense matrices****************************************************
941  template< typename MT // Type of the target dense matrix
942  , bool SO > // Storage order of the target dense matrix
943  friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
944  subAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
945  {
947 
948  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
949  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
950 
951  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
952  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
953 
954  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
955  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
956  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
957  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
958  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
959  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
960 
961  DMatSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
962  }
964  //**********************************************************************************************
965 
966  //**Subtraction assignment to dense matrices (kernel selection)*********************************
977  template< typename MT3 // Type of the left-hand side target matrix
978  , typename MT4 // Type of the left-hand side matrix operand
979  , typename MT5 > // Type of the right-hand side matrix operand
980  static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
981  {
982  if( C.rows() * C.columns() < DMATSMATMULT_THRESHOLD )
983  selectSmallSubAssignKernel( C, A, B );
984  else
985  selectLargeSubAssignKernel( C, A, B );
986  }
988  //**********************************************************************************************
989 
990  //**Optimized subtraction assignment to dense matrices (small matrices)*************************
1004  template< typename MT3 // Type of the left-hand side target matrix
1005  , typename MT4 // Type of the left-hand side matrix operand
1006  , typename MT5 > // Type of the right-hand side matrix operand
1007  static inline void selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1008  {
1009  typedef ConstIterator_<MT5> ConstIterator;
1010 
1011  for( size_t j=0UL; j<B.rows(); ++j )
1012  {
1013  if( IsDiagonal<MT4>::value )
1014  {
1015  ConstIterator element( B.begin(j) );
1016  const ConstIterator end( B.end(j) );
1017 
1018  for( ; element!=end; ++element ) {
1019  C(j,element->index()) -= A(j,j) * element->value();
1020  }
1021  }
1022  else
1023  {
1024  const size_t iibegin( ( IsLower<MT4>::value )
1025  ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
1026  :( 0UL ) );
1027  const size_t iiend( ( IsUpper<MT4>::value )
1028  ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
1029  :( A.rows() ) );
1030  BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
1031 
1032  for( size_t ii=iibegin; ii<iiend; ii+=8UL )
1033  {
1034  ConstIterator element( B.begin(j) );
1035  const ConstIterator end( B.end(j) );
1036  const size_t iend( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
1037 
1038  for( ; element!=end; ++element ) {
1039  for( size_t i=ii; i<iend; ++i ) {
1040  C(i,element->index()) -= A(i,j) * element->value();
1041  }
1042  }
1043  }
1044  }
1045  }
1046  }
1048  //**********************************************************************************************
1049 
1050  //**Optimized subtraction assignment to dense matrices (large matrices)*************************
1064  template< typename MT3 // Type of the left-hand side target matrix
1065  , typename MT4 // Type of the left-hand side matrix operand
1066  , typename MT5 > // Type of the right-hand side matrix operand
1067  static inline void selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1068  {
1070 
1071  const OppositeType_<MT5> tmp( serial( B ) );
1072  subAssign( C, A * tmp );
1073  }
1075  //**********************************************************************************************
1076 
1077  //**Restructuring subtraction assignment********************************************************
1092  template< typename MT // Type of the target matrix
1093  , bool SO > // Storage order of the target matrix
1094  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1095  subAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1096  {
1098 
1100 
1101  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1102  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1103 
1104  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1105  subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1106  else if( IsSymmetric<MT1>::value )
1107  subAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1108  else
1109  subAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1110  }
1112  //**********************************************************************************************
1113 
1114  //**Subtraction assignment to sparse matrices***************************************************
1115  // No special implementation for the subtraction assignment to sparse matrices.
1116  //**********************************************************************************************
1117 
1118  //**Multiplication assignment to dense matrices*************************************************
1119  // No special implementation for the multiplication assignment to dense matrices.
1120  //**********************************************************************************************
1121 
1122  //**Multiplication assignment to sparse matrices************************************************
1123  // No special implementation for the multiplication assignment to sparse matrices.
1124  //**********************************************************************************************
1125 
1126  //**SMP assignment to dense matrices************************************************************
1141  template< typename MT // Type of the target dense matrix
1142  , bool SO > // Storage order of the target dense matrix
1143  friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
1144  smpAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1145  {
1147 
1148  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1149  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1150 
1151  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1152  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1153 
1154  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1155  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1156  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1157  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1158  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1159  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1160 
1161  smpAssign( ~lhs, A * B );
1162  }
1164  //**********************************************************************************************
1165 
1166  //**SMP assignment to sparse matrices***********************************************************
1181  template< typename MT // Type of the target sparse matrix
1182  , bool SO > // Storage order of the target sparse matrix
1183  friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
1184  smpAssign( SparseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1185  {
1187 
1188  typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
1189 
1195  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
1196 
1197  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1198  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1199 
1200  const TmpType tmp( rhs );
1201  smpAssign( ~lhs, tmp );
1202  }
1204  //**********************************************************************************************
1205 
1206  //**Restructuring SMP assignment****************************************************************
1221  template< typename MT // Type of the target matrix
1222  , bool SO > // Storage order of the target matrix
1223  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1224  smpAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1225  {
1227 
1229 
1230  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1231  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1232 
1233  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1234  smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1235  else if( IsSymmetric<MT1>::value )
1236  smpAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1237  else
1238  smpAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1239  }
1241  //**********************************************************************************************
1242 
1243  //**SMP addition assignment to dense matrices***************************************************
1258  template< typename MT // Type of the target dense matrix
1259  , bool SO > // Storage order of the target sparse matrix
1260  friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
1261  smpAddAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1262  {
1264 
1265  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1266  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1267 
1268  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1269  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1270 
1271  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1272  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1273  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1274  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1275  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1276  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1277 
1278  smpAddAssign( ~lhs, A * B );
1279  }
1281  //**********************************************************************************************
1282 
1283  //**Restructuring SMP addition assignment*******************************************************
1298  template< typename MT // Type of the target matrix
1299  , bool SO > // Storage order of the target matrix
1300  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1301  smpAddAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1302  {
1304 
1306 
1307  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1308  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1309 
1310  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1311  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1312  else if( IsSymmetric<MT1>::value )
1313  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1314  else
1315  smpAddAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1316  }
1318  //**********************************************************************************************
1319 
1320  //**SMP addition assignment to sparse matrices**************************************************
1321  // No special implementation for the SMP addition assignment to sparse matrices.
1322  //**********************************************************************************************
1323 
1324  //**SMP subtraction assignment to dense matrices************************************************
1340  template< typename MT // Type of the target dense matrix
1341  , bool SO > // Storage order of the target sparse matrix
1342  friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
1343  smpSubAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1344  {
1346 
1347  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1348  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1349 
1350  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1351  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1352 
1353  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1354  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1355  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1356  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1357  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1358  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1359 
1360  smpSubAssign( ~lhs, A * B );
1361  }
1363  //**********************************************************************************************
1364 
1365  //**Restructuring SMP subtraction assignment****************************************************
1380  template< typename MT // Type of the target matrix
1381  , bool SO > // Storage order of the target matrix
1382  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1383  smpSubAssign( Matrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1384  {
1386 
1388 
1389  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1390  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1391 
1392  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1393  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1394  else if( IsSymmetric<MT1>::value )
1395  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1396  else
1397  smpSubAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1398  }
1400  //**********************************************************************************************
1401 
1402  //**SMP subtraction assignment to sparse matrices***********************************************
1403  // No special implementation for the SMP subtraction assignment to sparse matrices.
1404  //**********************************************************************************************
1405 
1406  //**SMP multiplication assignment to dense matrices*********************************************
1407  // No special implementation for the SMP multiplication assignment to dense matrices.
1408  //**********************************************************************************************
1409 
1410  //**SMP multiplication assignment to sparse matrices********************************************
1411  // No special implementation for the SMP multiplication assignment to sparse matrices.
1412  //**********************************************************************************************
1413 
1414  //**Compile time checks*************************************************************************
1422  //**********************************************************************************************
1423 };
1424 //*************************************************************************************************
1425 
1426 
1427 
1428 
1429 //=================================================================================================
1430 //
1431 // GLOBAL BINARY ARITHMETIC OPERATORS
1432 //
1433 //=================================================================================================
1434 
1435 //*************************************************************************************************
1464 template< typename T1 // Type of the left-hand side dense matrix
1465  , typename T2 > // Type of the right-hand side sparse matrix
1466 inline const DMatSMatMultExpr<T1,T2>
1468 {
1470 
1471  if( (~lhs).columns() != (~rhs).rows() ) {
1472  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1473  }
1474 
1475  return DMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
1476 }
1477 //*************************************************************************************************
1478 
1479 
1480 
1481 
1482 //=================================================================================================
1483 //
1484 // ROWS SPECIALIZATIONS
1485 //
1486 //=================================================================================================
1487 
1488 //*************************************************************************************************
1490 template< typename MT1, typename MT2 >
1491 struct Rows< DMatSMatMultExpr<MT1,MT2> > : public Rows<MT1>
1492 {};
1494 //*************************************************************************************************
1495 
1496 
1497 
1498 
1499 //=================================================================================================
1500 //
1501 // COLUMNS SPECIALIZATIONS
1502 //
1503 //=================================================================================================
1504 
1505 //*************************************************************************************************
1507 template< typename MT1, typename MT2 >
1508 struct Columns< DMatSMatMultExpr<MT1,MT2> > : public Columns<MT2>
1509 {};
1511 //*************************************************************************************************
1512 
1513 
1514 
1515 
1516 //=================================================================================================
1517 //
1518 // ISALIGNED SPECIALIZATIONS
1519 //
1520 //=================================================================================================
1521 
1522 //*************************************************************************************************
1524 template< typename MT1, typename MT2 >
1525 struct IsAligned< DMatSMatMultExpr<MT1,MT2> >
1526  : public BoolConstant< IsAligned<MT1>::value >
1527 {};
1529 //*************************************************************************************************
1530 
1531 
1532 
1533 
1534 //=================================================================================================
1535 //
1536 // ISLOWER SPECIALIZATIONS
1537 //
1538 //=================================================================================================
1539 
1540 //*************************************************************************************************
1542 template< typename MT1, typename MT2 >
1543 struct IsLower< DMatSMatMultExpr<MT1,MT2> >
1544  : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
1545 {};
1547 //*************************************************************************************************
1548 
1549 
1550 
1551 
1552 //=================================================================================================
1553 //
1554 // ISUNILOWER SPECIALIZATIONS
1555 //
1556 //=================================================================================================
1557 
1558 //*************************************************************************************************
1560 template< typename MT1, typename MT2 >
1561 struct IsUniLower< DMatSMatMultExpr<MT1,MT2> >
1562  : public BoolConstant< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
1563 {};
1565 //*************************************************************************************************
1566 
1567 
1568 
1569 
1570 //=================================================================================================
1571 //
1572 // ISSTRICTLYLOWER SPECIALIZATIONS
1573 //
1574 //=================================================================================================
1575 
1576 //*************************************************************************************************
1578 template< typename MT1, typename MT2 >
1579 struct IsStrictlyLower< DMatSMatMultExpr<MT1,MT2> >
1580  : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
1581  , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
1582 {};
1584 //*************************************************************************************************
1585 
1586 
1587 
1588 
1589 //=================================================================================================
1590 //
1591 // ISUPPER SPECIALIZATIONS
1592 //
1593 //=================================================================================================
1594 
1595 //*************************************************************************************************
1597 template< typename MT1, typename MT2 >
1598 struct IsUpper< DMatSMatMultExpr<MT1,MT2> >
1599  : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
1600 {};
1602 //*************************************************************************************************
1603 
1604 
1605 
1606 
1607 //=================================================================================================
1608 //
1609 // ISUNIUPPER SPECIALIZATIONS
1610 //
1611 //=================================================================================================
1612 
1613 //*************************************************************************************************
1615 template< typename MT1, typename MT2 >
1616 struct IsUniUpper< DMatSMatMultExpr<MT1,MT2> >
1617  : public BoolConstant< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
1618 {};
1620 //*************************************************************************************************
1621 
1622 
1623 
1624 
1625 //=================================================================================================
1626 //
1627 // ISSTRICTLYUPPER SPECIALIZATIONS
1628 //
1629 //=================================================================================================
1630 
1631 //*************************************************************************************************
1633 template< typename MT1, typename MT2 >
1634 struct IsStrictlyUpper< DMatSMatMultExpr<MT1,MT2> >
1635  : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
1636  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
1637 {};
1639 //*************************************************************************************************
1640 
1641 
1642 
1643 
1644 //=================================================================================================
1645 //
1646 // EXPRESSION TRAIT SPECIALIZATIONS
1647 //
1648 //=================================================================================================
1649 
1650 //*************************************************************************************************
1652 template< typename MT1, typename MT2, typename VT >
1653 struct DMatDVecMultExprTrait< DMatSMatMultExpr<MT1,MT2>, VT >
1654 {
1655  public:
1656  //**********************************************************************************************
1657  using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
1658  , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
1659  , IsDenseVector<VT>, IsColumnVector<VT> >
1660  , DMatDVecMultExprTrait_< MT1, SMatDVecMultExprTrait_<MT2,VT> >
1661  , INVALID_TYPE >;
1662  //**********************************************************************************************
1663 };
1665 //*************************************************************************************************
1666 
1667 
1668 //*************************************************************************************************
1670 template< typename MT1, typename MT2, typename VT >
1671 struct DMatSVecMultExprTrait< DMatSMatMultExpr<MT1,MT2>, VT >
1672 {
1673  public:
1674  //**********************************************************************************************
1675  using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
1676  , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
1677  , IsSparseVector<VT>, IsColumnVector<VT> >
1678  , DMatSVecMultExprTrait_< MT1, SMatSVecMultExprTrait_<MT2,VT> >
1679  , INVALID_TYPE >;
1680  //**********************************************************************************************
1681 };
1683 //*************************************************************************************************
1684 
1685 
1686 //*************************************************************************************************
1688 template< typename VT, typename MT1, typename MT2 >
1689 struct TDVecDMatMultExprTrait< VT, DMatSMatMultExpr<MT1,MT2> >
1690 {
1691  public:
1692  //**********************************************************************************************
1693  using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
1694  , IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
1695  , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
1696  , TDVecSMatMultExprTrait_< TDVecDMatMultExprTrait_<VT,MT1>, MT2 >
1697  , INVALID_TYPE >;
1698  //**********************************************************************************************
1699 };
1701 //*************************************************************************************************
1702 
1703 
1704 //*************************************************************************************************
1706 template< typename VT, typename MT1, typename MT2 >
1707 struct TSVecDMatMultExprTrait< VT, DMatSMatMultExpr<MT1,MT2> >
1708 {
1709  public:
1710  //**********************************************************************************************
1711  using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
1712  , IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
1713  , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
1714  , TDVecSMatMultExprTrait_< TDVecDMatMultExprTrait_<VT,MT1>, MT2 >
1715  , INVALID_TYPE >;
1716  //**********************************************************************************************
1717 };
1719 //*************************************************************************************************
1720 
1721 
1722 //*************************************************************************************************
1724 template< typename MT1, typename MT2, bool AF >
1725 struct SubmatrixExprTrait< DMatSMatMultExpr<MT1,MT2>, AF >
1726 {
1727  public:
1728  //**********************************************************************************************
1729  using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
1730  , SubmatrixExprTrait_<const MT2,AF> >;
1731  //**********************************************************************************************
1732 };
1734 //*************************************************************************************************
1735 
1736 
1737 //*************************************************************************************************
1739 template< typename MT1, typename MT2 >
1740 struct RowExprTrait< DMatSMatMultExpr<MT1,MT2> >
1741 {
1742  public:
1743  //**********************************************************************************************
1744  using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
1745  //**********************************************************************************************
1746 };
1748 //*************************************************************************************************
1749 
1750 
1751 //*************************************************************************************************
1753 template< typename MT1, typename MT2 >
1754 struct ColumnExprTrait< DMatSMatMultExpr<MT1,MT2> >
1755 {
1756  public:
1757  //**********************************************************************************************
1758  using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
1759  //**********************************************************************************************
1760 };
1762 //*************************************************************************************************
1763 
1764 } // namespace blaze
1765 
1766 #endif
ResultType_< MT1 > RT1
Result type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:133
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exception.This macro encapsulates the default way o...
Definition: Exception.h:235
Header file for auxiliary alias declarations.
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:72
Header file for mathematical functions.
constexpr bool useOptimizedKernels
Configuration switch for optimized kernels.This configuration switch enables/disables all optimized c...
Definition: Optimizations.h:84
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: DMatSMatMultExpr.h:404
Header file for the SMatDVecMultExprTrait class template.
Header file for the Rows type trait.
Header file for the IsUniUpper type trait.
const DMatDMatMultExpr< T1, T2 > operator*(const DenseMatrix< T1, false > &lhs, const DenseMatrix< T2, false > &rhs)
Multiplication operator for the multiplication of two row-major dense matrices ( ).
Definition: DMatDMatMultExpr.h:7800
Compile time check for triangular matrix types.This type trait tests whether or not the given templat...
Definition: IsTriangular.h:87
Header file for basic type definitions.
const ResultType CompositeType
Data type for composite expression templates.
Definition: DMatSMatMultExpr.h:213
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: DMatSMatMultExpr.h:258
const ElementType ReturnType
Return type for expression template evaluations.
Definition: DMatSMatMultExpr.h:212
IfTrue_< evaluateLeft, const RT1, CT1 > LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: DMatSMatMultExpr.h:222
ElementType_< RT1 > ET1
Element type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:135
EnableIf_< IsDenseMatrix< MT1 > > smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:160
Header file for the IsSparseMatrix type trait.
Header file for the serial shim.
Header file for the IsDiagonal type trait.
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional matrix type...
Definition: DenseMatrix.h:61
Header file for the ColumnExprTrait class template.
If_< IsExpression< MT2 >, const MT2, const MT2 & > RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:219
BLAZE_ALWAYS_INLINE MT::Iterator begin(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator to the first element of row/column i.
Definition: Matrix.h:188
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: DMatSMatMultExpr.h:396
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:533
Header file for the IsRowVector type trait.
typename DisableIf< Condition, T >::Type DisableIf_
Auxiliary type for the DisableIf class template.The DisableIf_ alias declaration provides a convenien...
Definition: DisableIf.h:223
Header file for the And class template.
const ElementType_< MT > min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1669
Compile time check for lower triangular matrices.This type trait tests whether or not the given templ...
Definition: IsLower.h:88
bool isAligned() const noexcept
Returns whether the operands of the expression are properly aligned in memory.
Definition: DMatSMatMultExpr.h:386
Header file for the TDVecSMatMultExprTrait class template.
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: DMatSMatMultExpr.h:322
const DMatSerialExpr< MT, SO > serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:723
typename MultTrait< T1, T2 >::Type MultTrait_
Auxiliary alias declaration for the MultTrait class template.The MultTrait_ alias declaration provide...
Definition: MultTrait.h:245
Header file for the Computation base class.
Header file for the MatMatMultExpr base class.
Compile time check for upper triangular matrices.This type trait tests whether or not the given templ...
Definition: IsUpper.h:88
Constraints on the storage order of matrix types.
Header file for the RequiresEvaluation type trait.
System settings for performance optimizations.
Header file for the IsUniLower type trait.
typename T::ResultType ResultType_
Alias declaration for nested ResultType type definitions.The ResultType_ alias declaration provides a...
Definition: Aliases.h:323
const ElementType_< MT > max(const DenseMatrix< MT, SO > &dm)
Returns the largest element of the dense matrix.
Definition: DenseMatrix.h:1716
EnableIf_< IsDenseMatrix< MT1 > > smpAddAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:129
DisableIf_< Or< IsComputation< MT >, IsTransExpr< MT > >, ColumnExprTrait_< MT > > column(Matrix< MT, SO > &matrix, size_t index)
Creating a view on a specific column of the given matrix.
Definition: Column.h:126
CompositeType_< MT2 > CT2
Composite type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:138
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:70
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes...
Definition: Forward.h:109
TransposeType_< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: DMatSMatMultExpr.h:210
DMatSMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the DMatSMatMultExpr class.
Definition: DMatSMatMultExpr.h:243
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:573
Constraint on the data type.
ElementType_< ResultType > ElementType
Resulting element type.
Definition: DMatSMatMultExpr.h:211
typename IfTrue< Condition, T1, T2 >::Type IfTrue_
Auxiliary alias declaration for the IfTrue class template.The IfTrue_ alias declaration provides a co...
Definition: If.h:109
Constraint on the data type.
Constraint on the data type.
Header file for the MultExprTrait class template.
Compile time check to query the requirement to evaluate an expression.Via this type trait it is possi...
Definition: RequiresEvaluation.h:72
SubvectorExprTrait_< VT, unaligned > subvector(Vector< VT, TF > &vector, size_t index, size_t size)
Creating a view on a specific subvector of the given vector.
Definition: Subvector.h:152
typename T::CompositeType CompositeType_
Alias declaration for nested CompositeType type definitions.The CompositeType_ alias declaration prov...
Definition: Aliases.h:83
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: DMatSMatMultExpr.h:364
LeftOperand lhs_
Left-hand side dense matrix of the multiplication expression.
Definition: DMatSMatMultExpr.h:403
Header file for the DisableIf class template.
Header file for the multiplication trait.
Header file for the IsStrictlyUpper type trait.
Header file for the IsSymmetric type trait.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:57
ElementType_< RT2 > ET2
Element type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:136
Header file for the If class template.
#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a column-major dense or sparse matri...
Definition: ColumnMajorMatrix.h:61
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2647
EnableIf_< IsDenseMatrix< MT1 > > smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:98
Header file for the Or class template.
#define BLAZE_THROW_OUT_OF_RANGE(MESSAGE)
Macro for the emission of a std::out_of_range exception.This macro encapsulates the default way of Bl...
Definition: Exception.h:331
Header file for the DenseMatrix base class.
Header file for the Columns type trait.
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: DMatSMatMultExpr.h:332
typename T::ElementType ElementType_
Alias declaration for nested ElementType type definitions.The ElementType_ alias declaration provides...
Definition: Aliases.h:163
LeftOperand leftOperand() const noexcept
Returns the left-hand side dense matrix operand.
Definition: DMatSMatMultExpr.h:342
Header file for the DMatDVecMultExprTrait class template.
CompositeType_< MT1 > CT1
Composite type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:137
Header file for the IsLower type trait.
Header file for the IsAligned type trait.
Compile time check for diagonal matrices.This type trait tests whether or not the given template para...
Definition: IsDiagonal.h:90
If_< IsExpression< MT1 >, const MT1, const MT1 & > LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:216
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: DMatSMatMultExpr.h:376
Header file for the SMatSVecMultExprTrait class template.
#define BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE(T)
Constraint on the data type.In case the given data type T is not a reference type, a compilation error is created.
Definition: Reference.h:60
Header file for the IsTriangular type trait.
Constraints on the storage order of matrix types.
Header file for the exception macros of the math module.
Compile time check for strictly upper triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyUpper.h:86
BLAZE_ALWAYS_INLINE MT::Iterator end(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator just past the last element of row/column i.
Definition: Matrix.h:254
Header file for the RowExprTrait class template.
Header file for all forward declarations for expression class templates.
Header file for the IsDenseMatrix type trait.
OppositeType_< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: DMatSMatMultExpr.h:209
Header file for the EnableIf class template.
Header file for the IsStrictlyLower type trait.
#define BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR(T1, T2)
Constraint on the data type.In case the given data types T1 and T2 do not form a valid matrix/matrix ...
Definition: MatMatMultExpr.h:109
DisableIf_< Or< IsComputation< MT >, IsTransExpr< MT > >, RowExprTrait_< MT > > row(Matrix< MT, SO > &matrix, size_t index)
Creating a view on a specific row of the given matrix.
Definition: Row.h:126
Base class for all matrix/matrix multiplication expression templates.The MatMatMultExpr class serves ...
Definition: MatMatMultExpr.h:65
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: DMatSMatMultExpr.h:306
Header file for the IsSparseVector type trait.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a symmetric matrix type, a compilation error is created.
Definition: Symmetric.h:79
Header file for the SubmatrixExprTrait class template.
#define BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a row-major dense or sparse matrix t...
Definition: RowMajorMatrix.h:61
Header file for run time assertion macros.
Utility type for generic codes.
Expression object for dense matrix-sparse matrix multiplications.The DMatSMatMultExpr class represent...
Definition: DMatSMatMultExpr.h:127
typename If< T1, T2, T3 >::Type If_
Auxiliary alias declaration for the If class template.The If_ alias declaration provides a convenient...
Definition: If.h:160
Header file for the reset shim.
ResultType_< MT2 > RT2
Result type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:134
Header file for the isDefault shim.
MultTrait_< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: DMatSMatMultExpr.h:208
Constraint on the data type.
Constraints on the storage order of matrix types.
IntegralConstant< bool, B > BoolConstant
Generic wrapper for a compile time constant boolean value.The BoolConstant class template represents ...
Definition: IntegralConstant.h:100
RightOperand rightOperand() const noexcept
Returns the right-hand side sparse matrix operand.
Definition: DMatSMatMultExpr.h:352
typename T::OppositeType OppositeType_
Alias declaration for nested OppositeType type definitions.The OppositeType_ alias declaration provid...
Definition: Aliases.h:243
#define BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER(T1, T2)
Constraint on the data type.In case either of the two given data types T1 or T2 is not a matrix type ...
Definition: StorageOrder.h:84
Header file for the IsDenseVector type trait.
Compile time check for strictly lower triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyLower.h:86
Header file for the IsRowMajorMatrix type trait.
const DMatTransExpr< MT,!SO > trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:950
Header file for the IsComputation type trait class.
Base class for all compute expression templates.The Computation class serves as a tag for all computa...
Definition: Computation.h:59
Header file for the TDVecDMatMultExprTrait class template.
IfTrue_< evaluateRight, const RT2, CT2 > RT
Type for the assignment of the right-hand side sparse matrix operand.
Definition: DMatSMatMultExpr.h:225
#define BLAZE_FUNCTION_TRACE
Function trace macro.This macro can be used to reliably trace function calls. In case function tracin...
Definition: FunctionTrace.h:157
Header file for the IntegralConstant class template.
Header file for the TSVecDMatMultExprTrait class template.
DMatSMatMultExpr< MT1, MT2 > This
Type of this DMatSMatMultExpr instance.
Definition: DMatSMatMultExpr.h:207
typename T::TransposeType TransposeType_
Alias declaration for nested TransposeType type definitions.The TransposeType_ alias declaration prov...
Definition: Aliases.h:403
Header file for the IsUpper type trait.
Header file for the DMatSVecMultExprTrait class template.
Header file for the IsColumnVector type trait.
Constraint on the data type.
Header file for the IsResizable type trait.
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
#define BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a sparse, N-dimensional matrix type...
Definition: SparseMatrix.h:61
Header file for the IsExpression type trait class.
Header file for the FunctionTrace class.