All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DMatSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_DMATSMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_DMATSMATMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
31 #include <boost/type_traits/remove_reference.hpp>
40 #include <blaze/math/shims/Reset.h>
58 #include <blaze/util/Assert.h>
60 #include <blaze/util/DisableIf.h>
61 #include <blaze/util/EnableIf.h>
62 #include <blaze/util/InvalidType.h>
63 #include <blaze/util/SelectType.h>
64 #include <blaze/util/Types.h>
65 
66 
67 namespace blaze {
68 
69 //=================================================================================================
70 //
71 // CLASS DMATSMATMULTEXPR
72 //
73 //=================================================================================================
74 
75 //*************************************************************************************************
82 template< typename MT1 // Type of the left-hand side dense matrix
83  , typename MT2 > // Type of the right-hand side sparse matrix
84 class DMatSMatMultExpr : public DenseMatrix< DMatSMatMultExpr<MT1,MT2>, false >
85  , private Expression
86  , private Computation
87 {
88  private:
89  //**Type definitions****************************************************************************
90  typedef typename MT1::ResultType RT1;
91  typedef typename MT2::ResultType RT2;
92  typedef typename MT1::CompositeType CT1;
93  typedef typename MT2::CompositeType CT2;
94  //**********************************************************************************************
95 
96  public:
97  //**Type definitions****************************************************************************
100  typedef typename ResultType::OppositeType OppositeType;
101  typedef typename ResultType::TransposeType TransposeType;
102  typedef typename ResultType::ElementType ElementType;
103  typedef const ElementType ReturnType;
104  typedef const ResultType CompositeType;
105 
107  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
108 
110  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
111 
113  typedef typename SelectType< IsComputation<MT1>::value, const RT1, CT1 >::Type LT;
114 
116  typedef typename SelectType< IsComputation<MT2>::value, const RT2, CT2 >::Type RT;
117  //**********************************************************************************************
118 
119  //**Compilation flags***************************************************************************
121  enum { vectorizable = 0 };
122 
124  enum { canAlias = !IsComputation<MT1>::value };
125  //**********************************************************************************************
126 
127  //**Constructor*********************************************************************************
133  explicit inline DMatSMatMultExpr( const MT1& lhs, const MT2& rhs )
134  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
135  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
136  {
137  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
138  }
139  //**********************************************************************************************
140 
141  //**Access operator*****************************************************************************
148  inline ReturnType operator()( size_t i, size_t j ) const {
149  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
150  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
151 
152  ElementType tmp;
153 
154  if( lhs_.columns() != 0UL ) {
155  tmp = lhs_(i,0UL) * rhs_(0UL,j);
156  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
157  tmp += lhs_(i,k) * rhs_(k,j);
158  }
159  }
160  else {
161  reset( tmp );
162  }
163 
164  return tmp;
165  }
166  //**********************************************************************************************
167 
168  //**Rows function*******************************************************************************
173  inline size_t rows() const {
174  return lhs_.rows();
175  }
176  //**********************************************************************************************
177 
178  //**Columns function****************************************************************************
183  inline size_t columns() const {
184  return rhs_.columns();
185  }
186  //**********************************************************************************************
187 
188  //**Left operand access*************************************************************************
193  inline LeftOperand leftOperand() const {
194  return lhs_;
195  }
196  //**********************************************************************************************
197 
198  //**Right operand access************************************************************************
203  inline RightOperand rightOperand() const {
204  return rhs_;
205  }
206  //**********************************************************************************************
207 
208  //**********************************************************************************************
214  template< typename T >
215  inline bool isAliased( const T* alias ) const {
216  return ( !IsComputation<MT1>::value && lhs_.isAliased( alias ) );
217  }
218  //**********************************************************************************************
219 
220  private:
221  //**Member variables****************************************************************************
224  //**********************************************************************************************
225 
226  //**Default assignment to row-major dense matrices**********************************************
240  template< typename MT > // Type of the target dense matrix
241  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
242  assign( DenseMatrix<MT,false>& lhs, const DMatSMatMultExpr& rhs )
243  {
244  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
245  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
246 
247  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
248 
249  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
250  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
251 
252  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
253  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
254  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
255  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
256  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
257  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
258 
259  for( size_t i=0UL; i<A.rows(); ++i ) {
260  for( size_t j=0UL; j<(~lhs).columns(); ++j ) {
261  reset( (~lhs)(i,j) );
262  }
263  for( size_t j=0UL; j<B.rows(); ++j ) {
264  ConstIterator element( B.begin(j) );
265  const ConstIterator end( B.end(j) );
266  for( ; element!=end; ++element ) {
267  if( isDefault( (~lhs)(i,element->index()) ) )
268  (~lhs)(i,element->index()) = A(i,j) * element->value();
269  else
270  (~lhs)(i,element->index()) += A(i,j) * element->value();
271  }
272  }
273  }
274  }
276  //**********************************************************************************************
277 
278  //**Default assignment to column-major dense matrices*******************************************
292  template< typename MT > // Type of the target dense matrix
293  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
294  assign( DenseMatrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
295  {
296  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
297  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
298 
299  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
300 
301  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
302  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
303 
304  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
305  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
306  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
307  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
308  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
309  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
310 
311  reset( ~lhs );
312 
313  for( size_t i=0UL; i<B.rows(); ++i ) {
314  for( size_t jj=0UL; jj<A.rows(); jj+=8UL ) {
315  const size_t jend( ( jj+8UL > A.rows() )?( A.rows() ):( jj+8UL ) );
316  ConstIterator element( B.begin(i) );
317  const ConstIterator end( B.end(i) );
318  for( ; element!=end; ++element ) {
319  for( size_t j=jj; j<jend; ++j ) {
320  if( isDefault( (~lhs)(j,element->index()) ) )
321  (~lhs)(j,element->index()) = A(j,i) * element->value();
322  else
323  (~lhs)(j,element->index()) += A(j,i) * element->value();
324  }
325  }
326  }
327  }
328  }
330  //**********************************************************************************************
331 
332  //**Optimized assignment to row-major dense matrices********************************************
346  template< typename MT > // Type of the target dense matrix
347  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
348  assign( DenseMatrix<MT,false>& lhs, const DMatSMatMultExpr& rhs )
349  {
350  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
351  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
352 
353  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
354 
355  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
356  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
357 
358  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
359  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
360  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
361  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
362  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
363  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
364 
365  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
366  const size_t last( A.rows() & size_t(-4) );
367 
368  for( size_t i=0UL; i<last; i+=4UL ) {
369  for( size_t j=0UL; j<(~lhs).columns(); ++j ) {
370  reset( (~lhs)(i ,j) );
371  reset( (~lhs)(i+1UL,j) );
372  reset( (~lhs)(i+2UL,j) );
373  reset( (~lhs)(i+3UL,j) );
374  }
375  for( size_t j=0UL; j<B.rows(); ++j ) {
376  ConstIterator element( B.begin(j) );
377  const ConstIterator end( B.end(j) );
378  for( ; element!=end; ++element ) {
379  (~lhs)(i ,element->index()) += A(i ,j) * element->value();
380  (~lhs)(i+1UL,element->index()) += A(i+1UL,j) * element->value();
381  (~lhs)(i+2UL,element->index()) += A(i+2UL,j) * element->value();
382  (~lhs)(i+3UL,element->index()) += A(i+3UL,j) * element->value();
383  }
384  }
385  }
386 
387  for( size_t i=last; i<A.rows(); ++i ) {
388  for( size_t j=0UL; j<(~lhs).columns(); ++j ) {
389  reset( (~lhs)(i,j) );
390  }
391  for( size_t j=0UL; j<B.rows(); ++j ) {
392  ConstIterator element( B.begin(j) );
393  const ConstIterator end( B.end(j) );
394  for( ; element!=end; ++element ) {
395  (~lhs)(i,element->index()) += A(i,j) * element->value();
396  }
397  }
398  }
399  }
401  //**********************************************************************************************
402 
403  //**Optimized assignment to column-major dense matrices*****************************************
417  template< typename MT > // Type of the target dense matrix
418  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
419  assign( DenseMatrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
420  {
421  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
422  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
423 
424  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
425 
426  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
427  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
428 
429  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
430  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
431  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
432  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
433  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
434  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
435 
436  reset( ~lhs );
437 
438  for( size_t i=0UL; i<B.rows(); ++i ) {
439  for( size_t jj=0UL; jj<A.rows(); jj+=8UL ) {
440  const size_t jend( ( jj+8UL > A.rows() )?( A.rows() ):( jj+8UL ) );
441  ConstIterator element( B.begin(i) );
442  const ConstIterator end( B.end(i) );
443  for( ; element!=end; ++element ) {
444  for( size_t j=jj; j<jend; ++j ) {
445  (~lhs)(j,element->index()) += A(j,i) * element->value();
446  }
447  }
448  }
449  }
450  }
452  //**********************************************************************************************
453 
454  //**Assignment to sparse matrices***************************************************************
466  template< typename MT // Type of the target sparse matrix
467  , bool SO > // Storage order of the target sparse matrix
468  friend inline void assign( SparseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
469  {
470  typedef typename SelectType< SO, OppositeType, ResultType >::Type TmpType;
471 
477  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename TmpType::CompositeType );
478 
479  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
480  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
481 
482  const TmpType tmp( rhs );
483  assign( ~lhs, tmp );
484  }
486  //**********************************************************************************************
487 
488  //**Addition assignment to row-major dense matrices*********************************************
501  template< typename MT > // Type of the target dense matrix
502  friend inline void addAssign( DenseMatrix<MT,false>& lhs, const DMatSMatMultExpr& rhs )
503  {
504  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
505  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
506 
507  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
508 
509  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
510  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
511 
512  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
513  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
514  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
515  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
516  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
517  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
518 
519  const size_t last( A.rows() & size_t(-4) );
520 
521  for( size_t i=0UL; i<last; i+=4UL ) {
522  for( size_t j=0UL; j<B.rows(); ++j ) {
523  ConstIterator element( B.begin(j) );
524  const ConstIterator end( B.end(j) );
525  for( ; element!=end; ++element ) {
526  (~lhs)(i ,element->index()) += A(i ,j) * element->value();
527  (~lhs)(i+1UL,element->index()) += A(i+1UL,j) * element->value();
528  (~lhs)(i+2UL,element->index()) += A(i+2UL,j) * element->value();
529  (~lhs)(i+3UL,element->index()) += A(i+3UL,j) * element->value();
530  }
531  }
532  }
533 
534  for( size_t i=last; i<A.rows(); ++i ) {
535  for( size_t j=0UL; j<B.rows(); ++j ) {
536  ConstIterator element( B.begin(j) );
537  const ConstIterator end( B.end(j) );
538  for( ; element!=end; ++element ) {
539  (~lhs)(i,element->index()) += A(i,j) * element->value();
540  }
541  }
542  }
543  }
545  //**********************************************************************************************
546 
547  //**Addition assignment to column-major dense matrices******************************************
560  template< typename MT > // Type of the target dense matrix
561  friend inline void addAssign( DenseMatrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
562  {
563  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
564  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
565 
566  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
567 
568  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
569  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
570 
571  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
572  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
573  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
574  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
575  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
576  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
577 
578  for( size_t i=0UL; i<B.rows(); ++i ) {
579  for( size_t jj=0UL; jj<A.rows(); jj+=8UL ) {
580  const size_t jend( ( jj+8UL > A.rows() )?( A.rows() ):( jj+8UL ) );
581  ConstIterator element( B.begin(i) );
582  const ConstIterator end( B.end(i) );
583  for( ; element!=end; ++element ) {
584  for( size_t j=jj; j<jend; ++j ) {
585  (~lhs)(j,element->index()) += A(j,i) * element->value();
586  }
587  }
588  }
589  }
590  }
592  //**********************************************************************************************
593 
594  //**Addition assignment to sparse matrices******************************************************
595  // No special implementation for the addition assignment to sparse matrices.
596  //**********************************************************************************************
597 
598  //**Subtraction assignment to row-major dense matrices******************************************
611  template< typename MT > // Type of the target dense matrix
612  friend inline void subAssign( DenseMatrix<MT,false>& lhs, const DMatSMatMultExpr& rhs )
613  {
614  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
615  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
616 
617  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
618 
619  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
620  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
621 
622  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
623  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
624  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
625  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
626  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
627  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
628 
629  const size_t last( A.rows() & size_t(-4) );
630 
631  for( size_t i=0UL; i<last; i+=4UL ) {
632  for( size_t j=0UL; j<B.rows(); ++j ) {
633  ConstIterator element( B.begin(j) );
634  const ConstIterator end( B.end(j) );
635  for( ; element!=end; ++element ) {
636  (~lhs)(i ,element->index()) -= A(i ,j) * element->value();
637  (~lhs)(i+1UL,element->index()) -= A(i+1UL,j) * element->value();
638  (~lhs)(i+2UL,element->index()) -= A(i+2UL,j) * element->value();
639  (~lhs)(i+3UL,element->index()) -= A(i+3UL,j) * element->value();
640  }
641  }
642  }
643 
644  for( size_t i=last; i<A.rows(); ++i ) {
645  for( size_t j=0UL; j<B.rows(); ++j ) {
646  ConstIterator element( B.begin(j) );
647  const ConstIterator end( B.end(j) );
648  for( ; element!=end; ++element ) {
649  (~lhs)(i,element->index()) -= A(i,j) * element->value();
650  }
651  }
652  }
653  }
655  //**********************************************************************************************
656 
657  //**Subtraction assignment to column-major dense matrices***************************************
670  template< typename MT > // Type of the target dense matrix
671  friend inline void subAssign( DenseMatrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
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  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
677 
678  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
679  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
680 
681  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
682  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
683  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
684  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
685  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
686  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
687 
688  for( size_t i=0UL; i<B.rows(); ++i ) {
689  for( size_t jj=0UL; jj<A.rows(); jj+=8UL ) {
690  const size_t jend( ( jj+8UL > A.rows() )?( A.rows() ):( jj+8UL ) );
691  ConstIterator element( B.begin(i) );
692  const ConstIterator end( B.end(i) );
693  for( ; element!=end; ++element ) {
694  for( size_t j=jj; j<jend; ++j ) {
695  (~lhs)(j,element->index()) -= A(j,i) * element->value();
696  }
697  }
698  }
699  }
700  }
702  //**********************************************************************************************
703 
704  //**Subtraction assignment to sparse matrices***************************************************
705  // No special implementation for the subtraction assignment to sparse matrices.
706  //**********************************************************************************************
707 
708  //**Multiplication assignment to dense matrices*************************************************
709  // No special implementation for the multiplication assignment to dense matrices.
710  //**********************************************************************************************
711 
712  //**Multiplication assignment to sparse matrices************************************************
713  // No special implementation for the multiplication assignment to sparse matrices.
714  //**********************************************************************************************
715 
716  //**Compile time checks*************************************************************************
723  //**********************************************************************************************
724 };
725 //*************************************************************************************************
726 
727 
728 
729 
730 //=================================================================================================
731 //
732 // GLOBAL BINARY ARITHMETIC OPERATORS
733 //
734 //=================================================================================================
735 
736 //*************************************************************************************************
765 template< typename T1 // Type of the left-hand side dense matrix
766  , typename T2 > // Type of the right-hand side sparse matrix
767 inline const DMatSMatMultExpr<T1,T2>
769 {
770  if( (~lhs).columns() != (~rhs).rows() )
771  throw std::invalid_argument( "Matrix sizes do not match" );
772 
773  return DMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
774 }
775 //*************************************************************************************************
776 
777 
778 
779 
780 //=================================================================================================
781 //
782 // EXPRESSION TRAIT SPECIALIZATIONS
783 //
784 //=================================================================================================
785 
786 //*************************************************************************************************
788 template< typename MT1, typename MT2, typename VT >
789 struct DMatDVecMultExprTrait< DMatSMatMultExpr<MT1,MT2>, VT >
790 {
791  public:
792  //**********************************************************************************************
793  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
794  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
795  IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
796  , typename DMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
797  , INVALID_TYPE >::Type Type;
798  //**********************************************************************************************
799 };
801 //*************************************************************************************************
802 
803 
804 //*************************************************************************************************
806 template< typename MT1, typename MT2, typename VT >
807 struct DMatSVecMultExprTrait< DMatSMatMultExpr<MT1,MT2>, VT >
808 {
809  public:
810  //**********************************************************************************************
811  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
812  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
813  IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
814  , typename DMatSVecMultExprTrait< MT1, typename SMatSVecMultExprTrait<MT2,VT>::Type >::Type
815  , INVALID_TYPE >::Type Type;
816  //**********************************************************************************************
817 };
819 //*************************************************************************************************
820 
821 
822 //*************************************************************************************************
824 template< typename VT, typename MT1, typename MT2 >
825 struct TDVecDMatMultExprTrait< VT, DMatSMatMultExpr<MT1,MT2> >
826 {
827  public:
828  //**********************************************************************************************
829  typedef typename SelectType< IsDenseVector<VT>::value && IsTransposeVector<VT>::value &&
830  IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
831  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
832  , typename TDVecSMatMultExprTrait< typename TDVecDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
833  , INVALID_TYPE >::Type Type;
834  //**********************************************************************************************
835 };
837 //*************************************************************************************************
838 
839 
840 //*************************************************************************************************
842 template< typename VT, typename MT1, typename MT2 >
843 struct TSVecDMatMultExprTrait< VT, DMatSMatMultExpr<MT1,MT2> >
844 {
845  public:
846  //**********************************************************************************************
847  typedef typename SelectType< IsSparseVector<VT>::value && IsTransposeVector<VT>::value &&
848  IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
849  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
850  , typename TDVecSMatMultExprTrait< typename TDVecDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
851  , INVALID_TYPE >::Type Type;
852  //**********************************************************************************************
853 };
855 //*************************************************************************************************
856 
857 } // namespace blaze
858 
859 #endif