TDMatSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_TDMATSMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_TDMATSMATMULTEXPR_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>
98 #include <blaze/util/Assert.h>
100 #include <blaze/util/DisableIf.h>
101 #include <blaze/util/EnableIf.h>
103 #include <blaze/util/InvalidType.h>
105 #include <blaze/util/mpl/And.h>
106 #include <blaze/util/mpl/If.h>
107 #include <blaze/util/mpl/Or.h>
108 #include <blaze/util/Types.h>
109 
110 
111 namespace blaze {
112 
113 //=================================================================================================
114 //
115 // CLASS TDMATSMATMULTEXPR
116 //
117 //=================================================================================================
118 
119 //*************************************************************************************************
126 template< typename MT1 // Type of the left-hand side dense matrix
127  , typename MT2 > // Type of the right-hand side sparse matrix
128 class TDMatSMatMultExpr : public DenseMatrix< TDMatSMatMultExpr<MT1,MT2>, true >
129  , private MatMatMultExpr
130  , private Computation
131 {
132  private:
133  //**Type definitions****************************************************************************
140  //**********************************************************************************************
141 
142  //**********************************************************************************************
144  enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
145  //**********************************************************************************************
146 
147  //**********************************************************************************************
149  enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
150  //**********************************************************************************************
151 
152  //**********************************************************************************************
154 
159  template< typename T1, typename T2, typename T3 >
160  struct CanExploitSymmetry {
161  enum : bool { value = IsSymmetric<T3>::value };
162  };
164  //**********************************************************************************************
165 
166  //**********************************************************************************************
168 
172  template< typename T1, typename T2, typename T3 >
173  struct IsEvaluationRequired {
174  enum : bool { value = ( evaluateLeft || evaluateRight ) &&
175  !CanExploitSymmetry<T1,T2,T3>::value };
176  };
178  //**********************************************************************************************
179 
180  //**********************************************************************************************
182 
186  template< typename T1, typename T2, typename T3 >
187  struct UseOptimizedKernel {
188  enum : bool { value = useOptimizedKernels &&
189  !IsDiagonal<T2>::value &&
190  !IsResizable< ElementType_<T1> >::value &&
191  !( IsColumnMajorMatrix<T1>::value && IsResizable<ET2>::value ) };
192  };
194  //**********************************************************************************************
195 
196  //**********************************************************************************************
198 
201  template< typename T1, typename T2, typename T3 >
202  struct UseDefaultKernel {
203  enum : bool { value = !UseOptimizedKernel<T1,T2,T3>::value };
204  };
206  //**********************************************************************************************
207 
208  public:
209  //**Type definitions****************************************************************************
215  typedef const ElementType ReturnType;
216  typedef const ResultType CompositeType;
217 
219  typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
220 
222  typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
223 
226 
229  //**********************************************************************************************
230 
231  //**Compilation flags***************************************************************************
233  enum : bool { simdEnabled = false };
234 
236  enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
237  !evaluateRight && MT2::smpAssignable };
238  //**********************************************************************************************
239 
240  //**Constructor*********************************************************************************
246  explicit inline TDMatSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
247  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
248  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
249  {
250  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
251  }
252  //**********************************************************************************************
253 
254  //**Access operator*****************************************************************************
261  inline ReturnType operator()( size_t i, size_t j ) const {
262  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
263  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
264 
265  if( IsDiagonal<MT1>::value ) {
266  return lhs_(i,i) * rhs_(i,j);
267  }
268  else if( IsDiagonal<MT2>::value ) {
269  return lhs_(i,j) * rhs_(j,j);
270  }
272  const size_t begin( ( IsUpper<MT1>::value )
273  ?( ( IsLower<MT2>::value )
274  ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
275  , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
276  :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
277  :( ( IsLower<MT2>::value )
278  ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
279  :( 0UL ) ) );
280  const size_t end( ( IsLower<MT1>::value )
281  ?( ( IsUpper<MT2>::value )
282  ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
283  , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
284  :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
285  :( ( IsUpper<MT2>::value )
286  ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
287  :( lhs_.columns() ) ) );
288 
289  if( begin >= end ) return ElementType();
290 
291  const size_t n( end - begin );
292 
293  return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
294  }
295  else {
296  return row( lhs_, i ) * column( rhs_, j );
297  }
298  }
299  //**********************************************************************************************
300 
301  //**At function*********************************************************************************
309  inline ReturnType at( size_t i, size_t j ) const {
310  if( i >= lhs_.rows() ) {
311  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
312  }
313  if( j >= rhs_.columns() ) {
314  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
315  }
316  return (*this)(i,j);
317  }
318  //**********************************************************************************************
319 
320  //**Rows function*******************************************************************************
325  inline size_t rows() const noexcept {
326  return lhs_.rows();
327  }
328  //**********************************************************************************************
329 
330  //**Columns function****************************************************************************
335  inline size_t columns() const noexcept {
336  return rhs_.columns();
337  }
338  //**********************************************************************************************
339 
340  //**Left operand access*************************************************************************
345  inline LeftOperand leftOperand() const noexcept {
346  return lhs_;
347  }
348  //**********************************************************************************************
349 
350  //**Right operand access************************************************************************
355  inline RightOperand rightOperand() const noexcept {
356  return rhs_;
357  }
358  //**********************************************************************************************
359 
360  //**********************************************************************************************
366  template< typename T >
367  inline bool canAlias( const T* alias ) const noexcept {
368  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
369  }
370  //**********************************************************************************************
371 
372  //**********************************************************************************************
378  template< typename T >
379  inline bool isAliased( const T* alias ) const {
380  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
381  }
382  //**********************************************************************************************
383 
384  //**********************************************************************************************
389  inline bool isAligned() const noexcept {
390  return lhs_.isAligned();
391  }
392  //**********************************************************************************************
393 
394  //**********************************************************************************************
399  inline bool canSMPAssign() const noexcept {
400  return ( rows() * columns() >= SMP_TDMATSMATMULT_THRESHOLD );
401  }
402  //**********************************************************************************************
403 
404  private:
405  //**Member variables****************************************************************************
406  LeftOperand lhs_;
407  RightOperand rhs_;
408  //**********************************************************************************************
409 
410  //**Assignment to dense matrices****************************************************************
423  template< typename MT // Type of the target dense matrix
424  , bool SO > // Storage order of the target dense matrix
426  assign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
427  {
429 
430  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
431  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
432 
433  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
434  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
435 
436  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
437  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
438  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
439  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
440  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
441  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
442 
443  TDMatSMatMultExpr::selectAssignKernel( ~lhs, A, B );
444  }
446  //**********************************************************************************************
447 
448  //**Assignment to dense matrices (kernel selection)*********************************************
459  template< typename MT3 // Type of the left-hand side target matrix
460  , typename MT4 // Type of the left-hand side matrix operand
461  , typename MT5 > // Type of the right-hand side matrix operand
462  static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
463  {
464  if( C.rows() * C.columns() < TDMATSMATMULT_THRESHOLD )
465  selectSmallAssignKernel( C, A, B );
466  else
467  selectLargeAssignKernel( C, A, B );
468  }
470  //**********************************************************************************************
471 
472  //**Default assignment to dense matrices********************************************************
487  template< typename MT3 // Type of the left-hand side target matrix
488  , typename MT4 // Type of the left-hand side matrix operand
489  , typename MT5 > // Type of the right-hand side matrix operand
490  static inline void selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
491  {
492  typedef ConstIterator_<MT5> ConstIterator;
493 
494  reset( C );
495 
496  for( size_t j=0UL; j<B.rows(); ++j )
497  {
498  ConstIterator element( B.begin(j) );
499  const ConstIterator end( B.end(j) );
500 
501  if( IsDiagonal<MT4>::value )
502  {
503  for( ; element!=end; ++element ) {
504  C(j,element->index()) = A(j,j) * element->value();
505  }
506  }
507  else
508  {
509  const size_t ibegin( ( IsLower<MT4>::value )
510  ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
511  :( 0UL ) );
512  const size_t iend( ( IsUpper<MT4>::value )
513  ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
514  :( A.rows() ) );
515  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
516 
517  for( ; element!=end; ++element ) {
518  for( size_t i=ibegin; i<iend; ++i ) {
519  if( isDefault( C(i,element->index()) ) )
520  C(i,element->index()) = A(i,j) * element->value();
521  else
522  C(i,element->index()) += A(i,j) * element->value();
523  }
524  }
525  }
526  }
527  }
529  //**********************************************************************************************
530 
531  //**Default assignment to dense matrices (small matrices)***************************************
545  template< typename MT3 // Type of the left-hand side target matrix
546  , typename MT4 // Type of the left-hand side matrix operand
547  , typename MT5 > // Type of the right-hand side matrix operand
548  static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
549  selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
550  {
551  selectDefaultAssignKernel( C, A, B );
552  }
554  //**********************************************************************************************
555 
556  //**Optimized assignment to dense matrices (small matrices)*************************************
571  template< typename MT3 // Type of the left-hand side target matrix
572  , typename MT4 // Type of the left-hand side matrix operand
573  , typename MT5 > // Type of the right-hand side matrix operand
574  static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
575  selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
576  {
577  typedef ConstIterator_<MT5> ConstIterator;
578 
579  reset( C );
580 
581  size_t i( 0UL );
582 
583  for( size_t j=0UL; j<B.rows(); ++j )
584  {
585  ConstIterator element( B.begin(j) );
586  const ConstIterator end( B.end(j) );
587 
588  const size_t nonzeros( B.nonZeros(j) );
589  const size_t kpos( nonzeros & size_t(-4) );
590  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
591 
592  const size_t ibegin( ( IsLower<MT4>::value )
593  ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
594  :( 0UL ) );
595  const size_t iend( ( IsUpper<MT4>::value )
596  ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
597  :( A.rows() ) );
598  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
599 
600  const size_t inum( iend - ibegin );
601  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
602  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
603 
604  for( size_t k=0UL; k<kpos; k+=4UL )
605  {
606  const size_t j1( element->index() );
607  const ET2 v1( element->value() );
608  ++element;
609  const size_t j2( element->index() );
610  const ET2 v2( element->value() );
611  ++element;
612  const size_t j3( element->index() );
613  const ET2 v3( element->value() );
614  ++element;
615  const size_t j4( element->index() );
616  const ET2 v4( element->value() );
617  ++element;
618 
619  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
620 
621  for( i=ibegin; i<ipos; i+=4UL ) {
622  C(i ,j1) += A(i ,j) * v1;
623  C(i+1UL,j1) += A(i+1UL,j) * v1;
624  C(i+2UL,j1) += A(i+2UL,j) * v1;
625  C(i+3UL,j1) += A(i+3UL,j) * v1;
626  C(i ,j2) += A(i ,j) * v2;
627  C(i+1UL,j2) += A(i+1UL,j) * v2;
628  C(i+2UL,j2) += A(i+2UL,j) * v2;
629  C(i+3UL,j2) += A(i+3UL,j) * v2;
630  C(i ,j3) += A(i ,j) * v3;
631  C(i+1UL,j3) += A(i+1UL,j) * v3;
632  C(i+2UL,j3) += A(i+2UL,j) * v3;
633  C(i+3UL,j3) += A(i+3UL,j) * v3;
634  C(i ,j4) += A(i ,j) * v4;
635  C(i+1UL,j4) += A(i+1UL,j) * v4;
636  C(i+2UL,j4) += A(i+2UL,j) * v4;
637  C(i+3UL,j4) += A(i+3UL,j) * v4;
638  }
639  for( ; i<iend; ++i ) {
640  C(i,j1) += A(i,j) * v1;
641  C(i,j2) += A(i,j) * v2;
642  C(i,j3) += A(i,j) * v3;
643  C(i,j4) += A(i,j) * v4;
644  }
645  }
646 
647  for( ; element!=end; ++element )
648  {
649  const size_t j1( element->index() );
650  const ET2 v1( element->value() );
651 
652  for( i=ibegin; i<ipos; i+=4UL ) {
653  C(i ,j1) += A(i ,j) * v1;
654  C(i+1UL,j1) += A(i+1UL,j) * v1;
655  C(i+2UL,j1) += A(i+2UL,j) * v1;
656  C(i+3UL,j1) += A(i+3UL,j) * v1;
657  }
658  for( ; i<iend; ++i ) {
659  C(i,j1) += A(i,j) * v1;
660  }
661  }
662  }
663  }
665  //**********************************************************************************************
666 
667  //**Default assignment to dense matrices (large matrices)***************************************
681  template< typename MT3 // Type of the left-hand side target matrix
682  , typename MT4 // Type of the left-hand side matrix operand
683  , typename MT5 > // Type of the right-hand side matrix operand
684  static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
685  selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
686  {
687  selectDefaultAssignKernel( C, A, B );
688  }
690  //**********************************************************************************************
691 
692  //**Optimized assignment to dense matrices (large matrices)*************************************
707  template< typename MT3 // Type of the left-hand side target matrix
708  , typename MT4 // Type of the left-hand side matrix operand
709  , typename MT5 > // Type of the right-hand side matrix operand
710  static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
711  selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
712  {
714 
715  const OppositeType_<MT5> tmp( serial( B ) );
716  assign( C, A * tmp );
717  }
719  //**********************************************************************************************
720 
721  //**Assignment to sparse matrices***************************************************************
734  template< typename MT // Type of the target sparse matrix
735  , bool SO > // Storage order of the target sparse matrix
736  friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
737  assign( SparseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
738  {
740 
741  typedef IfTrue_< SO, ResultType, OppositeType > TmpType;
742 
748  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
749 
750  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
751  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
752 
753  const TmpType tmp( serial( rhs ) );
754  assign( ~lhs, tmp );
755  }
757  //**********************************************************************************************
758 
759  //**Restructuring assignment********************************************************************
774  template< typename MT // Type of the target matrix
775  , bool SO > // Storage order of the target matrix
776  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
777  assign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
778  {
780 
782 
783  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
784  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
785 
786  assign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
787  }
789  //**********************************************************************************************
790 
791  //**Addition assignment to dense matrices*******************************************************
804  template< typename MT // Type of the target dense matrix
805  , bool SO > // Storage order of the target dense matrix
806  friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
807  addAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
808  {
810 
811  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
812  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
813 
814  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
815  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
816 
817  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
818  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
819  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
820  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
821  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
822  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
823 
824  TDMatSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
825  }
827  //**********************************************************************************************
828 
829  //**Addition assignment to dense matrices (kernel selection)************************************
840  template< typename MT3 // Type of the left-hand side target matrix
841  , typename MT4 // Type of the left-hand side matrix operand
842  , typename MT5 > // Type of the right-hand side matrix operand
843  static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
844  {
845  if( C.rows() * C.columns() < TDMATSMATMULT_THRESHOLD )
846  selectSmallAddAssignKernel( C, A, B );
847  else
848  selectLargeAddAssignKernel( C, A, B );
849  }
851  //**********************************************************************************************
852 
853  //**Default addition assignment to dense matrices***********************************************
868  template< typename MT3 // Type of the left-hand side target matrix
869  , typename MT4 // Type of the left-hand side matrix operand
870  , typename MT5 > // Type of the right-hand side matrix operand
871  static inline void selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
872  {
873  typedef ConstIterator_<MT5> ConstIterator;
874 
875  size_t i( 0UL );
876 
877  for( size_t j=0UL; j<B.rows(); ++j )
878  {
879  ConstIterator element( B.begin(j) );
880  const ConstIterator end( B.end(j) );
881 
882  if( IsDiagonal<MT4>::value )
883  {
884  for( ; element!=end; ++element ) {
885  C(j,element->index()) += A(j,j) * element->value();
886  }
887  }
888  else
889  {
890  const size_t ibegin( ( IsLower<MT4>::value )
891  ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
892  :( 0UL ) );
893  const size_t iend( ( IsUpper<MT4>::value )
894  ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
895  :( A.rows() ) );
896  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
897 
898  const size_t inum( iend - ibegin );
899  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
900  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
901 
902  for( ; element!=end; ++element ) {
903  for( i=ibegin; i<ipos; i+=4UL ) {
904  C(i ,element->index()) += A(i ,j) * element->value();
905  C(i+1UL,element->index()) += A(i+1UL,j) * element->value();
906  C(i+2UL,element->index()) += A(i+2UL,j) * element->value();
907  C(i+3UL,element->index()) += A(i+3UL,j) * element->value();
908  }
909  for( ; i<iend; ++i ) {
910  C(i,element->index()) += A(i,j) * element->value();
911  }
912  }
913  }
914  }
915  }
917  //**********************************************************************************************
918 
919  //**Default addition assignment to dense matrices (small matrices)******************************
933  template< typename MT3 // Type of the left-hand side target matrix
934  , typename MT4 // Type of the left-hand side matrix operand
935  , typename MT5 > // Type of the right-hand side matrix operand
936  static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
937  selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
938  {
939  selectDefaultAddAssignKernel( C, A, B );
940  }
942  //**********************************************************************************************
943 
944  //**Optimized addition assignment to dense matrices (small matrices)****************************
959  template< typename MT3 // Type of the left-hand side target matrix
960  , typename MT4 // Type of the left-hand side matrix operand
961  , typename MT5 > // Type of the right-hand side matrix operand
962  static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
963  selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
964  {
965  typedef ConstIterator_<MT5> ConstIterator;
966 
967  size_t i( 0UL );
968 
969  for( size_t j=0UL; j<B.rows(); ++j )
970  {
971  ConstIterator element( B.begin(j) );
972  const ConstIterator end( B.end(j) );
973 
974  const size_t nonzeros( B.nonZeros(j) );
975  const size_t kpos( nonzeros & size_t(-4) );
976  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
977 
978  const size_t ibegin( ( IsLower<MT4>::value )
979  ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
980  :( 0UL ) );
981  const size_t iend( ( IsUpper<MT4>::value )
982  ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
983  :( A.rows() ) );
984  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
985 
986  const size_t inum( iend - ibegin );
987  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
988  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
989 
990  for( size_t k=0UL; k<kpos; k+=4UL )
991  {
992  const size_t j1( element->index() );
993  const ET2 v1( element->value() );
994  ++element;
995  const size_t j2( element->index() );
996  const ET2 v2( element->value() );
997  ++element;
998  const size_t j3( element->index() );
999  const ET2 v3( element->value() );
1000  ++element;
1001  const size_t j4( element->index() );
1002  const ET2 v4( element->value() );
1003  ++element;
1004 
1005  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1006 
1007  for( i=ibegin; i<ipos; i+=4UL ) {
1008  C(i ,j1) += A(i ,j) * v1;
1009  C(i+1UL,j1) += A(i+1UL,j) * v1;
1010  C(i+2UL,j1) += A(i+2UL,j) * v1;
1011  C(i+3UL,j1) += A(i+3UL,j) * v1;
1012  C(i ,j2) += A(i ,j) * v2;
1013  C(i+1UL,j2) += A(i+1UL,j) * v2;
1014  C(i+2UL,j2) += A(i+2UL,j) * v2;
1015  C(i+3UL,j2) += A(i+3UL,j) * v2;
1016  C(i ,j3) += A(i ,j) * v3;
1017  C(i+1UL,j3) += A(i+1UL,j) * v3;
1018  C(i+2UL,j3) += A(i+2UL,j) * v3;
1019  C(i+3UL,j3) += A(i+3UL,j) * v3;
1020  C(i ,j4) += A(i ,j) * v4;
1021  C(i+1UL,j4) += A(i+1UL,j) * v4;
1022  C(i+2UL,j4) += A(i+2UL,j) * v4;
1023  C(i+3UL,j4) += A(i+3UL,j) * v4;
1024  }
1025  for( ; i<iend; ++i ) {
1026  C(i,j1) += A(i,j) * v1;
1027  C(i,j2) += A(i,j) * v2;
1028  C(i,j3) += A(i,j) * v3;
1029  C(i,j4) += A(i,j) * v4;
1030  }
1031  }
1032 
1033  for( ; element!=end; ++element )
1034  {
1035  const size_t j1( element->index() );
1036  const ET2 v1( element->value() );
1037 
1038  for( i=ibegin; i<ipos; i+=4UL ) {
1039  C(i ,j1) += A(i ,j) * v1;
1040  C(i+1UL,j1) += A(i+1UL,j) * v1;
1041  C(i+2UL,j1) += A(i+2UL,j) * v1;
1042  C(i+3UL,j1) += A(i+3UL,j) * v1;
1043  }
1044  for( ; i<iend; ++i ) {
1045  C(i,j1) += A(i,j) * v1;
1046  }
1047  }
1048  }
1049  }
1051  //**********************************************************************************************
1052 
1053  //**Default addition assignment to dense matrices (large matrices)******************************
1067  template< typename MT3 // Type of the left-hand side target matrix
1068  , typename MT4 // Type of the left-hand side matrix operand
1069  , typename MT5 > // Type of the right-hand side matrix operand
1070  static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
1071  selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1072  {
1073  selectDefaultAddAssignKernel( C, A, B );
1074  }
1076  //**********************************************************************************************
1077 
1078  //**Optimized addition assignment to dense matrices (large matrices)****************************
1093  template< typename MT3 // Type of the left-hand side target matrix
1094  , typename MT4 // Type of the left-hand side matrix operand
1095  , typename MT5 > // Type of the right-hand side matrix operand
1096  static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
1097  selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1098  {
1100 
1101  const OppositeType_<MT5> tmp( serial( B ) );
1102  addAssign( C, A * tmp );
1103  }
1105  //**********************************************************************************************
1106 
1107  //**Restructuring addition assignment***********************************************************
1122  template< typename MT // Type of the target matrix
1123  , bool SO > // Storage order of the target matrix
1124  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1125  addAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1126  {
1128 
1129  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1130  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1131 
1132  addAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1133  }
1135  //**********************************************************************************************
1136 
1137  //**Addition assignment to sparse matrices******************************************************
1138  // No special implementation for the addition assignment to sparse matrices.
1139  //**********************************************************************************************
1140 
1141  //**Subtraction assignment to dense matrices****************************************************
1154  template< typename MT // Type of the target dense matrix
1155  , bool SO > // Storage order of the target dense matrix
1156  friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1157  subAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1158  {
1160 
1161  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1162  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1163 
1164  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1165  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1166 
1167  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1168  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1169  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1170  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1171  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1172  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1173 
1174  TDMatSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1175  }
1177  //**********************************************************************************************
1178 
1179  //**Subtraction assignment to dense matrices (kernel selection)*********************************
1190  template< typename MT3 // Type of the left-hand side target matrix
1191  , typename MT4 // Type of the left-hand side matrix operand
1192  , typename MT5 > // Type of the right-hand side matrix operand
1193  static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1194  {
1195  if( C.rows() * C.columns() < TDMATSMATMULT_THRESHOLD )
1196  selectSmallSubAssignKernel( C, A, B );
1197  else
1198  selectLargeSubAssignKernel( C, A, B );
1199  }
1201  //**********************************************************************************************
1202 
1203  //**Default subtraction assignment to dense matrices********************************************
1218  template< typename MT3 // Type of the left-hand side target matrix
1219  , typename MT4 // Type of the left-hand side matrix operand
1220  , typename MT5 > // Type of the right-hand side matrix operand
1221  static inline void selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1222  {
1223  typedef ConstIterator_<MT5> ConstIterator;
1224 
1225  size_t i( 0UL );
1226 
1227  for( size_t j=0UL; j<B.rows(); ++j )
1228  {
1229  ConstIterator element( B.begin(j) );
1230  const ConstIterator end( B.end(j) );
1231 
1232  if( IsDiagonal<MT4>::value )
1233  {
1234  for( ; element!=end; ++element ) {
1235  C(j,element->index()) -= A(j,j) * element->value();
1236  }
1237  }
1238  else
1239  {
1240  const size_t ibegin( ( IsLower<MT4>::value )
1241  ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
1242  :( 0UL ) );
1243  const size_t iend( ( IsUpper<MT4>::value )
1244  ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
1245  :( A.rows() ) );
1246  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
1247 
1248  const size_t inum( iend - ibegin );
1249  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
1250  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
1251 
1252  for( ; element!=end; ++element ) {
1253  for( i=ibegin; i<ipos; i+=4UL ) {
1254  C(i ,element->index()) -= A(i ,j) * element->value();
1255  C(i+1UL,element->index()) -= A(i+1UL,j) * element->value();
1256  C(i+2UL,element->index()) -= A(i+2UL,j) * element->value();
1257  C(i+3UL,element->index()) -= A(i+3UL,j) * element->value();
1258  }
1259  for( ; i<iend; ++i ) {
1260  C(i,element->index()) -= A(i,j) * element->value();
1261  }
1262  }
1263  }
1264  }
1265  }
1267  //**********************************************************************************************
1268 
1269  //**Default subtraction assignment to dense matrices (small matrices)***************************
1283  template< typename MT3 // Type of the left-hand side target matrix
1284  , typename MT4 // Type of the left-hand side matrix operand
1285  , typename MT5 > // Type of the right-hand side matrix operand
1286  static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
1287  selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1288  {
1289  selectDefaultSubAssignKernel( C, A, B );
1290  }
1292  //**********************************************************************************************
1293 
1294  //**Optimized subtraction assignment to dense matrices (small matrices)*************************
1309  template< typename MT3 // Type of the left-hand side target matrix
1310  , typename MT4 // Type of the left-hand side matrix operand
1311  , typename MT5 > // Type of the right-hand side matrix operand
1312  static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
1313  selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1314  {
1315  typedef ConstIterator_<MT5> ConstIterator;
1316 
1317  size_t i( 0UL );
1318 
1319  for( size_t j=0UL; j<B.rows(); ++j )
1320  {
1321  ConstIterator element( B.begin(j) );
1322  const ConstIterator end( B.end(j) );
1323 
1324  const size_t nonzeros( B.nonZeros(j) );
1325  const size_t kpos( nonzeros & size_t(-4) );
1326  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1327 
1328  const size_t ibegin( ( IsLower<MT4>::value )
1329  ?( IsStrictlyLower<MT4>::value ? j+1UL : j )
1330  :( 0UL ) );
1331  const size_t iend( ( IsUpper<MT4>::value )
1332  ?( IsStrictlyUpper<MT4>::value ? j : j+1UL )
1333  :( A.rows() ) );
1334  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
1335 
1336  const size_t inum( iend - ibegin );
1337  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
1338  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
1339 
1340  for( size_t k=0UL; k<kpos; k+=4UL )
1341  {
1342  const size_t j1( element->index() );
1343  const ET2 v1( element->value() );
1344  ++element;
1345  const size_t j2( element->index() );
1346  const ET2 v2( element->value() );
1347  ++element;
1348  const size_t j3( element->index() );
1349  const ET2 v3( element->value() );
1350  ++element;
1351  const size_t j4( element->index() );
1352  const ET2 v4( element->value() );
1353  ++element;
1354 
1355  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1356 
1357  for( i=ibegin; i<ipos; i+=4UL ) {
1358  C(i ,j1) -= A(i ,j) * v1;
1359  C(i+1UL,j1) -= A(i+1UL,j) * v1;
1360  C(i+2UL,j1) -= A(i+2UL,j) * v1;
1361  C(i+3UL,j1) -= A(i+3UL,j) * v1;
1362  C(i ,j2) -= A(i ,j) * v2;
1363  C(i+1UL,j2) -= A(i+1UL,j) * v2;
1364  C(i+2UL,j2) -= A(i+2UL,j) * v2;
1365  C(i+3UL,j2) -= A(i+3UL,j) * v2;
1366  C(i ,j3) -= A(i ,j) * v3;
1367  C(i+1UL,j3) -= A(i+1UL,j) * v3;
1368  C(i+2UL,j3) -= A(i+2UL,j) * v3;
1369  C(i+3UL,j3) -= A(i+3UL,j) * v3;
1370  C(i ,j4) -= A(i ,j) * v4;
1371  C(i+1UL,j4) -= A(i+1UL,j) * v4;
1372  C(i+2UL,j4) -= A(i+2UL,j) * v4;
1373  C(i+3UL,j4) -= A(i+3UL,j) * v4;
1374  }
1375  for( ; i<iend; ++i ) {
1376  C(i,j1) -= A(i,j) * v1;
1377  C(i,j2) -= A(i,j) * v2;
1378  C(i,j3) -= A(i,j) * v3;
1379  C(i,j4) -= A(i,j) * v4;
1380  }
1381  }
1382 
1383  for( ; element!=end; ++element )
1384  {
1385  const size_t j1( element->index() );
1386  const ET2 v1( element->value() );
1387 
1388  for( i=ibegin; i<ipos; i+=4UL ) {
1389  C(i ,j1) -= A(i ,j) * v1;
1390  C(i+1UL,j1) -= A(i+1UL,j) * v1;
1391  C(i+2UL,j1) -= A(i+2UL,j) * v1;
1392  C(i+3UL,j1) -= A(i+3UL,j) * v1;
1393  }
1394  for( ; i<iend; ++i ) {
1395  C(i,j1) -= A(i,j) * v1;
1396  }
1397  }
1398  }
1399  }
1401  //**********************************************************************************************
1402 
1403  //**Default subtraction assignment to dense matrices (large matrices)***************************
1417  template< typename MT3 // Type of the left-hand side target matrix
1418  , typename MT4 // Type of the left-hand side matrix operand
1419  , typename MT5 > // Type of the right-hand side matrix operand
1420  static inline EnableIf_< UseDefaultKernel<MT3,MT4,MT5> >
1421  selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1422  {
1423  selectDefaultSubAssignKernel( C, A, B );
1424  }
1426  //**********************************************************************************************
1427 
1428  //**Optimized subtraction assignment to dense matrices (large matrices)*************************
1443  template< typename MT3 // Type of the left-hand side target matrix
1444  , typename MT4 // Type of the left-hand side matrix operand
1445  , typename MT5 > // Type of the right-hand side matrix operand
1446  static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
1447  selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1448  {
1450 
1451  const OppositeType_<MT5> tmp( serial( B ) );
1452  subAssign( C, A * tmp );
1453  }
1455  //**********************************************************************************************
1456 
1457  //**Restructuring subtraction assignment********************************************************
1472  template< typename MT // Type of the target matrix
1473  , bool SO > // Storage order of the target matrix
1474  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1475  subAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1476  {
1478 
1480 
1481  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1482  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1483 
1484  subAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1485  }
1487  //**********************************************************************************************
1488 
1489  //**Subtraction assignment to sparse matrices***************************************************
1490  // No special implementation for the subtraction assignment to sparse matrices.
1491  //**********************************************************************************************
1492 
1493  //**Multiplication assignment to dense matrices*************************************************
1494  // No special implementation for the multiplication assignment to dense matrices.
1495  //**********************************************************************************************
1496 
1497  //**Multiplication assignment to sparse matrices************************************************
1498  // No special implementation for the multiplication assignment to sparse matrices.
1499  //**********************************************************************************************
1500 
1501  //**SMP assignment to dense matrices************************************************************
1517  template< typename MT // Type of the target dense matrix
1518  , bool SO > // Storage order of the target dense matrix
1519  friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
1520  smpAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1521  {
1523 
1524  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1525  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1526 
1527  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1528  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1529 
1530  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1531  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1532  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1533  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1534  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1535  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1536 
1537  smpAssign( ~lhs, A * B );
1538  }
1540  //**********************************************************************************************
1541 
1542  //**SMP assignment to sparse matrices***********************************************************
1558  template< typename MT // Type of the target sparse matrix
1559  , bool SO > // Storage order of the target sparse matrix
1560  friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
1561  smpAssign( SparseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1562  {
1564 
1565  typedef IfTrue_< SO, ResultType, OppositeType > TmpType;
1566 
1572  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
1573 
1574  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1575  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1576 
1577  const TmpType tmp( rhs );
1578  smpAssign( ~lhs, tmp );
1579  }
1581  //**********************************************************************************************
1582 
1583  //**Restructuring SMP assignment****************************************************************
1598  template< typename MT // Type of the target matrix
1599  , bool SO > // Storage order of the target matrix
1600  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1601  smpAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1602  {
1604 
1605  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1606  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1607 
1608  smpAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1609  }
1611  //**********************************************************************************************
1612 
1613  //**SMP addition assignment to dense matrices***************************************************
1629  template< typename MT // Type of the target dense matrix
1630  , bool SO > // Storage order of the target sparse matrix
1631  friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
1632  smpAddAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1633  {
1635 
1636  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1637  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1638 
1639  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1640  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1641 
1642  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1643  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1644  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1645  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1646  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1647  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1648 
1649  smpAddAssign( ~lhs, A * B );
1650  }
1652  //**********************************************************************************************
1653 
1654  //**Restructuring SMP addition assignment*******************************************************
1669  template< typename MT // Type of the target matrix
1670  , bool SO > // Storage order of the target matrix
1671  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1672  smpAddAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1673  {
1675 
1677 
1678  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1679  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1680 
1681  smpAddAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1682  }
1684  //**********************************************************************************************
1685 
1686  //**SMP addition assignment to sparse matrices**************************************************
1687  // No special implementation for the SMP addition assignment to sparse matrices.
1688  //**********************************************************************************************
1689 
1690  //**SMP subtraction assignment to dense matrices************************************************
1706  template< typename MT // Type of the target dense matrix
1707  , bool SO > // Storage order of the target sparse matrix
1708  friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
1709  smpSubAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1710  {
1712 
1713  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1714  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1715 
1716  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1717  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1718 
1719  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1720  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1721  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1722  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1723  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1724  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1725 
1726  smpSubAssign( ~lhs, A * B );
1727  }
1729  //**********************************************************************************************
1730 
1731  //**Restructuring SMP subtraction assignment****************************************************
1746  template< typename MT // Type of the target matrix
1747  , bool SO > // Storage order of the target matrix
1748  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1749  smpSubAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1750  {
1752 
1754 
1755  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1756  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1757 
1758  smpSubAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1759  }
1761  //**********************************************************************************************
1762 
1763  //**SMP subtraction assignment to sparse matrices***********************************************
1764  // No special implementation for the SMP subtraction assignment to sparse matrices.
1765  //**********************************************************************************************
1766 
1767  //**SMP multiplication assignment to dense matrices*********************************************
1768  // No special implementation for the SMP multiplication assignment to dense matrices.
1769  //**********************************************************************************************
1770 
1771  //**SMP multiplication assignment to sparse matrices********************************************
1772  // No special implementation for the SMP multiplication assignment to sparse matrices.
1773  //**********************************************************************************************
1774 
1775  //**Compile time checks*************************************************************************
1783  //**********************************************************************************************
1784 };
1785 //*************************************************************************************************
1786 
1787 
1788 
1789 
1790 //=================================================================================================
1791 //
1792 // GLOBAL BINARY ARITHMETIC OPERATORS
1793 //
1794 //=================================================================================================
1795 
1796 //*************************************************************************************************
1826 template< typename T1 // Type of the left-hand side dense matrix
1827  , typename T2 > // Type of the right-hand side sparse matrix
1828 inline const TDMatSMatMultExpr<T1,T2>
1830 {
1832 
1833  if( (~lhs).columns() != (~rhs).rows() ) {
1834  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1835  }
1836 
1837  return TDMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
1838 }
1839 //*************************************************************************************************
1840 
1841 
1842 
1843 
1844 //=================================================================================================
1845 //
1846 // ROWS SPECIALIZATIONS
1847 //
1848 //=================================================================================================
1849 
1850 //*************************************************************************************************
1852 template< typename MT1, typename MT2 >
1853 struct Rows< TDMatSMatMultExpr<MT1,MT2> > : public Rows<MT1>
1854 {};
1856 //*************************************************************************************************
1857 
1858 
1859 
1860 
1861 //=================================================================================================
1862 //
1863 // COLUMNS SPECIALIZATIONS
1864 //
1865 //=================================================================================================
1866 
1867 //*************************************************************************************************
1869 template< typename MT1, typename MT2 >
1870 struct Columns< TDMatSMatMultExpr<MT1,MT2> > : public Columns<MT2>
1871 {};
1873 //*************************************************************************************************
1874 
1875 
1876 
1877 
1878 //=================================================================================================
1879 //
1880 // ISALIGNED SPECIALIZATIONS
1881 //
1882 //=================================================================================================
1883 
1884 //*************************************************************************************************
1886 template< typename MT1, typename MT2 >
1887 struct IsAligned< TDMatSMatMultExpr<MT1,MT2> >
1888  : public BoolConstant< IsAligned<MT1>::value >
1889 {};
1891 //*************************************************************************************************
1892 
1893 
1894 
1895 
1896 //=================================================================================================
1897 //
1898 // ISLOWER SPECIALIZATIONS
1899 //
1900 //=================================================================================================
1901 
1902 //*************************************************************************************************
1904 template< typename MT1, typename MT2 >
1905 struct IsLower< TDMatSMatMultExpr<MT1,MT2> >
1906  : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
1907 {};
1909 //*************************************************************************************************
1910 
1911 
1912 
1913 
1914 //=================================================================================================
1915 //
1916 // ISUNILOWER SPECIALIZATIONS
1917 //
1918 //=================================================================================================
1919 
1920 //*************************************************************************************************
1922 template< typename MT1, typename MT2 >
1923 struct IsUniLower< TDMatSMatMultExpr<MT1,MT2> >
1924  : public BoolConstant< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
1925 {};
1927 //*************************************************************************************************
1928 
1929 
1930 
1931 
1932 //=================================================================================================
1933 //
1934 // ISSTRICTLYLOWER SPECIALIZATIONS
1935 //
1936 //=================================================================================================
1937 
1938 //*************************************************************************************************
1940 template< typename MT1, typename MT2 >
1941 struct IsStrictlyLower< TDMatSMatMultExpr<MT1,MT2> >
1942  : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
1943  , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
1944 {};
1946 //*************************************************************************************************
1947 
1948 
1949 
1950 
1951 //=================================================================================================
1952 //
1953 // ISUPPER SPECIALIZATIONS
1954 //
1955 //=================================================================================================
1956 
1957 //*************************************************************************************************
1959 template< typename MT1, typename MT2 >
1960 struct IsUpper< TDMatSMatMultExpr<MT1,MT2> >
1961  : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
1962 {};
1964 //*************************************************************************************************
1965 
1966 
1967 
1968 
1969 //=================================================================================================
1970 //
1971 // ISUNIUPPER SPECIALIZATIONS
1972 //
1973 //=================================================================================================
1974 
1975 //*************************************************************************************************
1977 template< typename MT1, typename MT2 >
1978 struct IsUniUpper< TDMatSMatMultExpr<MT1,MT2> >
1979  : public BoolConstant< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
1980 {};
1982 //*************************************************************************************************
1983 
1984 
1985 
1986 
1987 //=================================================================================================
1988 //
1989 // ISSTRICTLYUPPER SPECIALIZATIONS
1990 //
1991 //=================================================================================================
1992 
1993 //*************************************************************************************************
1995 template< typename MT1, typename MT2 >
1996 struct IsStrictlyUpper< TDMatSMatMultExpr<MT1,MT2> >
1997  : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
1998  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
1999 {};
2001 //*************************************************************************************************
2002 
2003 
2004 
2005 
2006 //=================================================================================================
2007 //
2008 // EXPRESSION TRAIT SPECIALIZATIONS
2009 //
2010 //=================================================================================================
2011 
2012 //*************************************************************************************************
2014 template< typename MT1, typename MT2, typename VT >
2015 struct TDMatDVecMultExprTrait< TDMatSMatMultExpr<MT1,MT2>, VT >
2016 {
2017  public:
2018  //**********************************************************************************************
2019  using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
2020  , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
2021  , IsDenseVector<VT>, IsColumnVector<VT> >
2022  , TDMatDVecMultExprTrait_< MT1, SMatDVecMultExprTrait_<MT2,VT> >
2023  , INVALID_TYPE >;
2024  //**********************************************************************************************
2025 };
2027 //*************************************************************************************************
2028 
2029 
2030 //*************************************************************************************************
2032 template< typename MT1, typename MT2, typename VT >
2033 struct TDMatSVecMultExprTrait< TDMatSMatMultExpr<MT1,MT2>, VT >
2034 {
2035  public:
2036  //**********************************************************************************************
2037  using Type = If_< And< IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
2038  , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2>
2039  , IsSparseVector<VT>, IsColumnVector<VT> >
2040  , TDMatSVecMultExprTrait_< MT1, SMatSVecMultExprTrait_<MT2,VT> >
2041  , INVALID_TYPE >;
2042  //**********************************************************************************************
2043 };
2045 //*************************************************************************************************
2046 
2047 
2048 //*************************************************************************************************
2050 template< typename VT, typename MT1, typename MT2 >
2051 struct TDVecTDMatMultExprTrait< VT, TDMatSMatMultExpr<MT1,MT2> >
2052 {
2053  public:
2054  //**********************************************************************************************
2055  using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
2056  , IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
2057  , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
2058  , TDMatDVecMultExprTrait_< MT1, SMatDVecMultExprTrait_<MT2,VT> >
2059  , INVALID_TYPE >;
2060  //**********************************************************************************************
2061 };
2063 //*************************************************************************************************
2064 
2065 
2066 //*************************************************************************************************
2068 template< typename VT, typename MT1, typename MT2 >
2069 struct TSVecTDMatMultExprTrait< VT, TDMatSMatMultExpr<MT1,MT2> >
2070 {
2071  public:
2072  //**********************************************************************************************
2073  using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
2074  , IsDenseMatrix<MT1>, IsColumnMajorMatrix<MT1>
2075  , IsSparseMatrix<MT2>, IsRowMajorMatrix<MT2> >
2076  , TDVecSMatMultExprTrait_< TSVecTDMatMultExprTrait_<VT,MT1>, MT2 >
2077  , INVALID_TYPE >;
2078  //**********************************************************************************************
2079 };
2081 //*************************************************************************************************
2082 
2083 
2084 //*************************************************************************************************
2086 template< typename MT1, typename MT2, bool AF >
2087 struct SubmatrixExprTrait< TDMatSMatMultExpr<MT1,MT2>, AF >
2088 {
2089  public:
2090  //**********************************************************************************************
2091  using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
2092  , SubmatrixExprTrait_<const MT2,AF> >;
2093  //**********************************************************************************************
2094 };
2096 //*************************************************************************************************
2097 
2098 
2099 //*************************************************************************************************
2101 template< typename MT1, typename MT2 >
2102 struct RowExprTrait< TDMatSMatMultExpr<MT1,MT2> >
2103 {
2104  public:
2105  //**********************************************************************************************
2106  using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
2107  //**********************************************************************************************
2108 };
2110 //*************************************************************************************************
2111 
2112 
2113 //*************************************************************************************************
2115 template< typename MT1, typename MT2 >
2116 struct ColumnExprTrait< TDMatSMatMultExpr<MT1,MT2> >
2117 {
2118  public:
2119  //**********************************************************************************************
2120  using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
2121  //**********************************************************************************************
2122 };
2124 //*************************************************************************************************
2125 
2126 } // namespace blaze
2127 
2128 #endif
CompositeType_< MT1 > CT1
Composite type of the left-hand side dense matrix expression.
Definition: TDMatSMatMultExpr.h:138
#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
Header file for the SMatDVecMultExprTrait class template.
const ResultType CompositeType
Data type for composite expression templates.
Definition: TDMatSMatMultExpr.h:216
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
If_< IsExpression< MT2 >, const MT2, const MT2 & > RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: TDMatSMatMultExpr.h:222
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.
RightOperand rightOperand() const noexcept
Returns the right-hand side sparse matrix operand.
Definition: TDMatSMatMultExpr.h:355
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.
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
Header file for the IsColumnMajorMatrix type trait.
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:533
ResultType_< MT2 > RT2
Result type of the right-hand side sparse matrix expression.
Definition: TDMatSMatMultExpr.h:135
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
Header file for the TDVecSMatMultExprTrait class template.
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
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TDMatSMatMultExpr.h:215
Constraints on the storage order of matrix types.
Header file for the RequiresEvaluation type trait.
System settings for performance optimizations.
Expression object for transpose dense matrix-sparse matrix multiplications.The TDMatSMatMultExpr clas...
Definition: Forward.h:131
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
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
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:573
Constraint on the data type.
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
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: TDMatSMatMultExpr.h:335
Header file for the DisableIf class template.
Header file for the multiplication trait.
Header file for the IsStrictlyUpper type trait.
bool isAligned() const noexcept
Returns whether the operands of the expression are properly aligned in memory.
Definition: TDMatSMatMultExpr.h:389
Header file for the IsSymmetric type trait.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:57
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
MultTrait_< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: TDMatSMatMultExpr.h:211
Header file for the TSVecTDMatMultExprTrait class template.
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2647
IfTrue_< evaluateLeft, const RT1, CT1 > LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: TDMatSMatMultExpr.h:225
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.
Header file for the TDMatSVecMultExprTrait 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.
typename T::ElementType ElementType_
Alias declaration for nested ElementType type definitions.The ElementType_ alias declaration provides...
Definition: Aliases.h:163
ElementType_< RT1 > ET1
Element type of the left-hand side dense matrix expression.
Definition: TDMatSMatMultExpr.h:136
Header file for the IsLower type trait.
Header file for the IsAligned type trait.
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: TDMatSMatMultExpr.h:367
Compile time check for diagonal matrices.This type trait tests whether or not the given template para...
Definition: IsDiagonal.h:90
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: TDMatSMatMultExpr.h:407
LeftOperand lhs_
Left-hand side dense matrix of the multiplication expression.
Definition: TDMatSMatMultExpr.h:406
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.
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: TDMatSMatMultExpr.h:379
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
ElementType_< ResultType > ElementType
Resulting element type.
Definition: TDMatSMatMultExpr.h:214
OppositeType_< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: TDMatSMatMultExpr.h:212
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
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: TDMatSMatMultExpr.h:261
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.
ElementType_< RT2 > ET2
Element type of the right-hand side sparse matrix expression.
Definition: TDMatSMatMultExpr.h:137
CompositeType_< MT2 > CT2
Composite type of the right-hand side sparse matrix expression.
Definition: TDMatSMatMultExpr.h:139
#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
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: TDMatSMatMultExpr.h:309
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
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.
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.
Header file for the isDefault shim.
TransposeType_< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: TDMatSMatMultExpr.h:213
Constraint on the data type.
Constraints on the storage order of matrix types.
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: TDMatSMatMultExpr.h:399
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: TDMatSMatMultExpr.h:325
IntegralConstant< bool, B > BoolConstant
Generic wrapper for a compile time constant boolean value.The BoolConstant class template represents ...
Definition: IntegralConstant.h:100
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
TDMatSMatMultExpr< MT1, MT2 > This
Type of this TDMatSMatMultExpr instance.
Definition: TDMatSMatMultExpr.h:210
Header file for the IsComputation type trait class.
Header file for the TDMatDVecMultExprTrait class template.
#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.
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 IsColumnVector type trait.
Constraint on the data type.
LeftOperand leftOperand() const noexcept
Returns the left-hand side transpose dense matrix operand.
Definition: TDMatSMatMultExpr.h:345
IfTrue_< evaluateRight, const RT2, CT2 > RT
Type for the assignment of the right-hand side sparse matrix operand.
Definition: TDMatSMatMultExpr.h:228
Header file for the IsResizable type trait.
TDMatSMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the TDMatSMatMultExpr class.
Definition: TDMatSMatMultExpr.h:246
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
Header file for the TDVecTDMatMultExprTrait class template.
#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
If_< IsExpression< MT1 >, const MT1, const MT1 & > LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: TDMatSMatMultExpr.h:219
ResultType_< MT1 > RT1
Result type of the left-hand side dense matrix expression.
Definition: TDMatSMatMultExpr.h:134
Header file for the IsExpression type trait class.
Header file for the FunctionTrace class.