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>
55 #include <blaze/math/Infinity.h>
57 #include <blaze/math/shims/Reset.h>
85 #include <blaze/util/Assert.h>
86 #include <blaze/util/Byte.h>
87 #include <blaze/util/DisableIf.h>
88 #include <blaze/util/EnableIf.h>
89 #include <blaze/util/InvalidType.h>
91 #include <blaze/util/SelectType.h>
92 #include <blaze/util/Types.h>
94 #include <blaze/util/Unused.h>
96 
97 
98 namespace blaze {
99 
100 //=================================================================================================
101 //
102 // CLASS SMATSMATMULTEXPR
103 //
104 //=================================================================================================
105 
106 //*************************************************************************************************
113 template< typename MT1 // Type of the left-hand side sparse matrix
114  , typename MT2 > // Type of the right-hand side sparse matrix
115 class SMatSMatMultExpr : public SparseMatrix< SMatSMatMultExpr<MT1,MT2>, false >
116  , private MatMatMultExpr
117  , private Computation
118 {
119  private:
120  //**Type definitions****************************************************************************
121  typedef typename MT1::ResultType RT1;
122  typedef typename MT2::ResultType RT2;
123  typedef typename MT1::CompositeType CT1;
124  typedef typename MT2::CompositeType CT2;
125  //**********************************************************************************************
126 
127  //**********************************************************************************************
129  enum { evaluateLeft = RequiresEvaluation<MT1>::value };
130  //**********************************************************************************************
131 
132  //**********************************************************************************************
134  enum { evaluateRight = RequiresEvaluation<MT2>::value };
135  //**********************************************************************************************
136 
137  //**********************************************************************************************
139 
144  template< typename T1, typename T2, typename T3 >
145  struct CanExploitSymmetry {
146  enum { value = IsColumnMajorMatrix<T1>::value &&
147  IsSymmetric<T2>::value && IsSymmetric<T3>::value };
148  };
150  //**********************************************************************************************
151 
152  //**********************************************************************************************
154 
159  template< typename T1, typename T2, typename T3 >
160  struct IsEvaluationRequired {
161  enum { value = ( evaluateLeft || evaluateRight ) &&
162  !CanExploitSymmetry<T1,T2,T3>::value };
163  };
165  //**********************************************************************************************
166 
167  public:
168  //**Type definitions****************************************************************************
174  typedef const ElementType ReturnType;
175  typedef const ResultType CompositeType;
176 
178  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
179 
181  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
182  //**********************************************************************************************
183 
184  //**Compilation flags***************************************************************************
186  enum { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
187  !evaluateRight && MT2::smpAssignable };
188  //**********************************************************************************************
189 
190  //**Constructor*********************************************************************************
196  explicit inline SMatSMatMultExpr( const MT1& lhs, const MT2& rhs )
197  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
198  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
199  {
200  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
201  }
202  //**********************************************************************************************
203 
204  //**Access operator*****************************************************************************
211  inline ReturnType operator()( size_t i, size_t j ) const {
212  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
213  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
214 
216 
217  ElementType tmp = ElementType();
218 
219  // Early exit
220  if( lhs_.columns() == 0UL )
221  return tmp;
222 
223  // Fast computation in case the left-hand side sparse matrix directly provides iterators
225  {
226  // Evaluation of the left-hand side sparse matrix operand
227  CT1 A( lhs_ );
228 
229  const ConstIterator end( A.end(i) );
230  ConstIterator element( A.begin(i) );
231 
232  // Early exit in case row i is empty
233  if( element == end )
234  return tmp;
235 
236  // Calculating element (i,j)
237  tmp = element->value() * rhs_(element->index(),j);
238  ++element;
239  for( ; element!=end; ++element )
240  tmp += element->value() * rhs_(element->index(),j);
241  }
242 
243  // Default computation in case the left-hand side sparse matrix doesn't provide iterators
244  else {
245  tmp = lhs_(i,0UL) * rhs_(0UL,j);
246  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
247  tmp += lhs_(i,k) * rhs_(k,j);
248  }
249  }
250 
251  return tmp;
252  }
253  //**********************************************************************************************
254 
255  //**Rows function*******************************************************************************
260  inline size_t rows() const {
261  return lhs_.rows();
262  }
263  //**********************************************************************************************
264 
265  //**Columns function****************************************************************************
270  inline size_t columns() const {
271  return rhs_.columns();
272  }
273  //**********************************************************************************************
274 
275  //**NonZeros function***************************************************************************
280  inline size_t nonZeros() const {
281  return 0UL;
282  }
283  //**********************************************************************************************
284 
285  //**NonZeros function***************************************************************************
291  inline size_t nonZeros( size_t i ) const {
292  UNUSED_PARAMETER( i );
293  return 0UL;
294  }
295  //**********************************************************************************************
296 
297  //**Left operand access*************************************************************************
302  inline LeftOperand leftOperand() const {
303  return lhs_;
304  }
305  //**********************************************************************************************
306 
307  //**Right operand access************************************************************************
312  inline RightOperand rightOperand() const {
313  return rhs_;
314  }
315  //**********************************************************************************************
316 
317  //**********************************************************************************************
323  template< typename T >
324  inline bool canAlias( const T* alias ) const {
325  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
326  }
327  //**********************************************************************************************
328 
329  //**********************************************************************************************
335  template< typename T >
336  inline bool isAliased( const T* alias ) const {
337  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
338  }
339  //**********************************************************************************************
340 
341  //**********************************************************************************************
346  inline bool canSMPAssign() const {
347  return ( rows() > SMP_SMATSMATMULT_THRESHOLD );
348  }
349  //**********************************************************************************************
350 
351  private:
352  //**Member variables****************************************************************************
355  //**********************************************************************************************
356 
357  //**Assignment to dense matrices****************************************************************
370  template< typename MT // Type of the target dense matrix
371  , bool SO > // Storage order of the target dense matrix
372  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
373  assign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
374  {
376 
377  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
378  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
379 
380  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
381  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
382 
383  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
384  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
385  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
386  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
387  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
388  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
389 
390  SMatSMatMultExpr::selectAssignKernel( ~lhs, A, B );
391  }
393  //**********************************************************************************************
394 
395  //**Default assignment to dense matrices********************************************************
408  template< typename MT3 // Type of the left-hand side target matrix
409  , typename MT4 // Type of the left-hand side matrix operand
410  , typename MT5 > // Type of the right-hand side matrix operand
411  static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
412  {
413  typedef typename MT4::ConstIterator LeftIterator;
414  typedef typename MT5::ConstIterator RightIterator;
415 
416  for( size_t i=0UL; i<C.rows(); ++i ) {
417  const LeftIterator lend( A.end(i) );
418  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
419  const RightIterator rend( B.end( lelem->index() ) );
420  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem )
421  {
423  isDefault( C(i,relem->index()) ) ) {
424  C(i,relem->index()) = lelem->value() * relem->value();
425  }
426  else {
427  C(i,relem->index()) += lelem->value() * relem->value();
428  }
429  }
430  }
431  }
432  }
434  //**********************************************************************************************
435 
436  //**Assignment to row-major sparse matrices*****************************************************
449  template< typename MT > // Type of the target sparse matrix
450  friend inline void assign( SparseMatrix<MT,false>& lhs, const SMatSMatMultExpr& rhs )
451  {
453 
454  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
455  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
456 
457  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
458  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
459 
460  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
461  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
462 
463  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
464  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
465  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
466  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
467  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
468  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
469 
470  // (Over-)Estimating the number of non-zero entries in the resulting matrix
471  size_t nonzeros( 0UL );
472 
473  for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
474  const LeftIterator lend( A.end(i) );
475  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
476  nonzeros += B.nonZeros( lelem->index() );
477  }
478  }
479 
480  if( nonzeros > (~lhs).rows() * (~lhs).columns() ) {
481  nonzeros = (~lhs).rows() * (~lhs).columns();
482  }
483 
484  (~lhs).reserve( nonzeros );
485  nonzeros = 0UL;
486 
487  // Performing the matrix-matrix multiplication
488  std::vector<ElementType> values ( (~lhs).columns(), ElementType() );
489  std::vector<byte> valid ( (~lhs).columns(), 0 );
490  std::vector<size_t> indices( (~lhs).columns(), 0UL );
491  size_t minIndex( inf ), maxIndex( 0UL );
492 
493  for( size_t i=0UL; i<(~lhs).rows(); ++i )
494  {
495  const LeftIterator lend( A.end(i) );
496  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem )
497  {
498  const RightIterator rend( B.end( lelem->index() ) );
499  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem )
500  {
501  if( !valid[relem->index()] ) {
502  values[relem->index()] = lelem->value() * relem->value();
503  valid [relem->index()] = 1;
504  indices[nonzeros] = relem->index();
505  ++nonzeros;
506  if( relem->index() < minIndex ) minIndex = relem->index();
507  if( relem->index() > maxIndex ) maxIndex = relem->index();
508  }
509  else {
510  values[relem->index()] += lelem->value() * relem->value();
511  }
512  }
513  }
514 
515  BLAZE_INTERNAL_ASSERT( nonzeros <= (~lhs).columns(), "Invalid number of non-zero elements" );
516 
517  if( nonzeros > 0UL )
518  {
519  BLAZE_INTERNAL_ASSERT( minIndex <= maxIndex, "Invalid index detected" );
520 
521  if( ( nonzeros + nonzeros ) < ( maxIndex - minIndex ) )
522  {
523  std::sort( indices.begin(), indices.begin() + nonzeros );
524 
525  for( size_t j=0UL; j<nonzeros; ++j )
526  {
527  const size_t index( indices[j] );
528  if( !isDefault( values[index] ) ) {
529  (~lhs).append( i, index, values[index] );
530  reset( values[index] );
531  }
532 
533  reset( valid [index] );
534  }
535  }
536  else {
537  for( size_t j=minIndex; j<=maxIndex; ++j )
538  {
539  if( !isDefault( values[j] ) ) {
540  (~lhs).append( i, j, values[j] );
541  reset( values[j] );
542  }
543 
544  reset( valid [j] );
545  }
546  }
547 
548  nonzeros = 0UL;
549  minIndex = inf;
550  maxIndex = 0UL;
551  }
552 
553  (~lhs).finalize( i );
554  }
555  }
557  //**********************************************************************************************
558 
559  //**Assignment to column-major sparse matrices**************************************************
572  template< typename MT > // Type of the target sparse matrix
573  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
574  assign( SparseMatrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
575  {
577 
579 
580  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
581  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
582 
585 
586  const ResultType tmp( serial( rhs ) );
587  (~lhs).reserve( tmp.nonZeros() );
588  assign( ~lhs, tmp );
589  }
591  //**********************************************************************************************
592 
593  //**Restructuring assignment to column-major matrices*******************************************
608  template< typename MT > // Type of the target matrix
609  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
610  assign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
611  {
613 
615 
616  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
617  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
618 
619  assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
620  }
622  //**********************************************************************************************
623 
624  //**Addition assignment to dense matrices*******************************************************
637  template< typename MT // Type of the target dense matrix
638  , bool SO > // Storage order of the target dense matarix
639  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
640  addAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
641  {
643 
644  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
645  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
646 
647  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
648  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
649 
650  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
651  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
652  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
653  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
654  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
655  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
656 
657  SMatSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
658  }
660  //**********************************************************************************************
661 
662  //**Default addition assignment to dense matrices***********************************************
676  template< typename MT3 // Type of the left-hand side target matrix
677  , typename MT4 // Type of the left-hand side matrix operand
678  , typename MT5 > // Type of the right-hand side matrix operand
679  static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
680  {
681  typedef typename MT4::ConstIterator LeftIterator;
682  typedef typename MT5::ConstIterator RightIterator;
683 
684  for( size_t i=0UL; i<C.rows(); ++i ) {
685  const LeftIterator lend( A.end(i) );
686  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
687  const RightIterator rend( B.end( lelem->index() ) );
688  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem ) {
689  C(i,relem->index()) += lelem->value() * relem->value();
690  }
691  }
692  }
693  }
695  //**********************************************************************************************
696 
697  //**Restructuring addition assignment to column-major matrices**********************************
712  template< typename MT > // Type of the target matrix
713  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
714  addAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
715  {
717 
719 
720  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
721  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
722 
723  addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
724  }
726  //**********************************************************************************************
727 
728  //**Addition assignment to sparse matrices******************************************************
729  // No special implementation for the addition assignment to sparse matrices.
730  //**********************************************************************************************
731 
732  //**Subtraction assignment to dense matrices****************************************************
745  template< typename MT // Type of the target dense matrix
746  , bool SO > // Storage order of the target dense matrix
747  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
748  subAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
749  {
751 
752  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
753  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
754 
755  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
756  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
757 
758  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
759  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
760  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
761  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
762  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
763  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
764 
765  SMatSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
766  }
768  //**********************************************************************************************
769 
770  //**Default subtraction assignment to dense matrices********************************************
784  template< typename MT3 // Type of the left-hand side target matrix
785  , typename MT4 // Type of the left-hand side matrix operand
786  , typename MT5 > // Type of the right-hand side matrix operand
787  static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
788  {
789  typedef typename MT4::ConstIterator LeftIterator;
790  typedef typename MT5::ConstIterator RightIterator;
791 
792  for( size_t i=0UL; i<C.rows(); ++i ) {
793  const LeftIterator lend( A.end(i) );
794  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
795  const RightIterator rend( B.end( lelem->index() ) );
796  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem ) {
797  C(i,relem->index()) -= lelem->value() * relem->value();
798  }
799  }
800  }
801  }
803  //**********************************************************************************************
804 
805  //**Restructuring subtraction assignment to column-major matrices*******************************
820  template< typename MT > // Type of the target matrix
821  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
822  subAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
823  {
825 
827 
828  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
829  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
830 
831  subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
832  }
834  //**********************************************************************************************
835 
836  //**Subtraction assignment to sparse matrices***************************************************
837  // No special implementation for the subtraction assignment to sparse matrices.
838  //**********************************************************************************************
839 
840  //**Multiplication assignment to dense matrices*************************************************
841  // No special implementation for the multiplication assignment to dense matrices.
842  //**********************************************************************************************
843 
844  //**Multiplication assignment to sparse matrices************************************************
845  // No special implementation for the multiplication assignment to sparse matrices.
846  //**********************************************************************************************
847 
848  //**SMP assignment to matrices******************************************************************
863  template< typename MT // Type of the target matrix
864  , bool SO > // Storage order of the target matrix
865  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
866  smpAssign( Matrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
867  {
869 
870  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
871  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
872 
873  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
874  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
875 
876  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
877  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
878  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
879  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
880  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
881  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
882 
883  smpAssign( ~lhs, A * B );
884  }
886  //**********************************************************************************************
887 
888  //**Restructuring SMP assignment to column-major matrices***************************************
903  template< typename MT > // Type of the target matrix
904  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
905  smpAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
906  {
908 
910 
911  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
912  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
913 
914  smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
915  }
917  //**********************************************************************************************
918 
919  //**SMP addition assignment to dense matrices***************************************************
935  template< typename MT // Type of the target dense matrix
936  , bool SO > // Storage order of the target dense matarix
937  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
938  smpAddAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
939  {
941 
942  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
943  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
944 
945  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
946  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
947 
948  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
949  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
950  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
951  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
952  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
953  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
954 
955  smpAddAssign( ~lhs, A * B );
956  }
958  //**********************************************************************************************
959 
960  //**Restructuring SMP addition assignment to column-major matrices******************************
975  template< typename MT > // Type of the target matrix
976  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
977  smpAddAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
978  {
980 
982 
983  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
984  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
985 
986  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
987  }
989  //**********************************************************************************************
990 
991  //**SMP addition assignment to sparse matrices**************************************************
992  // No special implementation for the SMP addition assignment to sparse matrices.
993  //**********************************************************************************************
994 
995  //**SMP subtraction assignment to dense matrices************************************************
1011  template< typename MT // Type of the target dense matrix
1012  , bool SO > // Storage order of the target dense matrix
1013  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1014  smpSubAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
1015  {
1017 
1018  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1019  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1020 
1021  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
1022  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1023 
1024  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1025  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1026  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1027  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1028  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1029  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1030 
1031  smpSubAssign( ~lhs, A * B );
1032  }
1034  //**********************************************************************************************
1035 
1036  //**Restructuring SMP subtraction assignment to column-major matrices***************************
1051  template< typename MT > // Type of the target matrix
1052  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1053  smpSubAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
1054  {
1056 
1058 
1059  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1060  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1061 
1062  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1063  }
1065  //**********************************************************************************************
1066 
1067  //**SMP subtraction assignment to sparse matrices***********************************************
1068  // No special implementation for the SMP subtraction assignment to sparse matrices.
1069  //**********************************************************************************************
1070 
1071  //**SMP multiplication assignment to dense matrices*********************************************
1072  // No special implementation for the SMP multiplication assignment to dense matrices.
1073  //**********************************************************************************************
1074 
1075  //**SMP multiplication assignment to sparse matrices********************************************
1076  // No special implementation for the SMP multiplication assignment to sparse matrices.
1077  //**********************************************************************************************
1078 
1079  //**Compile time checks*************************************************************************
1087  //**********************************************************************************************
1088 };
1089 //*************************************************************************************************
1090 
1091 
1092 
1093 
1094 //=================================================================================================
1095 //
1096 // GLOBAL BINARY ARITHMETIC OPERATORS
1097 //
1098 //=================================================================================================
1099 
1100 //*************************************************************************************************
1127 template< typename T1 // Type of the left-hand side sparse matrix
1128  , typename T2 > // Type of the right-hand side sparse matrix
1129 inline const SMatSMatMultExpr<T1,T2>
1131 {
1133 
1134  if( (~lhs).columns() != (~rhs).rows() )
1135  throw std::invalid_argument( "Matrix sizes do not match" );
1136 
1137  return SMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
1138 }
1139 //*************************************************************************************************
1140 
1141 
1142 
1143 
1144 //=================================================================================================
1145 //
1146 // ROWS SPECIALIZATIONS
1147 //
1148 //=================================================================================================
1149 
1150 //*************************************************************************************************
1152 template< typename MT1, typename MT2 >
1153 struct Rows< SMatSMatMultExpr<MT1,MT2> >
1154  : public Rows<MT1>
1155 {};
1157 //*************************************************************************************************
1158 
1159 
1160 
1161 
1162 //=================================================================================================
1163 //
1164 // COLUMNS SPECIALIZATIONS
1165 //
1166 //=================================================================================================
1167 
1168 //*************************************************************************************************
1170 template< typename MT1, typename MT2 >
1171 struct Columns< SMatSMatMultExpr<MT1,MT2> >
1172  : public Columns<MT2>
1173 {};
1175 //*************************************************************************************************
1176 
1177 
1178 
1179 
1180 //=================================================================================================
1181 //
1182 // ISLOWER SPECIALIZATIONS
1183 //
1184 //=================================================================================================
1185 
1186 //*************************************************************************************************
1188 template< typename MT1, typename MT2 >
1189 struct IsLower< SMatSMatMultExpr<MT1,MT2> >
1190  : public IsTrue< IsLower<MT1>::value && IsLower<MT2>::value >
1191 {};
1193 //*************************************************************************************************
1194 
1195 
1196 
1197 
1198 //=================================================================================================
1199 //
1200 // ISUPPER SPECIALIZATIONS
1201 //
1202 //=================================================================================================
1203 
1204 //*************************************************************************************************
1206 template< typename MT1, typename MT2 >
1207 struct IsUpper< SMatSMatMultExpr<MT1,MT2> >
1208  : public IsTrue< IsUpper<MT1>::value && IsUpper<MT2>::value >
1209 {};
1211 //*************************************************************************************************
1212 
1213 
1214 
1215 
1216 //=================================================================================================
1217 //
1218 // EXPRESSION TRAIT SPECIALIZATIONS
1219 //
1220 //=================================================================================================
1221 
1222 //*************************************************************************************************
1224 template< typename MT1, typename MT2, typename VT >
1225 struct SMatDVecMultExprTrait< SMatSMatMultExpr<MT1,MT2>, VT >
1226 {
1227  public:
1228  //**********************************************************************************************
1229  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1230  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1231  IsDenseVector<VT>::value && IsColumnVector<VT>::value
1232  , typename SMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
1233  , INVALID_TYPE >::Type Type;
1234  //**********************************************************************************************
1235 };
1237 //*************************************************************************************************
1238 
1239 
1240 //*************************************************************************************************
1242 template< typename MT1, typename MT2, typename VT >
1243 struct SMatSVecMultExprTrait< SMatSMatMultExpr<MT1,MT2>, VT >
1244 {
1245  public:
1246  //**********************************************************************************************
1247  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1248  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1249  IsSparseVector<VT>::value && IsColumnVector<VT>::value
1250  , typename SMatSVecMultExprTrait< MT1, typename SMatSVecMultExprTrait<MT2,VT>::Type >::Type
1251  , INVALID_TYPE >::Type Type;
1252  //**********************************************************************************************
1253 };
1255 //*************************************************************************************************
1256 
1257 
1258 //*************************************************************************************************
1260 template< typename VT, typename MT1, typename MT2 >
1261 struct TDVecSMatMultExprTrait< VT, SMatSMatMultExpr<MT1,MT2> >
1262 {
1263  public:
1264  //**********************************************************************************************
1265  typedef typename SelectType< IsDenseVector<VT>::value && IsRowVector<VT>::value &&
1266  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1267  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1268  , typename TDVecSMatMultExprTrait< typename TDVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1269  , INVALID_TYPE >::Type Type;
1270  //**********************************************************************************************
1271 };
1273 //*************************************************************************************************
1274 
1275 
1276 //*************************************************************************************************
1278 template< typename VT, typename MT1, typename MT2 >
1279 struct TSVecSMatMultExprTrait< VT, SMatSMatMultExpr<MT1,MT2> >
1280 {
1281  public:
1282  //**********************************************************************************************
1283  typedef typename SelectType< IsSparseVector<VT>::value && IsRowVector<VT>::value &&
1284  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1285  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1286  , typename TSVecSMatMultExprTrait< typename TSVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1287  , INVALID_TYPE >::Type Type;
1288  //**********************************************************************************************
1289 };
1291 //*************************************************************************************************
1292 
1293 
1294 //*************************************************************************************************
1296 template< typename MT1, typename MT2, bool AF >
1297 struct SubmatrixExprTrait< SMatSMatMultExpr<MT1,MT2>, AF >
1298 {
1299  public:
1300  //**********************************************************************************************
1301  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT1,AF>::Type
1302  , typename SubmatrixExprTrait<const MT2,AF>::Type >::Type Type;
1303  //**********************************************************************************************
1304 };
1306 //*************************************************************************************************
1307 
1308 
1309 //*************************************************************************************************
1311 template< typename MT1, typename MT2 >
1312 struct RowExprTrait< SMatSMatMultExpr<MT1,MT2> >
1313 {
1314  public:
1315  //**********************************************************************************************
1316  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
1317  //**********************************************************************************************
1318 };
1320 //*************************************************************************************************
1321 
1322 
1323 //*************************************************************************************************
1325 template< typename MT1, typename MT2 >
1326 struct ColumnExprTrait< SMatSMatMultExpr<MT1,MT2> >
1327 {
1328  public:
1329  //**********************************************************************************************
1330  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
1331  //**********************************************************************************************
1332 };
1334 //*************************************************************************************************
1335 
1336 } // namespace blaze
1337 
1338 #endif
Header file for the SMatDVecMultExprTrait class template.
Header file for the Rows type trait.
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:4838
BLAZE_ALWAYS_INLINE MT::Iterator end(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator just past the last element of row/column i.
Definition: Matrix.h:258
MultTrait< RT1, RT2 >::Type ResultType
Result type for expression template evaluations.
Definition: SMatSMatMultExpr.h:170
Header file for the IsSparseMatrix type trait.
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:205
Header file for the ColumnExprTrait class template.
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: SMatSMatMultExpr.h:346
Header file for the IsColumnMajorMatrix type trait.
ResultType::ElementType ElementType
Resulting element type.
Definition: SMatSMatMultExpr.h:173
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2478
RightOperand rightOperand() const
Returns the right-hand side sparse matrix operand.
Definition: SMatSMatMultExpr.h:312
Header file for the IsRowVector type trait.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:257
void UNUSED_PARAMETER(const T1 &)
Suppression of unused parameter warnings.
Definition: Unused.h:81
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:695
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:280
MT1::CompositeType CT1
Composite type of the left-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:123
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:171
MT1::ResultType RT1
Result type of the left-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:121
Header file for the SparseMatrix base class.
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: SMatSMatMultExpr.h:172
Constraint on the data type.
Header file for the MultExprTrait class template.
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:174
Compile time type selection.The SelectType class template selects one of the two given types T1 and T...
Definition: SelectType.h:59
Header file for the DisableIf class template.
size_t rows() const
Returns the current number of rows of the matrix.
Definition: SMatSMatMultExpr.h:260
size_t columns() const
Returns the current number of columns of the matrix.
Definition: SMatSMatMultExpr.h:270
Header file for the multiplication trait.
Header file for the IsSymmetric type trait.
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: SMatSMatMultExpr.h:354
SMatSMatMultExpr< MT1, MT2 > This
Type of this SMatSMatMultExpr instance.
Definition: SMatSMatMultExpr.h:169
SelectType< IsExpression< MT1 >::value, const MT1, const MT1 & >::Type LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:178
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2482
BLAZE_ALWAYS_INLINE 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:635
Header file for the Columns type trait.
Numerical infinity for built-in data types.
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: SMatSMatMultExpr.h:324
Header file for the IsLower type trait.
LeftOperand leftOperand() const
Returns the left-hand side sparse matrix operand.
Definition: SMatSMatMultExpr.h:302
Header file for the SMatSVecMultExprTrait class template.
SMatSMatMultExpr(const MT1 &lhs, const MT2 &rhs)
Constructor for the SMatSMatMultExpr class.
Definition: SMatSMatMultExpr.h:196
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: SMatSMatMultExpr.h:336
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.
#define BLAZE_CONSTRAINT_MUST_FORM_VALID_MATMATMULTEXPR(T1, T2)
Constraint on the data type.In case the given data types T1 and T2 do not form a valid matrix/matrix ...
Definition: MatMatMultExpr.h:165
Header file for the byte type.
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:291
EnableIf< IsDenseMatrix< MT1 > >::Type smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:160
Header file for the IsSparseVector type trait.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a symmetric matrix type, a compilation error is created.
Definition: Symmetric.h:116
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.
EnableIf< IsDenseMatrix< MT1 > >::Type smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:98
Utility type for generic codes.
Base template for the MultTrait class.
Definition: MultTrait.h:142
BLAZE_ALWAYS_INLINE 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:742
Header file for the reset shim.
Header file for the isDefault shim.
BLAZE_ALWAYS_INLINE bool isDefault(const NonNumericProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: NonNumericProxy.h:874
Constraint on the data type.
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:211
BLAZE_ALWAYS_INLINE void reset(const NonNumericProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: NonNumericProxy.h:833
Header file for the RemoveReference type trait.
Substitution Failure Is Not An Error (SFINAE) class.The DisableIf class template is an auxiliary tool...
Definition: DisableIf.h:184
Header file for the IsDenseVector type trait.
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: SMatSMatMultExpr.h:353
SelectType< IsExpression< MT2 >::value, const MT2, const MT2 & >::Type RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:181
Header file for the IsRowMajorMatrix type trait.
const DMatTransExpr< MT,!SO > trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:932
Header file for the IsComputation type trait class.
MT2::ResultType RT2
Result type of the right-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:122
EnableIf< IsDenseMatrix< MT1 > >::Type smpAddAssign(Matrix< 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:129
#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:2473
Header file for the IsTrue value trait.
Header file for basic type definitions.
Header file for the IsUpper type trait.
Header file for the IsColumnVector type trait.
Constraint on the data type.
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:175
#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.
BLAZE_ALWAYS_INLINE 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:849
MT2::CompositeType CT2
Composite type of the right-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:124