All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TSMatTDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TSMATTDMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TSMATTDMATMULTEXPR_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>
57 #include <blaze/util/Assert.h>
58 #include <blaze/util/EnableIf.h>
59 #include <blaze/util/DisableIf.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 SMATDMATMULTEXPR
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 TSMatTDMatMultExpr : public DenseMatrix< TSMatTDMatMultExpr<MT1,MT2>, true >
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::ElementType ET1;
91  typedef typename MT2::ElementType ET2;
92  typedef typename MT1::CompositeType CT1;
93  typedef typename MT2::CompositeType CT2;
94  //**********************************************************************************************
95 
96  public:
97  //**Type definitions****************************************************************************
100  typedef typename ResultType::OppositeType OppositeType;
101  typedef typename ResultType::TransposeType TransposeType;
102  typedef typename ResultType::ElementType ElementType;
103  typedef const ElementType ReturnType;
104  typedef const ResultType CompositeType;
105 
107  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
108 
110  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
111 
113  typedef typename SelectType< IsComputation<MT1>::value, const RT1, CT1 >::Type LT;
114 
116  typedef typename SelectType< IsComputation<MT2>::value, const RT2, CT2 >::Type RT;
117  //**********************************************************************************************
118 
119  //**Compilation flags***************************************************************************
121  enum { vectorizable = 0 };
122 
124  enum { canAlias = !IsComputation<MT2>::value };
125  //**********************************************************************************************
126 
127  //**Constructor*********************************************************************************
133  explicit inline TSMatTDMatMultExpr( const MT1& lhs, const MT2& rhs )
134  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
135  , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
136  {
137  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
138  }
139  //**********************************************************************************************
140 
141  //**Access operator*****************************************************************************
148  inline ReturnType operator()( size_t i, size_t j ) const {
149  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
150  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
151 
152  ElementType tmp;
153 
154  if( lhs_.columns() != 0UL ) {
155  tmp = lhs_(i,0UL) * rhs_(0UL,j);
156  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
157  tmp += lhs_(i,k) * rhs_(k,j);
158  }
159  }
160  else {
161  reset( tmp );
162  }
163 
164  return tmp;
165  }
166  //**********************************************************************************************
167 
168  //**Rows function*******************************************************************************
173  inline size_t rows() const {
174  return lhs_.rows();
175  }
176  //**********************************************************************************************
177 
178  //**Columns function****************************************************************************
183  inline size_t columns() const {
184  return rhs_.columns();
185  }
186  //**********************************************************************************************
187 
188  //**Left operand access*************************************************************************
193  inline LeftOperand leftOperand() const {
194  return lhs_;
195  }
196  //**********************************************************************************************
197 
198  //**Right operand access************************************************************************
203  inline RightOperand rightOperand() const {
204  return rhs_;
205  }
206  //**********************************************************************************************
207 
208  //**********************************************************************************************
214  template< typename T >
215  inline bool isAliased( const T* alias ) const {
216  return ( !IsComputation<MT2>::value && rhs_.isAliased( alias ) );
217  }
218  //**********************************************************************************************
219 
220  private:
221  //**Member variables****************************************************************************
224  //**********************************************************************************************
225 
226  //**Default assignment to dense matrices********************************************************
240  template< typename MT // Type of the target dense matrix
241  , bool SO > // Storage order of the target dense matrix
242  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
243  assign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
244  {
245  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
246  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
247 
248  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
249 
250  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
251  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
252 
253  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
254  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
255  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
256  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
257  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
258  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
259 
260  reset( ~lhs );
261 
262  const size_t block( 64UL );
263 
264  for( size_t jj=0UL; jj<B.columns(); jj+=block ) {
265  const size_t jend( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
266  for( size_t i=0UL; i<A.columns(); ++i ) {
267  const ConstIterator end( A.end(i) );
268  ConstIterator element( A.begin(i) );
269  for( ; element!=end; ++element ) {
270  for( size_t j=jj; j<jend; ++j ) {
271  if( isDefault( (~lhs)(element->index(),j) ) )
272  (~lhs)(element->index(),j) = element->value() * B(i,j);
273  else
274  (~lhs)(element->index(),j) += element->value() * B(i,j);
275  }
276  }
277  }
278  }
279  }
281  //**********************************************************************************************
282 
283  //**Optimized assignment to dense matrices******************************************************
297  template< typename MT // Type of the target dense matrix
298  , bool SO > // Storage order of the target dense matrix
299  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
300  assign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
301  {
302  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
303  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
304 
305  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
306 
307  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
308  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
309 
310  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
311  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
312  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
313  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
314  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
315  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
316 
317  const size_t block( SO ? 64UL : 128UL );
318 
319  for( size_t jj=0UL; jj<B.columns(); jj+=block ) {
320  const size_t jend( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
321  for( size_t i=0UL; i<A.rows(); ++i ) {
322  for( size_t j=jj; j<jend; ++j ) {
323  reset( (~lhs)(i,j) );
324  }
325  }
326  for( size_t i=0UL; i<A.columns(); ++i )
327  {
328  const ConstIterator end( A.end(i) );
329  ConstIterator element( A.begin(i) );
330 
331  const size_t nonzeros( A.nonZeros(i) );
332 
333  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == ( nonzeros & size_t(-4) ), "Invalid end calculation" );
334  const size_t kend( nonzeros & size_t(-4) );
335 
336  for( size_t k=0UL; k<kend; k+=4UL ) {
337  const size_t i1( element->index() );
338  const ET1 v1( element->value() );
339  ++element;
340  const size_t i2( element->index() );
341  const ET1 v2( element->value() );
342  ++element;
343  const size_t i3( element->index() );
344  const ET1 v3( element->value() );
345  ++element;
346  const size_t i4( element->index() );
347  const ET1 v4( element->value() );
348  ++element;
349 
350  for( size_t j=jj; j<jend; ++j ) {
351  (~lhs)(i1,j) += v1 * B(i,j);
352  (~lhs)(i2,j) += v2 * B(i,j);
353  (~lhs)(i3,j) += v3 * B(i,j);
354  (~lhs)(i4,j) += v4 * B(i,j);
355  }
356  }
357 
358  for( ; element!=end; ++element ) {
359  for( size_t j=jj; j<jend; ++j ) {
360  (~lhs)(element->index(),j) += element->value() * B(i,j);
361  }
362  }
363  }
364  }
365  }
367  //**********************************************************************************************
368 
369  //**Assignment to sparse matrices***************************************************************
382  template< typename MT // Type of the target sparse matrix
383  , bool SO > // Storage order of the target sparse matrix
384  friend inline void assign( SparseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
385  {
386  typedef typename SelectType< SO, ResultType, OppositeType >::Type TmpType;
387 
393  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename TmpType::CompositeType );
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  const TmpType tmp( rhs );
399  assign( ~lhs, tmp );
400  }
402  //**********************************************************************************************
403 
404  //**Addition assignment to dense matrices*******************************************************
417  template< typename MT // Type of the target dense matrix
418  , bool SO > // Storage order of the target dense matrix
419  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
420  {
421  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
422  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
423 
424  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
425 
426  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
427  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
428 
429  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
430  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
431  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
432  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
433  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
434  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
435 
436  const size_t block( SO ? 64UL : 128UL );
437 
438  for( size_t jj=0UL; jj<B.columns(); jj+=block ) {
439  const size_t jend( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
440  for( size_t i=0UL; i<A.columns(); ++i )
441  {
442  const ConstIterator end( A.end(i) );
443  ConstIterator element( A.begin(i) );
444 
445  const size_t nonzeros( A.nonZeros(i) );
446 
447  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == ( nonzeros & size_t(-4) ), "Invalid end calculation" );
448  const size_t kend( nonzeros & size_t(-4) );
449 
450  for( size_t k=0UL; k<kend; k+=4UL ) {
451  const size_t i1( element->index() );
452  const ET1 v1( element->value() );
453  ++element;
454  const size_t i2( element->index() );
455  const ET1 v2( element->value() );
456  ++element;
457  const size_t i3( element->index() );
458  const ET1 v3( element->value() );
459  ++element;
460  const size_t i4( element->index() );
461  const ET1 v4( element->value() );
462  ++element;
463 
464  for( size_t j=jj; j<jend; ++j ) {
465  (~lhs)(i1,j) += v1 * B(i,j);
466  (~lhs)(i2,j) += v2 * B(i,j);
467  (~lhs)(i3,j) += v3 * B(i,j);
468  (~lhs)(i4,j) += v4 * B(i,j);
469  }
470  }
471 
472  for( ; element!=end; ++element ) {
473  for( size_t j=jj; j<jend; ++j ) {
474  (~lhs)(element->index(),j) += element->value() * B(i,j);
475  }
476  }
477  }
478  }
479  }
481  //**********************************************************************************************
482 
483  //**Addition assignment to sparse matrices******************************************************
484  // No special implementation for the addition assignment to sparse matrices.
485  //**********************************************************************************************
486 
487  //**Subtraction assignment to dense matrices****************************************************
500  template< typename MT // Type of the target dense matrix
501  , bool SO > // Storage order of the target dense matrix
502  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TSMatTDMatMultExpr& rhs )
503  {
504  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
505  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
506 
507  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
508 
509  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
510  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
511 
512  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
513  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
514  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
515  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
516  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
517  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
518 
519  const size_t block( SO ? 64UL : 128UL );
520 
521  for( size_t jj=0UL; jj<B.columns(); jj+=block ) {
522  const size_t jend( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
523  for( size_t i=0UL; i<A.columns(); ++i )
524  {
525  const ConstIterator end( A.end(i) );
526  ConstIterator element( A.begin(i) );
527 
528  const size_t nonzeros( A.nonZeros(i) );
529 
530  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == ( nonzeros & size_t(-4) ), "Invalid end calculation" );
531  const size_t kend( nonzeros & size_t(-4) );
532 
533  for( size_t k=0UL; k<kend; k+=4UL ) {
534  const size_t i1( element->index() );
535  const ET1 v1( element->value() );
536  ++element;
537  const size_t i2( element->index() );
538  const ET1 v2( element->value() );
539  ++element;
540  const size_t i3( element->index() );
541  const ET1 v3( element->value() );
542  ++element;
543  const size_t i4( element->index() );
544  const ET1 v4( element->value() );
545  ++element;
546 
547  for( size_t j=jj; j<jend; ++j ) {
548  (~lhs)(i1,j) -= v1 * B(i,j);
549  (~lhs)(i2,j) -= v2 * B(i,j);
550  (~lhs)(i3,j) -= v3 * B(i,j);
551  (~lhs)(i4,j) -= v4 * B(i,j);
552  }
553  }
554 
555  for( ; element!=end; ++element ) {
556  for( size_t j=jj; j<jend; ++j ) {
557  (~lhs)(element->index(),j) -= element->value() * B(i,j);
558  }
559  }
560  }
561  }
562  }
564  //**********************************************************************************************
565 
566  //**Subtraction assignment to sparse matrices***************************************************
567  // No special implementation for the subtraction assignment to sparse matrices.
568  //**********************************************************************************************
569 
570  //**Multiplication assignment to dense matrices*************************************************
571  // No special implementation for the multiplication assignment to dense matrices.
572  //**********************************************************************************************
573 
574  //**Multiplication assignment to sparse matrices************************************************
575  // No special implementation for the multiplication assignment to sparse matrices.
576  //**********************************************************************************************
577 
578  //**Compile time checks*************************************************************************
585  //**********************************************************************************************
586 };
587 //*************************************************************************************************
588 
589 
590 
591 
592 //=================================================================================================
593 //
594 // GLOBAL BINARY ARITHMETIC OPERATORS
595 //
596 //=================================================================================================
597 
598 //*************************************************************************************************
627 template< typename T1 // Type of the left-hand side sparse matrix
628  , typename T2 > // Type of the right-hand side dense matrix
629 inline const TSMatTDMatMultExpr<T1,T2>
631 {
632  if( (~lhs).columns() != (~rhs).rows() )
633  throw std::invalid_argument( "Matrix sizes do not match" );
634 
635  return TSMatTDMatMultExpr<T1,T2>( ~lhs, ~rhs );
636 }
637 //*************************************************************************************************
638 
639 
640 
641 
642 //=================================================================================================
643 //
644 // EXPRESSION TRAIT SPECIALIZATIONS
645 //
646 //=================================================================================================
647 
648 //*************************************************************************************************
650 template< typename MT1, typename MT2, typename VT >
651 struct TDMatDVecMultExprTrait< TSMatTDMatMultExpr<MT1,MT2>, VT >
652 {
653  public:
654  //**********************************************************************************************
655  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
656  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
657  IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
658  , typename TSMatDVecMultExprTrait< MT1, typename TDMatDVecMultExprTrait<MT2,VT>::Type >::Type
659  , INVALID_TYPE >::Type Type;
660  //**********************************************************************************************
661 };
663 //*************************************************************************************************
664 
665 
666 //*************************************************************************************************
668 template< typename MT1, typename MT2, typename VT >
669 struct TDMatSVecMultExprTrait< TSMatTDMatMultExpr<MT1,MT2>, VT >
670 {
671  public:
672  //**********************************************************************************************
673  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
674  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value &&
675  IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
676  , typename TSMatDVecMultExprTrait< MT1, typename TDMatSVecMultExprTrait<MT2,VT>::Type >::Type
677  , INVALID_TYPE >::Type Type;
678  //**********************************************************************************************
679 };
681 //*************************************************************************************************
682 
683 
684 //*************************************************************************************************
686 template< typename VT, typename MT1, typename MT2 >
687 struct TDVecTDMatMultExprTrait< VT, TSMatTDMatMultExpr<MT1,MT2> >
688 {
689  public:
690  //**********************************************************************************************
691  typedef typename SelectType< IsDenseVector<VT>::value && !IsTransposeVector<VT>::value &&
692  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
693  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
694  , typename TDVecTDMatMultExprTrait< typename TDVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
695  , INVALID_TYPE >::Type Type;
696  //**********************************************************************************************
697 };
699 //*************************************************************************************************
700 
701 
702 //*************************************************************************************************
704 template< typename VT, typename MT1, typename MT2 >
705 struct TSVecTDMatMultExprTrait< VT, TSMatTDMatMultExpr<MT1,MT2> >
706 {
707  public:
708  //**********************************************************************************************
709  typedef typename SelectType< IsSparseVector<VT>::value && !IsTransposeVector<VT>::value &&
710  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
711  IsDenseMatrix<MT2>::value && IsColumnMajorMatrix<MT2>::value
712  , typename TSVecTDMatMultExprTrait< typename TSVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
713  , INVALID_TYPE >::Type Type;
714  //**********************************************************************************************
715 };
717 //*************************************************************************************************
718 
719 } // namespace blaze
720 
721 #endif