All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SMatSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_SMATSMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_SMATSMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <algorithm>
44 #include <stdexcept>
45 #include <vector>
53 #include <blaze/math/Infinity.h>
55 #include <blaze/math/shims/Reset.h>
77 #include <blaze/util/Assert.h>
78 #include <blaze/util/Byte.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 #include <blaze/util/Unused.h>
86 
87 
88 namespace blaze {
89 
90 //=================================================================================================
91 //
92 // CLASS SMATSMATMULTEXPR
93 //
94 //=================================================================================================
95 
96 //*************************************************************************************************
103 template< typename MT1 // Type of the left-hand side sparse matrix
104  , typename MT2 > // Type of the right-hand side sparse matrix
105 class SMatSMatMultExpr : public SparseMatrix< SMatSMatMultExpr<MT1,MT2>, false >
106  , private MatMatMultExpr
107  , private Computation
108 {
109  private:
110  //**Type definitions****************************************************************************
111  typedef typename MT1::ResultType RT1;
112  typedef typename MT2::ResultType RT2;
113  typedef typename MT1::CompositeType CT1;
114  typedef typename MT2::CompositeType CT2;
115  //**********************************************************************************************
116 
117  //**********************************************************************************************
119  enum { evaluateLeft = RequiresEvaluation<MT1>::value };
120  //**********************************************************************************************
121 
122  //**********************************************************************************************
124  enum { evaluateRight = RequiresEvaluation<MT2>::value };
125  //**********************************************************************************************
126 
127  //**********************************************************************************************
129 
133  template< typename MT >
134  struct UseSMPAssign {
135  enum { value = ( evaluateLeft || evaluateRight ) };
136  };
138  //**********************************************************************************************
139 
140  public:
141  //**Type definitions****************************************************************************
147  typedef const ElementType ReturnType;
148  typedef const ResultType CompositeType;
149 
151  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
152 
154  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
155  //**********************************************************************************************
156 
157  //**Compilation flags***************************************************************************
159  enum { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
160  !evaluateRight && MT2::smpAssignable };
161  //**********************************************************************************************
162 
163  //**Constructor*********************************************************************************
169  explicit inline SMatSMatMultExpr( const MT1& lhs, const MT2& rhs )
170  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
171  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
172  {
173  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
174  }
175  //**********************************************************************************************
176 
177  //**Access operator*****************************************************************************
184  inline ReturnType operator()( size_t i, size_t j ) const {
185  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
186  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
187 
189 
190  ElementType tmp = ElementType();
191 
192  // Early exit
193  if( lhs_.columns() == 0UL )
194  return tmp;
195 
196  // Fast computation in case the left-hand side sparse matrix directly provides iterators
198  {
199  // Evaluation of the left-hand side sparse matrix operand
200  CT1 A( lhs_ );
201 
202  const ConstIterator end( A.end(i) );
203  ConstIterator element( A.begin(i) );
204 
205  // Early exit in case row i is empty
206  if( element == end )
207  return tmp;
208 
209  // Calculating element (i,j)
210  tmp = element->value() * rhs_(element->index(),j);
211  ++element;
212  for( ; element!=end; ++element )
213  tmp += element->value() * rhs_(element->index(),j);
214  }
215 
216  // Default computation in case the left-hand side sparse matrix doesn't provide iterators
217  else {
218  tmp = lhs_(i,0UL) * rhs_(0UL,j);
219  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
220  tmp += lhs_(i,k) * rhs_(k,j);
221  }
222  }
223 
224  return tmp;
225  }
226  //**********************************************************************************************
227 
228  //**Rows function*******************************************************************************
233  inline size_t rows() const {
234  return lhs_.rows();
235  }
236  //**********************************************************************************************
237 
238  //**Columns function****************************************************************************
243  inline size_t columns() const {
244  return rhs_.columns();
245  }
246  //**********************************************************************************************
247 
248  //**NonZeros function***************************************************************************
253  inline size_t nonZeros() const {
254  return 0UL;
255  }
256  //**********************************************************************************************
257 
258  //**NonZeros function***************************************************************************
264  inline size_t nonZeros( size_t i ) const {
265  UNUSED_PARAMETER( i );
266  return 0UL;
267  }
268  //**********************************************************************************************
269 
270  //**Left operand access*************************************************************************
275  inline LeftOperand leftOperand() const {
276  return lhs_;
277  }
278  //**********************************************************************************************
279 
280  //**Right operand access************************************************************************
285  inline RightOperand rightOperand() const {
286  return rhs_;
287  }
288  //**********************************************************************************************
289 
290  //**********************************************************************************************
296  template< typename T >
297  inline bool canAlias( const T* alias ) const {
298  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
299  }
300  //**********************************************************************************************
301 
302  //**********************************************************************************************
308  template< typename T >
309  inline bool isAliased( const T* alias ) const {
310  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
311  }
312  //**********************************************************************************************
313 
314  //**********************************************************************************************
319  inline bool canSMPAssign() const {
320  return ( rows() > SMP_SMATSMATMULT_THRESHOLD );
321  }
322  //**********************************************************************************************
323 
324  private:
325  //**Member variables****************************************************************************
328  //**********************************************************************************************
329 
330  //**Assignment to dense matrices****************************************************************
343  template< typename MT // Type of the target dense matrix
344  , bool SO > // Storage order of the target dense matrix
345  friend inline void assign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
346  {
348 
349  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
350  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
351 
352  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
353  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
354 
355  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
356  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
357  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
358  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
359  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
360  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
361 
362  SMatSMatMultExpr::selectAssignKernel( ~lhs, A, B );
363  }
365  //**********************************************************************************************
366 
367  //**Default assignment to dense matrices********************************************************
380  template< typename MT3 // Type of the left-hand side target matrix
381  , typename MT4 // Type of the left-hand side matrix operand
382  , typename MT5 > // Type of the right-hand side matrix operand
383  static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
384  {
385  typedef typename MT4::ConstIterator LeftIterator;
386  typedef typename MT5::ConstIterator RightIterator;
387 
388  for( size_t i=0UL; i<C.rows(); ++i ) {
389  const LeftIterator lend( A.end(i) );
390  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
391  const RightIterator rend( B.end( lelem->index() ) );
392  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem )
393  {
395  isDefault( C(i,relem->index()) ) ) {
396  C(i,relem->index()) = lelem->value() * relem->value();
397  }
398  else {
399  C(i,relem->index()) += lelem->value() * relem->value();
400  }
401  }
402  }
403  }
404  }
406  //**********************************************************************************************
407 
408  //**Assignment to row-major sparse matrices*****************************************************
421  template< typename MT > // Type of the target sparse matrix
422  friend inline void assign( SparseMatrix<MT,false>& lhs, const SMatSMatMultExpr& rhs )
423  {
425 
426  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
427  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
428 
429  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
430  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
431 
432  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
433  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
434 
435  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
436  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
437  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
438  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
439  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
440  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
441 
442  // (Over-)Estimating the number of non-zero entries in the resulting matrix
443  size_t nonzeros( 0UL );
444 
445  for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
446  const LeftIterator lend( A.end(i) );
447  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
448  nonzeros += B.nonZeros( lelem->index() );
449  }
450  }
451 
452  if( nonzeros > (~lhs).rows() * (~lhs).columns() ) {
453  nonzeros = (~lhs).rows() * (~lhs).columns();
454  }
455 
456  (~lhs).reserve( nonzeros );
457  nonzeros = 0UL;
458 
459  // Performing the matrix-matrix multiplication
460  std::vector<ElementType> values ( (~lhs).columns(), ElementType() );
461  std::vector<byte> valid ( (~lhs).columns(), 0 );
462  std::vector<size_t> indices( (~lhs).columns(), 0UL );
463  size_t minIndex( inf ), maxIndex( 0UL );
464 
465  for( size_t i=0UL; i<(~lhs).rows(); ++i )
466  {
467  const LeftIterator lend( A.end(i) );
468  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem )
469  {
470  const RightIterator rend( B.end( lelem->index() ) );
471  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem )
472  {
473  if( !valid[relem->index()] ) {
474  values[relem->index()] = lelem->value() * relem->value();
475  valid [relem->index()] = 1;
476  indices[nonzeros] = relem->index();
477  ++nonzeros;
478  if( relem->index() < minIndex ) minIndex = relem->index();
479  if( relem->index() > maxIndex ) maxIndex = relem->index();
480  }
481  else {
482  values[relem->index()] += lelem->value() * relem->value();
483  }
484  }
485  }
486 
487  BLAZE_INTERNAL_ASSERT( nonzeros <= (~lhs).columns(), "Invalid number of non-zero elements" );
488 
489  if( nonzeros > 0UL )
490  {
491  BLAZE_INTERNAL_ASSERT( minIndex <= maxIndex, "Invalid index detected" );
492 
493  if( ( nonzeros + nonzeros ) < ( maxIndex - minIndex ) )
494  {
495  std::sort( indices.begin(), indices.begin() + nonzeros );
496 
497  for( size_t j=0UL; j<nonzeros; ++j )
498  {
499  const size_t index( indices[j] );
500  if( !isDefault( values[index] ) ) {
501  (~lhs).append( i, index, values[index] );
502  reset( values[index] );
503  }
504 
505  reset( valid [index] );
506  }
507  }
508  else {
509  for( size_t j=minIndex; j<=maxIndex; ++j )
510  {
511  if( !isDefault( values[j] ) ) {
512  (~lhs).append( i, j, values[j] );
513  reset( values[j] );
514  }
515 
516  reset( valid [j] );
517  }
518  }
519 
520  nonzeros = 0UL;
521  minIndex = inf;
522  maxIndex = 0UL;
523  }
524 
525  (~lhs).finalize( i );
526  }
527  }
529  //**********************************************************************************************
530 
531  //**Assignment to column-major sparse matrices**************************************************
544  template< typename MT > // Type of the target sparse matrix
545  friend inline void assign( SparseMatrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
546  {
548 
549  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
550  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
551 
554 
555  const ResultType tmp( serial( rhs ) );
556  (~lhs).reserve( tmp.nonZeros() );
557  assign( ~lhs, tmp );
558  }
560  //**********************************************************************************************
561 
562  //**Addition assignment to dense matrices*******************************************************
575  template< typename MT // Type of the target dense matrix
576  , bool SO > // Storage order of the target dense matarix
577  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
578  {
580 
581  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
582  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
583 
584  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
585  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
586 
587  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
588  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
589  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
590  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
591  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
592  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
593 
594  SMatSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
595  }
597  //**********************************************************************************************
598 
599  //**Default addition assignment to dense matrices***********************************************
613  template< typename MT3 // Type of the left-hand side target matrix
614  , typename MT4 // Type of the left-hand side matrix operand
615  , typename MT5 > // Type of the right-hand side matrix operand
616  static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
617  {
618  typedef typename MT4::ConstIterator LeftIterator;
619  typedef typename MT5::ConstIterator RightIterator;
620 
621  for( size_t i=0UL; i<C.rows(); ++i ) {
622  const LeftIterator lend( A.end(i) );
623  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
624  const RightIterator rend( B.end( lelem->index() ) );
625  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem ) {
626  C(i,relem->index()) += lelem->value() * relem->value();
627  }
628  }
629  }
630  }
632  //**********************************************************************************************
633 
634  //**Addition assignment to sparse matrices******************************************************
635  // No special implementation for the addition assignment to sparse matrices.
636  //**********************************************************************************************
637 
638  //**Subtraction assignment to dense matrices****************************************************
651  template< typename MT // Type of the target dense matrix
652  , bool SO > // Storage order of the target dense matrix
653  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& 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 
660  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
661  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
662 
663  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
664  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
665  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
666  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
667  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
668  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
669 
670  SMatSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
671  }
673  //**********************************************************************************************
674 
675  //**Default subtraction assignment to dense matrices********************************************
689  template< typename MT3 // Type of the left-hand side target matrix
690  , typename MT4 // Type of the left-hand side matrix operand
691  , typename MT5 > // Type of the right-hand side matrix operand
692  static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
693  {
694  typedef typename MT4::ConstIterator LeftIterator;
695  typedef typename MT5::ConstIterator RightIterator;
696 
697  for( size_t i=0UL; i<C.rows(); ++i ) {
698  const LeftIterator lend( A.end(i) );
699  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
700  const RightIterator rend( B.end( lelem->index() ) );
701  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem ) {
702  C(i,relem->index()) -= lelem->value() * relem->value();
703  }
704  }
705  }
706  }
708  //**********************************************************************************************
709 
710  //**Subtraction assignment to sparse matrices***************************************************
711  // No special implementation for the subtraction assignment to sparse matrices.
712  //**********************************************************************************************
713 
714  //**Multiplication assignment to dense matrices*************************************************
715  // No special implementation for the multiplication assignment to dense matrices.
716  //**********************************************************************************************
717 
718  //**Multiplication assignment to sparse matrices************************************************
719  // No special implementation for the multiplication assignment to sparse matrices.
720  //**********************************************************************************************
721 
722  //**SMP assignment to dense matrices************************************************************
737  template< typename MT // Type of the target dense matrix
738  , bool SO > // Storage order of the target dense matrix
739  friend inline typename EnableIf< UseSMPAssign<MT> >::Type
740  smpAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
741  {
743 
744  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
745  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
746 
747  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
748  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
749 
750  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
751  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
752  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
753  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
754  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
755  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
756 
757  smpAssign( ~lhs, A * B );
758  }
760  //**********************************************************************************************
761 
762  //**SMP assignment to sparse matrices***********************************************************
777  template< typename MT // Type of the target sparse matrix
778  , bool SO > // Storage order of the target sparse matrix
779  friend inline typename EnableIf< UseSMPAssign<MT> >::Type
780  smpAssign( SparseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
781  {
783 
784  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
785  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
786 
787  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
788  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
789 
790  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
791  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
792  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
793  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
794  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
795  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
796 
797  smpAssign( ~lhs, A * B );
798  }
800  //**********************************************************************************************
801 
802  //**SMP addition assignment to dense matrices***************************************************
817  template< typename MT // Type of the target dense matrix
818  , bool SO > // Storage order of the target dense matarix
819  friend inline typename EnableIf< UseSMPAssign<MT> >::Type
820  smpAddAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& 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 
827  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
828  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
829 
830  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
831  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
832  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
833  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
834  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
835  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
836 
837  smpAddAssign( ~lhs, A * B );
838  }
840  //**********************************************************************************************
841 
842  //**SMP addition assignment to sparse matrices**************************************************
843  // No special implementation for the SMP addition assignment to sparse matrices.
844  //**********************************************************************************************
845 
846  //**SMP subtraction assignment to dense matrices************************************************
861  template< typename MT // Type of the target dense matrix
862  , bool SO > // Storage order of the target dense matrix
863  friend inline typename EnableIf< UseSMPAssign<MT> >::Type
864  smpSubAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
865  {
867 
868  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
869  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
870 
871  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
872  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
873 
874  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
875  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
876  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
877  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
878  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
879  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
880 
881  smpSubAssign( ~lhs, A * B );
882  }
884  //**********************************************************************************************
885 
886  //**SMP subtraction assignment to sparse matrices***********************************************
887  // No special implementation for the SMP subtraction assignment to sparse matrices.
888  //**********************************************************************************************
889 
890  //**SMP multiplication assignment to dense matrices*********************************************
891  // No special implementation for the SMP multiplication assignment to dense matrices.
892  //**********************************************************************************************
893 
894  //**SMP multiplication assignment to sparse matrices********************************************
895  // No special implementation for the SMP multiplication assignment to sparse matrices.
896  //**********************************************************************************************
897 
898  //**Compile time checks*************************************************************************
905  //**********************************************************************************************
906 };
907 //*************************************************************************************************
908 
909 
910 
911 
912 //=================================================================================================
913 //
914 // GLOBAL BINARY ARITHMETIC OPERATORS
915 //
916 //=================================================================================================
917 
918 //*************************************************************************************************
945 template< typename T1 // Type of the left-hand side sparse matrix
946  , typename T2 > // Type of the right-hand side sparse matrix
947 inline const SMatSMatMultExpr<T1,T2>
949 {
951 
952  if( (~lhs).columns() != (~rhs).rows() )
953  throw std::invalid_argument( "Matrix sizes do not match" );
954 
955  return SMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
956 }
957 //*************************************************************************************************
958 
959 
960 
961 
962 //=================================================================================================
963 //
964 // EXPRESSION TRAIT SPECIALIZATIONS
965 //
966 //=================================================================================================
967 
968 //*************************************************************************************************
970 template< typename MT1, typename MT2, typename VT >
971 struct SMatDVecMultExprTrait< SMatSMatMultExpr<MT1,MT2>, VT >
972 {
973  public:
974  //**********************************************************************************************
975  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
976  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
977  IsDenseVector<VT>::value && IsColumnVector<VT>::value
978  , typename SMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
979  , INVALID_TYPE >::Type Type;
980  //**********************************************************************************************
981 };
983 //*************************************************************************************************
984 
985 
986 //*************************************************************************************************
988 template< typename MT1, typename MT2, typename VT >
989 struct SMatSVecMultExprTrait< SMatSMatMultExpr<MT1,MT2>, VT >
990 {
991  public:
992  //**********************************************************************************************
993  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
994  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
995  IsSparseVector<VT>::value && IsColumnVector<VT>::value
996  , typename SMatSVecMultExprTrait< MT1, typename SMatSVecMultExprTrait<MT2,VT>::Type >::Type
997  , INVALID_TYPE >::Type Type;
998  //**********************************************************************************************
999 };
1001 //*************************************************************************************************
1002 
1003 
1004 //*************************************************************************************************
1006 template< typename VT, typename MT1, typename MT2 >
1007 struct TDVecSMatMultExprTrait< VT, SMatSMatMultExpr<MT1,MT2> >
1008 {
1009  public:
1010  //**********************************************************************************************
1011  typedef typename SelectType< IsDenseVector<VT>::value && IsRowVector<VT>::value &&
1012  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1013  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1014  , typename TDVecSMatMultExprTrait< typename TDVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1015  , INVALID_TYPE >::Type Type;
1016  //**********************************************************************************************
1017 };
1019 //*************************************************************************************************
1020 
1021 
1022 //*************************************************************************************************
1024 template< typename VT, typename MT1, typename MT2 >
1025 struct TSVecSMatMultExprTrait< VT, SMatSMatMultExpr<MT1,MT2> >
1026 {
1027  public:
1028  //**********************************************************************************************
1029  typedef typename SelectType< IsSparseVector<VT>::value && IsRowVector<VT>::value &&
1030  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1031  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1032  , typename TSVecSMatMultExprTrait< typename TSVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1033  , INVALID_TYPE >::Type Type;
1034  //**********************************************************************************************
1035 };
1037 //*************************************************************************************************
1038 
1039 
1040 //*************************************************************************************************
1042 template< typename MT1, typename MT2, bool AF >
1043 struct SubmatrixExprTrait< SMatSMatMultExpr<MT1,MT2>, AF >
1044 {
1045  public:
1046  //**********************************************************************************************
1047  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT1,AF>::Type
1048  , typename SubmatrixExprTrait<const MT2,AF>::Type >::Type Type;
1049  //**********************************************************************************************
1050 };
1052 //*************************************************************************************************
1053 
1054 
1055 //*************************************************************************************************
1057 template< typename MT1, typename MT2 >
1058 struct RowExprTrait< SMatSMatMultExpr<MT1,MT2> >
1059 {
1060  public:
1061  //**********************************************************************************************
1062  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
1063  //**********************************************************************************************
1064 };
1066 //*************************************************************************************************
1067 
1068 
1069 //*************************************************************************************************
1071 template< typename MT1, typename MT2 >
1072 struct ColumnExprTrait< SMatSMatMultExpr<MT1,MT2> >
1073 {
1074  public:
1075  //**********************************************************************************************
1076  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
1077  //**********************************************************************************************
1078 };
1080 //*************************************************************************************************
1081 
1082 } // namespace blaze
1083 
1084 #endif
Header file for the SMatDVecMultExprTrait class template.
void reset(DynamicMatrix< Type, SO > &m)
Resetting the given dense matrix.
Definition: DynamicMatrix.h:4599
Header file for the UNUSED_PARAMETER function template.
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:4329
void smpSubAssign(DenseMatrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:152
MultTrait< RT1, RT2 >::Type ResultType
Result type for expression template evaluations.
Definition: SMatSMatMultExpr.h:143
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:4642
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:199
Header file for the ColumnExprTrait class template.
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: SMatSMatMultExpr.h:319
ResultType::ElementType ElementType
Resulting element type.
Definition: SMatSMatMultExpr.h:146
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2408
RightOperand rightOperand() const
Returns the right-hand side sparse matrix operand.
Definition: SMatSMatMultExpr.h:285
Header file for the IsRowVector type trait.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:251
void UNUSED_PARAMETER(const T1 &)
Suppression of unused parameter warnings.
Definition: Unused.h:84
Header file for the TDVecSMatMultExprTrait class template.
const DMatSerialExpr< MT, SO > serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:690
Header file for the Computation base class.
Header file for the MatMatMultExpr base class.
Header file for the RequiresEvaluation type trait.
Header file for the TSVecSMatMultExprTrait class template.
size_t nonZeros() const
Returns the number of non-zero elements in the sparse matrix.
Definition: SMatSMatMultExpr.h:253
MT1::CompositeType CT1
Composite type of the left-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:113
Header file for the implementation of an arbitrarily sized vector.
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:107
ResultType::OppositeType OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: SMatSMatMultExpr.h:144
MT1::ResultType RT1
Result type of the left-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:111
Header file for the SparseMatrix base class.
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: SMatSMatMultExpr.h:145
Constraint on the data type.
Header file for the MultExprTrait class template.
void smpAddAssign(DenseMatrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:122
Compile time check to query the requirement to evaluate an expression.Via this type trait it is possi...
Definition: RequiresEvaluation.h:90
const ElementType ReturnType
Return type for expression template evaluations.
Definition: SMatSMatMultExpr.h:147
Compile time type selection.The SelectType class template selects one of the two given types T1 and T...
Definition: SelectType.h:59
size_t rows() const
Returns the current number of rows of the matrix.
Definition: SMatSMatMultExpr.h:233
size_t columns() const
Returns the current number of columns of the matrix.
Definition: SMatSMatMultExpr.h:243
Header file for the multiplication trait.
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: SMatSMatMultExpr.h:327
SMatSMatMultExpr< MT1, MT2 > This
Type of this SMatSMatMultExpr instance.
Definition: SMatSMatMultExpr.h:142
SelectType< IsExpression< MT1 >::value, const MT1, const MT1 & >::Type LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:151
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2412
Numerical infinity for built-in data types.
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:271
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: SMatSMatMultExpr.h:297
LeftOperand leftOperand() const
Returns the left-hand side sparse matrix operand.
Definition: SMatSMatMultExpr.h:275
Header file for the SMatSVecMultExprTrait class template.
SMatSMatMultExpr(const MT1 &lhs, const MT2 &rhs)
Constructor for the SMatSMatMultExpr class.
Definition: SMatSMatMultExpr.h:169
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: SMatSMatMultExpr.h:309
Constraints on the storage order of matrix types.
const size_t SMP_SMATSMATMULT_THRESHOLD
SMP row-major sparse matrix/row-major sparse matrix multiplication threshold.This threshold specifies...
Definition: Thresholds.h:1110
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 EnableIf class template.
Header file for the serial shim.
Header file for the byte type.
void smpAssign(DenseMatrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:92
Compile time check for resizable data types.This type trait tests whether the given data type is a re...
Definition: IsResizable.h:75
size_t nonZeros(size_t i) const
Returns the number of non-zero elements in the specified row.
Definition: SMatSMatMultExpr.h:264
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
Expression object for sparse matrix-sparse matrix multiplications.The SMatSMatMultExpr class represen...
Definition: Forward.h:97
Header file for run time assertion macros.
Utility type for generic codes.
Base template for the MultTrait class.
Definition: MultTrait.h:141
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:301
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:331
Header file for the isDefault shim.
const Infinity inf
Global Infinity instance.The blaze::inf instance can be used wherever a built-in data type is expecte...
Definition: Infinity.h:1098
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: SMatSMatMultExpr.h:184
Header file for the RemoveReference type trait.
Header file for the IsDenseVector type trait.
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: SMatSMatMultExpr.h:326
SelectType< IsExpression< MT2 >::value, const MT2, const MT2 & >::Type RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:154
Header file for the IsRowMajorMatrix type trait.
Header file for the IsComputation type trait class.
MT2::ResultType RT2
Result type of the right-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:112
#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:2403
Header file for basic type definitions.
Header file for the IsColumnVector type trait.
Header file for the IsResizable type trait.
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
#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
const ResultType CompositeType
Data type for composite expression templates.
Definition: SMatSMatMultExpr.h:148
#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
Header file for the IsExpression type trait class.
Header file for the FunctionTrace class.
MT2::CompositeType CT2
Composite type of the right-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:114