SMatTDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_SMATTDMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_SMATTDMATMULTEXPR_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>
98 #include <blaze/util/Assert.h>
99 #include <blaze/util/DisableIf.h>
100 #include <blaze/util/EnableIf.h>
102 #include <blaze/util/InvalidType.h>
104 #include <blaze/util/mpl/And.h>
105 #include <blaze/util/mpl/If.h>
106 #include <blaze/util/mpl/Or.h>
107 #include <blaze/util/Types.h>
109 
110 
111 namespace blaze {
112 
113 //=================================================================================================
114 //
115 // CLASS SMATTDMATMULTEXPR
116 //
117 //=================================================================================================
118 
119 //*************************************************************************************************
126 template< typename MT1 // Type of the left-hand side sparse matrix
127  , typename MT2 > // Type of the right-hand side dense matrix
128 class SMatTDMatMultExpr : public DenseMatrix< SMatTDMatMultExpr<MT1,MT2>, false >
129  , private MatMatMultExpr
130  , private Computation
131 {
132  private:
133  //**Type definitions****************************************************************************
140  //**********************************************************************************************
141 
142  //**********************************************************************************************
144  enum : bool { evaluateLeft = IsComputation<MT1>::value || RequiresEvaluation<MT1>::value };
145  //**********************************************************************************************
146 
147  //**********************************************************************************************
149  enum : bool { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
150  //**********************************************************************************************
151 
152  //**********************************************************************************************
154 
159  template< typename T1, typename T2, typename T3 >
160  struct CanExploitSymmetry {
161  enum : bool { value = IsSymmetric<T3>::value };
162  };
164  //**********************************************************************************************
165 
166  //**********************************************************************************************
168 
172  template< typename T1, typename T2, typename T3 >
173  struct IsEvaluationRequired {
174  enum : bool { value = ( evaluateLeft || evaluateRight ) &&
175  CanExploitSymmetry<T1,T2,T3>::value };
176  };
178  //**********************************************************************************************
179 
180  //**********************************************************************************************
182 
185  template< typename T1, typename T2, typename T3 >
186  struct UseOptimizedKernel {
187  enum : bool { value = useOptimizedKernels &&
188  !IsDiagonal<T3>::value &&
189  !IsResizable< ElementType_<T1> >::value &&
190  !IsResizable<ET1>::value };
191  };
193  //**********************************************************************************************
194 
195  public:
196  //**Type definitions****************************************************************************
202  typedef const ElementType ReturnType;
203  typedef const ResultType CompositeType;
204 
206  typedef If_< IsExpression<MT1>, const MT1, const MT1& > LeftOperand;
207 
209  typedef If_< IsExpression<MT2>, const MT2, const MT2& > RightOperand;
210 
213 
216  //**********************************************************************************************
217 
218  //**Compilation flags***************************************************************************
220  enum : bool { simdEnabled = false };
221 
223  enum : bool { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
224  !evaluateRight && MT2::smpAssignable };
225  //**********************************************************************************************
226 
227  //**Constructor*********************************************************************************
233  explicit inline SMatTDMatMultExpr( const MT1& lhs, const MT2& rhs ) noexcept
234  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
235  , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
236  {
237  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
238  }
239  //**********************************************************************************************
240 
241  //**Access operator*****************************************************************************
248  inline ReturnType operator()( size_t i, size_t j ) const {
249  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
250  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
251 
252  if( IsDiagonal<MT1>::value ) {
253  return lhs_(i,i) * rhs_(i,j);
254  }
255  else if( IsDiagonal<MT2>::value ) {
256  return lhs_(i,j) * rhs_(j,j);
257  }
259  const size_t begin( ( IsUpper<MT1>::value )
260  ?( ( IsLower<MT2>::value )
261  ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
262  , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
263  :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
264  :( ( IsLower<MT2>::value )
265  ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
266  :( 0UL ) ) );
267  const size_t end( ( IsLower<MT1>::value )
268  ?( ( IsUpper<MT2>::value )
269  ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
270  , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
271  :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
272  :( ( IsUpper<MT2>::value )
273  ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
274  :( lhs_.columns() ) ) );
275 
276  if( begin >= end ) return ElementType();
277 
278  const size_t n( end - begin );
279 
280  return subvector( row( lhs_, i ), begin, n ) * subvector( column( rhs_, j ), begin, n );
281  }
282  else {
283  return row( lhs_, i ) * column( rhs_, j );
284  }
285  }
286  //**********************************************************************************************
287 
288  //**At function*********************************************************************************
296  inline ReturnType at( size_t i, size_t j ) const {
297  if( i >= lhs_.rows() ) {
298  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
299  }
300  if( j >= rhs_.columns() ) {
301  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
302  }
303  return (*this)(i,j);
304  }
305  //**********************************************************************************************
306 
307  //**Rows function*******************************************************************************
312  inline size_t rows() const noexcept {
313  return lhs_.rows();
314  }
315  //**********************************************************************************************
316 
317  //**Columns function****************************************************************************
322  inline size_t columns() const noexcept {
323  return rhs_.columns();
324  }
325  //**********************************************************************************************
326 
327  //**Left operand access*************************************************************************
332  inline LeftOperand leftOperand() const noexcept {
333  return lhs_;
334  }
335  //**********************************************************************************************
336 
337  //**Right operand access************************************************************************
342  inline RightOperand rightOperand() const noexcept {
343  return rhs_;
344  }
345  //**********************************************************************************************
346 
347  //**********************************************************************************************
353  template< typename T >
354  inline bool canAlias( const T* alias ) const noexcept {
355  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
356  }
357  //**********************************************************************************************
358 
359  //**********************************************************************************************
365  template< typename T >
366  inline bool isAliased( const T* alias ) const noexcept {
367  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
368  }
369  //**********************************************************************************************
370 
371  //**********************************************************************************************
376  inline bool isAligned() const noexcept {
377  return rhs_.isAligned();
378  }
379  //**********************************************************************************************
380 
381  //**********************************************************************************************
386  inline bool canSMPAssign() const noexcept {
387  return ( rows() * columns() >= SMP_SMATTDMATMULT_THRESHOLD );
388  }
389  //**********************************************************************************************
390 
391  private:
392  //**Member variables****************************************************************************
393  LeftOperand lhs_;
394  RightOperand rhs_;
395  //**********************************************************************************************
396 
397  //**Assignment to dense matrices****************************************************************
410  template< typename MT // Type of the target dense matrix
411  , bool SO > // Storage order of the target dense matrix
413  assign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
414  {
416 
417  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
418  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
419 
420  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
421  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
422 
423  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
424  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
425  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
426  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
427  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
428  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
429 
430  SMatTDMatMultExpr::selectAssignKernel( ~lhs, A, B );
431  }
433  //**********************************************************************************************
434 
435  //**Default assignment to dense matrices********************************************************
449  template< typename MT3 // Type of the left-hand side target matrix
450  , typename MT4 // Type of the left-hand side matrix operand
451  , typename MT5 > // Type of the right-hand side matrix operand
453  selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
454  {
456 
457  const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 256UL );
458 
459  for( size_t ii=0UL; ii<A.rows(); ii+=block )
460  {
461  const size_t iend( min( ii+block, A.rows() ) );
462 
463  size_t j( 0UL );
464 
465  for( ; (j+4UL) <= B.columns(); j+=4UL ) {
466  for( size_t i=ii; i<iend; ++i )
467  {
468  const ConstIterator end( ( IsUpper<MT5>::value )
469  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
470  :( A.end(i) ) );
471  ConstIterator element( ( IsLower<MT5>::value )
472  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
473  :( A.begin(i) ) );
474 
475  if( element == end ) {
476  reset( C(i,j ) );
477  reset( C(i,j+1UL) );
478  reset( C(i,j+2UL) );
479  reset( C(i,j+3UL) );
480  continue;
481  }
482 
483  C(i,j ) = element->value() * B(element->index(),j );
484  C(i,j+1UL) = element->value() * B(element->index(),j+1UL);
485  C(i,j+2UL) = element->value() * B(element->index(),j+2UL);
486  C(i,j+3UL) = element->value() * B(element->index(),j+3UL);
487  ++element;
488  for( ; element!=end; ++element ) {
489  C(i,j ) += element->value() * B(element->index(),j );
490  C(i,j+1UL) += element->value() * B(element->index(),j+1UL);
491  C(i,j+2UL) += element->value() * B(element->index(),j+2UL);
492  C(i,j+3UL) += element->value() * B(element->index(),j+3UL);
493  }
494  }
495  }
496 
497  for( ; (j+2UL) <= B.columns(); j+=2UL ) {
498  for( size_t i=ii; i<iend; ++i )
499  {
500  const ConstIterator end( ( IsUpper<MT5>::value )
501  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
502  :( A.end(i) ) );
503  ConstIterator element( ( IsLower<MT5>::value )
504  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
505  :( A.begin(i) ) );
506 
507  if( element == end ) {
508  reset( C(i,j ) );
509  reset( C(i,j+1UL) );
510  continue;
511  }
512 
513  C(i,j ) = element->value() * B(element->index(),j );
514  C(i,j+1UL) = element->value() * B(element->index(),j+1UL);
515  ++element;
516  for( ; element!=end; ++element ) {
517  C(i,j ) += element->value() * B(element->index(),j );
518  C(i,j+1UL) += element->value() * B(element->index(),j+1UL);
519  }
520  }
521  }
522 
523  for( ; j<B.columns(); ++j ) {
524  for( size_t i=ii; i<iend; ++i )
525  {
526  const ConstIterator end( ( IsUpper<MT5>::value )
527  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
528  :( A.end(i) ) );
529  ConstIterator element( ( IsLower<MT5>::value )
530  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
531  :( A.begin(i) ) );
532 
533  if( element == end ) {
534  reset( C(i,j) );
535  continue;
536  }
537 
538  C(i,j) = element->value() * B(element->index(),j);
539  ++element;
540  for( ; element!=end; ++element ) {
541  C(i,j) += element->value() * B(element->index(),j);
542  }
543  }
544  }
545  }
546  }
548  //**********************************************************************************************
549 
550  //**Optimized assignment to dense matrices******************************************************
564  template< typename MT3 // Type of the left-hand side target matrix
565  , typename MT4 // Type of the left-hand side matrix operand
566  , typename MT5 > // Type of the right-hand side matrix operand
567  static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
568  selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
569  {
570  typedef ConstIterator_<MT4> ConstIterator;
571 
572  const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 256UL );
573 
574  reset( C );
575 
576  for( size_t ii=0UL; ii<A.rows(); ii+=block )
577  {
578  const size_t iend( min( ii+block, A.rows() ) );
579 
580  size_t j( 0UL );
581 
582  for( ; (j+4UL) <= B.columns(); j+=4UL ) {
583  for( size_t i=ii; i<iend; ++i )
584  {
585  const ConstIterator end( ( IsUpper<MT5>::value )
586  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
587  :( A.end(i) ) );
588  ConstIterator element( ( IsLower<MT5>::value )
589  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
590  :( A.begin(i) ) );
591 
592  const size_t nonzeros( end - element );
593  const size_t kpos( nonzeros & size_t(-4) );
594  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
595 
596  for( size_t k=0UL; k<kpos; k+=4UL )
597  {
598  const size_t i1( element->index() );
599  const ET1 v1( element->value() );
600  ++element;
601  const size_t i2( element->index() );
602  const ET1 v2( element->value() );
603  ++element;
604  const size_t i3( element->index() );
605  const ET1 v3( element->value() );
606  ++element;
607  const size_t i4( element->index() );
608  const ET1 v4( element->value() );
609  ++element;
610 
611  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
612 
613  C(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
614  C(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
615  C(i,j+2UL) += v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
616  C(i,j+3UL) += v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
617  }
618 
619  for( ; element!=end; ++element )
620  {
621  const size_t i1( element->index() );
622  const ET1 v1( element->value() );
623 
624  C(i,j ) += v1 * B(i1,j );
625  C(i,j+1UL) += v1 * B(i1,j+1UL);
626  C(i,j+2UL) += v1 * B(i1,j+2UL);
627  C(i,j+3UL) += v1 * B(i1,j+3UL);
628  }
629  }
630  }
631 
632  for( ; (j+2UL) <= B.columns(); j+=2UL ) {
633  for( size_t i=ii; i<iend; ++i )
634  {
635  const ConstIterator end( ( IsUpper<MT5>::value )
636  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
637  :( A.end(i) ) );
638  ConstIterator element( ( IsLower<MT5>::value )
639  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
640  :( A.begin(i) ) );
641 
642  const size_t nonzeros( end - element );
643  const size_t kpos( nonzeros & size_t(-4) );
644  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
645 
646  for( size_t k=0UL; k<kpos; k+=4UL )
647  {
648  const size_t i1( element->index() );
649  const ET1 v1( element->value() );
650  ++element;
651  const size_t i2( element->index() );
652  const ET1 v2( element->value() );
653  ++element;
654  const size_t i3( element->index() );
655  const ET1 v3( element->value() );
656  ++element;
657  const size_t i4( element->index() );
658  const ET1 v4( element->value() );
659  ++element;
660 
661  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
662 
663  C(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
664  C(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
665  }
666 
667  for( ; element!=end; ++element )
668  {
669  const size_t i1( element->index() );
670  const ET1 v1( element->value() );
671 
672  C(i,j ) += v1 * B(i1,j );
673  C(i,j+1UL) += v1 * B(i1,j+1UL);
674  }
675  }
676  }
677 
678  for( ; j<B.columns(); ++j ) {
679  for( size_t i=ii; i<iend; ++i )
680  {
681  const ConstIterator end( ( IsUpper<MT5>::value )
682  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
683  :( A.end(i) ) );
684  ConstIterator element( ( IsLower<MT5>::value )
685  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
686  :( A.begin(i) ) );
687 
688  const size_t nonzeros( end - element );
689  const size_t kpos( nonzeros & size_t(-4) );
690  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
691 
692  for( size_t k=0UL; k<kpos; k+=4UL )
693  {
694  const size_t i1( element->index() );
695  const ET1 v1( element->value() );
696  ++element;
697  const size_t i2( element->index() );
698  const ET1 v2( element->value() );
699  ++element;
700  const size_t i3( element->index() );
701  const ET1 v3( element->value() );
702  ++element;
703  const size_t i4( element->index() );
704  const ET1 v4( element->value() );
705  ++element;
706 
707  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
708 
709  C(i,j) += v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
710  }
711 
712  for( ; element!=end; ++element )
713  {
714  const size_t i1( element->index() );
715  const ET1 v1( element->value() );
716 
717  C(i,j) += v1 * B(i1,j);
718  }
719  }
720  }
721  }
722  }
724  //**********************************************************************************************
725 
726  //**Assignment to sparse matrices***************************************************************
739  template< typename MT // Type of the target sparse matrix
740  , bool SO > // Storage order of the target sparse matrix
741  friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
742  assign( SparseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
743  {
745 
746  typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
747 
753  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
754 
755  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
756  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
757 
758  const TmpType tmp( serial( rhs ) );
759  assign( ~lhs, tmp );
760  }
762  //**********************************************************************************************
763 
764  //**Restructuring assignment********************************************************************
779  template< typename MT // Type of the target matrix
780  , bool SO > // Storage order of the target matrix
781  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
782  assign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
783  {
785 
786  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
787  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
788 
789  assign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
790  }
792  //**********************************************************************************************
793 
794  //**Addition assignment to dense matrices*******************************************************
807  template< typename MT // Type of the target dense matrix
808  , bool SO > // Storage order of the target dense matrix
809  friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
810  addAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
811  {
813 
814  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
815  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
816 
817  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
818  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
819 
820  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
821  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
822  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
823  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
824  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
825  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
826 
827  SMatTDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
828  }
830  //**********************************************************************************************
831 
832  //**Default addition assignment to dense matrices***********************************************
846  template< typename MT3 // Type of the left-hand side target matrix
847  , typename MT4 // Type of the left-hand side matrix operand
848  , typename MT5 > // Type of the right-hand side matrix operand
849  static inline DisableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
850  selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
851  {
852  typedef ConstIterator_<MT4> ConstIterator;
853 
854  const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 256UL );
855 
856  for( size_t ii=0UL; ii<A.rows(); ii+=block )
857  {
858  const size_t iend( min( ii+block, A.rows() ) );
859 
860  size_t j( 0UL );
861 
862  for( ; (j+4UL) <= B.columns(); j+=4UL ) {
863  for( size_t i=ii; i<iend; ++i )
864  {
865  const ConstIterator end( ( IsUpper<MT5>::value )
866  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
867  :( A.end(i) ) );
868  ConstIterator element( ( IsLower<MT5>::value )
869  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
870  :( A.begin(i) ) );
871 
872  for( ; element!=end; ++element ) {
873  C(i,j ) += element->value() * B(element->index(),j );
874  C(i,j+1UL) += element->value() * B(element->index(),j+1UL);
875  C(i,j+2UL) += element->value() * B(element->index(),j+2UL);
876  C(i,j+3UL) += element->value() * B(element->index(),j+3UL);
877  }
878  }
879  }
880 
881  for( ; (j+2UL) <= B.columns(); j+=2UL ) {
882  for( size_t i=ii; i<iend; ++i )
883  {
884  const ConstIterator end( ( IsUpper<MT5>::value )
885  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
886  :( A.end(i) ) );
887  ConstIterator element( ( IsLower<MT5>::value )
888  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
889  :( A.begin(i) ) );
890 
891  for( ; element!=end; ++element ) {
892  C(i,j ) += element->value() * B(element->index(),j );
893  C(i,j+1UL) += element->value() * B(element->index(),j+1UL);
894  }
895  }
896  }
897 
898  for( ; j<B.columns(); ++j ) {
899  for( size_t i=ii; i<iend; ++i )
900  {
901  const ConstIterator end( ( IsUpper<MT5>::value )
902  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
903  :( A.end(i) ) );
904  ConstIterator element( ( IsLower<MT5>::value )
905  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
906  :( A.begin(i) ) );
907 
908  for( ; element!=end; ++element ) {
909  C(i,j) += element->value() * B(element->index(),j);
910  }
911  }
912  }
913  }
914  }
916  //**********************************************************************************************
917 
918  //**Optimized addition assignment to dense matrices*********************************************
932  template< typename MT3 // Type of the left-hand side target matrix
933  , typename MT4 // Type of the left-hand side matrix operand
934  , typename MT5 > // Type of the right-hand side matrix operand
935  static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
936  selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
937  {
938  typedef ConstIterator_<MT4> ConstIterator;
939 
940  const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 256UL );
941 
942  for( size_t ii=0UL; ii<A.rows(); ii+=block )
943  {
944  const size_t iend( min( ii+block, A.rows() ) );
945 
946  size_t j( 0UL );
947 
948  for( ; (j+4UL) <= B.columns(); j+=4UL ) {
949  for( size_t i=ii; i<iend; ++i )
950  {
951  const ConstIterator end( ( IsUpper<MT5>::value )
952  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
953  :( A.end(i) ) );
954  ConstIterator element( ( IsLower<MT5>::value )
955  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
956  :( A.begin(i) ) );
957 
958  const size_t nonzeros( end - element );
959  const size_t kpos( nonzeros & size_t(-4) );
960  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
961 
962  for( size_t k=0UL; k<kpos; k+=4UL )
963  {
964  const size_t i1( element->index() );
965  const ET1 v1( element->value() );
966  ++element;
967  const size_t i2( element->index() );
968  const ET1 v2( element->value() );
969  ++element;
970  const size_t i3( element->index() );
971  const ET1 v3( element->value() );
972  ++element;
973  const size_t i4( element->index() );
974  const ET1 v4( element->value() );
975  ++element;
976 
977  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
978 
979  C(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
980  C(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
981  C(i,j+2UL) += v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
982  C(i,j+3UL) += v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
983  }
984 
985  for( ; element!=end; ++element )
986  {
987  const size_t i1( element->index() );
988  const ET1 v1( element->value() );
989 
990  C(i,j ) += v1 * B(i1,j );
991  C(i,j+1UL) += v1 * B(i1,j+1UL);
992  C(i,j+2UL) += v1 * B(i1,j+2UL);
993  C(i,j+3UL) += v1 * B(i1,j+3UL);
994  }
995  }
996  }
997 
998  for( ; (j+2UL) <= B.columns(); j+=2UL ) {
999  for( size_t i=ii; i<iend; ++i )
1000  {
1001  const ConstIterator end( ( IsUpper<MT5>::value )
1002  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
1003  :( A.end(i) ) );
1004  ConstIterator element( ( IsLower<MT5>::value )
1005  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1006  :( A.begin(i) ) );
1007 
1008  const size_t nonzeros( end - element );
1009  const size_t kpos( nonzeros & size_t(-4) );
1010  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1011 
1012  for( size_t k=0UL; k<kpos; k+=4UL )
1013  {
1014  const size_t i1( element->index() );
1015  const ET1 v1( element->value() );
1016  ++element;
1017  const size_t i2( element->index() );
1018  const ET1 v2( element->value() );
1019  ++element;
1020  const size_t i3( element->index() );
1021  const ET1 v3( element->value() );
1022  ++element;
1023  const size_t i4( element->index() );
1024  const ET1 v4( element->value() );
1025  ++element;
1026 
1027  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1028 
1029  C(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
1030  C(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
1031  }
1032 
1033  for( ; element!=end; ++element )
1034  {
1035  const size_t i1( element->index() );
1036  const ET1 v1( element->value() );
1037 
1038  C(i,j ) += v1 * B(i1,j );
1039  C(i,j+1UL) += v1 * B(i1,j+1UL);
1040  }
1041  }
1042  }
1043 
1044  for( ; j<B.columns(); ++j ) {
1045  for( size_t i=ii; i<iend; ++i )
1046  {
1047  const ConstIterator end( ( IsUpper<MT5>::value )
1048  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
1049  :( A.end(i) ) );
1050  ConstIterator element( ( IsLower<MT5>::value )
1051  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1052  :( A.begin(i) ) );
1053 
1054  const size_t nonzeros( end - element );
1055  const size_t kpos( nonzeros & size_t(-4) );
1056  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1057 
1058  for( size_t k=0UL; k<kpos; k+=4UL )
1059  {
1060  const size_t i1( element->index() );
1061  const ET1 v1( element->value() );
1062  ++element;
1063  const size_t i2( element->index() );
1064  const ET1 v2( element->value() );
1065  ++element;
1066  const size_t i3( element->index() );
1067  const ET1 v3( element->value() );
1068  ++element;
1069  const size_t i4( element->index() );
1070  const ET1 v4( element->value() );
1071  ++element;
1072 
1073  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1074 
1075  C(i,j) += v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
1076  }
1077 
1078  for( ; element!=end; ++element )
1079  {
1080  const size_t i1( element->index() );
1081  const ET1 v1( element->value() );
1082 
1083  C(i,j) += v1 * B(i1,j);
1084  }
1085  }
1086  }
1087  }
1088  }
1090  //**********************************************************************************************
1091 
1092  //**Restructuring addition assignment***********************************************************
1107  template< typename MT // Type of the target matrix
1108  , bool SO > // Storage order of the target matrix
1109  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1110  addAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1111  {
1113 
1114  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1115  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1116 
1117  addAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1118  }
1120  //**********************************************************************************************
1121 
1122  //**Addition assignment to sparse matrices******************************************************
1123  // No special implementation for the addition assignment to sparse matrices.
1124  //**********************************************************************************************
1125 
1126  //**Subtraction assignment to dense matrices****************************************************
1139  template< typename MT // Type of the target dense matrix
1140  , bool SO > // Storage order of the target dense matrix
1141  friend inline DisableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1142  subAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1143  {
1145 
1146  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1147  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1148 
1149  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
1150  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
1151 
1152  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1153  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1154  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1155  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1156  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1157  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1158 
1159  SMatTDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1160  }
1162  //**********************************************************************************************
1163 
1164  //**Default subtraction assignment to dense matrices********************************************
1178  template< typename MT3 // Type of the left-hand side target matrix
1179  , typename MT4 // Type of the left-hand side matrix operand
1180  , typename MT5 > // Type of the right-hand side matrix operand
1181  static inline DisableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
1182  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1183  {
1184  typedef ConstIterator_<MT4> ConstIterator;
1185 
1186  const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 256UL );
1187 
1188  for( size_t ii=0UL; ii<A.rows(); ii+=block )
1189  {
1190  const size_t iend( min( ii+block, A.rows() ) );
1191 
1192  size_t j( 0UL );
1193 
1194  for( ; (j+4UL) <= B.columns(); j+=4UL ) {
1195  for( size_t i=ii; i<iend; ++i )
1196  {
1197  const ConstIterator end( ( IsUpper<MT5>::value )
1198  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
1199  :( A.end(i) ) );
1200  ConstIterator element( ( IsLower<MT5>::value )
1201  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1202  :( A.begin(i) ) );
1203 
1204  for( ; element!=end; ++element ) {
1205  C(i,j ) -= element->value() * B(element->index(),j );
1206  C(i,j+1UL) -= element->value() * B(element->index(),j+1UL);
1207  C(i,j+2UL) -= element->value() * B(element->index(),j+2UL);
1208  C(i,j+3UL) -= element->value() * B(element->index(),j+3UL);
1209  }
1210  }
1211  }
1212 
1213  for( ; (j+2UL) <= B.columns(); j+=2UL ) {
1214  for( size_t i=ii; i<iend; ++i )
1215  {
1216  const ConstIterator end( ( IsUpper<MT5>::value )
1217  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
1218  :( A.end(i) ) );
1219  ConstIterator element( ( IsLower<MT5>::value )
1220  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1221  :( A.begin(i) ) );
1222 
1223  for( ; element!=end; ++element ) {
1224  C(i,j ) -= element->value() * B(element->index(),j );
1225  C(i,j+1UL) -= element->value() * B(element->index(),j+1UL);
1226  }
1227  }
1228  }
1229 
1230  for( ; j<B.columns(); ++j ) {
1231  for( size_t i=ii; i<iend; ++i )
1232  {
1233  const ConstIterator end( ( IsUpper<MT5>::value )
1234  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
1235  :( A.end(i) ) );
1236  ConstIterator element( ( IsLower<MT5>::value )
1237  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1238  :( A.begin(i) ) );
1239 
1240  for( ; element!=end; ++element ) {
1241  C(i,j) -= element->value() * B(element->index(),j);
1242  }
1243  }
1244  }
1245  }
1246  }
1248  //**********************************************************************************************
1249 
1250  //**Optimized subtraction assignment to dense matrices******************************************
1264  template< typename MT3 // Type of the left-hand side target matrix
1265  , typename MT4 // Type of the left-hand side matrix operand
1266  , typename MT5 > // Type of the right-hand side matrix operand
1267  static inline EnableIf_< UseOptimizedKernel<MT3,MT4,MT5> >
1268  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1269  {
1270  typedef ConstIterator_<MT4> ConstIterator;
1271 
1272  const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 256UL );
1273 
1274  for( size_t ii=0UL; ii<A.rows(); ii+=block )
1275  {
1276  const size_t iend( min( ii+block, A.rows() ) );
1277 
1278  size_t j( 0UL );
1279 
1280  for( ; (j+4UL) <= B.columns(); j+=4UL ) {
1281  for( size_t i=ii; i<iend; ++i )
1282  {
1283  const ConstIterator end( ( IsUpper<MT5>::value )
1284  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
1285  :( A.end(i) ) );
1286  ConstIterator element( ( IsLower<MT5>::value )
1287  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1288  :( A.begin(i) ) );
1289 
1290  const size_t nonzeros( end - element );
1291  const size_t kpos( nonzeros & size_t(-4) );
1292  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1293 
1294  for( size_t k=0UL; k<kpos; k+=4UL )
1295  {
1296  const size_t i1( element->index() );
1297  const ET1 v1( element->value() );
1298  ++element;
1299  const size_t i2( element->index() );
1300  const ET1 v2( element->value() );
1301  ++element;
1302  const size_t i3( element->index() );
1303  const ET1 v3( element->value() );
1304  ++element;
1305  const size_t i4( element->index() );
1306  const ET1 v4( element->value() );
1307  ++element;
1308 
1309  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1310 
1311  C(i,j ) -= v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
1312  C(i,j+1UL) -= v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
1313  C(i,j+2UL) -= v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
1314  C(i,j+3UL) -= v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
1315  }
1316 
1317  for( ; element!=end; ++element )
1318  {
1319  const size_t i1( element->index() );
1320  const ET1 v1( element->value() );
1321 
1322  C(i,j ) -= v1 * B(i1,j );
1323  C(i,j+1UL) -= v1 * B(i1,j+1UL);
1324  C(i,j+2UL) -= v1 * B(i1,j+2UL);
1325  C(i,j+3UL) -= v1 * B(i1,j+3UL);
1326  }
1327  }
1328  }
1329 
1330  for( ; (j+2UL) <= B.columns(); j+=2UL ) {
1331  for( size_t i=ii; i<iend; ++i )
1332  {
1333  const ConstIterator end( ( IsUpper<MT5>::value )
1334  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
1335  :( A.end(i) ) );
1336  ConstIterator element( ( IsLower<MT5>::value )
1337  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1338  :( A.begin(i) ) );
1339 
1340  const size_t nonzeros( end - element );
1341  const size_t kpos( nonzeros & size_t(-4) );
1342  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1343 
1344  for( size_t k=0UL; k<kpos; k+=4UL )
1345  {
1346  const size_t i1( element->index() );
1347  const ET1 v1( element->value() );
1348  ++element;
1349  const size_t i2( element->index() );
1350  const ET1 v2( element->value() );
1351  ++element;
1352  const size_t i3( element->index() );
1353  const ET1 v3( element->value() );
1354  ++element;
1355  const size_t i4( element->index() );
1356  const ET1 v4( element->value() );
1357  ++element;
1358 
1359  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1360 
1361  C(i,j ) -= v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
1362  C(i,j+1UL) -= v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
1363  }
1364 
1365  for( ; element!=end; ++element )
1366  {
1367  const size_t i1( element->index() );
1368  const ET1 v1( element->value() );
1369 
1370  C(i,j ) -= v1 * B(i1,j );
1371  C(i,j+1UL) -= v1 * B(i1,j+1UL);
1372  }
1373  }
1374  }
1375 
1376  for( ; j<B.columns(); ++j ) {
1377  for( size_t i=ii; i<iend; ++i )
1378  {
1379  const ConstIterator end( ( IsUpper<MT5>::value )
1380  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
1381  :( A.end(i) ) );
1382  ConstIterator element( ( IsLower<MT5>::value )
1383  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1384  :( A.begin(i) ) );
1385 
1386  const size_t nonzeros( end - element );
1387  const size_t kpos( nonzeros & size_t(-4) );
1388  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1389 
1390  for( size_t k=0UL; k<kpos; k+=4UL )
1391  {
1392  const size_t i1( element->index() );
1393  const ET1 v1( element->value() );
1394  ++element;
1395  const size_t i2( element->index() );
1396  const ET1 v2( element->value() );
1397  ++element;
1398  const size_t i3( element->index() );
1399  const ET1 v3( element->value() );
1400  ++element;
1401  const size_t i4( element->index() );
1402  const ET1 v4( element->value() );
1403  ++element;
1404 
1405  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1406 
1407  C(i,j) -= v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
1408  }
1409 
1410  for( ; element!=end; ++element )
1411  {
1412  const size_t i1( element->index() );
1413  const ET1 v1( element->value() );
1414 
1415  C(i,j) -= v1 * B(i1,j);
1416  }
1417  }
1418  }
1419  }
1420  }
1422  //**********************************************************************************************
1423 
1424  //**Restructuring subtraction assignment********************************************************
1439  template< typename MT // Type of the target matrix
1440  , bool SO > // Storage order of the target matrix
1441  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1442  subAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1443  {
1445 
1446  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1447  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1448 
1449  subAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1450  }
1452  //**********************************************************************************************
1453 
1454  //**Subtraction assignment to sparse matrices***************************************************
1455  // No special implementation for the subtraction assignment to sparse matrices.
1456  //**********************************************************************************************
1457 
1458  //**Multiplication assignment to dense matrices*************************************************
1459  // No special implementation for the multiplication assignment to dense matrices.
1460  //**********************************************************************************************
1461 
1462  //**Multiplication assignment to sparse matrices************************************************
1463  // No special implementation for the multiplication assignment to sparse matrices.
1464  //**********************************************************************************************
1465 
1466  //**SMP assignment to dense matrices************************************************************
1481  template< typename MT // Type of the target dense matrix
1482  , bool SO > // Storage order of the target dense matrix
1483  friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
1484  smpAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1485  {
1487 
1488  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1489  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1490 
1491  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
1492  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
1493 
1494  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1495  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1496  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1497  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1498  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1499  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1500 
1501  smpAssign( ~lhs, A * B );
1502  }
1504  //**********************************************************************************************
1505 
1506  //**SMP assignment to sparse matrices***********************************************************
1521  template< typename MT // Type of the target sparse matrix
1522  , bool SO > // Storage order of the target sparse matrix
1523  friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
1524  smpAssign( SparseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1525  {
1527 
1528  typedef IfTrue_< SO, OppositeType, ResultType > TmpType;
1529 
1535  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_<TmpType> );
1536 
1537  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1538  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1539 
1540  const TmpType tmp( rhs );
1541  smpAssign( ~lhs, tmp );
1542  }
1544  //**********************************************************************************************
1545 
1546  //**Restructuring SMP assignment****************************************************************
1561  template< typename MT // Type of the target matrix
1562  , bool SO > // Storage order of the target matrix
1563  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1564  smpAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1565  {
1567 
1568  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1569  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1570 
1571  smpAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1572  }
1574  //**********************************************************************************************
1575 
1576  //**SMP addition assignment to dense matrices***************************************************
1592  template< typename MT // Type of the target dense matrix
1593  , bool SO > // Storage order of the target dense matrix
1594  friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
1595  smpAddAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1596  {
1598 
1599  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1600  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1601 
1602  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
1603  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
1604 
1605  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1606  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1607  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1608  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1609  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1610  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1611 
1612  smpAddAssign( ~lhs, A * B );
1613  }
1615  //**********************************************************************************************
1616 
1617  //**Restructuring SMP addition assignment*******************************************************
1632  template< typename MT // Type of the target matrix
1633  , bool SO > // Storage order of the target matrix
1634  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1635  smpAddAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1636  {
1638 
1639  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1640  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1641 
1642  smpAddAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1643  }
1645  //**********************************************************************************************
1646 
1647  //**SMP addition assignment to sparse matrices**************************************************
1648  // No special implementation for the SMP addition assignment to sparse matrices.
1649  //**********************************************************************************************
1650 
1651  //**SMP subtraction assignment to dense matrices************************************************
1667  template< typename MT // Type of the target dense matrix
1668  , bool SO > // Storage order of the target dense matrix
1669  friend inline EnableIf_< IsEvaluationRequired<MT,MT1,MT2> >
1670  smpSubAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1671  {
1673 
1674  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1675  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1676 
1677  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
1678  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
1679 
1680  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1681  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1682  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1683  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1684  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1685  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1686 
1687  smpSubAssign( ~lhs, A * B );
1688  }
1690  //**********************************************************************************************
1691 
1692  //**Restructuring SMP subtraction assignment****************************************************
1707  template< typename MT // Type of the target matrix
1708  , bool SO > // Storage order of the target matrix
1709  friend inline EnableIf_< CanExploitSymmetry<MT,MT1,MT2> >
1710  smpSubAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1711  {
1713 
1714  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1715  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1716 
1717  smpSubAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1718  }
1720  //**********************************************************************************************
1721 
1722  //**SMP subtraction assignment to sparse matrices***********************************************
1723  // No special implementation for the SMP subtraction assignment to sparse matrices.
1724  //**********************************************************************************************
1725 
1726  //**SMP multiplication assignment to dense matrices*********************************************
1727  // No special implementation for the SMP multiplication assignment to dense matrices.
1728  //**********************************************************************************************
1729 
1730  //**SMP multiplication assignment to sparse matrices********************************************
1731  // No special implementation for the SMP multiplication assignment to sparse matrices.
1732  //**********************************************************************************************
1733 
1734  //**Compile time checks*************************************************************************
1742  //**********************************************************************************************
1743 };
1744 //*************************************************************************************************
1745 
1746 
1747 
1748 
1749 //=================================================================================================
1750 //
1751 // GLOBAL BINARY ARITHMETIC OPERATORS
1752 //
1753 //=================================================================================================
1754 
1755 //*************************************************************************************************
1786 template< typename T1 // Type of the left-hand side sparse matrix
1787  , typename T2 > // Type of the right-hand side dense matrix
1788 inline const SMatTDMatMultExpr<T1,T2>
1790 {
1792 
1793  if( (~lhs).columns() != (~rhs).rows() ) {
1794  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1795  }
1796 
1797  return SMatTDMatMultExpr<T1,T2>( ~lhs, ~rhs );
1798 }
1799 //*************************************************************************************************
1800 
1801 
1802 
1803 
1804 //=================================================================================================
1805 //
1806 // ROWS SPECIALIZATIONS
1807 //
1808 //=================================================================================================
1809 
1810 //*************************************************************************************************
1812 template< typename MT1, typename MT2 >
1813 struct Rows< SMatTDMatMultExpr<MT1,MT2> > : public Rows<MT1>
1814 {};
1816 //*************************************************************************************************
1817 
1818 
1819 
1820 
1821 //=================================================================================================
1822 //
1823 // COLUMNS SPECIALIZATIONS
1824 //
1825 //=================================================================================================
1826 
1827 //*************************************************************************************************
1829 template< typename MT1, typename MT2 >
1830 struct Columns< SMatTDMatMultExpr<MT1,MT2> > : public Columns<MT2>
1831 {};
1833 //*************************************************************************************************
1834 
1835 
1836 
1837 
1838 //=================================================================================================
1839 //
1840 // ISALIGNED SPECIALIZATIONS
1841 //
1842 //=================================================================================================
1843 
1844 //*************************************************************************************************
1846 template< typename MT1, typename MT2 >
1847 struct IsAligned< SMatTDMatMultExpr<MT1,MT2> >
1848  : public BoolConstant< IsAligned<MT2>::value >
1849 {};
1851 //*************************************************************************************************
1852 
1853 
1854 
1855 
1856 //=================================================================================================
1857 //
1858 // ISLOWER SPECIALIZATIONS
1859 //
1860 //=================================================================================================
1861 
1862 //*************************************************************************************************
1864 template< typename MT1, typename MT2 >
1865 struct IsLower< SMatTDMatMultExpr<MT1,MT2> >
1866  : public BoolConstant< And< IsLower<MT1>, IsLower<MT2> >::value >
1867 {};
1869 //*************************************************************************************************
1870 
1871 
1872 
1873 
1874 //=================================================================================================
1875 //
1876 // ISUNILOWER SPECIALIZATIONS
1877 //
1878 //=================================================================================================
1879 
1880 //*************************************************************************************************
1882 template< typename MT1, typename MT2 >
1883 struct IsUniLower< SMatTDMatMultExpr<MT1,MT2> >
1884  : public BoolConstant< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
1885 {};
1887 //*************************************************************************************************
1888 
1889 
1890 
1891 
1892 //=================================================================================================
1893 //
1894 // ISSTRICTLYLOWER SPECIALIZATIONS
1895 //
1896 //=================================================================================================
1897 
1898 //*************************************************************************************************
1900 template< typename MT1, typename MT2 >
1901 struct IsStrictlyLower< SMatTDMatMultExpr<MT1,MT2> >
1902  : public BoolConstant< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
1903  , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
1904 {};
1906 //*************************************************************************************************
1907 
1908 
1909 
1910 
1911 //=================================================================================================
1912 //
1913 // ISUPPER SPECIALIZATIONS
1914 //
1915 //=================================================================================================
1916 
1917 //*************************************************************************************************
1919 template< typename MT1, typename MT2 >
1920 struct IsUpper< SMatTDMatMultExpr<MT1,MT2> >
1921  : public BoolConstant< And< IsUpper<MT1>, IsUpper<MT2> >::value >
1922 {};
1924 //*************************************************************************************************
1925 
1926 
1927 
1928 
1929 //=================================================================================================
1930 //
1931 // ISUNIUPPER SPECIALIZATIONS
1932 //
1933 //=================================================================================================
1934 
1935 //*************************************************************************************************
1937 template< typename MT1, typename MT2 >
1938 struct IsUniUpper< SMatTDMatMultExpr<MT1,MT2> >
1939  : public BoolConstant< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
1940 {};
1942 //*************************************************************************************************
1943 
1944 
1945 
1946 
1947 //=================================================================================================
1948 //
1949 // ISSTRICTLYUPPER SPECIALIZATIONS
1950 //
1951 //=================================================================================================
1952 
1953 //*************************************************************************************************
1955 template< typename MT1, typename MT2 >
1956 struct IsStrictlyUpper< SMatTDMatMultExpr<MT1,MT2> >
1957  : public BoolConstant< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
1958  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
1959 {};
1961 //*************************************************************************************************
1962 
1963 
1964 
1965 
1966 //=================================================================================================
1967 //
1968 // EXPRESSION TRAIT SPECIALIZATIONS
1969 //
1970 //=================================================================================================
1971 
1972 //*************************************************************************************************
1974 template< typename MT1, typename MT2, typename VT >
1975 struct DMatDVecMultExprTrait< SMatTDMatMultExpr<MT1,MT2>, VT >
1976 {
1977  public:
1978  //**********************************************************************************************
1979  using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
1980  , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
1981  , IsDenseVector<VT>, IsColumnVector<VT> >
1982  , SMatDVecMultExprTrait_< MT1, TDMatDVecMultExprTrait_<MT2,VT> >
1983  , INVALID_TYPE >;
1984  //**********************************************************************************************
1985 };
1987 //*************************************************************************************************
1988 
1989 
1990 //*************************************************************************************************
1992 template< typename MT1, typename MT2, typename VT >
1993 struct DMatSVecMultExprTrait< SMatTDMatMultExpr<MT1,MT2>, VT >
1994 {
1995  public:
1996  //**********************************************************************************************
1997  using Type = If_< And< IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
1998  , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2>
1999  , IsSparseVector<VT>, IsColumnVector<VT> >
2000  , SMatDVecMultExprTrait_< MT1, TDMatSVecMultExprTrait_<MT2,VT> >
2001  , INVALID_TYPE >;
2002  //**********************************************************************************************
2003 };
2005 //*************************************************************************************************
2006 
2007 
2008 //*************************************************************************************************
2010 template< typename VT, typename MT1, typename MT2 >
2011 struct TDVecDMatMultExprTrait< VT, SMatTDMatMultExpr<MT1,MT2> >
2012 {
2013  public:
2014  //**********************************************************************************************
2015  using Type = If_< And< IsDenseVector<VT>, IsRowVector<VT>
2016  , IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
2017  , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
2018  , TDVecTDMatMultExprTrait_< TDVecSMatMultExprTrait_<VT,MT1>, MT2 >
2019  , INVALID_TYPE >;
2020  //**********************************************************************************************
2021 };
2023 //*************************************************************************************************
2024 
2025 
2026 //*************************************************************************************************
2028 template< typename VT, typename MT1, typename MT2 >
2029 struct TSVecDMatMultExprTrait< VT, SMatTDMatMultExpr<MT1,MT2> >
2030 {
2031  public:
2032  //**********************************************************************************************
2033  using Type = If_< And< IsSparseVector<VT>, IsRowVector<VT>
2034  , IsSparseMatrix<MT1>, IsRowMajorMatrix<MT1>
2035  , IsDenseMatrix<MT2>, IsColumnMajorMatrix<MT2> >
2036  , TSVecTDMatMultExprTrait_< TSVecSMatMultExprTrait_<VT,MT1>, MT2 >
2037  , INVALID_TYPE >;
2038  //**********************************************************************************************
2039 };
2041 //*************************************************************************************************
2042 
2043 
2044 //*************************************************************************************************
2046 template< typename MT1, typename MT2, bool AF >
2047 struct SubmatrixExprTrait< SMatTDMatMultExpr<MT1,MT2>, AF >
2048 {
2049  public:
2050  //**********************************************************************************************
2051  using Type = MultExprTrait_< SubmatrixExprTrait_<const MT1,AF>
2052  , SubmatrixExprTrait_<const MT2,AF> >;
2053  //**********************************************************************************************
2054 };
2056 //*************************************************************************************************
2057 
2058 
2059 //*************************************************************************************************
2061 template< typename MT1, typename MT2 >
2062 struct RowExprTrait< SMatTDMatMultExpr<MT1,MT2> >
2063 {
2064  public:
2065  //**********************************************************************************************
2066  using Type = MultExprTrait_< RowExprTrait_<const MT1>, MT2 >;
2067  //**********************************************************************************************
2068 };
2070 //*************************************************************************************************
2071 
2072 
2073 //*************************************************************************************************
2075 template< typename MT1, typename MT2 >
2076 struct ColumnExprTrait< SMatTDMatMultExpr<MT1,MT2> >
2077 {
2078  public:
2079  //**********************************************************************************************
2080  using Type = MultExprTrait_< MT1, ColumnExprTrait_<const MT2> >;
2081  //**********************************************************************************************
2082 };
2084 //*************************************************************************************************
2085 
2086 } // namespace blaze
2087 
2088 #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
const ElementType ReturnType
Return type for expression template evaluations.
Definition: SMatTDMatMultExpr.h:202
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
Header file for the SMatDVecMultExprTrait class template.
TransposeType_< ResultType > TransposeType
Transpose type for expression template evaluations.
Definition: SMatTDMatMultExpr.h:200
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.
IfTrue_< evaluateRight, const RT2, CT2 > RT
Type for the assignment of the right-hand side dense matrix operand.
Definition: SMatTDMatMultExpr.h:215
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: SMatTDMatMultExpr.h:296
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.
If_< IsExpression< MT2 >, const MT2, const MT2 & > RightOperand
Composite type of the right-hand side dense matrix expression.
Definition: SMatTDMatMultExpr.h:209
#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
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: SMatTDMatMultExpr.h:312
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
CompositeType_< MT2 > CT2
Composite type of the right-hand side dense matrix expression.
Definition: SMatTDMatMultExpr.h:139
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:1669
Compile time check for lower triangular matrices.This type trait tests whether or not the given templ...
Definition: IsLower.h:88
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: SMatTDMatMultExpr.h:248
Header file for the TDVecSMatMultExprTrait class template.
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.
ElementType_< RT1 > ET1
Element type of the left-hand side dense matrix expression.
Definition: SMatTDMatMultExpr.h:136
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.
LeftOperand leftOperand() const noexcept
Returns the left-hand side sparse matrix operand.
Definition: SMatTDMatMultExpr.h:332
System settings for performance optimizations.
Header file for the TSVecSMatMultExprTrait class template.
IfTrue_< evaluateLeft, const RT1, CT1 > LT
Type for the assignment of the left-hand side sparse matrix operand.
Definition: SMatTDMatMultExpr.h:212
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
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
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
If_< IsExpression< MT1 >, const MT1, const MT1 & > LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: SMatTDMatMultExpr.h:206
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: SMatTDMatMultExpr.h:393
SMatTDMatMultExpr(const MT1 &lhs, const MT2 &rhs) noexcept
Constructor for the SMatTDMatMultExpr class.
Definition: SMatTDMatMultExpr.h:233
Constraint on the data type.
Constraint on the data type.
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
bool canSMPAssign() const noexcept
Returns whether the expression can be used in SMP assignments.
Definition: SMatTDMatMultExpr.h:386
ElementType_< ResultType > ElementType
Resulting element type.
Definition: SMatTDMatMultExpr.h:201
Header file for the DisableIf class template.
Header file for the multiplication trait.
Header file for the IsStrictlyUpper type trait.
bool canAlias(const T *alias) const noexcept
Returns whether the expression can alias with the given address alias.
Definition: SMatTDMatMultExpr.h:354
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.
#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
Header file for the TSVecTDMatMultExprTrait class template.
ResultType_< MT1 > RT1
Result type of the left-hand side sparse matrix expression.
Definition: SMatTDMatMultExpr.h:134
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2647
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 TDMatSVecMultExprTrait class template.
RightOperand rightOperand() const noexcept
Returns the right-hand side transpose dense matrix operand.
Definition: SMatTDMatMultExpr.h:342
#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.
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
Expression object for sparse matrix-transpose dense matrix multiplications.The SMatTDMatMultExpr clas...
Definition: Forward.h:102
#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.
Constraints on the storage order of matrix types.
ElementType_< RT2 > ET2
Element type of the right-hand side sparse matrix expression.
Definition: SMatTDMatMultExpr.h:137
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
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
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
Header file for the IsSparseVector type trait.
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
MultTrait_< RT1, RT2 > ResultType
Result type for expression template evaluations.
Definition: SMatTDMatMultExpr.h:198
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:83
Utility type for generic codes.
RightOperand rhs_
Right-hand side dense matrix of the multiplication expression.
Definition: SMatTDMatMultExpr.h:394
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
Header file for the reset shim.
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.
Compile time check for strictly lower triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyLower.h:86
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: SMatTDMatMultExpr.h:322
typename T::ConstIterator ConstIterator_
Alias declaration for nested ConstIterator type definitions.The ConstIterator_ alias declaration prov...
Definition: Aliases.h:103
Header file for the IsRowMajorMatrix type trait.
const DMatTransExpr< MT,!SO > trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:950
Header file for the IsComputation type trait class.
Header file for the TDVecDMatMultExprTrait class template.
bool isAligned() const noexcept
Returns whether the operands of the expression are properly aligned in memory.
Definition: SMatTDMatMultExpr.h:376
CompositeType_< MT1 > CT1
Composite type of the left-hand side sparse matrix expression.
Definition: SMatTDMatMultExpr.h:138
Header file for the TDMatDVecMultExprTrait 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.
const ResultType CompositeType
Data type for composite expression templates.
Definition: SMatTDMatMultExpr.h:203
Header file for the TSVecDMatMultExprTrait class template.
SMatTDMatMultExpr< MT1, MT2 > This
Type of this SMatTDMatMultExpr instance.
Definition: SMatTDMatMultExpr.h:197
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.
OppositeType_< ResultType > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: SMatTDMatMultExpr.h:199
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
ResultType_< MT2 > RT2
Result type of the right-hand side dense matrix expression.
Definition: SMatTDMatMultExpr.h:135
#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 TDVecTDMatMultExprTrait class template.
#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
bool isAliased(const T *alias) const noexcept
Returns whether the expression is aliased with the given address alias.
Definition: SMatTDMatMultExpr.h:366
Header file for the IsExpression type trait class.
Header file for the FunctionTrace class.