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>
84 #include <blaze/math/views/Check.h>
89 #include <blaze/util/Assert.h>
90 #include <blaze/util/DisableIf.h>
91 #include <blaze/util/EnableIf.h>
93 #include <blaze/util/mpl/And.h>
94 #include <blaze/util/mpl/Bool.h>
95 #include <blaze/util/mpl/If.h>
96 #include <blaze/util/mpl/Or.h>
97 #include <blaze/util/Types.h>
99 
100 
101 namespace blaze {
102 
103 //=================================================================================================
104 //
105 // CLASS TDMATSMATMULTEXPR
106 //
107 //=================================================================================================
108 
109 //*************************************************************************************************
116 template< typename MT1 // Type of the left-hand side dense matrix
117  , typename MT2 // Type of the right-hand side sparse matrix
118  , bool SF // Symmetry flag
119  , bool HF // Hermitian flag
120  , bool LF // Lower flag
121  , bool UF > // Upper flag
122 class TDMatSMatMultExpr
123  : public MatMatMultExpr< DenseMatrix< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>, true > >
124  , private Computation
125 {
126  private:
127  //**Type definitions****************************************************************************
134  //**********************************************************************************************
135 
136  //**********************************************************************************************
138  enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
139  //**********************************************************************************************
140 
141  //**********************************************************************************************
143  enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
144  //**********************************************************************************************
145 
146  //**********************************************************************************************
148  enum : bool {
149  SYM = ( SF && !( HF || LF || UF ) ),
150  HERM = ( HF && !( LF || UF ) ),
151  LOW = ( LF || ( ( SF || HF ) && UF ) ),
152  UPP = ( UF || ( ( SF || HF ) && LF ) )
153  };
154  //**********************************************************************************************
155 
156  //**********************************************************************************************
158 
163  template< typename T1, typename T2, typename T3 >
164  struct CanExploitSymmetry {
165  enum : bool { value = IsSymmetric<T3>::value };
166  };
168  //**********************************************************************************************
169 
170  //**********************************************************************************************
172 
176  template< typename T1, typename T2, typename T3 >
177  struct IsEvaluationRequired {
178  enum : bool { value = ( evaluateLeft || evaluateRight ) &&
179  !CanExploitSymmetry<T1,T2,T3>::value };
180  };
182  //**********************************************************************************************
183 
184  //**********************************************************************************************
186 
190  template< typename T1, typename T2, typename T3 >
191  struct UseOptimizedKernel {
192  enum : bool { value = useOptimizedKernels &&
194  !IsResizable< ElementType_<T1> >::value &&
196  };
198  //**********************************************************************************************
199 
200  //**********************************************************************************************
202 
205  template< typename T1, typename T2, typename T3 >
206  struct UseDefaultKernel {
207  enum : bool { value = !UseOptimizedKernel<T1,T2,T3>::value };
208  };
210  //**********************************************************************************************
211 
212  //**********************************************************************************************
214 
217  using ForwardFunctor = IfTrue_< HERM
218  , DeclHerm
219  , IfTrue_< SYM
220  , DeclSym
221  , IfTrue_< LOW
222  , IfTrue_< UPP
223  , DeclDiag
224  , DeclLow >
225  , IfTrue_< UPP
226  , DeclUpp
227  , Noop > > > >;
229  //**********************************************************************************************
230 
231  public:
232  //**Type definitions****************************************************************************
235 
240  using ReturnType = const ElementType;
241  using CompositeType = const ResultType;
242 
244  using LeftOperand = If_< IsExpression<MT1>, const MT1, const MT1& >;
245 
247  using RightOperand = If_< IsExpression<MT2>, const MT2, const MT2& >;
248 
251 
254  //**********************************************************************************************
255 
256  //**Compilation flags***************************************************************************
258  enum : bool { simdEnabled = false };
259 
261  enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
262  !evaluateRight && MT2::smpAssignable };
263  //**********************************************************************************************
264 
265  //**Constructor*********************************************************************************
271  explicit inline TDMatSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
272  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
273  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
274  {
275  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
276  }
277  //**********************************************************************************************
278 
279  //**Access operator*****************************************************************************
286  inline ReturnType operator()( size_t i, size_t j ) const {
287  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
288  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
289 
290  if( IsDiagonal<MT1>::value ) {
291  return lhs_(i,i) * rhs_(i,j);
292  }
293  else if( IsDiagonal<MT2>::value ) {
294  return lhs_(i,j) * rhs_(j,j);
295  }
297  const size_t begin( ( IsUpper<MT1>::value )
298  ?( ( IsLower<MT2>::value )
299  ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
300  , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
301  :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
302  :( ( IsLower<MT2>::value )
303  ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
304  :( 0UL ) ) );
305  const size_t end( ( IsLower<MT1>::value )
306  ?( ( IsUpper<MT2>::value )
307  ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
308  , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
309  :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
310  :( ( IsUpper<MT2>::value )
311  ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
312  :( lhs_.columns() ) ) );
313 
314  if( begin >= end ) return ElementType();
315 
316  const size_t n( end - begin );
317 
318  return subvector( row( lhs_, i, unchecked ), begin, n, unchecked ) *
319  subvector( column( rhs_, j, unchecked ), begin, n, unchecked );
320  }
321  else {
322  return row( lhs_, i, unchecked ) * column( rhs_, j, unchecked );
323  }
324  }
325  //**********************************************************************************************
326 
327  //**At function*********************************************************************************
335  inline ReturnType at( size_t i, size_t j ) const {
336  if( i >= lhs_.rows() ) {
337  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
338  }
339  if( j >= rhs_.columns() ) {
340  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
341  }
342  return (*this)(i,j);
343  }
344  //**********************************************************************************************
345 
346  //**Rows function*******************************************************************************
351  inline size_t rows() const noexcept {
352  return lhs_.rows();
353  }
354  //**********************************************************************************************
355 
356  //**Columns function****************************************************************************
361  inline size_t columns() const noexcept {
362  return rhs_.columns();
363  }
364  //**********************************************************************************************
365 
366  //**Left operand access*************************************************************************
371  inline LeftOperand leftOperand() const noexcept {
372  return lhs_;
373  }
374  //**********************************************************************************************
375 
376  //**Right operand access************************************************************************
381  inline RightOperand rightOperand() const noexcept {
382  return rhs_;
383  }
384  //**********************************************************************************************
385 
386  //**********************************************************************************************
392  template< typename T >
393  inline bool canAlias( const T* alias ) const noexcept {
394  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
395  }
396  //**********************************************************************************************
397 
398  //**********************************************************************************************
404  template< typename T >
405  inline bool isAliased( const T* alias ) const {
406  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
407  }
408  //**********************************************************************************************
409 
410  //**********************************************************************************************
415  inline bool isAligned() const noexcept {
416  return lhs_.isAligned();
417  }
418  //**********************************************************************************************
419 
420  //**********************************************************************************************
425  inline bool canSMPAssign() const noexcept {
426  return ( rows() * columns() >= SMP_TDMATSMATMULT_THRESHOLD ) && !IsDiagonal<MT1>::value;
427  }
428  //**********************************************************************************************
429 
430  private:
431  //**Member variables****************************************************************************
434  //**********************************************************************************************
435 
436  //**Assignment to dense matrices****************************************************************
449  template< typename MT // Type of the target dense matrix
450  , bool SO > // Storage order of the target dense matrix
452  assign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
453  {
455 
456  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
457  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
458 
459  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
460  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
461 
462  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
463  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
464  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
465  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
466  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
467  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
468 
469  TDMatSMatMultExpr::selectAssignKernel( ~lhs, A, B );
470  }
472  //**********************************************************************************************
473 
474  //**Assignment to dense matrices (kernel selection)*********************************************
485  template< typename MT3 // Type of the left-hand side target matrix
486  , typename MT4 // Type of the left-hand side matrix operand
487  , typename MT5 > // Type of the right-hand side matrix operand
488  static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
489  {
490  if( C.rows() * C.columns() < TDMATSMATMULT_THRESHOLD )
491  selectSmallAssignKernel( C, A, B );
492  else
493  selectLargeAssignKernel( C, A, B );
494  }
496  //**********************************************************************************************
497 
498  //**Default assignment to dense matrices********************************************************
513  template< typename MT3 // Type of the left-hand side target matrix
514  , typename MT4 // Type of the left-hand side matrix operand
515  , typename MT5 > // Type of the right-hand side matrix operand
516  static inline void selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
517  {
519 
520  reset( C );
521 
522  for( size_t j=0UL; j<B.rows(); ++j )
523  {
524  ConstIterator element( B.begin(j) );
525  const ConstIterator end( B.end(j) );
526 
528  {
529  for( ; element!=end; ++element ) {
530  C(j,element->index()) = A(j,j) * element->value();
531  }
532  }
533  else
534  {
535  for( ; element!=end; ++element )
536  {
537  const size_t j1( element->index() );
538 
539  const size_t ibegin( ( IsLower<MT4>::value )
541  ?( SYM || HERM || LOW ? max(j1,j+1UL) : j+1UL )
542  :( SYM || HERM || LOW ? max(j1,j) : j ) )
543  :( SYM || HERM || LOW ? j1 : 0UL ) );
544  const size_t iend( ( IsUpper<MT4>::value )
546  ?( UPP ? min(j1+1UL,j) : j )
547  :( UPP ? min(j1,j)+1UL : j+1UL ) )
548  :( UPP ? j1+1UL : A.rows() ) );
549 
550  if( ( SYM || HERM || LOW || UPP ) && ( ibegin >= iend ) ) continue;
551  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
552 
553  for( size_t i=ibegin; i<iend; ++i ) {
554  if( isDefault( C(i,j1) ) )
555  C(i,j1) = A(i,j) * element->value();
556  else
557  C(i,j1) += A(i,j) * element->value();
558  }
559  }
560  }
561  }
562 
563  if( SYM || HERM ) {
564  for( size_t j=1UL; j<B.columns(); ++j ) {
565  for( size_t i=0UL; i<j; ++i ) {
566  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
567  }
568  }
569  }
570  }
572  //**********************************************************************************************
573 
574  //**Default assignment to dense matrices (small matrices)***************************************
588  template< typename MT3 // Type of the left-hand side target matrix
589  , typename MT4 // Type of the left-hand side matrix operand
590  , typename MT5 > // Type of the right-hand side matrix operand
592  selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
593  {
594  selectDefaultAssignKernel( C, A, B );
595  }
597  //**********************************************************************************************
598 
599  //**Optimized assignment to dense matrices (small matrices)*************************************
614  template< typename MT3 // Type of the left-hand side target matrix
615  , typename MT4 // Type of the left-hand side matrix operand
616  , typename MT5 > // Type of the right-hand side matrix operand
618  selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
619  {
621 
622  reset( C );
623 
624  for( size_t j=0UL; j<B.rows(); ++j )
625  {
626  ConstIterator element( B.begin(j) );
627  const ConstIterator end( B.end(j) );
628 
629  const size_t nonzeros( B.nonZeros(j) );
630  const size_t kpos( nonzeros & size_t(-4) );
631  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
632 
633  for( size_t k=0UL; k<kpos; k+=4UL )
634  {
635  const size_t j1( element->index() );
636  const ET2 v1( element->value() );
637  ++element;
638  const size_t j2( element->index() );
639  const ET2 v2( element->value() );
640  ++element;
641  const size_t j3( element->index() );
642  const ET2 v3( element->value() );
643  ++element;
644  const size_t j4( element->index() );
645  const ET2 v4( element->value() );
646  ++element;
647 
648  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
649 
650  const size_t ibegin( ( IsLower<MT4>::value )
652  ?( SYM || HERM || LOW ? max(j1,j+1UL) : j+1UL )
653  :( SYM || HERM || LOW ? max(j1,j) : j ) )
654  :( SYM || HERM || LOW ? j1 : 0UL ) );
655  const size_t iend( ( IsUpper<MT4>::value )
657  ?( UPP ? min(j4+1UL,j) : j )
658  :( UPP ? min(j4,j)+1UL : j+1UL ) )
659  :( UPP ? j4+1UL : A.rows() ) );
660 
661  if( ( SYM || HERM || LOW || UPP ) && ( ibegin >= iend ) ) continue;
662  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
663 
664  const size_t inum( iend - ibegin );
665  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
666  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
667 
668  size_t i( ibegin );
669 
670  for( ; i<ipos; i+=4UL ) {
671  C(i ,j1) += A(i ,j) * v1;
672  C(i+1UL,j1) += A(i+1UL,j) * v1;
673  C(i+2UL,j1) += A(i+2UL,j) * v1;
674  C(i+3UL,j1) += A(i+3UL,j) * v1;
675  C(i ,j2) += A(i ,j) * v2;
676  C(i+1UL,j2) += A(i+1UL,j) * v2;
677  C(i+2UL,j2) += A(i+2UL,j) * v2;
678  C(i+3UL,j2) += A(i+3UL,j) * v2;
679  C(i ,j3) += A(i ,j) * v3;
680  C(i+1UL,j3) += A(i+1UL,j) * v3;
681  C(i+2UL,j3) += A(i+2UL,j) * v3;
682  C(i+3UL,j3) += A(i+3UL,j) * v3;
683  C(i ,j4) += A(i ,j) * v4;
684  C(i+1UL,j4) += A(i+1UL,j) * v4;
685  C(i+2UL,j4) += A(i+2UL,j) * v4;
686  C(i+3UL,j4) += A(i+3UL,j) * v4;
687  }
688  for( ; i<iend; ++i ) {
689  C(i,j1) += A(i,j) * v1;
690  C(i,j2) += A(i,j) * v2;
691  C(i,j3) += A(i,j) * v3;
692  C(i,j4) += A(i,j) * v4;
693  }
694  }
695 
696  for( ; element!=end; ++element )
697  {
698  const size_t j1( element->index() );
699  const ET2 v1( element->value() );
700 
701  const size_t ibegin( ( IsLower<MT4>::value )
703  ?( SYM || HERM || LOW ? max(j1,j+1UL) : j+1UL )
704  :( SYM || HERM || LOW ? max(j1,j) : j ) )
705  :( SYM || HERM || LOW ? j1 : 0UL ) );
706  const size_t iend( ( IsUpper<MT4>::value )
708  ?( UPP ? min(j1+1UL,j) : j )
709  :( UPP ? min(j1,j)+1UL : j+1UL ) )
710  :( UPP ? j1+1UL : A.rows() ) );
711 
712  if( ( SYM || HERM || LOW || UPP ) && ( ibegin >= iend ) ) continue;
713  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
714 
715  const size_t inum( iend - ibegin );
716  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
717  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
718 
719  size_t i( ibegin );
720 
721  for( ; i<ipos; i+=4UL ) {
722  C(i ,j1) += A(i ,j) * v1;
723  C(i+1UL,j1) += A(i+1UL,j) * v1;
724  C(i+2UL,j1) += A(i+2UL,j) * v1;
725  C(i+3UL,j1) += A(i+3UL,j) * v1;
726  }
727  for( ; i<iend; ++i ) {
728  C(i,j1) += A(i,j) * v1;
729  }
730  }
731  }
732 
733  if( SYM || HERM ) {
734  for( size_t j=1UL; j<B.columns(); ++j ) {
735  for( size_t i=0UL; i<j; ++i ) {
736  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
737  }
738  }
739  }
740  }
742  //**********************************************************************************************
743 
744  //**Default assignment to dense matrices (large matrices)***************************************
758  template< typename MT3 // Type of the left-hand side target matrix
759  , typename MT4 // Type of the left-hand side matrix operand
760  , typename MT5 > // Type of the right-hand side matrix operand
762  selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
763  {
764  selectDefaultAssignKernel( C, A, B );
765  }
767  //**********************************************************************************************
768 
769  //**Optimized assignment to dense matrices (large matrices)*************************************
784  template< typename MT3 // Type of the left-hand side target matrix
785  , typename MT4 // Type of the left-hand side matrix operand
786  , typename MT5 > // Type of the right-hand side matrix operand
788  selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
789  {
791 
792  const ForwardFunctor fwd;
793 
794  const OppositeType_<MT5> tmp( serial( B ) );
795  assign( C, fwd( A * tmp ) );
796  }
798  //**********************************************************************************************
799 
800  //**Assignment to sparse matrices***************************************************************
813  template< typename MT // Type of the target sparse matrix
814  , bool SO > // Storage order of the target sparse matrix
816  assign( SparseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
817  {
819 
821 
828 
829  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
830  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
831 
832  const ForwardFunctor fwd;
833 
834  const TmpType tmp( serial( rhs ) );
835  assign( ~lhs, fwd( tmp ) );
836  }
838  //**********************************************************************************************
839 
840  //**Restructuring assignment********************************************************************
855  template< typename MT // Type of the target matrix
856  , bool SO > // Storage order of the target matrix
858  assign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
859  {
861 
863 
864  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
865  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
866 
867  const ForwardFunctor fwd;
868 
869  assign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
870  }
872  //**********************************************************************************************
873 
874  //**Addition assignment to dense matrices*******************************************************
887  template< typename MT // Type of the target dense matrix
888  , bool SO > // Storage order of the target dense matrix
890  addAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
891  {
893 
894  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
895  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
896 
897  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
898  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
899 
900  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
901  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
902  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
903  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
904  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
905  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
906 
907  TDMatSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
908  }
910  //**********************************************************************************************
911 
912  //**Addition assignment to dense matrices (kernel selection)************************************
923  template< typename MT3 // Type of the left-hand side target matrix
924  , typename MT4 // Type of the left-hand side matrix operand
925  , typename MT5 > // Type of the right-hand side matrix operand
926  static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
927  {
928  if( C.rows() * C.columns() < TDMATSMATMULT_THRESHOLD )
929  selectSmallAddAssignKernel( C, A, B );
930  else
931  selectLargeAddAssignKernel( C, A, B );
932  }
934  //**********************************************************************************************
935 
936  //**Default addition assignment to dense matrices***********************************************
951  template< typename MT3 // Type of the left-hand side target matrix
952  , typename MT4 // Type of the left-hand side matrix operand
953  , typename MT5 > // Type of the right-hand side matrix operand
954  static inline void selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
955  {
957 
958  size_t i( 0UL );
959 
960  for( size_t j=0UL; j<B.rows(); ++j )
961  {
962  ConstIterator element( B.begin(j) );
963  const ConstIterator end( B.end(j) );
964 
966  {
967  for( ; element!=end; ++element ) {
968  C(j,element->index()) += A(j,j) * element->value();
969  }
970  }
971  else
972  {
973  for( ; element!=end; ++element )
974  {
975  const size_t j1( element->index() );
976 
977  const size_t ibegin( ( IsLower<MT4>::value )
979  ?( LOW ? max(j1,j+1UL) : j+1UL )
980  :( LOW ? max(j1,j) : j ) )
981  :( LOW ? j1 : 0UL ) );
982  const size_t iend( ( IsUpper<MT4>::value )
984  ?( UPP ? min(j1+1UL,j) : j )
985  :( UPP ? min(j1,j)+1UL : j+1UL ) )
986  :( UPP ? j1+1UL : A.rows() ) );
987 
988  if( ( LOW || UPP ) && ( ibegin >= iend ) ) continue;
989  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
990 
991  const size_t inum( iend - ibegin );
992  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
993  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
994 
995  for( i=ibegin; i<ipos; i+=4UL ) {
996  C(i ,j1) += A(i ,j) * element->value();
997  C(i+1UL,j1) += A(i+1UL,j) * element->value();
998  C(i+2UL,j1) += A(i+2UL,j) * element->value();
999  C(i+3UL,j1) += A(i+3UL,j) * element->value();
1000  }
1001  for( ; i<iend; ++i ) {
1002  C(i,j1) += A(i,j) * element->value();
1003  }
1004  }
1005  }
1006  }
1007  }
1009  //**********************************************************************************************
1010 
1011  //**Default addition assignment to dense matrices (small matrices)******************************
1025  template< typename MT3 // Type of the left-hand side target matrix
1026  , typename MT4 // Type of the left-hand side matrix operand
1027  , typename MT5 > // Type of the right-hand side matrix operand
1029  selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1030  {
1031  selectDefaultAddAssignKernel( C, A, B );
1032  }
1034  //**********************************************************************************************
1035 
1036  //**Optimized addition assignment to dense matrices (small matrices)****************************
1051  template< typename MT3 // Type of the left-hand side target matrix
1052  , typename MT4 // Type of the left-hand side matrix operand
1053  , typename MT5 > // Type of the right-hand side matrix operand
1055  selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1056  {
1058 
1059  for( size_t j=0UL; j<B.rows(); ++j )
1060  {
1061  ConstIterator element( B.begin(j) );
1062  const ConstIterator end( B.end(j) );
1063 
1064  const size_t nonzeros( B.nonZeros(j) );
1065  const size_t kpos( nonzeros & size_t(-4) );
1066  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1067 
1068  for( size_t k=0UL; k<kpos; k+=4UL )
1069  {
1070  const size_t j1( element->index() );
1071  const ET2 v1( element->value() );
1072  ++element;
1073  const size_t j2( element->index() );
1074  const ET2 v2( element->value() );
1075  ++element;
1076  const size_t j3( element->index() );
1077  const ET2 v3( element->value() );
1078  ++element;
1079  const size_t j4( element->index() );
1080  const ET2 v4( element->value() );
1081  ++element;
1082 
1083  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1084 
1085  const size_t ibegin( ( IsLower<MT4>::value )
1087  ?( LOW ? max(j1,j+1UL) : j+1UL )
1088  :( LOW ? max(j1,j) : j ) )
1089  :( LOW ? j1 : 0UL ) );
1090  const size_t iend( ( IsUpper<MT4>::value )
1092  ?( UPP ? min(j4+1UL,j) : j )
1093  :( UPP ? min(j4,j)+1UL : j+1UL ) )
1094  :( UPP ? j4+1UL : A.rows() ) );
1095 
1096  if( ( LOW || UPP ) && ( ibegin >= iend ) ) continue;
1097  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
1098 
1099  const size_t inum( iend - ibegin );
1100  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
1101  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
1102 
1103  size_t i( ibegin );
1104 
1105  for( i=ibegin; i<ipos; i+=4UL ) {
1106  C(i ,j1) += A(i ,j) * v1;
1107  C(i+1UL,j1) += A(i+1UL,j) * v1;
1108  C(i+2UL,j1) += A(i+2UL,j) * v1;
1109  C(i+3UL,j1) += A(i+3UL,j) * v1;
1110  C(i ,j2) += A(i ,j) * v2;
1111  C(i+1UL,j2) += A(i+1UL,j) * v2;
1112  C(i+2UL,j2) += A(i+2UL,j) * v2;
1113  C(i+3UL,j2) += A(i+3UL,j) * v2;
1114  C(i ,j3) += A(i ,j) * v3;
1115  C(i+1UL,j3) += A(i+1UL,j) * v3;
1116  C(i+2UL,j3) += A(i+2UL,j) * v3;
1117  C(i+3UL,j3) += A(i+3UL,j) * v3;
1118  C(i ,j4) += A(i ,j) * v4;
1119  C(i+1UL,j4) += A(i+1UL,j) * v4;
1120  C(i+2UL,j4) += A(i+2UL,j) * v4;
1121  C(i+3UL,j4) += A(i+3UL,j) * v4;
1122  }
1123  for( ; i<iend; ++i ) {
1124  C(i,j1) += A(i,j) * v1;
1125  C(i,j2) += A(i,j) * v2;
1126  C(i,j3) += A(i,j) * v3;
1127  C(i,j4) += A(i,j) * v4;
1128  }
1129  }
1130 
1131  for( ; element!=end; ++element )
1132  {
1133  const size_t j1( element->index() );
1134  const ET2 v1( element->value() );
1135 
1136  const size_t ibegin( ( IsLower<MT4>::value )
1138  ?( LOW ? max(j1,j+1UL) : j+1UL )
1139  :( LOW ? max(j1,j) : j ) )
1140  :( LOW ? j1 : 0UL ) );
1141  const size_t iend( ( IsUpper<MT4>::value )
1143  ?( UPP ? min(j1+1UL,j) : j )
1144  :( UPP ? min(j1,j)+1UL : j+1UL ) )
1145  :( UPP ? j1+1UL : A.rows() ) );
1146 
1147  if( ( LOW || UPP ) && ( ibegin >= iend ) ) continue;
1148  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
1149 
1150  const size_t inum( iend - ibegin );
1151  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
1152  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
1153 
1154  size_t i( ibegin );
1155 
1156  for( ; i<ipos; i+=4UL ) {
1157  C(i ,j1) += A(i ,j) * v1;
1158  C(i+1UL,j1) += A(i+1UL,j) * v1;
1159  C(i+2UL,j1) += A(i+2UL,j) * v1;
1160  C(i+3UL,j1) += A(i+3UL,j) * v1;
1161  }
1162  for( ; i<iend; ++i ) {
1163  C(i,j1) += A(i,j) * v1;
1164  }
1165  }
1166  }
1167  }
1169  //**********************************************************************************************
1170 
1171  //**Default addition assignment to dense matrices (large matrices)******************************
1185  template< typename MT3 // Type of the left-hand side target matrix
1186  , typename MT4 // Type of the left-hand side matrix operand
1187  , typename MT5 > // Type of the right-hand side matrix operand
1189  selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1190  {
1191  selectDefaultAddAssignKernel( C, A, B );
1192  }
1194  //**********************************************************************************************
1195 
1196  //**Optimized addition assignment to dense matrices (large matrices)****************************
1211  template< typename MT3 // Type of the left-hand side target matrix
1212  , typename MT4 // Type of the left-hand side matrix operand
1213  , typename MT5 > // Type of the right-hand side matrix operand
1215  selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1216  {
1218 
1219  const ForwardFunctor fwd;
1220 
1221  const OppositeType_<MT5> tmp( serial( B ) );
1222  addAssign( C, fwd( A * tmp ) );
1223  }
1225  //**********************************************************************************************
1226 
1227  //**Restructuring addition assignment***********************************************************
1242  template< typename MT // Type of the target matrix
1243  , bool SO > // Storage order of the target matrix
1245  addAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1246  {
1248 
1249  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1250  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1251 
1252  const ForwardFunctor fwd;
1253 
1254  addAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1255  }
1257  //**********************************************************************************************
1258 
1259  //**Addition assignment to sparse matrices******************************************************
1260  // No special implementation for the addition assignment to sparse matrices.
1261  //**********************************************************************************************
1262 
1263  //**Subtraction assignment to dense matrices****************************************************
1276  template< typename MT // Type of the target dense matrix
1277  , bool SO > // Storage order of the target dense matrix
1279  subAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1280  {
1282 
1283  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1284  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1285 
1286  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1287  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1288 
1289  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1290  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1291  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1292  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1293  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1294  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1295 
1296  TDMatSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1297  }
1299  //**********************************************************************************************
1300 
1301  //**Subtraction assignment to dense matrices (kernel selection)*********************************
1312  template< typename MT3 // Type of the left-hand side target matrix
1313  , typename MT4 // Type of the left-hand side matrix operand
1314  , typename MT5 > // Type of the right-hand side matrix operand
1315  static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1316  {
1317  if( C.rows() * C.columns() < TDMATSMATMULT_THRESHOLD )
1318  selectSmallSubAssignKernel( C, A, B );
1319  else
1320  selectLargeSubAssignKernel( C, A, B );
1321  }
1323  //**********************************************************************************************
1324 
1325  //**Default subtraction assignment to dense matrices********************************************
1340  template< typename MT3 // Type of the left-hand side target matrix
1341  , typename MT4 // Type of the left-hand side matrix operand
1342  , typename MT5 > // Type of the right-hand side matrix operand
1343  static inline void selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1344  {
1346 
1347  size_t i( 0UL );
1348 
1349  for( size_t j=0UL; j<B.rows(); ++j )
1350  {
1351  ConstIterator element( B.begin(j) );
1352  const ConstIterator end( B.end(j) );
1353 
1355  {
1356  for( ; element!=end; ++element ) {
1357  C(j,element->index()) -= A(j,j) * element->value();
1358  }
1359  }
1360  else
1361  {
1362  for( ; element!=end; ++element )
1363  {
1364  const size_t j1( element->index() );
1365 
1366  const size_t ibegin( ( IsLower<MT4>::value )
1368  ?( LOW ? max(j1,j+1UL) : j+1UL )
1369  :( LOW ? max(j1,j) : j ) )
1370  :( LOW ? j1 : 0UL ) );
1371  const size_t iend( ( IsUpper<MT4>::value )
1373  ?( UPP ? min(j1+1UL,j) : j )
1374  :( UPP ? min(j1,j)+1UL : j+1UL ) )
1375  :( UPP ? j1+1UL : A.rows() ) );
1376 
1377  if( ( LOW || UPP ) && ( ibegin >= iend ) ) continue;
1378  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
1379 
1380  const size_t inum( iend - ibegin );
1381  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
1382  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
1383 
1384  for( i=ibegin; i<ipos; i+=4UL ) {
1385  C(i ,j1) -= A(i ,j) * element->value();
1386  C(i+1UL,j1) -= A(i+1UL,j) * element->value();
1387  C(i+2UL,j1) -= A(i+2UL,j) * element->value();
1388  C(i+3UL,j1) -= A(i+3UL,j) * element->value();
1389  }
1390  for( ; i<iend; ++i ) {
1391  C(i,j1) -= A(i,j) * element->value();
1392  }
1393  }
1394  }
1395  }
1396  }
1398  //**********************************************************************************************
1399 
1400  //**Default subtraction assignment to dense matrices (small matrices)***************************
1414  template< typename MT3 // Type of the left-hand side target matrix
1415  , typename MT4 // Type of the left-hand side matrix operand
1416  , typename MT5 > // Type of the right-hand side matrix operand
1418  selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1419  {
1420  selectDefaultSubAssignKernel( C, A, B );
1421  }
1423  //**********************************************************************************************
1424 
1425  //**Optimized subtraction assignment to dense matrices (small matrices)*************************
1440  template< typename MT3 // Type of the left-hand side target matrix
1441  , typename MT4 // Type of the left-hand side matrix operand
1442  , typename MT5 > // Type of the right-hand side matrix operand
1444  selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1445  {
1447 
1448  for( size_t j=0UL; j<B.rows(); ++j )
1449  {
1450  ConstIterator element( B.begin(j) );
1451  const ConstIterator end( B.end(j) );
1452 
1453  const size_t nonzeros( B.nonZeros(j) );
1454  const size_t kpos( nonzeros & size_t(-4) );
1455  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1456 
1457  for( size_t k=0UL; k<kpos; k+=4UL )
1458  {
1459  const size_t j1( element->index() );
1460  const ET2 v1( element->value() );
1461  ++element;
1462  const size_t j2( element->index() );
1463  const ET2 v2( element->value() );
1464  ++element;
1465  const size_t j3( element->index() );
1466  const ET2 v3( element->value() );
1467  ++element;
1468  const size_t j4( element->index() );
1469  const ET2 v4( element->value() );
1470  ++element;
1471 
1472  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1473 
1474  const size_t ibegin( ( IsLower<MT4>::value )
1476  ?( LOW ? max(j1,j+1UL) : j+1UL )
1477  :( LOW ? max(j1,j) : j ) )
1478  :( LOW ? j1 : 0UL ) );
1479  const size_t iend( ( IsUpper<MT4>::value )
1481  ?( UPP ? min(j4+1UL,j) : j )
1482  :( UPP ? min(j4,j)+1UL : j+1UL ) )
1483  :( UPP ? j4+1UL : A.rows() ) );
1484 
1485  if( ( LOW || UPP ) && ( ibegin >= iend ) ) continue;
1486  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
1487 
1488  const size_t inum( iend - ibegin );
1489  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
1490  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
1491 
1492  size_t i( ibegin );
1493 
1494  for( ; i<ipos; i+=4UL ) {
1495  C(i ,j1) -= A(i ,j) * v1;
1496  C(i+1UL,j1) -= A(i+1UL,j) * v1;
1497  C(i+2UL,j1) -= A(i+2UL,j) * v1;
1498  C(i+3UL,j1) -= A(i+3UL,j) * v1;
1499  C(i ,j2) -= A(i ,j) * v2;
1500  C(i+1UL,j2) -= A(i+1UL,j) * v2;
1501  C(i+2UL,j2) -= A(i+2UL,j) * v2;
1502  C(i+3UL,j2) -= A(i+3UL,j) * v2;
1503  C(i ,j3) -= A(i ,j) * v3;
1504  C(i+1UL,j3) -= A(i+1UL,j) * v3;
1505  C(i+2UL,j3) -= A(i+2UL,j) * v3;
1506  C(i+3UL,j3) -= A(i+3UL,j) * v3;
1507  C(i ,j4) -= A(i ,j) * v4;
1508  C(i+1UL,j4) -= A(i+1UL,j) * v4;
1509  C(i+2UL,j4) -= A(i+2UL,j) * v4;
1510  C(i+3UL,j4) -= A(i+3UL,j) * v4;
1511  }
1512  for( ; i<iend; ++i ) {
1513  C(i,j1) -= A(i,j) * v1;
1514  C(i,j2) -= A(i,j) * v2;
1515  C(i,j3) -= A(i,j) * v3;
1516  C(i,j4) -= A(i,j) * v4;
1517  }
1518  }
1519 
1520  for( ; element!=end; ++element )
1521  {
1522  const size_t j1( element->index() );
1523  const ET2 v1( element->value() );
1524 
1525  const size_t ibegin( ( IsLower<MT4>::value )
1527  ?( LOW ? max(j1,j+1UL) : j+1UL )
1528  :( LOW ? max(j1,j) : j ) )
1529  :( LOW ? j1 : 0UL ) );
1530  const size_t iend( ( IsUpper<MT4>::value )
1532  ?( UPP ? min(j1+1UL,j) : j )
1533  :( UPP ? min(j1,j)+1UL : j+1UL ) )
1534  :( UPP ? j1+1UL : A.rows() ) );
1535 
1536  if( ( LOW || UPP ) && ( ibegin >= iend ) ) continue;
1537  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
1538 
1539  const size_t inum( iend - ibegin );
1540  const size_t ipos( ibegin + ( inum & size_t(-4) ) );
1541  BLAZE_INTERNAL_ASSERT( ( ibegin + inum - ( inum % 4UL ) ) == ipos, "Invalid end calculation" );
1542 
1543  size_t i( ibegin );
1544 
1545  for( ; i<ipos; i+=4UL ) {
1546  C(i ,j1) -= A(i ,j) * v1;
1547  C(i+1UL,j1) -= A(i+1UL,j) * v1;
1548  C(i+2UL,j1) -= A(i+2UL,j) * v1;
1549  C(i+3UL,j1) -= A(i+3UL,j) * v1;
1550  }
1551  for( ; i<iend; ++i ) {
1552  C(i,j1) -= A(i,j) * v1;
1553  }
1554  }
1555  }
1556  }
1558  //**********************************************************************************************
1559 
1560  //**Default subtraction assignment to dense matrices (large matrices)***************************
1574  template< typename MT3 // Type of the left-hand side target matrix
1575  , typename MT4 // Type of the left-hand side matrix operand
1576  , typename MT5 > // Type of the right-hand side matrix operand
1578  selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1579  {
1580  selectDefaultSubAssignKernel( C, A, B );
1581  }
1583  //**********************************************************************************************
1584 
1585  //**Optimized subtraction assignment to dense matrices (large matrices)*************************
1600  template< typename MT3 // Type of the left-hand side target matrix
1601  , typename MT4 // Type of the left-hand side matrix operand
1602  , typename MT5 > // Type of the right-hand side matrix operand
1604  selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1605  {
1607 
1608  const ForwardFunctor fwd;
1609 
1610  const OppositeType_<MT5> tmp( serial( B ) );
1611  subAssign( C, fwd( A * tmp ) );
1612  }
1614  //**********************************************************************************************
1615 
1616  //**Restructuring subtraction assignment********************************************************
1631  template< typename MT // Type of the target matrix
1632  , bool SO > // Storage order of the target matrix
1634  subAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1635  {
1637 
1639 
1640  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1641  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1642 
1643  const ForwardFunctor fwd;
1644 
1645  subAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1646  }
1648  //**********************************************************************************************
1649 
1650  //**Subtraction assignment to sparse matrices***************************************************
1651  // No special implementation for the subtraction assignment to sparse matrices.
1652  //**********************************************************************************************
1653 
1654  //**Schur product 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 void schurAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1670  {
1672 
1676 
1677  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1678  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1679 
1680  const ResultType tmp( serial( rhs ) );
1681  schurAssign( ~lhs, tmp );
1682  }
1684  //**********************************************************************************************
1685 
1686  //**Schur product assignment to sparse matrices*************************************************
1687  // No special implementation for the Schur product assignment to sparse matrices.
1688  //**********************************************************************************************
1689 
1690  //**Multiplication assignment to dense matrices*************************************************
1691  // No special implementation for the multiplication assignment to dense matrices.
1692  //**********************************************************************************************
1693 
1694  //**Multiplication assignment to sparse matrices************************************************
1695  // No special implementation for the multiplication assignment to sparse matrices.
1696  //**********************************************************************************************
1697 
1698  //**SMP assignment to dense matrices************************************************************
1714  template< typename MT // Type of the target dense matrix
1715  , bool SO > // Storage order of the target dense matrix
1717  smpAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1718  {
1720 
1721  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1722  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1723 
1724  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1725  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1726 
1727  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1728  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1729  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1730  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1731  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1732  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1733 
1734  smpAssign( ~lhs, A * B );
1735  }
1737  //**********************************************************************************************
1738 
1739  //**SMP assignment to sparse matrices***********************************************************
1755  template< typename MT // Type of the target sparse matrix
1756  , bool SO > // Storage order of the target sparse matrix
1758  smpAssign( SparseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1759  {
1761 
1763 
1770 
1771  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1772  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1773 
1774  const ForwardFunctor fwd;
1775 
1776  const TmpType tmp( rhs );
1777  smpAssign( ~lhs, fwd( tmp ) );
1778  }
1780  //**********************************************************************************************
1781 
1782  //**Restructuring SMP assignment****************************************************************
1797  template< typename MT // Type of the target matrix
1798  , bool SO > // Storage order of the target matrix
1800  smpAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1801  {
1803 
1804  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1805  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1806 
1807  const ForwardFunctor fwd;
1808 
1809  smpAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1810  }
1812  //**********************************************************************************************
1813 
1814  //**SMP addition assignment to dense matrices***************************************************
1830  template< typename MT // Type of the target dense matrix
1831  , bool SO > // Storage order of the target sparse matrix
1834  {
1836 
1837  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1838  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1839 
1840  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1841  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1842 
1843  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1844  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1845  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1846  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1847  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1848  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1849 
1850  smpAddAssign( ~lhs, A * B );
1851  }
1853  //**********************************************************************************************
1854 
1855  //**Restructuring SMP addition assignment*******************************************************
1870  template< typename MT // Type of the target matrix
1871  , bool SO > // Storage order of the target matrix
1873  smpAddAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1874  {
1876 
1878 
1879  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1880  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1881 
1882  const ForwardFunctor fwd;
1883 
1884  smpAddAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1885  }
1887  //**********************************************************************************************
1888 
1889  //**SMP addition assignment to sparse matrices**************************************************
1890  // No special implementation for the SMP addition assignment to sparse matrices.
1891  //**********************************************************************************************
1892 
1893  //**SMP subtraction assignment to dense matrices************************************************
1909  template< typename MT // Type of the target dense matrix
1910  , bool SO > // Storage order of the target sparse matrix
1913  {
1915 
1916  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1917  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1918 
1919  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1920  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1921 
1922  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1923  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1924  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1925  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1926  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1927  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1928 
1929  smpSubAssign( ~lhs, A * B );
1930  }
1932  //**********************************************************************************************
1933 
1934  //**Restructuring SMP subtraction assignment****************************************************
1949  template< typename MT // Type of the target matrix
1950  , bool SO > // Storage order of the target matrix
1952  smpSubAssign( Matrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1953  {
1955 
1957 
1958  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1959  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1960 
1961  const ForwardFunctor fwd;
1962 
1963  smpSubAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1964  }
1966  //**********************************************************************************************
1967 
1968  //**SMP subtraction assignment to sparse matrices***********************************************
1969  // No special implementation for the SMP subtraction assignment to sparse matrices.
1970  //**********************************************************************************************
1971 
1972  //**SMP Schur product assignment to dense matrices**********************************************
1985  template< typename MT // Type of the target dense matrix
1986  , bool SO > // Storage order of the target sparse matrix
1987  friend inline void smpSchurAssign( DenseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
1988  {
1990 
1994 
1995  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1996  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1997 
1998  const ResultType tmp( rhs );
1999  smpSchurAssign( ~lhs, tmp );
2000  }
2002  //**********************************************************************************************
2003 
2004  //**SMP Schur product assignment to sparse matrices*********************************************
2005  // No special implementation for the SMP Schur product assignment to sparse matrices.
2006  //**********************************************************************************************
2007 
2008  //**SMP multiplication assignment to dense matrices*********************************************
2009  // No special implementation for the SMP multiplication assignment to dense matrices.
2010  //**********************************************************************************************
2011 
2012  //**SMP multiplication assignment to sparse matrices********************************************
2013  // No special implementation for the SMP multiplication assignment to sparse matrices.
2014  //**********************************************************************************************
2015 
2016  //**Compile time checks*************************************************************************
2024  //**********************************************************************************************
2025 };
2026 //*************************************************************************************************
2027 
2028 
2029 
2030 
2031 //=================================================================================================
2032 //
2033 // GLOBAL BINARY ARITHMETIC OPERATORS
2034 //
2035 //=================================================================================================
2036 
2037 //*************************************************************************************************
2067 template< typename MT1 // Type of the left-hand side dense matrix
2068  , typename MT2 > // Type of the right-hand side sparse matrix
2069 inline decltype(auto)
2070  operator*( const DenseMatrix<MT1,true>& lhs, const SparseMatrix<MT2,false>& rhs )
2071 {
2073 
2074  if( (~lhs).columns() != (~rhs).rows() ) {
2075  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
2076  }
2077 
2078 
2080  return ReturnType( ~lhs, ~rhs );
2081 }
2082 //*************************************************************************************************
2083 
2084 
2085 
2086 
2087 //=================================================================================================
2088 //
2089 // GLOBAL FUNCTIONS
2090 //
2091 //=================================================================================================
2092 
2093 //*************************************************************************************************
2118 template< typename MT1 // Type of the left-hand side dense matrix
2119  , typename MT2 // Type of the right-hand side dense matrix
2120  , bool SF // Symmetry flag
2121  , bool HF // Hermitian flag
2122  , bool LF // Lower flag
2123  , bool UF > // Upper flag
2124 inline decltype(auto) declsym( const TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2125 {
2127 
2128  if( !isSquare( dm ) ) {
2129  BLAZE_THROW_INVALID_ARGUMENT( "Invalid symmetric matrix specification" );
2130  }
2131 
2133  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2134 }
2136 //*************************************************************************************************
2137 
2138 
2139 //*************************************************************************************************
2164 template< typename MT1 // Type of the left-hand side dense matrix
2165  , typename MT2 // Type of the right-hand side dense matrix
2166  , bool SF // Symmetry flag
2167  , bool HF // Hermitian flag
2168  , bool LF // Lower flag
2169  , bool UF > // Upper flag
2170 inline decltype(auto) declherm( const TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2171 {
2173 
2174  if( !isSquare( dm ) ) {
2175  BLAZE_THROW_INVALID_ARGUMENT( "Invalid Hermitian matrix specification" );
2176  }
2177 
2179  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2180 }
2182 //*************************************************************************************************
2183 
2184 
2185 //*************************************************************************************************
2210 template< typename MT1 // Type of the left-hand side dense matrix
2211  , typename MT2 // Type of the right-hand side dense matrix
2212  , bool SF // Symmetry flag
2213  , bool HF // Hermitian flag
2214  , bool LF // Lower flag
2215  , bool UF > // Upper flag
2216 inline decltype(auto) decllow( const TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2217 {
2219 
2220  if( !isSquare( dm ) ) {
2221  BLAZE_THROW_INVALID_ARGUMENT( "Invalid lower matrix specification" );
2222  }
2223 
2225  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2226 }
2228 //*************************************************************************************************
2229 
2230 
2231 //*************************************************************************************************
2256 template< typename MT1 // Type of the left-hand side dense matrix
2257  , typename MT2 // Type of the right-hand side dense matrix
2258  , bool SF // Symmetry flag
2259  , bool HF // Hermitian flag
2260  , bool LF // Lower flag
2261  , bool UF > // Upper flag
2262 inline decltype(auto) declupp( const TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2263 {
2265 
2266  if( !isSquare( dm ) ) {
2267  BLAZE_THROW_INVALID_ARGUMENT( "Invalid upper matrix specification" );
2268  }
2269 
2271  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2272 }
2274 //*************************************************************************************************
2275 
2276 
2277 //*************************************************************************************************
2302 template< typename MT1 // Type of the left-hand side dense matrix
2303  , typename MT2 // Type of the right-hand side dense matrix
2304  , bool SF // Symmetry flag
2305  , bool HF // Hermitian flag
2306  , bool LF // Lower flag
2307  , bool UF > // Upper flag
2308 inline decltype(auto) decldiag( const TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2309 {
2311 
2312  if( !isSquare( dm ) ) {
2313  BLAZE_THROW_INVALID_ARGUMENT( "Invalid diagonal matrix specification" );
2314  }
2315 
2317  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2318 }
2320 //*************************************************************************************************
2321 
2322 
2323 
2324 
2325 //=================================================================================================
2326 //
2327 // SIZE SPECIALIZATIONS
2328 //
2329 //=================================================================================================
2330 
2331 //*************************************************************************************************
2333 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2334 struct Size< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 0UL >
2335  : public Size<MT1,0UL>
2336 {};
2337 
2338 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2339 struct Size< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 1UL >
2340  : public Size<MT2,1UL>
2341 {};
2343 //*************************************************************************************************
2344 
2345 
2346 
2347 
2348 //=================================================================================================
2349 //
2350 // ISALIGNED SPECIALIZATIONS
2351 //
2352 //=================================================================================================
2353 
2354 //*************************************************************************************************
2356 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2357 struct IsAligned< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2358  : public IsAligned<MT1>
2359 {};
2361 //*************************************************************************************************
2362 
2363 
2364 
2365 
2366 //=================================================================================================
2367 //
2368 // ISSYMMETRIC SPECIALIZATIONS
2369 //
2370 //=================================================================================================
2371 
2372 //*************************************************************************************************
2374 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2375 struct IsSymmetric< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2376  : public Or< Bool<SF>
2377  , And< Bool<HF>
2378  , IsBuiltin< ElementType_< TDMatSMatMultExpr<MT1,MT2,false,true,false,false> > > >
2379  , And< Bool<LF>, Bool<UF> > >
2380 {};
2382 //*************************************************************************************************
2383 
2384 
2385 
2386 
2387 //=================================================================================================
2388 //
2389 // ISHERMITIAN SPECIALIZATIONS
2390 //
2391 //=================================================================================================
2392 
2393 //*************************************************************************************************
2395 template< typename MT1, typename MT2, bool SF, bool LF, bool UF >
2396 struct IsHermitian< TDMatSMatMultExpr<MT1,MT2,SF,true,LF,UF> >
2397  : public TrueType
2398 {};
2400 //*************************************************************************************************
2401 
2402 
2403 
2404 
2405 //=================================================================================================
2406 //
2407 // ISLOWER SPECIALIZATIONS
2408 //
2409 //=================================================================================================
2410 
2411 //*************************************************************************************************
2413 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2414 struct IsLower< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2415  : public Or< Bool<LF>
2416  , And< IsLower<MT1>, IsLower<MT2> >
2417  , And< Or< Bool<SF>, Bool<HF> >
2418  , IsUpper<MT1>, IsUpper<MT2> > >
2419 {};
2421 //*************************************************************************************************
2422 
2423 
2424 
2425 
2426 //=================================================================================================
2427 //
2428 // ISUNILOWER SPECIALIZATIONS
2429 //
2430 //=================================================================================================
2431 
2432 //*************************************************************************************************
2434 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2435 struct IsUniLower< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2436  : public Or< And< IsUniLower<MT1>, IsUniLower<MT2> >
2437  , And< Or< Bool<SF>, Bool<HF> >
2438  , IsUniUpper<MT1>, IsUniUpper<MT2> > >
2439 {};
2441 //*************************************************************************************************
2442 
2443 
2444 
2445 
2446 //=================================================================================================
2447 //
2448 // ISSTRICTLYLOWER SPECIALIZATIONS
2449 //
2450 //=================================================================================================
2451 
2452 //*************************************************************************************************
2454 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2455 struct IsStrictlyLower< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2456  : public Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
2457  , And< IsStrictlyLower<MT2>, IsLower<MT1> >
2458  , And< Or< Bool<SF>, Bool<HF> >
2459  , Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
2460  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > > > >
2461 {};
2463 //*************************************************************************************************
2464 
2465 
2466 
2467 
2468 //=================================================================================================
2469 //
2470 // ISUPPER SPECIALIZATIONS
2471 //
2472 //=================================================================================================
2473 
2474 //*************************************************************************************************
2476 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2477 struct IsUpper< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2478  : public Or< Bool<UF>
2479  , And< IsUpper<MT1>, IsUpper<MT2> >
2480  , And< Or< Bool<SF>, Bool<HF> >
2481  , IsLower<MT1>, IsLower<MT2> > >
2482 {};
2484 //*************************************************************************************************
2485 
2486 
2487 
2488 
2489 //=================================================================================================
2490 //
2491 // ISUNIUPPER SPECIALIZATIONS
2492 //
2493 //=================================================================================================
2494 
2495 //*************************************************************************************************
2497 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2498 struct IsUniUpper< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2499  : public Or< And< IsUniUpper<MT1>, IsUniUpper<MT2> >
2500  , And< Or< Bool<SF>, Bool<HF> >
2501  , IsUniLower<MT1>, IsUniLower<MT2> > >
2502 {};
2504 //*************************************************************************************************
2505 
2506 
2507 
2508 
2509 //=================================================================================================
2510 //
2511 // ISSTRICTLYUPPER SPECIALIZATIONS
2512 //
2513 //=================================================================================================
2514 
2515 //*************************************************************************************************
2517 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2518 struct IsStrictlyUpper< TDMatSMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2519  : public Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
2520  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> >
2521  , And< Or< Bool<SF>, Bool<HF> >
2522  , Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
2523  , And< IsStrictlyLower<MT2>, IsLower<MT1> > > > >
2524 {};
2526 //*************************************************************************************************
2527 
2528 } // namespace blaze
2529 
2530 #endif
decltype(auto) subvector(Vector< VT, TF > &, RSAs...)
Creating a view on a specific subvector of the given vector.
Definition: Subvector.h:329
Flag for lower matrices.
Definition: TDMatSMatMultExpr.h:151
#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
Flag for Hermitian matrices.
Definition: TDMatSMatMultExpr.h:150
If_< IsExpression< MT2 >, const MT2, const MT2 &> RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: TDMatSMatMultExpr.h:247
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:131
Headerfile for the generic min algorithm.
Header file for the blaze::checked and blaze::unchecked instances.
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:71
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:351
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:286
Compile time check for triangular matrix types.This type trait tests whether or not the given templat...
Definition: IsTriangular.h:86
Header file for basic type definitions.
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: TDMatSMatMultExpr.h:335
LeftOperand leftOperand() const noexcept
Returns the left-hand side transpose dense matrix operand.
Definition: TDMatSMatMultExpr.h:371
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:364
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:588
RightOperand rightOperand() const noexcept
Returns the right-hand side sparse matrix operand.
Definition: TDMatSMatMultExpr.h:381
constexpr Unchecked unchecked
Global Unchecked instance.The blaze::unchecked instance is an optional token for the creation of view...
Definition: Check.h:138
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:1903
Compile time check for lower triangular matrices.This type trait tests whether or not the given templ...
Definition: IsLower.h:87
decltype(auto) declupp(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as upper.
Definition: DMatDeclUppExpr.h:1026
typename MultTrait< T1, T2 >::Type MultTrait_
Auxiliary alias declaration for the MultTrait class template.The MultTrait_ alias declaration provide...
Definition: MultTrait.h:291
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:87
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:133
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:1950
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:241
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:80
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes...
Definition: Forward.h: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:131
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:433
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:71
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: TDMatSMatMultExpr.h:393
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:58
Header file for the DeclLow functor.
Header file for the If class template.
#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a column-major dense or sparse matri...
Definition: ColumnMajorMatrix.h:61
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.
#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.
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:3085
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:1026
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:89
ResultType_< MT2 > RT2
Result type of the right-hand side sparse matrix expression.
Definition: TDMatSMatMultExpr.h:129
Generic wrapper for the null function.
Definition: Noop.h:59
Header file for the IsTriangular type trait.
ResultType_< MT1 > RT1
Result type of the left-hand side dense matrix expression.
Definition: TDMatSMatMultExpr.h:128
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:132
ElementType_< RT1 > ET1
Element type of the left-hand side dense matrix expression.
Definition: TDMatSMatMultExpr.h:130
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:430
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:415
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:237
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:107
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:250
#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:240
Header file for run time assertion macros.
TDMatSMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the TDMatSMatMultExpr class.
Definition: TDMatSMatMultExpr.h:271
Compile time check for column-major matrix types.This type trait tests whether or not the given templ...
Definition: IsColumnMajorMatrix.h:110
MultTrait_< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: TDMatSMatMultExpr.h:236
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
decltype(auto) row(Matrix< MT, SO > &, RRAs...)
Creating a view on a specific row of the given matrix.
Definition: Row.h:131
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:239
LeftOperand lhs_
Left-hand side dense matrix of the multiplication expression.
Definition: TDMatSMatMultExpr.h:432
decltype(auto) declsym(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as symmetric.
Definition: DMatDeclSymExpr.h:1028
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
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:816
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:361
Flag for symmetric matrices.
Definition: TDMatSMatMultExpr.h:149
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:3080
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:789
decltype(auto) declherm(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as Hermitian.
Definition: DMatDeclHermExpr.h:1028
If_< IsExpression< MT1 >, const MT1, const MT1 &> LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: TDMatSMatMultExpr.h:244
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: TDMatSMatMultExpr.h:405
Header file for the IsComputation type trait class.
Header file for the IsBuiltin type trait.
Compile time logical &#39;or&#39; evaluation.The Or alias declaration performs at compile time a logical &#39;or&#39;...
Definition: Or.h:76
Compile time evaluation of the size of vectors and matrices.The Size type trait evaluates the size of...
Definition: Size.h:80
Flag for upper matrices.
Definition: TDMatSMatMultExpr.h:152
IfTrue_< evaluateRight, const RT2, CT2 > RT
Type for the assignment of the right-hand side sparse matrix operand.
Definition: TDMatSMatMultExpr.h:253
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: TDMatSMatMultExpr.h:425
Generic wrapper for the decldiag() function.
Definition: DeclDiag.h:58
Header file for the DeclHerm functor.
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:628
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.
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:908
Header file for the IsResizable type trait.
Header file for the Size 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:238
Header file for the function trace functionality.