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 <stdexcept>
54 #include <blaze/math/shims/Reset.h>
90 #include <blaze/util/Assert.h>
92 #include <blaze/util/DisableIf.h>
93 #include <blaze/util/EnableIf.h>
94 #include <blaze/util/InvalidType.h>
96 #include <blaze/util/mpl/And.h>
97 #include <blaze/util/mpl/Or.h>
98 #include <blaze/util/SelectType.h>
99 #include <blaze/util/Types.h>
101 
102 
103 namespace blaze {
104 
105 //=================================================================================================
106 //
107 // CLASS DMATSMATMULTEXPR
108 //
109 //=================================================================================================
110 
111 //*************************************************************************************************
118 template< typename MT1 // Type of the left-hand side dense matrix
119  , typename MT2 > // Type of the right-hand side sparse matrix
120 class DMatSMatMultExpr : public DenseMatrix< DMatSMatMultExpr<MT1,MT2>, false >
121  , private MatMatMultExpr
122  , private Computation
123 {
124  private:
125  //**Type definitions****************************************************************************
126  typedef typename MT1::ResultType RT1;
127  typedef typename MT2::ResultType RT2;
128  typedef typename RT1::ElementType ET1;
129  typedef typename RT2::ElementType ET2;
130  typedef typename MT1::CompositeType CT1;
131  typedef typename MT2::CompositeType CT2;
132  //**********************************************************************************************
133 
134  //**********************************************************************************************
137  //**********************************************************************************************
138 
139  //**********************************************************************************************
141  enum { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
142  //**********************************************************************************************
143 
144  //**********************************************************************************************
146 
152  template< typename T1, typename T2, typename T3 >
153  struct CanExploitSymmetry {
154  enum { value = IsColumnMajorMatrix<T1>::value &&
155  ( IsSymmetric<T2>::value || IsSymmetric<T3>::value ) };
156  };
158  //**********************************************************************************************
159 
160  //**********************************************************************************************
162 
166  template< typename T1, typename T2, typename T3 >
167  struct IsEvaluationRequired {
168  enum { value = ( evaluateLeft || evaluateRight ) &&
169  !CanExploitSymmetry<T1,T2,T3>::value };
170  };
172  //**********************************************************************************************
173 
174  //**********************************************************************************************
176 
179  template< typename T1, typename T2, typename T3 >
180  struct UseOptimizedKernel {
181  enum { value = !IsDiagonal<T2>::value &&
182  !IsResizable<typename T1::ElementType>::value };
183  };
185  //**********************************************************************************************
186 
187  //**********************************************************************************************
189 
192  template< typename T1, typename T2, typename T3 >
193  struct UseDefaultKernel {
194  enum { value = !UseOptimizedKernel<T1,T2,T3>::value };
195  };
197  //**********************************************************************************************
198 
199  public:
200  //**Type definitions****************************************************************************
206  typedef const ElementType ReturnType;
207  typedef const ResultType CompositeType;
208 
210  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
211 
213  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
214 
217 
220  //**********************************************************************************************
221 
222  //**Compilation flags***************************************************************************
224  enum { vectorizable = 0 };
225 
227  enum { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
228  !evaluateRight && MT2::smpAssignable };
229  //**********************************************************************************************
230 
231  //**Constructor*********************************************************************************
237  explicit inline DMatSMatMultExpr( const MT1& lhs, const MT2& rhs )
238  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
239  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
240  {
241  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
242  }
243  //**********************************************************************************************
244 
245  //**Access operator*****************************************************************************
252  inline ReturnType operator()( size_t i, size_t j ) const {
253  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
254  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
255 
256  const size_t kbegin( ( IsUpper<MT1>::value )
257  ?( ( IsLower<MT2>::value )
258  ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
259  , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
260  :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
261  :( ( IsLower<MT2>::value )
262  ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
263  :( 0UL ) ) );
264  const size_t kend( ( IsLower<MT1>::value )
265  ?( ( IsUpper<MT2>::value )
266  ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
267  , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
268  :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
269  :( ( IsUpper<MT2>::value )
270  ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
271  :( lhs_.columns() ) ) );
272 
273  if( lhs_.columns() == 0UL ||
274  ( ( IsTriangular<MT1>::value || IsTriangular<MT2>::value ) && kbegin >= kend ) )
275  return ElementType();
276 
277  ElementType tmp( lhs_(i,kbegin) * rhs_(kbegin,j) );
278  for( size_t k=kbegin+1UL; k<kend; ++k ) {
279  tmp += lhs_(i,k) * rhs_(k,j);
280  }
281 
282  return tmp;
283  }
284  //**********************************************************************************************
285 
286  //**Rows function*******************************************************************************
291  inline size_t rows() const {
292  return lhs_.rows();
293  }
294  //**********************************************************************************************
295 
296  //**Columns function****************************************************************************
301  inline size_t columns() const {
302  return rhs_.columns();
303  }
304  //**********************************************************************************************
305 
306  //**Left operand access*************************************************************************
311  inline LeftOperand leftOperand() const {
312  return lhs_;
313  }
314  //**********************************************************************************************
315 
316  //**Right operand access************************************************************************
321  inline RightOperand rightOperand() const {
322  return rhs_;
323  }
324  //**********************************************************************************************
325 
326  //**********************************************************************************************
332  template< typename T >
333  inline bool canAlias( const T* alias ) const {
334  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
335  }
336  //**********************************************************************************************
337 
338  //**********************************************************************************************
344  template< typename T >
345  inline bool isAliased( const T* alias ) const {
346  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
347  }
348  //**********************************************************************************************
349 
350  //**********************************************************************************************
355  inline bool isAligned() const {
356  return lhs_.isAligned();
357  }
358  //**********************************************************************************************
359 
360  //**********************************************************************************************
365  inline bool canSMPAssign() const {
366  return ( rows() > SMP_DMATSMATMULT_THRESHOLD );
367  }
368  //**********************************************************************************************
369 
370  private:
371  //**Member variables****************************************************************************
372  LeftOperand lhs_;
373  RightOperand rhs_;
374  //**********************************************************************************************
375 
376  //**Assignment to row-major dense matrices******************************************************
389  template< typename MT > // Type of the target dense matrix
390  friend inline void assign( DenseMatrix<MT,false>& lhs, const DMatSMatMultExpr& rhs )
391  {
393 
394  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
395  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
396 
397  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
398  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
399 
400  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
401  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
402  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
403  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
404  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
405  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
406 
407  DMatSMatMultExpr::selectRowMajorAssignKernel( ~lhs, A, B );
408  }
410  //**********************************************************************************************
411 
412  //**Default assignment to row-major dense matrices**********************************************
426  template< typename MT3 // Type of the left-hand side target matrix
427  , typename MT4 // Type of the left-hand side matrix operand
428  , typename MT5 > // Type of the right-hand side matrix operand
429  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
430  selectRowMajorAssignKernel( MT3& C, const MT4& A, const MT5& B )
431  {
432  typedef typename MT5::ConstIterator ConstIterator;
433 
434  for( size_t i=0UL; i<A.rows(); ++i )
435  {
436  for( size_t j=0UL; j<C.columns(); ++j ) {
437  reset( C(i,j) );
438  }
439 
440  if( IsDiagonal<MT4>::value )
441  {
442  ConstIterator element( B.begin(i) );
443  const ConstIterator end( B.end(i) );
444 
445  for( ; element!=end; ++element ) {
446  C(i,element->index()) = A(i,i) * element->value();
447  }
448  }
449  else
450  {
451  const size_t jbegin( ( IsUpper<MT4>::value )
452  ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
453  :( 0UL ) );
454  const size_t jend( ( IsLower<MT4>::value )
455  ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
456  :( B.rows() ) );
457  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
458 
459  for( size_t j=jbegin; j<jend; ++j )
460  {
461  ConstIterator element( B.begin(j) );
462  const ConstIterator end( B.end(j) );
463 
464  for( ; element!=end; ++element ) {
465  if( isDefault( C(i,element->index()) ) )
466  C(i,element->index()) = A(i,j) * element->value();
467  else
468  C(i,element->index()) += A(i,j) * element->value();
469  }
470  }
471  }
472  }
473  }
475  //**********************************************************************************************
476 
477  //**Optimized assignment to row-major dense matrices********************************************
491  template< typename MT3 // Type of the left-hand side target matrix
492  , typename MT4 // Type of the left-hand side matrix operand
493  , typename MT5 > // Type of the right-hand side matrix operand
494  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
495  selectRowMajorAssignKernel( MT3& C, const MT4& A, const MT5& B )
496  {
497  typedef typename MT5::ConstIterator ConstIterator;
498 
499  const size_t ipos( A.rows() & size_t(-4) );
500  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ipos, "Invalid end calculation" );
501 
502  for( size_t i=0UL; i<ipos; i+=4UL )
503  {
504  for( size_t j=0UL; j<C.columns(); ++j ) {
505  reset( C(i ,j) );
506  reset( C(i+1UL,j) );
507  reset( C(i+2UL,j) );
508  reset( C(i+3UL,j) );
509  }
510 
511  const size_t jbegin( ( IsUpper<MT4>::value )
512  ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
513  :( 0UL ) );
514  const size_t jend( ( IsLower<MT4>::value )
515  ?( IsStrictlyLower<MT4>::value ? i+3UL : i+4UL )
516  :( B.rows() ) );
517  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
518 
519  for( size_t j=jbegin; j<jend; ++j )
520  {
521  ConstIterator element( B.begin(j) );
522  const ConstIterator end( B.end(j) );
523 
524  for( ; element!=end; ++element ) {
525  C(i ,element->index()) += A(i ,j) * element->value();
526  C(i+1UL,element->index()) += A(i+1UL,j) * element->value();
527  C(i+2UL,element->index()) += A(i+2UL,j) * element->value();
528  C(i+3UL,element->index()) += A(i+3UL,j) * element->value();
529  }
530  }
531  }
532 
533  for( size_t i=ipos; i<A.rows(); ++i )
534  {
535  for( size_t j=0UL; j<C.columns(); ++j ) {
536  reset( C(i,j) );
537  }
538 
539  const size_t jbegin( ( IsUpper<MT4>::value )
540  ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
541  :( 0UL ) );
542  const size_t jend( ( IsLower<MT4>::value )
543  ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
544  :( B.rows() ) );
545  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
546 
547  for( size_t j=jbegin; j<jend; ++j )
548  {
549  ConstIterator element( B.begin(j) );
550  const ConstIterator end( B.end(j) );
551 
552  for( ; element!=end; ++element ) {
553  C(i,element->index()) += A(i,j) * element->value();
554  }
555  }
556  }
557  }
559  //**********************************************************************************************
560 
561  //**Assignment to column-major dense matrices***************************************************
574  template< typename MT > // Type of the target dense matrix
575  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
576  assign( DenseMatrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
577  {
579 
581 
582  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
583  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
584 
585  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
586  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
587 
588  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
589  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
590  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
591  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
592  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
593  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
594 
595  DMatSMatMultExpr::selectColumnMajorAssignKernel( ~lhs, A, B );
596  }
598  //**********************************************************************************************
599 
600  //**Default assignment to column-major dense matrices*******************************************
614  template< typename MT3 // Type of the left-hand side target matrix
615  , typename MT4 // Type of the left-hand side matrix operand
616  , typename MT5 > // Type of the right-hand side matrix operand
617  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
618  selectColumnMajorAssignKernel( MT3& C, const MT4& A, const MT5& B )
619  {
620  typedef typename MT5::ConstIterator ConstIterator;
621 
622  reset( C );
623 
624  for( size_t j=0UL; j<B.rows(); ++j )
625  {
626  if( IsDiagonal<MT4>::value )
627  {
628  ConstIterator element( B.begin(j) );
629  const ConstIterator end( B.end(j) );
630 
631  for( ; element!=end; ++element ) {
632  C(j,element->index()) = A(j,j) * element->value();
633  }
634  }
635  else
636  {
637  const size_t iibegin( ( IsLower<MT4>::value )
638  ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
639  :( 0UL ) );
640  const size_t iiend( ( IsUpper<MT4>::value )
641  ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
642  :( A.rows() ) );
643  BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
644 
645  for( size_t ii=iibegin; ii<iiend; ii+=8UL )
646  {
647  ConstIterator element( B.begin(j) );
648  const ConstIterator end( B.end(j) );
649  const size_t iend( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
650 
651  for( ; element!=end; ++element ) {
652  for( size_t i=ii; i<iend; ++i ) {
653  if( isDefault( C(i,element->index()) ) )
654  C(i,element->index()) = A(i,j) * element->value();
655  else
656  C(i,element->index()) += A(i,j) * element->value();
657  }
658  }
659  }
660  }
661  }
662  }
664  //**********************************************************************************************
665 
666  //**Optimized assignment to column-major dense matrices*****************************************
680  template< typename MT3 // Type of the left-hand side target matrix
681  , typename MT4 // Type of the left-hand side matrix operand
682  , typename MT5 > // Type of the right-hand side matrix operand
683  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
684  selectColumnMajorAssignKernel( MT3& C, const MT4& A, const MT5& B )
685  {
686  typedef typename MT5::ConstIterator ConstIterator;
687 
688  reset( C );
689 
690  for( size_t j=0UL; j<B.rows(); ++j )
691  {
692  const size_t iibegin( ( IsLower<MT4>::value )
693  ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
694  :( 0UL ) );
695  const size_t iiend( ( IsUpper<MT4>::value )
696  ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
697  :( A.rows() ) );
698  BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
699 
700  for( size_t ii=iibegin; ii<iiend; ii+=8UL )
701  {
702  ConstIterator element( B.begin(j) );
703  const ConstIterator end( B.end(j) );
704  const size_t iend( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
705 
706  for( ; element!=end; ++element ) {
707  for( size_t i=ii; i<iend; ++i ) {
708  C(i,element->index()) += A(i,j) * element->value();
709  }
710  }
711  }
712  }
713  }
715  //**********************************************************************************************
716 
717  //**Assignment to sparse matrices***************************************************************
730  template< typename MT // Type of the target sparse matrix
731  , bool SO > // Storage order of the target sparse matrix
732  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
733  assign( SparseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
734  {
736 
737  typedef typename SelectType< SO, OppositeType, ResultType >::Type TmpType;
738 
745 
746  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
747  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
748 
749  const TmpType tmp( serial( rhs ) );
750  assign( ~lhs, tmp );
751  }
753  //**********************************************************************************************
754 
755  //**Restructuring assignment to column-major matrices*******************************************
770  template< typename MT > // Type of the target matrix
771  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
772  assign( Matrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
773  {
775 
777 
778  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
779  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
780 
781  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
782  assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
783  else if( IsSymmetric<MT1>::value )
784  assign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
785  else
786  assign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
787  }
789  //**********************************************************************************************
790 
791  //**Addition assignment to row-major dense matrices*********************************************
804  template< typename MT > // Type of the target dense matrix
805  friend inline void addAssign( DenseMatrix<MT,false>& lhs, const DMatSMatMultExpr& rhs )
806  {
808 
809  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
810  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
811 
812  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
813  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
814 
815  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
816  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
817  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
818  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
819  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
820  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
821 
822  DMatSMatMultExpr::selectRowMajorAddAssignKernel( ~lhs, A, B );
823  }
825  //**********************************************************************************************
826 
827  //**Optimized addition assignment to row-major dense matrices***********************************
841  template< typename MT3 // Type of the left-hand side target matrix
842  , typename MT4 // Type of the left-hand side matrix operand
843  , typename MT5 > // Type of the right-hand side matrix operand
844  static inline void selectRowMajorAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
845  {
846  typedef typename MT5::ConstIterator ConstIterator;
847 
848  size_t i( 0UL );
849 
850  if( !IsDiagonal<MT4>::value )
851  {
852  const size_t ipos( A.rows() & size_t(-4) );
853  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ipos, "Invalid end calculation" );
854 
855  for( ; i<ipos; i+=4UL )
856  {
857  const size_t jbegin( ( IsUpper<MT4>::value )
858  ?( IsStrictlyUpper<MT4>::value ? i+1U : i )
859  :( 0UL ) );
860  const size_t jend( ( IsLower<MT4>::value )
861  ?( IsStrictlyLower<MT4>::value ? i+3UL : i+4UL )
862  :( B.rows() ) );
863  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
864 
865  for( size_t j=jbegin; j<jend; ++j )
866  {
867  ConstIterator element( B.begin(j) );
868  const ConstIterator end( B.end(j) );
869 
870  for( ; element!=end; ++element ) {
871  C(i ,element->index()) += A(i ,j) * element->value();
872  C(i+1UL,element->index()) += A(i+1UL,j) * element->value();
873  C(i+2UL,element->index()) += A(i+2UL,j) * element->value();
874  C(i+3UL,element->index()) += A(i+3UL,j) * element->value();
875  }
876  }
877  }
878  }
879 
880  for( ; i<A.rows(); ++i )
881  {
882  if( IsDiagonal<MT4>::value )
883  {
884  ConstIterator element( B.begin(i) );
885  const ConstIterator end( B.end(i) );
886 
887  for( ; element!=end; ++element ) {
888  C(i,element->index()) += A(i,i) * element->value();
889  }
890  }
891  else
892  {
893  const size_t jbegin( ( IsUpper<MT4>::value )
894  ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
895  :( 0UL ) );
896  const size_t jend( ( IsLower<MT4>::value )
897  ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
898  :( B.rows() ) );
899  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
900 
901  for( size_t j=jbegin; j<jend; ++j )
902  {
903  ConstIterator element( B.begin(j) );
904  const ConstIterator end( B.end(j) );
905 
906  for( ; element!=end; ++element ) {
907  C(i,element->index()) += A(i,j) * element->value();
908  }
909  }
910  }
911  }
912  }
914  //**********************************************************************************************
915 
916  //**Addition assignment to column-major dense matrices******************************************
929  template< typename MT > // Type of the target dense matrix
930  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
931  addAssign( DenseMatrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
932  {
934 
936 
937  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
938  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
939 
940  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
941  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
942 
943  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
944  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
945  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
946  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
947  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
948  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
949 
950  DMatSMatMultExpr::selectColumnMajorAddAssignKernel( ~lhs, A, B );
951  }
953  //**********************************************************************************************
954 
955  //**Optimized addition assignment to column-major dense matrices********************************
969  template< typename MT3 // Type of the left-hand side target matrix
970  , typename MT4 // Type of the left-hand side matrix operand
971  , typename MT5 > // Type of the right-hand side matrix operand
972  static inline void selectColumnMajorAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
973  {
974  typedef typename MT5::ConstIterator ConstIterator;
975 
976  for( size_t j=0UL; j<B.rows(); ++j )
977  {
978  if( IsDiagonal<MT4>::value )
979  {
980  ConstIterator element( B.begin(j) );
981  const ConstIterator end( B.end(j) );
982 
983  for( ; element!=end; ++element ) {
984  C(j,element->index()) += A(j,j) * element->value();
985  }
986  }
987  else
988  {
989  const size_t iibegin( ( IsLower<MT4>::value )
990  ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
991  :( 0UL ) );
992  const size_t iiend( ( IsUpper<MT4>::value )
993  ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
994  :( A.rows() ) );
995  BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
996 
997  for( size_t ii=iibegin; ii<iiend; ii+=8UL )
998  {
999  ConstIterator element( B.begin(j) );
1000  const ConstIterator end( B.end(j) );
1001  const size_t iend( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
1002 
1003  for( ; element!=end; ++element ) {
1004  for( size_t i=ii; i<iend; ++i ) {
1005  C(i,element->index()) += A(i,j) * element->value();
1006  }
1007  }
1008  }
1009  }
1010  }
1011  }
1013  //**********************************************************************************************
1014 
1015  //**Restructuring addition assignment to column-major matrices**********************************
1030  template< typename MT > // Type of the target matrix
1031  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1032  addAssign( Matrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
1033  {
1035 
1037 
1038  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1039  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1040 
1041  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1042  addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1043  else if( IsSymmetric<MT1>::value )
1044  addAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1045  else
1046  addAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1047  }
1049  //**********************************************************************************************
1050 
1051  //**Addition assignment to sparse matrices******************************************************
1052  // No special implementation for the addition assignment to sparse matrices.
1053  //**********************************************************************************************
1054 
1055  //**Subtraction assignment to row-major dense matrices******************************************
1068  template< typename MT > // Type of the target dense matrix
1069  friend inline void subAssign( DenseMatrix<MT,false>& lhs, const DMatSMatMultExpr& rhs )
1070  {
1072 
1073  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1074  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1075 
1076  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1077  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1078 
1079  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1080  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1081  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1082  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1083  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1084  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1085 
1086  DMatSMatMultExpr::selectRowMajorSubAssignKernel( ~lhs, A, B );
1087  }
1089  //**********************************************************************************************
1090 
1091  //**Optimized subtraction assignment to row-major dense matrices********************************
1105  template< typename MT3 // Type of the left-hand side target matrix
1106  , typename MT4 // Type of the left-hand side matrix operand
1107  , typename MT5 > // Type of the right-hand side matrix operand
1108  static inline void selectRowMajorSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1109  {
1110  typedef typename MT5::ConstIterator ConstIterator;
1111 
1112  size_t i( 0UL );
1113 
1114  if( !IsDiagonal<MT4>::value )
1115  {
1116  const size_t ipos( A.rows() & size_t(-4) );
1117  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ipos, "Invalid end calculation" );
1118 
1119  for( ; i<ipos; i+=4UL )
1120  {
1121  const size_t jbegin( ( IsUpper<MT4>::value )
1122  ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
1123  :( 0UL ) );
1124  const size_t jend( ( IsLower<MT4>::value )
1125  ?( IsStrictlyLower<MT4>::value ? i+3UL : i+4UL )
1126  :( B.rows() ) );
1127  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
1128 
1129  for( size_t j=jbegin; j<jend; ++j )
1130  {
1131  ConstIterator element( B.begin(j) );
1132  const ConstIterator end( B.end(j) );
1133 
1134  for( ; element!=end; ++element ) {
1135  C(i ,element->index()) -= A(i ,j) * element->value();
1136  C(i+1UL,element->index()) -= A(i+1UL,j) * element->value();
1137  C(i+2UL,element->index()) -= A(i+2UL,j) * element->value();
1138  C(i+3UL,element->index()) -= A(i+3UL,j) * element->value();
1139  }
1140  }
1141  }
1142  }
1143 
1144  for( ; i<A.rows(); ++i )
1145  {
1146  if( IsDiagonal<MT4>::value )
1147  {
1148  ConstIterator element( B.begin(i) );
1149  const ConstIterator end( B.end(i) );
1150 
1151  for( ; element!=end; ++element ) {
1152  C(i,element->index()) -= A(i,i) * element->value();
1153  }
1154  }
1155  else
1156  {
1157  const size_t jbegin( ( IsUpper<MT4>::value )
1158  ?( IsStrictlyUpper<MT4>::value ? i+1UL : i )
1159  :( 0UL ) );
1160  const size_t jend( ( IsLower<MT4>::value )
1161  ?( IsStrictlyLower<MT4>::value ? i : i+1UL )
1162  :( B.rows() ) );
1163  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
1164 
1165  for( size_t j=jbegin; j<jend; ++j )
1166  {
1167  ConstIterator element( B.begin(j) );
1168  const ConstIterator end( B.end(j) );
1169 
1170  for( ; element!=end; ++element ) {
1171  C(i,element->index()) -= A(i,j) * element->value();
1172  }
1173  }
1174  }
1175  }
1176  }
1178  //**********************************************************************************************
1179 
1180  //**Subtraction assignment to column-major dense matrices***************************************
1193  template< typename MT > // Type of the target dense matrix
1194  friend inline void subAssign( DenseMatrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
1195  {
1197 
1199 
1200  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1201  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1202 
1203  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1204  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1205 
1206  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1207  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1208  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1209  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1210  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1211  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1212 
1213  DMatSMatMultExpr::selectColumnMajorSubAssignKernel( ~lhs, A, B );
1214  }
1216  //**********************************************************************************************
1217 
1218  //**Optimized subtraction assignment to column-major dense matrices*****************************
1232  template< typename MT3 // Type of the left-hand side target matrix
1233  , typename MT4 // Type of the left-hand side matrix operand
1234  , typename MT5 > // Type of the right-hand side matrix operand
1235  static inline void selectColumnMajorSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1236  {
1237  typedef typename MT5::ConstIterator ConstIterator;
1238 
1239  for( size_t j=0UL; j<B.rows(); ++j )
1240  {
1241  if( IsDiagonal<MT4>::value )
1242  {
1243  ConstIterator element( B.begin(j) );
1244  const ConstIterator end( B.end(j) );
1245 
1246  for( ; element!=end; ++element ) {
1247  C(j,element->index()) -= A(j,j) * element->value();
1248  }
1249  }
1250  else
1251  {
1252  const size_t iibegin( ( IsLower<MT4>::value )
1253  ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
1254  :( 0UL ) );
1255  const size_t iiend( ( IsUpper<MT4>::value )
1256  ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
1257  :( A.rows() ) );
1258  BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" );
1259 
1260  for( size_t ii=iibegin; ii<iiend; ii+=8UL )
1261  {
1262  ConstIterator element( B.begin(j) );
1263  const ConstIterator end( B.end(j) );
1264  const size_t iend( ( ii+8UL > iiend )?( iiend ):( ii+8UL ) );
1265 
1266  for( ; element!=end; ++element ) {
1267  for( size_t i=ii; i<iend; ++i ) {
1268  C(i,element->index()) -= A(i,j) * element->value();
1269  }
1270  }
1271  }
1272  }
1273  }
1274  }
1276  //**********************************************************************************************
1277 
1278  //**Restructuring subtraction assignment to column-major matrices*******************************
1293  template< typename MT > // Type of the target matrix
1294  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1295  subAssign( Matrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
1296  {
1298 
1300 
1301  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1302  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1303 
1304  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1305  subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1306  else if( IsSymmetric<MT1>::value )
1307  subAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1308  else
1309  subAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1310  }
1312  //**********************************************************************************************
1313 
1314  //**Subtraction assignment to sparse matrices***************************************************
1315  // No special implementation for the subtraction assignment to sparse matrices.
1316  //**********************************************************************************************
1317 
1318  //**Multiplication assignment to dense matrices*************************************************
1319  // No special implementation for the multiplication assignment to dense matrices.
1320  //**********************************************************************************************
1321 
1322  //**Multiplication assignment to sparse matrices************************************************
1323  // No special implementation for the multiplication assignment to sparse matrices.
1324  //**********************************************************************************************
1325 
1326  //**SMP assignment to dense matrices************************************************************
1341  template< typename MT // Type of the target dense matrix
1342  , bool SO > // Storage order of the target dense matrix
1343  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1344  smpAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1345  {
1347 
1348  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1349  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1350 
1351  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1352  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1353 
1354  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1355  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1356  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1357  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1358  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1359  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1360 
1361  smpAssign( ~lhs, A * B );
1362  }
1364  //**********************************************************************************************
1365 
1366  //**SMP assignment to sparse matrices***********************************************************
1381  template< typename MT // Type of the target sparse matrix
1382  , bool SO > // Storage order of the target sparse matrix
1383  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1384  smpAssign( SparseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1385  {
1387 
1388  typedef typename SelectType< SO, OppositeType, ResultType >::Type TmpType;
1389 
1396 
1397  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1398  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1399 
1400  const TmpType tmp( rhs );
1401  smpAssign( ~lhs, tmp );
1402  }
1404  //**********************************************************************************************
1405 
1406  //**Restructuring SMP assignment to column-major matrices***************************************
1421  template< typename MT > // Type of the target matrix
1422  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1423  smpAssign( Matrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
1424  {
1426 
1428 
1429  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1430  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1431 
1432  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1433  smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1434  else if( IsSymmetric<MT1>::value )
1435  smpAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1436  else
1437  smpAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1438  }
1440  //**********************************************************************************************
1441 
1442  //**SMP addition assignment to dense matrices***************************************************
1457  template< typename MT // Type of the target dense matrix
1458  , bool SO > // Storage order of the target sparse matrix
1459  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1460  smpAddAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1461  {
1463 
1464  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1465  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1466 
1467  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1468  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1469 
1470  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1471  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1472  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1473  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1474  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1475  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1476 
1477  smpAddAssign( ~lhs, A * B );
1478  }
1480  //**********************************************************************************************
1481 
1482  //**Restructuring SMP addition assignment to column-major matrices******************************
1497  template< typename MT > // Type of the target matrix
1498  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1499  smpAddAssign( Matrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
1500  {
1502 
1504 
1505  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1506  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1507 
1508  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1509  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1510  else if( IsSymmetric<MT1>::value )
1511  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1512  else
1513  smpAddAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1514  }
1516  //**********************************************************************************************
1517 
1518  //**SMP addition assignment to sparse matrices**************************************************
1519  // No special implementation for the SMP addition assignment to sparse matrices.
1520  //**********************************************************************************************
1521 
1522  //**SMP subtraction assignment to dense matrices************************************************
1538  template< typename MT // Type of the target dense matrix
1539  , bool SO > // Storage order of the target sparse matrix
1540  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1541  smpSubAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1542  {
1544 
1545  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1546  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1547 
1548  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1549  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1550 
1551  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1552  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1553  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1554  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1555  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1556  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1557 
1558  smpSubAssign( ~lhs, A * B );
1559  }
1561  //**********************************************************************************************
1562 
1563  //**Restructuring SMP subtraction assignment to column-major matrices***************************
1578  template< typename MT > // Type of the target matrix
1579  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1580  smpSubAssign( Matrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
1581  {
1583 
1585 
1586  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1587  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1588 
1589  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1590  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1591  else if( IsSymmetric<MT1>::value )
1592  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1593  else
1594  smpSubAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1595  }
1597  //**********************************************************************************************
1598 
1599  //**SMP subtraction assignment to sparse matrices***********************************************
1600  // No special implementation for the SMP subtraction assignment to sparse matrices.
1601  //**********************************************************************************************
1602 
1603  //**SMP multiplication assignment to dense matrices*********************************************
1604  // No special implementation for the SMP multiplication assignment to dense matrices.
1605  //**********************************************************************************************
1606 
1607  //**SMP multiplication assignment to sparse matrices********************************************
1608  // No special implementation for the SMP multiplication assignment to sparse matrices.
1609  //**********************************************************************************************
1610 
1611  //**Compile time checks*************************************************************************
1619  //**********************************************************************************************
1620 };
1621 //*************************************************************************************************
1622 
1623 
1624 
1625 
1626 //=================================================================================================
1627 //
1628 // GLOBAL BINARY ARITHMETIC OPERATORS
1629 //
1630 //=================================================================================================
1631 
1632 //*************************************************************************************************
1661 template< typename T1 // Type of the left-hand side dense matrix
1662  , typename T2 > // Type of the right-hand side sparse matrix
1663 inline const DMatSMatMultExpr<T1,T2>
1665 {
1667 
1668  if( (~lhs).columns() != (~rhs).rows() )
1669  throw std::invalid_argument( "Matrix sizes do not match" );
1670 
1671  return DMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
1672 }
1673 //*************************************************************************************************
1674 
1675 
1676 
1677 
1678 //=================================================================================================
1679 //
1680 // ROWS SPECIALIZATIONS
1681 //
1682 //=================================================================================================
1683 
1684 //*************************************************************************************************
1686 template< typename MT1, typename MT2 >
1687 struct Rows< DMatSMatMultExpr<MT1,MT2> >
1688  : public Rows<MT1>
1689 {};
1691 //*************************************************************************************************
1692 
1693 
1694 
1695 
1696 //=================================================================================================
1697 //
1698 // COLUMNS SPECIALIZATIONS
1699 //
1700 //=================================================================================================
1701 
1702 //*************************************************************************************************
1704 template< typename MT1, typename MT2 >
1705 struct Columns< DMatSMatMultExpr<MT1,MT2> >
1706  : public Columns<MT2>
1707 {};
1709 //*************************************************************************************************
1710 
1711 
1712 
1713 
1714 //=================================================================================================
1715 //
1716 // ISLOWER SPECIALIZATIONS
1717 //
1718 //=================================================================================================
1719 
1720 //*************************************************************************************************
1722 template< typename MT1, typename MT2 >
1723 struct IsLower< DMatSMatMultExpr<MT1,MT2> >
1724  : public IsTrue< And< IsLower<MT1>, IsLower<MT2> >::value >
1725 {};
1727 //*************************************************************************************************
1728 
1729 
1730 
1731 
1732 //=================================================================================================
1733 //
1734 // ISUNILOWER SPECIALIZATIONS
1735 //
1736 //=================================================================================================
1737 
1738 //*************************************************************************************************
1740 template< typename MT1, typename MT2 >
1741 struct IsUniLower< DMatSMatMultExpr<MT1,MT2> >
1742  : public IsTrue< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
1743 {};
1745 //*************************************************************************************************
1746 
1747 
1748 
1749 
1750 //=================================================================================================
1751 //
1752 // ISSTRICTLYLOWER SPECIALIZATIONS
1753 //
1754 //=================================================================================================
1755 
1756 //*************************************************************************************************
1758 template< typename MT1, typename MT2 >
1759 struct IsStrictlyLower< DMatSMatMultExpr<MT1,MT2> >
1760  : public IsTrue< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
1761  , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
1762 {};
1764 //*************************************************************************************************
1765 
1766 
1767 
1768 
1769 //=================================================================================================
1770 //
1771 // ISUPPER SPECIALIZATIONS
1772 //
1773 //=================================================================================================
1774 
1775 //*************************************************************************************************
1777 template< typename MT1, typename MT2 >
1778 struct IsUpper< DMatSMatMultExpr<MT1,MT2> >
1779  : public IsTrue< And< IsUpper<MT1>, IsUpper<MT2> >::value >
1780 {};
1782 //*************************************************************************************************
1783 
1784 
1785 
1786 
1787 //=================================================================================================
1788 //
1789 // ISUNIUPPER SPECIALIZATIONS
1790 //
1791 //=================================================================================================
1792 
1793 //*************************************************************************************************
1795 template< typename MT1, typename MT2 >
1796 struct IsUniUpper< DMatSMatMultExpr<MT1,MT2> >
1797  : public IsTrue< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
1798 {};
1800 //*************************************************************************************************
1801 
1802 
1803 
1804 
1805 //=================================================================================================
1806 //
1807 // ISSTRICTLYUPPER SPECIALIZATIONS
1808 //
1809 //=================================================================================================
1810 
1811 //*************************************************************************************************
1813 template< typename MT1, typename MT2 >
1814 struct IsStrictlyUpper< DMatSMatMultExpr<MT1,MT2> >
1815  : public IsTrue< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
1816  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
1817 {};
1819 //*************************************************************************************************
1820 
1821 
1822 
1823 
1824 //=================================================================================================
1825 //
1826 // EXPRESSION TRAIT SPECIALIZATIONS
1827 //
1828 //=================================================================================================
1829 
1830 //*************************************************************************************************
1832 template< typename MT1, typename MT2, typename VT >
1833 struct DMatDVecMultExprTrait< DMatSMatMultExpr<MT1,MT2>, VT >
1834 {
1835  public:
1836  //**********************************************************************************************
1837  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1838  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1839  IsDenseVector<VT>::value && IsColumnVector<VT>::value
1840  , typename DMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
1841  , INVALID_TYPE >::Type Type;
1842  //**********************************************************************************************
1843 };
1845 //*************************************************************************************************
1846 
1847 
1848 //*************************************************************************************************
1850 template< typename MT1, typename MT2, typename VT >
1851 struct DMatSVecMultExprTrait< DMatSMatMultExpr<MT1,MT2>, VT >
1852 {
1853  public:
1854  //**********************************************************************************************
1855  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1856  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1857  IsSparseVector<VT>::value && IsColumnVector<VT>::value
1858  , typename DMatSVecMultExprTrait< MT1, typename SMatSVecMultExprTrait<MT2,VT>::Type >::Type
1859  , INVALID_TYPE >::Type Type;
1860  //**********************************************************************************************
1861 };
1863 //*************************************************************************************************
1864 
1865 
1866 //*************************************************************************************************
1868 template< typename VT, typename MT1, typename MT2 >
1869 struct TDVecDMatMultExprTrait< VT, DMatSMatMultExpr<MT1,MT2> >
1870 {
1871  public:
1872  //**********************************************************************************************
1873  typedef typename SelectType< IsDenseVector<VT>::value && IsRowVector<VT>::value &&
1874  IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1875  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1876  , typename TDVecSMatMultExprTrait< typename TDVecDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1877  , INVALID_TYPE >::Type Type;
1878  //**********************************************************************************************
1879 };
1881 //*************************************************************************************************
1882 
1883 
1884 //*************************************************************************************************
1886 template< typename VT, typename MT1, typename MT2 >
1887 struct TSVecDMatMultExprTrait< VT, DMatSMatMultExpr<MT1,MT2> >
1888 {
1889  public:
1890  //**********************************************************************************************
1891  typedef typename SelectType< IsSparseVector<VT>::value && IsRowVector<VT>::value &&
1892  IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1893  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1894  , typename TDVecSMatMultExprTrait< typename TDVecDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1895  , INVALID_TYPE >::Type Type;
1896  //**********************************************************************************************
1897 };
1899 //*************************************************************************************************
1900 
1901 
1902 //*************************************************************************************************
1904 template< typename MT1, typename MT2, bool AF >
1905 struct SubmatrixExprTrait< DMatSMatMultExpr<MT1,MT2>, AF >
1906 {
1907  public:
1908  //**********************************************************************************************
1909  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT1,AF>::Type
1910  , typename SubmatrixExprTrait<const MT2,AF>::Type >::Type Type;
1911  //**********************************************************************************************
1912 };
1914 //*************************************************************************************************
1915 
1916 
1917 //*************************************************************************************************
1919 template< typename MT1, typename MT2 >
1920 struct RowExprTrait< DMatSMatMultExpr<MT1,MT2> >
1921 {
1922  public:
1923  //**********************************************************************************************
1924  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
1925  //**********************************************************************************************
1926 };
1928 //*************************************************************************************************
1929 
1930 
1931 //*************************************************************************************************
1933 template< typename MT1, typename MT2 >
1934 struct ColumnExprTrait< DMatSMatMultExpr<MT1,MT2> >
1935 {
1936  public:
1937  //**********************************************************************************************
1938  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
1939  //**********************************************************************************************
1940 };
1942 //*************************************************************************************************
1943 
1944 } // namespace blaze
1945 
1946 #endif
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: DMatSMatMultExpr.h:204
const MT::ElementType max(const DenseMatrix< MT, SO > &dm)
Returns the largest element of the dense matrix.
Definition: DenseMatrix.h:1649
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:89
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: DMatSMatMultExpr.h:373
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:8247
Compile time check for triangular matrix types.This type trait tests whether or not the given templat...
Definition: IsTriangular.h:105
Header file for basic type definitions.
const ResultType CompositeType
Data type for composite expression templates.
Definition: DMatSMatMultExpr.h:207
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: DMatSMatMultExpr.h:252
const ElementType ReturnType
Return type for expression template evaluations.
Definition: DMatSMatMultExpr.h:206
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:258
SelectType< evaluateRight, const RT2, CT2 >::Type RT
Type for the assignment of the right-hand side sparse matrix operand.
Definition: DMatSMatMultExpr.h:219
Header file for the IsSparseMatrix type trait.
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:209
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:79
Header file for the ColumnExprTrait class template.
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:821
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2507
Header file for the IsRowVector type trait.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:261
Header file for the And class template.
size_t columns() const
Returns the current number of columns of the matrix.
Definition: DMatSMatMultExpr.h:301
Compile time check for lower triangular matrices.This type trait tests whether or not the given templ...
Definition: IsLower.h:90
bool isAligned() const
Returns whether the operands of the expression are properly aligned in memory.
Definition: DMatSMatMultExpr.h:355
MT2::ResultType RT2
Result type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:127
Header file for the TDVecSMatMultExprTrait class template.
MultTrait< RT1, RT2 >::Type ResultType
Result type for expression template evaluations.
Definition: DMatSMatMultExpr.h:202
const DMatSerialExpr< MT, SO > serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:699
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:90
Header file for the IsUniLower type trait.
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:107
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:861
Constraint on the data type.
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:90
SelectType< IsExpression< MT2 >::value, const MT2, const MT2 & >::Type RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:213
LeftOperand lhs_
Left-hand side dense matrix of the multiplication expression.
Definition: DMatSMatMultExpr.h:372
size_t rows() const
Returns the current number of rows of the matrix.
Definition: DMatSMatMultExpr.h:291
Compile time type selection.The SelectType class template selects one of the two given types T1 and T...
Definition: SelectType.h:59
Header file for the DisableIf class template.
Header file for the multiplication trait.
Header file for the IsStrictlyUpper type trait.
MT1::ResultType RT1
Result type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:126
Header file for the IsSymmetric type trait.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:57
#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: StorageOrder.h:161
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2511
LeftOperand leftOperand() const
Returns the left-hand side dense matrix operand.
Definition: DMatSMatMultExpr.h:311
Header file for the Or class template.
const MT::ElementType min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1602
Header file for the DenseMatrix base class.
BLAZE_ALWAYS_INLINE void assign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the assignment of a matrix to a matrix.
Definition: Matrix.h:635
Header file for the Columns type trait.
ResultType::OppositeType OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: DMatSMatMultExpr.h:203
Header file for the DMatDVecMultExprTrait class template.
Header file for the IsLower type trait.
RT2::ElementType ET2
Element type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:129
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:78
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: DMatSMatMultExpr.h:365
Header file for the IsTriangular type trait.
Constraints on the storage order of matrix types.
SelectType< evaluateLeft, const RT1, CT1 >::Type LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: DMatSMatMultExpr.h:216
Compile time check for strictly upper triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyUpper.h:86
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:2505
Header file for the SelectType class template.
Header file for the RowExprTrait class template.
Header file for all forward declarations for expression class templates.
Header file for the IsDenseMatrix type trait.
Header file for the EnableIf class template.
Header file for the IsStrictlyLower type trait.
Header file for the serial shim.
#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:165
ResultType::ElementType ElementType
Resulting element type.
Definition: DMatSMatMultExpr.h:205
MT1::CompositeType CT1
Composite type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:130
RT1::ElementType ET1
Element type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:128
Base class for all matrix/matrix multiplication expression templates.The MatMatMultExpr class serves ...
Definition: MatMatMultExpr.h:65
EnableIf< IsDenseMatrix< MT1 > >::Type 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 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:116
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: StorageOrder.h:81
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: DMatSMatMultExpr.h:333
Header file for run time assertion macros.
EnableIf< IsDenseMatrix< MT1 > >::Type 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
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: DMatSMatMultExpr.h:345
Utility type for generic codes.
Base template for the MultTrait class.
Definition: MultTrait.h:150
Expression object for dense matrix-sparse matrix multiplications.The DMatSMatMultExpr class represent...
Definition: DMatSMatMultExpr.h:120
BLAZE_ALWAYS_INLINE void addAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the addition assignment of a matrix to a matrix.
Definition: Matrix.h:742
Substitution Failure Is Not An Error (SFINAE) class.The EnableIf class template is an auxiliary tool ...
Definition: EnableIf.h:184
Header file for the reset shim.
Header file for the isDefault shim.
Constraint on the data type.
#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:283
MT2::CompositeType CT2
Composite type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:131
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
SelectType< IsExpression< MT1 >::value, const MT1, const MT1 & >::Type LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:210
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:937
Header file for the IsComputation type trait class.
const size_t SMP_DMATSMATMULT_THRESHOLD
SMP row-major dense matrix/row-major sparse matrix multiplication threshold.This threshold specifies ...
Definition: Thresholds.h:926
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.
EnableIf< IsDenseMatrix< MT1 > >::Type 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
#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
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:2502
Header file for the IsTrue value trait.
DMatSMatMultExpr(const MT1 &lhs, const MT2 &rhs)
Constructor for the DMatSMatMultExpr class.
Definition: DMatSMatMultExpr.h:237
Header file for the TSVecDMatMultExprTrait class template.
DMatSMatMultExpr< MT1, MT2 > This
Type of this DMatSMatMultExpr instance.
Definition: DMatSMatMultExpr.h:201
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:79
Header file for the IsExpression type trait class.
Header file for the FunctionTrace class.
BLAZE_ALWAYS_INLINE void subAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the subtraction assignment of a matrix to matrix.
Definition: Matrix.h:849
RightOperand rightOperand() const
Returns the right-hand side sparse matrix operand.
Definition: DMatSMatMultExpr.h:321