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>
78 #include <blaze/util/Assert.h>
79 #include <blaze/util/DisableIf.h>
80 #include <blaze/util/EnableIf.h>
81 #include <blaze/util/InvalidType.h>
83 #include <blaze/util/SelectType.h>
84 #include <blaze/util/Types.h>
87 
88 
89 namespace blaze {
90 
91 //=================================================================================================
92 //
93 // CLASS SMATDMATMULTEXPR
94 //
95 //=================================================================================================
96 
97 //*************************************************************************************************
104 template< typename MT1 // Type of the left-hand side sparse matrix
105  , typename MT2 > // Type of the right-hand side dense matrix
106 class SMatDMatMultExpr : public DenseMatrix< SMatDMatMultExpr<MT1,MT2>, false >
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 && T3::vectorizable &&
151  IsRowMajorMatrix<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 = MT2::vectorizable &&
219 
221  enum { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
222  !evaluateRight && MT2::smpAssignable };
223  //**********************************************************************************************
224 
225  //**Constructor*********************************************************************************
231  explicit inline SMatDMatMultExpr( const MT1& lhs, const MT2& rhs )
232  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
233  , rhs_( rhs ) // Right-hand side dense 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() == 0 )
256  return tmp;
257 
258  // Fast computation in case the left-hand side sparse matrix directly provides iterators
260  {
261  CT1 A( lhs_ ); // Evaluation of the left-hand side sparse matrix operand
262 
263  const ConstIterator end( A.end(i) );
264  ConstIterator element( A.begin(i) );
265 
266  // Early exit in case row i is empty
267  if( element == end )
268  return tmp;
269 
270  // Calculating element (i,j)
271  tmp = element->value() * rhs_(element->index(),j);
272  ++element;
273  for( ; element!=end; ++element )
274  tmp += element->value() * rhs_(element->index(),j);
275  }
276 
277  // Default computation in case the left-hand side sparse matrix doesn't provide iterators
278  else {
279  tmp = lhs_(i,0) * rhs_(0,j);
280  for( size_t k=1; 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 rhs_.isAligned();
360  }
361  //**********************************************************************************************
362 
363  //**********************************************************************************************
368  inline bool canSMPAssign() const {
369  return ( rows() > SMP_SMATDMATMULT_THRESHOLD );
370  }
371  //**********************************************************************************************
372 
373  private:
374  //**Member variables****************************************************************************
377  //**********************************************************************************************
378 
379  //**Assignment to dense matrices****************************************************************
391  template< typename MT // Type of the target dense matrix
392  , bool SO > // Storage order of the target dense matrix
393  friend inline void assign( DenseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
394  {
396 
397  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
398  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
399 
400  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
401  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
402 
403  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
404  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
405  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
406  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
407  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
408  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
409 
410  SMatDMatMultExpr::selectAssignKernel( ~lhs, A, B );
411  }
413  //**********************************************************************************************
414 
415  //**Default assignment to row-major dense matrices**********************************************
429  template< typename MT3 // Type of the left-hand side target matrix
430  , typename MT4 // Type of the left-hand side matrix operand
431  , typename MT5 > // Type of the right-hand side matrix operand
432  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
433  selectAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
434  {
435  typedef typename MT4::ConstIterator ConstIterator;
436 
437  for( size_t i=0UL; i<A.rows(); ++i )
438  {
439  const ConstIterator end( A.end(i) );
440 
441  for( size_t j=0UL; j<B.columns(); ++j )
442  {
443  ConstIterator element( A.begin(i) );
444 
445  if( element != end ) {
446  (~C)(i,j) = element->value() * B(element->index(),j);
447  ++element;
448  for( ; element!=end; ++element ) {
449  (~C)(i,j) += element->value() * B(element->index(),j);
450  }
451  }
452  else {
453  reset( (~C)(i,j) );
454  }
455  }
456  }
457  }
459  //**********************************************************************************************
460 
461  //**Optimized assignment to row-major dense matrices********************************************
475  template< typename MT3 // Type of the left-hand side target matrix
476  , typename MT4 // Type of the left-hand side matrix operand
477  , typename MT5 > // Type of the right-hand side matrix operand
478  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
479  selectAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
480  {
481  typedef typename MT4::ConstIterator ConstIterator;
482 
483  const size_t jend( B.columns() & size_t(-4) );
484  BLAZE_INTERNAL_ASSERT( ( B.columns() - ( B.columns() % 4UL ) ) == jend, "Invalid end calculation" );
485 
486  reset( ~C );
487 
488  for( size_t i=0UL; i<A.rows(); ++i )
489  {
490  const ConstIterator end( A.end(i) );
491  ConstIterator element( A.begin(i) );
492 
493  const size_t kend( A.nonZeros(i) & size_t(-4) );
494 
495  for( size_t k=0UL; k<kend; k+=4UL ) {
496  const size_t i1( element->index() );
497  const ET1 v1( element->value() );
498  ++element;
499  const size_t i2( element->index() );
500  const ET1 v2( element->value() );
501  ++element;
502  const size_t i3( element->index() );
503  const ET1 v3( element->value() );
504  ++element;
505  const size_t i4( element->index() );
506  const ET1 v4( element->value() );
507  ++element;
508 
509  for( size_t j=0UL; j<jend; j+=4UL ) {
510  (~C)(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
511  (~C)(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
512  (~C)(i,j+2UL) += v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
513  (~C)(i,j+3UL) += v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
514  }
515  for( size_t j=jend; j<B.columns(); ++j ) {
516  (~C)(i,j) += v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
517  }
518  }
519 
520  for( ; element!=end; ++element ) {
521  for( size_t j=0UL; j<jend; j+=4UL ) {
522  (~C)(i,j ) += element->value() * B(element->index(),j );
523  (~C)(i,j+1UL) += element->value() * B(element->index(),j+1UL);
524  (~C)(i,j+2UL) += element->value() * B(element->index(),j+2UL);
525  (~C)(i,j+3UL) += element->value() * B(element->index(),j+3UL);
526  }
527  for( size_t j=jend; j<B.columns(); ++j ) {
528  (~C)(i,j) += element->value() * B(element->index(),j);
529  }
530  }
531  }
532  }
534  //**********************************************************************************************
535 
536  //**Vectorized assignment to row-major dense matrices*******************************************
550  template< typename MT3 // Type of the left-hand side target matrix
551  , typename MT4 // Type of the left-hand side matrix operand
552  , typename MT5 > // Type of the right-hand side matrix operand
553  static inline typename EnableIf< UseVectorizedKernel<MT3,MT4,MT5> >::Type
554  selectAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
555  {
556  typedef IntrinsicTrait<ElementType> IT;
557  typedef typename MT4::ConstIterator ConstIterator;
558 
559  const size_t N( B.columns() );
560 
561  reset( ~C );
562 
563  for( size_t i=0UL; i<A.rows(); ++i )
564  {
565  const ConstIterator end( A.end(i) );
566  ConstIterator element( A.begin(i) );
567 
568  const size_t kend( A.nonZeros(i) & size_t(-4) );
569 
570  for( size_t k=0UL; k<kend; k+=4UL ) {
571  const size_t i1( element->index() );
572  const IntrinsicType v1( set( element->value() ) );
573  ++element;
574  const size_t i2( element->index() );
575  const IntrinsicType v2( set( element->value() ) );
576  ++element;
577  const size_t i3( element->index() );
578  const IntrinsicType v3( set( element->value() ) );
579  ++element;
580  const size_t i4( element->index() );
581  const IntrinsicType v4( set( element->value() ) );
582  ++element;
583 
584  for( size_t j=0UL; j<N; j+=IT::size ) {
585  (~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) );
586  }
587  }
588 
589  for( ; element!=end; ++element ) {
590  const size_t i1( element->index() );
591  const IntrinsicType v1( set( element->value() ) );
592 
593  for( size_t j=0UL; j<N; j+=IT::size ) {
594  (~C).store( i, j, (~C).load(i,j) + v1 * B.load(i1,j) );
595  }
596  }
597  }
598  }
600  //**********************************************************************************************
601 
602  //**Default assignment to column-major dense matrices*******************************************
616  template< typename MT3 // Type of the left-hand side target matrix
617  , typename MT4 // Type of the left-hand side matrix operand
618  , typename MT5 > // Type of the right-hand side matrix operand
619  static inline void selectAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
620  {
621  typedef typename MT4::ConstIterator ConstIterator;
622 
623  const size_t jend( B.columns() & size_t(-4) );
624  BLAZE_INTERNAL_ASSERT( ( B.columns() - ( B.columns() % 4UL ) ) == jend, "Invalid end calculation" );
625 
626  for( size_t j=0UL; j<jend; j+=4UL ) {
627  for( size_t i=0UL; i<A.rows(); ++i )
628  {
629  ConstIterator element( A.begin(i) );
630  const ConstIterator end( A.end(i) );
631 
632  if( element == end ) {
633  reset( (~C)(i,j ) );
634  reset( (~C)(i,j+1UL) );
635  reset( (~C)(i,j+2UL) );
636  reset( (~C)(i,j+3UL) );
637  continue;
638  }
639 
640  (~C)(i,j ) = element->value() * B(element->index(),j );
641  (~C)(i,j+1UL) = element->value() * B(element->index(),j+1UL);
642  (~C)(i,j+2UL) = element->value() * B(element->index(),j+2UL);
643  (~C)(i,j+3UL) = element->value() * B(element->index(),j+3UL);
644  ++element;
645  for( ; element!=end; ++element ) {
646  (~C)(i,j ) += element->value() * B(element->index(),j );
647  (~C)(i,j+1UL) += element->value() * B(element->index(),j+1UL);
648  (~C)(i,j+2UL) += element->value() * B(element->index(),j+2UL);
649  (~C)(i,j+3UL) += element->value() * B(element->index(),j+3UL);
650  }
651  }
652  }
653 
654  for( size_t j=jend; j<B.columns(); ++j ) {
655  for( size_t i=0UL; i<A.rows(); ++i )
656  {
657  ConstIterator element( A.begin(i) );
658  const ConstIterator end( A.end(i) );
659 
660  if( element == end ) {
661  reset( (~C)(i,j) );
662  continue;
663  }
664 
665  (~C)(i,j) = element->value() * B(element->index(),j);
666  ++element;
667  for( ; element!=end; ++element )
668  (~C)(i,j) += element->value() * B(element->index(),j);
669  }
670  }
671  }
673  //**********************************************************************************************
674 
675  //**Assignment to sparse matrices***************************************************************
687  template< typename MT // Type of the target sparse matrix
688  , bool SO > // Storage order of the target sparse matrix
689  friend inline void assign( SparseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
690  {
692 
693  typedef typename SelectType< SO, OppositeType, ResultType >::Type TmpType;
694 
701 
702  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
703  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
704 
705  const TmpType tmp( serial( rhs ) );
706  assign( ~lhs, tmp );
707  }
709  //**********************************************************************************************
710 
711  //**Addition assignment to dense matrices*******************************************************
723  template< typename MT // Type of the target dense matrix
724  , bool SO > // Storage order of the target dense matrix
725  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
726  {
728 
729  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
730  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
731 
732  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
733  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
734 
735  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
736  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
737  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
738  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
739  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
740  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
741 
742  SMatDMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
743  }
745  //**********************************************************************************************
746 
747  //**Default addition assignment to row-major dense matrices*************************************
761  template< typename MT3 // Type of the left-hand side target matrix
762  , typename MT4 // Type of the left-hand side matrix operand
763  , typename MT5 > // Type of the right-hand side matrix operand
764  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
765  selectAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
766  {
767  typedef typename MT4::ConstIterator ConstIterator;
768 
769  for( size_t i=0UL; i<A.rows(); ++i )
770  {
771  const ConstIterator end( A.end(i) );
772 
773  for( size_t j=0UL; j<B.columns(); ++j )
774  {
775  ConstIterator element( A.begin(i) );
776 
777  for( ; element!=end; ++element ) {
778  (~C)(i,j) += element->value() * B(element->index(),j);
779  }
780  }
781  }
782  }
784  //**********************************************************************************************
785 
786  //**Optimized addition assignment to row-major dense matrices***********************************
800  template< typename MT3 // Type of the left-hand side target matrix
801  , typename MT4 // Type of the left-hand side matrix operand
802  , typename MT5 > // Type of the right-hand side matrix operand
803  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
804  selectAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
805  {
806  typedef typename MT4::ConstIterator ConstIterator;
807 
808  const size_t jend( B.columns() & size_t(-4) );
809  BLAZE_INTERNAL_ASSERT( ( B.columns() - ( B.columns() % 4UL ) ) == jend, "Invalid end calculation" );
810 
811  for( size_t i=0UL; i<A.rows(); ++i )
812  {
813  const ConstIterator end( A.end(i) );
814  ConstIterator element( A.begin(i) );
815 
816  const size_t kend( A.nonZeros(i) & size_t(-4) );
817 
818  for( size_t k=0UL; k<kend; k+=4UL ) {
819  const size_t i1( element->index() );
820  const ET1 v1( element->value() );
821  ++element;
822  const size_t i2( element->index() );
823  const ET1 v2( element->value() );
824  ++element;
825  const size_t i3( element->index() );
826  const ET1 v3( element->value() );
827  ++element;
828  const size_t i4( element->index() );
829  const ET1 v4( element->value() );
830  ++element;
831 
832  for( size_t j=0UL; j<jend; j+=4UL ) {
833  (~C)(i,j ) += v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
834  (~C)(i,j+1UL) += v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
835  (~C)(i,j+2UL) += v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
836  (~C)(i,j+3UL) += v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
837  }
838  for( size_t j=jend; j<B.columns(); ++j ) {
839  (~C)(i,j) += v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
840  }
841  }
842 
843  for( ; element!=end; ++element ) {
844  for( size_t j=0UL; j<jend; j+=4UL ) {
845  (~C)(i,j ) += element->value() * B(element->index(),j );
846  (~C)(i,j+1UL) += element->value() * B(element->index(),j+1UL);
847  (~C)(i,j+2UL) += element->value() * B(element->index(),j+2UL);
848  (~C)(i,j+3UL) += element->value() * B(element->index(),j+3UL);
849  }
850  for( size_t j=jend; j<B.columns(); ++j ) {
851  (~C)(i,j) += element->value() * B(element->index(),j);
852  }
853  }
854  }
855  }
857  //**********************************************************************************************
858 
859  //**Vectorized addition assignment to row-major dense matrices**********************************
873  template< typename MT3 // Type of the left-hand side target matrix
874  , typename MT4 // Type of the left-hand side matrix operand
875  , typename MT5 > // Type of the right-hand side matrix operand
876  static inline typename EnableIf< UseVectorizedKernel<MT3,MT4,MT5> >::Type
877  selectAddAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
878  {
879  typedef IntrinsicTrait<ElementType> IT;
880  typedef typename MT4::ConstIterator ConstIterator;
881 
882  const size_t N( B.columns() );
883 
884  for( size_t i=0UL; i<A.rows(); ++i )
885  {
886  const ConstIterator end( A.end(i) );
887  ConstIterator element( A.begin(i) );
888 
889  const size_t kend( A.nonZeros(i) & size_t(-4) );
890 
891  for( size_t k=0UL; k<kend; k+=4UL ) {
892  const size_t i1( element->index() );
893  const IntrinsicType v1( set( element->value() ) );
894  ++element;
895  const size_t i2( element->index() );
896  const IntrinsicType v2( set( element->value() ) );
897  ++element;
898  const size_t i3( element->index() );
899  const IntrinsicType v3( set( element->value() ) );
900  ++element;
901  const size_t i4( element->index() );
902  const IntrinsicType v4( set( element->value() ) );
903  ++element;
904 
905  for( size_t j=0UL; j<N; j+=IT::size ) {
906  (~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) );
907  }
908  }
909 
910  for( ; element!=end; ++element ) {
911  const size_t i1( element->index() );
912  const IntrinsicType v1( set( element->value() ) );
913 
914  for( size_t j=0UL; j<N; j+=IT::size ) {
915  (~C).store( i, j, (~C).load(i,j) + v1 * B.load(i1,j) );
916  }
917  }
918  }
919  }
921  //**********************************************************************************************
922 
923  //**Default addition assignment to column-major dense matrices**********************************
937  template< typename MT3 // Type of the left-hand side target matrix
938  , typename MT4 // Type of the left-hand side matrix operand
939  , typename MT5 > // Type of the right-hand side matrix operand
940  static inline void selectAddAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
941  {
942  typedef typename MT4::ConstIterator ConstIterator;
943 
944  const size_t jend( B.columns() & size_t(-4) );
945  BLAZE_INTERNAL_ASSERT( ( B.columns() - ( B.columns() % 4UL ) ) == jend, "Invalid end calculation" );
946 
947  for( size_t j=0UL; j<jend; j+=4UL ) {
948  for( size_t i=0UL; i<A.rows(); ++i )
949  {
950  ConstIterator element( A.begin(i) );
951  const ConstIterator end( A.end(i) );
952 
953  for( ; element!=end; ++element ) {
954  (~C)(i,j ) += element->value() * B(element->index(),j );
955  (~C)(i,j+1UL) += element->value() * B(element->index(),j+1UL);
956  (~C)(i,j+2UL) += element->value() * B(element->index(),j+2UL);
957  (~C)(i,j+3UL) += element->value() * B(element->index(),j+3UL);
958  }
959  }
960  }
961 
962  for( size_t j=jend; j<B.columns(); ++j ) {
963  for( size_t i=0UL; i<A.rows(); ++i )
964  {
965  ConstIterator element( A.begin(i) );
966  const ConstIterator end( A.end(i) );
967 
968  for( ; element!=end; ++element )
969  (~C)(i,j) += element->value() * B(element->index(),j);
970  }
971  }
972  }
974  //**********************************************************************************************
975 
976  //**Addition assignment to sparse matrices******************************************************
977  // No special implementation for the addition assignment to sparse matrices.
978  //**********************************************************************************************
979 
980  //**Subtraction assignment to dense matrices****************************************************
992  template< typename MT // Type of the target dense matrix
993  , bool SO > // Storage order of the target dense matrix
994  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
995  {
997 
998  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
999  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1000 
1001  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
1002  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side dense matrix operand
1003 
1004  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1005  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1006  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1007  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1008  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1009  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1010 
1011  SMatDMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
1012  }
1014  //**********************************************************************************************
1015 
1016  //**Default subtraction assignment to row-major dense matrices**********************************
1030  template< typename MT3 // Type of the left-hand side target matrix
1031  , typename MT4 // Type of the left-hand side matrix operand
1032  , typename MT5 > // Type of the right-hand side matrix operand
1033  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
1034  selectSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
1035  {
1036  typedef typename MT4::ConstIterator ConstIterator;
1037 
1038  for( size_t i=0UL; i<A.rows(); ++i )
1039  {
1040  const ConstIterator end( A.end(i) );
1041 
1042  for( size_t j=0UL; j<B.columns(); ++j )
1043  {
1044  ConstIterator element( A.begin(i) );
1045 
1046  for( ; element!=end; ++element ) {
1047  (~C)(i,j) -= element->value() * B(element->index(),j);
1048  }
1049  }
1050  }
1051  }
1053  //**********************************************************************************************
1054 
1055  //**Optimized subtraction assignment to row-major dense matrices********************************
1069  template< typename MT3 // Type of the left-hand side target matrix
1070  , typename MT4 // Type of the left-hand side matrix operand
1071  , typename MT5 > // Type of the right-hand side matrix operand
1072  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
1073  selectSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
1074  {
1075  typedef typename MT4::ConstIterator ConstIterator;
1076 
1077  const size_t jend( B.columns() & size_t(-4) );
1078  BLAZE_INTERNAL_ASSERT( ( B.columns() - ( B.columns() % 4UL ) ) == jend, "Invalid end calculation" );
1079 
1080  for( size_t i=0UL; i<A.rows(); ++i )
1081  {
1082  const ConstIterator end( A.end(i) );
1083  ConstIterator element( A.begin(i) );
1084 
1085  const size_t kend( A.nonZeros(i) & size_t(-4) );
1086 
1087  for( size_t k=0UL; k<kend; k+=4UL ) {
1088  const size_t i1( element->index() );
1089  const ET1 v1( element->value() );
1090  ++element;
1091  const size_t i2( element->index() );
1092  const ET1 v2( element->value() );
1093  ++element;
1094  const size_t i3( element->index() );
1095  const ET1 v3( element->value() );
1096  ++element;
1097  const size_t i4( element->index() );
1098  const ET1 v4( element->value() );
1099  ++element;
1100 
1101  for( size_t j=0UL; j<jend; j+=4UL ) {
1102  (~C)(i,j ) -= v1 * B(i1,j ) + v2 * B(i2,j ) + v3 * B(i3,j ) + v4 * B(i4,j );
1103  (~C)(i,j+1UL) -= v1 * B(i1,j+1UL) + v2 * B(i2,j+1UL) + v3 * B(i3,j+1UL) + v4 * B(i4,j+1UL);
1104  (~C)(i,j+2UL) -= v1 * B(i1,j+2UL) + v2 * B(i2,j+2UL) + v3 * B(i3,j+2UL) + v4 * B(i4,j+2UL);
1105  (~C)(i,j+3UL) -= v1 * B(i1,j+3UL) + v2 * B(i2,j+3UL) + v3 * B(i3,j+3UL) + v4 * B(i4,j+3UL);
1106  }
1107  for( size_t j=jend; j<B.columns(); ++j ) {
1108  (~C)(i,j) -= v1 * B(i1,j) + v2 * B(i2,j) + v3 * B(i3,j) + v4 * B(i4,j);
1109  }
1110  }
1111 
1112  for( ; element!=end; ++element ) {
1113  for( size_t j=0UL; j<jend; j+=4UL ) {
1114  (~C)(i,j ) -= element->value() * B(element->index(),j );
1115  (~C)(i,j+1UL) -= element->value() * B(element->index(),j+1UL);
1116  (~C)(i,j+2UL) -= element->value() * B(element->index(),j+2UL);
1117  (~C)(i,j+3UL) -= element->value() * B(element->index(),j+3UL);
1118  }
1119  for( size_t j=jend; j<B.columns(); ++j ) {
1120  (~C)(i,j) -= element->value() * B(element->index(),j);
1121  }
1122  }
1123  }
1124  }
1126  //**********************************************************************************************
1127 
1128  //**Vectorized subtraction assignment to row-major dense matrices*******************************
1142  template< typename MT3 // Type of the left-hand side target matrix
1143  , typename MT4 // Type of the left-hand side matrix operand
1144  , typename MT5 > // Type of the right-hand side matrix operand
1145  static inline typename EnableIf< UseVectorizedKernel<MT3,MT4,MT5> >::Type
1146  selectSubAssignKernel( DenseMatrix<MT3,false>& C, const MT4& A, const MT5& B )
1147  {
1148  typedef IntrinsicTrait<ElementType> IT;
1149  typedef typename MT4::ConstIterator ConstIterator;
1150 
1151  const size_t N( B.columns() );
1152 
1153  for( size_t i=0UL; i<A.rows(); ++i )
1154  {
1155  const ConstIterator end( A.end(i) );
1156  ConstIterator element( A.begin(i) );
1157 
1158  const size_t kend( A.nonZeros(i) & size_t(-4) );
1159 
1160  for( size_t k=0UL; k<kend; k+=4UL ) {
1161  const size_t i1( element->index() );
1162  const IntrinsicType v1( set( element->value() ) );
1163  ++element;
1164  const size_t i2( element->index() );
1165  const IntrinsicType v2( set( element->value() ) );
1166  ++element;
1167  const size_t i3( element->index() );
1168  const IntrinsicType v3( set( element->value() ) );
1169  ++element;
1170  const size_t i4( element->index() );
1171  const IntrinsicType v4( set( element->value() ) );
1172  ++element;
1173 
1174  for( size_t j=0UL; j<N; j+=IT::size ) {
1175  (~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) );
1176  }
1177  }
1178 
1179  for( ; element!=end; ++element ) {
1180  const size_t i1( element->index() );
1181  const IntrinsicType v1( set( element->value() ) );
1182 
1183  for( size_t j=0UL; j<N; j+=IT::size ) {
1184  (~C).store( i, j, (~C).load(i,j) - v1 * B.load(i1,j) );
1185  }
1186  }
1187  }
1188  }
1190  //**********************************************************************************************
1191 
1192  //**Default subtraction assignment to column-major dense matrices*******************************
1206  template< typename MT3 // Type of the left-hand side target matrix
1207  , typename MT4 // Type of the left-hand side matrix operand
1208  , typename MT5 > // Type of the right-hand side matrix operand
1209  static inline void selectSubAssignKernel( DenseMatrix<MT3,true>& C, const MT4& A, const MT5& B )
1210  {
1211  typedef typename MT4::ConstIterator ConstIterator;
1212 
1213  const size_t jend( B.columns() & size_t(-4) );
1214  BLAZE_INTERNAL_ASSERT( ( B.columns() - ( B.columns() % 4UL ) ) == jend, "Invalid end calculation" );
1215 
1216  for( size_t j=0UL; j<jend; j+=4UL ) {
1217  for( size_t i=0UL; i<A.rows(); ++i )
1218  {
1219  ConstIterator element( A.begin(i) );
1220  const ConstIterator end( A.end(i) );
1221 
1222  for( ; element!=end; ++element ) {
1223  (~C)(i,j ) -= element->value() * B(element->index(),j );
1224  (~C)(i,j+1UL) -= element->value() * B(element->index(),j+1UL);
1225  (~C)(i,j+2UL) -= element->value() * B(element->index(),j+2UL);
1226  (~C)(i,j+3UL) -= element->value() * B(element->index(),j+3UL);
1227  }
1228  }
1229  }
1230 
1231  for( size_t j=jend; j<B.columns(); ++j ) {
1232  for( size_t i=0UL; i<A.rows(); ++i )
1233  {
1234  ConstIterator element( A.begin(i) );
1235  const ConstIterator end( A.end(i) );
1236 
1237  for( ; element!=end; ++element )
1238  (~C)(i,j) -= element->value() * B(element->index(),j);
1239  }
1240  }
1241  }
1243  //**********************************************************************************************
1244 
1245  //**Subtraction assignment to sparse matrices***************************************************
1246  // No special implementation for the subtraction assignment to sparse matrices.
1247  //**********************************************************************************************
1248 
1249  //**Multiplication assignment to dense matrices*************************************************
1250  // No special implementation for the multiplication assignment to dense matrices.
1251  //**********************************************************************************************
1252 
1253  //**Multiplication assignment to sparse matrices************************************************
1254  // No special implementation for the multiplication assignment to sparse matrices.
1255  //**********************************************************************************************
1256 
1257  //**SMP assignment to dense matrices************************************************************
1271  template< typename MT // Type of the target dense matrix
1272  , bool SO > // Storage order of the target dense matrix
1273  friend inline typename EnableIf< UseSMPAssign<MT> >::Type
1274  smpAssign( DenseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
1275  {
1277 
1278  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1279  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1280 
1281  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
1282  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
1283 
1284  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1285  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1286  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1287  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1288  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1289  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1290 
1291  smpAssign( ~lhs, A * B );
1292  }
1294  //**********************************************************************************************
1295 
1296  //**SMP assignment to sparse matrices***********************************************************
1310  template< typename MT // Type of the target sparse matrix
1311  , bool SO > // Storage order of the target sparse matrix
1312  friend inline typename EnableIf< UseSMPAssign<MT> >::Type
1313  smpAssign( SparseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
1314  {
1316 
1317  typedef typename SelectType< SO, OppositeType, ResultType >::Type TmpType;
1318 
1325 
1326  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1327  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1328 
1329  const TmpType tmp( rhs );
1330  smpAssign( ~lhs, tmp );
1331  }
1333  //**********************************************************************************************
1334 
1335  //**SMP addition assignment to dense matrices***************************************************
1350  template< typename MT // Type of the target dense matrix
1351  , bool SO > // Storage order of the target dense matrix
1352  friend inline typename EnableIf< UseSMPAssign<MT> >::Type
1353  smpAddAssign( DenseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
1354  {
1356 
1357  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1358  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1359 
1360  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
1361  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
1362 
1363  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1364  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1365  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1366  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1367  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1368  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1369 
1370  smpAddAssign( ~lhs, A * B );
1371  }
1373  //**********************************************************************************************
1374 
1375  //**SMP addition assignment to sparse matrices**************************************************
1376  // No special implementation for the SMP addition assignment to sparse matrices.
1377  //**********************************************************************************************
1378 
1379  //**SMP subtraction assignment to dense matrices************************************************
1394  template< typename MT // Type of the target dense matrix
1395  , bool SO > // Storage order of the target dense matrix
1396  friend inline typename EnableIf< UseSMPAssign<MT> >::Type
1397  smpSubAssign( DenseMatrix<MT,SO>& lhs, const SMatDMatMultExpr& rhs )
1398  {
1400 
1401  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1402  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1403 
1404  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
1405  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
1406 
1407  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1408  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1409  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1410  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1411  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1412  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1413 
1414  smpSubAssign( ~lhs, A * B );
1415  }
1417  //**********************************************************************************************
1418 
1419  //**SMP subtraction assignment to sparse matrices***********************************************
1420  // No special implementation for the SMP subtraction assignment to sparse matrices.
1421  //**********************************************************************************************
1422 
1423  //**SMP multiplication assignment to dense matrices*********************************************
1424  // No special implementation for the SMP multiplication assignment to dense matrices.
1425  //**********************************************************************************************
1426 
1427  //**SMP multiplication assignment to sparse matrices********************************************
1428  // No special implementation for the SMP multiplication assignment to sparse matrices.
1429  //**********************************************************************************************
1430 
1431  //**Compile time checks*************************************************************************
1438  //**********************************************************************************************
1439 };
1440 //*************************************************************************************************
1441 
1442 
1443 
1444 
1445 //=================================================================================================
1446 //
1447 // GLOBAL BINARY ARITHMETIC OPERATORS
1448 //
1449 //=================================================================================================
1450 
1451 //*************************************************************************************************
1480 template< typename T1 // Type of the left-hand side sparse matrix
1481  , typename T2 > // Type of the right-hand side dense matrix
1482 inline const SMatDMatMultExpr<T1,T2>
1484 {
1486 
1487  if( (~lhs).columns() != (~rhs).rows() )
1488  throw std::invalid_argument( "Matrix sizes do not match" );
1489 
1490  return SMatDMatMultExpr<T1,T2>( ~lhs, ~rhs );
1491 }
1492 //*************************************************************************************************
1493 
1494 
1495 
1496 
1497 //=================================================================================================
1498 //
1499 // EXPRESSION TRAIT SPECIALIZATIONS
1500 //
1501 //=================================================================================================
1502 
1503 //*************************************************************************************************
1505 template< typename MT1, typename MT2, typename VT >
1506 struct DMatDVecMultExprTrait< SMatDMatMultExpr<MT1,MT2>, VT >
1507 {
1508  public:
1509  //**********************************************************************************************
1510  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1511  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1512  IsDenseVector<VT>::value && IsColumnVector<VT>::value
1513  , typename SMatDVecMultExprTrait< MT1, typename DMatDVecMultExprTrait<MT2,VT>::Type >::Type
1514  , INVALID_TYPE >::Type Type;
1515  //**********************************************************************************************
1516 };
1518 //*************************************************************************************************
1519 
1520 
1521 //*************************************************************************************************
1523 template< typename MT1, typename MT2, typename VT >
1524 struct DMatSVecMultExprTrait< SMatDMatMultExpr<MT1,MT2>, VT >
1525 {
1526  public:
1527  //**********************************************************************************************
1528  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1529  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1530  IsSparseVector<VT>::value && IsColumnVector<VT>::value
1531  , typename SMatDVecMultExprTrait< MT1, typename DMatSVecMultExprTrait<MT2,VT>::Type >::Type
1532  , INVALID_TYPE >::Type Type;
1533  //**********************************************************************************************
1534 };
1536 //*************************************************************************************************
1537 
1538 
1539 //*************************************************************************************************
1541 template< typename VT, typename MT1, typename MT2 >
1542 struct TDVecDMatMultExprTrait< VT, SMatDMatMultExpr<MT1,MT2> >
1543 {
1544  public:
1545  //**********************************************************************************************
1546  typedef typename SelectType< IsDenseVector<VT>::value && IsRowVector<VT>::value &&
1547  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1548  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1549  , typename TDVecDMatMultExprTrait< typename TDVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1550  , INVALID_TYPE >::Type Type;
1551  //**********************************************************************************************
1552 };
1554 //*************************************************************************************************
1555 
1556 
1557 //*************************************************************************************************
1559 template< typename VT, typename MT1, typename MT2 >
1560 struct TSVecDMatMultExprTrait< VT, SMatDMatMultExpr<MT1,MT2> >
1561 {
1562  public:
1563  //**********************************************************************************************
1564  typedef typename SelectType< IsSparseVector<VT>::value && IsRowVector<VT>::value &&
1565  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1566  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1567  , typename TSVecDMatMultExprTrait< typename TSVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1568  , INVALID_TYPE >::Type Type;
1569  //**********************************************************************************************
1570 };
1572 //*************************************************************************************************
1573 
1574 
1575 //*************************************************************************************************
1577 template< typename MT1, typename MT2, bool AF >
1578 struct SubmatrixExprTrait< SMatDMatMultExpr<MT1,MT2>, AF >
1579 {
1580  public:
1581  //**********************************************************************************************
1582  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT1,AF>::Type
1583  , typename SubmatrixExprTrait<const MT2,AF>::Type >::Type Type;
1584  //**********************************************************************************************
1585 };
1587 //*************************************************************************************************
1588 
1589 
1590 //*************************************************************************************************
1592 template< typename MT1, typename MT2 >
1593 struct RowExprTrait< SMatDMatMultExpr<MT1,MT2> >
1594 {
1595  public:
1596  //**********************************************************************************************
1597  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
1598  //**********************************************************************************************
1599 };
1601 //*************************************************************************************************
1602 
1603 
1604 //*************************************************************************************************
1606 template< typename MT1, typename MT2 >
1607 struct ColumnExprTrait< SMatDMatMultExpr<MT1,MT2> >
1608 {
1609  public:
1610  //**********************************************************************************************
1611  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
1612  //**********************************************************************************************
1613 };
1615 //*************************************************************************************************
1616 
1617 } // namespace blaze
1618 
1619 #endif
SelectType< IsExpression< MT1 >::value, const MT1, const MT1 & >::Type LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: SMatDMatMultExpr.h:201
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: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
LeftOperand leftOperand() const
Returns the left-hand side sparse matrix operand.
Definition: SMatDMatMultExpr.h:314
Header file for the IsSparseMatrix type trait.
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:199
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: SMatDMatMultExpr.h:368
#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.
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
Header file for the TDVecSMatMultExprTrait class template.
const DMatSerialExpr< MT, SO > serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:690
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:89
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:197
SelectType< IsExpression< MT2 >::value, const MT2, const MT2 & >::Type RightOperand
Composite type of the right-hand side dense matrix expression.
Definition: SMatDMatMultExpr.h:204
const ResultType CompositeType
Data type for composite expression templates.
Definition: SMatDMatMultExpr.h:198
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
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
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: SMatDMatMultExpr.h:348
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:114
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:2412
Header file for the DenseMatrix base class.
MT2::ResultType RT2
Result type of the right-hand side dense matrix expression.
Definition: SMatDMatMultExpr.h:113
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
Header file for the DMatDVecMultExprTrait class template.
RightOperand rightOperand() const
Returns the right-hand side dense matrix operand.
Definition: SMatDMatMultExpr.h:324
#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:192
SelectType< evaluateLeft, const RT1, CT1 >::Type LT
Type for the assignment of the left-hand side sparse matrix operand.
Definition: SMatDMatMultExpr.h:207
RightOperand rhs_
Right-hand side dense matrix of the multiplication expression.
Definition: SMatDMatMultExpr.h:376
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:2406
bool isAligned() const
Returns whether the operands of the expression are properly aligned in memory.
Definition: SMatDMatMultExpr.h:358
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:196
Header file for the IsDenseMatrix type trait.
Header file for the EnableIf class template.
const size_t SMP_SMATDMATMULT_THRESHOLD
SMP row-major sparse matrix/row-major dense matrix multiplication threshold.This threshold specifies ...
Definition: Thresholds.h:1018
Header file for the serial shim.
ResultType::ElementType ElementType
Resulting element type.
Definition: SMatDMatMultExpr.h:195
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
ResultType::OppositeType OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: SMatDMatMultExpr.h:193
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:375
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:336
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:210
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
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:331
size_t rows() const
Returns the current number of rows of the matrix.
Definition: SMatDMatMultExpr.h:294
MT1::ResultType RT1
Result type of the left-hand side sparse matrix expression.
Definition: SMatDMatMultExpr.h:112
Header file for the RemoveReference type trait.
MT2::CompositeType CT2
Composite type of the right-hand side dense matrix expression.
Definition: SMatDMatMultExpr.h:117
SMatDMatMultExpr< MT1, MT2 > This
Type of this SMatDMatMultExpr instance.
Definition: SMatDMatMultExpr.h:191
#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:115
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:231
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:2403
MT1::CompositeType CT1
Composite type of the left-hand side sparse matrix expression.
Definition: SMatDMatMultExpr.h:116
Header file for basic type definitions.
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: SMatDMatMultExpr.h:246
Header file for the TSVecDMatMultExprTrait class template.
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: SMatDMatMultExpr.h:194
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:304
Header file for the IsResizable type trait.
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
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 FunctionTrace class.