TSMatDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_TSMATDMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_TSMATDMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <blaze/math/Aliases.h>
53 #include <blaze/math/Exception.h>
66 #include <blaze/math/shims/Reset.h>
91 #include <blaze/math/views/Check.h>
96 #include <blaze/util/Assert.h>
97 #include <blaze/util/DisableIf.h>
98 #include <blaze/util/EnableIf.h>
101 #include <blaze/util/mpl/If.h>
102 #include <blaze/util/Types.h>
104 
105 
106 namespace blaze {
107 
108 //=================================================================================================
109 //
110 // CLASS SMATDMATMULTEXPR
111 //
112 //=================================================================================================
113 
114 //*************************************************************************************************
121 template< typename MT1 // Type of the left-hand side dense matrix
122  , typename MT2 // Type of the right-hand side sparse matrix
123  , bool SF // Symmetry flag
124  , bool HF // Hermitian flag
125  , bool LF // Lower flag
126  , bool UF > // Upper flag
127 class TSMatDMatMultExpr
128  : public MatMatMultExpr< DenseMatrix< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, false > >
129  , private Computation
130 {
131  private:
132  //**Type definitions****************************************************************************
139  //**********************************************************************************************
140 
141  //**********************************************************************************************
143  static constexpr bool evaluateLeft = ( IsComputation_v<MT1> || RequiresEvaluation_v<MT1> );
144  //**********************************************************************************************
145 
146  //**********************************************************************************************
148  static constexpr bool evaluateRight = ( IsComputation_v<MT2> || RequiresEvaluation_v<MT2> );
149  //**********************************************************************************************
150 
151  //**********************************************************************************************
152  static constexpr bool SYM = ( SF && !( HF || LF || UF ) );
153  static constexpr bool HERM = ( HF && !( LF || UF ) );
154  static constexpr bool LOW = ( LF || ( ( SF || HF ) && UF ) );
155  static constexpr bool UPP = ( UF || ( ( SF || HF ) && LF ) );
156  //**********************************************************************************************
157 
158  //**********************************************************************************************
160 
165  template< typename T1, typename T2, typename T3 >
166  static constexpr bool CanExploitSymmetry_v = IsSymmetric_v<T2>;
168  //**********************************************************************************************
169 
170  //**********************************************************************************************
172 
176  template< typename T1, typename T2, typename T3 >
177  static constexpr bool IsEvaluationRequired_v =
178  ( ( evaluateLeft || evaluateRight ) && !CanExploitSymmetry_v<T1,T2,T3> );
180  //**********************************************************************************************
181 
182  //**********************************************************************************************
184 
187  template< typename T1, typename T2, typename T3 >
188  static constexpr bool UseOptimizedKernel_v =
189  ( useOptimizedKernels &&
190  !IsDiagonal_v<T3> &&
191  !IsResizable_v< ElementType_t<T1> > &&
192  !IsResizable_v<ET1> );
194  //**********************************************************************************************
195 
196  //**********************************************************************************************
198 
201  template< typename T1, typename T2, typename T3 >
202  static constexpr bool UseDefaultKernel_v = !UseOptimizedKernel_v<T1,T2,T3>;
204  //**********************************************************************************************
205 
206  //**********************************************************************************************
208 
211  using ForwardFunctor = If_t< HERM
212  , DeclHerm
213  , If_t< SYM
214  , DeclSym
215  , If_t< LOW
216  , If_t< UPP
217  , DeclDiag
218  , DeclLow >
219  , If_t< UPP
220  , DeclUpp
221  , Noop > > > >;
223  //**********************************************************************************************
224 
225  public:
226  //**Type definitions****************************************************************************
229 
232 
234  using ResultType = typename If_t< HERM
236  , If_t< SYM
238  , If_t< LOW
239  , If_t< UPP
242  , If_t< UPP
244  , MultTrait<RT1,RT2> > > > >::Type;
245 
249  using ReturnType = const ElementType;
250  using CompositeType = const ResultType;
251 
253  using LeftOperand = If_t< IsExpression_v<MT1>, const MT1, const MT1& >;
254 
256  using RightOperand = If_t< IsExpression_v<MT2>, const MT2, const MT2& >;
257 
260 
263  //**********************************************************************************************
264 
265  //**Compilation flags***************************************************************************
267  static constexpr bool simdEnabled = false;
268 
270  static constexpr bool smpAssignable =
272  //**********************************************************************************************
273 
274  //**Constructor*********************************************************************************
280  explicit inline TSMatDMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
281  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
282  , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
283  {
284  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
285  }
286  //**********************************************************************************************
287 
288  //**Access operator*****************************************************************************
295  inline ReturnType operator()( size_t i, size_t j ) const {
296  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
297  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
298 
299  if( IsDiagonal_v<MT1> ) {
300  return lhs_(i,i) * rhs_(i,j);
301  }
302  else if( IsDiagonal_v<MT2> ) {
303  return lhs_(i,j) * rhs_(j,j);
304  }
305  else if( IsTriangular_v<MT1> || IsTriangular_v<MT2> ) {
306  const size_t begin( ( IsUpper_v<MT1> )
307  ?( ( IsLower_v<MT2> )
308  ?( max( ( IsStrictlyUpper_v<MT1> ? i+1UL : i )
309  , ( IsStrictlyLower_v<MT2> ? j+1UL : j ) ) )
310  :( IsStrictlyUpper_v<MT1> ? i+1UL : i ) )
311  :( ( IsLower_v<MT2> )
312  ?( IsStrictlyLower_v<MT2> ? j+1UL : j )
313  :( 0UL ) ) );
314  const size_t end( ( IsLower_v<MT1> )
315  ?( ( IsUpper_v<MT2> )
316  ?( min( ( IsStrictlyLower_v<MT1> ? i : i+1UL )
317  , ( IsStrictlyUpper_v<MT2> ? j : j+1UL ) ) )
318  :( IsStrictlyLower_v<MT1> ? i : i+1UL ) )
319  :( ( IsUpper_v<MT2> )
320  ?( IsStrictlyUpper_v<MT2> ? j : j+1UL )
321  :( lhs_.columns() ) ) );
322 
323  if( begin >= end ) return ElementType();
324 
325  const size_t n( end - begin );
326 
327  return subvector( row( lhs_, i, unchecked ), begin, n, unchecked ) *
328  subvector( column( rhs_, j, unchecked ), begin, n, unchecked );
329  }
330  else {
331  return row( lhs_, i, unchecked ) * column( rhs_, j, unchecked );
332  }
333  }
334  //**********************************************************************************************
335 
336  //**At function*********************************************************************************
344  inline ReturnType at( size_t i, size_t j ) const {
345  if( i >= lhs_.rows() ) {
346  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
347  }
348  if( j >= rhs_.columns() ) {
349  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
350  }
351  return (*this)(i,j);
352  }
353  //**********************************************************************************************
354 
355  //**Rows function*******************************************************************************
360  inline size_t rows() const noexcept {
361  return lhs_.rows();
362  }
363  //**********************************************************************************************
364 
365  //**Columns function****************************************************************************
370  inline size_t columns() const noexcept {
371  return rhs_.columns();
372  }
373  //**********************************************************************************************
374 
375  //**Left operand access*************************************************************************
380  inline LeftOperand leftOperand() const noexcept {
381  return lhs_;
382  }
383  //**********************************************************************************************
384 
385  //**Right operand access************************************************************************
390  inline RightOperand rightOperand() const noexcept {
391  return rhs_;
392  }
393  //**********************************************************************************************
394 
395  //**********************************************************************************************
401  template< typename T >
402  inline bool canAlias( const T* alias ) const noexcept {
403  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
404  }
405  //**********************************************************************************************
406 
407  //**********************************************************************************************
413  template< typename T >
414  inline bool isAliased( const T* alias ) const noexcept {
415  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
416  }
417  //**********************************************************************************************
418 
419  //**********************************************************************************************
424  inline bool isAligned() const noexcept {
425  return rhs_.isAligned();
426  }
427  //**********************************************************************************************
428 
429  //**********************************************************************************************
434  inline bool canSMPAssign() const noexcept {
435  return ( rows() * columns() >= SMP_TSMATDMATMULT_THRESHOLD ) && !IsDiagonal_v<MT2>;
436  }
437  //**********************************************************************************************
438 
439  private:
440  //**Member variables****************************************************************************
443  //**********************************************************************************************
444 
445  //**Assignment to dense matrices****************************************************************
458  template< typename MT // Type of the target dense matrix
459  , bool SO > // Storage order of the target dense matrix
460  friend inline auto assign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
462  {
464 
465  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
466  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
467 
468  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
469  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
470 
471  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
472  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
473  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
474  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
475  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
476  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
477 
478  TSMatDMatMultExpr::selectAssignKernel( ~lhs, A, B );
479  }
481  //**********************************************************************************************
482 
483  //**Assignment to dense matrices (kernel selection)*********************************************
494  template< typename MT3 // Type of the left-hand side target matrix
495  , typename MT4 // Type of the left-hand side matrix operand
496  , typename MT5 > // Type of the right-hand side matrix operand
497  static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
498  {
499  const size_t size( C.rows() * C.columns() );
500 
501  if( ( IsRowMajorMatrix_v<MT3> && size < TSMATDMATMULT_THRESHOLD ) ||
502  ( IsColumnMajorMatrix_v<MT3> && size < 625UL ) )
503  selectSmallAssignKernel( C, A, B );
504  else
505  selectLargeAssignKernel( C, A, B );
506  }
508  //**********************************************************************************************
509 
510  //**Default assignment to dense matrices********************************************************
525  template< typename MT3 // Type of the left-hand side target matrix
526  , typename MT4 // Type of the left-hand side matrix operand
527  , typename MT5 > // Type of the right-hand side matrix operand
528  static inline void selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
529  {
530  reset( C );
531 
532  if( IsDiagonal_v<MT5> )
533  {
534  for( size_t i=0UL; i<A.columns(); ++i )
535  {
536  const auto end( A.end(i) );
537  auto element( A.begin(i) );
538 
539  for( ; element!=end; ++element ) {
540  C(element->index(),i) = element->value() * B(i,i);
541  }
542  }
543  }
544  else
545  {
546  const size_t block( IsRowMajorMatrix_v<MT3> ? 256UL : 8UL );
547 
548  for( size_t jj=0UL; jj<B.columns(); jj+=block )
549  {
550  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
551 
552  for( size_t i=0UL; i<A.columns(); ++i )
553  {
554  const auto end( A.end(i) );
555  auto element( A.begin(i) );
556 
557  for( ; element!=end; ++element )
558  {
559  const size_t i1( element->index() );
560 
561  const size_t jbegin( ( IsUpper_v<MT5> )
562  ?( ( SYM || HERM || UPP )
563  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
564  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
565  :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
566  const size_t jend( ( IsLower_v<MT5> )
567  ?( ( LOW )
568  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
569  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
570  :( LOW ? min(i1+1UL,jpos) : jpos ) );
571 
572  if( jbegin >= jend )
573  continue;
574 
575  for( size_t j=jbegin; j<jend; ++j ) {
576  if( isDefault( C(i1,j) ) )
577  C(i1,j) = element->value() * B(i,j);
578  else
579  C(i1,j) += element->value() * B(i,j);
580  }
581  }
582  }
583  }
584  }
585 
586  if( SYM || HERM ) {
587  for( size_t j=0UL; j<B.columns(); ++j ) {
588  for( size_t i=j+1UL; i<A.rows(); ++i ) {
589  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
590  }
591  }
592  }
593  }
595  //**********************************************************************************************
596 
597  //**Default assignment to dense matrices (small matrices)***************************************
611  template< typename MT3 // Type of the left-hand side target matrix
612  , typename MT4 // Type of the left-hand side matrix operand
613  , typename MT5 > // Type of the right-hand side matrix operand
614  static inline auto selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
615  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
616  {
617  selectDefaultAssignKernel( C, A, B );
618  }
620  //**********************************************************************************************
621 
622  //**Optimized assignment to dense matrices (small matrices)*************************************
637  template< typename MT3 // Type of the left-hand side target matrix
638  , typename MT4 // Type of the left-hand side matrix operand
639  , typename MT5 > // Type of the right-hand side matrix operand
640  static inline auto selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
641  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
642  {
643  const size_t block( ( IsRowMajorMatrix_v<MT3> )?( 256UL ):( 8UL ) );
644 
645  reset( C );
646 
647  for( size_t jj=0UL; jj<B.columns(); jj+=block )
648  {
649  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
650 
651  for( size_t i=0UL; i<A.columns(); ++i )
652  {
653  const auto end( A.end(i) );
654  auto element( A.begin(i) );
655 
656  const size_t nonzeros( A.nonZeros(i) );
657  const size_t kpos( nonzeros & size_t(-4) );
658  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
659 
660  for( size_t k=0UL; k<kpos; k+=4UL )
661  {
662  const size_t i1( element->index() );
663  const ET1 v1( element->value() );
664  ++element;
665  const size_t i2( element->index() );
666  const ET1 v2( element->value() );
667  ++element;
668  const size_t i3( element->index() );
669  const ET1 v3( element->value() );
670  ++element;
671  const size_t i4( element->index() );
672  const ET1 v4( element->value() );
673  ++element;
674 
675  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
676 
677  const size_t jbegin( ( IsUpper_v<MT5> )
678  ?( ( SYM || HERM || UPP )
679  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
680  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
681  :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
682  const size_t jend( ( IsLower_v<MT5> )
683  ?( ( LOW )
684  ?( min( i4+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
685  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
686  :( LOW ? min(i4+1UL,jpos) : jpos ) );
687 
688  if( jbegin >= jend )
689  continue;
690 
691  for( size_t j=jbegin; j<jend; ++j ) {
692  C(i1,j) += v1 * B(i,j);
693  C(i2,j) += v2 * B(i,j);
694  C(i3,j) += v3 * B(i,j);
695  C(i4,j) += v4 * B(i,j);
696  }
697  }
698 
699  for( ; element!=end; ++element )
700  {
701  const size_t i1( element->index() );
702 
703  const size_t jbegin( ( IsUpper_v<MT5> )
704  ?( ( SYM || HERM || UPP )
705  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
706  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
707  :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
708  const size_t jend( ( IsLower_v<MT5> )
709  ?( ( LOW )
710  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
711  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
712  :( LOW ? min(i1+1UL,jpos) : jpos ) );
713 
714  if( jbegin >= jend )
715  continue;
716 
717  for( size_t j=jbegin; j<jend; ++j ) {
718  C(i1,j) += element->value() * B(i,j);
719  }
720  }
721  }
722  }
723 
724  if( SYM || HERM ) {
725  for( size_t j=0UL; j<B.columns(); ++j ) {
726  for( size_t i=j+1UL; i<A.rows(); ++i ) {
727  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
728  }
729  }
730  }
731  }
733  //**********************************************************************************************
734 
735  //**Default assignment to dense matrices (large matrices)***************************************
749  template< typename MT3 // Type of the left-hand side target matrix
750  , typename MT4 // Type of the left-hand side matrix operand
751  , typename MT5 > // Type of the right-hand side matrix operand
752  static inline auto selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
753  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
754  {
755  selectDefaultAssignKernel( C, A, B );
756  }
758  //**********************************************************************************************
759 
760  //**Optimized assignment to dense matrices (large matrices)*************************************
775  template< typename MT3 // Type of the left-hand side target matrix
776  , typename MT4 // Type of the left-hand side matrix operand
777  , typename MT5 > // Type of the right-hand side matrix operand
778  static inline auto selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
779  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
780  {
781  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_t<MT4> );
782 
783  const ForwardFunctor fwd;
784 
785  const OppositeType_t<MT4> tmp( serial( A ) );
786  assign( C, fwd( tmp * B ) );
787  }
789  //**********************************************************************************************
790 
791  //**Assignment to sparse matrices***************************************************************
804  template< typename MT // Type of the target sparse matrix
805  , bool SO > // Storage order of the target sparse matrix
806  friend inline auto assign( SparseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
807  -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
808  {
810 
811  using TmpType = If_t< SO, OppositeType, ResultType >;
812 
819 
820  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
821  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
822 
823  const ForwardFunctor fwd;
824 
825  const TmpType tmp( serial( rhs ) );
826  assign( ~lhs, fwd( tmp ) );
827  }
829  //**********************************************************************************************
830 
831  //**Restructuring assignment to row-major matrices**********************************************
846  template< typename MT // Type of the target matrix
847  , bool SO > // Storage order of the target matrix
848  friend inline auto assign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
849  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
850  {
852 
854 
855  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
856  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
857 
858  const ForwardFunctor fwd;
859 
860  assign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
861  }
863  //**********************************************************************************************
864 
865  //**Addition assignment to dense matrices*******************************************************
878  template< typename MT // Type of the target dense matrix
879  , bool SO > // Storage order of the target dense matrix
880  friend inline auto addAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
881  -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
882  {
884 
885  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
886  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
887 
888  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
889  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
890 
891  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
892  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
893  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
894  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
895  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
896  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
897 
898  TSMatDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
899  }
901  //**********************************************************************************************
902 
903  //**Addition assignment to dense matrices (kernel selection)************************************
914  template< typename MT3 // Type of the left-hand side target matrix
915  , typename MT4 // Type of the left-hand side matrix operand
916  , typename MT5 > // Type of the right-hand side matrix operand
917  static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
918  {
919  const size_t size( C.rows() * C.columns() );
920 
921  if( ( IsRowMajorMatrix_v<MT3> && size < TSMATDMATMULT_THRESHOLD ) ||
922  ( IsColumnMajorMatrix_v<MT3> && size < 625UL ) )
923  selectSmallAddAssignKernel( C, A, B );
924  else
925  selectLargeAddAssignKernel( C, A, B );
926  }
928  //**********************************************************************************************
929 
930  //**Default addition assignment to dense matrices***********************************************
945  template< typename MT3 // Type of the left-hand side target matrix
946  , typename MT4 // Type of the left-hand side matrix operand
947  , typename MT5 > // Type of the right-hand side matrix operand
948  static inline void selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
949  {
950  if( IsDiagonal_v<MT5> )
951  {
952  for( size_t i=0UL; i<A.columns(); ++i )
953  {
954  const auto end( A.end(i) );
955  auto element( A.begin(i) );
956 
957  for( ; element!=end; ++element ) {
958  C(element->index(),i) += element->value() * B(i,i);
959  }
960  }
961  }
962  else
963  {
964  const size_t block( IsRowMajorMatrix_v<MT3> ? 256UL : 8UL );
965 
966  for( size_t jj=0UL; jj<B.columns(); jj+=block )
967  {
968  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
969 
970  for( size_t i=0UL; i<A.columns(); ++i )
971  {
972  const auto end( A.end(i) );
973  auto element( A.begin(i) );
974 
975  for( ; element!=end; ++element )
976  {
977  const size_t i1( element->index() );
978 
979  const size_t jbegin( ( IsUpper_v<MT5> )
980  ?( ( UPP )
981  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
982  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
983  :( UPP ? max(i1,jj) : jj ) );
984  const size_t jend( ( IsLower_v<MT5> )
985  ?( ( LOW )
986  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
987  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
988  :( LOW ? min(i1+1UL,jpos) : jpos ) );
989 
990  if( jbegin >= jend )
991  continue;
992 
993  for( size_t j=jbegin; j<jend; ++j ) {
994  C(i1,j) += element->value() * B(i,j);
995  }
996  }
997  }
998  }
999  }
1000  }
1002  //**********************************************************************************************
1003 
1004  //**Default addition assignment to dense matrices (small matrices)******************************
1018  template< typename MT3 // Type of the left-hand side target matrix
1019  , typename MT4 // Type of the left-hand side matrix operand
1020  , typename MT5 > // Type of the right-hand side matrix operand
1021  static inline auto selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1022  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1023  {
1024  selectDefaultAddAssignKernel( C, A, B );
1025  }
1027  //**********************************************************************************************
1028 
1029  //**Optimized addition assignment to dense matrices (small matrices)****************************
1044  template< typename MT3 // Type of the left-hand side target matrix
1045  , typename MT4 // Type of the left-hand side matrix operand
1046  , typename MT5 > // Type of the right-hand side matrix operand
1047  static inline auto selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1048  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1049  {
1050  const size_t block( ( IsRowMajorMatrix_v<MT3> )?( 256UL ):( 8UL ) );
1051 
1052  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1053  {
1054  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1055 
1056  for( size_t i=0UL; i<A.columns(); ++i )
1057  {
1058  const auto end( A.end(i) );
1059  auto element( A.begin(i) );
1060 
1061  const size_t nonzeros( A.nonZeros(i) );
1062  const size_t kpos( nonzeros & size_t(-4) );
1063  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1064 
1065  for( size_t k=0UL; k<kpos; k+=4UL )
1066  {
1067  const size_t i1( element->index() );
1068  const ET1 v1( element->value() );
1069  ++element;
1070  const size_t i2( element->index() );
1071  const ET1 v2( element->value() );
1072  ++element;
1073  const size_t i3( element->index() );
1074  const ET1 v3( element->value() );
1075  ++element;
1076  const size_t i4( element->index() );
1077  const ET1 v4( element->value() );
1078  ++element;
1079 
1080  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1081 
1082  const size_t jbegin( ( IsUpper_v<MT5> )
1083  ?( ( UPP )
1084  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1085  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1086  :( UPP ? max(i1,jj) : jj ) );
1087  const size_t jend( ( IsLower_v<MT5> )
1088  ?( ( LOW )
1089  ?( min( i4+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1090  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1091  :( LOW ? min(i4+1UL,jpos) : jpos ) );
1092 
1093  if( jbegin >= jend )
1094  continue;
1095 
1096  for( size_t j=jbegin; j<jend; ++j ) {
1097  C(i1,j) += v1 * B(i,j);
1098  C(i2,j) += v2 * B(i,j);
1099  C(i3,j) += v3 * B(i,j);
1100  C(i4,j) += v4 * B(i,j);
1101  }
1102  }
1103 
1104  for( ; element!=end; ++element )
1105  {
1106  const size_t i1( element->index() );
1107 
1108  const size_t jbegin( ( IsUpper_v<MT5> )
1109  ?( ( UPP )
1110  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1111  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1112  :( UPP ? max(i1,jj) : jj ) );
1113  const size_t jend( ( IsLower_v<MT5> )
1114  ?( ( LOW )
1115  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1116  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1117  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1118 
1119  if( jbegin >= jend )
1120  continue;
1121 
1122  for( size_t j=jbegin; j<jend; ++j ) {
1123  C(i1,j) += element->value() * B(i,j);
1124  }
1125  }
1126  }
1127  }
1128  }
1130  //**********************************************************************************************
1131 
1132  //**Default addition assignment to dense matrices (large matrices)******************************
1146  template< typename MT3 // Type of the left-hand side target matrix
1147  , typename MT4 // Type of the left-hand side matrix operand
1148  , typename MT5 > // Type of the right-hand side matrix operand
1149  static inline auto selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1150  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1151  {
1152  selectDefaultAddAssignKernel( C, A, B );
1153  }
1155  //**********************************************************************************************
1156 
1157  //**Optimized addition assignment to dense matrices (large matrices)****************************
1172  template< typename MT3 // Type of the left-hand side target matrix
1173  , typename MT4 // Type of the left-hand side matrix operand
1174  , typename MT5 > // Type of the right-hand side matrix operand
1175  static inline auto selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1176  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1177  {
1178  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_t<MT4> );
1179 
1180  const ForwardFunctor fwd;
1181 
1182  const OppositeType_t<MT4> tmp( serial( A ) );
1183  addAssign( C, fwd( tmp * B ) );
1184  }
1186  //**********************************************************************************************
1187 
1188  //**Restructuring addition assignment to row-major matrices*************************************
1203  template< typename MT // Type of the target matrix
1204  , bool SO > // Storage order of the target matrix
1205  friend inline auto addAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1206  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1207  {
1209 
1211 
1212  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1213  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1214 
1215  const ForwardFunctor fwd;
1216 
1217  addAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1218  }
1220  //**********************************************************************************************
1221 
1222  //**Addition assignment to sparse matrices******************************************************
1223  // No special implementation for the addition assignment to sparse matrices.
1224  //**********************************************************************************************
1225 
1226  //**Subtraction assignment to dense matrices****************************************************
1239  template< typename MT // Type of the target dense matrix
1240  , bool SO > // Storage order of the target dense matrix
1241  friend inline auto subAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1242  -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1243  {
1245 
1246  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1247  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1248 
1249  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1250  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1251 
1252  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1253  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1254  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1255  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1256  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1257  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1258 
1259  TSMatDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1260  }
1262  //**********************************************************************************************
1263 
1264  //**Subtraction assignment to dense matrices (kernel selection)*********************************
1275  template< typename MT3 // Type of the left-hand side target matrix
1276  , typename MT4 // Type of the left-hand side matrix operand
1277  , typename MT5 > // Type of the right-hand side matrix operand
1278  static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1279  {
1280  const size_t size( C.rows() * C.columns() );
1281 
1282  if( ( IsRowMajorMatrix_v<MT3> && size < TSMATDMATMULT_THRESHOLD ) ||
1283  ( IsColumnMajorMatrix_v<MT3> && size < 625UL ) )
1284  selectSmallSubAssignKernel( C, A, B );
1285  else
1286  selectLargeSubAssignKernel( C, A, B );
1287  }
1289  //**********************************************************************************************
1290 
1291  //**Default subtraction assignment to dense matrices********************************************
1306  template< typename MT3 // Type of the left-hand side target matrix
1307  , typename MT4 // Type of the left-hand side matrix operand
1308  , typename MT5 > // Type of the right-hand side matrix operand
1309  static inline void selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1310  {
1311  if( IsDiagonal_v<MT5> )
1312  {
1313  for( size_t i=0UL; i<A.columns(); ++i )
1314  {
1315  const auto end( A.end(i) );
1316  auto element( A.begin(i) );
1317 
1318  for( ; element!=end; ++element ) {
1319  C(element->index(),i) -= element->value() * B(i,i);
1320  }
1321  }
1322  }
1323  else
1324  {
1325  const size_t block( IsRowMajorMatrix_v<MT3> ? 256UL : 8UL );
1326 
1327  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1328  {
1329  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1330 
1331  for( size_t i=0UL; i<A.columns(); ++i )
1332  {
1333  const auto end( A.end(i) );
1334  auto element( A.begin(i) );
1335 
1336  for( ; element!=end; ++element )
1337  {
1338  const size_t i1( element->index() );
1339 
1340  const size_t jbegin( ( IsUpper_v<MT5> )
1341  ?( ( UPP )
1342  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1343  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1344  :( UPP ? max(i1,jj) : jj ) );
1345  const size_t jend( ( IsLower_v<MT5> )
1346  ?( ( LOW )
1347  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1348  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1349  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1350 
1351  if( jbegin >= jend )
1352  continue;
1353 
1354  for( size_t j=jbegin; j<jend; ++j ) {
1355  C(i1,j) -= element->value() * B(i,j);
1356  }
1357  }
1358  }
1359  }
1360  }
1361  }
1363  //**********************************************************************************************
1364 
1365  //**Default subtraction assignment to dense matrices (small matrices)***************************
1379  template< typename MT3 // Type of the left-hand side target matrix
1380  , typename MT4 // Type of the left-hand side matrix operand
1381  , typename MT5 > // Type of the right-hand side matrix operand
1382  static inline auto selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1383  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1384  {
1385  selectDefaultSubAssignKernel( C, A, B );
1386  }
1388  //**********************************************************************************************
1389 
1390  //**Optimized subtraction assignment to dense matrices (small matrices)*************************
1405  template< typename MT3 // Type of the left-hand side target matrix
1406  , typename MT4 // Type of the left-hand side matrix operand
1407  , typename MT5 > // Type of the right-hand side matrix operand
1408  static inline auto selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1409  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1410  {
1411  const size_t block( ( IsRowMajorMatrix_v<MT3> )?( 256UL ):( 8UL ) );
1412 
1413  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1414  {
1415  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1416 
1417  for( size_t i=0UL; i<A.columns(); ++i )
1418  {
1419  const auto end( A.end(i) );
1420  auto element( A.begin(i) );
1421 
1422  const size_t nonzeros( A.nonZeros(i) );
1423  const size_t kpos( nonzeros & size_t(-4) );
1424  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1425 
1426  for( size_t k=0UL; k<kpos; k+=4UL )
1427  {
1428  const size_t i1( element->index() );
1429  const ET1 v1( element->value() );
1430  ++element;
1431  const size_t i2( element->index() );
1432  const ET1 v2( element->value() );
1433  ++element;
1434  const size_t i3( element->index() );
1435  const ET1 v3( element->value() );
1436  ++element;
1437  const size_t i4( element->index() );
1438  const ET1 v4( element->value() );
1439  ++element;
1440 
1441  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1442 
1443  const size_t jbegin( ( IsUpper_v<MT5> )
1444  ?( ( UPP )
1445  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1446  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1447  :( UPP ? max(i1,jj) : jj ) );
1448  const size_t jend( ( IsLower_v<MT5> )
1449  ?( ( LOW )
1450  ?( min( i4+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1451  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1452  :( LOW ? min(i4+1UL,jpos) : jpos ) );
1453 
1454  if( jbegin >= jend )
1455  continue;
1456 
1457  for( size_t j=jbegin; j<jend; ++j ) {
1458  C(i1,j) -= v1 * B(i,j);
1459  C(i2,j) -= v2 * B(i,j);
1460  C(i3,j) -= v3 * B(i,j);
1461  C(i4,j) -= v4 * B(i,j);
1462  }
1463  }
1464 
1465  for( ; element!=end; ++element )
1466  {
1467  const size_t i1( element->index() );
1468 
1469  const size_t jbegin( ( IsUpper_v<MT5> )
1470  ?( ( UPP )
1471  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1472  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1473  :( UPP ? max(i1,jj) : jj ) );
1474  const size_t jend( ( IsLower_v<MT5> )
1475  ?( ( LOW )
1476  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1477  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1478  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1479 
1480  if( jbegin >= jend )
1481  continue;
1482 
1483  for( size_t j=jbegin; j<jend; ++j ) {
1484  C(i1,j) -= element->value() * B(i,j);
1485  }
1486  }
1487  }
1488  }
1489  }
1491  //**********************************************************************************************
1492 
1493  //**Default subtraction assignment to dense matrices (large matrices)***************************
1507  template< typename MT3 // Type of the left-hand side target matrix
1508  , typename MT4 // Type of the left-hand side matrix operand
1509  , typename MT5 > // Type of the right-hand side matrix operand
1510  static inline auto selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1511  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1512  {
1513  selectDefaultSubAssignKernel( C, A, B );
1514  }
1516  //**********************************************************************************************
1517 
1518  //**Optimized subtraction assignment to dense matrices (large matrices)*************************
1533  template< typename MT3 // Type of the left-hand side target matrix
1534  , typename MT4 // Type of the left-hand side matrix operand
1535  , typename MT5 > // Type of the right-hand side matrix operand
1536  static inline auto selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1537  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1538  {
1539  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_t<MT4> );
1540 
1541  const ForwardFunctor fwd;
1542 
1543  const OppositeType_t<MT4> tmp( serial( A ) );
1544  subAssign( C, fwd( tmp * B ) );
1545  }
1547  //**********************************************************************************************
1548 
1549  //**Restructuring subtraction assignment to row-major matrices**********************************
1564  template< typename MT // Type of the target matrix
1565  , bool SO > // Storage order of the target matrix
1566  friend inline auto subAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1567  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1568  {
1570 
1572 
1573  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1574  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1575 
1576  const ForwardFunctor fwd;
1577 
1578  subAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1579  }
1581  //**********************************************************************************************
1582 
1583  //**Subtraction assignment to sparse matrices***************************************************
1584  // No special implementation for the subtraction assignment to sparse matrices.
1585  //**********************************************************************************************
1586 
1587  //**Schur product assignment to dense matrices**************************************************
1600  template< typename MT // Type of the target dense matrix
1601  , bool SO > // Storage order of the target dense matrix
1602  friend inline void schurAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1603  {
1605 
1609 
1610  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1611  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1612 
1613  const ResultType tmp( serial( rhs ) );
1614  schurAssign( ~lhs, tmp );
1615  }
1617  //**********************************************************************************************
1618 
1619  //**Schur product assignment to sparse matrices*************************************************
1620  // No special implementation for the Schur product assignment to sparse matrices.
1621  //**********************************************************************************************
1622 
1623  //**Multiplication assignment to dense matrices*************************************************
1624  // No special implementation for the multiplication assignment to dense matrices.
1625  //**********************************************************************************************
1626 
1627  //**Multiplication assignment to sparse matrices************************************************
1628  // No special implementation for the multiplication assignment to sparse matrices.
1629  //**********************************************************************************************
1630 
1631  //**SMP assignment to dense matrices************************************************************
1647  template< typename MT // Type of the target dense matrix
1648  , bool SO > // Storage order of the target dense matrix
1649  friend inline auto smpAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1650  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1651  {
1653 
1654  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1655  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1656 
1657  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1658  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1659 
1660  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1661  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1662  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1663  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1664  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1665  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1666 
1667  smpAssign( ~lhs, A * B );
1668  }
1670  //**********************************************************************************************
1671 
1672  //**SMP assignment to sparse matrices***********************************************************
1688  template< typename MT // Type of the target sparse matrix
1689  , bool SO > // Storage order of the target sparse matrix
1690  friend inline auto smpAssign( SparseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1691  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1692  {
1694 
1695  using TmpType = If_t< SO, OppositeType, ResultType >;
1696 
1703 
1704  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1705  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1706 
1707  const ForwardFunctor fwd;
1708 
1709  const TmpType tmp( rhs );
1710  smpAssign( ~lhs, fwd( tmp ) );
1711  }
1713  //**********************************************************************************************
1714 
1715  //**Restructuring SMP assignment to row-major matrices******************************************
1730  template< typename MT // Type of the target matrix
1731  , bool SO > // Storage order of the target matrix
1732  friend inline auto smpAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1733  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1734  {
1736 
1737  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1738  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1739 
1740  const ForwardFunctor fwd;
1741 
1742  smpAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1743  }
1745  //**********************************************************************************************
1746 
1747  //**SMP addition assignment to dense matrices***************************************************
1763  template< typename MT // Type of the target dense matrix
1764  , bool SO > // Storage order of the target dense matrix
1765  friend inline auto smpAddAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1766  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1767  {
1769 
1770  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1771  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1772 
1773  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1774  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1775 
1776  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1777  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1778  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1779  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1780  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1781  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1782 
1783  smpAddAssign( ~lhs, A * B );
1784  }
1786  //**********************************************************************************************
1787 
1788  //**Restructuring SMP addition assignment to row-major matrices*********************************
1803  template< typename MT // Type of the target matrix
1804  , bool SO > // Storage order of the target matrix
1805  friend inline auto smpAddAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1806  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1807  {
1809 
1810  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1811  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1812 
1813  const ForwardFunctor fwd;
1814 
1815  smpAddAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1816  }
1818  //**********************************************************************************************
1819 
1820  //**SMP addition assignment to sparse matrices**************************************************
1821  // No special implementation for the SMP addition assignment to sparse matrices.
1822  //**********************************************************************************************
1823 
1824  //**SMP subtraction assignment to dense matrices************************************************
1840  template< typename MT // Type of the target dense matrix
1841  , bool SO > // Storage order of the target dense matrix
1842  friend inline auto smpSubAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1843  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1844  {
1846 
1847  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1848  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1849 
1850  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1851  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1852 
1853  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1854  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1855  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1856  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1857  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1858  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1859 
1860  smpSubAssign( ~lhs, A * B );
1861  }
1863  //**********************************************************************************************
1864 
1865  //**Restructuring SMP subtraction assignment to row-major matrices******************************
1880  template< typename MT // Type of the target matrix
1881  , bool SO > // Storage order of the target matrix
1882  friend inline auto smpSubAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1883  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1884  {
1886 
1887  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1888  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1889 
1890  const ForwardFunctor fwd;
1891 
1892  smpSubAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1893  }
1895  //**********************************************************************************************
1896 
1897  //**SMP subtraction assignment to sparse matrices***********************************************
1898  // No special implementation for the SMP subtraction assignment to sparse matrices.
1899  //**********************************************************************************************
1900 
1901  //**SMP Schur product assignment to dense matrices**********************************************
1914  template< typename MT // Type of the target dense matrix
1915  , bool SO > // Storage order of the target dense matrix
1916  friend inline void smpSchurAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1917  {
1919 
1923 
1924  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1925  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1926 
1927  const ResultType tmp( rhs );
1928  smpSchurAssign( ~lhs, tmp );
1929  }
1931  //**********************************************************************************************
1932 
1933  //**SMP Schur product assignment to sparse matrices*********************************************
1934  // No special implementation for the SMP Schur product assignment to sparse matrices.
1935  //**********************************************************************************************
1936 
1937  //**SMP multiplication assignment to dense matrices*********************************************
1938  // No special implementation for the SMP multiplication assignment to dense matrices.
1939  //**********************************************************************************************
1940 
1941  //**SMP multiplication assignment to sparse matrices********************************************
1942  // No special implementation for the SMP multiplication assignment to sparse matrices.
1943  //**********************************************************************************************
1944 
1945  //**Compile time checks*************************************************************************
1954  //**********************************************************************************************
1955 };
1956 //*************************************************************************************************
1957 
1958 
1959 
1960 
1961 //=================================================================================================
1962 //
1963 // GLOBAL BINARY ARITHMETIC OPERATORS
1964 //
1965 //=================================================================================================
1966 
1967 //*************************************************************************************************
1980 template< typename MT1 // Type of the left-hand side dense matrix
1981  , typename MT2 // Type of the right-hand side sparse matrix
1982  , DisableIf_t< ( IsIdentity_v<MT1> &&
1983  IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > ) ||
1984  IsZero_v<MT1> >* = nullptr >
1985 inline const TSMatDMatMultExpr<MT1,MT2,false,false,false,false>
1986  tsmatdmatmult( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs )
1987 {
1989 
1990  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).rows(), "Invalid matrix sizes" );
1991 
1992  return TSMatDMatMultExpr<MT1,MT2,false,false,false,false>( ~lhs, ~rhs );
1993 }
1995 //*************************************************************************************************
1996 
1997 
1998 //*************************************************************************************************
2012 template< typename MT1 // Type of the left-hand side sparse matrix
2013  , typename MT2 // Type of the right-hand side dense matrix
2014  , EnableIf_t< IsIdentity_v<MT1> &&
2015  IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > >* = nullptr >
2016 inline const MT2&
2017  tsmatdmatmult( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs )
2018 {
2020 
2021  UNUSED_PARAMETER( lhs );
2022 
2023  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).rows(), "Invalid matrix sizes" );
2024 
2025  return (~rhs);
2026 }
2028 //*************************************************************************************************
2029 
2030 
2031 //*************************************************************************************************
2044 template< typename MT1 // Type of the left-hand side dense matrix
2045  , typename MT2 // Type of the right-hand side sparse matrix
2046  , EnableIf_t< IsZero_v<MT1> >* = nullptr >
2047 inline decltype(auto)
2048  tsmatdmatmult( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs )
2049 {
2051 
2052  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).rows(), "Invalid matrix sizes" );
2053 
2054  using ReturnType = const MultTrait_t< ResultType_t<MT1>, ResultType_t<MT2> >;
2055 
2058 
2059  return ReturnType( (~lhs).rows(), (~rhs).columns() );
2060 }
2062 //*************************************************************************************************
2063 
2064 
2065 //*************************************************************************************************
2096 template< typename MT1 // Type of the left-hand side sparse matrix
2097  , typename MT2 > // Type of the right-hand side dense matrix
2098 inline decltype(auto)
2099  operator*( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs )
2100 {
2102 
2103  if( (~lhs).columns() != (~rhs).rows() ) {
2104  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
2105  }
2106 
2107  return tsmatdmatmult( ~lhs, ~rhs );
2108 }
2109 //*************************************************************************************************
2110 
2111 
2112 
2113 
2114 //=================================================================================================
2115 //
2116 // GLOBAL FUNCTIONS
2117 //
2118 //=================================================================================================
2119 
2120 //*************************************************************************************************
2146 template< typename MT1 // Type of the left-hand side dense matrix
2147  , typename MT2 // Type of the right-hand side dense matrix
2148  , bool SF // Symmetry flag
2149  , bool HF // Hermitian flag
2150  , bool LF // Lower flag
2151  , bool UF > // Upper flag
2152 inline decltype(auto) declsym( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2153 {
2155 
2156  if( !isSquare( dm ) ) {
2157  BLAZE_THROW_INVALID_ARGUMENT( "Invalid symmetric matrix specification" );
2158  }
2159 
2160  using ReturnType = const TSMatDMatMultExpr<MT1,MT2,true,HF,LF,UF>;
2161  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2162 }
2164 //*************************************************************************************************
2165 
2166 
2167 //*************************************************************************************************
2193 template< typename MT1 // Type of the left-hand side dense matrix
2194  , typename MT2 // Type of the right-hand side dense matrix
2195  , bool SF // Symmetry flag
2196  , bool HF // Hermitian flag
2197  , bool LF // Lower flag
2198  , bool UF > // Upper flag
2199 inline decltype(auto) declherm( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2200 {
2202 
2203  if( !isSquare( dm ) ) {
2204  BLAZE_THROW_INVALID_ARGUMENT( "Invalid Hermitian matrix specification" );
2205  }
2206 
2207  using ReturnType = const TSMatDMatMultExpr<MT1,MT2,SF,true,LF,UF>;
2208  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2209 }
2211 //*************************************************************************************************
2212 
2213 
2214 //*************************************************************************************************
2240 template< typename MT1 // Type of the left-hand side dense matrix
2241  , typename MT2 // Type of the right-hand side dense matrix
2242  , bool SF // Symmetry flag
2243  , bool HF // Hermitian flag
2244  , bool LF // Lower flag
2245  , bool UF > // Upper flag
2246 inline decltype(auto) decllow( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2247 {
2249 
2250  if( !isSquare( dm ) ) {
2251  BLAZE_THROW_INVALID_ARGUMENT( "Invalid lower matrix specification" );
2252  }
2253 
2254  using ReturnType = const TSMatDMatMultExpr<MT1,MT2,SF,HF,true,UF>;
2255  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2256 }
2258 //*************************************************************************************************
2259 
2260 
2261 //*************************************************************************************************
2287 template< typename MT1 // Type of the left-hand side dense matrix
2288  , typename MT2 // Type of the right-hand side dense matrix
2289  , bool SF // Symmetry flag
2290  , bool HF // Hermitian flag
2291  , bool LF // Lower flag
2292  , bool UF > // Upper flag
2293 inline decltype(auto) declupp( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2294 {
2296 
2297  if( !isSquare( dm ) ) {
2298  BLAZE_THROW_INVALID_ARGUMENT( "Invalid upper matrix specification" );
2299  }
2300 
2301  using ReturnType = const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,true>;
2302  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2303 }
2305 //*************************************************************************************************
2306 
2307 
2308 //*************************************************************************************************
2334 template< typename MT1 // Type of the left-hand side dense matrix
2335  , typename MT2 // Type of the right-hand side dense matrix
2336  , bool SF // Symmetry flag
2337  , bool HF // Hermitian flag
2338  , bool LF // Lower flag
2339  , bool UF > // Upper flag
2340 inline decltype(auto) decldiag( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2341 {
2343 
2344  if( !isSquare( dm ) ) {
2345  BLAZE_THROW_INVALID_ARGUMENT( "Invalid diagonal matrix specification" );
2346  }
2347 
2348  using ReturnType = const TSMatDMatMultExpr<MT1,MT2,SF,HF,true,true>;
2349  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2350 }
2352 //*************************************************************************************************
2353 
2354 
2355 
2356 
2357 //=================================================================================================
2358 //
2359 // SIZE SPECIALIZATIONS
2360 //
2361 //=================================================================================================
2362 
2363 //*************************************************************************************************
2365 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2366 struct Size< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 0UL >
2367  : public Size<MT1,0UL>
2368 {};
2369 
2370 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2371 struct Size< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 1UL >
2372  : public Size<MT2,1UL>
2373 {};
2375 //*************************************************************************************************
2376 
2377 
2378 
2379 
2380 //=================================================================================================
2381 //
2382 // ISALIGNED SPECIALIZATIONS
2383 //
2384 //=================================================================================================
2385 
2386 //*************************************************************************************************
2388 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2389 struct IsAligned< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2390  : public IsAligned<MT2>
2391 {};
2393 //*************************************************************************************************
2394 
2395 } // namespace blaze
2396 
2397 #endif
decltype(auto) subvector(Vector< VT, TF > &, RSAs...)
Creating a view on a specific subvector of the given vector.
Definition: Subvector.h:329
OppositeType_t< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: TSMatDMatMultExpr.h:246
#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.
decltype(auto) column(Matrix< MT, SO > &matrix, RCAs... args)
Creating a view on a specific column of the given matrix.
Definition: Column.h:133
Headerfile for the generic min algorithm.
Header file for the blaze::checked and blaze::unchecked instances.
Header file for the decldiag trait.
decltype(auto) decldiag(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as diagonal.
Definition: DMatDeclDiagExpr.h:975
If_t< IsExpression_v< MT2 >, const MT2, const MT2 &> RightOperand
Composite type of the right-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:256
bool isAligned() const noexcept
Returns whether the operands of the expression are properly aligned in memory.
Definition: TSMatDMatMultExpr.h:424
Header file for basic type definitions.
typename If< Condition, T1, T2 >::Type If_t
Auxiliary alias declaration for the If class template.The If_t alias declaration provides a convenien...
Definition: If.h:109
Header file for the declherm trait.
typename T::ResultType ResultType_t
Alias declaration for nested ResultType type definitions.The ResultType_t alias declaration provides ...
Definition: Aliases.h:390
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: TSMatDMatMultExpr.h:295
Header file for the serial shim.
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: TSMatDMatMultExpr.h:370
Header file for the IsDiagonal type trait.
Base template for the DeclUppTrait class.
Definition: DeclUppTrait.h:134
#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 DeclUpp functor.
ResultType_t< MT1 > RT1
Result type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:133
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: TSMatDMatMultExpr.h:441
MT::Iterator begin(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator to the first element of row/column i.
Definition: Matrix.h:372
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:591
static constexpr bool smpAssignable
Compilation flag for SMP assignments.
Definition: CompressedMatrix.h:3113
constexpr Unchecked unchecked
Global Unchecked instance.The blaze::unchecked instance is an optional token for the creation of view...
Definition: Check.h:138
Constraint on the data type.
Header file for the IsIdentity type trait.
If_t< evaluateLeft, const RT1, CT1 > LT
Type for the assignment of the left-hand side sparse matrix operand.
Definition: TSMatDMatMultExpr.h:259
static constexpr bool SYM
Flag for symmetric matrices.
Definition: TSMatDMatMultExpr.h:152
decltype(auto) declupp(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as upper.
Definition: DMatDeclUppExpr.h:1002
CompositeType_t< MT2 > CT2
Composite type of the right-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:138
static constexpr bool simdEnabled
Compilation switch for the expression template evaluation strategy.
Definition: TSMatDMatMultExpr.h:267
LeftOperand leftOperand() const noexcept
Returns the left-hand side transpose sparse matrix operand.
Definition: TSMatDMatMultExpr.h:380
Header file for the Computation base class.
Header file for the MatMatMultExpr base class.
Header file for the reset shim.
static constexpr bool evaluateRight
Compilation switch for the composite type of the right-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:148
Constraints on the storage order of matrix types.
Header file for the RequiresEvaluation type trait.
System settings for performance optimizations.
constexpr void UNUSED_PARAMETER(const Args &...)
Suppression of unused parameter warnings.
Definition: Unused.h:81
If_t< IsExpression_v< MT1 >, const MT1, const MT1 &> LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:253
constexpr size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:514
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: TSMatDMatMultExpr.h:360
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:80
const ResultType CompositeType
Data type for composite expression templates.
Definition: TSMatDMatMultExpr.h:250
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes...
Definition: Forward.h:137
typename T::ElementType ElementType_t
Alias declaration for nested ElementType type definitions.The ElementType_t alias declaration provide...
Definition: Aliases.h:170
static constexpr bool UPP
Flag for upper matrices.
Definition: TSMatDMatMultExpr.h:155
static constexpr bool LOW
Flag for lower matrices.
Definition: TSMatDMatMultExpr.h:154
RightOperand rhs_
Right-hand side dense matrix of the multiplication expression.
Definition: TSMatDMatMultExpr.h:442
Constraint on the data type.
Constraint on the data type.
typename If_t< HERM, DeclHermTrait< MultTrait_t< RT1, RT2 > >, If_t< SYM, DeclSymTrait< MultTrait_t< RT1, RT2 > >, If_t< LOW, If_t< UPP, DeclDiagTrait< MultTrait_t< RT1, RT2 > >, DeclLowTrait< MultTrait_t< RT1, RT2 > > >, If_t< UPP, DeclUppTrait< MultTrait_t< RT1, RT2 > >, MultTrait< RT1, RT2 > > > > >::Type ResultType
Result type for expression template evaluations.
Definition: TSMatDMatMultExpr.h:244
Headerfile for the generic max algorithm.
Header file for the DisableIf class template.
Header file for the multiplication trait.
Header file for the IsStrictlyUpper type trait.
Header file for the IsSymmetric type trait.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:58
Header file for the DeclLow functor.
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
static constexpr bool smpAssignable
Compilation switch for the expression template assignment strategy.
Definition: TSMatDMatMultExpr.h:270
#define BLAZE_CONSTRAINT_MUST_BE_ZERO_TYPE(T)
Constraint on the data type.In case the given data type T is not a zero vector or matrix type...
Definition: Zero.h:61
ElementType_t< RT2 > ET2
Element type of the right-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:136
Generic wrapper for the decllow() function.
Definition: DeclLow.h:58
decltype(auto) min(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the componentwise minimum of the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1147
Header file for the decllow trait.
#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.
decltype(auto) decllow(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as lower.
Definition: DMatDeclLowExpr.h:1002
Header file for the IsLower type trait.
Header file for the IsAligned type trait.
If_t< evaluateRight, const RT2, CT2 > RT
Type for the assignment of the right-hand side dense matrix operand.
Definition: TSMatDMatMultExpr.h:262
Generic wrapper for the null function.
Definition: Noop.h:59
Header file for the IsTriangular type trait.
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: TSMatDMatMultExpr.h:344
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: TSMatDMatMultExpr.h:434
Base template for the DeclSymTrait class.
Definition: DeclSymTrait.h:134
Constraints on the storage order of matrix types.
Header file for the exception macros of the math module.
decltype(auto) max(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the componentwise maximum of the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1179
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:438
Header file for the DeclDiag functor.
Constraint on the data type.
Header file for all forward declarations for expression class templates.
CompositeType_t< MT1 > CT1
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:137
Header file for the EnableIf class template.
Header file for the IsStrictlyLower type trait.
#define BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR(T1, T2)
Constraint on the data type.In case the given data types T1 and T2 do not form a valid matrix/matrix ...
Definition: MatMatMultExpr.h:103
RightOperand rightOperand() const noexcept
Returns the right-hand side dense matrix operand.
Definition: TSMatDMatMultExpr.h:390
ElementType_t< ResultType > ElementType
Resulting element type.
Definition: TSMatDMatMultExpr.h:248
typename T::OppositeType OppositeType_t
Alias declaration for nested OppositeType type definitions.The OppositeType_t alias declaration provi...
Definition: Aliases.h:270
Header file for the conjugate shim.
Header file for the declupp trait.
ResultType_t< MT2 > RT2
Result type of the right-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:134
#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
#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
typename T::TransposeType TransposeType_t
Alias declaration for nested TransposeType type definitions.The TransposeType_t alias declaration pro...
Definition: Aliases.h:470
Header file for run time assertion macros.
Base template for the DeclHermTrait class.
Definition: DeclHermTrait.h:134
typename T::CompositeType CompositeType_t
Alias declaration for nested CompositeType type definitions.The CompositeType_t alias declaration pro...
Definition: Aliases.h:90
TransposeType_t< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: TSMatDMatMultExpr.h:247
Base template for the MultTrait class.
Definition: MultTrait.h:146
auto smpAddAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:131
decltype(auto) row(Matrix< MT, SO > &, RRAs...)
Creating a view on a specific row of the given matrix.
Definition: Row.h:133
TSMatDMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the TSMatDMatMultExpr class.
Definition: TSMatDMatMultExpr.h:280
Header file for the IsZero type trait.
ElementType_t< RT1 > ET1
Element type of the left-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:135
Header file for the declsym trait.
#define BLAZE_FUNCTION_TRACE
Function trace macro.This macro can be used to reliably trace function calls. In case function tracin...
Definition: FunctionTrace.h:94
decltype(auto) declsym(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as symmetric.
Definition: DMatDeclSymExpr.h:1002
Header file for the isDefault shim.
constexpr size_t size(const Matrix< MT, SO > &matrix) noexcept
Returns the total number of elements of the matrix.
Definition: Matrix.h:530
auto smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:100
Constraint on the data type.
Constraints on the storage order of matrix types.
Generic wrapper for the declherm() function.
Definition: DeclHerm.h:58
decltype(auto) serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:808
Header file for the Noop functor.
#define BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION(T)
Constraint on the data type.In case the given data type T requires an intermediate evaluation within ...
Definition: RequiresEvaluation.h:81
auto smpSchurAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP Schur product assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:194
constexpr size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:498
#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
Generic wrapper for the declupp() function.
Definition: DeclUpp.h:58
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TSMatDMatMultExpr.h:249
const Type & ReturnType
Return type for expression template evaluations.
Definition: CompressedMatrix.h:3081
decltype(auto) trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:765
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: TSMatDMatMultExpr.h:414
Base template for the DeclLowTrait class.
Definition: DeclLowTrait.h:134
decltype(auto) declherm(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as Hermitian.
Definition: DMatDeclHermExpr.h:1002
Header file for the IsRowMajorMatrix type trait.
Header file for the IsComputation type trait class.
Header file for the IsBuiltin type trait.
auto smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:162
Expression object for transpose sparse matrix-dense matrix multiplications.The TSMatDMatMultExpr clas...
Definition: Forward.h:169
static constexpr bool evaluateLeft
Compilation switch for the composite type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:143
Header file for the IntegralConstant class template.
Generic wrapper for the decldiag() function.
Definition: DeclDiag.h:58
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: TSMatDMatMultExpr.h:402
Header file for the DeclHerm functor.
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:631
Header file for the IsUpper type trait.
typename DisableIf< Condition, T >::Type DisableIf_t
Auxiliary type for the DisableIf class template.The DisableIf_t alias declaration provides a convenie...
Definition: DisableIf.h:138
decltype(auto) conj(const DenseMatrix< MT, SO > &dm)
Returns a matrix containing the complex conjugate of each single element of dm.
Definition: DMatMapExpr.h:1326
Constraint on the data type.
Generic wrapper for the declsym() function.
Definition: DeclSym.h:58
Base template for the DeclDiagTrait class.
Definition: DeclDiagTrait.h:134
bool isSquare(const Matrix< MT, SO > &matrix) noexcept
Checks if the given matrix is a square matrix.
Definition: Matrix.h:951
static constexpr bool HERM
Flag for Hermitian matrices.
Definition: TSMatDMatMultExpr.h:153
Header file for the IsResizable type trait.
Header file for the Size type trait.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_ZERO_TYPE(T)
Constraint on the data type.In case the given data type T is a zero vector or matrix type...
Definition: Zero.h:81
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 DeclSym functor.
#define BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a sparse, N-dimensional matrix type...
Definition: SparseMatrix.h:61
Header file for the IsExpression type trait class.
Header file for the function trace functionality.