All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TDMatSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TDMATSMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TDMATSMATMULTEXPR_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>
62 #include <blaze/util/Assert.h>
64 #include <blaze/util/DisableIf.h>
65 #include <blaze/util/EnableIf.h>
66 #include <blaze/util/InvalidType.h>
68 #include <blaze/util/SelectType.h>
69 #include <blaze/util/Types.h>
70 
71 
72 namespace blaze {
73 
74 //=================================================================================================
75 //
76 // CLASS TDMATSMATMULTEXPR
77 //
78 //=================================================================================================
79 
80 //*************************************************************************************************
87 template< typename MT1 // Type of the left-hand side dense matrix
88  , typename MT2 > // Type of the right-hand side sparse matrix
89 class TDMatSMatMultExpr : public DenseMatrix< TDMatSMatMultExpr<MT1,MT2>, true >
90  , private Expression
91  , private Computation
92 {
93  private:
94  //**Type definitions****************************************************************************
95  typedef typename MT1::ResultType RT1;
96  typedef typename MT2::ResultType RT2;
97  typedef typename MT1::ElementType ET1;
98  typedef typename MT2::ElementType ET2;
99  typedef typename MT1::CompositeType CT1;
100  typedef typename MT2::CompositeType CT2;
101  //**********************************************************************************************
102 
103  public:
104  //**Type definitions****************************************************************************
107  typedef typename ResultType::OppositeType OppositeType;
108  typedef typename ResultType::TransposeType TransposeType;
109  typedef typename ResultType::ElementType ElementType;
110  typedef const ElementType ReturnType;
111  typedef const ResultType CompositeType;
112 
114  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
115 
117  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
118 
120  typedef typename SelectType< IsComputation<MT1>::value, const RT1, CT1 >::Type LT;
121 
123  typedef typename SelectType< IsComputation<MT2>::value, const RT2, CT2 >::Type RT;
124  //**********************************************************************************************
125 
126  //**Compilation flags***************************************************************************
128  enum { vectorizable = 0 };
129  //**********************************************************************************************
130 
131  //**Constructor*********************************************************************************
137  explicit inline TDMatSMatMultExpr( const MT1& lhs, const MT2& rhs )
138  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
139  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
140  {
141  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
142  }
143  //**********************************************************************************************
144 
145  //**Access operator*****************************************************************************
152  inline ReturnType operator()( size_t i, size_t j ) const {
153  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
154  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
155 
156  ElementType tmp;
157 
158  if( lhs_.columns() != 0 ) {
159  tmp = lhs_(i,0) * rhs_(0,j);
160  for( size_t k=1; k<lhs_.columns(); ++k ) {
161  tmp += lhs_(i,k) * rhs_(k,j);
162  }
163  }
164  else {
165  reset( tmp );
166  }
167 
168  return tmp;
169  }
170  //**********************************************************************************************
171 
172  //**Rows function*******************************************************************************
177  inline size_t rows() const {
178  return lhs_.rows();
179  }
180  //**********************************************************************************************
181 
182  //**Columns function****************************************************************************
187  inline size_t columns() const {
188  return rhs_.columns();
189  }
190  //**********************************************************************************************
191 
192  //**Left operand access*************************************************************************
197  inline LeftOperand leftOperand() const {
198  return lhs_;
199  }
200  //**********************************************************************************************
201 
202  //**Right operand access************************************************************************
207  inline RightOperand rightOperand() const {
208  return rhs_;
209  }
210  //**********************************************************************************************
211 
212  //**********************************************************************************************
218  template< typename T >
219  inline bool canAlias( const T* alias ) const {
220  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
221  }
222  //**********************************************************************************************
223 
224  //**********************************************************************************************
230  template< typename T >
231  inline bool isAliased( const T* alias ) const {
232  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
233  }
234  //**********************************************************************************************
235 
236  private:
237  //**Member variables****************************************************************************
240  //**********************************************************************************************
241 
242  //**Default assignment to row-major dense matrices**********************************************
256  template< typename MT > // Type of the target dense matrix
257  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
259  {
261 
262  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
263  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
264 
265  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
266 
267  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
268  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
269 
270  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
271  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
272  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
273  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
274  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
275  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
276 
277  for( size_t i=0; i<A.rows(); ++i ) {
278  for( size_t j=0; j<(~lhs).columns(); ++j ) {
279  reset( (~lhs)(i,j) );
280  }
281  for( size_t j=0; j<B.rows(); ++j ) {
282  ConstIterator element( B.begin(j) );
283  const ConstIterator end( B.end(j) );
284  for( ; element!=end; ++element ) {
285  if( isDefault( (~lhs)(i,element->index()) ) )
286  (~lhs)(i,element->index()) = A(i,j) * element->value();
287  else
288  (~lhs)(i,element->index()) += A(i,j) * element->value();
289  }
290  }
291  }
292  }
294  //**********************************************************************************************
295 
296  //**Default assignment to column-major dense matrices*******************************************
310  template< typename MT > // Type of the target dense matrix
311  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
312  assign( DenseMatrix<MT,true>& lhs, const TDMatSMatMultExpr& rhs )
313  {
315 
316  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
317  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
318 
319  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
320 
321  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
322  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
323 
324  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
325  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
326  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
327  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
328  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
329  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
330 
331  reset( ~lhs );
332 
333  for( size_t i=0; i<B.rows(); ++i ) {
334  ConstIterator element( B.begin(i) );
335  const ConstIterator end( B.end(i) );
336  for( ; element!=end; ++element ) {
337  for( size_t j=0; j<A.rows(); ++j ) {
338  if( isDefault( (~lhs)(j,element->index()) ) )
339  (~lhs)(j,element->index()) = A(j,i) * element->value();
340  else
341  (~lhs)(j,element->index()) += A(j,i) * element->value();
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 TDMatSMatMultExpr& 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  const size_t last( A.rows() & size_t(-4) );
385 
386  for( size_t i=0; i<last; i+=4 ) {
387  for( size_t j=0; j<(~lhs).columns(); ++j ) {
388  reset( (~lhs)(i ,j) );
389  reset( (~lhs)(i+1,j) );
390  reset( (~lhs)(i+2,j) );
391  reset( (~lhs)(i+3,j) );
392  }
393  for( size_t j=0; j<B.rows(); ++j ) {
394  ConstIterator element( B.begin(j) );
395  const ConstIterator end( B.end(j) );
396  for( ; element!=end; ++element ) {
397  (~lhs)(i ,element->index()) += A(i ,j) * element->value();
398  (~lhs)(i+1,element->index()) += A(i+1,j) * element->value();
399  (~lhs)(i+2,element->index()) += A(i+2,j) * element->value();
400  (~lhs)(i+3,element->index()) += A(i+3,j) * element->value();
401  }
402  }
403  }
404 
405  for( size_t i=last; i<A.rows(); ++i ) {
406  for( size_t j=0; j<(~lhs).columns(); ++j ) {
407  reset( (~lhs)(i,j) );
408  }
409  for( size_t j=0; j<B.rows(); ++j ) {
410  ConstIterator element( B.begin(j) );
411  const ConstIterator end( B.end(j) );
412  for( ; element!=end; ++element ) {
413  (~lhs)(i,element->index()) += A(i,j) * element->value();
414  }
415  }
416  }
417  }
419  //**********************************************************************************************
420 
421  //**Optimized assignment to column-major dense matrices*****************************************
435  template< typename MT > // Type of the target dense matrix
436  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
437  assign( DenseMatrix<MT,true>& lhs, const TDMatSMatMultExpr& rhs )
438  {
440 
441  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
442  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
443 
444  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
445 
446  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
447  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
448 
449  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
450  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
451  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
452  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
453  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
454  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
455 
456  reset( ~lhs );
457 
458  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
459  const size_t jend( A.rows() & size_t(-4) );
460  size_t j( 0UL );
461 
462  for( size_t i=0UL; i<B.rows(); ++i ) {
463  ConstIterator element( B.begin(i) );
464  const ConstIterator end( B.end(i) );
465 
466  const size_t nonzeros( B.nonZeros(i) );
467  const size_t kend( nonzeros & size_t(-4) );
468 
469  for( size_t k=0UL; k<kend; k+=4UL )
470  {
471  const size_t i1( element->index() );
472  const ET2 v1( element->value() );
473  ++element;
474  const size_t i2( element->index() );
475  const ET2 v2( element->value() );
476  ++element;
477  const size_t i3( element->index() );
478  const ET2 v3( element->value() );
479  ++element;
480  const size_t i4( element->index() );
481  const ET2 v4( element->value() );
482  ++element;
483 
484  for( j=0UL; j<jend; j+=4UL ) {
485  (~lhs)(j ,i1) += A(j ,i) * v1;
486  (~lhs)(j+1UL,i1) += A(j+1UL,i) * v1;
487  (~lhs)(j+2UL,i1) += A(j+2UL,i) * v1;
488  (~lhs)(j+3UL,i1) += A(j+3UL,i) * v1;
489  (~lhs)(j ,i2) += A(j ,i) * v2;
490  (~lhs)(j+1UL,i2) += A(j+1UL,i) * v2;
491  (~lhs)(j+2UL,i2) += A(j+2UL,i) * v2;
492  (~lhs)(j+3UL,i2) += A(j+3UL,i) * v2;
493  (~lhs)(j ,i3) += A(j ,i) * v3;
494  (~lhs)(j+1UL,i3) += A(j+1UL,i) * v3;
495  (~lhs)(j+2UL,i3) += A(j+2UL,i) * v3;
496  (~lhs)(j+3UL,i3) += A(j+3UL,i) * v3;
497  (~lhs)(j ,i4) += A(j ,i) * v4;
498  (~lhs)(j+1UL,i4) += A(j+1UL,i) * v4;
499  (~lhs)(j+2UL,i4) += A(j+2UL,i) * v4;
500  (~lhs)(j+3UL,i4) += A(j+3UL,i) * v4;
501  }
502  for( ; j<A.rows(); ++j ) {
503  (~lhs)(j,i1) += A(j,i) * v1;
504  (~lhs)(j,i2) += A(j,i) * v2;
505  (~lhs)(j,i3) += A(j,i) * v3;
506  (~lhs)(j,i4) += A(j,i) * v4;
507  }
508  }
509 
510  for( ; element!=end; ++element ) {
511  for( j=0UL; j<jend; j+=4UL ) {
512  (~lhs)(j ,element->index()) += A(j ,i) * element->value();
513  (~lhs)(j+1UL,element->index()) += A(j+1UL,i) * element->value();
514  (~lhs)(j+2UL,element->index()) += A(j+2UL,i) * element->value();
515  (~lhs)(j+3UL,element->index()) += A(j+3UL,i) * element->value();
516  }
517  for( ; j<A.rows(); ++j ) {
518  (~lhs)(j,element->index()) += A(j,i) * element->value();
519  }
520  }
521  }
522  }
524  //**********************************************************************************************
525 
526  //**Assignment to sparse matrices***************************************************************
538  template< typename MT // Type of the target sparse matrix
539  , bool SO > // Storage order of the target sparse matrix
540  friend inline void assign( SparseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
541  {
543 
544  typedef typename SelectType< SO, ResultType, OppositeType >::Type TmpType;
545 
551  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename TmpType::CompositeType );
552 
553  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
554  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
555 
556  const TmpType tmp( rhs );
557  assign( ~lhs, tmp );
558  }
560  //**********************************************************************************************
561 
562  //**Addition assignment to row-major dense matrices*********************************************
575  template< typename MT > // Type of the target dense matrix
576  friend inline void addAssign( DenseMatrix<MT,false>& lhs, const TDMatSMatMultExpr& rhs )
577  {
579 
580  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
581  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
582 
583  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
584 
585  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
586  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
587 
588  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
589  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
590  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
591  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
592  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
593  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
594 
595  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
596  const size_t last( A.rows() & size_t(-4) );
597 
598  for( size_t i=0UL; i<last; i+=4UL ) {
599  for( size_t j=0UL; j<B.rows(); ++j ) {
600  ConstIterator element( B.begin(j) );
601  const ConstIterator end( B.end(j) );
602  for( ; element!=end; ++element ) {
603  (~lhs)(i ,element->index()) += A(i ,j) * element->value();
604  (~lhs)(i+1UL,element->index()) += A(i+1UL,j) * element->value();
605  (~lhs)(i+2UL,element->index()) += A(i+2UL,j) * element->value();
606  (~lhs)(i+3UL,element->index()) += A(i+3UL,j) * element->value();
607  }
608  }
609  }
610 
611  for( size_t i=last; i<A.rows(); ++i ) {
612  for( size_t j=0UL; j<B.rows(); ++j ) {
613  ConstIterator element( B.begin(j) );
614  const ConstIterator end( B.end(j) );
615  for( ; element!=end; ++element ) {
616  (~lhs)(i,element->index()) += A(i,j) * element->value();
617  }
618  }
619  }
620  }
622  //**********************************************************************************************
623 
624  //**Addition assignment to column-major dense matrices******************************************
637  template< typename MT > // Type of the target dense matrix
638  friend inline void addAssign( DenseMatrix<MT,true>& lhs, const TDMatSMatMultExpr& rhs )
639  {
641 
642  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
643  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
644 
645  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
646 
647  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
648  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
649 
650  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
651  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
652  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
653  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
654  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
655  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
656 
657  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
658  const size_t jend( A.rows() & size_t(-4) );
659  size_t j( 0UL );
660 
661  for( size_t i=0UL; i<B.rows(); ++i ) {
662  ConstIterator element( B.begin(i) );
663  const ConstIterator end( B.end(i) );
664 
665  const size_t nonzeros( B.nonZeros(i) );
666  const size_t kend( nonzeros & size_t(-4) );
667 
668  for( size_t k=0UL; k<kend; k+=4UL )
669  {
670  const size_t i1( element->index() );
671  const ET2 v1( element->value() );
672  ++element;
673  const size_t i2( element->index() );
674  const ET2 v2( element->value() );
675  ++element;
676  const size_t i3( element->index() );
677  const ET2 v3( element->value() );
678  ++element;
679  const size_t i4( element->index() );
680  const ET2 v4( element->value() );
681  ++element;
682 
683  for( j=0UL; j<jend; j+=4UL ) {
684  (~lhs)(j ,i1) += A(j ,i) * v1;
685  (~lhs)(j+1UL,i1) += A(j+1UL,i) * v1;
686  (~lhs)(j+2UL,i1) += A(j+2UL,i) * v1;
687  (~lhs)(j+3UL,i1) += A(j+3UL,i) * v1;
688  (~lhs)(j ,i2) += A(j ,i) * v2;
689  (~lhs)(j+1UL,i2) += A(j+1UL,i) * v2;
690  (~lhs)(j+2UL,i2) += A(j+2UL,i) * v2;
691  (~lhs)(j+3UL,i2) += A(j+3UL,i) * v2;
692  (~lhs)(j ,i3) += A(j ,i) * v3;
693  (~lhs)(j+1UL,i3) += A(j+1UL,i) * v3;
694  (~lhs)(j+2UL,i3) += A(j+2UL,i) * v3;
695  (~lhs)(j+3UL,i3) += A(j+3UL,i) * v3;
696  (~lhs)(j ,i4) += A(j ,i) * v4;
697  (~lhs)(j+1UL,i4) += A(j+1UL,i) * v4;
698  (~lhs)(j+2UL,i4) += A(j+2UL,i) * v4;
699  (~lhs)(j+3UL,i4) += A(j+3UL,i) * v4;
700  }
701  for( ; j<A.rows(); ++j ) {
702  (~lhs)(j,i1) += A(j,i) * v1;
703  (~lhs)(j,i2) += A(j,i) * v2;
704  (~lhs)(j,i3) += A(j,i) * v3;
705  (~lhs)(j,i4) += A(j,i) * v4;
706  }
707  }
708 
709  for( ; element!=end; ++element ) {
710  for( j=0UL; j<jend; j+=4UL ) {
711  (~lhs)(j ,element->index()) += A(j ,i) * element->value();
712  (~lhs)(j+1UL,element->index()) += A(j+1UL,i) * element->value();
713  (~lhs)(j+2UL,element->index()) += A(j+2UL,i) * element->value();
714  (~lhs)(j+3UL,element->index()) += A(j+3UL,i) * element->value();
715  }
716  for( ; j<A.rows(); ++j ) {
717  (~lhs)(j,element->index()) += A(j,i) * element->value();
718  }
719  }
720  }
721  }
723  //**********************************************************************************************
724 
725  //**Addition assignment to sparse matrices******************************************************
726  // No special implementation for the addition assignment to sparse matrices.
727  //**********************************************************************************************
728 
729  //**Subtraction assignment to row-major dense matrices******************************************
742  template< typename MT > // Type of the target dense matrix
743  friend inline void subAssign( DenseMatrix<MT,false>& lhs, const TDMatSMatMultExpr& rhs )
744  {
746 
747  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
748  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
749 
750  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
751 
752  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
753  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
754 
755  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
756  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
757  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
758  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
759  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
760  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
761 
762  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
763  const size_t last( A.rows() & size_t(-4) );
764 
765  for( size_t i=0UL; i<last; i+=4UL ) {
766  for( size_t j=0UL; j<B.rows(); ++j ) {
767  ConstIterator element( B.begin(j) );
768  const ConstIterator end( B.end(j) );
769  for( ; element!=end; ++element ) {
770  (~lhs)(i ,element->index()) -= A(i ,j) * element->value();
771  (~lhs)(i+1UL,element->index()) -= A(i+1UL,j) * element->value();
772  (~lhs)(i+2UL,element->index()) -= A(i+2UL,j) * element->value();
773  (~lhs)(i+3UL,element->index()) -= A(i+3UL,j) * element->value();
774  }
775  }
776  }
777 
778  for( size_t i=last; i<A.rows(); ++i ) {
779  for( size_t j=0UL; j<B.rows(); ++j ) {
780  ConstIterator element( B.begin(j) );
781  const ConstIterator end( B.end(j) );
782  for( ; element!=end; ++element ) {
783  (~lhs)(i,element->index()) -= A(i,j) * element->value();
784  }
785  }
786  }
787  }
789  //**********************************************************************************************
790 
791  //**Subtraction assignment to column-major dense matrices***************************************
804  template< typename MT > // Type of the target dense matrix
805  friend inline void subAssign( DenseMatrix<MT,true>& lhs, const TDMatSMatMultExpr& rhs )
806  {
808 
809  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
810  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
811 
812  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
813 
814  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
815  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
816 
817  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
818  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
819  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
820  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
821  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
822  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
823 
824  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
825  const size_t jend( A.rows() & size_t(-4) );
826  size_t j( 0UL );
827 
828  for( size_t i=0UL; i<B.rows(); ++i ) {
829  ConstIterator element( B.begin(i) );
830  const ConstIterator end( B.end(i) );
831 
832  const size_t nonzeros( B.nonZeros(i) );
833  const size_t kend( nonzeros & size_t(-4) );
834 
835  for( size_t k=0UL; k<kend; k+=4UL )
836  {
837  const size_t i1( element->index() );
838  const ET2 v1( element->value() );
839  ++element;
840  const size_t i2( element->index() );
841  const ET2 v2( element->value() );
842  ++element;
843  const size_t i3( element->index() );
844  const ET2 v3( element->value() );
845  ++element;
846  const size_t i4( element->index() );
847  const ET2 v4( element->value() );
848  ++element;
849 
850  for( j=0UL; j<jend; j+=4UL ) {
851  (~lhs)(j ,i1) -= A(j ,i) * v1;
852  (~lhs)(j+1UL,i1) -= A(j+1UL,i) * v1;
853  (~lhs)(j+2UL,i1) -= A(j+2UL,i) * v1;
854  (~lhs)(j+3UL,i1) -= A(j+3UL,i) * v1;
855  (~lhs)(j ,i2) -= A(j ,i) * v2;
856  (~lhs)(j+1UL,i2) -= A(j+1UL,i) * v2;
857  (~lhs)(j+2UL,i2) -= A(j+2UL,i) * v2;
858  (~lhs)(j+3UL,i2) -= A(j+3UL,i) * v2;
859  (~lhs)(j ,i3) -= A(j ,i) * v3;
860  (~lhs)(j+1UL,i3) -= A(j+1UL,i) * v3;
861  (~lhs)(j+2UL,i3) -= A(j+2UL,i) * v3;
862  (~lhs)(j+3UL,i3) -= A(j+3UL,i) * v3;
863  (~lhs)(j ,i4) -= A(j ,i) * v4;
864  (~lhs)(j+1UL,i4) -= A(j+1UL,i) * v4;
865  (~lhs)(j+2UL,i4) -= A(j+2UL,i) * v4;
866  (~lhs)(j+3UL,i4) -= A(j+3UL,i) * v4;
867  }
868  for( ; j<A.rows(); ++j ) {
869  (~lhs)(j,i1) -= A(j,i) * v1;
870  (~lhs)(j,i2) -= A(j,i) * v2;
871  (~lhs)(j,i3) -= A(j,i) * v3;
872  (~lhs)(j,i4) -= A(j,i) * v4;
873  }
874  }
875 
876  for( ; element!=end; ++element ) {
877  for( j=0UL; j<jend; j+=4UL ) {
878  (~lhs)(j ,element->index()) -= A(j ,i) * element->value();
879  (~lhs)(j+1UL,element->index()) -= A(j+1UL,i) * element->value();
880  (~lhs)(j+2UL,element->index()) -= A(j+2UL,i) * element->value();
881  (~lhs)(j+3UL,element->index()) -= A(j+3UL,i) * element->value();
882  }
883  for( ; j<A.rows(); ++j ) {
884  (~lhs)(j,element->index()) -= A(j,i) * element->value();
885  }
886  }
887  }
888  }
890  //**********************************************************************************************
891 
892  //**Subtraction assignment to sparse matrices***************************************************
893  // No special implementation for the subtraction assignment to sparse matrices.
894  //**********************************************************************************************
895 
896  //**Multiplication assignment to dense matrices*************************************************
897  // No special implementation for the multiplication assignment to dense matrices.
898  //**********************************************************************************************
899 
900  //**Multiplication assignment to sparse matrices************************************************
901  // No special implementation for the multiplication assignment to sparse matrices.
902  //**********************************************************************************************
903 
904  //**Compile time checks*************************************************************************
911  //**********************************************************************************************
912 };
913 //*************************************************************************************************
914 
915 
916 
917 
918 //=================================================================================================
919 //
920 // GLOBAL BINARY ARITHMETIC OPERATORS
921 //
922 //=================================================================================================
923 
924 //*************************************************************************************************
954 template< typename T1 // Type of the left-hand side dense matrix
955  , typename T2 > // Type of the right-hand side sparse matrix
956 inline const TDMatSMatMultExpr<T1,T2>
958 {
960 
961  if( (~lhs).columns() != (~rhs).rows() )
962  throw std::invalid_argument( "Matrix sizes do not match" );
963 
964  return TDMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
965 }
966 //*************************************************************************************************
967 
968 
969 
970 
971 //=================================================================================================
972 //
973 // GLOBAL OPERATORS
974 //
975 //=================================================================================================
976 
977 //*************************************************************************************************
990 template< typename MT1 // Type of the left-hand side dense matrix
991  , typename MT2 > // Type of the right-hand side sparse matrix
992 inline typename RowExprTrait< TDMatSMatMultExpr<MT1,MT2> >::Type
993  row( const TDMatSMatMultExpr<MT1,MT2>& dm, size_t index )
994 {
996 
997  return row( dm.leftOperand(), index ) * dm.rightOperand();
998 }
1000 //*************************************************************************************************
1001 
1002 
1003 //*************************************************************************************************
1016 template< typename MT1 // Type of the left-hand side dense matrix
1017  , typename MT2 > // Type of the right-hand side sparse matrix
1018 inline typename ColumnExprTrait< TDMatSMatMultExpr<MT1,MT2> >::Type
1019  column( const TDMatSMatMultExpr<MT1,MT2>& dm, size_t index )
1020 {
1022 
1023  return dm.leftOperand() * column( dm.rightOperand(), index );
1024 }
1026 //*************************************************************************************************
1027 
1028 
1029 
1030 
1031 //=================================================================================================
1032 //
1033 // EXPRESSION TRAIT SPECIALIZATIONS
1034 //
1035 //=================================================================================================
1036 
1037 //*************************************************************************************************
1039 template< typename MT1, typename MT2, typename VT >
1040 struct TDMatDVecMultExprTrait< TDMatSMatMultExpr<MT1,MT2>, VT >
1041 {
1042  public:
1043  //**********************************************************************************************
1044  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1045  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1046  IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
1047  , typename TDMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
1048  , INVALID_TYPE >::Type Type;
1049  //**********************************************************************************************
1050 };
1052 //*************************************************************************************************
1053 
1054 
1055 //*************************************************************************************************
1057 template< typename MT1, typename MT2, typename VT >
1058 struct TDMatSVecMultExprTrait< TDMatSMatMultExpr<MT1,MT2>, VT >
1059 {
1060  public:
1061  //**********************************************************************************************
1062  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1063  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1064  IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
1065  , typename TDMatSVecMultExprTrait< MT1, typename SMatSVecMultExprTrait<MT2,VT>::Type >::Type
1066  , INVALID_TYPE >::Type Type;
1067  //**********************************************************************************************
1068 };
1070 //*************************************************************************************************
1071 
1072 
1073 //*************************************************************************************************
1075 template< typename VT, typename MT1, typename MT2 >
1076 struct TDVecTDMatMultExprTrait< VT, TDMatSMatMultExpr<MT1,MT2> >
1077 {
1078  public:
1079  //**********************************************************************************************
1080  typedef typename SelectType< IsDenseVector<VT>::value && IsTransposeVector<VT>::value &&
1081  IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1082  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1083  , typename TDMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
1084  , INVALID_TYPE >::Type Type;
1085  //**********************************************************************************************
1086 };
1088 //*************************************************************************************************
1089 
1090 
1091 //*************************************************************************************************
1093 template< typename VT, typename MT1, typename MT2 >
1094 struct TSVecTDMatMultExprTrait< VT, TDMatSMatMultExpr<MT1,MT2> >
1095 {
1096  public:
1097  //**********************************************************************************************
1098  typedef typename SelectType< IsSparseVector<VT>::value && IsTransposeVector<VT>::value &&
1099  IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1100  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1101  , typename TDVecSMatMultExprTrait< typename TSVecTDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1102  , INVALID_TYPE >::Type Type;
1103  //**********************************************************************************************
1104 };
1106 //*************************************************************************************************
1107 
1108 
1109 //*************************************************************************************************
1111 template< typename MT1, typename MT2 >
1112 struct RowExprTrait< TDMatSMatMultExpr<MT1,MT2> >
1113 {
1114  public:
1115  //**********************************************************************************************
1116  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
1117  //**********************************************************************************************
1118 };
1120 //*************************************************************************************************
1121 
1122 
1123 //*************************************************************************************************
1125 template< typename MT1, typename MT2 >
1126 struct ColumnExprTrait< TDMatSMatMultExpr<MT1,MT2> >
1127 {
1128  public:
1129  //**********************************************************************************************
1130  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
1131  //**********************************************************************************************
1132 };
1134 //*************************************************************************************************
1135 
1136 } // namespace blaze
1137 
1138 #endif