Blaze  3.6
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/MaybeUnused.h>
102 #include <blaze/util/mpl/If.h>
103 #include <blaze/util/Types.h>
105 
106 
107 namespace blaze {
108 
109 //=================================================================================================
110 //
111 // CLASS SMATDMATMULTEXPR
112 //
113 //=================================================================================================
114 
115 //*************************************************************************************************
122 template< typename MT1 // Type of the left-hand side dense matrix
123  , typename MT2 // Type of the right-hand side sparse matrix
124  , bool SF // Symmetry flag
125  , bool HF // Hermitian flag
126  , bool LF // Lower flag
127  , bool UF > // Upper flag
128 class TSMatDMatMultExpr
129  : public MatMatMultExpr< DenseMatrix< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, false > >
130  , private Computation
131 {
132  private:
133  //**Type definitions****************************************************************************
140  //**********************************************************************************************
141 
142  //**********************************************************************************************
144  static constexpr bool evaluateLeft = ( IsComputation_v<MT1> || RequiresEvaluation_v<MT1> );
145  //**********************************************************************************************
146 
147  //**********************************************************************************************
149  static constexpr bool evaluateRight = ( IsComputation_v<MT2> || RequiresEvaluation_v<MT2> );
150  //**********************************************************************************************
151 
152  //**********************************************************************************************
153  static constexpr bool SYM = ( SF && !( HF || LF || UF ) );
154  static constexpr bool HERM = ( HF && !( LF || UF ) );
155  static constexpr bool LOW = ( LF || ( ( SF || HF ) && UF ) );
156  static constexpr bool UPP = ( UF || ( ( SF || HF ) && LF ) );
157  //**********************************************************************************************
158 
159  //**********************************************************************************************
161 
166  template< typename T1, typename T2, typename T3 >
167  static constexpr bool CanExploitSymmetry_v = IsSymmetric_v<T2>;
169  //**********************************************************************************************
170 
171  //**********************************************************************************************
173 
177  template< typename T1, typename T2, typename T3 >
178  static constexpr bool IsEvaluationRequired_v =
179  ( ( evaluateLeft || evaluateRight ) && !CanExploitSymmetry_v<T1,T2,T3> );
181  //**********************************************************************************************
182 
183  //**********************************************************************************************
185 
188  template< typename T1, typename T2, typename T3 >
189  static constexpr bool UseOptimizedKernel_v =
190  ( useOptimizedKernels &&
191  !IsDiagonal_v<T3> &&
192  !IsResizable_v< ElementType_t<T1> > &&
193  !IsResizable_v<ET1> );
195  //**********************************************************************************************
196 
197  //**********************************************************************************************
199 
202  template< typename T1, typename T2, typename T3 >
203  static constexpr bool UseDefaultKernel_v = !UseOptimizedKernel_v<T1,T2,T3>;
205  //**********************************************************************************************
206 
207  //**********************************************************************************************
209 
212  using ForwardFunctor = If_t< HERM
213  , DeclHerm
214  , If_t< SYM
215  , DeclSym
216  , If_t< LOW
217  , If_t< UPP
218  , DeclDiag
219  , DeclLow >
220  , If_t< UPP
221  , DeclUpp
222  , Noop > > > >;
224  //**********************************************************************************************
225 
226  public:
227  //**Type definitions****************************************************************************
230 
233 
235  using ResultType = typename If_t< HERM
237  , If_t< SYM
239  , If_t< LOW
240  , If_t< UPP
243  , If_t< UPP
245  , MultTrait<RT1,RT2> > > > >::Type;
246 
250  using ReturnType = const ElementType;
251  using CompositeType = const ResultType;
252 
254  using LeftOperand = If_t< IsExpression_v<MT1>, const MT1, const MT1& >;
255 
257  using RightOperand = If_t< IsExpression_v<MT2>, const MT2, const MT2& >;
258 
261 
264  //**********************************************************************************************
265 
266  //**Compilation flags***************************************************************************
268  static constexpr bool simdEnabled = false;
269 
271  static constexpr bool smpAssignable =
272  ( !evaluateLeft && MT1::smpAssignable && !evaluateRight && MT2::smpAssignable );
273  //**********************************************************************************************
274 
275  //**Constructor*********************************************************************************
281  explicit inline TSMatDMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
282  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
283  , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
284  {
285  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
286  }
287  //**********************************************************************************************
288 
289  //**Access operator*****************************************************************************
296  inline ReturnType operator()( size_t i, size_t j ) const {
297  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
298  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
299 
300  if( IsDiagonal_v<MT1> ) {
301  return lhs_(i,i) * rhs_(i,j);
302  }
303  else if( IsDiagonal_v<MT2> ) {
304  return lhs_(i,j) * rhs_(j,j);
305  }
306  else if( IsTriangular_v<MT1> || IsTriangular_v<MT2> ) {
307  const size_t begin( ( IsUpper_v<MT1> )
308  ?( ( IsLower_v<MT2> )
309  ?( max( ( IsStrictlyUpper_v<MT1> ? i+1UL : i )
310  , ( IsStrictlyLower_v<MT2> ? j+1UL : j ) ) )
311  :( IsStrictlyUpper_v<MT1> ? i+1UL : i ) )
312  :( ( IsLower_v<MT2> )
313  ?( IsStrictlyLower_v<MT2> ? j+1UL : j )
314  :( 0UL ) ) );
315  const size_t end( ( IsLower_v<MT1> )
316  ?( ( IsUpper_v<MT2> )
317  ?( min( ( IsStrictlyLower_v<MT1> ? i : i+1UL )
318  , ( IsStrictlyUpper_v<MT2> ? j : j+1UL ) ) )
319  :( IsStrictlyLower_v<MT1> ? i : i+1UL ) )
320  :( ( IsUpper_v<MT2> )
321  ?( IsStrictlyUpper_v<MT2> ? j : j+1UL )
322  :( lhs_.columns() ) ) );
323 
324  if( begin >= end ) return ElementType();
325 
326  const size_t n( end - begin );
327 
328  return subvector( row( lhs_, i, unchecked ), begin, n, unchecked ) *
329  subvector( column( rhs_, j, unchecked ), begin, n, unchecked );
330  }
331  else {
332  return row( lhs_, i, unchecked ) * column( rhs_, j, unchecked );
333  }
334  }
335  //**********************************************************************************************
336 
337  //**At function*********************************************************************************
345  inline ReturnType at( size_t i, size_t j ) const {
346  if( i >= lhs_.rows() ) {
347  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
348  }
349  if( j >= rhs_.columns() ) {
350  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
351  }
352  return (*this)(i,j);
353  }
354  //**********************************************************************************************
355 
356  //**Rows function*******************************************************************************
361  inline size_t rows() const noexcept {
362  return lhs_.rows();
363  }
364  //**********************************************************************************************
365 
366  //**Columns function****************************************************************************
371  inline size_t columns() const noexcept {
372  return rhs_.columns();
373  }
374  //**********************************************************************************************
375 
376  //**Left operand access*************************************************************************
381  inline LeftOperand leftOperand() const noexcept {
382  return lhs_;
383  }
384  //**********************************************************************************************
385 
386  //**Right operand access************************************************************************
391  inline RightOperand rightOperand() const noexcept {
392  return rhs_;
393  }
394  //**********************************************************************************************
395 
396  //**********************************************************************************************
402  template< typename T >
403  inline bool canAlias( const T* alias ) const noexcept {
404  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
405  }
406  //**********************************************************************************************
407 
408  //**********************************************************************************************
414  template< typename T >
415  inline bool isAliased( const T* alias ) const noexcept {
416  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
417  }
418  //**********************************************************************************************
419 
420  //**********************************************************************************************
425  inline bool isAligned() const noexcept {
426  return rhs_.isAligned();
427  }
428  //**********************************************************************************************
429 
430  //**********************************************************************************************
435  inline bool canSMPAssign() const noexcept {
436  return ( rows() * columns() >= SMP_TSMATDMATMULT_THRESHOLD ) && !IsDiagonal_v<MT2>;
437  }
438  //**********************************************************************************************
439 
440  private:
441  //**Member variables****************************************************************************
444  //**********************************************************************************************
445 
446  //**Assignment to dense matrices****************************************************************
459  template< typename MT // Type of the target dense matrix
460  , bool SO > // Storage order of the target dense matrix
461  friend inline auto assign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
463  {
465 
466  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
467  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
468 
469  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
470  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
471 
472  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
473  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
474  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
475  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
476  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
477  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
478 
479  TSMatDMatMultExpr::selectAssignKernel( ~lhs, A, B );
480  }
482  //**********************************************************************************************
483 
484  //**Assignment to dense matrices (kernel selection)*********************************************
495  template< typename MT3 // Type of the left-hand side target matrix
496  , typename MT4 // Type of the left-hand side matrix operand
497  , typename MT5 > // Type of the right-hand side matrix operand
498  static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
499  {
500  const size_t size( C.rows() * C.columns() );
501 
502  if( ( IsRowMajorMatrix_v<MT3> && size < TSMATDMATMULT_THRESHOLD ) ||
503  ( IsColumnMajorMatrix_v<MT3> && size < 625UL ) )
504  selectSmallAssignKernel( C, A, B );
505  else
506  selectLargeAssignKernel( C, A, B );
507  }
509  //**********************************************************************************************
510 
511  //**Default assignment to dense matrices********************************************************
526  template< typename MT3 // Type of the left-hand side target matrix
527  , typename MT4 // Type of the left-hand side matrix operand
528  , typename MT5 > // Type of the right-hand side matrix operand
529  static inline void selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
530  {
531  reset( C );
532 
533  if( IsDiagonal_v<MT5> )
534  {
535  for( size_t i=0UL; i<A.columns(); ++i )
536  {
537  const auto end( A.end(i) );
538  auto element( A.begin(i) );
539 
540  for( ; element!=end; ++element ) {
541  C(element->index(),i) = element->value() * B(i,i);
542  }
543  }
544  }
545  else
546  {
547  const size_t block( IsRowMajorMatrix_v<MT3> ? 256UL : 8UL );
548 
549  for( size_t jj=0UL; jj<B.columns(); jj+=block )
550  {
551  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
552 
553  for( size_t i=0UL; i<A.columns(); ++i )
554  {
555  const auto end( A.end(i) );
556  auto element( A.begin(i) );
557 
558  for( ; element!=end; ++element )
559  {
560  const size_t i1( element->index() );
561 
562  const size_t jbegin( ( IsUpper_v<MT5> )
563  ?( ( SYM || HERM || UPP )
564  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
565  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
566  :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
567  const size_t jend( ( IsLower_v<MT5> )
568  ?( ( LOW )
569  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
570  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
571  :( LOW ? min(i1+1UL,jpos) : jpos ) );
572 
573  if( jbegin >= jend )
574  continue;
575 
576  for( size_t j=jbegin; j<jend; ++j ) {
577  if( isDefault( C(i1,j) ) )
578  C(i1,j) = element->value() * B(i,j);
579  else
580  C(i1,j) += element->value() * B(i,j);
581  }
582  }
583  }
584  }
585  }
586 
587  if( SYM || HERM ) {
588  for( size_t j=0UL; j<B.columns(); ++j ) {
589  for( size_t i=j+1UL; i<A.rows(); ++i ) {
590  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
591  }
592  }
593  }
594  }
596  //**********************************************************************************************
597 
598  //**Default assignment to dense matrices (small matrices)***************************************
612  template< typename MT3 // Type of the left-hand side target matrix
613  , typename MT4 // Type of the left-hand side matrix operand
614  , typename MT5 > // Type of the right-hand side matrix operand
615  static inline auto selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
616  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
617  {
618  selectDefaultAssignKernel( C, A, B );
619  }
621  //**********************************************************************************************
622 
623  //**Optimized assignment to dense matrices (small matrices)*************************************
638  template< typename MT3 // Type of the left-hand side target matrix
639  , typename MT4 // Type of the left-hand side matrix operand
640  , typename MT5 > // Type of the right-hand side matrix operand
641  static inline auto selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
642  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
643  {
644  const size_t block( ( IsRowMajorMatrix_v<MT3> )?( 256UL ):( 8UL ) );
645 
646  reset( C );
647 
648  for( size_t jj=0UL; jj<B.columns(); jj+=block )
649  {
650  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
651 
652  for( size_t i=0UL; i<A.columns(); ++i )
653  {
654  const auto end( A.end(i) );
655  auto element( A.begin(i) );
656 
657  const size_t nonzeros( A.nonZeros(i) );
658  const size_t kpos( nonzeros & size_t(-4) );
659  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
660 
661  for( size_t k=0UL; k<kpos; k+=4UL )
662  {
663  const size_t i1( element->index() );
664  const ET1 v1( element->value() );
665  ++element;
666  const size_t i2( element->index() );
667  const ET1 v2( element->value() );
668  ++element;
669  const size_t i3( element->index() );
670  const ET1 v3( element->value() );
671  ++element;
672  const size_t i4( element->index() );
673  const ET1 v4( element->value() );
674  ++element;
675 
676  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
677 
678  const size_t jbegin( ( IsUpper_v<MT5> )
679  ?( ( SYM || HERM || UPP )
680  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
681  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
682  :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
683  const size_t jend( ( IsLower_v<MT5> )
684  ?( ( LOW )
685  ?( min( i4+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
686  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
687  :( LOW ? min(i4+1UL,jpos) : jpos ) );
688 
689  if( jbegin >= jend )
690  continue;
691 
692  for( size_t j=jbegin; j<jend; ++j ) {
693  C(i1,j) += v1 * B(i,j);
694  C(i2,j) += v2 * B(i,j);
695  C(i3,j) += v3 * B(i,j);
696  C(i4,j) += v4 * B(i,j);
697  }
698  }
699 
700  for( ; element!=end; ++element )
701  {
702  const size_t i1( element->index() );
703 
704  const size_t jbegin( ( IsUpper_v<MT5> )
705  ?( ( SYM || HERM || UPP )
706  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
707  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
708  :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
709  const size_t jend( ( IsLower_v<MT5> )
710  ?( ( LOW )
711  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
712  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
713  :( LOW ? min(i1+1UL,jpos) : jpos ) );
714 
715  if( jbegin >= jend )
716  continue;
717 
718  for( size_t j=jbegin; j<jend; ++j ) {
719  C(i1,j) += element->value() * B(i,j);
720  }
721  }
722  }
723  }
724 
725  if( SYM || HERM ) {
726  for( size_t j=0UL; j<B.columns(); ++j ) {
727  for( size_t i=j+1UL; i<A.rows(); ++i ) {
728  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
729  }
730  }
731  }
732  }
734  //**********************************************************************************************
735 
736  //**Default assignment to dense matrices (large matrices)***************************************
750  template< typename MT3 // Type of the left-hand side target matrix
751  , typename MT4 // Type of the left-hand side matrix operand
752  , typename MT5 > // Type of the right-hand side matrix operand
753  static inline auto selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
754  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
755  {
756  selectDefaultAssignKernel( C, A, B );
757  }
759  //**********************************************************************************************
760 
761  //**Optimized assignment to dense matrices (large matrices)*************************************
776  template< typename MT3 // Type of the left-hand side target matrix
777  , typename MT4 // Type of the left-hand side matrix operand
778  , typename MT5 > // Type of the right-hand side matrix operand
779  static inline auto selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
780  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
781  {
782  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_t<MT4> );
783 
784  const ForwardFunctor fwd;
785 
786  const OppositeType_t<MT4> tmp( serial( A ) );
787  assign( C, fwd( tmp * B ) );
788  }
790  //**********************************************************************************************
791 
792  //**Assignment to sparse matrices***************************************************************
805  template< typename MT // Type of the target sparse matrix
806  , bool SO > // Storage order of the target sparse matrix
807  friend inline auto assign( SparseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
808  -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
809  {
811 
812  using TmpType = If_t< SO, OppositeType, ResultType >;
813 
820 
821  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
822  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
823 
824  const ForwardFunctor fwd;
825 
826  const TmpType tmp( serial( rhs ) );
827  assign( ~lhs, fwd( tmp ) );
828  }
830  //**********************************************************************************************
831 
832  //**Restructuring assignment to row-major matrices**********************************************
847  template< typename MT // Type of the target matrix
848  , bool SO > // Storage order of the target matrix
849  friend inline auto assign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
850  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
851  {
853 
855 
856  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
857  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
858 
859  const ForwardFunctor fwd;
860 
861  assign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
862  }
864  //**********************************************************************************************
865 
866  //**Addition assignment to dense matrices*******************************************************
879  template< typename MT // Type of the target dense matrix
880  , bool SO > // Storage order of the target dense matrix
881  friend inline auto addAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
882  -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
883  {
885 
886  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
887  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
888 
889  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
890  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
891 
892  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
893  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
894  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
895  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
896  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
897  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
898 
899  TSMatDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
900  }
902  //**********************************************************************************************
903 
904  //**Addition assignment to dense matrices (kernel selection)************************************
915  template< typename MT3 // Type of the left-hand side target matrix
916  , typename MT4 // Type of the left-hand side matrix operand
917  , typename MT5 > // Type of the right-hand side matrix operand
918  static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
919  {
920  const size_t size( C.rows() * C.columns() );
921 
922  if( ( IsRowMajorMatrix_v<MT3> && size < TSMATDMATMULT_THRESHOLD ) ||
923  ( IsColumnMajorMatrix_v<MT3> && size < 625UL ) )
924  selectSmallAddAssignKernel( C, A, B );
925  else
926  selectLargeAddAssignKernel( C, A, B );
927  }
929  //**********************************************************************************************
930 
931  //**Default addition assignment to dense matrices***********************************************
946  template< typename MT3 // Type of the left-hand side target matrix
947  , typename MT4 // Type of the left-hand side matrix operand
948  , typename MT5 > // Type of the right-hand side matrix operand
949  static inline void selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
950  {
951  if( IsDiagonal_v<MT5> )
952  {
953  for( size_t i=0UL; i<A.columns(); ++i )
954  {
955  const auto end( A.end(i) );
956  auto element( A.begin(i) );
957 
958  for( ; element!=end; ++element ) {
959  C(element->index(),i) += element->value() * B(i,i);
960  }
961  }
962  }
963  else
964  {
965  const size_t block( IsRowMajorMatrix_v<MT3> ? 256UL : 8UL );
966 
967  for( size_t jj=0UL; jj<B.columns(); jj+=block )
968  {
969  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
970 
971  for( size_t i=0UL; i<A.columns(); ++i )
972  {
973  const auto end( A.end(i) );
974  auto element( A.begin(i) );
975 
976  for( ; element!=end; ++element )
977  {
978  const size_t i1( element->index() );
979 
980  const size_t jbegin( ( IsUpper_v<MT5> )
981  ?( ( UPP )
982  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
983  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
984  :( UPP ? max(i1,jj) : jj ) );
985  const size_t jend( ( IsLower_v<MT5> )
986  ?( ( LOW )
987  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
988  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
989  :( LOW ? min(i1+1UL,jpos) : jpos ) );
990 
991  if( jbegin >= jend )
992  continue;
993 
994  for( size_t j=jbegin; j<jend; ++j ) {
995  C(i1,j) += element->value() * B(i,j);
996  }
997  }
998  }
999  }
1000  }
1001  }
1003  //**********************************************************************************************
1004 
1005  //**Default addition assignment to dense matrices (small matrices)******************************
1019  template< typename MT3 // Type of the left-hand side target matrix
1020  , typename MT4 // Type of the left-hand side matrix operand
1021  , typename MT5 > // Type of the right-hand side matrix operand
1022  static inline auto selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1023  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1024  {
1025  selectDefaultAddAssignKernel( C, A, B );
1026  }
1028  //**********************************************************************************************
1029 
1030  //**Optimized addition assignment to dense matrices (small matrices)****************************
1045  template< typename MT3 // Type of the left-hand side target matrix
1046  , typename MT4 // Type of the left-hand side matrix operand
1047  , typename MT5 > // Type of the right-hand side matrix operand
1048  static inline auto selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1049  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1050  {
1051  const size_t block( ( IsRowMajorMatrix_v<MT3> )?( 256UL ):( 8UL ) );
1052 
1053  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1054  {
1055  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1056 
1057  for( size_t i=0UL; i<A.columns(); ++i )
1058  {
1059  const auto end( A.end(i) );
1060  auto element( A.begin(i) );
1061 
1062  const size_t nonzeros( A.nonZeros(i) );
1063  const size_t kpos( nonzeros & size_t(-4) );
1064  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1065 
1066  for( size_t k=0UL; k<kpos; k+=4UL )
1067  {
1068  const size_t i1( element->index() );
1069  const ET1 v1( element->value() );
1070  ++element;
1071  const size_t i2( element->index() );
1072  const ET1 v2( element->value() );
1073  ++element;
1074  const size_t i3( element->index() );
1075  const ET1 v3( element->value() );
1076  ++element;
1077  const size_t i4( element->index() );
1078  const ET1 v4( element->value() );
1079  ++element;
1080 
1081  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1082 
1083  const size_t jbegin( ( IsUpper_v<MT5> )
1084  ?( ( UPP )
1085  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1086  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1087  :( UPP ? max(i1,jj) : jj ) );
1088  const size_t jend( ( IsLower_v<MT5> )
1089  ?( ( LOW )
1090  ?( min( i4+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1091  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1092  :( LOW ? min(i4+1UL,jpos) : jpos ) );
1093 
1094  if( jbegin >= jend )
1095  continue;
1096 
1097  for( size_t j=jbegin; j<jend; ++j ) {
1098  C(i1,j) += v1 * B(i,j);
1099  C(i2,j) += v2 * B(i,j);
1100  C(i3,j) += v3 * B(i,j);
1101  C(i4,j) += v4 * B(i,j);
1102  }
1103  }
1104 
1105  for( ; element!=end; ++element )
1106  {
1107  const size_t i1( element->index() );
1108 
1109  const size_t jbegin( ( IsUpper_v<MT5> )
1110  ?( ( UPP )
1111  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1112  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1113  :( UPP ? max(i1,jj) : jj ) );
1114  const size_t jend( ( IsLower_v<MT5> )
1115  ?( ( LOW )
1116  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1117  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1118  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1119 
1120  if( jbegin >= jend )
1121  continue;
1122 
1123  for( size_t j=jbegin; j<jend; ++j ) {
1124  C(i1,j) += element->value() * B(i,j);
1125  }
1126  }
1127  }
1128  }
1129  }
1131  //**********************************************************************************************
1132 
1133  //**Default addition assignment to dense matrices (large matrices)******************************
1147  template< typename MT3 // Type of the left-hand side target matrix
1148  , typename MT4 // Type of the left-hand side matrix operand
1149  , typename MT5 > // Type of the right-hand side matrix operand
1150  static inline auto selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1151  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1152  {
1153  selectDefaultAddAssignKernel( C, A, B );
1154  }
1156  //**********************************************************************************************
1157 
1158  //**Optimized addition assignment to dense matrices (large matrices)****************************
1173  template< typename MT3 // Type of the left-hand side target matrix
1174  , typename MT4 // Type of the left-hand side matrix operand
1175  , typename MT5 > // Type of the right-hand side matrix operand
1176  static inline auto selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1177  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1178  {
1179  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_t<MT4> );
1180 
1181  const ForwardFunctor fwd;
1182 
1183  const OppositeType_t<MT4> tmp( serial( A ) );
1184  addAssign( C, fwd( tmp * B ) );
1185  }
1187  //**********************************************************************************************
1188 
1189  //**Restructuring addition assignment to row-major matrices*************************************
1204  template< typename MT // Type of the target matrix
1205  , bool SO > // Storage order of the target matrix
1206  friend inline auto addAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1207  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1208  {
1210 
1212 
1213  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1214  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1215 
1216  const ForwardFunctor fwd;
1217 
1218  addAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1219  }
1221  //**********************************************************************************************
1222 
1223  //**Addition assignment to sparse matrices******************************************************
1224  // No special implementation for the addition assignment to sparse matrices.
1225  //**********************************************************************************************
1226 
1227  //**Subtraction assignment to dense matrices****************************************************
1240  template< typename MT // Type of the target dense matrix
1241  , bool SO > // Storage order of the target dense matrix
1242  friend inline auto subAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1243  -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1244  {
1246 
1247  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1248  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1249 
1250  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1251  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1252 
1253  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1254  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1255  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1256  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1257  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1258  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1259 
1260  TSMatDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1261  }
1263  //**********************************************************************************************
1264 
1265  //**Subtraction assignment to dense matrices (kernel selection)*********************************
1276  template< typename MT3 // Type of the left-hand side target matrix
1277  , typename MT4 // Type of the left-hand side matrix operand
1278  , typename MT5 > // Type of the right-hand side matrix operand
1279  static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1280  {
1281  const size_t size( C.rows() * C.columns() );
1282 
1283  if( ( IsRowMajorMatrix_v<MT3> && size < TSMATDMATMULT_THRESHOLD ) ||
1284  ( IsColumnMajorMatrix_v<MT3> && size < 625UL ) )
1285  selectSmallSubAssignKernel( C, A, B );
1286  else
1287  selectLargeSubAssignKernel( C, A, B );
1288  }
1290  //**********************************************************************************************
1291 
1292  //**Default subtraction assignment to dense matrices********************************************
1307  template< typename MT3 // Type of the left-hand side target matrix
1308  , typename MT4 // Type of the left-hand side matrix operand
1309  , typename MT5 > // Type of the right-hand side matrix operand
1310  static inline void selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1311  {
1312  if( IsDiagonal_v<MT5> )
1313  {
1314  for( size_t i=0UL; i<A.columns(); ++i )
1315  {
1316  const auto end( A.end(i) );
1317  auto element( A.begin(i) );
1318 
1319  for( ; element!=end; ++element ) {
1320  C(element->index(),i) -= element->value() * B(i,i);
1321  }
1322  }
1323  }
1324  else
1325  {
1326  const size_t block( IsRowMajorMatrix_v<MT3> ? 256UL : 8UL );
1327 
1328  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1329  {
1330  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1331 
1332  for( size_t i=0UL; i<A.columns(); ++i )
1333  {
1334  const auto end( A.end(i) );
1335  auto element( A.begin(i) );
1336 
1337  for( ; element!=end; ++element )
1338  {
1339  const size_t i1( element->index() );
1340 
1341  const size_t jbegin( ( IsUpper_v<MT5> )
1342  ?( ( UPP )
1343  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1344  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1345  :( UPP ? max(i1,jj) : jj ) );
1346  const size_t jend( ( IsLower_v<MT5> )
1347  ?( ( LOW )
1348  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1349  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1350  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1351 
1352  if( jbegin >= jend )
1353  continue;
1354 
1355  for( size_t j=jbegin; j<jend; ++j ) {
1356  C(i1,j) -= element->value() * B(i,j);
1357  }
1358  }
1359  }
1360  }
1361  }
1362  }
1364  //**********************************************************************************************
1365 
1366  //**Default subtraction assignment to dense matrices (small matrices)***************************
1380  template< typename MT3 // Type of the left-hand side target matrix
1381  , typename MT4 // Type of the left-hand side matrix operand
1382  , typename MT5 > // Type of the right-hand side matrix operand
1383  static inline auto selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1384  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1385  {
1386  selectDefaultSubAssignKernel( C, A, B );
1387  }
1389  //**********************************************************************************************
1390 
1391  //**Optimized subtraction assignment to dense matrices (small matrices)*************************
1406  template< typename MT3 // Type of the left-hand side target matrix
1407  , typename MT4 // Type of the left-hand side matrix operand
1408  , typename MT5 > // Type of the right-hand side matrix operand
1409  static inline auto selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1410  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1411  {
1412  const size_t block( ( IsRowMajorMatrix_v<MT3> )?( 256UL ):( 8UL ) );
1413 
1414  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1415  {
1416  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1417 
1418  for( size_t i=0UL; i<A.columns(); ++i )
1419  {
1420  const auto end( A.end(i) );
1421  auto element( A.begin(i) );
1422 
1423  const size_t nonzeros( A.nonZeros(i) );
1424  const size_t kpos( nonzeros & size_t(-4) );
1425  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1426 
1427  for( size_t k=0UL; k<kpos; k+=4UL )
1428  {
1429  const size_t i1( element->index() );
1430  const ET1 v1( element->value() );
1431  ++element;
1432  const size_t i2( element->index() );
1433  const ET1 v2( element->value() );
1434  ++element;
1435  const size_t i3( element->index() );
1436  const ET1 v3( element->value() );
1437  ++element;
1438  const size_t i4( element->index() );
1439  const ET1 v4( element->value() );
1440  ++element;
1441 
1442  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1443 
1444  const size_t jbegin( ( IsUpper_v<MT5> )
1445  ?( ( UPP )
1446  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1447  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1448  :( UPP ? max(i1,jj) : jj ) );
1449  const size_t jend( ( IsLower_v<MT5> )
1450  ?( ( LOW )
1451  ?( min( i4+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1452  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1453  :( LOW ? min(i4+1UL,jpos) : jpos ) );
1454 
1455  if( jbegin >= jend )
1456  continue;
1457 
1458  for( size_t j=jbegin; j<jend; ++j ) {
1459  C(i1,j) -= v1 * B(i,j);
1460  C(i2,j) -= v2 * B(i,j);
1461  C(i3,j) -= v3 * B(i,j);
1462  C(i4,j) -= v4 * B(i,j);
1463  }
1464  }
1465 
1466  for( ; element!=end; ++element )
1467  {
1468  const size_t i1( element->index() );
1469 
1470  const size_t jbegin( ( IsUpper_v<MT5> )
1471  ?( ( UPP )
1472  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1473  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1474  :( UPP ? max(i1,jj) : jj ) );
1475  const size_t jend( ( IsLower_v<MT5> )
1476  ?( ( LOW )
1477  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1478  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1479  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1480 
1481  if( jbegin >= jend )
1482  continue;
1483 
1484  for( size_t j=jbegin; j<jend; ++j ) {
1485  C(i1,j) -= element->value() * B(i,j);
1486  }
1487  }
1488  }
1489  }
1490  }
1492  //**********************************************************************************************
1493 
1494  //**Default subtraction assignment to dense matrices (large matrices)***************************
1508  template< typename MT3 // Type of the left-hand side target matrix
1509  , typename MT4 // Type of the left-hand side matrix operand
1510  , typename MT5 > // Type of the right-hand side matrix operand
1511  static inline auto selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1512  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1513  {
1514  selectDefaultSubAssignKernel( C, A, B );
1515  }
1517  //**********************************************************************************************
1518 
1519  //**Optimized subtraction assignment to dense matrices (large matrices)*************************
1534  template< typename MT3 // Type of the left-hand side target matrix
1535  , typename MT4 // Type of the left-hand side matrix operand
1536  , typename MT5 > // Type of the right-hand side matrix operand
1537  static inline auto selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1538  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1539  {
1540  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_t<MT4> );
1541 
1542  const ForwardFunctor fwd;
1543 
1544  const OppositeType_t<MT4> tmp( serial( A ) );
1545  subAssign( C, fwd( tmp * B ) );
1546  }
1548  //**********************************************************************************************
1549 
1550  //**Restructuring subtraction assignment to row-major matrices**********************************
1565  template< typename MT // Type of the target matrix
1566  , bool SO > // Storage order of the target matrix
1567  friend inline auto subAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1568  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1569  {
1571 
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 ForwardFunctor fwd;
1578 
1579  subAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1580  }
1582  //**********************************************************************************************
1583 
1584  //**Subtraction assignment to sparse matrices***************************************************
1585  // No special implementation for the subtraction assignment to sparse matrices.
1586  //**********************************************************************************************
1587 
1588  //**Schur product assignment to dense matrices**************************************************
1601  template< typename MT // Type of the target dense matrix
1602  , bool SO > // Storage order of the target dense matrix
1603  friend inline void schurAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1604  {
1606 
1610 
1611  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1612  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1613 
1614  const ResultType tmp( serial( rhs ) );
1615  schurAssign( ~lhs, tmp );
1616  }
1618  //**********************************************************************************************
1619 
1620  //**Schur product assignment to sparse matrices*************************************************
1621  // No special implementation for the Schur product assignment to sparse matrices.
1622  //**********************************************************************************************
1623 
1624  //**Multiplication assignment to dense matrices*************************************************
1625  // No special implementation for the multiplication assignment to dense matrices.
1626  //**********************************************************************************************
1627 
1628  //**Multiplication assignment to sparse matrices************************************************
1629  // No special implementation for the multiplication assignment to sparse matrices.
1630  //**********************************************************************************************
1631 
1632  //**SMP assignment to dense matrices************************************************************
1648  template< typename MT // Type of the target dense matrix
1649  , bool SO > // Storage order of the target dense matrix
1650  friend inline auto smpAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1651  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1652  {
1654 
1655  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1656  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1657 
1658  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1659  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1660 
1661  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1662  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1663  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1664  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1665  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1666  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1667 
1668  smpAssign( ~lhs, A * B );
1669  }
1671  //**********************************************************************************************
1672 
1673  //**SMP assignment to sparse matrices***********************************************************
1689  template< typename MT // Type of the target sparse matrix
1690  , bool SO > // Storage order of the target sparse matrix
1691  friend inline auto smpAssign( SparseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1692  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1693  {
1695 
1696  using TmpType = If_t< SO, OppositeType, ResultType >;
1697 
1704 
1705  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1706  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1707 
1708  const ForwardFunctor fwd;
1709 
1710  const TmpType tmp( rhs );
1711  smpAssign( ~lhs, fwd( tmp ) );
1712  }
1714  //**********************************************************************************************
1715 
1716  //**Restructuring SMP assignment to row-major matrices******************************************
1731  template< typename MT // Type of the target matrix
1732  , bool SO > // Storage order of the target matrix
1733  friend inline auto smpAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1734  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1735  {
1737 
1738  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1739  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1740 
1741  const ForwardFunctor fwd;
1742 
1743  smpAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1744  }
1746  //**********************************************************************************************
1747 
1748  //**SMP addition assignment to dense matrices***************************************************
1764  template< typename MT // Type of the target dense matrix
1765  , bool SO > // Storage order of the target dense matrix
1766  friend inline auto smpAddAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1767  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1768  {
1770 
1771  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1772  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1773 
1774  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1775  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1776 
1777  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1778  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1779  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1780  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1781  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1782  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1783 
1784  smpAddAssign( ~lhs, A * B );
1785  }
1787  //**********************************************************************************************
1788 
1789  //**Restructuring SMP addition assignment to row-major matrices*********************************
1804  template< typename MT // Type of the target matrix
1805  , bool SO > // Storage order of the target matrix
1806  friend inline auto smpAddAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1807  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1808  {
1810 
1811  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1812  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1813 
1814  const ForwardFunctor fwd;
1815 
1816  smpAddAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1817  }
1819  //**********************************************************************************************
1820 
1821  //**SMP addition assignment to sparse matrices**************************************************
1822  // No special implementation for the SMP addition assignment to sparse matrices.
1823  //**********************************************************************************************
1824 
1825  //**SMP subtraction assignment to dense matrices************************************************
1841  template< typename MT // Type of the target dense matrix
1842  , bool SO > // Storage order of the target dense matrix
1843  friend inline auto smpSubAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1844  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1845  {
1847 
1848  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1849  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1850 
1851  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1852  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1853 
1854  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1855  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1856  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1857  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1858  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1859  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1860 
1861  smpSubAssign( ~lhs, A * B );
1862  }
1864  //**********************************************************************************************
1865 
1866  //**Restructuring SMP subtraction assignment to row-major matrices******************************
1881  template< typename MT // Type of the target matrix
1882  , bool SO > // Storage order of the target matrix
1883  friend inline auto smpSubAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1884  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1885  {
1887 
1888  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1889  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1890 
1891  const ForwardFunctor fwd;
1892 
1893  smpSubAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1894  }
1896  //**********************************************************************************************
1897 
1898  //**SMP subtraction assignment to sparse matrices***********************************************
1899  // No special implementation for the SMP subtraction assignment to sparse matrices.
1900  //**********************************************************************************************
1901 
1902  //**SMP Schur product assignment to dense matrices**********************************************
1915  template< typename MT // Type of the target dense matrix
1916  , bool SO > // Storage order of the target dense matrix
1917  friend inline void smpSchurAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1918  {
1920 
1924 
1925  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1926  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1927 
1928  const ResultType tmp( rhs );
1929  smpSchurAssign( ~lhs, tmp );
1930  }
1932  //**********************************************************************************************
1933 
1934  //**SMP Schur product assignment to sparse matrices*********************************************
1935  // No special implementation for the SMP Schur product assignment to sparse matrices.
1936  //**********************************************************************************************
1937 
1938  //**SMP multiplication assignment to dense matrices*********************************************
1939  // No special implementation for the SMP multiplication assignment to dense matrices.
1940  //**********************************************************************************************
1941 
1942  //**SMP multiplication assignment to sparse matrices********************************************
1943  // No special implementation for the SMP multiplication assignment to sparse matrices.
1944  //**********************************************************************************************
1945 
1946  //**Compile time checks*************************************************************************
1955  //**********************************************************************************************
1956 };
1957 //*************************************************************************************************
1958 
1959 
1960 
1961 
1962 //=================================================================================================
1963 //
1964 // GLOBAL BINARY ARITHMETIC OPERATORS
1965 //
1966 //=================================================================================================
1967 
1968 //*************************************************************************************************
1981 template< typename MT1 // Type of the left-hand side dense matrix
1982  , typename MT2 // Type of the right-hand side sparse matrix
1983  , DisableIf_t< ( IsIdentity_v<MT1> &&
1984  IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > ) ||
1985  IsZero_v<MT1> >* = nullptr >
1986 inline const TSMatDMatMultExpr<MT1,MT2,false,false,false,false>
1987  tsmatdmatmult( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs )
1988 {
1990 
1991  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).rows(), "Invalid matrix sizes" );
1992 
1993  return TSMatDMatMultExpr<MT1,MT2,false,false,false,false>( ~lhs, ~rhs );
1994 }
1996 //*************************************************************************************************
1997 
1998 
1999 //*************************************************************************************************
2013 template< typename MT1 // Type of the left-hand side sparse matrix
2014  , typename MT2 // Type of the right-hand side dense matrix
2015  , EnableIf_t< IsIdentity_v<MT1> &&
2016  IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > >* = nullptr >
2017 inline const MT2&
2018  tsmatdmatmult( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs )
2019 {
2021 
2022  MAYBE_UNUSED( lhs );
2023 
2024  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).rows(), "Invalid matrix sizes" );
2025 
2026  return (~rhs);
2027 }
2029 //*************************************************************************************************
2030 
2031 
2032 //*************************************************************************************************
2045 template< typename MT1 // Type of the left-hand side dense matrix
2046  , typename MT2 // Type of the right-hand side sparse matrix
2047  , EnableIf_t< IsZero_v<MT1> >* = nullptr >
2048 inline decltype(auto)
2049  tsmatdmatmult( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs )
2050 {
2052 
2053  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).rows(), "Invalid matrix sizes" );
2054 
2055  using ReturnType = const MultTrait_t< ResultType_t<MT1>, ResultType_t<MT2> >;
2056 
2058  BLAZE_CONSTRAINT_MUST_BE_ZERO_TYPE( ReturnType );
2059 
2060  return ReturnType( (~lhs).rows(), (~rhs).columns() );
2061 }
2063 //*************************************************************************************************
2064 
2065 
2066 //*************************************************************************************************
2097 template< typename MT1 // Type of the left-hand side sparse matrix
2098  , typename MT2 > // Type of the right-hand side dense matrix
2099 inline decltype(auto)
2100  operator*( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs )
2101 {
2103 
2104  if( (~lhs).columns() != (~rhs).rows() ) {
2105  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
2106  }
2107 
2108  return tsmatdmatmult( ~lhs, ~rhs );
2109 }
2110 //*************************************************************************************************
2111 
2112 
2113 
2114 
2115 //=================================================================================================
2116 //
2117 // GLOBAL FUNCTIONS
2118 //
2119 //=================================================================================================
2120 
2121 //*************************************************************************************************
2147 template< typename MT1 // Type of the left-hand side dense matrix
2148  , typename MT2 // Type of the right-hand side dense matrix
2149  , bool SF // Symmetry flag
2150  , bool HF // Hermitian flag
2151  , bool LF // Lower flag
2152  , bool UF > // Upper flag
2153 inline decltype(auto) declsym( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2154 {
2156 
2157  if( !isSquare( dm ) ) {
2158  BLAZE_THROW_INVALID_ARGUMENT( "Invalid symmetric matrix specification" );
2159  }
2160 
2161  using ReturnType = const TSMatDMatMultExpr<MT1,MT2,true,HF,LF,UF>;
2162  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2163 }
2165 //*************************************************************************************************
2166 
2167 
2168 //*************************************************************************************************
2194 template< typename MT1 // Type of the left-hand side dense matrix
2195  , typename MT2 // Type of the right-hand side dense matrix
2196  , bool SF // Symmetry flag
2197  , bool HF // Hermitian flag
2198  , bool LF // Lower flag
2199  , bool UF > // Upper flag
2200 inline decltype(auto) declherm( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2201 {
2203 
2204  if( !isSquare( dm ) ) {
2205  BLAZE_THROW_INVALID_ARGUMENT( "Invalid Hermitian matrix specification" );
2206  }
2207 
2208  using ReturnType = const TSMatDMatMultExpr<MT1,MT2,SF,true,LF,UF>;
2209  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2210 }
2212 //*************************************************************************************************
2213 
2214 
2215 //*************************************************************************************************
2241 template< typename MT1 // Type of the left-hand side dense matrix
2242  , typename MT2 // Type of the right-hand side dense matrix
2243  , bool SF // Symmetry flag
2244  , bool HF // Hermitian flag
2245  , bool LF // Lower flag
2246  , bool UF > // Upper flag
2247 inline decltype(auto) decllow( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2248 {
2250 
2251  if( !isSquare( dm ) ) {
2252  BLAZE_THROW_INVALID_ARGUMENT( "Invalid lower matrix specification" );
2253  }
2254 
2255  using ReturnType = const TSMatDMatMultExpr<MT1,MT2,SF,HF,true,UF>;
2256  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2257 }
2259 //*************************************************************************************************
2260 
2261 
2262 //*************************************************************************************************
2288 template< typename MT1 // Type of the left-hand side dense matrix
2289  , typename MT2 // Type of the right-hand side dense matrix
2290  , bool SF // Symmetry flag
2291  , bool HF // Hermitian flag
2292  , bool LF // Lower flag
2293  , bool UF > // Upper flag
2294 inline decltype(auto) declupp( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2295 {
2297 
2298  if( !isSquare( dm ) ) {
2299  BLAZE_THROW_INVALID_ARGUMENT( "Invalid upper matrix specification" );
2300  }
2301 
2302  using ReturnType = const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,true>;
2303  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2304 }
2306 //*************************************************************************************************
2307 
2308 
2309 //*************************************************************************************************
2335 template< typename MT1 // Type of the left-hand side dense matrix
2336  , typename MT2 // Type of the right-hand side dense matrix
2337  , bool SF // Symmetry flag
2338  , bool HF // Hermitian flag
2339  , bool LF // Lower flag
2340  , bool UF > // Upper flag
2341 inline decltype(auto) decldiag( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2342 {
2344 
2345  if( !isSquare( dm ) ) {
2346  BLAZE_THROW_INVALID_ARGUMENT( "Invalid diagonal matrix specification" );
2347  }
2348 
2349  using ReturnType = const TSMatDMatMultExpr<MT1,MT2,SF,HF,true,true>;
2350  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2351 }
2353 //*************************************************************************************************
2354 
2355 
2356 
2357 
2358 //=================================================================================================
2359 //
2360 // SIZE SPECIALIZATIONS
2361 //
2362 //=================================================================================================
2363 
2364 //*************************************************************************************************
2366 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2367 struct Size< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 0UL >
2368  : public Size<MT1,0UL>
2369 {};
2370 
2371 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2372 struct Size< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 1UL >
2373  : public Size<MT2,1UL>
2374 {};
2376 //*************************************************************************************************
2377 
2378 
2379 
2380 
2381 //=================================================================================================
2382 //
2383 // ISALIGNED SPECIALIZATIONS
2384 //
2385 //=================================================================================================
2386 
2387 //*************************************************************************************************
2389 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2390 struct IsAligned< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2391  : public IsAligned<MT2>
2392 {};
2394 //*************************************************************************************************
2395 
2396 } // namespace blaze
2397 
2398 #endif
OppositeType_t< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: TSMatDMatMultExpr.h:247
#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:257
bool isAligned() const noexcept
Returns whether the operands of the expression are properly aligned in memory.
Definition: TSMatDMatMultExpr.h:425
Header file for basic type definitions.
typename If< Condition, T1, T2 >::Type If_t
Auxiliary alias template for the If class template.The If_t alias template provides a convenient shor...
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:296
Header file for the serial shim.
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: TSMatDMatMultExpr.h:371
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:134
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: TSMatDMatMultExpr.h:442
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:595
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.
decltype(auto) subvector(Vector< VT, TF > &, RSAs...)
Creating a view on a specific subvector of the given vector.
Definition: Subvector.h:154
Header file for the MAYBE_UNUSED function template.
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:260
static constexpr bool SYM
Flag for symmetric matrices.
Definition: TSMatDMatMultExpr.h:153
decltype(auto) declupp(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as upper.
Definition: DMatDeclUppExpr.h:1001
CompositeType_t< MT2 > CT2
Composite type of the right-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:139
static constexpr bool simdEnabled
Compilation switch for the expression template evaluation strategy.
Definition: TSMatDMatMultExpr.h:268
LeftOperand leftOperand() const noexcept
Returns the left-hand side transpose sparse matrix operand.
Definition: TSMatDMatMultExpr.h:381
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:149
Constraints on the storage order of matrix types.
Header file for the RequiresEvaluation type trait.
System settings for performance optimizations.
If_t< IsExpression_v< MT1 >, const MT1, const MT1 & > LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:254
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:361
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes....
Definition: DenseMatrix.h:81
const ResultType CompositeType
Data type for composite expression templates.
Definition: TSMatDMatMultExpr.h:251
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes....
Definition: Forward.h:145
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:156
static constexpr bool LOW
Flag for lower matrices.
Definition: TSMatDMatMultExpr.h:155
RightOperand rhs_
Right-hand side dense matrix of the multiplication expression.
Definition: TSMatDMatMultExpr.h:443
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:245
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:271
#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:137
Generic wrapper for the decllow() function.
Definition: DeclLow.h:59
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:1162
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:1001
Header file for the IsLower type trait.
constexpr void MAYBE_UNUSED(const Args &...)
Suppression of unused parameter warnings.
Definition: MaybeUnused.h:81
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:263
Generic wrapper for the null function.
Definition: Noop.h:60
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:345
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: TSMatDMatMultExpr.h:435
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:1198
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.
CompositeType_t< MT1 > CT1
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:138
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:391
ElementType_t< ResultType > ElementType
Resulting element type.
Definition: TSMatDMatMultExpr.h:249
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:135
#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,...
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:248
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:281
Header file for the IsZero type trait.
ElementType_t< RT1 > ET1
Element type of the left-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:136
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
Header file for all forward declarations for expression class templates.
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:59
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:59
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TSMatDMatMultExpr.h:250
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:415
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:179
static constexpr bool evaluateLeft
Compilation switch for the composite type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:144
Header file for the IntegralConstant class template.
Generic wrapper for the decldiag() function.
Definition: DeclDiag.h:59
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: TSMatDMatMultExpr.h:403
Header file for the DeclHerm functor.
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:635
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:1324
Constraint on the data type.
Generic wrapper for the declsym() function.
Definition: DeclSym.h:59
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:154
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,...
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.