All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SMatTDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_SMATTDMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_SMATTDMATMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
31 #include <boost/type_traits/remove_reference.hpp>
39 #include <blaze/math/shims/Reset.h>
62 #include <blaze/util/Assert.h>
63 #include <blaze/util/InvalidType.h>
64 #include <blaze/util/SelectType.h>
65 #include <blaze/util/Types.h>
66 
67 
68 namespace blaze {
69 
70 //=================================================================================================
71 //
72 // CLASS SMATTDMATMULTEXPR
73 //
74 //=================================================================================================
75 
76 //*************************************************************************************************
83 template< typename MT1 // Type of the left-hand side sparse matrix
84  , typename MT2 > // Type of the right-hand side dense matrix
85 class SMatTDMatMultExpr : public DenseMatrix< SMatTDMatMultExpr<MT1,MT2>, false >
86  , private Expression
87  , private Computation
88 {
89  private:
90  //**Type definitions****************************************************************************
91  typedef typename MT1::ResultType RT1;
92  typedef typename MT2::ResultType RT2;
93  typedef typename MT1::CompositeType CT1;
94  typedef typename MT2::CompositeType CT2;
95  //**********************************************************************************************
96 
97  public:
98  //**Type definitions****************************************************************************
101  typedef typename ResultType::OppositeType OppositeType;
102  typedef typename ResultType::TransposeType TransposeType;
103  typedef typename ResultType::ElementType ElementType;
104  typedef const ElementType ReturnType;
105  typedef const ResultType CompositeType;
106 
108  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
109 
111  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
112 
114  typedef typename SelectType< IsComputation<MT1>::value, const RT1, CT1 >::Type LT;
115 
117  typedef typename SelectType< IsComputation<MT2>::value, const RT2, CT2 >::Type RT;
118  //**********************************************************************************************
119 
120  //**Compilation flags***************************************************************************
122  enum { vectorizable = 0 };
123 
125  enum { canAlias = !IsComputation<MT2>::value };
126  //**********************************************************************************************
127 
128  //**Constructor*********************************************************************************
134  explicit inline SMatTDMatMultExpr( const MT1& lhs, const MT2& rhs )
135  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
136  , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
137  {
138  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
139  }
140  //**********************************************************************************************
141 
142  //**Access operator*****************************************************************************
149  inline ReturnType operator()( size_t i, size_t j ) const {
150  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
151  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
152 
153  typedef typename boost::remove_reference<CT1>::type::ConstIterator ConstIterator;
154 
155  ElementType tmp = ElementType();
156 
157  // Early exit
158  if( lhs_.columns() == 0UL )
159  return tmp;
160 
161  // Fast computation in case the left-hand side sparse matrix directly provides iterators
163  {
164  // Evaluation of the left-hand side sparse matrix operand
165  CT1 A( lhs_ );
166 
167  const ConstIterator end( A.end(i) );
168  ConstIterator element( A.begin(i) );
169 
170  // Early exit in case row i is empty
171  if( element == end )
172  return tmp;
173 
174  // Calculating element (i,j)
175  tmp = element->value() * rhs_(element->index(),j);
176  ++element;
177  for( ; element!=end; ++element )
178  tmp += element->value() * rhs_(element->index(),j);
179  }
180 
181  // Default computation in case the left-hand side sparse matrix doesn't provide iterators
182  else {
183  tmp = lhs_(i,0UL) * rhs_(0UL,j);
184  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
185  tmp += lhs_(i,k) * rhs_(k,j);
186  }
187  }
188 
189  return tmp;
190  }
191  //**********************************************************************************************
192 
193  //**Rows function*******************************************************************************
198  inline size_t rows() const {
199  return lhs_.rows();
200  }
201  //**********************************************************************************************
202 
203  //**Columns function****************************************************************************
208  inline size_t columns() const {
209  return rhs_.columns();
210  }
211  //**********************************************************************************************
212 
213  //**Left operand access*************************************************************************
218  inline LeftOperand leftOperand() const {
219  return lhs_;
220  }
221  //**********************************************************************************************
222 
223  //**Right operand access************************************************************************
228  inline RightOperand rightOperand() const {
229  return rhs_;
230  }
231  //**********************************************************************************************
232 
233  //**********************************************************************************************
239  template< typename T >
240  inline bool isAliased( const T* alias ) const {
241  return ( !IsComputation<MT2>::value && rhs_.isAliased( alias ) );
242  }
243  //**********************************************************************************************
244 
245  private:
246  //**Member variables****************************************************************************
249  //**********************************************************************************************
250 
251  //**Assignment to dense matrices****************************************************************
263  template< typename MT // Type of the target dense matrix
264  , bool SO > // Storage order of the target dense matrix
265  friend inline void assign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
266  {
267  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
268  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
269 
270  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
271 
272  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
273  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
274 
275  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
276  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
277  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
278  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
279  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
280  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
281 
282  const size_t block( 256UL );
283 
284  BLAZE_INTERNAL_ASSERT( ( B.columns() - ( B.columns() % 4UL ) ) == ( B.columns() & size_t(-4) ), "Invalid end calculation" );
285  const size_t jend( B.columns() & size_t(-4) );
286 
287  for( size_t ii=0UL; ii<A.rows(); ii+=block ) {
288  const size_t iend( ( ii+block > A.rows() )?( A.rows() ):( ii+block ) );
289  for( size_t j=0UL; j<jend; j+=4UL ) {
290  for( size_t i=ii; i<iend; ++i ) {
291  const ConstIterator end( A.end(i) );
292  ConstIterator element( A.begin(i) );
293  if( element!=end ) {
294  (~lhs)(i,j ) = element->value() * B(element->index(),j );
295  (~lhs)(i,j+1UL) = element->value() * B(element->index(),j+1UL);
296  (~lhs)(i,j+2UL) = element->value() * B(element->index(),j+2UL);
297  (~lhs)(i,j+3UL) = element->value() * B(element->index(),j+3UL);
298  ++element;
299  for( ; element!=end; ++element ) {
300  (~lhs)(i,j ) += element->value() * B(element->index(),j );
301  (~lhs)(i,j+1UL) += element->value() * B(element->index(),j+1UL);
302  (~lhs)(i,j+2UL) += element->value() * B(element->index(),j+2UL);
303  (~lhs)(i,j+3UL) += element->value() * B(element->index(),j+3UL);
304  }
305  }
306  else {
307  reset( (~lhs)(i,j ) );
308  reset( (~lhs)(i,j+1UL) );
309  reset( (~lhs)(i,j+2UL) );
310  reset( (~lhs)(i,j+3UL) );
311  }
312  }
313  }
314  for( size_t j=jend; j<B.columns(); ++j ) {
315  for( size_t i=ii; i<iend; ++i ) {
316  const ConstIterator end( A.end(i) );
317  ConstIterator element( A.begin(i) );
318  if( element!=end ) {
319  (~lhs)(i,j) = element->value() * B(element->index(),j);
320  ++element;
321  for( ; element!=end; ++element ) {
322  (~lhs)(i,j) += element->value() * B(element->index(),j);
323  }
324  }
325  else {
326  reset( (~lhs)(i,j) );
327  }
328  }
329  }
330  }
331  }
333  //**********************************************************************************************
334 
335  //**Assignment to sparse matrices***************************************************************
347  template< typename MT // Type of the target sparse matrix
348  , bool SO > // Storage order of the target sparse matrix
349  friend inline void assign( SparseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
350  {
351  typedef typename SelectType< SO, OppositeType, ResultType >::Type TmpType;
352 
358  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename TmpType::CompositeType );
359 
360  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
361  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
362 
363  const TmpType tmp( rhs );
364  assign( ~lhs, tmp );
365  }
367  //**********************************************************************************************
368 
369  //**Addition assignment to dense matrices*******************************************************
382  template< typename MT // Type of the target dense matrix
383  , bool SO > // Storage order of the target dense matrix
384  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& 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  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
390 
391  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
392  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
393 
394  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
395  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
396  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
397  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
398  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
399  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
400 
401  const size_t block( 256UL );
402  BLAZE_INTERNAL_ASSERT( ( B.columns() - ( B.columns() % 4UL ) ) == ( B.columns() & size_t(-4) ), "Invalid end calculation" );
403  const size_t jend( B.columns() & size_t(-4) );
404 
405  for( size_t ii=0UL; ii<A.rows(); ii+=block ) {
406  const size_t iend( ( ii+block > A.rows() )?( A.rows() ):( ii+block ) );
407  for( size_t j=0UL; j<jend; j+=4UL ) {
408  for( size_t i=ii; i<iend; ++i ) {
409  const ConstIterator end( A.end(i) );
410  ConstIterator element( A.begin(i) );
411  for( ; element!=end; ++element ) {
412  (~lhs)(i,j ) += element->value() * B(element->index(),j );
413  (~lhs)(i,j+1UL) += element->value() * B(element->index(),j+1UL);
414  (~lhs)(i,j+2UL) += element->value() * B(element->index(),j+2UL);
415  (~lhs)(i,j+3UL) += element->value() * B(element->index(),j+3UL);
416  }
417  }
418  }
419  for( size_t j=jend; j<B.columns(); ++j ) {
420  for( size_t i=ii; i<iend; ++i ) {
421  const ConstIterator end( A.end(i) );
422  ConstIterator element( A.begin(i) );
423  for( ; element!=end; ++element ) {
424  (~lhs)(i,j) += element->value() * B(element->index(),j);
425  }
426  }
427  }
428  }
429  }
431  //**********************************************************************************************
432 
433  //**Addition assignment to sparse matrices******************************************************
434  // No special implementation for the addition assignment to sparse matrices.
435  //**********************************************************************************************
436 
437  //**Subtraction assignment to dense matrices****************************************************
450  template< typename MT // Type of the target dense matrix
451  , bool SO > // Storage order of the target dense matrix
452  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const SMatTDMatMultExpr& rhs )
453  {
454  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
455  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
456 
457  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
458 
459  LT A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
460  RT B( rhs.rhs_ ); // Evaluation of the right-hand side dense matrix operand
461 
462  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
463  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
464  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
465  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
466  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
467  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
468 
469  const size_t block( 256UL );
470  BLAZE_INTERNAL_ASSERT( ( B.columns() - ( B.columns() % 4UL ) ) == ( B.columns() & size_t(-4) ), "Invalid end calculation" );
471  const size_t jend( B.columns() & size_t(-4) );
472 
473  for( size_t ii=0UL; ii<A.rows(); ii+=block ) {
474  const size_t iend( ( ii+block > A.rows() )?( A.rows() ):( ii+block ) );
475  for( size_t j=0UL; j<jend; j+=4UL ) {
476  for( size_t i=ii; i<iend; ++i ) {
477  const ConstIterator end( A.end(i) );
478  ConstIterator element( A.begin(i) );
479  for( ; element!=end; ++element ) {
480  (~lhs)(i,j ) -= element->value() * B(element->index(),j );
481  (~lhs)(i,j+1UL) -= element->value() * B(element->index(),j+1UL);
482  (~lhs)(i,j+2UL) -= element->value() * B(element->index(),j+2UL);
483  (~lhs)(i,j+3UL) -= element->value() * B(element->index(),j+3UL);
484  }
485  }
486  }
487  for( size_t j=jend; j<B.columns(); ++j ) {
488  for( size_t i=ii; i<iend; ++i ) {
489  const ConstIterator end( A.end(i) );
490  ConstIterator element( A.begin(i) );
491  for( ; element!=end; ++element ) {
492  (~lhs)(i,j) -= element->value() * B(element->index(),j);
493  }
494  }
495  }
496  }
497  }
499  //**********************************************************************************************
500 
501  //**Subtraction assignment to sparse matrices***************************************************
502  // No special implementation for the subtraction assignment to sparse matrices.
503  //**********************************************************************************************
504 
505  //**Multiplication assignment to dense matrices*************************************************
506  // No special implementation for the multiplication assignment to dense matrices.
507  //**********************************************************************************************
508 
509  //**Multiplication assignment to sparse matrices************************************************
510  // No special implementation for the multiplication assignment to sparse matrices.
511  //**********************************************************************************************
512 
513  //**Compile time checks*************************************************************************
520  //**********************************************************************************************
521 };
522 //*************************************************************************************************
523 
524 
525 
526 
527 //=================================================================================================
528 //
529 // GLOBAL BINARY ARITHMETIC OPERATORS
530 //
531 //=================================================================================================
532 
533 //*************************************************************************************************
564 template< typename T1 // Type of the left-hand side sparse matrix
565  , typename T2 > // Type of the right-hand side dense matrix
566 inline const SMatTDMatMultExpr<T1,T2>
568 {
569  if( (~lhs).columns() != (~rhs).rows() )
570  throw std::invalid_argument( "Matrix sizes do not match" );
571 
572  return SMatTDMatMultExpr<T1,T2>( ~lhs, ~rhs );
573 }
574 //*************************************************************************************************
575 
576 
577 
578 
579 //=================================================================================================
580 //
581 // EXPRESSION TRAIT SPECIALIZATIONS
582 //
583 //=================================================================================================
584 
585 //*************************************************************************************************
587 template< typename MT1, typename MT2, typename VT >
588 struct DMatDVecMultExprTrait< SMatTDMatMultExpr<MT1,MT2>, VT >
589 {
590  public:
591  //**********************************************************************************************
592  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
593  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
594  IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
595  , typename SMatDVecMultExprTrait< MT1, typename TDMatDVecMultExprTrait<MT2,VT>::Type >::Type
596  , INVALID_TYPE >::Type Type;
597  //**********************************************************************************************
598 };
600 //*************************************************************************************************
601 
602 
603 //*************************************************************************************************
605 template< typename MT1, typename MT2, typename VT >
606 struct DMatSVecMultExprTrait< SMatTDMatMultExpr<MT1,MT2>, VT >
607 {
608  public:
609  //**********************************************************************************************
610  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
611  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
612  IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
613  , typename SMatDVecMultExprTrait< MT1, typename TDMatSVecMultExprTrait<MT2,VT>::Type >::Type
614  , INVALID_TYPE >::Type Type;
615  //**********************************************************************************************
616 };
618 //*************************************************************************************************
619 
620 
621 //*************************************************************************************************
623 template< typename VT, typename MT1, typename MT2 >
624 struct TDVecDMatMultExprTrait< VT, SMatTDMatMultExpr<MT1,MT2> >
625 {
626  public:
627  //**********************************************************************************************
628  typedef typename SelectType< IsDenseVector<VT>::value && IsTransposeVector<VT>::value &&
629  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
630  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
631  , typename TDVecTDMatMultExprTrait< typename TDVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
632  , INVALID_TYPE >::Type Type;
633  //**********************************************************************************************
634 };
636 //*************************************************************************************************
637 
638 
639 //*************************************************************************************************
641 template< typename VT, typename MT1, typename MT2 >
642 struct TSVecDMatMultExprTrait< VT, SMatTDMatMultExpr<MT1,MT2> >
643 {
644  public:
645  //**********************************************************************************************
646  typedef typename SelectType< IsSparseVector<VT>::value && IsTransposeVector<VT>::value &&
647  IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
648  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
649  , typename TSVecTDMatMultExprTrait< typename TSVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
650  , INVALID_TYPE >::Type Type;
651  //**********************************************************************************************
652 };
654 //*************************************************************************************************
655 
656 } // namespace blaze
657 
658 #endif