All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DMatSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_DMATSMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_DMATSMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <stdexcept>
54 #include <blaze/math/shims/Reset.h>
84 #include <blaze/util/Assert.h>
86 #include <blaze/util/DisableIf.h>
87 #include <blaze/util/EnableIf.h>
88 #include <blaze/util/InvalidType.h>
90 #include <blaze/util/SelectType.h>
91 #include <blaze/util/Types.h>
93 
94 
95 namespace blaze {
96 
97 //=================================================================================================
98 //
99 // CLASS DMATSMATMULTEXPR
100 //
101 //=================================================================================================
102 
103 //*************************************************************************************************
110 template< typename MT1 // Type of the left-hand side dense matrix
111  , typename MT2 > // Type of the right-hand side sparse matrix
112 class DMatSMatMultExpr : public DenseMatrix< DMatSMatMultExpr<MT1,MT2>, false >
113  , private MatMatMultExpr
114  , private Computation
115 {
116  private:
117  //**Type definitions****************************************************************************
118  typedef typename MT1::ResultType RT1;
119  typedef typename MT2::ResultType RT2;
120  typedef typename RT1::ElementType ET1;
121  typedef typename RT2::ElementType ET2;
122  typedef typename MT1::CompositeType CT1;
123  typedef typename MT2::CompositeType CT2;
124  //**********************************************************************************************
125 
126  //**********************************************************************************************
129  //**********************************************************************************************
130 
131  //**********************************************************************************************
133  enum { evaluateRight = IsComputation<MT2>::value || RequiresEvaluation<MT2>::value };
134  //**********************************************************************************************
135 
136  //**********************************************************************************************
138 
144  template< typename T1, typename T2, typename T3 >
145  struct CanExploitSymmetry {
146  enum { value = IsColumnMajorMatrix<T1>::value &&
147  ( IsSymmetric<T2>::value || IsSymmetric<T3>::value ) };
148  };
150  //**********************************************************************************************
151 
152  //**********************************************************************************************
154 
158  template< typename T1, typename T2, typename T3 >
159  struct IsEvaluationRequired {
160  enum { value = ( evaluateLeft || evaluateRight ) &&
161  !CanExploitSymmetry<T1,T2,T3>::value };
162  };
164  //**********************************************************************************************
165 
166  //**********************************************************************************************
168 
171  template< typename T1, typename T2, typename T3 >
172  struct UseOptimizedKernel {
173  enum { value = !IsResizable<typename T1::ElementType>::value };
174  };
176  //**********************************************************************************************
177 
178  //**********************************************************************************************
180 
183  template< typename T1, typename T2, typename T3 >
184  struct UseDefaultKernel {
185  enum { value = !UseOptimizedKernel<T1,T2,T3>::value };
186  };
188  //**********************************************************************************************
189 
190  public:
191  //**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 = 0 };
216 
218  enum { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
219  !evaluateRight && MT2::smpAssignable };
220  //**********************************************************************************************
221 
222  //**Constructor*********************************************************************************
228  explicit inline DMatSMatMultExpr( const MT1& lhs, const MT2& rhs )
229  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
230  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
231  {
232  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
233  }
234  //**********************************************************************************************
235 
236  //**Access operator*****************************************************************************
243  inline ReturnType operator()( size_t i, size_t j ) const {
244  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
245  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
246 
247  ElementType tmp;
248 
249  if( lhs_.columns() != 0UL ) {
250  tmp = lhs_(i,0UL) * rhs_(0UL,j);
251  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
252  tmp += lhs_(i,k) * rhs_(k,j);
253  }
254  }
255  else {
256  reset( tmp );
257  }
258 
259  return tmp;
260  }
261  //**********************************************************************************************
262 
263  //**Rows function*******************************************************************************
268  inline size_t rows() const {
269  return lhs_.rows();
270  }
271  //**********************************************************************************************
272 
273  //**Columns function****************************************************************************
278  inline size_t columns() const {
279  return rhs_.columns();
280  }
281  //**********************************************************************************************
282 
283  //**Left operand access*************************************************************************
288  inline LeftOperand leftOperand() const {
289  return lhs_;
290  }
291  //**********************************************************************************************
292 
293  //**Right operand access************************************************************************
298  inline RightOperand rightOperand() const {
299  return rhs_;
300  }
301  //**********************************************************************************************
302 
303  //**********************************************************************************************
309  template< typename T >
310  inline bool canAlias( const T* alias ) const {
311  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
312  }
313  //**********************************************************************************************
314 
315  //**********************************************************************************************
321  template< typename T >
322  inline bool isAliased( const T* alias ) const {
323  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
324  }
325  //**********************************************************************************************
326 
327  //**********************************************************************************************
332  inline bool isAligned() const {
333  return lhs_.isAligned();
334  }
335  //**********************************************************************************************
336 
337  //**********************************************************************************************
342  inline bool canSMPAssign() const {
343  return ( rows() > SMP_DMATSMATMULT_THRESHOLD );
344  }
345  //**********************************************************************************************
346 
347  private:
348  //**Member variables****************************************************************************
351  //**********************************************************************************************
352 
353  //**Assignment to row-major dense matrices******************************************************
366  template< typename MT > // Type of the target dense matrix
367  friend inline void assign( DenseMatrix<MT,false>& lhs, const DMatSMatMultExpr& rhs )
368  {
370 
371  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
372  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
373 
374  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
375  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
376 
377  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
378  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
379  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
380  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
381  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
382  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
383 
384  DMatSMatMultExpr::selectRowMajorAssignKernel( ~lhs, A, B );
385  }
387  //**********************************************************************************************
388 
389  //**Default assignment to row-major dense matrices**********************************************
403  template< typename MT3 // Type of the left-hand side target matrix
404  , typename MT4 // Type of the left-hand side matrix operand
405  , typename MT5 > // Type of the right-hand side matrix operand
406  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
407  selectRowMajorAssignKernel( MT3& C, const MT4& A, const MT5& B )
408  {
409  typedef typename MT5::ConstIterator ConstIterator;
410 
411  for( size_t i=0UL; i<A.rows(); ++i ) {
412  for( size_t j=0UL; j<C.columns(); ++j ) {
413  reset( C(i,j) );
414  }
415  for( size_t j=0UL; j<B.rows(); ++j ) {
416  ConstIterator element( B.begin(j) );
417  const ConstIterator end( B.end(j) );
418  for( ; element!=end; ++element ) {
419  if( isDefault( C(i,element->index()) ) )
420  C(i,element->index()) = A(i,j) * element->value();
421  else
422  C(i,element->index()) += A(i,j) * element->value();
423  }
424  }
425  }
426  }
428  //**********************************************************************************************
429 
430  //**Optimized assignment to row-major dense matrices********************************************
444  template< typename MT3 // Type of the left-hand side target matrix
445  , typename MT4 // Type of the left-hand side matrix operand
446  , typename MT5 > // Type of the right-hand side matrix operand
447  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
448  selectRowMajorAssignKernel( MT3& C, const MT4& A, const MT5& B )
449  {
450  typedef typename MT5::ConstIterator ConstIterator;
451 
452  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
453  const size_t last( A.rows() & size_t(-4) );
454 
455  for( size_t i=0UL; i<last; i+=4UL ) {
456  for( size_t j=0UL; j<C.columns(); ++j ) {
457  reset( C(i ,j) );
458  reset( C(i+1UL,j) );
459  reset( C(i+2UL,j) );
460  reset( C(i+3UL,j) );
461  }
462  for( size_t j=0UL; j<B.rows(); ++j ) {
463  ConstIterator element( B.begin(j) );
464  const ConstIterator end( B.end(j) );
465  for( ; element!=end; ++element ) {
466  C(i ,element->index()) += A(i ,j) * element->value();
467  C(i+1UL,element->index()) += A(i+1UL,j) * element->value();
468  C(i+2UL,element->index()) += A(i+2UL,j) * element->value();
469  C(i+3UL,element->index()) += A(i+3UL,j) * element->value();
470  }
471  }
472  }
473 
474  for( size_t i=last; i<A.rows(); ++i ) {
475  for( size_t j=0UL; j<C.columns(); ++j ) {
476  reset( C(i,j) );
477  }
478  for( size_t j=0UL; j<B.rows(); ++j ) {
479  ConstIterator element( B.begin(j) );
480  const ConstIterator end( B.end(j) );
481  for( ; element!=end; ++element ) {
482  C(i,element->index()) += A(i,j) * element->value();
483  }
484  }
485  }
486  }
488  //**********************************************************************************************
489 
490  //**Assignment to column-major dense matrices***************************************************
503  template< typename MT > // Type of the target dense matrix
504  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
505  assign( DenseMatrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
506  {
508 
510 
511  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
512  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
513 
514  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
515  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
516 
517  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
518  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
519  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
520  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
521  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
522  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
523 
524  DMatSMatMultExpr::selectColumnMajorAssignKernel( ~lhs, A, B );
525  }
527  //**********************************************************************************************
528 
529  //**Default assignment to column-major dense matrices*******************************************
543  template< typename MT3 // Type of the left-hand side target matrix
544  , typename MT4 // Type of the left-hand side matrix operand
545  , typename MT5 > // Type of the right-hand side matrix operand
546  static inline typename EnableIf< UseDefaultKernel<MT3,MT4,MT5> >::Type
547  selectColumnMajorAssignKernel( MT3& C, const MT4& A, const MT5& B )
548  {
549  typedef typename MT5::ConstIterator ConstIterator;
550 
551  reset( C );
552 
553  for( size_t i=0UL; i<B.rows(); ++i ) {
554  for( size_t jj=0UL; jj<A.rows(); jj+=8UL ) {
555  const size_t jend( ( jj+8UL > A.rows() )?( A.rows() ):( jj+8UL ) );
556  ConstIterator element( B.begin(i) );
557  const ConstIterator end( B.end(i) );
558  for( ; element!=end; ++element ) {
559  for( size_t j=jj; j<jend; ++j ) {
560  if( isDefault( C(j,element->index()) ) )
561  C(j,element->index()) = A(j,i) * element->value();
562  else
563  C(j,element->index()) += A(j,i) * element->value();
564  }
565  }
566  }
567  }
568  }
570  //**********************************************************************************************
571 
572  //**Optimized assignment to column-major dense matrices*****************************************
586  template< typename MT3 // Type of the left-hand side target matrix
587  , typename MT4 // Type of the left-hand side matrix operand
588  , typename MT5 > // Type of the right-hand side matrix operand
589  static inline typename EnableIf< UseOptimizedKernel<MT3,MT4,MT5> >::Type
590  selectColumnMajorAssignKernel( MT3& C, const MT4& A, const MT5& B )
591  {
592  typedef typename MT5::ConstIterator ConstIterator;
593 
594  reset( C );
595 
596  for( size_t i=0UL; i<B.rows(); ++i ) {
597  for( size_t jj=0UL; jj<A.rows(); jj+=8UL ) {
598  const size_t jend( ( jj+8UL > A.rows() )?( A.rows() ):( jj+8UL ) );
599  ConstIterator element( B.begin(i) );
600  const ConstIterator end( B.end(i) );
601  for( ; element!=end; ++element ) {
602  for( size_t j=jj; j<jend; ++j ) {
603  C(j,element->index()) += A(j,i) * element->value();
604  }
605  }
606  }
607  }
608  }
610  //**********************************************************************************************
611 
612  //**Assignment to sparse matrices***************************************************************
625  template< typename MT // Type of the target sparse matrix
626  , bool SO > // Storage order of the target sparse matrix
627  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
628  assign( SparseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
629  {
631 
632  typedef typename SelectType< SO, OppositeType, ResultType >::Type TmpType;
633 
640 
641  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
642  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
643 
644  const TmpType tmp( serial( rhs ) );
645  assign( ~lhs, tmp );
646  }
648  //**********************************************************************************************
649 
650  //**Restructuring assignment to column-major matrices*******************************************
665  template< typename MT > // Type of the target matrix
666  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
667  assign( Matrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
668  {
670 
672 
673  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
674  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
675 
676  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
677  assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
678  else if( IsSymmetric<MT1>::value )
679  assign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
680  else
681  assign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
682  }
684  //**********************************************************************************************
685 
686  //**Addition assignment to row-major dense matrices*********************************************
699  template< typename MT > // Type of the target dense matrix
700  friend inline void addAssign( DenseMatrix<MT,false>& lhs, const DMatSMatMultExpr& rhs )
701  {
703 
704  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
705  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
706 
707  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
708  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
709 
710  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
711  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
712  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
713  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
714  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
715  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
716 
717  DMatSMatMultExpr::selectRowMajorAddAssignKernel( ~lhs, A, B );
718  }
720  //**********************************************************************************************
721 
722  //**Optimized addition assignment to row-major dense matrices***********************************
736  template< typename MT3 // Type of the left-hand side target matrix
737  , typename MT4 // Type of the left-hand side matrix operand
738  , typename MT5 > // Type of the right-hand side matrix operand
739  static inline void selectRowMajorAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
740  {
741  typedef typename MT5::ConstIterator ConstIterator;
742 
743  const size_t last( A.rows() & size_t(-4) );
744 
745  for( size_t i=0UL; i<last; i+=4UL ) {
746  for( size_t j=0UL; j<B.rows(); ++j ) {
747  ConstIterator element( B.begin(j) );
748  const ConstIterator end( B.end(j) );
749  for( ; element!=end; ++element ) {
750  C(i ,element->index()) += A(i ,j) * element->value();
751  C(i+1UL,element->index()) += A(i+1UL,j) * element->value();
752  C(i+2UL,element->index()) += A(i+2UL,j) * element->value();
753  C(i+3UL,element->index()) += A(i+3UL,j) * element->value();
754  }
755  }
756  }
757 
758  for( size_t i=last; i<A.rows(); ++i ) {
759  for( size_t j=0UL; j<B.rows(); ++j ) {
760  ConstIterator element( B.begin(j) );
761  const ConstIterator end( B.end(j) );
762  for( ; element!=end; ++element ) {
763  C(i,element->index()) += A(i,j) * element->value();
764  }
765  }
766  }
767  }
769  //**********************************************************************************************
770 
771  //**Addition assignment to column-major dense matrices******************************************
784  template< typename MT > // Type of the target dense matrix
785  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
786  addAssign( DenseMatrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
787  {
789 
791 
792  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
793  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
794 
795  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
796  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
797 
798  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
799  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
800  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
801  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
802  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
803  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
804 
805  DMatSMatMultExpr::selectColumnMajorAddAssignKernel( ~lhs, A, B );
806  }
808  //**********************************************************************************************
809 
810  //**Optimized addition assignment to column-major dense matrices********************************
824  template< typename MT3 // Type of the left-hand side target matrix
825  , typename MT4 // Type of the left-hand side matrix operand
826  , typename MT5 > // Type of the right-hand side matrix operand
827  static inline void selectColumnMajorAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
828  {
829  typedef typename MT5::ConstIterator ConstIterator;
830 
831  for( size_t i=0UL; i<B.rows(); ++i ) {
832  for( size_t jj=0UL; jj<A.rows(); jj+=8UL ) {
833  const size_t jend( ( jj+8UL > A.rows() )?( A.rows() ):( jj+8UL ) );
834  ConstIterator element( B.begin(i) );
835  const ConstIterator end( B.end(i) );
836  for( ; element!=end; ++element ) {
837  for( size_t j=jj; j<jend; ++j ) {
838  C(j,element->index()) += A(j,i) * element->value();
839  }
840  }
841  }
842  }
843  }
845  //**********************************************************************************************
846 
847  //**Restructuring addition assignment to column-major matrices**********************************
862  template< typename MT > // Type of the target matrix
863  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
864  addAssign( Matrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
865  {
867 
869 
870  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
871  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
872 
873  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
874  addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
875  else if( IsSymmetric<MT1>::value )
876  addAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
877  else
878  addAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
879  }
881  //**********************************************************************************************
882 
883  //**Addition assignment to sparse matrices******************************************************
884  // No special implementation for the addition assignment to sparse matrices.
885  //**********************************************************************************************
886 
887  //**Subtraction assignment to row-major dense matrices******************************************
900  template< typename MT > // Type of the target dense matrix
901  friend inline void subAssign( DenseMatrix<MT,false>& lhs, const DMatSMatMultExpr& rhs )
902  {
904 
905  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
906  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
907 
908  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
909  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
910 
911  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
912  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
913  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
914  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
915  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
916  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
917 
918  DMatSMatMultExpr::selectRowMajorSubAssignKernel( ~lhs, A, B );
919  }
921  //**********************************************************************************************
922 
923  //**Optimized subtraction assignment to row-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 selectRowMajorSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
941  {
942  typedef typename MT5::ConstIterator ConstIterator;
943 
944  const size_t last( A.rows() & size_t(-4) );
945 
946  for( size_t i=0UL; i<last; i+=4UL ) {
947  for( size_t j=0UL; j<B.rows(); ++j ) {
948  ConstIterator element( B.begin(j) );
949  const ConstIterator end( B.end(j) );
950  for( ; element!=end; ++element ) {
951  C(i ,element->index()) -= A(i ,j) * element->value();
952  C(i+1UL,element->index()) -= A(i+1UL,j) * element->value();
953  C(i+2UL,element->index()) -= A(i+2UL,j) * element->value();
954  C(i+3UL,element->index()) -= A(i+3UL,j) * element->value();
955  }
956  }
957  }
958 
959  for( size_t i=last; i<A.rows(); ++i ) {
960  for( size_t j=0UL; j<B.rows(); ++j ) {
961  ConstIterator element( B.begin(j) );
962  const ConstIterator end( B.end(j) );
963  for( ; element!=end; ++element ) {
964  C(i,element->index()) -= A(i,j) * element->value();
965  }
966  }
967  }
968  }
970  //**********************************************************************************************
971 
972  //**Subtraction assignment to column-major dense matrices***************************************
985  template< typename MT > // Type of the target dense matrix
986  friend inline void subAssign( DenseMatrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
987  {
989 
991 
992  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
993  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
994 
995  LT A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side dense matrix operand
996  RT B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
997 
998  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
999  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1000  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1001  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1002  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1003  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1004 
1005  DMatSMatMultExpr::selectColumnMajorSubAssignKernel( ~lhs, A, B );
1006  }
1008  //**********************************************************************************************
1009 
1010  //**Optimized subtraction assignment to column-major dense matrices*****************************
1024  template< typename MT3 // Type of the left-hand side target matrix
1025  , typename MT4 // Type of the left-hand side matrix operand
1026  , typename MT5 > // Type of the right-hand side matrix operand
1027  static inline void selectColumnMajorSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
1028  {
1029  typedef typename MT5::ConstIterator ConstIterator;
1030 
1031  for( size_t i=0UL; i<B.rows(); ++i ) {
1032  for( size_t jj=0UL; jj<A.rows(); jj+=8UL ) {
1033  const size_t jend( ( jj+8UL > A.rows() )?( A.rows() ):( jj+8UL ) );
1034  ConstIterator element( B.begin(i) );
1035  const ConstIterator end( B.end(i) );
1036  for( ; element!=end; ++element ) {
1037  for( size_t j=jj; j<jend; ++j ) {
1038  C(j,element->index()) -= A(j,i) * element->value();
1039  }
1040  }
1041  }
1042  }
1043  }
1045  //**********************************************************************************************
1046 
1047  //**Restructuring subtraction assignment to column-major matrices*******************************
1062  template< typename MT > // Type of the target matrix
1063  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1064  subAssign( Matrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
1065  {
1067 
1069 
1070  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1071  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1072 
1073  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1074  subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1075  else if( IsSymmetric<MT1>::value )
1076  subAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1077  else
1078  subAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1079  }
1081  //**********************************************************************************************
1082 
1083  //**Subtraction assignment to sparse matrices***************************************************
1084  // No special implementation for the subtraction assignment to sparse matrices.
1085  //**********************************************************************************************
1086 
1087  //**Multiplication assignment to dense matrices*************************************************
1088  // No special implementation for the multiplication assignment to dense matrices.
1089  //**********************************************************************************************
1090 
1091  //**Multiplication assignment to sparse matrices************************************************
1092  // No special implementation for the multiplication assignment to sparse matrices.
1093  //**********************************************************************************************
1094 
1095  //**SMP assignment to dense matrices************************************************************
1110  template< typename MT // Type of the target dense matrix
1111  , bool SO > // Storage order of the target dense matrix
1112  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1113  smpAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1114  {
1116 
1117  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1118  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1119 
1120  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1121  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1122 
1123  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1124  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1125  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1126  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1127  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1128  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1129 
1130  smpAssign( ~lhs, A * B );
1131  }
1133  //**********************************************************************************************
1134 
1135  //**SMP assignment to sparse matrices***********************************************************
1150  template< typename MT // Type of the target sparse matrix
1151  , bool SO > // Storage order of the target sparse matrix
1152  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1153  smpAssign( SparseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1154  {
1156 
1157  typedef typename SelectType< SO, OppositeType, ResultType >::Type TmpType;
1158 
1165 
1166  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1167  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1168 
1169  const TmpType tmp( rhs );
1170  smpAssign( ~lhs, tmp );
1171  }
1173  //**********************************************************************************************
1174 
1175  //**Restructuring SMP assignment to column-major matrices***************************************
1190  template< typename MT > // Type of the target matrix
1191  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1192  smpAssign( Matrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
1193  {
1195 
1197 
1198  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1199  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1200 
1201  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1202  smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1203  else if( IsSymmetric<MT1>::value )
1204  smpAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1205  else
1206  smpAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1207  }
1209  //**********************************************************************************************
1210 
1211  //**SMP addition assignment to dense matrices***************************************************
1226  template< typename MT // Type of the target dense matrix
1227  , bool SO > // Storage order of the target sparse matrix
1228  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1229  smpAddAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1230  {
1232 
1233  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1234  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1235 
1236  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1237  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1238 
1239  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1240  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1241  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1242  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1243  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1244  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1245 
1246  smpAddAssign( ~lhs, A * B );
1247  }
1249  //**********************************************************************************************
1250 
1251  //**Restructuring SMP addition assignment to column-major matrices******************************
1266  template< typename MT > // Type of the target matrix
1267  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1268  smpAddAssign( Matrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
1269  {
1271 
1273 
1274  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1275  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1276 
1277  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1278  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1279  else if( IsSymmetric<MT1>::value )
1280  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1281  else
1282  smpAddAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1283  }
1285  //**********************************************************************************************
1286 
1287  //**SMP addition assignment to sparse matrices**************************************************
1288  // No special implementation for the SMP addition assignment to sparse matrices.
1289  //**********************************************************************************************
1290 
1291  //**SMP subtraction assignment to dense matrices************************************************
1307  template< typename MT // Type of the target dense matrix
1308  , bool SO > // Storage order of the target sparse matrix
1309  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1310  smpSubAssign( DenseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
1311  {
1313 
1314  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1315  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1316 
1317  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
1318  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1319 
1320  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1321  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1322  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1323  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1324  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1325  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1326 
1327  smpSubAssign( ~lhs, A * B );
1328  }
1330  //**********************************************************************************************
1331 
1332  //**Restructuring SMP subtraction assignment to column-major matrices***************************
1347  template< typename MT > // Type of the target matrix
1348  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1349  smpSubAssign( Matrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
1350  {
1352 
1354 
1355  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1356  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1357 
1358  if( IsSymmetric<MT1>::value && IsSymmetric<MT2>::value )
1359  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1360  else if( IsSymmetric<MT1>::value )
1361  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * rhs.rhs_ );
1362  else
1363  smpSubAssign( ~lhs, rhs.lhs_ * trans( rhs.rhs_ ) );
1364  }
1366  //**********************************************************************************************
1367 
1368  //**SMP subtraction assignment to sparse matrices***********************************************
1369  // No special implementation for the SMP subtraction assignment to sparse matrices.
1370  //**********************************************************************************************
1371 
1372  //**SMP multiplication assignment to dense matrices*********************************************
1373  // No special implementation for the SMP multiplication assignment to dense matrices.
1374  //**********************************************************************************************
1375 
1376  //**SMP multiplication assignment to sparse matrices********************************************
1377  // No special implementation for the SMP multiplication assignment to sparse matrices.
1378  //**********************************************************************************************
1379 
1380  //**Compile time checks*************************************************************************
1388  //**********************************************************************************************
1389 };
1390 //*************************************************************************************************
1391 
1392 
1393 
1394 
1395 //=================================================================================================
1396 //
1397 // GLOBAL BINARY ARITHMETIC OPERATORS
1398 //
1399 //=================================================================================================
1400 
1401 //*************************************************************************************************
1430 template< typename T1 // Type of the left-hand side dense matrix
1431  , typename T2 > // Type of the right-hand side sparse matrix
1432 inline const DMatSMatMultExpr<T1,T2>
1434 {
1436 
1437  if( (~lhs).columns() != (~rhs).rows() )
1438  throw std::invalid_argument( "Matrix sizes do not match" );
1439 
1440  return DMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
1441 }
1442 //*************************************************************************************************
1443 
1444 
1445 
1446 
1447 //=================================================================================================
1448 //
1449 // ROWS SPECIALIZATIONS
1450 //
1451 //=================================================================================================
1452 
1453 //*************************************************************************************************
1455 template< typename MT1, typename MT2 >
1456 struct Rows< DMatSMatMultExpr<MT1,MT2> >
1457  : public Rows<MT1>
1458 {};
1460 //*************************************************************************************************
1461 
1462 
1463 
1464 
1465 //=================================================================================================
1466 //
1467 // COLUMNS SPECIALIZATIONS
1468 //
1469 //=================================================================================================
1470 
1471 //*************************************************************************************************
1473 template< typename MT1, typename MT2 >
1474 struct Columns< DMatSMatMultExpr<MT1,MT2> >
1475  : public Columns<MT2>
1476 {};
1478 //*************************************************************************************************
1479 
1480 
1481 
1482 
1483 //=================================================================================================
1484 //
1485 // ISLOWER SPECIALIZATIONS
1486 //
1487 //=================================================================================================
1488 
1489 //*************************************************************************************************
1491 template< typename MT1, typename MT2 >
1492 struct IsLower< DMatSMatMultExpr<MT1,MT2> >
1493  : public IsTrue< IsLower<MT1>::value && IsLower<MT2>::value >
1494 {};
1496 //*************************************************************************************************
1497 
1498 
1499 
1500 
1501 //=================================================================================================
1502 //
1503 // ISUPPER SPECIALIZATIONS
1504 //
1505 //=================================================================================================
1506 
1507 //*************************************************************************************************
1509 template< typename MT1, typename MT2 >
1510 struct IsUpper< DMatSMatMultExpr<MT1,MT2> >
1511  : public IsTrue< IsUpper<MT1>::value && IsUpper<MT2>::value >
1512 {};
1514 //*************************************************************************************************
1515 
1516 
1517 
1518 
1519 //=================================================================================================
1520 //
1521 // EXPRESSION TRAIT SPECIALIZATIONS
1522 //
1523 //=================================================================================================
1524 
1525 //*************************************************************************************************
1527 template< typename MT1, typename MT2, typename VT >
1528 struct DMatDVecMultExprTrait< DMatSMatMultExpr<MT1,MT2>, VT >
1529 {
1530  public:
1531  //**********************************************************************************************
1532  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1533  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1534  IsDenseVector<VT>::value && IsColumnVector<VT>::value
1535  , typename DMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
1536  , INVALID_TYPE >::Type Type;
1537  //**********************************************************************************************
1538 };
1540 //*************************************************************************************************
1541 
1542 
1543 //*************************************************************************************************
1545 template< typename MT1, typename MT2, typename VT >
1546 struct DMatSVecMultExprTrait< DMatSMatMultExpr<MT1,MT2>, VT >
1547 {
1548  public:
1549  //**********************************************************************************************
1550  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1551  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1552  IsSparseVector<VT>::value && IsColumnVector<VT>::value
1553  , typename DMatSVecMultExprTrait< MT1, typename SMatSVecMultExprTrait<MT2,VT>::Type >::Type
1554  , INVALID_TYPE >::Type Type;
1555  //**********************************************************************************************
1556 };
1558 //*************************************************************************************************
1559 
1560 
1561 //*************************************************************************************************
1563 template< typename VT, typename MT1, typename MT2 >
1564 struct TDVecDMatMultExprTrait< VT, DMatSMatMultExpr<MT1,MT2> >
1565 {
1566  public:
1567  //**********************************************************************************************
1568  typedef typename SelectType< IsDenseVector<VT>::value && IsRowVector<VT>::value &&
1569  IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1570  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1571  , typename TDVecSMatMultExprTrait< typename TDVecDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1572  , INVALID_TYPE >::Type Type;
1573  //**********************************************************************************************
1574 };
1576 //*************************************************************************************************
1577 
1578 
1579 //*************************************************************************************************
1581 template< typename VT, typename MT1, typename MT2 >
1582 struct TSVecDMatMultExprTrait< VT, DMatSMatMultExpr<MT1,MT2> >
1583 {
1584  public:
1585  //**********************************************************************************************
1586  typedef typename SelectType< IsSparseVector<VT>::value && IsRowVector<VT>::value &&
1587  IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1588  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1589  , typename TDVecSMatMultExprTrait< typename TDVecDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1590  , INVALID_TYPE >::Type Type;
1591  //**********************************************************************************************
1592 };
1594 //*************************************************************************************************
1595 
1596 
1597 //*************************************************************************************************
1599 template< typename MT1, typename MT2, bool AF >
1600 struct SubmatrixExprTrait< DMatSMatMultExpr<MT1,MT2>, AF >
1601 {
1602  public:
1603  //**********************************************************************************************
1604  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT1,AF>::Type
1605  , typename SubmatrixExprTrait<const MT2,AF>::Type >::Type Type;
1606  //**********************************************************************************************
1607 };
1609 //*************************************************************************************************
1610 
1611 
1612 //*************************************************************************************************
1614 template< typename MT1, typename MT2 >
1615 struct RowExprTrait< DMatSMatMultExpr<MT1,MT2> >
1616 {
1617  public:
1618  //**********************************************************************************************
1619  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
1620  //**********************************************************************************************
1621 };
1623 //*************************************************************************************************
1624 
1625 
1626 //*************************************************************************************************
1628 template< typename MT1, typename MT2 >
1629 struct ColumnExprTrait< DMatSMatMultExpr<MT1,MT2> >
1630 {
1631  public:
1632  //**********************************************************************************************
1633  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
1634  //**********************************************************************************************
1635 };
1637 //*************************************************************************************************
1638 
1639 } // namespace blaze
1640 
1641 #endif
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: DMatSMatMultExpr.h:195
Compile time check whether the given type is a computational expression template.This type trait clas...
Definition: IsComputation.h:89
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: DMatSMatMultExpr.h:350
Header file for the SMatDVecMultExprTrait class template.
Header file for the Rows type trait.
const DMatDMatMultExpr< T1, T2 > operator*(const DenseMatrix< T1, false > &lhs, const DenseMatrix< T2, false > &rhs)
Multiplication operator for the multiplication of two row-major dense matrices ( ).
Definition: DMatDMatMultExpr.h:4838
const ResultType CompositeType
Data type for composite expression templates.
Definition: DMatSMatMultExpr.h:198
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: DMatSMatMultExpr.h:243
const ElementType ReturnType
Return type for expression template evaluations.
Definition: DMatSMatMultExpr.h:197
BLAZE_ALWAYS_INLINE MT::Iterator end(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator just past the last element of row/column i.
Definition: Matrix.h:258
SelectType< evaluateRight, const RT2, CT2 >::Type RT
Type for the assignment of the right-hand side sparse matrix operand.
Definition: DMatSMatMultExpr.h:210
Header file for the IsSparseMatrix type trait.
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:205
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional matrix type...
Definition: DenseMatrix.h:79
Header file for the ColumnExprTrait class template.
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2478
Header file for the IsRowVector type trait.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:257
size_t columns() const
Returns the current number of columns of the matrix.
Definition: DMatSMatMultExpr.h:278
bool isAligned() const
Returns whether the operands of the expression are properly aligned in memory.
Definition: DMatSMatMultExpr.h:332
MT2::ResultType RT2
Result type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:119
Header file for the TDVecSMatMultExprTrait class template.
MultTrait< RT1, RT2 >::Type ResultType
Result type for expression template evaluations.
Definition: DMatSMatMultExpr.h:193
const DMatSerialExpr< MT, SO > serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:695
Header file for the Computation base class.
Header file for the MatMatMultExpr base class.
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.
Constraint on the data type.
Header file for the MultExprTrait class template.
Compile time check to query the requirement to evaluate an expression.Via this type trait it is possi...
Definition: RequiresEvaluation.h:90
SelectType< IsExpression< MT2 >::value, const MT2, const MT2 & >::Type RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:204
LeftOperand lhs_
Left-hand side dense matrix of the multiplication expression.
Definition: DMatSMatMultExpr.h:349
size_t rows() const
Returns the current number of rows of the matrix.
Definition: DMatSMatMultExpr.h:268
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.
MT1::ResultType RT1
Result type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:118
Header file for the IsSymmetric type trait.
#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a column-major dense or sparse matri...
Definition: StorageOrder.h:161
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2482
LeftOperand leftOperand() const
Returns the left-hand side dense matrix operand.
Definition: DMatSMatMultExpr.h:288
Header file for the DenseMatrix base class.
BLAZE_ALWAYS_INLINE void assign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the assignment of a matrix to a matrix.
Definition: Matrix.h:635
Header file for the Columns type trait.
ResultType::OppositeType OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: DMatSMatMultExpr.h:194
Header file for the DMatDVecMultExprTrait class template.
Header file for the IsLower type trait.
RT2::ElementType ET2
Element type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:121
Header file for the SMatSVecMultExprTrait class template.
#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
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: DMatSMatMultExpr.h:342
Constraints on the storage order of matrix types.
SelectType< evaluateLeft, const RT1, CT1 >::Type LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: DMatSMatMultExpr.h:207
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:2476
Header file for the SelectType class template.
Header file for the RowExprTrait class template.
Header file for all forward declarations for expression class templates.
Header file for the IsDenseMatrix type trait.
Header file for the EnableIf class template.
Header file for the serial shim.
#define BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR(T1, T2)
Constraint on the data type.In case the given data types T1 and T2 do not form a valid matrix/matrix ...
Definition: MatMatMultExpr.h:165
ResultType::ElementType ElementType
Resulting element type.
Definition: DMatSMatMultExpr.h:196
MT1::CompositeType CT1
Composite type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:122
RT1::ElementType ET1
Element type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:120
Base class for all matrix/matrix multiplication expression templates.The MatMatMultExpr class serves ...
Definition: MatMatMultExpr.h:65
EnableIf< IsDenseMatrix< MT1 > >::Type smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:160
Header file for the IsSparseVector type trait.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a symmetric matrix type, a compilation error is created.
Definition: Symmetric.h:116
Header file for the SubmatrixExprTrait class template.
#define BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a row-major dense or sparse matrix t...
Definition: StorageOrder.h:81
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: DMatSMatMultExpr.h:310
Header file for run time assertion macros.
EnableIf< IsDenseMatrix< MT1 > >::Type smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:98
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: DMatSMatMultExpr.h:322
Utility type for generic codes.
Base template for the MultTrait class.
Definition: MultTrait.h:142
Expression object for dense matrix-sparse matrix multiplications.The DMatSMatMultExpr class represent...
Definition: DMatSMatMultExpr.h:112
BLAZE_ALWAYS_INLINE void addAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the addition assignment of a matrix to a matrix.
Definition: Matrix.h:742
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.
Header file for the isDefault shim.
BLAZE_ALWAYS_INLINE bool isDefault(const NonNumericProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: NonNumericProxy.h:874
Constraint on the data type.
BLAZE_ALWAYS_INLINE void reset(const NonNumericProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: NonNumericProxy.h:833
#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
MT2::CompositeType CT2
Composite type of the right-hand side sparse matrix expression.
Definition: DMatSMatMultExpr.h:123
Header file for the IsDenseVector type trait.
SelectType< IsExpression< MT1 >::value, const MT1, const MT1 & >::Type LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: DMatSMatMultExpr.h:201
Header file for the IsRowMajorMatrix type trait.
const DMatTransExpr< MT,!SO > trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:932
Header file for the IsComputation type trait class.
const size_t SMP_DMATSMATMULT_THRESHOLD
SMP row-major dense matrix/row-major sparse matrix multiplication threshold.This threshold specifies ...
Definition: Thresholds.h:926
Base class for all compute expression templates.The Computation class serves as a tag for all computa...
Definition: Computation.h:59
Header file for the TDVecDMatMultExprTrait class template.
EnableIf< IsDenseMatrix< MT1 > >::Type smpAddAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:129
#define BLAZE_FUNCTION_TRACE
Function trace macro.This macro can be used to reliably trace function calls. In case function tracin...
Definition: FunctionTrace.h:157
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:2473
Header file for the IsTrue value trait.
DMatSMatMultExpr(const MT1 &lhs, const MT2 &rhs)
Constructor for the DMatSMatMultExpr class.
Definition: DMatSMatMultExpr.h:228
Header file for basic type definitions.
Header file for the TSVecDMatMultExprTrait class template.
DMatSMatMultExpr< MT1, MT2 > This
Type of this DMatSMatMultExpr instance.
Definition: DMatSMatMultExpr.h:192
Header file for the IsUpper type trait.
Header file for the DMatSVecMultExprTrait class template.
Header file for the IsColumnVector type trait.
Constraint on the data type.
Header file for the IsResizable type trait.
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
#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.
BLAZE_ALWAYS_INLINE void subAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the subtraction assignment of a matrix to matrix.
Definition: Matrix.h:849
RightOperand rightOperand() const
Returns the right-hand side sparse matrix operand.
Definition: DMatSMatMultExpr.h:298