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 
53 #include <blaze/math/Functions.h>
54 #include <blaze/math/shims/Reset.h>
96 #include <blaze/util/Assert.h>
97 #include <blaze/util/DisableIf.h>
98 #include <blaze/util/EnableIf.h>
99 #include <blaze/util/Exception.h>
100 #include <blaze/util/InvalidType.h>
102 #include <blaze/util/mpl/And.h>
103 #include <blaze/util/mpl/Or.h>
104 #include <blaze/util/SelectType.h>
105 #include <blaze/util/Types.h>
108 
109 
110 namespace blaze {
111 
112 //=================================================================================================
113 //
114 // CLASS SMATTDMATMULTEXPR
115 //
116 //=================================================================================================
117 
118 //*************************************************************************************************
125 template< typename MT1 // Type of the left-hand side sparse matrix
126  , typename MT2 > // Type of the right-hand side dense matrix
127 class SMatTDMatMultExpr : public DenseMatrix< SMatTDMatMultExpr<MT1,MT2>, false >
128  , private MatMatMultExpr
129  , private Computation
130 {
131  private:
132  //**Type definitions****************************************************************************
133  typedef typename MT1::ResultType RT1;
134  typedef typename MT2::ResultType RT2;
135  typedef typename RT1::ElementType ET1;
136  typedef typename RT2::ElementType ET2;
137  typedef typename MT1::CompositeType CT1;
138  typedef typename MT2::CompositeType CT2;
139  //**********************************************************************************************
140 
141  //**********************************************************************************************
144  //**********************************************************************************************
145 
146  //**********************************************************************************************
148  enum { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
149  //**********************************************************************************************
150 
151  //**********************************************************************************************
153 
158  template< typename T1, typename T2, typename T3 >
159  struct CanExploitSymmetry {
160  enum { value = IsSymmetric<T3>::value };
161  };
163  //**********************************************************************************************
164 
165  //**********************************************************************************************
167 
171  template< typename T1, typename T2, typename T3 >
172  struct IsEvaluationRequired {
173  enum { 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 { value = useOptimizedKernels &&
187  !IsDiagonal<T3>::value &&
188  !IsResizable<typename T1::ElementType>::value &&
189  !IsResizable<ET1>::value };
190  };
192  //**********************************************************************************************
193 
194  public:
195  //**Type definitions****************************************************************************
201  typedef const ElementType ReturnType;
202  typedef const ResultType CompositeType;
203 
205  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
206 
208  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
209 
212 
215  //**********************************************************************************************
216 
217  //**Compilation flags***************************************************************************
219  enum { vectorizable = 0 };
220 
222  enum { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
223  !evaluateRight && MT2::smpAssignable };
224  //**********************************************************************************************
225 
226  //**Constructor*********************************************************************************
232  explicit inline SMatTDMatMultExpr( const MT1& lhs, const MT2& rhs )
233  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
234  , rhs_( rhs ) // Right-hand side dense 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 
252 
253  ElementType tmp = ElementType();
254 
255  // Early exit
256  if( lhs_.columns() == 0UL )
257  return tmp;
258 
259  // Fast computation in case the left-hand side sparse matrix directly provides iterators
261  {
262  CT1 A( lhs_ ); // Evaluation of the left-hand side sparse matrix operand
263 
264  const ConstIterator end( ( IsUpper<MT2>::value )
265  ?( IsStrictlyUpper<MT2>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
266  :( A.end(i) ) );
267  ConstIterator element( ( IsLower<MT2>::value )
268  ?( IsStrictlyLower<MT2>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
269  :( A.begin(i) ) );
270 
271  if( element != end ) {
272  tmp = element->value() * rhs_(element->index(),j);
273  ++element;
274  for( ; element!=end; ++element ) {
275  tmp += element->value() * rhs_(element->index(),j);
276  }
277  }
278  }
279 
280  // Default computation in case the left-hand side sparse matrix doesn't provide iterators
281  else
282  {
283  const size_t kbegin( ( IsUpper<MT1>::value )
284  ?( ( IsLower<MT2>::value )
285  ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
286  , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
287  :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
288  :( ( IsLower<MT2>::value )
289  ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
290  :( 0UL ) ) );
291  const size_t kend( ( IsLower<MT1>::value )
292  ?( ( IsUpper<MT2>::value )
293  ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
294  , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
295  :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
296  :( ( IsUpper<MT2>::value )
297  ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
298  :( lhs_.columns() ) ) );
299 
300  if( ( !IsTriangular<MT1>::value && !IsTriangular<MT2>::value ) || kbegin < kend ) {
301  tmp = lhs_(i,kbegin) * rhs_(kbegin,j);
302  for( size_t k=kbegin+1UL; k<kend; ++k ) {
303  tmp += lhs_(i,k) * rhs_(k,j);
304  }
305  }
306  }
307 
308  return tmp;
309  }
310  //**********************************************************************************************
311 
312  //**At function*********************************************************************************
320  inline ReturnType at( size_t i, size_t j ) const {
321  if( i >= lhs_.rows() ) {
322  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
323  }
324  if( j >= rhs_.columns() ) {
325  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
326  }
327  return (*this)(i,j);
328  }
329  //**********************************************************************************************
330 
331  //**Rows function*******************************************************************************
336  inline size_t rows() const {
337  return lhs_.rows();
338  }
339  //**********************************************************************************************
340 
341  //**Columns function****************************************************************************
346  inline size_t columns() const {
347  return rhs_.columns();
348  }
349  //**********************************************************************************************
350 
351  //**Left operand access*************************************************************************
356  inline LeftOperand leftOperand() const {
357  return lhs_;
358  }
359  //**********************************************************************************************
360 
361  //**Right operand access************************************************************************
366  inline RightOperand rightOperand() const {
367  return rhs_;
368  }
369  //**********************************************************************************************
370 
371  //**********************************************************************************************
377  template< typename T >
378  inline bool canAlias( const T* alias ) const {
379  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
380  }
381  //**********************************************************************************************
382 
383  //**********************************************************************************************
389  template< typename T >
390  inline bool isAliased( const T* alias ) const {
391  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
392  }
393  //**********************************************************************************************
394 
395  //**********************************************************************************************
400  inline bool isAligned() const {
401  return rhs_.isAligned();
402  }
403  //**********************************************************************************************
404 
405  //**********************************************************************************************
410  inline bool canSMPAssign() const {
411  return ( rows() > SMP_SMATTDMATMULT_THRESHOLD );
412  }
413  //**********************************************************************************************
414 
415  private:
416  //**Member variables****************************************************************************
417  LeftOperand lhs_;
418  RightOperand rhs_;
419  //**********************************************************************************************
420 
421  //**Assignment to dense matrices****************************************************************
434  template< typename MT // Type of the target dense matrix
435  , bool SO > // Storage order of the target dense matrix
436  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
437  assign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
438  {
440 
441  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
442  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
443 
444  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
445  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
446 
447  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
448  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
449  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
450  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
451  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
452  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
453 
454  SMatTDMatMultExpr::selectAssignKernel( ~lhs, A, B );
455  }
457  //**********************************************************************************************
458 
459  //**Default assignment to dense matrices********************************************************
473  template< typename MT3 // Type of the left-hand side target matrix
474  , typename MT4 // Type of the left-hand side matrix operand
475  , typename MT5 > // Type of the right-hand side matrix operand
476  static inline typename DisableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
477  selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
478  {
479  typedef typename MT4::ConstIterator ConstIterator;
480 
481  const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 256UL );
482 
483  for( size_t ii=0UL; ii<A.rows(); ii+=block )
484  {
485  const size_t iend( min( ii+block, A.rows() ) );
486 
487  size_t j( 0UL );
488 
489  for( ; (j+4UL) <= B.columns(); j+=4UL ) {
490  for( size_t i=ii; i<iend; ++i )
491  {
492  const ConstIterator end( ( IsUpper<MT5>::value )
493  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
494  :( A.end(i) ) );
495  ConstIterator element( ( IsLower<MT5>::value )
496  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
497  :( A.begin(i) ) );
498 
499  if( element == end ) {
500  reset( C(i,j ) );
501  reset( C(i,j+1UL) );
502  reset( C(i,j+2UL) );
503  reset( C(i,j+3UL) );
504  continue;
505  }
506 
507  C(i,j ) = element->value() * B(element->index(),j );
508  C(i,j+1UL) = element->value() * B(element->index(),j+1UL);
509  C(i,j+2UL) = element->value() * B(element->index(),j+2UL);
510  C(i,j+3UL) = element->value() * B(element->index(),j+3UL);
511  ++element;
512  for( ; element!=end; ++element ) {
513  C(i,j ) += element->value() * B(element->index(),j );
514  C(i,j+1UL) += element->value() * B(element->index(),j+1UL);
515  C(i,j+2UL) += element->value() * B(element->index(),j+2UL);
516  C(i,j+3UL) += element->value() * B(element->index(),j+3UL);
517  }
518  }
519  }
520 
521  for( ; (j+2UL) <= B.columns(); j+=2UL ) {
522  for( size_t i=ii; i<iend; ++i )
523  {
524  const ConstIterator end( ( IsUpper<MT5>::value )
525  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
526  :( A.end(i) ) );
527  ConstIterator element( ( IsLower<MT5>::value )
528  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
529  :( A.begin(i) ) );
530 
531  if( element == end ) {
532  reset( C(i,j ) );
533  reset( C(i,j+1UL) );
534  continue;
535  }
536 
537  C(i,j ) = element->value() * B(element->index(),j );
538  C(i,j+1UL) = element->value() * B(element->index(),j+1UL);
539  ++element;
540  for( ; element!=end; ++element ) {
541  C(i,j ) += element->value() * B(element->index(),j );
542  C(i,j+1UL) += element->value() * B(element->index(),j+1UL);
543  }
544  }
545  }
546 
547  for( ; j<B.columns(); ++j ) {
548  for( size_t i=ii; i<iend; ++i )
549  {
550  const ConstIterator end( ( IsUpper<MT5>::value )
551  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
552  :( A.end(i) ) );
553  ConstIterator element( ( IsLower<MT5>::value )
554  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
555  :( A.begin(i) ) );
556 
557  if( element == end ) {
558  reset( C(i,j) );
559  continue;
560  }
561 
562  C(i,j) = element->value() * B(element->index(),j);
563  ++element;
564  for( ; element!=end; ++element ) {
565  C(i,j) += element->value() * B(element->index(),j);
566  }
567  }
568  }
569  }
570  }
572  //**********************************************************************************************
573 
574  //**Optimized assignment to dense matrices******************************************************
588  template< typename MT3 // Type of the left-hand side target matrix
589  , typename MT4 // Type of the left-hand side matrix operand
590  , typename MT5 > // Type of the right-hand side matrix operand
591  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
592  selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
593  {
594  typedef typename MT4::ConstIterator ConstIterator;
595 
596  const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 256UL );
597 
598  reset( C );
599 
600  for( size_t ii=0UL; ii<A.rows(); ii+=block )
601  {
602  const size_t iend( min( ii+block, A.rows() ) );
603 
604  size_t j( 0UL );
605 
606  for( ; (j+4UL) <= B.columns(); j+=4UL ) {
607  for( size_t i=ii; i<iend; ++i )
608  {
609  const ConstIterator end( ( IsUpper<MT5>::value )
610  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
611  :( A.end(i) ) );
612  ConstIterator element( ( IsLower<MT5>::value )
613  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
614  :( A.begin(i) ) );
615 
616  const size_t nonzeros( end - element );
617  const size_t kpos( nonzeros & size_t(-4) );
618  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
619 
620  for( size_t k=0UL; k<kpos; k+=4UL )
621  {
622  const size_t i1( element->index() );
623  const ET1 v1( element->value() );
624  ++element;
625  const size_t i2( element->index() );
626  const ET1 v2( element->value() );
627  ++element;
628  const size_t i3( element->index() );
629  const ET1 v3( element->value() );
630  ++element;
631  const size_t i4( element->index() );
632  const ET1 v4( element->value() );
633  ++element;
634 
635  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
636 
637  C(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
638  C(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
639  C(i,j+2UL) += v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
640  C(i,j+3UL) += v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
641  }
642 
643  for( ; element!=end; ++element )
644  {
645  const size_t i1( element->index() );
646  const ET1 v1( element->value() );
647 
648  C(i,j ) += v1 * B(i1,j );
649  C(i,j+1UL) += v1 * B(i1,j+1UL);
650  C(i,j+2UL) += v1 * B(i1,j+2UL);
651  C(i,j+3UL) += v1 * B(i1,j+3UL);
652  }
653  }
654  }
655 
656  for( ; (j+2UL) <= B.columns(); j+=2UL ) {
657  for( size_t i=ii; i<iend; ++i )
658  {
659  const ConstIterator end( ( IsUpper<MT5>::value )
660  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
661  :( A.end(i) ) );
662  ConstIterator element( ( IsLower<MT5>::value )
663  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
664  :( A.begin(i) ) );
665 
666  const size_t nonzeros( end - element );
667  const size_t kpos( nonzeros & size_t(-4) );
668  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
669 
670  for( size_t k=0UL; k<kpos; k+=4UL )
671  {
672  const size_t i1( element->index() );
673  const ET1 v1( element->value() );
674  ++element;
675  const size_t i2( element->index() );
676  const ET1 v2( element->value() );
677  ++element;
678  const size_t i3( element->index() );
679  const ET1 v3( element->value() );
680  ++element;
681  const size_t i4( element->index() );
682  const ET1 v4( element->value() );
683  ++element;
684 
685  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
686 
687  C(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
688  C(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
689  }
690 
691  for( ; element!=end; ++element )
692  {
693  const size_t i1( element->index() );
694  const ET1 v1( element->value() );
695 
696  C(i,j ) += v1 * B(i1,j );
697  C(i,j+1UL) += v1 * B(i1,j+1UL);
698  }
699  }
700  }
701 
702  for( ; j<B.columns(); ++j ) {
703  for( size_t i=ii; i<iend; ++i )
704  {
705  const ConstIterator end( ( IsUpper<MT5>::value )
706  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
707  :( A.end(i) ) );
708  ConstIterator element( ( IsLower<MT5>::value )
709  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
710  :( A.begin(i) ) );
711 
712  const size_t nonzeros( end - element );
713  const size_t kpos( nonzeros & size_t(-4) );
714  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
715 
716  for( size_t k=0UL; k<kpos; k+=4UL )
717  {
718  const size_t i1( element->index() );
719  const ET1 v1( element->value() );
720  ++element;
721  const size_t i2( element->index() );
722  const ET1 v2( element->value() );
723  ++element;
724  const size_t i3( element->index() );
725  const ET1 v3( element->value() );
726  ++element;
727  const size_t i4( element->index() );
728  const ET1 v4( element->value() );
729  ++element;
730 
731  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
732 
733  C(i,j) += v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
734  }
735 
736  for( ; element!=end; ++element )
737  {
738  const size_t i1( element->index() );
739  const ET1 v1( element->value() );
740 
741  C(i,j) += v1 * B(i1,j);
742  }
743  }
744  }
745  }
746  }
748  //**********************************************************************************************
749 
750  //**Assignment to sparse matrices***************************************************************
763  template< typename MT // Type of the target sparse matrix
764  , bool SO > // Storage order of the target sparse matrix
765  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
766  assign( SparseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
767  {
769 
770  typedef typename SelectType< SO, OppositeType, ResultType >::Type TmpType;
771 
778 
779  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
780  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
781 
782  const TmpType tmp( serial( rhs ) );
783  assign( ~lhs, tmp );
784  }
786  //**********************************************************************************************
787 
788  //**Restructuring assignment********************************************************************
803  template< typename MT // Type of the target matrix
804  , bool SO > // Storage order of the target matrix
805  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
806  assign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
807  {
809 
810  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
811  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
812 
813  assign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
814  }
816  //**********************************************************************************************
817 
818  //**Addition assignment to dense matrices*******************************************************
831  template< typename MT // Type of the target dense matrix
832  , bool SO > // Storage order of the target dense matrix
833  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
834  addAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
835  {
837 
838  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
839  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
840 
841  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
842  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
843 
844  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
845  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
846  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
847  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
848  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
849  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
850 
851  SMatTDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
852  }
854  //**********************************************************************************************
855 
856  //**Default addition assignment to dense matrices***********************************************
870  template< typename MT3 // Type of the left-hand side target matrix
871  , typename MT4 // Type of the left-hand side matrix operand
872  , typename MT5 > // Type of the right-hand side matrix operand
873  static inline typename DisableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
874  selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
875  {
876  typedef typename MT4::ConstIterator ConstIterator;
877 
878  const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 256UL );
879 
880  for( size_t ii=0UL; ii<A.rows(); ii+=block )
881  {
882  const size_t iend( min( ii+block, A.rows() ) );
883 
884  size_t j( 0UL );
885 
886  for( ; (j+4UL) <= B.columns(); j+=4UL ) {
887  for( size_t i=ii; i<iend; ++i )
888  {
889  const ConstIterator end( ( IsUpper<MT5>::value )
890  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
891  :( A.end(i) ) );
892  ConstIterator element( ( IsLower<MT5>::value )
893  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
894  :( A.begin(i) ) );
895 
896  for( ; element!=end; ++element ) {
897  C(i,j ) += element->value() * B(element->index(),j );
898  C(i,j+1UL) += element->value() * B(element->index(),j+1UL);
899  C(i,j+2UL) += element->value() * B(element->index(),j+2UL);
900  C(i,j+3UL) += element->value() * B(element->index(),j+3UL);
901  }
902  }
903  }
904 
905  for( ; (j+2UL) <= B.columns(); j+=2UL ) {
906  for( size_t i=ii; i<iend; ++i )
907  {
908  const ConstIterator end( ( IsUpper<MT5>::value )
909  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
910  :( A.end(i) ) );
911  ConstIterator element( ( IsLower<MT5>::value )
912  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
913  :( A.begin(i) ) );
914 
915  for( ; element!=end; ++element ) {
916  C(i,j ) += element->value() * B(element->index(),j );
917  C(i,j+1UL) += element->value() * B(element->index(),j+1UL);
918  }
919  }
920  }
921 
922  for( ; j<B.columns(); ++j ) {
923  for( size_t i=ii; i<iend; ++i )
924  {
925  const ConstIterator end( ( IsUpper<MT5>::value )
926  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
927  :( A.end(i) ) );
928  ConstIterator element( ( IsLower<MT5>::value )
929  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
930  :( A.begin(i) ) );
931 
932  for( ; element!=end; ++element ) {
933  C(i,j) += element->value() * B(element->index(),j);
934  }
935  }
936  }
937  }
938  }
940  //**********************************************************************************************
941 
942  //**Optimized addition assignment to dense matrices*********************************************
956  template< typename MT3 // Type of the left-hand side target matrix
957  , typename MT4 // Type of the left-hand side matrix operand
958  , typename MT5 > // Type of the right-hand side matrix operand
959  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
960  selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
961  {
962  typedef typename MT4::ConstIterator ConstIterator;
963 
964  const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 256UL );
965 
966  for( size_t ii=0UL; ii<A.rows(); ii+=block )
967  {
968  const size_t iend( min( ii+block, A.rows() ) );
969 
970  size_t j( 0UL );
971 
972  for( ; (j+4UL) <= B.columns(); j+=4UL ) {
973  for( size_t i=ii; i<iend; ++i )
974  {
975  const ConstIterator end( ( IsUpper<MT5>::value )
976  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
977  :( A.end(i) ) );
978  ConstIterator element( ( IsLower<MT5>::value )
979  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
980  :( A.begin(i) ) );
981 
982  const size_t nonzeros( end - element );
983  const size_t kpos( nonzeros & size_t(-4) );
984  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
985 
986  for( size_t k=0UL; k<kpos; k+=4UL )
987  {
988  const size_t i1( element->index() );
989  const ET1 v1( element->value() );
990  ++element;
991  const size_t i2( element->index() );
992  const ET1 v2( element->value() );
993  ++element;
994  const size_t i3( element->index() );
995  const ET1 v3( element->value() );
996  ++element;
997  const size_t i4( element->index() );
998  const ET1 v4( element->value() );
999  ++element;
1000 
1001  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1002 
1003  C(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
1004  C(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
1005  C(i,j+2UL) += v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
1006  C(i,j+3UL) += v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
1007  }
1008 
1009  for( ; element!=end; ++element )
1010  {
1011  const size_t i1( element->index() );
1012  const ET1 v1( element->value() );
1013 
1014  C(i,j ) += v1 * B(i1,j );
1015  C(i,j+1UL) += v1 * B(i1,j+1UL);
1016  C(i,j+2UL) += v1 * B(i1,j+2UL);
1017  C(i,j+3UL) += v1 * B(i1,j+3UL);
1018  }
1019  }
1020  }
1021 
1022  for( ; (j+2UL) <= B.columns(); j+=2UL ) {
1023  for( size_t i=ii; i<iend; ++i )
1024  {
1025  const ConstIterator end( ( IsUpper<MT5>::value )
1026  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
1027  :( A.end(i) ) );
1028  ConstIterator element( ( IsLower<MT5>::value )
1029  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1030  :( A.begin(i) ) );
1031 
1032  const size_t nonzeros( end - element );
1033  const size_t kpos( nonzeros & size_t(-4) );
1034  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1035 
1036  for( size_t k=0UL; k<kpos; k+=4UL )
1037  {
1038  const size_t i1( element->index() );
1039  const ET1 v1( element->value() );
1040  ++element;
1041  const size_t i2( element->index() );
1042  const ET1 v2( element->value() );
1043  ++element;
1044  const size_t i3( element->index() );
1045  const ET1 v3( element->value() );
1046  ++element;
1047  const size_t i4( element->index() );
1048  const ET1 v4( element->value() );
1049  ++element;
1050 
1051  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1052 
1053  C(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
1054  C(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
1055  }
1056 
1057  for( ; element!=end; ++element )
1058  {
1059  const size_t i1( element->index() );
1060  const ET1 v1( element->value() );
1061 
1062  C(i,j ) += v1 * B(i1,j );
1063  C(i,j+1UL) += v1 * B(i1,j+1UL);
1064  }
1065  }
1066  }
1067 
1068  for( ; j<B.columns(); ++j ) {
1069  for( size_t i=ii; i<iend; ++i )
1070  {
1071  const ConstIterator end( ( IsUpper<MT5>::value )
1072  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
1073  :( A.end(i) ) );
1074  ConstIterator element( ( IsLower<MT5>::value )
1075  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1076  :( A.begin(i) ) );
1077 
1078  const size_t nonzeros( end - element );
1079  const size_t kpos( nonzeros & size_t(-4) );
1080  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1081 
1082  for( size_t k=0UL; k<kpos; k+=4UL )
1083  {
1084  const size_t i1( element->index() );
1085  const ET1 v1( element->value() );
1086  ++element;
1087  const size_t i2( element->index() );
1088  const ET1 v2( element->value() );
1089  ++element;
1090  const size_t i3( element->index() );
1091  const ET1 v3( element->value() );
1092  ++element;
1093  const size_t i4( element->index() );
1094  const ET1 v4( element->value() );
1095  ++element;
1096 
1097  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1098 
1099  C(i,j) += v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
1100  }
1101 
1102  for( ; element!=end; ++element )
1103  {
1104  const size_t i1( element->index() );
1105  const ET1 v1( element->value() );
1106 
1107  C(i,j) += v1 * B(i1,j);
1108  }
1109  }
1110  }
1111  }
1112  }
1114  //**********************************************************************************************
1115 
1116  //**Restructuring addition assignment***********************************************************
1131  template< typename MT // Type of the target matrix
1132  , bool SO > // Storage order of the target matrix
1133  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1134  addAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1135  {
1137 
1138  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1139  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1140 
1141  addAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1142  }
1144  //**********************************************************************************************
1145 
1146  //**Addition assignment to sparse matrices******************************************************
1147  // No special implementation for the addition assignment to sparse matrices.
1148  //**********************************************************************************************
1149 
1150  //**Subtraction assignment to dense matrices****************************************************
1163  template< typename MT // Type of the target dense matrix
1164  , bool SO > // Storage order of the target dense matrix
1165  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1166  subAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1167  {
1169 
1170  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1171  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1172 
1173  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
1174  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
1175 
1176  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1177  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1178  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1179  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1180  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1181  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1182 
1183  SMatTDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1184  }
1186  //**********************************************************************************************
1187 
1188  //**Default subtraction assignment to dense matrices********************************************
1202  template< typename MT3 // Type of the left-hand side target matrix
1203  , typename MT4 // Type of the left-hand side matrix operand
1204  , typename MT5 > // Type of the right-hand side matrix operand
1205  static inline typename DisableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
1206  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1207  {
1208  typedef typename MT4::ConstIterator ConstIterator;
1209 
1210  const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 256UL );
1211 
1212  for( size_t ii=0UL; ii<A.rows(); ii+=block )
1213  {
1214  const size_t iend( min( ii+block, A.rows() ) );
1215 
1216  size_t j( 0UL );
1217 
1218  for( ; (j+4UL) <= B.columns(); j+=4UL ) {
1219  for( size_t i=ii; i<iend; ++i )
1220  {
1221  const ConstIterator end( ( IsUpper<MT5>::value )
1222  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
1223  :( A.end(i) ) );
1224  ConstIterator element( ( IsLower<MT5>::value )
1225  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1226  :( A.begin(i) ) );
1227 
1228  for( ; element!=end; ++element ) {
1229  C(i,j ) -= element->value() * B(element->index(),j );
1230  C(i,j+1UL) -= element->value() * B(element->index(),j+1UL);
1231  C(i,j+2UL) -= element->value() * B(element->index(),j+2UL);
1232  C(i,j+3UL) -= element->value() * B(element->index(),j+3UL);
1233  }
1234  }
1235  }
1236 
1237  for( ; (j+2UL) <= B.columns(); j+=2UL ) {
1238  for( size_t i=ii; i<iend; ++i )
1239  {
1240  const ConstIterator end( ( IsUpper<MT5>::value )
1241  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
1242  :( A.end(i) ) );
1243  ConstIterator element( ( IsLower<MT5>::value )
1244  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1245  :( A.begin(i) ) );
1246 
1247  for( ; element!=end; ++element ) {
1248  C(i,j ) -= element->value() * B(element->index(),j );
1249  C(i,j+1UL) -= element->value() * B(element->index(),j+1UL);
1250  }
1251  }
1252  }
1253 
1254  for( ; j<B.columns(); ++j ) {
1255  for( size_t i=ii; i<iend; ++i )
1256  {
1257  const ConstIterator end( ( IsUpper<MT5>::value )
1258  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
1259  :( A.end(i) ) );
1260  ConstIterator element( ( IsLower<MT5>::value )
1261  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1262  :( A.begin(i) ) );
1263 
1264  for( ; element!=end; ++element ) {
1265  C(i,j) -= element->value() * B(element->index(),j);
1266  }
1267  }
1268  }
1269  }
1270  }
1272  //**********************************************************************************************
1273 
1274  //**Optimized subtraction assignment to dense matrices******************************************
1288  template< typename MT3 // Type of the left-hand side target matrix
1289  , typename MT4 // Type of the left-hand side matrix operand
1290  , typename MT5 > // Type of the right-hand side matrix operand
1291  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
1292  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1293  {
1294  typedef typename MT4::ConstIterator ConstIterator;
1295 
1296  const size_t block( IsColumnMajorMatrix<MT3>::value ? A.rows() : 256UL );
1297 
1298  for( size_t ii=0UL; ii<A.rows(); ii+=block )
1299  {
1300  const size_t iend( min( ii+block, A.rows() ) );
1301 
1302  size_t j( 0UL );
1303 
1304  for( ; (j+4UL) <= B.columns(); j+=4UL ) {
1305  for( size_t i=ii; i<iend; ++i )
1306  {
1307  const ConstIterator end( ( IsUpper<MT5>::value )
1308  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) )
1309  :( A.end(i) ) );
1310  ConstIterator element( ( IsLower<MT5>::value )
1311  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1312  :( A.begin(i) ) );
1313 
1314  const size_t nonzeros( end - element );
1315  const size_t kpos( nonzeros & size_t(-4) );
1316  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1317 
1318  for( size_t k=0UL; k<kpos; k+=4UL )
1319  {
1320  const size_t i1( element->index() );
1321  const ET1 v1( element->value() );
1322  ++element;
1323  const size_t i2( element->index() );
1324  const ET1 v2( element->value() );
1325  ++element;
1326  const size_t i3( element->index() );
1327  const ET1 v3( element->value() );
1328  ++element;
1329  const size_t i4( element->index() );
1330  const ET1 v4( element->value() );
1331  ++element;
1332 
1333  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1334 
1335  C(i,j ) -= v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
1336  C(i,j+1UL) -= v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
1337  C(i,j+2UL) -= v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
1338  C(i,j+3UL) -= v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
1339  }
1340 
1341  for( ; element!=end; ++element )
1342  {
1343  const size_t i1( element->index() );
1344  const ET1 v1( element->value() );
1345 
1346  C(i,j ) -= v1 * B(i1,j );
1347  C(i,j+1UL) -= v1 * B(i1,j+1UL);
1348  C(i,j+2UL) -= v1 * B(i1,j+2UL);
1349  C(i,j+3UL) -= v1 * B(i1,j+3UL);
1350  }
1351  }
1352  }
1353 
1354  for( ; (j+2UL) <= B.columns(); j+=2UL ) {
1355  for( size_t i=ii; i<iend; ++i )
1356  {
1357  const ConstIterator end( ( IsUpper<MT5>::value )
1358  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) )
1359  :( A.end(i) ) );
1360  ConstIterator element( ( IsLower<MT5>::value )
1361  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1362  :( A.begin(i) ) );
1363 
1364  const size_t nonzeros( end - element );
1365  const size_t kpos( nonzeros & size_t(-4) );
1366  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1367 
1368  for( size_t k=0UL; k<kpos; k+=4UL )
1369  {
1370  const size_t i1( element->index() );
1371  const ET1 v1( element->value() );
1372  ++element;
1373  const size_t i2( element->index() );
1374  const ET1 v2( element->value() );
1375  ++element;
1376  const size_t i3( element->index() );
1377  const ET1 v3( element->value() );
1378  ++element;
1379  const size_t i4( element->index() );
1380  const ET1 v4( element->value() );
1381  ++element;
1382 
1383  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1384 
1385  C(i,j ) -= v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
1386  C(i,j+1UL) -= v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
1387  }
1388 
1389  for( ; element!=end; ++element )
1390  {
1391  const size_t i1( element->index() );
1392  const ET1 v1( element->value() );
1393 
1394  C(i,j ) -= v1 * B(i1,j );
1395  C(i,j+1UL) -= v1 * B(i1,j+1UL);
1396  }
1397  }
1398  }
1399 
1400  for( ; j<B.columns(); ++j ) {
1401  for( size_t i=ii; i<iend; ++i )
1402  {
1403  const ConstIterator end( ( IsUpper<MT5>::value )
1404  ?( IsStrictlyUpper<MT5>::value ? A.lowerBound(i,j) : A.upperBound(i,j) )
1405  :( A.end(i) ) );
1406  ConstIterator element( ( IsLower<MT5>::value )
1407  ?( IsStrictlyLower<MT5>::value ? A.upperBound(i,j) : A.lowerBound(i,j) )
1408  :( A.begin(i) ) );
1409 
1410  const size_t nonzeros( end - element );
1411  const size_t kpos( nonzeros & size_t(-4) );
1412  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1413 
1414  for( size_t k=0UL; k<kpos; k+=4UL )
1415  {
1416  const size_t i1( element->index() );
1417  const ET1 v1( element->value() );
1418  ++element;
1419  const size_t i2( element->index() );
1420  const ET1 v2( element->value() );
1421  ++element;
1422  const size_t i3( element->index() );
1423  const ET1 v3( element->value() );
1424  ++element;
1425  const size_t i4( element->index() );
1426  const ET1 v4( element->value() );
1427  ++element;
1428 
1429  BLAZE_INTERNAL_ASSERT( i1 < i2 && i2 < i3 && i3 < i4, "Invalid sparse matrix index detected" );
1430 
1431  C(i,j) -= v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
1432  }
1433 
1434  for( ; element!=end; ++element )
1435  {
1436  const size_t i1( element->index() );
1437  const ET1 v1( element->value() );
1438 
1439  C(i,j) -= v1 * B(i1,j);
1440  }
1441  }
1442  }
1443  }
1444  }
1446  //**********************************************************************************************
1447 
1448  //**Restructuring subtraction assignment********************************************************
1463  template< typename MT // Type of the target matrix
1464  , bool SO > // Storage order of the target matrix
1465  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1466  subAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1467  {
1469 
1470  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1471  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1472 
1473  subAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1474  }
1476  //**********************************************************************************************
1477 
1478  //**Subtraction assignment to sparse matrices***************************************************
1479  // No special implementation for the subtraction assignment to sparse matrices.
1480  //**********************************************************************************************
1481 
1482  //**Multiplication assignment to dense matrices*************************************************
1483  // No special implementation for the multiplication assignment to dense matrices.
1484  //**********************************************************************************************
1485 
1486  //**Multiplication assignment to sparse matrices************************************************
1487  // No special implementation for the multiplication assignment to sparse matrices.
1488  //**********************************************************************************************
1489 
1490  //**SMP assignment to dense matrices************************************************************
1505  template< typename MT // Type of the target dense matrix
1506  , bool SO > // Storage order of the target dense matrix
1507  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1508  smpAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1509  {
1511 
1512  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1513  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1514 
1515  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
1516  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
1517 
1518  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1519  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1520  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1521  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1522  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1523  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1524 
1525  smpAssign( ~lhs, A * B );
1526  }
1528  //**********************************************************************************************
1529 
1530  //**SMP assignment to sparse matrices***********************************************************
1545  template< typename MT // Type of the target sparse matrix
1546  , bool SO > // Storage order of the target sparse matrix
1547  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1548  smpAssign( SparseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1549  {
1551 
1552  typedef typename SelectType< SO, OppositeType, ResultType >::Type TmpType;
1553 
1560 
1561  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1562  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1563 
1564  const TmpType tmp( rhs );
1565  smpAssign( ~lhs, tmp );
1566  }
1568  //**********************************************************************************************
1569 
1570  //**Restructuring SMP assignment****************************************************************
1585  template< typename MT // Type of the target matrix
1586  , bool SO > // Storage order of the target matrix
1587  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1588  smpAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1589  {
1591 
1592  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1593  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1594 
1595  smpAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1596  }
1598  //**********************************************************************************************
1599 
1600  //**SMP addition assignment to dense matrices***************************************************
1616  template< typename MT // Type of the target dense matrix
1617  , bool SO > // Storage order of the target dense matrix
1618  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1619  smpAddAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1620  {
1622 
1623  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1624  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1625 
1626  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
1627  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
1628 
1629  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1630  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1631  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1632  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1633  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1634  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1635 
1636  smpAddAssign( ~lhs, A * B );
1637  }
1639  //**********************************************************************************************
1640 
1641  //**Restructuring SMP addition assignment*******************************************************
1656  template< typename MT // Type of the target matrix
1657  , bool SO > // Storage order of the target matrix
1658  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1659  smpAddAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& 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  smpAddAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1667  }
1669  //**********************************************************************************************
1670 
1671  //**SMP addition assignment to sparse matrices**************************************************
1672  // No special implementation for the SMP addition assignment to sparse matrices.
1673  //**********************************************************************************************
1674 
1675  //**SMP subtraction assignment to dense matrices************************************************
1691  template< typename MT // Type of the target dense matrix
1692  , bool SO > // Storage order of the target dense matrix
1693  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1694  smpSubAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1695  {
1697 
1698  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1699  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1700 
1701  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
1702  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
1703 
1704  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1705  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1706  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1707  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1708  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1709  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1710 
1711  smpSubAssign( ~lhs, A * B );
1712  }
1714  //**********************************************************************************************
1715 
1716  //**Restructuring SMP subtraction assignment****************************************************
1731  template< typename MT // Type of the target matrix
1732  , bool SO > // Storage order of the target matrix
1733  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1734  smpSubAssign( Matrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
1735  {
1737 
1738  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1739  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1740 
1741  smpSubAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1742  }
1744  //**********************************************************************************************
1745 
1746  //**SMP subtraction assignment to sparse matrices***********************************************
1747  // No special implementation for the SMP subtraction assignment to sparse matrices.
1748  //**********************************************************************************************
1749 
1750  //**SMP multiplication assignment to dense matrices*********************************************
1751  // No special implementation for the SMP multiplication assignment to dense matrices.
1752  //**********************************************************************************************
1753 
1754  //**SMP multiplication assignment to sparse matrices********************************************
1755  // No special implementation for the SMP multiplication assignment to sparse matrices.
1756  //**********************************************************************************************
1757 
1758  //**Compile time checks*************************************************************************
1766  //**********************************************************************************************
1767 };
1768 //*************************************************************************************************
1769 
1770 
1771 
1772 
1773 //=================================================================================================
1774 //
1775 // GLOBAL BINARY ARITHMETIC OPERATORS
1776 //
1777 //=================================================================================================
1778 
1779 //*************************************************************************************************
1810 template< typename T1 // Type of the left-hand side sparse matrix
1811  , typename T2 > // Type of the right-hand side dense matrix
1812 inline const SMatTDMatMultExpr<T1,T2>
1814 {
1816 
1817  if( (~lhs).columns() != (~rhs).rows() ) {
1818  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1819  }
1820 
1821  return SMatTDMatMultExpr<T1,T2>( ~lhs, ~rhs );
1822 }
1823 //*************************************************************************************************
1824 
1825 
1826 
1827 
1828 //=================================================================================================
1829 //
1830 // ROWS SPECIALIZATIONS
1831 //
1832 //=================================================================================================
1833 
1834 //*************************************************************************************************
1836 template< typename MT1, typename MT2 >
1837 struct Rows< SMatTDMatMultExpr<MT1,MT2> > : public Rows<MT1>
1838 {};
1840 //*************************************************************************************************
1841 
1842 
1843 
1844 
1845 //=================================================================================================
1846 //
1847 // COLUMNS SPECIALIZATIONS
1848 //
1849 //=================================================================================================
1850 
1851 //*************************************************************************************************
1853 template< typename MT1, typename MT2 >
1854 struct Columns< SMatTDMatMultExpr<MT1,MT2> > : public Columns<MT2>
1855 {};
1857 //*************************************************************************************************
1858 
1859 
1860 
1861 
1862 //=================================================================================================
1863 //
1864 // ISALIGNED SPECIALIZATIONS
1865 //
1866 //=================================================================================================
1867 
1868 //*************************************************************************************************
1870 template< typename MT1, typename MT2 >
1871 struct IsAligned< SMatTDMatMultExpr<MT1,MT2> > : public IsTrue< IsAligned<MT2>::value >
1872 {};
1874 //*************************************************************************************************
1875 
1876 
1877 
1878 
1879 //=================================================================================================
1880 //
1881 // ISLOWER SPECIALIZATIONS
1882 //
1883 //=================================================================================================
1884 
1885 //*************************************************************************************************
1887 template< typename MT1, typename MT2 >
1888 struct IsLower< SMatTDMatMultExpr<MT1,MT2> >
1889  : public IsTrue< And< IsLower<MT1>, IsLower<MT2> >::value >
1890 {};
1892 //*************************************************************************************************
1893 
1894 
1895 
1896 
1897 //=================================================================================================
1898 //
1899 // ISUNILOWER SPECIALIZATIONS
1900 //
1901 //=================================================================================================
1902 
1903 //*************************************************************************************************
1905 template< typename MT1, typename MT2 >
1906 struct IsUniLower< SMatTDMatMultExpr<MT1,MT2> >
1907  : public IsTrue< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
1908 {};
1910 //*************************************************************************************************
1911 
1912 
1913 
1914 
1915 //=================================================================================================
1916 //
1917 // ISSTRICTLYLOWER SPECIALIZATIONS
1918 //
1919 //=================================================================================================
1920 
1921 //*************************************************************************************************
1923 template< typename MT1, typename MT2 >
1924 struct IsStrictlyLower< SMatTDMatMultExpr<MT1,MT2> >
1925  : public IsTrue< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
1926  , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
1927 {};
1929 //*************************************************************************************************
1930 
1931 
1932 
1933 
1934 //=================================================================================================
1935 //
1936 // ISUPPER SPECIALIZATIONS
1937 //
1938 //=================================================================================================
1939 
1940 //*************************************************************************************************
1942 template< typename MT1, typename MT2 >
1943 struct IsUpper< SMatTDMatMultExpr<MT1,MT2> >
1944  : public IsTrue< And< IsUpper<MT1>, IsUpper<MT2> >::value >
1945 {};
1947 //*************************************************************************************************
1948 
1949 
1950 
1951 
1952 //=================================================================================================
1953 //
1954 // ISUNIUPPER SPECIALIZATIONS
1955 //
1956 //=================================================================================================
1957 
1958 //*************************************************************************************************
1960 template< typename MT1, typename MT2 >
1961 struct IsUniUpper< SMatTDMatMultExpr<MT1,MT2> >
1962  : public IsTrue< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
1963 {};
1965 //*************************************************************************************************
1966 
1967 
1968 
1969 
1970 //=================================================================================================
1971 //
1972 // ISSTRICTLYUPPER SPECIALIZATIONS
1973 //
1974 //=================================================================================================
1975 
1976 //*************************************************************************************************
1978 template< typename MT1, typename MT2 >
1979 struct IsStrictlyUpper< SMatTDMatMultExpr<MT1,MT2> >
1980  : public IsTrue< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
1981  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
1982 {};
1984 //*************************************************************************************************
1985 
1986 
1987 
1988 
1989 //=================================================================================================
1990 //
1991 // EXPRESSION TRAIT SPECIALIZATIONS
1992 //
1993 //=================================================================================================
1994 
1995 //*************************************************************************************************
1997 template< typename MT1, typename MT2, typename VT >
1998 struct DMatDVecMultExprTrait< SMatTDMatMultExpr<MT1,MT2>, VT >
1999 {
2000  public:
2001  //**********************************************************************************************
2002  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
2003  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
2004  IsDenseVector<VT>::value && IsColumnVector<VT>::value
2005  , typename SMatDVecMultExprTrait< MT1, typename TDMatDVecMultExprTrait<MT2,VT>::Type >::Type
2006  , INVALID_TYPE >::Type Type;
2007  //**********************************************************************************************
2008 };
2010 //*************************************************************************************************
2011 
2012 
2013 //*************************************************************************************************
2015 template< typename MT1, typename MT2, typename VT >
2016 struct DMatSVecMultExprTrait< SMatTDMatMultExpr<MT1,MT2>, VT >
2017 {
2018  public:
2019  //**********************************************************************************************
2020  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
2021  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
2022  IsSparseVector<VT>::value && IsColumnVector<VT>::value
2023  , typename SMatDVecMultExprTrait< MT1, typename TDMatSVecMultExprTrait<MT2,VT>::Type >::Type
2024  , INVALID_TYPE >::Type Type;
2025  //**********************************************************************************************
2026 };
2028 //*************************************************************************************************
2029 
2030 
2031 //*************************************************************************************************
2033 template< typename VT, typename MT1, typename MT2 >
2034 struct TDVecDMatMultExprTrait< VT, SMatTDMatMultExpr<MT1,MT2> >
2035 {
2036  public:
2037  //**********************************************************************************************
2038  typedef typename SelectType< IsDenseVector<VT>::value && IsRowVector<VT>::value &&
2039  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
2040  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
2041  , typename TDVecTDMatMultExprTrait< typename TDVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
2042  , INVALID_TYPE >::Type Type;
2043  //**********************************************************************************************
2044 };
2046 //*************************************************************************************************
2047 
2048 
2049 //*************************************************************************************************
2051 template< typename VT, typename MT1, typename MT2 >
2052 struct TSVecDMatMultExprTrait< VT, SMatTDMatMultExpr<MT1,MT2> >
2053 {
2054  public:
2055  //**********************************************************************************************
2056  typedef typename SelectType< IsSparseVector<VT>::value && IsRowVector<VT>::value &&
2057  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
2058  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
2059  , typename TSVecTDMatMultExprTrait< typename TSVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
2060  , INVALID_TYPE >::Type Type;
2061  //**********************************************************************************************
2062 };
2064 //*************************************************************************************************
2065 
2066 
2067 //*************************************************************************************************
2069 template< typename MT1, typename MT2, bool AF >
2070 struct SubmatrixExprTrait< SMatTDMatMultExpr<MT1,MT2>, AF >
2071 {
2072  public:
2073  //**********************************************************************************************
2074  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT1,AF>::Type
2075  , typename SubmatrixExprTrait<const MT2,AF>::Type >::Type Type;
2076  //**********************************************************************************************
2077 };
2079 //*************************************************************************************************
2080 
2081 
2082 //*************************************************************************************************
2084 template< typename MT1, typename MT2 >
2085 struct RowExprTrait< SMatTDMatMultExpr<MT1,MT2> >
2086 {
2087  public:
2088  //**********************************************************************************************
2089  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
2090  //**********************************************************************************************
2091 };
2093 //*************************************************************************************************
2094 
2095 
2096 //*************************************************************************************************
2098 template< typename MT1, typename MT2 >
2099 struct ColumnExprTrait< SMatTDMatMultExpr<MT1,MT2> >
2100 {
2101  public:
2102  //**********************************************************************************************
2103  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
2104  //**********************************************************************************************
2105 };
2107 //*************************************************************************************************
2108 
2109 } // namespace blaze
2110 
2111 #endif
ResultType::OppositeType OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: SMatTDMatMultExpr.h:198
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exceptionThis macro encapsulates the default way of...
Definition: Exception.h:187
const ElementType ReturnType
Return type for expression template evaluations.
Definition: SMatTDMatMultExpr.h:201
const MT::ElementType max(const DenseMatrix< MT, SO > &dm)
Returns the largest element of the dense matrix.
Definition: DenseMatrix.h:1729
ResultType::ElementType ElementType
Resulting element type.
Definition: SMatTDMatMultExpr.h:200
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:89
Header file for mathematical functions.
Header file for the SMatDVecMultExprTrait class template.
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:7820
Compile time check for triangular matrix types.This type trait tests whether or not the given templat...
Definition: IsTriangular.h:105
Header file for basic type definitions.
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:250
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: SMatTDMatMultExpr.h:320
Header file for the IsSparseMatrix type trait.
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:207
#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:79
Header file for the ColumnExprTrait class template.
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:507
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2588
Header file for the IsRowVector type trait.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:259
Header file for the And class template.
Compile time check for lower triangular matrices.This type trait tests whether or not the given templ...
Definition: IsLower.h:90
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: SMatTDMatMultExpr.h:247
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:721
LeftOperand leftOperand() const
Returns the left-hand side sparse matrix operand.
Definition: SMatTDMatMultExpr.h:356
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:90
MT2::CompositeType CT2
Composite type of the right-hand side dense matrix expression.
Definition: SMatTDMatMultExpr.h:138
Constraints on the storage order of matrix types.
Header file for the RequiresEvaluation type trait.
System settings for performance optimizations.
Header file for the TSVecSMatMultExprTrait class template.
RT2::ElementType ET2
Element type of the right-hand side sparse matrix expression.
Definition: SMatTDMatMultExpr.h:136
SMatTDMatMultExpr(const MT1 &lhs, const MT2 &rhs)
Constructor for the SMatTDMatMultExpr class.
Definition: SMatTDMatMultExpr.h:232
Header file for the IsUniLower type trait.
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:70
MT1::CompositeType CT1
Composite type of the left-hand side sparse matrix expression.
Definition: SMatTDMatMultExpr.h:137
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes...
Definition: Forward.h:117
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: SMatTDMatMultExpr.h:417
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:90
Compile time type selection.The SelectType class template selects one of the two given types T1 and T...
Definition: SelectType.h:59
Header file for the DisableIf class template.
MT1::ResultType RT1
Result type of the left-hand side sparse matrix expression.
Definition: SMatTDMatMultExpr.h:133
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
#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:79
Header file for the TSVecTDMatMultExprTrait class template.
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2592
Header file for the Or class template.
Header file for the TDMatSVecMultExprTrait class template.
#define BLAZE_THROW_OUT_OF_RANGE(MESSAGE)
Macro for the emission of a std::out_of_range exceptionThis macro encapsulates the default way of Bla...
Definition: Exception.h:331
const MT::ElementType min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1682
Header file for the DenseMatrix base class.
Header file for the Columns type trait.
MultTrait< RT1, RT2 >::Type ResultType
Result type for expression template evaluations.
Definition: SMatTDMatMultExpr.h:197
Header file for the DMatDVecMultExprTrait class template.
Header file for the IsLower type trait.
SelectType< IsExpression< MT1 >::value, const MT1, const MT1 & >::Type LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: SMatTDMatMultExpr.h:205
Header file for the IsAligned type trait.
Expression object for sparse matrix-transpose dense matrix multiplications.The SMatTDMatMultExpr clas...
Definition: Forward.h:110
#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:78
Header file for the IsTriangular type trait.
Constraints on the storage order of matrix types.
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: SMatTDMatMultExpr.h:378
Compile time check for strictly upper triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyUpper.h:86
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:2586
Header file for the SelectType class template.
Header file for the RowExprTrait class template.
Header file for all forward declarations for expression class templates.
Header file for the IsDenseMatrix type trait.
bool isAligned() const
Returns whether the operands of the expression are properly aligned in memory.
Definition: SMatTDMatMultExpr.h:400
Header file for the EnableIf class template.
Header file for the IsStrictlyLower type trait.
Header file for the serial shim.
#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:165
EnableIf< IsDenseMatrix< MT1 > >::Type 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
RT1::ElementType ET1
Element type of the left-hand side dense matrix expression.
Definition: SMatTDMatMultExpr.h:135
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:79
Removal of reference modifiers.The RemoveCV type trait removes any reference modifiers from the given...
Definition: RemoveReference.h:69
Header file for run time assertion macros.
Compile time check for column-major matrix types.This type trait tests whether or not the given templ...
Definition: IsColumnMajorMatrix.h:110
EnableIf< IsDenseMatrix< MT1 > >::Type 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
Utility type for generic codes.
Base template for the MultTrait class.
Definition: MultTrait.h:138
SelectType< evaluateRight, const RT2, CT2 >::Type RT
Type for the assignment of the right-hand side dense matrix operand.
Definition: SMatTDMatMultExpr.h:214
RightOperand rhs_
Right-hand side dense matrix of the multiplication expression.
Definition: SMatTDMatMultExpr.h:418
const bool useOptimizedKernels
Configuration switch for optimized kernels.This configuration switch enables/disables all optimized c...
Definition: Optimizations.h:84
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: SMatTDMatMultExpr.h:390
Header file for the reset shim.
size_t columns() const
Returns the current number of columns of the matrix.
Definition: SMatTDMatMultExpr.h:346
Constraints on the storage order of matrix types.
Header file for the RemoveReference type trait.
Substitution Failure Is Not An Error (SFINAE) class.The DisableIf class template is an auxiliary tool...
Definition: DisableIf.h:184
#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:122
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
SelectType< evaluateLeft, const RT1, CT1 >::Type LT
Type for the assignment of the left-hand side sparse matrix operand.
Definition: SMatTDMatMultExpr.h:211
size_t rows() const
Returns the current number of rows of the matrix.
Definition: SMatTDMatMultExpr.h:336
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:944
Header file for the IsComputation type trait class.
Header file for the TDVecDMatMultExprTrait class template.
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: SMatTDMatMultExpr.h:410
EnableIf< IsDenseMatrix< MT1 > >::Type 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
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
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: SMatTDMatMultExpr.h:199
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:2583
Header file for the IsTrue value trait.
const ResultType CompositeType
Data type for composite expression templates.
Definition: SMatTDMatMultExpr.h:202
Header file for the TSVecDMatMultExprTrait class template.
SelectType< IsExpression< MT2 >::value, const MT2, const MT2 & >::Type RightOperand
Composite type of the right-hand side dense matrix expression.
Definition: SMatTDMatMultExpr.h:208
SMatTDMatMultExpr< MT1, MT2 > This
Type of this SMatTDMatMultExpr instance.
Definition: SMatTDMatMultExpr.h:196
RightOperand rightOperand() const
Returns the right-hand side transpose dense matrix operand.
Definition: SMatTDMatMultExpr.h:366
Header file for the IsUpper type trait.
Header file for exception macros.
MT2::ResultType RT2
Result type of the right-hand side dense matrix expression.
Definition: SMatTDMatMultExpr.h:134
Header file for the DMatSVecMultExprTrait class template.
Header file for the IsColumnVector type trait.
Constraint on the data type.
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
Header file for the 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:79
Header file for the IsExpression type trait class.
Header file for the FunctionTrace class.