All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SMatSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_EXPRESSIONS_SMATSMATMULTEXPR_H_
36 #define _BLAZE_MATH_EXPRESSIONS_SMATSMATMULTEXPR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <algorithm>
44 #include <stdexcept>
45 #include <vector>
53 #include <blaze/math/Infinity.h>
55 #include <blaze/math/shims/Reset.h>
75 #include <blaze/util/Assert.h>
76 #include <blaze/util/Byte.h>
77 #include <blaze/util/DisableIf.h>
78 #include <blaze/util/EnableIf.h>
79 #include <blaze/util/InvalidType.h>
81 #include <blaze/util/SelectType.h>
82 #include <blaze/util/Types.h>
84 #include <blaze/util/Unused.h>
85 
86 
87 namespace blaze {
88 
89 //=================================================================================================
90 //
91 // CLASS SMATSMATMULTEXPR
92 //
93 //=================================================================================================
94 
95 //*************************************************************************************************
102 template< typename MT1 // Type of the left-hand side sparse matrix
103  , typename MT2 > // Type of the right-hand side sparse matrix
104 class SMatSMatMultExpr : public SparseMatrix< SMatSMatMultExpr<MT1,MT2>, false >
105  , private MatMatMultExpr
106  , private Computation
107 {
108  private:
109  //**Type definitions****************************************************************************
110  typedef typename MT1::ResultType RT1;
111  typedef typename MT2::ResultType RT2;
112  typedef typename MT1::CompositeType CT1;
113  typedef typename MT2::CompositeType CT2;
114  //**********************************************************************************************
115 
116  public:
117  //**Type definitions****************************************************************************
123  typedef const ElementType ReturnType;
124  typedef const ResultType CompositeType;
125 
127  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
128 
130  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
131  //**********************************************************************************************
132 
133  //**Constructor*********************************************************************************
139  explicit inline SMatSMatMultExpr( const MT1& lhs, const MT2& rhs )
140  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
141  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
142  {
143  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
144  }
145  //**********************************************************************************************
146 
147  //**Access operator*****************************************************************************
154  inline ReturnType operator()( size_t i, size_t j ) const {
155  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
156  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
157 
159 
160  ElementType tmp = ElementType();
161 
162  // Early exit
163  if( lhs_.columns() == 0UL )
164  return tmp;
165 
166  // Fast computation in case the left-hand side sparse matrix directly provides iterators
168  {
169  // Evaluation of the left-hand side sparse matrix operand
170  CT1 A( lhs_ );
171 
172  const ConstIterator end( A.end(i) );
173  ConstIterator element( A.begin(i) );
174 
175  // Early exit in case row i is empty
176  if( element == end )
177  return tmp;
178 
179  // Calculating element (i,j)
180  tmp = element->value() * rhs_(element->index(),j);
181  ++element;
182  for( ; element!=end; ++element )
183  tmp += element->value() * rhs_(element->index(),j);
184  }
185 
186  // Default computation in case the left-hand side sparse matrix doesn't provide iterators
187  else {
188  tmp = lhs_(i,0UL) * rhs_(0UL,j);
189  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
190  tmp += lhs_(i,k) * rhs_(k,j);
191  }
192  }
193 
194  return tmp;
195  }
196  //**********************************************************************************************
197 
198  //**Rows function*******************************************************************************
203  inline size_t rows() const {
204  return lhs_.rows();
205  }
206  //**********************************************************************************************
207 
208  //**Columns function****************************************************************************
213  inline size_t columns() const {
214  return rhs_.columns();
215  }
216  //**********************************************************************************************
217 
218  //**NonZeros function***************************************************************************
223  inline size_t nonZeros() const {
224  return 0UL;
225  }
226  //**********************************************************************************************
227 
228  //**NonZeros function***************************************************************************
234  inline size_t nonZeros( size_t i ) const {
235  UNUSED_PARAMETER( i );
236  return 0UL;
237  }
238  //**********************************************************************************************
239 
240  //**Left operand access*************************************************************************
245  inline LeftOperand leftOperand() const {
246  return lhs_;
247  }
248  //**********************************************************************************************
249 
250  //**Right operand access************************************************************************
255  inline RightOperand rightOperand() const {
256  return rhs_;
257  }
258  //**********************************************************************************************
259 
260  //**********************************************************************************************
266  template< typename T >
267  inline bool canAlias( const T* alias ) const {
268  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
269  }
270  //**********************************************************************************************
271 
272  //**********************************************************************************************
278  template< typename T >
279  inline bool isAliased( const T* alias ) const {
280  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
281  }
282  //**********************************************************************************************
283 
284  private:
285  //**Member variables****************************************************************************
288  //**********************************************************************************************
289 
290  //**Default assignment to dense matrices********************************************************
303  template< typename MT // Type of the target dense matrix
304  , bool SO > // Storage order of the target dense matrix
305  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
306  assign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
307  {
309 
310  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
311  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
312 
313  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
314  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
315 
316  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
317  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
318 
319  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
320  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
321  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
322  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
323  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
324  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
325 
326  for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
327  const LeftIterator lend( A.end(i) );
328  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
329  const RightIterator rend( B.end( lelem->index() ) );
330  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem )
331  {
332  if( isDefault( (~lhs)(i,relem->index()) ) ) {
333  (~lhs)(i,relem->index()) = lelem->value() * relem->value();
334  }
335  else {
336  (~lhs)(i,relem->index()) += lelem->value() * relem->value();
337  }
338  }
339  }
340  }
341  }
343  //**********************************************************************************************
344 
345  //**Optimized assignment to dense matrices******************************************************
358  template< typename MT // Type of the target dense matrix
359  , bool SO > // Storage order of the target dense matrix
360  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
361  assign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
362  {
364 
365  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
366  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
367 
368  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
369  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
370 
371  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
372  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
373 
374  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
375  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
376  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
377  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
378  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
379  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
380 
381  for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
382  const LeftIterator lend( A.end(i) );
383  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
384  const RightIterator rend( B.end( lelem->index() ) );
385  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem ) {
386  (~lhs)(i,relem->index()) += lelem->value() * relem->value();
387  }
388  }
389  }
390  }
392  //**********************************************************************************************
393 
394  //**Assignment to row-major sparse matrices*****************************************************
406  template< typename MT > // Type of the target sparse matrix
407  friend inline void assign( SparseMatrix<MT,false>& lhs, const SMatSMatMultExpr& rhs )
408  {
410 
411  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
412  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
413 
414  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
415  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
416 
417  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
418  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
419 
420  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
421  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
422  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
423  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
424  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
425  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
426 
427  // (Over-)Estimating the number of non-zero entries in the resulting matrix
428  size_t nonzeros( 0UL );
429 
430  for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
431  const LeftIterator lend( A.end(i) );
432  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
433  nonzeros += B.nonZeros( lelem->index() );
434  }
435  }
436 
437  if( nonzeros > (~lhs).rows() * (~lhs).columns() ) {
438  nonzeros = (~lhs).rows() * (~lhs).columns();
439  }
440 
441  (~lhs).reserve( nonzeros );
442  nonzeros = 0UL;
443 
444  // Performing the matrix-matrix multiplication
445  std::vector<ElementType> values ( (~lhs).columns(), ElementType() );
446  std::vector<byte> valid ( (~lhs).columns(), 0 );
447  std::vector<size_t> indices( (~lhs).columns(), 0UL );
448  size_t minIndex( inf ), maxIndex( 0UL );
449 
450  for( size_t i=0UL; i<(~lhs).rows(); ++i )
451  {
452  const LeftIterator lend( A.end(i) );
453  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem )
454  {
455  const RightIterator rend( B.end( lelem->index() ) );
456  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem )
457  {
458  if( !valid[relem->index()] ) {
459  values[relem->index()] = lelem->value() * relem->value();
460  valid [relem->index()] = 1;
461  indices[nonzeros] = relem->index();
462  ++nonzeros;
463  if( relem->index() < minIndex ) minIndex = relem->index();
464  if( relem->index() > maxIndex ) maxIndex = relem->index();
465  }
466  else {
467  values[relem->index()] += lelem->value() * relem->value();
468  }
469  }
470  }
471 
472  BLAZE_INTERNAL_ASSERT( nonzeros <= (~lhs).columns(), "Invalid number of non-zero elements" );
473 
474  if( nonzeros > 0UL )
475  {
476  BLAZE_INTERNAL_ASSERT( minIndex <= maxIndex, "Invalid index detected" );
477 
478  if( ( nonzeros + nonzeros ) < ( maxIndex - minIndex ) )
479  {
480  std::sort( indices.begin(), indices.begin() + nonzeros );
481 
482  for( size_t j=0UL; j<nonzeros; ++j )
483  {
484  const size_t index( indices[j] );
485  if( !isDefault( values[index] ) ) {
486  (~lhs).append( i, index, values[index] );
487  reset( values[index] );
488  }
489 
490  reset( valid [index] );
491  }
492  }
493  else {
494  for( size_t j=minIndex; j<=maxIndex; ++j )
495  {
496  if( !isDefault( values[j] ) ) {
497  (~lhs).append( i, j, values[j] );
498  reset( values[j] );
499  }
500 
501  reset( valid [j] );
502  }
503  }
504 
505  nonzeros = 0UL;
506  minIndex = inf;
507  maxIndex = 0UL;
508  }
509 
510  (~lhs).finalize( i );
511  }
512  }
514  //**********************************************************************************************
515 
516  //**Assignment to column-major sparse matrices**************************************************
528  template< typename MT > // Type of the target sparse matrix
529  friend inline void assign( SparseMatrix<MT,true>& lhs, const SMatSMatMultExpr& rhs )
530  {
532 
533  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
534  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
535 
538 
539  const ResultType tmp( rhs );
540  (~lhs).reserve( tmp.nonZeros() );
541  assign( ~lhs, tmp );
542  }
544  //**********************************************************************************************
545 
546  //**Addition assignment to dense matrices*******************************************************
558  template< typename MT // Type of the target dense matrix
559  , bool SO > // Storage order of the target dense matarix
560  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
561  {
563 
564  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
565  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
566 
567  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
568  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
569 
570  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
571  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
572 
573  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
574  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
575  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
576  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
577  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
578  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
579 
580  for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
581  const LeftIterator lend( A.end(i) );
582  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
583  const RightIterator rend( B.end( lelem->index() ) );
584  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem ) {
585  (~lhs)(i,relem->index()) += lelem->value() * relem->value();
586  }
587  }
588  }
589  }
591  //**********************************************************************************************
592 
593  //**Addition assignment to sparse matrices******************************************************
594  // No special implementation for the addition assignment to sparse matrices.
595  //**********************************************************************************************
596 
597  //**Subtraction assignment to dense matrices****************************************************
610  template< typename MT // Type of the target dense matrix
611  , bool SO > // Storage order of the target dense matrix
612  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatMultExpr& rhs )
613  {
615 
616  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
617  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
618 
619  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
620  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
621 
622  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
623  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
624 
625  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
626  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
627  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
628  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
629  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
630  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
631 
632  for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
633  const LeftIterator lend( A.end(i) );
634  for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
635  const RightIterator rend( B.end( lelem->index() ) );
636  for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem ) {
637  (~lhs)(i,relem->index()) -= lelem->value() * relem->value();
638  }
639  }
640  }
641  }
643  //**********************************************************************************************
644 
645  //**Subtraction assignment to sparse matrices***************************************************
646  // No special implementation for the subtraction assignment to sparse matrices.
647  //**********************************************************************************************
648 
649  //**Multiplication assignment to dense matrices*************************************************
650  // No special implementation for the multiplication assignment to dense matrices.
651  //**********************************************************************************************
652 
653  //**Multiplication assignment to sparse matrices************************************************
654  // No special implementation for the multiplication assignment to sparse matrices.
655  //**********************************************************************************************
656 
657  //**Compile time checks*************************************************************************
664  //**********************************************************************************************
665 };
666 //*************************************************************************************************
667 
668 
669 
670 
671 //=================================================================================================
672 //
673 // GLOBAL BINARY ARITHMETIC OPERATORS
674 //
675 //=================================================================================================
676 
677 //*************************************************************************************************
704 template< typename T1 // Type of the left-hand side sparse matrix
705  , typename T2 > // Type of the right-hand side sparse matrix
706 inline const SMatSMatMultExpr<T1,T2>
708 {
710 
711  if( (~lhs).columns() != (~rhs).rows() )
712  throw std::invalid_argument( "Matrix sizes do not match" );
713 
714  return SMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
715 }
716 //*************************************************************************************************
717 
718 
719 
720 
721 //=================================================================================================
722 //
723 // EXPRESSION TRAIT SPECIALIZATIONS
724 //
725 //=================================================================================================
726 
727 //*************************************************************************************************
729 template< typename MT1, typename MT2, typename VT >
730 struct SMatDVecMultExprTrait< SMatSMatMultExpr<MT1,MT2>, VT >
731 {
732  public:
733  //**********************************************************************************************
734  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
735  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
736  IsDenseVector<VT>::value && IsColumnVector<VT>::value
737  , typename SMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
738  , INVALID_TYPE >::Type Type;
739  //**********************************************************************************************
740 };
742 //*************************************************************************************************
743 
744 
745 //*************************************************************************************************
747 template< typename MT1, typename MT2, typename VT >
748 struct SMatSVecMultExprTrait< SMatSMatMultExpr<MT1,MT2>, VT >
749 {
750  public:
751  //**********************************************************************************************
752  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
753  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
754  IsSparseVector<VT>::value && IsColumnVector<VT>::value
755  , typename SMatSVecMultExprTrait< MT1, typename SMatSVecMultExprTrait<MT2,VT>::Type >::Type
756  , INVALID_TYPE >::Type Type;
757  //**********************************************************************************************
758 };
760 //*************************************************************************************************
761 
762 
763 //*************************************************************************************************
765 template< typename VT, typename MT1, typename MT2 >
766 struct TDVecSMatMultExprTrait< VT, SMatSMatMultExpr<MT1,MT2> >
767 {
768  public:
769  //**********************************************************************************************
770  typedef typename SelectType< IsDenseVector<VT>::value && IsRowVector<VT>::value &&
771  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
772  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
773  , typename TDVecSMatMultExprTrait< typename TDVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
774  , INVALID_TYPE >::Type Type;
775  //**********************************************************************************************
776 };
778 //*************************************************************************************************
779 
780 
781 //*************************************************************************************************
783 template< typename VT, typename MT1, typename MT2 >
784 struct TSVecSMatMultExprTrait< VT, SMatSMatMultExpr<MT1,MT2> >
785 {
786  public:
787  //**********************************************************************************************
788  typedef typename SelectType< IsSparseVector<VT>::value && IsRowVector<VT>::value &&
789  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
790  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
791  , typename TSVecSMatMultExprTrait< typename TSVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
792  , INVALID_TYPE >::Type Type;
793  //**********************************************************************************************
794 };
796 //*************************************************************************************************
797 
798 
799 //*************************************************************************************************
801 template< typename MT1, typename MT2 >
802 struct SubmatrixExprTrait< SMatSMatMultExpr<MT1,MT2> >
803 {
804  public:
805  //**********************************************************************************************
806  typedef typename MultExprTrait< typename SubmatrixExprTrait<const MT1>::Type
807  , typename SubmatrixExprTrait<const MT2>::Type >::Type Type;
808  //**********************************************************************************************
809 };
811 //*************************************************************************************************
812 
813 
814 //*************************************************************************************************
816 template< typename MT1, typename MT2 >
817 struct RowExprTrait< SMatSMatMultExpr<MT1,MT2> >
818 {
819  public:
820  //**********************************************************************************************
821  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
822  //**********************************************************************************************
823 };
825 //*************************************************************************************************
826 
827 
828 //*************************************************************************************************
830 template< typename MT1, typename MT2 >
831 struct ColumnExprTrait< SMatSMatMultExpr<MT1,MT2> >
832 {
833  public:
834  //**********************************************************************************************
835  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
836  //**********************************************************************************************
837 };
839 //*************************************************************************************************
840 
841 } // namespace blaze
842 
843 #endif
Header file for the SMatDVecMultExprTrait class template.
void reset(DynamicMatrix< Type, SO > &m)
Resetting the given dense matrix.
Definition: DynamicMatrix.h:4512
Header file for the UNUSED_PARAMETER function template.
const DMatDMatMultExpr< T1, T2 > operator*(const DenseMatrix< T1, false > &lhs, const DenseMatrix< T2, false > &rhs)
Multiplication operator for the multiplication of two row-major dense matrices ( ).
Definition: DMatDMatMultExpr.h:3703
MultTrait< RT1, RT2 >::Type ResultType
Result type for expression template evaluations.
Definition: SMatSMatMultExpr.h:119
Header file for the IsSparseMatrix type trait.
bool isDefault(const DynamicMatrix< Type, SO > &m)
Returns whether the given dense matrix is in default state.
Definition: DynamicMatrix.h:4555
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:196
Header file for the ColumnExprTrait class template.
ResultType::ElementType ElementType
Resulting element type.
Definition: SMatSMatMultExpr.h:122
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2375
RightOperand rightOperand() const
Returns the right-hand side sparse matrix operand.
Definition: SMatSMatMultExpr.h:255
Header file for the IsRowVector type trait.
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:248
void UNUSED_PARAMETER(const T1 &)
Suppression of unused parameter warnings.
Definition: Unused.h:84
Header file for the TDVecSMatMultExprTrait class template.
Header file for the Computation base class.
Header file for the MatMatMultExpr base class.
Header file for the RequiresEvaluation type trait.
Header file for the TSVecSMatMultExprTrait class template.
size_t nonZeros() const
Returns the number of non-zero elements in the sparse matrix.
Definition: SMatSMatMultExpr.h:223
MT1::CompositeType CT1
Composite type of the left-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:112
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:104
ResultType::OppositeType OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: SMatSMatMultExpr.h:120
MT1::ResultType RT1
Result type of the left-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:110
Header file for the SparseMatrix base class.
ResultType::TransposeType TransposeType
Transpose type for expression template evaluations.
Definition: SMatSMatMultExpr.h:121
Constraint on the data type.
Header file for the MultExprTrait class template.
Compile time check to query the requirement to evaluate an expression.Via this type trait it is possi...
Definition: RequiresEvaluation.h:90
const ElementType ReturnType
Return type for expression template evaluations.
Definition: SMatSMatMultExpr.h:123
Compile time type selection.The SelectType class template selects one of the two given types T1 and T...
Definition: SelectType.h:59
Header file for the DisableIf class template.
size_t rows() const
Returns the current number of rows of the matrix.
Definition: SMatSMatMultExpr.h:203
size_t columns() const
Returns the current number of columns of the matrix.
Definition: SMatSMatMultExpr.h:213
Header file for the multiplication trait.
RightOperand rhs_
Right-hand side sparse matrix of the multiplication expression.
Definition: SMatSMatMultExpr.h:287
SMatSMatMultExpr< MT1, MT2 > This
Type of this SMatSMatMultExpr instance.
Definition: SMatSMatMultExpr.h:118
SelectType< IsExpression< MT1 >::value, const MT1, const MT1 & >::Type LeftOperand
Composite type of the left-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:127
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2379
Numerical infinity for built-in data types.
void assign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the assignment of a matrix to a matrix.
Definition: Matrix.h:179
bool canAlias(const T *alias) const
Returns whether the expression can alias with the given address alias.
Definition: SMatSMatMultExpr.h:267
LeftOperand leftOperand() const
Returns the left-hand side sparse matrix operand.
Definition: SMatSMatMultExpr.h:245
Header file for the SMatSVecMultExprTrait class template.
SMatSMatMultExpr(const MT1 &lhs, const MT2 &rhs)
Constructor for the SMatSMatMultExpr class.
Definition: SMatSMatMultExpr.h:139
bool isAliased(const T *alias) const
Returns whether the expression is aliased with the given address alias.
Definition: SMatSMatMultExpr.h:279
Constraints on the storage order of matrix types.
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 byte type.
size_t nonZeros(size_t i) const
Returns the number of non-zero elements in the specified row.
Definition: SMatSMatMultExpr.h:234
Header file for the IsSparseVector type trait.
Header file for the SubmatrixExprTrait class template.
#define BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a row-major dense or sparse matrix t...
Definition: StorageOrder.h:81
Removal of reference modifiers.The RemoveCV type trait removes any reference modifiers from the given...
Definition: RemoveReference.h:69
Expression object for sparse matrix-sparse matrix multiplications.The SMatSMatMultExpr class represen...
Definition: Forward.h:94
Header file for run time assertion macros.
Utility type for generic codes.
Base template for the MultTrait class.
Definition: MultTrait.h:141
void addAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the addition assignment of a matrix to a matrix.
Definition: Matrix.h:209
Substitution Failure Is Not An Error (SFINAE) class.The EnableIf class template is an auxiliary tool ...
Definition: EnableIf.h:184
Header file for the reset shim.
void subAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the subtraction assignment of a matrix to matrix.
Definition: Matrix.h:239
Header file for the isDefault shim.
const Infinity inf
Global Infinity instance.The blaze::inf instance can be used wherever a built-in data type is expecte...
Definition: Infinity.h:1098
ReturnType operator()(size_t i, size_t j) const
2D-access to the matrix elements.
Definition: SMatSMatMultExpr.h:154
Header file for the RemoveReference type trait.
Substitution Failure Is Not An Error (SFINAE) class.The DisableIf class template is an auxiliary tool...
Definition: DisableIf.h:184
Header file for the IsDenseVector type trait.
LeftOperand lhs_
Left-hand side sparse matrix of the multiplication expression.
Definition: SMatSMatMultExpr.h:286
SelectType< IsExpression< MT2 >::value, const MT2, const MT2 & >::Type RightOperand
Composite type of the right-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:130
Header file for the IsRowMajorMatrix type trait.
Header file for the IsComputation type trait class.
MT2::ResultType RT2
Result type of the right-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:111
#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:2370
size_t columns(const Matrix< MT, SO > &m)
Returns the current number of columns of the matrix.
Definition: Matrix.h:154
Header file for basic type definitions.
Header file for the IsColumnVector type trait.
Header file for the IsResizable type trait.
size_t rows(const Matrix< MT, SO > &m)
Returns the current number of rows of the matrix.
Definition: Matrix.h:138
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
const ResultType CompositeType
Data type for composite expression templates.
Definition: SMatSMatMultExpr.h:124
#define BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a sparse, N-dimensional matrix type...
Definition: SparseMatrix.h:79
Header file for the IsExpression type trait class.
Header file for the FunctionTrace class.
MT2::CompositeType CT2
Composite type of the right-hand side sparse matrix expression.
Definition: SMatSMatMultExpr.h:113