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>
32 #include <boost/type_traits/remove_reference.hpp>
44 #include <blaze/math/shims/Reset.h>
65 #include <blaze/util/Assert.h>
66 #include <blaze/util/DisableIf.h>
67 #include <blaze/util/EnableIf.h>
68 #include <blaze/util/InvalidType.h>
69 #include <blaze/util/SelectType.h>
70 #include <blaze/util/Types.h>
71 
72 
73 namespace blaze {
74 
75 //=================================================================================================
76 //
77 // CLASS TSMATSMATMULTEXPR
78 //
79 //=================================================================================================
80 
81 //*************************************************************************************************
88 template< typename MT1 // Type of the left-hand side sparse matrix
89  , typename MT2 > // Type of the right-hand side sparse matrix
90 class TSMatSMatMultExpr : public SparseMatrix< TSMatSMatMultExpr<MT1,MT2>, true >
91  , private Expression
92  , private Computation
93 {
94  private:
95  //**Type definitions****************************************************************************
96  typedef typename MT1::ResultType RT1;
97  typedef typename MT2::ResultType RT2;
98  typedef typename MT1::CompositeType CT1;
99  typedef typename MT2::CompositeType CT2;
100  //**********************************************************************************************
101 
102  public:
103  //**Type definitions****************************************************************************
106  typedef typename ResultType::OppositeType OppositeType;
107  typedef typename ResultType::TransposeType TransposeType;
108  typedef typename ResultType::ElementType ElementType;
109  typedef const ElementType ReturnType;
110  typedef const ResultType CompositeType;
111 
113  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
114 
116  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
117  //**********************************************************************************************
118 
119  //**Compilation flags***************************************************************************
123  //**********************************************************************************************
124 
125  //**Constructor*********************************************************************************
131  explicit inline TSMatSMatMultExpr( const MT1& lhs, const MT2& rhs )
132  : lhs_( lhs ) // Left-hand side sparse 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  ElementType tmp = ElementType();
151 
152  if( lhs_.columns() != 0UL ) {
153  tmp = lhs_(i,0UL) * rhs_(0UL,j);
154  for( size_t k=1UL; k<lhs_.columns(); ++k ) {
155  tmp += lhs_(i,k) * rhs_(k,j);
156  }
157  }
158 
159  return tmp;
160  }
161  //**********************************************************************************************
162 
163  //**Rows function*******************************************************************************
168  inline size_t rows() const {
169  return lhs_.rows();
170  }
171  //**********************************************************************************************
172 
173  //**Columns function****************************************************************************
178  inline size_t columns() const {
179  return rhs_.columns();
180  }
181  //**********************************************************************************************
182 
183  //**NonZeros function***************************************************************************
188  inline size_t nonZeros() const {
189  return 0UL;
190  }
191  //**********************************************************************************************
192 
193  //**NonZeros function***************************************************************************
199  inline size_t nonZeros( size_t i ) const {
200  return 0UL;
201  }
202  //**********************************************************************************************
203 
204  //**Left operand access*************************************************************************
209  inline LeftOperand leftOperand() const {
210  return lhs_;
211  }
212  //**********************************************************************************************
213 
214  //**Right operand access************************************************************************
219  inline RightOperand rightOperand() const {
220  return rhs_;
221  }
222  //**********************************************************************************************
223 
224  //**********************************************************************************************
230  template< typename T >
231  inline bool isAliased( const T* alias ) const {
233  !RequiresEvaluation<MT1>::value && lhs_.isAliased( alias ) ) ||
235  !RequiresEvaluation<MT2>::value && rhs_.isAliased( alias ) );
236  }
237  //**********************************************************************************************
238 
239  private:
240  //**Member variables****************************************************************************
243  //**********************************************************************************************
244 
245  //**Default 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 typename EnableIf< IsResizable<typename MT::ElementType> >::Type
262  assign( DenseMatrix<MT,SO>& lhs, const TSMatSMatMultExpr& rhs )
263  {
264  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
265  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
266 
267  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
268  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
269 
270  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
271  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
272 
273  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
274  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
275  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
276  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
277  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
278  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
279 
280  for( size_t j=0UL; j<A.columns(); ++j ) {
281  const LeftIterator lend( A.end(j) );
282  for( LeftIterator lelem=A.begin(j); lelem!=lend; ++lelem ) {
283  const RightIterator rend( B.end(j) );
284  for( RightIterator relem=B.begin(j); relem!=rend; ++relem )
285  {
286  if( isDefault( (~lhs)(lelem->index(),relem->index()) ) ) {
287  (~lhs)(lelem->index(),relem->index()) = lelem->value() * relem->value();
288  }
289  else {
290  (~lhs)(lelem->index(),relem->index()) += lelem->value() * relem->value();
291  }
292  }
293  }
294  }
295  }
297  //**********************************************************************************************
298 
299  //**Optimized assignment to dense matrices******************************************************
313  template< typename MT // Type of the target dense matrix
314  , bool SO > // Storage order of the target dense matrix
315  friend inline typename DisableIf< IsResizable<typename MT::ElementType> >::Type
316  assign( DenseMatrix<MT,SO>& lhs, const TSMatSMatMultExpr& rhs )
317  {
318  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
319  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
320 
321  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
322  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
323 
324  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
325  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
326 
327  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
328  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
329  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
330  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
331  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
332  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
333 
334  for( size_t j=0UL; j<A.columns(); ++j ) {
335  const LeftIterator lend( A.end(j) );
336  for( LeftIterator lelem=A.begin(j); lelem!=lend; ++lelem ) {
337  const RightIterator rend( B.end(j) );
338  for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
339  (~lhs)(lelem->index(),relem->index()) += lelem->value() * relem->value();
340  }
341  }
342  }
343  }
345  //**********************************************************************************************
346 
347  //**Assignment to row-major sparse matrices*****************************************************
360  template< typename MT > // Type of the target sparse matrix
361  friend inline void assign( SparseMatrix<MT,false>& lhs, const TSMatSMatMultExpr& rhs )
362  {
363  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
364  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
365 
366  BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( typename MT1::OppositeType );
367 
368  const typename MT1::OppositeType tmp( rhs.lhs_ );
369  assign( ~lhs, tmp * rhs.rhs_ );
370  }
372  //**********************************************************************************************
373 
374  //**Assignment to column-major sparse matrices**************************************************
387  template< typename MT > // Type of the target sparse matrix
388  friend inline void assign( SparseMatrix<MT,true>& lhs, const TSMatSMatMultExpr& rhs )
389  {
390  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
391  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
392 
393  BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( typename MT2::OppositeType );
394 
395  const typename MT2::OppositeType tmp( rhs.rhs_ );
396  assign( ~lhs, rhs.lhs_ * tmp );
397  }
399  //**********************************************************************************************
400 
401  //**Addition assignment to dense matrices*******************************************************
414  template< typename MT // Type of the target dense matrix
415  , bool SO > // Storage order of the target dense matarix
416  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const TSMatSMatMultExpr& rhs )
417  {
418  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
419  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
420 
421  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
422  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
423 
424  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
425  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
426 
427  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
428  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
429  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
430  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
431  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
432  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
433 
434  for( size_t j=0UL; j<A.columns(); ++j ) {
435  const LeftIterator lend( A.end(j) );
436  for( LeftIterator lelem=A.begin(j); lelem!=lend; ++lelem ) {
437  const RightIterator rend( B.end(j) );
438  for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
439  (~lhs)(lelem->index(),relem->index()) += lelem->value() * relem->value();
440  }
441  }
442  }
443  }
445  //**********************************************************************************************
446 
447  //**Addition assignment to sparse matrices******************************************************
448  // No special implementation for the addition assignment to sparse matrices.
449  //**********************************************************************************************
450 
451  //**Subtraction assignment to dense matrices****************************************************
464  template< typename MT // Type of the target dense matrix
465  , bool SO > // Storage order of the target dense matrix
466  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TSMatSMatMultExpr& rhs )
467  {
468  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
469  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
470 
471  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
472  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
473 
474  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
475  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
476 
477  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
478  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
479  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
480  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
481  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
482  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
483 
484  for( size_t j=0UL; j<A.columns(); ++j ) {
485  const LeftIterator lend( A.end(j) );
486  for( LeftIterator lelem=A.begin(j); lelem!=lend; ++lelem ) {
487  const RightIterator rend( B.end(j) );
488  for( RightIterator relem=B.begin(j); relem!=rend; ++relem ) {
489  (~lhs)(lelem->index(),relem->index()) -= lelem->value() * relem->value();
490  }
491  }
492  }
493  }
495  //**********************************************************************************************
496 
497  //**Subtraction assignment to sparse matrices***************************************************
498  // No special implementation for the subtraction assignment to sparse matrices.
499  //**********************************************************************************************
500 
501  //**Multiplication assignment to dense matrices*************************************************
502  // No special implementation for the multiplication assignment to dense matrices.
503  //**********************************************************************************************
504 
505  //**Multiplication assignment to sparse matrices************************************************
506  // No special implementation for the multiplication assignment to sparse matrices.
507  //**********************************************************************************************
508 
509  //**Compile time checks*************************************************************************
516  //**********************************************************************************************
517 };
518 //*************************************************************************************************
519 
520 
521 
522 
523 //=================================================================================================
524 //
525 // GLOBAL BINARY ARITHMETIC OPERATORS
526 //
527 //=================================================================================================
528 
529 //*************************************************************************************************
559 template< typename T1 // Type of the left-hand side sparse matrix
560  , typename T2 > // Type of the right-hand side sparse matrix
561 inline const TSMatSMatMultExpr<T1,T2>
563 {
564  if( (~lhs).columns() != (~rhs).rows() )
565  throw std::invalid_argument( "Matrix sizes do not match" );
566 
567  return TSMatSMatMultExpr<T1,T2>( ~lhs, ~rhs );
568 }
569 //*************************************************************************************************
570 
571 
572 
573 
574 //=================================================================================================
575 //
576 // EXPRESSION TRAIT SPECIALIZATIONS
577 //
578 //=================================================================================================
579 
580 //*************************************************************************************************
582 template< typename MT1, typename MT2, typename VT >
583 struct TSMatDVecMultExprTrait< TSMatSMatMultExpr<MT1,MT2>, VT >
584 {
585  public:
586  //**********************************************************************************************
587  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
588  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
589  IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
590  , typename TSMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
591  , INVALID_TYPE >::Type Type;
592  //**********************************************************************************************
593 };
595 //*************************************************************************************************
596 
597 
598 //*************************************************************************************************
600 template< typename MT1, typename MT2, typename VT >
601 struct TSMatSVecMultExprTrait< TSMatSMatMultExpr<MT1,MT2>, VT >
602 {
603  public:
604  //**********************************************************************************************
605  typedef typename SelectType< IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
606  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
607  IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
608  , typename TSMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
609  , INVALID_TYPE >::Type Type;
610  //**********************************************************************************************
611 };
613 //*************************************************************************************************
614 
615 
616 //*************************************************************************************************
618 template< typename VT, typename MT1, typename MT2 >
619 struct TDVecTSMatMultExprTrait< VT, TSMatSMatMultExpr<MT1,MT2> >
620 {
621  public:
622  //**********************************************************************************************
623  typedef typename SelectType< IsDenseVector<VT>::value && IsTransposeVector<VT>::value &&
624  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
625  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
626  , typename TDVecSMatMultExprTrait< typename TDVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
627  , INVALID_TYPE >::Type Type;
628  //**********************************************************************************************
629 };
631 //*************************************************************************************************
632 
633 
634 //*************************************************************************************************
636 template< typename VT, typename MT1, typename MT2 >
637 struct TSVecTSMatMultExprTrait< VT, TSMatSMatMultExpr<MT1,MT2> >
638 {
639  public:
640  //**********************************************************************************************
641  typedef typename SelectType< IsSparseVector<VT>::value && IsTransposeVector<VT>::value &&
642  IsSparseMatrix<MT1>::value && IsColumnMajorMatrix<MT1>::value &&
643  IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
644  , typename TDVecSMatMultExprTrait< typename TDVecTSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
645  , INVALID_TYPE >::Type Type;
646  //**********************************************************************************************
647 };
649 //*************************************************************************************************
650 
651 } // namespace blaze
652 
653 #endif