All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TSMatDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TSMATDMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TSMATDMATMULTEXPR_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/DisableIf.h>
64 #include <blaze/util/EnableIf.h>
65 #include <blaze/util/InvalidType.h>
66 #include <blaze/util/SelectType.h>
67 #include <blaze/util/Types.h>
68 
69 
70 namespace blaze {
71 
72 //=================================================================================================
73 //
74 // CLASS SMATDMATMULTEXPR
75 //
76 //=================================================================================================
77 
78 //*************************************************************************************************
85 template< typename MT1 // Type of the left-hand side dense matrix
86  , typename MT2 > // Type of the right-hand side sparse matrix
87 class TSMatDMatMultExpr : public DenseMatrix< TSMatDMatMultExpr<MT1,MT2>, true >
88  , private Expression
89  , private Computation
90 {
91  private:
92  //**Type definitions****************************************************************************
93  typedef typename MT1::ResultType RT1;
94  typedef typename MT2::ResultType RT2;
95  typedef typename MT1::ElementType ET1;
96  typedef typename MT2::ElementType ET2;
97  typedef typename MT1::CompositeType CT1;
98  typedef typename MT2::CompositeType CT2;
99  //**********************************************************************************************
100 
101  public:
102  //**Type definitions****************************************************************************
105  typedef typename ResultType::OppositeType OppositeType;
106  typedef typename ResultType::TransposeType TransposeType;
107  typedef typename ResultType::ElementType ElementType;
108  typedef const ElementType ReturnType;
109  typedef const ResultType CompositeType;
110 
112  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
113 
115  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
116 
118  typedef typename SelectType< IsComputation<MT1>::value, const RT1, CT1 >::Type LT;
119 
121  typedef typename SelectType< IsComputation<MT2>::value, const RT2, CT2 >::Type RT;
122  //**********************************************************************************************
123 
124  //**Compilation flags***************************************************************************
126  enum { vectorizable = 0 };
127 
129  enum { canAlias = !IsComputation<MT2>::value };
130  //**********************************************************************************************
131 
132  //**Constructor*********************************************************************************
138  explicit inline TSMatDMatMultExpr( const MT1& lhs, const MT2& rhs )
139  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
140  , rhs_( rhs ) // Right-hand side dense matrix of the multiplication expression
141  {
142  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
143  }
144  //**********************************************************************************************
145 
146  //**Access operator*****************************************************************************
153  inline ReturnType operator()( size_t i, size_t j ) const {
154  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
155  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
156 
157  ElementType tmp;
158 
159  if( lhs_.columns() != 0UL ) {
160  tmp = lhs_(i,0UL) * rhs_(0UL,j);
161  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
162  tmp += lhs_(i,k) * rhs_(k,j);
163  }
164  }
165  else {
166  reset( tmp );
167  }
168 
169  return tmp;
170  }
171  //**********************************************************************************************
172 
173  //**Rows function*******************************************************************************
178  inline size_t rows() const {
179  return lhs_.rows();
180  }
181  //**********************************************************************************************
182 
183  //**Columns function****************************************************************************
188  inline size_t columns() const {
189  return rhs_.columns();
190  }
191  //**********************************************************************************************
192 
193  //**Left operand access*************************************************************************
198  inline LeftOperand leftOperand() const {
199  return lhs_;
200  }
201  //**********************************************************************************************
202 
203  //**Right operand access************************************************************************
208  inline RightOperand rightOperand() const {
209  return rhs_;
210  }
211  //**********************************************************************************************
212 
213  //**********************************************************************************************
219  template< typename T >
220  inline bool isAliased( const T* alias ) const {
221  return ( !IsComputation<MT2>::value && rhs_.isAliased( alias ) );
222  }
223  //**********************************************************************************************
224 
225  private:
226  //**Member variables****************************************************************************
229  //**********************************************************************************************
230 
231  //**Default assignment to dense matrices********************************************************
245  template< typename MT // Type of the target dense matrix
246  , bool SO > // Storage order of the target dense matrix
247  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
248  assign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
249  {
250  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
251  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
252 
253  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
254 
255  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
256  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
257 
258  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
259  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
260  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
261  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
262  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
263  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
264 
265  reset( ~lhs );
266 
267  const size_t block( SO ? 8UL : 256UL );
268 
269  for( size_t jj=0UL; jj<B.columns(); jj+=block ) {
270  const size_t jend( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
271  for( size_t i=0UL; i<A.columns(); ++i ) {
272  const ConstIterator end( A.end(i) );
273  ConstIterator element( A.begin(i) );
274  for( ; element!=end; ++element ) {
275  for( size_t j=jj; j<jend; ++j ) {
276  if( isDefault( (~lhs)(element->index(),j) ) )
277  (~lhs)(element->index(),j) = element->value() * B(i,j);
278  else
279  (~lhs)(element->index(),j) += element->value() * B(i,j);
280  }
281  }
282  }
283  }
284  }
286  //**********************************************************************************************
287 
288  //**Optimized assignment to dense matrices******************************************************
302  template< typename MT // Type of the target dense matrix
303  , bool SO > // Storage order of the target dense matrix
304  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
305  assign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
306  {
307  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
308  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
309 
310  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
311 
312  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
313  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
314 
315  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
316  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
317  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
318  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
319  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
320  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
321 
322  const size_t block( SO ? 8UL : 256UL );
323 
324  for( size_t jj=0UL; jj<B.columns(); jj+=block ) {
325  const size_t jend( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
326  for( size_t i=0UL; i<A.rows(); ++i ) {
327  for( size_t j=jj; j<jend; ++j ) {
328  reset( (~lhs)(i,j) );
329  }
330  }
331  for( size_t i=0UL; i<A.columns(); ++i )
332  {
333  const ConstIterator end( A.end(i) );
334  ConstIterator element( A.begin(i) );
335 
336  const size_t nonzeros( A.nonZeros(i) );
337 
338  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == ( nonzeros & size_t(-4) ), "Invalid end calculation" );
339  const size_t kend( nonzeros & size_t(-4) );
340 
341  for( size_t k=0UL; k<kend; k+=4UL ) {
342  const size_t i1( element->index() );
343  const ET1 v1( element->value() );
344  ++element;
345  const size_t i2( element->index() );
346  const ET1 v2( element->value() );
347  ++element;
348  const size_t i3( element->index() );
349  const ET1 v3( element->value() );
350  ++element;
351  const size_t i4( element->index() );
352  const ET1 v4( element->value() );
353  ++element;
354 
355  for( size_t j=jj; j<jend; ++j ) {
356  (~lhs)(i1,j) += v1 * B(i,j);
357  (~lhs)(i2,j) += v2 * B(i,j);
358  (~lhs)(i3,j) += v3 * B(i,j);
359  (~lhs)(i4,j) += v4 * B(i,j);
360  }
361  }
362 
363  for( ; element!=end; ++element ) {
364  for( size_t j=jj; j<jend; ++j ) {
365  (~lhs)(element->index(),j) += element->value() * B(i,j);
366  }
367  }
368  }
369  }
370  }
372  //**********************************************************************************************
373 
374  //**Assignment to sparse matrices***************************************************************
386  template< typename MT // Type of the target sparse matrix
387  , bool SO > // Storage order of the target sparse matrix
388  friend inline void assign( SparseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
389  {
390  typedef typename SelectType< SO, ResultType, OppositeType >::Type TmpType;
391 
397  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename TmpType::CompositeType );
398 
399  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
400  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
401 
402  const TmpType tmp( rhs );
403  assign( ~lhs, tmp );
404  }
406  //**********************************************************************************************
407 
408  //**Addition assignment to dense matrices*******************************************************
421  template< typename MT // Type of the target dense matrix
422  , bool SO > // Storage order of the target dense matrix
423  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
424  {
425  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
426  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
427 
428  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
429 
430  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
431  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
432 
433  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
434  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
435  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
436  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
437  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
438  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
439 
440  const size_t block( SO ? 8UL : 256UL );
441 
442  for( size_t jj=0UL; jj<B.columns(); jj+=block ) {
443  const size_t jend( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
444  for( size_t i=0UL; i<A.columns(); ++i )
445  {
446  const ConstIterator end( A.end(i) );
447  ConstIterator element( A.begin(i) );
448 
449  const size_t nonzeros( A.nonZeros(i) );
450 
451  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == ( nonzeros & size_t(-4) ), "Invalid end calculation" );
452  const size_t kend( nonzeros & size_t(-4) );
453 
454  for( size_t k=0UL; k<kend; k+=4UL ) {
455  const size_t i1( element->index() );
456  const ET1 v1( element->value() );
457  ++element;
458  const size_t i2( element->index() );
459  const ET1 v2( element->value() );
460  ++element;
461  const size_t i3( element->index() );
462  const ET1 v3( element->value() );
463  ++element;
464  const size_t i4( element->index() );
465  const ET1 v4( element->value() );
466  ++element;
467 
468  for( size_t j=jj; j<jend; ++j ) {
469  (~lhs)(i1,j) += v1 * B(i,j);
470  (~lhs)(i2,j) += v2 * B(i,j);
471  (~lhs)(i3,j) += v3 * B(i,j);
472  (~lhs)(i4,j) += v4 * B(i,j);
473  }
474  }
475 
476  for( ; element!=end; ++element ) {
477  for( size_t j=jj; j<jend; ++j ) {
478  (~lhs)(element->index(),j) += element->value() * B(i,j);
479  }
480  }
481  }
482  }
483  }
485  //**********************************************************************************************
486 
487  //**Addition assignment to sparse matrices******************************************************
488  // No special implementation for the addition assignment to sparse matrices.
489  //**********************************************************************************************
490 
491  //**Subtraction assignment to dense matrices****************************************************
504  template< typename MT // Type of the target dense matrix
505  , bool SO > // Storage order of the target dense matrix
506  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TSMatDMatMultExpr& rhs )
507  {
508  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
509  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
510 
511  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
512 
513  LT A( rhs.lhs_ ); // Evaluation of the right-hand side sparse matrix operand
514  RT B( rhs.rhs_ ); // Evaluation of the left-hand side dense matrix operand
515 
516  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
517  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
518  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
519  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
520  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
521  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
522 
523  const size_t block( SO ? 8UL : 256UL );
524 
525  for( size_t jj=0UL; jj<B.columns(); jj+=block ) {
526  const size_t jend( ( jj+block > B.columns() )?( B.columns() ):( jj+block ) );
527  for( size_t i=0UL; i<A.columns(); ++i )
528  {
529  const ConstIterator end( A.end(i) );
530  ConstIterator element( A.begin(i) );
531 
532  const size_t nonzeros( A.nonZeros(i) );
533 
534  BLAZE_INTERNAL_ASSERT( ( nonzeros - ( nonzeros % 4UL ) ) == ( nonzeros & size_t(-4) ), "Invalid end calculation" );
535  const size_t kend( nonzeros & size_t(-4) );
536 
537  for( size_t k=0UL; k<kend; k+=4UL ) {
538  const size_t i1( element->index() );
539  const ET1 v1( element->value() );
540  ++element;
541  const size_t i2( element->index() );
542  const ET1 v2( element->value() );
543  ++element;
544  const size_t i3( element->index() );
545  const ET1 v3( element->value() );
546  ++element;
547  const size_t i4( element->index() );
548  const ET1 v4( element->value() );
549  ++element;
550 
551  for( size_t j=jj; j<jend; ++j ) {
552  (~lhs)(i1,j) -= v1 * B(i,j);
553  (~lhs)(i2,j) -= v2 * B(i,j);
554  (~lhs)(i3,j) -= v3 * B(i,j);
555  (~lhs)(i4,j) -= v4 * B(i,j);
556  }
557  }
558 
559  for( ; element!=end; ++element ) {
560  for( size_t j=jj; j<jend; ++j ) {
561  (~lhs)(element->index(),j) -= element->value() * B(i,j);
562  }
563  }
564  }
565  }
566  }
568  //**********************************************************************************************
569 
570  //**Subtraction assignment to sparse matrices***************************************************
571  // No special implementation for the subtraction assignment to sparse matrices.
572  //**********************************************************************************************
573 
574  //**Multiplication assignment to dense matrices*************************************************
575  // No special implementation for the multiplication assignment to dense matrices.
576  //**********************************************************************************************
577 
578  //**Multiplication assignment to sparse matrices************************************************
579  // No special implementation for the multiplication assignment to sparse matrices.
580  //**********************************************************************************************
581 
582  //**Compile time checks*************************************************************************
589  //**********************************************************************************************
590 };
591 //*************************************************************************************************
592 
593 
594 
595 
596 //=================================================================================================
597 //
598 // GLOBAL BINARY ARITHMETIC OPERATORS
599 //
600 //=================================================================================================
601 
602 //*************************************************************************************************
633 template< typename T1 // Type of the left-hand side sparse matrix
634  , typename T2 > // Type of the right-hand side dense matrix
635 inline const TSMatDMatMultExpr<T1,T2>
637 {
638  if( (~lhs).columns() != (~rhs).rows() )
639  throw std::invalid_argument( "Matrix sizes do not match" );
640 
641  return TSMatDMatMultExpr<T1,T2>( ~lhs, ~rhs );
642 }
643 //*************************************************************************************************
644 
645 
646 
647 
648 //=================================================================================================
649 //
650 // EXPRESSION TRAIT SPECIALIZATIONS
651 //
652 //=================================================================================================
653 
654 //*************************************************************************************************
656 template< typename MT1, typename MT2, typename VT >
657 struct TDMatDVecMultExprTrait< TSMatDMatMultExpr<MT1,MT2>, VT >
658 {
659  public:
660  //**********************************************************************************************
661  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
662  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
663  IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
664  , typename TSMatDVecMultExprTrait< MT1, typename DMatDVecMultExprTrait<MT2,VT>::Type >::Type
665  , INVALID_TYPE >::Type Type;
666  //**********************************************************************************************
667 };
669 //*************************************************************************************************
670 
671 
672 //*************************************************************************************************
674 template< typename MT1, typename MT2, typename VT >
675 struct TDMatSVecMultExprTrait< TSMatDMatMultExpr<MT1,MT2>, VT >
676 {
677  public:
678  //**********************************************************************************************
679  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
680  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
681  IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
682  , typename TSMatDVecMultExprTrait< MT1, typename DMatSVecMultExprTrait<MT2,VT>::Type >::Type
683  , INVALID_TYPE >::Type Type;
684  //**********************************************************************************************
685 };
687 //*************************************************************************************************
688 
689 
690 //*************************************************************************************************
692 template< typename VT, typename MT1, typename MT2 >
693 struct TDVecTDMatMultExprTrait< VT, TSMatDMatMultExpr<MT1,MT2> >
694 {
695  public:
696  //**********************************************************************************************
697  typedef typename SelectType< IsDenseVector<VT>::value && IsTransposeVector<VT>::value &&
698  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
699  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
700  , typename TDVecDMatMultExprTrait< typename TDVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
701  , INVALID_TYPE >::Type Type;
702  //**********************************************************************************************
703 };
705 //*************************************************************************************************
706 
707 
708 //*************************************************************************************************
710 template< typename VT, typename MT1, typename MT2 >
711 struct TSVecTDMatMultExprTrait< VT, TSMatDMatMultExpr<MT1,MT2> >
712 {
713  public:
714  //**********************************************************************************************
715  typedef typename SelectType< IsSparseVector<VT>::value && IsTransposeVector<VT>::value &&
716  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
717  IsDenseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
718  , typename TDVecDMatMultExprTrait< typename TDVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
719  , INVALID_TYPE >::Type Type;
720  //**********************************************************************************************
721 };
723 //*************************************************************************************************
724 
725 } // namespace blaze
726 
727 #endif