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>
39 #include <blaze/math/shims/Reset.h>
46 #include <blaze/util/Assert.h>
48 #include <blaze/util/DisableIf.h>
49 #include <blaze/util/EnableIf.h>
51 #include <blaze/util/SelectType.h>
52 #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 MatVecMultExpr
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  //**********************************************************************************************
134 
135  //**Constructor*********************************************************************************
141  explicit inline SMatDVecMultExpr( const MT& mat, const VT& vec )
142  : mat_( mat ) // Left-hand side sparse matrix of the multiplication expression
143  , vec_( vec ) // Right-hand side dense vector of the multiplication expression
144  {
145  BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
146  }
147  //**********************************************************************************************
148 
149  //**Subscript operator**************************************************************************
155  inline ReturnType operator[]( size_t index ) const {
156  BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
157 
158  typedef typename RemoveReference<MCT>::Type::ConstIterator ConstIterator;
159 
160  ElementType tmp = ElementType();
161 
162  // Early exit
163  if( mat_.columns() == 0UL )
164  return tmp;
165 
166  // Fast computation in case the left-hand side sparse matrix directly provides iterators
168  {
169  MCT A( mat_ ); // Evaluation of the left-hand side sparse matrix operand
170 
171  const ConstIterator end( A.end(index) );
172  ConstIterator element( A.begin(index) );
173 
174  // Early exit in case row i is empty
175  if( element == end )
176  return tmp;
177 
178  // Calculating element 'index' for numeric data types
180  {
181  const size_t last( A.nonZeros(index) & size_t(-2) );
182  ElementType tmp2 = ElementType();
183 
184  for( size_t i=0UL; i<last; i+=2UL )
185  {
186  const ElementType value1( element->value() );
187  const size_t index1( element->index() );
188  ++element;
189  const ElementType value2( element->value() );
190  const size_t index2( element->index() );
191  ++element;
192 
193  tmp += value1 * vec_[index1];
194  tmp2 += value2 * vec_[index2];
195  }
196  if( element!=end ) {
197  tmp += element->value() * vec_[element->index()];
198  }
199 
200  tmp += tmp2;
201  }
202 
203  // Calculating element 'index' for non-numeric data types
204  else {
205  tmp = element->value() * vec_[element->index()];
206  ++element;
207  for( ; element!=end; ++element )
208  tmp += element->value() * vec_[element->index()];
209  }
210  }
211 
212  // Default computation in case the left-hand side sparse matrix doesn't provide iterators
213  else {
214  tmp = mat_(index,0UL) * vec_[0UL];
215  for( size_t k=1UL; k<mat_.columns(); ++k ) {
216  tmp += mat_(index,k) * vec_[k];
217  }
218  }
219 
220  return tmp;
221  }
222  //**********************************************************************************************
223 
224  //**Size function*******************************************************************************
229  inline size_t size() const {
230  return mat_.rows();
231  }
232  //**********************************************************************************************
233 
234  //**Left function*******************************************************************************
239  inline LeftOperand leftOperand() const {
240  return mat_;
241  }
242  //**********************************************************************************************
243 
244  //**Right function******************************************************************************
249  inline RightOperand rightOperand() const {
250  return vec_;
251  }
252  //**********************************************************************************************
253 
254  //**********************************************************************************************
260  template< typename T >
261  inline bool canAlias( const T* alias ) const {
262  return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
263  }
264  //**********************************************************************************************
265 
266  //**********************************************************************************************
272  template< typename T >
273  inline bool isAliased( const T* alias ) const {
274  return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
275  }
276  //**********************************************************************************************
277 
278  private:
279  //**Member variables****************************************************************************
280  LeftOperand mat_;
281  RightOperand vec_;
282  //**********************************************************************************************
283 
284  //**Assignment to dense vectors*****************************************************************
299  template< typename VT1 > // Type of the target dense vector
300  friend inline typename EnableIf< UseAssign<VT1> >::Type
302  {
304 
305  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
306 
307  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
308 
309  if( rhs.mat_.columns() == 0UL ) {
310  reset( ~lhs );
311  return;
312  }
313 
314  LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
315  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
316 
317  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
318  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
319  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
320  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
321 
322  (~lhs).assign( A * x );
323  }
325  //**********************************************************************************************
326 
327  //**Assignment to sparse vectors****************************************************************
342  template< typename VT1 > // Type of the target sparse vector
343  friend inline typename EnableIf< UseAssign<VT1> >::Type
345  {
347 
350  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
351 
352  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
353 
354  const ResultType tmp( rhs );
355  assign( ~lhs, tmp );
356  }
358  //**********************************************************************************************
359 
360  //**Addition assignment to dense vectors********************************************************
375  template< typename VT1 > // Type of the target dense vector
376  friend inline typename EnableIf< UseAssign<VT1> >::Type
377  addAssign( DenseVector<VT1,false>& lhs, const SMatDVecMultExpr& rhs )
378  {
380 
381  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
382 
383  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
384 
385  if( rhs.mat_.columns() == 0UL ) {
386  return;
387  }
388 
389  LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
390  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
391 
392  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
393  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
394  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
395  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
396 
397  (~lhs).addAssign( A * x );
398  }
400  //**********************************************************************************************
401 
402  //**Addition assignment to sparse vectors*******************************************************
403  // No special implementation for the addition assignment to sparse vectors.
404  //**********************************************************************************************
405 
406  //**Subtraction assignment to dense vectors*****************************************************
421  template< typename VT1 > // Type of the target dense vector
422  friend inline typename EnableIf< UseAssign<VT1> >::Type
423  subAssign( DenseVector<VT1,false>& lhs, const SMatDVecMultExpr& rhs )
424  {
426 
427  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
428 
429  typedef typename RemoveReference<LT>::Type::ConstIterator ConstIterator;
430 
431  if( rhs.mat_.columns() == 0UL ) {
432  return;
433  }
434 
435  LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
436  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
437 
438  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
439  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
440  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
441  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
442 
443  (~lhs).subAssign( A * x );
444  }
446  //**********************************************************************************************
447 
448  //**Subtraction assignment to sparse vectors****************************************************
449  // No special implementation for the subtraction assignment to sparse vectors.
450  //**********************************************************************************************
451 
452  //**Multiplication assignment to dense vectors**************************************************
467  template< typename VT1 > // Type of the target dense vector
468  friend inline typename EnableIf< UseAssign<VT1> >::Type
469  multAssign( DenseVector<VT1,false>& lhs, const SMatDVecMultExpr& rhs )
470  {
472 
475  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
476 
477  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
478 
479  const ResultType tmp( rhs );
480  multAssign( ~lhs, tmp );
481  }
483  //**********************************************************************************************
484 
485  //**Multiplication assignment to sparse vectors*************************************************
486  // No special implementation for the multiplication assignment to sparse vectors.
487  //**********************************************************************************************
488 
489  //**Compile time checks*************************************************************************
496  //**********************************************************************************************
497 };
498 //*************************************************************************************************
499 
500 
501 
502 
503 //=================================================================================================
504 //
505 // GLOBAL BINARY ARITHMETIC OPERATORS
506 //
507 //=================================================================================================
508 
509 //*************************************************************************************************
540 template< typename T1 // Type of the left-hand side sparse matrix
541  , typename T2 > // Type of the right-hand side dense vector
542 inline const typename DisableIf< IsMatMatMultExpr<T1>, SMatDVecMultExpr<T1,T2> >::Type
544 {
546 
547  if( (~mat).columns() != (~vec).size() )
548  throw std::invalid_argument( "Matrix and vector sizes do not match" );
549 
550  return SMatDVecMultExpr<T1,T2>( ~mat, ~vec );
551 }
552 //*************************************************************************************************
553 
554 
555 
556 
557 //=================================================================================================
558 //
559 // GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
560 //
561 //=================================================================================================
562 
563 //*************************************************************************************************
576 template< typename T1 // Type of the left-hand side sparse matrix
577  , bool SO // Storage order of the left-hand side sparse matrix
578  , typename T2 > // Type of the right-hand side dense vector
579 inline const typename EnableIf< IsMatMatMultExpr<T1>, MultExprTrait<T1,T2> >::Type::Type
581 {
583 
584  return (~mat).leftOperand() * ( (~mat).rightOperand() * vec );
585 }
586 //*************************************************************************************************
587 
588 } // namespace blaze
589 
590 #endif