TDMatSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_TDMATSMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_TDMATSMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <blaze/math/Aliases.h>
52 #include <blaze/math/Exception.h>
65 #include <blaze/math/shims/Reset.h>
89 #include <blaze/util/Assert.h>
90 #include <blaze/util/DisableIf.h>
91 #include <blaze/util/EnableIf.h>
94 #include <blaze/util/InvalidType.h>
95 #include <blaze/util/mpl/And.h>
96 #include <blaze/util/mpl/Bool.h>
97 #include <blaze/util/mpl/If.h>
98 #include <blaze/util/mpl/Or.h>
99 #include <blaze/util/Types.h>
101 
102 
103 namespace blaze {
104 
105 //=================================================================================================
106 //
107 // CLASS TDMATSMATMULTEXPR
108 //
109 //=================================================================================================
110 
111 //*************************************************************************************************
118 template< typename MT1 // Type of the left-hand side dense matrix
119  , typename MT2 // Type of the right-hand side sparse matrix
120  , bool SF // Symmetry flag
121  , bool HF // Hermitian flag
122  , bool LF // Lower flag
123  , bool UF > // Upper flag
124 class TDMatSMatMultExpr
125  : public MatMatMultExpr< DenseMatrix< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>, true > >
126  , private Computation
127 {
128  private:
129  //**Type definitions****************************************************************************
136  //**********************************************************************************************
137 
138  //**********************************************************************************************
140  enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
141  //**********************************************************************************************
142 
143  //**********************************************************************************************
145  enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
146  //**********************************************************************************************
147 
148  //**********************************************************************************************
150  enum : bool {
151  SYM = ( SF && !( HF || LF || UF ) ),
152  HERM = ( HF && !( LF || UF ) ),
153  LOW = ( LF || ( ( SF || HF ) && UF ) ),
154  UPP = ( UF || ( ( SF || HF ) && LF ) )
155  };
156  //**********************************************************************************************
157 
158  //**********************************************************************************************
160 
165  template< typename T1, typename T2, typename T3 >
166  struct CanExploitSymmetry {
167  enum : bool { value = IsSymmetric<T3>::value };
168  };
170  //**********************************************************************************************
171 
172  //**********************************************************************************************
174 
178  template< typename T1, typename T2, typename T3 >
179  struct IsEvaluationRequired {
180  enum : bool { value = ( evaluateLeft || evaluateRight ) &&
181  !CanExploitSymmetry<T1,T2,T3>::value };
182  };
184  //**********************************************************************************************
185 
186  //**********************************************************************************************
188 
192  template< typename T1, typename T2, typename T3 >
193  struct UseOptimizedKernel {
194  enum : bool { value = useOptimizedKernels &&
196  !IsResizable< ElementType_<T1> >::value &&
198  };
200  //**********************************************************************************************
201 
202  //**********************************************************************************************
204 
207  template< typename T1, typename T2, typename T3 >
208  struct UseDefaultKernel {
209  enum : bool { value = !UseOptimizedKernel<T1,T2,T3>::value };
210  };
212  //**********************************************************************************************
213 
214  //**********************************************************************************************
216 
219  using ForwardFunctor = IfTrue_< HERM
220  , DeclHerm
221  , IfTrue_< SYM
222  , DeclSym
223  , IfTrue_< LOW
224  , IfTrue_< UPP
225  , DeclDiag
226  , DeclLow >
227  , IfTrue_< UPP
228  , DeclUpp
229  , Noop > > > >;
231  //**********************************************************************************************
232 
233  public:
234  //**Type definitions****************************************************************************
237 
242  using ReturnType = const ElementType;
243  using CompositeType = const ResultType;
244 
246  using LeftOperand = If_< IsExpression<MT1>, const MT1, const MT1& >;
247 
249  using RightOperand = If_< IsExpression<MT2>, const MT2, const MT2& >;
250 
253 
256  //**********************************************************************************************
257 
258  //**Compilation flags***************************************************************************
260  enum : bool { simdEnabled = false };
261 
263  enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
264  !evaluateRight && MT2::smpAssignable };
265  //**********************************************************************************************
266 
267  //**Constructor*********************************************************************************
273  explicit inline TDMatSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
274  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
275  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
276  {
277  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
278  }
279  //**********************************************************************************************
280 
281  //**Access operator*****************************************************************************
288  inline ReturnType operator()( size_t i, size_t j ) const {
289  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
290  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
291 
292  if( IsDiagonal<MT1>::value ) {
293  return lhs_(i,i) * rhs_(i,j);
294  }
295  else if( IsDiagonal<MT2>::value ) {
296  return lhs_(i,j) * rhs_(j,j);
297  }
299  const size_t begin( ( IsUpper<MT1>::value )
300  ?( ( IsLower<MT2>::value )
301  ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
302  , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
303  :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
304  :( ( IsLower<MT2>::value )
305  ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
306  :( 0UL ) ) );
307  const size_t end( ( IsLower<MT1>::value )
308  ?( ( IsUpper<MT2>::value )
309  ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
310  , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
311  :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
312  :( ( IsUpper<MT2>::value )
313  ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
314  :( lhs_.columns() ) ) );
315 
316  if( begin >= end ) return ElementType();
317 
318  const size_t n( end - begin );
319 
320  return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
321  }
322  else {
323  return row( lhs_, i ) * column( rhs_, j );
324  }
325  }
326  //**********************************************************************************************
327 
328  //**At function*********************************************************************************
336  inline ReturnType at( size_t i, size_t j ) const {
337  if( i >= lhs_.rows() ) {
338  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
339  }
340  if( j >= rhs_.columns() ) {
341  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
342  }
343  return (*this)(i,j);
344  }
345  //**********************************************************************************************
346 
347  //**Rows function*******************************************************************************
352  inline size_t rows() const noexcept {
353  return lhs_.rows();
354  }
355  //**********************************************************************************************
356 
357  //**Columns function****************************************************************************
362  inline size_t columns() const noexcept {
363  return rhs_.columns();
364  }
365  //**********************************************************************************************
366 
367  //**Left operand access*************************************************************************
372  inline LeftOperand leftOperand() const noexcept {
373  return lhs_;
374  }
375  //**********************************************************************************************
376 
377  //**Right operand access************************************************************************
382  inline RightOperand rightOperand() const noexcept {
383  return rhs_;
384  }
385  //**********************************************************************************************
386 
387  //**********************************************************************************************
393  template< typename T >
394  inline bool canAlias( const T* alias ) const noexcept {
395  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
396  }
397  //**********************************************************************************************
398 
399  //**********************************************************************************************
405  template< typename T >
406  inline bool isAliased( const T* alias ) const {
407  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
408  }
409  //**********************************************************************************************
410 
411  //**********************************************************************************************
416  inline bool isAligned() const noexcept {
417  return lhs_.isAligned();
418  }
419  //**********************************************************************************************
420 
421  //**********************************************************************************************
426  inline bool canSMPAssign() const noexcept {
427  return ( rows() * columns() >= SMP_TDMATSMATMULT_THRESHOLD ) && !IsDiagonal<MT1>::value;
428  }
429  //**********************************************************************************************
430 
431  private:
432  //**Member variables****************************************************************************
435  //**********************************************************************************************
436 
437  //**Assignment to dense matrices****************************************************************
450  template< typename MT // Type of the target dense matrix
451  , bool SO > // Storage order of the target dense matrix
453  assign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
454  {
456 
457  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
458  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
459 
460  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
461  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
462 
463  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
464  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
465  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
466  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
467  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
468  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
469 
470  TDMatSMatMultExpr::selectAssignKernel( ~lhs, A, B );
471  }
473  //**********************************************************************************************
474 
475  //**Assignment to dense matrices (kernel selection)*********************************************
486  template< typename MT3 // Type of the left-hand side target matrix
487  , typename MT4 // Type of the left-hand side matrix operand
488  , typename MT5 > // Type of the right-hand side matrix operand
489  static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
490  {
491  if( C.rows() * C.columns() < TDMATSMATMULT_THRESHOLD )
492  selectSmallAssignKernel( C, A, B );
493  else
494  selectLargeAssignKernel( C, A, B );
495  }
497  //**********************************************************************************************
498 
499  //**Default assignment to dense matrices********************************************************
514  template< typename MT3 // Type of the left-hand side target matrix
515  , typename MT4 // Type of the left-hand side matrix operand
516  , typename MT5 > // Type of the right-hand side matrix operand
517  static inline void selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
518  {
520 
521  reset( C );
522 
523  for( size_t j=0UL; j<B.rows(); ++j )
524  {
525  ConstIterator element( B.begin(j) );
526  const ConstIterator end( B.end(j) );
527 
529  {
530  for( ; element!=end; ++element ) {
531  C(j,element->index()) = A(j,j) * element->value();
532  }
533  }
534  else
535  {
536  for( ; element!=end; ++element )
537  {
538  const size_t j1( element->index() );
539 
540  const size_t ibegin( ( IsLower<MT4>::value )
542  ?( SYM || HERM || LOW ? max(j1,j+1UL) : j+1UL )
543  :( SYM || HERM || LOW ? max(j1,j) : j ) )
544  :( SYM || HERM || LOW ? j1 : 0UL ) );
545  const size_t iend( ( IsUpper<MT4>::value )
547  ?( UPP ? min(j1+1UL,j) : j )
548  :( UPP ? min(j1,j)+1UL : j+1UL ) )
549  :( UPP ? j1+1UL : A.rows() ) );
550 
551  if( ( SYM || HERM || LOW || UPP ) && ( ibegin >= iend ) ) continue;
552  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
553 
554  for( size_t i=ibegin; i<iend; ++i ) {
555  if( isDefault( C(i,j1) ) )
556  C(i,j1) = A(i,j) * element->value();
557  else
558  C(i,j1) += A(i,j) * element->value();
559  }
560  }
561  }
562  }
563 
564  if( SYM || HERM ) {
565  for( size_t j=1UL; j<B.columns(); ++j ) {
566  for( size_t i=0UL; i<j; ++i ) {
567  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
568  }
569  }
570  }
571  }
573  //**********************************************************************************************
574 
575  //**Default assignment to dense matrices (small matrices)***************************************
589  template< typename MT3 // Type of the left-hand side target matrix
590  , typename MT4 // Type of the left-hand side matrix operand
591  , typename MT5 > // Type of the right-hand side matrix operand
593  selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
594  {
595  selectDefaultAssignKernel( C, A, B );
596  }
598  //**********************************************************************************************
599 
600  //**Optimized assignment to dense matrices (small matrices)*************************************
615  template< typename MT3 // Type of the left-hand side target matrix
616  , typename MT4 // Type of the left-hand side matrix operand
617  , typename MT5 > // Type of the right-hand side matrix operand
619  selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
620  {
622 
623  reset( C );
624 
625  for( size_t j=0UL; j<B.rows(); ++j )
626  {
627  ConstIterator element( B.begin(j) );
628  const ConstIterator end( B.end(j) );
629 
630  const size_t nonzeros( B.nonZeros(j) );
631  const size_t kpos( nonzeros & size_t(-4) );
632  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
633 
634  for( size_t k=0UL; k<kpos; k+=4UL )
635  {
636  const size_t j1( element->index() );
637  const ET2 v1( element->value() );
638  ++element;
639  const size_t j2( element->index() );
640  const ET2 v2( element->value() );
641  ++element;
642  const size_t j3( element->index() );
643  const ET2 v3( element->value() );
644  ++element;
645  const size_t j4( element->index() );
646  const ET2 v4( element->value() );
647  ++element;
648 
649  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
650 
651  const size_t ibegin( ( IsLower<MT4>::value )
653  ?( SYM || HERM || LOW ? max(j1,j+1UL) : j+1UL )
654  :( SYM || HERM || LOW ? max(j1,j) : j ) )
655  :( SYM || HERM || LOW ? j1 : 0UL ) );
656  const size_t iend( ( IsUpper<MT4>::value )
658  ?( UPP ? min(j4+1UL,j) : j )
659  :( UPP ? min(j4,j)+1UL : j+1UL ) )
660  :( UPP ? j4+1UL : A.rows() ) );
661 
662  if( ( SYM || HERM || LOW || UPP ) && ( ibegin >= iend ) ) continue;
663  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
664 
665  const size_t inum( iend - ibegin );
666  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
667  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
668 
669  size_t i( ibegin );
670 
671  for( ; i<ipos; i+=4UL ) {
672  C(i ,j1) += A(i ,j) * v1;
673  C(i+1UL,j1) += A(i+1UL,j) * v1;
674  C(i+2UL,j1) += A(i+2UL,j) * v1;
675  C(i+3UL,j1) += A(i+3UL,j) * v1;
676  C(i ,j2) += A(i ,j) * v2;
677  C(i+1UL,j2) += A(i+1UL,j) * v2;
678  C(i+2UL,j2) += A(i+2UL,j) * v2;
679  C(i+3UL,j2) += A(i+3UL,j) * v2;
680  C(i ,j3) += A(i ,j) * v3;
681  C(i+1UL,j3) += A(i+1UL,j) * v3;
682  C(i+2UL,j3) += A(i+2UL,j) * v3;
683  C(i+3UL,j3) += A(i+3UL,j) * v3;
684  C(i ,j4) += A(i ,j) * v4;
685  C(i+1UL,j4) += A(i+1UL,j) * v4;
686  C(i+2UL,j4) += A(i+2UL,j) * v4;
687  C(i+3UL,j4) += A(i+3UL,j) * v4;
688  }
689  for( ; i<iend; ++i ) {
690  C(i,j1) += A(i,j) * v1;
691  C(i,j2) += A(i,j) * v2;
692  C(i,j3) += A(i,j) * v3;
693  C(i,j4) += A(i,j) * v4;
694  }
695  }
696 
697  for( ; element!=end; ++element )
698  {
699  const size_t j1( element->index() );
700  const ET2 v1( element->value() );
701 
702  const size_t ibegin( ( IsLower<MT4>::value )
704  ?( SYM || HERM || LOW ? max(j1,j+1UL) : j+1UL )
705  :( SYM || HERM || LOW ? max(j1,j) : j ) )
706  :( SYM || HERM || LOW ? j1 : 0UL ) );
707  const size_t iend( ( IsUpper<MT4>::value )
709  ?( UPP ? min(j1+1UL,j) : j )
710  :( UPP ? min(j1,j)+1UL : j+1UL ) )
711  :( UPP ? j1+1UL : A.rows() ) );
712 
713  if( ( SYM || HERM || LOW || UPP ) && ( ibegin >= iend ) ) continue;
714  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
715 
716  const size_t inum( iend - ibegin );
717  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
718  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
719 
720  size_t i( ibegin );
721 
722  for( ; i<ipos; i+=4UL ) {
723  C(i ,j1) += A(i ,j) * v1;
724  C(i+1UL,j1) += A(i+1UL,j) * v1;
725  C(i+2UL,j1) += A(i+2UL,j) * v1;
726  C(i+3UL,j1) += A(i+3UL,j) * v1;
727  }
728  for( ; i<iend; ++i ) {
729  C(i,j1) += A(i,j) * v1;
730  }
731  }
732  }
733 
734  if( SYM || HERM ) {
735  for( size_t j=1UL; j<B.columns(); ++j ) {
736  for( size_t i=0UL; i<j; ++i ) {
737  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
738  }
739  }
740  }
741  }
743  //**********************************************************************************************
744 
745  //**Default assignment to dense matrices (large matrices)***************************************
759  template< typename MT3 // Type of the left-hand side target matrix
760  , typename MT4 // Type of the left-hand side matrix operand
761  , typename MT5 > // Type of the right-hand side matrix operand
763  selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
764  {
765  selectDefaultAssignKernel( C, A, B );
766  }
768  //**********************************************************************************************
769 
770  //**Optimized assignment to dense matrices (large matrices)*************************************
785  template< typename MT3 // Type of the left-hand side target matrix
786  , typename MT4 // Type of the left-hand side matrix operand
787  , typename MT5 > // Type of the right-hand side matrix operand
789  selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
790  {
792 
793  const ForwardFunctor fwd;
794 
795  const OppositeType_<MT5> tmp( serial( B ) );
796  assign( C, fwd( A * tmp ) );
797  }
799  //**********************************************************************************************
800 
801  //**Assignment to sparse matrices***************************************************************
814  template< typename MT // Type of the target sparse matrix
815  , bool SO > // Storage order of the target sparse matrix
817  assign( SparseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
818  {
820 
822 
829 
830  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
831  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
832 
833  const ForwardFunctor fwd;
834 
835  const TmpType tmp( serial( rhs ) );
836  assign( ~lhs, fwd( tmp ) );
837  }
839  //**********************************************************************************************
840 
841  //**Restructuring assignment********************************************************************
856  template< typename MT // Type of the target matrix
857  , bool SO > // Storage order of the target matrix
859  assign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
860  {
862 
864 
865  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
866  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
867 
868  const ForwardFunctor fwd;
869 
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
891  addAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
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 left-hand side dense matrix operand
899  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse 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  TDMatSMatMultExpr::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  if( C.rows() * C.columns() < TDMATSMATMULT_THRESHOLD )
930  selectSmallAddAssignKernel( C, A, B );
931  else
932  selectLargeAddAssignKernel( C, A, B );
933  }
935  //**********************************************************************************************
936 
937  //**Default addition assignment to dense matrices***********************************************
952  template< typename MT3 // Type of the left-hand side target matrix
953  , typename MT4 // Type of the left-hand side matrix operand
954  , typename MT5 > // Type of the right-hand side matrix operand
955  static inline void selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
956  {
958 
959  size_t i( 0UL );
960 
961  for( size_t j=0UL; j<B.rows(); ++j )
962  {
963  ConstIterator element( B.begin(j) );
964  const ConstIterator end( B.end(j) );
965 
967  {
968  for( ; element!=end; ++element ) {
969  C(j,element->index()) += A(j,j) * element->value();
970  }
971  }
972  else
973  {
974  for( ; element!=end; ++element )
975  {
976  const size_t j1( element->index() );
977 
978  const size_t ibegin( ( IsLower<MT4>::value )
980  ?( LOW ? max(j1,j+1UL) : j+1UL )
981  :( LOW ? max(j1,j) : j ) )
982  :( LOW ? j1 : 0UL ) );
983  const size_t iend( ( IsUpper<MT4>::value )
985  ?( UPP ? min(j1+1UL,j) : j )
986  :( UPP ? min(j1,j)+1UL : j+1UL ) )
987  :( UPP ? j1+1UL : A.rows() ) );
988 
989  if( ( LOW || UPP ) && ( ibegin >= iend ) ) continue;
990  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
991 
992  const size_t inum( iend - ibegin );
993  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
994  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
995 
996  for( i=ibegin; i<ipos; i+=4UL ) {
997  C(i ,j1) += A(i ,j) * element->value();
998  C(i+1UL,j1) += A(i+1UL,j) * element->value();
999  C(i+2UL,j1) += A(i+2UL,j) * element->value();
1000  C(i+3UL,j1) += A(i+3UL,j) * element->value();
1001  }
1002  for( ; i<iend; ++i ) {
1003  C(i,j1) += A(i,j) * element->value();
1004  }
1005  }
1006  }
1007  }
1008  }
1010  //**********************************************************************************************
1011 
1012  //**Default addition assignment to dense matrices (small matrices)******************************
1026  template< typename MT3 // Type of the left-hand side target matrix
1027  , typename MT4 // Type of the left-hand side matrix operand
1028  , typename MT5 > // Type of the right-hand side matrix operand
1030  selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1031  {
1032  selectDefaultAddAssignKernel( C, A, B );
1033  }
1035  //**********************************************************************************************
1036 
1037  //**Optimized addition assignment to dense matrices (small matrices)****************************
1052  template< typename MT3 // Type of the left-hand side target matrix
1053  , typename MT4 // Type of the left-hand side matrix operand
1054  , typename MT5 > // Type of the right-hand side matrix operand
1056  selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1057  {
1059 
1060  for( size_t j=0UL; j<B.rows(); ++j )
1061  {
1062  ConstIterator element( B.begin(j) );
1063  const ConstIterator end( B.end(j) );
1064 
1065  const size_t nonzeros( B.nonZeros(j) );
1066  const size_t kpos( nonzeros & size_t(-4) );
1067  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1068 
1069  for( size_t k=0UL; k<kpos; k+=4UL )
1070  {
1071  const size_t j1( element->index() );
1072  const ET2 v1( element->value() );
1073  ++element;
1074  const size_t j2( element->index() );
1075  const ET2 v2( element->value() );
1076  ++element;
1077  const size_t j3( element->index() );
1078  const ET2 v3( element->value() );
1079  ++element;
1080  const size_t j4( element->index() );
1081  const ET2 v4( element->value() );
1082  ++element;
1083 
1084  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1085 
1086  const size_t ibegin( ( IsLower<MT4>::value )
1088  ?( LOW ? max(j1,j+1UL) : j+1UL )
1089  :( LOW ? max(j1,j) : j ) )
1090  :( LOW ? j1 : 0UL ) );
1091  const size_t iend( ( IsUpper<MT4>::value )
1093  ?( UPP ? min(j4+1UL,j) : j )
1094  :( UPP ? min(j4,j)+1UL : j+1UL ) )
1095  :( UPP ? j4+1UL : A.rows() ) );
1096 
1097  if( ( LOW || UPP ) && ( ibegin >= iend ) ) continue;
1098  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
1099 
1100  const size_t inum( iend - ibegin );
1101  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
1102  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
1103 
1104  size_t i( ibegin );
1105 
1106  for( i=ibegin; i<ipos; i+=4UL ) {
1107  C(i ,j1) += A(i ,j) * v1;
1108  C(i+1UL,j1) += A(i+1UL,j) * v1;
1109  C(i+2UL,j1) += A(i+2UL,j) * v1;
1110  C(i+3UL,j1) += A(i+3UL,j) * v1;
1111  C(i ,j2) += A(i ,j) * v2;
1112  C(i+1UL,j2) += A(i+1UL,j) * v2;
1113  C(i+2UL,j2) += A(i+2UL,j) * v2;
1114  C(i+3UL,j2) += A(i+3UL,j) * v2;
1115  C(i ,j3) += A(i ,j) * v3;
1116  C(i+1UL,j3) += A(i+1UL,j) * v3;
1117  C(i+2UL,j3) += A(i+2UL,j) * v3;
1118  C(i+3UL,j3) += A(i+3UL,j) * v3;
1119  C(i ,j4) += A(i ,j) * v4;
1120  C(i+1UL,j4) += A(i+1UL,j) * v4;
1121  C(i+2UL,j4) += A(i+2UL,j) * v4;
1122  C(i+3UL,j4) += A(i+3UL,j) * v4;
1123  }
1124  for( ; i<iend; ++i ) {
1125  C(i,j1) += A(i,j) * v1;
1126  C(i,j2) += A(i,j) * v2;
1127  C(i,j3) += A(i,j) * v3;
1128  C(i,j4) += A(i,j) * v4;
1129  }
1130  }
1131 
1132  for( ; element!=end; ++element )
1133  {
1134  const size_t j1( element->index() );
1135  const ET2 v1( element->value() );
1136 
1137  const size_t ibegin( ( IsLower<MT4>::value )
1139  ?( LOW ? max(j1,j+1UL) : j+1UL )
1140  :( LOW ? max(j1,j) : j ) )
1141  :( LOW ? j1 : 0UL ) );
1142  const size_t iend( ( IsUpper<MT4>::value )
1144  ?( UPP ? min(j1+1UL,j) : j )
1145  :( UPP ? min(j1,j)+1UL : j+1UL ) )
1146  :( UPP ? j1+1UL : A.rows() ) );
1147 
1148  if( ( LOW || UPP ) && ( ibegin >= iend ) ) continue;
1149  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
1150 
1151  const size_t inum( iend - ibegin );
1152  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
1153  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
1154 
1155  size_t i( ibegin );
1156 
1157  for( ; i<ipos; i+=4UL ) {
1158  C(i ,j1) += A(i ,j) * v1;
1159  C(i+1UL,j1) += A(i+1UL,j) * v1;
1160  C(i+2UL,j1) += A(i+2UL,j) * v1;
1161  C(i+3UL,j1) += A(i+3UL,j) * v1;
1162  }
1163  for( ; i<iend; ++i ) {
1164  C(i,j1) += A(i,j) * v1;
1165  }
1166  }
1167  }
1168  }
1170  //**********************************************************************************************
1171 
1172  //**Default addition assignment to dense matrices (large matrices)******************************
1186  template< typename MT3 // Type of the left-hand side target matrix
1187  , typename MT4 // Type of the left-hand side matrix operand
1188  , typename MT5 > // Type of the right-hand side matrix operand
1190  selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1191  {
1192  selectDefaultAddAssignKernel( C, A, B );
1193  }
1195  //**********************************************************************************************
1196 
1197  //**Optimized addition assignment to dense matrices (large matrices)****************************
1212  template< typename MT3 // Type of the left-hand side target matrix
1213  , typename MT4 // Type of the left-hand side matrix operand
1214  , typename MT5 > // Type of the right-hand side matrix operand
1216  selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1217  {
1219 
1220  const ForwardFunctor fwd;
1221 
1222  const OppositeType_<MT5> tmp( serial( B ) );
1223  addAssign( C, fwd( A * tmp ) );
1224  }
1226  //**********************************************************************************************
1227 
1228  //**Restructuring addition assignment***********************************************************
1243  template< typename MT // Type of the target matrix
1244  , bool SO > // Storage order of the target matrix
1246  addAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1247  {
1249 
1250  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1251  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1252 
1253  const ForwardFunctor fwd;
1254 
1255  addAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1256  }
1258  //**********************************************************************************************
1259 
1260  //**Addition assignment to sparse matrices******************************************************
1261  // No special implementation for the addition assignment to sparse matrices.
1262  //**********************************************************************************************
1263 
1264  //**Subtraction assignment to dense matrices****************************************************
1277  template< typename MT // Type of the target dense matrix
1278  , bool SO > // Storage order of the target dense matrix
1280  subAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1281  {
1283 
1284  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1285  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1286 
1287  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1288  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1289 
1290  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1291  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1292  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1293  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1294  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1295  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1296 
1297  TDMatSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1298  }
1300  //**********************************************************************************************
1301 
1302  //**Subtraction assignment to dense matrices (kernel selection)*********************************
1313  template< typename MT3 // Type of the left-hand side target matrix
1314  , typename MT4 // Type of the left-hand side matrix operand
1315  , typename MT5 > // Type of the right-hand side matrix operand
1316  static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1317  {
1318  if( C.rows() * C.columns() < TDMATSMATMULT_THRESHOLD )
1319  selectSmallSubAssignKernel( C, A, B );
1320  else
1321  selectLargeSubAssignKernel( C, A, B );
1322  }
1324  //**********************************************************************************************
1325 
1326  //**Default subtraction assignment to dense matrices********************************************
1341  template< typename MT3 // Type of the left-hand side target matrix
1342  , typename MT4 // Type of the left-hand side matrix operand
1343  , typename MT5 > // Type of the right-hand side matrix operand
1344  static inline void selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1345  {
1347 
1348  size_t i( 0UL );
1349 
1350  for( size_t j=0UL; j<B.rows(); ++j )
1351  {
1352  ConstIterator element( B.begin(j) );
1353  const ConstIterator end( B.end(j) );
1354 
1356  {
1357  for( ; element!=end; ++element ) {
1358  C(j,element->index()) -= A(j,j) * element->value();
1359  }
1360  }
1361  else
1362  {
1363  for( ; element!=end; ++element )
1364  {
1365  const size_t j1( element->index() );
1366 
1367  const size_t ibegin( ( IsLower<MT4>::value )
1369  ?( LOW ? max(j1,j+1UL) : j+1UL )
1370  :( LOW ? max(j1,j) : j ) )
1371  :( LOW ? j1 : 0UL ) );
1372  const size_t iend( ( IsUpper<MT4>::value )
1374  ?( UPP ? min(j1+1UL,j) : j )
1375  :( UPP ? min(j1,j)+1UL : j+1UL ) )
1376  :( UPP ? j1+1UL : A.rows() ) );
1377 
1378  if( ( LOW || UPP ) && ( ibegin >= iend ) ) continue;
1379  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
1380 
1381  const size_t inum( iend - ibegin );
1382  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
1383  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
1384 
1385  for( i=ibegin; i<ipos; i+=4UL ) {
1386  C(i ,j1) -= A(i ,j) * element->value();
1387  C(i+1UL,j1) -= A(i+1UL,j) * element->value();
1388  C(i+2UL,j1) -= A(i+2UL,j) * element->value();
1389  C(i+3UL,j1) -= A(i+3UL,j) * element->value();
1390  }
1391  for( ; i<iend; ++i ) {
1392  C(i,j1) -= A(i,j) * element->value();
1393  }
1394  }
1395  }
1396  }
1397  }
1399  //**********************************************************************************************
1400 
1401  //**Default subtraction assignment to dense matrices (small matrices)***************************
1415  template< typename MT3 // Type of the left-hand side target matrix
1416  , typename MT4 // Type of the left-hand side matrix operand
1417  , typename MT5 > // Type of the right-hand side matrix operand
1419  selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1420  {
1421  selectDefaultSubAssignKernel( C, A, B );
1422  }
1424  //**********************************************************************************************
1425 
1426  //**Optimized subtraction assignment to dense matrices (small matrices)*************************
1441  template< typename MT3 // Type of the left-hand side target matrix
1442  , typename MT4 // Type of the left-hand side matrix operand
1443  , typename MT5 > // Type of the right-hand side matrix operand
1445  selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1446  {
1448 
1449  for( size_t j=0UL; j<B.rows(); ++j )
1450  {
1451  ConstIterator element( B.begin(j) );
1452  const ConstIterator end( B.end(j) );
1453 
1454  const size_t nonzeros( B.nonZeros(j) );
1455  const size_t kpos( nonzeros & size_t(-4) );
1456  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1457 
1458  for( size_t k=0UL; k<kpos; k+=4UL )
1459  {
1460  const size_t j1( element->index() );
1461  const ET2 v1( element->value() );
1462  ++element;
1463  const size_t j2( element->index() );
1464  const ET2 v2( element->value() );
1465  ++element;
1466  const size_t j3( element->index() );
1467  const ET2 v3( element->value() );
1468  ++element;
1469  const size_t j4( element->index() );
1470  const ET2 v4( element->value() );
1471  ++element;
1472 
1473  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1474 
1475  const size_t ibegin( ( IsLower<MT4>::value )
1477  ?( LOW ? max(j1,j+1UL) : j+1UL )
1478  :( LOW ? max(j1,j) : j ) )
1479  :( LOW ? j1 : 0UL ) );
1480  const size_t iend( ( IsUpper<MT4>::value )
1482  ?( UPP ? min(j4+1UL,j) : j )
1483  :( UPP ? min(j4,j)+1UL : j+1UL ) )
1484  :( UPP ? j4+1UL : A.rows() ) );
1485 
1486  if( ( LOW || UPP ) && ( ibegin >= iend ) ) continue;
1487  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
1488 
1489  const size_t inum( iend - ibegin );
1490  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
1491  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
1492 
1493  size_t i( ibegin );
1494 
1495  for( ; i<ipos; i+=4UL ) {
1496  C(i ,j1) -= A(i ,j) * v1;
1497  C(i+1UL,j1) -= A(i+1UL,j) * v1;
1498  C(i+2UL,j1) -= A(i+2UL,j) * v1;
1499  C(i+3UL,j1) -= A(i+3UL,j) * v1;
1500  C(i ,j2) -= A(i ,j) * v2;
1501  C(i+1UL,j2) -= A(i+1UL,j) * v2;
1502  C(i+2UL,j2) -= A(i+2UL,j) * v2;
1503  C(i+3UL,j2) -= A(i+3UL,j) * v2;
1504  C(i ,j3) -= A(i ,j) * v3;
1505  C(i+1UL,j3) -= A(i+1UL,j) * v3;
1506  C(i+2UL,j3) -= A(i+2UL,j) * v3;
1507  C(i+3UL,j3) -= A(i+3UL,j) * v3;
1508  C(i ,j4) -= A(i ,j) * v4;
1509  C(i+1UL,j4) -= A(i+1UL,j) * v4;
1510  C(i+2UL,j4) -= A(i+2UL,j) * v4;
1511  C(i+3UL,j4) -= A(i+3UL,j) * v4;
1512  }
1513  for( ; i<iend; ++i ) {
1514  C(i,j1) -= A(i,j) * v1;
1515  C(i,j2) -= A(i,j) * v2;
1516  C(i,j3) -= A(i,j) * v3;
1517  C(i,j4) -= A(i,j) * v4;
1518  }
1519  }
1520 
1521  for( ; element!=end; ++element )
1522  {
1523  const size_t j1( element->index() );
1524  const ET2 v1( element->value() );
1525 
1526  const size_t ibegin( ( IsLower<MT4>::value )
1528  ?( LOW ? max(j1,j+1UL) : j+1UL )
1529  :( LOW ? max(j1,j) : j ) )
1530  :( LOW ? j1 : 0UL ) );
1531  const size_t iend( ( IsUpper<MT4>::value )
1533  ?( UPP ? min(j1+1UL,j) : j )
1534  :( UPP ? min(j1,j)+1UL : j+1UL ) )
1535  :( UPP ? j1+1UL : A.rows() ) );
1536 
1537  if( ( LOW || UPP ) && ( ibegin >= iend ) ) continue;
1538  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
1539 
1540  const size_t inum( iend - ibegin );
1541  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
1542  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
1543 
1544  size_t i( ibegin );
1545 
1546  for( ; i<ipos; i+=4UL ) {
1547  C(i ,j1) -= A(i ,j) * v1;
1548  C(i+1UL,j1) -= A(i+1UL,j) * v1;
1549  C(i+2UL,j1) -= A(i+2UL,j) * v1;
1550  C(i+3UL,j1) -= A(i+3UL,j) * v1;
1551  }
1552  for( ; i<iend; ++i ) {
1553  C(i,j1) -= A(i,j) * v1;
1554  }
1555  }
1556  }
1557  }
1559  //**********************************************************************************************
1560 
1561  //**Default subtraction assignment to dense matrices (large matrices)***************************
1575  template< typename MT3 // Type of the left-hand side target matrix
1576  , typename MT4 // Type of the left-hand side matrix operand
1577  , typename MT5 > // Type of the right-hand side matrix operand
1579  selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1580  {
1581  selectDefaultSubAssignKernel( C, A, B );
1582  }
1584  //**********************************************************************************************
1585 
1586  //**Optimized subtraction assignment to dense matrices (large matrices)*************************
1601  template< typename MT3 // Type of the left-hand side target matrix
1602  , typename MT4 // Type of the left-hand side matrix operand
1603  , typename MT5 > // Type of the right-hand side matrix operand
1605  selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1606  {
1608 
1609  const ForwardFunctor fwd;
1610 
1611  const OppositeType_<MT5> tmp( serial( B ) );
1612  subAssign( C, fwd( A * tmp ) );
1613  }
1615  //**********************************************************************************************
1616 
1617  //**Restructuring subtraction assignment********************************************************
1632  template< typename MT // Type of the target matrix
1633  , bool SO > // Storage order of the target matrix
1635  subAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1636  {
1638 
1640 
1641  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1642  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1643 
1644  const ForwardFunctor fwd;
1645 
1646  subAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1647  }
1649  //**********************************************************************************************
1650 
1651  //**Subtraction assignment to sparse matrices***************************************************
1652  // No special implementation for the subtraction assignment to sparse matrices.
1653  //**********************************************************************************************
1654 
1655  //**Schur product assignment to dense matrices**************************************************
1668  template< typename MT // Type of the target dense matrix
1669  , bool SO > // Storage order of the target dense matrix
1670  friend inline void schurAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1671  {
1673 
1677 
1678  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1679  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1680 
1681  const ResultType tmp( serial( rhs ) );
1682  schurAssign( ~lhs, tmp );
1683  }
1685  //**********************************************************************************************
1686 
1687  //**Schur product assignment to sparse matrices*************************************************
1688  // No special implementation for the Schur product assignment to sparse matrices.
1689  //**********************************************************************************************
1690 
1691  //**Multiplication assignment to dense matrices*************************************************
1692  // No special implementation for the multiplication assignment to dense matrices.
1693  //**********************************************************************************************
1694 
1695  //**Multiplication assignment to sparse matrices************************************************
1696  // No special implementation for the multiplication assignment to sparse matrices.
1697  //**********************************************************************************************
1698 
1699  //**SMP assignment to dense matrices************************************************************
1715  template< typename MT // Type of the target dense matrix
1716  , bool SO > // Storage order of the target dense matrix
1718  smpAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1719  {
1721 
1722  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1723  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1724 
1725  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1726  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1727 
1728  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1729  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1730  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1731  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1732  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1733  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1734 
1735  smpAssign( ~lhs, A * B );
1736  }
1738  //**********************************************************************************************
1739 
1740  //**SMP assignment to sparse matrices***********************************************************
1756  template< typename MT // Type of the target sparse matrix
1757  , bool SO > // Storage order of the target sparse matrix
1759  smpAssign( SparseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1760  {
1762 
1764 
1771 
1772  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1773  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1774 
1775  const ForwardFunctor fwd;
1776 
1777  const TmpType tmp( rhs );
1778  smpAssign( ~lhs, fwd( tmp ) );
1779  }
1781  //**********************************************************************************************
1782 
1783  //**Restructuring SMP assignment****************************************************************
1798  template< typename MT // Type of the target matrix
1799  , bool SO > // Storage order of the target matrix
1801  smpAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1802  {
1804 
1805  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1806  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1807 
1808  const ForwardFunctor fwd;
1809 
1810  smpAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1811  }
1813  //**********************************************************************************************
1814 
1815  //**SMP addition assignment to dense matrices***************************************************
1831  template< typename MT // Type of the target dense matrix
1832  , bool SO > // Storage order of the target sparse matrix
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  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1842  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1843 
1844  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1845  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1846  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1847  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1848  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1849  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1850 
1851  smpAddAssign( ~lhs, A * B );
1852  }
1854  //**********************************************************************************************
1855 
1856  //**Restructuring SMP addition assignment*******************************************************
1871  template< typename MT // Type of the target matrix
1872  , bool SO > // Storage order of the target matrix
1874  smpAddAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1875  {
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  const ForwardFunctor fwd;
1884 
1885  smpAddAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1886  }
1888  //**********************************************************************************************
1889 
1890  //**SMP addition assignment to sparse matrices**************************************************
1891  // No special implementation for the SMP addition assignment to sparse matrices.
1892  //**********************************************************************************************
1893 
1894  //**SMP subtraction assignment to dense matrices************************************************
1910  template< typename MT // Type of the target dense matrix
1911  , bool SO > // Storage order of the target sparse matrix
1914  {
1916 
1917  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1918  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1919 
1920  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1921  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1922 
1923  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1924  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1925  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1926  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1927  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1928  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1929 
1930  smpSubAssign( ~lhs, A * B );
1931  }
1933  //**********************************************************************************************
1934 
1935  //**Restructuring SMP subtraction assignment****************************************************
1950  template< typename MT // Type of the target matrix
1951  , bool SO > // Storage order of the target matrix
1953  smpSubAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1954  {
1956 
1958 
1959  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1960  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1961 
1962  const ForwardFunctor fwd;
1963 
1964  smpSubAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1965  }
1967  //**********************************************************************************************
1968 
1969  //**SMP subtraction assignment to sparse matrices***********************************************
1970  // No special implementation for the SMP subtraction assignment to sparse matrices.
1971  //**********************************************************************************************
1972 
1973  //**SMP Schur product assignment to dense matrices**********************************************
1986  template< typename MT // Type of the target dense matrix
1987  , bool SO > // Storage order of the target sparse matrix
1988  friend inline void smpSchurAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1989  {
1991 
1995 
1996  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1997  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1998 
1999  const ResultType tmp( rhs );
2000  smpSchurAssign( ~lhs, tmp );
2001  }
2003  //**********************************************************************************************
2004 
2005  //**SMP Schur product assignment to sparse matrices*********************************************
2006  // No special implementation for the SMP Schur product assignment to sparse matrices.
2007  //**********************************************************************************************
2008 
2009  //**SMP multiplication assignment to dense matrices*********************************************
2010  // No special implementation for the SMP multiplication assignment to dense matrices.
2011  //**********************************************************************************************
2012 
2013  //**SMP multiplication assignment to sparse matrices********************************************
2014  // No special implementation for the SMP multiplication assignment to sparse matrices.
2015  //**********************************************************************************************
2016 
2017  //**Compile time checks*************************************************************************
2025  //**********************************************************************************************
2026 };
2027 //*************************************************************************************************
2028 
2029 
2030 
2031 
2032 //=================================================================================================
2033 //
2034 // GLOBAL BINARY ARITHMETIC OPERATORS
2035 //
2036 //=================================================================================================
2037 
2038 //*************************************************************************************************
2068 template< typename MT1 // Type of the left-hand side dense matrix
2069  , typename MT2 > // Type of the right-hand side sparse matrix
2070 inline decltype(auto)
2071  operator*( const DenseMatrix<MT1,true>& lhs, const SparseMatrix<MT2,false>& rhs )
2072 {
2074 
2075  if( (~lhs).columns() != (~rhs).rows() ) {
2076  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
2077  }
2078 
2079 
2081  return ReturnType( ~lhs, ~rhs );
2082 }
2083 //*************************************************************************************************
2084 
2085 
2086 
2087 
2088 //=================================================================================================
2089 //
2090 // GLOBAL FUNCTIONS
2091 //
2092 //=================================================================================================
2093 
2094 //*************************************************************************************************
2119 template< typename MT1 // Type of the left-hand side dense matrix
2120  , typename MT2 // Type of the right-hand side dense matrix
2121  , bool SF // Symmetry flag
2122  , bool HF // Hermitian flag
2123  , bool LF // Lower flag
2124  , bool UF > // Upper flag
2125 inline decltype(auto) declsym( const TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2126 {
2128 
2129  if( !isSquare( dm ) ) {
2130  BLAZE_THROW_INVALID_ARGUMENT( "Invalid symmetric matrix specification" );
2131  }
2132 
2134  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2135 }
2137 //*************************************************************************************************
2138 
2139 
2140 //*************************************************************************************************
2165 template< typename MT1 // Type of the left-hand side dense matrix
2166  , typename MT2 // Type of the right-hand side dense matrix
2167  , bool SF // Symmetry flag
2168  , bool HF // Hermitian flag
2169  , bool LF // Lower flag
2170  , bool UF > // Upper flag
2171 inline decltype(auto) declherm( const TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2172 {
2174 
2175  if( !isSquare( dm ) ) {
2176  BLAZE_THROW_INVALID_ARGUMENT( "Invalid Hermitian matrix specification" );
2177  }
2178 
2180  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2181 }
2183 //*************************************************************************************************
2184 
2185 
2186 //*************************************************************************************************
2211 template< typename MT1 // Type of the left-hand side dense matrix
2212  , typename MT2 // Type of the right-hand side dense matrix
2213  , bool SF // Symmetry flag
2214  , bool HF // Hermitian flag
2215  , bool LF // Lower flag
2216  , bool UF > // Upper flag
2217 inline decltype(auto) decllow( const TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2218 {
2220 
2221  if( !isSquare( dm ) ) {
2222  BLAZE_THROW_INVALID_ARGUMENT( "Invalid lower matrix specification" );
2223  }
2224 
2226  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2227 }
2229 //*************************************************************************************************
2230 
2231 
2232 //*************************************************************************************************
2257 template< typename MT1 // Type of the left-hand side dense matrix
2258  , typename MT2 // Type of the right-hand side dense matrix
2259  , bool SF // Symmetry flag
2260  , bool HF // Hermitian flag
2261  , bool LF // Lower flag
2262  , bool UF > // Upper flag
2263 inline decltype(auto) declupp( const TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2264 {
2266 
2267  if( !isSquare( dm ) ) {
2268  BLAZE_THROW_INVALID_ARGUMENT( "Invalid upper matrix specification" );
2269  }
2270 
2272  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2273 }
2275 //*************************************************************************************************
2276 
2277 
2278 //*************************************************************************************************
2303 template< typename MT1 // Type of the left-hand side dense matrix
2304  , typename MT2 // Type of the right-hand side dense matrix
2305  , bool SF // Symmetry flag
2306  , bool HF // Hermitian flag
2307  , bool LF // Lower flag
2308  , bool UF > // Upper flag
2309 inline decltype(auto) decldiag( const TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2310 {
2312 
2313  if( !isSquare( dm ) ) {
2314  BLAZE_THROW_INVALID_ARGUMENT( "Invalid diagonal matrix specification" );
2315  }
2316 
2318  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2319 }
2321 //*************************************************************************************************
2322 
2323 
2324 
2325 
2326 //=================================================================================================
2327 //
2328 // ROWS SPECIALIZATIONS
2329 //
2330 //=================================================================================================
2331 
2332 //*************************************************************************************************
2334 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2335 struct Rows< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2336  : public Rows<MT1>
2337 {};
2339 //*************************************************************************************************
2340 
2341 
2342 
2343 
2344 //=================================================================================================
2345 //
2346 // COLUMNS SPECIALIZATIONS
2347 //
2348 //=================================================================================================
2349 
2350 //*************************************************************************************************
2352 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2353 struct Columns< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2354  : public Columns<MT2>
2355 {};
2357 //*************************************************************************************************
2358 
2359 
2360 
2361 
2362 //=================================================================================================
2363 //
2364 // ISALIGNED SPECIALIZATIONS
2365 //
2366 //=================================================================================================
2367 
2368 //*************************************************************************************************
2370 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2371 struct IsAligned< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2372  : public BoolConstant< IsAligned<MT1>::value >
2373 {};
2375 //*************************************************************************************************
2376 
2377 
2378 
2379 
2380 //=================================================================================================
2381 //
2382 // ISSYMMETRIC SPECIALIZATIONS
2383 //
2384 //=================================================================================================
2385 
2386 //*************************************************************************************************
2388 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2389 struct IsSymmetric< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2390  : public BoolConstant< Or< Bool<SF>
2391  , And< Bool<HF>
2392  , IsBuiltin< ElementType_< TDMatSMatMultExpr<MT1,MT2,false,true,false,false> > > >
2393  , And< Bool<LF>, Bool<UF> > >::value >
2394 {};
2396 //*************************************************************************************************
2397 
2398 
2399 
2400 
2401 //=================================================================================================
2402 //
2403 // ISHERMITIAN SPECIALIZATIONS
2404 //
2405 //=================================================================================================
2406 
2407 //*************************************************************************************************
2409 template< typename MT1, typename MT2, bool SF, bool LF, bool UF >
2410 struct IsHermitian< TDMatSMatMultExpr<MT1,MT2,SF,true,LF,UF> >
2411  : public TrueType
2412 {};
2414 //*************************************************************************************************
2415 
2416 
2417 
2418 
2419 //=================================================================================================
2420 //
2421 // ISLOWER SPECIALIZATIONS
2422 //
2423 //=================================================================================================
2424 
2425 //*************************************************************************************************
2427 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2428 struct IsLower< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2429  : public BoolConstant< Or< Bool<LF>
2430  , And< IsLower<MT1>, IsLower<MT2> >
2431  , And< Or< Bool<SF>, Bool<HF> >
2432  , IsUpper<MT1>, IsUpper<MT2> > >::value >
2433 {};
2435 //*************************************************************************************************
2436 
2437 
2438 
2439 
2440 //=================================================================================================
2441 //
2442 // ISUNILOWER SPECIALIZATIONS
2443 //
2444 //=================================================================================================
2445 
2446 //*************************************************************************************************
2448 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2449 struct IsUniLower< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2450  : public BoolConstant< Or< And< IsUniLower<MT1>, IsUniLower<MT2> >
2451  , And< Or< Bool<SF>, Bool<HF> >
2452  , IsUniUpper<MT1>, IsUniUpper<MT2> > >::value >
2453 {};
2455 //*************************************************************************************************
2456 
2457 
2458 
2459 
2460 //=================================================================================================
2461 //
2462 // ISSTRICTLYLOWER SPECIALIZATIONS
2463 //
2464 //=================================================================================================
2465 
2466 //*************************************************************************************************
2468 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2469 struct IsStrictlyLower< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2470  : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
2471  , And< IsStrictlyLower<MT2>, IsLower<MT1> >
2472  , And< Or< Bool<SF>, Bool<HF> >
2473  , Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
2474  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > > > >::value >
2475 {};
2477 //*************************************************************************************************
2478 
2479 
2480 
2481 
2482 //=================================================================================================
2483 //
2484 // ISUPPER SPECIALIZATIONS
2485 //
2486 //=================================================================================================
2487 
2488 //*************************************************************************************************
2490 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2491 struct IsUpper< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2492  : public BoolConstant< Or< Bool<UF>
2493  , And< IsUpper<MT1>, IsUpper<MT2> >
2494  , And< Or< Bool<SF>, Bool<HF> >
2495  , IsLower<MT1>, IsLower<MT2> > >::value >
2496 {};
2498 //*************************************************************************************************
2499 
2500 
2501 
2502 
2503 //=================================================================================================
2504 //
2505 // ISUNIUPPER SPECIALIZATIONS
2506 //
2507 //=================================================================================================
2508 
2509 //*************************************************************************************************
2511 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2512 struct IsUniUpper< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2513  : public BoolConstant< Or< And< IsUniUpper<MT1>, IsUniUpper<MT2> >
2514  , And< Or< Bool<SF>, Bool<HF> >
2515  , IsUniLower<MT1>, IsUniLower<MT2> > >::value >
2516 {};
2518 //*************************************************************************************************
2519 
2520 
2521 
2522 
2523 //=================================================================================================
2524 //
2525 // ISSTRICTLYUPPER SPECIALIZATIONS
2526 //
2527 //=================================================================================================
2528 
2529 //*************************************************************************************************
2531 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2532 struct IsStrictlyUpper< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2533  : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
2534  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> >
2535  , And< Or< Bool<SF>, Bool<HF> >
2536  , Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
2537  , And< IsStrictlyLower<MT2>, IsLower<MT1> > > > >::value >
2538 {};
2540 //*************************************************************************************************
2541 
2542 } // namespace blaze
2543 
2544 #endif
#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
If_< IsExpression< MT2 >, const MT2, const MT2 &> RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: TDMatSMatMultExpr.h:249
Header file for auxiliary alias declarations.
Headerfile for the generic min algorithm.
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:72
decltype(auto) decldiag(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as diagonal.
Definition: DMatDeclDiagExpr.h:996
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: TDMatSMatMultExpr.h:352
Header file for the Rows type trait.
Header file for the IsUniUpper type trait.
EnableIf_< IsDenseMatrix< MT1 > > smpSchurAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP Schur product assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:196
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: TDMatSMatMultExpr.h:288
Compile time check for triangular matrix types.This type trait tests whether or not the given templat...
Definition: IsTriangular.h:87
Header file for basic type definitions.
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: TDMatSMatMultExpr.h:336
LeftOperand leftOperand() const noexcept
Returns the left-hand side transpose dense matrix operand.
Definition: TDMatSMatMultExpr.h:372
Subvector< VT, AF > subvector(Vector< VT, TF > &vector, size_t index, size_t size)
Creating a view on a specific subvector of the given vector.
Definition: Subvector.h:322
EnableIf_< IsDenseMatrix< MT1 > > smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:164
Header file for the serial shim.
Header file for the IsDiagonal type trait.
Generic wrapper for a compile time constant integral value.The IntegralConstant class template repres...
Definition: IntegralConstant.h:71
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional matrix type...
Definition: DenseMatrix.h:61
Header file for the DeclUpp functor.
BLAZE_ALWAYS_INLINE MT::Iterator begin(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator to the first element of row/column i.
Definition: Matrix.h:198
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:560
RightOperand rightOperand() const noexcept
Returns the right-hand side sparse matrix operand.
Definition: TDMatSMatMultExpr.h:382
typename DisableIf< Condition, T >::Type DisableIf_
Auxiliary type for the DisableIf class template.The DisableIf_ alias declaration provides a convenien...
Definition: DisableIf.h:224
Header file for the And class template.
const ElementType_< MT > min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1762
Compile time check for lower triangular matrices.This type trait tests whether or not the given templ...
Definition: IsLower.h:88
decltype(auto) declupp(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as upper.
Definition: DMatDeclUppExpr.h:1027
typename MultTrait< T1, T2 >::Type MultTrait_
Auxiliary alias declaration for the MultTrait class template.The MultTrait_ alias declaration provide...
Definition: MultTrait.h:250
Column< MT > column(Matrix< MT, SO > &matrix, size_t index)
Creating a view on a specific column of the given matrix.
Definition: Column.h:124
Header file for the Computation base class.
Header file for the MatMatMultExpr base class.
Compile time check for upper triangular matrices.This type trait tests whether or not the given templ...
Definition: IsUpper.h:88
Constraints on the storage order of matrix types.
Header file for the RequiresEvaluation type trait.
System settings for performance optimizations.
Expression object for transpose dense matrix-sparse matrix multiplications.The TDMatSMatMultExpr clas...
Definition: Forward.h:151
Header file for the IsUniLower type trait.
CompositeType_< MT2 > CT2
Composite type of the right-hand side sparse matrix expression.
Definition: TDMatSMatMultExpr.h:135
typename T::ResultType ResultType_
Alias declaration for nested ResultType type definitions.The ResultType_ alias declaration provides a...
Definition: Aliases.h:343
const ElementType_< MT > max(const DenseMatrix< MT, SO > &dm)
Returns the largest element of the dense matrix.
Definition: DenseMatrix.h:1809
EnableIf_< IsDenseMatrix< MT1 > > smpAddAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:133
const ResultType CompositeType
Data type for composite expression templates.
Definition: TDMatSMatMultExpr.h:243
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:78
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes...
Definition: Forward.h:129
typename IfTrue< Condition, T1, T2 >::Type IfTrue_
Auxiliary alias declaration for the IfTrue class template.The IfTrue_ alias declaration provides a co...
Definition: If.h:109
ElementType_< RT2 > ET2
Element type of the right-hand side sparse matrix expression.
Definition: TDMatSMatMultExpr.h:133
Row< MT > row(Matrix< MT, SO > &matrix, size_t index)
Creating a view on a specific row of the given matrix.
Definition: Row.h:124
Compile time check for the alignment of data types.This type trait tests whether the given data type ...
Definition: IsAligned.h:87
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: TDMatSMatMultExpr.h:434
Constraint on the data type.
Constraint on the data type.
Compile time check to query the requirement to evaluate an expression.Via this type trait it is possi...
Definition: RequiresEvaluation.h:72
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: TDMatSMatMultExpr.h:394
typename T::CompositeType CompositeType_
Alias declaration for nested CompositeType type definitions.The CompositeType_ alias declaration prov...
Definition: Aliases.h:83
Compile time check for upper unitriangular matrices.This type trait tests whether or not the given te...
Definition: IsUniUpper.h:86
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:57
Header file for the DeclLow functor.
Header file for the If class template.
#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a column-major dense or sparse matri...
Definition: ColumnMajorMatrix.h:61
Generic wrapper for the decllow() function.
Definition: DeclLow.h:58
EnableIf_< IsDenseMatrix< MT1 > > smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:102
Header file for the Or class template.
Flag for lower matrices.
Definition: TDMatSMatMultExpr.h:153
#define BLAZE_THROW_OUT_OF_RANGE(MESSAGE)
Macro for the emission of a std::out_of_range exception.This macro encapsulates the default way of Bl...
Definition: Exception.h:331
Header file for the DenseMatrix base class.
Header file for the Columns type trait.
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:3087
typename T::ElementType ElementType_
Alias declaration for nested ElementType type definitions.The ElementType_ alias declaration provides...
Definition: Aliases.h:163
decltype(auto) decllow(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as lower.
Definition: DMatDeclLowExpr.h:1027
Header file for the IsLower type trait.
Header file for the IsAligned type trait.
Compile time check for diagonal matrices.This type trait tests whether or not the given template para...
Definition: IsDiagonal.h:90
ResultType_< MT2 > RT2
Result type of the right-hand side sparse matrix expression.
Definition: TDMatSMatMultExpr.h:131
Generic wrapper for the null function.
Definition: Noop.h:58
Header file for the IsTriangular type trait.
ResultType_< MT1 > RT1
Result type of the left-hand side dense matrix expression.
Definition: TDMatSMatMultExpr.h:130
Constraints on the storage order of matrix types.
Compile time check for symmetric matrices.This type trait tests whether or not the given template par...
Definition: IsSymmetric.h:85
Header file for the exception macros of the math module.
Compile time check for strictly upper triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyUpper.h:86
CompositeType_< MT1 > CT1
Composite type of the left-hand side dense matrix expression.
Definition: TDMatSMatMultExpr.h:134
ElementType_< RT1 > ET1
Element type of the left-hand side dense matrix expression.
Definition: TDMatSMatMultExpr.h:132
BLAZE_ALWAYS_INLINE MT::Iterator end(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator just past the last element of row/column i.
Definition: Matrix.h:264
Header file for the DeclDiag functor.
bool isAligned() const noexcept
Returns whether the operands of the expression are properly aligned in memory.
Definition: TDMatSMatMultExpr.h:416
Constraint on the data type.
Header file for all forward declarations for expression class templates.
OppositeType_< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: TDMatSMatMultExpr.h:239
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:108
Compile time check for lower unitriangular matrices.This type trait tests whether or not the given te...
Definition: IsUniLower.h:86
Header file for the conjugate shim.
Compile time check for resizable data types.This type trait tests whether the given data type is a re...
Definition: IsResizable.h:75
IfTrue_< evaluateLeft, const RT1, CT1 > LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: TDMatSMatMultExpr.h:252
#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
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TDMatSMatMultExpr.h:242
Header file for run time assertion macros.
TDMatSMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the TDMatSMatMultExpr class.
Definition: TDMatSMatMultExpr.h:273
Compile time check for column-major matrix types.This type trait tests whether or not the given templ...
Definition: IsColumnMajorMatrix.h:110
Utility type for generic codes.
MultTrait_< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: TDMatSMatMultExpr.h:238
typename If< T1, T2, T3 >::Type If_
Auxiliary alias declaration for the If class template.The If_ alias declaration provides a convenient...
Definition: If.h:154
Header file for the reset shim.
#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_< ResultType > ElementType
Resulting element type.
Definition: TDMatSMatMultExpr.h:241
LeftOperand lhs_
Left-hand side dense matrix of the multiplication expression.
Definition: TDMatSMatMultExpr.h:433
decltype(auto) declsym(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as symmetric.
Definition: DMatDeclSymExpr.h:1029
Header file for the isDefault shim.
Compile time check for Hermitian matrices.This type trait tests whether or not the given template par...
Definition: IsHermitian.h:85
Base class for matrices.The Matrix class is a base class for all dense and sparse matrix classes with...
Definition: Forward.h:101
Flag for Hermitian matrices.
Definition: TDMatSMatMultExpr.h:152
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:819
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
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: TDMatSMatMultExpr.h:362
typename EnableIf< Condition, T >::Type EnableIf_
Auxiliary alias declaration for the EnableIf class template.The EnableIf_ alias declaration provides ...
Definition: EnableIf.h:224
typename T::OppositeType OppositeType_
Alias declaration for nested OppositeType type definitions.The OppositeType_ alias declaration provid...
Definition: Aliases.h:263
#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
Compile time check for strictly lower triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyLower.h:86
const Type & ReturnType
Return type for expression template evaluations.
Definition: CompressedMatrix.h:3082
typename T::ConstIterator ConstIterator_
Alias declaration for nested ConstIterator type definitions.The ConstIterator_ alias declaration prov...
Definition: Aliases.h:103
decltype(auto) trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:790
decltype(auto) declherm(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as Hermitian.
Definition: DMatDeclHermExpr.h:1029
If_< IsExpression< MT1 >, const MT1, const MT1 &> LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: TDMatSMatMultExpr.h:246
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: TDMatSMatMultExpr.h:406
Header file for the IsComputation type trait class.
Header file for the IsBuiltin type trait.
Flag for upper matrices.
Definition: TDMatSMatMultExpr.h:154
IfTrue_< evaluateRight, const RT2, CT2 > RT
Type for the assignment of the right-hand side sparse matrix operand.
Definition: TDMatSMatMultExpr.h:255
Header file for the IntegralConstant class template.
Compile time evaluation of the number of columns of a matrix.The Columns type trait evaluates the num...
Definition: Columns.h:75
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: TDMatSMatMultExpr.h:426
Generic wrapper for the decldiag() function.
Definition: DeclDiag.h:58
Compile time evaluation of the number of rows of a matrix.The Rows type trait evaluates the number of...
Definition: Rows.h:75
Header file for the DeclHerm functor.
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:600
typename T::TransposeType TransposeType_
Alias declaration for nested TransposeType type definitions.The TransposeType_ alias declaration prov...
Definition: Aliases.h:423
Header file for the IsUpper type trait.
decltype(auto) conj(const DenseMatrix< MT, SO > &dm)
Returns a matrix containing the complex conjugate of each single element of dm.
Definition: DMatMapExpr.h:1321
Constraint on the data type.
Flag for symmetric matrices.
Definition: TDMatSMatMultExpr.h:151
Generic wrapper for the declsym() function.
Definition: DeclSym.h:58
BLAZE_ALWAYS_INLINE bool isSquare(const Matrix< MT, SO > &matrix) noexcept
Checks if the given matrix is a square matrix.
Definition: Matrix.h:742
Header file for the IsResizable type trait.
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 Bool class template.
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.
TransposeType_< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: TDMatSMatMultExpr.h:240
Header file for the function trace functionality.