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>
59 #include <blaze/util/Assert.h>
61 #include <blaze/util/DisableIf.h>
62 #include <blaze/util/EnableIf.h>
63 #include <blaze/util/InvalidType.h>
64 #include <blaze/util/SelectType.h>
65 #include <blaze/util/Types.h>
66 
67 
68 namespace blaze {
69 
70 //=================================================================================================
71 //
72 // CLASS TDMATSMATMULTEXPR
73 //
74 //=================================================================================================
75 
76 //*************************************************************************************************
83 template< typename MT1 // Type of the left-hand side dense matrix
84  , typename MT2 > // Type of the right-hand side sparse matrix
85 class TDMatSMatMultExpr : public DenseMatrix< TDMatSMatMultExpr<MT1,MT2>, true >
86  , private Expression
87  , private Computation
88 {
89  private:
90  //**Type definitions****************************************************************************
91  typedef typename MT1::ResultType RT1;
92  typedef typename MT2::ResultType RT2;
93  typedef typename MT1::ElementType ET1;
94  typedef typename MT2::ElementType ET2;
95  typedef typename MT1::CompositeType CT1;
96  typedef typename MT2::CompositeType CT2;
97  //**********************************************************************************************
98 
99  public:
100  //**Type definitions****************************************************************************
103  typedef typename ResultType::OppositeType OppositeType;
104  typedef typename ResultType::TransposeType TransposeType;
105  typedef typename ResultType::ElementType ElementType;
106  typedef const ElementType ReturnType;
107  typedef const ResultType CompositeType;
108 
110  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
111 
113  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
114 
116  typedef typename SelectType< IsComputation<MT1>::value, const RT1, CT1 >::Type LT;
117 
119  typedef typename SelectType< IsComputation<MT2>::value, const RT2, CT2 >::Type RT;
120  //**********************************************************************************************
121 
122  //**Compilation flags***************************************************************************
124  enum { vectorizable = 0 };
125 
127  enum { canAlias = !IsComputation<MT1>::value };
128  //**********************************************************************************************
129 
130  //**Constructor*********************************************************************************
136  explicit inline TDMatSMatMultExpr( const MT1& lhs, const MT2& rhs )
137  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
138  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
139  {
140  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
141  }
142  //**********************************************************************************************
143 
144  //**Access operator*****************************************************************************
151  inline ReturnType operator()( size_t i, size_t j ) const {
152  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
153  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
154 
155  ElementType tmp;
156 
157  if( lhs_.columns() != 0 ) {
158  tmp = lhs_(i,0) * rhs_(0,j);
159  for( size_t k=1; k<lhs_.columns(); ++k ) {
160  tmp += lhs_(i,k) * rhs_(k,j);
161  }
162  }
163  else {
164  reset( tmp );
165  }
166 
167  return tmp;
168  }
169  //**********************************************************************************************
170 
171  //**Rows function*******************************************************************************
176  inline size_t rows() const {
177  return lhs_.rows();
178  }
179  //**********************************************************************************************
180 
181  //**Columns function****************************************************************************
186  inline size_t columns() const {
187  return rhs_.columns();
188  }
189  //**********************************************************************************************
190 
191  //**Left operand access*************************************************************************
196  inline LeftOperand leftOperand() const {
197  return lhs_;
198  }
199  //**********************************************************************************************
200 
201  //**Right operand access************************************************************************
206  inline RightOperand rightOperand() const {
207  return rhs_;
208  }
209  //**********************************************************************************************
210 
211  //**********************************************************************************************
217  template< typename T >
218  inline bool isAliased( const T* alias ) const {
219  return ( !IsComputation<MT1>::value && lhs_.isAliased( alias ) );
220  }
221  //**********************************************************************************************
222 
223  private:
224  //**Member variables****************************************************************************
227  //**********************************************************************************************
228 
229  //**Default assignment to row-major dense matrices**********************************************
243  template< typename MT > // Type of the target dense matrix
244  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
246  {
247  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
248  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
249 
250  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
251 
252  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
253  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
254 
255  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
256  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
257  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
258  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
259  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
260  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
261 
262  for( size_t i=0; i<A.rows(); ++i ) {
263  for( size_t j=0; j<(~lhs).columns(); ++j ) {
264  reset( (~lhs)(i,j) );
265  }
266  for( size_t j=0; j<B.rows(); ++j ) {
267  ConstIterator element( B.begin(j) );
268  const ConstIterator end( B.end(j) );
269  for( ; element!=end; ++element ) {
270  if( isDefault( (~lhs)(i,element->index()) ) )
271  (~lhs)(i,element->index()) = A(i,j) * element->value();
272  else
273  (~lhs)(i,element->index()) += A(i,j) * element->value();
274  }
275  }
276  }
277  }
279  //**********************************************************************************************
280 
281  //**Default assignment to column-major dense matrices*******************************************
295  template< typename MT > // Type of the target dense matrix
296  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
297  assign( DenseMatrix<MT,true>& lhs, const TDMatSMatMultExpr& rhs )
298  {
299  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
300  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
301 
302  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
303 
304  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
305  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
306 
307  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
308  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
309  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
310  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
311  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
312  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
313 
314  reset( ~lhs );
315 
316  for( size_t i=0; i<B.rows(); ++i ) {
317  ConstIterator element( B.begin(i) );
318  const ConstIterator end( B.end(i) );
319  for( ; element!=end; ++element ) {
320  for( size_t j=0; j<A.rows(); ++j ) {
321  if( isDefault( (~lhs)(j,element->index()) ) )
322  (~lhs)(j,element->index()) = A(j,i) * element->value();
323  else
324  (~lhs)(j,element->index()) += A(j,i) * element->value();
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 TDMatSMatMultExpr& 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  const size_t last( A.rows() & size_t(-4) );
366 
367  for( size_t i=0; i<last; i+=4 ) {
368  for( size_t j=0; j<(~lhs).columns(); ++j ) {
369  reset( (~lhs)(i ,j) );
370  reset( (~lhs)(i+1,j) );
371  reset( (~lhs)(i+2,j) );
372  reset( (~lhs)(i+3,j) );
373  }
374  for( size_t j=0; j<B.rows(); ++j ) {
375  ConstIterator element( B.begin(j) );
376  const ConstIterator end( B.end(j) );
377  for( ; element!=end; ++element ) {
378  (~lhs)(i ,element->index()) += A(i ,j) * element->value();
379  (~lhs)(i+1,element->index()) += A(i+1,j) * element->value();
380  (~lhs)(i+2,element->index()) += A(i+2,j) * element->value();
381  (~lhs)(i+3,element->index()) += A(i+3,j) * element->value();
382  }
383  }
384  }
385 
386  for( size_t i=last; i<A.rows(); ++i ) {
387  for( size_t j=0; j<(~lhs).columns(); ++j ) {
388  reset( (~lhs)(i,j) );
389  }
390  for( size_t j=0; j<B.rows(); ++j ) {
391  ConstIterator element( B.begin(j) );
392  const ConstIterator end( B.end(j) );
393  for( ; element!=end; ++element ) {
394  (~lhs)(i,element->index()) += A(i,j) * element->value();
395  }
396  }
397  }
398  }
400  //**********************************************************************************************
401 
402  //**Optimized assignment to column-major dense matrices*****************************************
416  template< typename MT > // Type of the target dense matrix
417  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
418  assign( DenseMatrix<MT,true>& lhs, const TDMatSMatMultExpr& rhs )
419  {
420  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
421  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
422 
423  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
424 
425  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
426  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
427 
428  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
429  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
430  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
431  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
432  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
433  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
434 
435  reset( ~lhs );
436 
437  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
438  const size_t jend( A.rows() & size_t(-4) );
439  size_t j( 0UL );
440 
441  for( size_t i=0UL; i<B.rows(); ++i ) {
442  ConstIterator element( B.begin(i) );
443  const ConstIterator end( B.end(i) );
444 
445  const size_t nonzeros( B.nonZeros(i) );
446  const size_t kend( nonzeros & size_t(-4) );
447 
448  for( size_t k=0UL; k<kend; k+=4UL )
449  {
450  const size_t i1( element->index() );
451  const ET2 v1( element->value() );
452  ++element;
453  const size_t i2( element->index() );
454  const ET2 v2( element->value() );
455  ++element;
456  const size_t i3( element->index() );
457  const ET2 v3( element->value() );
458  ++element;
459  const size_t i4( element->index() );
460  const ET2 v4( element->value() );
461  ++element;
462 
463  for( j=0UL; j<jend; j+=4UL ) {
464  (~lhs)(j ,i1) += A(j ,i) * v1;
465  (~lhs)(j+1UL,i1) += A(j+1UL,i) * v1;
466  (~lhs)(j+2UL,i1) += A(j+2UL,i) * v1;
467  (~lhs)(j+3UL,i1) += A(j+3UL,i) * v1;
468  (~lhs)(j ,i2) += A(j ,i) * v2;
469  (~lhs)(j+1UL,i2) += A(j+1UL,i) * v2;
470  (~lhs)(j+2UL,i2) += A(j+2UL,i) * v2;
471  (~lhs)(j+3UL,i2) += A(j+3UL,i) * v2;
472  (~lhs)(j ,i3) += A(j ,i) * v3;
473  (~lhs)(j+1UL,i3) += A(j+1UL,i) * v3;
474  (~lhs)(j+2UL,i3) += A(j+2UL,i) * v3;
475  (~lhs)(j+3UL,i3) += A(j+3UL,i) * v3;
476  (~lhs)(j ,i4) += A(j ,i) * v4;
477  (~lhs)(j+1UL,i4) += A(j+1UL,i) * v4;
478  (~lhs)(j+2UL,i4) += A(j+2UL,i) * v4;
479  (~lhs)(j+3UL,i4) += A(j+3UL,i) * v4;
480  }
481  for( ; j<A.rows(); ++j ) {
482  (~lhs)(j,i1) += A(j,i) * v1;
483  (~lhs)(j,i2) += A(j,i) * v2;
484  (~lhs)(j,i3) += A(j,i) * v3;
485  (~lhs)(j,i4) += A(j,i) * v4;
486  }
487  }
488 
489  for( ; element!=end; ++element ) {
490  for( j=0UL; j<jend; j+=4UL ) {
491  (~lhs)(j ,element->index()) += A(j ,i) * element->value();
492  (~lhs)(j+1UL,element->index()) += A(j+1UL,i) * element->value();
493  (~lhs)(j+2UL,element->index()) += A(j+2UL,i) * element->value();
494  (~lhs)(j+3UL,element->index()) += A(j+3UL,i) * element->value();
495  }
496  for( ; j<A.rows(); ++j ) {
497  (~lhs)(j,element->index()) += A(j,i) * element->value();
498  }
499  }
500  }
501  }
503  //**********************************************************************************************
504 
505  //**Assignment to sparse matrices***************************************************************
517  template< typename MT // Type of the target sparse matrix
518  , bool SO > // Storage order of the target sparse matrix
519  friend inline void assign( SparseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
520  {
521  typedef typename SelectType< SO, ResultType, OppositeType >::Type TmpType;
522 
528  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename TmpType::CompositeType );
529 
530  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
531  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
532 
533  const TmpType tmp( rhs );
534  assign( ~lhs, tmp );
535  }
537  //**********************************************************************************************
538 
539  //**Addition assignment to row-major dense matrices*********************************************
552  template< typename MT > // Type of the target dense matrix
553  friend inline void addAssign( DenseMatrix<MT,false>& lhs, const TDMatSMatMultExpr& rhs )
554  {
555  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
556  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
557 
558  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
559 
560  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
561  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
562 
563  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
564  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
565  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
566  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
567  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
568  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
569 
570  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
571  const size_t last( A.rows() & size_t(-4) );
572 
573  for( size_t i=0UL; i<last; i+=4UL ) {
574  for( size_t j=0UL; j<B.rows(); ++j ) {
575  ConstIterator element( B.begin(j) );
576  const ConstIterator end( B.end(j) );
577  for( ; element!=end; ++element ) {
578  (~lhs)(i ,element->index()) += A(i ,j) * element->value();
579  (~lhs)(i+1UL,element->index()) += A(i+1UL,j) * element->value();
580  (~lhs)(i+2UL,element->index()) += A(i+2UL,j) * element->value();
581  (~lhs)(i+3UL,element->index()) += A(i+3UL,j) * element->value();
582  }
583  }
584  }
585 
586  for( size_t i=last; i<A.rows(); ++i ) {
587  for( size_t j=0UL; j<B.rows(); ++j ) {
588  ConstIterator element( B.begin(j) );
589  const ConstIterator end( B.end(j) );
590  for( ; element!=end; ++element ) {
591  (~lhs)(i,element->index()) += A(i,j) * element->value();
592  }
593  }
594  }
595  }
597  //**********************************************************************************************
598 
599  //**Addition assignment to column-major dense matrices******************************************
612  template< typename MT > // Type of the target dense matrix
613  friend inline void addAssign( DenseMatrix<MT,true>& lhs, const TDMatSMatMultExpr& rhs )
614  {
615  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
616  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
617 
618  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
619 
620  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
621  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
622 
623  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
624  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
625  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
626  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
627  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
628  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
629 
630  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
631  const size_t jend( A.rows() & size_t(-4) );
632  size_t j( 0UL );
633 
634  for( size_t i=0UL; i<B.rows(); ++i ) {
635  ConstIterator element( B.begin(i) );
636  const ConstIterator end( B.end(i) );
637 
638  const size_t nonzeros( B.nonZeros(i) );
639  const size_t kend( nonzeros & size_t(-4) );
640 
641  for( size_t k=0UL; k<kend; k+=4UL )
642  {
643  const size_t i1( element->index() );
644  const ET2 v1( element->value() );
645  ++element;
646  const size_t i2( element->index() );
647  const ET2 v2( element->value() );
648  ++element;
649  const size_t i3( element->index() );
650  const ET2 v3( element->value() );
651  ++element;
652  const size_t i4( element->index() );
653  const ET2 v4( element->value() );
654  ++element;
655 
656  for( j=0UL; j<jend; j+=4UL ) {
657  (~lhs)(j ,i1) += A(j ,i) * v1;
658  (~lhs)(j+1UL,i1) += A(j+1UL,i) * v1;
659  (~lhs)(j+2UL,i1) += A(j+2UL,i) * v1;
660  (~lhs)(j+3UL,i1) += A(j+3UL,i) * v1;
661  (~lhs)(j ,i2) += A(j ,i) * v2;
662  (~lhs)(j+1UL,i2) += A(j+1UL,i) * v2;
663  (~lhs)(j+2UL,i2) += A(j+2UL,i) * v2;
664  (~lhs)(j+3UL,i2) += A(j+3UL,i) * v2;
665  (~lhs)(j ,i3) += A(j ,i) * v3;
666  (~lhs)(j+1UL,i3) += A(j+1UL,i) * v3;
667  (~lhs)(j+2UL,i3) += A(j+2UL,i) * v3;
668  (~lhs)(j+3UL,i3) += A(j+3UL,i) * v3;
669  (~lhs)(j ,i4) += A(j ,i) * v4;
670  (~lhs)(j+1UL,i4) += A(j+1UL,i) * v4;
671  (~lhs)(j+2UL,i4) += A(j+2UL,i) * v4;
672  (~lhs)(j+3UL,i4) += A(j+3UL,i) * v4;
673  }
674  for( ; j<A.rows(); ++j ) {
675  (~lhs)(j,i1) += A(j,i) * v1;
676  (~lhs)(j,i2) += A(j,i) * v2;
677  (~lhs)(j,i3) += A(j,i) * v3;
678  (~lhs)(j,i4) += A(j,i) * v4;
679  }
680  }
681 
682  for( ; element!=end; ++element ) {
683  for( j=0UL; j<jend; j+=4UL ) {
684  (~lhs)(j ,element->index()) += A(j ,i) * element->value();
685  (~lhs)(j+1UL,element->index()) += A(j+1UL,i) * element->value();
686  (~lhs)(j+2UL,element->index()) += A(j+2UL,i) * element->value();
687  (~lhs)(j+3UL,element->index()) += A(j+3UL,i) * element->value();
688  }
689  for( ; j<A.rows(); ++j ) {
690  (~lhs)(j,element->index()) += A(j,i) * element->value();
691  }
692  }
693  }
694  }
696  //**********************************************************************************************
697 
698  //**Addition assignment to sparse matrices******************************************************
699  // No special implementation for the addition assignment to sparse matrices.
700  //**********************************************************************************************
701 
702  //**Subtraction assignment to row-major dense matrices******************************************
715  template< typename MT > // Type of the target dense matrix
716  friend inline void subAssign( DenseMatrix<MT,false>& lhs, const TDMatSMatMultExpr& rhs )
717  {
718  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
719  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
720 
721  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
722 
723  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
724  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
725 
726  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
727  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
728  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
729  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
730  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
731  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
732 
733  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
734  const size_t last( A.rows() & size_t(-4) );
735 
736  for( size_t i=0UL; i<last; i+=4UL ) {
737  for( size_t j=0UL; j<B.rows(); ++j ) {
738  ConstIterator element( B.begin(j) );
739  const ConstIterator end( B.end(j) );
740  for( ; element!=end; ++element ) {
741  (~lhs)(i ,element->index()) -= A(i ,j) * element->value();
742  (~lhs)(i+1UL,element->index()) -= A(i+1UL,j) * element->value();
743  (~lhs)(i+2UL,element->index()) -= A(i+2UL,j) * element->value();
744  (~lhs)(i+3UL,element->index()) -= A(i+3UL,j) * element->value();
745  }
746  }
747  }
748 
749  for( size_t i=last; i<A.rows(); ++i ) {
750  for( size_t j=0UL; j<B.rows(); ++j ) {
751  ConstIterator element( B.begin(j) );
752  const ConstIterator end( B.end(j) );
753  for( ; element!=end; ++element ) {
754  (~lhs)(i,element->index()) -= A(i,j) * element->value();
755  }
756  }
757  }
758  }
760  //**********************************************************************************************
761 
762  //**Subtraction assignment to column-major dense matrices***************************************
775  template< typename MT > // Type of the target dense matrix
776  friend inline void subAssign( DenseMatrix<MT,true>& lhs, const TDMatSMatMultExpr& rhs )
777  {
778  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
779  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
780 
781  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
782 
783  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
784  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
785 
786  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
787  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
788  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
789  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
790  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
791  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
792 
793  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
794  const size_t jend( A.rows() & size_t(-4) );
795  size_t j( 0UL );
796 
797  for( size_t i=0UL; i<B.rows(); ++i ) {
798  ConstIterator element( B.begin(i) );
799  const ConstIterator end( B.end(i) );
800 
801  const size_t nonzeros( B.nonZeros(i) );
802  const size_t kend( nonzeros & size_t(-4) );
803 
804  for( size_t k=0UL; k<kend; k+=4UL )
805  {
806  const size_t i1( element->index() );
807  const ET2 v1( element->value() );
808  ++element;
809  const size_t i2( element->index() );
810  const ET2 v2( element->value() );
811  ++element;
812  const size_t i3( element->index() );
813  const ET2 v3( element->value() );
814  ++element;
815  const size_t i4( element->index() );
816  const ET2 v4( element->value() );
817  ++element;
818 
819  for( j=0UL; j<jend; j+=4UL ) {
820  (~lhs)(j ,i1) -= A(j ,i) * v1;
821  (~lhs)(j+1UL,i1) -= A(j+1UL,i) * v1;
822  (~lhs)(j+2UL,i1) -= A(j+2UL,i) * v1;
823  (~lhs)(j+3UL,i1) -= A(j+3UL,i) * v1;
824  (~lhs)(j ,i2) -= A(j ,i) * v2;
825  (~lhs)(j+1UL,i2) -= A(j+1UL,i) * v2;
826  (~lhs)(j+2UL,i2) -= A(j+2UL,i) * v2;
827  (~lhs)(j+3UL,i2) -= A(j+3UL,i) * v2;
828  (~lhs)(j ,i3) -= A(j ,i) * v3;
829  (~lhs)(j+1UL,i3) -= A(j+1UL,i) * v3;
830  (~lhs)(j+2UL,i3) -= A(j+2UL,i) * v3;
831  (~lhs)(j+3UL,i3) -= A(j+3UL,i) * v3;
832  (~lhs)(j ,i4) -= A(j ,i) * v4;
833  (~lhs)(j+1UL,i4) -= A(j+1UL,i) * v4;
834  (~lhs)(j+2UL,i4) -= A(j+2UL,i) * v4;
835  (~lhs)(j+3UL,i4) -= A(j+3UL,i) * v4;
836  }
837  for( ; j<A.rows(); ++j ) {
838  (~lhs)(j,i1) -= A(j,i) * v1;
839  (~lhs)(j,i2) -= A(j,i) * v2;
840  (~lhs)(j,i3) -= A(j,i) * v3;
841  (~lhs)(j,i4) -= A(j,i) * v4;
842  }
843  }
844 
845  for( ; element!=end; ++element ) {
846  for( j=0UL; j<jend; j+=4UL ) {
847  (~lhs)(j ,element->index()) -= A(j ,i) * element->value();
848  (~lhs)(j+1UL,element->index()) -= A(j+1UL,i) * element->value();
849  (~lhs)(j+2UL,element->index()) -= A(j+2UL,i) * element->value();
850  (~lhs)(j+3UL,element->index()) -= A(j+3UL,i) * element->value();
851  }
852  for( ; j<A.rows(); ++j ) {
853  (~lhs)(j,element->index()) -= A(j,i) * element->value();
854  }
855  }
856  }
857  }
859  //**********************************************************************************************
860 
861  //**Subtraction assignment to sparse matrices***************************************************
862  // No special implementation for the subtraction assignment to sparse matrices.
863  //**********************************************************************************************
864 
865  //**Multiplication assignment to dense matrices*************************************************
866  // No special implementation for the multiplication assignment to dense matrices.
867  //**********************************************************************************************
868 
869  //**Multiplication assignment to sparse matrices************************************************
870  // No special implementation for the multiplication assignment to sparse matrices.
871  //**********************************************************************************************
872 
873  //**Compile time checks*************************************************************************
880  //**********************************************************************************************
881 };
882 //*************************************************************************************************
883 
884 
885 
886 
887 //=================================================================================================
888 //
889 // GLOBAL BINARY ARITHMETIC OPERATORS
890 //
891 //=================================================================================================
892 
893 //*************************************************************************************************
923 template< typename T1 // Type of the left-hand side dense matrix
924  , typename T2 > // Type of the right-hand side sparse matrix
925 inline const TDMatSMatMultExpr<T1,T2>
927 {
928  if( (~lhs).columns() != (~rhs).rows() )
929  throw std::invalid_argument( "Matrix sizes do not match" );
930 
931  return TDMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
932 }
933 //*************************************************************************************************
934 
935 
936 
937 
938 //=================================================================================================
939 //
940 // EXPRESSION TRAIT SPECIALIZATIONS
941 //
942 //=================================================================================================
943 
944 //*************************************************************************************************
946 template< typename MT1, typename MT2, typename VT >
947 struct TDMatDVecMultExprTrait< TDMatSMatMultExpr<MT1,MT2>, VT >
948 {
949  public:
950  //**********************************************************************************************
951  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
952  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
953  IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
954  , typename TDMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
955  , INVALID_TYPE >::Type Type;
956  //**********************************************************************************************
957 };
959 //*************************************************************************************************
960 
961 
962 //*************************************************************************************************
964 template< typename MT1, typename MT2, typename VT >
965 struct TDMatSVecMultExprTrait< TDMatSMatMultExpr<MT1,MT2>, VT >
966 {
967  public:
968  //**********************************************************************************************
969  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
970  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
971  IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
972  , typename TDMatSVecMultExprTrait< MT1, typename SMatSVecMultExprTrait<MT2,VT>::Type >::Type
973  , INVALID_TYPE >::Type Type;
974  //**********************************************************************************************
975 };
977 //*************************************************************************************************
978 
979 
980 //*************************************************************************************************
982 template< typename VT, typename MT1, typename MT2 >
983 struct TDVecTDMatMultExprTrait< VT, TDMatSMatMultExpr<MT1,MT2> >
984 {
985  public:
986  //**********************************************************************************************
987  typedef typename SelectType< IsDenseVector<VT>::value && IsTransposeVector<VT>::value &&
988  IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
989  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
990  , typename TDMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
991  , INVALID_TYPE >::Type Type;
992  //**********************************************************************************************
993 };
995 //*************************************************************************************************
996 
997 
998 //*************************************************************************************************
1000 template< typename VT, typename MT1, typename MT2 >
1001 struct TSVecTDMatMultExprTrait< VT, TDMatSMatMultExpr<MT1,MT2> >
1002 {
1003  public:
1004  //**********************************************************************************************
1005  typedef typename SelectType< IsSparseVector<VT>::value && IsTransposeVector<VT>::value &&
1006  IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1007  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1008  , typename TDVecSMatMultExprTrait< typename TSVecTDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1009  , INVALID_TYPE >::Type Type;
1010  //**********************************************************************************************
1011 };
1013 //*************************************************************************************************
1014 
1015 } // namespace blaze
1016 
1017 #endif