TSMatTDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_TSMATTDMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_TSMATTDMATMULTEXPR_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 TSMatTDMatMultExpr
128  : public MatMatMultExpr< DenseMatrix< TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, true > >
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> || IsSymmetric_v<T3> );
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 TSMatTDMatMultExpr( 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_TSMATTDMATMULT_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 TSMatTDMatMultExpr& 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  TSMatTDMatMultExpr::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 < TSMATTDMATMULT_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( 64UL );
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> ? 128UL : 64UL );
644 
645  for( size_t jj=0UL; jj<B.columns(); jj+=block )
646  {
647  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
648 
649  for( size_t i=0UL; i<A.rows(); ++i ) {
650  for( size_t j=jj; j<jpos; ++j ) {
651  reset( C(i,j) );
652  }
653  }
654 
655  for( size_t i=0UL; i<A.columns(); ++i )
656  {
657  const auto end( A.end(i) );
658  auto element( A.begin(i) );
659 
660  const size_t nonzeros( A.nonZeros(i) );
661  const size_t kpos( nonzeros & size_t(-4) );
662  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
663 
664  for( size_t k=0UL; k<kpos; k+=4UL )
665  {
666  const size_t i1( element->index() );
667  const ET1 v1( element->value() );
668  ++element;
669  const size_t i2( element->index() );
670  const ET1 v2( element->value() );
671  ++element;
672  const size_t i3( element->index() );
673  const ET1 v3( element->value() );
674  ++element;
675  const size_t i4( element->index() );
676  const ET1 v4( element->value() );
677  ++element;
678 
679  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
680 
681  const size_t jbegin( ( IsUpper_v<MT5> )
682  ?( ( SYM || HERM || UPP )
683  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
684  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
685  :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
686  const size_t jend( ( IsLower_v<MT5> )
687  ?( ( LOW )
688  ?( min( i4+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
689  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
690  :( LOW ? min(i4+1UL,jpos) : jpos ) );
691 
692  if( jbegin >= jend )
693  continue;
694 
695  for( size_t j=jbegin; j<jend; ++j ) {
696  C(i1,j) += v1 * B(i,j);
697  C(i2,j) += v2 * B(i,j);
698  C(i3,j) += v3 * B(i,j);
699  C(i4,j) += v4 * B(i,j);
700  }
701  }
702 
703  for( ; element!=end; ++element )
704  {
705  const size_t i1( element->index() );
706 
707  const size_t jbegin( ( IsUpper_v<MT5> )
708  ?( ( SYM || HERM || UPP )
709  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
710  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
711  :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
712  const size_t jend( ( IsLower_v<MT5> )
713  ?( ( LOW )
714  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
715  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
716  :( LOW ? min(i1+1UL,jpos) : jpos ) );
717 
718  if( jbegin >= jend )
719  continue;
720 
721  for( size_t j=jbegin; j<jend; ++j ) {
722  C(i1,j) += element->value() * B(i,j);
723  }
724  }
725  }
726  }
727 
728  if( SYM || HERM ) {
729  for( size_t j=0UL; j<B.columns(); ++j ) {
730  for( size_t i=j+1UL; i<A.rows(); ++i ) {
731  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
732  }
733  }
734  }
735  }
737  //**********************************************************************************************
738 
739  //**Default assignment to dense matrices (large matrices)***************************************
753  template< typename MT3 // Type of the left-hand side target matrix
754  , typename MT4 // Type of the left-hand side matrix operand
755  , typename MT5 > // Type of the right-hand side matrix operand
756  static inline auto selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
757  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
758  {
759  selectDefaultAssignKernel( C, A, B );
760  }
762  //**********************************************************************************************
763 
764  //**Optimized assignment to dense matrices (large matrices)*************************************
779  template< typename MT3 // Type of the left-hand side target matrix
780  , typename MT4 // Type of the left-hand side matrix operand
781  , typename MT5 > // Type of the right-hand side matrix operand
782  static inline auto selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
783  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
784  {
785  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_t<MT4> );
786 
787  const ForwardFunctor fwd;
788 
789  const OppositeType_t<MT4> tmp( serial( A ) );
790  assign( C, fwd( tmp * B ) );
791  }
793  //**********************************************************************************************
794 
795  //**Assignment to sparse matrices***************************************************************
808  template< typename MT // Type of the target sparse matrix
809  , bool SO > // Storage order of the target sparse matrix
810  friend inline auto assign( SparseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
811  -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
812  {
814 
815  using TmpType = If_t< SO, ResultType, OppositeType >;
816 
823 
824  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
825  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
826 
827  const ForwardFunctor fwd;
828 
829  const TmpType tmp( serial( rhs ) );
830  assign( ~lhs, fwd( tmp ) );
831  }
833  //**********************************************************************************************
834 
835  //**Restructuring assignment********************************************************************
850  template< typename MT // Type of the target matrix
851  , bool SO > // Storage order of the target matrix
852  friend inline auto assign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
853  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
854  {
856 
858 
859  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
860  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
861 
862  const ForwardFunctor fwd;
863 
864  if( IsSymmetric_v<MT1> && IsSymmetric_v<MT2> )
865  assign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
866  else if( IsSymmetric_v<MT1> )
867  assign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
868  else
869  assign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
870  }
872  //**********************************************************************************************
873 
874  //**Addition assignment to dense matrices*******************************************************
887  template< typename MT // Type of the target dense matrix
888  , bool SO > // Storage order of the target dense matrix
889  friend inline auto addAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
890  -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
891  {
893 
894  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
895  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
896 
897  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
898  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
899 
900  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
901  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
902  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
903  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
904  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
905  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
906 
907  TSMatTDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
908  }
910  //**********************************************************************************************
911 
912  //**Addition assignment to dense matrices (kernel selection)************************************
923  template< typename MT3 // Type of the left-hand side target matrix
924  , typename MT4 // Type of the left-hand side matrix operand
925  , typename MT5 > // Type of the right-hand side matrix operand
926  static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
927  {
928  const size_t size( C.rows() * C.columns() );
929 
930  if( ( IsRowMajorMatrix_v<MT3> && size < TSMATTDMATMULT_THRESHOLD ) ||
931  ( IsColumnMajorMatrix_v<MT3> && size < 625UL ) )
932  selectSmallAddAssignKernel( C, A, B );
933  else
934  selectLargeAddAssignKernel( C, A, B );
935  }
937  //**********************************************************************************************
938 
939  //**Default addition assignment to dense matrices***********************************************
954  template< typename MT3 // Type of the left-hand side target matrix
955  , typename MT4 // Type of the left-hand side matrix operand
956  , typename MT5 > // Type of the right-hand side matrix operand
957  static inline void selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
958  {
959  if( IsDiagonal_v<MT5> )
960  {
961  for( size_t i=0UL; i<A.columns(); ++i )
962  {
963  const auto end( A.end(i) );
964  auto element( A.begin(i) );
965 
966  for( ; element!=end; ++element ) {
967  C(element->index(),i) += element->value() * B(i,i);
968  }
969  }
970  }
971  else
972  {
973  const size_t block( 64UL );
974 
975  for( size_t jj=0UL; jj<B.columns(); jj+=block )
976  {
977  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
978 
979  for( size_t i=0UL; i<A.columns(); ++i )
980  {
981  const auto end( A.end(i) );
982  auto element( A.begin(i) );
983 
984  for( ; element!=end; ++element )
985  {
986  const size_t i1( element->index() );
987 
988  const size_t jbegin( ( IsUpper_v<MT5> )
989  ?( ( UPP )
990  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
991  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
992  :( UPP ? max(i1,jj) : jj ) );
993  const size_t jend( ( IsLower_v<MT5> )
994  ?( ( LOW )
995  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
996  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
997  :( LOW ? min(i1+1UL,jpos) : jpos ) );
998 
999  if( jbegin >= jend )
1000  continue;
1001 
1002  for( size_t j=jbegin; j<jend; ++j ) {
1003  C(i1,j) += element->value() * B(i,j);
1004  }
1005  }
1006  }
1007  }
1008  }
1009  }
1011  //**********************************************************************************************
1012 
1013  //**Default addition assignment to dense matrices (small matrices)******************************
1027  template< typename MT3 // Type of the left-hand side target matrix
1028  , typename MT4 // Type of the left-hand side matrix operand
1029  , typename MT5 > // Type of the right-hand side matrix operand
1030  static inline auto selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1031  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1032  {
1033  selectDefaultAddAssignKernel( C, A, B );
1034  }
1036  //**********************************************************************************************
1037 
1038  //**Optimized addition assignment to dense matrices (small matrices)****************************
1053  template< typename MT3 // Type of the left-hand side target matrix
1054  , typename MT4 // Type of the left-hand side matrix operand
1055  , typename MT5 > // Type of the right-hand side matrix operand
1056  static inline auto selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1057  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1058  {
1059  const size_t block( IsRowMajorMatrix_v<MT3> ? 128UL : 64UL );
1060 
1061  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1062  {
1063  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1064 
1065  for( size_t i=0UL; i<A.columns(); ++i )
1066  {
1067  const auto end( A.end(i) );
1068  auto element( A.begin(i) );
1069 
1070  const size_t nonzeros( A.nonZeros(i) );
1071  const size_t kpos( nonzeros & size_t(-4) );
1072  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1073 
1074  for( size_t k=0UL; k<kpos; k+=4UL )
1075  {
1076  const size_t i1( element->index() );
1077  const ET1 v1( element->value() );
1078  ++element;
1079  const size_t i2( element->index() );
1080  const ET1 v2( element->value() );
1081  ++element;
1082  const size_t i3( element->index() );
1083  const ET1 v3( element->value() );
1084  ++element;
1085  const size_t i4( element->index() );
1086  const ET1 v4( element->value() );
1087  ++element;
1088 
1089  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1090 
1091  const size_t jbegin( ( IsUpper_v<MT5> )
1092  ?( ( UPP )
1093  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1094  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1095  :( UPP ? max(i1,jj) : jj ) );
1096  const size_t jend( ( IsLower_v<MT5> )
1097  ?( ( LOW )
1098  ?( min( i4+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1099  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1100  :( LOW ? min(i4+1UL,jpos) : jpos ) );
1101 
1102  if( jbegin >= jend )
1103  continue;
1104 
1105  for( size_t j=jbegin; j<jend; ++j ) {
1106  C(i1,j) += v1 * B(i,j);
1107  C(i2,j) += v2 * B(i,j);
1108  C(i3,j) += v3 * B(i,j);
1109  C(i4,j) += v4 * B(i,j);
1110  }
1111  }
1112 
1113  for( ; element!=end; ++element )
1114  {
1115  const size_t i1( element->index() );
1116 
1117  const size_t jbegin( ( IsUpper_v<MT5> )
1118  ?( ( UPP )
1119  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1120  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1121  :( UPP ? max(i1,jj) : jj ) );
1122  const size_t jend( ( IsLower_v<MT5> )
1123  ?( ( LOW )
1124  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1125  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1126  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1127 
1128  if( jbegin >= jend )
1129  continue;
1130 
1131  for( size_t j=jbegin; j<jend; ++j ) {
1132  C(i1,j) += element->value() * B(i,j);
1133  }
1134  }
1135  }
1136  }
1137  }
1139  //**********************************************************************************************
1140 
1141  //**Default addition assignment to dense matrices (large matrices)******************************
1155  template< typename MT3 // Type of the left-hand side target matrix
1156  , typename MT4 // Type of the left-hand side matrix operand
1157  , typename MT5 > // Type of the right-hand side matrix operand
1158  static inline auto selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1159  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1160  {
1161  selectDefaultAddAssignKernel( C, A, B );
1162  }
1164  //**********************************************************************************************
1165 
1166  //**Optimized addition assignment to dense matrices (large matrices)****************************
1181  template< typename MT3 // Type of the left-hand side target matrix
1182  , typename MT4 // Type of the left-hand side matrix operand
1183  , typename MT5 > // Type of the right-hand side matrix operand
1184  static inline auto selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1185  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1186  {
1187  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_t<MT4> );
1188 
1189  const ForwardFunctor fwd;
1190 
1191  const OppositeType_t<MT4> tmp( serial( A ) );
1192  addAssign( C, fwd( tmp * B ) );
1193  }
1195  //**********************************************************************************************
1196 
1197  //**Restructuring addition assignment***********************************************************
1212  template< typename MT // Type of the target matrix
1213  , bool SO > // Storage order of the target matrix
1214  friend inline auto addAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1215  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1216  {
1218 
1220 
1221  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1222  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1223 
1224  const ForwardFunctor fwd;
1225 
1226  if( IsSymmetric_v<MT1> && IsSymmetric_v<MT2> )
1227  addAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1228  else if( IsSymmetric_v<MT1> )
1229  addAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1230  else
1231  addAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1232  }
1234  //**********************************************************************************************
1235 
1236  //**Addition assignment to sparse matrices******************************************************
1237  // No special implementation for the addition assignment to sparse matrices.
1238  //**********************************************************************************************
1239 
1240  //**Subtraction assignment to dense matrices****************************************************
1253  template< typename MT // Type of the target dense matrix
1254  , bool SO > // Storage order of the target dense matrix
1255  friend inline auto subAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1256  -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1257  {
1259 
1260  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1261  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1262 
1263  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1264  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1265 
1266  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1267  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1268  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1269  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1270  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1271  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1272 
1273  TSMatTDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1274  }
1276  //**********************************************************************************************
1277 
1278  //**Subtraction assignment to dense matrices (kernel selection)*********************************
1289  template< typename MT3 // Type of the left-hand side target matrix
1290  , typename MT4 // Type of the left-hand side matrix operand
1291  , typename MT5 > // Type of the right-hand side matrix operand
1292  static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1293  {
1294  const size_t size( C.rows() * C.columns() );
1295 
1296  if( ( IsRowMajorMatrix_v<MT3> && size < TSMATTDMATMULT_THRESHOLD ) ||
1297  ( IsColumnMajorMatrix_v<MT3> && size < 625UL ) )
1298  selectSmallSubAssignKernel( C, A, B );
1299  else
1300  selectLargeSubAssignKernel( C, A, B );
1301  }
1303  //**********************************************************************************************
1304 
1305  //**Default subtraction assignment to dense matrices********************************************
1320  template< typename MT3 // Type of the left-hand side target matrix
1321  , typename MT4 // Type of the left-hand side matrix operand
1322  , typename MT5 > // Type of the right-hand side matrix operand
1323  static inline void selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1324  {
1325  if( IsDiagonal_v<MT5> )
1326  {
1327  for( size_t i=0UL; i<A.columns(); ++i )
1328  {
1329  const auto end( A.end(i) );
1330  auto element( A.begin(i) );
1331 
1332  for( ; element!=end; ++element ) {
1333  C(element->index(),i) -= element->value() * B(i,i);
1334  }
1335  }
1336  }
1337  else
1338  {
1339  const size_t block( 64UL );
1340 
1341  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1342  {
1343  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1344 
1345  for( size_t i=0UL; i<A.columns(); ++i )
1346  {
1347  const auto end( A.end(i) );
1348  auto element( A.begin(i) );
1349 
1350  for( ; element!=end; ++element )
1351  {
1352  const size_t i1( element->index() );
1353 
1354  const size_t jbegin( ( IsUpper_v<MT5> )
1355  ?( ( UPP )
1356  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1357  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1358  :( UPP ? max(i1,jj) : jj ) );
1359  const size_t jend( ( IsLower_v<MT5> )
1360  ?( ( LOW )
1361  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1362  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1363  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1364 
1365  if( jbegin >= jend )
1366  continue;
1367 
1368  for( size_t j=jbegin; j<jend; ++j ) {
1369  C(i1,j) -= element->value() * B(i,j);
1370  }
1371  }
1372  }
1373  }
1374  }
1375  }
1377  //**********************************************************************************************
1378 
1379  //**Default subtraction assignment to dense matrices (small matrices)***************************
1393  template< typename MT3 // Type of the left-hand side target matrix
1394  , typename MT4 // Type of the left-hand side matrix operand
1395  , typename MT5 > // Type of the right-hand side matrix operand
1396  static inline auto selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1397  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1398  {
1399  selectDefaultSubAssignKernel( C, A, B );
1400  }
1402  //**********************************************************************************************
1403 
1404  //**Optimized subtraction assignment to dense matrices (small matrices)*************************
1419  template< typename MT3 // Type of the left-hand side target matrix
1420  , typename MT4 // Type of the left-hand side matrix operand
1421  , typename MT5 > // Type of the right-hand side matrix operand
1422  static inline auto selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1423  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1424  {
1425  const size_t block( IsRowMajorMatrix_v<MT3> ? 128UL : 64UL );
1426 
1427  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1428  {
1429  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1430 
1431  for( size_t i=0UL; i<A.columns(); ++i )
1432  {
1433  const auto end( A.end(i) );
1434  auto element( A.begin(i) );
1435 
1436  const size_t nonzeros( A.nonZeros(i) );
1437  const size_t kpos( nonzeros & size_t(-4) );
1438  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1439 
1440  for( size_t k=0UL; k<kpos; k+=4UL )
1441  {
1442  const size_t i1( element->index() );
1443  const ET1 v1( element->value() );
1444  ++element;
1445  const size_t i2( element->index() );
1446  const ET1 v2( element->value() );
1447  ++element;
1448  const size_t i3( element->index() );
1449  const ET1 v3( element->value() );
1450  ++element;
1451  const size_t i4( element->index() );
1452  const ET1 v4( element->value() );
1453  ++element;
1454 
1455  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1456 
1457  const size_t jbegin( ( IsUpper_v<MT5> )
1458  ?( ( UPP )
1459  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1460  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1461  :( UPP ? max(i1,jj) : jj ) );
1462  const size_t jend( ( IsLower_v<MT5> )
1463  ?( ( LOW )
1464  ?( min( i4+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1465  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1466  :( LOW ? min(i4+1UL,jpos) : jpos ) );
1467 
1468  if( jbegin >= jend )
1469  continue;
1470 
1471  for( size_t j=jbegin; j<jend; ++j ) {
1472  C(i1,j) -= v1 * B(i,j);
1473  C(i2,j) -= v2 * B(i,j);
1474  C(i3,j) -= v3 * B(i,j);
1475  C(i4,j) -= v4 * B(i,j);
1476  }
1477  }
1478 
1479  for( ; element!=end; ++element )
1480  {
1481  const size_t i1( element->index() );
1482 
1483  const size_t jbegin( ( IsUpper_v<MT5> )
1484  ?( ( UPP )
1485  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1486  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1487  :( UPP ? max(i1,jj) : jj ) );
1488  const size_t jend( ( IsLower_v<MT5> )
1489  ?( ( LOW )
1490  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1491  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1492  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1493 
1494  if( jbegin >= jend )
1495  continue;
1496 
1497  for( size_t j=jbegin; j<jend; ++j ) {
1498  C(i1,j) -= element->value() * B(i,j);
1499  }
1500  }
1501  }
1502  }
1503  }
1505  //**********************************************************************************************
1506 
1507  //**Default subtraction assignment to dense matrices (large matrices)***************************
1521  template< typename MT3 // Type of the left-hand side target matrix
1522  , typename MT4 // Type of the left-hand side matrix operand
1523  , typename MT5 > // Type of the right-hand side matrix operand
1524  static inline auto selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1525  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1526  {
1527  selectDefaultSubAssignKernel( C, A, B );
1528  }
1530  //**********************************************************************************************
1531 
1532  //**Optimized subtraction assignment to dense matrices (large matrices)*************************
1547  template< typename MT3 // Type of the left-hand side target matrix
1548  , typename MT4 // Type of the left-hand side matrix operand
1549  , typename MT5 > // Type of the right-hand side matrix operand
1550  static inline auto selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1551  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1552  {
1553  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_t<MT4> );
1554 
1555  const ForwardFunctor fwd;
1556 
1557  const OppositeType_t<MT4> tmp( serial( A ) );
1558  subAssign( C, fwd( tmp * B ) );
1559  }
1561  //**********************************************************************************************
1562 
1563  //**Restructuring subtraction assignment********************************************************
1578  template< typename MT // Type of the target matrix
1579  , bool SO > // Storage order of the target matrix
1580  friend inline auto subAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1581  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1582  {
1584 
1586 
1587  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1588  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1589 
1590  const ForwardFunctor fwd;
1591 
1592  if( IsSymmetric_v<MT1> && IsSymmetric_v<MT2> )
1593  subAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1594  else if( IsSymmetric_v<MT1> )
1595  subAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1596  else
1597  subAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1598  }
1600  //**********************************************************************************************
1601 
1602  //**Subtraction assignment to sparse matrices***************************************************
1603  // No special implementation for the subtraction assignment to sparse matrices.
1604  //**********************************************************************************************
1605 
1606  //**Schur product assignment to dense matrices**************************************************
1619  template< typename MT // Type of the target dense matrix
1620  , bool SO > // Storage order of the target dense matrix
1621  friend inline void schurAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1622  {
1624 
1628 
1629  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1630  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1631 
1632  const ResultType tmp( serial( rhs ) );
1633  schurAssign( ~lhs, tmp );
1634  }
1636  //**********************************************************************************************
1637 
1638  //**Schur product assignment to sparse matrices*************************************************
1639  // No special implementation for the Schur product assignment to sparse matrices.
1640  //**********************************************************************************************
1641 
1642  //**Multiplication assignment to dense matrices*************************************************
1643  // No special implementation for the multiplication assignment to dense matrices.
1644  //**********************************************************************************************
1645 
1646  //**Multiplication assignment to sparse matrices************************************************
1647  // No special implementation for the multiplication assignment to sparse matrices.
1648  //**********************************************************************************************
1649 
1650  //**SMP assignment to dense matrices************************************************************
1666  template< typename MT // Type of the target dense matrix
1667  , bool SO > // Storage order of the target dense matrix
1668  friend inline auto smpAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1669  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1670  {
1672 
1673  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1674  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1675 
1676  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1677  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1678 
1679  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1680  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1681  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1682  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1683  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1684  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1685 
1686  smpAssign( ~lhs, A * B );
1687  }
1689  //**********************************************************************************************
1690 
1691  //**SMP assignment to sparse matrices***********************************************************
1707  template< typename MT // Type of the target sparse matrix
1708  , bool SO > // Storage order of the target sparse matrix
1709  friend inline auto smpAssign( SparseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1710  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1711  {
1713 
1714  using TmpType = If_t< SO, ResultType, OppositeType >;
1715 
1722 
1723  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1724  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1725 
1726  const ForwardFunctor fwd;
1727 
1728  const TmpType tmp( rhs );
1729  smpAssign( ~lhs, fwd( tmp ) );
1730  }
1732  //**********************************************************************************************
1733 
1734  //**Restructuring SMP assignment****************************************************************
1749  template< typename MT // Type of the target matrix
1750  , bool SO > // Storage order of the target matrix
1751  friend inline auto smpAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1752  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1753  {
1755 
1757 
1758  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1759  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1760 
1761  const ForwardFunctor fwd;
1762 
1763  if( IsSymmetric_v<MT1> && IsSymmetric_v<MT2> )
1764  smpAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1765  else if( IsSymmetric_v<MT1> )
1766  smpAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1767  else
1768  smpAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1769  }
1771  //**********************************************************************************************
1772 
1773  //**SMP addition assignment to dense matrices***************************************************
1789  template< typename MT // Type of the target dense matrix
1790  , bool SO > // Storage order of the target dense matrix
1791  friend inline auto smpAddAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1792  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1793  {
1795 
1796  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1797  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1798 
1799  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1800  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1801 
1802  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1803  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1804  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1805  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1806  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1807  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1808 
1809  smpAddAssign( ~lhs, A * B );
1810  }
1812  //**********************************************************************************************
1813 
1814  //**Restructuring SMP addition assignment*******************************************************
1829  template< typename MT // Type of the target matrix
1830  , bool SO > // Storage order of the target matrix
1831  friend inline auto smpAddAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1832  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1833  {
1835 
1837 
1838  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1839  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1840 
1841  const ForwardFunctor fwd;
1842 
1843  if( IsSymmetric_v<MT1> && IsSymmetric_v<MT2> )
1844  smpAddAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1845  else if( IsSymmetric_v<MT1> )
1846  smpAddAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1847  else
1848  smpAddAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1849  }
1851  //**********************************************************************************************
1852 
1853  //**SMP addition assignment to sparse matrices**************************************************
1854  // No special implementation for the SMP addition assignment to sparse matrices.
1855  //**********************************************************************************************
1856 
1857  //**SMP subtraction assignment to dense matrices************************************************
1873  template< typename MT // Type of the target dense matrix
1874  , bool SO > // Storage order of the target dense matrix
1875  friend inline auto smpSubAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1876  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1877  {
1879 
1880  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1881  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1882 
1883  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1884  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1885 
1886  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1887  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1888  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1889  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1890  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1891  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1892 
1893  smpSubAssign( ~lhs, A * B );
1894  }
1896  //**********************************************************************************************
1897 
1898  //**Restructuring SMP subtraction assignment****************************************************
1913  template< typename MT // Type of the target matrix
1914  , bool SO > // Storage order of the target matrix
1915  friend inline auto smpSubAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1916  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1917  {
1919 
1921 
1922  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1923  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1924 
1925  const ForwardFunctor fwd;
1926 
1927  if( IsSymmetric_v<MT1> && IsSymmetric_v<MT2> )
1928  smpSubAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1929  else if( IsSymmetric_v<MT1> )
1930  smpSubAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1931  else
1932  smpSubAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1933  }
1935  //**********************************************************************************************
1936 
1937  //**SMP subtraction assignment to sparse matrices***********************************************
1938  // No special implementation for the SMP subtraction assignment to sparse matrices.
1939  //**********************************************************************************************
1940 
1941  //**SMP Schur product assignment to dense matrices**********************************************
1954  template< typename MT // Type of the target dense matrix
1955  , bool SO > // Storage order of the target dense matrix
1956  friend inline void smpSchurAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1957  {
1959 
1963 
1964  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1965  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1966 
1967  const ResultType tmp( rhs );
1968  smpSchurAssign( ~lhs, tmp );
1969  }
1971  //**********************************************************************************************
1972 
1973  //**SMP Schur product assignment to sparse matrices*********************************************
1974  // No special implementation for the SMP Schur product assignment to sparse matrices.
1975  //**********************************************************************************************
1976 
1977  //**SMP multiplication assignment to dense matrices*********************************************
1978  // No special implementation for the SMP multiplication assignment to dense matrices.
1979  //**********************************************************************************************
1980 
1981  //**SMP multiplication assignment to sparse matrices********************************************
1982  // No special implementation for the SMP multiplication assignment to sparse matrices.
1983  //**********************************************************************************************
1984 
1985  //**Compile time checks*************************************************************************
1994  //**********************************************************************************************
1995 };
1996 //*************************************************************************************************
1997 
1998 
1999 
2000 
2001 //=================================================================================================
2002 //
2003 // GLOBAL BINARY ARITHMETIC OPERATORS
2004 //
2005 //=================================================================================================
2006 
2007 //*************************************************************************************************
2020 template< typename MT1 // Type of the left-hand side dense matrix
2021  , typename MT2 // Type of the right-hand side sparse matrix
2022  , DisableIf_t< ( IsIdentity_v<MT1> &&
2023  IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > ) ||
2024  IsZero_v<MT1> >* = nullptr >
2025 inline const TSMatTDMatMultExpr<MT1,MT2,false,false,false,false>
2026  tsmattdmatmult( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,true>& rhs )
2027 {
2029 
2030  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).rows(), "Invalid matrix sizes" );
2031 
2032  return TSMatTDMatMultExpr<MT1,MT2,false,false,false,false>( ~lhs, ~rhs );
2033 }
2035 //*************************************************************************************************
2036 
2037 
2038 //*************************************************************************************************
2052 template< typename MT1 // Type of the left-hand side sparse matrix
2053  , typename MT2 // Type of the right-hand side dense matrix
2054  , EnableIf_t< IsIdentity_v<MT1> &&
2055  IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > >* = nullptr >
2056 inline const MT2&
2057  tsmattdmatmult( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,true>& rhs )
2058 {
2060 
2061  UNUSED_PARAMETER( lhs );
2062 
2063  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).rows(), "Invalid matrix sizes" );
2064 
2065  return (~rhs);
2066 }
2068 //*************************************************************************************************
2069 
2070 
2071 //*************************************************************************************************
2084 template< typename MT1 // Type of the left-hand side dense matrix
2085  , typename MT2 // Type of the right-hand side sparse matrix
2086  , EnableIf_t< IsZero_v<MT1> >* = nullptr >
2087 inline decltype(auto)
2088  tsmattdmatmult( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,true>& rhs )
2089 {
2091 
2092  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).rows(), "Invalid matrix sizes" );
2093 
2094  using ReturnType = const MultTrait_t< ResultType_t<MT1>, ResultType_t<MT2> >;
2095 
2098 
2099  return ReturnType( (~lhs).rows(), (~rhs).columns() );
2100 }
2102 //*************************************************************************************************
2103 
2104 
2105 //*************************************************************************************************
2134 template< typename MT1 // Type of the left-hand side sparse matrix
2135  , typename MT2 > // Type of the right-hand side dense matrix
2136 inline decltype(auto)
2137  operator*( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,true>& rhs )
2138 {
2140 
2141  if( (~lhs).columns() != (~rhs).rows() ) {
2142  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
2143  }
2144 
2145  return tsmattdmatmult( ~lhs, ~rhs );
2146 }
2147 //*************************************************************************************************
2148 
2149 
2150 
2151 
2152 //=================================================================================================
2153 //
2154 // GLOBAL FUNCTIONS
2155 //
2156 //=================================================================================================
2157 
2158 //*************************************************************************************************
2182 template< typename MT1 // Type of the left-hand side dense matrix
2183  , typename MT2 // Type of the right-hand side dense matrix
2184  , bool SF // Symmetry flag
2185  , bool HF // Hermitian flag
2186  , bool LF // Lower flag
2187  , bool UF > // Upper flag
2188 inline decltype(auto) declsym( const TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2189 {
2191 
2192  if( !isSquare( dm ) ) {
2193  BLAZE_THROW_INVALID_ARGUMENT( "Invalid symmetric matrix specification" );
2194  }
2195 
2196  using ReturnType = const TSMatTDMatMultExpr<MT1,MT2,true,HF,LF,UF>;
2197  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2198 }
2200 //*************************************************************************************************
2201 
2202 
2203 //*************************************************************************************************
2227 template< typename MT1 // Type of the left-hand side dense matrix
2228  , typename MT2 // Type of the right-hand side dense matrix
2229  , bool SF // Symmetry flag
2230  , bool HF // Hermitian flag
2231  , bool LF // Lower flag
2232  , bool UF > // Upper flag
2233 inline decltype(auto) declherm( const TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2234 {
2236 
2237  if( !isSquare( dm ) ) {
2238  BLAZE_THROW_INVALID_ARGUMENT( "Invalid Hermitian matrix specification" );
2239  }
2240 
2241  using ReturnType = const TSMatTDMatMultExpr<MT1,MT2,SF,true,LF,UF>;
2242  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2243 }
2245 //*************************************************************************************************
2246 
2247 
2248 //*************************************************************************************************
2272 template< typename MT1 // Type of the left-hand side dense matrix
2273  , typename MT2 // Type of the right-hand side dense matrix
2274  , bool SF // Symmetry flag
2275  , bool HF // Hermitian flag
2276  , bool LF // Lower flag
2277  , bool UF > // Upper flag
2278 inline decltype(auto) decllow( const TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2279 {
2281 
2282  if( !isSquare( dm ) ) {
2283  BLAZE_THROW_INVALID_ARGUMENT( "Invalid lower matrix specification" );
2284  }
2285 
2286  using ReturnType = const TSMatTDMatMultExpr<MT1,MT2,SF,HF,true,UF>;
2287  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2288 }
2290 //*************************************************************************************************
2291 
2292 
2293 //*************************************************************************************************
2317 template< typename MT1 // Type of the left-hand side dense matrix
2318  , typename MT2 // Type of the right-hand side dense matrix
2319  , bool SF // Symmetry flag
2320  , bool HF // Hermitian flag
2321  , bool LF // Lower flag
2322  , bool UF > // Upper flag
2323 inline decltype(auto) declupp( const TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2324 {
2326 
2327  if( !isSquare( dm ) ) {
2328  BLAZE_THROW_INVALID_ARGUMENT( "Invalid upper matrix specification" );
2329  }
2330 
2331  using ReturnType = const TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,true>;
2332  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2333 }
2335 //*************************************************************************************************
2336 
2337 
2338 //*************************************************************************************************
2362 template< typename MT1 // Type of the left-hand side dense matrix
2363  , typename MT2 // Type of the right-hand side dense matrix
2364  , bool SF // Symmetry flag
2365  , bool HF // Hermitian flag
2366  , bool LF // Lower flag
2367  , bool UF > // Upper flag
2368 inline decltype(auto) decldiag( const TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2369 {
2371 
2372  if( !isSquare( dm ) ) {
2373  BLAZE_THROW_INVALID_ARGUMENT( "Invalid diagonal matrix specification" );
2374  }
2375 
2376  using ReturnType = const TSMatTDMatMultExpr<MT1,MT2,SF,HF,true,true>;
2377  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2378 }
2380 //*************************************************************************************************
2381 
2382 
2383 
2384 
2385 //=================================================================================================
2386 //
2387 // SIZE SPECIALIZATIONS
2388 //
2389 //=================================================================================================
2390 
2391 //*************************************************************************************************
2393 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2394 struct Size< TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 0UL >
2395  : public Size<MT1,0UL>
2396 {};
2397 
2398 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2399 struct Size< TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 1UL >
2400  : public Size<MT2,1UL>
2401 {};
2403 //*************************************************************************************************
2404 
2405 
2406 
2407 
2408 //=================================================================================================
2409 //
2410 // ISALIGNED SPECIALIZATIONS
2411 //
2412 //=================================================================================================
2413 
2414 //*************************************************************************************************
2416 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2417 struct IsAligned< TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2418  : public IsAligned<MT2>
2419 {};
2421 //*************************************************************************************************
2422 
2423 } // namespace blaze
2424 
2425 #endif
decltype(auto) subvector(Vector< VT, TF > &, RSAs...)
Creating a view on a specific subvector of the given vector.
Definition: Subvector.h:329
ResultType_t< MT2 > RT2
Result type of the right-hand side dense matrix expression.
Definition: TSMatTDMatMultExpr.h:134
If_t< evaluateRight, const RT2, CT2 > RT
Type for the assignment of the right-hand side dense matrix operand.
Definition: TSMatTDMatMultExpr.h:262
#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.
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: TSMatTDMatMultExpr.h:434
decltype(auto) decldiag(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as diagonal.
Definition: DMatDeclDiagExpr.h:975
Header file for basic type definitions.
Expression object for transpose sparse matrix-transpose dense matrix multiplications.The TSMatTDMatMultExpr class represents the compile time expression for multiplications between a column-major sparse matrix and a column-major dense matrix.
Definition: Forward.h:177
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
static constexpr bool LOW
Flag for lower matrices.
Definition: TSMatTDMatMultExpr.h:154
Header file for the serial shim.
static constexpr bool evaluateLeft
Compilation switch for the composite type of the left-hand side sparse matrix expression.
Definition: TSMatTDMatMultExpr.h:143
Header file for the IsDiagonal type trait.
Base template for the DeclUppTrait class.
Definition: DeclUppTrait.h:134
CompositeType_t< MT1 > CT1
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatTDMatMultExpr.h:137
#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
bool isAligned() const noexcept
Returns whether the operands of the expression are properly aligned in memory.
Definition: TSMatTDMatMultExpr.h:424
Header file for the DeclUpp functor.
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: TSMatTDMatMultExpr.h:414
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.
decltype(auto) declupp(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as upper.
Definition: DMatDeclUppExpr.h:1002
Header file for the Computation base class.
Header file for the MatMatMultExpr base class.
Header file for the reset shim.
Constraints on the storage order of matrix types.
static constexpr bool simdEnabled
Compilation switch for the expression template evaluation strategy.
Definition: TSMatTDMatMultExpr.h:267
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
constexpr size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:514
RightOperand rhs_
Right-hand side dense matrix of the multiplication expression.
Definition: TSMatTDMatMultExpr.h:442
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:80
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
const ResultType CompositeType
Data type for composite expression templates.
Definition: TSMatTDMatMultExpr.h:250
Constraint on the data type.
Constraint on the data type.
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: TSMatTDMatMultExpr.h:402
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.
static constexpr bool smpAssignable
Compilation switch for the expression template assignment strategy.
Definition: TSMatTDMatMultExpr.h:270
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
If_t< IsExpression_v< MT1 >, const MT1, const MT1 &> LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatTDMatMultExpr.h:253
#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
static constexpr bool UPP
Flag for upper matrices.
Definition: TSMatTDMatMultExpr.h:155
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
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: TSMatTDMatMultExpr.h:295
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.
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: TSMatTDMatMultExpr.h:441
If_t< evaluateLeft, const RT1, CT1 > LT
Type for the assignment of the left-hand side sparse matrix operand.
Definition: TSMatTDMatMultExpr.h:259
static constexpr bool evaluateRight
Compilation switch for the composite type of the right-hand side dense matrix expression.
Definition: TSMatTDMatMultExpr.h:148
TSMatTDMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the TSMatTDMatMultExpr class.
Definition: TSMatTDMatMultExpr.h:280
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.
ResultType_t< MT1 > RT1
Result type of the left-hand side sparse matrix expression.
Definition: TSMatTDMatMultExpr.h:133
static constexpr bool SYM
Flag for symmetric matrices.
Definition: TSMatTDMatMultExpr.h:152
Generic wrapper for the null function.
Definition: Noop.h:59
Header file for the IsTriangular type trait.
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: TSMatTDMatMultExpr.h:360
Base template for the DeclSymTrait class.
Definition: DeclSymTrait.h:134
LeftOperand leftOperand() const noexcept
Returns the left-hand side transpose sparse matrix operand.
Definition: TSMatTDMatMultExpr.h:380
Constraints on the storage order of matrix types.
ElementType_t< RT1 > ET1
Element type of the left-hand side dense matrix expression.
Definition: TSMatTDMatMultExpr.h:135
Header file for the exception macros of the math module.
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: TSMatTDMatMultExpr.h:244
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.
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TSMatTDMatMultExpr.h:249
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
TransposeType_t< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: TSMatTDMatMultExpr.h:247
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.
#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
CompositeType_t< MT2 > CT2
Composite type of the right-hand side dense matrix expression.
Definition: TSMatTDMatMultExpr.h:138
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
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
OppositeType_t< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: TSMatTDMatMultExpr.h:246
decltype(auto) row(Matrix< MT, SO > &, RRAs...)
Creating a view on a specific row of the given matrix.
Definition: Row.h:133
Header file for the IsZero type trait.
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
ElementType_t< ResultType > ElementType
Resulting element type.
Definition: TSMatTDMatMultExpr.h:248
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
ElementType_t< RT2 > ET2
Element type of the right-hand side sparse matrix expression.
Definition: TSMatTDMatMultExpr.h:136
static constexpr bool HERM
Flag for Hermitian matrices.
Definition: TSMatTDMatMultExpr.h:153
#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 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
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.
RightOperand rightOperand() const noexcept
Returns the right-hand side transpose dense matrix operand.
Definition: TSMatTDMatMultExpr.h:390
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
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: TSMatTDMatMultExpr.h:370
If_t< IsExpression_v< MT2 >, const MT2, const MT2 &> RightOperand
Composite type of the right-hand side dense matrix expression.
Definition: TSMatTDMatMultExpr.h:256
Header file for the IntegralConstant class template.
Generic wrapper for the decldiag() function.
Definition: DeclDiag.h:58
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
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.
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: TSMatTDMatMultExpr.h:344