All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DMatTSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_DMATTSMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_DMATTSMATMULTEXPR_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>
58 #include <blaze/util/Assert.h>
60 #include <blaze/util/InvalidType.h>
61 #include <blaze/util/SelectType.h>
62 #include <blaze/util/Types.h>
63 
64 
65 namespace blaze {
66 
67 //=================================================================================================
68 //
69 // CLASS DMATTSMATMULTEXPR
70 //
71 //=================================================================================================
72 
73 //*************************************************************************************************
80 template< typename MT1 // Type of the left-hand side dense matrix
81  , typename MT2 > // Type of the right-hand side sparse matrix
82 class DMatTSMatMultExpr : public DenseMatrix< DMatTSMatMultExpr<MT1,MT2>, false >
83  , private Expression
84  , private Computation
85 {
86  private:
87  //**Type definitions****************************************************************************
88  typedef typename MT1::ResultType RT1;
89  typedef typename MT2::ResultType RT2;
90  typedef typename MT1::CompositeType CT1;
91  typedef typename MT2::CompositeType CT2;
92  //**********************************************************************************************
93 
94  public:
95  //**Type definitions****************************************************************************
98  typedef typename ResultType::OppositeType OppositeType;
99  typedef typename ResultType::TransposeType TransposeType;
100  typedef typename ResultType::ElementType ElementType;
101  typedef const ElementType ReturnType;
102  typedef const ResultType CompositeType;
103 
105  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
106 
108  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
109 
111  typedef typename SelectType< IsComputation<MT1>::value, const RT1, CT1 >::Type LT;
112 
114  typedef typename SelectType< IsComputation<MT2>::value, const RT2, CT2 >::Type RT;
115  //**********************************************************************************************
116 
117  //**Compilation flags***************************************************************************
119  enum { vectorizable = 0 };
120 
122  enum { canAlias = !IsComputation<MT1>::value };
123  //**********************************************************************************************
124 
125  //**Constructor*********************************************************************************
131  explicit inline DMatTSMatMultExpr( const MT1& lhs, const MT2& rhs )
132  : lhs_( lhs ) // Left-hand side dense matrix of the multiplication expression
133  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
134  {
135  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
136  }
137  //**********************************************************************************************
138 
139  //**Access operator*****************************************************************************
146  inline ReturnType operator()( size_t i, size_t j ) const {
147  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
148  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
149 
150  typedef typename boost::remove_reference<CT2>::type::ConstIterator ConstIterator;
151 
152  ElementType tmp = ElementType();
153 
154  // Early exit
155  if( lhs_.columns() == 0UL )
156  return tmp;
157 
158  // Fast computation in case the right-hand side sparse matrix directly provides iterators
160  {
161  CT2 B( rhs_ ); // Evaluation of the right-hand side sparse matrix operand
162 
163  const ConstIterator end( B.end(j) );
164  ConstIterator element( B.begin(j) );
165 
166  // Early exit in case column j is empty
167  if( element == end )
168  return tmp;
169 
170  // Calculating element (i,j)
171  tmp = lhs_(i,element->index()) * element->value();
172  ++element;
173  for( ; element!=end; ++element )
174  tmp += lhs_(i,element->index()) * element->value();
175  }
176 
177  // Default computation in case the right-hand side sparse matrix doesn't provide iterators
178  else {
179  tmp = lhs_(i,0UL) * rhs_(0UL,j);
180  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
181  tmp += lhs_(i,k) * rhs_(k,j);
182  }
183  }
184 
185  return tmp;
186  }
187  //**********************************************************************************************
188 
189  //**Rows function*******************************************************************************
194  inline size_t rows() const {
195  return lhs_.rows();
196  }
197  //**********************************************************************************************
198 
199  //**Columns function****************************************************************************
204  inline size_t columns() const {
205  return rhs_.columns();
206  }
207  //**********************************************************************************************
208 
209  //**Left operand access*************************************************************************
214  inline LeftOperand leftOperand() const {
215  return lhs_;
216  }
217  //**********************************************************************************************
218 
219  //**Right operand access************************************************************************
224  inline RightOperand rightOperand() const {
225  return rhs_;
226  }
227  //**********************************************************************************************
228 
229  //**********************************************************************************************
235  template< typename T >
236  inline bool isAliased( const T* alias ) const {
237  return ( !IsComputation<MT1>::value && lhs_.isAliased( alias ) );
238  }
239  //**********************************************************************************************
240 
241  private:
242  //**Member variables****************************************************************************
245  //**********************************************************************************************
246 
247  //**Assignment to dense matrices****************************************************************
259  template< typename MT // Type of the target dense matrix
260  , bool SO > // Storage order of the target dense matrix
261  friend inline void assign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
262  {
263  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
264  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
265 
266  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
267 
268  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
269  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
270 
271  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
272  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
273  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
274 
275  for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
276  for( size_t j=0UL; j<(~lhs).columns(); ++j )
277  {
278  ConstIterator element( B.begin(j) );
279  const ConstIterator end( B.end(j) );
280 
281  if( element == end ) {
282  reset( (~lhs)(i,j) );
283  continue;
284  }
285 
286  (~lhs)(i,j) = A(i,element->index()) * element->value();
287  ++element;
288  for( ; element!=end; ++element )
289  (~lhs)(i,j) += A(i,element->index()) * element->value();
290  }
291  }
292  }
294  //**********************************************************************************************
295 
296  //**Assignment to sparse matrices***************************************************************
309  template< typename MT // Type of the target sparse matrix
310  , bool SO > // Storage order of the target sparse matrix
311  friend inline void assign( SparseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
312  {
313  typedef typename SelectType< SO, OppositeType, ResultType >::Type TmpType;
314 
320  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename TmpType::CompositeType );
321 
322  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
323  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
324 
325  const TmpType tmp( rhs );
326  assign( ~lhs, tmp );
327  }
329  //**********************************************************************************************
330 
331  //**Addition assignment to dense matrices*******************************************************
344  template< typename MT // Type of the target dense matrix
345  , bool SO > // Storage order of the target dense matrix
346  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
347  {
348  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
349  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
350 
351  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
352 
353  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
354  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
355 
356  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
357  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
358  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
359 
360  for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
361  for( size_t j=0UL; j<(~lhs).columns(); ++j )
362  {
363  ConstIterator element( B.begin(j) );
364  const ConstIterator end( B.end(j) );
365 
366  for( ; element!=end; ++element )
367  (~lhs)(i,j) += A(i,element->index()) * element->value();
368  }
369  }
370  }
372  //**********************************************************************************************
373 
374  //**Addition assignment to sparse matrices******************************************************
375  // No special implementation for the addition assignment to sparse matrices.
376  //**********************************************************************************************
377 
378  //**Subtraction assignment to dense matrices****************************************************
391  template< typename MT // Type of the target dense matrix
392  , bool SO > // Storage order of the target dense matrix
393  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const DMatTSMatMultExpr& rhs )
394  {
395  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
396  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
397 
398  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
399 
400  LT A( rhs.lhs_ ); // Evaluation of the left-hand side dense matrix operand
401  RT B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
402 
403  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
404  BLAZE_INTERNAL_ASSERT( A.columns() == B.rows() , "Invalid matrix sizes" );
405  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns(), "Invalid number of columns" );
406 
407  for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
408  for( size_t j=0UL; j<(~lhs).columns(); ++j )
409  {
410  ConstIterator element( B.begin(j) );
411  const ConstIterator end( B.end(j) );
412 
413  for( ; element!=end; ++element )
414  (~lhs)(i,j) -= A(i,element->index()) * element->value();
415  }
416  }
417  }
419  //**********************************************************************************************
420 
421  //**Subtraction assignment to sparse matrices***************************************************
422  // No special implementation for the subtraction assignment to sparse matrices.
423  //**********************************************************************************************
424 
425  //**Multiplication assignment to dense matrices*************************************************
426  // No special implementation for the multiplication assignment to dense matrices.
427  //**********************************************************************************************
428 
429  //**Multiplication assignment to sparse matrices************************************************
430  // No special implementation for the multiplication assignment to sparse matrices.
431  //**********************************************************************************************
432 
433  //**Compile time checks*************************************************************************
440  //**********************************************************************************************
441 };
442 //*************************************************************************************************
443 
444 
445 
446 
447 //=================================================================================================
448 //
449 // GLOBAL BINARY ARITHMETIC OPERATORS
450 //
451 //=================================================================================================
452 
453 //*************************************************************************************************
483 template< typename T1 // Type of the left-hand side dense matrix
484  , typename T2 > // Type of the right-hand side sparse matrix
485 inline const DMatTSMatMultExpr<T1,T2>
487 {
488  if( (~lhs).columns() != (~rhs).rows() )
489  throw std::invalid_argument( "Matrix sizes do not match" );
490 
491  return DMatTSMatMultExpr<T1,T2>( ~lhs, ~rhs );
492 }
493 //*************************************************************************************************
494 
495 
496 
497 
498 //=================================================================================================
499 //
500 // EXPRESSION TRAIT SPECIALIZATIONS
501 //
502 //=================================================================================================
503 
504 //*************************************************************************************************
506 template< typename MT1, typename MT2, typename VT >
507 struct DMatDVecMultExprTrait< DMatTSMatMultExpr<MT1,MT2>, VT >
508 {
509  public:
510  //**********************************************************************************************
511  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
512  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
513  IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
514  , typename DMatDVecMultExprTrait< MT1, typename TSMatDVecMultExprTrait<MT2,VT>::Type >::Type
515  , INVALID_TYPE >::Type Type;
516  //**********************************************************************************************
517 };
519 //*************************************************************************************************
520 
521 
522 //*************************************************************************************************
524 template< typename MT1, typename MT2, typename VT >
525 struct DMatSVecMultExprTrait< DMatTSMatMultExpr<MT1,MT2>, VT >
526 {
527  public:
528  //**********************************************************************************************
529  typedef typename SelectType< IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
530  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
531  IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
532  , typename DMatSVecMultExprTrait< MT1, typename TSMatSVecMultExprTrait<MT2,VT>::Type >::Type
533  , INVALID_TYPE >::Type Type;
534  //**********************************************************************************************
535 };
537 //*************************************************************************************************
538 
539 
540 //*************************************************************************************************
542 template< typename VT, typename MT1, typename MT2 >
543 struct TDVecDMatMultExprTrait< VT, DMatTSMatMultExpr<MT1,MT2> >
544 {
545  public:
546  //**********************************************************************************************
547  typedef typename SelectType< IsDenseVector<VT>::value && IsTransposeVector<VT>::value &&
548  IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
549  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
550  , typename TDVecTSMatMultExprTrait< typename TDVecDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
551  , INVALID_TYPE >::Type Type;
552  //**********************************************************************************************
553 };
555 //*************************************************************************************************
556 
557 
558 //*************************************************************************************************
560 template< typename VT, typename MT1, typename MT2 >
561 struct TSVecDMatMultExprTrait< VT, DMatTSMatMultExpr<MT1,MT2> >
562 {
563  public:
564  //**********************************************************************************************
565  typedef typename SelectType< IsSparseVector<VT>::value && IsTransposeVector<VT>::value &&
566  IsDenseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
567  IsSparseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
568  , typename TDVecTSMatMultExprTrait< typename TSVecDMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
569  , INVALID_TYPE >::Type Type;
570  //**********************************************************************************************
571 };
573 //*************************************************************************************************
574 
575 } // namespace blaze
576 
577 #endif