All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TDMatTSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TDMATTSMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TDMATTSMATMULTEXPR_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 TDMATTSMATMULTEXPR
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 TDMatTSMatMultExpr : public DenseMatrix< TDMatTSMatMultExpr<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 TDMatTSMatMultExpr( 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  typedef typename boost::remove_reference<CT2>::type::ConstIterator ConstIterator;
157 
158  ElementType tmp = ElementType();
159 
160  // Early exit
161  if( lhs_.columns() == 0UL )
162  return tmp;
163 
164  // Fast computation in case the right-hand side sparse matrix directly provides iterators
166  {
167  CT2 B( rhs_ ); // Evaluation of the right-hand side sparse matrix operand
168 
169  const ConstIterator end( B.end(j) );
170  ConstIterator element( B.begin(j) );
171 
172  // Early exit in case column j is empty
173  if( element == end )
174  return tmp;
175 
176  // Calculating element (i,j)
177  tmp = lhs_(i,element->index()) * element->value();
178  ++element;
179  for( ; element!=end; ++element )
180  tmp += lhs_(i,element->index()) * element->value();
181  }
182 
183  // Default computation in case the right-hand side sparse matrix doesn't provide iterators
184  else {
185  tmp = lhs_(i,0UL) * rhs_(0UL,j);
186  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
187  tmp += lhs_(i,k) * rhs_(k,j);
188  }
189  }
190 
191  return tmp;
192  }
193  //**********************************************************************************************
194 
195  //**Rows function*******************************************************************************
200  inline size_t rows() const {
201  return lhs_.rows();
202  }
203  //**********************************************************************************************
204 
205  //**Columns function****************************************************************************
210  inline size_t columns() const {
211  return rhs_.columns();
212  }
213  //**********************************************************************************************
214 
215  //**Left operand access*************************************************************************
220  inline LeftOperand leftOperand() const {
221  return lhs_;
222  }
223  //**********************************************************************************************
224 
225  //**Right operand access************************************************************************
230  inline RightOperand rightOperand() const {
231  return rhs_;
232  }
233  //**********************************************************************************************
234 
235  //**********************************************************************************************
241  template< typename T >
242  inline bool canAlias( const T* alias ) const {
243  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
244  }
245  //**********************************************************************************************
246 
247  //**********************************************************************************************
253  template< typename T >
254  inline bool isAliased( const T* alias ) const {
255  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
256  }
257  //**********************************************************************************************
258 
259  private:
260  //**Member variables****************************************************************************
263  //**********************************************************************************************
264 
265  //**Default assignment to row-major dense matrices**********************************************
279  template< typename MT > // Type of the target dense matrix
280  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
282  {
284 
285  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
286  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
287 
288  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
289 
290  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
291  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
292 
293  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
294  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
295  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
296  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
297  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
298  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
299 
300  for( size_t i=0UL; i<A.rows(); ++i ) {
301  for( size_t j=0UL; j<B.columns(); ++j )
302  {
303  ConstIterator element( B.begin(j) );
304  const ConstIterator end( B.end(j) );
305 
306  if( element == end ) {
307  reset( (~lhs)(i,j) );
308  continue;
309  }
310 
311  (~lhs)(i,j) = A(i,element->index()) * element->value();
312  ++element;
313  for( ; element!=end; ++element )
314  (~lhs)(i,j) += A(i,element->index()) * element->value();
315  }
316  }
317  }
319  //**********************************************************************************************
320 
321  //**Default assignment to column-major dense matrices*******************************************
335  template< typename MT > // Type of the target dense matrix
336  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
338  {
340 
341  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
342  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
343 
344  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
345 
346  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
347  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
348 
349  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
350  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
351  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
352  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
353  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
354  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
355 
356  for( size_t j=0UL; j<B.columns(); ++j ) {
357  for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
358  reset( (~lhs)(i,j) );
359  }
360  ConstIterator element( B.begin(j) );
361  const ConstIterator end( B.end(j) );
362  for( ; element!=end; ++element ) {
363  for( size_t i=0UL; i<A.rows(); ++i ) {
364  if( isDefault( (~lhs)(element->index(),j) ) )
365  (~lhs)(i,j) = A(i,element->index()) * element->value();
366  else
367  (~lhs)(i,j) += A(i,element->index()) * element->value();
368  }
369  }
370  }
371  }
373  //**********************************************************************************************
374 
375  //**Optimized assignment to row-major dense matrices********************************************
389  template< typename MT > // Type of the target dense matrix
390  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
391  assign( DenseMatrix<MT,false>& lhs, const TDMatTSMatMultExpr& rhs )
392  {
394 
395  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
396  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
397 
398  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
399 
400  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
401  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
402 
403  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
404  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
405  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
406  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
407  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
408  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
409 
410  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
411  const size_t iend( A.rows() & size_t(-4) );
412 
413  for( size_t i=0UL; i<iend; i+=4UL ) {
414  for( size_t j=0UL; j<B.columns(); ++j )
415  {
416  ConstIterator element( B.begin(j) );
417  const ConstIterator end( B.end(j) );
418 
419  if( element == end ) {
420  reset( (~lhs)(i ,j) );
421  reset( (~lhs)(i+1UL,j) );
422  reset( (~lhs)(i+2UL,j) );
423  reset( (~lhs)(i+3UL,j) );
424  continue;
425  }
426 
427  (~lhs)(i ,j) = A(i ,element->index()) * element->value();
428  (~lhs)(i+1UL,j) = A(i+1UL,element->index()) * element->value();
429  (~lhs)(i+2UL,j) = A(i+2UL,element->index()) * element->value();
430  (~lhs)(i+3UL,j) = A(i+3UL,element->index()) * element->value();
431  ++element;
432  for( ; element!=end; ++element ) {
433  (~lhs)(i ,j) += A(i ,element->index()) * element->value();
434  (~lhs)(i+1UL,j) += A(i+1UL,element->index()) * element->value();
435  (~lhs)(i+2UL,j) += A(i+2UL,element->index()) * element->value();
436  (~lhs)(i+3UL,j) += A(i+3UL,element->index()) * element->value();
437  }
438  }
439  }
440 
441  for( size_t i=iend; i<A.rows(); ++i ) {
442  for( size_t j=0UL; j<B.columns(); ++j )
443  {
444  ConstIterator element( B.begin(j) );
445  const ConstIterator end( B.end(j) );
446 
447  if( element == end ) {
448  reset( (~lhs)(i,j) );
449  continue;
450  }
451 
452  (~lhs)(i,j) = A(i,element->index()) * element->value();
453  ++element;
454  for( ; element!=end; ++element )
455  (~lhs)(i,j) += A(i,element->index()) * element->value();
456  }
457  }
458  }
460  //**********************************************************************************************
461 
462  //**Optimized assignment to column-major dense matrices*****************************************
476  template< typename MT > // Type of the target dense matrix
477  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
478  assign( DenseMatrix<MT,true>& lhs, const TDMatTSMatMultExpr& rhs )
479  {
481 
482  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
483  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
484 
485  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
486 
487  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
488  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
489 
490  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
491  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
492  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
493  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
494  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
495  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
496 
497  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
498  const size_t iend( A.rows() & size_t(-4) );
499 
500  for( size_t j=0UL; j<B.columns(); ++j ) {
501  for( size_t i=0UL; i<iend; i+=4UL ) {
502  reset( (~lhs)(i ,j) );
503  reset( (~lhs)(i+1UL,j) );
504  reset( (~lhs)(i+2UL,j) );
505  reset( (~lhs)(i+3UL,j) );
506  }
507  for( size_t i=iend; i<(~lhs).rows(); ++i ) {
508  reset( (~lhs)(i,j) );
509  }
510  ConstIterator element( B.begin(j) );
511  const ConstIterator end( B.end(j) );
512 
513  while( element!=end )
514  {
515  const ET2 v1( element->value() );
516  const size_t i1( element->index() );
517  ++element;
518 
519  if( element != end ) {
520  const ET2 v2( element->value() );
521  const size_t i2( element->index() );
522  ++element;
523 
524  if( element != end ) {
525  const ET2 v3( element->value() );
526  const size_t i3( element->index() );
527  ++element;
528 
529  if( element != end ) {
530  const ET2 v4( element->value() );
531  const size_t i4( element->index() );
532  ++element;
533 
534  for( size_t i=0UL; i<iend; i+=4UL ) {
535  (~lhs)(i ,j) += A(i ,i1) * v1 + A(i ,i2) * v2 + A(i ,i3) * v3 + A(i ,i4) * v4;
536  (~lhs)(i+1UL,j) += A(i+1UL,i1) * v1 + A(i+1UL,i2) * v2 + A(i+1UL,i3) * v3 + A(i+1UL,i4) * v4;
537  (~lhs)(i+2UL,j) += A(i+2UL,i1) * v1 + A(i+2UL,i2) * v2 + A(i+2UL,i3) * v3 + A(i+2UL,i4) * v4;
538  (~lhs)(i+3UL,j) += A(i+3UL,i1) * v1 + A(i+3UL,i2) * v2 + A(i+3UL,i3) * v3 + A(i+3UL,i4) * v4;
539  }
540  for( size_t i=iend; i<A.rows(); ++i ) {
541  (~lhs)(i,j) += A(i,i1) * v1 + A(i,i2) * v2 + A(i,i3) * v3 + A(i,i4) * v4;
542  }
543  }
544  else {
545  for( size_t i=0UL; i<iend; i+=4UL ) {
546  (~lhs)(i ,j) += A(i ,i1) * v1 + A(i ,i2) * v2 + A(i ,i3) * v3;
547  (~lhs)(i+1UL,j) += A(i+1UL,i1) * v1 + A(i+1UL,i2) * v2 + A(i+1UL,i3) * v3;
548  (~lhs)(i+2UL,j) += A(i+2UL,i1) * v1 + A(i+2UL,i2) * v2 + A(i+2UL,i3) * v3;
549  (~lhs)(i+3UL,j) += A(i+3UL,i1) * v1 + A(i+3UL,i2) * v2 + A(i+3UL,i3) * v3;
550  }
551  for( size_t i=iend; i<A.rows(); ++i ) {
552  (~lhs)(i,j) += A(i,i1) * v1 + A(i,i2) * v2 + A(i,i3) * v3;
553  }
554  }
555  }
556  else {
557  for( size_t i=0UL; i<iend; i+=4UL ) {
558  (~lhs)(i ,j) += A(i ,i1) * v1 + A(i ,i2) * v2;
559  (~lhs)(i+1UL,j) += A(i+1UL,i1) * v1 + A(i+1UL,i2) * v2;
560  (~lhs)(i+2UL,j) += A(i+2UL,i1) * v1 + A(i+2UL,i2) * v2;
561  (~lhs)(i+3UL,j) += A(i+3UL,i1) * v1 + A(i+3UL,i2) * v2;
562  }
563  for( size_t i=iend; i<A.rows(); ++i ) {
564  (~lhs)(i,j) += A(i,i1) * v1 + A(i,i2) * v2;
565  }
566  }
567  }
568  else {
569  for( size_t i=0UL; i<iend; i+=4UL ) {
570  (~lhs)(i ,j) += A(i ,i1) * v1;
571  (~lhs)(i+1UL,j) += A(i+1UL,i1) * v1;
572  (~lhs)(i+2UL,j) += A(i+2UL,i1) * v1;
573  (~lhs)(i+3UL,j) += A(i+3UL,i1) * v1;
574  }
575  for( size_t i=iend; i<A.rows(); ++i ) {
576  (~lhs)(i,j) += A(i,i1) * v1;
577  }
578  }
579  }
580  }
581  }
583  //**********************************************************************************************
584 
585  //**Assignment to sparse matrices***************************************************************
597  template< typename MT // Type of the target sparse matrix
598  , bool SO > // Storage order of the target sparse matrix
599  friend inline void assign( SparseMatrix<MT,SO>& lhs, const TDMatTSMatMultExpr& rhs )
600  {
602 
603  typedef typename SelectType< SO, ResultType, OppositeType >::Type TmpType;
604 
610  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename TmpType::CompositeType );
611 
612  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
613  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
614 
615  const TmpType tmp( rhs );
616  assign( ~lhs, tmp );
617  }
619  //**********************************************************************************************
620 
621  //**Addition assignment to row-major dense matrices*********************************************
634  template< typename MT > // Type of the target dense matrix
635  friend inline void addAssign( DenseMatrix<MT,false>& lhs, const TDMatTSMatMultExpr& rhs )
636  {
638 
639  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
640  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
641 
642  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
643 
644  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
645  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
646 
647  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
648  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
649  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
650  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
651  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
652  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
653 
654  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
655  const size_t iend( A.rows() & size_t(-4) );
656 
657  for( size_t i=0UL; i<iend; i+=4UL ) {
658  for( size_t j=0UL; j<B.columns(); ++j )
659  {
660  ConstIterator element( B.begin(j) );
661  const ConstIterator end( B.end(j) );
662 
663  for( ; element!=end; ++element ) {
664  (~lhs)(i ,j) += A(i ,element->index()) * element->value();
665  (~lhs)(i+1UL,j) += A(i+1UL,element->index()) * element->value();
666  (~lhs)(i+2UL,j) += A(i+2UL,element->index()) * element->value();
667  (~lhs)(i+3UL,j) += A(i+3UL,element->index()) * element->value();
668  }
669  }
670  }
671 
672  for( size_t i=iend; i<A.rows(); ++i ) {
673  for( size_t j=0UL; j<B.columns(); ++j )
674  {
675  ConstIterator element( B.begin(j) );
676  const ConstIterator end( B.end(j) );
677 
678  for( ; element!=end; ++element )
679  (~lhs)(i,j) += A(i,element->index()) * element->value();
680  }
681  }
682  }
684  //**********************************************************************************************
685 
686  //**Addition assignment to column-major dense matrices******************************************
699  template< typename MT > // Type of the target dense matrix
700  friend inline void addAssign( DenseMatrix<MT,true>& lhs, const TDMatTSMatMultExpr& 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  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
720  const size_t iend( A.rows() & size_t(-4) );
721 
722  for( size_t j=0UL; j<B.columns(); ++j )
723  {
724  ConstIterator element( B.begin(j) );
725  const ConstIterator end( B.end(j) );
726 
727  while( element!=end )
728  {
729  const ET2 v1( element->value() );
730  const size_t i1( element->index() );
731  ++element;
732 
733  if( element != end ) {
734  const ET2 v2( element->value() );
735  const size_t i2( element->index() );
736  ++element;
737 
738  if( element != end ) {
739  const ET2 v3( element->value() );
740  const size_t i3( element->index() );
741  ++element;
742 
743  if( element != end ) {
744  const ET2 v4( element->value() );
745  const size_t i4( element->index() );
746  ++element;
747 
748  for( size_t i=0UL; i<iend; i+=4UL ) {
749  (~lhs)(i ,j) += A(i ,i1) * v1 + A(i ,i2) * v2 + A(i ,i3) * v3 + A(i ,i4) * v4;
750  (~lhs)(i+1UL,j) += A(i+1UL,i1) * v1 + A(i+1UL,i2) * v2 + A(i+1UL,i3) * v3 + A(i+1UL,i4) * v4;
751  (~lhs)(i+2UL,j) += A(i+2UL,i1) * v1 + A(i+2UL,i2) * v2 + A(i+2UL,i3) * v3 + A(i+2UL,i4) * v4;
752  (~lhs)(i+3UL,j) += A(i+3UL,i1) * v1 + A(i+3UL,i2) * v2 + A(i+3UL,i3) * v3 + A(i+3UL,i4) * v4;
753  }
754  for( size_t i=iend; i<A.rows(); ++i ) {
755  (~lhs)(i,j) += A(i,i1) * v1 + A(i,i2) * v2 + A(i,i3) * v3 + A(i,i4) * v4;
756  }
757  }
758  else {
759  for( size_t i=0UL; i<iend; i+=4UL ) {
760  (~lhs)(i ,j) += A(i ,i1) * v1 + A(i ,i2) * v2 + A(i ,i3) * v3;
761  (~lhs)(i+1UL,j) += A(i+1UL,i1) * v1 + A(i+1UL,i2) * v2 + A(i+1UL,i3) * v3;
762  (~lhs)(i+2UL,j) += A(i+2UL,i1) * v1 + A(i+2UL,i2) * v2 + A(i+2UL,i3) * v3;
763  (~lhs)(i+3UL,j) += A(i+3UL,i1) * v1 + A(i+3UL,i2) * v2 + A(i+3UL,i3) * v3;
764  }
765  for( size_t i=iend; i<A.rows(); ++i ) {
766  (~lhs)(i,j) += A(i,i1) * v1 + A(i,i2) * v2 + A(i,i3) * v3;
767  }
768  }
769  }
770  else {
771  for( size_t i=0UL; i<iend; i+=4UL ) {
772  (~lhs)(i ,j) += A(i ,i1) * v1 + A(i ,i2) * v2;
773  (~lhs)(i+1UL,j) += A(i+1UL,i1) * v1 + A(i+1UL,i2) * v2;
774  (~lhs)(i+2UL,j) += A(i+2UL,i1) * v1 + A(i+2UL,i2) * v2;
775  (~lhs)(i+3UL,j) += A(i+3UL,i1) * v1 + A(i+3UL,i2) * v2;
776  }
777  for( size_t i=iend; i<A.rows(); ++i ) {
778  (~lhs)(i,j) += A(i,i1) * v1 + A(i,i2) * v2;
779  }
780  }
781  }
782  else {
783  for( size_t i=0UL; i<iend; i+=4UL ) {
784  (~lhs)(i ,j) += A(i ,i1) * v1;
785  (~lhs)(i+1UL,j) += A(i+1UL,i1) * v1;
786  (~lhs)(i+2UL,j) += A(i+2UL,i1) * v1;
787  (~lhs)(i+3UL,j) += A(i+3UL,i1) * v1;
788  }
789  for( size_t i=iend; i<A.rows(); ++i ) {
790  (~lhs)(i,j) += A(i,i1) * v1;
791  }
792  }
793  }
794  }
795  }
797  //**********************************************************************************************
798 
799  //**Addition assignment to sparse matrices******************************************************
800  // No special implementation for the addition assignment to sparse matrices.
801  //**********************************************************************************************
802 
803  //**Subtraction assignment to row-major dense matrices******************************************
816  template< typename MT > // Type of the target dense matrix
817  friend inline void subAssign( DenseMatrix<MT,false>& lhs, const TDMatTSMatMultExpr& rhs )
818  {
820 
821  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
822  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
823 
824  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
825 
826  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
827  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
828 
829  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
830  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
831  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
832  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
833  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
834  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
835 
836  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
837  const size_t iend( A.rows() & size_t(-4) );
838 
839  for( size_t i=0UL; i<iend; i+=4 ) {
840  for( size_t j=0UL; j<B.columns(); ++j )
841  {
842  ConstIterator element( B.begin(j) );
843  const ConstIterator end( B.end(j) );
844 
845  for( ; element!=end; ++element ) {
846  (~lhs)(i ,j) -= A(i ,element->index()) * element->value();
847  (~lhs)(i+1UL,j) -= A(i+1UL,element->index()) * element->value();
848  (~lhs)(i+2UL,j) -= A(i+2UL,element->index()) * element->value();
849  (~lhs)(i+3UL,j) -= A(i+3UL,element->index()) * element->value();
850  }
851  }
852  }
853 
854  for( size_t i=iend; i<A.rows(); ++i ) {
855  for( size_t j=0UL; j<B.columns(); ++j )
856  {
857  ConstIterator element( B.begin(j) );
858  const ConstIterator end( B.end(j) );
859 
860  for( ; element!=end; ++element )
861  (~lhs)(i,j) -= A(i,element->index()) * element->value();
862  }
863  }
864  }
866  //**********************************************************************************************
867 
868  //**Subtraction assignment to column-major dense matrices***************************************
881  template< typename MT > // Type of the target dense matrix
882  friend inline void subAssign( DenseMatrix<MT,true>& lhs, const TDMatTSMatMultExpr& rhs )
883  {
885 
886  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
887  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
888 
889  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
890 
891  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
892  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
893 
894  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
895  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
896  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
897  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
898  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
899  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
900 
901  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
902  const size_t iend( A.rows() & size_t(-4) );
903 
904  for( size_t j=0UL; j<B.columns(); ++j )
905  {
906  ConstIterator element( B.begin(j) );
907  const ConstIterator end( B.end(j) );
908 
909  while( element!=end )
910  {
911  const ET2 v1( element->value() );
912  const size_t i1( element->index() );
913  ++element;
914 
915  if( element != end ) {
916  const ET2 v2( element->value() );
917  const size_t i2( element->index() );
918  ++element;
919 
920  if( element != end ) {
921  const ET2 v3( element->value() );
922  const size_t i3( element->index() );
923  ++element;
924 
925  if( element != end ) {
926  const ET2 v4( element->value() );
927  const size_t i4( element->index() );
928  ++element;
929 
930  for( size_t i=0UL; i<iend; i+=4UL ) {
931  (~lhs)(i ,j) -= A(i ,i1) * v1 + A(i ,i2) * v2 + A(i ,i3) * v3 + A(i ,i4) * v4;
932  (~lhs)(i+1UL,j) -= A(i+1UL,i1) * v1 + A(i+1UL,i2) * v2 + A(i+1UL,i3) * v3 + A(i+1UL,i4) * v4;
933  (~lhs)(i+2UL,j) -= A(i+2UL,i1) * v1 + A(i+2UL,i2) * v2 + A(i+2UL,i3) * v3 + A(i+2UL,i4) * v4;
934  (~lhs)(i+3UL,j) -= A(i+3UL,i1) * v1 + A(i+3UL,i2) * v2 + A(i+3UL,i3) * v3 + A(i+3UL,i4) * v4;
935  }
936  for( size_t i=iend; i<A.rows(); ++i ) {
937  (~lhs)(i,j) -= A(i,i1) * v1 + A(i,i2) * v2 + A(i,i3) * v3 + A(i,i4) * v4;
938  }
939  }
940  else {
941  for( size_t i=0UL; i<iend; i+=4UL ) {
942  (~lhs)(i ,j) -= A(i ,i1) * v1 + A(i ,i2) * v2 + A(i ,i3) * v3;
943  (~lhs)(i+1UL,j) -= A(i+1UL,i1) * v1 + A(i+1UL,i2) * v2 + A(i+1UL,i3) * v3;
944  (~lhs)(i+2UL,j) -= A(i+2UL,i1) * v1 + A(i+2UL,i2) * v2 + A(i+2UL,i3) * v3;
945  (~lhs)(i+3UL,j) -= A(i+3UL,i1) * v1 + A(i+3UL,i2) * v2 + A(i+3UL,i3) * v3;
946  }
947  for( size_t i=iend; i<A.rows(); ++i ) {
948  (~lhs)(i,j) -= A(i,i1) * v1 + A(i,i2) * v2 + A(i,i3) * v3;
949  }
950  }
951  }
952  else {
953  for( size_t i=0UL; i<iend; i+=4UL ) {
954  (~lhs)(i ,j) -= A(i ,i1) * v1 + A(i ,i2) * v2;
955  (~lhs)(i+1UL,j) -= A(i+1UL,i1) * v1 + A(i+1UL,i2) * v2;
956  (~lhs)(i+2UL,j) -= A(i+2UL,i1) * v1 + A(i+2UL,i2) * v2;
957  (~lhs)(i+3UL,j) -= A(i+3UL,i1) * v1 + A(i+3UL,i2) * v2;
958  }
959  for( size_t i=iend; i<A.rows(); ++i ) {
960  (~lhs)(i,j) -= A(i,i1) * v1 + A(i,i2) * v2;
961  }
962  }
963  }
964  else {
965  for( size_t i=0UL; i<iend; i+=4UL ) {
966  (~lhs)(i ,j) -= A(i ,i1) * v1;
967  (~lhs)(i+1UL,j) -= A(i+1UL,i1) * v1;
968  (~lhs)(i+2UL,j) -= A(i+2UL,i1) * v1;
969  (~lhs)(i+3UL,j) -= A(i+3UL,i1) * v1;
970  }
971  for( size_t i=iend; i<A.rows(); ++i ) {
972  (~lhs)(i,j) -= A(i,i1) * v1;
973  }
974  }
975  }
976  }
977  }
979  //**********************************************************************************************
980 
981  //**Subtraction assignment to sparse matrices***************************************************
982  // No special implementation for the subtraction assignment to sparse matrices.
983  //**********************************************************************************************
984 
985  //**Multiplication assignment to dense matrices*************************************************
986  // No special implementation for the multiplication assignment to dense matrices.
987  //**********************************************************************************************
988 
989  //**Multiplication assignment to sparse matrices************************************************
990  // No special implementation for the multiplication assignment to sparse matrices.
991  //**********************************************************************************************
992 
993  //**Compile time checks*************************************************************************
1000  //**********************************************************************************************
1001 };
1002 //*************************************************************************************************
1003 
1004 
1005 
1006 
1007 //=================================================================================================
1008 //
1009 // GLOBAL BINARY ARITHMETIC OPERATORS
1010 //
1011 //=================================================================================================
1012 
1013 //*************************************************************************************************
1042 template< typename T1 // Type of the left-hand side dense matrix
1043  , typename T2 > // Type of the right-hand side sparse matrix
1044 inline const TDMatTSMatMultExpr<T1,T2>
1046 {
1048 
1049  if( (~lhs).columns() != (~rhs).rows() )
1050  throw std::invalid_argument( "Matrix sizes do not match" );
1051 
1052  return TDMatTSMatMultExpr<T1,T2>( ~lhs, ~rhs );
1053 }
1054 //*************************************************************************************************
1055 
1056 
1057 
1058 
1059 //=================================================================================================
1060 //
1061 // GLOBAL OPERATORS
1062 //
1063 //=================================================================================================
1064 
1065 //*************************************************************************************************
1078 template< typename MT1 // Type of the left-hand side dense matrix
1079  , typename MT2 > // Type of the right-hand side sparse matrix
1080 inline typename RowExprTrait< TDMatTSMatMultExpr<MT1,MT2> >::Type
1081  row( const TDMatTSMatMultExpr<MT1,MT2>& dm, size_t index )
1082 {
1084 
1085  return row( dm.leftOperand(), index ) * dm.rightOperand();
1086 }
1088 //*************************************************************************************************
1089 
1090 
1091 //*************************************************************************************************
1104 template< typename MT1 // Type of the left-hand side dense matrix
1105  , typename MT2 > // Type of the right-hand side sparse matrix
1106 inline typename ColumnExprTrait< TDMatTSMatMultExpr<MT1,MT2> >::Type
1107  column( const TDMatTSMatMultExpr<MT1,MT2>& dm, size_t index )
1108 {
1110 
1111  return dm.leftOperand() * column( dm.rightOperand(), index );
1112 }
1114 //*************************************************************************************************
1115 
1116 
1117 
1118 
1119 //=================================================================================================
1120 //
1121 // EXPRESSION TRAIT SPECIALIZATIONS
1122 //
1123 //=================================================================================================
1124 
1125 //*************************************************************************************************
1127 template< typename MT1, typename MT2, typename VT >
1128 struct TDMatDVecMultExprTrait< TDMatTSMatMultExpr<MT1,MT2>, VT >
1129 {
1130  public:
1131  //**********************************************************************************************
1132  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1133  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
1134  IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
1135  , typename TDMatDVecMultExprTrait< MT1, typename TSMatDVecMultExprTrait<MT2,VT>::Type >::Type
1136  , INVALID_TYPE >::Type Type;
1137  //**********************************************************************************************
1138 };
1140 //*************************************************************************************************
1141 
1142 
1143 //*************************************************************************************************
1145 template< typename MT1, typename MT2, typename VT >
1146 struct TDMatSVecMultExprTrait< TDMatTSMatMultExpr<MT1,MT2>, VT >
1147 {
1148  public:
1149  //**********************************************************************************************
1150  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1151  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
1152  IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
1153  , typename TDMatDVecMultExprTrait< MT1, typename TSMatDVecMultExprTrait<MT2,VT>::Type >::Type
1154  , INVALID_TYPE >::Type Type;
1155  //**********************************************************************************************
1156 };
1158 //*************************************************************************************************
1159 
1160 
1161 //*************************************************************************************************
1163 template< typename VT, typename MT1, typename MT2 >
1164 struct TDVecTDMatMultExprTrait< VT, TDMatTSMatMultExpr<MT1,MT2> >
1165 {
1166  public:
1167  //**********************************************************************************************
1168  typedef typename SelectType< IsDenseVector<VT>::value && IsTransposeVector<VT>::value &&
1169  IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1170  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
1171  , typename TDVecTSMatMultExprTrait< typename TDVecTDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1172  , INVALID_TYPE >::Type Type;
1173  //**********************************************************************************************
1174 };
1176 //*************************************************************************************************
1177 
1178 
1179 //*************************************************************************************************
1181 template< typename VT, typename MT1, typename MT2 >
1182 struct TSVecTDMatMultExprTrait< VT, TDMatTSMatMultExpr<MT1,MT2> >
1183 {
1184  public:
1185  //**********************************************************************************************
1186  typedef typename SelectType< IsSparseVector<VT>::value && IsTransposeVector<VT>::value &&
1187  IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1188  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
1189  , typename TDVecTSMatMultExprTrait< typename TSVecTDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1190  , INVALID_TYPE >::Type Type;
1191  //**********************************************************************************************
1192 };
1194 //*************************************************************************************************
1195 
1196 
1197 //*************************************************************************************************
1199 template< typename MT1, typename MT2 >
1200 struct RowExprTrait< TDMatTSMatMultExpr<MT1,MT2> >
1201 {
1202  public:
1203  //**********************************************************************************************
1204  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
1205  //**********************************************************************************************
1206 };
1208 //*************************************************************************************************
1209 
1210 
1211 //*************************************************************************************************
1213 template< typename MT1, typename MT2 >
1214 struct ColumnExprTrait< TDMatTSMatMultExpr<MT1,MT2> >
1215 {
1216  public:
1217  //**********************************************************************************************
1218  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
1219  //**********************************************************************************************
1220 };
1222 //*************************************************************************************************
1223 
1224 } // namespace blaze
1225 
1226 #endif