TSMatDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_TSMATDMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_TSMATDMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <blaze/math/Aliases.h>
52 #include <blaze/math/Exception.h>
65 #include <blaze/math/shims/Reset.h>
90 #include <blaze/util/Assert.h>
91 #include <blaze/util/DisableIf.h>
92 #include <blaze/util/EnableIf.h>
95 #include <blaze/util/InvalidType.h>
96 #include <blaze/util/mpl/And.h>
97 #include <blaze/util/mpl/Bool.h>
98 #include <blaze/util/mpl/If.h>
99 #include <blaze/util/mpl/Or.h>
100 #include <blaze/util/Types.h>
102 
103 
104 namespace blaze {
105 
106 //=================================================================================================
107 //
108 // CLASS SMATDMATMULTEXPR
109 //
110 //=================================================================================================
111 
112 //*************************************************************************************************
119 template< typename MT1 // Type of the left-hand side dense matrix
120  , typename MT2 // Type of the right-hand side sparse matrix
121  , bool SF // Symmetry flag
122  , bool HF // Hermitian flag
123  , bool LF // Lower flag
124  , bool UF > // Upper flag
125 class TSMatDMatMultExpr
126  : public MatMatMultExpr< DenseMatrix< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, true > >
127  , private Computation
128 {
129  private:
130  //**Type definitions****************************************************************************
137  //**********************************************************************************************
138 
139  //**********************************************************************************************
141  enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
142  //**********************************************************************************************
143 
144  //**********************************************************************************************
146  enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
147  //**********************************************************************************************
148 
149  //**********************************************************************************************
151  enum : bool {
152  SYM = ( SF && !( HF || LF || UF ) ),
153  HERM = ( HF && !( LF || UF ) ),
154  LOW = ( LF || ( ( SF || HF ) && UF ) ),
155  UPP = ( UF || ( ( SF || HF ) && LF ) )
156  };
157  //**********************************************************************************************
158 
159  //**********************************************************************************************
161 
166  template< typename T1, typename T2, typename T3 >
167  struct CanExploitSymmetry {
168  enum : bool { value = IsSymmetric<T2>::value };
169  };
171  //**********************************************************************************************
172 
173  //**********************************************************************************************
175 
179  template< typename T1, typename T2, typename T3 >
180  struct IsEvaluationRequired {
181  enum : bool { value = ( evaluateLeft || evaluateRight ) &&
182  !CanExploitSymmetry<T1,T2,T3>::value };
183  };
185  //**********************************************************************************************
186 
187  //**********************************************************************************************
189 
193  template< typename T1, typename T2, typename T3 >
194  struct UseOptimizedKernel {
195  enum : bool { value = useOptimizedKernels &&
197  !IsResizable< ElementType_<T1> >::value &&
199  };
201  //**********************************************************************************************
202 
203  //**********************************************************************************************
205 
208  template< typename T1, typename T2, typename T3 >
209  struct UseDefaultKernel {
210  enum : bool { value = !UseOptimizedKernel<T1,T2,T3>::value };
211  };
213  //**********************************************************************************************
214 
215  //**********************************************************************************************
217 
220  using ForwardFunctor = IfTrue_< HERM
221  , DeclHerm
222  , IfTrue_< SYM
223  , DeclSym
224  , IfTrue_< LOW
225  , IfTrue_< UPP
226  , DeclDiag
227  , DeclLow >
228  , IfTrue_< UPP
229  , DeclUpp
230  , Noop > > > >;
232  //**********************************************************************************************
233 
234  public:
235  //**Type definitions****************************************************************************
238 
243  using ReturnType = const ElementType;
244  using CompositeType = const ResultType;
245 
247  using LeftOperand = If_< IsExpression<MT1>, const MT1, const MT1& >;
248 
250  using RightOperand = If_< IsExpression<MT2>, const MT2, const MT2& >;
251 
254 
257  //**********************************************************************************************
258 
259  //**Compilation flags***************************************************************************
261  enum : bool { simdEnabled = false };
262 
264  enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
265  !evaluateRight && MT2::smpAssignable };
266  //**********************************************************************************************
267 
268  //**Constructor*********************************************************************************
274  explicit inline TSMatDMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
275  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
276  , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
277  {
278  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
279  }
280  //**********************************************************************************************
281 
282  //**Access operator*****************************************************************************
289  inline ReturnType operator()( size_t i, size_t j ) const {
290  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
291  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
292 
293  if( IsDiagonal<MT1>::value ) {
294  return lhs_(i,i) * rhs_(i,j);
295  }
296  else if( IsDiagonal<MT2>::value ) {
297  return lhs_(i,j) * rhs_(j,j);
298  }
300  const size_t begin( ( IsUpper<MT1>::value )
301  ?( ( IsLower<MT2>::value )
302  ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
303  , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
304  :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
305  :( ( IsLower<MT2>::value )
306  ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
307  :( 0UL ) ) );
308  const size_t end( ( IsLower<MT1>::value )
309  ?( ( IsUpper<MT2>::value )
310  ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
311  , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
312  :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
313  :( ( IsUpper<MT2>::value )
314  ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
315  :( lhs_.columns() ) ) );
316 
317  if( begin >= end ) return ElementType();
318 
319  const size_t n( end - begin );
320 
321  return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
322  }
323  else {
324  return row( lhs_, i ) * column( rhs_, j );
325  }
326  }
327  //**********************************************************************************************
328 
329  //**At function*********************************************************************************
337  inline ReturnType at( size_t i, size_t j ) const {
338  if( i >= lhs_.rows() ) {
339  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
340  }
341  if( j >= rhs_.columns() ) {
342  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
343  }
344  return (*this)(i,j);
345  }
346  //**********************************************************************************************
347 
348  //**Rows function*******************************************************************************
353  inline size_t rows() const noexcept {
354  return lhs_.rows();
355  }
356  //**********************************************************************************************
357 
358  //**Columns function****************************************************************************
363  inline size_t columns() const noexcept {
364  return rhs_.columns();
365  }
366  //**********************************************************************************************
367 
368  //**Left operand access*************************************************************************
373  inline LeftOperand leftOperand() const noexcept {
374  return lhs_;
375  }
376  //**********************************************************************************************
377 
378  //**Right operand access************************************************************************
383  inline RightOperand rightOperand() const noexcept {
384  return rhs_;
385  }
386  //**********************************************************************************************
387 
388  //**********************************************************************************************
394  template< typename T >
395  inline bool canAlias( const T* alias ) const noexcept {
396  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
397  }
398  //**********************************************************************************************
399 
400  //**********************************************************************************************
406  template< typename T >
407  inline bool isAliased( const T* alias ) const noexcept {
408  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
409  }
410  //**********************************************************************************************
411 
412  //**********************************************************************************************
417  inline bool isAligned() const noexcept {
418  return rhs_.isAligned();
419  }
420  //**********************************************************************************************
421 
422  //**********************************************************************************************
427  inline bool canSMPAssign() const noexcept {
428  return ( rows() * columns() >= SMP_TSMATDMATMULT_THRESHOLD ) && !IsDiagonal<MT2>::value;
429  }
430  //**********************************************************************************************
431 
432  private:
433  //**Member variables****************************************************************************
436  //**********************************************************************************************
437 
438  //**Assignment to dense matrices****************************************************************
451  template< typename MT // Type of the target dense matrix
452  , bool SO > // Storage order of the target dense matrix
454  assign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
455  {
457 
458  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
459  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
460 
461  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
462  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
463 
464  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
465  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
466  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
467  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
468  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
469  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
470 
471  TSMatDMatMultExpr::selectAssignKernel( ~lhs, A, B );
472  }
474  //**********************************************************************************************
475 
476  //**Assignment to dense matrices (kernel selection)*********************************************
487  template< typename MT3 // Type of the left-hand side target matrix
488  , typename MT4 // Type of the left-hand side matrix operand
489  , typename MT5 > // Type of the right-hand side matrix operand
490  static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
491  {
492  const size_t size( C.rows() * C.columns() );
493 
494  if( ( IsRowMajorMatrix<MT3>::value && size < TSMATDMATMULT_THRESHOLD ) ||
495  ( IsColumnMajorMatrix<MT3>::value && size < 625UL ) )
496  selectSmallAssignKernel( C, A, B );
497  else
498  selectLargeAssignKernel( C, A, B );
499  }
501  //**********************************************************************************************
502 
503  //**Default assignment to dense matrices********************************************************
518  template< typename MT3 // Type of the left-hand side target matrix
519  , typename MT4 // Type of the left-hand side matrix operand
520  , typename MT5 > // Type of the right-hand side matrix operand
521  static inline void selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
522  {
524 
525  reset( C );
526 
528  {
529  for( size_t i=0UL; i<A.columns(); ++i )
530  {
531  const ConstIterator end( A.end(i) );
532  ConstIterator element( A.begin(i) );
533 
534  for( ; element!=end; ++element ) {
535  C(element->index(),i) = element->value() * B(i,i);
536  }
537  }
538  }
539  else
540  {
541  const size_t block( IsRowMajorMatrix<MT3>::value ? 256UL : 8UL );
542 
543  for( size_t jj=0UL; jj<B.columns(); jj+=block )
544  {
545  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
546 
547  for( size_t i=0UL; i<A.columns(); ++i )
548  {
549  const ConstIterator end( A.end(i) );
550  ConstIterator element( A.begin(i) );
551 
552  for( ; element!=end; ++element )
553  {
554  const size_t i1( element->index() );
555 
556  const size_t jbegin( ( IsUpper<MT5>::value )
557  ?( ( SYM || HERM || UPP )
558  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
559  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
560  :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
561  const size_t jend( ( IsLower<MT5>::value )
562  ?( ( LOW )
563  ?( min( i1+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
564  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
565  :( LOW ? min(i1+1UL,jpos) : jpos ) );
566 
567  if( jbegin >= jend )
568  continue;
569 
570  for( size_t j=jbegin; j<jend; ++j ) {
571  if( isDefault( C(i1,j) ) )
572  C(i1,j) = element->value() * B(i,j);
573  else
574  C(i1,j) += element->value() * B(i,j);
575  }
576  }
577  }
578  }
579  }
580 
581  if( SYM || HERM ) {
582  for( size_t j=0UL; j<B.columns(); ++j ) {
583  for( size_t i=j+1UL; i<A.rows(); ++i ) {
584  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
585  }
586  }
587  }
588  }
590  //**********************************************************************************************
591 
592  //**Default assignment to dense matrices (small matrices)***************************************
606  template< typename MT3 // Type of the left-hand side target matrix
607  , typename MT4 // Type of the left-hand side matrix operand
608  , typename MT5 > // Type of the right-hand side matrix operand
610  selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
611  {
612  selectDefaultAssignKernel( C, A, B );
613  }
615  //**********************************************************************************************
616 
617  //**Optimized assignment to dense matrices (small matrices)*************************************
632  template< typename MT3 // Type of the left-hand side target matrix
633  , typename MT4 // Type of the left-hand side matrix operand
634  , typename MT5 > // Type of the right-hand side matrix operand
636  selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
637  {
639 
640  const size_t block( ( IsRowMajorMatrix<MT3>::value )?( 256UL ):( 8UL ) );
641 
642  reset( C );
643 
644  for( size_t jj=0UL; jj<B.columns(); jj+=block )
645  {
646  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
647 
648  for( size_t i=0UL; i<A.columns(); ++i )
649  {
650  const ConstIterator end( A.end(i) );
651  ConstIterator element( A.begin(i) );
652 
653  const size_t nonzeros( A.nonZeros(i) );
654  const size_t kpos( nonzeros & size_t(-4) );
655  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
656 
657  for( size_t k=0UL; k<kpos; k+=4UL )
658  {
659  const size_t i1( element->index() );
660  const ET1 v1( element->value() );
661  ++element;
662  const size_t i2( element->index() );
663  const ET1 v2( element->value() );
664  ++element;
665  const size_t i3( element->index() );
666  const ET1 v3( element->value() );
667  ++element;
668  const size_t i4( element->index() );
669  const ET1 v4( element->value() );
670  ++element;
671 
672  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
673 
674  const size_t jbegin( ( IsUpper<MT5>::value )
675  ?( ( SYM || HERM || UPP )
676  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
677  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
678  :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
679  const size_t jend( ( IsLower<MT5>::value )
680  ?( ( LOW )
681  ?( min( i4+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
682  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
683  :( LOW ? min(i4+1UL,jpos) : jpos ) );
684 
685  if( jbegin >= jend )
686  continue;
687 
688  for( size_t j=jbegin; j<jend; ++j ) {
689  C(i1,j) += v1 * B(i,j);
690  C(i2,j) += v2 * B(i,j);
691  C(i3,j) += v3 * B(i,j);
692  C(i4,j) += v4 * B(i,j);
693  }
694  }
695 
696  for( ; element!=end; ++element )
697  {
698  const size_t i1( element->index() );
699 
700  const size_t jbegin( ( IsUpper<MT5>::value )
701  ?( ( SYM || HERM || UPP )
702  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
703  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
704  :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
705  const size_t jend( ( IsLower<MT5>::value )
706  ?( ( LOW )
707  ?( min( i1+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
708  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
709  :( LOW ? min(i1+1UL,jpos) : jpos ) );
710 
711  if( jbegin >= jend )
712  continue;
713 
714  for( size_t j=jbegin; j<jend; ++j ) {
715  C(i1,j) += element->value() * B(i,j);
716  }
717  }
718  }
719  }
720 
721  if( SYM || HERM ) {
722  for( size_t j=0UL; j<B.columns(); ++j ) {
723  for( size_t i=j+1UL; i<A.rows(); ++i ) {
724  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
725  }
726  }
727  }
728  }
730  //**********************************************************************************************
731 
732  //**Default assignment to dense matrices (large matrices)***************************************
746  template< typename MT3 // Type of the left-hand side target matrix
747  , typename MT4 // Type of the left-hand side matrix operand
748  , typename MT5 > // Type of the right-hand side matrix operand
750  selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
751  {
752  selectDefaultAssignKernel( C, A, B );
753  }
755  //**********************************************************************************************
756 
757  //**Optimized assignment to dense matrices (large matrices)*************************************
772  template< typename MT3 // Type of the left-hand side target matrix
773  , typename MT4 // Type of the left-hand side matrix operand
774  , typename MT5 > // Type of the right-hand side matrix operand
776  selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
777  {
779 
780  const ForwardFunctor fwd;
781 
782  const OppositeType_<MT4> tmp( serial( A ) );
783  assign( C, fwd( tmp * B ) );
784  }
786  //**********************************************************************************************
787 
788  //**Assignment to sparse matrices***************************************************************
801  template< typename MT // Type of the target sparse matrix
802  , bool SO > // Storage order of the target sparse matrix
804  assign( SparseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
805  {
807 
809 
816 
817  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
818  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
819 
820  const ForwardFunctor fwd;
821 
822  const TmpType tmp( serial( rhs ) );
823  assign( ~lhs, fwd( tmp ) );
824  }
826  //**********************************************************************************************
827 
828  //**Restructuring assignment to row-major matrices**********************************************
843  template< typename MT // Type of the target matrix
844  , bool SO > // Storage order of the target matrix
846  assign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
847  {
849 
851 
852  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
853  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
854 
855  const ForwardFunctor fwd;
856 
857  assign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
858  }
860  //**********************************************************************************************
861 
862  //**Addition assignment to dense matrices*******************************************************
875  template< typename MT // Type of the target dense matrix
876  , bool SO > // Storage order of the target dense matrix
878  addAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
879  {
881 
882  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
883  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
884 
885  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
886  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
887 
888  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
889  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
890  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
891  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
892  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
893  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
894 
895  TSMatDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
896  }
898  //**********************************************************************************************
899 
900  //**Addition assignment to dense matrices (kernel selection)************************************
911  template< typename MT3 // Type of the left-hand side target matrix
912  , typename MT4 // Type of the left-hand side matrix operand
913  , typename MT5 > // Type of the right-hand side matrix operand
914  static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
915  {
916  const size_t size( C.rows() * C.columns() );
917 
918  if( ( IsRowMajorMatrix<MT3>::value && size < TSMATDMATMULT_THRESHOLD ) ||
919  ( IsColumnMajorMatrix<MT3>::value && size < 625UL ) )
920  selectSmallAddAssignKernel( C, A, B );
921  else
922  selectLargeAddAssignKernel( C, A, B );
923  }
925  //**********************************************************************************************
926 
927  //**Default addition assignment to dense matrices***********************************************
942  template< typename MT3 // Type of the left-hand side target matrix
943  , typename MT4 // Type of the left-hand side matrix operand
944  , typename MT5 > // Type of the right-hand side matrix operand
945  static inline void selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
946  {
948 
950  {
951  for( size_t i=0UL; i<A.columns(); ++i )
952  {
953  const ConstIterator end( A.end(i) );
954  ConstIterator element( A.begin(i) );
955 
956  for( ; element!=end; ++element ) {
957  C(element->index(),i) += element->value() * B(i,i);
958  }
959  }
960  }
961  else
962  {
963  const size_t block( IsRowMajorMatrix<MT3>::value ? 256UL : 8UL );
964 
965  for( size_t jj=0UL; jj<B.columns(); jj+=block )
966  {
967  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
968 
969  for( size_t i=0UL; i<A.columns(); ++i )
970  {
971  const ConstIterator end( A.end(i) );
972  ConstIterator element( A.begin(i) );
973 
974  for( ; element!=end; ++element )
975  {
976  const size_t i1( element->index() );
977 
978  const size_t jbegin( ( IsUpper<MT5>::value )
979  ?( ( UPP )
980  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
981  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
982  :( UPP ? max(i1,jj) : jj ) );
983  const size_t jend( ( IsLower<MT5>::value )
984  ?( ( LOW )
985  ?( min( i1+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
986  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
987  :( LOW ? min(i1+1UL,jpos) : jpos ) );
988 
989  if( jbegin >= jend )
990  continue;
991 
992  for( size_t j=jbegin; j<jend; ++j ) {
993  C(i1,j) += element->value() * B(i,j);
994  }
995  }
996  }
997  }
998  }
999  }
1001  //**********************************************************************************************
1002 
1003  //**Default addition assignment to dense matrices (small matrices)******************************
1017  template< typename MT3 // Type of the left-hand side target matrix
1018  , typename MT4 // Type of the left-hand side matrix operand
1019  , typename MT5 > // Type of the right-hand side matrix operand
1021  selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1022  {
1023  selectDefaultAddAssignKernel( C, A, B );
1024  }
1026  //**********************************************************************************************
1027 
1028  //**Optimized addition assignment to dense matrices (small matrices)****************************
1043  template< typename MT3 // Type of the left-hand side target matrix
1044  , typename MT4 // Type of the left-hand side matrix operand
1045  , typename MT5 > // Type of the right-hand side matrix operand
1047  selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1048  {
1050 
1051  const size_t block( ( IsRowMajorMatrix<MT3>::value )?( 256UL ):( 8UL ) );
1052 
1053  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1054  {
1055  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1056 
1057  for( size_t i=0UL; i<A.columns(); ++i )
1058  {
1059  const ConstIterator end( A.end(i) );
1060  ConstIterator element( A.begin(i) );
1061 
1062  const size_t nonzeros( A.nonZeros(i) );
1063  const size_t kpos( nonzeros & size_t(-4) );
1064  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1065 
1066  for( size_t k=0UL; k<kpos; k+=4UL )
1067  {
1068  const size_t i1( element->index() );
1069  const ET1 v1( element->value() );
1070  ++element;
1071  const size_t i2( element->index() );
1072  const ET1 v2( element->value() );
1073  ++element;
1074  const size_t i3( element->index() );
1075  const ET1 v3( element->value() );
1076  ++element;
1077  const size_t i4( element->index() );
1078  const ET1 v4( element->value() );
1079  ++element;
1080 
1081  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1082 
1083  const size_t jbegin( ( IsUpper<MT5>::value )
1084  ?( ( UPP )
1085  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
1086  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
1087  :( UPP ? max(i1,jj) : jj ) );
1088  const size_t jend( ( IsLower<MT5>::value )
1089  ?( ( LOW )
1090  ?( min( i4+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
1091  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
1092  :( LOW ? min(i4+1UL,jpos) : jpos ) );
1093 
1094  if( jbegin >= jend )
1095  continue;
1096 
1097  for( size_t j=jbegin; j<jend; ++j ) {
1098  C(i1,j) += v1 * B(i,j);
1099  C(i2,j) += v2 * B(i,j);
1100  C(i3,j) += v3 * B(i,j);
1101  C(i4,j) += v4 * B(i,j);
1102  }
1103  }
1104 
1105  for( ; element!=end; ++element )
1106  {
1107  const size_t i1( element->index() );
1108 
1109  const size_t jbegin( ( IsUpper<MT5>::value )
1110  ?( ( UPP )
1111  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
1112  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
1113  :( UPP ? max(i1,jj) : jj ) );
1114  const size_t jend( ( IsLower<MT5>::value )
1115  ?( ( LOW )
1116  ?( min( i1+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
1117  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
1118  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1119 
1120  if( jbegin >= jend )
1121  continue;
1122 
1123  for( size_t j=jbegin; j<jend; ++j ) {
1124  C(i1,j) += element->value() * B(i,j);
1125  }
1126  }
1127  }
1128  }
1129  }
1131  //**********************************************************************************************
1132 
1133  //**Default addition assignment to dense matrices (large matrices)******************************
1147  template< typename MT3 // Type of the left-hand side target matrix
1148  , typename MT4 // Type of the left-hand side matrix operand
1149  , typename MT5 > // Type of the right-hand side matrix operand
1151  selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1152  {
1153  selectDefaultAddAssignKernel( C, A, B );
1154  }
1156  //**********************************************************************************************
1157 
1158  //**Optimized addition assignment to dense matrices (large matrices)****************************
1173  template< typename MT3 // Type of the left-hand side target matrix
1174  , typename MT4 // Type of the left-hand side matrix operand
1175  , typename MT5 > // Type of the right-hand side matrix operand
1177  selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1178  {
1180 
1181  const ForwardFunctor fwd;
1182 
1183  const OppositeType_<MT4> tmp( serial( A ) );
1184  addAssign( C, fwd( tmp * B ) );
1185  }
1187  //**********************************************************************************************
1188 
1189  //**Restructuring addition assignment to row-major matrices*************************************
1204  template< typename MT // Type of the target matrix
1205  , bool SO > // Storage order of the target matrix
1207  addAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1208  {
1210 
1212 
1213  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1214  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1215 
1216  const ForwardFunctor fwd;
1217 
1218  addAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1219  }
1221  //**********************************************************************************************
1222 
1223  //**Addition assignment to sparse matrices******************************************************
1224  // No special implementation for the addition assignment to sparse matrices.
1225  //**********************************************************************************************
1226 
1227  //**Subtraction assignment to dense matrices****************************************************
1240  template< typename MT // Type of the target dense matrix
1241  , bool SO > // Storage order of the target dense matrix
1243  subAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1244  {
1246 
1247  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1248  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1249 
1250  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1251  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1252 
1253  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1254  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1255  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1256  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1257  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1258  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1259 
1260  TSMatDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1261  }
1263  //**********************************************************************************************
1264 
1265  //**Subtraction assignment to dense matrices (kernel selection)*********************************
1276  template< typename MT3 // Type of the left-hand side target matrix
1277  , typename MT4 // Type of the left-hand side matrix operand
1278  , typename MT5 > // Type of the right-hand side matrix operand
1279  static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1280  {
1281  const size_t size( C.rows() * C.columns() );
1282 
1283  if( ( IsRowMajorMatrix<MT3>::value && size < TSMATDMATMULT_THRESHOLD ) ||
1284  ( IsColumnMajorMatrix<MT3>::value && size < 625UL ) )
1285  selectSmallSubAssignKernel( C, A, B );
1286  else
1287  selectLargeSubAssignKernel( C, A, B );
1288  }
1290  //**********************************************************************************************
1291 
1292  //**Default subtraction assignment to dense matrices********************************************
1307  template< typename MT3 // Type of the left-hand side target matrix
1308  , typename MT4 // Type of the left-hand side matrix operand
1309  , typename MT5 > // Type of the right-hand side matrix operand
1310  static inline void selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1311  {
1313 
1315  {
1316  for( size_t i=0UL; i<A.columns(); ++i )
1317  {
1318  const ConstIterator end( A.end(i) );
1319  ConstIterator element( A.begin(i) );
1320 
1321  for( ; element!=end; ++element ) {
1322  C(element->index(),i) -= element->value() * B(i,i);
1323  }
1324  }
1325  }
1326  else
1327  {
1328  const size_t block( IsRowMajorMatrix<MT3>::value ? 256UL : 8UL );
1329 
1330  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1331  {
1332  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1333 
1334  for( size_t i=0UL; i<A.columns(); ++i )
1335  {
1336  const ConstIterator end( A.end(i) );
1337  ConstIterator element( A.begin(i) );
1338 
1339  for( ; element!=end; ++element )
1340  {
1341  const size_t i1( element->index() );
1342 
1343  const size_t jbegin( ( IsUpper<MT5>::value )
1344  ?( ( UPP )
1345  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
1346  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
1347  :( UPP ? max(i1,jj) : jj ) );
1348  const size_t jend( ( IsLower<MT5>::value )
1349  ?( ( LOW )
1350  ?( min( i1+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
1351  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
1352  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1353 
1354  if( jbegin >= jend )
1355  continue;
1356 
1357  for( size_t j=jbegin; j<jend; ++j ) {
1358  C(i1,j) -= element->value() * B(i,j);
1359  }
1360  }
1361  }
1362  }
1363  }
1364  }
1366  //**********************************************************************************************
1367 
1368  //**Default subtraction assignment to dense matrices (small matrices)***************************
1382  template< typename MT3 // Type of the left-hand side target matrix
1383  , typename MT4 // Type of the left-hand side matrix operand
1384  , typename MT5 > // Type of the right-hand side matrix operand
1386  selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1387  {
1388  selectDefaultSubAssignKernel( C, A, B );
1389  }
1391  //**********************************************************************************************
1392 
1393  //**Optimized subtraction assignment to dense matrices (small matrices)*************************
1408  template< typename MT3 // Type of the left-hand side target matrix
1409  , typename MT4 // Type of the left-hand side matrix operand
1410  , typename MT5 > // Type of the right-hand side matrix operand
1412  selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1413  {
1415 
1416  const size_t block( ( IsRowMajorMatrix<MT3>::value )?( 256UL ):( 8UL ) );
1417 
1418  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1419  {
1420  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1421 
1422  for( size_t i=0UL; i<A.columns(); ++i )
1423  {
1424  const ConstIterator end( A.end(i) );
1425  ConstIterator element( A.begin(i) );
1426 
1427  const size_t nonzeros( A.nonZeros(i) );
1428  const size_t kpos( nonzeros & size_t(-4) );
1429  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1430 
1431  for( size_t k=0UL; k<kpos; k+=4UL )
1432  {
1433  const size_t i1( element->index() );
1434  const ET1 v1( element->value() );
1435  ++element;
1436  const size_t i2( element->index() );
1437  const ET1 v2( element->value() );
1438  ++element;
1439  const size_t i3( element->index() );
1440  const ET1 v3( element->value() );
1441  ++element;
1442  const size_t i4( element->index() );
1443  const ET1 v4( element->value() );
1444  ++element;
1445 
1446  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1447 
1448  const size_t jbegin( ( IsUpper<MT5>::value )
1449  ?( ( UPP )
1450  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
1451  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
1452  :( UPP ? max(i1,jj) : jj ) );
1453  const size_t jend( ( IsLower<MT5>::value )
1454  ?( ( LOW )
1455  ?( min( i4+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
1456  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
1457  :( LOW ? min(i4+1UL,jpos) : jpos ) );
1458 
1459  if( jbegin >= jend )
1460  continue;
1461 
1462  for( size_t j=jbegin; j<jend; ++j ) {
1463  C(i1,j) -= v1 * B(i,j);
1464  C(i2,j) -= v2 * B(i,j);
1465  C(i3,j) -= v3 * B(i,j);
1466  C(i4,j) -= v4 * B(i,j);
1467  }
1468  }
1469 
1470  for( ; element!=end; ++element )
1471  {
1472  const size_t i1( element->index() );
1473 
1474  const size_t jbegin( ( IsUpper<MT5>::value )
1475  ?( ( UPP )
1476  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
1477  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
1478  :( UPP ? max(i1,jj) : jj ) );
1479  const size_t jend( ( IsLower<MT5>::value )
1480  ?( ( LOW )
1481  ?( min( i1+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
1482  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
1483  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1484 
1485  if( jbegin >= jend )
1486  continue;
1487 
1488  for( size_t j=jbegin; j<jend; ++j ) {
1489  C(i1,j) -= element->value() * B(i,j);
1490  }
1491  }
1492  }
1493  }
1494  }
1496  //**********************************************************************************************
1497 
1498  //**Default subtraction assignment to dense matrices (large matrices)***************************
1512  template< typename MT3 // Type of the left-hand side target matrix
1513  , typename MT4 // Type of the left-hand side matrix operand
1514  , typename MT5 > // Type of the right-hand side matrix operand
1516  selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1517  {
1518  selectDefaultSubAssignKernel( C, A, B );
1519  }
1521  //**********************************************************************************************
1522 
1523  //**Optimized subtraction assignment to dense matrices (large matrices)*************************
1538  template< typename MT3 // Type of the left-hand side target matrix
1539  , typename MT4 // Type of the left-hand side matrix operand
1540  , typename MT5 > // Type of the right-hand side matrix operand
1542  selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1543  {
1545 
1546  const ForwardFunctor fwd;
1547 
1548  const OppositeType_<MT4> tmp( serial( A ) );
1549  subAssign( C, fwd( tmp * B ) );
1550  }
1552  //**********************************************************************************************
1553 
1554  //**Restructuring subtraction assignment to row-major matrices**********************************
1569  template< typename MT // Type of the target matrix
1570  , bool SO > // Storage order of the target matrix
1572  subAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1573  {
1575 
1577 
1578  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1579  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1580 
1581  const ForwardFunctor fwd;
1582 
1583  subAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1584  }
1586  //**********************************************************************************************
1587 
1588  //**Subtraction assignment to sparse matrices***************************************************
1589  // No special implementation for the subtraction assignment to sparse matrices.
1590  //**********************************************************************************************
1591 
1592  //**Schur product assignment to dense matrices**************************************************
1605  template< typename MT // Type of the target dense matrix
1606  , bool SO > // Storage order of the target dense matrix
1607  friend inline void schurAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1608  {
1610 
1614 
1615  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1616  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1617 
1618  const ResultType tmp( serial( rhs ) );
1619  schurAssign( ~lhs, tmp );
1620  }
1622  //**********************************************************************************************
1623 
1624  //**Schur product assignment to sparse matrices*************************************************
1625  // No special implementation for the Schur product assignment to sparse matrices.
1626  //**********************************************************************************************
1627 
1628  //**Multiplication assignment to dense matrices*************************************************
1629  // No special implementation for the multiplication assignment to dense matrices.
1630  //**********************************************************************************************
1631 
1632  //**Multiplication assignment to sparse matrices************************************************
1633  // No special implementation for the multiplication assignment to sparse matrices.
1634  //**********************************************************************************************
1635 
1636  //**SMP assignment to dense matrices************************************************************
1652  template< typename MT // Type of the target dense matrix
1653  , bool SO > // Storage order of the target dense matrix
1655  smpAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1656  {
1658 
1659  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1660  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1661 
1662  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1663  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1664 
1665  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1666  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1667  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1668  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1669  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1670  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1671 
1672  smpAssign( ~lhs, A * B );
1673  }
1675  //**********************************************************************************************
1676 
1677  //**SMP assignment to sparse matrices***********************************************************
1693  template< typename MT // Type of the target sparse matrix
1694  , bool SO > // Storage order of the target sparse matrix
1696  smpAssign( SparseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1697  {
1699 
1701 
1708 
1709  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1710  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1711 
1712  const ForwardFunctor fwd;
1713 
1714  const TmpType tmp( rhs );
1715  smpAssign( ~lhs, fwd( tmp ) );
1716  }
1718  //**********************************************************************************************
1719 
1720  //**Restructuring SMP assignment to row-major matrices******************************************
1735  template< typename MT // Type of the target matrix
1736  , bool SO > // Storage order of the target matrix
1738  smpAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1739  {
1741 
1742  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1743  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1744 
1745  const ForwardFunctor fwd;
1746 
1747  smpAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1748  }
1750  //**********************************************************************************************
1751 
1752  //**SMP addition assignment to dense matrices***************************************************
1768  template< typename MT // Type of the target dense matrix
1769  , bool SO > // Storage order of the target dense matrix
1772  {
1774 
1775  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1776  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1777 
1778  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1779  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1780 
1781  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1782  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1783  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1784  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1785  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1786  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1787 
1788  smpAddAssign( ~lhs, A * B );
1789  }
1791  //**********************************************************************************************
1792 
1793  //**Restructuring SMP addition assignment to row-major matrices*********************************
1808  template< typename MT // Type of the target matrix
1809  , bool SO > // Storage order of the target matrix
1811  smpAddAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1812  {
1814 
1815  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1816  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1817 
1818  const ForwardFunctor fwd;
1819 
1820  smpAddAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1821  }
1823  //**********************************************************************************************
1824 
1825  //**SMP addition assignment to sparse matrices**************************************************
1826  // No special implementation for the SMP addition assignment to sparse matrices.
1827  //**********************************************************************************************
1828 
1829  //**SMP subtraction assignment to dense matrices************************************************
1845  template< typename MT // Type of the target dense matrix
1846  , bool SO > // Storage order of the target dense matrix
1849  {
1851 
1852  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1853  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1854 
1855  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1856  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1857 
1858  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1859  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1860  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1861  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1862  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1863  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1864 
1865  smpSubAssign( ~lhs, A * B );
1866  }
1868  //**********************************************************************************************
1869 
1870  //**Restructuring SMP subtraction assignment to row-major matrices******************************
1885  template< typename MT // Type of the target matrix
1886  , bool SO > // Storage order of the target matrix
1888  smpSubAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1889  {
1891 
1892  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1893  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1894 
1895  const ForwardFunctor fwd;
1896 
1897  smpSubAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1898  }
1900  //**********************************************************************************************
1901 
1902  //**SMP subtraction assignment to sparse matrices***********************************************
1903  // No special implementation for the SMP subtraction assignment to sparse matrices.
1904  //**********************************************************************************************
1905 
1906  //**SMP Schur product assignment to dense matrices**********************************************
1919  template< typename MT // Type of the target dense matrix
1920  , bool SO > // Storage order of the target dense matrix
1921  friend inline void smpSchurAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1922  {
1924 
1928 
1929  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1930  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1931 
1932  const ResultType tmp( rhs );
1933  smpSchurAssign( ~lhs, tmp );
1934  }
1936  //**********************************************************************************************
1937 
1938  //**SMP Schur product assignment to sparse matrices*********************************************
1939  // No special implementation for the SMP Schur product assignment to sparse matrices.
1940  //**********************************************************************************************
1941 
1942  //**SMP multiplication assignment to dense matrices*********************************************
1943  // No special implementation for the SMP multiplication assignment to dense matrices.
1944  //**********************************************************************************************
1945 
1946  //**SMP multiplication assignment to sparse matrices********************************************
1947  // No special implementation for the SMP multiplication assignment to sparse matrices.
1948  //**********************************************************************************************
1949 
1950  //**Compile time checks*************************************************************************
1958  //**********************************************************************************************
1959 };
1960 //*************************************************************************************************
1961 
1962 
1963 
1964 
1965 //=================================================================================================
1966 //
1967 // GLOBAL BINARY ARITHMETIC OPERATORS
1968 //
1969 //=================================================================================================
1970 
1971 //*************************************************************************************************
2002 template< typename MT1 // Type of the left-hand side sparse matrix
2003  , typename MT2 > // Type of the right-hand side dense matrix
2004 inline decltype(auto)
2005  operator*( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs )
2006 {
2008 
2009  if( (~lhs).columns() != (~rhs).rows() ) {
2010  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
2011  }
2012 
2014  return ReturnType( ~lhs, ~rhs );
2015 }
2016 //*************************************************************************************************
2017 
2018 
2019 
2020 
2021 //=================================================================================================
2022 //
2023 // GLOBAL FUNCTIONS
2024 //
2025 //=================================================================================================
2026 
2027 //*************************************************************************************************
2053 template< typename MT1 // Type of the left-hand side dense matrix
2054  , typename MT2 // Type of the right-hand side dense matrix
2055  , bool SF // Symmetry flag
2056  , bool HF // Hermitian flag
2057  , bool LF // Lower flag
2058  , bool UF > // Upper flag
2059 inline decltype(auto) declsym( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2060 {
2062 
2063  if( !isSquare( dm ) ) {
2064  BLAZE_THROW_INVALID_ARGUMENT( "Invalid symmetric matrix specification" );
2065  }
2066 
2068  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2069 }
2071 //*************************************************************************************************
2072 
2073 
2074 //*************************************************************************************************
2100 template< typename MT1 // Type of the left-hand side dense matrix
2101  , typename MT2 // Type of the right-hand side dense matrix
2102  , bool SF // Symmetry flag
2103  , bool HF // Hermitian flag
2104  , bool LF // Lower flag
2105  , bool UF > // Upper flag
2106 inline decltype(auto) declherm( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2107 {
2109 
2110  if( !isSquare( dm ) ) {
2111  BLAZE_THROW_INVALID_ARGUMENT( "Invalid Hermitian matrix specification" );
2112  }
2113 
2115  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2116 }
2118 //*************************************************************************************************
2119 
2120 
2121 //*************************************************************************************************
2147 template< typename MT1 // Type of the left-hand side dense matrix
2148  , typename MT2 // Type of the right-hand side dense matrix
2149  , bool SF // Symmetry flag
2150  , bool HF // Hermitian flag
2151  , bool LF // Lower flag
2152  , bool UF > // Upper flag
2153 inline decltype(auto) decllow( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2154 {
2156 
2157  if( !isSquare( dm ) ) {
2158  BLAZE_THROW_INVALID_ARGUMENT( "Invalid lower matrix specification" );
2159  }
2160 
2162  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2163 }
2165 //*************************************************************************************************
2166 
2167 
2168 //*************************************************************************************************
2194 template< typename MT1 // Type of the left-hand side dense matrix
2195  , typename MT2 // Type of the right-hand side dense matrix
2196  , bool SF // Symmetry flag
2197  , bool HF // Hermitian flag
2198  , bool LF // Lower flag
2199  , bool UF > // Upper flag
2200 inline decltype(auto) declupp( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2201 {
2203 
2204  if( !isSquare( dm ) ) {
2205  BLAZE_THROW_INVALID_ARGUMENT( "Invalid upper matrix specification" );
2206  }
2207 
2209  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2210 }
2212 //*************************************************************************************************
2213 
2214 
2215 //*************************************************************************************************
2241 template< typename MT1 // Type of the left-hand side dense matrix
2242  , typename MT2 // Type of the right-hand side dense matrix
2243  , bool SF // Symmetry flag
2244  , bool HF // Hermitian flag
2245  , bool LF // Lower flag
2246  , bool UF > // Upper flag
2247 inline decltype(auto) decldiag( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2248 {
2250 
2251  if( !isSquare( dm ) ) {
2252  BLAZE_THROW_INVALID_ARGUMENT( "Invalid diagonal matrix specification" );
2253  }
2254 
2256  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2257 }
2259 //*************************************************************************************************
2260 
2261 
2262 
2263 
2264 //=================================================================================================
2265 //
2266 // ROWS SPECIALIZATIONS
2267 //
2268 //=================================================================================================
2269 
2270 //*************************************************************************************************
2272 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2273 struct Rows< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2274  : public Rows<MT1>
2275 {};
2277 //*************************************************************************************************
2278 
2279 
2280 
2281 
2282 //=================================================================================================
2283 //
2284 // COLUMNS SPECIALIZATIONS
2285 //
2286 //=================================================================================================
2287 
2288 //*************************************************************************************************
2290 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2291 struct Columns< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2292  : public Columns<MT2>
2293 {};
2295 //*************************************************************************************************
2296 
2297 
2298 
2299 
2300 //=================================================================================================
2301 //
2302 // ISALIGNED SPECIALIZATIONS
2303 //
2304 //=================================================================================================
2305 
2306 //*************************************************************************************************
2308 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2309 struct IsAligned< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2310  : public BoolConstant< IsAligned<MT2>::value >
2311 {};
2313 //*************************************************************************************************
2314 
2315 
2316 
2317 
2318 //=================================================================================================
2319 //
2320 // ISSYMMETRIC SPECIALIZATIONS
2321 //
2322 //=================================================================================================
2323 
2324 //*************************************************************************************************
2326 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2327 struct IsSymmetric< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2328  : public BoolConstant< Or< Bool<SF>
2329  , And< Bool<HF>
2330  , IsBuiltin< ElementType_< TSMatDMatMultExpr<MT1,MT2,false,true,false,false> > > >
2331  , And< Bool<LF>, Bool<UF> > >::value >
2332 {};
2334 //*************************************************************************************************
2335 
2336 
2337 
2338 
2339 //=================================================================================================
2340 //
2341 // ISHERMITIAN SPECIALIZATIONS
2342 //
2343 //=================================================================================================
2344 
2345 //*************************************************************************************************
2347 template< typename MT1, typename MT2, bool SF, bool LF, bool UF >
2348 struct IsHermitian< TSMatDMatMultExpr<MT1,MT2,SF,true,LF,UF> >
2349  : public TrueType
2350 {};
2352 //*************************************************************************************************
2353 
2354 
2355 
2356 
2357 //=================================================================================================
2358 //
2359 // ISLOWER SPECIALIZATIONS
2360 //
2361 //=================================================================================================
2362 
2363 //*************************************************************************************************
2365 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2366 struct IsLower< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2367  : public BoolConstant< Or< Bool<LF>
2368  , And< IsLower<MT1>, IsLower<MT2> >
2369  , And< Or< Bool<SF>, Bool<HF> >
2370  , IsUpper<MT1>, IsUpper<MT2> > >::value >
2371 {};
2373 //*************************************************************************************************
2374 
2375 
2376 
2377 
2378 //=================================================================================================
2379 //
2380 // ISUNILOWER SPECIALIZATIONS
2381 //
2382 //=================================================================================================
2383 
2384 //*************************************************************************************************
2386 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2387 struct IsUniLower< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2388  : public BoolConstant< Or< And< IsUniLower<MT1>, IsUniLower<MT2> >
2389  , And< Or< Bool<SF>, Bool<HF> >
2390  , IsUniUpper<MT1>, IsUniUpper<MT2> > >::value >
2391 {};
2393 //*************************************************************************************************
2394 
2395 
2396 
2397 
2398 //=================================================================================================
2399 //
2400 // ISSTRICTLYLOWER SPECIALIZATIONS
2401 //
2402 //=================================================================================================
2403 
2404 //*************************************************************************************************
2406 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2407 struct IsStrictlyLower< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2408  : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
2409  , And< IsStrictlyLower<MT2>, IsLower<MT1> >
2410  , And< Or< Bool<SF>, Bool<HF> >
2411  , Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
2412  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > > > >::value >
2413 {};
2415 //*************************************************************************************************
2416 
2417 
2418 
2419 
2420 //=================================================================================================
2421 //
2422 // ISUPPER SPECIALIZATIONS
2423 //
2424 //=================================================================================================
2425 
2426 //*************************************************************************************************
2428 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2429 struct IsUpper< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2430  : public BoolConstant< Or< Bool<UF>
2431  , And< IsUpper<MT1>, IsUpper<MT2> >
2432  , And< Or< Bool<SF>, Bool<HF> >
2433  , IsLower<MT1>, IsLower<MT2> > >::value >
2434 {};
2436 //*************************************************************************************************
2437 
2438 
2439 
2440 
2441 //=================================================================================================
2442 //
2443 // ISUNIUPPER SPECIALIZATIONS
2444 //
2445 //=================================================================================================
2446 
2447 //*************************************************************************************************
2449 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2450 struct IsUniUpper< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2451  : public BoolConstant< Or< And< IsUniUpper<MT1>, IsUniUpper<MT2> >
2452  , And< Or< Bool<SF>, Bool<HF> >
2453  , IsUniLower<MT1>, IsUniLower<MT2> > >::value >
2454 {};
2456 //*************************************************************************************************
2457 
2458 
2459 
2460 
2461 //=================================================================================================
2462 //
2463 // ISSTRICTLYUPPER SPECIALIZATIONS
2464 //
2465 //=================================================================================================
2466 
2467 //*************************************************************************************************
2469 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2470 struct IsStrictlyUpper< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2471  : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
2472  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> >
2473  , And< Or< Bool<SF>, Bool<HF> >
2474  , Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
2475  , And< IsStrictlyLower<MT2>, IsLower<MT1> > > > >::value >
2476 {};
2478 //*************************************************************************************************
2479 
2480 } // namespace blaze
2481 
2482 #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
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
ResultType_< MT2 > RT2
Result type of the right-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:132
decltype(auto) decldiag(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as diagonal.
Definition: DMatDeclDiagExpr.h:996
bool isAligned() const noexcept
Returns whether the operands of the expression are properly aligned in memory.
Definition: TSMatDMatMultExpr.h:417
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
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.
ElementType_< ResultType > ElementType
Resulting element type.
Definition: TSMatDMatMultExpr.h:242
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
CompositeType_< MT1 > CT1
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:135
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
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: TSMatDMatMultExpr.h:289
Header file for the serial shim.
ElementType_< RT2 > ET2
Element type of the right-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:134
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: TSMatDMatMultExpr.h:363
Header file for the IsDiagonal type trait.
BLAZE_ALWAYS_INLINE size_t size(const Vector< VT, TF > &vector) noexcept
Returns the current size/dimension of the vector.
Definition: Vector.h:265
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.
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: TSMatDMatMultExpr.h:434
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
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
LeftOperand leftOperand() const noexcept
Returns the left-hand side transpose sparse matrix operand.
Definition: TSMatDMatMultExpr.h:373
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.
IfTrue_< evaluateRight, const RT2, CT2 > RT
Type for the assignment of the right-hand side dense matrix operand.
Definition: TSMatDMatMultExpr.h:256
Header file for the RequiresEvaluation type trait.
System settings for performance optimizations.
Header file for the IsUniLower type trait.
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
CompositeType_< MT2 > CT2
Composite type of the right-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:136
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: TSMatDMatMultExpr.h:353
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:78
const ResultType CompositeType
Data type for composite expression templates.
Definition: TSMatDMatMultExpr.h:244
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
IfTrue_< evaluateLeft, const RT1, CT1 > LT
Type for the assignment of the left-hand side sparse matrix operand.
Definition: TSMatDMatMultExpr.h:253
RightOperand rhs_
Right-hand side dense matrix of the multiplication expression.
Definition: TSMatDMatMultExpr.h:435
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
If_< IsExpression< MT2 >, const MT2, const MT2 &> RightOperand
Composite type of the right-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:250
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
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.
Compile time check for row-major matrix types.This type trait tests whether or not the given template...
Definition: IsRowMajorMatrix.h:110
#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
TransposeType_< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: TSMatDMatMultExpr.h:241
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.
If_< IsExpression< MT1 >, const MT1, const MT1 &> LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:247
#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.
Flag for Hermitian matrices.
Definition: TSMatDMatMultExpr.h:153
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
MultTrait_< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: TSMatDMatMultExpr.h:239
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
Flag for upper matrices.
Definition: TSMatDMatMultExpr.h:155
ElementType_< RT1 > ET1
Element type of the left-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:133
Generic wrapper for the null function.
Definition: Noop.h:58
Header file for the IsTriangular type trait.
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: TSMatDMatMultExpr.h:337
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: TSMatDMatMultExpr.h:427
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
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.
Constraint on the data type.
Header file for all forward declarations for expression class templates.
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
RightOperand rightOperand() const noexcept
Returns the right-hand side dense matrix operand.
Definition: TSMatDMatMultExpr.h:383
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
#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
Header file for run time assertion macros.
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.
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
TSMatDMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the TSMatDMatMultExpr class.
Definition: TSMatDMatMultExpr.h:274
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
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
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
OppositeType_< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: TSMatDMatMultExpr.h:240
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
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TSMatDMatMultExpr.h:243
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
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: TSMatDMatMultExpr.h:407
decltype(auto) declherm(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as Hermitian.
Definition: DMatDeclHermExpr.h:1029
Header file for the IsRowMajorMatrix type trait.
Flag for symmetric matrices.
Definition: TSMatDMatMultExpr.h:152
Header file for the IsComputation type trait class.
Header file for the IsBuiltin type trait.
Expression object for transpose sparse matrix-dense matrix multiplications.The TSMatDMatMultExpr clas...
Definition: Forward.h:160
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
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
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: TSMatDMatMultExpr.h:395
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 lower matrices.
Definition: TSMatDMatMultExpr.h:154
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.
Header file for the function trace functionality.
ResultType_< MT1 > RT1
Result type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:131