All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SMatDVecMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_SMATDVECMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_SMATDVECMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
31 #include <boost/type_traits/remove_reference.hpp>
40 #include <blaze/math/shims/Reset.h>
48 #include <blaze/util/Assert.h>
50 #include <blaze/util/DisableIf.h>
51 #include <blaze/util/EnableIf.h>
52 #include <blaze/util/SelectType.h>
53 #include <blaze/util/Types.h>
54 
55 
56 namespace blaze {
57 
58 //=================================================================================================
59 //
60 // CLASS SMATDVECMULTEXPR
61 //
62 //=================================================================================================
63 
64 //*************************************************************************************************
71 template< typename MT // Type of the left-hand side sparse matrix
72  , typename VT > // Type of the right-hand side dense vector
73 class SMatDVecMultExpr : public DenseVector< SMatDVecMultExpr<MT,VT>, false >
74  , private Expression
75  , private Computation
76 {
77  private:
78  //**Type definitions****************************************************************************
79  typedef typename MT::ResultType MRT;
80  typedef typename VT::ResultType VRT;
81  typedef typename MT::CompositeType MCT;
82  typedef typename VT::CompositeType VCT;
83  //**********************************************************************************************
84 
85  //**********************************************************************************************
87 
93  enum { useAssign = ( RequiresEvaluation<MT>::value || IsComputation<VT>::value ) };
94  //**********************************************************************************************
95 
96  //**********************************************************************************************
98 
99  template< typename VT2 >
100  struct UseAssign {
101  enum { value = useAssign };
102  };
104  //**********************************************************************************************
105 
106  public:
107  //**Type definitions****************************************************************************
110  typedef typename ResultType::TransposeType TransposeType;
111  typedef typename ResultType::ElementType ElementType;
112  typedef const ElementType ReturnType;
113 
116 
118  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type LeftOperand;
119 
121  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type RightOperand;
122 
124  typedef MCT LT;
125 
127  typedef typename SelectType< IsComputation<VT>::value, const VRT, VCT >::Type RT;
128  //**********************************************************************************************
129 
130  //**Compilation flags***************************************************************************
132  enum { vectorizable = 0 };
133 
137  //**********************************************************************************************
138 
139  //**Constructor*********************************************************************************
145  explicit inline SMatDVecMultExpr( const MT& mat, const VT& vec )
146  : mat_( mat ) // Left-hand side sparse matrix of the multiplication expression
147  , vec_( vec ) // Right-hand side dense vector of the multiplication expression
148  {
149  BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
150  }
151  //**********************************************************************************************
152 
153  //**Subscript operator**************************************************************************
159  inline ReturnType operator[]( size_t index ) const {
160  BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
161 
162  typedef typename boost::remove_reference<MCT>::type::ConstIterator ConstIterator;
163 
164  ElementType tmp = ElementType();
165 
166  // Early exit
167  if( mat_.columns() == 0UL )
168  return tmp;
169 
170  // Fast computation in case the left-hand side sparse matrix directly provides iterators
172  {
173  MCT A( mat_ ); // Evaluation of the left-hand side sparse matrix operand
174 
175  const ConstIterator end( A.end(index) );
176  ConstIterator element( A.begin(index) );
177 
178  // Early exit in case row i is empty
179  if( element == end )
180  return tmp;
181 
182  // Calculating element 'index' for numeric data types
184  {
185  const size_t last( A.nonZeros(index) & size_t(-2) );
186  ElementType tmp2 = ElementType();
187 
188  for( size_t i=0UL; i<last; i+=2UL )
189  {
190  const ElementType value1( element->value() );
191  const size_t index1( element->index() );
192  ++element;
193  const ElementType value2( element->value() );
194  const size_t index2( element->index() );
195  ++element;
196 
197  tmp += value1 * vec_[index1];
198  tmp2 += value2 * vec_[index2];
199  }
200  if( element!=end ) {
201  tmp += element->value() * vec_[element->index()];
202  }
203 
204  tmp += tmp2;
205  }
206 
207  // Calculating element 'index' for non-numeric data types
208  else {
209  tmp = element->value() * vec_[element->index()];
210  ++element;
211  for( ; element!=end; ++element )
212  tmp += element->value() * vec_[element->index()];
213  }
214  }
215 
216  // Default computation in case the left-hand side sparse matrix doesn't provide iterators
217  else {
218  tmp = mat_(index,0UL) * vec_[0UL];
219  for( size_t k=1UL; k<mat_.columns(); ++k ) {
220  tmp += mat_(index,k) * vec_[k];
221  }
222  }
223 
224  return tmp;
225  }
226  //**********************************************************************************************
227 
228  //**Size function*******************************************************************************
233  inline size_t size() const {
234  return mat_.rows();
235  }
236  //**********************************************************************************************
237 
238  //**Left function*******************************************************************************
243  inline LeftOperand leftOperand() const {
244  return mat_;
245  }
246  //**********************************************************************************************
247 
248  //**Right function******************************************************************************
253  inline RightOperand rightOperand() const {
254  return vec_;
255  }
256  //**********************************************************************************************
257 
258  //**********************************************************************************************
264  template< typename T >
265  inline bool isAliased( const T* alias ) const {
267  CanAlias<MT>::value && mat_.isAliased( alias ) ) ||
268  ( !IsComputation<VT>::value && vec_.isAliased( alias ) );
269  }
270  //**********************************************************************************************
271 
272  private:
273  //**Member variables****************************************************************************
274  LeftOperand mat_;
275  RightOperand vec_;
276  //**********************************************************************************************
277 
278  //**Assignment to dense vectors*****************************************************************
293  template< typename VT1 > // Type of the target dense vector
294  friend inline typename EnableIf< UseAssign<VT1> >::Type
296  {
297  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
298 
299  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
300 
301  if( rhs.mat_.columns() == 0UL ) {
302  reset( ~lhs );
303  return;
304  }
305 
306  LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
307  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
308 
309  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
310  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
311  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
312  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
313 
314  (~lhs).assign( A * x );
315  }
317  //**********************************************************************************************
318 
319  //**Assignment to sparse vectors****************************************************************
334  template< typename VT1 > // Type of the target sparse vector
335  friend inline typename EnableIf< UseAssign<VT1> >::Type
337  {
340  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
341 
342  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
343 
344  const ResultType tmp( rhs );
345  assign( ~lhs, tmp );
346  }
348  //**********************************************************************************************
349 
350  //**Addition assignment to dense vectors********************************************************
365  template< typename VT1 > // Type of the target dense vector
366  friend inline typename EnableIf< UseAssign<VT1> >::Type
367  addAssign( DenseVector<VT1,false>& lhs, const SMatDVecMultExpr& rhs )
368  {
369  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
370 
371  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
372 
373  if( rhs.mat_.columns() == 0UL ) {
374  return;
375  }
376 
377  LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
378  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
379 
380  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
381  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
382  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
383  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
384 
385  (~lhs).addAssign( A * x );
386  }
388  //**********************************************************************************************
389 
390  //**Addition assignment to sparse vectors*******************************************************
391  // No special implementation for the addition assignment to sparse vectors.
392  //**********************************************************************************************
393 
394  //**Subtraction assignment to dense vectors*****************************************************
409  template< typename VT1 > // Type of the target dense vector
410  friend inline typename EnableIf< UseAssign<VT1> >::Type
411  subAssign( DenseVector<VT1,false>& lhs, const SMatDVecMultExpr& rhs )
412  {
413  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
414 
415  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
416 
417  if( rhs.mat_.columns() == 0UL ) {
418  return;
419  }
420 
421  LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
422  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
423 
424  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
425  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
426  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
427  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
428 
429  (~lhs).subAssign( A * x );
430  }
432  //**********************************************************************************************
433 
434  //**Subtraction assignment to sparse vectors****************************************************
435  // No special implementation for the subtraction assignment to sparse vectors.
436  //**********************************************************************************************
437 
438  //**Multiplication assignment to dense vectors**************************************************
453  template< typename VT1 > // Type of the target dense vector
454  friend inline typename EnableIf< UseAssign<VT1> >::Type
455  multAssign( DenseVector<VT1,false>& lhs, const SMatDVecMultExpr& rhs )
456  {
459  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
460 
461  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
462 
463  const ResultType tmp( rhs );
464  multAssign( ~lhs, tmp );
465  }
467  //**********************************************************************************************
468 
469  //**Multiplication assignment to sparse vectors*************************************************
470  // No special implementation for the multiplication assignment to sparse vectors.
471  //**********************************************************************************************
472 
473  //**Compile time checks*************************************************************************
480  //**********************************************************************************************
481 };
482 //*************************************************************************************************
483 
484 
485 
486 
487 //=================================================================================================
488 //
489 // GLOBAL BINARY ARITHMETIC OPERATORS
490 //
491 //=================================================================================================
492 
493 //*************************************************************************************************
524 template< typename T1 // Type of the left-hand side sparse matrix
525  , typename T2 > // Type of the right-hand side dense vector
526 inline const typename DisableIf< IsMatMatMultExpr<T1>, SMatDVecMultExpr<T1,T2> >::Type
528 {
529  if( (~mat).columns() != (~vec).size() )
530  throw std::invalid_argument( "Matrix and vector sizes do not match" );
531 
532  return SMatDVecMultExpr<T1,T2>( ~mat, ~vec );
533 }
534 //*************************************************************************************************
535 
536 
537 
538 
539 //=================================================================================================
540 //
541 // GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
542 //
543 //=================================================================================================
544 
545 //*************************************************************************************************
558 template< typename T1 // Type of the left-hand side sparse matrix
559  , bool SO // Storage order of the left-hand side sparse matrix
560  , typename T2 > // Type of the right-hand side dense vector
561 inline const typename EnableIf< IsMatMatMultExpr<T1>, MultExprTrait<T1,T2> >::Type::Type
563 {
564  return (~mat).leftOperand() * ( (~mat).rightOperand() * vec );
565 }
566 //*************************************************************************************************
567 
568 } // namespace blaze
569 
570 #endif