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>
89 #include <blaze/util/Assert.h>
90 #include <blaze/util/Byte.h>
91 #include <blaze/util/DisableIf.h>
92 #include <blaze/util/EnableIf.h>
93 #include <blaze/util/InvalidType.h>
95 #include <blaze/util/mpl/And.h>
96 #include <blaze/util/mpl/Or.h>
97 #include <blaze/util/SelectType.h>
98 #include <blaze/util/Types.h>
100 #include <blaze/util/Unused.h>
102 
103 
104 namespace blaze {
105 
106 //=================================================================================================
107 //
108 // CLASS SMATSMATMULTEXPR
109 //
110 //=================================================================================================
111 
112 //*************************************************************************************************
119 template< typename MT1 // Type of the left-hand side sparse matrix
120  , typename MT2 > // Type of the right-hand side sparse matrix
121 class SMatSMatMultExpr : public SparseMatrix< SMatSMatMultExpr<MT1,MT2>, false >
122  , private MatMatMultExpr
123  , private Computation
124 {
125  private:
126  //**Type definitions****************************************************************************
127  typedef typename MT1::ResultType RT1;
128  typedef typename MT2::ResultType RT2;
129  typedef typename MT1::CompositeType CT1;
130  typedef typename MT2::CompositeType CT2;
131  //**********************************************************************************************
132 
133  //**********************************************************************************************
135  enum { evaluateLeft = RequiresEvaluation<MT1>::value };
136  //**********************************************************************************************
137 
138  //**********************************************************************************************
140  enum { evaluateRight = RequiresEvaluation<MT2>::value };
141  //**********************************************************************************************
142 
143  //**********************************************************************************************
145 
150  template< typename T1, typename T2, typename T3 >
151  struct CanExploitSymmetry {
152  enum { value = IsColumnMajorMatrix<T1>::value &&
153  IsSymmetric<T2>::value && IsSymmetric<T3>::value };
154  };
156  //**********************************************************************************************
157 
158  //**********************************************************************************************
160 
165  template< typename T1, typename T2, typename T3 >
166  struct IsEvaluationRequired {
167  enum { value = ( evaluateLeft || evaluateRight ) &&
168  !CanExploitSymmetry<T1,T2,T3>::value };
169  };
171  //**********************************************************************************************
172 
173  public:
174  //**Type definitions****************************************************************************
180  typedef const ElementType ReturnType;
181  typedef const ResultType CompositeType;
182 
184  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
185 
187  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
188  //**********************************************************************************************
189 
190  //**Compilation flags***************************************************************************
192  enum { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
193  !evaluateRight && MT2::smpAssignable };
194  //**********************************************************************************************
195 
196  //**Constructor*********************************************************************************
202  explicit inline SMatSMatMultExpr( const MT1& lhs, const MT2& rhs )
203  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
204  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
205  {
206  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
207  }
208  //**********************************************************************************************
209 
210  //**Access operator*****************************************************************************
217  inline ReturnType operator()( size_t i, size_t j ) const {
218  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
219  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
220 
222 
223  ElementType tmp = ElementType();
224 
225  // Early exit
226  if( lhs_.columns() == 0UL )
227  return tmp;
228 
229  // Fast computation in case the left-hand side sparse matrix directly provides iterators
231  {
232  // Evaluation of the left-hand side sparse matrix operand
233  CT1 A( lhs_ );
234 
235  const ConstIterator end( ( IsUpper<MT2>::value )?( A.upperBound(i,j) ):( A.end(i) ) );
236  ConstIterator element( ( IsLower<MT2>::value )?( A.lowerBound(i,j) ):( A.begin(i) ) );
237 
238  // Early exit in case row i is empty
239  if( element == end )
240  return tmp;
241 
242  // Calculating element (i,j)
243  tmp = element->value() * rhs_(element->index(),j);
244  ++element;
245  for( ; element!=end; ++element ) {
246  tmp += element->value() * rhs_(element->index(),j);
247  }
248  }
249 
250  // Default computation in case the left-hand side sparse matrix doesn't provide iterators
251  else {
252  const size_t kbegin( max( ( IsUpper<MT1>::value )?( i ):( 0UL ),
253  ( IsLower<MT2>::value )?( j ):( 0UL ) ) );
254  const size_t kend ( min( ( IsLower<MT1>::value )?( i+1UL ):( lhs_.columns() ),
255  ( IsUpper<MT2>::value )?( j+1UL ):( lhs_.columns() ) ) );
256 
257  tmp = lhs_(i,kbegin) * rhs_(kbegin,j);
258  for( size_t k=kbegin+1UL; k<kend; ++k ) {
259  tmp += lhs_(i,k) * rhs_(k,j);
260  }
261  }
262 
263  return tmp;
264  }
265  //**********************************************************************************************
266 
267  //**Rows function*******************************************************************************
272  inline size_t rows() const {
273  return lhs_.rows();
274  }
275  //**********************************************************************************************
276 
277  //**Columns function****************************************************************************
282  inline size_t columns() const {
283  return rhs_.columns();
284  }
285  //**********************************************************************************************
286 
287  //**NonZeros function***************************************************************************
292  inline size_t nonZeros() const {
293  return 0UL;
294  }
295  //**********************************************************************************************
296 
297  //**NonZeros function***************************************************************************
303  inline size_t nonZeros( size_t i ) const {
304  UNUSED_PARAMETER( i );
305  return 0UL;
306  }
307  //**********************************************************************************************
308 
309  //**Left operand access*************************************************************************
314  inline LeftOperand leftOperand() const {
315  return lhs_;
316  }
317  //**********************************************************************************************
318 
319  //**Right operand access************************************************************************
324  inline RightOperand rightOperand() const {
325  return rhs_;
326  }
327  //**********************************************************************************************
328 
329  //**********************************************************************************************
335  template< typename T >
336  inline bool canAlias( const T* alias ) const {
337  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
338  }
339  //**********************************************************************************************
340 
341  //**********************************************************************************************
347  template< typename T >
348  inline bool isAliased( const T* alias ) const {
349  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
350  }
351  //**********************************************************************************************
352 
353  //**********************************************************************************************
358  inline bool canSMPAssign() const {
359  return ( rows() > SMP_SMATSMATMULT_THRESHOLD );
360  }
361  //**********************************************************************************************
362 
363  private:
364  //**Member variables****************************************************************************
365  LeftOperand lhs_;
366  RightOperand rhs_;
367  //**********************************************************************************************
368 
369  //**Assignment to dense matrices****************************************************************
382  template< typename MT // Type of the target dense matrix
383  , bool SO > // Storage order of the target dense matrix
384  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
385  assign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
386  {
388 
389  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
390  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
391 
392  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
393  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
394 
395  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
396  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
397  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
398  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
399  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
400  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
401 
402  SMatSMatMultExpr::selectAssignKernel( ~lhs, A, B );
403  }
405  //**********************************************************************************************
406 
407  //**Default assignment to dense matrices********************************************************
420  template< typename MT3 // Type of the left-hand side target matrix
421  , typename MT4 // Type of the left-hand side matrix operand
422  , typename MT5 > // Type of the right-hand side matrix operand
423  static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
424  {
425  typedef typename MT4::ConstIterator LeftIterator;
426  typedef typename MT5::ConstIterator RightIterator;
427 
428  for( size_t i=0UL; i<C.rows(); ++i ) {
429  const LeftIterator lend( A.end(i) );
430  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
431  const RightIterator rend( B.end( lelem->index() ) );
432  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem )
433  {
435  isDefault( C(i,relem->index()) ) ) {
436  C(i,relem->index()) = lelem->value() * relem->value();
437  }
438  else {
439  C(i,relem->index()) += lelem->value() * relem->value();
440  }
441  }
442  }
443  }
444  }
446  //**********************************************************************************************
447 
448  //**Assignment to row-major sparse matrices*****************************************************
461  template< typename MT > // Type of the target sparse matrix
462  friend inline void assign( SparseMatrix<MT,false>& lhs, const SMatSMatMultExpr& rhs )
463  {
465 
466  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
467  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
468 
469  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
470  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
471 
472  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
473  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
474 
475  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
476  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
477  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
478  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
479  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
480  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
481 
482  // (Over-)Estimating the number of non-zero entries in the resulting matrix
483  size_t nonzeros( 0UL );
484 
485  for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
486  const LeftIterator lend( A.end(i) );
487  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
488  nonzeros += B.nonZeros( lelem->index() );
489  }
490  }
491 
492  if( nonzeros > (~lhs).rows() * (~lhs).columns() ) {
493  nonzeros = (~lhs).rows() * (~lhs).columns();
494  }
495 
496  (~lhs).reserve( nonzeros );
497  nonzeros = 0UL;
498 
499  // Performing the matrix-matrix multiplication
500  std::vector<ElementType> values ( (~lhs).columns(), ElementType() );
501  std::vector<byte> valid ( (~lhs).columns(), 0 );
502  std::vector<size_t> indices( (~lhs).columns(), 0UL );
503  size_t minIndex( inf ), maxIndex( 0UL );
504 
505  for( size_t i=0UL; i<(~lhs).rows(); ++i )
506  {
507  const LeftIterator lend( A.end(i) );
508  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem )
509  {
510  const RightIterator rend( B.end( lelem->index() ) );
511  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem )
512  {
513  if( !valid[relem->index()] ) {
514  values[relem->index()] = lelem->value() * relem->value();
515  valid [relem->index()] = 1;
516  indices[nonzeros] = relem->index();
517  ++nonzeros;
518  if( relem->index() < minIndex ) minIndex = relem->index();
519  if( relem->index() > maxIndex ) maxIndex = relem->index();
520  }
521  else {
522  values[relem->index()] += lelem->value() * relem->value();
523  }
524  }
525  }
526 
527  BLAZE_INTERNAL_ASSERT( nonzeros <= (~lhs).columns(), "Invalid number of non-zero elements" );
528 
529  if( nonzeros > 0UL )
530  {
531  BLAZE_INTERNAL_ASSERT( minIndex <= maxIndex, "Invalid index detected" );
532 
533  if( ( nonzeros + nonzeros ) < ( maxIndex - minIndex ) )
534  {
535  std::sort( indices.begin(), indices.begin() + nonzeros );
536 
537  for( size_t j=0UL; j<nonzeros; ++j )
538  {
539  const size_t index( indices[j] );
540  if( !isDefault( values[index] ) ) {
541  (~lhs).append( i, index, values[index] );
542  reset( values[index] );
543  }
544 
545  reset( valid [index] );
546  }
547  }
548  else {
549  for( size_t j=minIndex; j<=maxIndex; ++j )
550  {
551  if( !isDefault( values[j] ) ) {
552  (~lhs).append( i, j, values[j] );
553  reset( values[j] );
554  }
555 
556  reset( valid [j] );
557  }
558  }
559 
560  nonzeros = 0UL;
561  minIndex = inf;
562  maxIndex = 0UL;
563  }
564 
565  (~lhs).finalize( i );
566  }
567  }
569  //**********************************************************************************************
570 
571  //**Assignment to column-major sparse matrices**************************************************
584  template< typename MT > // Type of the target sparse matrix
585  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
586  assign( SparseMatrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
587  {
589 
591 
592  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
593  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
594 
597 
598  const ResultType tmp( serial( rhs ) );
599  (~lhs).reserve( tmp.nonZeros() );
600  assign( ~lhs, tmp );
601  }
603  //**********************************************************************************************
604 
605  //**Restructuring assignment to column-major matrices*******************************************
620  template< typename MT > // Type of the target matrix
621  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
622  assign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
623  {
625 
627 
628  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
629  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
630 
631  assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
632  }
634  //**********************************************************************************************
635 
636  //**Addition assignment to dense matrices*******************************************************
649  template< typename MT // Type of the target dense matrix
650  , bool SO > // Storage order of the target dense matarix
651  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
652  addAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
653  {
655 
656  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
657  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
658 
659  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
660  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
661 
662  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
663  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
664  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
665  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
666  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
667  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
668 
669  SMatSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
670  }
672  //**********************************************************************************************
673 
674  //**Default addition assignment to dense matrices***********************************************
688  template< typename MT3 // Type of the left-hand side target matrix
689  , typename MT4 // Type of the left-hand side matrix operand
690  , typename MT5 > // Type of the right-hand side matrix operand
691  static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
692  {
693  typedef typename MT4::ConstIterator LeftIterator;
694  typedef typename MT5::ConstIterator RightIterator;
695 
696  for( size_t i=0UL; i<C.rows(); ++i ) {
697  const LeftIterator lend( A.end(i) );
698  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
699  const RightIterator rend( B.end( lelem->index() ) );
700  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem ) {
701  C(i,relem->index()) += lelem->value() * relem->value();
702  }
703  }
704  }
705  }
707  //**********************************************************************************************
708 
709  //**Restructuring addition assignment to column-major matrices**********************************
724  template< typename MT > // Type of the target matrix
725  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
726  addAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
727  {
729 
731 
732  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
733  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
734 
735  addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
736  }
738  //**********************************************************************************************
739 
740  //**Addition assignment to sparse matrices******************************************************
741  // No special implementation for the addition assignment to sparse matrices.
742  //**********************************************************************************************
743 
744  //**Subtraction assignment to dense matrices****************************************************
757  template< typename MT // Type of the target dense matrix
758  , bool SO > // Storage order of the target dense matrix
759  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
760  subAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
761  {
763 
764  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
765  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
766 
767  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
768  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
769 
770  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
771  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
772  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
773  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
774  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
775  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
776 
777  SMatSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
778  }
780  //**********************************************************************************************
781 
782  //**Default subtraction assignment to dense matrices********************************************
796  template< typename MT3 // Type of the left-hand side target matrix
797  , typename MT4 // Type of the left-hand side matrix operand
798  , typename MT5 > // Type of the right-hand side matrix operand
799  static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
800  {
801  typedef typename MT4::ConstIterator LeftIterator;
802  typedef typename MT5::ConstIterator RightIterator;
803 
804  for( size_t i=0UL; i<C.rows(); ++i ) {
805  const LeftIterator lend( A.end(i) );
806  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
807  const RightIterator rend( B.end( lelem->index() ) );
808  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem ) {
809  C(i,relem->index()) -= lelem->value() * relem->value();
810  }
811  }
812  }
813  }
815  //**********************************************************************************************
816 
817  //**Restructuring subtraction assignment to column-major matrices*******************************
832  template< typename MT > // Type of the target matrix
833  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
834  subAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
835  {
837 
839 
840  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
841  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
842 
843  subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
844  }
846  //**********************************************************************************************
847 
848  //**Subtraction assignment to sparse matrices***************************************************
849  // No special implementation for the subtraction assignment to sparse matrices.
850  //**********************************************************************************************
851 
852  //**Multiplication assignment to dense matrices*************************************************
853  // No special implementation for the multiplication assignment to dense matrices.
854  //**********************************************************************************************
855 
856  //**Multiplication assignment to sparse matrices************************************************
857  // No special implementation for the multiplication assignment to sparse matrices.
858  //**********************************************************************************************
859 
860  //**SMP assignment to matrices******************************************************************
875  template< typename MT // Type of the target matrix
876  , bool SO > // Storage order of the target matrix
877  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
878  smpAssign( Matrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
879  {
881 
882  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
883  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
884 
885  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
886  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
887 
888  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
889  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
890  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
891  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
892  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
893  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
894 
895  smpAssign( ~lhs, A * B );
896  }
898  //**********************************************************************************************
899 
900  //**Restructuring SMP assignment to column-major matrices***************************************
915  template< typename MT > // Type of the target matrix
916  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
917  smpAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
918  {
920 
922 
923  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
924  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
925 
926  smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
927  }
929  //**********************************************************************************************
930 
931  //**SMP addition assignment to dense matrices***************************************************
947  template< typename MT // Type of the target dense matrix
948  , bool SO > // Storage order of the target dense matarix
949  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
950  smpAddAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
951  {
953 
954  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
955  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
956 
957  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
958  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
959 
960  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
961  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
962  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
963  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
964  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
965  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
966 
967  smpAddAssign( ~lhs, A * B );
968  }
970  //**********************************************************************************************
971 
972  //**Restructuring SMP addition assignment to column-major matrices******************************
987  template< typename MT > // Type of the target matrix
988  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
989  smpAddAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
990  {
992 
994 
995  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
996  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
997 
998  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
999  }
1001  //**********************************************************************************************
1002 
1003  //**SMP addition assignment to sparse matrices**************************************************
1004  // No special implementation for the SMP addition assignment to sparse matrices.
1005  //**********************************************************************************************
1006 
1007  //**SMP subtraction assignment to dense matrices************************************************
1023  template< typename MT // Type of the target dense matrix
1024  , bool SO > // Storage order of the target dense matrix
1025  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1026  smpSubAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
1027  {
1029 
1030  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1031  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1032 
1033  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
1034  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1035 
1036  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1037  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1038  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1039  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1040  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1041  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1042 
1043  smpSubAssign( ~lhs, A * B );
1044  }
1046  //**********************************************************************************************
1047 
1048  //**Restructuring SMP subtraction assignment to column-major matrices***************************
1063  template< typename MT > // Type of the target matrix
1064  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1065  smpSubAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
1066  {
1068 
1070 
1071  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1072  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1073 
1074  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1075  }
1077  //**********************************************************************************************
1078 
1079  //**SMP subtraction assignment to sparse matrices***********************************************
1080  // No special implementation for the SMP subtraction assignment to sparse matrices.
1081  //**********************************************************************************************
1082 
1083  //**SMP multiplication assignment to dense matrices*********************************************
1084  // No special implementation for the SMP multiplication assignment to dense matrices.
1085  //**********************************************************************************************
1086 
1087  //**SMP multiplication assignment to sparse matrices********************************************
1088  // No special implementation for the SMP multiplication assignment to sparse matrices.
1089  //**********************************************************************************************
1090 
1091  //**Compile time checks*************************************************************************
1099  //**********************************************************************************************
1100 };
1101 //*************************************************************************************************
1102 
1103 
1104 
1105 
1106 //=================================================================================================
1107 //
1108 // GLOBAL BINARY ARITHMETIC OPERATORS
1109 //
1110 //=================================================================================================
1111 
1112 //*************************************************************************************************
1139 template< typename T1 // Type of the left-hand side sparse matrix
1140  , typename T2 > // Type of the right-hand side sparse matrix
1141 inline const SMatSMatMultExpr<T1,T2>
1143 {
1145 
1146  if( (~lhs).columns() != (~rhs).rows() )
1147  throw std::invalid_argument( "Matrix sizes do not match" );
1148 
1149  return SMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
1150 }
1151 //*************************************************************************************************
1152 
1153 
1154 
1155 
1156 //=================================================================================================
1157 //
1158 // ROWS SPECIALIZATIONS
1159 //
1160 //=================================================================================================
1161 
1162 //*************************************************************************************************
1164 template< typename MT1, typename MT2 >
1165 struct Rows< SMatSMatMultExpr<MT1,MT2> >
1166  : public Rows<MT1>
1167 {};
1169 //*************************************************************************************************
1170 
1171 
1172 
1173 
1174 //=================================================================================================
1175 //
1176 // COLUMNS SPECIALIZATIONS
1177 //
1178 //=================================================================================================
1179 
1180 //*************************************************************************************************
1182 template< typename MT1, typename MT2 >
1183 struct Columns< SMatSMatMultExpr<MT1,MT2> >
1184  : public Columns<MT2>
1185 {};
1187 //*************************************************************************************************
1188 
1189 
1190 
1191 
1192 //=================================================================================================
1193 //
1194 // ISLOWER SPECIALIZATIONS
1195 //
1196 //=================================================================================================
1197 
1198 //*************************************************************************************************
1200 template< typename MT1, typename MT2 >
1201 struct IsLower< SMatSMatMultExpr<MT1,MT2> >
1202  : public IsTrue< And< IsLower<MT1>, IsLower<MT2> >::value >
1203 {};
1205 //*************************************************************************************************
1206 
1207 
1208 
1209 
1210 //=================================================================================================
1211 //
1212 // ISUNILOWER SPECIALIZATIONS
1213 //
1214 //=================================================================================================
1215 
1216 //*************************************************************************************************
1218 template< typename MT1, typename MT2 >
1219 struct IsUniLower< SMatSMatMultExpr<MT1,MT2> >
1220  : public IsTrue< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
1221 {};
1223 //*************************************************************************************************
1224 
1225 
1226 
1227 
1228 //=================================================================================================
1229 //
1230 // ISSTRICTLYLOWER SPECIALIZATIONS
1231 //
1232 //=================================================================================================
1233 
1234 //*************************************************************************************************
1236 template< typename MT1, typename MT2 >
1237 struct IsStrictlyLower< SMatSMatMultExpr<MT1,MT2> >
1238  : public IsTrue< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
1239  , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
1240 {};
1242 //*************************************************************************************************
1243 
1244 
1245 
1246 
1247 //=================================================================================================
1248 //
1249 // ISUPPER SPECIALIZATIONS
1250 //
1251 //=================================================================================================
1252 
1253 //*************************************************************************************************
1255 template< typename MT1, typename MT2 >
1256 struct IsUpper< SMatSMatMultExpr<MT1,MT2> >
1257  : public IsTrue< And< IsUpper<MT1>, IsUpper<MT2> >::value >
1258 {};
1260 //*************************************************************************************************
1261 
1262 
1263 
1264 
1265 //=================================================================================================
1266 //
1267 // ISUNIUPPER SPECIALIZATIONS
1268 //
1269 //=================================================================================================
1270 
1271 //*************************************************************************************************
1273 template< typename MT1, typename MT2 >
1274 struct IsUniUpper< SMatSMatMultExpr<MT1,MT2> >
1275  : public IsTrue< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
1276 {};
1278 //*************************************************************************************************
1279 
1280 
1281 
1282 
1283 //=================================================================================================
1284 //
1285 // ISSTRICTLYUPPER SPECIALIZATIONS
1286 //
1287 //=================================================================================================
1288 
1289 //*************************************************************************************************
1291 template< typename MT1, typename MT2 >
1292 struct IsStrictlyUpper< SMatSMatMultExpr<MT1,MT2> >
1293  : public IsTrue< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
1294  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
1295 {};
1297 //*************************************************************************************************
1298 
1299 
1300 
1301 
1302 //=================================================================================================
1303 //
1304 // EXPRESSION TRAIT SPECIALIZATIONS
1305 //
1306 //=================================================================================================
1307 
1308 //*************************************************************************************************
1310 template< typename MT1, typename MT2, typename VT >
1311 struct SMatDVecMultExprTrait< SMatSMatMultExpr<MT1,MT2>, VT >
1312 {
1313  public:
1314  //**********************************************************************************************
1315  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1316  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1317  IsDenseVector<VT>::value && IsColumnVector<VT>::value
1318  , typename SMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
1319  , INVALID_TYPE >::Type Type;
1320  //**********************************************************************************************
1321 };
1323 //*************************************************************************************************
1324 
1325 
1326 //*************************************************************************************************
1328 template< typename MT1, typename MT2, typename VT >
1329 struct SMatSVecMultExprTrait< SMatSMatMultExpr<MT1,MT2>, VT >
1330 {
1331  public:
1332  //**********************************************************************************************
1333  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1334  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1335  IsSparseVector<VT>::value && IsColumnVector<VT>::value
1336  , typename SMatSVecMultExprTrait< MT1, typename SMatSVecMultExprTrait<MT2,VT>::Type >::Type
1337  , INVALID_TYPE >::Type Type;
1338  //**********************************************************************************************
1339 };
1341 //*************************************************************************************************
1342 
1343 
1344 //*************************************************************************************************
1346 template< typename VT, typename MT1, typename MT2 >
1347 struct TDVecSMatMultExprTrait< VT, SMatSMatMultExpr<MT1,MT2> >
1348 {
1349  public:
1350  //**********************************************************************************************
1351  typedef typename SelectType< IsDenseVector<VT>::value && IsRowVector<VT>::value &&
1352  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1353  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1354  , typename TDVecSMatMultExprTrait< typename TDVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1355  , INVALID_TYPE >::Type Type;
1356  //**********************************************************************************************
1357 };
1359 //*************************************************************************************************
1360 
1361 
1362 //*************************************************************************************************
1364 template< typename VT, typename MT1, typename MT2 >
1365 struct TSVecSMatMultExprTrait< VT, SMatSMatMultExpr<MT1,MT2> >
1366 {
1367  public:
1368  //**********************************************************************************************
1369  typedef typename SelectType< IsSparseVector<VT>::value && IsRowVector<VT>::value &&
1370  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1371  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1372  , typename TSVecSMatMultExprTrait< typename TSVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1373  , INVALID_TYPE >::Type Type;
1374  //**********************************************************************************************
1375 };
1377 //*************************************************************************************************
1378 
1379 
1380 //*************************************************************************************************
1382 template< typename MT1, typename MT2, bool AF >
1383 struct SubmatrixExprTrait< SMatSMatMultExpr<MT1,MT2>, AF >
1384 {
1385  public:
1386  //**********************************************************************************************
1387  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT1,AF>::Type
1388  , typename SubmatrixExprTrait<const MT2,AF>::Type >::Type Type;
1389  //**********************************************************************************************
1390 };
1392 //*************************************************************************************************
1393 
1394 
1395 //*************************************************************************************************
1397 template< typename MT1, typename MT2 >
1398 struct RowExprTrait< SMatSMatMultExpr<MT1,MT2> >
1399 {
1400  public:
1401  //**********************************************************************************************
1402  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
1403  //**********************************************************************************************
1404 };
1406 //*************************************************************************************************
1407 
1408 
1409 //*************************************************************************************************
1411 template< typename MT1, typename MT2 >
1412 struct ColumnExprTrait< SMatSMatMultExpr<MT1,MT2> >
1413 {
1414  public:
1415  //**********************************************************************************************
1416  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
1417  //**********************************************************************************************
1418 };
1420 //*************************************************************************************************
1421 
1422 } // namespace blaze
1423 
1424 #endif
const MT::ElementType max(const DenseMatrix< MT, SO > &dm)
Returns the largest element of the dense matrix.
Definition: DenseMatrix.h:1649
MT2::CompositeType CT2
Composite type of the right-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:130
Header file for the SMatDVecMultExprTrait class template.
MT1::CompositeType CT1
Composite type of the left-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:129
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: SMatSMatMultExpr.h:358
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: SMatSMatMultExpr.h:366
Header file for the Rows type trait.
Header file for the UNUSED_PARAMETER function template.
Header file for the IsUniUpper type trait.
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:8247
Header file for basic type definitions.
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: SMatSMatMultExpr.h:217
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: SMatSMatMultExpr.h:336
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
Header file for the IsSparseMatrix type trait.
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:209
Header file for the ColumnExprTrait class template.
Header file for the IsColumnMajorMatrix type trait.
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:821
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2507
Header file for the IsRowVector type trait.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:261
void UNUSED_PARAMETER(const T1 &)
Suppression of unused parameter warnings.
Definition: Unused.h:81
Header file for the And class template.
Compile time check for lower triangular matrices.This type trait tests whether or not the given templ...
Definition: IsLower.h:90
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:699
Header file for the Computation base class.
Header file for the MatMatMultExpr base class.
Compile time check for upper triangular matrices.This type trait tests whether or not the given templ...
Definition: IsUpper.h:90
Header file for the RequiresEvaluation type trait.
ResultType::ElementType ElementType
Resulting element type.
Definition: SMatSMatMultExpr.h:179
Header file for the TSVecSMatMultExprTrait class template.
Header file for the IsUniLower type trait.
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
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:861
const ElementType ReturnType
Return type for expression template evaluations.
Definition: SMatSMatMultExpr.h:180
Header file for the SparseMatrix base class.
Constraint on the data type.
SelectType< IsExpression< MT2 >::value, const MT2, const MT2 & >::Type RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:187
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
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: SMatSMatMultExpr.h:178
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.
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: SMatSMatMultExpr.h:365
Header file for the multiplication trait.
Header file for the IsStrictlyUpper type trait.
Header file for the IsSymmetric type trait.
ResultType::OppositeType OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: SMatSMatMultExpr.h:177
Namespace of the Blaze C++ math library.
Definition: Blaze.h:57
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: SMatSMatMultExpr.h:348
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2511
Header file for the Or class template.
SelectType< IsExpression< MT1 >::value, const MT1, const MT1 & >::Type LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:184
size_t nonZeros() const
Returns the number of non-zero elements in the sparse matrix.
Definition: SMatSMatMultExpr.h:292
const MT::ElementType min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1602
SMatSMatMultExpr(const MT1 &lhs, const MT2 &rhs)
Constructor for the SMatSMatMultExpr class.
Definition: SMatSMatMultExpr.h:202
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.
MT1::ResultType RT1
Result type of the left-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:127
Numerical infinity for built-in data types.
SMatSMatMultExpr< MT1, MT2 > This
Type of this SMatSMatMultExpr instance.
Definition: SMatSMatMultExpr.h:175
size_t nonZeros(size_t i) const
Returns the number of non-zero elements in the specified row.
Definition: SMatSMatMultExpr.h:303
Header file for the IsLower type trait.
Header file for the SMatSVecMultExprTrait class template.
Constraints on the storage order of matrix types.
size_t rows() const
Returns the current number of rows of the matrix.
Definition: SMatSMatMultExpr.h:272
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 IsStrictlyLower type trait.
Header file for the serial shim.
RightOperand rightOperand() const
Returns the right-hand side sparse matrix operand.
Definition: SMatSMatMultExpr.h:324
#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
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:150
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
const ResultType CompositeType
Data type for composite expression templates.
Definition: SMatSMatMultExpr.h:181
Header file for the reset shim.
Header file for the isDefault shim.
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
LeftOperand leftOperand() const
Returns the left-hand side sparse matrix operand.
Definition: SMatSMatMultExpr.h:314
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.
size_t columns() const
Returns the current number of columns of the matrix.
Definition: SMatSMatMultExpr.h:282
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:937
Header file for the IsComputation type trait class.
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:2502
Header file for the IsTrue value trait.
Header file for the IsUpper type trait.
MT2::ResultType RT2
Result type of the right-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:128
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
#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
MultTrait< RT1, RT2 >::Type ResultType
Result type for expression template evaluations.
Definition: SMatSMatMultExpr.h:176