All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TDMatSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_TDMATSMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_TDMATSMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <stdexcept>
52 #include <blaze/math/shims/Reset.h>
76 #include <blaze/util/Assert.h>
78 #include <blaze/util/DisableIf.h>
79 #include <blaze/util/EnableIf.h>
80 #include <blaze/util/InvalidType.h>
82 #include <blaze/util/SelectType.h>
83 #include <blaze/util/Types.h>
85 
86 
87 namespace blaze {
88 
89 //=================================================================================================
90 //
91 // CLASS TDMATSMATMULTEXPR
92 //
93 //=================================================================================================
94 
95 //*************************************************************************************************
102 template< typename MT1 // Type of the left-hand side dense matrix
103  , typename MT2 > // Type of the right-hand side sparse matrix
104 class TDMatSMatMultExpr : public DenseMatrix< TDMatSMatMultExpr<MT1,MT2>, true >
105  , private MatMatMultExpr
106  , private Computation
107 {
108  private:
109  //**Type definitions****************************************************************************
110  typedef typename MT1::ResultType RT1;
111  typedef typename MT2::ResultType RT2;
112  typedef typename MT1::ElementType ET1;
113  typedef typename MT2::ElementType ET2;
114  typedef typename MT1::CompositeType CT1;
115  typedef typename MT2::CompositeType CT2;
116  //**********************************************************************************************
117 
118  public:
119  //**Type definitions****************************************************************************
125  typedef const ElementType ReturnType;
126  typedef const ResultType CompositeType;
127 
129  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
130 
132  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
133 
135  typedef typename SelectType< IsComputation<MT1>::value, const RT1, CT1 >::Type LT;
136 
138  typedef typename SelectType< IsComputation<MT2>::value, const RT2, CT2 >::Type RT;
139  //**********************************************************************************************
140 
141  //**Compilation flags***************************************************************************
143  enum { vectorizable = 0 };
144  //**********************************************************************************************
145 
146  //**Constructor*********************************************************************************
152  explicit inline TDMatSMatMultExpr( const MT1& lhs, const MT2& rhs )
153  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
154  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
155  {
156  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
157  }
158  //**********************************************************************************************
159 
160  //**Access operator*****************************************************************************
167  inline ReturnType operator()( size_t i, size_t j ) const {
168  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
169  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
170 
171  ElementType tmp;
172 
173  if( lhs_.columns() != 0 ) {
174  tmp = lhs_(i,0) * rhs_(0,j);
175  for( size_t k=1; k<lhs_.columns(); ++k ) {
176  tmp += lhs_(i,k) * rhs_(k,j);
177  }
178  }
179  else {
180  reset( tmp );
181  }
182 
183  return tmp;
184  }
185  //**********************************************************************************************
186 
187  //**Rows function*******************************************************************************
192  inline size_t rows() const {
193  return lhs_.rows();
194  }
195  //**********************************************************************************************
196 
197  //**Columns function****************************************************************************
202  inline size_t columns() const {
203  return rhs_.columns();
204  }
205  //**********************************************************************************************
206 
207  //**Left operand access*************************************************************************
212  inline LeftOperand leftOperand() const {
213  return lhs_;
214  }
215  //**********************************************************************************************
216 
217  //**Right operand access************************************************************************
222  inline RightOperand rightOperand() const {
223  return rhs_;
224  }
225  //**********************************************************************************************
226 
227  //**********************************************************************************************
233  template< typename T >
234  inline bool canAlias( const T* alias ) const {
235  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
236  }
237  //**********************************************************************************************
238 
239  //**********************************************************************************************
245  template< typename T >
246  inline bool isAliased( const T* alias ) const {
247  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
248  }
249  //**********************************************************************************************
250 
251  private:
252  //**Member variables****************************************************************************
255  //**********************************************************************************************
256 
257  //**Default assignment to row-major dense matrices**********************************************
271  template< typename MT > // Type of the target dense matrix
272  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
274  {
276 
277  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
278  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
279 
281 
282  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
283  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
284 
285  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
286  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
287  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
288  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
289  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
290  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
291 
292  for( size_t i=0; i<A.rows(); ++i ) {
293  for( size_t j=0; j<(~lhs).columns(); ++j ) {
294  reset( (~lhs)(i,j) );
295  }
296  for( size_t j=0; j<B.rows(); ++j ) {
297  ConstIterator element( B.begin(j) );
298  const ConstIterator end( B.end(j) );
299  for( ; element!=end; ++element ) {
300  if( isDefault( (~lhs)(i,element->index()) ) )
301  (~lhs)(i,element->index()) = A(i,j) * element->value();
302  else
303  (~lhs)(i,element->index()) += A(i,j) * element->value();
304  }
305  }
306  }
307  }
309  //**********************************************************************************************
310 
311  //**Default assignment to column-major dense matrices*******************************************
325  template< typename MT > // Type of the target dense matrix
326  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
327  assign( DenseMatrix<MT,true>& lhs, const TDMatSMatMultExpr& rhs )
328  {
330 
331  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
332  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
333 
335 
336  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
337  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
338 
339  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
340  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
341  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
342  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
343  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
344  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
345 
346  reset( ~lhs );
347 
348  for( size_t i=0; i<B.rows(); ++i ) {
349  ConstIterator element( B.begin(i) );
350  const ConstIterator end( B.end(i) );
351  for( ; element!=end; ++element ) {
352  for( size_t j=0; j<A.rows(); ++j ) {
353  if( isDefault( (~lhs)(j,element->index()) ) )
354  (~lhs)(j,element->index()) = A(j,i) * element->value();
355  else
356  (~lhs)(j,element->index()) += A(j,i) * element->value();
357  }
358  }
359  }
360  }
362  //**********************************************************************************************
363 
364  //**Optimized assignment to row-major dense matrices********************************************
378  template< typename MT > // Type of the target dense matrix
379  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
380  assign( DenseMatrix<MT,false>& lhs, const TDMatSMatMultExpr& rhs )
381  {
383 
384  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
385  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
386 
388 
389  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
390  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
391 
392  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
393  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
394  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
395  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
396  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
397  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
398 
399  const size_t last( A.rows() & size_t(-4) );
400 
401  for( size_t i=0; i<last; i+=4 ) {
402  for( size_t j=0; j<(~lhs).columns(); ++j ) {
403  reset( (~lhs)(i ,j) );
404  reset( (~lhs)(i+1,j) );
405  reset( (~lhs)(i+2,j) );
406  reset( (~lhs)(i+3,j) );
407  }
408  for( size_t j=0; j<B.rows(); ++j ) {
409  ConstIterator element( B.begin(j) );
410  const ConstIterator end( B.end(j) );
411  for( ; element!=end; ++element ) {
412  (~lhs)(i ,element->index()) += A(i ,j) * element->value();
413  (~lhs)(i+1,element->index()) += A(i+1,j) * element->value();
414  (~lhs)(i+2,element->index()) += A(i+2,j) * element->value();
415  (~lhs)(i+3,element->index()) += A(i+3,j) * element->value();
416  }
417  }
418  }
419 
420  for( size_t i=last; i<A.rows(); ++i ) {
421  for( size_t j=0; j<(~lhs).columns(); ++j ) {
422  reset( (~lhs)(i,j) );
423  }
424  for( size_t j=0; j<B.rows(); ++j ) {
425  ConstIterator element( B.begin(j) );
426  const ConstIterator end( B.end(j) );
427  for( ; element!=end; ++element ) {
428  (~lhs)(i,element->index()) += A(i,j) * element->value();
429  }
430  }
431  }
432  }
434  //**********************************************************************************************
435 
436  //**Optimized assignment to column-major dense matrices*****************************************
450  template< typename MT > // Type of the target dense matrix
451  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
452  assign( DenseMatrix<MT,true>& lhs, const TDMatSMatMultExpr& rhs )
453  {
455 
456  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
457  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
458 
460 
461  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
462  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
463 
464  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
465  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
466  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
467  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
468  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
469  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
470 
471  reset( ~lhs );
472 
473  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
474  const size_t jend( A.rows() & size_t(-4) );
475  size_t j( 0UL );
476 
477  for( size_t i=0UL; i<B.rows(); ++i ) {
478  ConstIterator element( B.begin(i) );
479  const ConstIterator end( B.end(i) );
480 
481  const size_t nonzeros( B.nonZeros(i) );
482  const size_t kend( nonzeros & size_t(-4) );
483 
484  for( size_t k=0UL; k<kend; k+=4UL )
485  {
486  const size_t i1( element->index() );
487  const ET2 v1( element->value() );
488  ++element;
489  const size_t i2( element->index() );
490  const ET2 v2( element->value() );
491  ++element;
492  const size_t i3( element->index() );
493  const ET2 v3( element->value() );
494  ++element;
495  const size_t i4( element->index() );
496  const ET2 v4( element->value() );
497  ++element;
498 
499  for( j=0UL; j<jend; j+=4UL ) {
500  (~lhs)(j ,i1) += A(j ,i) * v1;
501  (~lhs)(j+1UL,i1) += A(j+1UL,i) * v1;
502  (~lhs)(j+2UL,i1) += A(j+2UL,i) * v1;
503  (~lhs)(j+3UL,i1) += A(j+3UL,i) * v1;
504  (~lhs)(j ,i2) += A(j ,i) * v2;
505  (~lhs)(j+1UL,i2) += A(j+1UL,i) * v2;
506  (~lhs)(j+2UL,i2) += A(j+2UL,i) * v2;
507  (~lhs)(j+3UL,i2) += A(j+3UL,i) * v2;
508  (~lhs)(j ,i3) += A(j ,i) * v3;
509  (~lhs)(j+1UL,i3) += A(j+1UL,i) * v3;
510  (~lhs)(j+2UL,i3) += A(j+2UL,i) * v3;
511  (~lhs)(j+3UL,i3) += A(j+3UL,i) * v3;
512  (~lhs)(j ,i4) += A(j ,i) * v4;
513  (~lhs)(j+1UL,i4) += A(j+1UL,i) * v4;
514  (~lhs)(j+2UL,i4) += A(j+2UL,i) * v4;
515  (~lhs)(j+3UL,i4) += A(j+3UL,i) * v4;
516  }
517  for( ; j<A.rows(); ++j ) {
518  (~lhs)(j,i1) += A(j,i) * v1;
519  (~lhs)(j,i2) += A(j,i) * v2;
520  (~lhs)(j,i3) += A(j,i) * v3;
521  (~lhs)(j,i4) += A(j,i) * v4;
522  }
523  }
524 
525  for( ; element!=end; ++element ) {
526  for( j=0UL; j<jend; j+=4UL ) {
527  (~lhs)(j ,element->index()) += A(j ,i) * element->value();
528  (~lhs)(j+1UL,element->index()) += A(j+1UL,i) * element->value();
529  (~lhs)(j+2UL,element->index()) += A(j+2UL,i) * element->value();
530  (~lhs)(j+3UL,element->index()) += A(j+3UL,i) * element->value();
531  }
532  for( ; j<A.rows(); ++j ) {
533  (~lhs)(j,element->index()) += A(j,i) * element->value();
534  }
535  }
536  }
537  }
539  //**********************************************************************************************
540 
541  //**Assignment to sparse matrices***************************************************************
553  template< typename MT // Type of the target sparse matrix
554  , bool SO > // Storage order of the target sparse matrix
555  friend inline void assign( SparseMatrix<MT,SO>& lhs, const TDMatSMatMultExpr& rhs )
556  {
558 
559  typedef typename SelectType< SO, ResultType, OppositeType >::Type TmpType;
560 
567 
568  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
569  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
570 
571  const TmpType tmp( rhs );
572  assign( ~lhs, tmp );
573  }
575  //**********************************************************************************************
576 
577  //**Addition assignment to row-major dense matrices*********************************************
590  template< typename MT > // Type of the target dense matrix
591  friend inline void addAssign( DenseMatrix<MT,false>& lhs, const TDMatSMatMultExpr& rhs )
592  {
594 
595  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
596  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
597 
599 
600  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
601  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
602 
603  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
604  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
605  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
606  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
607  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
608  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
609 
610  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
611  const size_t last( A.rows() & size_t(-4) );
612 
613  for( size_t i=0UL; i<last; i+=4UL ) {
614  for( size_t j=0UL; j<B.rows(); ++j ) {
615  ConstIterator element( B.begin(j) );
616  const ConstIterator end( B.end(j) );
617  for( ; element!=end; ++element ) {
618  (~lhs)(i ,element->index()) += A(i ,j) * element->value();
619  (~lhs)(i+1UL,element->index()) += A(i+1UL,j) * element->value();
620  (~lhs)(i+2UL,element->index()) += A(i+2UL,j) * element->value();
621  (~lhs)(i+3UL,element->index()) += A(i+3UL,j) * element->value();
622  }
623  }
624  }
625 
626  for( size_t i=last; i<A.rows(); ++i ) {
627  for( size_t j=0UL; j<B.rows(); ++j ) {
628  ConstIterator element( B.begin(j) );
629  const ConstIterator end( B.end(j) );
630  for( ; element!=end; ++element ) {
631  (~lhs)(i,element->index()) += A(i,j) * element->value();
632  }
633  }
634  }
635  }
637  //**********************************************************************************************
638 
639  //**Addition assignment to column-major dense matrices******************************************
652  template< typename MT > // Type of the target dense matrix
653  friend inline void addAssign( DenseMatrix<MT,true>& lhs, const TDMatSMatMultExpr& rhs )
654  {
656 
657  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
658  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
659 
661 
662  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
663  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
664 
665  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
666  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
667  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
668  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
669  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
670  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
671 
672  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
673  const size_t jend( A.rows() & size_t(-4) );
674  size_t j( 0UL );
675 
676  for( size_t i=0UL; i<B.rows(); ++i ) {
677  ConstIterator element( B.begin(i) );
678  const ConstIterator end( B.end(i) );
679 
680  const size_t nonzeros( B.nonZeros(i) );
681  const size_t kend( nonzeros & size_t(-4) );
682 
683  for( size_t k=0UL; k<kend; k+=4UL )
684  {
685  const size_t i1( element->index() );
686  const ET2 v1( element->value() );
687  ++element;
688  const size_t i2( element->index() );
689  const ET2 v2( element->value() );
690  ++element;
691  const size_t i3( element->index() );
692  const ET2 v3( element->value() );
693  ++element;
694  const size_t i4( element->index() );
695  const ET2 v4( element->value() );
696  ++element;
697 
698  for( j=0UL; j<jend; j+=4UL ) {
699  (~lhs)(j ,i1) += A(j ,i) * v1;
700  (~lhs)(j+1UL,i1) += A(j+1UL,i) * v1;
701  (~lhs)(j+2UL,i1) += A(j+2UL,i) * v1;
702  (~lhs)(j+3UL,i1) += A(j+3UL,i) * v1;
703  (~lhs)(j ,i2) += A(j ,i) * v2;
704  (~lhs)(j+1UL,i2) += A(j+1UL,i) * v2;
705  (~lhs)(j+2UL,i2) += A(j+2UL,i) * v2;
706  (~lhs)(j+3UL,i2) += A(j+3UL,i) * v2;
707  (~lhs)(j ,i3) += A(j ,i) * v3;
708  (~lhs)(j+1UL,i3) += A(j+1UL,i) * v3;
709  (~lhs)(j+2UL,i3) += A(j+2UL,i) * v3;
710  (~lhs)(j+3UL,i3) += A(j+3UL,i) * v3;
711  (~lhs)(j ,i4) += A(j ,i) * v4;
712  (~lhs)(j+1UL,i4) += A(j+1UL,i) * v4;
713  (~lhs)(j+2UL,i4) += A(j+2UL,i) * v4;
714  (~lhs)(j+3UL,i4) += A(j+3UL,i) * v4;
715  }
716  for( ; j<A.rows(); ++j ) {
717  (~lhs)(j,i1) += A(j,i) * v1;
718  (~lhs)(j,i2) += A(j,i) * v2;
719  (~lhs)(j,i3) += A(j,i) * v3;
720  (~lhs)(j,i4) += A(j,i) * v4;
721  }
722  }
723 
724  for( ; element!=end; ++element ) {
725  for( j=0UL; j<jend; j+=4UL ) {
726  (~lhs)(j ,element->index()) += A(j ,i) * element->value();
727  (~lhs)(j+1UL,element->index()) += A(j+1UL,i) * element->value();
728  (~lhs)(j+2UL,element->index()) += A(j+2UL,i) * element->value();
729  (~lhs)(j+3UL,element->index()) += A(j+3UL,i) * element->value();
730  }
731  for( ; j<A.rows(); ++j ) {
732  (~lhs)(j,element->index()) += A(j,i) * element->value();
733  }
734  }
735  }
736  }
738  //**********************************************************************************************
739 
740  //**Addition assignment to sparse matrices******************************************************
741  // No special implementation for the addition assignment to sparse matrices.
742  //**********************************************************************************************
743 
744  //**Subtraction assignment to row-major dense matrices******************************************
757  template< typename MT > // Type of the target dense matrix
758  friend inline void subAssign( DenseMatrix<MT,false>& lhs, const TDMatSMatMultExpr& rhs )
759  {
761 
762  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
763  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
764 
766 
767  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
768  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
769 
770  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
771  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
772  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
773  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
774  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
775  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
776 
777  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
778  const size_t last( A.rows() & size_t(-4) );
779 
780  for( size_t i=0UL; i<last; i+=4UL ) {
781  for( size_t j=0UL; j<B.rows(); ++j ) {
782  ConstIterator element( B.begin(j) );
783  const ConstIterator end( B.end(j) );
784  for( ; element!=end; ++element ) {
785  (~lhs)(i ,element->index()) -= A(i ,j) * element->value();
786  (~lhs)(i+1UL,element->index()) -= A(i+1UL,j) * element->value();
787  (~lhs)(i+2UL,element->index()) -= A(i+2UL,j) * element->value();
788  (~lhs)(i+3UL,element->index()) -= A(i+3UL,j) * element->value();
789  }
790  }
791  }
792 
793  for( size_t i=last; i<A.rows(); ++i ) {
794  for( size_t j=0UL; j<B.rows(); ++j ) {
795  ConstIterator element( B.begin(j) );
796  const ConstIterator end( B.end(j) );
797  for( ; element!=end; ++element ) {
798  (~lhs)(i,element->index()) -= A(i,j) * element->value();
799  }
800  }
801  }
802  }
804  //**********************************************************************************************
805 
806  //**Subtraction assignment to column-major dense matrices***************************************
819  template< typename MT > // Type of the target dense matrix
820  friend inline void subAssign( DenseMatrix<MT,true>& lhs, const TDMatSMatMultExpr& rhs )
821  {
823 
824  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
825  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
826 
828 
829  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
830  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
831 
832  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
833  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
834  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
835  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
836  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
837  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
838 
839  BLAZE_INTERNAL_ASSERT( ( A.rows() - ( A.rows() % 4UL ) ) == ( A.rows() & size_t(-4) ), "Invalid end calculation" );
840  const size_t jend( A.rows() & size_t(-4) );
841  size_t j( 0UL );
842 
843  for( size_t i=0UL; i<B.rows(); ++i ) {
844  ConstIterator element( B.begin(i) );
845  const ConstIterator end( B.end(i) );
846 
847  const size_t nonzeros( B.nonZeros(i) );
848  const size_t kend( nonzeros & size_t(-4) );
849 
850  for( size_t k=0UL; k<kend; k+=4UL )
851  {
852  const size_t i1( element->index() );
853  const ET2 v1( element->value() );
854  ++element;
855  const size_t i2( element->index() );
856  const ET2 v2( element->value() );
857  ++element;
858  const size_t i3( element->index() );
859  const ET2 v3( element->value() );
860  ++element;
861  const size_t i4( element->index() );
862  const ET2 v4( element->value() );
863  ++element;
864 
865  for( j=0UL; j<jend; j+=4UL ) {
866  (~lhs)(j ,i1) -= A(j ,i) * v1;
867  (~lhs)(j+1UL,i1) -= A(j+1UL,i) * v1;
868  (~lhs)(j+2UL,i1) -= A(j+2UL,i) * v1;
869  (~lhs)(j+3UL,i1) -= A(j+3UL,i) * v1;
870  (~lhs)(j ,i2) -= A(j ,i) * v2;
871  (~lhs)(j+1UL,i2) -= A(j+1UL,i) * v2;
872  (~lhs)(j+2UL,i2) -= A(j+2UL,i) * v2;
873  (~lhs)(j+3UL,i2) -= A(j+3UL,i) * v2;
874  (~lhs)(j ,i3) -= A(j ,i) * v3;
875  (~lhs)(j+1UL,i3) -= A(j+1UL,i) * v3;
876  (~lhs)(j+2UL,i3) -= A(j+2UL,i) * v3;
877  (~lhs)(j+3UL,i3) -= A(j+3UL,i) * v3;
878  (~lhs)(j ,i4) -= A(j ,i) * v4;
879  (~lhs)(j+1UL,i4) -= A(j+1UL,i) * v4;
880  (~lhs)(j+2UL,i4) -= A(j+2UL,i) * v4;
881  (~lhs)(j+3UL,i4) -= A(j+3UL,i) * v4;
882  }
883  for( ; j<A.rows(); ++j ) {
884  (~lhs)(j,i1) -= A(j,i) * v1;
885  (~lhs)(j,i2) -= A(j,i) * v2;
886  (~lhs)(j,i3) -= A(j,i) * v3;
887  (~lhs)(j,i4) -= A(j,i) * v4;
888  }
889  }
890 
891  for( ; element!=end; ++element ) {
892  for( j=0UL; j<jend; j+=4UL ) {
893  (~lhs)(j ,element->index()) -= A(j ,i) * element->value();
894  (~lhs)(j+1UL,element->index()) -= A(j+1UL,i) * element->value();
895  (~lhs)(j+2UL,element->index()) -= A(j+2UL,i) * element->value();
896  (~lhs)(j+3UL,element->index()) -= A(j+3UL,i) * element->value();
897  }
898  for( ; j<A.rows(); ++j ) {
899  (~lhs)(j,element->index()) -= A(j,i) * element->value();
900  }
901  }
902  }
903  }
905  //**********************************************************************************************
906 
907  //**Subtraction assignment to sparse matrices***************************************************
908  // No special implementation for the subtraction assignment to sparse matrices.
909  //**********************************************************************************************
910 
911  //**Multiplication assignment to dense matrices*************************************************
912  // No special implementation for the multiplication assignment to dense matrices.
913  //**********************************************************************************************
914 
915  //**Multiplication assignment to sparse matrices************************************************
916  // No special implementation for the multiplication assignment to sparse matrices.
917  //**********************************************************************************************
918 
919  //**Compile time checks*************************************************************************
926  //**********************************************************************************************
927 };
928 //*************************************************************************************************
929 
930 
931 
932 
933 //=================================================================================================
934 //
935 // GLOBAL BINARY ARITHMETIC OPERATORS
936 //
937 //=================================================================================================
938 
939 //*************************************************************************************************
969 template< typename T1 // Type of the left-hand side dense matrix
970  , typename T2 > // Type of the right-hand side sparse matrix
971 inline const TDMatSMatMultExpr<T1,T2>
973 {
975 
976  if( (~lhs).columns() != (~rhs).rows() )
977  throw std::invalid_argument( "Matrix sizes do not match" );
978 
979  return TDMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
980 }
981 //*************************************************************************************************
982 
983 
984 
985 
986 //=================================================================================================
987 //
988 // EXPRESSION TRAIT SPECIALIZATIONS
989 //
990 //=================================================================================================
991 
992 //*************************************************************************************************
994 template< typename MT1, typename MT2, typename VT >
995 struct TDMatDVecMultExprTrait< TDMatSMatMultExpr<MT1,MT2>, VT >
996 {
997  public:
998  //**********************************************************************************************
999  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1000  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1001  IsDenseVector<VT>::value && IsColumnVector<VT>::value
1002  , typename TDMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
1003  , INVALID_TYPE >::Type Type;
1004  //**********************************************************************************************
1005 };
1007 //*************************************************************************************************
1008 
1009 
1010 //*************************************************************************************************
1012 template< typename MT1, typename MT2, typename VT >
1013 struct TDMatSVecMultExprTrait< TDMatSMatMultExpr<MT1,MT2>, VT >
1014 {
1015  public:
1016  //**********************************************************************************************
1017  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1018  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1019  IsSparseVector<VT>::value && IsColumnVector<VT>::value
1020  , typename TDMatSVecMultExprTrait< MT1, typename SMatSVecMultExprTrait<MT2,VT>::Type >::Type
1021  , INVALID_TYPE >::Type Type;
1022  //**********************************************************************************************
1023 };
1025 //*************************************************************************************************
1026 
1027 
1028 //*************************************************************************************************
1030 template< typename VT, typename MT1, typename MT2 >
1031 struct TDVecTDMatMultExprTrait< VT, TDMatSMatMultExpr<MT1,MT2> >
1032 {
1033  public:
1034  //**********************************************************************************************
1035  typedef typename SelectType< IsDenseVector<VT>::value && IsRowVector<VT>::value &&
1036  IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1037  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1038  , typename TDMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
1039  , INVALID_TYPE >::Type Type;
1040  //**********************************************************************************************
1041 };
1043 //*************************************************************************************************
1044 
1045 
1046 //*************************************************************************************************
1048 template< typename VT, typename MT1, typename MT2 >
1049 struct TSVecTDMatMultExprTrait< VT, TDMatSMatMultExpr<MT1,MT2> >
1050 {
1051  public:
1052  //**********************************************************************************************
1053  typedef typename SelectType< IsSparseVector<VT>::value && IsRowVector<VT>::value &&
1054  IsDenseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1055  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1056  , typename TDVecSMatMultExprTrait< typename TSVecTDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1057  , INVALID_TYPE >::Type Type;
1058  //**********************************************************************************************
1059 };
1061 //*************************************************************************************************
1062 
1063 
1064 //*************************************************************************************************
1066 template< typename MT1, typename MT2 >
1067 struct SubmatrixExprTrait< TDMatSMatMultExpr<MT1,MT2> >
1068 {
1069  public:
1070  //**********************************************************************************************
1071  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT1>::Type
1072  , typename SubmatrixExprTrait<const MT2>::Type >::Type Type;
1073  //**********************************************************************************************
1074 };
1076 //*************************************************************************************************
1077 
1078 
1079 //*************************************************************************************************
1081 template< typename MT1, typename MT2 >
1082 struct RowExprTrait< TDMatSMatMultExpr<MT1,MT2> >
1083 {
1084  public:
1085  //**********************************************************************************************
1086  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
1087  //**********************************************************************************************
1088 };
1090 //*************************************************************************************************
1091 
1092 
1093 //*************************************************************************************************
1095 template< typename MT1, typename MT2 >
1096 struct ColumnExprTrait< TDMatSMatMultExpr<MT1,MT2> >
1097 {
1098  public:
1099  //**********************************************************************************************
1100  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
1101  //**********************************************************************************************
1102 };
1104 //*************************************************************************************************
1105 
1106 } // namespace blaze
1107 
1108 #endif
size_t columns() const
Returns the current number of columns of the matrix.
Definition: TDMatSMatMultExpr.h:202
Header file for the SMatDVecMultExprTrait class template.
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: TDMatSMatMultExpr.h:123
void reset(DynamicMatrix< Type, SO > &m)
Resetting the given dense matrix.
Definition: DynamicMatrix.h:4512
const DMatDMatMultExpr< T1, T2 > operator*(const DenseMatrix< T1, false > &lhs, const DenseMatrix< T2, false > &rhs)
Multiplication operator for the multiplication of two row-major dense matrices ( ).
Definition: DMatDMatMultExpr.h:3703
Header file for the IsSparseMatrix type trait.
bool isDefault(const DynamicMatrix< Type, SO > &m)
Returns whether the given dense matrix is in default state.
Definition: DynamicMatrix.h:4555
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:196
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional matrix type...
Definition: DenseMatrix.h:79
Header file for the ColumnExprTrait class template.
TDMatSMatMultExpr(const MT1 &lhs, const MT2 &rhs)
Constructor for the TDMatSMatMultExpr class.
Definition: TDMatSMatMultExpr.h:152
Header file for the IsColumnMajorMatrix type trait.
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2375
Header file for the IsRowVector type trait.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:248
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TDMatSMatMultExpr.h:125
Header file for the TDVecSMatMultExprTrait class template.
Header file for the Computation base class.
Header file for the MatMatMultExpr base class.
Expression object for transpose dense matrix-sparse matrix multiplications.The TDMatSMatMultExpr clas...
Definition: Forward.h:124
size_t rows() const
Returns the current number of rows of the matrix.
Definition: TDMatSMatMultExpr.h:192
TDMatSMatMultExpr< MT1, MT2 > This
Type of this TDMatSMatMultExpr instance.
Definition: TDMatSMatMultExpr.h:120
ResultType::ElementType ElementType
Resulting element type.
Definition: TDMatSMatMultExpr.h:124
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:70
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes...
Definition: Forward.h:104
Constraint on the data type.
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: TDMatSMatMultExpr.h:234
Constraint on the data type.
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: TDMatSMatMultExpr.h:246
Constraint on the data type.
Header file for the MultExprTrait class template.
Compile time type selection.The SelectType class template selects one of the two given types T1 and T...
Definition: SelectType.h:59
Header file for the DisableIf class template.
Header file for the multiplication trait.
MultTrait< RT1, RT2 >::Type ResultType
Result type for expression template evaluations.
Definition: TDMatSMatMultExpr.h:121
#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a column-major dense or sparse matri...
Definition: StorageOrder.h:161
Header file for the TSVecTDMatMultExprTrait class template.
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2379
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: TDMatSMatMultExpr.h:254
SelectType< IsExpression< MT2 >::value, const MT2, const MT2 & >::Type RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: TDMatSMatMultExpr.h:132
Header file for the TDMatSVecMultExprTrait class template.
Header file for the DenseMatrix base class.
void assign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the assignment of a matrix to a matrix.
Definition: Matrix.h:179
SelectType< IsExpression< MT1 >::value, const MT1, const MT1 & >::Type LeftOperand
Composite type of the left-hand side dense matrix expression.
Definition: TDMatSMatMultExpr.h:129
Header file for the SMatSVecMultExprTrait class template.
#define BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE(T)
Constraint on the data type.In case the given data type T is not a reference type, a compilation error is created.
Definition: Reference.h:78
LeftOperand leftOperand() const
Returns the left-hand side transpose dense matrix operand.
Definition: TDMatSMatMultExpr.h:212
Constraints on the storage order of matrix types.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:2373
Header file for the SelectType class template.
Header file for the RowExprTrait class template.
Header file for all forward declarations for expression class templates.
Header file for the IsDenseMatrix type trait.
Header file for the EnableIf class template.
ResultType::OppositeType OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: TDMatSMatMultExpr.h:122
MT1::ElementType ET1
Element type of the left-hand side dense matrix expression.
Definition: TDMatSMatMultExpr.h:112
Header file for the IsSparseVector type trait.
Header file for the SubmatrixExprTrait class template.
#define BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a row-major dense or sparse matrix t...
Definition: StorageOrder.h:81
Removal of reference modifiers.The RemoveCV type trait removes any reference modifiers from the given...
Definition: RemoveReference.h:69
Header file for run time assertion macros.
Utility type for generic codes.
Base template for the MultTrait class.
Definition: MultTrait.h:141
SelectType< IsComputation< MT2 >::value, const RT2, CT2 >::Type RT
Type for the assignment of the right-hand side dense matrix operand.
Definition: TDMatSMatMultExpr.h:138
void addAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the addition assignment of a matrix to a matrix.
Definition: Matrix.h:209
Substitution Failure Is Not An Error (SFINAE) class.The EnableIf class template is an auxiliary tool ...
Definition: EnableIf.h:184
Header file for the reset shim.
void subAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the subtraction assignment of a matrix to matrix.
Definition: Matrix.h:239
MT2::ElementType ET2
Element type of the right-hand side sparse matrix expression.
Definition: TDMatSMatMultExpr.h:113
Header file for the isDefault shim.
SelectType< IsComputation< MT1 >::value, const RT1, CT1 >::Type LT
Type for the assignment of the left-hand side dense matrix operand.
Definition: TDMatSMatMultExpr.h:135
Header file for the RemoveReference type trait.
#define BLAZE_CONSTRAINT_MATRICES_MUST_HAVE_SAME_STORAGE_ORDER(T1, T2)
Constraint on the data type.In case either of the two given data types T1 or T2 is not a matrix type ...
Definition: StorageOrder.h:283
Header file for the IsDenseVector type trait.
MT2::ResultType RT2
Result type of the right-hand side sparse matrix expression.
Definition: TDMatSMatMultExpr.h:111
MT1::CompositeType CT1
Composite type of the left-hand side dense matrix expression.
Definition: TDMatSMatMultExpr.h:114
LeftOperand lhs_
Left-hand side dense matrix of the multiplication expression.
Definition: TDMatSMatMultExpr.h:253
Header file for the IsRowMajorMatrix type trait.
Header file for the IsComputation type trait class.
MT2::CompositeType CT2
Composite type of the right-hand side sparse matrix expression.
Definition: TDMatSMatMultExpr.h:115
Header file for the TDMatDVecMultExprTrait class template.
#define BLAZE_FUNCTION_TRACE
Function trace macro.This macro can be used to reliably trace function calls. In case function tracin...
Definition: FunctionTrace.h:157
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:2370
size_t columns(const Matrix< MT, SO > &m)
Returns the current number of columns of the matrix.
Definition: Matrix.h:154
Header file for basic type definitions.
Header file for the IsColumnVector type trait.
Header file for the IsResizable type trait.
size_t rows(const Matrix< MT, SO > &m)
Returns the current number of rows of the matrix.
Definition: Matrix.h:138
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
Header file for the TDVecTDMatMultExprTrait class template.
#define BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a sparse, N-dimensional matrix type...
Definition: SparseMatrix.h:79
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: TDMatSMatMultExpr.h:167
MT1::ResultType RT1
Result type of the left-hand side dense matrix expression.
Definition: TDMatSMatMultExpr.h:110
RightOperand rightOperand() const
Returns the right-hand side sparse matrix operand.
Definition: TDMatSMatMultExpr.h:222
const ResultType CompositeType
Data type for composite expression templates.
Definition: TDMatSMatMultExpr.h:126
Header file for the IsExpression type trait class.
Header file for the FunctionTrace class.