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>
61 #include <blaze/util/Assert.h>
63 #include <blaze/util/DisableIf.h>
64 #include <blaze/util/EnableIf.h>
65 #include <blaze/util/InvalidType.h>
67 #include <blaze/util/SelectType.h>
68 #include <blaze/util/Types.h>
69 
70 
71 namespace blaze {
72 
73 //=================================================================================================
74 //
75 // CLASS DMATSMATMULTEXPR
76 //
77 //=================================================================================================
78 
79 //*************************************************************************************************
86 template< typename MT1 // Type of the left-hand side dense matrix
87  , typename MT2 > // Type of the right-hand side sparse matrix
88 class DMatSMatMultExpr : public DenseMatrix< DMatSMatMultExpr<MT1,MT2>, false >
89  , private Expression
90  , private Computation
91 {
92  private:
93  //**Type definitions****************************************************************************
94  typedef typename MT1::ResultType RT1;
95  typedef typename MT2::ResultType RT2;
96  typedef typename MT1::CompositeType CT1;
97  typedef typename MT2::CompositeType CT2;
98  //**********************************************************************************************
99 
100  public:
101  //**Type definitions****************************************************************************
104  typedef typename ResultType::OppositeType OppositeType;
105  typedef typename ResultType::TransposeType TransposeType;
106  typedef typename ResultType::ElementType ElementType;
107  typedef const ElementType ReturnType;
108  typedef const ResultType CompositeType;
109 
111  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
112 
114  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
115 
117  typedef typename SelectType< IsComputation<MT1>::value, const RT1, CT1 >::Type LT;
118 
120  typedef typename SelectType< IsComputation<MT2>::value, const RT2, CT2 >::Type RT;
121  //**********************************************************************************************
122 
123  //**Compilation flags***************************************************************************
125  enum { vectorizable = 0 };
126  //**********************************************************************************************
127 
128  //**Constructor*********************************************************************************
134  explicit inline DMatSMatMultExpr( const MT1& lhs, const MT2& rhs )
135  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
136  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
137  {
138  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
139  }
140  //**********************************************************************************************
141 
142  //**Access operator*****************************************************************************
149  inline ReturnType operator()( size_t i, size_t j ) const {
150  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
151  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
152 
153  ElementType tmp;
154 
155  if( lhs_.columns() != 0UL ) {
156  tmp = lhs_(i,0UL) * rhs_(0UL,j);
157  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
158  tmp += lhs_(i,k) * rhs_(k,j);
159  }
160  }
161  else {
162  reset( tmp );
163  }
164 
165  return tmp;
166  }
167  //**********************************************************************************************
168 
169  //**Rows function*******************************************************************************
174  inline size_t rows() const {
175  return lhs_.rows();
176  }
177  //**********************************************************************************************
178 
179  //**Columns function****************************************************************************
184  inline size_t columns() const {
185  return rhs_.columns();
186  }
187  //**********************************************************************************************
188 
189  //**Left operand access*************************************************************************
194  inline LeftOperand leftOperand() const {
195  return lhs_;
196  }
197  //**********************************************************************************************
198 
199  //**Right operand access************************************************************************
204  inline RightOperand rightOperand() const {
205  return rhs_;
206  }
207  //**********************************************************************************************
208 
209  //**********************************************************************************************
215  template< typename T >
216  inline bool canAlias( const T* alias ) const {
217  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
218  }
219  //**********************************************************************************************
220 
221  //**********************************************************************************************
227  template< typename T >
228  inline bool isAliased( const T* alias ) const {
229  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
230  }
231  //**********************************************************************************************
232 
233  private:
234  //**Member variables****************************************************************************
237  //**********************************************************************************************
238 
239  //**Default assignment to row-major dense matrices**********************************************
253  template< typename MT > // Type of the target dense matrix
254  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
255  assign( DenseMatrix<MT,false>& lhs, const DMatSMatMultExpr& rhs )
256  {
258 
259  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
260  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
261 
262  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
263 
264  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
265  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
266 
267  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
268  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
269  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
270  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
271  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
272  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
273 
274  for( size_t i=0UL; i<A.rows(); ++i ) {
275  for( size_t j=0UL; j<(~lhs).columns(); ++j ) {
276  reset( (~lhs)(i,j) );
277  }
278  for( size_t j=0UL; j<B.rows(); ++j ) {
279  ConstIterator element( B.begin(j) );
280  const ConstIterator end( B.end(j) );
281  for( ; element!=end; ++element ) {
282  if( isDefault( (~lhs)(i,element->index()) ) )
283  (~lhs)(i,element->index()) = A(i,j) * element->value();
284  else
285  (~lhs)(i,element->index()) += A(i,j) * element->value();
286  }
287  }
288  }
289  }
291  //**********************************************************************************************
292 
293  //**Default assignment to column-major dense matrices*******************************************
307  template< typename MT > // Type of the target dense matrix
308  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
309  assign( DenseMatrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
310  {
312 
313  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
314  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
315 
316  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
317 
318  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
319  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
320 
321  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
322  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
323  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
324  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
325  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
326  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
327 
328  reset( ~lhs );
329 
330  for( size_t i=0UL; i<B.rows(); ++i ) {
331  for( size_t jj=0UL; jj<A.rows(); jj+=8UL ) {
332  const size_t jend( ( jj+8UL > A.rows() )?( A.rows() ):( jj+8UL ) );
333  ConstIterator element( B.begin(i) );
334  const ConstIterator end( B.end(i) );
335  for( ; element!=end; ++element ) {
336  for( size_t j=jj; j<jend; ++j ) {
337  if( isDefault( (~lhs)(j,element->index()) ) )
338  (~lhs)(j,element->index()) = A(j,i) * element->value();
339  else
340  (~lhs)(j,element->index()) += A(j,i) * element->value();
341  }
342  }
343  }
344  }
345  }
347  //**********************************************************************************************
348 
349  //**Optimized assignment to row-major dense matrices********************************************
363  template< typename MT > // Type of the target dense matrix
364  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
365  assign( DenseMatrix<MT,false>& lhs, const DMatSMatMultExpr& rhs )
366  {
368 
369  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
370  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
371 
372  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
373 
374  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
375  RT B( 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  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
385  const size_t last( A.rows() & size_t(-4) );
386 
387  for( size_t i=0UL; i<last; i+=4UL ) {
388  for( size_t j=0UL; j<(~lhs).columns(); ++j ) {
389  reset( (~lhs)(i ,j) );
390  reset( (~lhs)(i+1UL,j) );
391  reset( (~lhs)(i+2UL,j) );
392  reset( (~lhs)(i+3UL,j) );
393  }
394  for( size_t j=0UL; j<B.rows(); ++j ) {
395  ConstIterator element( B.begin(j) );
396  const ConstIterator end( B.end(j) );
397  for( ; element!=end; ++element ) {
398  (~lhs)(i ,element->index()) += A(i ,j) * element->value();
399  (~lhs)(i+1UL,element->index()) += A(i+1UL,j) * element->value();
400  (~lhs)(i+2UL,element->index()) += A(i+2UL,j) * element->value();
401  (~lhs)(i+3UL,element->index()) += A(i+3UL,j) * element->value();
402  }
403  }
404  }
405 
406  for( size_t i=last; i<A.rows(); ++i ) {
407  for( size_t j=0UL; j<(~lhs).columns(); ++j ) {
408  reset( (~lhs)(i,j) );
409  }
410  for( size_t j=0UL; j<B.rows(); ++j ) {
411  ConstIterator element( B.begin(j) );
412  const ConstIterator end( B.end(j) );
413  for( ; element!=end; ++element ) {
414  (~lhs)(i,element->index()) += A(i,j) * element->value();
415  }
416  }
417  }
418  }
420  //**********************************************************************************************
421 
422  //**Optimized assignment to column-major dense matrices*****************************************
436  template< typename MT > // Type of the target dense matrix
437  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
438  assign( DenseMatrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
439  {
441 
442  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
443  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
444 
445  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
446 
447  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
448  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
449 
450  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
451  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
452  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
453  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
454  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
455  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
456 
457  reset( ~lhs );
458 
459  for( size_t i=0UL; i<B.rows(); ++i ) {
460  for( size_t jj=0UL; jj<A.rows(); jj+=8UL ) {
461  const size_t jend( ( jj+8UL > A.rows() )?( A.rows() ):( jj+8UL ) );
462  ConstIterator element( B.begin(i) );
463  const ConstIterator end( B.end(i) );
464  for( ; element!=end; ++element ) {
465  for( size_t j=jj; j<jend; ++j ) {
466  (~lhs)(j,element->index()) += A(j,i) * element->value();
467  }
468  }
469  }
470  }
471  }
473  //**********************************************************************************************
474 
475  //**Assignment to sparse matrices***************************************************************
487  template< typename MT // Type of the target sparse matrix
488  , bool SO > // Storage order of the target sparse matrix
489  friend inline void assign( SparseMatrix<MT,SO>& lhs, const DMatSMatMultExpr& rhs )
490  {
492 
493  typedef typename SelectType< SO, OppositeType, ResultType >::Type TmpType;
494 
500  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename TmpType::CompositeType );
501 
502  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
503  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
504 
505  const TmpType tmp( rhs );
506  assign( ~lhs, tmp );
507  }
509  //**********************************************************************************************
510 
511  //**Addition assignment to row-major dense matrices*********************************************
524  template< typename MT > // Type of the target dense matrix
525  friend inline void addAssign( DenseMatrix<MT,false>& lhs, const DMatSMatMultExpr& rhs )
526  {
528 
529  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
530  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
531 
532  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
533 
534  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
535  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
536 
537  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
538  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
539  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
540  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
541  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
542  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
543 
544  const size_t last( A.rows() & size_t(-4) );
545 
546  for( size_t i=0UL; i<last; i+=4UL ) {
547  for( size_t j=0UL; j<B.rows(); ++j ) {
548  ConstIterator element( B.begin(j) );
549  const ConstIterator end( B.end(j) );
550  for( ; element!=end; ++element ) {
551  (~lhs)(i ,element->index()) += A(i ,j) * element->value();
552  (~lhs)(i+1UL,element->index()) += A(i+1UL,j) * element->value();
553  (~lhs)(i+2UL,element->index()) += A(i+2UL,j) * element->value();
554  (~lhs)(i+3UL,element->index()) += A(i+3UL,j) * element->value();
555  }
556  }
557  }
558 
559  for( size_t i=last; i<A.rows(); ++i ) {
560  for( size_t j=0UL; j<B.rows(); ++j ) {
561  ConstIterator element( B.begin(j) );
562  const ConstIterator end( B.end(j) );
563  for( ; element!=end; ++element ) {
564  (~lhs)(i,element->index()) += A(i,j) * element->value();
565  }
566  }
567  }
568  }
570  //**********************************************************************************************
571 
572  //**Addition assignment to column-major dense matrices******************************************
585  template< typename MT > // Type of the target dense matrix
586  friend inline void addAssign( DenseMatrix<MT,true>& lhs, const DMatSMatMultExpr& rhs )
587  {
589 
590  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
591  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
592 
593  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
594 
595  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
596  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
597 
598  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
599  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
600  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
601  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
602  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
603  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
604 
605  for( size_t i=0UL; i<B.rows(); ++i ) {
606  for( size_t jj=0UL; jj<A.rows(); jj+=8UL ) {
607  const size_t jend( ( jj+8UL > A.rows() )?( A.rows() ):( jj+8UL ) );
608  ConstIterator element( B.begin(i) );
609  const ConstIterator end( B.end(i) );
610  for( ; element!=end; ++element ) {
611  for( size_t j=jj; j<jend; ++j ) {
612  (~lhs)(j,element->index()) += A(j,i) * element->value();
613  }
614  }
615  }
616  }
617  }
619  //**********************************************************************************************
620 
621  //**Addition assignment to sparse matrices******************************************************
622  // No special implementation for the addition assignment to sparse matrices.
623  //**********************************************************************************************
624 
625  //**Subtraction assignment to row-major dense matrices******************************************
638  template< typename MT > // Type of the target dense matrix
639  friend inline void subAssign( DenseMatrix<MT,false>& lhs, const DMatSMatMultExpr& rhs )
640  {
642 
643  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
644  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
645 
646  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
647 
648  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
649  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
650 
651  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
652  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
653  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
654  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
655  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
656  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
657 
658  const size_t last( A.rows() & size_t(-4) );
659 
660  for( size_t i=0UL; i<last; i+=4UL ) {
661  for( size_t j=0UL; j<B.rows(); ++j ) {
662  ConstIterator element( B.begin(j) );
663  const ConstIterator end( B.end(j) );
664  for( ; element!=end; ++element ) {
665  (~lhs)(i ,element->index()) -= A(i ,j) * element->value();
666  (~lhs)(i+1UL,element->index()) -= A(i+1UL,j) * element->value();
667  (~lhs)(i+2UL,element->index()) -= A(i+2UL,j) * element->value();
668  (~lhs)(i+3UL,element->index()) -= A(i+3UL,j) * element->value();
669  }
670  }
671  }
672 
673  for( size_t i=last; i<A.rows(); ++i ) {
674  for( size_t j=0UL; j<B.rows(); ++j ) {
675  ConstIterator element( B.begin(j) );
676  const ConstIterator end( B.end(j) );
677  for( ; element!=end; ++element ) {
678  (~lhs)(i,element->index()) -= A(i,j) * element->value();
679  }
680  }
681  }
682  }
684  //**********************************************************************************************
685 
686  //**Subtraction assignment to column-major dense matrices***************************************
699  template< typename MT > // Type of the target dense matrix
700  friend inline void subAssign( DenseMatrix<MT,true>& 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  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
708 
709  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
710  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
711 
712  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
713  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
714  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
715  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
716  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
717  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
718 
719  for( size_t i=0UL; i<B.rows(); ++i ) {
720  for( size_t jj=0UL; jj<A.rows(); jj+=8UL ) {
721  const size_t jend( ( jj+8UL > A.rows() )?( A.rows() ):( jj+8UL ) );
722  ConstIterator element( B.begin(i) );
723  const ConstIterator end( B.end(i) );
724  for( ; element!=end; ++element ) {
725  for( size_t j=jj; j<jend; ++j ) {
726  (~lhs)(j,element->index()) -= A(j,i) * element->value();
727  }
728  }
729  }
730  }
731  }
733  //**********************************************************************************************
734 
735  //**Subtraction assignment to sparse matrices***************************************************
736  // No special implementation for the subtraction assignment to sparse matrices.
737  //**********************************************************************************************
738 
739  //**Multiplication assignment to dense matrices*************************************************
740  // No special implementation for the multiplication assignment to dense matrices.
741  //**********************************************************************************************
742 
743  //**Multiplication assignment to sparse matrices************************************************
744  // No special implementation for the multiplication assignment to sparse matrices.
745  //**********************************************************************************************
746 
747  //**Compile time checks*************************************************************************
754  //**********************************************************************************************
755 };
756 //*************************************************************************************************
757 
758 
759 
760 
761 //=================================================================================================
762 //
763 // GLOBAL BINARY ARITHMETIC OPERATORS
764 //
765 //=================================================================================================
766 
767 //*************************************************************************************************
796 template< typename T1 // Type of the left-hand side dense matrix
797  , typename T2 > // Type of the right-hand side sparse matrix
798 inline const DMatSMatMultExpr<T1,T2>
800 {
802 
803  if( (~lhs).columns() != (~rhs).rows() )
804  throw std::invalid_argument( "Matrix sizes do not match" );
805 
806  return DMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
807 }
808 //*************************************************************************************************
809 
810 
811 
812 
813 //=================================================================================================
814 //
815 // GLOBAL OPERATORS
816 //
817 //=================================================================================================
818 
819 //*************************************************************************************************
831 template< typename MT1 // Type of the left-hand side dense matrix
832  , typename MT2 > // Type of the right-hand side sparse matrix
833 inline typename RowExprTrait< DMatSMatMultExpr<MT1,MT2> >::Type
834  row( const DMatSMatMultExpr<MT1,MT2>& dm, size_t index )
835 {
837 
838  return row( dm.leftOperand(), index ) * dm.rightOperand();
839 }
841 //*************************************************************************************************
842 
843 
844 //*************************************************************************************************
856 template< typename MT1 // Type of the left-hand side dense matrix
857  , typename MT2 > // Type of the right-hand side sparse matrix
858 inline typename ColumnExprTrait< DMatSMatMultExpr<MT1,MT2> >::Type
859  column( const DMatSMatMultExpr<MT1,MT2>& dm, size_t index )
860 {
862 
863  return dm.leftOperand() * column( dm.rightOperand(), index );
864 }
866 //*************************************************************************************************
867 
868 
869 
870 
871 //=================================================================================================
872 //
873 // EXPRESSION TRAIT SPECIALIZATIONS
874 //
875 //=================================================================================================
876 
877 //*************************************************************************************************
879 template< typename MT1, typename MT2, typename VT >
880 struct DMatDVecMultExprTrait< DMatSMatMultExpr<MT1,MT2>, VT >
881 {
882  public:
883  //**********************************************************************************************
884  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
885  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
886  IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
887  , typename DMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
888  , INVALID_TYPE >::Type Type;
889  //**********************************************************************************************
890 };
892 //*************************************************************************************************
893 
894 
895 //*************************************************************************************************
897 template< typename MT1, typename MT2, typename VT >
898 struct DMatSVecMultExprTrait< DMatSMatMultExpr<MT1,MT2>, VT >
899 {
900  public:
901  //**********************************************************************************************
902  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
903  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
904  IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
905  , typename DMatSVecMultExprTrait< MT1, typename SMatSVecMultExprTrait<MT2,VT>::Type >::Type
906  , INVALID_TYPE >::Type Type;
907  //**********************************************************************************************
908 };
910 //*************************************************************************************************
911 
912 
913 //*************************************************************************************************
915 template< typename VT, typename MT1, typename MT2 >
916 struct TDVecDMatMultExprTrait< VT, DMatSMatMultExpr<MT1,MT2> >
917 {
918  public:
919  //**********************************************************************************************
920  typedef typename SelectType< IsDenseVector<VT>::value && IsTransposeVector<VT>::value &&
921  IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
922  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
923  , typename TDVecSMatMultExprTrait< typename TDVecDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
924  , INVALID_TYPE >::Type Type;
925  //**********************************************************************************************
926 };
928 //*************************************************************************************************
929 
930 
931 //*************************************************************************************************
933 template< typename VT, typename MT1, typename MT2 >
934 struct TSVecDMatMultExprTrait< VT, DMatSMatMultExpr<MT1,MT2> >
935 {
936  public:
937  //**********************************************************************************************
938  typedef typename SelectType< IsSparseVector<VT>::value && IsTransposeVector<VT>::value &&
939  IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
940  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
941  , typename TDVecSMatMultExprTrait< typename TDVecDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
942  , INVALID_TYPE >::Type Type;
943  //**********************************************************************************************
944 };
946 //*************************************************************************************************
947 
948 
949 //*************************************************************************************************
951 template< typename MT1, typename MT2 >
952 struct RowExprTrait< DMatSMatMultExpr<MT1,MT2> >
953 {
954  public:
955  //**********************************************************************************************
956  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
957  //**********************************************************************************************
958 };
960 //*************************************************************************************************
961 
962 
963 //*************************************************************************************************
965 template< typename MT1, typename MT2 >
966 struct ColumnExprTrait< DMatSMatMultExpr<MT1,MT2> >
967 {
968  public:
969  //**********************************************************************************************
970  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
971  //**********************************************************************************************
972 };
974 //*************************************************************************************************
975 
976 } // namespace blaze
977 
978 #endif