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>
85 #include <blaze/math/views/Check.h>
90 #include <blaze/util/Assert.h>
91 #include <blaze/util/DisableIf.h>
92 #include <blaze/util/EnableIf.h>
94 #include <blaze/util/mpl/And.h>
95 #include <blaze/util/mpl/Bool.h>
96 #include <blaze/util/mpl/If.h>
97 #include <blaze/util/mpl/Or.h>
98 #include <blaze/util/Types.h>
100 
101 
102 namespace blaze {
103 
104 //=================================================================================================
105 //
106 // CLASS SMATDMATMULTEXPR
107 //
108 //=================================================================================================
109 
110 //*************************************************************************************************
117 template< typename MT1 // Type of the left-hand side dense matrix
118  , typename MT2 // Type of the right-hand side sparse matrix
119  , bool SF // Symmetry flag
120  , bool HF // Hermitian flag
121  , bool LF // Lower flag
122  , bool UF > // Upper flag
123 class TSMatDMatMultExpr
124  : public MatMatMultExpr< DenseMatrix< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, true > >
125  , private Computation
126 {
127  private:
128  //**Type definitions****************************************************************************
135  //**********************************************************************************************
136 
137  //**********************************************************************************************
139  enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
140  //**********************************************************************************************
141 
142  //**********************************************************************************************
144  enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
145  //**********************************************************************************************
146 
147  //**********************************************************************************************
149  enum : bool {
150  SYM = ( SF && !( HF || LF || UF ) ),
151  HERM = ( HF && !( LF || UF ) ),
152  LOW = ( LF || ( ( SF || HF ) && UF ) ),
153  UPP = ( UF || ( ( SF || HF ) && LF ) )
154  };
155  //**********************************************************************************************
156 
157  //**********************************************************************************************
159 
164  template< typename T1, typename T2, typename T3 >
165  struct CanExploitSymmetry {
166  enum : bool { value = IsSymmetric<T2>::value };
167  };
169  //**********************************************************************************************
170 
171  //**********************************************************************************************
173 
177  template< typename T1, typename T2, typename T3 >
178  struct IsEvaluationRequired {
179  enum : bool { value = ( evaluateLeft || evaluateRight ) &&
180  !CanExploitSymmetry<T1,T2,T3>::value };
181  };
183  //**********************************************************************************************
184 
185  //**********************************************************************************************
187 
191  template< typename T1, typename T2, typename T3 >
192  struct UseOptimizedKernel {
193  enum : bool { value = useOptimizedKernels &&
195  !IsResizable< ElementType_<T1> >::value &&
197  };
199  //**********************************************************************************************
200 
201  //**********************************************************************************************
203 
206  template< typename T1, typename T2, typename T3 >
207  struct UseDefaultKernel {
208  enum : bool { value = !UseOptimizedKernel<T1,T2,T3>::value };
209  };
211  //**********************************************************************************************
212 
213  //**********************************************************************************************
215 
218  using ForwardFunctor = IfTrue_< HERM
219  , DeclHerm
220  , IfTrue_< SYM
221  , DeclSym
222  , IfTrue_< LOW
223  , IfTrue_< UPP
224  , DeclDiag
225  , DeclLow >
226  , IfTrue_< UPP
227  , DeclUpp
228  , Noop > > > >;
230  //**********************************************************************************************
231 
232  public:
233  //**Type definitions****************************************************************************
236 
241  using ReturnType = const ElementType;
242  using CompositeType = const ResultType;
243 
245  using LeftOperand = If_< IsExpression<MT1>, const MT1, const MT1& >;
246 
248  using RightOperand = If_< IsExpression<MT2>, const MT2, const MT2& >;
249 
252 
255  //**********************************************************************************************
256 
257  //**Compilation flags***************************************************************************
259  enum : bool { simdEnabled = false };
260 
262  enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
263  !evaluateRight && MT2::smpAssignable };
264  //**********************************************************************************************
265 
266  //**Constructor*********************************************************************************
272  explicit inline TSMatDMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
273  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
274  , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
275  {
276  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
277  }
278  //**********************************************************************************************
279 
280  //**Access operator*****************************************************************************
287  inline ReturnType operator()( size_t i, size_t j ) const {
288  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
289  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
290 
291  if( IsDiagonal<MT1>::value ) {
292  return lhs_(i,i) * rhs_(i,j);
293  }
294  else if( IsDiagonal<MT2>::value ) {
295  return lhs_(i,j) * rhs_(j,j);
296  }
298  const size_t begin( ( IsUpper<MT1>::value )
299  ?( ( IsLower<MT2>::value )
300  ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
301  , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
302  :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
303  :( ( IsLower<MT2>::value )
304  ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
305  :( 0UL ) ) );
306  const size_t end( ( IsLower<MT1>::value )
307  ?( ( IsUpper<MT2>::value )
308  ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
309  , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
310  :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
311  :( ( IsUpper<MT2>::value )
312  ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
313  :( lhs_.columns() ) ) );
314 
315  if( begin >= end ) return ElementType();
316 
317  const size_t n( end - begin );
318 
319  return subvector( row( lhs_, i, unchecked ), begin, n, unchecked ) *
320  subvector( column( rhs_, j, unchecked ), begin, n, unchecked );
321  }
322  else {
323  return row( lhs_, i, unchecked ) * column( rhs_, j, unchecked );
324  }
325  }
326  //**********************************************************************************************
327 
328  //**At function*********************************************************************************
336  inline ReturnType at( size_t i, size_t j ) const {
337  if( i >= lhs_.rows() ) {
338  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
339  }
340  if( j >= rhs_.columns() ) {
341  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
342  }
343  return (*this)(i,j);
344  }
345  //**********************************************************************************************
346 
347  //**Rows function*******************************************************************************
352  inline size_t rows() const noexcept {
353  return lhs_.rows();
354  }
355  //**********************************************************************************************
356 
357  //**Columns function****************************************************************************
362  inline size_t columns() const noexcept {
363  return rhs_.columns();
364  }
365  //**********************************************************************************************
366 
367  //**Left operand access*************************************************************************
372  inline LeftOperand leftOperand() const noexcept {
373  return lhs_;
374  }
375  //**********************************************************************************************
376 
377  //**Right operand access************************************************************************
382  inline RightOperand rightOperand() const noexcept {
383  return rhs_;
384  }
385  //**********************************************************************************************
386 
387  //**********************************************************************************************
393  template< typename T >
394  inline bool canAlias( const T* alias ) const noexcept {
395  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
396  }
397  //**********************************************************************************************
398 
399  //**********************************************************************************************
405  template< typename T >
406  inline bool isAliased( const T* alias ) const noexcept {
407  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
408  }
409  //**********************************************************************************************
410 
411  //**********************************************************************************************
416  inline bool isAligned() const noexcept {
417  return rhs_.isAligned();
418  }
419  //**********************************************************************************************
420 
421  //**********************************************************************************************
426  inline bool canSMPAssign() const noexcept {
427  return ( rows() * columns() >= SMP_TSMATDMATMULT_THRESHOLD ) && !IsDiagonal<MT2>::value;
428  }
429  //**********************************************************************************************
430 
431  private:
432  //**Member variables****************************************************************************
435  //**********************************************************************************************
436 
437  //**Assignment to dense matrices****************************************************************
450  template< typename MT // Type of the target dense matrix
451  , bool SO > // Storage order of the target dense matrix
453  assign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
454  {
456 
457  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
458  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
459 
460  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
461  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
462 
463  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
464  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
465  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
466  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
467  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
468  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
469 
470  TSMatDMatMultExpr::selectAssignKernel( ~lhs, A, B );
471  }
473  //**********************************************************************************************
474 
475  //**Assignment to dense matrices (kernel selection)*********************************************
486  template< typename MT3 // Type of the left-hand side target matrix
487  , typename MT4 // Type of the left-hand side matrix operand
488  , typename MT5 > // Type of the right-hand side matrix operand
489  static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
490  {
491  const size_t size( C.rows() * C.columns() );
492 
493  if( ( IsRowMajorMatrix<MT3>::value && size < TSMATDMATMULT_THRESHOLD ) ||
494  ( IsColumnMajorMatrix<MT3>::value && size < 625UL ) )
495  selectSmallAssignKernel( C, A, B );
496  else
497  selectLargeAssignKernel( C, A, B );
498  }
500  //**********************************************************************************************
501 
502  //**Default assignment to dense matrices********************************************************
517  template< typename MT3 // Type of the left-hand side target matrix
518  , typename MT4 // Type of the left-hand side matrix operand
519  , typename MT5 > // Type of the right-hand side matrix operand
520  static inline void selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B )
521  {
523 
524  reset( C );
525 
527  {
528  for( size_t i=0UL; i<A.columns(); ++i )
529  {
530  const ConstIterator end( A.end(i) );
531  ConstIterator element( A.begin(i) );
532 
533  for( ; element!=end; ++element ) {
534  C(element->index(),i) = element->value() * B(i,i);
535  }
536  }
537  }
538  else
539  {
540  const size_t block( IsRowMajorMatrix<MT3>::value ? 256UL : 8UL );
541 
542  for( size_t jj=0UL; jj<B.columns(); jj+=block )
543  {
544  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
545 
546  for( size_t i=0UL; i<A.columns(); ++i )
547  {
548  const ConstIterator end( A.end(i) );
549  ConstIterator element( A.begin(i) );
550 
551  for( ; element!=end; ++element )
552  {
553  const size_t i1( element->index() );
554 
555  const size_t jbegin( ( IsUpper<MT5>::value )
556  ?( ( SYM || HERM || UPP )
557  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
558  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
559  :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
560  const size_t jend( ( IsLower<MT5>::value )
561  ?( ( LOW )
562  ?( min( i1+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
563  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
564  :( LOW ? min(i1+1UL,jpos) : jpos ) );
565 
566  if( jbegin >= jend )
567  continue;
568 
569  for( size_t j=jbegin; j<jend; ++j ) {
570  if( isDefault( C(i1,j) ) )
571  C(i1,j) = element->value() * B(i,j);
572  else
573  C(i1,j) += element->value() * B(i,j);
574  }
575  }
576  }
577  }
578  }
579 
580  if( SYM || HERM ) {
581  for( size_t j=0UL; j<B.columns(); ++j ) {
582  for( size_t i=j+1UL; i<A.rows(); ++i ) {
583  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
584  }
585  }
586  }
587  }
589  //**********************************************************************************************
590 
591  //**Default assignment to dense matrices (small matrices)***************************************
605  template< typename MT3 // Type of the left-hand side target matrix
606  , typename MT4 // Type of the left-hand side matrix operand
607  , typename MT5 > // Type of the right-hand side matrix operand
609  selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
610  {
611  selectDefaultAssignKernel( C, A, B );
612  }
614  //**********************************************************************************************
615 
616  //**Optimized assignment to dense matrices (small matrices)*************************************
631  template< typename MT3 // Type of the left-hand side target matrix
632  , typename MT4 // Type of the left-hand side matrix operand
633  , typename MT5 > // Type of the right-hand side matrix operand
635  selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B )
636  {
638 
639  const size_t block( ( IsRowMajorMatrix<MT3>::value )?( 256UL ):( 8UL ) );
640 
641  reset( C );
642 
643  for( size_t jj=0UL; jj<B.columns(); jj+=block )
644  {
645  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
646 
647  for( size_t i=0UL; i<A.columns(); ++i )
648  {
649  const ConstIterator end( A.end(i) );
650  ConstIterator element( A.begin(i) );
651 
652  const size_t nonzeros( A.nonZeros(i) );
653  const size_t kpos( nonzeros & size_t(-4) );
654  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
655 
656  for( size_t k=0UL; k<kpos; k+=4UL )
657  {
658  const size_t i1( element->index() );
659  const ET1 v1( element->value() );
660  ++element;
661  const size_t i2( element->index() );
662  const ET1 v2( element->value() );
663  ++element;
664  const size_t i3( element->index() );
665  const ET1 v3( element->value() );
666  ++element;
667  const size_t i4( element->index() );
668  const ET1 v4( element->value() );
669  ++element;
670 
671  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
672 
673  const size_t jbegin( ( IsUpper<MT5>::value )
674  ?( ( SYM || HERM || UPP )
675  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
676  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
677  :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
678  const size_t jend( ( IsLower<MT5>::value )
679  ?( ( LOW )
680  ?( min( i4+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
681  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
682  :( LOW ? min(i4+1UL,jpos) : jpos ) );
683 
684  if( jbegin >= jend )
685  continue;
686 
687  for( size_t j=jbegin; j<jend; ++j ) {
688  C(i1,j) += v1 * B(i,j);
689  C(i2,j) += v2 * B(i,j);
690  C(i3,j) += v3 * B(i,j);
691  C(i4,j) += v4 * B(i,j);
692  }
693  }
694 
695  for( ; element!=end; ++element )
696  {
697  const size_t i1( element->index() );
698 
699  const size_t jbegin( ( IsUpper<MT5>::value )
700  ?( ( SYM || HERM || UPP )
701  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
702  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
703  :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
704  const size_t jend( ( IsLower<MT5>::value )
705  ?( ( LOW )
706  ?( min( i1+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
707  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
708  :( LOW ? min(i1+1UL,jpos) : jpos ) );
709 
710  if( jbegin >= jend )
711  continue;
712 
713  for( size_t j=jbegin; j<jend; ++j ) {
714  C(i1,j) += element->value() * B(i,j);
715  }
716  }
717  }
718  }
719 
720  if( SYM || HERM ) {
721  for( size_t j=0UL; j<B.columns(); ++j ) {
722  for( size_t i=j+1UL; i<A.rows(); ++i ) {
723  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
724  }
725  }
726  }
727  }
729  //**********************************************************************************************
730 
731  //**Default assignment to dense matrices (large matrices)***************************************
745  template< typename MT3 // Type of the left-hand side target matrix
746  , typename MT4 // Type of the left-hand side matrix operand
747  , typename MT5 > // Type of the right-hand side matrix operand
749  selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
750  {
751  selectDefaultAssignKernel( C, A, B );
752  }
754  //**********************************************************************************************
755 
756  //**Optimized assignment to dense matrices (large matrices)*************************************
771  template< typename MT3 // Type of the left-hand side target matrix
772  , typename MT4 // Type of the left-hand side matrix operand
773  , typename MT5 > // Type of the right-hand side matrix operand
775  selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
776  {
778 
779  const ForwardFunctor fwd;
780 
781  const OppositeType_<MT4> tmp( serial( A ) );
782  assign( C, fwd( tmp * B ) );
783  }
785  //**********************************************************************************************
786 
787  //**Assignment to sparse matrices***************************************************************
800  template< typename MT // Type of the target sparse matrix
801  , bool SO > // Storage order of the target sparse matrix
803  assign( SparseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
804  {
806 
808 
815 
816  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
817  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
818 
819  const ForwardFunctor fwd;
820 
821  const TmpType tmp( serial( rhs ) );
822  assign( ~lhs, fwd( tmp ) );
823  }
825  //**********************************************************************************************
826 
827  //**Restructuring assignment to row-major matrices**********************************************
842  template< typename MT // Type of the target matrix
843  , bool SO > // Storage order of the target matrix
845  assign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
846  {
848 
850 
851  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
852  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
853 
854  const ForwardFunctor fwd;
855 
856  assign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
857  }
859  //**********************************************************************************************
860 
861  //**Addition assignment to dense matrices*******************************************************
874  template< typename MT // Type of the target dense matrix
875  , bool SO > // Storage order of the target dense matrix
877  addAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
878  {
880 
881  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
882  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
883 
884  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
885  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
886 
887  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
888  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
889  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
890  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
891  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
892  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
893 
894  TSMatDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
895  }
897  //**********************************************************************************************
898 
899  //**Addition assignment to dense matrices (kernel selection)************************************
910  template< typename MT3 // Type of the left-hand side target matrix
911  , typename MT4 // Type of the left-hand side matrix operand
912  , typename MT5 > // Type of the right-hand side matrix operand
913  static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
914  {
915  const size_t size( C.rows() * C.columns() );
916 
917  if( ( IsRowMajorMatrix<MT3>::value && size < TSMATDMATMULT_THRESHOLD ) ||
918  ( IsColumnMajorMatrix<MT3>::value && size < 625UL ) )
919  selectSmallAddAssignKernel( C, A, B );
920  else
921  selectLargeAddAssignKernel( C, A, B );
922  }
924  //**********************************************************************************************
925 
926  //**Default addition assignment to dense matrices***********************************************
941  template< typename MT3 // Type of the left-hand side target matrix
942  , typename MT4 // Type of the left-hand side matrix operand
943  , typename MT5 > // Type of the right-hand side matrix operand
944  static inline void selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
945  {
947 
949  {
950  for( size_t i=0UL; i<A.columns(); ++i )
951  {
952  const ConstIterator end( A.end(i) );
953  ConstIterator element( A.begin(i) );
954 
955  for( ; element!=end; ++element ) {
956  C(element->index(),i) += element->value() * B(i,i);
957  }
958  }
959  }
960  else
961  {
962  const size_t block( IsRowMajorMatrix<MT3>::value ? 256UL : 8UL );
963 
964  for( size_t jj=0UL; jj<B.columns(); jj+=block )
965  {
966  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
967 
968  for( size_t i=0UL; i<A.columns(); ++i )
969  {
970  const ConstIterator end( A.end(i) );
971  ConstIterator element( A.begin(i) );
972 
973  for( ; element!=end; ++element )
974  {
975  const size_t i1( element->index() );
976 
977  const size_t jbegin( ( IsUpper<MT5>::value )
978  ?( ( UPP )
979  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
980  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
981  :( UPP ? max(i1,jj) : jj ) );
982  const size_t jend( ( IsLower<MT5>::value )
983  ?( ( LOW )
984  ?( min( i1+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
985  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
986  :( LOW ? min(i1+1UL,jpos) : jpos ) );
987 
988  if( jbegin >= jend )
989  continue;
990 
991  for( size_t j=jbegin; j<jend; ++j ) {
992  C(i1,j) += element->value() * B(i,j);
993  }
994  }
995  }
996  }
997  }
998  }
1000  //**********************************************************************************************
1001 
1002  //**Default addition assignment to dense matrices (small matrices)******************************
1016  template< typename MT3 // Type of the left-hand side target matrix
1017  , typename MT4 // Type of the left-hand side matrix operand
1018  , typename MT5 > // Type of the right-hand side matrix operand
1020  selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1021  {
1022  selectDefaultAddAssignKernel( C, A, B );
1023  }
1025  //**********************************************************************************************
1026 
1027  //**Optimized addition assignment to dense matrices (small matrices)****************************
1042  template< typename MT3 // Type of the left-hand side target matrix
1043  , typename MT4 // Type of the left-hand side matrix operand
1044  , typename MT5 > // Type of the right-hand side matrix operand
1046  selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1047  {
1049 
1050  const size_t block( ( IsRowMajorMatrix<MT3>::value )?( 256UL ):( 8UL ) );
1051 
1052  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1053  {
1054  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1055 
1056  for( size_t i=0UL; i<A.columns(); ++i )
1057  {
1058  const ConstIterator end( A.end(i) );
1059  ConstIterator element( A.begin(i) );
1060 
1061  const size_t nonzeros( A.nonZeros(i) );
1062  const size_t kpos( nonzeros & size_t(-4) );
1063  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1064 
1065  for( size_t k=0UL; k<kpos; k+=4UL )
1066  {
1067  const size_t i1( element->index() );
1068  const ET1 v1( element->value() );
1069  ++element;
1070  const size_t i2( element->index() );
1071  const ET1 v2( element->value() );
1072  ++element;
1073  const size_t i3( element->index() );
1074  const ET1 v3( element->value() );
1075  ++element;
1076  const size_t i4( element->index() );
1077  const ET1 v4( element->value() );
1078  ++element;
1079 
1080  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1081 
1082  const size_t jbegin( ( IsUpper<MT5>::value )
1083  ?( ( UPP )
1084  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
1085  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
1086  :( UPP ? max(i1,jj) : jj ) );
1087  const size_t jend( ( IsLower<MT5>::value )
1088  ?( ( LOW )
1089  ?( min( i4+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
1090  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
1091  :( LOW ? min(i4+1UL,jpos) : jpos ) );
1092 
1093  if( jbegin >= jend )
1094  continue;
1095 
1096  for( size_t j=jbegin; j<jend; ++j ) {
1097  C(i1,j) += v1 * B(i,j);
1098  C(i2,j) += v2 * B(i,j);
1099  C(i3,j) += v3 * B(i,j);
1100  C(i4,j) += v4 * B(i,j);
1101  }
1102  }
1103 
1104  for( ; element!=end; ++element )
1105  {
1106  const size_t i1( element->index() );
1107 
1108  const size_t jbegin( ( IsUpper<MT5>::value )
1109  ?( ( UPP )
1110  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
1111  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
1112  :( UPP ? max(i1,jj) : jj ) );
1113  const size_t jend( ( IsLower<MT5>::value )
1114  ?( ( LOW )
1115  ?( min( i1+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
1116  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
1117  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1118 
1119  if( jbegin >= jend )
1120  continue;
1121 
1122  for( size_t j=jbegin; j<jend; ++j ) {
1123  C(i1,j) += element->value() * B(i,j);
1124  }
1125  }
1126  }
1127  }
1128  }
1130  //**********************************************************************************************
1131 
1132  //**Default addition assignment to dense matrices (large matrices)******************************
1146  template< typename MT3 // Type of the left-hand side target matrix
1147  , typename MT4 // Type of the left-hand side matrix operand
1148  , typename MT5 > // Type of the right-hand side matrix operand
1150  selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1151  {
1152  selectDefaultAddAssignKernel( C, A, B );
1153  }
1155  //**********************************************************************************************
1156 
1157  //**Optimized addition assignment to dense matrices (large matrices)****************************
1172  template< typename MT3 // Type of the left-hand side target matrix
1173  , typename MT4 // Type of the left-hand side matrix operand
1174  , typename MT5 > // Type of the right-hand side matrix operand
1176  selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1177  {
1179 
1180  const ForwardFunctor fwd;
1181 
1182  const OppositeType_<MT4> tmp( serial( A ) );
1183  addAssign( C, fwd( tmp * B ) );
1184  }
1186  //**********************************************************************************************
1187 
1188  //**Restructuring addition assignment to row-major matrices*************************************
1203  template< typename MT // Type of the target matrix
1204  , bool SO > // Storage order of the target matrix
1206  addAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1207  {
1209 
1211 
1212  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1213  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1214 
1215  const ForwardFunctor fwd;
1216 
1217  addAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1218  }
1220  //**********************************************************************************************
1221 
1222  //**Addition assignment to sparse matrices******************************************************
1223  // No special implementation for the addition assignment to sparse matrices.
1224  //**********************************************************************************************
1225 
1226  //**Subtraction assignment to dense matrices****************************************************
1239  template< typename MT // Type of the target dense matrix
1240  , bool SO > // Storage order of the target dense matrix
1242  subAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1243  {
1245 
1246  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1247  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1248 
1249  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1250  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1251 
1252  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1253  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1254  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1255  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1256  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1257  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1258 
1259  TSMatDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1260  }
1262  //**********************************************************************************************
1263 
1264  //**Subtraction assignment to dense matrices (kernel selection)*********************************
1275  template< typename MT3 // Type of the left-hand side target matrix
1276  , typename MT4 // Type of the left-hand side matrix operand
1277  , typename MT5 > // Type of the right-hand side matrix operand
1278  static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1279  {
1280  const size_t size( C.rows() * C.columns() );
1281 
1282  if( ( IsRowMajorMatrix<MT3>::value && size < TSMATDMATMULT_THRESHOLD ) ||
1283  ( IsColumnMajorMatrix<MT3>::value && size < 625UL ) )
1284  selectSmallSubAssignKernel( C, A, B );
1285  else
1286  selectLargeSubAssignKernel( C, A, B );
1287  }
1289  //**********************************************************************************************
1290 
1291  //**Default subtraction assignment to dense matrices********************************************
1306  template< typename MT3 // Type of the left-hand side target matrix
1307  , typename MT4 // Type of the left-hand side matrix operand
1308  , typename MT5 > // Type of the right-hand side matrix operand
1309  static inline void selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1310  {
1312 
1314  {
1315  for( size_t i=0UL; i<A.columns(); ++i )
1316  {
1317  const ConstIterator end( A.end(i) );
1318  ConstIterator element( A.begin(i) );
1319 
1320  for( ; element!=end; ++element ) {
1321  C(element->index(),i) -= element->value() * B(i,i);
1322  }
1323  }
1324  }
1325  else
1326  {
1327  const size_t block( IsRowMajorMatrix<MT3>::value ? 256UL : 8UL );
1328 
1329  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1330  {
1331  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1332 
1333  for( size_t i=0UL; i<A.columns(); ++i )
1334  {
1335  const ConstIterator end( A.end(i) );
1336  ConstIterator element( A.begin(i) );
1337 
1338  for( ; element!=end; ++element )
1339  {
1340  const size_t i1( element->index() );
1341 
1342  const size_t jbegin( ( IsUpper<MT5>::value )
1343  ?( ( UPP )
1344  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
1345  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
1346  :( UPP ? max(i1,jj) : jj ) );
1347  const size_t jend( ( IsLower<MT5>::value )
1348  ?( ( LOW )
1349  ?( min( i1+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
1350  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
1351  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1352 
1353  if( jbegin >= jend )
1354  continue;
1355 
1356  for( size_t j=jbegin; j<jend; ++j ) {
1357  C(i1,j) -= element->value() * B(i,j);
1358  }
1359  }
1360  }
1361  }
1362  }
1363  }
1365  //**********************************************************************************************
1366 
1367  //**Default subtraction assignment to dense matrices (small matrices)***************************
1381  template< typename MT3 // Type of the left-hand side target matrix
1382  , typename MT4 // Type of the left-hand side matrix operand
1383  , typename MT5 > // Type of the right-hand side matrix operand
1385  selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1386  {
1387  selectDefaultSubAssignKernel( C, A, B );
1388  }
1390  //**********************************************************************************************
1391 
1392  //**Optimized subtraction assignment to dense matrices (small matrices)*************************
1407  template< typename MT3 // Type of the left-hand side target matrix
1408  , typename MT4 // Type of the left-hand side matrix operand
1409  , typename MT5 > // Type of the right-hand side matrix operand
1411  selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1412  {
1414 
1415  const size_t block( ( IsRowMajorMatrix<MT3>::value )?( 256UL ):( 8UL ) );
1416 
1417  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1418  {
1419  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1420 
1421  for( size_t i=0UL; i<A.columns(); ++i )
1422  {
1423  const ConstIterator end( A.end(i) );
1424  ConstIterator element( A.begin(i) );
1425 
1426  const size_t nonzeros( A.nonZeros(i) );
1427  const size_t kpos( nonzeros & size_t(-4) );
1428  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1429 
1430  for( size_t k=0UL; k<kpos; k+=4UL )
1431  {
1432  const size_t i1( element->index() );
1433  const ET1 v1( element->value() );
1434  ++element;
1435  const size_t i2( element->index() );
1436  const ET1 v2( element->value() );
1437  ++element;
1438  const size_t i3( element->index() );
1439  const ET1 v3( element->value() );
1440  ++element;
1441  const size_t i4( element->index() );
1442  const ET1 v4( element->value() );
1443  ++element;
1444 
1445  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1446 
1447  const size_t jbegin( ( IsUpper<MT5>::value )
1448  ?( ( UPP )
1449  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
1450  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
1451  :( UPP ? max(i1,jj) : jj ) );
1452  const size_t jend( ( IsLower<MT5>::value )
1453  ?( ( LOW )
1454  ?( min( i4+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
1455  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
1456  :( LOW ? min(i4+1UL,jpos) : jpos ) );
1457 
1458  if( jbegin >= jend )
1459  continue;
1460 
1461  for( size_t j=jbegin; j<jend; ++j ) {
1462  C(i1,j) -= v1 * B(i,j);
1463  C(i2,j) -= v2 * B(i,j);
1464  C(i3,j) -= v3 * B(i,j);
1465  C(i4,j) -= v4 * B(i,j);
1466  }
1467  }
1468 
1469  for( ; element!=end; ++element )
1470  {
1471  const size_t i1( element->index() );
1472 
1473  const size_t jbegin( ( IsUpper<MT5>::value )
1474  ?( ( UPP )
1475  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
1476  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
1477  :( UPP ? max(i1,jj) : jj ) );
1478  const size_t jend( ( IsLower<MT5>::value )
1479  ?( ( LOW )
1480  ?( min( i1+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
1481  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
1482  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1483 
1484  if( jbegin >= jend )
1485  continue;
1486 
1487  for( size_t j=jbegin; j<jend; ++j ) {
1488  C(i1,j) -= element->value() * B(i,j);
1489  }
1490  }
1491  }
1492  }
1493  }
1495  //**********************************************************************************************
1496 
1497  //**Default subtraction assignment to dense matrices (large matrices)***************************
1511  template< typename MT3 // Type of the left-hand side target matrix
1512  , typename MT4 // Type of the left-hand side matrix operand
1513  , typename MT5 > // Type of the right-hand side matrix operand
1515  selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1516  {
1517  selectDefaultSubAssignKernel( C, A, B );
1518  }
1520  //**********************************************************************************************
1521 
1522  //**Optimized subtraction assignment to dense matrices (large matrices)*************************
1537  template< typename MT3 // Type of the left-hand side target matrix
1538  , typename MT4 // Type of the left-hand side matrix operand
1539  , typename MT5 > // Type of the right-hand side matrix operand
1541  selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1542  {
1544 
1545  const ForwardFunctor fwd;
1546 
1547  const OppositeType_<MT4> tmp( serial( A ) );
1548  subAssign( C, fwd( tmp * B ) );
1549  }
1551  //**********************************************************************************************
1552 
1553  //**Restructuring subtraction assignment to row-major matrices**********************************
1568  template< typename MT // Type of the target matrix
1569  , bool SO > // Storage order of the target matrix
1571  subAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1572  {
1574 
1576 
1577  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1578  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1579 
1580  const ForwardFunctor fwd;
1581 
1582  subAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1583  }
1585  //**********************************************************************************************
1586 
1587  //**Subtraction assignment to sparse matrices***************************************************
1588  // No special implementation for the subtraction assignment to sparse matrices.
1589  //**********************************************************************************************
1590 
1591  //**Schur product assignment to dense matrices**************************************************
1604  template< typename MT // Type of the target dense matrix
1605  , bool SO > // Storage order of the target dense matrix
1606  friend inline void schurAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1607  {
1609 
1613 
1614  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1615  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1616 
1617  const ResultType tmp( serial( rhs ) );
1618  schurAssign( ~lhs, tmp );
1619  }
1621  //**********************************************************************************************
1622 
1623  //**Schur product assignment to sparse matrices*************************************************
1624  // No special implementation for the Schur product assignment to sparse matrices.
1625  //**********************************************************************************************
1626 
1627  //**Multiplication assignment to dense matrices*************************************************
1628  // No special implementation for the multiplication assignment to dense matrices.
1629  //**********************************************************************************************
1630 
1631  //**Multiplication assignment to sparse matrices************************************************
1632  // No special implementation for the multiplication assignment to sparse matrices.
1633  //**********************************************************************************************
1634 
1635  //**SMP assignment to dense matrices************************************************************
1651  template< typename MT // Type of the target dense matrix
1652  , bool SO > // Storage order of the target dense matrix
1654  smpAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1655  {
1657 
1658  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1659  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1660 
1661  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1662  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1663 
1664  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1665  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1666  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1667  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1668  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1669  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1670 
1671  smpAssign( ~lhs, A * B );
1672  }
1674  //**********************************************************************************************
1675 
1676  //**SMP assignment to sparse matrices***********************************************************
1692  template< typename MT // Type of the target sparse matrix
1693  , bool SO > // Storage order of the target sparse matrix
1695  smpAssign( SparseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1696  {
1698 
1700 
1707 
1708  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1709  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1710 
1711  const ForwardFunctor fwd;
1712 
1713  const TmpType tmp( rhs );
1714  smpAssign( ~lhs, fwd( tmp ) );
1715  }
1717  //**********************************************************************************************
1718 
1719  //**Restructuring SMP assignment to row-major matrices******************************************
1734  template< typename MT // Type of the target matrix
1735  , bool SO > // Storage order of the target matrix
1737  smpAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1738  {
1740 
1741  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1742  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1743 
1744  const ForwardFunctor fwd;
1745 
1746  smpAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1747  }
1749  //**********************************************************************************************
1750 
1751  //**SMP addition assignment to dense matrices***************************************************
1767  template< typename MT // Type of the target dense matrix
1768  , bool SO > // Storage order of the target dense matrix
1771  {
1773 
1774  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1775  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1776 
1777  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1778  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1779 
1780  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1781  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1782  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1783  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1784  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1785  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1786 
1787  smpAddAssign( ~lhs, A * B );
1788  }
1790  //**********************************************************************************************
1791 
1792  //**Restructuring SMP addition assignment to row-major matrices*********************************
1807  template< typename MT // Type of the target matrix
1808  , bool SO > // Storage order of the target matrix
1810  smpAddAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1811  {
1813 
1814  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1815  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1816 
1817  const ForwardFunctor fwd;
1818 
1819  smpAddAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1820  }
1822  //**********************************************************************************************
1823 
1824  //**SMP addition assignment to sparse matrices**************************************************
1825  // No special implementation for the SMP addition assignment to sparse matrices.
1826  //**********************************************************************************************
1827 
1828  //**SMP subtraction assignment to dense matrices************************************************
1844  template< typename MT // Type of the target dense matrix
1845  , bool SO > // Storage order of the target dense matrix
1848  {
1850 
1851  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1852  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1853 
1854  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1855  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1856 
1857  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1858  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1859  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1860  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1861  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1862  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1863 
1864  smpSubAssign( ~lhs, A * B );
1865  }
1867  //**********************************************************************************************
1868 
1869  //**Restructuring SMP subtraction assignment to row-major matrices******************************
1884  template< typename MT // Type of the target matrix
1885  , bool SO > // Storage order of the target matrix
1887  smpSubAssign( Matrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1888  {
1890 
1891  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1892  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1893 
1894  const ForwardFunctor fwd;
1895 
1896  smpSubAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1897  }
1899  //**********************************************************************************************
1900 
1901  //**SMP subtraction assignment to sparse matrices***********************************************
1902  // No special implementation for the SMP subtraction assignment to sparse matrices.
1903  //**********************************************************************************************
1904 
1905  //**SMP Schur product assignment to dense matrices**********************************************
1918  template< typename MT // Type of the target dense matrix
1919  , bool SO > // Storage order of the target dense matrix
1920  friend inline void smpSchurAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
1921  {
1923 
1927 
1928  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1929  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1930 
1931  const ResultType tmp( rhs );
1932  smpSchurAssign( ~lhs, tmp );
1933  }
1935  //**********************************************************************************************
1936 
1937  //**SMP Schur product assignment to sparse matrices*********************************************
1938  // No special implementation for the SMP Schur product assignment to sparse matrices.
1939  //**********************************************************************************************
1940 
1941  //**SMP multiplication assignment to dense matrices*********************************************
1942  // No special implementation for the SMP multiplication assignment to dense matrices.
1943  //**********************************************************************************************
1944 
1945  //**SMP multiplication assignment to sparse matrices********************************************
1946  // No special implementation for the SMP multiplication assignment to sparse matrices.
1947  //**********************************************************************************************
1948 
1949  //**Compile time checks*************************************************************************
1957  //**********************************************************************************************
1958 };
1959 //*************************************************************************************************
1960 
1961 
1962 
1963 
1964 //=================================================================================================
1965 //
1966 // GLOBAL BINARY ARITHMETIC OPERATORS
1967 //
1968 //=================================================================================================
1969 
1970 //*************************************************************************************************
2001 template< typename MT1 // Type of the left-hand side sparse matrix
2002  , typename MT2 > // Type of the right-hand side dense matrix
2003 inline decltype(auto)
2004  operator*( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,false>& rhs )
2005 {
2007 
2008  if( (~lhs).columns() != (~rhs).rows() ) {
2009  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
2010  }
2011 
2013  return ReturnType( ~lhs, ~rhs );
2014 }
2015 //*************************************************************************************************
2016 
2017 
2018 
2019 
2020 //=================================================================================================
2021 //
2022 // GLOBAL FUNCTIONS
2023 //
2024 //=================================================================================================
2025 
2026 //*************************************************************************************************
2052 template< typename MT1 // Type of the left-hand side dense matrix
2053  , typename MT2 // Type of the right-hand side dense matrix
2054  , bool SF // Symmetry flag
2055  , bool HF // Hermitian flag
2056  , bool LF // Lower flag
2057  , bool UF > // Upper flag
2058 inline decltype(auto) declsym( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2059 {
2061 
2062  if( !isSquare( dm ) ) {
2063  BLAZE_THROW_INVALID_ARGUMENT( "Invalid symmetric matrix specification" );
2064  }
2065 
2067  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2068 }
2070 //*************************************************************************************************
2071 
2072 
2073 //*************************************************************************************************
2099 template< typename MT1 // Type of the left-hand side dense matrix
2100  , typename MT2 // Type of the right-hand side dense matrix
2101  , bool SF // Symmetry flag
2102  , bool HF // Hermitian flag
2103  , bool LF // Lower flag
2104  , bool UF > // Upper flag
2105 inline decltype(auto) declherm( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2106 {
2108 
2109  if( !isSquare( dm ) ) {
2110  BLAZE_THROW_INVALID_ARGUMENT( "Invalid Hermitian matrix specification" );
2111  }
2112 
2114  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2115 }
2117 //*************************************************************************************************
2118 
2119 
2120 //*************************************************************************************************
2146 template< typename MT1 // Type of the left-hand side dense matrix
2147  , typename MT2 // Type of the right-hand side dense matrix
2148  , bool SF // Symmetry flag
2149  , bool HF // Hermitian flag
2150  , bool LF // Lower flag
2151  , bool UF > // Upper flag
2152 inline decltype(auto) decllow( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2153 {
2155 
2156  if( !isSquare( dm ) ) {
2157  BLAZE_THROW_INVALID_ARGUMENT( "Invalid lower matrix specification" );
2158  }
2159 
2161  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2162 }
2164 //*************************************************************************************************
2165 
2166 
2167 //*************************************************************************************************
2193 template< typename MT1 // Type of the left-hand side dense matrix
2194  , typename MT2 // Type of the right-hand side dense matrix
2195  , bool SF // Symmetry flag
2196  , bool HF // Hermitian flag
2197  , bool LF // Lower flag
2198  , bool UF > // Upper flag
2199 inline decltype(auto) declupp( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2200 {
2202 
2203  if( !isSquare( dm ) ) {
2204  BLAZE_THROW_INVALID_ARGUMENT( "Invalid upper matrix specification" );
2205  }
2206 
2208  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2209 }
2211 //*************************************************************************************************
2212 
2213 
2214 //*************************************************************************************************
2240 template< typename MT1 // Type of the left-hand side dense matrix
2241  , typename MT2 // Type of the right-hand side dense matrix
2242  , bool SF // Symmetry flag
2243  , bool HF // Hermitian flag
2244  , bool LF // Lower flag
2245  , bool UF > // Upper flag
2246 inline decltype(auto) decldiag( const TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2247 {
2249 
2250  if( !isSquare( dm ) ) {
2251  BLAZE_THROW_INVALID_ARGUMENT( "Invalid diagonal matrix specification" );
2252  }
2253 
2255  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2256 }
2258 //*************************************************************************************************
2259 
2260 
2261 
2262 
2263 //=================================================================================================
2264 //
2265 // SIZE SPECIALIZATIONS
2266 //
2267 //=================================================================================================
2268 
2269 //*************************************************************************************************
2271 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2272 struct Size< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 0UL >
2273  : public Size<MT1,0UL>
2274 {};
2275 
2276 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2277 struct Size< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF>, 1UL >
2278  : public Size<MT2,1UL>
2279 {};
2281 //*************************************************************************************************
2282 
2283 
2284 
2285 
2286 //=================================================================================================
2287 //
2288 // ISALIGNED SPECIALIZATIONS
2289 //
2290 //=================================================================================================
2291 
2292 //*************************************************************************************************
2294 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2295 struct IsAligned< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2296  : public IsAligned<MT2>
2297 {};
2299 //*************************************************************************************************
2300 
2301 
2302 
2303 
2304 //=================================================================================================
2305 //
2306 // ISSYMMETRIC SPECIALIZATIONS
2307 //
2308 //=================================================================================================
2309 
2310 //*************************************************************************************************
2312 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2313 struct IsSymmetric< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2314  : public Or< Bool<SF>
2315  , And< Bool<HF>
2316  , IsBuiltin< ElementType_< TSMatDMatMultExpr<MT1,MT2,false,true,false,false> > > >
2317  , And< Bool<LF>, Bool<UF> > >
2318 {};
2320 //*************************************************************************************************
2321 
2322 
2323 
2324 
2325 //=================================================================================================
2326 //
2327 // ISHERMITIAN SPECIALIZATIONS
2328 //
2329 //=================================================================================================
2330 
2331 //*************************************************************************************************
2333 template< typename MT1, typename MT2, bool SF, bool LF, bool UF >
2334 struct IsHermitian< TSMatDMatMultExpr<MT1,MT2,SF,true,LF,UF> >
2335  : public TrueType
2336 {};
2338 //*************************************************************************************************
2339 
2340 
2341 
2342 
2343 //=================================================================================================
2344 //
2345 // ISLOWER SPECIALIZATIONS
2346 //
2347 //=================================================================================================
2348 
2349 //*************************************************************************************************
2351 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2352 struct IsLower< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2353  : public Or< Bool<LF>
2354  , And< IsLower<MT1>, IsLower<MT2> >
2355  , And< Or< Bool<SF>, Bool<HF> >
2356  , IsUpper<MT1>, IsUpper<MT2> > >
2357 {};
2359 //*************************************************************************************************
2360 
2361 
2362 
2363 
2364 //=================================================================================================
2365 //
2366 // ISUNILOWER SPECIALIZATIONS
2367 //
2368 //=================================================================================================
2369 
2370 //*************************************************************************************************
2372 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2373 struct IsUniLower< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2374  : public Or< And< IsUniLower<MT1>, IsUniLower<MT2> >
2375  , And< Or< Bool<SF>, Bool<HF> >
2376  , IsUniUpper<MT1>, IsUniUpper<MT2> > >
2377 {};
2379 //*************************************************************************************************
2380 
2381 
2382 
2383 
2384 //=================================================================================================
2385 //
2386 // ISSTRICTLYLOWER SPECIALIZATIONS
2387 //
2388 //=================================================================================================
2389 
2390 //*************************************************************************************************
2392 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2393 struct IsStrictlyLower< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2394  : public Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
2395  , And< IsStrictlyLower<MT2>, IsLower<MT1> >
2396  , And< Or< Bool<SF>, Bool<HF> >
2397  , Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
2398  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > > > >
2399 {};
2401 //*************************************************************************************************
2402 
2403 
2404 
2405 
2406 //=================================================================================================
2407 //
2408 // ISUPPER SPECIALIZATIONS
2409 //
2410 //=================================================================================================
2411 
2412 //*************************************************************************************************
2414 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2415 struct IsUpper< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2416  : public Or< Bool<UF>
2417  , And< IsUpper<MT1>, IsUpper<MT2> >
2418  , And< Or< Bool<SF>, Bool<HF> >
2419  , IsLower<MT1>, IsLower<MT2> > >
2420 {};
2422 //*************************************************************************************************
2423 
2424 
2425 
2426 
2427 //=================================================================================================
2428 //
2429 // ISUNIUPPER SPECIALIZATIONS
2430 //
2431 //=================================================================================================
2432 
2433 //*************************************************************************************************
2435 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2436 struct IsUniUpper< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2437  : public Or< And< IsUniUpper<MT1>, IsUniUpper<MT2> >
2438  , And< Or< Bool<SF>, Bool<HF> >
2439  , IsUniLower<MT1>, IsUniLower<MT2> > >
2440 {};
2442 //*************************************************************************************************
2443 
2444 
2445 
2446 
2447 //=================================================================================================
2448 //
2449 // ISSTRICTLYUPPER SPECIALIZATIONS
2450 //
2451 //=================================================================================================
2452 
2453 //*************************************************************************************************
2455 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2456 struct IsStrictlyUpper< TSMatDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2457  : public Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
2458  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> >
2459  , And< Or< Bool<SF>, Bool<HF> >
2460  , Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
2461  , And< IsStrictlyLower<MT2>, IsLower<MT1> > > > >
2462 {};
2464 //*************************************************************************************************
2465 
2466 } // namespace blaze
2467 
2468 #endif
decltype(auto) subvector(Vector< VT, TF > &, RSAs...)
Creating a view on a specific subvector of the given vector.
Definition: Subvector.h:329
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exception.This macro encapsulates the default way o...
Definition: Exception.h:235
Header file for auxiliary alias declarations.
decltype(auto) column(Matrix< MT, SO > &matrix, RCAs... args)
Creating a view on a specific column of the given matrix.
Definition: Column.h: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
ResultType_< MT2 > RT2
Result type of the right-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:130
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:416
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:86
Header file for basic type definitions.
ElementType_< ResultType > ElementType
Resulting element type.
Definition: TSMatDMatMultExpr.h:240
CompositeType_< MT1 > CT1
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:133
Flag for symmetric matrices.
Definition: TSMatDMatMultExpr.h:150
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:287
Header file for the serial shim.
ElementType_< RT2 > ET2
Element type of the right-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:132
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: TSMatDMatMultExpr.h:362
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:433
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
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
LeftOperand leftOperand() const noexcept
Returns the left-hand side transpose sparse matrix operand.
Definition: TSMatDMatMultExpr.h:372
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.
IfTrue_< evaluateRight, const RT2, CT2 > RT
Type for the assignment of the right-hand side dense matrix operand.
Definition: TSMatDMatMultExpr.h:254
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: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
CompositeType_< MT2 > CT2
Composite type of the right-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:134
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: TSMatDMatMultExpr.h:352
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:80
const ResultType CompositeType
Data type for composite expression templates.
Definition: TSMatDMatMultExpr.h:242
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:251
RightOperand rhs_
Right-hand side dense matrix of the multiplication expression.
Definition: TSMatDMatMultExpr.h:434
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:248
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
Flag for Hermitian matrices.
Definition: TSMatDMatMultExpr.h:151
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.
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:239
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:245
#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.
Flag for lower matrices.
Definition: TSMatDMatMultExpr.h:152
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
MultTrait_< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: TSMatDMatMultExpr.h:237
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
ElementType_< RT1 > ET1
Element type of the left-hand side dense matrix expression.
Definition: TSMatDMatMultExpr.h:131
Generic wrapper for the null function.
Definition: Noop.h:59
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:336
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: TSMatDMatMultExpr.h:426
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:430
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:107
RightOperand rightOperand() const noexcept
Returns the right-hand side dense matrix operand.
Definition: TSMatDMatMultExpr.h:382
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
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
TSMatDMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the TSMatDMatMultExpr class.
Definition: TSMatDMatMultExpr.h:272
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: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
OppositeType_< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: TSMatDMatMultExpr.h:238
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:241
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
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: TSMatDMatMultExpr.h:406
decltype(auto) declherm(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as Hermitian.
Definition: DMatDeclHermExpr.h:1028
Header file for the IsRowMajorMatrix type trait.
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
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
Generic wrapper for the decldiag() function.
Definition: DeclDiag.h:58
Flag for upper matrices.
Definition: TSMatDMatMultExpr.h:153
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: TSMatDMatMultExpr.h:394
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.
Header file for the function trace functionality.
ResultType_< MT1 > RT1
Result type of the left-hand side sparse matrix expression.
Definition: TSMatDMatMultExpr.h:129