All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SMatTSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_SMATTSMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_SMATTSMATMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
31 #include <boost/type_traits/remove_reference.hpp>
57 #include <blaze/util/Assert.h>
58 #include <blaze/util/InvalidType.h>
59 #include <blaze/util/SelectType.h>
60 #include <blaze/util/Types.h>
61 
62 
63 namespace blaze {
64 
65 //=================================================================================================
66 //
67 // CLASS SMATTSMATMULTEXPR
68 //
69 //=================================================================================================
70 
71 //*************************************************************************************************
78 template< typename MT1 // Type of the left-hand side sparse matrix
79  , typename MT2 > // Type of the right-hand side sparse matrix
80 class SMatTSMatMultExpr : public SparseMatrix< SMatTSMatMultExpr<MT1,MT2>, false >
81  , private Expression
82  , private Computation
83 {
84  private:
85  //**Type definitions****************************************************************************
86  typedef typename MT1::ResultType RT1;
87  typedef typename MT2::ResultType RT2;
88  typedef typename MT1::CompositeType CT1;
89  typedef typename MT2::CompositeType CT2;
90  //**********************************************************************************************
91 
92  public:
93  //**Type definitions****************************************************************************
96  typedef typename ResultType::OppositeType OppositeType;
97  typedef typename ResultType::TransposeType TransposeType;
98  typedef typename ResultType::ElementType ElementType;
99  typedef const ElementType ReturnType;
100  typedef const ResultType CompositeType;
101 
103  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
104 
106  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
107  //**********************************************************************************************
108 
109  //**Compilation flags***************************************************************************
113  //**********************************************************************************************
114 
115  //**Constructor*********************************************************************************
121  explicit inline SMatTSMatMultExpr( const MT1& lhs, const MT2& rhs )
122  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
123  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
124  {
125  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
126  }
127  //**********************************************************************************************
128 
129  //**Access operator*****************************************************************************
136  inline ReturnType operator()( size_t i, size_t j ) const {
137  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
138  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
139 
140  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
141  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
142 
143  ElementType tmp = ElementType();
144 
145  // Early exit
146  if( lhs_.columns() == 0UL )
147  return tmp;
148 
149  // Fast computation in case both the left-hand side and the right-hand side
150  // sparse matrices directly provide iterators
152  {
153  // Evaluation of the left-hand side sparse matrix operand
154  CT1 A( lhs_ );
155 
156  const LeftIterator lend( A.end(i) );
157  LeftIterator lelem( A.begin(i) );
158 
159  // Evaluation of the right-hand side sparse matrix operand
160  CT2 B( rhs_ );
161 
162  const RightIterator rend( B.end(j) );
163  RightIterator relem( B.begin(j) );
164 
165  // Early exit in case row i or column j are empty
166  if( lelem == lend || relem == rend )
167  return tmp;
168 
169  // Calculating element (i,j)
170  while( true ) {
171  if( lelem->index() < relem->index() ) {
172  ++lelem;
173  if( lelem == lend ) break;
174  }
175  else if( relem->index() < lelem->index() ) {
176  ++relem;
177  if( relem == rend ) break;
178  }
179  else {
180  tmp = lelem->value() * relem->value();
181  ++lelem;
182  ++relem;
183  break;
184  }
185  }
186 
187  if( lelem != lend && relem != rend )
188  {
189  while( true ) {
190  if( lelem->index() < relem->index() ) {
191  ++lelem;
192  if( lelem == lend ) break;
193  }
194  else if( relem->index() < lelem->index() ) {
195  ++relem;
196  if( relem == rend ) break;
197  }
198  else {
199  tmp += lelem->value() * relem->value();
200  ++lelem;
201  if( lelem == lend ) break;
202  ++relem;
203  if( relem == rend ) break;
204  }
205  }
206  }
207  }
208 
209  // Optimized computation in case the left-hand side sparse matrix directly provides iterators
211  {
212  // Evaluation of the left-hand side sparse matrix operand
213  CT1 A( lhs_ );
214 
215  const LeftIterator end( A.end(i) );
216  LeftIterator element( A.begin(i) );
217 
218  // Early exit in case row i is empty
219  if( element == end )
220  return tmp;
221 
222  // Calculating element (i,j)
223  tmp = element->value() * rhs_(element->index(),j);
224  ++element;
225  for( ; element!=end; ++element )
226  tmp += element->value() * rhs_(element->index(),j);
227  }
228 
229  // Optimized computation in case the right-hand side sparse matrix directly provides iterators
231  {
232  // Evaluation of the right-hand side sparse matrix operand
233  CT2 B( rhs_ );
234 
235  const RightIterator end( B.end(j) );
236  RightIterator element( B.begin(j) );
237 
238  // Early exit in case row i is empty
239  if( element == end )
240  return tmp;
241 
242  // Calculating element (i,j)
243  tmp = lhs_(i,element->index()) * element->value();
244  ++element;
245  for( ; element!=end; ++element )
246  tmp += lhs_(i,element->index()) * element->value();
247  }
248 
249  // Default computation in case both sparse matrices don't provide iterators
250  else {
251  tmp = lhs_(i,0UL) * rhs_(0UL,j);
252  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
253  tmp += lhs_(i,k) * rhs_(k,j);
254  }
255  }
256 
257  return tmp;
258  }
259  //**********************************************************************************************
260 
261  //**Rows function*******************************************************************************
266  inline size_t rows() const {
267  return lhs_.rows();
268  }
269  //**********************************************************************************************
270 
271  //**Columns function****************************************************************************
276  inline size_t columns() const {
277  return rhs_.columns();
278  }
279  //**********************************************************************************************
280 
281  //**NonZeros function***************************************************************************
286  inline size_t nonZeros() const {
287  return 0UL;
288  }
289  //**********************************************************************************************
290 
291  //**NonZeros function***************************************************************************
297  inline size_t nonZeros( size_t i ) const {
298  return 0UL;
299  }
300  //**********************************************************************************************
301 
302  //**Left operand access*************************************************************************
307  inline LeftOperand leftOperand() const {
308  return lhs_;
309  }
310  //**********************************************************************************************
311 
312  //**Right operand access************************************************************************
317  inline RightOperand rightOperand() const {
318  return rhs_;
319  }
320  //**********************************************************************************************
321 
322  //**********************************************************************************************
328  template< typename T >
329  inline bool isAliased( const T* alias ) const {
331  !RequiresEvaluation<MT1>::value && lhs_.isAliased( alias ) ) ||
333  !RequiresEvaluation<MT2>::value && rhs_.isAliased( alias ) );
334  }
335  //**********************************************************************************************
336 
337  private:
338  //**Member variables****************************************************************************
341  //**********************************************************************************************
342 
343  //**Assignment to row-major dense matrices******************************************************
356  template< typename MT > // Type of the target dense matrix
357  friend inline void assign( DenseMatrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
358  {
359  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
360  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
361 
362  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( typename MT2::OppositeType );
363 
364  const typename MT2::OppositeType tmp( rhs.rhs_ );
365  assign( ~lhs, rhs.lhs_ * tmp );
366  }
368  //**********************************************************************************************
369 
370  //**Assignment to column-major dense matrices***************************************************
383  template< typename MT > // Type of the target dense matrix
384  friend inline void assign( DenseMatrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
385  {
386  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
387  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
388 
389  BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( typename MT1::OppositeType );
390 
391  const typename MT1::OppositeType tmp( rhs.lhs_ );
392  assign( ~lhs, tmp * rhs.rhs_ );
393  }
395  //**********************************************************************************************
396 
397  //**Assignment to row-major sparse matrices*****************************************************
410  template< typename MT > // Type of the target sparse matrix
411  friend inline void assign( SparseMatrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
412  {
413  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
414  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
415 
416  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( typename MT2::OppositeType );
417 
418  const typename MT2::OppositeType tmp( rhs.rhs_ );
419  assign( ~lhs, rhs.lhs_ * tmp );
420  }
422  //**********************************************************************************************
423 
424  //**Assignment to column-major sparse matrices**************************************************
437  template< typename MT > // Type of the target sparse matrix
438  friend inline void assign( SparseMatrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
439  {
440  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
441  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
442 
443  BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( typename MT1::OppositeType );
444 
445  const typename MT1::OppositeType tmp( rhs.lhs_ );
446  assign( ~lhs, tmp * rhs.rhs_ );
447  }
449  //**********************************************************************************************
450 
451  //**Addition assignment to row-major dense matrices*********************************************
464  template< typename MT > // Type of the target dense matrix
465  friend inline void addAssign( DenseMatrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
466  {
467  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
468  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
469 
470  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( typename MT2::OppositeType );
471 
472  const typename MT2::OppositeType tmp( rhs.rhs_ );
473  addAssign( ~lhs, rhs.lhs_ * tmp );
474  }
476  //**********************************************************************************************
477 
478  //**Addition assignment to column-major dense matrices******************************************
491  template< typename MT > // Type of the target dense matrix
492  friend inline void addAssign( DenseMatrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
493  {
494  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
495  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
496 
497  BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( typename MT1::OppositeType );
498 
499  const typename MT1::OppositeType tmp( rhs.lhs_ );
500  addAssign( ~lhs, tmp * rhs.rhs_ );
501  }
503  //**********************************************************************************************
504 
505  //**Addition assignment to sparse matrices******************************************************
506  // No special implementation for the addition assignment to sparse matrices.
507  //**********************************************************************************************
508 
509  //**Subtraction assignment to row-major dense matrices******************************************
522  template< typename MT > // Type of the target dense matrix
523  friend inline void subAssign( DenseMatrix<MT,false>& lhs, const SMatTSMatMultExpr& rhs )
524  {
525  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
526  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
527 
528  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( typename MT2::OppositeType );
529 
530  const typename MT2::OppositeType tmp( rhs.rhs_ );
531  subAssign( ~lhs, rhs.lhs_ * tmp );
532  }
534  //**********************************************************************************************
535 
536  //**Subtraction assignment to column-major dense matrices***************************************
549  template< typename MT > // Type of the target dense matrix
550  friend inline void subAssign( DenseMatrix<MT,true>& lhs, const SMatTSMatMultExpr& rhs )
551  {
552  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
553  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
554 
555  BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( typename MT1::OppositeType );
556 
557  const typename MT1::OppositeType tmp( rhs.lhs_ );
558  subAssign( ~lhs, tmp * rhs.rhs_ );
559  }
561  //**********************************************************************************************
562 
563  //**Subtraction assignment to sparse matrices***************************************************
564  // No special implementation for the subtraction assignment to sparse matrices.
565  //**********************************************************************************************
566 
567  //**Multiplication assignment to dense matrices*************************************************
568  // No special implementation for the multiplication assignment to dense matrices.
569  //**********************************************************************************************
570 
571  //**Multiplication assignment to sparse matrices************************************************
572  // No special implementation for the multiplication assignment to sparse matrices.
573  //**********************************************************************************************
574 
575  //**Compile time checks*************************************************************************
582  //**********************************************************************************************
583 };
584 //*************************************************************************************************
585 
586 
587 
588 
589 //=================================================================================================
590 //
591 // GLOBAL BINARY ARITHMETIC OPERATORS
592 //
593 //=================================================================================================
594 
595 //*************************************************************************************************
625 template< typename T1 // Type of the left-hand side sparse matrix
626  , typename T2 > // Type of the right-hand side sparse matrix
627 inline const SMatTSMatMultExpr<T1,T2>
629 {
630  if( (~lhs).columns() != (~rhs).rows() )
631  throw std::invalid_argument( "Matrix sizes do not match" );
632 
633  return SMatTSMatMultExpr<T1,T2>( ~lhs, ~rhs );
634 }
635 //*************************************************************************************************
636 
637 
638 
639 
640 //=================================================================================================
641 //
642 // EXPRESSION TRAIT SPECIALIZATIONS
643 //
644 //=================================================================================================
645 
646 //*************************************************************************************************
648 template< typename MT1, typename MT2, typename VT >
649 struct SMatDVecMultExprTrait< SMatTSMatMultExpr<MT1,MT2>, VT >
650 {
651  public:
652  //**********************************************************************************************
653  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
654  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
655  IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
656  , typename SMatDVecMultExprTrait< MT1, typename TSMatDVecMultExprTrait<MT2,VT>::Type >::Type
657  , INVALID_TYPE >::Type Type;
658  //**********************************************************************************************
659 };
661 //*************************************************************************************************
662 
663 
664 //*************************************************************************************************
666 template< typename MT1, typename MT2, typename VT >
667 struct SMatSVecMultExprTrait< SMatTSMatMultExpr<MT1,MT2>, VT >
668 {
669  public:
670  //**********************************************************************************************
671  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
672  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
673  IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
674  , typename SMatSVecMultExprTrait< MT1, typename TSMatSVecMultExprTrait<MT2,VT>::Type >::Type
675  , INVALID_TYPE >::Type Type;
676  //**********************************************************************************************
677 };
679 //*************************************************************************************************
680 
681 
682 //*************************************************************************************************
684 template< typename VT, typename MT1, typename MT2 >
685 struct TDVecSMatMultExprTrait< VT, SMatTSMatMultExpr<MT1,MT2> >
686 {
687  public:
688  //**********************************************************************************************
689  typedef typename SelectType< IsDenseVector<VT>::value && IsTransposeVector<VT>::value &&
690  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
691  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
692  , typename TDVecTSMatMultExprTrait< typename TDVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
693  , INVALID_TYPE >::Type Type;
694  //**********************************************************************************************
695 };
697 //*************************************************************************************************
698 
699 
700 //*************************************************************************************************
702 template< typename VT, typename MT1, typename MT2 >
703 struct TSVecSMatMultExprTrait< VT, SMatTSMatMultExpr<MT1,MT2> >
704 {
705  public:
706  //**********************************************************************************************
707  typedef typename SelectType< IsSparseVector<VT>::value && IsTransposeVector<VT>::value &&
708  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
709  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
710  , typename TDVecTSMatMultExprTrait< typename TDVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
711  , INVALID_TYPE >::Type Type;
712  //**********************************************************************************************
713 };
715 //*************************************************************************************************
716 
717 } // namespace blaze
718 
719 #endif