All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TSMatTSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_TSMATTSMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_TSMATTSMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <algorithm>
44 #include <stdexcept>
45 #include <vector>
55 #include <blaze/math/Infinity.h>
57 #include <blaze/math/shims/Reset.h>
79 #include <blaze/util/Assert.h>
80 #include <blaze/util/Byte.h>
81 #include <blaze/util/EnableIf.h>
82 #include <blaze/util/InvalidType.h>
84 #include <blaze/util/SelectType.h>
85 #include <blaze/util/Types.h>
88 #include <blaze/util/Unused.h>
89 
90 
91 namespace blaze {
92 
93 //=================================================================================================
94 //
95 // CLASS TSMATTSMATMULTEXPR
96 //
97 //=================================================================================================
98 
99 //*************************************************************************************************
106 template< typename MT1 // Type of the left-hand side sparse matrix
107  , typename MT2 > // Type of the right-hand side sparse matrix
108 class TSMatTSMatMultExpr : public SparseMatrix< TSMatTSMatMultExpr<MT1,MT2>, true >
109  , private MatMatMultExpr
110  , private Computation
111 {
112  private:
113  //**Type definitions****************************************************************************
114  typedef typename MT1::ResultType RT1;
115  typedef typename MT2::ResultType RT2;
116  typedef typename MT1::CompositeType CT1;
117  typedef typename MT2::CompositeType CT2;
118  //**********************************************************************************************
119 
120  //**********************************************************************************************
122  enum { evaluateLeft = RequiresEvaluation<MT1>::value };
123  //**********************************************************************************************
124 
125  //**********************************************************************************************
127  enum { evaluateRight = RequiresEvaluation<MT2>::value };
128  //**********************************************************************************************
129 
130  //**********************************************************************************************
132 
136  template< typename MT >
137  struct UseSMPAssign {
138  enum { value = ( evaluateLeft || evaluateRight ) };
139  };
141  //**********************************************************************************************
142 
143  public:
144  //**Type definitions****************************************************************************
150  typedef const ElementType ReturnType;
151  typedef const ResultType CompositeType;
152 
154  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
155 
157  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
158  //**********************************************************************************************
159 
160  //**Compilation flags***************************************************************************
162  enum { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
163  !evaluateRight && MT2::smpAssignable };
164  //**********************************************************************************************
165 
166  //**Constructor*********************************************************************************
172  explicit inline TSMatTSMatMultExpr( const MT1& lhs, const MT2& rhs )
173  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
174  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
175  {
176  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
177  }
178  //**********************************************************************************************
179 
180  //**Access operator*****************************************************************************
187  inline ReturnType operator()( size_t i, size_t j ) const {
188  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
189  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
190 
192 
193  ElementType tmp = ElementType();
194 
195  // Early exit
196  if( lhs_.columns() == 0UL )
197  return tmp;
198 
199  // Fast computation in case the right-hand side sparse matrix directly provides iterators
201  {
202  // Evaluation of the right-hand side sparse matrix operand
203  CT2 B( rhs_ );
204 
205  const ConstIterator end( B.end(j) );
206  ConstIterator element( B.begin(j) );
207 
208  // Early exit in case row i is empty
209  if( element == end )
210  return tmp;
211 
212  // Calculating element (i,j)
213  tmp = lhs_(i,element->index()) * element->value();
214  ++element;
215  for( ; element!=end; ++element )
216  tmp += lhs_(i,element->index()) * element->value();
217  }
218 
219  // Default computation in case the right-hand side sparse matrix doesn't provide iterators
220  else {
221  tmp = lhs_(i,0UL) * rhs_(0UL,j);
222  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
223  tmp += lhs_(i,k) * rhs_(k,j);
224  }
225  }
226 
227  return tmp;
228  }
229  //**********************************************************************************************
230 
231  //**Rows function*******************************************************************************
236  inline size_t rows() const {
237  return lhs_.rows();
238  }
239  //**********************************************************************************************
240 
241  //**Columns function****************************************************************************
246  inline size_t columns() const {
247  return rhs_.columns();
248  }
249  //**********************************************************************************************
250 
251  //**NonZeros function***************************************************************************
256  inline size_t nonZeros() const {
257  return 0UL;
258  }
259  //**********************************************************************************************
260 
261  //**NonZeros function***************************************************************************
267  inline size_t nonZeros( size_t i ) const {
268  UNUSED_PARAMETER( i );
269  return 0UL;
270  }
271  //**********************************************************************************************
272 
273  //**Left operand access*************************************************************************
278  inline LeftOperand leftOperand() const {
279  return lhs_;
280  }
281  //**********************************************************************************************
282 
283  //**Right operand access************************************************************************
288  inline RightOperand rightOperand() const {
289  return rhs_;
290  }
291  //**********************************************************************************************
292 
293  //**********************************************************************************************
299  template< typename T >
300  inline bool canAlias( const T* alias ) const {
301  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
302  }
303  //**********************************************************************************************
304 
305  //**********************************************************************************************
311  template< typename T >
312  inline bool isAliased( const T* alias ) const {
313  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
314  }
315  //**********************************************************************************************
316 
317  //**********************************************************************************************
322  inline bool canSMPAssign() const {
323  return ( rows() > SMP_TSMATTSMATMULT_THRESHOLD );
324  }
325  //**********************************************************************************************
326 
327  private:
328  //**Member variables****************************************************************************
331  //**********************************************************************************************
332 
333  //**Assignment to dense matrices****************************************************************
346  template< typename MT // Type of the target dense matrix
347  , bool SO > // Storage order of the target dense matrix
348  friend inline void assign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
349  {
351 
352  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
353  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
354 
355  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
356  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
357 
358  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
359  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
360  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
361  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
362  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
363  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
364 
365  TSMatTSMatMultExpr::selectAssignKernel( ~lhs, A, B );
366  }
368  //**********************************************************************************************
369 
370  //**Default assignment to dense matrices********************************************************
384  template< typename MT3 // Type of the left-hand side target matrix
385  , typename MT4 // Type of the left-hand side matrix operand
386  , typename MT5 > // Type of the right-hand side matrix operand
387  static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
388  {
389  typedef typename MT4::ConstIterator LeftIterator;
390  typedef typename MT5::ConstIterator RightIterator;
391 
392  for( size_t j=0UL; j<C.columns(); ++j ) {
393  const RightIterator rend( B.end(j) );
394  for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
395  const LeftIterator lend( A.end( relem->index() ) );
396  for( LeftIterator lelem=A.begin( relem->index() ); lelem!=lend; ++lelem )
397  {
399  isDefault( C(lelem->index(),j) ) ) {
400  C(lelem->index(),j) = lelem->value() * relem->value();
401  }
402  else {
403  C(lelem->index(),j) += lelem->value() * relem->value();
404  }
405  }
406  }
407  }
408  }
410  //**********************************************************************************************
411 
412  //**Assignment to row-major sparse matrices*****************************************************
425  template< typename MT > // Type of the target sparse matrix
426  friend inline void assign( SparseMatrix<MT,false>& lhs, const TSMatTSMatMultExpr& rhs )
427  {
429 
430  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
431  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
432 
435 
436  const ResultType tmp( serial( rhs ) );
437  (~lhs).reserve( tmp.nonZeros() );
438  assign( ~lhs, tmp );
439  }
441  //**********************************************************************************************
442 
443  //**Assignment to column-major sparse matrices**************************************************
456  template< typename MT > // Type of the target sparse matrix
457  friend inline void assign( SparseMatrix<MT,true>& lhs, const TSMatTSMatMultExpr& rhs )
458  {
460 
461  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
462  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
463 
464  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
465  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
466 
467  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
468  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
469 
470  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
471  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
472  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
473  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
474  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
475  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
476 
477  // (Over-)Estimating the number of non-zero entries in the resulting matrix
478  size_t nonzeros( 0UL );
479 
480  for( size_t j=0UL; j<(~lhs).columns(); ++j ) {
481  const RightIterator rend( B.end(j) );
482  for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
483  nonzeros += A.nonZeros( relem->index() );
484  }
485  }
486 
487  if( nonzeros > (~lhs).rows() * (~lhs).columns() ) {
488  nonzeros = (~lhs).rows() * (~lhs).columns();
489  }
490 
491  (~lhs).reserve( nonzeros );
492  nonzeros = 0UL;
493 
494  // Performing the matrix-matrix multiplication
495  std::vector<ElementType> values ( (~lhs).rows(), ElementType() );
496  std::vector<byte> valid ( (~lhs).rows(), 0 );
497  std::vector<size_t> indices( (~lhs).rows(), 0UL );
498  size_t minIndex( inf ), maxIndex( 0UL );
499 
500  for( size_t j=0UL; j<(~lhs).columns(); ++j )
501  {
502  const RightIterator rend( B.end(j) );
503  for( RightIterator relem=B.begin(j); relem!=rend; ++relem )
504  {
505  const LeftIterator lend( A.end( relem->index() ) );
506  for( LeftIterator lelem=A.begin( relem->index() ); lelem!=lend; ++lelem )
507  {
508  if( !valid[lelem->index()] ) {
509  values[lelem->index()] = lelem->value() * relem->value();
510  valid [lelem->index()] = 1;
511  indices[nonzeros] = lelem->index();
512  ++nonzeros;
513  if( lelem->index() < minIndex ) minIndex = lelem->index();
514  if( lelem->index() > maxIndex ) maxIndex = lelem->index();
515  }
516  else {
517  values[lelem->index()] += lelem->value() * relem->value();
518  }
519  }
520  }
521 
522  BLAZE_INTERNAL_ASSERT( nonzeros <= (~lhs).rows(), "Invalid number of non-zero elements" );
523 
524  if( nonzeros > 0UL )
525  {
526  BLAZE_INTERNAL_ASSERT( minIndex <= maxIndex, "Invalid index detected" );
527 
528  if( ( nonzeros + nonzeros ) < ( maxIndex - minIndex ) )
529  {
530  std::sort( indices.begin(), indices.begin() + nonzeros );
531 
532  for( size_t i=0UL; i<nonzeros; ++i )
533  {
534  const size_t index( indices[i] );
535  if( !isDefault( values[index] ) ) {
536  (~lhs).append( index, j, values[index] );
537  reset( values[index] );
538  }
539 
540  reset( valid [index] );
541  }
542  }
543  else {
544  for( size_t i=minIndex; i<=maxIndex; ++i )
545  {
546  if( !isDefault( values[i] ) ) {
547  (~lhs).append( i, j, values[i] );
548  reset( values[i] );
549  }
550 
551  reset( valid [i] );
552  }
553  }
554 
555  nonzeros = 0UL;
556  minIndex = inf;
557  maxIndex = 0UL;
558  }
559 
560  (~lhs).finalize( j );
561  }
562  }
564  //**********************************************************************************************
565 
566  //**Addition assignment to dense matrices*******************************************************
579  template< typename MT // Type of the target dense matrix
580  , bool SO > // Storage order of the target dense matarix
581  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
582  {
584 
585  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
586  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
587 
588  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
589  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
590 
591  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
592  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
593  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
594  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
595  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
596  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
597 
598  TSMatTSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
599  }
601  //**********************************************************************************************
602 
603  //**Default addition assignment to dense matrices***********************************************
617  template< typename MT3 // Type of the left-hand side target matrix
618  , typename MT4 // Type of the left-hand side matrix operand
619  , typename MT5 > // Type of the right-hand side matrix operand
620  static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
621  {
622  typedef typename MT4::ConstIterator LeftIterator;
623  typedef typename MT5::ConstIterator RightIterator;
624 
625  for( size_t j=0UL; j<C.columns(); ++j ) {
626  const RightIterator rend( B.end(j) );
627  for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
628  const LeftIterator lend( A.end( relem->index() ) );
629  for( LeftIterator lelem=A.begin( relem->index() ); lelem!=lend; ++lelem ) {
630  C(lelem->index(),j) += lelem->value() * relem->value();
631  }
632  }
633  }
634  }
636  //**********************************************************************************************
637 
638  //**Addition assignment to sparse matrices******************************************************
639  // No special implementation for the addition assignment to sparse matrices.
640  //**********************************************************************************************
641 
642  //**Subtraction assignment to dense matrices****************************************************
655  template< typename MT // Type of the target dense matrix
656  , bool SO > // Storage order of the target dense matarix
657  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
658  {
660 
661  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
662  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
663 
664  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
665  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
666 
667  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
668  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
669 
670  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
671  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
672  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
673  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
674  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
675  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
676 
677  TSMatTSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
678  }
680  //**********************************************************************************************
681 
682  //**Default subtraction assignment to dense matrices********************************************
696  template< typename MT3 // Type of the left-hand side target matrix
697  , typename MT4 // Type of the left-hand side matrix operand
698  , typename MT5 > // Type of the right-hand side matrix operand
699  static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
700  {
701  typedef typename MT4::ConstIterator LeftIterator;
702  typedef typename MT5::ConstIterator RightIterator;
703 
704  for( size_t j=0UL; j<C.columns(); ++j ) {
705  const RightIterator rend( B.end(j) );
706  for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
707  const LeftIterator lend( A.end( relem->index() ) );
708  for( LeftIterator lelem=A.begin( relem->index() ); lelem!=lend; ++lelem ) {
709  C(lelem->index(),j) -= lelem->value() * relem->value();
710  }
711  }
712  }
713  }
715  //**********************************************************************************************
716 
717  //**Subtraction assignment to sparse matrices***************************************************
718  // No special implementation for the subtraction assignment to sparse matrices.
719  //**********************************************************************************************
720 
721  //**Multiplication assignment to dense matrices*************************************************
722  // No special implementation for the multiplication assignment to dense matrices.
723  //**********************************************************************************************
724 
725  //**Multiplication assignment to sparse matrices************************************************
726  // No special implementation for the multiplication assignment to sparse matrices.
727  //**********************************************************************************************
728 
729  //**SMP assignment to dense matrices************************************************************
744  template< typename MT // Type of the target dense matrix
745  , bool SO > // Storage order of the target dense matrix
746  friend inline typename EnableIf< UseSMPAssign<MT> >::Type
747  smpAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
748  {
750 
751  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
752  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
753 
754  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
755  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
756 
757  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
758  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
759  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
760  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
761  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
762  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
763 
764  smpAssign( ~lhs, A * B );
765  }
767  //**********************************************************************************************
768 
769  //**SMP assignment to sparse matrices***********************************************************
784  template< typename MT > // Type of the target sparse matrix
785  friend inline typename EnableIf< UseSMPAssign<MT> >::Type
786  smpAssign( SparseMatrix<MT,true>& lhs, const TSMatTSMatMultExpr& rhs )
787  {
789 
790  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
791  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
792 
793  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
794  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
795 
796  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
797  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
798  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
799  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
800  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
801  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
802 
803  smpAssign( ~lhs, A * B );
804  }
806  //**********************************************************************************************
807 
808  //**SMP addition assignment to dense matrices***************************************************
823  template< typename MT // Type of the target dense matrix
824  , bool SO > // Storage order of the target dense matarix
825  friend inline typename EnableIf< UseSMPAssign<MT> >::Type
826  smpAddAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
827  {
829 
830  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
831  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
832 
833  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
834  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
835 
836  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
837  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
838  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
839  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
840  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
841  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
842 
843  smpAddAssign( ~lhs, A * B );
844  }
846  //**********************************************************************************************
847 
848  //**SMP addition assignment to sparse matrices**************************************************
849  // No special implementation for the SMP addition assignment to sparse matrices.
850  //**********************************************************************************************
851 
852  //**SMP subtraction assignment to dense matrices************************************************
867  template< typename MT // Type of the target dense matrix
868  , bool SO > // Storage order of the target dense matarix
869  friend inline typename EnableIf< UseSMPAssign<MT> >::Type
870  smpSubAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatMultExpr& rhs )
871  {
873 
874  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
875  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
876 
877  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
878  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
879 
880  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
881  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
882  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
883  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
884  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
885  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
886 
887  smpSubAssign( ~lhs, A * B );
888  }
890  //**********************************************************************************************
891 
892  //**SMP subtraction assignment to sparse matrices***********************************************
893  // No special implementation for the SMP subtraction assignment to sparse matrices.
894  //**********************************************************************************************
895 
896  //**SMP multiplication assignment to dense matrices*********************************************
897  // No special implementation for the SMP multiplication assignment to dense matrices.
898  //**********************************************************************************************
899 
900  //**SMP multiplication assignment to sparse matrices********************************************
901  // No special implementation for the SMP multiplication assignment to sparse matrices.
902  //**********************************************************************************************
903 
904  //**Compile time checks*************************************************************************
911  //**********************************************************************************************
912 };
913 //*************************************************************************************************
914 
915 
916 
917 
918 //=================================================================================================
919 //
920 // GLOBAL BINARY ARITHMETIC OPERATORS
921 //
922 //=================================================================================================
923 
924 //*************************************************************************************************
951 template< typename T1 // Type of the left-hand side sparse matrix
952  , typename T2 > // Type of the right-hand side sparse matrix
953 inline const TSMatTSMatMultExpr<T1,T2>
955 {
957 
958  if( (~lhs).columns() != (~rhs).rows() )
959  throw std::invalid_argument( "Matrix sizes do not match" );
960 
961  return TSMatTSMatMultExpr<T1,T2>( ~lhs, ~rhs );
962 }
963 //*************************************************************************************************
964 
965 
966 
967 
968 //=================================================================================================
969 //
970 // EXPRESSION TRAIT SPECIALIZATIONS
971 //
972 //=================================================================================================
973 
974 //*************************************************************************************************
976 template< typename MT1, typename MT2, typename VT >
977 struct TSMatDVecMultExprTrait< TSMatTSMatMultExpr<MT1,MT2>, VT >
978 {
979  public:
980  //**********************************************************************************************
981  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
982  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
983  IsDenseVector<VT>::value && IsColumnVector<VT>::value
984  , typename TSMatDVecMultExprTrait< MT1, typename TSMatDVecMultExprTrait<MT2,VT>::Type >::Type
985  , INVALID_TYPE >::Type Type;
986  //**********************************************************************************************
987 };
989 //*************************************************************************************************
990 
991 
992 //*************************************************************************************************
994 template< typename MT1, typename MT2, typename VT >
995 struct TSMatSVecMultExprTrait< TSMatTSMatMultExpr<MT1,MT2>, VT >
996 {
997  public:
998  //**********************************************************************************************
999  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1000  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
1001  IsSparseVector<VT>::value && IsColumnVector<VT>::value
1002  , typename TSMatDVecMultExprTrait< MT1, typename TSMatDVecMultExprTrait<MT2,VT>::Type >::Type
1003  , INVALID_TYPE >::Type Type;
1004  //**********************************************************************************************
1005 };
1007 //*************************************************************************************************
1008 
1009 
1010 //*************************************************************************************************
1012 template< typename VT, typename MT1, typename MT2 >
1013 struct TDVecTSMatMultExprTrait< VT, TSMatTSMatMultExpr<MT1,MT2> >
1014 {
1015  public:
1016  //**********************************************************************************************
1017  typedef typename SelectType< IsDenseVector<VT>::value && IsRowVector<VT>::value &&
1018  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1019  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
1020  , typename TDVecTSMatMultExprTrait< typename TDVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1021  , INVALID_TYPE >::Type Type;
1022  //**********************************************************************************************
1023 };
1025 //*************************************************************************************************
1026 
1027 
1028 //*************************************************************************************************
1030 template< typename VT, typename MT1, typename MT2 >
1031 struct TSVecTSMatMultExprTrait< VT, TSMatTSMatMultExpr<MT1,MT2> >
1032 {
1033  public:
1034  //**********************************************************************************************
1035  typedef typename SelectType< IsSparseVector<VT>::value && IsRowVector<VT>::value &&
1036  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
1037  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
1038  , typename TSVecTSMatMultExprTrait< typename TSVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1039  , INVALID_TYPE >::Type Type;
1040  //**********************************************************************************************
1041 };
1043 //*************************************************************************************************
1044 
1045 
1046 //*************************************************************************************************
1048 template< typename MT1, typename MT2, bool AF >
1049 struct SubmatrixExprTrait< TSMatTSMatMultExpr<MT1,MT2>, AF >
1050 {
1051  public:
1052  //**********************************************************************************************
1053  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT1,AF>::Type
1054  , typename SubmatrixExprTrait<const MT2,AF>::Type >::Type Type;
1055  //**********************************************************************************************
1056 };
1058 //*************************************************************************************************
1059 
1060 
1061 //*************************************************************************************************
1063 template< typename MT1, typename MT2 >
1064 struct RowExprTrait< TSMatTSMatMultExpr<MT1,MT2> >
1065 {
1066  public:
1067  //**********************************************************************************************
1068  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
1069  //**********************************************************************************************
1070 };
1072 //*************************************************************************************************
1073 
1074 
1075 //*************************************************************************************************
1077 template< typename MT1, typename MT2 >
1078 struct ColumnExprTrait< TSMatTSMatMultExpr<MT1,MT2> >
1079 {
1080  public:
1081  //**********************************************************************************************
1082  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
1083  //**********************************************************************************************
1084 };
1086 //*************************************************************************************************
1087 
1088 } // namespace blaze
1089 
1090 #endif
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
MT2::CompositeType CT2
Composite type of the right-hand side sparse matrix expression.
Definition: TSMatTSMatMultExpr.h:117
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
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: TSMatTSMatMultExpr.h:322
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.
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: TSMatTSMatMultExpr.h:148
const ElementType ReturnType
Return type for expression template evaluations.
Definition: TSMatTSMatMultExpr.h:150
Header file for the IsColumnMajorMatrix type trait.
MT1::ResultType RT1
Result type of the left-hand side sparse matrix expression.
Definition: TSMatTSMatMultExpr.h:114
Header file for the TSVecTSMatMultExprTrait class template.
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2408
Header file for the IsRowVector type trait.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:251
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: TSMatTSMatMultExpr.h:187
void UNUSED_PARAMETER(const T1 &)
Suppression of unused parameter warnings.
Definition: Unused.h:84
LeftOperand leftOperand() const
Returns the left-hand side transpose sparse matrix operand.
Definition: TSMatTSMatMultExpr.h:278
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
TSMatTSMatMultExpr(const MT1 &lhs, const MT2 &rhs)
Constructor for the TSMatTSMatMultExpr class.
Definition: TSMatTSMatMultExpr.h:172
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: TSMatTSMatMultExpr.h:300
Header file for the Computation base class.
Header file for the MatMatMultExpr base class.
Header file for the RequiresEvaluation type trait.
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
RightOperand rightOperand() const
Returns the right-hand side transpose sparse matrix operand.
Definition: TSMatTSMatMultExpr.h:288
Header file for the SparseMatrix base class.
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
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: TSMatTSMatMultExpr.h:330
size_t columns() const
Returns the current number of columns of the matrix.
Definition: TSMatTSMatMultExpr.h:246
size_t nonZeros(size_t i) const
Returns the number of non-zero elements in the specified row.
Definition: TSMatTSMatMultExpr.h:267
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 multiplication trait.
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: TSMatTSMatMultExpr.h:329
const size_t SMP_TSMATTSMATMULT_THRESHOLD
SMP column-major sparse matrix/column-major sparse matrix multiplication threshold.This threshold specifies when a column-major sparse matrix/column-major sparse matrix multiplication can be executed in parallel. In case the number of rows/columns of the target matrix is larger or equal to this threshold, the operation is executed in parallel. If the number of rows/columns is below this threshold the operation is executed single-threaded.
Definition: Thresholds.h:1179
#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
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2412
MultTrait< RT1, RT2 >::Type ResultType
Result type for expression template evaluations.
Definition: TSMatTSMatMultExpr.h:146
Header file for the TDVecTSMatMultExprTrait class template.
Header file for the TSMatDVecMultExprTrait class template.
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
ResultType::OppositeType OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: TSMatTSMatMultExpr.h:147
Expression object for transpose sparse matrix-transpose sparse matrix multiplications.The TSMatTSMatMultExpr class represents the compile time expression for multiplications between two column-major sparse matrices.
Definition: Forward.h:145
Constraint on the data type.
Constraints on the storage order of matrix types.
Constraint on the data type.
size_t nonZeros() const
Returns the number of non-zero elements in the sparse matrix.
Definition: TSMatTSMatMultExpr.h:256
Header file for the SelectType class template.
Header file for the RowExprTrait class template.
Header file for all forward declarations for expression class templates.
Constraint on the data type.
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
SelectType< IsExpression< MT1 >::value, const MT1, const MT1 & >::Type LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatTSMatMultExpr.h:154
Compile time check for resizable data types.This type trait tests whether the given data type is a re...
Definition: IsResizable.h:75
Header file for the IsSparseVector type trait.
Header file for the SubmatrixExprTrait class template.
Removal of reference modifiers.The RemoveCV type trait removes any reference modifiers from the given...
Definition: RemoveReference.h:69
TSMatTSMatMultExpr< MT1, MT2 > This
Type of this TSMatTSMatMultExpr instance.
Definition: TSMatTSMatMultExpr.h:145
size_t rows() const
Returns the current number of rows of the matrix.
Definition: TSMatTSMatMultExpr.h:236
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
ResultType::ElementType ElementType
Resulting element type.
Definition: TSMatTSMatMultExpr.h:149
Header file for the isDefault shim.
MT2::ResultType RT2
Result type of the right-hand side sparse matrix expression.
Definition: TSMatTSMatMultExpr.h:115
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
const ResultType CompositeType
Data type for composite expression templates.
Definition: TSMatTSMatMultExpr.h:151
Header file for the RemoveReference type trait.
MT1::CompositeType CT1
Composite type of the left-hand side sparse matrix expression.
Definition: TSMatTSMatMultExpr.h:116
Header file for the IsDenseVector type trait.
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: TSMatTSMatMultExpr.h:312
Header file for the IsComputation type trait class.
Header file for the IsBuiltin type trait.
#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.
SelectType< IsExpression< MT2 >::value, const MT2, const MT2 & >::Type RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: TSMatTSMatMultExpr.h:157
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
#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 TSMatSVecMultExprTrait class template.
Header file for the FunctionTrace class.