All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TDMatSVecMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TDMATSVECMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TDMATSVECMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
31 #include <boost/type_traits/remove_reference.hpp>
41 #include <blaze/math/shims/Reset.h>
47 #include <blaze/util/Assert.h>
49 #include <blaze/util/DisableIf.h>
51 #include <blaze/util/SelectType.h>
52 #include <blaze/util/Types.h>
53 
54 
55 namespace blaze {
56 
57 //=================================================================================================
58 //
59 // CLASS TDMATSVECMULTEXPR
60 //
61 //=================================================================================================
62 
63 //*************************************************************************************************
70 template< typename MT // Type of the left-hand side dense matrix
71  , typename VT > // Type of the right-hand side sparse vector
72 class TDMatSVecMultExpr : public DenseVector< TDMatSVecMultExpr<MT,VT>, false >
73  , private Expression
74  , private Computation
75 {
76  private:
77  //**Type definitions****************************************************************************
78  typedef typename MT::ResultType MRT;
79  typedef typename VT::ResultType VRT;
80  typedef typename MT::CompositeType MCT;
81  typedef typename VT::CompositeType VCT;
82  //**********************************************************************************************
83 
84  public:
85  //**Type definitions****************************************************************************
88  typedef typename ResultType::TransposeType TransposeType;
89  typedef typename ResultType::ElementType ElementType;
90  typedef const ElementType ReturnType;
91  typedef const ResultType CompositeType;
92 
94  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type LeftOperand;
95 
97  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type RightOperand;
98 
100  typedef typename MT::CompositeType LT;
101 
103  typedef typename SelectType< IsComputation<VT>::value, const VRT, typename VT::CompositeType >::Type RT;
104  //**********************************************************************************************
105 
106  //**Compilation flags***************************************************************************
108  enum { vectorizable = 0 };
109  //**********************************************************************************************
110 
111  //**Constructor*********************************************************************************
117  explicit inline TDMatSVecMultExpr( const MT& mat, const VT& vec )
118  : mat_( mat ) // Left-hand side dense matrix of the multiplication expression
119  , vec_( vec ) // Right-hand side sparse vector of the multiplication expression
120  {
121  BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
122  }
123  //**********************************************************************************************
124 
125  //**Subscript operator**************************************************************************
131  inline ReturnType operator[]( size_t index ) const {
132  BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
133 
134  typedef typename boost::remove_reference<VCT>::type::ConstIterator ConstIterator;
135 
136  VCT x( vec_ ); // Evaluation of the right-hand side sparse vector operand
137 
138  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size(), "Invalid vector size" );
139 
140  ConstIterator element( x.begin() );
141  ElementType res;
142 
143  if( element != x.end() ) {
144  res = mat_( index, element->index() ) * element->value();
145  ++element;
146  for( ; element!=x.end(); ++element )
147  res += mat_( index, element->index() ) * element->value();
148  }
149  else {
150  reset( res );
151  }
152 
153  return res;
154  }
155  //**********************************************************************************************
156 
157  //**Size function*******************************************************************************
162  inline size_t size() const {
163  return mat_.rows();
164  }
165  //**********************************************************************************************
166 
167  //**Left function*******************************************************************************
172  inline LeftOperand leftOperand() const {
173  return mat_;
174  }
175  //**********************************************************************************************
176 
177  //**Right function******************************************************************************
182  inline RightOperand rightOperand() const {
183  return vec_;
184  }
185  //**********************************************************************************************
186 
187  //**********************************************************************************************
193  template< typename T >
194  inline bool canAlias( const T* alias ) const {
195  return mat_.isAliased( alias ) || vec_.isAliased( alias );
196  }
197  //**********************************************************************************************
198 
199  //**********************************************************************************************
205  template< typename T >
206  inline bool isAliased( const T* alias ) const {
207  return mat_.isAliased( alias ) || vec_.isAliased( alias );
208  }
209  //**********************************************************************************************
210 
211  private:
212  //**Member variables****************************************************************************
215  //**********************************************************************************************
216 
217  //**Assignment to dense vectors*****************************************************************
229  template< typename VT1 > // Type of the target dense vector
230  friend inline void assign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
231  {
233 
234  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
235 
236  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
237 
238  // Evaluation of the right-hand side sparse vector operand
239  RT x( rhs.vec_ );
240  if( x.nonZeros() == 0UL ) {
241  reset( ~lhs );
242  return;
243  }
244 
245  // Evaluation of the left-hand side dense matrix operand
246  LT A( rhs.mat_ );
247 
248  // Checking the evaluated operands
249  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
250  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
251  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
252  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
253 
254  // Performing the dense matrix-sparse vector multiplication
255  ConstIterator element( x.begin() );
256  const ConstIterator end( x.end() );
257 
258  for( size_t i=0UL; i<A.rows(); ++i )
259  (~lhs)[i] = A(i,element->index()) * element->value();
260  ++element;
261 
262  while( element != end ) {
263  for( size_t i=0UL; i<A.rows(); ++i )
264  (~lhs)[i] += A(i,element->index()) * element->value();
265  ++element;
266  }
267  }
269  //**********************************************************************************************
270 
271  //**Assignment to sparse vectors****************************************************************
286  template< typename VT1 > // Type of the target sparse vector
287  friend inline void assign( SparseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
288  {
290 
293  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
294 
295  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
296 
297  const ResultType tmp( rhs );
298  assign( ~lhs, tmp );
299  }
301  //**********************************************************************************************
302 
303  //**Addition assignment to dense vectors********************************************************
318  template< typename VT1 > // Type of the target dense vector
319  friend inline void addAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
320  {
322 
323  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
324 
325  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
326 
327  // Evaluation of the right-hand side sparse vector operand
328  RT x( rhs.vec_ );
329  if( x.nonZeros() == 0UL ) return;
330 
331  // Evaluation of the left-hand side dense matrix operand
332  LT A( rhs.mat_ );
333 
334  // Checking the evaluated operands
335  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
336  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
337  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
338  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
339 
340  // Performing the dense matrix-sparse vector multiplication
341  ConstIterator element( x.begin() );
342  const ConstIterator end( x.end() );
343 
344  while( element != end ) {
345  for( size_t i=0UL; i<A.rows(); ++i )
346  (~lhs)[i] += A(i,element->index()) * element->value();
347  ++element;
348  }
349  }
351  //**********************************************************************************************
352 
353  //**Addition assignment to sparse vectors*******************************************************
354  // No special implementation for the addition assignment to sparse vectors.
355  //**********************************************************************************************
356 
357  //**Subtraction assignment to dense vectors*****************************************************
372  template< typename VT1 > // Type of the target dense vector
373  friend inline void subAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
374  {
376 
377  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
378 
379  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
380 
381  // Evaluation of the right-hand side sparse vector operand
382  RT x( rhs.vec_ );
383  if( x.nonZeros() == 0UL ) return;
384 
385  // Evaluation of the left-hand side dense matrix operand
386  LT A( rhs.mat_ );
387 
388  // Checking the evaluated operands
389  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
390  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
391  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
392  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
393 
394  // Performing the dense matrix-sparse vector multiplication
395  ConstIterator element( x.begin() );
396  const ConstIterator end( x.end() );
397 
398  while( element != end ) {
399  for( size_t i=0UL; i<A.rows(); ++i )
400  (~lhs)[i] -= A(i,element->index()) * element->value();
401  ++element;
402  }
403  }
405  //**********************************************************************************************
406 
407  //**Subtraction assignment to sparse vectors****************************************************
408  // No special implementation for the subtraction assignment to sparse vectors.
409  //**********************************************************************************************
410 
411  //**Multiplication assignment to dense vectors**************************************************
426  template< typename VT1 > // Type of the target dense vector
427  friend inline void multAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
428  {
430 
433  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
434 
435  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
436 
437  const ResultType tmp( rhs );
438  multAssign( ~lhs, tmp );
439  }
441  //**********************************************************************************************
442 
443  //**Addition assignment to sparse vectors*******************************************************
444  // No special implementation for the multiplication assignment to sparse vectors.
445  //**********************************************************************************************
446 
447  //**Compile time checks*************************************************************************
454  //**********************************************************************************************
455 };
456 //*************************************************************************************************
457 
458 
459 
460 
461 //=================================================================================================
462 //
463 // GLOBAL BINARY ARITHMETIC OPERATORS
464 //
465 //=================================================================================================
466 
467 //*************************************************************************************************
499 template< typename T1 // Type of the left-hand side dense matrix
500  , typename T2 > // Type of the right-hand side sparse vector
501 inline const typename DisableIf< IsMatMatMultExpr<T1>, TDMatSVecMultExpr<T1,T2> >::Type
503 {
505 
506  if( (~mat).columns() != (~vec).size() )
507  throw std::invalid_argument( "Matrix and vector sizes do not match" );
508 
509  return TDMatSVecMultExpr<T1,T2>( ~mat, ~vec );
510 }
511 //*************************************************************************************************
512 
513 } // namespace blaze
514 
515 #endif