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>
51 #include <blaze/math/Intrinsics.h>
53 #include <blaze/math/shims/Reset.h>
79 #include <blaze/util/Assert.h>
81 #include <blaze/util/EnableIf.h>
82 #include <blaze/util/InvalidType.h>
84 #include <blaze/util/SelectType.h>
85 #include <blaze/util/Types.h>
87 
88 
89 namespace blaze {
90 
91 //=================================================================================================
92 //
93 // CLASS TDMATTSMATMULTEXPR
94 //
95 //=================================================================================================
96 
97 //*************************************************************************************************
104 template< typename MT1 // Type of the left-hand side dense matrix
105  , typename MT2 > // Type of the right-hand side sparse matrix
106 class TDMatTSMatMultExpr : public DenseMatrix< TDMatTSMatMultExpr<MT1,MT2>, true >
107  , private MatMatMultExpr
108  , private Computation
109 {
110  private:
111  //**Type definitions****************************************************************************
112  typedef typename MT1::ResultType RT1;
113  typedef typename MT2::ResultType RT2;
114  typedef typename RT1::ElementType ET1;
115  typedef typename RT2::ElementType ET2;
116  typedef typename MT1::CompositeType CT1;
117  typedef typename MT2::CompositeType CT2;
118  //**********************************************************************************************
119 
120  //**********************************************************************************************
123  //**********************************************************************************************
124 
125  //**********************************************************************************************
127  enum { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
128  //**********************************************************************************************
129 
130  //**********************************************************************************************
132 
136  template< typename MT >
137  struct UseSMPAssign {
138  enum { value = ( evaluateLeft || evaluateRight ) };
139  };
141  //**********************************************************************************************
142 
143  //**********************************************************************************************
145 
148  template< typename T1, typename T2, typename T3 >
149  struct UseVectorizedKernel {
150  enum { value = T1::vectorizable && T2::vectorizable &&
151  IsColumnMajorMatrix<T1>::value &&
152  IsSame<typename T1::ElementType,typename T2::ElementType>::value &&
153  IsSame<typename T1::ElementType,typename T3::ElementType>::value &&
154  IntrinsicTrait<typename T1::ElementType>::addition &&
155  IntrinsicTrait<typename T1::ElementType>::subtraction &&
156  IntrinsicTrait<typename T1::ElementType>::multiplication };
157  };
159  //**********************************************************************************************
160 
161  //**********************************************************************************************
163 
167  template< typename T1, typename T2, typename T3 >
168  struct UseOptimizedKernel {
169  enum { value = !UseVectorizedKernel<T1,T2,T3>::value &&
170  !IsResizable<typename T1::ElementType>::value &&
171  !IsResizable<ET1>::value };
172  };
174  //**********************************************************************************************
175 
176  //**********************************************************************************************
178 
181  template< typename T1, typename T2, typename T3 >
182  struct UseDefaultKernel {
183  enum { value = !UseVectorizedKernel<T1,T2,T3>::value &&
184  !UseOptimizedKernel<T1,T2,T3>::value };
185  };
187  //**********************************************************************************************
188 
189  public:
190  //**Type definitions****************************************************************************
197  typedef const ElementType ReturnType;
198  typedef const ResultType CompositeType;
199 
201  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
202 
204  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
205 
208 
211  //**********************************************************************************************
212 
213  //**Compilation flags***************************************************************************
215  enum { vectorizable = MT1::vectorizable &&
219 
221  enum { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
222  !evaluateRight && MT2::smpAssignable };
223  //**********************************************************************************************
224 
225  //**Constructor*********************************************************************************
231  explicit inline TDMatTSMatMultExpr( 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( B.end(j) );
264  ConstIterator element( B.begin(j) );
265 
266  // Early exit in case column j is empty
267  if( element == end )
268  return tmp;
269 
270  // Calculating element (i,j)
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  // Default computation in case the right-hand side sparse matrix doesn't provide iterators
278  else {
279  tmp = lhs_(i,0UL) * rhs_(0UL,j);
280  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
281  tmp += lhs_(i,k) * rhs_(k,j);
282  }
283  }
284 
285  return tmp;
286  }
287  //**********************************************************************************************
288 
289  //**Rows function*******************************************************************************
294  inline size_t rows() const {
295  return lhs_.rows();
296  }
297  //**********************************************************************************************
298 
299  //**Columns function****************************************************************************
304  inline size_t columns() const {
305  return rhs_.columns();
306  }
307  //**********************************************************************************************
308 
309  //**Left operand access*************************************************************************
314  inline LeftOperand leftOperand() const {
315  return lhs_;
316  }
317  //**********************************************************************************************
318 
319  //**Right operand access************************************************************************
324  inline RightOperand rightOperand() const {
325  return rhs_;
326  }
327  //**********************************************************************************************
328 
329  //**********************************************************************************************
335  template< typename T >
336  inline bool canAlias( const T* alias ) const {
337  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
338  }
339  //**********************************************************************************************
340 
341  //**********************************************************************************************
347  template< typename T >
348  inline bool isAliased( const T* alias ) const {
349  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
350  }
351  //**********************************************************************************************
352 
353  //**********************************************************************************************
358  inline bool isAligned() const {
359  return lhs_.isAligned();
360  }
361  //**********************************************************************************************
362 
363  //**********************************************************************************************
368  inline bool canSMPAssign() const {
369  return ( columns() > SMP_TDMATTSMATMULT_THRESHOLD );
370  }
371  //**********************************************************************************************
372 
373  private:
374  //**Member variables****************************************************************************
377  //**********************************************************************************************
378 
379  //**Assignment to dense matrices****************************************************************
392  template< typename MT // Type of the target dense matrix
393  , bool SO > // Storage order of the target dense matrix
394  friend inline void assign( DenseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
395  {
397 
398  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
399  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
400 
401  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
402  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
403 
404  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
405  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
406  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
407  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
408  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
409  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
410 
411  TDMatTSMatMultExpr::selectAssignKernel( ~lhs, A, B );
412  }
414  //**********************************************************************************************
415 
416  //**Default assignment to row-major dense matrices**********************************************
430  template< typename MT3 // Type of the left-hand side target matrix
431  , typename MT4 // Type of the left-hand side matrix operand
432  , typename MT5 > // Type of the right-hand side matrix operand
433  static inline void selectAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
434  {
435  typedef typename MT5::ConstIterator ConstIterator;
436 
437  const size_t iend( A.rows() & size_t(-4) );
438  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == iend, "Invalid end calculation" );
439 
440  for( size_t i=0UL; i<iend; i+=4UL ) {
441  for( size_t j=0UL; j<B.columns(); ++j )
442  {
443  ConstIterator element( B.begin(j) );
444  const ConstIterator end( B.end(j) );
445 
446  if( element == end ) {
447  reset( (~C)(i ,j) );
448  reset( (~C)(i+1UL,j) );
449  reset( (~C)(i+2UL,j) );
450  reset( (~C)(i+3UL,j) );
451  continue;
452  }
453 
454  (~C)(i ,j) = A(i ,element->index()) * element->value();
455  (~C)(i+1UL,j) = A(i+1UL,element->index()) * element->value();
456  (~C)(i+2UL,j) = A(i+2UL,element->index()) * element->value();
457  (~C)(i+3UL,j) = A(i+3UL,element->index()) * element->value();
458  ++element;
459  for( ; element!=end; ++element ) {
460  (~C)(i ,j) += A(i ,element->index()) * element->value();
461  (~C)(i+1UL,j) += A(i+1UL,element->index()) * element->value();
462  (~C)(i+2UL,j) += A(i+2UL,element->index()) * element->value();
463  (~C)(i+3UL,j) += A(i+3UL,element->index()) * element->value();
464  }
465  }
466  }
467 
468  for( size_t i=iend; i<A.rows(); ++i ) {
469  for( size_t j=0UL; j<B.columns(); ++j )
470  {
471  ConstIterator element( B.begin(j) );
472  const ConstIterator end( B.end(j) );
473 
474  if( element == end ) {
475  reset( (~C)(i,j) );
476  continue;
477  }
478 
479  (~C)(i,j) = A(i,element->index()) * element->value();
480  ++element;
481  for( ; element!=end; ++element )
482  (~C)(i,j) += A(i,element->index()) * element->value();
483  }
484  }
485  }
487  //**********************************************************************************************
488 
489  //**Default assignment to column-major dense matrices*******************************************
503  template< typename MT3 // Type of the left-hand side target matrix
504  , typename MT4 // Type of the left-hand side matrix operand
505  , typename MT5 > // Type of the right-hand side matrix operand
506  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
507  selectAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
508  {
509  typedef typename MT5::ConstIterator ConstIterator;
510 
511  for( size_t j=0UL; j<B.columns(); ++j ) {
512  for( size_t i=0UL; i<(~C).rows(); ++i ) {
513  reset( (~C)(i,j) );
514  }
515  ConstIterator element( B.begin(j) );
516  const ConstIterator end( B.end(j) );
517  for( ; element!=end; ++element ) {
518  for( size_t i=0UL; i<A.rows(); ++i ) {
519  if( isDefault( (~C)(i,j) ) )
520  (~C)(i,j) = A(i,element->index()) * element->value();
521  else
522  (~C)(i,j) += A(i,element->index()) * element->value();
523  }
524  }
525  }
526  }
528  //**********************************************************************************************
529 
530  //**Optimized assignment to column-major dense matrices*****************************************
544  template< typename MT3 // Type of the left-hand side target matrix
545  , typename MT4 // Type of the left-hand side matrix operand
546  , typename MT5 > // Type of the right-hand side matrix operand
547  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
548  selectAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
549  {
550  typedef typename MT5::ConstIterator ConstIterator;
551 
552  const size_t iend( A.rows() & size_t(-4) );
553  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == iend, "Invalid end calculation" );
554 
555  reset( ~C );
556 
557  for( size_t j=0UL; j<B.columns(); ++j )
558  {
559  const ConstIterator end( B.end(j) );
560  ConstIterator element( B.begin(j) );
561 
562  const size_t kend( B.nonZeros(j) & size_t(-4) );
563 
564  for( size_t k=0UL; k<kend; k+=4UL ) {
565  const size_t j1( element->index() );
566  const ET2 v1( element->value() );
567  ++element;
568  const size_t j2( element->index() );
569  const ET2 v2( element->value() );
570  ++element;
571  const size_t j3( element->index() );
572  const ET2 v3( element->value() );
573  ++element;
574  const size_t j4( element->index() );
575  const ET2 v4( element->value() );
576  ++element;
577 
578  for( size_t i=0UL; i<iend; i+=4UL ) {
579  (~C)(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
580  (~C)(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
581  (~C)(i+2UL,j) += A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
582  (~C)(i+3UL,j) += A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
583  }
584  for( size_t i=iend; i<A.rows(); ++i ) {
585  (~C)(i,j) += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
586  }
587  }
588 
589  for( ; element!=end; ++element ) {
590  for( size_t i=0UL; i<iend; i+=4UL ) {
591  (~C)(i ,j) += A(i ,element->index()) * element->value();
592  (~C)(i+1UL,j) += A(i+1UL,element->index()) * element->value();
593  (~C)(i+2UL,j) += A(i+2UL,element->index()) * element->value();
594  (~C)(i+3UL,j) += A(i+3UL,element->index()) * element->value();
595  }
596  for( size_t i=iend; i<A.rows(); ++i ) {
597  (~C)(i,j) += A(i,element->index()) * element->value();
598  }
599  }
600  }
601  }
603  //**********************************************************************************************
604 
605  //**Vectorized assignment to column-major dense matrices****************************************
619  template< typename MT3 // Type of the left-hand side target matrix
620  , typename MT4 // Type of the left-hand side matrix operand
621  , typename MT5 > // Type of the right-hand side matrix operand
622  static inline typename EnableIf< UseVectorizedKernel<MT3,MT4,MT5> >::Type
623  selectAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
624  {
625  typedef IntrinsicTrait<ElementType> IT;
626  typedef typename MT5::ConstIterator ConstIterator;
627 
628  const size_t M( A.rows() );
629 
630  reset( ~C );
631 
632  for( size_t j=0UL; j<B.columns(); ++j )
633  {
634  const ConstIterator end( B.end(j) );
635  ConstIterator element( B.begin(j) );
636 
637  const size_t kend( B.nonZeros(j) & size_t(-4) );
638 
639  for( size_t k=0UL; k<kend; k+=4UL ) {
640  const size_t j1( element->index() );
641  const IntrinsicType v1( set( element->value() ) );
642  ++element;
643  const size_t j2( element->index() );
644  const IntrinsicType v2( set( element->value() ) );
645  ++element;
646  const size_t j3( element->index() );
647  const IntrinsicType v3( set( element->value() ) );
648  ++element;
649  const size_t j4( element->index() );
650  const IntrinsicType v4( set( element->value() ) );
651  ++element;
652 
653  for( size_t i=0UL; i<M; i+=IT::size ) {
654  (~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 );
655  }
656  }
657 
658  for( ; element!=end; ++element ) {
659  const size_t j1( element->index() );
660  const IntrinsicType v1( set( element->value() ) );
661 
662  for( size_t i=0UL; i<M; i+=IT::size ) {
663  (~C).store( i, j, (~C).load(i,j) + A.load(i,j1) * v1 );
664  }
665  }
666  }
667  }
669  //**********************************************************************************************
670 
671  //**Assignment to sparse matrices***************************************************************
684  template< typename MT // Type of the target sparse matrix
685  , bool SO > // Storage order of the target sparse matrix
686  friend inline void assign( SparseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
687  {
689 
690  typedef typename SelectType< SO, ResultType, OppositeType >::Type TmpType;
691 
698 
699  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
700  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
701 
702  const TmpType tmp( serial( rhs ) );
703  assign( ~lhs, tmp );
704  }
706  //**********************************************************************************************
707 
708  //**Addition assignment to dense matrices*******************************************************
721  template< typename MT // Type of the target dense matrix
722  , bool SO > // Storage order of the target dense matrix
723  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
724  {
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  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
731  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
732 
733  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
734  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
735  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
736  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
737  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
738  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
739 
740  TDMatTSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
741  }
743  //**********************************************************************************************
744 
745  //**Default addition assignment to row-major dense matrices*************************************
759  template< typename MT3 // Type of the left-hand side target matrix
760  , typename MT4 // Type of the left-hand side matrix operand
761  , typename MT5 > // Type of the right-hand side matrix operand
762  static inline void selectAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
763  {
764  typedef typename MT5::ConstIterator ConstIterator;
765 
766  const size_t iend( A.rows() & size_t(-4) );
767  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == iend, "Invalid end calculation" );
768 
769  for( size_t i=0UL; i<iend; i+=4UL ) {
770  for( size_t j=0UL; j<B.columns(); ++j )
771  {
772  ConstIterator element( B.begin(j) );
773  const ConstIterator end( B.end(j) );
774 
775  for( ; element!=end; ++element ) {
776  (~C)(i ,j) += A(i ,element->index()) * element->value();
777  (~C)(i+1UL,j) += A(i+1UL,element->index()) * element->value();
778  (~C)(i+2UL,j) += A(i+2UL,element->index()) * element->value();
779  (~C)(i+3UL,j) += A(i+3UL,element->index()) * element->value();
780  }
781  }
782  }
783 
784  for( size_t i=iend; i<A.rows(); ++i ) {
785  for( size_t j=0UL; j<B.columns(); ++j )
786  {
787  ConstIterator element( B.begin(j) );
788  const ConstIterator end( B.end(j) );
789 
790  for( ; element!=end; ++element )
791  (~C)(i,j) += A(i,element->index()) * element->value();
792  }
793  }
794  }
796  //**********************************************************************************************
797 
798  //**Default addition assignment to column-major dense matrices**********************************
812  template< typename MT3 // Type of the left-hand side target matrix
813  , typename MT4 // Type of the left-hand side matrix operand
814  , typename MT5 > // Type of the right-hand side matrix operand
815  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
816  selectAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
817  {
818  typedef typename MT5::ConstIterator ConstIterator;
819 
820  for( size_t j=0UL; j<B.columns(); ++j ) {
821  ConstIterator element( B.begin(j) );
822  const ConstIterator end( B.end(j) );
823  for( ; element!=end; ++element ) {
824  for( size_t i=0UL; i<A.rows(); ++i ) {
825  if( isDefault( (~C)(i,j) ) )
826  (~C)(i,j) = A(i,element->index()) * element->value();
827  else
828  (~C)(i,j) += A(i,element->index()) * element->value();
829  }
830  }
831  }
832  }
834  //**********************************************************************************************
835 
836  //**Optimized addition assignment to column-major dense matrices********************************
850  template< typename MT3 // Type of the left-hand side target matrix
851  , typename MT4 // Type of the left-hand side matrix operand
852  , typename MT5 > // Type of the right-hand side matrix operand
853  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
854  selectAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
855  {
856  typedef typename MT5::ConstIterator ConstIterator;
857 
858  const size_t iend( A.rows() & size_t(-4) );
859  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == iend, "Invalid end calculation" );
860 
861  for( size_t j=0UL; j<B.columns(); ++j )
862  {
863  const ConstIterator end( B.end(j) );
864  ConstIterator element( B.begin(j) );
865 
866  const size_t kend( B.nonZeros(j) & size_t(-4) );
867 
868  for( size_t k=0UL; k<kend; k+=4UL ) {
869  const size_t j1( element->index() );
870  const ET2 v1( element->value() );
871  ++element;
872  const size_t j2( element->index() );
873  const ET2 v2( element->value() );
874  ++element;
875  const size_t j3( element->index() );
876  const ET2 v3( element->value() );
877  ++element;
878  const size_t j4( element->index() );
879  const ET2 v4( element->value() );
880  ++element;
881 
882  for( size_t i=0UL; i<iend; i+=4UL ) {
883  (~C)(i ,j) += A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
884  (~C)(i+1UL,j) += A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
885  (~C)(i+2UL,j) += A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
886  (~C)(i+3UL,j) += A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
887  }
888  for( size_t i=iend; i<A.rows(); ++i ) {
889  (~C)(i,j) += A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
890  }
891  }
892 
893  for( ; element!=end; ++element ) {
894  for( size_t i=0UL; i<iend; i+=4UL ) {
895  (~C)(i ,j) += A(i ,element->index()) * element->value();
896  (~C)(i+1UL,j) += A(i+1UL,element->index()) * element->value();
897  (~C)(i+2UL,j) += A(i+2UL,element->index()) * element->value();
898  (~C)(i+3UL,j) += A(i+3UL,element->index()) * element->value();
899  }
900  for( size_t i=iend; i<A.rows(); ++i ) {
901  (~C)(i,j) += A(i,element->index()) * element->value();
902  }
903  }
904  }
905  }
907  //**********************************************************************************************
908 
909  //**Vectorized addition assignment to column-major dense matrices*******************************
923  template< typename MT3 // Type of the left-hand side target matrix
924  , typename MT4 // Type of the left-hand side matrix operand
925  , typename MT5 > // Type of the right-hand side matrix operand
926  static inline typename EnableIf< UseVectorizedKernel<MT3,MT4,MT5> >::Type
927  selectAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
928  {
929  typedef IntrinsicTrait<ElementType> IT;
930  typedef typename MT5::ConstIterator ConstIterator;
931 
932  const size_t M( A.rows() );
933 
934  for( size_t j=0UL; j<B.columns(); ++j )
935  {
936  const ConstIterator end( B.end(j) );
937  ConstIterator element( B.begin(j) );
938 
939  const size_t kend( B.nonZeros(j) & size_t(-4) );
940 
941  for( size_t k=0UL; k<kend; k+=4UL ) {
942  const size_t j1( element->index() );
943  const IntrinsicType v1( set( element->value() ) );
944  ++element;
945  const size_t j2( element->index() );
946  const IntrinsicType v2( set( element->value() ) );
947  ++element;
948  const size_t j3( element->index() );
949  const IntrinsicType v3( set( element->value() ) );
950  ++element;
951  const size_t j4( element->index() );
952  const IntrinsicType v4( set( element->value() ) );
953  ++element;
954 
955  for( size_t i=0UL; i<M; i+=IT::size ) {
956  (~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 );
957  }
958  }
959 
960  for( ; element!=end; ++element ) {
961  const size_t j1( element->index() );
962  const IntrinsicType v1( set( element->value() ) );
963 
964  for( size_t i=0UL; i<M; i+=IT::size ) {
965  (~C).store( i, j, (~C).load(i,j) + A.load(i,j1) * v1 );
966  }
967  }
968  }
969  }
971  //**********************************************************************************************
972 
973  //**Addition assignment to sparse matrices******************************************************
974  // No special implementation for the addition assignment to sparse matrices.
975  //**********************************************************************************************
976 
977  //**Subtraction assignment to dense matrices****************************************************
990  template< typename MT // Type of the target dense matrix
991  , bool SO > // Storage order of the target dense matrix
992  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
993  {
995 
996  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
997  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
998 
999  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
1000  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
1001 
1002  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1003  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1004  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1005  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1006  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1007  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1008 
1009  TDMatTSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1010  }
1012  //**********************************************************************************************
1013 
1014  //**Default subtraction assignment to row-major dense matrices**********************************
1028  template< typename MT3 // Type of the left-hand side target matrix
1029  , typename MT4 // Type of the left-hand side matrix operand
1030  , typename MT5 > // Type of the right-hand side matrix operand
1031  static inline void selectSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
1032  {
1033  typedef typename MT5::ConstIterator ConstIterator;
1034 
1035  const size_t iend( A.rows() & size_t(-4) );
1036  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == iend, "Invalid end calculation" );
1037 
1038  for( size_t i=0UL; i<iend; i+=4UL ) {
1039  for( size_t j=0UL; j<B.columns(); ++j )
1040  {
1041  ConstIterator element( B.begin(j) );
1042  const ConstIterator end( B.end(j) );
1043 
1044  for( ; element!=end; ++element ) {
1045  (~C)(i ,j) -= A(i ,element->index()) * element->value();
1046  (~C)(i+1UL,j) -= A(i+1UL,element->index()) * element->value();
1047  (~C)(i+2UL,j) -= A(i+2UL,element->index()) * element->value();
1048  (~C)(i+3UL,j) -= A(i+3UL,element->index()) * element->value();
1049  }
1050  }
1051  }
1052 
1053  for( size_t i=iend; i<A.rows(); ++i ) {
1054  for( size_t j=0UL; j<B.columns(); ++j )
1055  {
1056  ConstIterator element( B.begin(j) );
1057  const ConstIterator end( B.end(j) );
1058 
1059  for( ; element!=end; ++element )
1060  (~C)(i,j) -= A(i,element->index()) * element->value();
1061  }
1062  }
1063  }
1065  //**********************************************************************************************
1066 
1067  //**Default subtraction assignment to column-major dense matrices*******************************
1081  template< typename MT3 // Type of the left-hand side target matrix
1082  , typename MT4 // Type of the left-hand side matrix operand
1083  , typename MT5 > // Type of the right-hand side matrix operand
1084  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
1085  selectSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
1086  {
1087  typedef typename MT5::ConstIterator ConstIterator;
1088 
1089  for( size_t j=0UL; j<B.columns(); ++j ) {
1090  ConstIterator element( B.begin(j) );
1091  const ConstIterator end( B.end(j) );
1092  for( ; element!=end; ++element ) {
1093  for( size_t i=0UL; i<A.rows(); ++i ) {
1094  if( isDefault( (~C)(i,j) ) )
1095  (~C)(i,j) = -A(i,element->index()) * element->value();
1096  else
1097  (~C)(i,j) -= A(i,element->index()) * element->value();
1098  }
1099  }
1100  }
1101  }
1103  //**********************************************************************************************
1104 
1105  //**Optimized subtraction assignment to column-major dense matrices*****************************
1119  template< typename MT3 // Type of the left-hand side target matrix
1120  , typename MT4 // Type of the left-hand side matrix operand
1121  , typename MT5 > // Type of the right-hand side matrix operand
1122  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
1123  selectSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
1124  {
1125  typedef typename MT5::ConstIterator ConstIterator;
1126 
1127  const size_t iend( A.rows() & size_t(-4) );
1128  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == iend, "Invalid end calculation" );
1129 
1130  for( size_t j=0UL; j<B.columns(); ++j )
1131  {
1132  const ConstIterator end( B.end(j) );
1133  ConstIterator element( B.begin(j) );
1134 
1135  const size_t kend( B.nonZeros(j) & size_t(-4) );
1136 
1137  for( size_t k=0UL; k<kend; k+=4UL ) {
1138  const size_t j1( element->index() );
1139  const ET2 v1( element->value() );
1140  ++element;
1141  const size_t j2( element->index() );
1142  const ET2 v2( element->value() );
1143  ++element;
1144  const size_t j3( element->index() );
1145  const ET2 v3( element->value() );
1146  ++element;
1147  const size_t j4( element->index() );
1148  const ET2 v4( element->value() );
1149  ++element;
1150 
1151  for( size_t i=0UL; i<iend; i+=4UL ) {
1152  (~C)(i ,j) -= A(i ,j1) * v1 + A(i ,j2) * v2 + A(i ,j3) * v3 + A(i ,j4) * v4;
1153  (~C)(i+1UL,j) -= A(i+1UL,j1) * v1 + A(i+1UL,j2) * v2 + A(i+1UL,j3) * v3 + A(i+1UL,j4) * v4;
1154  (~C)(i+2UL,j) -= A(i+2UL,j1) * v1 + A(i+2UL,j2) * v2 + A(i+2UL,j3) * v3 + A(i+2UL,j4) * v4;
1155  (~C)(i+3UL,j) -= A(i+3UL,j1) * v1 + A(i+3UL,j2) * v2 + A(i+3UL,j3) * v3 + A(i+3UL,j4) * v4;
1156  }
1157  for( size_t i=iend; i<A.rows(); ++i ) {
1158  (~C)(i,j) -= A(i,j1) * v1 + A(i,j2) * v2 + A(i,j3) * v3 + A(i,j4) * v4;
1159  }
1160  }
1161 
1162  for( ; element!=end; ++element ) {
1163  for( size_t i=0UL; i<iend; i+=4UL ) {
1164  (~C)(i ,j) -= A(i ,element->index()) * element->value();
1165  (~C)(i+1UL,j) -= A(i+1UL,element->index()) * element->value();
1166  (~C)(i+2UL,j) -= A(i+2UL,element->index()) * element->value();
1167  (~C)(i+3UL,j) -= A(i+3UL,element->index()) * element->value();
1168  }
1169  for( size_t i=iend; i<A.rows(); ++i ) {
1170  (~C)(i,j) -= A(i,element->index()) * element->value();
1171  }
1172  }
1173  }
1174  }
1176  //**********************************************************************************************
1177 
1178  //**Vectorized subtraction assignment to column-major 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 EnableIf< UseVectorizedKernel<MT3,MT4,MT5> >::Type
1196  selectSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
1197  {
1198  typedef IntrinsicTrait<ElementType> IT;
1199  typedef typename MT5::ConstIterator ConstIterator;
1200 
1201  const size_t M( A.rows() );
1202 
1203  for( size_t j=0UL; j<B.columns(); ++j )
1204  {
1205  const ConstIterator end( B.end(j) );
1206  ConstIterator element( B.begin(j) );
1207 
1208  const size_t kend( B.nonZeros(j) & size_t(-4) );
1209 
1210  for( size_t k=0UL; k<kend; k+=4UL ) {
1211  const size_t j1( element->index() );
1212  const IntrinsicType v1( set( element->value() ) );
1213  ++element;
1214  const size_t j2( element->index() );
1215  const IntrinsicType v2( set( element->value() ) );
1216  ++element;
1217  const size_t j3( element->index() );
1218  const IntrinsicType v3( set( element->value() ) );
1219  ++element;
1220  const size_t j4( element->index() );
1221  const IntrinsicType v4( set( element->value() ) );
1222  ++element;
1223 
1224  for( size_t i=0UL; i<M; i+=IT::size ) {
1225  (~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 );
1226  }
1227  }
1228 
1229  for( ; element!=end; ++element ) {
1230  const size_t j1( element->index() );
1231  const IntrinsicType v1( set( element->value() ) );
1232 
1233  for( size_t i=0UL; i<M; i+=IT::size ) {
1234  (~C).store( i, j, (~C).load(i,j) - A.load(i,j1) * v1 );
1235  }
1236  }
1237  }
1238  }
1240  //**********************************************************************************************
1241 
1242  //**Subtraction assignment to sparse matrices***************************************************
1243  // No special implementation for the subtraction assignment to sparse matrices.
1244  //**********************************************************************************************
1245 
1246  //**Multiplication assignment to dense matrices*************************************************
1247  // No special implementation for the multiplication assignment to dense matrices.
1248  //**********************************************************************************************
1249 
1250  //**Multiplication assignment to sparse matrices************************************************
1251  // No special implementation for the multiplication assignment to sparse matrices.
1252  //**********************************************************************************************
1253 
1254  //**SMP assignment to dense matrices************************************************************
1269  template< typename MT // Type of the target dense matrix
1270  , bool SO > // Storage order of the target dense matrix
1271  friend inline typename EnableIf< UseSMPAssign<MT> >::Type
1272  smpAssign( DenseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
1273  {
1275 
1276  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1277  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1278 
1279  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1280  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1281 
1282  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1283  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1284  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1285  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1286  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1287  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1288 
1289  smpAssign( ~lhs, A * B );
1290  }
1292  //**********************************************************************************************
1293 
1294  //**SMP assignment to sparse matrices***********************************************************
1309  template< typename MT // Type of the target sparse matrix
1310  , bool SO > // Storage order of the target sparse matrix
1311  friend inline typename EnableIf< UseSMPAssign<MT> >::Type
1312  smpAssign( SparseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
1313  {
1315 
1316  typedef typename SelectType< SO, ResultType, OppositeType >::Type TmpType;
1317 
1324 
1325  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1326  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1327 
1328  const TmpType tmp( rhs );
1329  smpAssign( ~lhs, tmp );
1330  }
1332  //**********************************************************************************************
1333 
1334  //**SMP addition assignment to dense matrices***************************************************
1349  template< typename MT // Type of the target dense matrix
1350  , bool SO > // Storage order of the target dense matrix
1351  friend inline typename EnableIf< UseSMPAssign<MT> >::Type
1352  smpAddAssign( DenseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
1353  {
1355 
1356  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1357  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1358 
1359  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1360  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1361 
1362  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1363  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1364  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1365  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1366  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1367  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1368 
1369  smpAddAssign( ~lhs, A * B );
1370  }
1372  //**********************************************************************************************
1373 
1374  //**SMP addition assignment to sparse matrices**************************************************
1375  // No special implementation for the SMP addition assignment to sparse matrices.
1376  //**********************************************************************************************
1377 
1378  //**SMP subtraction assignment to dense matrices************************************************
1393  template< typename MT // Type of the target dense matrix
1394  , bool SO > // Storage order of the target dense matrix
1395  friend inline typename EnableIf< UseSMPAssign<MT> >::Type
1396  smpSubAssign( DenseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
1397  {
1399 
1400  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1401  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1402 
1403  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1404  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1405 
1406  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1407  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1408  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1409  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1410  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1411  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1412 
1413  smpSubAssign( ~lhs, A * B );
1414  }
1416  //**********************************************************************************************
1417 
1418  //**SMP subtraction assignment to sparse matrices***********************************************
1419  // No special implementation for the SMP subtraction assignment to sparse matrices.
1420  //**********************************************************************************************
1421 
1422  //**SMP multiplication assignment to dense matrices*********************************************
1423  // No special implementation for the SMP multiplication assignment to dense matrices.
1424  //**********************************************************************************************
1425 
1426  //**SMP multiplication assignment to sparse matrices********************************************
1427  // No special implementation for the SMP multiplication assignment to sparse matrices.
1428  //**********************************************************************************************
1429 
1430  //**Compile time checks*************************************************************************
1437  //**********************************************************************************************
1438 };
1439 //*************************************************************************************************
1440 
1441 
1442 
1443 
1444 //=================================================================================================
1445 //
1446 // GLOBAL BINARY ARITHMETIC OPERATORS
1447 //
1448 //=================================================================================================
1449 
1450 //*************************************************************************************************
1479 template< typename T1 // Type of the left-hand side dense matrix
1480  , typename T2 > // Type of the right-hand side sparse matrix
1481 inline const TDMatTSMatMultExpr<T1,T2>
1483 {
1485 
1486  if( (~lhs).columns() != (~rhs).rows() )
1487  throw std::invalid_argument( "Matrix sizes do not match" );
1488 
1489  return TDMatTSMatMultExpr<T1,T2>( ~lhs, ~rhs );
1490 }
1491 //*************************************************************************************************
1492 
1493 
1494 
1495 
1496 //=================================================================================================
1497 //
1498 // EXPRESSION TRAIT SPECIALIZATIONS
1499 //
1500 //=================================================================================================
1501 
1502 //*************************************************************************************************
1504 template< typename MT1, typename MT2, typename VT >
1505 struct TDMatDVecMultExprTrait< TDMatTSMatMultExpr<MT1,MT2>, VT >
1506 {
1507  public:
1508  //**********************************************************************************************
1509  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1510  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
1511  IsDenseVector<VT>::value && IsColumnVector<VT>::value
1512  , typename TDMatDVecMultExprTrait< MT1, typename TSMatDVecMultExprTrait<MT2,VT>::Type >::Type
1513  , INVALID_TYPE >::Type Type;
1514  //**********************************************************************************************
1515 };
1517 //*************************************************************************************************
1518 
1519 
1520 //*************************************************************************************************
1522 template< typename MT1, typename MT2, typename VT >
1523 struct TDMatSVecMultExprTrait< TDMatTSMatMultExpr<MT1,MT2>, VT >
1524 {
1525  public:
1526  //**********************************************************************************************
1527  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1528  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
1529  IsSparseVector<VT>::value && IsColumnVector<VT>::value
1530  , typename TDMatDVecMultExprTrait< MT1, typename TSMatDVecMultExprTrait<MT2,VT>::Type >::Type
1531  , INVALID_TYPE >::Type Type;
1532  //**********************************************************************************************
1533 };
1535 //*************************************************************************************************
1536 
1537 
1538 //*************************************************************************************************
1540 template< typename VT, typename MT1, typename MT2 >
1541 struct TDVecTDMatMultExprTrait< VT, TDMatTSMatMultExpr<MT1,MT2> >
1542 {
1543  public:
1544  //**********************************************************************************************
1545  typedef typename SelectType< IsDenseVector<VT>::value && IsRowVector<VT>::value &&
1546  IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1547  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
1548  , typename TDVecTSMatMultExprTrait< typename TDVecTDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1549  , INVALID_TYPE >::Type Type;
1550  //**********************************************************************************************
1551 };
1553 //*************************************************************************************************
1554 
1555 
1556 //*************************************************************************************************
1558 template< typename VT, typename MT1, typename MT2 >
1559 struct TSVecTDMatMultExprTrait< VT, TDMatTSMatMultExpr<MT1,MT2> >
1560 {
1561  public:
1562  //**********************************************************************************************
1563  typedef typename SelectType< IsSparseVector<VT>::value && IsRowVector<VT>::value &&
1564  IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1565  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
1566  , typename TDVecTSMatMultExprTrait< typename TSVecTDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1567  , INVALID_TYPE >::Type Type;
1568  //**********************************************************************************************
1569 };
1571 //*************************************************************************************************
1572 
1573 
1574 //*************************************************************************************************
1576 template< typename MT1, typename MT2, bool AF >
1577 struct SubmatrixExprTrait< TDMatTSMatMultExpr<MT1,MT2>, AF >
1578 {
1579  public:
1580  //**********************************************************************************************
1581  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT1,AF>::Type
1582  , typename SubmatrixExprTrait<const MT2,AF>::Type >::Type Type;
1583  //**********************************************************************************************
1584 };
1586 //*************************************************************************************************
1587 
1588 
1589 //*************************************************************************************************
1591 template< typename MT1, typename MT2 >
1592 struct RowExprTrait< TDMatTSMatMultExpr<MT1,MT2> >
1593 {
1594  public:
1595  //**********************************************************************************************
1596  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
1597  //**********************************************************************************************
1598 };
1600 //*************************************************************************************************
1601 
1602 
1603 //*************************************************************************************************
1605 template< typename MT1, typename MT2 >
1606 struct ColumnExprTrait< TDMatTSMatMultExpr<MT1,MT2> >
1607 {
1608  public:
1609  //**********************************************************************************************
1610  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
1611  //**********************************************************************************************
1612 };
1614 //*************************************************************************************************
1615 
1616 } // namespace blaze
1617 
1618 #endif
RT1::ElementType ET1
Element type of the left-hand side dense matrix expression.
Definition: TDMatTSMatMultExpr.h:114
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:89
void reset(DynamicMatrix< Type, SO > &m)
Resetting the given dense matrix.
Definition: DynamicMatrix.h:4599
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:223
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:4329
void smpSubAssign(DenseMatrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:152
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.
bool isDefault(const DynamicMatrix< Type, SO > &m)
Returns whether the given dense matrix is in default state.
Definition: DynamicMatrix.h:4642
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:199
#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:198
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2408
Header file for the IsRowVector type trait.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:251
const DMatSerialExpr< MT, SO > serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:690
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:201
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:294
Constraint on the data type.
TDMatTSMatMultExpr(const MT1 &lhs, const MT2 &rhs)
Constructor for the TDMatTSMatMultExpr class.
Definition: TDMatTSMatMultExpr.h:231
Constraint on the data type.
Constraint on the data type.
Header file for the MultExprTrait class template.
void smpAddAssign(DenseMatrix< 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:122
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:196
MT2::CompositeType CT2
Composite type of the right-hand side sparse matrix expression.
Definition: TDMatTSMatMultExpr.h:117
Compile time type selection.The SelectType class template selects one of the two given types T1 and T...
Definition: SelectType.h:59
MT1::CompositeType CT1
Composite type of the left-hand side dense matrix expression.
Definition: TDMatTSMatMultExpr.h:116
Header file for the multiplication 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:2412
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: TDMatTSMatMultExpr.h:246
Header file for the TDMatSVecMultExprTrait class template.
Header file for the TDVecTSMatMultExprTrait class template.
Header file for the DenseMatrix base class.
Header file for the TSMatDVecMultExprTrait class template.
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: TDMatTSMatMultExpr.h:368
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:271
bool isAligned() const
Returns whether the operands of the expression are properly aligned in memory.
Definition: TDMatTSMatMultExpr.h:358
LeftOperand leftOperand() const
Returns the left-hand side transpose dense matrix operand.
Definition: TDMatTSMatMultExpr.h:314
#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:324
Constraints on the storage order of matrix types.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:2406
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:195
Header file for the EnableIf class template.
Header file for the serial shim.
LeftOperand lhs_
Left-hand side dense matrix of the multiplication expression.
Definition: TDMatTSMatMultExpr.h:375
void smpAssign(DenseMatrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:92
Header file for the IsSparseVector type trait.
Header file for the SubmatrixExprTrait class template.
#define BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a row-major dense or sparse matrix t...
Definition: 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:748
Header file for run time assertion macros.
Utility type for generic codes.
Base template for the MultTrait class.
Definition: MultTrait.h:141
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TDMatTSMatMultExpr.h:197
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:301
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: TDMatTSMatMultExpr.h:194
Header file for the reset shim.
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:331
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:336
MT1::ResultType RT1
Result type of the left-hand side dense matrix expression.
Definition: TDMatTSMatMultExpr.h:112
RT2::ElementType ET2
Element type of the right-hand side sparse matrix expression.
Definition: TDMatTSMatMultExpr.h:115
ResultType::OppositeType OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: TDMatTSMatMultExpr.h:193
Header file for the RemoveReference type trait.
#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:210
TDMatTSMatMultExpr< MT1, MT2 > This
Type of this TDMatTSMatMultExpr instance.
Definition: TDMatTSMatMultExpr.h:191
MT2::ResultType RT2
Result type of the right-hand side sparse matrix expression.
Definition: TDMatTSMatMultExpr.h:113
SelectType< evaluateLeft, const RT1, CT1 >::Type LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: TDMatTSMatMultExpr.h:207
Header file for the IsComputation type trait class.
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:348
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:2403
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:204
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: TDMatTSMatMultExpr.h:376
Header file for the IsColumnVector type trait.
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.
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:209
#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:192
size_t columns() const
Returns the current number of columns of the matrix.
Definition: TDMatTSMatMultExpr.h:304