DMatTSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_DMATTSMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_DMATTSMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
53 #include <blaze/math/Functions.h>
54 #include <blaze/math/shims/Reset.h>
94 #include <blaze/util/Assert.h>
96 #include <blaze/util/DisableIf.h>
97 #include <blaze/util/EnableIf.h>
98 #include <blaze/util/Exception.h>
99 #include <blaze/util/InvalidType.h>
101 #include <blaze/util/mpl/And.h>
102 #include <blaze/util/mpl/Or.h>
103 #include <blaze/util/SelectType.h>
104 #include <blaze/util/Types.h>
107 
108 
109 namespace blaze {
110 
111 //=================================================================================================
112 //
113 // CLASS DMATTSMATMULTEXPR
114 //
115 //=================================================================================================
116 
117 //*************************************************************************************************
124 template< typename MT1 // Type of the left-hand side dense matrix
125  , typename MT2 > // Type of the right-hand side sparse matrix
126 class DMatTSMatMultExpr : public DenseMatrix< DMatTSMatMultExpr<MT1,MT2>, false >
127  , private MatMatMultExpr
128  , private Computation
129 {
130  private:
131  //**Type definitions****************************************************************************
132  typedef typename MT1::ResultType RT1;
133  typedef typename MT2::ResultType RT2;
134  typedef typename RT1::ElementType ET1;
135  typedef typename RT2::ElementType ET2;
136  typedef typename MT1::CompositeType CT1;
137  typedef typename MT2::CompositeType CT2;
138  //**********************************************************************************************
139 
140  //**********************************************************************************************
143  //**********************************************************************************************
144 
145  //**********************************************************************************************
147  enum { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
148  //**********************************************************************************************
149 
150  //**********************************************************************************************
152 
157  template< typename T1, typename T2, typename T3 >
158  struct CanExploitSymmetry {
159  enum { value = IsSymmetric<T2>::value };
160  };
162  //**********************************************************************************************
163 
164  //**********************************************************************************************
166 
170  template< typename T1, typename T2, typename T3 >
171  struct IsEvaluationRequired {
172  enum { value = ( evaluateLeft || evaluateRight ) &&
173  !CanExploitSymmetry<T1,T2,T3>::value };
174  };
176  //**********************************************************************************************
177 
178  //**********************************************************************************************
180 
183  template< typename T1, typename T2, typename T3 >
184  struct UseOptimizedKernel {
185  enum { value = useOptimizedKernels &&
186  !IsDiagonal<T2>::value &&
187  !IsResizable<typename T1::ElementType>::value &&
188  !IsResizable<ET2>::value };
189  };
191  //**********************************************************************************************
192 
193  public:
194  //**Type definitions****************************************************************************
200  typedef const ElementType ReturnType;
201  typedef const ResultType CompositeType;
202 
204  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
205 
207  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
208 
211 
214  //**********************************************************************************************
215 
216  //**Compilation flags***************************************************************************
218  enum { vectorizable = 0 };
219 
221  enum { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
222  !evaluateRight && MT2::smpAssignable };
223  //**********************************************************************************************
224 
225  //**Constructor*********************************************************************************
231  explicit inline DMatTSMatMultExpr( const MT1& lhs, const MT2& rhs )
232  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
233  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
234  {
235  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
236  }
237  //**********************************************************************************************
238 
239  //**Access operator*****************************************************************************
246  inline ReturnType operator()( size_t i, size_t j ) const {
247  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
248  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
249 
251 
252  ElementType tmp = ElementType();
253 
254  // Early exit
255  if( lhs_.columns() == 0UL )
256  return tmp;
257 
258  // Fast computation in case the right-hand side sparse matrix directly provides iterators
260  {
261  CT2 B( rhs_ ); // Evaluation of the right-hand side sparse matrix operand
262 
263  const ConstIterator end( ( IsLower<MT1>::value )
264  ?( IsStrictlyLower<MT1>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
265  :( B.end(j) ) );
266  ConstIterator element( ( IsUpper<MT1>::value )
267  ?( IsStrictlyUpper<MT1>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
268  :( B.begin(j) ) );
269 
270  if( element != end ) {
271  tmp = lhs_(i,element->index()) * element->value();
272  ++element;
273  for( ; element!=end; ++element ) {
274  tmp += lhs_(i,element->index()) * element->value();
275  }
276  }
277  }
278 
279  // Default computation in case the right-hand side sparse matrix doesn't provide iterators
280  else
281  {
282  const size_t kbegin( ( IsUpper<MT1>::value )
283  ?( ( IsLower<MT2>::value )
284  ?( max( ( IsStrictlyUpper<MT1>::value ? i+1UL : i )
285  , ( IsStrictlyLower<MT2>::value ? j+1UL : j ) ) )
286  :( IsStrictlyUpper<MT1>::value ? i+1UL : i ) )
287  :( ( IsLower<MT2>::value )
288  ?( IsStrictlyLower<MT2>::value ? j+1UL : j )
289  :( 0UL ) ) );
290  const size_t kend( ( IsLower<MT1>::value )
291  ?( ( IsUpper<MT2>::value )
292  ?( min( ( IsStrictlyLower<MT1>::value ? i : i+1UL )
293  , ( IsStrictlyUpper<MT2>::value ? j : j+1UL ) ) )
294  :( IsStrictlyLower<MT1>::value ? i : i+1UL ) )
295  :( ( IsUpper<MT2>::value )
296  ?( IsStrictlyUpper<MT2>::value ? j : j+1UL )
297  :( lhs_.columns() ) ) );
298 
299  if( ( !IsTriangular<MT1>::value && !IsTriangular<MT2>::value ) || kbegin < kend ) {
300  tmp = lhs_(i,kbegin) * rhs_(kbegin,j);
301  for( size_t k=kbegin+1UL; k<kend; ++k ) {
302  tmp += lhs_(i,k) * rhs_(k,j);
303  }
304  }
305  }
306 
307  return tmp;
308  }
309  //**********************************************************************************************
310 
311  //**At function*********************************************************************************
319  inline ReturnType at( size_t i, size_t j ) const {
320  if( i >= lhs_.rows() ) {
321  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
322  }
323  if( j >= rhs_.columns() ) {
324  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
325  }
326  return (*this)(i,j);
327  }
328  //**********************************************************************************************
329 
330  //**Rows function*******************************************************************************
335  inline size_t rows() const {
336  return lhs_.rows();
337  }
338  //**********************************************************************************************
339 
340  //**Columns function****************************************************************************
345  inline size_t columns() const {
346  return rhs_.columns();
347  }
348  //**********************************************************************************************
349 
350  //**Left operand access*************************************************************************
355  inline LeftOperand leftOperand() const {
356  return lhs_;
357  }
358  //**********************************************************************************************
359 
360  //**Right operand access************************************************************************
365  inline RightOperand rightOperand() const {
366  return rhs_;
367  }
368  //**********************************************************************************************
369 
370  //**********************************************************************************************
376  template< typename T >
377  inline bool canAlias( const T* alias ) const {
378  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
379  }
380  //**********************************************************************************************
381 
382  //**********************************************************************************************
388  template< typename T >
389  inline bool isAliased( const T* alias ) const {
390  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
391  }
392  //**********************************************************************************************
393 
394  //**********************************************************************************************
399  inline bool isAligned() const {
400  return lhs_.isAligned();
401  }
402  //**********************************************************************************************
403 
404  //**********************************************************************************************
409  inline bool canSMPAssign() const {
410  return ( rows() > SMP_DMATTSMATMULT_THRESHOLD );
411  }
412  //**********************************************************************************************
413 
414  private:
415  //**Member variables****************************************************************************
416  LeftOperand lhs_;
417  RightOperand rhs_;
418  //**********************************************************************************************
419 
420  //**Assignment to dense matrices****************************************************************
433  template< typename MT // Type of the target dense matrix
434  , bool SO > // Storage order of the target dense matrix
435  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
436  assign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
437  {
439 
440  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
441  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
442 
443  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
444  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
445 
446  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
447  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
448  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
449 
450  DMatTSMatMultExpr::selectAssignKernel( ~lhs, A, B );
451  }
453  //**********************************************************************************************
454 
455  //**Default assignment to dense matrices********************************************************
469  template< typename MT3 // Type of the left-hand side target matrix
470  , typename MT4 // Type of the left-hand side matrix operand
471  , typename MT5 > // Type of the right-hand side matrix operand
472  static inline typename DisableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
473  selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
474  {
475  typedef typename MT5::ConstIterator ConstIterator;
476 
477  const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 256UL );
478 
479  for( size_t jj=0UL; jj<B.columns(); jj+=block )
480  {
481  const size_t jend( min( jj+block, B.columns() ) );
482 
483  size_t i( 0UL );
484 
485  for( ; (i+4UL) <= A.rows(); i+=4UL ) {
486  for( size_t j=jj; j<jend; ++j )
487  {
488  ConstIterator element( ( IsUpper<MT4>::value )
489  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
490  :( B.begin(j) ) );
491  const ConstIterator end( ( IsLower<MT4>::value )
492  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
493  :( B.end(j) ) );
494 
495  if( element == end ) {
496  reset( C(i ,j) );
497  reset( C(i+1UL,j) );
498  reset( C(i+2UL,j) );
499  reset( C(i+3UL,j) );
500  continue;
501  }
502 
503  C(i ,j) = A(i ,element->index()) * element->value();
504  C(i+1UL,j) = A(i+1UL,element->index()) * element->value();
505  C(i+2UL,j) = A(i+2UL,element->index()) * element->value();
506  C(i+3UL,j) = A(i+3UL,element->index()) * element->value();
507  ++element;
508  for( ; element!=end; ++element ) {
509  C(i ,j) += A(i ,element->index()) * element->value();
510  C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
511  C(i+2UL,j) += A(i+2UL,element->index()) * element->value();
512  C(i+3UL,j) += A(i+3UL,element->index()) * element->value();
513  }
514  }
515  }
516 
517  for( ; (i+2UL) <= A.rows(); i+=2UL ) {
518  for( size_t j=jj; j<jend; ++j )
519  {
520  ConstIterator element( ( IsUpper<MT4>::value )
521  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
522  :( B.begin(j) ) );
523  const ConstIterator end( ( IsLower<MT4>::value )
524  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
525  :( B.end(j) ) );
526 
527  if( element == end ) {
528  reset( C(i ,j) );
529  reset( C(i+1UL,j) );
530  continue;
531  }
532 
533  C(i ,j) = A(i ,element->index()) * element->value();
534  C(i+1UL,j) = A(i+1UL,element->index()) * element->value();
535  ++element;
536  for( ; element!=end; ++element ) {
537  C(i ,j) += A(i ,element->index()) * element->value();
538  C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
539  }
540  }
541  }
542 
543  for( ; i<A.rows(); ++i ) {
544  for( size_t j=jj; j<jend; ++j )
545  {
546  ConstIterator element( ( IsUpper<MT4>::value )
547  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
548  :( B.begin(j) ) );
549  const ConstIterator end( ( IsLower<MT4>::value )
550  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
551  :( B.end(j) ) );
552 
553  if( element == end ) {
554  reset( C(i,j) );
555  continue;
556  }
557 
558  C(i,j) = A(i,element->index()) * element->value();
559  ++element;
560  for( ; element!=end; ++element )
561  C(i,j) += A(i,element->index()) * element->value();
562  }
563  }
564  }
565  }
567  //**********************************************************************************************
568 
569  //**Optimized assignment to dense matrices******************************************************
583  template< typename MT3 // Type of the left-hand side target matrix
584  , typename MT4 // Type of the left-hand side matrix operand
585  , typename MT5 > // Type of the right-hand side matrix operand
586  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
587  selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
588  {
589  typedef typename MT5::ConstIterator ConstIterator;
590 
591  const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 256UL );
592 
593  reset( C );
594 
595  for( size_t jj=0UL; jj<B.columns(); jj+=block )
596  {
597  const size_t jend( min( jj+block, B.columns() ) );
598 
599  size_t i( 0UL );
600 
601  for( ; (i+4UL) <= A.rows(); i+=4UL ) {
602  for( size_t j=jj; j<jend; ++j )
603  {
604  ConstIterator element( ( IsUpper<MT4>::value )
605  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
606  :( B.begin(j) ) );
607  const ConstIterator end( ( IsLower<MT4>::value )
608  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
609  :( B.end(j) ) );
610 
611  const size_t nonzeros( end - element );
612  const size_t kpos( nonzeros & size_t(-4) );
613  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
614 
615  for( size_t k=0UL; k<kpos; k+=4UL )
616  {
617  const size_t j1( element->index() );
618  const ET2 v1( element->value() );
619  ++element;
620  const size_t j2( element->index() );
621  const ET2 v2( element->value() );
622  ++element;
623  const size_t j3( element->index() );
624  const ET2 v3( element->value() );
625  ++element;
626  const size_t j4( element->index() );
627  const ET2 v4( element->value() );
628  ++element;
629 
630  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
631 
632  C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
633  C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
634  C(i+2UL,j) += A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
635  C(i+3UL,j) += A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
636  }
637 
638  for( ; element!=end; ++element )
639  {
640  const size_t j1( element->index() );
641  const ET2 v1( element->value() );
642 
643  C(i ,j) += A(i ,j1) * v1;
644  C(i+1UL,j) += A(i+1UL,j1) * v1;
645  C(i+2UL,j) += A(i+2UL,j1) * v1;
646  C(i+3UL,j) += A(i+3UL,j1) * v1;
647  }
648  }
649  }
650 
651  for( ; (i+2UL) <= A.rows(); i+=2UL ) {
652  for( size_t j=jj; j<jend; ++j )
653  {
654  ConstIterator element( ( IsUpper<MT4>::value )
655  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
656  :( B.begin(j) ) );
657  const ConstIterator end( ( IsLower<MT4>::value )
658  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
659  :( B.end(j) ) );
660 
661  const size_t nonzeros( end - element );
662  const size_t kpos( nonzeros & size_t(-4) );
663  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
664 
665  for( size_t k=0UL; k<kpos; k+=4UL )
666  {
667  const size_t j1( element->index() );
668  const ET2 v1( element->value() );
669  ++element;
670  const size_t j2( element->index() );
671  const ET2 v2( element->value() );
672  ++element;
673  const size_t j3( element->index() );
674  const ET2 v3( element->value() );
675  ++element;
676  const size_t j4( element->index() );
677  const ET2 v4( element->value() );
678  ++element;
679 
680  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
681 
682  C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
683  C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
684  }
685 
686  for( ; element!=end; ++element )
687  {
688  const size_t j1( element->index() );
689  const ET2 v1( element->value() );
690 
691  C(i ,j) += A(i ,j1) * v1;
692  C(i+1UL,j) += A(i+1UL,j1) * v1;
693  }
694  }
695  }
696 
697  for( ; i<A.rows(); ++i ) {
698  for( size_t j=jj; j<jend; ++j )
699  {
700  ConstIterator element( ( IsUpper<MT4>::value )
701  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
702  :( B.begin(j) ) );
703  const ConstIterator end( ( IsLower<MT4>::value )
704  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
705  :( B.end(j) ) );
706 
707  const size_t nonzeros( end - element );
708  const size_t kpos( nonzeros & size_t(-4) );
709  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
710 
711  for( size_t k=0UL; k<kpos; k+=4UL )
712  {
713  const size_t j1( element->index() );
714  const ET2 v1( element->value() );
715  ++element;
716  const size_t j2( element->index() );
717  const ET2 v2( element->value() );
718  ++element;
719  const size_t j3( element->index() );
720  const ET2 v3( element->value() );
721  ++element;
722  const size_t j4( element->index() );
723  const ET2 v4( element->value() );
724  ++element;
725 
726  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
727 
728  C(i,j) += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
729  }
730 
731  for( ; element!=end; ++element )
732  {
733  const size_t j1( element->index() );
734  const ET2 v1( element->value() );
735 
736  C(i,j) += A(i,j1) * v1;
737  }
738  }
739  }
740  }
741  }
743  //**********************************************************************************************
744 
745  //**Assignment to sparse matrices***************************************************************
758  template< typename MT // Type of the target sparse matrix
759  , bool SO > // Storage order of the target sparse matrix
760  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
761  assign( SparseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
762  {
764 
765  typedef typename SelectType< SO, OppositeType, ResultType >::Type TmpType;
766 
773 
774  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
775  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
776 
777  const TmpType tmp( serial( rhs ) );
778  assign( ~lhs, tmp );
779  }
781  //**********************************************************************************************
782 
783  //**Restructuring assignment********************************************************************
798  template< typename MT // Type of the target matrix
799  , bool SO > // Storage order of the target matrix
800  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
801  assign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
802  {
804 
805  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
806  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
807 
808  assign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
809  }
811  //**********************************************************************************************
812 
813  //**Addition assignment to dense matrices*******************************************************
826  template< typename MT // Type of the target dense matrix
827  , bool SO > // Storage order of the target dense matrix
828  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
829  addAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
830  {
832 
833  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
834  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
835 
836  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
837  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
838 
839  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
840  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
841  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
842 
843  DMatTSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
844  }
846  //**********************************************************************************************
847 
848  //**Default addition assignment to dense matrices***********************************************
862  template< typename MT3 // Type of the left-hand side target matrix
863  , typename MT4 // Type of the left-hand side matrix operand
864  , typename MT5 > // Type of the right-hand side matrix operand
865  static inline typename DisableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
866  selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
867  {
868  typedef typename MT5::ConstIterator ConstIterator;
869 
870  const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 256UL );
871 
872  for( size_t jj=0UL; jj<B.columns(); jj+=block )
873  {
874  const size_t jend( min( jj+block, B.columns() ) );
875 
876  size_t i( 0UL );
877 
878  for( ; (i+4UL) <= A.rows(); i+=4UL ) {
879  for( size_t j=jj; j<jend; ++j )
880  {
881  ConstIterator element( ( IsUpper<MT4>::value )
882  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
883  :( B.begin(j) ) );
884  const ConstIterator end( ( IsLower<MT4>::value )
885  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
886  :( B.end(j) ) );
887 
888  for( ; element!=end; ++element ) {
889  C(i ,j) += A(i ,element->index()) * element->value();
890  C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
891  C(i+2UL,j) += A(i+2UL,element->index()) * element->value();
892  C(i+3UL,j) += A(i+3UL,element->index()) * element->value();
893  }
894  }
895  }
896 
897  for( ; (i+2UL) <= A.rows(); i+=2UL ) {
898  for( size_t j=jj; j<jend; ++j )
899  {
900  ConstIterator element( ( IsUpper<MT4>::value )
901  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
902  :( B.begin(j) ) );
903  const ConstIterator end( ( IsLower<MT4>::value )
904  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
905  :( B.end(j) ) );
906 
907  for( ; element!=end; ++element ) {
908  C(i ,j) += A(i ,element->index()) * element->value();
909  C(i+1UL,j) += A(i+1UL,element->index()) * element->value();
910  }
911  }
912  }
913 
914  for( ; i<A.rows(); ++i ) {
915  for( size_t j=jj; j<jend; ++j )
916  {
917  ConstIterator element( ( IsUpper<MT4>::value )
918  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
919  :( B.begin(j) ) );
920  const ConstIterator end( ( IsLower<MT4>::value )
921  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
922  :( B.end(j) ) );
923 
924  for( ; element!=end; ++element )
925  C(i,j) += A(i,element->index()) * element->value();
926  }
927  }
928  }
929  }
931  //**********************************************************************************************
932 
933  //**Optimized addition assignment to dense matrices*********************************************
947  template< typename MT3 // Type of the left-hand side target matrix
948  , typename MT4 // Type of the left-hand side matrix operand
949  , typename MT5 > // Type of the right-hand side matrix operand
950  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
951  selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
952  {
953  typedef typename MT5::ConstIterator ConstIterator;
954 
955  const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 256UL );
956 
957  for( size_t jj=0UL; jj<B.columns(); jj+=block )
958  {
959  const size_t jend( min( jj+block, B.columns() ) );
960 
961  size_t i( 0UL );
962 
963  for( ; (i+4UL) <= A.rows(); i+=4UL ) {
964  for( size_t j=jj; j<jend; ++j )
965  {
966  ConstIterator element( ( IsUpper<MT4>::value )
967  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
968  :( B.begin(j) ) );
969  const ConstIterator end( ( IsLower<MT4>::value )
970  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
971  :( B.end(j) ) );
972 
973  const size_t nonzeros( end - element );
974  const size_t kpos( nonzeros & size_t(-4) );
975  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
976 
977  for( size_t k=0UL; k<kpos; k+=4UL )
978  {
979  const size_t j1( element->index() );
980  const ET2 v1( element->value() );
981  ++element;
982  const size_t j2( element->index() );
983  const ET2 v2( element->value() );
984  ++element;
985  const size_t j3( element->index() );
986  const ET2 v3( element->value() );
987  ++element;
988  const size_t j4( element->index() );
989  const ET2 v4( element->value() );
990  ++element;
991 
992  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
993 
994  C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
995  C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
996  C(i+2UL,j) += A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
997  C(i+3UL,j) += A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
998  }
999 
1000  for( ; element!=end; ++element )
1001  {
1002  const size_t j1( element->index() );
1003  const ET2 v1( element->value() );
1004 
1005  C(i ,j) += A(i ,j1) * v1;
1006  C(i+1UL,j) += A(i+1UL,j1) * v1;
1007  C(i+2UL,j) += A(i+2UL,j1) * v1;
1008  C(i+3UL,j) += A(i+3UL,j1) * v1;
1009  }
1010  }
1011  }
1012 
1013  for( ; (i+2UL) <= A.rows(); i+=2UL ) {
1014  for( size_t j=jj; j<jend; ++j )
1015  {
1016  ConstIterator element( ( IsUpper<MT4>::value )
1017  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1018  :( B.begin(j) ) );
1019  const ConstIterator end( ( IsLower<MT4>::value )
1020  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
1021  :( B.end(j) ) );
1022 
1023  const size_t nonzeros( end - element );
1024  const size_t kpos( nonzeros & size_t(-4) );
1025  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1026 
1027  for( size_t k=0UL; k<kpos; k+=4UL )
1028  {
1029  const size_t j1( element->index() );
1030  const ET2 v1( element->value() );
1031  ++element;
1032  const size_t j2( element->index() );
1033  const ET2 v2( element->value() );
1034  ++element;
1035  const size_t j3( element->index() );
1036  const ET2 v3( element->value() );
1037  ++element;
1038  const size_t j4( element->index() );
1039  const ET2 v4( element->value() );
1040  ++element;
1041 
1042  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1043 
1044  C(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
1045  C(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
1046  }
1047 
1048  for( ; element!=end; ++element )
1049  {
1050  const size_t j1( element->index() );
1051  const ET2 v1( element->value() );
1052 
1053  C(i ,j) += A(i ,j1) * v1;
1054  C(i+1UL,j) += A(i+1UL,j1) * v1;
1055  }
1056  }
1057  }
1058 
1059  for( ; i<A.rows(); ++i ) {
1060  for( size_t j=jj; j<jend; ++j )
1061  {
1062  ConstIterator element( ( IsUpper<MT4>::value )
1063  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1064  :( B.begin(j) ) );
1065  const ConstIterator end( ( IsLower<MT4>::value )
1066  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
1067  :( B.end(j) ) );
1068 
1069  const size_t nonzeros( end - element );
1070  const size_t kpos( nonzeros & size_t(-4) );
1071  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1072 
1073  for( size_t k=0UL; k<kpos; k+=4UL )
1074  {
1075  const size_t j1( element->index() );
1076  const ET2 v1( element->value() );
1077  ++element;
1078  const size_t j2( element->index() );
1079  const ET2 v2( element->value() );
1080  ++element;
1081  const size_t j3( element->index() );
1082  const ET2 v3( element->value() );
1083  ++element;
1084  const size_t j4( element->index() );
1085  const ET2 v4( element->value() );
1086  ++element;
1087 
1088  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1089 
1090  C(i,j) += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
1091  }
1092 
1093  for( ; element!=end; ++element )
1094  {
1095  const size_t j1( element->index() );
1096  const ET2 v1( element->value() );
1097 
1098  C(i,j) += A(i,j1) * v1;
1099  }
1100  }
1101  }
1102  }
1103  }
1105  //**********************************************************************************************
1106 
1107  //**Restructuring addition assignment***********************************************************
1122  template< typename MT // Type of the target matrix
1123  , bool SO > // Storage order of the target matrix
1124  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1125  addAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1126  {
1128 
1130 
1131  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1132  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1133 
1134  addAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1135  }
1137  //**********************************************************************************************
1138 
1139  //**Addition assignment to sparse matrices******************************************************
1140  // No special implementation for the addition assignment to sparse matrices.
1141  //**********************************************************************************************
1142 
1143  //**Subtraction assignment to dense matrices****************************************************
1156  template< typename MT // Type of the target dense matrix
1157  , bool SO > // Storage order of the target dense matrix
1158  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1159  subAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1160  {
1162 
1163  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1164  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1165 
1166  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1167  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1168 
1169  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1170  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
1171  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
1172 
1173  DMatTSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1174  }
1176  //**********************************************************************************************
1177 
1178  //**Default subtraction assignment to dense matrices********************************************
1192  template< typename MT3 // Type of the left-hand side target matrix
1193  , typename MT4 // Type of the left-hand side matrix operand
1194  , typename MT5 > // Type of the right-hand side matrix operand
1195  static inline typename DisableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
1196  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1197  {
1198  typedef typename MT5::ConstIterator ConstIterator;
1199 
1200  const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 256UL );
1201 
1202  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1203  {
1204  const size_t jend( min( jj+block, B.columns() ) );
1205 
1206  size_t i( 0UL );
1207 
1208  for( ; (i+4UL) <= A.rows(); i+=4UL ) {
1209  for( size_t j=jj; j<jend; ++j )
1210  {
1211  ConstIterator element( ( IsUpper<MT4>::value )
1212  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1213  :( B.begin(j) ) );
1214  const ConstIterator end( ( IsLower<MT4>::value )
1215  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
1216  :( B.end(j) ) );
1217 
1218  for( ; element!=end; ++element ) {
1219  C(i ,j) -= A(i ,element->index()) * element->value();
1220  C(i+1UL,j) -= A(i+1UL,element->index()) * element->value();
1221  C(i+2UL,j) -= A(i+2UL,element->index()) * element->value();
1222  C(i+3UL,j) -= A(i+3UL,element->index()) * element->value();
1223  }
1224  }
1225  }
1226 
1227  for( ; (i+2UL) <= A.rows(); i+=2UL ) {
1228  for( size_t j=jj; j<jend; ++j )
1229  {
1230  ConstIterator element( ( IsUpper<MT4>::value )
1231  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1232  :( B.begin(j) ) );
1233  const ConstIterator end( ( IsLower<MT4>::value )
1234  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
1235  :( B.end(j) ) );
1236 
1237  for( ; element!=end; ++element ) {
1238  C(i ,j) -= A(i ,element->index()) * element->value();
1239  C(i+1UL,j) -= A(i+1UL,element->index()) * element->value();
1240  }
1241  }
1242  }
1243 
1244  for( ; i<A.rows(); ++i ) {
1245  for( size_t j=jj; j<jend; ++j )
1246  {
1247  ConstIterator element( ( IsUpper<MT4>::value )
1248  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1249  :( B.begin(j) ) );
1250  const ConstIterator end( ( IsLower<MT4>::value )
1251  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
1252  :( B.end(j) ) );
1253 
1254  for( ; element!=end; ++element )
1255  C(i,j) -= A(i,element->index()) * element->value();
1256  }
1257  }
1258  }
1259  }
1261  //**********************************************************************************************
1262 
1263  //**Optimized subtraction assignment to dense matrices******************************************
1277  template< typename MT3 // Type of the left-hand side target matrix
1278  , typename MT4 // Type of the left-hand side matrix operand
1279  , typename MT5 > // Type of the right-hand side matrix operand
1280  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
1281  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1282  {
1283  typedef typename MT5::ConstIterator ConstIterator;
1284 
1285  const size_t block( IsRowMajorMatrix<MT3>::value ? B.columns() : 256UL );
1286 
1287  for( size_t jj=0UL; jj<B.columns(); jj+=block )
1288  {
1289  const size_t jend( min( jj+block, B.columns() ) );
1290 
1291  size_t i( 0UL );
1292 
1293  for( ; (i+4UL) <= A.rows(); i+=4UL ) {
1294  for( size_t j=jj; j<jend; ++j )
1295  {
1296  ConstIterator element( ( IsUpper<MT4>::value )
1297  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1298  :( B.begin(j) ) );
1299  const ConstIterator end( ( IsLower<MT4>::value )
1300  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+4UL,j) : B.upperBound(i+4UL,j) )
1301  :( B.end(j) ) );
1302 
1303  const size_t nonzeros( end - element );
1304  const size_t kpos( nonzeros & size_t(-4) );
1305  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1306 
1307  for( size_t k=0UL; k<kpos; k+=4UL )
1308  {
1309  const size_t j1( element->index() );
1310  const ET2 v1( element->value() );
1311  ++element;
1312  const size_t j2( element->index() );
1313  const ET2 v2( element->value() );
1314  ++element;
1315  const size_t j3( element->index() );
1316  const ET2 v3( element->value() );
1317  ++element;
1318  const size_t j4( element->index() );
1319  const ET2 v4( element->value() );
1320  ++element;
1321 
1322  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1323 
1324  C(i ,j) -= A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
1325  C(i+1UL,j) -= A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
1326  C(i+2UL,j) -= A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
1327  C(i+3UL,j) -= A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
1328  }
1329 
1330  for( ; element!=end; ++element )
1331  {
1332  const size_t j1( element->index() );
1333  const ET2 v1( element->value() );
1334 
1335  C(i ,j) -= A(i ,j1) * v1;
1336  C(i+1UL,j) -= A(i+1UL,j1) * v1;
1337  C(i+2UL,j) -= A(i+2UL,j1) * v1;
1338  C(i+3UL,j) -= A(i+3UL,j1) * v1;
1339  }
1340  }
1341  }
1342 
1343  for( ; (i+2UL) <= A.rows(); i+=2UL ) {
1344  for( size_t j=jj; j<jend; ++j )
1345  {
1346  ConstIterator element( ( IsUpper<MT4>::value )
1347  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1348  :( B.begin(j) ) );
1349  const ConstIterator end( ( IsLower<MT4>::value )
1350  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i+2UL,j) : B.upperBound(i+2UL,j) )
1351  :( B.end(j) ) );
1352 
1353  const size_t nonzeros( end - element );
1354  const size_t kpos( nonzeros & size_t(-4) );
1355  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1356 
1357  for( size_t k=0UL; k<kpos; k+=4UL )
1358  {
1359  const size_t j1( element->index() );
1360  const ET2 v1( element->value() );
1361  ++element;
1362  const size_t j2( element->index() );
1363  const ET2 v2( element->value() );
1364  ++element;
1365  const size_t j3( element->index() );
1366  const ET2 v3( element->value() );
1367  ++element;
1368  const size_t j4( element->index() );
1369  const ET2 v4( element->value() );
1370  ++element;
1371 
1372  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1373 
1374  C(i ,j) -= A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
1375  C(i+1UL,j) -= A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
1376  }
1377 
1378  for( ; element!=end; ++element )
1379  {
1380  const size_t j1( element->index() );
1381  const ET2 v1( element->value() );
1382 
1383  C(i ,j) -= A(i ,j1) * v1;
1384  C(i+1UL,j) -= A(i+1UL,j1) * v1;
1385  }
1386  }
1387  }
1388 
1389  for( ; i<A.rows(); ++i ) {
1390  for( size_t j=jj; j<jend; ++j )
1391  {
1392  ConstIterator element( ( IsUpper<MT4>::value )
1393  ?( IsStrictlyUpper<MT4>::value ? B.upperBound(i,j) : B.lowerBound(i,j) )
1394  :( B.begin(j) ) );
1395  const ConstIterator end( ( IsLower<MT4>::value )
1396  ?( IsStrictlyLower<MT4>::value ? B.lowerBound(i,j) : B.upperBound(i,j) )
1397  :( B.end(j) ) );
1398 
1399  const size_t nonzeros( end - element );
1400  const size_t kpos( nonzeros & size_t(-4) );
1401  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == kpos, "Invalid end calculation" );
1402 
1403  for( size_t k=0UL; k<kpos; k+=4UL )
1404  {
1405  const size_t j1( element->index() );
1406  const ET2 v1( element->value() );
1407  ++element;
1408  const size_t j2( element->index() );
1409  const ET2 v2( element->value() );
1410  ++element;
1411  const size_t j3( element->index() );
1412  const ET2 v3( element->value() );
1413  ++element;
1414  const size_t j4( element->index() );
1415  const ET2 v4( element->value() );
1416  ++element;
1417 
1418  BLAZE_INTERNAL_ASSERT( j1 < j2 && j2 < j3 && j3 < j4, "Invalid sparse matrix index detected" );
1419 
1420  C(i,j) -= A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
1421  }
1422 
1423  for( ; element!=end; ++element )
1424  {
1425  const size_t j1( element->index() );
1426  const ET2 v1( element->value() );
1427 
1428  C(i,j) -= A(i,j1) * v1;
1429  }
1430  }
1431  }
1432  }
1433  }
1435  //**********************************************************************************************
1436 
1437  //**Restructuring subtraction assignment********************************************************
1452  template< typename MT // Type of the target matrix
1453  , bool SO > // Storage order of the target matrix
1454  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1455  subAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1456  {
1458 
1460 
1461  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1462  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1463 
1464  subAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1465  }
1467  //**********************************************************************************************
1468 
1469  //**Subtraction assignment to sparse matrices***************************************************
1470  // No special implementation for the subtraction assignment to sparse matrices.
1471  //**********************************************************************************************
1472 
1473  //**Multiplication assignment to dense matrices*************************************************
1474  // No special implementation for the multiplication assignment to dense matrices.
1475  //**********************************************************************************************
1476 
1477  //**Multiplication assignment to sparse matrices************************************************
1478  // No special implementation for the multiplication assignment to sparse matrices.
1479  //**********************************************************************************************
1480 
1481  //**SMP assignment to dense matrices************************************************************
1496  template< typename MT // Type of the target dense matrix
1497  , bool SO > // Storage order of the target dense matrix
1498  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1499  smpAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1500  {
1502 
1503  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1504  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1505 
1506  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1507  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1508 
1509  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1510  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
1511  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
1512 
1513  smpAssign( ~lhs, A * B );
1514  }
1516  //**********************************************************************************************
1517 
1518  //**SMP assignment to sparse matrices***********************************************************
1533  template< typename MT // Type of the target sparse matrix
1534  , bool SO > // Storage order of the target sparse matrix
1535  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1536  smpAssign( SparseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1537  {
1539 
1540  typedef typename SelectType< SO, OppositeType, ResultType >::Type TmpType;
1541 
1548 
1549  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1550  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1551 
1552  const TmpType tmp( rhs );
1553  smpAssign( ~lhs, tmp );
1554  }
1556  //**********************************************************************************************
1557 
1558  //**Restructuring SMP assignment****************************************************************
1573  template< typename MT // Type of the target matrix
1574  , bool SO > // Storage order of the target matrix
1575  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1576  smpAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1577  {
1579 
1581 
1582  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1583  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1584 
1585  smpAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1586  }
1588  //**********************************************************************************************
1589 
1590  //**SMP addition assignment to dense matrices***************************************************
1606  template< typename MT // Type of the target dense matrix
1607  , bool SO > // Storage order of the target dense matrix
1608  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1609  smpAddAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1610  {
1612 
1613  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1614  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1615 
1616  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1617  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1618 
1619  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1620  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
1621  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
1622 
1623  smpAddAssign( ~lhs, A * B );
1624  }
1626  //**********************************************************************************************
1627 
1628  //**Restructuring SMP addition assignment*******************************************************
1643  template< typename MT // Type of the target matrix
1644  , bool SO > // Storage order of the target matrix
1645  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1646  smpAddAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1647  {
1649 
1651 
1652  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1653  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1654 
1655  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1656  }
1658  //**********************************************************************************************
1659 
1660  //**SMP addition assignment to sparse matrices**************************************************
1661  // No special implementation for the SMP addition assignment to sparse matrices.
1662  //**********************************************************************************************
1663 
1664  //**SMP subtraction assignment to dense matrices************************************************
1680  template< typename MT // Type of the target dense matrix
1681  , bool SO > // Storage order of the target dense matrix
1682  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1683  smpSubAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1684  {
1686 
1687  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1688  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1689 
1690  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1691  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1692 
1693  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1694  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
1695  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
1696 
1697  smpSubAssign( ~lhs, A * B );
1698  }
1700  //**********************************************************************************************
1701 
1702  //**Restructuring SMP subtraction assignment****************************************************
1717  template< typename MT // Type of the target matrix
1718  , bool SO > // Storage order of the target matrix
1719  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1720  smpSubAssign( Matrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
1721  {
1723 
1725 
1726  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1727  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1728 
1729  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1730  }
1732  //**********************************************************************************************
1733 
1734  //**SMP subtraction assignment to sparse matrices***********************************************
1735  // No special implementation for the SMP subtraction assignment to sparse matrices.
1736  //**********************************************************************************************
1737 
1738  //**SMP multiplication assignment to dense matrices*********************************************
1739  // No special implementation for the SMP multiplication assignment to dense matrices.
1740  //**********************************************************************************************
1741 
1742  //**SMP multiplication assignment to sparse matrices********************************************
1743  // No special implementation for the SMP multiplication assignment to sparse matrices.
1744  //**********************************************************************************************
1745 
1746  //**Compile time checks*************************************************************************
1754  //**********************************************************************************************
1755 };
1756 //*************************************************************************************************
1757 
1758 
1759 
1760 
1761 //=================================================================================================
1762 //
1763 // GLOBAL BINARY ARITHMETIC OPERATORS
1764 //
1765 //=================================================================================================
1766 
1767 //*************************************************************************************************
1797 template< typename T1 // Type of the left-hand side dense matrix
1798  , typename T2 > // Type of the right-hand side sparse matrix
1799 inline const DMatTSMatMultExpr<T1,T2>
1801 {
1803 
1804  if( (~lhs).columns() != (~rhs).rows() ) {
1805  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1806  }
1807 
1808  return DMatTSMatMultExpr<T1,T2>( ~lhs, ~rhs );
1809 }
1810 //*************************************************************************************************
1811 
1812 
1813 
1814 
1815 //=================================================================================================
1816 //
1817 // ROWS SPECIALIZATIONS
1818 //
1819 //=================================================================================================
1820 
1821 //*************************************************************************************************
1823 template< typename MT1, typename MT2 >
1824 struct Rows< DMatTSMatMultExpr<MT1,MT2> > : public Rows<MT1>
1825 {};
1827 //*************************************************************************************************
1828 
1829 
1830 
1831 
1832 //=================================================================================================
1833 //
1834 // COLUMNS SPECIALIZATIONS
1835 //
1836 //=================================================================================================
1837 
1838 //*************************************************************************************************
1840 template< typename MT1, typename MT2 >
1841 struct Columns< DMatTSMatMultExpr<MT1,MT2> > : public Columns<MT2>
1842 {};
1844 //*************************************************************************************************
1845 
1846 
1847 
1848 
1849 //=================================================================================================
1850 //
1851 // ISALIGNED SPECIALIZATIONS
1852 //
1853 //=================================================================================================
1854 
1855 //*************************************************************************************************
1857 template< typename MT1, typename MT2 >
1858 struct IsAligned< DMatTSMatMultExpr<MT1,MT2> > : public IsTrue< IsAligned<MT1>::value >
1859 {};
1861 //*************************************************************************************************
1862 
1863 
1864 
1865 
1866 //=================================================================================================
1867 //
1868 // ISLOWER SPECIALIZATIONS
1869 //
1870 //=================================================================================================
1871 
1872 //*************************************************************************************************
1874 template< typename MT1, typename MT2 >
1875 struct IsLower< DMatTSMatMultExpr<MT1,MT2> >
1876  : public IsTrue< IsLower<MT1>::value && IsLower<MT2>::value >
1877 {};
1879 //*************************************************************************************************
1880 
1881 
1882 
1883 
1884 //=================================================================================================
1885 //
1886 // ISUNILOWER SPECIALIZATIONS
1887 //
1888 //=================================================================================================
1889 
1890 //*************************************************************************************************
1892 template< typename MT1, typename MT2 >
1893 struct IsUniLower< DMatTSMatMultExpr<MT1,MT2> >
1894  : public IsTrue< IsUniLower<MT1>::value && IsUniLower<MT2>::value >
1895 {};
1897 //*************************************************************************************************
1898 
1899 
1900 
1901 
1902 //=================================================================================================
1903 //
1904 // ISSTRICTLYLOWER SPECIALIZATIONS
1905 //
1906 //=================================================================================================
1907 
1908 //*************************************************************************************************
1910 template< typename MT1, typename MT2 >
1911 struct IsStrictlyLower< DMatTSMatMultExpr<MT1,MT2> >
1912  : public IsTrue< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
1913  , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
1914 {};
1916 //*************************************************************************************************
1917 
1918 
1919 
1920 
1921 //=================================================================================================
1922 //
1923 // ISUPPER SPECIALIZATIONS
1924 //
1925 //=================================================================================================
1926 
1927 //*************************************************************************************************
1929 template< typename MT1, typename MT2 >
1930 struct IsUpper< DMatTSMatMultExpr<MT1,MT2> >
1931  : public IsTrue< IsUpper<MT1>::value && IsUpper<MT2>::value >
1932 {};
1934 //*************************************************************************************************
1935 
1936 
1937 
1938 
1939 //=================================================================================================
1940 //
1941 // ISUNIUPPER SPECIALIZATIONS
1942 //
1943 //=================================================================================================
1944 
1945 //*************************************************************************************************
1947 template< typename MT1, typename MT2 >
1948 struct IsUniUpper< DMatTSMatMultExpr<MT1,MT2> >
1949  : public IsTrue< IsUniUpper<MT1>::value && IsUniUpper<MT2>::value >
1950 {};
1952 //*************************************************************************************************
1953 
1954 
1955 
1956 
1957 //=================================================================================================
1958 //
1959 // ISSTRICTLYUPPER SPECIALIZATIONS
1960 //
1961 //=================================================================================================
1962 
1963 //*************************************************************************************************
1965 template< typename MT1, typename MT2 >
1966 struct IsStrictlyUpper< DMatTSMatMultExpr<MT1,MT2> >
1967  : public IsTrue< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
1968  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
1969 {};
1971 //*************************************************************************************************
1972 
1973 
1974 
1975 
1976 //=================================================================================================
1977 //
1978 // EXPRESSION TRAIT SPECIALIZATIONS
1979 //
1980 //=================================================================================================
1981 
1982 //*************************************************************************************************
1984 template< typename MT1, typename MT2, typename VT >
1985 struct DMatDVecMultExprTrait< DMatTSMatMultExpr<MT1,MT2>, VT >
1986 {
1987  public:
1988  //**********************************************************************************************
1989  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1990  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
1991  IsDenseVector<VT>::value && IsColumnVector<VT>::value
1992  , typename DMatDVecMultExprTrait< MT1, typename TSMatDVecMultExprTrait<MT2,VT>::Type >::Type
1993  , INVALID_TYPE >::Type Type;
1994  //**********************************************************************************************
1995 };
1997 //*************************************************************************************************
1998 
1999 
2000 //*************************************************************************************************
2002 template< typename MT1, typename MT2, typename VT >
2003 struct DMatSVecMultExprTrait< DMatTSMatMultExpr<MT1,MT2>, VT >
2004 {
2005  public:
2006  //**********************************************************************************************
2007  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
2008  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
2009  IsSparseVector<VT>::value && IsColumnVector<VT>::value
2010  , typename DMatSVecMultExprTrait< MT1, typename TSMatSVecMultExprTrait<MT2,VT>::Type >::Type
2011  , INVALID_TYPE >::Type Type;
2012  //**********************************************************************************************
2013 };
2015 //*************************************************************************************************
2016 
2017 
2018 //*************************************************************************************************
2020 template< typename VT, typename MT1, typename MT2 >
2021 struct TDVecDMatMultExprTrait< VT, DMatTSMatMultExpr<MT1,MT2> >
2022 {
2023  public:
2024  //**********************************************************************************************
2025  typedef typename SelectType< IsDenseVector<VT>::value && IsRowVector<VT>::value &&
2026  IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
2027  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
2028  , typename TDVecTSMatMultExprTrait< typename TDVecDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
2029  , INVALID_TYPE >::Type Type;
2030  //**********************************************************************************************
2031 };
2033 //*************************************************************************************************
2034 
2035 
2036 //*************************************************************************************************
2038 template< typename VT, typename MT1, typename MT2 >
2039 struct TSVecDMatMultExprTrait< VT, DMatTSMatMultExpr<MT1,MT2> >
2040 {
2041  public:
2042  //**********************************************************************************************
2043  typedef typename SelectType< IsSparseVector<VT>::value && IsRowVector<VT>::value &&
2044  IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
2045  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
2046  , typename TDVecTSMatMultExprTrait< typename TSVecDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
2047  , INVALID_TYPE >::Type Type;
2048  //**********************************************************************************************
2049 };
2051 //*************************************************************************************************
2052 
2053 
2054 //*************************************************************************************************
2056 template< typename MT1, typename MT2, bool AF >
2057 struct SubmatrixExprTrait< DMatTSMatMultExpr<MT1,MT2>, AF >
2058 {
2059  public:
2060  //**********************************************************************************************
2061  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT1,AF>::Type
2062  , typename SubmatrixExprTrait<const MT2,AF>::Type >::Type Type;
2063  //**********************************************************************************************
2064 };
2066 //*************************************************************************************************
2067 
2068 
2069 //*************************************************************************************************
2071 template< typename MT1, typename MT2 >
2072 struct RowExprTrait< DMatTSMatMultExpr<MT1,MT2> >
2073 {
2074  public:
2075  //**********************************************************************************************
2076  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
2077  //**********************************************************************************************
2078 };
2080 //*************************************************************************************************
2081 
2082 
2083 //*************************************************************************************************
2085 template< typename MT1, typename MT2 >
2086 struct ColumnExprTrait< DMatTSMatMultExpr<MT1,MT2> >
2087 {
2088  public:
2089  //**********************************************************************************************
2090  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
2091  //**********************************************************************************************
2092 };
2094 //*************************************************************************************************
2095 
2096 } // namespace blaze
2097 
2098 #endif
#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
ResultType::ElementType ElementType
Resulting element type.
Definition: DMatTSMatMultExpr.h:199
const MT::ElementType max(const DenseMatrix< MT, SO > &dm)
Returns the largest element of the dense matrix.
Definition: DenseMatrix.h:1729
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.
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: DMatTSMatMultExpr.h:246
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
SelectType< IsExpression< MT1 >::value, const MT1, const MT1 & >::Type LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: DMatTSMatMultExpr.h:204
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.
MT2::CompositeType CT2
Composite type of the right-hand side sparse matrix expression.
Definition: DMatTSMatMultExpr.h:137
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
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: DMatTSMatMultExpr.h:377
Header file for the IsSparseMatrix type trait.
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:207
Header file for the IsDiagonal type trait.
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional matrix type...
Definition: DenseMatrix.h: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
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: DMatTSMatMultExpr.h:198
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
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
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
Constraints on the storage order of matrix types.
Header file for the RequiresEvaluation type trait.
System settings for performance optimizations.
LeftOperand leftOperand() const
Returns the left-hand side dense matrix operand.
Definition: DMatTSMatMultExpr.h:355
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
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes...
Definition: Forward.h:117
Constraint on the data type.
const ResultType CompositeType
Data type for composite expression templates.
Definition: DMatTSMatMultExpr.h:201
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
bool isAligned() const
Returns whether the operands of the expression are properly aligned in memory.
Definition: DMatTSMatMultExpr.h:399
DMatTSMatMultExpr(const MT1 &lhs, const MT2 &rhs)
Constructor for the DMatTSMatMultExpr class.
Definition: DMatTSMatMultExpr.h:231
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.
Header file for the multiplication trait.
Header file for the IsStrictlyUpper type trait.
Header file for the IsSymmetric type trait.
size_t rows() const
Returns the current number of rows of the matrix.
Definition: DMatTSMatMultExpr.h:335
Namespace of the Blaze C++ math library.
Definition: Blaze.h:57
Compile time check for row-major matrix types.This type trait tests whether or not the given template...
Definition: IsRowMajorMatrix.h:110
#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a column-major dense or sparse matri...
Definition: ColumnMajorMatrix.h:79
MT1::CompositeType CT1
Composite type of the left-hand side dense matrix expression.
Definition: DMatTSMatMultExpr.h:136
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2592
Header file for the Or class template.
Header file for the TDVecTSMatMultExprTrait class template.
#define BLAZE_THROW_OUT_OF_RANGE(MESSAGE)
Macro for the emission of a std::out_of_range 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.
Header file for the TSMatDVecMultExprTrait class template.
RT2::ElementType ET2
Element type of the right-hand side sparse matrix expression.
Definition: DMatTSMatMultExpr.h:135
SelectType< evaluateLeft, const RT1, CT1 >::Type LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: DMatTSMatMultExpr.h:210
Header file for the DMatDVecMultExprTrait class template.
MT1::ResultType RT1
Result type of the left-hand side dense matrix expression.
Definition: DMatTSMatMultExpr.h:132
Header file for the IsLower type trait.
Header file for the IsAligned type trait.
ResultType::OppositeType OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: DMatTSMatMultExpr.h:197
#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.
RT1::ElementType ET1
Element type of the left-hand side dense matrix expression.
Definition: DMatTSMatMultExpr.h:134
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
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: DMatTSMatMultExpr.h:417
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.
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
Base class for all matrix/matrix multiplication expression templates.The MatMatMultExpr class serves ...
Definition: MatMatMultExpr.h:65
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
Header file for the IsSparseVector type trait.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a symmetric matrix type, a compilation error is created.
Definition: Symmetric.h:116
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.
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
const ElementType ReturnType
Return type for expression template evaluations.
Definition: DMatTSMatMultExpr.h:200
MultTrait< RT1, RT2 >::Type ResultType
Result type for expression template evaluations.
Definition: DMatTSMatMultExpr.h:196
const bool useOptimizedKernels
Configuration switch for optimized kernels.This configuration switch enables/disables all optimized c...
Definition: Optimizations.h:84
RightOperand rightOperand() const
Returns the right-hand side transpose sparse matrix operand.
Definition: DMatTSMatMultExpr.h:365
Header file for the reset shim.
SelectType< evaluateRight, const RT2, CT2 >::Type RT
Type for the assignment of the right-hand side sparse matrix operand.
Definition: DMatTSMatMultExpr.h:213
Expression object for dense matrix-transpose sparse matrix multiplications.The DMatTSMatMultExpr clas...
Definition: DMatTSMatMultExpr.h:126
Constraints on the storage order of matrix types.
Header file for the RemoveReference type trait.
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: DMatTSMatMultExpr.h:389
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.
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: DMatTSMatMultExpr.h:319
Compile time check for strictly lower triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyLower.h:86
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: DMatTSMatMultExpr.h:409
LeftOperand lhs_
Left-hand side dense matrix of the multiplication expression.
Definition: DMatTSMatMultExpr.h:416
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.
Base class for all compute expression templates.The Computation class serves as a tag for all computa...
Definition: Computation.h:59
Header file for the TDVecDMatMultExprTrait class template.
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
#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
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:2583
Header file for the IsTrue value trait.
Header file for the TSVecDMatMultExprTrait class template.
size_t columns() const
Returns the current number of columns of the matrix.
Definition: DMatTSMatMultExpr.h:345
Header file for the IsUpper type trait.
Header file for exception macros.
MT2::ResultType RT2
Result type of the right-hand side sparse matrix expression.
Definition: DMatTSMatMultExpr.h:133
Header file for the DMatSVecMultExprTrait class template.
Header file for the IsColumnVector type trait.
Constraint on the data type.
Header file for the IsResizable type trait.
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
DMatTSMatMultExpr< MT1, MT2 > This
Type of this DMatTSMatMultExpr instance.
Definition: DMatTSMatMultExpr.h:195
#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
SelectType< IsExpression< MT2 >::value, const MT2, const MT2 & >::Type RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: DMatTSMatMultExpr.h:207
Header file for the IsExpression type trait class.
Header file for the TSMatSVecMultExprTrait class template.
Header file for the FunctionTrace class.