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>
48 #include <blaze/util/Assert.h>
50 #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 
112  //**********************************************************************************************
113 
114  //**Constructor*********************************************************************************
120  explicit inline TDMatSVecMultExpr( const MT& mat, const VT& vec )
121  : mat_( mat ) // Left-hand side dense matrix of the multiplication expression
122  , vec_( vec ) // Right-hand side sparse vector of the multiplication expression
123  {
124  BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
125  }
126  //**********************************************************************************************
127 
128  //**Subscript operator**************************************************************************
134  inline ReturnType operator[]( size_t index ) const {
135  BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
136 
137  typedef typename boost::remove_reference<VCT>::type::ConstIterator ConstIterator;
138 
139  VCT x( vec_ ); // Evaluation of the right-hand side sparse vector operand
140 
141  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size(), "Invalid vector size" );
142 
143  ConstIterator element( x.begin() );
144  ElementType res;
145 
146  if( element != x.end() ) {
147  res = mat_( index, element->index() ) * element->value();
148  ++element;
149  for( ; element!=x.end(); ++element )
150  res += mat_( index, element->index() ) * element->value();
151  }
152  else {
153  reset( res );
154  }
155 
156  return res;
157  }
158  //**********************************************************************************************
159 
160  //**Size function*******************************************************************************
165  inline size_t size() const {
166  return mat_.rows();
167  }
168  //**********************************************************************************************
169 
170  //**Left function*******************************************************************************
175  inline LeftOperand leftOperand() const {
176  return mat_;
177  }
178  //**********************************************************************************************
179 
180  //**Right function******************************************************************************
185  inline RightOperand rightOperand() const {
186  return vec_;
187  }
188  //**********************************************************************************************
189 
190  //**********************************************************************************************
196  template< typename T >
197  inline bool isAliased( const T* alias ) const {
199  CanAlias<MT>::value && mat_.isAliased( alias );
200  }
201  //**********************************************************************************************
202 
203  private:
204  //**Member variables****************************************************************************
207  //**********************************************************************************************
208 
209  //**Assignment to dense vectors*****************************************************************
221  template< typename VT1 > // Type of the target dense vector
222  friend inline void assign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
223  {
224  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
225 
226  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
227 
228  // Evaluation of the right-hand side sparse vector operand
229  RT x( rhs.vec_ );
230  if( x.nonZeros() == 0UL ) {
231  reset( ~lhs );
232  return;
233  }
234 
235  // Evaluation of the left-hand side dense matrix operand
236  LT A( rhs.mat_ );
237 
238  // Checking the evaluated operands
239  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
240  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
241  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
242  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
243 
244  // Performing the dense matrix-sparse vector multiplication
245  ConstIterator element( x.begin() );
246  const ConstIterator end( x.end() );
247 
248  for( size_t i=0UL; i<A.rows(); ++i )
249  (~lhs)[i] = A(i,element->index()) * element->value();
250  ++element;
251 
252  while( element != end ) {
253  for( size_t i=0UL; i<A.rows(); ++i )
254  (~lhs)[i] += A(i,element->index()) * element->value();
255  ++element;
256  }
257  }
259  //**********************************************************************************************
260 
261  //**Assignment to sparse vectors****************************************************************
276  template< typename VT1 > // Type of the target sparse vector
277  friend inline void assign( SparseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
278  {
281  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
282 
283  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
284 
285  const ResultType tmp( rhs );
286  assign( ~lhs, tmp );
287  }
289  //**********************************************************************************************
290 
291  //**Addition assignment to dense vectors********************************************************
306  template< typename VT1 > // Type of the target dense vector
307  friend inline void addAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
308  {
309  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
310 
311  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
312 
313  // Evaluation of the right-hand side sparse vector operand
314  RT x( rhs.vec_ );
315  if( x.nonZeros() == 0UL ) return;
316 
317  // Evaluation of the left-hand side dense matrix operand
318  LT A( rhs.mat_ );
319 
320  // Checking the evaluated operands
321  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
322  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
323  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
324  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
325 
326  // Performing the dense matrix-sparse vector multiplication
327  ConstIterator element( x.begin() );
328  const ConstIterator end( x.end() );
329 
330  while( element != end ) {
331  for( size_t i=0UL; i<A.rows(); ++i )
332  (~lhs)[i] += A(i,element->index()) * element->value();
333  ++element;
334  }
335  }
337  //**********************************************************************************************
338 
339  //**Addition assignment to sparse vectors*******************************************************
340  // No special implementation for the addition assignment to sparse vectors.
341  //**********************************************************************************************
342 
343  //**Subtraction assignment to dense vectors*****************************************************
358  template< typename VT1 > // Type of the target dense vector
359  friend inline void subAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
360  {
361  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
362 
363  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
364 
365  // Evaluation of the right-hand side sparse vector operand
366  RT x( rhs.vec_ );
367  if( x.nonZeros() == 0UL ) return;
368 
369  // Evaluation of the left-hand side dense matrix operand
370  LT A( rhs.mat_ );
371 
372  // Checking the evaluated operands
373  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
374  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
375  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
376  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
377 
378  // Performing the dense matrix-sparse vector multiplication
379  ConstIterator element( x.begin() );
380  const ConstIterator end( x.end() );
381 
382  while( element != end ) {
383  for( size_t i=0UL; i<A.rows(); ++i )
384  (~lhs)[i] -= A(i,element->index()) * element->value();
385  ++element;
386  }
387  }
389  //**********************************************************************************************
390 
391  //**Subtraction assignment to sparse vectors****************************************************
392  // No special implementation for the subtraction assignment to sparse vectors.
393  //**********************************************************************************************
394 
395  //**Multiplication assignment to dense vectors**************************************************
410  template< typename VT1 > // Type of the target dense vector
411  friend inline void multAssign( DenseVector<VT1,false>& lhs, const TDMatSVecMultExpr& rhs )
412  {
415  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
416 
417  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
418 
419  const ResultType tmp( rhs );
420  multAssign( ~lhs, tmp );
421  }
423  //**********************************************************************************************
424 
425  //**Addition assignment to sparse vectors*******************************************************
426  // No special implementation for the multiplication assignment to sparse vectors.
427  //**********************************************************************************************
428 
429  //**Compile time checks*************************************************************************
436  //**********************************************************************************************
437 };
438 //*************************************************************************************************
439 
440 
441 
442 
443 //=================================================================================================
444 //
445 // GLOBAL BINARY ARITHMETIC OPERATORS
446 //
447 //=================================================================================================
448 
449 //*************************************************************************************************
481 template< typename T1 // Type of the left-hand side dense matrix
482  , typename T2 > // Type of the right-hand side sparse vector
483 inline const typename DisableIf< IsMatMatMultExpr<T1>, TDMatSVecMultExpr<T1,T2> >::Type
485 {
486  if( (~mat).columns() != (~vec).size() )
487  throw std::invalid_argument( "Matrix and vector sizes do not match" );
488 
489  return TDMatSVecMultExpr<T1,T2>( ~mat, ~vec );
490 }
491 //*************************************************************************************************
492 
493 } // namespace blaze
494 
495 #endif