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 <vector>
54 #include <blaze/math/Functions.h>
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/Exception.h>
94 #include <blaze/util/InvalidType.h>
96 #include <blaze/util/mpl/And.h>
97 #include <blaze/util/mpl/Or.h>
98 #include <blaze/util/SelectType.h>
99 #include <blaze/util/Types.h>
101 #include <blaze/util/Unused.h>
103 
104 
105 namespace blaze {
106 
107 //=================================================================================================
108 //
109 // CLASS SMATSMATMULTEXPR
110 //
111 //=================================================================================================
112 
113 //*************************************************************************************************
120 template< typename MT1 // Type of the left-hand side sparse matrix
121  , typename MT2 > // Type of the right-hand side sparse matrix
122 class SMatSMatMultExpr : public SparseMatrix< SMatSMatMultExpr<MT1,MT2>, false >
123  , private MatMatMultExpr
124  , private Computation
125 {
126  private:
127  //**Type definitions****************************************************************************
128  typedef typename MT1::ResultType RT1;
129  typedef typename MT2::ResultType RT2;
130  typedef typename MT1::CompositeType CT1;
131  typedef typename MT2::CompositeType CT2;
132  //**********************************************************************************************
133 
134  //**********************************************************************************************
136  enum { evaluateLeft = RequiresEvaluation<MT1>::value };
137  //**********************************************************************************************
138 
139  //**********************************************************************************************
141  enum { evaluateRight = RequiresEvaluation<MT2>::value };
142  //**********************************************************************************************
143 
144  //**********************************************************************************************
146 
151  template< typename T1, typename T2, typename T3 >
152  struct CanExploitSymmetry {
153  enum { value = IsColumnMajorMatrix<T1>::value &&
154  IsSymmetric<T2>::value && IsSymmetric<T3>::value };
155  };
157  //**********************************************************************************************
158 
159  //**********************************************************************************************
161 
166  template< typename T1, typename T2, typename T3 >
167  struct IsEvaluationRequired {
168  enum { value = ( evaluateLeft || evaluateRight ) &&
169  !CanExploitSymmetry<T1,T2,T3>::value };
170  };
172  //**********************************************************************************************
173 
174  public:
175  //**Type definitions****************************************************************************
181  typedef const ElementType ReturnType;
182  typedef const ResultType CompositeType;
183 
185  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
186 
188  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
189  //**********************************************************************************************
190 
191  //**Compilation flags***************************************************************************
193  enum { smpAssignable = !evaluateLeft && MT1::smpAssignable &&
194  !evaluateRight && MT2::smpAssignable };
195  //**********************************************************************************************
196 
197  //**Constructor*********************************************************************************
203  explicit inline SMatSMatMultExpr( const MT1& lhs, const MT2& rhs )
204  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
205  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
206  {
207  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
208  }
209  //**********************************************************************************************
210 
211  //**Access operator*****************************************************************************
218  inline ReturnType operator()( size_t i, size_t j ) const {
219  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
220  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
221 
223 
224  ElementType tmp = ElementType();
225 
226  // Early exit
227  if( lhs_.columns() == 0UL )
228  return tmp;
229 
230  // Fast computation in case the left-hand side sparse matrix directly provides iterators
232  {
233  // Evaluation of the left-hand side sparse matrix operand
234  CT1 A( lhs_ );
235 
236  const ConstIterator end( ( IsUpper<MT2>::value )?( A.upperBound(i,j) ):( A.end(i) ) );
237  ConstIterator element( ( IsLower<MT2>::value )?( A.lowerBound(i,j) ):( A.begin(i) ) );
238 
239  // Early exit in case row i is empty
240  if( element == end )
241  return tmp;
242 
243  // Calculating element (i,j)
244  tmp = element->value() * rhs_(element->index(),j);
245  ++element;
246  for( ; element!=end; ++element ) {
247  tmp += element->value() * rhs_(element->index(),j);
248  }
249  }
250 
251  // Default computation in case the left-hand side sparse matrix doesn't provide iterators
252  else {
253  const size_t kbegin( max( ( IsUpper<MT1>::value )?( i ):( 0UL ),
254  ( IsLower<MT2>::value )?( j ):( 0UL ) ) );
255  const size_t kend ( min( ( IsLower<MT1>::value )?( i+1UL ):( lhs_.columns() ),
256  ( IsUpper<MT2>::value )?( j+1UL ):( lhs_.columns() ) ) );
257 
258  tmp = lhs_(i,kbegin) * rhs_(kbegin,j);
259  for( size_t k=kbegin+1UL; k<kend; ++k ) {
260  tmp += lhs_(i,k) * rhs_(k,j);
261  }
262  }
263 
264  return tmp;
265  }
266  //**********************************************************************************************
267 
268  //**At function*********************************************************************************
276  inline ReturnType at( size_t i, size_t j ) const {
277  if( i >= lhs_.rows() ) {
278  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
279  }
280  if( j >= rhs_.columns() ) {
281  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
282  }
283  return (*this)(i,j);
284  }
285  //**********************************************************************************************
286 
287  //**Rows function*******************************************************************************
292  inline size_t rows() const {
293  return lhs_.rows();
294  }
295  //**********************************************************************************************
296 
297  //**Columns function****************************************************************************
302  inline size_t columns() const {
303  return rhs_.columns();
304  }
305  //**********************************************************************************************
306 
307  //**NonZeros function***************************************************************************
312  inline size_t nonZeros() const {
313  return 0UL;
314  }
315  //**********************************************************************************************
316 
317  //**NonZeros function***************************************************************************
323  inline size_t nonZeros( size_t i ) const {
324  UNUSED_PARAMETER( i );
325  return 0UL;
326  }
327  //**********************************************************************************************
328 
329  //**Left operand access*************************************************************************
334  inline LeftOperand leftOperand() const {
335  return lhs_;
336  }
337  //**********************************************************************************************
338 
339  //**Right operand access************************************************************************
344  inline RightOperand rightOperand() const {
345  return rhs_;
346  }
347  //**********************************************************************************************
348 
349  //**********************************************************************************************
355  template< typename T >
356  inline bool canAlias( const T* alias ) const {
357  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
358  }
359  //**********************************************************************************************
360 
361  //**********************************************************************************************
367  template< typename T >
368  inline bool isAliased( const T* alias ) const {
369  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
370  }
371  //**********************************************************************************************
372 
373  //**********************************************************************************************
378  inline bool canSMPAssign() const {
379  return ( rows() > SMP_SMATSMATMULT_THRESHOLD );
380  }
381  //**********************************************************************************************
382 
383  private:
384  //**Member variables****************************************************************************
385  LeftOperand lhs_;
386  RightOperand rhs_;
387  //**********************************************************************************************
388 
389  //**Assignment to dense matrices****************************************************************
402  template< typename MT // Type of the target dense matrix
403  , bool SO > // Storage order of the target dense matrix
404  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
405  assign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
406  {
408 
409  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
410  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
411 
412  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
413  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
414 
415  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
416  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
417  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
418  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
419  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
420  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
421 
422  SMatSMatMultExpr::selectAssignKernel( ~lhs, A, B );
423  }
425  //**********************************************************************************************
426 
427  //**Default assignment to dense matrices********************************************************
440  template< typename MT3 // Type of the left-hand side target matrix
441  , typename MT4 // Type of the left-hand side matrix operand
442  , typename MT5 > // Type of the right-hand side matrix operand
443  static inline void selectAssignKernel( MT3& C, const MT4& A, const MT5& B )
444  {
445  typedef typename MT4::ConstIterator LeftIterator;
446  typedef typename MT5::ConstIterator RightIterator;
447 
448  for( size_t i=0UL; i<C.rows(); ++i ) {
449  const LeftIterator lend( A.end(i) );
450  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
451  const RightIterator rend( B.end( lelem->index() ) );
452  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem )
453  {
455  isDefault( C(i,relem->index()) ) ) {
456  C(i,relem->index()) = lelem->value() * relem->value();
457  }
458  else {
459  C(i,relem->index()) += lelem->value() * relem->value();
460  }
461  }
462  }
463  }
464  }
466  //**********************************************************************************************
467 
468  //**Assignment to row-major sparse matrices*****************************************************
481  template< typename MT > // Type of the target sparse matrix
482  friend inline void assign( SparseMatrix<MT,false>& lhs, const SMatSMatMultExpr& rhs )
483  {
485 
486  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
487  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
488 
489  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
490  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
491 
492  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
493  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
494 
495  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
496  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
497  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
498  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
499  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
500  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
501 
502  // (Over-)Estimating the number of non-zero entries in the resulting matrix
503  size_t nonzeros( 0UL );
504 
505  for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
506  const LeftIterator lend( A.end(i) );
507  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
508  nonzeros += B.nonZeros( lelem->index() );
509  }
510  }
511 
512  if( nonzeros > (~lhs).rows() * (~lhs).columns() ) {
513  nonzeros = (~lhs).rows() * (~lhs).columns();
514  }
515 
516  (~lhs).reserve( nonzeros );
517  nonzeros = 0UL;
518 
519  // Performing the matrix-matrix multiplication
520  std::vector<ElementType> values ( (~lhs).columns(), ElementType() );
521  std::vector<byte> valid ( (~lhs).columns(), 0 );
522  std::vector<size_t> indices( (~lhs).columns(), 0UL );
523  size_t minIndex( inf ), maxIndex( 0UL );
524 
525  for( size_t i=0UL; i<(~lhs).rows(); ++i )
526  {
527  const LeftIterator lend( A.end(i) );
528  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem )
529  {
530  const RightIterator rend( B.end( lelem->index() ) );
531  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem )
532  {
533  if( !valid[relem->index()] ) {
534  values[relem->index()] = lelem->value() * relem->value();
535  valid [relem->index()] = 1;
536  indices[nonzeros] = relem->index();
537  ++nonzeros;
538  if( relem->index() < minIndex ) minIndex = relem->index();
539  if( relem->index() > maxIndex ) maxIndex = relem->index();
540  }
541  else {
542  values[relem->index()] += lelem->value() * relem->value();
543  }
544  }
545  }
546 
547  BLAZE_INTERNAL_ASSERT( nonzeros <= (~lhs).columns(), "Invalid number of non-zero elements" );
548 
549  if( nonzeros > 0UL )
550  {
551  BLAZE_INTERNAL_ASSERT( minIndex <= maxIndex, "Invalid index detected" );
552 
553  if( ( nonzeros + nonzeros ) < ( maxIndex - minIndex ) )
554  {
555  std::sort( indices.begin(), indices.begin() + nonzeros );
556 
557  for( size_t j=0UL; j<nonzeros; ++j )
558  {
559  const size_t index( indices[j] );
560  if( !isDefault( values[index] ) ) {
561  (~lhs).append( i, index, values[index] );
562  reset( values[index] );
563  }
564 
565  reset( valid [index] );
566  }
567  }
568  else {
569  for( size_t j=minIndex; j<=maxIndex; ++j )
570  {
571  if( !isDefault( values[j] ) ) {
572  (~lhs).append( i, j, values[j] );
573  reset( values[j] );
574  }
575 
576  reset( valid [j] );
577  }
578  }
579 
580  nonzeros = 0UL;
581  minIndex = inf;
582  maxIndex = 0UL;
583  }
584 
585  (~lhs).finalize( i );
586  }
587  }
589  //**********************************************************************************************
590 
591  //**Assignment to column-major sparse matrices**************************************************
604  template< typename MT > // Type of the target sparse matrix
605  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
606  assign( SparseMatrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
607  {
609 
611 
612  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
613  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
614 
617 
618  const ResultType tmp( serial( rhs ) );
619  (~lhs).reserve( tmp.nonZeros() );
620  assign( ~lhs, tmp );
621  }
623  //**********************************************************************************************
624 
625  //**Restructuring assignment to column-major matrices*******************************************
640  template< typename MT > // Type of the target matrix
641  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
642  assign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
643  {
645 
647 
648  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
649  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
650 
651  assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
652  }
654  //**********************************************************************************************
655 
656  //**Addition assignment to dense matrices*******************************************************
669  template< typename MT // Type of the target dense matrix
670  , bool SO > // Storage order of the target dense matarix
671  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
672  addAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
673  {
675 
676  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
677  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
678 
679  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
680  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
681 
682  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
683  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
684  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
685  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
686  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
687  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
688 
689  SMatSMatMultExpr::selectAddAssignKernel( ~lhs, A, B );
690  }
692  //**********************************************************************************************
693 
694  //**Default addition assignment to dense matrices***********************************************
708  template< typename MT3 // Type of the left-hand side target matrix
709  , typename MT4 // Type of the left-hand side matrix operand
710  , typename MT5 > // Type of the right-hand side matrix operand
711  static inline void selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B )
712  {
713  typedef typename MT4::ConstIterator LeftIterator;
714  typedef typename MT5::ConstIterator RightIterator;
715 
716  for( size_t i=0UL; i<C.rows(); ++i ) {
717  const LeftIterator lend( A.end(i) );
718  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
719  const RightIterator rend( B.end( lelem->index() ) );
720  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem ) {
721  C(i,relem->index()) += lelem->value() * relem->value();
722  }
723  }
724  }
725  }
727  //**********************************************************************************************
728 
729  //**Restructuring addition assignment to column-major matrices**********************************
744  template< typename MT > // Type of the target matrix
745  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
746  addAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
747  {
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  addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
756  }
758  //**********************************************************************************************
759 
760  //**Addition assignment to sparse matrices******************************************************
761  // No special implementation for the addition assignment to sparse matrices.
762  //**********************************************************************************************
763 
764  //**Subtraction assignment to dense matrices****************************************************
777  template< typename MT // Type of the target dense matrix
778  , bool SO > // Storage order of the target dense matrix
779  friend inline typename DisableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
780  subAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
781  {
783 
784  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
785  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
786 
787  CT1 A( serial( rhs.lhs_ ) ); // Evaluation of the left-hand side sparse matrix operand
788  CT2 B( serial( rhs.rhs_ ) ); // Evaluation of the right-hand side sparse matrix operand
789 
790  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
791  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
792  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
793  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
794  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
795  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
796 
797  SMatSMatMultExpr::selectSubAssignKernel( ~lhs, A, B );
798  }
800  //**********************************************************************************************
801 
802  //**Default subtraction assignment to dense matrices********************************************
816  template< typename MT3 // Type of the left-hand side target matrix
817  , typename MT4 // Type of the left-hand side matrix operand
818  , typename MT5 > // Type of the right-hand side matrix operand
819  static inline void selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B )
820  {
821  typedef typename MT4::ConstIterator LeftIterator;
822  typedef typename MT5::ConstIterator RightIterator;
823 
824  for( size_t i=0UL; i<C.rows(); ++i ) {
825  const LeftIterator lend( A.end(i) );
826  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
827  const RightIterator rend( B.end( lelem->index() ) );
828  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem ) {
829  C(i,relem->index()) -= lelem->value() * relem->value();
830  }
831  }
832  }
833  }
835  //**********************************************************************************************
836 
837  //**Restructuring subtraction assignment to column-major matrices*******************************
852  template< typename MT > // Type of the target matrix
853  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
854  subAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
855  {
857 
859 
860  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
861  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
862 
863  subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
864  }
866  //**********************************************************************************************
867 
868  //**Subtraction assignment to sparse matrices***************************************************
869  // No special implementation for the subtraction assignment to sparse matrices.
870  //**********************************************************************************************
871 
872  //**Multiplication assignment to dense matrices*************************************************
873  // No special implementation for the multiplication assignment to dense matrices.
874  //**********************************************************************************************
875 
876  //**Multiplication assignment to sparse matrices************************************************
877  // No special implementation for the multiplication assignment to sparse matrices.
878  //**********************************************************************************************
879 
880  //**SMP assignment to matrices******************************************************************
895  template< typename MT // Type of the target matrix
896  , bool SO > // Storage order of the target matrix
897  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
898  smpAssign( Matrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
899  {
901 
902  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
903  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
904 
905  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
906  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
907 
908  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
909  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
910  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
911  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
912  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
913  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
914 
915  smpAssign( ~lhs, A * B );
916  }
918  //**********************************************************************************************
919 
920  //**Restructuring SMP assignment to column-major matrices***************************************
935  template< typename MT > // Type of the target matrix
936  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
937  smpAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
938  {
940 
942 
943  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
944  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
945 
946  smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
947  }
949  //**********************************************************************************************
950 
951  //**SMP addition assignment to dense matrices***************************************************
967  template< typename MT // Type of the target dense matrix
968  , bool SO > // Storage order of the target dense matarix
969  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
970  smpAddAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
971  {
973 
974  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
975  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
976 
977  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
978  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
979 
980  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
981  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
982  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
983  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
984  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
985  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
986 
987  smpAddAssign( ~lhs, A * B );
988  }
990  //**********************************************************************************************
991 
992  //**Restructuring SMP addition assignment to column-major matrices******************************
1007  template< typename MT > // Type of the target matrix
1008  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1009  smpAddAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
1010  {
1012 
1014 
1015  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1016  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1017 
1018  smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1019  }
1021  //**********************************************************************************************
1022 
1023  //**SMP addition assignment to sparse matrices**************************************************
1024  // No special implementation for the SMP addition assignment to sparse matrices.
1025  //**********************************************************************************************
1026 
1027  //**SMP subtraction assignment to dense matrices************************************************
1043  template< typename MT // Type of the target dense matrix
1044  , bool SO > // Storage order of the target dense matrix
1045  friend inline typename EnableIf< IsEvaluationRequired<MT,MT1,MT2> >::Type
1046  smpSubAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
1047  {
1049 
1050  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1051  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1052 
1053  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
1054  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
1055 
1056  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
1057  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
1058  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
1059  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
1060  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
1061  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
1062 
1063  smpSubAssign( ~lhs, A * B );
1064  }
1066  //**********************************************************************************************
1067 
1068  //**Restructuring SMP subtraction assignment to column-major matrices***************************
1083  template< typename MT > // Type of the target matrix
1084  friend inline typename EnableIf< CanExploitSymmetry<MT,MT1,MT2> >::Type
1085  smpSubAssign( Matrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
1086  {
1088 
1090 
1091  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
1092  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
1093 
1094  smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) );
1095  }
1097  //**********************************************************************************************
1098 
1099  //**SMP subtraction assignment to sparse matrices***********************************************
1100  // No special implementation for the SMP subtraction assignment to sparse matrices.
1101  //**********************************************************************************************
1102 
1103  //**SMP multiplication assignment to dense matrices*********************************************
1104  // No special implementation for the SMP multiplication assignment to dense matrices.
1105  //**********************************************************************************************
1106 
1107  //**SMP multiplication assignment to sparse matrices********************************************
1108  // No special implementation for the SMP multiplication assignment to sparse matrices.
1109  //**********************************************************************************************
1110 
1111  //**Compile time checks*************************************************************************
1119  //**********************************************************************************************
1120 };
1121 //*************************************************************************************************
1122 
1123 
1124 
1125 
1126 //=================================================================================================
1127 //
1128 // GLOBAL BINARY ARITHMETIC OPERATORS
1129 //
1130 //=================================================================================================
1131 
1132 //*************************************************************************************************
1159 template< typename T1 // Type of the left-hand side sparse matrix
1160  , typename T2 > // Type of the right-hand side sparse matrix
1161 inline const SMatSMatMultExpr<T1,T2>
1163 {
1165 
1166  if( (~lhs).columns() != (~rhs).rows() ) {
1167  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1168  }
1169 
1170  return SMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
1171 }
1172 //*************************************************************************************************
1173 
1174 
1175 
1176 
1177 //=================================================================================================
1178 //
1179 // ROWS SPECIALIZATIONS
1180 //
1181 //=================================================================================================
1182 
1183 //*************************************************************************************************
1185 template< typename MT1, typename MT2 >
1186 struct Rows< SMatSMatMultExpr<MT1,MT2> > : public Rows<MT1>
1187 {};
1189 //*************************************************************************************************
1190 
1191 
1192 
1193 
1194 //=================================================================================================
1195 //
1196 // COLUMNS SPECIALIZATIONS
1197 //
1198 //=================================================================================================
1199 
1200 //*************************************************************************************************
1202 template< typename MT1, typename MT2 >
1203 struct Columns< SMatSMatMultExpr<MT1,MT2> > : public Columns<MT2>
1204 {};
1206 //*************************************************************************************************
1207 
1208 
1209 
1210 
1211 //=================================================================================================
1212 //
1213 // ISLOWER SPECIALIZATIONS
1214 //
1215 //=================================================================================================
1216 
1217 //*************************************************************************************************
1219 template< typename MT1, typename MT2 >
1220 struct IsLower< SMatSMatMultExpr<MT1,MT2> >
1221  : public IsTrue< And< IsLower<MT1>, IsLower<MT2> >::value >
1222 {};
1224 //*************************************************************************************************
1225 
1226 
1227 
1228 
1229 //=================================================================================================
1230 //
1231 // ISUNILOWER SPECIALIZATIONS
1232 //
1233 //=================================================================================================
1234 
1235 //*************************************************************************************************
1237 template< typename MT1, typename MT2 >
1238 struct IsUniLower< SMatSMatMultExpr<MT1,MT2> >
1239  : public IsTrue< And< IsUniLower<MT1>, IsUniLower<MT2> >::value >
1240 {};
1242 //*************************************************************************************************
1243 
1244 
1245 
1246 
1247 //=================================================================================================
1248 //
1249 // ISSTRICTLYLOWER SPECIALIZATIONS
1250 //
1251 //=================================================================================================
1252 
1253 //*************************************************************************************************
1255 template< typename MT1, typename MT2 >
1256 struct IsStrictlyLower< SMatSMatMultExpr<MT1,MT2> >
1257  : public IsTrue< Or< And< IsStrictlyLower<MT1>, IsLower<MT2> >
1258  , And< IsStrictlyLower<MT2>, IsLower<MT1> > >::value >
1259 {};
1261 //*************************************************************************************************
1262 
1263 
1264 
1265 
1266 //=================================================================================================
1267 //
1268 // ISUPPER SPECIALIZATIONS
1269 //
1270 //=================================================================================================
1271 
1272 //*************************************************************************************************
1274 template< typename MT1, typename MT2 >
1275 struct IsUpper< SMatSMatMultExpr<MT1,MT2> >
1276  : public IsTrue< And< IsUpper<MT1>, IsUpper<MT2> >::value >
1277 {};
1279 //*************************************************************************************************
1280 
1281 
1282 
1283 
1284 //=================================================================================================
1285 //
1286 // ISUNIUPPER SPECIALIZATIONS
1287 //
1288 //=================================================================================================
1289 
1290 //*************************************************************************************************
1292 template< typename MT1, typename MT2 >
1293 struct IsUniUpper< SMatSMatMultExpr<MT1,MT2> >
1294  : public IsTrue< And< IsUniUpper<MT1>, IsUniUpper<MT2> >::value >
1295 {};
1297 //*************************************************************************************************
1298 
1299 
1300 
1301 
1302 //=================================================================================================
1303 //
1304 // ISSTRICTLYUPPER SPECIALIZATIONS
1305 //
1306 //=================================================================================================
1307 
1308 //*************************************************************************************************
1310 template< typename MT1, typename MT2 >
1311 struct IsStrictlyUpper< SMatSMatMultExpr<MT1,MT2> >
1312  : public IsTrue< Or< And< IsStrictlyUpper<MT1>, IsUpper<MT2> >
1313  , And< IsStrictlyUpper<MT2>, IsUpper<MT1> > >::value >
1314 {};
1316 //*************************************************************************************************
1317 
1318 
1319 
1320 
1321 //=================================================================================================
1322 //
1323 // EXPRESSION TRAIT SPECIALIZATIONS
1324 //
1325 //=================================================================================================
1326 
1327 //*************************************************************************************************
1329 template< typename MT1, typename MT2, typename VT >
1330 struct SMatDVecMultExprTrait< SMatSMatMultExpr<MT1,MT2>, VT >
1331 {
1332  public:
1333  //**********************************************************************************************
1334  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1335  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1336  IsDenseVector<VT>::value && IsColumnVector<VT>::value
1337  , typename SMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
1338  , INVALID_TYPE >::Type Type;
1339  //**********************************************************************************************
1340 };
1342 //*************************************************************************************************
1343 
1344 
1345 //*************************************************************************************************
1347 template< typename MT1, typename MT2, typename VT >
1348 struct SMatSVecMultExprTrait< SMatSMatMultExpr<MT1,MT2>, VT >
1349 {
1350  public:
1351  //**********************************************************************************************
1352  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1353  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
1354  IsSparseVector<VT>::value && IsColumnVector<VT>::value
1355  , typename SMatSVecMultExprTrait< MT1, typename SMatSVecMultExprTrait<MT2,VT>::Type >::Type
1356  , INVALID_TYPE >::Type Type;
1357  //**********************************************************************************************
1358 };
1360 //*************************************************************************************************
1361 
1362 
1363 //*************************************************************************************************
1365 template< typename VT, typename MT1, typename MT2 >
1366 struct TDVecSMatMultExprTrait< VT, SMatSMatMultExpr<MT1,MT2> >
1367 {
1368  public:
1369  //**********************************************************************************************
1370  typedef typename SelectType< IsDenseVector<VT>::value && IsRowVector<VT>::value &&
1371  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1372  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1373  , typename TDVecSMatMultExprTrait< typename TDVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1374  , INVALID_TYPE >::Type Type;
1375  //**********************************************************************************************
1376 };
1378 //*************************************************************************************************
1379 
1380 
1381 //*************************************************************************************************
1383 template< typename VT, typename MT1, typename MT2 >
1384 struct TSVecSMatMultExprTrait< VT, SMatSMatMultExpr<MT1,MT2> >
1385 {
1386  public:
1387  //**********************************************************************************************
1388  typedef typename SelectType< IsSparseVector<VT>::value && IsRowVector<VT>::value &&
1389  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
1390  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
1391  , typename TSVecSMatMultExprTrait< typename TSVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
1392  , INVALID_TYPE >::Type Type;
1393  //**********************************************************************************************
1394 };
1396 //*************************************************************************************************
1397 
1398 
1399 //*************************************************************************************************
1401 template< typename MT1, typename MT2, bool AF >
1402 struct SubmatrixExprTrait< SMatSMatMultExpr<MT1,MT2>, AF >
1403 {
1404  public:
1405  //**********************************************************************************************
1406  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT1,AF>::Type
1407  , typename SubmatrixExprTrait<const MT2,AF>::Type >::Type Type;
1408  //**********************************************************************************************
1409 };
1411 //*************************************************************************************************
1412 
1413 
1414 //*************************************************************************************************
1416 template< typename MT1, typename MT2 >
1417 struct RowExprTrait< SMatSMatMultExpr<MT1,MT2> >
1418 {
1419  public:
1420  //**********************************************************************************************
1421  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
1422  //**********************************************************************************************
1423 };
1425 //*************************************************************************************************
1426 
1427 
1428 //*************************************************************************************************
1430 template< typename MT1, typename MT2 >
1431 struct ColumnExprTrait< SMatSMatMultExpr<MT1,MT2> >
1432 {
1433  public:
1434  //**********************************************************************************************
1435  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
1436  //**********************************************************************************************
1437 };
1439 //*************************************************************************************************
1440 
1441 } // namespace blaze
1442 
1443 #endif
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exceptionThis macro encapsulates the default way of...
Definition: Exception.h:187
const MT::ElementType max(const DenseMatrix< MT, SO > &dm)
Returns the largest element of the dense matrix.
Definition: DenseMatrix.h:1729
MT2::CompositeType CT2
Composite type of the right-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:131
Header file for mathematical functions.
Header file for the SMatDVecMultExprTrait class template.
MT1::CompositeType CT1
Composite type of the left-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:130
bool canSMPAssign() const
Returns whether the expression can be used in SMP assignments.
Definition: SMatSMatMultExpr.h:378
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: SMatSMatMultExpr.h:386
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:7820
Header file for basic type definitions.
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: SMatSMatMultExpr.h:218
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: SMatSMatMultExpr.h:356
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:250
Header file for the IsSparseMatrix type trait.
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:207
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:507
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2588
Header file for the IsRowVector type trait.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:259
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:721
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
Constraints on the storage order of matrix types.
Header file for the RequiresEvaluation type trait.
ResultType::ElementType ElementType
Resulting element type.
Definition: SMatSMatMultExpr.h:180
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:117
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:547
const ElementType ReturnType
Return type for expression template evaluations.
Definition: SMatSMatMultExpr.h:181
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:188
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:179
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:385
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:178
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:368
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2592
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:185
size_t nonZeros() const
Returns the number of non-zero elements in the sparse matrix.
Definition: SMatSMatMultExpr.h:312
#define BLAZE_THROW_OUT_OF_RANGE(MESSAGE)
Macro for the emission of a std::out_of_range exceptionThis macro encapsulates the default way of Bla...
Definition: Exception.h:331
const MT::ElementType min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1682
SMatSMatMultExpr(const MT1 &lhs, const MT2 &rhs)
Constructor for the SMatSMatMultExpr class.
Definition: SMatSMatMultExpr.h:203
Header file for the Columns type trait.
MT1::ResultType RT1
Result type of the left-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:128
Numerical infinity for built-in data types.
SMatSMatMultExpr< MT1, MT2 > This
Type of this SMatSMatMultExpr instance.
Definition: SMatSMatMultExpr.h:176
size_t nonZeros(size_t i) const
Returns the number of non-zero elements in the specified row.
Definition: SMatSMatMultExpr.h:323
Header file for the IsLower type trait.
Header file for the SMatSVecMultExprTrait class template.
size_t rows() const
Returns the current number of rows of the matrix.
Definition: SMatSMatMultExpr.h:292
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:344
#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
ReturnType at(size_t i, size_t j) const
Checked access to the matrix elements.
Definition: SMatSMatMultExpr.h:276
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: RowMajorMatrix.h:79
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:107
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:138
const ResultType CompositeType
Data type for composite expression templates.
Definition: SMatSMatMultExpr.h:182
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:334
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:302
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:944
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:2583
Header file for the IsTrue value trait.
Header file for the IsUpper type trait.
Header file for exception macros.
MT2::ResultType RT2
Result type of the right-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:129
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.
MultTrait< RT1, RT2 >::Type ResultType
Result type for expression template evaluations.
Definition: SMatSMatMultExpr.h:177