DMatTSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_DMATTSMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_DMATTSMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <blaze/math/Aliases.h>
50 #include <blaze/math/Exception.h>
55 #include <blaze/math/Functions.h>
56 #include <blaze/math/shims/Reset.h>
96 #include <blaze/util/Assert.h>
98 #include <blaze/util/DisableIf.h>
99 #include <blaze/util/EnableIf.h>
101 #include <blaze/util/InvalidType.h>
103 #include <blaze/util/mpl/And.h>
104 #include <blaze/util/mpl/If.h>
105 #include <blaze/util/mpl/Or.h>
106 #include <blaze/util/Types.h>
108 
109 
110 namespace blaze {
111 
112 //=================================================================================================
113 //
114 // CLASS DMATTSMATMULTEXPR
115 //
116 //=================================================================================================
117 
118 //*************************************************************************************************
125 template< typename MT1 // Type of the left-hand side dense matrix
126  , typename MT2 > // Type of the right-hand side sparse matrix
127 class DMatTSMatMultExpr : public DenseMatrix< DMatTSMatMultExpr<MT1,MT2>, false >
128  , private MatMatMultExpr
129  , private Computation
130 {
131  private:
132  //**Type definitions****************************************************************************
139  //**********************************************************************************************
140 
141  //**********************************************************************************************
143  enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
144  //**********************************************************************************************
145 
146  //**********************************************************************************************
148  enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
149  //**********************************************************************************************
150 
151  //**********************************************************************************************
153 
158  template< typename T1, typename T2, typename T3 >
159  struct CanExploitSymmetry {
160  enum : bool { value = IsSymmetric<T2>::value };
161  };
163  //**********************************************************************************************
164 
165  //**********************************************************************************************
167 
171  template< typename T1, typename T2, typename T3 >
172  struct IsEvaluationRequired {
173  enum : bool { value = ( evaluateLeft || evaluateRight ) &&
174  !CanExploitSymmetry<T1,T2,T3>::value };
175  };
177  //**********************************************************************************************
178 
179  //**********************************************************************************************
181 
184  template< typename T1, typename T2, typename T3 >
185  struct UseOptimizedKernel {
186  enum : bool { value = useOptimizedKernels &&
187  !IsDiagonal<T2>::value &&
188  !IsResizable< ElementType_<T1> >::value &&
189  !IsResizable<ET2>::value };
190  };
192  //**********************************************************************************************
193 
194  public:
195  //**Type definitions****************************************************************************
201  typedef const ElementType ReturnType;
202  typedef const ResultType CompositeType;
203 
205  typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
206 
208  typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
209 
212 
215  //**********************************************************************************************
216 
217  //**Compilation flags***************************************************************************
219  enum : bool { simdEnabled = false };
220 
222  enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
223  !evaluateRight && MT2::smpAssignable };
224  //**********************************************************************************************
225 
226  //**Constructor*********************************************************************************
232  explicit inline DMatTSMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
233  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
234  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
235  {
236  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
237  }
238  //**********************************************************************************************
239 
240  //**Access operator*****************************************************************************
247  inline ReturnType operator()( size_t i, size_t j ) const {
248  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
249  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
250 
251  if( IsDiagonal<MT1>::value ) {
252  return lhs_(i,i) * rhs_(i,j);
253  }
254  else if( IsDiagonal<MT2>::value ) {
255  return lhs_(i,j) * rhs_(j,j);
256  }
258  const size_t begin( ( IsUpper<MT1>::value )
259  ?( ( IsLower<MT2>::value )
260  ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
261  , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
262  :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
263  :( ( IsLower<MT2>::value )
264  ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
265  :( 0UL ) ) );
266  const size_t end( ( IsLower<MT1>::value )
267  ?( ( IsUpper<MT2>::value )
268  ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
269  , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
270  :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
271  :( ( IsUpper<MT2>::value )
272  ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
273  :( lhs_.columns() ) ) );
274 
275  if( begin >= end ) return ElementType();
276 
277  const size_t n( end - begin );
278 
279  return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
280  }
281  else {
282  return row( lhs_, i ) * column( rhs_, j );
283  }
284  }
285  //**********************************************************************************************
286 
287  //**At function*********************************************************************************
295  inline ReturnType at( size_t i, size_t j ) const {
296  if( i >= lhs_.rows() ) {
297  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
298  }
299  if( j >= rhs_.columns() ) {
300  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
301  }
302  return (*this)(i,j);
303  }
304  //**********************************************************************************************
305 
306  //**Rows function*******************************************************************************
311  inline size_t rows() const noexcept {
312  return lhs_.rows();
313  }
314  //**********************************************************************************************
315 
316  //**Columns function****************************************************************************
321  inline size_t columns() const noexcept {
322  return rhs_.columns();
323  }
324  //**********************************************************************************************
325 
326  //**Left operand access*************************************************************************
331  inline LeftOperand leftOperand() const noexcept {
332  return lhs_;
333  }
334  //**********************************************************************************************
335 
336  //**Right operand access************************************************************************
341  inline RightOperand rightOperand() const noexcept {
342  return rhs_;
343  }
344  //**********************************************************************************************
345 
346  //**********************************************************************************************
352  template< typename T >
353  inline bool canAlias( const T* alias ) const noexcept {
354  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
355  }
356  //**********************************************************************************************
357 
358  //**********************************************************************************************
364  template< typename T >
365  inline bool isAliased( const T* alias ) const noexcept {
366  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
367  }
368  //**********************************************************************************************
369 
370  //**********************************************************************************************
375  inline bool isAligned() const noexcept {
376  return lhs_.isAligned();
377  }
378  //**********************************************************************************************
379 
380  //**********************************************************************************************
385  inline bool canSMPAssign() const noexcept {
386  return ( rows() * columns() >= SMP_DMATTSMATMULT_THRESHOLD );
387  }
388  //**********************************************************************************************
389 
390  private:
391  //**Member variables****************************************************************************
392  LeftOperand lhs_;
393  RightOperand rhs_;
394  //**********************************************************************************************
395 
396  //**Assignment to dense matrices****************************************************************
409  template< typename MT // Type of the target dense matrix
410  , bool SO > // Storage order of the target dense matrix
412  assign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
413  {
415 
416  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
417  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
418 
419  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
420  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
421 
422  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
423  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
424  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
425 
426  DMatTSMatMultExpr::selectAssignKernel( ~lhs, A, B );
427  }
429  //**********************************************************************************************
430 
431  //**Default assignment to dense matrices********************************************************
445  template< typename MT3 // Type of the left-hand side target matrix
446  , typename MT4 // Type of the left-hand side matrix operand
447  , typename MT5 > // Type of the right-hand side matrix operand
449  selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
450  {
452 
453  const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 256UL );
454 
455  for( size_t jj=0UL; jj<B.columns(); jj+=block )
456  {
457  const size_t jend( min( jj+block, B.columns() ) );
458 
459  size_t i( 0UL );
460 
461  for( ; (i+4UL) <= A.rows(); i+=4UL ) {
462  for( size_t j=jj; j<jend; ++j )
463  {
464  ConstIterator element( ( IsUpper<MT4>::value )
465  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
466  :( B.begin(j) ) );
467  const ConstIterator end( ( IsLower<MT4>::value )
468  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
469  :( B.end(j) ) );
470 
471  if( element == end ) {
472  reset( C(i ,j) );
473  reset( C(i+1UL,j) );
474  reset( C(i+2UL,j) );
475  reset( C(i+3UL,j) );
476  continue;
477  }
478 
479  C(i ,j) = A(i ,element->index()) * element->value();
480  C(i+1UL,j) = A(i+1UL,element->index()) * element->value();
481  C(i+2UL,j) = A(i+2UL,element->index()) * element->value();
482  C(i+3UL,j) = A(i+3UL,element->index()) * element->value();
483  ++element;
484  for( ; element!=end; ++element ) {
485  C(i ,j) += A(i ,element->index()) * element->value();
486  C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
487  C(i+2UL,j) += A(i+2UL,element->index()) * element->value();
488  C(i+3UL,j) += A(i+3UL,element->index()) * element->value();
489  }
490  }
491  }
492 
493  for( ; (i+2UL) <= A.rows(); i+=2UL ) {
494  for( size_t j=jj; j<jend; ++j )
495  {
496  ConstIterator element( ( IsUpper<MT4>::value )
497  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
498  :( B.begin(j) ) );
499  const ConstIterator end( ( IsLower<MT4>::value )
500  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
501  :( B.end(j) ) );
502 
503  if( element == end ) {
504  reset( C(i ,j) );
505  reset( C(i+1UL,j) );
506  continue;
507  }
508 
509  C(i ,j) = A(i ,element->index()) * element->value();
510  C(i+1UL,j) = A(i+1UL,element->index()) * element->value();
511  ++element;
512  for( ; element!=end; ++element ) {
513  C(i ,j) += A(i ,element->index()) * element->value();
514  C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
515  }
516  }
517  }
518 
519  for( ; i<A.rows(); ++i ) {
520  for( size_t j=jj; j<jend; ++j )
521  {
522  ConstIterator element( ( IsUpper<MT4>::value )
523  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
524  :( B.begin(j) ) );
525  const ConstIterator end( ( IsLower<MT4>::value )
526  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
527  :( B.end(j) ) );
528 
529  if( element == end ) {
530  reset( C(i,j) );
531  continue;
532  }
533 
534  C(i,j) = A(i,element->index()) * element->value();
535  ++element;
536  for( ; element!=end; ++element )
537  C(i,j) += A(i,element->index()) * element->value();
538  }
539  }
540  }
541  }
543  //**********************************************************************************************
544 
545  //**Optimized assignment to dense matrices******************************************************
559  template< typename MT3 // Type of the left-hand side target matrix
560  , typename MT4 // Type of the left-hand side matrix operand
561  , typename MT5 > // Type of the right-hand side matrix operand
562  static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
563  selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
564  {
565  typedef ConstIterator_<MT5> ConstIterator;
566 
567  const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 256UL );
568 
569  reset( C );
570 
571  for( size_t jj=0UL; jj<B.columns(); jj+=block )
572  {
573  const size_t jend( min( jj+block, B.columns() ) );
574 
575  size_t i( 0UL );
576 
577  for( ; (i+4UL) <= A.rows(); i+=4UL ) {
578  for( size_t j=jj; j<jend; ++j )
579  {
580  ConstIterator element( ( IsUpper<MT4>::value )
581  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
582  :( B.begin(j) ) );
583  const ConstIterator end( ( IsLower<MT4>::value )
584  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
585  :( B.end(j) ) );
586 
587  const size_t nonzeros( end - element );
588  const size_t kpos( nonzeros & size_t(-4) );
589  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
590 
591  for( size_t k=0UL; k<kpos; k+=4UL )
592  {
593  const size_t j1( element->index() );
594  const ET2 v1( element->value() );
595  ++element;
596  const size_t j2( element->index() );
597  const ET2 v2( element->value() );
598  ++element;
599  const size_t j3( element->index() );
600  const ET2 v3( element->value() );
601  ++element;
602  const size_t j4( element->index() );
603  const ET2 v4( element->value() );
604  ++element;
605 
606  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
607 
608  C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
609  C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
610  C(i+2UL,j) += A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
611  C(i+3UL,j) += A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
612  }
613 
614  for( ; element!=end; ++element )
615  {
616  const size_t j1( element->index() );
617  const ET2 v1( element->value() );
618 
619  C(i ,j) += A(i ,j1) * v1;
620  C(i+1UL,j) += A(i+1UL,j1) * v1;
621  C(i+2UL,j) += A(i+2UL,j1) * v1;
622  C(i+3UL,j) += A(i+3UL,j1) * v1;
623  }
624  }
625  }
626 
627  for( ; (i+2UL) <= A.rows(); i+=2UL ) {
628  for( size_t j=jj; j<jend; ++j )
629  {
630  ConstIterator element( ( IsUpper<MT4>::value )
631  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
632  :( B.begin(j) ) );
633  const ConstIterator end( ( IsLower<MT4>::value )
634  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
635  :( B.end(j) ) );
636 
637  const size_t nonzeros( end - element );
638  const size_t kpos( nonzeros & size_t(-4) );
639  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
640 
641  for( size_t k=0UL; k<kpos; k+=4UL )
642  {
643  const size_t j1( element->index() );
644  const ET2 v1( element->value() );
645  ++element;
646  const size_t j2( element->index() );
647  const ET2 v2( element->value() );
648  ++element;
649  const size_t j3( element->index() );
650  const ET2 v3( element->value() );
651  ++element;
652  const size_t j4( element->index() );
653  const ET2 v4( element->value() );
654  ++element;
655 
656  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
657 
658  C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
659  C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
660  }
661 
662  for( ; element!=end; ++element )
663  {
664  const size_t j1( element->index() );
665  const ET2 v1( element->value() );
666 
667  C(i ,j) += A(i ,j1) * v1;
668  C(i+1UL,j) += A(i+1UL,j1) * v1;
669  }
670  }
671  }
672 
673  for( ; i<A.rows(); ++i ) {
674  for( size_t j=jj; j<jend; ++j )
675  {
676  ConstIterator element( ( IsUpper<MT4>::value )
677  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
678  :( B.begin(j) ) );
679  const ConstIterator end( ( IsLower<MT4>::value )
680  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
681  :( B.end(j) ) );
682 
683  const size_t nonzeros( end - element );
684  const size_t kpos( nonzeros & size_t(-4) );
685  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
686 
687  for( size_t k=0UL; k<kpos; k+=4UL )
688  {
689  const size_t j1( element->index() );
690  const ET2 v1( element->value() );
691  ++element;
692  const size_t j2( element->index() );
693  const ET2 v2( element->value() );
694  ++element;
695  const size_t j3( element->index() );
696  const ET2 v3( element->value() );
697  ++element;
698  const size_t j4( element->index() );
699  const ET2 v4( element->value() );
700  ++element;
701 
702  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
703 
704  C(i,j) += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
705  }
706 
707  for( ; element!=end; ++element )
708  {
709  const size_t j1( element->index() );
710  const ET2 v1( element->value() );
711 
712  C(i,j) += A(i,j1) * v1;
713  }
714  }
715  }
716  }
717  }
719  //**********************************************************************************************
720 
721  //**Assignment to sparse matrices***************************************************************
734  template< typename MT // Type of the target sparse matrix
735  , bool SO > // Storage order of the target sparse matrix
736  friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
737  assign( SparseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
738  {
740 
741  typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
742 
748  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
749 
750  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
751  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
752 
753  const TmpType tmp( serial( rhs ) );
754  assign( ~lhs, tmp );
755  }
757  //**********************************************************************************************
758 
759  //**Restructuring assignment********************************************************************
774  template< typename MT // Type of the target matrix
775  , bool SO > // Storage order of the target matrix
776  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
777  assign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
778  {
780 
781  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
782  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
783 
784  assign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
785  }
787  //**********************************************************************************************
788 
789  //**Addition assignment to dense matrices*******************************************************
802  template< typename MT // Type of the target dense matrix
803  , bool SO > // Storage order of the target dense matrix
804  friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
805  addAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
806  {
808 
809  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
810  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
811 
812  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
813  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
814 
815  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
816  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
817  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
818 
819  DMatTSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
820  }
822  //**********************************************************************************************
823 
824  //**Default addition assignment to dense matrices***********************************************
838  template< typename MT3 // Type of the left-hand side target matrix
839  , typename MT4 // Type of the left-hand side matrix operand
840  , typename MT5 > // Type of the right-hand side matrix operand
841  static inline DisableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
842  selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
843  {
844  typedef ConstIterator_<MT5> ConstIterator;
845 
846  const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 256UL );
847 
848  for( size_t jj=0UL; jj<B.columns(); jj+=block )
849  {
850  const size_t jend( min( jj+block, B.columns() ) );
851 
852  size_t i( 0UL );
853 
854  for( ; (i+4UL) <= A.rows(); i+=4UL ) {
855  for( size_t j=jj; j<jend; ++j )
856  {
857  ConstIterator element( ( IsUpper<MT4>::value )
858  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
859  :( B.begin(j) ) );
860  const ConstIterator end( ( IsLower<MT4>::value )
861  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
862  :( B.end(j) ) );
863 
864  for( ; element!=end; ++element ) {
865  C(i ,j) += A(i ,element->index()) * element->value();
866  C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
867  C(i+2UL,j) += A(i+2UL,element->index()) * element->value();
868  C(i+3UL,j) += A(i+3UL,element->index()) * element->value();
869  }
870  }
871  }
872 
873  for( ; (i+2UL) <= A.rows(); i+=2UL ) {
874  for( size_t j=jj; j<jend; ++j )
875  {
876  ConstIterator element( ( IsUpper<MT4>::value )
877  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
878  :( B.begin(j) ) );
879  const ConstIterator end( ( IsLower<MT4>::value )
880  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
881  :( B.end(j) ) );
882 
883  for( ; element!=end; ++element ) {
884  C(i ,j) += A(i ,element->index()) * element->value();
885  C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
886  }
887  }
888  }
889 
890  for( ; i<A.rows(); ++i ) {
891  for( size_t j=jj; j<jend; ++j )
892  {
893  ConstIterator element( ( IsUpper<MT4>::value )
894  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
895  :( B.begin(j) ) );
896  const ConstIterator end( ( IsLower<MT4>::value )
897  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
898  :( B.end(j) ) );
899 
900  for( ; element!=end; ++element )
901  C(i,j) += A(i,element->index()) * element->value();
902  }
903  }
904  }
905  }
907  //**********************************************************************************************
908 
909  //**Optimized addition assignment to dense matrices*********************************************
923  template< typename MT3 // Type of the left-hand side target matrix
924  , typename MT4 // Type of the left-hand side matrix operand
925  , typename MT5 > // Type of the right-hand side matrix operand
926  static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
927  selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
928  {
929  typedef ConstIterator_<MT5> ConstIterator;
930 
931  const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 256UL );
932 
933  for( size_t jj=0UL; jj<B.columns(); jj+=block )
934  {
935  const size_t jend( min( jj+block, B.columns() ) );
936 
937  size_t i( 0UL );
938 
939  for( ; (i+4UL) <= A.rows(); i+=4UL ) {
940  for( size_t j=jj; j<jend; ++j )
941  {
942  ConstIterator element( ( IsUpper<MT4>::value )
943  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
944  :( B.begin(j) ) );
945  const ConstIterator end( ( IsLower<MT4>::value )
946  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
947  :( B.end(j) ) );
948 
949  const size_t nonzeros( end - element );
950  const size_t kpos( nonzeros & size_t(-4) );
951  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
952 
953  for( size_t k=0UL; k<kpos; k+=4UL )
954  {
955  const size_t j1( element->index() );
956  const ET2 v1( element->value() );
957  ++element;
958  const size_t j2( element->index() );
959  const ET2 v2( element->value() );
960  ++element;
961  const size_t j3( element->index() );
962  const ET2 v3( element->value() );
963  ++element;
964  const size_t j4( element->index() );
965  const ET2 v4( element->value() );
966  ++element;
967 
968  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
969 
970  C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
971  C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
972  C(i+2UL,j) += A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
973  C(i+3UL,j) += A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
974  }
975 
976  for( ; element!=end; ++element )
977  {
978  const size_t j1( element->index() );
979  const ET2 v1( element->value() );
980 
981  C(i ,j) += A(i ,j1) * v1;
982  C(i+1UL,j) += A(i+1UL,j1) * v1;
983  C(i+2UL,j) += A(i+2UL,j1) * v1;
984  C(i+3UL,j) += A(i+3UL,j1) * v1;
985  }
986  }
987  }
988 
989  for( ; (i+2UL) <= A.rows(); i+=2UL ) {
990  for( size_t j=jj; j<jend; ++j )
991  {
992  ConstIterator element( ( IsUpper<MT4>::value )
993  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
994  :( B.begin(j) ) );
995  const ConstIterator end( ( IsLower<MT4>::value )
996  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
997  :( B.end(j) ) );
998 
999  const size_t nonzeros( end - element );
1000  const size_t kpos( nonzeros & size_t(-4) );
1001  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1002 
1003  for( size_t k=0UL; k<kpos; k+=4UL )
1004  {
1005  const size_t j1( element->index() );
1006  const ET2 v1( element->value() );
1007  ++element;
1008  const size_t j2( element->index() );
1009  const ET2 v2( element->value() );
1010  ++element;
1011  const size_t j3( element->index() );
1012  const ET2 v3( element->value() );
1013  ++element;
1014  const size_t j4( element->index() );
1015  const ET2 v4( element->value() );
1016  ++element;
1017 
1018  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1019 
1020  C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
1021  C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
1022  }
1023 
1024  for( ; element!=end; ++element )
1025  {
1026  const size_t j1( element->index() );
1027  const ET2 v1( element->value() );
1028 
1029  C(i ,j) += A(i ,j1) * v1;
1030  C(i+1UL,j) += A(i+1UL,j1) * v1;
1031  }
1032  }
1033  }
1034 
1035  for( ; i<A.rows(); ++i ) {
1036  for( size_t j=jj; j<jend; ++j )
1037  {
1038  ConstIterator element( ( IsUpper<MT4>::value )
1039  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1040  :( B.begin(j) ) );
1041  const ConstIterator end( ( IsLower<MT4>::value )
1042  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
1043  :( B.end(j) ) );
1044 
1045  const size_t nonzeros( end - element );
1046  const size_t kpos( nonzeros & size_t(-4) );
1047  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1048 
1049  for( size_t k=0UL; k<kpos; k+=4UL )
1050  {
1051  const size_t j1( element->index() );
1052  const ET2 v1( element->value() );
1053  ++element;
1054  const size_t j2( element->index() );
1055  const ET2 v2( element->value() );
1056  ++element;
1057  const size_t j3( element->index() );
1058  const ET2 v3( element->value() );
1059  ++element;
1060  const size_t j4( element->index() );
1061  const ET2 v4( element->value() );
1062  ++element;
1063 
1064  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1065 
1066  C(i,j) += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
1067  }
1068 
1069  for( ; element!=end; ++element )
1070  {
1071  const size_t j1( element->index() );
1072  const ET2 v1( element->value() );
1073 
1074  C(i,j) += A(i,j1) * v1;
1075  }
1076  }
1077  }
1078  }
1079  }
1081  //**********************************************************************************************
1082 
1083  //**Restructuring addition assignment***********************************************************
1098  template< typename MT // Type of the target matrix
1099  , bool SO > // Storage order of the target matrix
1100  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1101  addAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1102  {
1104 
1106 
1107  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1108  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1109 
1110  addAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1111  }
1113  //**********************************************************************************************
1114 
1115  //**Addition assignment to sparse matrices******************************************************
1116  // No special implementation for the addition assignment to sparse matrices.
1117  //**********************************************************************************************
1118 
1119  //**Subtraction assignment to dense matrices****************************************************
1132  template< typename MT // Type of the target dense matrix
1133  , bool SO > // Storage order of the target dense matrix
1134  friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1135  subAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1136  {
1138 
1139  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1140  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1141 
1142  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1143  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1144 
1145  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1146  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
1147  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
1148 
1149  DMatTSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1150  }
1152  //**********************************************************************************************
1153 
1154  //**Default subtraction assignment to dense matrices********************************************
1168  template< typename MT3 // Type of the left-hand side target matrix
1169  , typename MT4 // Type of the left-hand side matrix operand
1170  , typename MT5 > // Type of the right-hand side matrix operand
1171  static inline DisableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
1172  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1173  {
1174  typedef ConstIterator_<MT5> ConstIterator;
1175 
1176  const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 256UL );
1177 
1178  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1179  {
1180  const size_t jend( min( jj+block, B.columns() ) );
1181 
1182  size_t i( 0UL );
1183 
1184  for( ; (i+4UL) <= A.rows(); i+=4UL ) {
1185  for( size_t j=jj; j<jend; ++j )
1186  {
1187  ConstIterator element( ( IsUpper<MT4>::value )
1188  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1189  :( B.begin(j) ) );
1190  const ConstIterator end( ( IsLower<MT4>::value )
1191  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
1192  :( B.end(j) ) );
1193 
1194  for( ; element!=end; ++element ) {
1195  C(i ,j) -= A(i ,element->index()) * element->value();
1196  C(i+1UL,j) -= A(i+1UL,element->index()) * element->value();
1197  C(i+2UL,j) -= A(i+2UL,element->index()) * element->value();
1198  C(i+3UL,j) -= A(i+3UL,element->index()) * element->value();
1199  }
1200  }
1201  }
1202 
1203  for( ; (i+2UL) <= A.rows(); i+=2UL ) {
1204  for( size_t j=jj; j<jend; ++j )
1205  {
1206  ConstIterator element( ( IsUpper<MT4>::value )
1207  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1208  :( B.begin(j) ) );
1209  const ConstIterator end( ( IsLower<MT4>::value )
1210  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
1211  :( B.end(j) ) );
1212 
1213  for( ; element!=end; ++element ) {
1214  C(i ,j) -= A(i ,element->index()) * element->value();
1215  C(i+1UL,j) -= A(i+1UL,element->index()) * element->value();
1216  }
1217  }
1218  }
1219 
1220  for( ; i<A.rows(); ++i ) {
1221  for( size_t j=jj; j<jend; ++j )
1222  {
1223  ConstIterator element( ( IsUpper<MT4>::value )
1224  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1225  :( B.begin(j) ) );
1226  const ConstIterator end( ( IsLower<MT4>::value )
1227  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
1228  :( B.end(j) ) );
1229 
1230  for( ; element!=end; ++element )
1231  C(i,j) -= A(i,element->index()) * element->value();
1232  }
1233  }
1234  }
1235  }
1237  //**********************************************************************************************
1238 
1239  //**Optimized subtraction assignment to dense matrices******************************************
1253  template< typename MT3 // Type of the left-hand side target matrix
1254  , typename MT4 // Type of the left-hand side matrix operand
1255  , typename MT5 > // Type of the right-hand side matrix operand
1256  static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
1257  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1258  {
1259  typedef ConstIterator_<MT5> ConstIterator;
1260 
1261  const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 256UL );
1262 
1263  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1264  {
1265  const size_t jend( min( jj+block, B.columns() ) );
1266 
1267  size_t i( 0UL );
1268 
1269  for( ; (i+4UL) <= A.rows(); i+=4UL ) {
1270  for( size_t j=jj; j<jend; ++j )
1271  {
1272  ConstIterator element( ( IsUpper<MT4>::value )
1273  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1274  :( B.begin(j) ) );
1275  const ConstIterator end( ( IsLower<MT4>::value )
1276  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
1277  :( B.end(j) ) );
1278 
1279  const size_t nonzeros( end - element );
1280  const size_t kpos( nonzeros & size_t(-4) );
1281  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1282 
1283  for( size_t k=0UL; k<kpos; k+=4UL )
1284  {
1285  const size_t j1( element->index() );
1286  const ET2 v1( element->value() );
1287  ++element;
1288  const size_t j2( element->index() );
1289  const ET2 v2( element->value() );
1290  ++element;
1291  const size_t j3( element->index() );
1292  const ET2 v3( element->value() );
1293  ++element;
1294  const size_t j4( element->index() );
1295  const ET2 v4( element->value() );
1296  ++element;
1297 
1298  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1299 
1300  C(i ,j) -= A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
1301  C(i+1UL,j) -= A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
1302  C(i+2UL,j) -= A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
1303  C(i+3UL,j) -= A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
1304  }
1305 
1306  for( ; element!=end; ++element )
1307  {
1308  const size_t j1( element->index() );
1309  const ET2 v1( element->value() );
1310 
1311  C(i ,j) -= A(i ,j1) * v1;
1312  C(i+1UL,j) -= A(i+1UL,j1) * v1;
1313  C(i+2UL,j) -= A(i+2UL,j1) * v1;
1314  C(i+3UL,j) -= A(i+3UL,j1) * v1;
1315  }
1316  }
1317  }
1318 
1319  for( ; (i+2UL) <= A.rows(); i+=2UL ) {
1320  for( size_t j=jj; j<jend; ++j )
1321  {
1322  ConstIterator element( ( IsUpper<MT4>::value )
1323  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1324  :( B.begin(j) ) );
1325  const ConstIterator end( ( IsLower<MT4>::value )
1326  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
1327  :( B.end(j) ) );
1328 
1329  const size_t nonzeros( end - element );
1330  const size_t kpos( nonzeros & size_t(-4) );
1331  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1332 
1333  for( size_t k=0UL; k<kpos; k+=4UL )
1334  {
1335  const size_t j1( element->index() );
1336  const ET2 v1( element->value() );
1337  ++element;
1338  const size_t j2( element->index() );
1339  const ET2 v2( element->value() );
1340  ++element;
1341  const size_t j3( element->index() );
1342  const ET2 v3( element->value() );
1343  ++element;
1344  const size_t j4( element->index() );
1345  const ET2 v4( element->value() );
1346  ++element;
1347 
1348  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1349 
1350  C(i ,j) -= A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
1351  C(i+1UL,j) -= A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
1352  }
1353 
1354  for( ; element!=end; ++element )
1355  {
1356  const size_t j1( element->index() );
1357  const ET2 v1( element->value() );
1358 
1359  C(i ,j) -= A(i ,j1) * v1;
1360  C(i+1UL,j) -= A(i+1UL,j1) * v1;
1361  }
1362  }
1363  }
1364 
1365  for( ; i<A.rows(); ++i ) {
1366  for( size_t j=jj; j<jend; ++j )
1367  {
1368  ConstIterator element( ( IsUpper<MT4>::value )
1369  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1370  :( B.begin(j) ) );
1371  const ConstIterator end( ( IsLower<MT4>::value )
1372  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
1373  :( B.end(j) ) );
1374 
1375  const size_t nonzeros( end - element );
1376  const size_t kpos( nonzeros & size_t(-4) );
1377  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1378 
1379  for( size_t k=0UL; k<kpos; k+=4UL )
1380  {
1381  const size_t j1( element->index() );
1382  const ET2 v1( element->value() );
1383  ++element;
1384  const size_t j2( element->index() );
1385  const ET2 v2( element->value() );
1386  ++element;
1387  const size_t j3( element->index() );
1388  const ET2 v3( element->value() );
1389  ++element;
1390  const size_t j4( element->index() );
1391  const ET2 v4( element->value() );
1392  ++element;
1393 
1394  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1395 
1396  C(i,j) -= A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
1397  }
1398 
1399  for( ; element!=end; ++element )
1400  {
1401  const size_t j1( element->index() );
1402  const ET2 v1( element->value() );
1403 
1404  C(i,j) -= A(i,j1) * v1;
1405  }
1406  }
1407  }
1408  }
1409  }
1411  //**********************************************************************************************
1412 
1413  //**Restructuring subtraction assignment********************************************************
1428  template< typename MT // Type of the target matrix
1429  , bool SO > // Storage order of the target matrix
1430  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1431  subAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1432  {
1434 
1436 
1437  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1438  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1439 
1440  subAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1441  }
1443  //**********************************************************************************************
1444 
1445  //**Subtraction assignment to sparse matrices***************************************************
1446  // No special implementation for the subtraction assignment to sparse matrices.
1447  //**********************************************************************************************
1448 
1449  //**Multiplication assignment to dense matrices*************************************************
1450  // No special implementation for the multiplication assignment to dense matrices.
1451  //**********************************************************************************************
1452 
1453  //**Multiplication assignment to sparse matrices************************************************
1454  // No special implementation for the multiplication assignment to sparse matrices.
1455  //**********************************************************************************************
1456 
1457  //**SMP assignment to dense matrices************************************************************
1472  template< typename MT // Type of the target dense matrix
1473  , bool SO > // Storage order of the target dense matrix
1474  friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
1475  smpAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1476  {
1478 
1479  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1480  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1481 
1482  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1483  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1484 
1485  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1486  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
1487  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
1488 
1489  smpAssign( ~lhs, A * B );
1490  }
1492  //**********************************************************************************************
1493 
1494  //**SMP assignment to sparse matrices***********************************************************
1509  template< typename MT // Type of the target sparse matrix
1510  , bool SO > // Storage order of the target sparse matrix
1511  friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
1512  smpAssign( SparseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1513  {
1515 
1516  typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
1517 
1523  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
1524 
1525  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1526  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1527 
1528  const TmpType tmp( rhs );
1529  smpAssign( ~lhs, tmp );
1530  }
1532  //**********************************************************************************************
1533 
1534  //**Restructuring SMP assignment****************************************************************
1549  template< typename MT // Type of the target matrix
1550  , bool SO > // Storage order of the target matrix
1551  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1552  smpAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1553  {
1555 
1557 
1558  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1559  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1560 
1561  smpAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1562  }
1564  //**********************************************************************************************
1565 
1566  //**SMP addition assignment to dense matrices***************************************************
1582  template< typename MT // Type of the target dense matrix
1583  , bool SO > // Storage order of the target dense matrix
1584  friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
1585  smpAddAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1586  {
1588 
1589  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1590  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1591 
1592  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1593  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1594 
1595  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1596  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
1597  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
1598 
1599  smpAddAssign( ~lhs, A * B );
1600  }
1602  //**********************************************************************************************
1603 
1604  //**Restructuring SMP addition assignment*******************************************************
1619  template< typename MT // Type of the target matrix
1620  , bool SO > // Storage order of the target matrix
1621  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1622  smpAddAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1623  {
1625 
1627 
1628  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1629  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1630 
1631  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1632  }
1634  //**********************************************************************************************
1635 
1636  //**SMP addition assignment to sparse matrices**************************************************
1637  // No special implementation for the SMP addition assignment to sparse matrices.
1638  //**********************************************************************************************
1639 
1640  //**SMP subtraction assignment to dense matrices************************************************
1656  template< typename MT // Type of the target dense matrix
1657  , bool SO > // Storage order of the target dense matrix
1658  friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
1659  smpSubAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1660  {
1662 
1663  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1664  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1665 
1666  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1667  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1668 
1669  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1670  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
1671  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
1672 
1673  smpSubAssign( ~lhs, A * B );
1674  }
1676  //**********************************************************************************************
1677 
1678  //**Restructuring SMP subtraction assignment****************************************************
1693  template< typename MT // Type of the target matrix
1694  , bool SO > // Storage order of the target matrix
1695  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1696  smpSubAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1697  {
1699 
1701 
1702  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1703  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1704 
1705  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1706  }
1708  //**********************************************************************************************
1709 
1710  //**SMP subtraction assignment to sparse matrices***********************************************
1711  // No special implementation for the SMP subtraction assignment to sparse matrices.
1712  //**********************************************************************************************
1713 
1714  //**SMP multiplication assignment to dense matrices*********************************************
1715  // No special implementation for the SMP multiplication assignment to dense matrices.
1716  //**********************************************************************************************
1717 
1718  //**SMP multiplication assignment to sparse matrices********************************************
1719  // No special implementation for the SMP multiplication assignment to sparse matrices.
1720  //**********************************************************************************************
1721 
1722  //**Compile time checks*************************************************************************
1730  //**********************************************************************************************
1731 };
1732 //*************************************************************************************************
1733 
1734 
1735 
1736 
1737 //=================================================================================================
1738 //
1739 // GLOBAL BINARY ARITHMETIC OPERATORS
1740 //
1741 //=================================================================================================
1742 
1743 //*************************************************************************************************
1773 template< typename T1 // Type of the left-hand side dense matrix
1774  , typename T2 > // Type of the right-hand side sparse matrix
1775 inline const DMatTSMatMultExpr<T1,T2>
1777 {
1779 
1780  if( (~lhs).columns() != (~rhs).rows() ) {
1781  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1782  }
1783 
1784  return DMatTSMatMultExpr<T1,T2>( ~lhs, ~rhs );
1785 }
1786 //*************************************************************************************************
1787 
1788 
1789 
1790 
1791 //=================================================================================================
1792 //
1793 // ROWS SPECIALIZATIONS
1794 //
1795 //=================================================================================================
1796 
1797 //*************************************************************************************************
1799 template< typename MT1, typename MT2 >
1800 struct Rows< DMatTSMatMultExpr<MT1,MT2> > : public Rows<MT1>
1801 {};
1803 //*************************************************************************************************
1804 
1805 
1806 
1807 
1808 //=================================================================================================
1809 //
1810 // COLUMNS SPECIALIZATIONS
1811 //
1812 //=================================================================================================
1813 
1814 //*************************************************************************************************
1816 template< typename MT1, typename MT2 >
1817 struct Columns< DMatTSMatMultExpr<MT1,MT2> > : public Columns<MT2>
1818 {};
1820 //*************************************************************************************************
1821 
1822 
1823 
1824 
1825 //=================================================================================================
1826 //
1827 // ISALIGNED SPECIALIZATIONS
1828 //
1829 //=================================================================================================
1830 
1831 //*************************************************************************************************
1833 template< typename MT1, typename MT2 >
1834 struct IsAligned< DMatTSMatMultExpr<MT1,MT2> >
1835  : public BoolConstant< IsAligned<MT1>::value >
1836 {};
1838 //*************************************************************************************************
1839 
1840 
1841 
1842 
1843 //=================================================================================================
1844 //
1845 // ISLOWER SPECIALIZATIONS
1846 //
1847 //=================================================================================================
1848 
1849 //*************************************************************************************************
1851 template< typename MT1, typename MT2 >
1852 struct IsLower< DMatTSMatMultExpr<MT1,MT2> >
1853  : public BoolConstant< IsLower<MT1>::value && IsLower<MT2>::value >
1854 {};
1856 //*************************************************************************************************
1857 
1858 
1859 
1860 
1861 //=================================================================================================
1862 //
1863 // ISUNILOWER SPECIALIZATIONS
1864 //
1865 //=================================================================================================
1866 
1867 //*************************************************************************************************
1869 template< typename MT1, typename MT2 >
1870 struct IsUniLower< DMatTSMatMultExpr<MT1,MT2> >
1871  : public BoolConstant< IsUniLower<MT1>::value && IsUniLower<MT2>::value >
1872 {};
1874 //*************************************************************************************************
1875 
1876 
1877 
1878 
1879 //=================================================================================================
1880 //
1881 // ISSTRICTLYLOWER SPECIALIZATIONS
1882 //
1883 //=================================================================================================
1884 
1885 //*************************************************************************************************
1887 template< typename MT1, typename MT2 >
1888 struct IsStrictlyLower< DMatTSMatMultExpr<MT1,MT2> >
1889  : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
1890  , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
1891 {};
1893 //*************************************************************************************************
1894 
1895 
1896 
1897 
1898 //=================================================================================================
1899 //
1900 // ISUPPER SPECIALIZATIONS
1901 //
1902 //=================================================================================================
1903 
1904 //*************************************************************************************************
1906 template< typename MT1, typename MT2 >
1907 struct IsUpper< DMatTSMatMultExpr<MT1,MT2> >
1908  : public BoolConstant< IsUpper<MT1>::value && IsUpper<MT2>::value >
1909 {};
1911 //*************************************************************************************************
1912 
1913 
1914 
1915 
1916 //=================================================================================================
1917 //
1918 // ISUNIUPPER SPECIALIZATIONS
1919 //
1920 //=================================================================================================
1921 
1922 //*************************************************************************************************
1924 template< typename MT1, typename MT2 >
1925 struct IsUniUpper< DMatTSMatMultExpr<MT1,MT2> >
1926  : public BoolConstant< IsUniUpper<MT1>::value && IsUniUpper<MT2>::value >
1927 {};
1929 //*************************************************************************************************
1930 
1931 
1932 
1933 
1934 //=================================================================================================
1935 //
1936 // ISSTRICTLYUPPER SPECIALIZATIONS
1937 //
1938 //=================================================================================================
1939 
1940 //*************************************************************************************************
1942 template< typename MT1, typename MT2 >
1943 struct IsStrictlyUpper< DMatTSMatMultExpr<MT1,MT2> >
1944  : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
1945  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
1946 {};
1948 //*************************************************************************************************
1949 
1950 
1951 
1952 
1953 //=================================================================================================
1954 //
1955 // EXPRESSION TRAIT SPECIALIZATIONS
1956 //
1957 //=================================================================================================
1958 
1959 //*************************************************************************************************
1961 template< typename MT1, typename MT2, typename VT >
1962 struct DMatDVecMultExprTrait< DMatTSMatMultExpr<MT1,MT2>, VT >
1963 {
1964  public:
1965  //**********************************************************************************************
1966  using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
1967  , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
1968  , IsDenseVector<VT>, IsColumnVector<VT> >
1969  , DMatDVecMultExprTrait_< MT1, TSMatDVecMultExprTrait_<MT2,VT> >
1970  , INVALID_TYPE >;
1971  //**********************************************************************************************
1972 };
1974 //*************************************************************************************************
1975 
1976 
1977 //*************************************************************************************************
1979 template< typename MT1, typename MT2, typename VT >
1980 struct DMatSVecMultExprTrait< DMatTSMatMultExpr<MT1,MT2>, VT >
1981 {
1982  public:
1983  //**********************************************************************************************
1984  using Type = If_< And< IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
1985  , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2>
1986  , IsSparseVector<VT>, IsColumnVector<VT> >
1987  , DMatSVecMultExprTrait_< MT1, TSMatSVecMultExprTrait_<MT2,VT> >
1988  , INVALID_TYPE >;
1989  //**********************************************************************************************
1990 };
1992 //*************************************************************************************************
1993 
1994 
1995 //*************************************************************************************************
1997 template< typename VT, typename MT1, typename MT2 >
1998 struct TDVecDMatMultExprTrait< VT, DMatTSMatMultExpr<MT1,MT2> >
1999 {
2000  public:
2001  //**********************************************************************************************
2002  using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
2003  , IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
2004  , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
2005  , TDVecTSMatMultExprTrait_< TDVecDMatMultExprTrait_<VT,MT1>, MT2 >
2006  , INVALID_TYPE >;
2007  //**********************************************************************************************
2008 };
2010 //*************************************************************************************************
2011 
2012 
2013 //*************************************************************************************************
2015 template< typename VT, typename MT1, typename MT2 >
2016 struct TSVecDMatMultExprTrait< VT, DMatTSMatMultExpr<MT1,MT2> >
2017 {
2018  public:
2019  //**********************************************************************************************
2020  using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
2021  , IsDenseMatrix<MT1>, IsRowMajorMatrix<MT1>
2022  , IsSparseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
2023  , TDVecTSMatMultExprTrait_< TSVecDMatMultExprTrait_<VT,MT1>, MT2 >
2024  , INVALID_TYPE >;
2025  //**********************************************************************************************
2026 };
2028 //*************************************************************************************************
2029 
2030 
2031 //*************************************************************************************************
2033 template< typename MT1, typename MT2, bool AF >
2034 struct SubmatrixExprTrait< DMatTSMatMultExpr<MT1,MT2>, AF >
2035 {
2036  public:
2037  //**********************************************************************************************
2038  using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
2039  , SubmatrixExprTrait_<const MT2,AF> >;
2040  //**********************************************************************************************
2041 };
2043 //*************************************************************************************************
2044 
2045 
2046 //*************************************************************************************************
2048 template< typename MT1, typename MT2 >
2049 struct RowExprTrait< DMatTSMatMultExpr<MT1,MT2> >
2050 {
2051  public:
2052  //**********************************************************************************************
2053  using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
2054  //**********************************************************************************************
2055 };
2057 //*************************************************************************************************
2058 
2059 
2060 //*************************************************************************************************
2062 template< typename MT1, typename MT2 >
2063 struct ColumnExprTrait< DMatTSMatMultExpr<MT1,MT2> >
2064 {
2065  public:
2066  //**********************************************************************************************
2067  using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
2068  //**********************************************************************************************
2069 };
2071 //*************************************************************************************************
2072 
2073 } // namespace blaze
2074 
2075 #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.
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:72
Header file for mathematical functions.
constexpr bool useOptimizedKernels
Configuration switch for optimized kernels.This configuration switch enables/disables all optimized c...
Definition: Optimizations.h:84
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: DMatTSMatMultExpr.h:247
Header file for the Rows type trait.
Header file for the IsUniUpper type trait.
const DMatDMatMultExpr< T1, T2 > operator*(const DenseMatrix< T1, false > &lhs, const DenseMatrix< T2, false > &rhs)
Multiplication operator for the multiplication of two row-major dense matrices ( ).
Definition: DMatDMatMultExpr.h:7800
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.
ResultType_< MT1 > RT1
Result type of the left-hand side dense matrix expression.
Definition: DMatTSMatMultExpr.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:160
Header file for the IsSparseMatrix type trait.
Header file for the serial shim.
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: DMatTSMatMultExpr.h:385
Header file for the IsDiagonal type trait.
#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 ColumnExprTrait class template.
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:188
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:533
Header file for the IsRowVector type trait.
typename DisableIf< Condition, T >::Type DisableIf_
Auxiliary type for the DisableIf class template.The DisableIf_ alias declaration provides a convenien...
Definition: DisableIf.h:223
Header file for the And class template.
LeftOperand leftOperand() const noexcept
Returns the left-hand side dense matrix operand.
Definition: DMatTSMatMultExpr.h:331
const ElementType_< MT > min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1669
Compile time check for lower triangular matrices.This type trait tests whether or not the given templ...
Definition: IsLower.h:88
const DMatSerialExpr< MT, SO > serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:723
typename MultTrait< T1, T2 >::Type MultTrait_
Auxiliary alias declaration for the MultTrait class template.The MultTrait_ alias declaration provide...
Definition: MultTrait.h:245
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:323
const ElementType_< MT > max(const DenseMatrix< MT, SO > &dm)
Returns the largest element of the dense matrix.
Definition: DenseMatrix.h:1716
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:129
ResultType_< MT2 > RT2
Result type of the right-hand side sparse matrix expression.
Definition: DMatTSMatMultExpr.h:134
DisableIf_< Or< IsComputation< MT >, IsTransExpr< MT > >, ColumnExprTrait_< MT > > column(Matrix< MT, SO > &matrix, size_t index)
Creating a view on a specific column of the given matrix.
Definition: Column.h:126
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:70
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes...
Definition: Forward.h:109
Constraint on the data type.
const ResultType CompositeType
Data type for composite expression templates.
Definition: DMatTSMatMultExpr.h:202
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
bool isAligned() const noexcept
Returns whether the operands of the expression are properly aligned in memory.
Definition: DMatTSMatMultExpr.h:375
Constraint on the data type.
Constraint on the data type.
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: DMatTSMatMultExpr.h:321
Header file for the MultExprTrait class template.
Compile time check to query the requirement to evaluate an expression.Via this type trait it is possi...
Definition: RequiresEvaluation.h:72
SubvectorExprTrait_< VT, unaligned > 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:152
typename T::CompositeType CompositeType_
Alias declaration for nested CompositeType type definitions.The CompositeType_ alias declaration prov...
Definition: Aliases.h:83
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 If class template.
Compile time check for row-major matrix types.This type trait tests whether or not the given template...
Definition: IsRowMajorMatrix.h:83
#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
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: DMatTSMatMultExpr.h:365
MultTrait_< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: DMatTSMatMultExpr.h:197
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2647
CompositeType_< MT1 > CT1
Composite type of the left-hand side dense matrix expression.
Definition: DMatTSMatMultExpr.h:137
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:98
Header file for the Or class template.
Header file for the TDVecTSMatMultExprTrait class template.
#define BLAZE_THROW_OUT_OF_RANGE(MESSAGE)
Macro for the emission of a std::out_of_range exception.This macro encapsulates the default way of Bl...
Definition: Exception.h:331
Header file for the DenseMatrix base class.
IfTrue_< evaluateRight, const RT2, CT2 > RT
Type for the assignment of the right-hand side sparse matrix operand.
Definition: DMatTSMatMultExpr.h:214
Header file for the Columns type trait.
Header file for the TSMatDVecMultExprTrait class template.
OppositeType_< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: DMatTSMatMultExpr.h:198
typename T::ElementType ElementType_
Alias declaration for nested ElementType type definitions.The ElementType_ alias declaration provides...
Definition: Aliases.h:163
Header file for the DMatDVecMultExprTrait class template.
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
TransposeType_< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: DMatTSMatMultExpr.h:199
#define BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE(T)
Constraint on the data type.In case the given data type T is not a reference type, a compilation error is created.
Definition: Reference.h:60
Header file for the IsTriangular type trait.
IfTrue_< evaluateLeft, const RT1, CT1 > LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: DMatTSMatMultExpr.h:211
Constraints on the storage order of matrix types.
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:254
ElementType_< RT2 > ET2
Element type of the right-hand side sparse matrix expression.
Definition: DMatTSMatMultExpr.h:136
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: DMatTSMatMultExpr.h:393
Header file for the RowExprTrait class template.
Header file for all forward declarations for expression class templates.
Header file for the IsDenseMatrix type trait.
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:109
If_< IsExpression< MT1 >, const MT1, const MT1 & > LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: DMatTSMatMultExpr.h:205
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: DMatTSMatMultExpr.h:311
ElementType_< RT1 > ET1
Element type of the left-hand side dense matrix expression.
Definition: DMatTSMatMultExpr.h:135
DisableIf_< Or< IsComputation< MT >, IsTransExpr< MT > >, RowExprTrait_< MT > > row(Matrix< MT, SO > &matrix, size_t index)
Creating a view on a specific row of the given matrix.
Definition: Row.h:126
Base class for all matrix/matrix multiplication expression templates.The MatMatMultExpr class serves ...
Definition: MatMatMultExpr.h:65
Header file for the IsSparseVector type trait.
#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
Header file for the SubmatrixExprTrait class template.
#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.
Utility type for generic codes.
const ElementType ReturnType
Return type for expression template evaluations.
Definition: DMatTSMatMultExpr.h:201
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:160
ElementType_< ResultType > ElementType
Resulting element type.
Definition: DMatTSMatMultExpr.h:200
Header file for the reset shim.
If_< IsExpression< MT2 >, const MT2, const MT2 & > RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: DMatTSMatMultExpr.h:208
Expression object for dense matrix-transpose sparse matrix multiplications.The DMatTSMatMultExpr clas...
Definition: DMatTSMatMultExpr.h:127
Constraints on the storage order of matrix types.
IntegralConstant< bool, B > BoolConstant
Generic wrapper for a compile time constant boolean value.The BoolConstant class template represents ...
Definition: IntegralConstant.h:100
Header file for the RemoveReference type trait.
typename T::OppositeType OppositeType_
Alias declaration for nested OppositeType type definitions.The OppositeType_ alias declaration provid...
Definition: Aliases.h:243
#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
Header file for the IsDenseVector type trait.
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: DMatTSMatMultExpr.h:295
Compile time check for strictly lower triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyLower.h:86
typename T::ConstIterator ConstIterator_
Alias declaration for nested ConstIterator type definitions.The ConstIterator_ alias declaration prov...
Definition: Aliases.h:103
DMatTSMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the DMatTSMatMultExpr class.
Definition: DMatTSMatMultExpr.h:232
LeftOperand lhs_
Left-hand side dense matrix of the multiplication expression.
Definition: DMatTSMatMultExpr.h:392
Header file for the IsRowMajorMatrix type trait.
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: DMatTSMatMultExpr.h:353
const DMatTransExpr< MT,!SO > trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:950
CompositeType_< MT2 > CT2
Composite type of the right-hand side sparse matrix expression.
Definition: DMatTSMatMultExpr.h:138
Header file for the IsComputation type trait class.
Base class for all compute expression templates.The Computation class serves as a tag for all computa...
Definition: Computation.h:59
Header file for the TDVecDMatMultExprTrait class template.
#define BLAZE_FUNCTION_TRACE
Function trace macro.This macro can be used to reliably trace function calls. In case function tracin...
Definition: FunctionTrace.h:157
Header file for the IntegralConstant class template.
Header file for the TSVecDMatMultExprTrait class template.
typename T::TransposeType TransposeType_
Alias declaration for nested TransposeType type definitions.The TransposeType_ alias declaration prov...
Definition: Aliases.h:403
Header file for the IsUpper type trait.
Header file for the DMatSVecMultExprTrait class template.
Header file for the IsColumnVector type trait.
Constraint on the data type.
RightOperand rightOperand() const noexcept
Returns the right-hand side transpose sparse matrix operand.
Definition: DMatTSMatMultExpr.h:341
Header file for the IsResizable type trait.
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
DMatTSMatMultExpr< MT1, MT2 > This
Type of this DMatTSMatMultExpr instance.
Definition: DMatTSMatMultExpr.h:196
#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 TSMatSVecMultExprTrait class template.
Header file for the FunctionTrace class.