All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TSMatSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TSMATSMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TSMATSMATMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
31 #include <vector>
43 #include <blaze/math/shims/Reset.h>
66 #include <blaze/util/Assert.h>
67 #include <blaze/util/DisableIf.h>
68 #include <blaze/util/EnableIf.h>
69 #include <blaze/util/InvalidType.h>
71 #include <blaze/util/SelectType.h>
72 #include <blaze/util/Types.h>
74 #include <blaze/util/Unused.h>
75 
76 
77 namespace blaze {
78 
79 //=================================================================================================
80 //
81 // CLASS TSMATSMATMULTEXPR
82 //
83 //=================================================================================================
84 
85 //*************************************************************************************************
92 template< typename MT1 // Type of the left-hand side sparse matrix
93  , typename MT2 > // Type of the right-hand side sparse matrix
94 class TSMatSMatMultExpr : public SparseMatrix< TSMatSMatMultExpr<MT1,MT2>, true >
95  , private MatMatMultExpr
96  , private Computation
97 {
98  private:
99  //**Type definitions****************************************************************************
100  typedef typename MT1::ResultType RT1;
101  typedef typename MT2::ResultType RT2;
102  typedef typename MT1::CompositeType CT1;
103  typedef typename MT2::CompositeType CT2;
104  //**********************************************************************************************
105 
106  public:
107  //**Type definitions****************************************************************************
110  typedef typename ResultType::OppositeType OppositeType;
111  typedef typename ResultType::TransposeType TransposeType;
112  typedef typename ResultType::ElementType ElementType;
113  typedef const ElementType ReturnType;
114  typedef const ResultType CompositeType;
115 
117  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
118 
120  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
121  //**********************************************************************************************
122 
123  //**Constructor*********************************************************************************
129  explicit inline TSMatSMatMultExpr( const MT1& lhs, const MT2& rhs )
130  : lhs_( lhs ) // Left-hand side sparse matrix of the multiplication expression
131  , rhs_( rhs ) // Right-hand side sparse matrix of the multiplication expression
132  {
133  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.rows(), "Invalid matrix sizes" );
134  }
135  //**********************************************************************************************
136 
137  //**Access operator*****************************************************************************
144  inline ReturnType operator()( size_t i, size_t j ) const {
145  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
146  BLAZE_INTERNAL_ASSERT( j < rhs_.columns(), "Invalid column access index" );
147 
148  ElementType tmp = ElementType();
149 
150  if( lhs_.columns() != 0UL ) {
151  tmp = lhs_(i,0UL) * rhs_(0UL,j);
152  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
153  tmp += lhs_(i,k) * rhs_(k,j);
154  }
155  }
156 
157  return tmp;
158  }
159  //**********************************************************************************************
160 
161  //**Rows function*******************************************************************************
166  inline size_t rows() const {
167  return lhs_.rows();
168  }
169  //**********************************************************************************************
170 
171  //**Columns function****************************************************************************
176  inline size_t columns() const {
177  return rhs_.columns();
178  }
179  //**********************************************************************************************
180 
181  //**NonZeros function***************************************************************************
186  inline size_t nonZeros() const {
187  return 0UL;
188  }
189  //**********************************************************************************************
190 
191  //**NonZeros function***************************************************************************
197  inline size_t nonZeros( size_t i ) const {
198  UNUSED_PARAMETER( i );
199  return 0UL;
200  }
201  //**********************************************************************************************
202 
203  //**Left operand access*************************************************************************
208  inline LeftOperand leftOperand() const {
209  return lhs_;
210  }
211  //**********************************************************************************************
212 
213  //**Right operand access************************************************************************
218  inline RightOperand rightOperand() const {
219  return rhs_;
220  }
221  //**********************************************************************************************
222 
223  //**********************************************************************************************
229  template< typename T >
230  inline bool canAlias( const T* alias ) const {
231  return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
232  }
233  //**********************************************************************************************
234 
235  //**********************************************************************************************
241  template< typename T >
242  inline bool isAliased( const T* alias ) const {
243  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
244  }
245  //**********************************************************************************************
246 
247  private:
248  //**Member variables****************************************************************************
251  //**********************************************************************************************
252 
253  //**Default assignment to dense matrices********************************************************
267  template< typename MT // Type of the target dense matrix
268  , bool SO > // Storage order of the target dense matrix
269  friend inline typename EnableIf< IsResizable<typename MT::ElementType> >::Type
270  assign( DenseMatrix<MT,SO>& lhs, const TSMatSMatMultExpr& rhs )
271  {
273 
274  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
275  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
276 
277  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
278  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
279 
280  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
281  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
282 
283  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
284  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
285  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
286  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
287  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
288  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
289 
290  for( size_t j=0UL; j<A.columns(); ++j ) {
291  const LeftIterator lend( A.end(j) );
292  for( LeftIterator lelem=A.begin(j); lelem!=lend; ++lelem ) {
293  const RightIterator rend( B.end(j) );
294  for( RightIterator relem=B.begin(j); relem!=rend; ++relem )
295  {
296  if( isDefault( (~lhs)(lelem->index(),relem->index()) ) ) {
297  (~lhs)(lelem->index(),relem->index()) = lelem->value() * relem->value();
298  }
299  else {
300  (~lhs)(lelem->index(),relem->index()) += lelem->value() * relem->value();
301  }
302  }
303  }
304  }
305  }
307  //**********************************************************************************************
308 
309  //**Optimized assignment to dense matrices******************************************************
323  template< typename MT // Type of the target dense matrix
324  , bool SO > // Storage order of the target dense matrix
325  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
326  assign( DenseMatrix<MT,SO>& lhs, const TSMatSMatMultExpr& rhs )
327  {
329 
330  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
331  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
332 
333  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
334  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
335 
336  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
337  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
338 
339  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
340  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
341  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
342  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
343  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
344  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
345 
346  for( size_t j=0UL; j<A.columns(); ++j ) {
347  const LeftIterator lend( A.end(j) );
348  for( LeftIterator lelem=A.begin(j); lelem!=lend; ++lelem ) {
349  const RightIterator rend( B.end(j) );
350  for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
351  (~lhs)(lelem->index(),relem->index()) += lelem->value() * relem->value();
352  }
353  }
354  }
355  }
357  //**********************************************************************************************
358 
359  //**Assignment to row-major sparse matrices*****************************************************
372  template< typename MT > // Type of the target sparse matrix
373  friend inline void assign( SparseMatrix<MT,false>& lhs, const TSMatSMatMultExpr& rhs )
374  {
376 
377  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
378  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
379 
380  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( typename MT1::OppositeType );
381 
382  const typename MT1::OppositeType tmp( rhs.lhs_ );
383  assign( ~lhs, tmp * rhs.rhs_ );
384  }
386  //**********************************************************************************************
387 
388  //**Assignment to column-major sparse matrices**************************************************
401  template< typename MT > // Type of the target sparse matrix
402  friend inline void assign( SparseMatrix<MT,true>& lhs, const TSMatSMatMultExpr& rhs )
403  {
405 
406  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
407  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
408 
409  BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( typename MT2::OppositeType );
410 
411  const typename MT2::OppositeType tmp( rhs.rhs_ );
412  assign( ~lhs, rhs.lhs_ * tmp );
413  }
415  //**********************************************************************************************
416 
417  //**Addition assignment to dense matrices*******************************************************
430  template< typename MT // Type of the target dense matrix
431  , bool SO > // Storage order of the target dense matarix
432  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const TSMatSMatMultExpr& rhs )
433  {
435 
436  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
437  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
438 
439  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
440  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
441 
442  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
443  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
444 
445  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
446  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
447  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
448  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
449  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
450  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
451 
452  for( size_t j=0UL; j<A.columns(); ++j ) {
453  const LeftIterator lend( A.end(j) );
454  for( LeftIterator lelem=A.begin(j); lelem!=lend; ++lelem ) {
455  const RightIterator rend( B.end(j) );
456  for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
457  (~lhs)(lelem->index(),relem->index()) += lelem->value() * relem->value();
458  }
459  }
460  }
461  }
463  //**********************************************************************************************
464 
465  //**Addition assignment to sparse matrices******************************************************
466  // No special implementation for the addition assignment to sparse matrices.
467  //**********************************************************************************************
468 
469  //**Subtraction assignment to dense matrices****************************************************
482  template< typename MT // Type of the target dense matrix
483  , bool SO > // Storage order of the target dense matrix
484  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TSMatSMatMultExpr& rhs )
485  {
487 
488  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
489  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
490 
491  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
492  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
493 
494  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
495  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
496 
497  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
498  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
499  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
500  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
501  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
502  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
503 
504  for( size_t j=0UL; j<A.columns(); ++j ) {
505  const LeftIterator lend( A.end(j) );
506  for( LeftIterator lelem=A.begin(j); lelem!=lend; ++lelem ) {
507  const RightIterator rend( B.end(j) );
508  for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
509  (~lhs)(lelem->index(),relem->index()) -= lelem->value() * relem->value();
510  }
511  }
512  }
513  }
515  //**********************************************************************************************
516 
517  //**Subtraction assignment to sparse matrices***************************************************
518  // No special implementation for the subtraction assignment to sparse matrices.
519  //**********************************************************************************************
520 
521  //**Multiplication assignment to dense matrices*************************************************
522  // No special implementation for the multiplication assignment to dense matrices.
523  //**********************************************************************************************
524 
525  //**Multiplication assignment to sparse matrices************************************************
526  // No special implementation for the multiplication assignment to sparse matrices.
527  //**********************************************************************************************
528 
529  //**Compile time checks*************************************************************************
536  //**********************************************************************************************
537 };
538 //*************************************************************************************************
539 
540 
541 
542 
543 //=================================================================================================
544 //
545 // GLOBAL BINARY ARITHMETIC OPERATORS
546 //
547 //=================================================================================================
548 
549 //*************************************************************************************************
579 template< typename T1 // Type of the left-hand side sparse matrix
580  , typename T2 > // Type of the right-hand side sparse matrix
581 inline const TSMatSMatMultExpr<T1,T2>
583 {
585 
586  if( (~lhs).columns() != (~rhs).rows() )
587  throw std::invalid_argument( "Matrix sizes do not match" );
588 
589  return TSMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
590 }
591 //*************************************************************************************************
592 
593 
594 
595 
596 //=================================================================================================
597 //
598 // EXPRESSION TRAIT SPECIALIZATIONS
599 //
600 //=================================================================================================
601 
602 //*************************************************************************************************
604 template< typename MT1, typename MT2, typename VT >
605 struct TSMatDVecMultExprTrait< TSMatSMatMultExpr<MT1,MT2>, VT >
606 {
607  public:
608  //**********************************************************************************************
609  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
610  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
611  IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
612  , typename TSMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
613  , INVALID_TYPE >::Type Type;
614  //**********************************************************************************************
615 };
617 //*************************************************************************************************
618 
619 
620 //*************************************************************************************************
622 template< typename MT1, typename MT2, typename VT >
623 struct TSMatSVecMultExprTrait< TSMatSMatMultExpr<MT1,MT2>, VT >
624 {
625  public:
626  //**********************************************************************************************
627  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
628  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
629  IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
630  , typename TSMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
631  , INVALID_TYPE >::Type Type;
632  //**********************************************************************************************
633 };
635 //*************************************************************************************************
636 
637 
638 //*************************************************************************************************
640 template< typename VT, typename MT1, typename MT2 >
641 struct TDVecTSMatMultExprTrait< VT, TSMatSMatMultExpr<MT1,MT2> >
642 {
643  public:
644  //**********************************************************************************************
645  typedef typename SelectType< IsDenseVector<VT>::value && IsTransposeVector<VT>::value &&
646  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
647  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
648  , typename TDVecSMatMultExprTrait< typename TDVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
649  , INVALID_TYPE >::Type Type;
650  //**********************************************************************************************
651 };
653 //*************************************************************************************************
654 
655 
656 //*************************************************************************************************
658 template< typename VT, typename MT1, typename MT2 >
659 struct TSVecTSMatMultExprTrait< VT, TSMatSMatMultExpr<MT1,MT2> >
660 {
661  public:
662  //**********************************************************************************************
663  typedef typename SelectType< IsSparseVector<VT>::value && IsTransposeVector<VT>::value &&
664  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
665  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
666  , typename TDVecSMatMultExprTrait< typename TDVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
667  , INVALID_TYPE >::Type Type;
668  //**********************************************************************************************
669 };
671 //*************************************************************************************************
672 
673 
674 //*************************************************************************************************
676 template< typename MT1, typename MT2 >
677 struct RowExprTrait< TSMatSMatMultExpr<MT1,MT2> >
678 {
679  public:
680  //**********************************************************************************************
681  typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
682  //**********************************************************************************************
683 };
685 //*************************************************************************************************
686 
687 
688 //*************************************************************************************************
690 template< typename MT1, typename MT2 >
691 struct ColumnExprTrait< TSMatSMatMultExpr<MT1,MT2> >
692 {
693  public:
694  //**********************************************************************************************
695  typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;
696  //**********************************************************************************************
697 };
699 //*************************************************************************************************
700 
701 } // namespace blaze
702 
703 #endif