All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TDMatTSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_TDMATTSMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_TDMATTSMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <stdexcept>
52 #include <blaze/math/Intrinsics.h>
54 #include <blaze/math/shims/Reset.h>
86 #include <blaze/util/Assert.h>
88 #include <blaze/util/DisableIf.h>
89 #include <blaze/util/EnableIf.h>
90 #include <blaze/util/InvalidType.h>
92 #include <blaze/util/SelectType.h>
93 #include <blaze/util/Types.h>
96 
97 
98 namespace blaze {
99 
100 //=================================================================================================
101 //
102 // CLASS TDMATTSMATMULTEXPR
103 //
104 //=================================================================================================
105 
106 //*************************************************************************************************
113 template< typename MT1 // Type of the left-hand side dense matrix
114  , typename MT2 > // Type of the right-hand side sparse matrix
115 class TDMatTSMatMultExpr : public DenseMatrix< TDMatTSMatMultExpr<MT1,MT2>, true >
116  , private MatMatMultExpr
117  , private Computation
118 {
119  private:
120  //**Type definitions****************************************************************************
121  typedef typename MT1::ResultType RT1;
122  typedef typename MT2::ResultType RT2;
123  typedef typename RT1::ElementType ET1;
124  typedef typename RT2::ElementType ET2;
125  typedef typename MT1::CompositeType CT1;
126  typedef typename MT2::CompositeType CT2;
127  //**********************************************************************************************
128 
129  //**********************************************************************************************
132  //**********************************************************************************************
133 
134  //**********************************************************************************************
136  enum { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
137  //**********************************************************************************************
138 
139  //**********************************************************************************************
141 
147  template< typename T1, typename T2, typename T3 >
148  struct CanExploitSymmetry {
149  enum { value = IsRowMajorMatrix<T1>::value &&
150  ( IsSymmetric<T2>::value || IsSymmetric<T3>::value ) };
151  };
153  //**********************************************************************************************
154 
155  //**********************************************************************************************
157 
161  template< typename T1, typename T2, typename T3 >
162  struct IsEvaluationRequired {
163  enum { value = ( evaluateLeft || evaluateRight ) &&
164  !CanExploitSymmetry<T1,T2,T3>::value };
165  };
167  //**********************************************************************************************
168 
169  //**********************************************************************************************
171 
174  template< typename T1, typename T2, typename T3 >
175  struct UseVectorizedKernel {
176  enum { value = T1::vectorizable && T2::vectorizable &&
177  IsColumnMajorMatrix<T1>::value &&
178  IsSame<typename T1::ElementType,typename T2::ElementType>::value &&
179  IsSame<typename T1::ElementType,typename T3::ElementType>::value &&
180  IntrinsicTrait<typename T1::ElementType>::addition &&
181  IntrinsicTrait<typename T1::ElementType>::subtraction &&
182  IntrinsicTrait<typename T1::ElementType>::multiplication };
183  };
185  //**********************************************************************************************
186 
187  //**********************************************************************************************
189 
193  template< typename T1, typename T2, typename T3 >
194  struct UseOptimizedKernel {
195  enum { value = !UseVectorizedKernel<T1,T2,T3>::value &&
196  !IsResizable<typename T1::ElementType>::value &&
197  !IsResizable<ET1>::value };
198  };
200  //**********************************************************************************************
201 
202  //**********************************************************************************************
204 
207  template< typename T1, typename T2, typename T3 >
208  struct UseDefaultKernel {
209  enum { value = !UseVectorizedKernel<T1,T2,T3>::value &&
210  !UseOptimizedKernel<T1,T2,T3>::value };
211  };
213  //**********************************************************************************************
214 
215  public:
216  //**Type definitions****************************************************************************
223  typedef const ElementType ReturnType;
224  typedef const ResultType CompositeType;
225 
227  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
228 
230  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
231 
234 
237  //**********************************************************************************************
238 
239  //**Compilation flags***************************************************************************
241  enum { vectorizable = MT1::vectorizable &&
245 
247  enum { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
248  !evaluateRight && MT2::smpAssignable };
249  //**********************************************************************************************
250 
251  //**Constructor*********************************************************************************
257  explicit inline TDMatTSMatMultExpr( const MT1& lhs, const MT2& rhs )
258  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
259  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
260  {
261  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
262  }
263  //**********************************************************************************************
264 
265  //**Access operator*****************************************************************************
272  inline ReturnType operator()( size_t i, size_t j ) const {
273  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
274  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
275 
277 
278  ElementType tmp = ElementType();
279 
280  // Early exit
281  if( lhs_.columns() == 0UL )
282  return tmp;
283 
284  // Fast computation in case the right-hand side sparse matrix directly provides iterators
286  {
287  CT2 B( rhs_ ); // Evaluation of the right-hand side sparse matrix operand
288 
289  const ConstIterator end( B.end(j) );
290  ConstIterator element( B.begin(j) );
291 
292  // Early exit in case column j is empty
293  if( element == end )
294  return tmp;
295 
296  // Calculating element (i,j)
297  tmp = lhs_(i,element->index()) * element->value();
298  ++element;
299  for( ; element!=end; ++element )
300  tmp += lhs_(i,element->index()) * element->value();
301  }
302 
303  // Default computation in case the right-hand side sparse matrix doesn't provide iterators
304  else {
305  tmp = lhs_(i,0UL) * rhs_(0UL,j);
306  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
307  tmp += lhs_(i,k) * rhs_(k,j);
308  }
309  }
310 
311  return tmp;
312  }
313  //**********************************************************************************************
314 
315  //**Rows function*******************************************************************************
320  inline size_t rows() const {
321  return lhs_.rows();
322  }
323  //**********************************************************************************************
324 
325  //**Columns function****************************************************************************
330  inline size_t columns() const {
331  return rhs_.columns();
332  }
333  //**********************************************************************************************
334 
335  //**Left operand access*************************************************************************
340  inline LeftOperand leftOperand() const {
341  return lhs_;
342  }
343  //**********************************************************************************************
344 
345  //**Right operand access************************************************************************
350  inline RightOperand rightOperand() const {
351  return rhs_;
352  }
353  //**********************************************************************************************
354 
355  //**********************************************************************************************
361  template< typename T >
362  inline bool canAlias( const T* alias ) const {
363  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
364  }
365  //**********************************************************************************************
366 
367  //**********************************************************************************************
373  template< typename T >
374  inline bool isAliased( const T* alias ) const {
375  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
376  }
377  //**********************************************************************************************
378 
379  //**********************************************************************************************
384  inline bool isAligned() const {
385  return lhs_.isAligned();
386  }
387  //**********************************************************************************************
388 
389  //**********************************************************************************************
394  inline bool canSMPAssign() const {
395  return ( columns() > SMP_TDMATTSMATMULT_THRESHOLD );
396  }
397  //**********************************************************************************************
398 
399  private:
400  //**Member variables****************************************************************************
403  //**********************************************************************************************
404 
405  //**Assignment to dense matrices****************************************************************
418  template< typename MT // Type of the target dense matrix
419  , bool SO > // Storage order of the target dense matrix
420  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
421  assign( DenseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
422  {
424 
425  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
426  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
427 
428  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
429  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
430 
431  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
432  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
433  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
434  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
435  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
436  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
437 
438  TDMatTSMatMultExpr::selectAssignKernel( ~lhs, A, B );
439  }
441  //**********************************************************************************************
442 
443  //**Default assignment to row-major dense matrices**********************************************
457  template< typename MT3 // Type of the left-hand side target matrix
458  , typename MT4 // Type of the left-hand side matrix operand
459  , typename MT5 > // Type of the right-hand side matrix operand
460  static inline void selectAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
461  {
462  typedef typename MT5::ConstIterator ConstIterator;
463 
464  const size_t iend( A.rows() & size_t(-4) );
465  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == iend, "Invalid end calculation" );
466 
467  for( size_t i=0UL; i<iend; i+=4UL ) {
468  for( size_t j=0UL; j<B.columns(); ++j )
469  {
470  ConstIterator element( B.begin(j) );
471  const ConstIterator end( B.end(j) );
472 
473  if( element == end ) {
474  reset( (~C)(i ,j) );
475  reset( (~C)(i+1UL,j) );
476  reset( (~C)(i+2UL,j) );
477  reset( (~C)(i+3UL,j) );
478  continue;
479  }
480 
481  (~C)(i ,j) = A(i ,element->index()) * element->value();
482  (~C)(i+1UL,j) = A(i+1UL,element->index()) * element->value();
483  (~C)(i+2UL,j) = A(i+2UL,element->index()) * element->value();
484  (~C)(i+3UL,j) = A(i+3UL,element->index()) * element->value();
485  ++element;
486  for( ; element!=end; ++element ) {
487  (~C)(i ,j) += A(i ,element->index()) * element->value();
488  (~C)(i+1UL,j) += A(i+1UL,element->index()) * element->value();
489  (~C)(i+2UL,j) += A(i+2UL,element->index()) * element->value();
490  (~C)(i+3UL,j) += A(i+3UL,element->index()) * element->value();
491  }
492  }
493  }
494 
495  for( size_t i=iend; i<A.rows(); ++i ) {
496  for( size_t j=0UL; j<B.columns(); ++j )
497  {
498  ConstIterator element( B.begin(j) );
499  const ConstIterator end( B.end(j) );
500 
501  if( element == end ) {
502  reset( (~C)(i,j) );
503  continue;
504  }
505 
506  (~C)(i,j) = A(i,element->index()) * element->value();
507  ++element;
508  for( ; element!=end; ++element )
509  (~C)(i,j) += A(i,element->index()) * element->value();
510  }
511  }
512  }
514  //**********************************************************************************************
515 
516  //**Default assignment to column-major dense matrices*******************************************
530  template< typename MT3 // Type of the left-hand side target matrix
531  , typename MT4 // Type of the left-hand side matrix operand
532  , typename MT5 > // Type of the right-hand side matrix operand
533  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
534  selectAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
535  {
536  typedef typename MT5::ConstIterator ConstIterator;
537 
538  for( size_t j=0UL; j<B.columns(); ++j ) {
539  for( size_t i=0UL; i<(~C).rows(); ++i ) {
540  reset( (~C)(i,j) );
541  }
542  ConstIterator element( B.begin(j) );
543  const ConstIterator end( B.end(j) );
544  for( ; element!=end; ++element ) {
545  for( size_t i=0UL; i<A.rows(); ++i ) {
546  if( isDefault( (~C)(i,j) ) )
547  (~C)(i,j) = A(i,element->index()) * element->value();
548  else
549  (~C)(i,j) += A(i,element->index()) * element->value();
550  }
551  }
552  }
553  }
555  //**********************************************************************************************
556 
557  //**Optimized assignment to column-major dense matrices*****************************************
571  template< typename MT3 // Type of the left-hand side target matrix
572  , typename MT4 // Type of the left-hand side matrix operand
573  , typename MT5 > // Type of the right-hand side matrix operand
574  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
575  selectAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
576  {
577  typedef typename MT5::ConstIterator ConstIterator;
578 
579  const size_t iend( A.rows() & size_t(-4) );
580  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == iend, "Invalid end calculation" );
581 
582  reset( ~C );
583 
584  for( size_t j=0UL; j<B.columns(); ++j )
585  {
586  const ConstIterator end( B.end(j) );
587  ConstIterator element( B.begin(j) );
588 
589  const size_t kend( B.nonZeros(j) & size_t(-4) );
590 
591  for( size_t k=0UL; k<kend; k+=4UL ) {
592  const size_t j1( element->index() );
593  const ET2 v1( element->value() );
594  ++element;
595  const size_t j2( element->index() );
596  const ET2 v2( element->value() );
597  ++element;
598  const size_t j3( element->index() );
599  const ET2 v3( element->value() );
600  ++element;
601  const size_t j4( element->index() );
602  const ET2 v4( element->value() );
603  ++element;
604 
605  for( size_t i=0UL; i<iend; i+=4UL ) {
606  (~C)(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
607  (~C)(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
608  (~C)(i+2UL,j) += A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
609  (~C)(i+3UL,j) += A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
610  }
611  for( size_t i=iend; i<A.rows(); ++i ) {
612  (~C)(i,j) += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
613  }
614  }
615 
616  for( ; element!=end; ++element ) {
617  for( size_t i=0UL; i<iend; i+=4UL ) {
618  (~C)(i ,j) += A(i ,element->index()) * element->value();
619  (~C)(i+1UL,j) += A(i+1UL,element->index()) * element->value();
620  (~C)(i+2UL,j) += A(i+2UL,element->index()) * element->value();
621  (~C)(i+3UL,j) += A(i+3UL,element->index()) * element->value();
622  }
623  for( size_t i=iend; i<A.rows(); ++i ) {
624  (~C)(i,j) += A(i,element->index()) * element->value();
625  }
626  }
627  }
628  }
630  //**********************************************************************************************
631 
632  //**Vectorized assignment to column-major dense matrices****************************************
646  template< typename MT3 // Type of the left-hand side target matrix
647  , typename MT4 // Type of the left-hand side matrix operand
648  , typename MT5 > // Type of the right-hand side matrix operand
649  static inline typename EnableIf< UseVectorizedKernel<MT3,MT4,MT5> >::Type
650  selectAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
651  {
652  typedef IntrinsicTrait<ElementType> IT;
653  typedef typename MT5::ConstIterator ConstIterator;
654 
655  const size_t M( A.rows() );
656 
657  reset( ~C );
658 
659  for( size_t j=0UL; j<B.columns(); ++j )
660  {
661  const ConstIterator end( B.end(j) );
662  ConstIterator element( B.begin(j) );
663 
664  const size_t kend( B.nonZeros(j) & size_t(-4) );
665 
666  for( size_t k=0UL; k<kend; k+=4UL ) {
667  const size_t j1( element->index() );
668  const IntrinsicType v1( set( element->value() ) );
669  ++element;
670  const size_t j2( element->index() );
671  const IntrinsicType v2( set( element->value() ) );
672  ++element;
673  const size_t j3( element->index() );
674  const IntrinsicType v3( set( element->value() ) );
675  ++element;
676  const size_t j4( element->index() );
677  const IntrinsicType v4( set( element->value() ) );
678  ++element;
679 
680  for( size_t i=0UL; i<M; i+=IT::size ) {
681  (~C).store( i, j, (~C).load(i,j) + A.load(i,j1) * v1 + A.load(i,j2) * v2 + A.load(i,j3) * v3 + A.load(i,j4) * v4 );
682  }
683  }
684 
685  for( ; element!=end; ++element ) {
686  const size_t j1( element->index() );
687  const IntrinsicType v1( set( element->value() ) );
688 
689  for( size_t i=0UL; i<M; i+=IT::size ) {
690  (~C).store( i, j, (~C).load(i,j) + A.load(i,j1) * v1 );
691  }
692  }
693  }
694  }
696  //**********************************************************************************************
697 
698  //**Assignment to sparse matrices***************************************************************
711  template< typename MT // Type of the target sparse matrix
712  , bool SO > // Storage order of the target sparse matrix
713  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
714  assign( SparseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
715  {
717 
718  typedef typename SelectType< SO, ResultType, OppositeType >::Type TmpType;
719 
726 
727  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
728  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
729 
730  const TmpType tmp( serial( rhs ) );
731  assign( ~lhs, tmp );
732  }
734  //**********************************************************************************************
735 
736  //**Restructuring assignment to row-major matrices************************************************************
751  template< typename MT > // Type of the target matrix
752  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
753  assign( Matrix<MT,false>& lhs, const TDMatTSMatMultExpr& rhs )
754  {
756 
758 
759  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
760  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
761 
762  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
763  assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
764  else if( IsSymmetric<MT1>::value )
765  assign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
766  else
767  assign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
768  }
770  //**********************************************************************************************
771 
772  //**Addition assignment to dense matrices*******************************************************
785  template< typename MT // Type of the target dense matrix
786  , bool SO > // Storage order of the target dense matrix
787  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
788  addAssign( DenseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
789  {
791 
792  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
793  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
794 
795  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
796  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
797 
798  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
799  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
800  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
801  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
802  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
803  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
804 
805  TDMatTSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
806  }
808  //**********************************************************************************************
809 
810  //**Default addition assignment to row-major dense matrices*************************************
824  template< typename MT3 // Type of the left-hand side target matrix
825  , typename MT4 // Type of the left-hand side matrix operand
826  , typename MT5 > // Type of the right-hand side matrix operand
827  static inline void selectAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
828  {
829  typedef typename MT5::ConstIterator ConstIterator;
830 
831  const size_t iend( A.rows() & size_t(-4) );
832  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == iend, "Invalid end calculation" );
833 
834  for( size_t i=0UL; i<iend; i+=4UL ) {
835  for( size_t j=0UL; j<B.columns(); ++j )
836  {
837  ConstIterator element( B.begin(j) );
838  const ConstIterator end( B.end(j) );
839 
840  for( ; element!=end; ++element ) {
841  (~C)(i ,j) += A(i ,element->index()) * element->value();
842  (~C)(i+1UL,j) += A(i+1UL,element->index()) * element->value();
843  (~C)(i+2UL,j) += A(i+2UL,element->index()) * element->value();
844  (~C)(i+3UL,j) += A(i+3UL,element->index()) * element->value();
845  }
846  }
847  }
848 
849  for( size_t i=iend; i<A.rows(); ++i ) {
850  for( size_t j=0UL; j<B.columns(); ++j )
851  {
852  ConstIterator element( B.begin(j) );
853  const ConstIterator end( B.end(j) );
854 
855  for( ; element!=end; ++element )
856  (~C)(i,j) += A(i,element->index()) * element->value();
857  }
858  }
859  }
861  //**********************************************************************************************
862 
863  //**Default addition assignment to column-major dense matrices**********************************
877  template< typename MT3 // Type of the left-hand side target matrix
878  , typename MT4 // Type of the left-hand side matrix operand
879  , typename MT5 > // Type of the right-hand side matrix operand
880  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
881  selectAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
882  {
883  typedef typename MT5::ConstIterator ConstIterator;
884 
885  for( size_t j=0UL; j<B.columns(); ++j ) {
886  ConstIterator element( B.begin(j) );
887  const ConstIterator end( B.end(j) );
888  for( ; element!=end; ++element ) {
889  for( size_t i=0UL; i<A.rows(); ++i ) {
890  if( isDefault( (~C)(i,j) ) )
891  (~C)(i,j) = A(i,element->index()) * element->value();
892  else
893  (~C)(i,j) += A(i,element->index()) * element->value();
894  }
895  }
896  }
897  }
899  //**********************************************************************************************
900 
901  //**Optimized addition assignment to column-major dense matrices********************************
915  template< typename MT3 // Type of the left-hand side target matrix
916  , typename MT4 // Type of the left-hand side matrix operand
917  , typename MT5 > // Type of the right-hand side matrix operand
918  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
919  selectAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
920  {
921  typedef typename MT5::ConstIterator ConstIterator;
922 
923  const size_t iend( A.rows() & size_t(-4) );
924  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == iend, "Invalid end calculation" );
925 
926  for( size_t j=0UL; j<B.columns(); ++j )
927  {
928  const ConstIterator end( B.end(j) );
929  ConstIterator element( B.begin(j) );
930 
931  const size_t kend( B.nonZeros(j) & size_t(-4) );
932 
933  for( size_t k=0UL; k<kend; k+=4UL ) {
934  const size_t j1( element->index() );
935  const ET2 v1( element->value() );
936  ++element;
937  const size_t j2( element->index() );
938  const ET2 v2( element->value() );
939  ++element;
940  const size_t j3( element->index() );
941  const ET2 v3( element->value() );
942  ++element;
943  const size_t j4( element->index() );
944  const ET2 v4( element->value() );
945  ++element;
946 
947  for( size_t i=0UL; i<iend; i+=4UL ) {
948  (~C)(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
949  (~C)(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
950  (~C)(i+2UL,j) += A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
951  (~C)(i+3UL,j) += A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
952  }
953  for( size_t i=iend; i<A.rows(); ++i ) {
954  (~C)(i,j) += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
955  }
956  }
957 
958  for( ; element!=end; ++element ) {
959  for( size_t i=0UL; i<iend; i+=4UL ) {
960  (~C)(i ,j) += A(i ,element->index()) * element->value();
961  (~C)(i+1UL,j) += A(i+1UL,element->index()) * element->value();
962  (~C)(i+2UL,j) += A(i+2UL,element->index()) * element->value();
963  (~C)(i+3UL,j) += A(i+3UL,element->index()) * element->value();
964  }
965  for( size_t i=iend; i<A.rows(); ++i ) {
966  (~C)(i,j) += A(i,element->index()) * element->value();
967  }
968  }
969  }
970  }
972  //**********************************************************************************************
973 
974  //**Vectorized addition assignment to column-major dense matrices*******************************
988  template< typename MT3 // Type of the left-hand side target matrix
989  , typename MT4 // Type of the left-hand side matrix operand
990  , typename MT5 > // Type of the right-hand side matrix operand
991  static inline typename EnableIf< UseVectorizedKernel<MT3,MT4,MT5> >::Type
992  selectAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
993  {
994  typedef IntrinsicTrait<ElementType> IT;
995  typedef typename MT5::ConstIterator ConstIterator;
996 
997  const size_t M( A.rows() );
998 
999  for( size_t j=0UL; j<B.columns(); ++j )
1000  {
1001  const ConstIterator end( B.end(j) );
1002  ConstIterator element( B.begin(j) );
1003 
1004  const size_t kend( B.nonZeros(j) & size_t(-4) );
1005 
1006  for( size_t k=0UL; k<kend; k+=4UL ) {
1007  const size_t j1( element->index() );
1008  const IntrinsicType v1( set( element->value() ) );
1009  ++element;
1010  const size_t j2( element->index() );
1011  const IntrinsicType v2( set( element->value() ) );
1012  ++element;
1013  const size_t j3( element->index() );
1014  const IntrinsicType v3( set( element->value() ) );
1015  ++element;
1016  const size_t j4( element->index() );
1017  const IntrinsicType v4( set( element->value() ) );
1018  ++element;
1019 
1020  for( size_t i=0UL; i<M; i+=IT::size ) {
1021  (~C).store( i, j, (~C).load(i,j) + A.load(i,j1) * v1 + A.load(i,j2) * v2 + A.load(i,j3) * v3 + A.load(i,j4) * v4 );
1022  }
1023  }
1024 
1025  for( ; element!=end; ++element ) {
1026  const size_t j1( element->index() );
1027  const IntrinsicType v1( set( element->value() ) );
1028 
1029  for( size_t i=0UL; i<M; i+=IT::size ) {
1030  (~C).store( i, j, (~C).load(i,j) + A.load(i,j1) * v1 );
1031  }
1032  }
1033  }
1034  }
1036  //**********************************************************************************************
1037 
1038  //**Restructuring addition assignment to row-major matrices*************************************
1053  template< typename MT > // Type of the target matrix
1054  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1055  addAssign( Matrix<MT,false>& lhs, const TDMatTSMatMultExpr& rhs )
1056  {
1058 
1060 
1061  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1062  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1063 
1064  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1065  addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1066  else if( IsSymmetric<MT1>::value )
1067  addAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1068  else
1069  addAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1070  }
1072  //**********************************************************************************************
1073 
1074  //**Addition assignment to sparse matrices******************************************************
1075  // No special implementation for the addition assignment to sparse matrices.
1076  //**********************************************************************************************
1077 
1078  //**Subtraction assignment to dense matrices****************************************************
1091  template< typename MT // Type of the target dense matrix
1092  , bool SO > // Storage order of the target dense matrix
1093  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
1094  {
1096 
1097  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1098  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1099 
1100  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1101  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1102 
1103  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1104  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1105  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1106  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1107  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1108  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1109 
1110  TDMatTSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1111  }
1113  //**********************************************************************************************
1114 
1115  //**Default subtraction assignment to row-major dense matrices**********************************
1129  template< typename MT3 // Type of the left-hand side target matrix
1130  , typename MT4 // Type of the left-hand side matrix operand
1131  , typename MT5 > // Type of the right-hand side matrix operand
1132  static inline void selectSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
1133  {
1134  typedef typename MT5::ConstIterator ConstIterator;
1135 
1136  const size_t iend( A.rows() & size_t(-4) );
1137  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == iend, "Invalid end calculation" );
1138 
1139  for( size_t i=0UL; i<iend; i+=4UL ) {
1140  for( size_t j=0UL; j<B.columns(); ++j )
1141  {
1142  ConstIterator element( B.begin(j) );
1143  const ConstIterator end( B.end(j) );
1144 
1145  for( ; element!=end; ++element ) {
1146  (~C)(i ,j) -= A(i ,element->index()) * element->value();
1147  (~C)(i+1UL,j) -= A(i+1UL,element->index()) * element->value();
1148  (~C)(i+2UL,j) -= A(i+2UL,element->index()) * element->value();
1149  (~C)(i+3UL,j) -= A(i+3UL,element->index()) * element->value();
1150  }
1151  }
1152  }
1153 
1154  for( size_t i=iend; i<A.rows(); ++i ) {
1155  for( size_t j=0UL; j<B.columns(); ++j )
1156  {
1157  ConstIterator element( B.begin(j) );
1158  const ConstIterator end( B.end(j) );
1159 
1160  for( ; element!=end; ++element )
1161  (~C)(i,j) -= A(i,element->index()) * element->value();
1162  }
1163  }
1164  }
1166  //**********************************************************************************************
1167 
1168  //**Default subtraction assignment to column-major dense matrices*******************************
1182  template< typename MT3 // Type of the left-hand side target matrix
1183  , typename MT4 // Type of the left-hand side matrix operand
1184  , typename MT5 > // Type of the right-hand side matrix operand
1185  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
1186  selectSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
1187  {
1188  typedef typename MT5::ConstIterator ConstIterator;
1189 
1190  for( size_t j=0UL; j<B.columns(); ++j ) {
1191  ConstIterator element( B.begin(j) );
1192  const ConstIterator end( B.end(j) );
1193  for( ; element!=end; ++element ) {
1194  for( size_t i=0UL; i<A.rows(); ++i ) {
1195  if( isDefault( (~C)(i,j) ) )
1196  (~C)(i,j) = -A(i,element->index()) * element->value();
1197  else
1198  (~C)(i,j) -= A(i,element->index()) * element->value();
1199  }
1200  }
1201  }
1202  }
1204  //**********************************************************************************************
1205 
1206  //**Optimized subtraction assignment to column-major dense matrices*****************************
1220  template< typename MT3 // Type of the left-hand side target matrix
1221  , typename MT4 // Type of the left-hand side matrix operand
1222  , typename MT5 > // Type of the right-hand side matrix operand
1223  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
1224  selectSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
1225  {
1226  typedef typename MT5::ConstIterator ConstIterator;
1227 
1228  const size_t iend( A.rows() & size_t(-4) );
1229  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == iend, "Invalid end calculation" );
1230 
1231  for( size_t j=0UL; j<B.columns(); ++j )
1232  {
1233  const ConstIterator end( B.end(j) );
1234  ConstIterator element( B.begin(j) );
1235 
1236  const size_t kend( B.nonZeros(j) & size_t(-4) );
1237 
1238  for( size_t k=0UL; k<kend; k+=4UL ) {
1239  const size_t j1( element->index() );
1240  const ET2 v1( element->value() );
1241  ++element;
1242  const size_t j2( element->index() );
1243  const ET2 v2( element->value() );
1244  ++element;
1245  const size_t j3( element->index() );
1246  const ET2 v3( element->value() );
1247  ++element;
1248  const size_t j4( element->index() );
1249  const ET2 v4( element->value() );
1250  ++element;
1251 
1252  for( size_t i=0UL; i<iend; i+=4UL ) {
1253  (~C)(i ,j) -= A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
1254  (~C)(i+1UL,j) -= A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
1255  (~C)(i+2UL,j) -= A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
1256  (~C)(i+3UL,j) -= A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
1257  }
1258  for( size_t i=iend; i<A.rows(); ++i ) {
1259  (~C)(i,j) -= A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
1260  }
1261  }
1262 
1263  for( ; element!=end; ++element ) {
1264  for( size_t i=0UL; i<iend; i+=4UL ) {
1265  (~C)(i ,j) -= A(i ,element->index()) * element->value();
1266  (~C)(i+1UL,j) -= A(i+1UL,element->index()) * element->value();
1267  (~C)(i+2UL,j) -= A(i+2UL,element->index()) * element->value();
1268  (~C)(i+3UL,j) -= A(i+3UL,element->index()) * element->value();
1269  }
1270  for( size_t i=iend; i<A.rows(); ++i ) {
1271  (~C)(i,j) -= A(i,element->index()) * element->value();
1272  }
1273  }
1274  }
1275  }
1277  //**********************************************************************************************
1278 
1279  //**Vectorized subtraction assignment to column-major dense matrices****************************
1293  template< typename MT3 // Type of the left-hand side target matrix
1294  , typename MT4 // Type of the left-hand side matrix operand
1295  , typename MT5 > // Type of the right-hand side matrix operand
1296  static inline typename EnableIf< UseVectorizedKernel<MT3,MT4,MT5> >::Type
1297  selectSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
1298  {
1299  typedef IntrinsicTrait<ElementType> IT;
1300  typedef typename MT5::ConstIterator ConstIterator;
1301 
1302  const size_t M( A.rows() );
1303 
1304  for( size_t j=0UL; j<B.columns(); ++j )
1305  {
1306  const ConstIterator end( B.end(j) );
1307  ConstIterator element( B.begin(j) );
1308 
1309  const size_t kend( B.nonZeros(j) & size_t(-4) );
1310 
1311  for( size_t k=0UL; k<kend; k+=4UL ) {
1312  const size_t j1( element->index() );
1313  const IntrinsicType v1( set( element->value() ) );
1314  ++element;
1315  const size_t j2( element->index() );
1316  const IntrinsicType v2( set( element->value() ) );
1317  ++element;
1318  const size_t j3( element->index() );
1319  const IntrinsicType v3( set( element->value() ) );
1320  ++element;
1321  const size_t j4( element->index() );
1322  const IntrinsicType v4( set( element->value() ) );
1323  ++element;
1324 
1325  for( size_t i=0UL; i<M; i+=IT::size ) {
1326  (~C).store( i, j, (~C).load(i,j) - A.load(i,j1) * v1 - A.load(i,j2) * v2 - A.load(i,j3) * v3 - A.load(i,j4) * v4 );
1327  }
1328  }
1329 
1330  for( ; element!=end; ++element ) {
1331  const size_t j1( element->index() );
1332  const IntrinsicType v1( set( element->value() ) );
1333 
1334  for( size_t i=0UL; i<M; i+=IT::size ) {
1335  (~C).store( i, j, (~C).load(i,j) - A.load(i,j1) * v1 );
1336  }
1337  }
1338  }
1339  }
1341  //**********************************************************************************************
1342 
1343  //**Restructuring subtraction assignment to row-major matrices**********************************
1359  template< typename MT > // Type of the target matrix
1360  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1361  subAssign( Matrix<MT,false>& lhs, const TDMatTSMatMultExpr& rhs )
1362  {
1364 
1366 
1367  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1368  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1369 
1370  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1371  subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1372  else if( IsSymmetric<MT1>::value )
1373  subAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1374  else
1375  subAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1376  }
1378  //**********************************************************************************************
1379 
1380  //**Subtraction assignment to sparse matrices***************************************************
1381  // No special implementation for the subtraction assignment to sparse matrices.
1382  //**********************************************************************************************
1383 
1384  //**Multiplication assignment to dense matrices*************************************************
1385  // No special implementation for the multiplication assignment to dense matrices.
1386  //**********************************************************************************************
1387 
1388  //**Multiplication assignment to sparse matrices************************************************
1389  // No special implementation for the multiplication assignment to sparse matrices.
1390  //**********************************************************************************************
1391 
1392  //**SMP assignment to dense matrices************************************************************
1408  template< typename MT // Type of the target dense matrix
1409  , bool SO > // Storage order of the target dense matrix
1410  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1411  smpAssign( DenseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
1412  {
1414 
1415  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1416  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1417 
1418  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1419  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1420 
1421  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1422  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1423  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1424  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1425  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1426  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1427 
1428  smpAssign( ~lhs, A * B );
1429  }
1431  //**********************************************************************************************
1432 
1433  //**SMP assignment to sparse matrices***********************************************************
1449  template< typename MT // Type of the target sparse matrix
1450  , bool SO > // Storage order of the target sparse matrix
1451  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1452  smpAssign( SparseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
1453  {
1455 
1456  typedef typename SelectType< SO, ResultType, OppositeType >::Type TmpType;
1457 
1464 
1465  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1466  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1467 
1468  const TmpType tmp( rhs );
1469  smpAssign( ~lhs, tmp );
1470  }
1472  //**********************************************************************************************
1473 
1474  //**Restructuring SMP assignment to row-major matrices******************************************
1489  template< typename MT > // Type of the target matrix
1490  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1491  smpAssign( Matrix<MT,false>& lhs, const TDMatTSMatMultExpr& rhs )
1492  {
1494 
1496 
1497  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1498  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1499 
1500  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1501  smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1502  else if( IsSymmetric<MT1>::value )
1503  smpAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1504  else
1505  smpAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1506  }
1508  //**********************************************************************************************
1509 
1510  //**SMP addition assignment to dense matrices***************************************************
1526  template< typename MT // Type of the target dense matrix
1527  , bool SO > // Storage order of the target dense matrix
1528  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1529  smpAddAssign( DenseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
1530  {
1532 
1533  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1534  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1535 
1536  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1537  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1538 
1539  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1540  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1541  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1542  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1543  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1544  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1545 
1546  smpAddAssign( ~lhs, A * B );
1547  }
1549  //**********************************************************************************************
1550 
1551  //**Restructuring SMP addition assignment to row-major matrices*********************************
1567  template< typename MT > // Type of the target matrix
1568  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1569  smpAddAssign( Matrix<MT,false>& lhs, const TDMatTSMatMultExpr& rhs )
1570  {
1572 
1574 
1575  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1576  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1577 
1578  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1579  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1580  else if( IsSymmetric<MT1>::value )
1581  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1582  else
1583  smpAddAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1584  }
1586  //**********************************************************************************************
1587 
1588  //**SMP addition assignment to sparse matrices**************************************************
1589  // No special implementation for the SMP addition assignment to sparse matrices.
1590  //**********************************************************************************************
1591 
1592  //**SMP subtraction assignment to dense matrices************************************************
1608  template< typename MT // Type of the target dense matrix
1609  , bool SO > // Storage order of the target dense matrix
1610  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1611  smpSubAssign( DenseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
1612  {
1614 
1615  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1616  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1617 
1618  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1619  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1620 
1621  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1622  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1623  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1624  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1625  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1626  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1627 
1628  smpSubAssign( ~lhs, A * B );
1629  }
1631  //**********************************************************************************************
1632 
1633  //**Restructuring SMP subtraction assignment to row-major matrices******************************
1649  template< typename MT > // Type of the target matrix
1650  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1651  smpSubAssign( Matrix<MT,false>& lhs, const TDMatTSMatMultExpr& rhs )
1652  {
1654 
1656 
1657  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1658  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1659 
1660  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1661  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1662  else if( IsSymmetric<MT1>::value )
1663  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1664  else
1665  smpSubAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1666  }
1668  //**********************************************************************************************
1669 
1670  //**SMP subtraction assignment to sparse matrices***********************************************
1671  // No special implementation for the SMP subtraction assignment to sparse matrices.
1672  //**********************************************************************************************
1673 
1674  //**SMP multiplication assignment to dense matrices*********************************************
1675  // No special implementation for the SMP multiplication assignment to dense matrices.
1676  //**********************************************************************************************
1677 
1678  //**SMP multiplication assignment to sparse matrices********************************************
1679  // No special implementation for the SMP multiplication assignment to sparse matrices.
1680  //**********************************************************************************************
1681 
1682  //**Compile time checks*************************************************************************
1690  //**********************************************************************************************
1691 };
1692 //*************************************************************************************************
1693 
1694 
1695 
1696 
1697 //=================================================================================================
1698 //
1699 // GLOBAL BINARY ARITHMETIC OPERATORS
1700 //
1701 //=================================================================================================
1702 
1703 //*************************************************************************************************
1732 template< typename T1 // Type of the left-hand side dense matrix
1733  , typename T2 > // Type of the right-hand side sparse matrix
1734 inline const TDMatTSMatMultExpr<T1,T2>
1736 {
1738 
1739  if( (~lhs).columns() != (~rhs).rows() )
1740  throw std::invalid_argument( "Matrix sizes do not match" );
1741 
1742  return TDMatTSMatMultExpr<T1,T2>( ~lhs, ~rhs );
1743 }
1744 //*************************************************************************************************
1745 
1746 
1747 
1748 
1749 //=================================================================================================
1750 //
1751 // ROWS SPECIALIZATIONS
1752 //
1753 //=================================================================================================
1754 
1755 //*************************************************************************************************
1757 template< typename MT1, typename MT2 >
1758 struct Rows< TDMatTSMatMultExpr<MT1,MT2> >
1759  : public Rows<MT1>
1760 {};
1762 //*************************************************************************************************
1763 
1764 
1765 
1766 
1767 //=================================================================================================
1768 //
1769 // COLUMNS SPECIALIZATIONS
1770 //
1771 //=================================================================================================
1772 
1773 //*************************************************************************************************
1775 template< typename MT1, typename MT2 >
1776 struct Columns< TDMatTSMatMultExpr<MT1,MT2> >
1777  : public Columns<MT2>
1778 {};
1780 //*************************************************************************************************
1781 
1782 
1783 
1784 
1785 //=================================================================================================
1786 //
1787 // ISLOWER SPECIALIZATIONS
1788 //
1789 //=================================================================================================
1790 
1791 //*************************************************************************************************
1793 template< typename MT1, typename MT2 >
1794 struct IsLower< TDMatTSMatMultExpr<MT1,MT2> >
1795  : public IsTrue< IsLower<MT1>::value && IsLower<MT2>::value >
1796 {};
1798 //*************************************************************************************************
1799 
1800 
1801 
1802 
1803 //=================================================================================================
1804 //
1805 // ISUPPER SPECIALIZATIONS
1806 //
1807 //=================================================================================================
1808 
1809 //*************************************************************************************************
1811 template< typename MT1, typename MT2 >
1812 struct IsUpper< TDMatTSMatMultExpr<MT1,MT2> >
1813  : public IsTrue< IsUpper<MT1>::value && IsUpper<MT2>::value >
1814 {};
1816 //*************************************************************************************************
1817 
1818 
1819 
1820 
1821 //=================================================================================================
1822 //
1823 // EXPRESSION TRAIT SPECIALIZATIONS
1824 //
1825 //=================================================================================================
1826 
1827 //*************************************************************************************************
1829 template< typename MT1, typename MT2, typename VT >
1830 struct TDMatDVecMultExprTrait< TDMatTSMatMultExpr<MT1,MT2>, VT >
1831 {
1832  public:
1833  //**********************************************************************************************
1834  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1835  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
1836  IsDenseVector<VT>::value && IsColumnVector<VT>::value
1837  , typename TDMatDVecMultExprTrait< MT1, typename TSMatDVecMultExprTrait<MT2,VT>::Type >::Type
1838  , INVALID_TYPE >::Type Type;
1839  //**********************************************************************************************
1840 };
1842 //*************************************************************************************************
1843 
1844 
1845 //*************************************************************************************************
1847 template< typename MT1, typename MT2, typename VT >
1848 struct TDMatSVecMultExprTrait< TDMatTSMatMultExpr<MT1,MT2>, VT >
1849 {
1850  public:
1851  //**********************************************************************************************
1852  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1853  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
1854  IsSparseVector<VT>::value && IsColumnVector<VT>::value
1855  , typename TDMatDVecMultExprTrait< MT1, typename TSMatDVecMultExprTrait<MT2,VT>::Type >::Type
1856  , INVALID_TYPE >::Type Type;
1857  //**********************************************************************************************
1858 };
1860 //*************************************************************************************************
1861 
1862 
1863 //*************************************************************************************************
1865 template< typename VT, typename MT1, typename MT2 >
1866 struct TDVecTDMatMultExprTrait< VT, TDMatTSMatMultExpr<MT1,MT2> >
1867 {
1868  public:
1869  //**********************************************************************************************
1870  typedef typename SelectType< IsDenseVector<VT>::value && IsRowVector<VT>::value &&
1871  IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1872  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
1873  , typename TDVecTSMatMultExprTrait< typename TDVecTDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1874  , INVALID_TYPE >::Type Type;
1875  //**********************************************************************************************
1876 };
1878 //*************************************************************************************************
1879 
1880 
1881 //*************************************************************************************************
1883 template< typename VT, typename MT1, typename MT2 >
1884 struct TSVecTDMatMultExprTrait< VT, TDMatTSMatMultExpr<MT1,MT2> >
1885 {
1886  public:
1887  //**********************************************************************************************
1888  typedef typename SelectType< IsSparseVector<VT>::value && IsRowVector<VT>::value &&
1889  IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1890  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
1891  , typename TDVecTSMatMultExprTrait< typename TSVecTDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1892  , INVALID_TYPE >::Type Type;
1893  //**********************************************************************************************
1894 };
1896 //*************************************************************************************************
1897 
1898 
1899 //*************************************************************************************************
1901 template< typename MT1, typename MT2, bool AF >
1902 struct SubmatrixExprTrait< TDMatTSMatMultExpr<MT1,MT2>, AF >
1903 {
1904  public:
1905  //**********************************************************************************************
1906  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT1,AF>::Type
1907  , typename SubmatrixExprTrait<const MT2,AF>::Type >::Type Type;
1908  //**********************************************************************************************
1909 };
1911 //*************************************************************************************************
1912 
1913 
1914 //*************************************************************************************************
1916 template< typename MT1, typename MT2 >
1917 struct RowExprTrait< TDMatTSMatMultExpr<MT1,MT2> >
1918 {
1919  public:
1920  //**********************************************************************************************
1921  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
1922  //**********************************************************************************************
1923 };
1925 //*************************************************************************************************
1926 
1927 
1928 //*************************************************************************************************
1930 template< typename MT1, typename MT2 >
1931 struct ColumnExprTrait< TDMatTSMatMultExpr<MT1,MT2> >
1932 {
1933  public:
1934  //**********************************************************************************************
1935  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
1936  //**********************************************************************************************
1937 };
1939 //*************************************************************************************************
1940 
1941 } // namespace blaze
1942 
1943 #endif
RT1::ElementType ET1
Element type of the left-hand side dense matrix expression.
Definition: TDMatTSMatMultExpr.h:123
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:89
Header file for the Rows 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:4838
BLAZE_ALWAYS_INLINE size_t size(const Vector< VT, TF > &vector)
Returns the current size/dimension of the vector.
Definition: Vector.h:258
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:258
Expression object for transpose dense matrix-transpose sparse matrix multiplications.The TDMatTSMatMultExpr class represents the compile time expression for multiplications between a column-major dense matrix and a column-major sparse matrix.
Definition: Forward.h:132
Header file for the IsSparseMatrix type trait.
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:205
#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.
const ResultType CompositeType
Data type for composite expression templates.
Definition: TDMatTSMatMultExpr.h:224
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2478
Header file for the IsRowVector type trait.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:257
const DMatSerialExpr< MT, SO > serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:695
Header file for the Computation base class.
Header file for the MatMatMultExpr base class.
Type relationship analysis.This class tests if the two data types A and B are equal. For this type comparison, the cv-qualifiers of both data types are ignored. If A and B are the same data type (ignoring the cv-qualifiers), then the value member enumeration is set to 1, the nested type definition Type is TrueType, and the class derives from TrueType. Otherwise value is set to 0, Type is FalseType, and the class derives from FalseType.
Definition: IsSame.h:158
Header file for the RequiresEvaluation type trait.
SelectType< IsExpression< MT1 >::value, const MT1, const MT1 & >::Type LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: TDMatTSMatMultExpr.h:227
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:107
size_t rows() const
Returns the current number of rows of the matrix.
Definition: TDMatTSMatMultExpr.h:320
Constraint on the data type.
TDMatTSMatMultExpr(const MT1 &lhs, const MT2 &rhs)
Constructor for the TDMatTSMatMultExpr class.
Definition: TDMatTSMatMultExpr.h:257
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
const size_t SMP_TDMATTSMATMULT_THRESHOLD
SMP column-major dense matrix/column-major sparse matrix multiplication threshold.This threshold specifies when a column-major dense matrix/column-major sparse matrix multiplication can be executed in parallel. In case the number of rows/columns of the target matrix is larger or equal to this threshold, the operation is executed in parallel. If the number of rows/columns is below this threshold the operation is executed single-threaded.
Definition: Thresholds.h:995
IntrinsicTrait< ElementType >::Type IntrinsicType
Resulting intrinsic element type.
Definition: TDMatTSMatMultExpr.h:222
MT2::CompositeType CT2
Composite type of the right-hand side sparse matrix expression.
Definition: TDMatTSMatMultExpr.h:126
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::CompositeType CT1
Composite type of the left-hand side dense matrix expression.
Definition: TDMatTSMatMultExpr.h:125
Header file for the multiplication trait.
Header file for the IsSymmetric type trait.
#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: StorageOrder.h:161
Header file for the TSVecTDMatMultExprTrait class template.
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2482
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: TDMatTSMatMultExpr.h:272
Header file for the TDMatSVecMultExprTrait class template.
Header file for the TDVecTSMatMultExprTrait class template.
Header file for the DenseMatrix base class.
BLAZE_ALWAYS_INLINE void assign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the assignment of a matrix to a matrix.
Definition: Matrix.h:635
Header file for the Columns type trait.
Header file for the TSMatDVecMultExprTrait class template.
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: TDMatTSMatMultExpr.h:394
bool isAligned() const
Returns whether the operands of the expression are properly aligned in memory.
Definition: TDMatTSMatMultExpr.h:384
Header file for the IsLower type trait.
LeftOperand leftOperand() const
Returns the left-hand side transpose dense matrix operand.
Definition: TDMatTSMatMultExpr.h:340
#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
RightOperand rightOperand() const
Returns the right-hand side transpose sparse matrix operand.
Definition: TDMatTSMatMultExpr.h:350
Constraints on the storage order of matrix types.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:2476
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.
ResultType::ElementType ElementType
Resulting element type.
Definition: TDMatTSMatMultExpr.h:221
Header file for the EnableIf class template.
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
LeftOperand lhs_
Left-hand side dense matrix of the multiplication expression.
Definition: TDMatTSMatMultExpr.h:401
BLAZE_ALWAYS_INLINE EnableIf< IsIntegral< T >, Set< T, sizeof(T)> >::Type::Type set(T value)
Sets all values in the vector to the given integral value.
Definition: Set.h:211
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: StorageOrder.h:81
Removal of reference modifiers.The RemoveCV type trait removes any reference modifiers from the given...
Definition: RemoveReference.h:69
Intrinsic characteristics of data types.The IntrinsicTrait class template provides the intrinsic char...
Definition: IntrinsicTrait.h:749
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:142
BLAZE_ALWAYS_INLINE void addAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the addition assignment of a matrix to a matrix.
Definition: Matrix.h:742
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TDMatTSMatMultExpr.h:223
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: TDMatTSMatMultExpr.h:220
Header file for the reset shim.
Header file for the isDefault shim.
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: TDMatTSMatMultExpr.h:362
BLAZE_ALWAYS_INLINE bool isDefault(const NonNumericProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: NonNumericProxy.h:874
MT1::ResultType RT1
Result type of the left-hand side dense matrix expression.
Definition: TDMatTSMatMultExpr.h:121
BLAZE_ALWAYS_INLINE void reset(const NonNumericProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: NonNumericProxy.h:833
RT2::ElementType ET2
Element type of the right-hand side sparse matrix expression.
Definition: TDMatTSMatMultExpr.h:124
ResultType::OppositeType OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: TDMatTSMatMultExpr.h:219
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:283
Header file for the IsDenseVector type trait.
Header file for all intrinsic functionality.
SelectType< evaluateRight, const RT2, CT2 >::Type RT
Type for the assignment of the right-hand side sparse matrix operand.
Definition: TDMatTSMatMultExpr.h:236
TDMatTSMatMultExpr< MT1, MT2 > This
Type of this TDMatTSMatMultExpr instance.
Definition: TDMatTSMatMultExpr.h:217
MT2::ResultType RT2
Result type of the right-hand side sparse matrix expression.
Definition: TDMatTSMatMultExpr.h:122
SelectType< evaluateLeft, const RT1, CT1 >::Type LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: TDMatTSMatMultExpr.h:233
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:932
Header file for the IsComputation type trait class.
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
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: TDMatTSMatMultExpr.h:374
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:2473
Header file for the IsTrue value trait.
Header file for basic type definitions.
SelectType< IsExpression< MT2 >::value, const MT2, const MT2 & >::Type RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: TDMatTSMatMultExpr.h:230
Header file for the IsUpper type trait.
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: TDMatTSMatMultExpr.h:402
Header file for the IsColumnVector type trait.
Constraint on the data type.
BLAZE_ALWAYS_INLINE EnableIf< IsIntegral< T > >::Type store(T *address, const typename Store< T, sizeof(T)>::Type &value)
Aligned store of a vector of integral values.
Definition: Store.h:225
Header file for the IsResizable type trait.
Size type of the Blaze library.
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 TSMatSVecMultExprTrait class template.
Header file for the FunctionTrace class.
MultTrait< RT1, RT2 >::Type ResultType
Result type for expression template evaluations.
Definition: TDMatTSMatMultExpr.h:218
BLAZE_ALWAYS_INLINE void subAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the subtraction assignment of a matrix to matrix.
Definition: Matrix.h:849
size_t columns() const
Returns the current number of columns of the matrix.
Definition: TDMatTSMatMultExpr.h:330