All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SMatDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_SMATDMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_SMATDMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <stdexcept>
51 #include <blaze/math/Intrinsics.h>
52 #include <blaze/math/shims/Reset.h>
79 #include <blaze/util/Assert.h>
80 #include <blaze/util/DisableIf.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>
88 
89 
90 namespace blaze {
91 
92 //=================================================================================================
93 //
94 // CLASS SMATDMATMULTEXPR
95 //
96 //=================================================================================================
97 
98 //*************************************************************************************************
105 template< typename MT1 // Type of the left-hand side sparse matrix
106  , typename MT2 > // Type of the right-hand side dense matrix
107 class SMatDMatMultExpr : public DenseMatrix< SMatDMatMultExpr<MT1,MT2>, false >
108  , private MatMatMultExpr
109  , private Computation
110 {
111  private:
112  //**Type definitions****************************************************************************
113  typedef typename MT1::ResultType RT1;
114  typedef typename MT2::ResultType RT2;
115  typedef typename RT1::ElementType ET1;
116  typedef typename RT2::ElementType ET2;
117  typedef typename MT1::CompositeType CT1;
118  typedef typename MT2::CompositeType CT2;
119  //**********************************************************************************************
120 
121  //**********************************************************************************************
124  //**********************************************************************************************
125 
126  //**********************************************************************************************
128  enum { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
129  //**********************************************************************************************
130 
131  //**********************************************************************************************
133 
136  template< typename T1, typename T2, typename T3 >
137  struct UseSMPAssignKernel {
138  enum { value = evaluateLeft || evaluateRight };
139  };
141  //**********************************************************************************************
142 
143  //**********************************************************************************************
145 
148  template< typename T1, typename T2, typename T3 >
149  struct UseVectorizedKernel {
150  enum { value = !UseSMPAssignKernel<T1,T2,T3>::value &&
151  T1::vectorizable && T3::vectorizable &&
152  IsRowMajorMatrix<T1>::value &&
153  IsSame<typename T1::ElementType,typename T2::ElementType>::value &&
154  IsSame<typename T1::ElementType,typename T3::ElementType>::value &&
155  IntrinsicTrait<typename T1::ElementType>::addition &&
156  IntrinsicTrait<typename T1::ElementType>::subtraction &&
157  IntrinsicTrait<typename T1::ElementType>::multiplication };
158  };
160  //**********************************************************************************************
161 
162  //**********************************************************************************************
164 
168  template< typename T1, typename T2, typename T3 >
169  struct UseOptimizedKernel {
170  enum { value = !UseSMPAssignKernel<T1,T2,T3>::value &&
171  !UseVectorizedKernel<T1,T2,T3>::value &&
172  !IsResizable<typename T1::ElementType>::value &&
173  !IsResizable<ET1>::value };
174  };
176  //**********************************************************************************************
177 
178  //**********************************************************************************************
180 
183  template< typename T1, typename T2, typename T3 >
184  struct UseDefaultKernel {
185  enum { value = !UseSMPAssignKernel<T1,T2,T3>::value &&
186  !UseVectorizedKernel<T1,T2,T3>::value &&
187  !UseOptimizedKernel<T1,T2,T3>::value };
188  };
190  //**********************************************************************************************
191 
192  public:
193  //**Type definitions****************************************************************************
200  typedef const ElementType ReturnType;
201  typedef const ResultType CompositeType;
202 
204  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
205 
207  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
208 
211 
214  //**********************************************************************************************
215 
216  //**Compilation flags***************************************************************************
218  enum { vectorizable = MT2::vectorizable &&
222 
224  enum { smpAssignable = !evaluateLeft && !evaluateRight };
225  //**********************************************************************************************
226 
227  //**Constructor*********************************************************************************
233  explicit inline SMatDMatMultExpr( const MT1& lhs, const MT2& rhs )
234  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
235  , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
236  {
237  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
238  }
239  //**********************************************************************************************
240 
241  //**Access operator*****************************************************************************
248  inline ReturnType operator()( size_t i, size_t j ) const {
249  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
250  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
251 
253 
254  ElementType tmp = ElementType();
255 
256  // Early exit
257  if( lhs_.columns() == 0 )
258  return tmp;
259 
260  // Fast computation in case the left-hand side sparse matrix directly provides iterators
262  {
263  CT1 A( lhs_ ); // Evaluation of the left-hand side sparse matrix operand
264 
265  const ConstIterator end( A.end(i) );
266  ConstIterator element( A.begin(i) );
267 
268  // Early exit in case row i is empty
269  if( element == end )
270  return tmp;
271 
272  // Calculating element (i,j)
273  tmp = element->value() * rhs_(element->index(),j);
274  ++element;
275  for( ; element!=end; ++element )
276  tmp += element->value() * rhs_(element->index(),j);
277  }
278 
279  // Default computation in case the left-hand side sparse matrix doesn't provide iterators
280  else {
281  tmp = lhs_(i,0) * rhs_(0,j);
282  for( size_t k=1; k<lhs_.columns(); ++k ) {
283  tmp += lhs_(i,k) * rhs_(k,j);
284  }
285  }
286 
287  return tmp;
288  }
289  //**********************************************************************************************
290 
291  //**Rows function*******************************************************************************
296  inline size_t rows() const {
297  return lhs_.rows();
298  }
299  //**********************************************************************************************
300 
301  //**Columns function****************************************************************************
306  inline size_t columns() const {
307  return rhs_.columns();
308  }
309  //**********************************************************************************************
310 
311  //**Left operand access*************************************************************************
316  inline LeftOperand leftOperand() const {
317  return lhs_;
318  }
319  //**********************************************************************************************
320 
321  //**Right operand access************************************************************************
326  inline RightOperand rightOperand() const {
327  return rhs_;
328  }
329  //**********************************************************************************************
330 
331  //**********************************************************************************************
337  template< typename T >
338  inline bool canAlias( const T* alias ) const {
339  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
340  }
341  //**********************************************************************************************
342 
343  //**********************************************************************************************
349  template< typename T >
350  inline bool isAliased( const T* alias ) const {
351  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
352  }
353  //**********************************************************************************************
354 
355  //**********************************************************************************************
360  inline bool isAligned() const {
361  return rhs_.isAligned();
362  }
363  //**********************************************************************************************
364 
365  //**********************************************************************************************
370  inline bool canSMPAssign() const {
371  return ( rows() > SMP_SMATDMATMULT_THRESHOLD );
372  }
373  //**********************************************************************************************
374 
375  private:
376  //**Member variables****************************************************************************
379  //**********************************************************************************************
380 
381  //**Assignment to dense matrices****************************************************************
393  template< typename MT // Type of the target dense matrix
394  , bool SO > // Storage order of the target dense matrix
395  friend inline void assign( DenseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
396  {
398 
399  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
400  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
401 
402  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
403  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
404 
405  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
406  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
407  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
408  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
409  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
410  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
411 
412  SMatDMatMultExpr::selectAssignKernel( ~lhs, A, B );
413  }
415  //**********************************************************************************************
416 
417  //**Default assignment to row-major dense matrices**********************************************
431  template< typename MT3 // Type of the left-hand side target matrix
432  , typename MT4 // Type of the left-hand side matrix operand
433  , typename MT5 > // Type of the right-hand side matrix operand
434  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
435  selectAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
436  {
437  typedef typename MT4::ConstIterator ConstIterator;
438 
439  for( size_t i=0UL; i<A.rows(); ++i )
440  {
441  const ConstIterator end( A.end(i) );
442 
443  for( size_t j=0UL; j<B.columns(); ++j )
444  {
445  ConstIterator element( A.begin(i) );
446 
447  if( element != end ) {
448  (~C)(i,j) = element->value() * B(element->index(),j);
449  ++element;
450  for( ; element!=end; ++element ) {
451  (~C)(i,j) += element->value() * B(element->index(),j);
452  }
453  }
454  else {
455  reset( (~C)(i,j) );
456  }
457  }
458  }
459  }
461  //**********************************************************************************************
462 
463  //**Optimized assignment to row-major dense matrices********************************************
477  template< typename MT3 // Type of the left-hand side target matrix
478  , typename MT4 // Type of the left-hand side matrix operand
479  , typename MT5 > // Type of the right-hand side matrix operand
480  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
481  selectAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
482  {
483  typedef typename MT4::ConstIterator ConstIterator;
484 
485  const size_t jend( B.columns() & size_t(-4) );
486  BLAZE_INTERNAL_ASSERT( ( B.columns() - ( B.columns() % 4UL ) ) == jend, "Invalid end calculation" );
487 
488  reset( ~C );
489 
490  for( size_t i=0UL; i<A.rows(); ++i )
491  {
492  const ConstIterator end( A.end(i) );
493  ConstIterator element( A.begin(i) );
494 
495  const size_t kend( A.nonZeros(i) & size_t(-4) );
496 
497  for( size_t k=0UL; k<kend; k+=4UL ) {
498  const size_t i1( element->index() );
499  const ET1 v1( element->value() );
500  ++element;
501  const size_t i2( element->index() );
502  const ET1 v2( element->value() );
503  ++element;
504  const size_t i3( element->index() );
505  const ET1 v3( element->value() );
506  ++element;
507  const size_t i4( element->index() );
508  const ET1 v4( element->value() );
509  ++element;
510 
511  for( size_t j=0UL; j<jend; j+=4UL ) {
512  (~C)(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
513  (~C)(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
514  (~C)(i,j+2UL) += v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
515  (~C)(i,j+3UL) += v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
516  }
517  for( size_t j=jend; j<B.columns(); ++j ) {
518  (~C)(i,j) += v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
519  }
520  }
521 
522  for( ; element!=end; ++element ) {
523  for( size_t j=0UL; j<jend; j+=4UL ) {
524  (~C)(i,j ) += element->value() * B(element->index(),j );
525  (~C)(i,j+1UL) += element->value() * B(element->index(),j+1UL);
526  (~C)(i,j+2UL) += element->value() * B(element->index(),j+2UL);
527  (~C)(i,j+3UL) += element->value() * B(element->index(),j+3UL);
528  }
529  for( size_t j=jend; j<B.columns(); ++j ) {
530  (~C)(i,j) += element->value() * B(element->index(),j);
531  }
532  }
533  }
534  }
536  //**********************************************************************************************
537 
538  //**Vectorized assignment to row-major dense matrices*******************************************
552  template< typename MT3 // Type of the left-hand side target matrix
553  , typename MT4 // Type of the left-hand side matrix operand
554  , typename MT5 > // Type of the right-hand side matrix operand
555  static inline typename EnableIf< UseVectorizedKernel<MT3,MT4,MT5> >::Type
556  selectAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
557  {
558  typedef IntrinsicTrait<ElementType> IT;
559  typedef typename MT4::ConstIterator ConstIterator;
560 
561  const size_t N( B.columns() );
562 
563  reset( ~C );
564 
565  for( size_t i=0UL; i<A.rows(); ++i )
566  {
567  const ConstIterator end( A.end(i) );
568  ConstIterator element( A.begin(i) );
569 
570  const size_t kend( A.nonZeros(i) & size_t(-4) );
571 
572  for( size_t k=0UL; k<kend; k+=4UL ) {
573  const size_t i1( element->index() );
574  const IntrinsicType v1( set( element->value() ) );
575  ++element;
576  const size_t i2( element->index() );
577  const IntrinsicType v2( set( element->value() ) );
578  ++element;
579  const size_t i3( element->index() );
580  const IntrinsicType v3( set( element->value() ) );
581  ++element;
582  const size_t i4( element->index() );
583  const IntrinsicType v4( set( element->value() ) );
584  ++element;
585 
586  for( size_t j=0UL; j<N; j+=IT::size ) {
587  (~C).store( i, j, (~C).load(i,j) + v1 * B.load(i1,j) + v2 * B.load(i2,j) + v3 * B.load(i3,j) + v4 * B.load(i4,j) );
588  }
589  }
590 
591  for( ; element!=end; ++element ) {
592  const size_t i1( element->index() );
593  const IntrinsicType v1( set( element->value() ) );
594 
595  for( size_t j=0UL; j<N; j+=IT::size ) {
596  (~C).store( i, j, (~C).load(i,j) + v1 * B.load(i1,j) );
597  }
598  }
599  }
600  }
602  //**********************************************************************************************
603 
604  //**Default assignment to column-major dense matrices*******************************************
618  template< typename MT3 // Type of the left-hand side target matrix
619  , typename MT4 // Type of the left-hand side matrix operand
620  , typename MT5 > // Type of the right-hand side matrix operand
621  static inline typename DisableIf< UseSMPAssignKernel<MT3,MT4,MT5> >::Type
622  selectAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
623  {
624  typedef typename MT4::ConstIterator ConstIterator;
625 
626  const size_t jend( B.columns() & size_t(-4) );
627  BLAZE_INTERNAL_ASSERT( ( B.columns() - ( B.columns() % 4UL ) ) == jend, "Invalid end calculation" );
628 
629  for( size_t j=0UL; j<jend; j+=4UL ) {
630  for( size_t i=0UL; i<A.rows(); ++i )
631  {
632  ConstIterator element( A.begin(i) );
633  const ConstIterator end( A.end(i) );
634 
635  if( element == end ) {
636  reset( (~C)(i,j ) );
637  reset( (~C)(i,j+1UL) );
638  reset( (~C)(i,j+2UL) );
639  reset( (~C)(i,j+3UL) );
640  continue;
641  }
642 
643  (~C)(i,j ) = element->value() * B(element->index(),j );
644  (~C)(i,j+1UL) = element->value() * B(element->index(),j+1UL);
645  (~C)(i,j+2UL) = element->value() * B(element->index(),j+2UL);
646  (~C)(i,j+3UL) = element->value() * B(element->index(),j+3UL);
647  ++element;
648  for( ; element!=end; ++element ) {
649  (~C)(i,j ) += element->value() * B(element->index(),j );
650  (~C)(i,j+1UL) += element->value() * B(element->index(),j+1UL);
651  (~C)(i,j+2UL) += element->value() * B(element->index(),j+2UL);
652  (~C)(i,j+3UL) += element->value() * B(element->index(),j+3UL);
653  }
654  }
655  }
656 
657  for( size_t j=jend; j<B.columns(); ++j ) {
658  for( size_t i=0UL; i<A.rows(); ++i )
659  {
660  ConstIterator element( A.begin(i) );
661  const ConstIterator end( A.end(i) );
662 
663  if( element == end ) {
664  reset( (~C)(i,j) );
665  continue;
666  }
667 
668  (~C)(i,j) = element->value() * B(element->index(),j);
669  ++element;
670  for( ; element!=end; ++element )
671  (~C)(i,j) += element->value() * B(element->index(),j);
672  }
673  }
674  }
676  //**********************************************************************************************
677 
678  //**SMP assignment to dense matrices************************************************************
692  template< typename MT3 // Type of the left-hand side target matrix
693  , typename MT4 // Type of the left-hand side matrix operand
694  , typename MT5 > // Type of the right-hand side matrix operand
695  static inline typename EnableIf< UseSMPAssignKernel<MT3,MT4,MT5> >::Type
696  selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
697  {
698  smpAssign( C, A * B );
699  }
701  //**********************************************************************************************
702 
703  //**Assignment to sparse matrices***************************************************************
715  template< typename MT // Type of the target sparse matrix
716  , bool SO > // Storage order of the target sparse matrix
717  friend inline void assign( SparseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
718  {
720 
721  typedef typename SelectType< SO, OppositeType, ResultType >::Type TmpType;
722 
729 
730  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
731  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
732 
733  const TmpType tmp( rhs );
734  smpAssign( ~lhs, tmp );
735  }
737  //**********************************************************************************************
738 
739  //**Addition assignment to dense matrices*******************************************************
751  template< typename MT // Type of the target dense matrix
752  , bool SO > // Storage order of the target dense matrix
753  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
754  {
756 
757  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
758  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
759 
760  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
761  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
762 
763  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
764  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
765  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
766  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
767  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
768  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
769 
770  SMatDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
771  }
773  //**********************************************************************************************
774 
775  //**Default addition assignment to row-major dense matrices*************************************
789  template< typename MT3 // Type of the left-hand side target matrix
790  , typename MT4 // Type of the left-hand side matrix operand
791  , typename MT5 > // Type of the right-hand side matrix operand
792  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
793  selectAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
794  {
795  typedef typename MT4::ConstIterator ConstIterator;
796 
797  for( size_t i=0UL; i<A.rows(); ++i )
798  {
799  const ConstIterator end( A.end(i) );
800 
801  for( size_t j=0UL; j<B.columns(); ++j )
802  {
803  ConstIterator element( A.begin(i) );
804 
805  for( ; element!=end; ++element ) {
806  (~C)(i,j) += element->value() * B(element->index(),j);
807  }
808  }
809  }
810  }
812  //**********************************************************************************************
813 
814  //**Optimized addition assignment to row-major dense matrices***********************************
828  template< typename MT3 // Type of the left-hand side target matrix
829  , typename MT4 // Type of the left-hand side matrix operand
830  , typename MT5 > // Type of the right-hand side matrix operand
831  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
832  selectAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
833  {
834  typedef typename MT4::ConstIterator ConstIterator;
835 
836  const size_t jend( B.columns() & size_t(-4) );
837  BLAZE_INTERNAL_ASSERT( ( B.columns() - ( B.columns() % 4UL ) ) == jend, "Invalid end calculation" );
838 
839  for( size_t i=0UL; i<A.rows(); ++i )
840  {
841  const ConstIterator end( A.end(i) );
842  ConstIterator element( A.begin(i) );
843 
844  const size_t kend( A.nonZeros(i) & size_t(-4) );
845 
846  for( size_t k=0UL; k<kend; k+=4UL ) {
847  const size_t i1( element->index() );
848  const ET1 v1( element->value() );
849  ++element;
850  const size_t i2( element->index() );
851  const ET1 v2( element->value() );
852  ++element;
853  const size_t i3( element->index() );
854  const ET1 v3( element->value() );
855  ++element;
856  const size_t i4( element->index() );
857  const ET1 v4( element->value() );
858  ++element;
859 
860  for( size_t j=0UL; j<jend; j+=4UL ) {
861  (~C)(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
862  (~C)(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
863  (~C)(i,j+2UL) += v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
864  (~C)(i,j+3UL) += v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
865  }
866  for( size_t j=jend; j<B.columns(); ++j ) {
867  (~C)(i,j) += v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
868  }
869  }
870 
871  for( ; element!=end; ++element ) {
872  for( size_t j=0UL; j<jend; j+=4UL ) {
873  (~C)(i,j ) += element->value() * B(element->index(),j );
874  (~C)(i,j+1UL) += element->value() * B(element->index(),j+1UL);
875  (~C)(i,j+2UL) += element->value() * B(element->index(),j+2UL);
876  (~C)(i,j+3UL) += element->value() * B(element->index(),j+3UL);
877  }
878  for( size_t j=jend; j<B.columns(); ++j ) {
879  (~C)(i,j) += element->value() * B(element->index(),j);
880  }
881  }
882  }
883  }
885  //**********************************************************************************************
886 
887  //**Vectorized addition assignment to row-major dense matrices**********************************
901  template< typename MT3 // Type of the left-hand side target matrix
902  , typename MT4 // Type of the left-hand side matrix operand
903  , typename MT5 > // Type of the right-hand side matrix operand
904  static inline typename EnableIf< UseVectorizedKernel<MT3,MT4,MT5> >::Type
905  selectAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
906  {
907  typedef IntrinsicTrait<ElementType> IT;
908  typedef typename MT4::ConstIterator ConstIterator;
909 
910  const size_t N( B.columns() );
911 
912  for( size_t i=0UL; i<A.rows(); ++i )
913  {
914  const ConstIterator end( A.end(i) );
915  ConstIterator element( A.begin(i) );
916 
917  const size_t kend( A.nonZeros(i) & size_t(-4) );
918 
919  for( size_t k=0UL; k<kend; k+=4UL ) {
920  const size_t i1( element->index() );
921  const IntrinsicType v1( set( element->value() ) );
922  ++element;
923  const size_t i2( element->index() );
924  const IntrinsicType v2( set( element->value() ) );
925  ++element;
926  const size_t i3( element->index() );
927  const IntrinsicType v3( set( element->value() ) );
928  ++element;
929  const size_t i4( element->index() );
930  const IntrinsicType v4( set( element->value() ) );
931  ++element;
932 
933  for( size_t j=0UL; j<N; j+=IT::size ) {
934  (~C).store( i, j, (~C).load(i,j) + v1 * B.load(i1,j) + v2 * B.load(i2,j) + v3 * B.load(i3,j) + v4 * B.load(i4,j) );
935  }
936  }
937 
938  for( ; element!=end; ++element ) {
939  const size_t i1( element->index() );
940  const IntrinsicType v1( set( element->value() ) );
941 
942  for( size_t j=0UL; j<N; j+=IT::size ) {
943  (~C).store( i, j, (~C).load(i,j) + v1 * B.load(i1,j) );
944  }
945  }
946  }
947  }
949  //**********************************************************************************************
950 
951  //**Default addition assignment to column-major dense matrices**********************************
965  template< typename MT3 // Type of the left-hand side target matrix
966  , typename MT4 // Type of the left-hand side matrix operand
967  , typename MT5 > // Type of the right-hand side matrix operand
968  static inline typename DisableIf< UseSMPAssignKernel<MT3,MT4,MT5> >::Type
969  selectAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
970  {
971  typedef typename MT4::ConstIterator ConstIterator;
972 
973  const size_t jend( B.columns() & size_t(-4) );
974  BLAZE_INTERNAL_ASSERT( ( B.columns() - ( B.columns() % 4UL ) ) == jend, "Invalid end calculation" );
975 
976  for( size_t j=0UL; j<jend; j+=4UL ) {
977  for( size_t i=0UL; i<A.rows(); ++i )
978  {
979  ConstIterator element( A.begin(i) );
980  const ConstIterator end( A.end(i) );
981 
982  for( ; element!=end; ++element ) {
983  (~C)(i,j ) += element->value() * B(element->index(),j );
984  (~C)(i,j+1UL) += element->value() * B(element->index(),j+1UL);
985  (~C)(i,j+2UL) += element->value() * B(element->index(),j+2UL);
986  (~C)(i,j+3UL) += element->value() * B(element->index(),j+3UL);
987  }
988  }
989  }
990 
991  for( size_t j=jend; j<B.columns(); ++j ) {
992  for( size_t i=0UL; i<A.rows(); ++i )
993  {
994  ConstIterator element( A.begin(i) );
995  const ConstIterator end( A.end(i) );
996 
997  for( ; element!=end; ++element )
998  (~C)(i,j) += element->value() * B(element->index(),j);
999  }
1000  }
1001  }
1003  //**********************************************************************************************
1004 
1005  //**SMP addition assignment to dense matrices***************************************************
1019  template< typename MT3 // Type of the left-hand side target matrix
1020  , typename MT4 // Type of the left-hand side matrix operand
1021  , typename MT5 > // Type of the right-hand side matrix operand
1022  static inline typename EnableIf< UseSMPAssignKernel<MT3,MT4,MT5> >::Type
1023  selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
1024  {
1025  smpAddAssign( C, A * B );
1026  }
1028  //**********************************************************************************************
1029 
1030  //**Addition assignment to sparse matrices******************************************************
1031  // No special implementation for the addition assignment to sparse matrices.
1032  //**********************************************************************************************
1033 
1034  //**Subtraction assignment to dense matrices****************************************************
1046  template< typename MT // Type of the target dense matrix
1047  , bool SO > // Storage order of the target dense matrix
1048  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
1049  {
1051 
1052  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1053  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1054 
1055  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
1056  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
1057 
1058  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1059  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1060  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1061  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1062  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1063  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1064 
1065  SMatDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1066  }
1068  //**********************************************************************************************
1069 
1070  //**Default subtraction assignment to row-major dense matrices**********************************
1084  template< typename MT3 // Type of the left-hand side target matrix
1085  , typename MT4 // Type of the left-hand side matrix operand
1086  , typename MT5 > // Type of the right-hand side matrix operand
1087  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
1088  selectSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
1089  {
1090  typedef typename MT4::ConstIterator ConstIterator;
1091 
1092  for( size_t i=0UL; i<A.rows(); ++i )
1093  {
1094  const ConstIterator end( A.end(i) );
1095 
1096  for( size_t j=0UL; j<B.columns(); ++j )
1097  {
1098  ConstIterator element( A.begin(i) );
1099 
1100  for( ; element!=end; ++element ) {
1101  (~C)(i,j) -= element->value() * B(element->index(),j);
1102  }
1103  }
1104  }
1105  }
1107  //**********************************************************************************************
1108 
1109  //**Optimized subtraction assignment to row-major dense matrices********************************
1123  template< typename MT3 // Type of the left-hand side target matrix
1124  , typename MT4 // Type of the left-hand side matrix operand
1125  , typename MT5 > // Type of the right-hand side matrix operand
1126  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
1127  selectSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
1128  {
1129  typedef typename MT4::ConstIterator ConstIterator;
1130 
1131  const size_t jend( B.columns() & size_t(-4) );
1132  BLAZE_INTERNAL_ASSERT( ( B.columns() - ( B.columns() % 4UL ) ) == jend, "Invalid end calculation" );
1133 
1134  for( size_t i=0UL; i<A.rows(); ++i )
1135  {
1136  const ConstIterator end( A.end(i) );
1137  ConstIterator element( A.begin(i) );
1138 
1139  const size_t kend( A.nonZeros(i) & size_t(-4) );
1140 
1141  for( size_t k=0UL; k<kend; k+=4UL ) {
1142  const size_t i1( element->index() );
1143  const ET1 v1( element->value() );
1144  ++element;
1145  const size_t i2( element->index() );
1146  const ET1 v2( element->value() );
1147  ++element;
1148  const size_t i3( element->index() );
1149  const ET1 v3( element->value() );
1150  ++element;
1151  const size_t i4( element->index() );
1152  const ET1 v4( element->value() );
1153  ++element;
1154 
1155  for( size_t j=0UL; j<jend; j+=4UL ) {
1156  (~C)(i,j ) -= v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
1157  (~C)(i,j+1UL) -= v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
1158  (~C)(i,j+2UL) -= v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
1159  (~C)(i,j+3UL) -= v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
1160  }
1161  for( size_t j=jend; j<B.columns(); ++j ) {
1162  (~C)(i,j) -= v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
1163  }
1164  }
1165 
1166  for( ; element!=end; ++element ) {
1167  for( size_t j=0UL; j<jend; j+=4UL ) {
1168  (~C)(i,j ) -= element->value() * B(element->index(),j );
1169  (~C)(i,j+1UL) -= element->value() * B(element->index(),j+1UL);
1170  (~C)(i,j+2UL) -= element->value() * B(element->index(),j+2UL);
1171  (~C)(i,j+3UL) -= element->value() * B(element->index(),j+3UL);
1172  }
1173  for( size_t j=jend; j<B.columns(); ++j ) {
1174  (~C)(i,j) -= element->value() * B(element->index(),j);
1175  }
1176  }
1177  }
1178  }
1180  //**********************************************************************************************
1181 
1182  //**Vectorized subtraction assignment to row-major dense matrices*******************************
1196  template< typename MT3 // Type of the left-hand side target matrix
1197  , typename MT4 // Type of the left-hand side matrix operand
1198  , typename MT5 > // Type of the right-hand side matrix operand
1199  static inline typename EnableIf< UseVectorizedKernel<MT3,MT4,MT5> >::Type
1200  selectSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
1201  {
1202  typedef IntrinsicTrait<ElementType> IT;
1203  typedef typename MT4::ConstIterator ConstIterator;
1204 
1205  const size_t N( B.columns() );
1206 
1207  for( size_t i=0UL; i<A.rows(); ++i )
1208  {
1209  const ConstIterator end( A.end(i) );
1210  ConstIterator element( A.begin(i) );
1211 
1212  const size_t kend( A.nonZeros(i) & size_t(-4) );
1213 
1214  for( size_t k=0UL; k<kend; k+=4UL ) {
1215  const size_t i1( element->index() );
1216  const IntrinsicType v1( set( element->value() ) );
1217  ++element;
1218  const size_t i2( element->index() );
1219  const IntrinsicType v2( set( element->value() ) );
1220  ++element;
1221  const size_t i3( element->index() );
1222  const IntrinsicType v3( set( element->value() ) );
1223  ++element;
1224  const size_t i4( element->index() );
1225  const IntrinsicType v4( set( element->value() ) );
1226  ++element;
1227 
1228  for( size_t j=0UL; j<N; j+=IT::size ) {
1229  (~C).store( i, j, (~C).load(i,j) - v1 * B.load(i1,j) - v2 * B.load(i2,j) - v3 * B.load(i3,j) - v4 * B.load(i4,j) );
1230  }
1231  }
1232 
1233  for( ; element!=end; ++element ) {
1234  const size_t i1( element->index() );
1235  const IntrinsicType v1( set( element->value() ) );
1236 
1237  for( size_t j=0UL; j<N; j+=IT::size ) {
1238  (~C).store( i, j, (~C).load(i,j) - v1 * B.load(i1,j) );
1239  }
1240  }
1241  }
1242  }
1244  //**********************************************************************************************
1245 
1246  //**Default subtraction assignment to column-major dense matrices*******************************
1260  template< typename MT3 // Type of the left-hand side target matrix
1261  , typename MT4 // Type of the left-hand side matrix operand
1262  , typename MT5 > // Type of the right-hand side matrix operand
1263  static inline typename DisableIf< UseSMPAssignKernel<MT3,MT4,MT5> >::Type
1264  selectSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
1265  {
1266  typedef typename MT4::ConstIterator ConstIterator;
1267 
1268  const size_t jend( B.columns() & size_t(-4) );
1269  BLAZE_INTERNAL_ASSERT( ( B.columns() - ( B.columns() % 4UL ) ) == jend, "Invalid end calculation" );
1270 
1271  for( size_t j=0UL; j<jend; j+=4UL ) {
1272  for( size_t i=0UL; i<A.rows(); ++i )
1273  {
1274  ConstIterator element( A.begin(i) );
1275  const ConstIterator end( A.end(i) );
1276 
1277  for( ; element!=end; ++element ) {
1278  (~C)(i,j ) -= element->value() * B(element->index(),j );
1279  (~C)(i,j+1UL) -= element->value() * B(element->index(),j+1UL);
1280  (~C)(i,j+2UL) -= element->value() * B(element->index(),j+2UL);
1281  (~C)(i,j+3UL) -= element->value() * B(element->index(),j+3UL);
1282  }
1283  }
1284  }
1285 
1286  for( size_t j=jend; j<B.columns(); ++j ) {
1287  for( size_t i=0UL; i<A.rows(); ++i )
1288  {
1289  ConstIterator element( A.begin(i) );
1290  const ConstIterator end( A.end(i) );
1291 
1292  for( ; element!=end; ++element )
1293  (~C)(i,j) -= element->value() * B(element->index(),j);
1294  }
1295  }
1296  }
1298  //**********************************************************************************************
1299 
1300  //**SMP subtraction assignment to dense matrices************************************************
1314  template< typename MT3 // Type of the left-hand side target matrix
1315  , typename MT4 // Type of the left-hand side matrix operand
1316  , typename MT5 > // Type of the right-hand side matrix operand
1317  static inline typename EnableIf< UseSMPAssignKernel<MT3,MT4,MT5> >::Type
1318  selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1319  {
1320  smpSubAssign( C, A * B );
1321  }
1323  //**********************************************************************************************
1324 
1325  //**Subtraction assignment to sparse matrices***************************************************
1326  // No special implementation for the subtraction assignment to sparse matrices.
1327  //**********************************************************************************************
1328 
1329  //**Multiplication assignment to dense matrices*************************************************
1330  // No special implementation for the multiplication assignment to dense matrices.
1331  //**********************************************************************************************
1332 
1333  //**Multiplication assignment to sparse matrices************************************************
1334  // No special implementation for the multiplication assignment to sparse matrices.
1335  //**********************************************************************************************
1336 
1337  //**Compile time checks*************************************************************************
1344  //**********************************************************************************************
1345 };
1346 //*************************************************************************************************
1347 
1348 
1349 
1350 
1351 //=================================================================================================
1352 //
1353 // GLOBAL BINARY ARITHMETIC OPERATORS
1354 //
1355 //=================================================================================================
1356 
1357 //*************************************************************************************************
1386 template< typename T1 // Type of the left-hand side sparse matrix
1387  , typename T2 > // Type of the right-hand side dense matrix
1388 inline const SMatDMatMultExpr<T1,T2>
1390 {
1392 
1393  if( (~lhs).columns() != (~rhs).rows() )
1394  throw std::invalid_argument( "Matrix sizes do not match" );
1395 
1396  return SMatDMatMultExpr<T1,T2>( ~lhs, ~rhs );
1397 }
1398 //*************************************************************************************************
1399 
1400 
1401 
1402 
1403 //=================================================================================================
1404 //
1405 // EXPRESSION TRAIT SPECIALIZATIONS
1406 //
1407 //=================================================================================================
1408 
1409 //*************************************************************************************************
1411 template< typename MT1, typename MT2, typename VT >
1412 struct DMatDVecMultExprTrait< SMatDMatMultExpr<MT1,MT2>, VT >
1413 {
1414  public:
1415  //**********************************************************************************************
1416  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1417  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1418  IsDenseVector<VT>::value && IsColumnVector<VT>::value
1419  , typename SMatDVecMultExprTrait< MT1, typename DMatDVecMultExprTrait<MT2,VT>::Type >::Type
1420  , INVALID_TYPE >::Type Type;
1421  //**********************************************************************************************
1422 };
1424 //*************************************************************************************************
1425 
1426 
1427 //*************************************************************************************************
1429 template< typename MT1, typename MT2, typename VT >
1430 struct DMatSVecMultExprTrait< SMatDMatMultExpr<MT1,MT2>, VT >
1431 {
1432  public:
1433  //**********************************************************************************************
1434  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1435  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1436  IsSparseVector<VT>::value && IsColumnVector<VT>::value
1437  , typename SMatDVecMultExprTrait< MT1, typename DMatSVecMultExprTrait<MT2,VT>::Type >::Type
1438  , INVALID_TYPE >::Type Type;
1439  //**********************************************************************************************
1440 };
1442 //*************************************************************************************************
1443 
1444 
1445 //*************************************************************************************************
1447 template< typename VT, typename MT1, typename MT2 >
1448 struct TDVecDMatMultExprTrait< VT, SMatDMatMultExpr<MT1,MT2> >
1449 {
1450  public:
1451  //**********************************************************************************************
1452  typedef typename SelectType< IsDenseVector<VT>::value && IsRowVector<VT>::value &&
1453  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1454  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1455  , typename TDVecDMatMultExprTrait< typename TDVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1456  , INVALID_TYPE >::Type Type;
1457  //**********************************************************************************************
1458 };
1460 //*************************************************************************************************
1461 
1462 
1463 //*************************************************************************************************
1465 template< typename VT, typename MT1, typename MT2 >
1466 struct TSVecDMatMultExprTrait< VT, SMatDMatMultExpr<MT1,MT2> >
1467 {
1468  public:
1469  //**********************************************************************************************
1470  typedef typename SelectType< IsSparseVector<VT>::value && IsRowVector<VT>::value &&
1471  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1472  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1473  , typename TSVecDMatMultExprTrait< typename TSVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1474  , INVALID_TYPE >::Type Type;
1475  //**********************************************************************************************
1476 };
1478 //*************************************************************************************************
1479 
1480 
1481 //*************************************************************************************************
1483 template< typename MT1, typename MT2, bool AF >
1484 struct SubmatrixExprTrait< SMatDMatMultExpr<MT1,MT2>, AF >
1485 {
1486  public:
1487  //**********************************************************************************************
1488  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT1,AF>::Type
1489  , typename SubmatrixExprTrait<const MT2,AF>::Type >::Type Type;
1490  //**********************************************************************************************
1491 };
1493 //*************************************************************************************************
1494 
1495 
1496 //*************************************************************************************************
1498 template< typename MT1, typename MT2 >
1499 struct RowExprTrait< SMatDMatMultExpr<MT1,MT2> >
1500 {
1501  public:
1502  //**********************************************************************************************
1503  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
1504  //**********************************************************************************************
1505 };
1507 //*************************************************************************************************
1508 
1509 
1510 //*************************************************************************************************
1512 template< typename MT1, typename MT2 >
1513 struct ColumnExprTrait< SMatDMatMultExpr<MT1,MT2> >
1514 {
1515  public:
1516  //**********************************************************************************************
1517  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
1518  //**********************************************************************************************
1519 };
1521 //*************************************************************************************************
1522 
1523 } // namespace blaze
1524 
1525 #endif
SelectType< IsExpression< MT1 >::value, const MT1, const MT1 & >::Type LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: SMatDMatMultExpr.h:204
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:89
Header file for the SMatDVecMultExprTrait class template.
void reset(DynamicMatrix< Type, SO > &m)
Resetting the given dense matrix.
Definition: DynamicMatrix.h:4579
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:4075
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:151
LeftOperand leftOperand() const
Returns the left-hand side sparse matrix operand.
Definition: SMatDMatMultExpr.h:316
Header file for the IsSparseMatrix type trait.
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:197
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: SMatDMatMultExpr.h:370
#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 IsSame and IsStrictlySame type traits.
Header file for the sparse matrix SMP implementation.
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2384
Header file for the IsRowVector type trait.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:249
Header file for the TDVecSMatMultExprTrait class template.
Header file for the Computation base class.
Header file for the MatMatMultExpr base class.
Expression object for sparse matrix-dense matrix multiplications.The SMatDMatMultExpr class represent...
Definition: Forward.h:87
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.
Header file for the TSVecSMatMultExprTrait class template.
const ElementType ReturnType
Return type for expression template evaluations.
Definition: SMatDMatMultExpr.h:200
SelectType< IsExpression< MT2 >::value, const MT2, const MT2 & >::Type RightOperand
Composite type of the right-hand side dense matrix expression.
Definition: SMatDMatMultExpr.h:207
const ResultType CompositeType
Data type for composite expression templates.
Definition: SMatDMatMultExpr.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:104
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:121
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: SMatDMatMultExpr.h:350
Compile time check to query the requirement to evaluate an expression.Via this type trait it is possi...
Definition: RequiresEvaluation.h:90
RT1::ElementType ET1
Element type of the left-hand side sparse matrix expression.
Definition: SMatDMatMultExpr.h:115
Compile time type selection.The SelectType class template selects one of the two given types T1 and T...
Definition: SelectType.h:59
Header file for the DisableIf class template.
Header file for the multiplication trait.
#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
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2388
Header file for the dense matrix SMP implementation.
Header file for the DenseMatrix base class.
MT2::ResultType RT2
Result type of the right-hand side dense matrix expression.
Definition: SMatDMatMultExpr.h:114
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:179
Header file for the DMatDVecMultExprTrait class template.
RightOperand rightOperand() const
Returns the right-hand side dense matrix operand.
Definition: SMatDMatMultExpr.h:326
#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
Constraints on the storage order of matrix types.
MultTrait< RT1, RT2 >::Type ResultType
Result type for expression template evaluations.
Definition: SMatDMatMultExpr.h:195
SelectType< evaluateLeft, const RT1, CT1 >::Type LT
Type for the assignment of the left-hand side sparse matrix operand.
Definition: SMatDMatMultExpr.h:210
RightOperand rhs_
Right-hand side dense matrix of the multiplication expression.
Definition: SMatDMatMultExpr.h:378
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:2382
bool isAligned() const
Returns whether the operands of the expression are properly aligned in memory.
Definition: SMatDMatMultExpr.h:360
Header file for the SelectType class template.
Header file for the RowExprTrait class template.
Header file for all forward declarations for expression class templates.
IntrinsicTrait< ElementType >::Type IntrinsicType
Resulting intrinsic element type.
Definition: SMatDMatMultExpr.h:199
Header file for the IsDenseMatrix type trait.
Header file for the EnableIf class template.
ResultType::ElementType ElementType
Resulting element type.
Definition: SMatDMatMultExpr.h:198
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:91
ResultType::OppositeType OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: SMatDMatMultExpr.h:196
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
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: SMatDMatMultExpr.h:377
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
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: SMatDMatMultExpr.h:338
Header file for run time assertion macros.
Utility type for generic codes.
Base template for the MultTrait class.
Definition: MultTrait.h:141
SelectType< evaluateRight, const RT2, CT2 >::Type RT
Type for the assignment of the right-hand side dense matrix operand.
Definition: SMatDMatMultExpr.h:213
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:209
Substitution Failure Is Not An Error (SFINAE) class.The EnableIf class template is an auxiliary tool ...
Definition: EnableIf.h:184
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:239
size_t rows() const
Returns the current number of rows of the matrix.
Definition: SMatDMatMultExpr.h:296
const size_t SMP_SMATDMATMULT_THRESHOLD
SMP row-major sparse matrix/row-major dense matrix multiplication threshold.This threshold represents...
Definition: Thresholds.h:537
MT1::ResultType RT1
Result type of the left-hand side sparse matrix expression.
Definition: SMatDMatMultExpr.h:113
Header file for the RemoveReference type trait.
MT2::CompositeType CT2
Composite type of the right-hand side dense matrix expression.
Definition: SMatDMatMultExpr.h:118
SMatDMatMultExpr< MT1, MT2 > This
Type of this SMatDMatMultExpr instance.
Definition: SMatDMatMultExpr.h:194
#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.
RT2::ElementType ET2
Element type of the right-hand side dense matrix expression.
Definition: SMatDMatMultExpr.h:116
Header file for the IsRowMajorMatrix type trait.
Header file for the IsComputation type trait class.
SMatDMatMultExpr(const MT1 &lhs, const MT2 &rhs)
Constructor for the SMatDMatMultExpr class.
Definition: SMatDMatMultExpr.h:233
Header file for the TDVecDMatMultExprTrait 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
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:2379
MT1::CompositeType CT1
Composite type of the left-hand side sparse matrix expression.
Definition: SMatDMatMultExpr.h:117
size_t columns(const Matrix< MT, SO > &m)
Returns the current number of columns of the matrix.
Definition: Matrix.h:154
Header file for basic type definitions.
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: SMatDMatMultExpr.h:248
Header file for the TSVecDMatMultExprTrait class template.
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: SMatDMatMultExpr.h:197
Header file for the DMatSVecMultExprTrait class template.
Header file for the IsColumnVector type trait.
size_t columns() const
Returns the current number of columns of the matrix.
Definition: SMatDMatMultExpr.h:306
Header file for the IsResizable type trait.
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
size_t rows(const Matrix< MT, SO > &m)
Returns the current number of rows of the matrix.
Definition: Matrix.h:138
#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
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
void store(float *address, const sse_float_t &value)
Aligned store of a vector of &#39;float&#39; values.
Definition: Store.h:242
Header file for the IsExpression type trait class.
Header file for the FunctionTrace class.