Blaze  3.6
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/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 TSMatTDMatMultExpr
129  : public MatMatMultExpr< DenseMatrix< TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, true > >
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> || IsSymmetric_v<T3> );
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 TSMatTDMatMultExpr( 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_TSMATTDMATMULT_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 TSMatTDMatMultExpr& 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  TSMatTDMatMultExpr::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 < TSMATTDMATMULT_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( 64UL );
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> ? 128UL : 64UL );
645 
646  for( size_t jj=0UL; jj<B.columns(); jj+=block )
647  {
648  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
649 
650  for( size_t i=0UL; i<A.rows(); ++i ) {
651  for( size_t j=jj; j<jpos; ++j ) {
652  reset( C(i,j) );
653  }
654  }
655 
656  for( size_t i=0UL; i<A.columns(); ++i )
657  {
658  const auto end( A.end(i) );
659  auto element( A.begin(i) );
660 
661  const size_t nonzeros( A.nonZeros(i) );
662  const size_t kpos( nonzeros & size_t(-4) );
663  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
664 
665  for( size_t k=0UL; k<kpos; k+=4UL )
666  {
667  const size_t i1( element->index() );
668  const ET1 v1( element->value() );
669  ++element;
670  const size_t i2( element->index() );
671  const ET1 v2( element->value() );
672  ++element;
673  const size_t i3( element->index() );
674  const ET1 v3( element->value() );
675  ++element;
676  const size_t i4( element->index() );
677  const ET1 v4( element->value() );
678  ++element;
679 
680  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
681 
682  const size_t jbegin( ( IsUpper_v<MT5> )
683  ?( ( SYM || HERM || UPP )
684  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
685  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
686  :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
687  const size_t jend( ( IsLower_v<MT5> )
688  ?( ( LOW )
689  ?( min( i4+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
690  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
691  :( LOW ? min(i4+1UL,jpos) : jpos ) );
692 
693  if( jbegin >= jend )
694  continue;
695 
696  for( size_t j=jbegin; j<jend; ++j ) {
697  C(i1,j) += v1 * B(i,j);
698  C(i2,j) += v2 * B(i,j);
699  C(i3,j) += v3 * B(i,j);
700  C(i4,j) += v4 * B(i,j);
701  }
702  }
703 
704  for( ; element!=end; ++element )
705  {
706  const size_t i1( element->index() );
707 
708  const size_t jbegin( ( IsUpper_v<MT5> )
709  ?( ( SYM || HERM || UPP )
710  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
711  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
712  :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
713  const size_t jend( ( IsLower_v<MT5> )
714  ?( ( LOW )
715  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
716  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
717  :( LOW ? min(i1+1UL,jpos) : jpos ) );
718 
719  if( jbegin >= jend )
720  continue;
721 
722  for( size_t j=jbegin; j<jend; ++j ) {
723  C(i1,j) += element->value() * B(i,j);
724  }
725  }
726  }
727  }
728 
729  if( SYM || HERM ) {
730  for( size_t j=0UL; j<B.columns(); ++j ) {
731  for( size_t i=j+1UL; i<A.rows(); ++i ) {
732  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
733  }
734  }
735  }
736  }
738  //**********************************************************************************************
739 
740  //**Default assignment to dense matrices (large matrices)***************************************
754  template< typename MT3 // Type of the left-hand side target matrix
755  , typename MT4 // Type of the left-hand side matrix operand
756  , typename MT5 > // Type of the right-hand side matrix operand
757  static inline auto selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
758  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
759  {
760  selectDefaultAssignKernel( C, A, B );
761  }
763  //**********************************************************************************************
764 
765  //**Optimized assignment to dense matrices (large matrices)*************************************
780  template< typename MT3 // Type of the left-hand side target matrix
781  , typename MT4 // Type of the left-hand side matrix operand
782  , typename MT5 > // Type of the right-hand side matrix operand
783  static inline auto selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
784  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
785  {
786  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_t<MT4> );
787 
788  const ForwardFunctor fwd;
789 
790  const OppositeType_t<MT4> tmp( serial( A ) );
791  assign( C, fwd( tmp * B ) );
792  }
794  //**********************************************************************************************
795 
796  //**Assignment to sparse matrices***************************************************************
809  template< typename MT // Type of the target sparse matrix
810  , bool SO > // Storage order of the target sparse matrix
811  friend inline auto assign( SparseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
812  -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
813  {
815 
816  using TmpType = If_t< SO, ResultType, OppositeType >;
817 
824 
825  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
826  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
827 
828  const ForwardFunctor fwd;
829 
830  const TmpType tmp( serial( rhs ) );
831  assign( ~lhs, fwd( tmp ) );
832  }
834  //**********************************************************************************************
835 
836  //**Restructuring assignment********************************************************************
851  template< typename MT // Type of the target matrix
852  , bool SO > // Storage order of the target matrix
853  friend inline auto assign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
854  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
855  {
857 
859 
860  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
861  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
862 
863  const ForwardFunctor fwd;
864 
865  if( IsSymmetric_v<MT1> && IsSymmetric_v<MT2> )
866  assign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
867  else if( IsSymmetric_v<MT1> )
868  assign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
869  else
870  assign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
871  }
873  //**********************************************************************************************
874 
875  //**Addition assignment to dense matrices*******************************************************
888  template< typename MT // Type of the target dense matrix
889  , bool SO > // Storage order of the target dense matrix
890  friend inline auto addAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
891  -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
892  {
894 
895  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
896  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
897 
898  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
899  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
900 
901  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
902  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
903  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
904  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
905  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
906  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
907 
908  TSMatTDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
909  }
911  //**********************************************************************************************
912 
913  //**Addition assignment to dense matrices (kernel selection)************************************
924  template< typename MT3 // Type of the left-hand side target matrix
925  , typename MT4 // Type of the left-hand side matrix operand
926  , typename MT5 > // Type of the right-hand side matrix operand
927  static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
928  {
929  const size_t size( C.rows() * C.columns() );
930 
931  if( ( IsRowMajorMatrix_v<MT3> && size < TSMATTDMATMULT_THRESHOLD ) ||
932  ( IsColumnMajorMatrix_v<MT3> && size < 625UL ) )
933  selectSmallAddAssignKernel( C, A, B );
934  else
935  selectLargeAddAssignKernel( C, A, B );
936  }
938  //**********************************************************************************************
939 
940  //**Default addition assignment to dense matrices***********************************************
955  template< typename MT3 // Type of the left-hand side target matrix
956  , typename MT4 // Type of the left-hand side matrix operand
957  , typename MT5 > // Type of the right-hand side matrix operand
958  static inline void selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
959  {
960  if( IsDiagonal_v<MT5> )
961  {
962  for( size_t i=0UL; i<A.columns(); ++i )
963  {
964  const auto end( A.end(i) );
965  auto element( A.begin(i) );
966 
967  for( ; element!=end; ++element ) {
968  C(element->index(),i) += element->value() * B(i,i);
969  }
970  }
971  }
972  else
973  {
974  const size_t block( 64UL );
975 
976  for( size_t jj=0UL; jj<B.columns(); jj+=block )
977  {
978  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
979 
980  for( size_t i=0UL; i<A.columns(); ++i )
981  {
982  const auto end( A.end(i) );
983  auto element( A.begin(i) );
984 
985  for( ; element!=end; ++element )
986  {
987  const size_t i1( element->index() );
988 
989  const size_t jbegin( ( IsUpper_v<MT5> )
990  ?( ( UPP )
991  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
992  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
993  :( UPP ? max(i1,jj) : jj ) );
994  const size_t jend( ( IsLower_v<MT5> )
995  ?( ( LOW )
996  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
997  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
998  :( LOW ? min(i1+1UL,jpos) : jpos ) );
999 
1000  if( jbegin >= jend )
1001  continue;
1002 
1003  for( size_t j=jbegin; j<jend; ++j ) {
1004  C(i1,j) += element->value() * B(i,j);
1005  }
1006  }
1007  }
1008  }
1009  }
1010  }
1012  //**********************************************************************************************
1013 
1014  //**Default addition assignment to dense matrices (small matrices)******************************
1028  template< typename MT3 // Type of the left-hand side target matrix
1029  , typename MT4 // Type of the left-hand side matrix operand
1030  , typename MT5 > // Type of the right-hand side matrix operand
1031  static inline auto selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1032  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1033  {
1034  selectDefaultAddAssignKernel( C, A, B );
1035  }
1037  //**********************************************************************************************
1038 
1039  //**Optimized addition assignment to dense matrices (small matrices)****************************
1054  template< typename MT3 // Type of the left-hand side target matrix
1055  , typename MT4 // Type of the left-hand side matrix operand
1056  , typename MT5 > // Type of the right-hand side matrix operand
1057  static inline auto selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1058  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1059  {
1060  const size_t block( IsRowMajorMatrix_v<MT3> ? 128UL : 64UL );
1061 
1062  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1063  {
1064  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1065 
1066  for( size_t i=0UL; i<A.columns(); ++i )
1067  {
1068  const auto end( A.end(i) );
1069  auto element( A.begin(i) );
1070 
1071  const size_t nonzeros( A.nonZeros(i) );
1072  const size_t kpos( nonzeros & size_t(-4) );
1073  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1074 
1075  for( size_t k=0UL; k<kpos; k+=4UL )
1076  {
1077  const size_t i1( element->index() );
1078  const ET1 v1( element->value() );
1079  ++element;
1080  const size_t i2( element->index() );
1081  const ET1 v2( element->value() );
1082  ++element;
1083  const size_t i3( element->index() );
1084  const ET1 v3( element->value() );
1085  ++element;
1086  const size_t i4( element->index() );
1087  const ET1 v4( element->value() );
1088  ++element;
1089 
1090  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1091 
1092  const size_t jbegin( ( IsUpper_v<MT5> )
1093  ?( ( UPP )
1094  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1095  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1096  :( UPP ? max(i1,jj) : jj ) );
1097  const size_t jend( ( IsLower_v<MT5> )
1098  ?( ( LOW )
1099  ?( min( i4+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1100  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1101  :( LOW ? min(i4+1UL,jpos) : jpos ) );
1102 
1103  if( jbegin >= jend )
1104  continue;
1105 
1106  for( size_t j=jbegin; j<jend; ++j ) {
1107  C(i1,j) += v1 * B(i,j);
1108  C(i2,j) += v2 * B(i,j);
1109  C(i3,j) += v3 * B(i,j);
1110  C(i4,j) += v4 * B(i,j);
1111  }
1112  }
1113 
1114  for( ; element!=end; ++element )
1115  {
1116  const size_t i1( element->index() );
1117 
1118  const size_t jbegin( ( IsUpper_v<MT5> )
1119  ?( ( UPP )
1120  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1121  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1122  :( UPP ? max(i1,jj) : jj ) );
1123  const size_t jend( ( IsLower_v<MT5> )
1124  ?( ( LOW )
1125  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1126  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1127  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1128 
1129  if( jbegin >= jend )
1130  continue;
1131 
1132  for( size_t j=jbegin; j<jend; ++j ) {
1133  C(i1,j) += element->value() * B(i,j);
1134  }
1135  }
1136  }
1137  }
1138  }
1140  //**********************************************************************************************
1141 
1142  //**Default addition assignment to dense matrices (large matrices)******************************
1156  template< typename MT3 // Type of the left-hand side target matrix
1157  , typename MT4 // Type of the left-hand side matrix operand
1158  , typename MT5 > // Type of the right-hand side matrix operand
1159  static inline auto selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1160  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1161  {
1162  selectDefaultAddAssignKernel( C, A, B );
1163  }
1165  //**********************************************************************************************
1166 
1167  //**Optimized addition assignment to dense matrices (large matrices)****************************
1182  template< typename MT3 // Type of the left-hand side target matrix
1183  , typename MT4 // Type of the left-hand side matrix operand
1184  , typename MT5 > // Type of the right-hand side matrix operand
1185  static inline auto selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1186  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1187  {
1188  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_t<MT4> );
1189 
1190  const ForwardFunctor fwd;
1191 
1192  const OppositeType_t<MT4> tmp( serial( A ) );
1193  addAssign( C, fwd( tmp * B ) );
1194  }
1196  //**********************************************************************************************
1197 
1198  //**Restructuring addition assignment***********************************************************
1213  template< typename MT // Type of the target matrix
1214  , bool SO > // Storage order of the target matrix
1215  friend inline auto addAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1216  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1217  {
1219 
1221 
1222  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1223  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1224 
1225  const ForwardFunctor fwd;
1226 
1227  if( IsSymmetric_v<MT1> && IsSymmetric_v<MT2> )
1228  addAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1229  else if( IsSymmetric_v<MT1> )
1230  addAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1231  else
1232  addAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1233  }
1235  //**********************************************************************************************
1236 
1237  //**Addition assignment to sparse matrices******************************************************
1238  // No special implementation for the addition assignment to sparse matrices.
1239  //**********************************************************************************************
1240 
1241  //**Subtraction assignment to dense matrices****************************************************
1254  template< typename MT // Type of the target dense matrix
1255  , bool SO > // Storage order of the target dense matrix
1256  friend inline auto subAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1257  -> DisableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1258  {
1260 
1261  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1262  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1263 
1264  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1265  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1266 
1267  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1268  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1269  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1270  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1271  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1272  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1273 
1274  TSMatTDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1275  }
1277  //**********************************************************************************************
1278 
1279  //**Subtraction assignment to dense matrices (kernel selection)*********************************
1290  template< typename MT3 // Type of the left-hand side target matrix
1291  , typename MT4 // Type of the left-hand side matrix operand
1292  , typename MT5 > // Type of the right-hand side matrix operand
1293  static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1294  {
1295  const size_t size( C.rows() * C.columns() );
1296 
1297  if( ( IsRowMajorMatrix_v<MT3> && size < TSMATTDMATMULT_THRESHOLD ) ||
1298  ( IsColumnMajorMatrix_v<MT3> && size < 625UL ) )
1299  selectSmallSubAssignKernel( C, A, B );
1300  else
1301  selectLargeSubAssignKernel( C, A, B );
1302  }
1304  //**********************************************************************************************
1305 
1306  //**Default subtraction assignment to dense matrices********************************************
1321  template< typename MT3 // Type of the left-hand side target matrix
1322  , typename MT4 // Type of the left-hand side matrix operand
1323  , typename MT5 > // Type of the right-hand side matrix operand
1324  static inline void selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1325  {
1326  if( IsDiagonal_v<MT5> )
1327  {
1328  for( size_t i=0UL; i<A.columns(); ++i )
1329  {
1330  const auto end( A.end(i) );
1331  auto element( A.begin(i) );
1332 
1333  for( ; element!=end; ++element ) {
1334  C(element->index(),i) -= element->value() * B(i,i);
1335  }
1336  }
1337  }
1338  else
1339  {
1340  const size_t block( 64UL );
1341 
1342  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1343  {
1344  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1345 
1346  for( size_t i=0UL; i<A.columns(); ++i )
1347  {
1348  const auto end( A.end(i) );
1349  auto element( A.begin(i) );
1350 
1351  for( ; element!=end; ++element )
1352  {
1353  const size_t i1( element->index() );
1354 
1355  const size_t jbegin( ( IsUpper_v<MT5> )
1356  ?( ( UPP )
1357  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1358  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1359  :( UPP ? max(i1,jj) : jj ) );
1360  const size_t jend( ( IsLower_v<MT5> )
1361  ?( ( LOW )
1362  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1363  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1364  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1365 
1366  if( jbegin >= jend )
1367  continue;
1368 
1369  for( size_t j=jbegin; j<jend; ++j ) {
1370  C(i1,j) -= element->value() * B(i,j);
1371  }
1372  }
1373  }
1374  }
1375  }
1376  }
1378  //**********************************************************************************************
1379 
1380  //**Default subtraction assignment to dense matrices (small matrices)***************************
1394  template< typename MT3 // Type of the left-hand side target matrix
1395  , typename MT4 // Type of the left-hand side matrix operand
1396  , typename MT5 > // Type of the right-hand side matrix operand
1397  static inline auto selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1398  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1399  {
1400  selectDefaultSubAssignKernel( C, A, B );
1401  }
1403  //**********************************************************************************************
1404 
1405  //**Optimized subtraction assignment to dense matrices (small matrices)*************************
1420  template< typename MT3 // Type of the left-hand side target matrix
1421  , typename MT4 // Type of the left-hand side matrix operand
1422  , typename MT5 > // Type of the right-hand side matrix operand
1423  static inline auto selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1424  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1425  {
1426  const size_t block( IsRowMajorMatrix_v<MT3> ? 128UL : 64UL );
1427 
1428  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1429  {
1430  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1431 
1432  for( size_t i=0UL; i<A.columns(); ++i )
1433  {
1434  const auto end( A.end(i) );
1435  auto element( A.begin(i) );
1436 
1437  const size_t nonzeros( A.nonZeros(i) );
1438  const size_t kpos( nonzeros & size_t(-4) );
1439  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1440 
1441  for( size_t k=0UL; k<kpos; k+=4UL )
1442  {
1443  const size_t i1( element->index() );
1444  const ET1 v1( element->value() );
1445  ++element;
1446  const size_t i2( element->index() );
1447  const ET1 v2( element->value() );
1448  ++element;
1449  const size_t i3( element->index() );
1450  const ET1 v3( element->value() );
1451  ++element;
1452  const size_t i4( element->index() );
1453  const ET1 v4( element->value() );
1454  ++element;
1455 
1456  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1457 
1458  const size_t jbegin( ( IsUpper_v<MT5> )
1459  ?( ( UPP )
1460  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1461  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1462  :( UPP ? max(i1,jj) : jj ) );
1463  const size_t jend( ( IsLower_v<MT5> )
1464  ?( ( LOW )
1465  ?( min( i4+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1466  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1467  :( LOW ? min(i4+1UL,jpos) : jpos ) );
1468 
1469  if( jbegin >= jend )
1470  continue;
1471 
1472  for( size_t j=jbegin; j<jend; ++j ) {
1473  C(i1,j) -= v1 * B(i,j);
1474  C(i2,j) -= v2 * B(i,j);
1475  C(i3,j) -= v3 * B(i,j);
1476  C(i4,j) -= v4 * B(i,j);
1477  }
1478  }
1479 
1480  for( ; element!=end; ++element )
1481  {
1482  const size_t i1( element->index() );
1483 
1484  const size_t jbegin( ( IsUpper_v<MT5> )
1485  ?( ( UPP )
1486  ?( max( i1, IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) )
1487  :( max( IsStrictlyUpper_v<MT5> ? i+1UL : i, jj ) ) )
1488  :( UPP ? max(i1,jj) : jj ) );
1489  const size_t jend( ( IsLower_v<MT5> )
1490  ?( ( LOW )
1491  ?( min( i1+1UL, IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) )
1492  :( min( IsStrictlyLower_v<MT5> ? i : i+1UL, jpos ) ) )
1493  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1494 
1495  if( jbegin >= jend )
1496  continue;
1497 
1498  for( size_t j=jbegin; j<jend; ++j ) {
1499  C(i1,j) -= element->value() * B(i,j);
1500  }
1501  }
1502  }
1503  }
1504  }
1506  //**********************************************************************************************
1507 
1508  //**Default subtraction assignment to dense matrices (large matrices)***************************
1522  template< typename MT3 // Type of the left-hand side target matrix
1523  , typename MT4 // Type of the left-hand side matrix operand
1524  , typename MT5 > // Type of the right-hand side matrix operand
1525  static inline auto selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1526  -> EnableIf_t< UseDefaultKernel_v<MT3,MT4,MT5> >
1527  {
1528  selectDefaultSubAssignKernel( C, A, B );
1529  }
1531  //**********************************************************************************************
1532 
1533  //**Optimized subtraction assignment to dense matrices (large matrices)*************************
1548  template< typename MT3 // Type of the left-hand side target matrix
1549  , typename MT4 // Type of the left-hand side matrix operand
1550  , typename MT5 > // Type of the right-hand side matrix operand
1551  static inline auto selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1552  -> EnableIf_t< UseOptimizedKernel_v<MT3,MT4,MT5> >
1553  {
1554  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_t<MT4> );
1555 
1556  const ForwardFunctor fwd;
1557 
1558  const OppositeType_t<MT4> tmp( serial( A ) );
1559  subAssign( C, fwd( tmp * B ) );
1560  }
1562  //**********************************************************************************************
1563 
1564  //**Restructuring subtraction assignment********************************************************
1579  template< typename MT // Type of the target matrix
1580  , bool SO > // Storage order of the target matrix
1581  friend inline auto subAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1582  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1583  {
1585 
1587 
1588  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1589  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1590 
1591  const ForwardFunctor fwd;
1592 
1593  if( IsSymmetric_v<MT1> && IsSymmetric_v<MT2> )
1594  subAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1595  else if( IsSymmetric_v<MT1> )
1596  subAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1597  else
1598  subAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1599  }
1601  //**********************************************************************************************
1602 
1603  //**Subtraction assignment to sparse matrices***************************************************
1604  // No special implementation for the subtraction assignment to sparse matrices.
1605  //**********************************************************************************************
1606 
1607  //**Schur product assignment to dense matrices**************************************************
1620  template< typename MT // Type of the target dense matrix
1621  , bool SO > // Storage order of the target dense matrix
1622  friend inline void schurAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1623  {
1625 
1629 
1630  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1631  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1632 
1633  const ResultType tmp( serial( rhs ) );
1634  schurAssign( ~lhs, tmp );
1635  }
1637  //**********************************************************************************************
1638 
1639  //**Schur product assignment to sparse matrices*************************************************
1640  // No special implementation for the Schur product assignment to sparse matrices.
1641  //**********************************************************************************************
1642 
1643  //**Multiplication assignment to dense matrices*************************************************
1644  // No special implementation for the multiplication assignment to dense matrices.
1645  //**********************************************************************************************
1646 
1647  //**Multiplication assignment to sparse matrices************************************************
1648  // No special implementation for the multiplication assignment to sparse matrices.
1649  //**********************************************************************************************
1650 
1651  //**SMP assignment to dense matrices************************************************************
1667  template< typename MT // Type of the target dense matrix
1668  , bool SO > // Storage order of the target dense matrix
1669  friend inline auto smpAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1670  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1671  {
1673 
1674  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1675  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1676 
1677  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1678  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1679 
1680  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1681  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1682  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1683  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1684  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1685  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1686 
1687  smpAssign( ~lhs, A * B );
1688  }
1690  //**********************************************************************************************
1691 
1692  //**SMP assignment to sparse matrices***********************************************************
1708  template< typename MT // Type of the target sparse matrix
1709  , bool SO > // Storage order of the target sparse matrix
1710  friend inline auto smpAssign( SparseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1711  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1712  {
1714 
1715  using TmpType = If_t< SO, ResultType, OppositeType >;
1716 
1723 
1724  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1725  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1726 
1727  const ForwardFunctor fwd;
1728 
1729  const TmpType tmp( rhs );
1730  smpAssign( ~lhs, fwd( tmp ) );
1731  }
1733  //**********************************************************************************************
1734 
1735  //**Restructuring SMP assignment****************************************************************
1750  template< typename MT // Type of the target matrix
1751  , bool SO > // Storage order of the target matrix
1752  friend inline auto smpAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1753  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1754  {
1756 
1758 
1759  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1760  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1761 
1762  const ForwardFunctor fwd;
1763 
1764  if( IsSymmetric_v<MT1> && IsSymmetric_v<MT2> )
1765  smpAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1766  else if( IsSymmetric_v<MT1> )
1767  smpAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1768  else
1769  smpAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1770  }
1772  //**********************************************************************************************
1773 
1774  //**SMP addition assignment to dense matrices***************************************************
1790  template< typename MT // Type of the target dense matrix
1791  , bool SO > // Storage order of the target dense matrix
1792  friend inline auto smpAddAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1793  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1794  {
1796 
1797  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1798  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1799 
1800  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1801  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1802 
1803  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1804  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1805  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1806  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1807  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1808  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1809 
1810  smpAddAssign( ~lhs, A * B );
1811  }
1813  //**********************************************************************************************
1814 
1815  //**Restructuring SMP addition assignment*******************************************************
1830  template< typename MT // Type of the target matrix
1831  , bool SO > // Storage order of the target matrix
1832  friend inline auto smpAddAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1833  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1834  {
1836 
1838 
1839  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1840  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1841 
1842  const ForwardFunctor fwd;
1843 
1844  if( IsSymmetric_v<MT1> && IsSymmetric_v<MT2> )
1845  smpAddAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1846  else if( IsSymmetric_v<MT1> )
1847  smpAddAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1848  else
1849  smpAddAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1850  }
1852  //**********************************************************************************************
1853 
1854  //**SMP addition assignment to sparse matrices**************************************************
1855  // No special implementation for the SMP addition assignment to sparse matrices.
1856  //**********************************************************************************************
1857 
1858  //**SMP subtraction assignment to dense matrices************************************************
1874  template< typename MT // Type of the target dense matrix
1875  , bool SO > // Storage order of the target dense matrix
1876  friend inline auto smpSubAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1877  -> EnableIf_t< IsEvaluationRequired_v<MT,MT1,MT2> >
1878  {
1880 
1881  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1882  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1883 
1884  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1885  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1886 
1887  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1888  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1889  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1890  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1891  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1892  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1893 
1894  smpSubAssign( ~lhs, A * B );
1895  }
1897  //**********************************************************************************************
1898 
1899  //**Restructuring SMP subtraction assignment****************************************************
1914  template< typename MT // Type of the target matrix
1915  , bool SO > // Storage order of the target matrix
1916  friend inline auto smpSubAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1917  -> EnableIf_t< CanExploitSymmetry_v<MT,MT1,MT2> >
1918  {
1920 
1922 
1923  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1924  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1925 
1926  const ForwardFunctor fwd;
1927 
1928  if( IsSymmetric_v<MT1> && IsSymmetric_v<MT2> )
1929  smpSubAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1930  else if( IsSymmetric_v<MT1> )
1931  smpSubAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1932  else
1933  smpSubAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1934  }
1936  //**********************************************************************************************
1937 
1938  //**SMP subtraction assignment to sparse matrices***********************************************
1939  // No special implementation for the SMP subtraction assignment to sparse matrices.
1940  //**********************************************************************************************
1941 
1942  //**SMP Schur product assignment to dense matrices**********************************************
1955  template< typename MT // Type of the target dense matrix
1956  , bool SO > // Storage order of the target dense matrix
1957  friend inline void smpSchurAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1958  {
1960 
1964 
1965  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1966  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1967 
1968  const ResultType tmp( rhs );
1969  smpSchurAssign( ~lhs, tmp );
1970  }
1972  //**********************************************************************************************
1973 
1974  //**SMP Schur product assignment to sparse matrices*********************************************
1975  // No special implementation for the SMP Schur product assignment to sparse matrices.
1976  //**********************************************************************************************
1977 
1978  //**SMP multiplication assignment to dense matrices*********************************************
1979  // No special implementation for the SMP multiplication assignment to dense matrices.
1980  //**********************************************************************************************
1981 
1982  //**SMP multiplication assignment to sparse matrices********************************************
1983  // No special implementation for the SMP multiplication assignment to sparse matrices.
1984  //**********************************************************************************************
1985 
1986  //**Compile time checks*************************************************************************
1995  //**********************************************************************************************
1996 };
1997 //*************************************************************************************************
1998 
1999 
2000 
2001 
2002 //=================================================================================================
2003 //
2004 // GLOBAL BINARY ARITHMETIC OPERATORS
2005 //
2006 //=================================================================================================
2007 
2008 //*************************************************************************************************
2021 template< typename MT1 // Type of the left-hand side dense matrix
2022  , typename MT2 // Type of the right-hand side sparse matrix
2023  , DisableIf_t< ( IsIdentity_v<MT1> &&
2024  IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > ) ||
2025  IsZero_v<MT1> >* = nullptr >
2026 inline const TSMatTDMatMultExpr<MT1,MT2,false,false,false,false>
2027  tsmattdmatmult( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,true>& rhs )
2028 {
2030 
2031  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).rows(), "Invalid matrix sizes" );
2032 
2033  return TSMatTDMatMultExpr<MT1,MT2,false,false,false,false>( ~lhs, ~rhs );
2034 }
2036 //*************************************************************************************************
2037 
2038 
2039 //*************************************************************************************************
2053 template< typename MT1 // Type of the left-hand side sparse matrix
2054  , typename MT2 // Type of the right-hand side dense matrix
2055  , EnableIf_t< IsIdentity_v<MT1> &&
2056  IsSame_v< ElementType_t<MT1>, ElementType_t<MT2> > >* = nullptr >
2057 inline const MT2&
2058  tsmattdmatmult( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,true>& rhs )
2059 {
2061 
2062  MAYBE_UNUSED( lhs );
2063 
2064  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).rows(), "Invalid matrix sizes" );
2065 
2066  return (~rhs);
2067 }
2069 //*************************************************************************************************
2070 
2071 
2072 //*************************************************************************************************
2085 template< typename MT1 // Type of the left-hand side dense matrix
2086  , typename MT2 // Type of the right-hand side sparse matrix
2087  , EnableIf_t< IsZero_v<MT1> >* = nullptr >
2088 inline decltype(auto)
2089  tsmattdmatmult( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,true>& rhs )
2090 {
2092 
2093  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).rows(), "Invalid matrix sizes" );
2094 
2095  using ReturnType = const MultTrait_t< ResultType_t<MT1>, ResultType_t<MT2> >;
2096 
2098  BLAZE_CONSTRAINT_MUST_BE_ZERO_TYPE( ReturnType );
2099 
2100  return ReturnType( (~lhs).rows(), (~rhs).columns() );
2101 }
2103 //*************************************************************************************************
2104 
2105 
2106 //*************************************************************************************************
2135 template< typename MT1 // Type of the left-hand side sparse matrix
2136  , typename MT2 > // Type of the right-hand side dense matrix
2137 inline decltype(auto)
2138  operator*( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,true>& rhs )
2139 {
2141 
2142  if( (~lhs).columns() != (~rhs).rows() ) {
2143  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
2144  }
2145 
2146  return tsmattdmatmult( ~lhs, ~rhs );
2147 }
2148 //*************************************************************************************************
2149 
2150 
2151 
2152 
2153 //=================================================================================================
2154 //
2155 // GLOBAL FUNCTIONS
2156 //
2157 //=================================================================================================
2158 
2159 //*************************************************************************************************
2183 template< typename MT1 // Type of the left-hand side dense matrix
2184  , typename MT2 // Type of the right-hand side dense matrix
2185  , bool SF // Symmetry flag
2186  , bool HF // Hermitian flag
2187  , bool LF // Lower flag
2188  , bool UF > // Upper flag
2189 inline decltype(auto) declsym( const TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2190 {
2192 
2193  if( !isSquare( dm ) ) {
2194  BLAZE_THROW_INVALID_ARGUMENT( "Invalid symmetric matrix specification" );
2195  }
2196 
2197  using ReturnType = const TSMatTDMatMultExpr<MT1,MT2,true,HF,LF,UF>;
2198  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2199 }
2201 //*************************************************************************************************
2202 
2203 
2204 //*************************************************************************************************
2228 template< typename MT1 // Type of the left-hand side dense matrix
2229  , typename MT2 // Type of the right-hand side dense matrix
2230  , bool SF // Symmetry flag
2231  , bool HF // Hermitian flag
2232  , bool LF // Lower flag
2233  , bool UF > // Upper flag
2234 inline decltype(auto) declherm( const TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2235 {
2237 
2238  if( !isSquare( dm ) ) {
2239  BLAZE_THROW_INVALID_ARGUMENT( "Invalid Hermitian matrix specification" );
2240  }
2241 
2242  using ReturnType = const TSMatTDMatMultExpr<MT1,MT2,SF,true,LF,UF>;
2243  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2244 }
2246 //*************************************************************************************************
2247 
2248 
2249 //*************************************************************************************************
2273 template< typename MT1 // Type of the left-hand side dense matrix
2274  , typename MT2 // Type of the right-hand side dense matrix
2275  , bool SF // Symmetry flag
2276  , bool HF // Hermitian flag
2277  , bool LF // Lower flag
2278  , bool UF > // Upper flag
2279 inline decltype(auto) decllow( const TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2280 {
2282 
2283  if( !isSquare( dm ) ) {
2284  BLAZE_THROW_INVALID_ARGUMENT( "Invalid lower matrix specification" );
2285  }
2286 
2287  using ReturnType = const TSMatTDMatMultExpr<MT1,MT2,SF,HF,true,UF>;
2288  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2289 }
2291 //*************************************************************************************************
2292 
2293 
2294 //*************************************************************************************************
2318 template< typename MT1 // Type of the left-hand side dense matrix
2319  , typename MT2 // Type of the right-hand side dense matrix
2320  , bool SF // Symmetry flag
2321  , bool HF // Hermitian flag
2322  , bool LF // Lower flag
2323  , bool UF > // Upper flag
2324 inline decltype(auto) declupp( const TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2325 {
2327 
2328  if( !isSquare( dm ) ) {
2329  BLAZE_THROW_INVALID_ARGUMENT( "Invalid upper matrix specification" );
2330  }
2331 
2332  using ReturnType = const TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,true>;
2333  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2334 }
2336 //*************************************************************************************************
2337 
2338 
2339 //*************************************************************************************************
2363 template< typename MT1 // Type of the left-hand side dense matrix
2364  , typename MT2 // Type of the right-hand side dense matrix
2365  , bool SF // Symmetry flag
2366  , bool HF // Hermitian flag
2367  , bool LF // Lower flag
2368  , bool UF > // Upper flag
2369 inline decltype(auto) decldiag( const TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2370 {
2372 
2373  if( !isSquare( dm ) ) {
2374  BLAZE_THROW_INVALID_ARGUMENT( "Invalid diagonal matrix specification" );
2375  }
2376 
2377  using ReturnType = const TSMatTDMatMultExpr<MT1,MT2,SF,HF,true,true>;
2378  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2379 }
2381 //*************************************************************************************************
2382 
2383 
2384 
2385 
2386 //=================================================================================================
2387 //
2388 // SIZE SPECIALIZATIONS
2389 //
2390 //=================================================================================================
2391 
2392 //*************************************************************************************************
2394 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2395 struct Size< TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 0UL >
2396  : public Size<MT1,0UL>
2397 {};
2398 
2399 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2400 struct Size< TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 1UL >
2401  : public Size<MT2,1UL>
2402 {};
2404 //*************************************************************************************************
2405 
2406 
2407 
2408 
2409 //=================================================================================================
2410 //
2411 // ISALIGNED SPECIALIZATIONS
2412 //
2413 //=================================================================================================
2414 
2415 //*************************************************************************************************
2417 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2418 struct IsAligned< TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2419  : public IsAligned<MT2>
2420 {};
2422 //*************************************************************************************************
2423 
2424 } // namespace blaze
2425 
2426 #endif
ResultType_t< MT2 > RT2
Result type of the right-hand side dense matrix expression.
Definition: TSMatTDMatMultExpr.h:135
If_t< evaluateRight, const RT2, CT2 > RT
Type for the assignment of the right-hand side dense matrix operand.
Definition: TSMatTDMatMultExpr.h:263
#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:435
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....
Definition: Forward.h:188
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
static constexpr bool LOW
Flag for lower matrices.
Definition: TSMatTDMatMultExpr.h:155
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:144
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:138
#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:425
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:415
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.
decltype(auto) declupp(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as upper.
Definition: DMatDeclUppExpr.h:1001
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:268
Header file for the RequiresEvaluation type trait.
System settings for performance optimizations.
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:443
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes....
Definition: DenseMatrix.h:81
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
const ResultType CompositeType
Data type for composite expression templates.
Definition: TSMatTDMatMultExpr.h:251
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:403
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:271
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:254
#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:156
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
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: TSMatTDMatMultExpr.h:296
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:442
If_t< evaluateLeft, const RT1, CT1 > LT
Type for the assignment of the left-hand side sparse matrix operand.
Definition: TSMatTDMatMultExpr.h:260
static constexpr bool evaluateRight
Compilation switch for the composite type of the right-hand side dense matrix expression.
Definition: TSMatTDMatMultExpr.h:149
TSMatTDMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the TSMatTDMatMultExpr class.
Definition: TSMatTDMatMultExpr.h:281
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.
ResultType_t< MT1 > RT1
Result type of the left-hand side sparse matrix expression.
Definition: TSMatTDMatMultExpr.h:134
static constexpr bool SYM
Flag for symmetric matrices.
Definition: TSMatTDMatMultExpr.h:153
Generic wrapper for the null function.
Definition: Noop.h:60
Header file for the IsTriangular type trait.
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: TSMatTDMatMultExpr.h:361
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:381
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:136
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:245
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.
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TSMatTDMatMultExpr.h:250
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:248
typename T::OppositeType OppositeType_t
Alias declaration for nested OppositeType type definitions.The OppositeType_t alias declaration provi...
Definition: Aliases.h:270
Header file for the conjugate shim.
Header file for the declupp trait.
#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
CompositeType_t< MT2 > CT2
Composite type of the right-hand side dense matrix expression.
Definition: TSMatTDMatMultExpr.h:139
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:247
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
Header file for all forward declarations for expression class templates.
ElementType_t< ResultType > ElementType
Resulting element type.
Definition: TSMatTDMatMultExpr.h:249
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
ElementType_t< RT2 > ET2
Element type of the right-hand side sparse matrix expression.
Definition: TSMatTDMatMultExpr.h:137
static constexpr bool HERM
Flag for Hermitian matrices.
Definition: TSMatTDMatMultExpr.h:154
#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
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:391
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:371
If_t< IsExpression_v< MT2 >, const MT2, const MT2 & > RightOperand
Composite type of the right-hand side dense matrix expression.
Definition: TSMatTDMatMultExpr.h:257
Header file for the IntegralConstant class template.
Generic wrapper for the decldiag() function.
Definition: DeclDiag.h:59
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
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.
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: TSMatTDMatMultExpr.h:345