TSMatTDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_TSMATTDMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_TSMATTDMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <blaze/math/Aliases.h>
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 TSMatTDMatMultExpr
126  : public MatMatMultExpr< DenseMatrix< TSMatTDMatMultExpr<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 || IsSymmetric<T3>::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 TSMatTDMatMultExpr( 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_TSMATTDMATMULT_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 TSMatTDMatMultExpr& 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  TSMatTDMatMultExpr::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 < TSMATTDMATMULT_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( 64UL );
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 ? 128UL : 64UL );
641 
642  for( size_t jj=0UL; jj<B.columns(); jj+=block )
643  {
644  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
645 
646  for( size_t i=0UL; i<A.rows(); ++i ) {
647  for( size_t j=jj; j<jpos; ++j ) {
648  reset( C(i,j) );
649  }
650  }
651 
652  for( size_t i=0UL; i<A.columns(); ++i )
653  {
654  const ConstIterator end( A.end(i) );
655  ConstIterator element( A.begin(i) );
656 
657  const size_t nonzeros( A.nonZeros(i) );
658  const size_t kpos( nonzeros & size_t(-4) );
659  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
660 
661  for( size_t k=0UL; k<kpos; k+=4UL )
662  {
663  const size_t i1( element->index() );
664  const ET1 v1( element->value() );
665  ++element;
666  const size_t i2( element->index() );
667  const ET1 v2( element->value() );
668  ++element;
669  const size_t i3( element->index() );
670  const ET1 v3( element->value() );
671  ++element;
672  const size_t i4( element->index() );
673  const ET1 v4( element->value() );
674  ++element;
675 
676  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
677 
678  const size_t jbegin( ( IsUpper<MT5>::value )
679  ?( ( SYM || HERM || UPP )
680  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
681  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
682  :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
683  const size_t jend( ( IsLower<MT5>::value )
684  ?( ( LOW )
685  ?( min( i4+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
686  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
687  :( LOW ? min(i4+1UL,jpos) : jpos ) );
688 
689  if( jbegin >= jend )
690  continue;
691 
692  for( size_t j=jbegin; j<jend; ++j ) {
693  C(i1,j) += v1 * B(i,j);
694  C(i2,j) += v2 * B(i,j);
695  C(i3,j) += v3 * B(i,j);
696  C(i4,j) += v4 * B(i,j);
697  }
698  }
699 
700  for( ; element!=end; ++element )
701  {
702  const size_t i1( element->index() );
703 
704  const size_t jbegin( ( IsUpper<MT5>::value )
705  ?( ( SYM || HERM || UPP )
706  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
707  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
708  :( SYM || HERM || UPP ? max(i1,jj) : jj ) );
709  const size_t jend( ( IsLower<MT5>::value )
710  ?( ( LOW )
711  ?( min( i1+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
712  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
713  :( LOW ? min(i1+1UL,jpos) : jpos ) );
714 
715  if( jbegin >= jend )
716  continue;
717 
718  for( size_t j=jbegin; j<jend; ++j ) {
719  C(i1,j) += element->value() * B(i,j);
720  }
721  }
722  }
723  }
724 
725  if( SYM || HERM ) {
726  for( size_t j=0UL; j<B.columns(); ++j ) {
727  for( size_t i=j+1UL; i<A.rows(); ++i ) {
728  C(i,j) = HERM ? conj( C(j,i) ) : C(j,i);
729  }
730  }
731  }
732  }
734  //**********************************************************************************************
735 
736  //**Default assignment to dense matrices (large matrices)***************************************
750  template< typename MT3 // Type of the left-hand side target matrix
751  , typename MT4 // Type of the left-hand side matrix operand
752  , typename MT5 > // Type of the right-hand side matrix operand
754  selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
755  {
756  selectDefaultAssignKernel( C, A, B );
757  }
759  //**********************************************************************************************
760 
761  //**Optimized assignment to dense matrices (large matrices)*************************************
776  template< typename MT3 // Type of the left-hand side target matrix
777  , typename MT4 // Type of the left-hand side matrix operand
778  , typename MT5 > // Type of the right-hand side matrix operand
780  selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B )
781  {
783 
784  const ForwardFunctor fwd;
785 
786  const OppositeType_<MT4> tmp( serial( A ) );
787  assign( C, fwd( tmp * B ) );
788  }
790  //**********************************************************************************************
791 
792  //**Assignment to sparse matrices***************************************************************
805  template< typename MT // Type of the target sparse matrix
806  , bool SO > // Storage order of the target sparse matrix
808  assign( SparseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
809  {
811 
813 
820 
821  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
822  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
823 
824  const ForwardFunctor fwd;
825 
826  const TmpType tmp( serial( rhs ) );
827  assign( ~lhs, fwd( tmp ) );
828  }
830  //**********************************************************************************************
831 
832  //**Restructuring assignment********************************************************************
847  template< typename MT // Type of the target matrix
848  , bool SO > // Storage order of the target matrix
850  assign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
851  {
853 
855 
856  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
857  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
858 
859  const ForwardFunctor fwd;
860 
862  assign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
863  else if( IsSymmetric<MT1>::value )
864  assign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
865  else
866  assign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
867  }
869  //**********************************************************************************************
870 
871  //**Addition assignment to dense matrices*******************************************************
884  template< typename MT // Type of the target dense matrix
885  , bool SO > // Storage order of the target dense matrix
887  addAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
888  {
890 
891  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
892  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
893 
894  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
895  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
896 
897  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
898  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
899  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
900  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
901  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
902  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
903 
904  TSMatTDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
905  }
907  //**********************************************************************************************
908 
909  //**Addition assignment to dense matrices (kernel selection)************************************
920  template< typename MT3 // Type of the left-hand side target matrix
921  , typename MT4 // Type of the left-hand side matrix operand
922  , typename MT5 > // Type of the right-hand side matrix operand
923  static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
924  {
925  const size_t size( C.rows() * C.columns() );
926 
927  if( ( IsRowMajorMatrix<MT3>::value && size < TSMATTDMATMULT_THRESHOLD ) ||
928  ( IsColumnMajorMatrix<MT3>::value && size < 625UL ) )
929  selectSmallAddAssignKernel( C, A, B );
930  else
931  selectLargeAddAssignKernel( C, A, B );
932  }
934  //**********************************************************************************************
935 
936  //**Default addition assignment to dense matrices***********************************************
951  template< typename MT3 // Type of the left-hand side target matrix
952  , typename MT4 // Type of the left-hand side matrix operand
953  , typename MT5 > // Type of the right-hand side matrix operand
954  static inline void selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
955  {
957 
959  {
960  for( size_t i=0UL; i<A.columns(); ++i )
961  {
962  const ConstIterator end( A.end(i) );
963  ConstIterator element( A.begin(i) );
964 
965  for( ; element!=end; ++element ) {
966  C(element->index(),i) += element->value() * B(i,i);
967  }
968  }
969  }
970  else
971  {
972  const size_t block( 64UL );
973 
974  for( size_t jj=0UL; jj<B.columns(); jj+=block )
975  {
976  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
977 
978  for( size_t i=0UL; i<A.columns(); ++i )
979  {
980  const ConstIterator end( A.end(i) );
981  ConstIterator element( A.begin(i) );
982 
983  for( ; element!=end; ++element )
984  {
985  const size_t i1( element->index() );
986 
987  const size_t jbegin( ( IsUpper<MT5>::value )
988  ?( ( UPP )
989  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
990  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
991  :( UPP ? max(i1,jj) : jj ) );
992  const size_t jend( ( IsLower<MT5>::value )
993  ?( ( LOW )
994  ?( min( i1+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
995  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
996  :( LOW ? min(i1+1UL,jpos) : jpos ) );
997 
998  if( jbegin >= jend )
999  continue;
1000 
1001  for( size_t j=jbegin; j<jend; ++j ) {
1002  C(i1,j) += element->value() * B(i,j);
1003  }
1004  }
1005  }
1006  }
1007  }
1008  }
1010  //**********************************************************************************************
1011 
1012  //**Default addition assignment to dense matrices (small matrices)******************************
1026  template< typename MT3 // Type of the left-hand side target matrix
1027  , typename MT4 // Type of the left-hand side matrix operand
1028  , typename MT5 > // Type of the right-hand side matrix operand
1030  selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1031  {
1032  selectDefaultAddAssignKernel( C, A, B );
1033  }
1035  //**********************************************************************************************
1036 
1037  //**Optimized addition assignment to dense matrices (small matrices)****************************
1052  template< typename MT3 // Type of the left-hand side target matrix
1053  , typename MT4 // Type of the left-hand side matrix operand
1054  , typename MT5 > // Type of the right-hand side matrix operand
1056  selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1057  {
1059 
1060  const size_t block( IsRowMajorMatrix<MT3>::value ? 128UL : 64UL );
1061 
1062  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1063  {
1064  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1065 
1066  for( size_t i=0UL; i<A.columns(); ++i )
1067  {
1068  const ConstIterator end( A.end(i) );
1069  ConstIterator element( A.begin(i) );
1070 
1071  const size_t nonzeros( A.nonZeros(i) );
1072  const size_t kpos( nonzeros & size_t(-4) );
1073  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1074 
1075  for( size_t k=0UL; k<kpos; k+=4UL )
1076  {
1077  const size_t i1( element->index() );
1078  const ET1 v1( element->value() );
1079  ++element;
1080  const size_t i2( element->index() );
1081  const ET1 v2( element->value() );
1082  ++element;
1083  const size_t i3( element->index() );
1084  const ET1 v3( element->value() );
1085  ++element;
1086  const size_t i4( element->index() );
1087  const ET1 v4( element->value() );
1088  ++element;
1089 
1090  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1091 
1092  const size_t jbegin( ( IsUpper<MT5>::value )
1093  ?( ( UPP )
1094  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
1095  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
1096  :( UPP ? max(i1,jj) : jj ) );
1097  const size_t jend( ( IsLower<MT5>::value )
1098  ?( ( LOW )
1099  ?( min( i4+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
1100  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
1101  :( LOW ? min(i4+1UL,jpos) : jpos ) );
1102 
1103  if( jbegin >= jend )
1104  continue;
1105 
1106  for( size_t j=jbegin; j<jend; ++j ) {
1107  C(i1,j) += v1 * B(i,j);
1108  C(i2,j) += v2 * B(i,j);
1109  C(i3,j) += v3 * B(i,j);
1110  C(i4,j) += v4 * B(i,j);
1111  }
1112  }
1113 
1114  for( ; element!=end; ++element )
1115  {
1116  const size_t i1( element->index() );
1117 
1118  const size_t jbegin( ( IsUpper<MT5>::value )
1119  ?( ( UPP )
1120  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
1121  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
1122  :( UPP ? max(i1,jj) : jj ) );
1123  const size_t jend( ( IsLower<MT5>::value )
1124  ?( ( LOW )
1125  ?( min( i1+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
1126  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
1127  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1128 
1129  if( jbegin >= jend )
1130  continue;
1131 
1132  for( size_t j=jbegin; j<jend; ++j ) {
1133  C(i1,j) += element->value() * B(i,j);
1134  }
1135  }
1136  }
1137  }
1138  }
1140  //**********************************************************************************************
1141 
1142  //**Default addition assignment to dense matrices (large matrices)******************************
1156  template< typename MT3 // Type of the left-hand side target matrix
1157  , typename MT4 // Type of the left-hand side matrix operand
1158  , typename MT5 > // Type of the right-hand side matrix operand
1160  selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1161  {
1162  selectDefaultAddAssignKernel( C, A, B );
1163  }
1165  //**********************************************************************************************
1166 
1167  //**Optimized addition assignment to dense matrices (large matrices)****************************
1182  template< typename MT3 // Type of the left-hand side target matrix
1183  , typename MT4 // Type of the left-hand side matrix operand
1184  , typename MT5 > // Type of the right-hand side matrix operand
1186  selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1187  {
1189 
1190  const ForwardFunctor fwd;
1191 
1192  const OppositeType_<MT4> tmp( serial( A ) );
1193  addAssign( C, fwd( tmp * B ) );
1194  }
1196  //**********************************************************************************************
1197 
1198  //**Restructuring addition assignment***********************************************************
1213  template< typename MT // Type of the target matrix
1214  , bool SO > // Storage order of the target matrix
1216  addAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1217  {
1219 
1221 
1222  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1223  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1224 
1225  const ForwardFunctor fwd;
1226 
1228  addAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1229  else if( IsSymmetric<MT1>::value )
1230  addAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1231  else
1232  addAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1233  }
1235  //**********************************************************************************************
1236 
1237  //**Addition assignment to sparse matrices******************************************************
1238  // No special implementation for the addition assignment to sparse matrices.
1239  //**********************************************************************************************
1240 
1241  //**Subtraction assignment to dense matrices****************************************************
1254  template< typename MT // Type of the target dense matrix
1255  , bool SO > // Storage order of the target dense matrix
1257  subAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1258  {
1260 
1261  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1262  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1263 
1264  LT A( serial( rhs.lhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1265  RT B( serial( rhs.rhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1266 
1267  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1268  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1269  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1270  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1271  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1272  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1273 
1274  TSMatTDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1275  }
1277  //**********************************************************************************************
1278 
1279  //**Subtraction assignment to dense matrices (kernel selection)*********************************
1290  template< typename MT3 // Type of the left-hand side target matrix
1291  , typename MT4 // Type of the left-hand side matrix operand
1292  , typename MT5 > // Type of the right-hand side matrix operand
1293  static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1294  {
1295  const size_t size( C.rows() * C.columns() );
1296 
1297  if( ( IsRowMajorMatrix<MT3>::value && size < TSMATTDMATMULT_THRESHOLD ) ||
1298  ( IsColumnMajorMatrix<MT3>::value && size < 625UL ) )
1299  selectSmallSubAssignKernel( C, A, B );
1300  else
1301  selectLargeSubAssignKernel( C, A, B );
1302  }
1304  //**********************************************************************************************
1305 
1306  //**Default subtraction assignment to dense matrices********************************************
1321  template< typename MT3 // Type of the left-hand side target matrix
1322  , typename MT4 // Type of the left-hand side matrix operand
1323  , typename MT5 > // Type of the right-hand side matrix operand
1324  static inline void selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1325  {
1327 
1329  {
1330  for( size_t i=0UL; i<A.columns(); ++i )
1331  {
1332  const ConstIterator end( A.end(i) );
1333  ConstIterator element( A.begin(i) );
1334 
1335  for( ; element!=end; ++element ) {
1336  C(element->index(),i) -= element->value() * B(i,i);
1337  }
1338  }
1339  }
1340  else
1341  {
1342  const size_t block( 64UL );
1343 
1344  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1345  {
1346  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1347 
1348  for( size_t i=0UL; i<A.columns(); ++i )
1349  {
1350  const ConstIterator end( A.end(i) );
1351  ConstIterator element( A.begin(i) );
1352 
1353  for( ; element!=end; ++element )
1354  {
1355  const size_t i1( element->index() );
1356 
1357  const size_t jbegin( ( IsUpper<MT5>::value )
1358  ?( ( UPP )
1359  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
1360  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
1361  :( UPP ? max(i1,jj) : jj ) );
1362  const size_t jend( ( IsLower<MT5>::value )
1363  ?( ( LOW )
1364  ?( min( i1+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
1365  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
1366  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1367 
1368  if( jbegin >= jend )
1369  continue;
1370 
1371  for( size_t j=jbegin; j<jend; ++j ) {
1372  C(i1,j) -= element->value() * B(i,j);
1373  }
1374  }
1375  }
1376  }
1377  }
1378  }
1380  //**********************************************************************************************
1381 
1382  //**Default subtraction assignment to dense matrices (small matrices)***************************
1396  template< typename MT3 // Type of the left-hand side target matrix
1397  , typename MT4 // Type of the left-hand side matrix operand
1398  , typename MT5 > // Type of the right-hand side matrix operand
1400  selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1401  {
1402  selectDefaultSubAssignKernel( C, A, B );
1403  }
1405  //**********************************************************************************************
1406 
1407  //**Optimized subtraction assignment to dense matrices (small matrices)*************************
1422  template< typename MT3 // Type of the left-hand side target matrix
1423  , typename MT4 // Type of the left-hand side matrix operand
1424  , typename MT5 > // Type of the right-hand side matrix operand
1426  selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1427  {
1429 
1430  const size_t block( IsRowMajorMatrix<MT3>::value ? 128UL : 64UL );
1431 
1432  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1433  {
1434  const size_t jpos( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
1435 
1436  for( size_t i=0UL; i<A.columns(); ++i )
1437  {
1438  const ConstIterator end( A.end(i) );
1439  ConstIterator element( A.begin(i) );
1440 
1441  const size_t nonzeros( A.nonZeros(i) );
1442  const size_t kpos( nonzeros & size_t(-4) );
1443  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1444 
1445  for( size_t k=0UL; k<kpos; k+=4UL )
1446  {
1447  const size_t i1( element->index() );
1448  const ET1 v1( element->value() );
1449  ++element;
1450  const size_t i2( element->index() );
1451  const ET1 v2( element->value() );
1452  ++element;
1453  const size_t i3( element->index() );
1454  const ET1 v3( element->value() );
1455  ++element;
1456  const size_t i4( element->index() );
1457  const ET1 v4( element->value() );
1458  ++element;
1459 
1460  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1461 
1462  const size_t jbegin( ( IsUpper<MT5>::value )
1463  ?( ( UPP )
1464  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
1465  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
1466  :( UPP ? max(i1,jj) : jj ) );
1467  const size_t jend( ( IsLower<MT5>::value )
1468  ?( ( LOW )
1469  ?( min( i4+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
1470  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
1471  :( LOW ? min(i4+1UL,jpos) : jpos ) );
1472 
1473  if( jbegin >= jend )
1474  continue;
1475 
1476  for( size_t j=jbegin; j<jend; ++j ) {
1477  C(i1,j) -= v1 * B(i,j);
1478  C(i2,j) -= v2 * B(i,j);
1479  C(i3,j) -= v3 * B(i,j);
1480  C(i4,j) -= v4 * B(i,j);
1481  }
1482  }
1483 
1484  for( ; element!=end; ++element )
1485  {
1486  const size_t i1( element->index() );
1487 
1488  const size_t jbegin( ( IsUpper<MT5>::value )
1489  ?( ( UPP )
1490  ?( max( i1, IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) )
1491  :( max( IsStrictlyUpper<MT5>::value ? i+1UL : i, jj ) ) )
1492  :( UPP ? max(i1,jj) : jj ) );
1493  const size_t jend( ( IsLower<MT5>::value )
1494  ?( ( LOW )
1495  ?( min( i1+1UL, IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) )
1496  :( min( IsStrictlyLower<MT5>::value ? i : i+1UL, jpos ) ) )
1497  :( LOW ? min(i1+1UL,jpos) : jpos ) );
1498 
1499  if( jbegin >= jend )
1500  continue;
1501 
1502  for( size_t j=jbegin; j<jend; ++j ) {
1503  C(i1,j) -= element->value() * B(i,j);
1504  }
1505  }
1506  }
1507  }
1508  }
1510  //**********************************************************************************************
1511 
1512  //**Default subtraction assignment to dense matrices (large matrices)***************************
1526  template< typename MT3 // Type of the left-hand side target matrix
1527  , typename MT4 // Type of the left-hand side matrix operand
1528  , typename MT5 > // Type of the right-hand side matrix operand
1530  selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1531  {
1532  selectDefaultSubAssignKernel( C, A, B );
1533  }
1535  //**********************************************************************************************
1536 
1537  //**Optimized subtraction assignment to dense matrices (large matrices)*************************
1552  template< typename MT3 // Type of the left-hand side target matrix
1553  , typename MT4 // Type of the left-hand side matrix operand
1554  , typename MT5 > // Type of the right-hand side matrix operand
1556  selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1557  {
1559 
1560  const ForwardFunctor fwd;
1561 
1562  const OppositeType_<MT4> tmp( serial( A ) );
1563  subAssign( C, fwd( tmp * B ) );
1564  }
1566  //**********************************************************************************************
1567 
1568  //**Restructuring subtraction assignment********************************************************
1583  template< typename MT // Type of the target matrix
1584  , bool SO > // Storage order of the target matrix
1586  subAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1587  {
1589 
1591 
1592  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1593  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1594 
1595  const ForwardFunctor fwd;
1596 
1598  subAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1599  else if( IsSymmetric<MT1>::value )
1600  subAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1601  else
1602  subAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1603  }
1605  //**********************************************************************************************
1606 
1607  //**Subtraction assignment to sparse matrices***************************************************
1608  // No special implementation for the subtraction assignment to sparse matrices.
1609  //**********************************************************************************************
1610 
1611  //**Schur product assignment to dense matrices**************************************************
1624  template< typename MT // Type of the target dense matrix
1625  , bool SO > // Storage order of the target dense matrix
1626  friend inline void schurAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1627  {
1629 
1633 
1634  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1635  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1636 
1637  const ResultType tmp( serial( rhs ) );
1638  schurAssign( ~lhs, tmp );
1639  }
1641  //**********************************************************************************************
1642 
1643  //**Schur product assignment to sparse matrices*************************************************
1644  // No special implementation for the Schur product assignment to sparse matrices.
1645  //**********************************************************************************************
1646 
1647  //**Multiplication assignment to dense matrices*************************************************
1648  // No special implementation for the multiplication assignment to dense matrices.
1649  //**********************************************************************************************
1650 
1651  //**Multiplication assignment to sparse matrices************************************************
1652  // No special implementation for the multiplication assignment to sparse matrices.
1653  //**********************************************************************************************
1654 
1655  //**SMP assignment to dense matrices************************************************************
1671  template< typename MT // Type of the target dense matrix
1672  , bool SO > // Storage order of the target dense matrix
1674  smpAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1675  {
1677 
1678  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1679  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1680 
1681  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1682  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1683 
1684  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1685  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1686  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1687  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1688  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1689  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1690 
1691  smpAssign( ~lhs, A * B );
1692  }
1694  //**********************************************************************************************
1695 
1696  //**SMP assignment to sparse matrices***********************************************************
1712  template< typename MT // Type of the target sparse matrix
1713  , bool SO > // Storage order of the target sparse matrix
1716  {
1718 
1720 
1727 
1728  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1729  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1730 
1731  const ForwardFunctor fwd;
1732 
1733  const TmpType tmp( rhs );
1734  smpAssign( ~lhs, fwd( tmp ) );
1735  }
1737  //**********************************************************************************************
1738 
1739  //**Restructuring SMP assignment****************************************************************
1754  template< typename MT // Type of the target matrix
1755  , bool SO > // Storage order of the target matrix
1757  smpAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1758  {
1760 
1762 
1763  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1764  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1765 
1766  const ForwardFunctor fwd;
1767 
1769  smpAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1770  else if( IsSymmetric<MT1>::value )
1771  smpAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1772  else
1773  smpAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1774  }
1776  //**********************************************************************************************
1777 
1778  //**SMP addition assignment to dense matrices***************************************************
1794  template< typename MT // Type of the target dense matrix
1795  , bool SO > // Storage order of the target dense matrix
1798  {
1800 
1801  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1802  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1803 
1804  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1805  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1806 
1807  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1808  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1809  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1810  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1811  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1812  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1813 
1814  smpAddAssign( ~lhs, A * B );
1815  }
1817  //**********************************************************************************************
1818 
1819  //**Restructuring SMP addition assignment*******************************************************
1834  template< typename MT // Type of the target matrix
1835  , bool SO > // Storage order of the target matrix
1837  smpAddAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1838  {
1840 
1842 
1843  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1844  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1845 
1846  const ForwardFunctor fwd;
1847 
1849  smpAddAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1850  else if( IsSymmetric<MT1>::value )
1851  smpAddAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1852  else
1853  smpAddAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1854  }
1856  //**********************************************************************************************
1857 
1858  //**SMP addition assignment to sparse matrices**************************************************
1859  // No special implementation for the SMP addition assignment to sparse matrices.
1860  //**********************************************************************************************
1861 
1862  //**SMP subtraction assignment to dense matrices************************************************
1878  template< typename MT // Type of the target dense matrix
1879  , bool SO > // Storage order of the target dense matrix
1882  {
1884 
1885  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1886  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1887 
1888  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
1889  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
1890 
1891  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1892  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1893  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1894  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1895  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1896  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1897 
1898  smpSubAssign( ~lhs, A * B );
1899  }
1901  //**********************************************************************************************
1902 
1903  //**Restructuring SMP subtraction assignment****************************************************
1918  template< typename MT // Type of the target matrix
1919  , bool SO > // Storage order of the target matrix
1921  smpSubAssign( Matrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1922  {
1924 
1926 
1927  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1928  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1929 
1930  const ForwardFunctor fwd;
1931 
1933  smpSubAssign( ~lhs, fwd( trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ) );
1934  else if( IsSymmetric<MT1>::value )
1935  smpSubAssign( ~lhs, fwd( trans( rhs.lhs_ ) * rhs.rhs_ ) );
1936  else
1937  smpSubAssign( ~lhs, fwd( rhs.lhs_ * trans( rhs.rhs_ ) ) );
1938  }
1940  //**********************************************************************************************
1941 
1942  //**SMP subtraction assignment to sparse matrices***********************************************
1943  // No special implementation for the SMP subtraction assignment to sparse matrices.
1944  //**********************************************************************************************
1945 
1946  //**SMP Schur product assignment to dense matrices**********************************************
1959  template< typename MT // Type of the target dense matrix
1960  , bool SO > // Storage order of the target dense matrix
1961  friend inline void smpSchurAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
1962  {
1964 
1968 
1969  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1970  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1971 
1972  const ResultType tmp( rhs );
1973  smpSchurAssign( ~lhs, tmp );
1974  }
1976  //**********************************************************************************************
1977 
1978  //**SMP Schur product assignment to sparse matrices*********************************************
1979  // No special implementation for the SMP Schur product assignment to sparse matrices.
1980  //**********************************************************************************************
1981 
1982  //**SMP multiplication assignment to dense matrices*********************************************
1983  // No special implementation for the SMP multiplication assignment to dense matrices.
1984  //**********************************************************************************************
1985 
1986  //**SMP multiplication assignment to sparse matrices********************************************
1987  // No special implementation for the SMP multiplication assignment to sparse matrices.
1988  //**********************************************************************************************
1989 
1990  //**Compile time checks*************************************************************************
1998  //**********************************************************************************************
1999 };
2000 //*************************************************************************************************
2001 
2002 
2003 
2004 
2005 //=================================================================================================
2006 //
2007 // GLOBAL BINARY ARITHMETIC OPERATORS
2008 //
2009 //=================================================================================================
2010 
2011 //*************************************************************************************************
2040 template< typename MT1 // Type of the left-hand side sparse matrix
2041  , typename MT2 > // Type of the right-hand side dense matrix
2042 inline decltype(auto)
2043  operator*( const SparseMatrix<MT1,true>& lhs, const DenseMatrix<MT2,true>& rhs )
2044 {
2046 
2047  if( (~lhs).columns() != (~rhs).rows() ) {
2048  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
2049  }
2050 
2052  return ReturnType( ~lhs, ~rhs );
2053 }
2054 //*************************************************************************************************
2055 
2056 
2057 
2058 
2059 //=================================================================================================
2060 //
2061 // GLOBAL FUNCTIONS
2062 //
2063 //=================================================================================================
2064 
2065 //*************************************************************************************************
2089 template< typename MT1 // Type of the left-hand side dense matrix
2090  , typename MT2 // Type of the right-hand side dense matrix
2091  , bool SF // Symmetry flag
2092  , bool HF // Hermitian flag
2093  , bool LF // Lower flag
2094  , bool UF > // Upper flag
2095 inline decltype(auto) declsym( const TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2096 {
2098 
2099  if( !isSquare( dm ) ) {
2100  BLAZE_THROW_INVALID_ARGUMENT( "Invalid symmetric matrix specification" );
2101  }
2102 
2104  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2105 }
2107 //*************************************************************************************************
2108 
2109 
2110 //*************************************************************************************************
2134 template< typename MT1 // Type of the left-hand side dense matrix
2135  , typename MT2 // Type of the right-hand side dense matrix
2136  , bool SF // Symmetry flag
2137  , bool HF // Hermitian flag
2138  , bool LF // Lower flag
2139  , bool UF > // Upper flag
2140 inline decltype(auto) declherm( const TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2141 {
2143 
2144  if( !isSquare( dm ) ) {
2145  BLAZE_THROW_INVALID_ARGUMENT( "Invalid Hermitian matrix specification" );
2146  }
2147 
2149  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2150 }
2152 //*************************************************************************************************
2153 
2154 
2155 //*************************************************************************************************
2179 template< typename MT1 // Type of the left-hand side dense matrix
2180  , typename MT2 // Type of the right-hand side dense matrix
2181  , bool SF // Symmetry flag
2182  , bool HF // Hermitian flag
2183  , bool LF // Lower flag
2184  , bool UF > // Upper flag
2185 inline decltype(auto) decllow( const TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2186 {
2188 
2189  if( !isSquare( dm ) ) {
2190  BLAZE_THROW_INVALID_ARGUMENT( "Invalid lower matrix specification" );
2191  }
2192 
2194  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2195 }
2197 //*************************************************************************************************
2198 
2199 
2200 //*************************************************************************************************
2224 template< typename MT1 // Type of the left-hand side dense matrix
2225  , typename MT2 // Type of the right-hand side dense matrix
2226  , bool SF // Symmetry flag
2227  , bool HF // Hermitian flag
2228  , bool LF // Lower flag
2229  , bool UF > // Upper flag
2230 inline decltype(auto) declupp( const TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2231 {
2233 
2234  if( !isSquare( dm ) ) {
2235  BLAZE_THROW_INVALID_ARGUMENT( "Invalid upper matrix specification" );
2236  }
2237 
2239  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2240 }
2242 //*************************************************************************************************
2243 
2244 
2245 //*************************************************************************************************
2269 template< typename MT1 // Type of the left-hand side dense matrix
2270  , typename MT2 // Type of the right-hand side dense matrix
2271  , bool SF // Symmetry flag
2272  , bool HF // Hermitian flag
2273  , bool LF // Lower flag
2274  , bool UF > // Upper flag
2275 inline decltype(auto) decldiag( const TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF>& dm )
2276 {
2278 
2279  if( !isSquare( dm ) ) {
2280  BLAZE_THROW_INVALID_ARGUMENT( "Invalid diagonal matrix specification" );
2281  }
2282 
2284  return ReturnType( dm.leftOperand(), dm.rightOperand() );
2285 }
2287 //*************************************************************************************************
2288 
2289 
2290 
2291 
2292 //=================================================================================================
2293 //
2294 // ROWS SPECIALIZATIONS
2295 //
2296 //=================================================================================================
2297 
2298 //*************************************************************************************************
2300 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2301 struct Rows< TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2302  : public Rows<MT1>
2303 {};
2305 //*************************************************************************************************
2306 
2307 
2308 
2309 
2310 //=================================================================================================
2311 //
2312 // COLUMNS SPECIALIZATIONS
2313 //
2314 //=================================================================================================
2315 
2316 //*************************************************************************************************
2318 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2319 struct Columns< TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2320  : public Columns<MT2>
2321 {};
2323 //*************************************************************************************************
2324 
2325 
2326 
2327 
2328 //=================================================================================================
2329 //
2330 // ISALIGNED SPECIALIZATIONS
2331 //
2332 //=================================================================================================
2333 
2334 //*************************************************************************************************
2336 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2337 struct IsAligned< TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2338  : public BoolConstant< IsAligned<MT2>::value >
2339 {};
2341 //*************************************************************************************************
2342 
2343 
2344 
2345 
2346 //=================================================================================================
2347 //
2348 // ISSYMMETRIC SPECIALIZATIONS
2349 //
2350 //=================================================================================================
2351 
2352 //*************************************************************************************************
2354 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2355 struct IsSymmetric< TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2356  : public BoolConstant< Or< Bool<SF>
2357  , And< Bool<HF>
2358  , IsBuiltin< ElementType_< TSMatTDMatMultExpr<MT1,MT2,false,true,false,false> > > >
2359  , And< Bool<LF>, Bool<UF> > >::value >
2360 {};
2362 //*************************************************************************************************
2363 
2364 
2365 
2366 
2367 //=================================================================================================
2368 //
2369 // ISHERMITIAN SPECIALIZATIONS
2370 //
2371 //=================================================================================================
2372 
2373 //*************************************************************************************************
2375 template< typename MT1, typename MT2, bool SF, bool LF, bool UF >
2376 struct IsHermitian< TSMatTDMatMultExpr<MT1,MT2,SF,true,LF,UF> >
2377  : public TrueType
2378 {};
2380 //*************************************************************************************************
2381 
2382 
2383 
2384 
2385 //=================================================================================================
2386 //
2387 // ISLOWER SPECIALIZATIONS
2388 //
2389 //=================================================================================================
2390 
2391 //*************************************************************************************************
2393 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2394 struct IsLower< TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2395  : public BoolConstant< Or< Bool<LF>
2396  , And< IsLower<MT1>, IsLower<MT2> >
2397  , And< Or< Bool<SF>, Bool<HF> >
2398  , IsUpper<MT1>, IsUpper<MT2> > >::value >
2399 {};
2401 //*************************************************************************************************
2402 
2403 
2404 
2405 
2406 //=================================================================================================
2407 //
2408 // ISUNILOWER SPECIALIZATIONS
2409 //
2410 //=================================================================================================
2411 
2412 //*************************************************************************************************
2414 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2415 struct IsUniLower< TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2416  : public BoolConstant< Or< And< IsUniLower<MT1>, IsUniLower<MT2> >
2417  , And< Or< Bool<SF>, Bool<HF> >
2418  , IsUniUpper<MT1>, IsUniUpper<MT2> > >::value >
2419 {};
2421 //*************************************************************************************************
2422 
2423 
2424 
2425 
2426 //=================================================================================================
2427 //
2428 // ISSTRICTLYLOWER SPECIALIZATIONS
2429 //
2430 //=================================================================================================
2431 
2432 //*************************************************************************************************
2434 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2435 struct IsStrictlyLower< TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2436  : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
2437  , And< IsStrictlyLower<MT2>, IsLower<MT1> >
2438  , And< Or< Bool<SF>, Bool<HF> >
2439  , Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
2440  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > > > >::value >
2441 {};
2443 //*************************************************************************************************
2444 
2445 
2446 
2447 
2448 //=================================================================================================
2449 //
2450 // ISUPPER SPECIALIZATIONS
2451 //
2452 //=================================================================================================
2453 
2454 //*************************************************************************************************
2456 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2457 struct IsUpper< TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2458  : public BoolConstant< Or< Bool<UF>
2459  , And< IsUpper<MT1>, IsUpper<MT2> >
2460  , And< Or< Bool<SF>, Bool<HF> >
2461  , IsLower<MT1>, IsLower<MT2> > >::value >
2462 {};
2464 //*************************************************************************************************
2465 
2466 
2467 
2468 
2469 //=================================================================================================
2470 //
2471 // ISUNIUPPER SPECIALIZATIONS
2472 //
2473 //=================================================================================================
2474 
2475 //*************************************************************************************************
2477 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2478 struct IsUniUpper< TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2479  : public BoolConstant< Or< And< IsUniUpper<MT1>, IsUniUpper<MT2> >
2480  , And< Or< Bool<SF>, Bool<HF> >
2481  , IsUniLower<MT1>, IsUniLower<MT2> > >::value >
2482 {};
2484 //*************************************************************************************************
2485 
2486 
2487 
2488 
2489 //=================================================================================================
2490 //
2491 // ISSTRICTLYUPPER SPECIALIZATIONS
2492 //
2493 //=================================================================================================
2494 
2495 //*************************************************************************************************
2497 template< typename MT1, typename MT2, bool SF, bool HF, bool LF, bool UF >
2498 struct IsStrictlyUpper< TSMatTDMatMultExpr<MT1,MT2,SF,HF,LF,UF> >
2499  : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
2500  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> >
2501  , And< Or< Bool<SF>, Bool<HF> >
2502  , Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
2503  , And< IsStrictlyLower<MT2>, IsLower<MT1> > > > >::value >
2504 {};
2506 //*************************************************************************************************
2507 
2508 } // namespace blaze
2509 
2510 #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
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: TSMatTDMatMultExpr.h:427
decltype(auto) decldiag(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as diagonal.
Definition: DMatDeclDiagExpr.h:996
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
ResultType_< MT2 > RT2
Result type of the right-hand side dense matrix expression.
Definition: TSMatTDMatMultExpr.h:132
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_< RT2 > ET2
Element type of the right-hand side sparse matrix expression.
Definition: TSMatTDMatMultExpr.h:134
Expression object for transpose sparse matrix-transpose dense matrix multiplications.The TSMatTDMatMultExpr class represents the compile time expression for multiplications between a column-major sparse matrix and a column-major dense matrix.
Definition: Forward.h:168
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
ElementType_< RT1 > ET1
Element type of the left-hand side dense matrix expression.
Definition: TSMatTDMatMultExpr.h:133
EnableIf_< IsDenseMatrix< MT1 > > smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:164
Header file for the serial shim.
Header file for the IsDiagonal type trait.
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
bool isAligned() const noexcept
Returns whether the operands of the expression are properly aligned in memory.
Definition: TSMatTDMatMultExpr.h:417
Header file for the DeclUpp functor.
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: TSMatTDMatMultExpr.h:407
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
IfTrue_< evaluateRight, const RT2, CT2 > RT
Type for the assignment of the right-hand side dense matrix operand.
Definition: TSMatTDMatMultExpr.h:256
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
MultTrait_< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: TSMatTDMatMultExpr.h:239
decltype(auto) declupp(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as upper.
Definition: DMatDeclUppExpr.h:1027
typename MultTrait< T1, T2 >::Type MultTrait_
Auxiliary alias declaration for the MultTrait class template.The MultTrait_ alias declaration provide...
Definition: MultTrait.h:250
Column< MT > column(Matrix< MT, SO > &matrix, size_t index)
Creating a view on a specific column of the given matrix.
Definition: Column.h:124
Header file for the Computation base class.
Header file for the MatMatMultExpr base class.
Compile time check for upper triangular matrices.This type trait tests whether or not the given templ...
Definition: IsUpper.h:88
Constraints on the storage order of matrix types.
Header file for the RequiresEvaluation type trait.
System settings for performance optimizations.
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
RightOperand rhs_
Right-hand side dense matrix of the multiplication expression.
Definition: TSMatTDMatMultExpr.h:435
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:78
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes...
Definition: Forward.h:129
typename IfTrue< Condition, T1, T2 >::Type IfTrue_
Auxiliary alias declaration for the IfTrue class template.The IfTrue_ alias declaration provides a co...
Definition: If.h:109
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
OppositeType_< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: TSMatTDMatMultExpr.h:240
Compile time check for the alignment of data types.This type trait tests whether the given data type ...
Definition: IsAligned.h:87
const ResultType CompositeType
Data type for composite expression templates.
Definition: TSMatTDMatMultExpr.h:244
Constraint on the data type.
Constraint on the data type.
Flag for symmetric matrices.
Definition: TSMatTDMatMultExpr.h:152
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
Flag for Hermitian matrices.
Definition: TSMatTDMatMultExpr.h:153
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: TSMatTDMatMultExpr.h:395
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
ResultType_< MT1 > RT1
Result type of the left-hand side sparse matrix expression.
Definition: TSMatTDMatMultExpr.h:131
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.
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: TSMatTDMatMultExpr.h:289
#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.
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: TSMatTDMatMultExpr.h:434
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
TSMatTDMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the TSMatTDMatMultExpr class.
Definition: TSMatTDMatMultExpr.h:274
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
Generic wrapper for the null function.
Definition: Noop.h:58
Header file for the IsTriangular type trait.
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: TSMatTDMatMultExpr.h:353
CompositeType_< MT1 > CT1
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatTDMatMultExpr.h:135
LeftOperand leftOperand() const noexcept
Returns the left-hand side transpose sparse matrix operand.
Definition: TSMatTDMatMultExpr.h:373
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.
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TSMatTDMatMultExpr.h:243
Header file for the EnableIf class template.
Header file for the IsStrictlyLower type trait.
#define BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR(T1, T2)
Constraint on the data type.In case the given data types T1 and T2 do not form a valid matrix/matrix ...
Definition: MatMatMultExpr.h:108
Compile time check for lower unitriangular matrices.This type trait tests whether or not the given te...
Definition: IsUniLower.h:86
Header file for the conjugate shim.
Compile time check for resizable data types.This type trait tests whether the given data type is a re...
Definition: IsResizable.h:75
Flag for lower matrices.
Definition: TSMatTDMatMultExpr.h:154
#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
ElementType_< ResultType > ElementType
Resulting element type.
Definition: TSMatTDMatMultExpr.h:242
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.
TransposeType_< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: TSMatTDMatMultExpr.h:241
#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
typename EnableIf< Condition, T >::Type EnableIf_
Auxiliary alias declaration for the EnableIf class template.The EnableIf_ alias declaration provides ...
Definition: EnableIf.h:224
typename T::OppositeType OppositeType_
Alias declaration for nested OppositeType type definitions.The OppositeType_ alias declaration provid...
Definition: Aliases.h:263
#define BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER(T1, T2)
Constraint on the data type.In case either of the two given data types T1 or T2 is not a matrix type ...
Definition: StorageOrder.h:84
Generic wrapper for the declupp() function.
Definition: DeclUpp.h:58
Compile time check for strictly lower triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyLower.h:86
const Type & ReturnType
Return type for expression template evaluations.
Definition: CompressedMatrix.h:3082
typename T::ConstIterator ConstIterator_
Alias declaration for nested ConstIterator type definitions.The ConstIterator_ alias declaration prov...
Definition: Aliases.h:103
decltype(auto) trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:790
decltype(auto) declherm(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as Hermitian.
Definition: DMatDeclHermExpr.h:1029
Flag for upper matrices.
Definition: TSMatTDMatMultExpr.h:155
If_< IsExpression< MT1 >, const MT1, const MT1 &> LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatTDMatMultExpr.h:247
Header file for the IsRowMajorMatrix type trait.
Header file for the IsComputation type trait class.
RightOperand rightOperand() const noexcept
Returns the right-hand side transpose dense matrix operand.
Definition: TSMatTDMatMultExpr.h:383
Header file for the IsBuiltin type trait.
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: TSMatTDMatMultExpr.h:363
If_< IsExpression< MT2 >, const MT2, const MT2 &> RightOperand
Composite type of the right-hand side dense matrix expression.
Definition: TSMatTDMatMultExpr.h:250
CompositeType_< MT2 > CT2
Composite type of the right-hand side dense matrix expression.
Definition: TSMatTDMatMultExpr.h:136
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
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.
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.
IfTrue_< evaluateLeft, const RT1, CT1 > LT
Type for the assignment of the left-hand side sparse matrix operand.
Definition: TSMatTDMatMultExpr.h:253
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.
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: TSMatTDMatMultExpr.h:337