All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TSMatSVecMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TSMATSVECMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TSMATSVECMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
31 #include <vector>
32 #include <boost/type_traits/remove_reference.hpp>
42 #include <blaze/math/shims/Reset.h>
50 #include <blaze/util/Assert.h>
52 #include <blaze/util/DisableIf.h>
53 #include <blaze/util/EnableIf.h>
54 #include <blaze/util/SelectType.h>
55 #include <blaze/util/Types.h>
56 
57 
58 namespace blaze {
59 
60 //=================================================================================================
61 //
62 // CLASS SMATDVECMULTEXPR
63 //
64 //=================================================================================================
65 
66 //*************************************************************************************************
73 template< typename MT // Type of the left-hand side sparse matrix
74  , typename VT > // Type of the right-hand side sparse vector
75 class TSMatSVecMultExpr : public SparseVector< TSMatSVecMultExpr<MT,VT>, false >
76  , private Expression
77  , private Computation
78 {
79  private:
80  //**Type definitions****************************************************************************
81  typedef typename MT::ResultType MRT;
82  typedef typename VT::ResultType VRT;
83  typedef typename MT::CompositeType MCT;
84  typedef typename VT::CompositeType VCT;
85  //**********************************************************************************************
86 
87  public:
88  //**Type definitions****************************************************************************
91  typedef typename ResultType::TransposeType TransposeType;
92  typedef typename ResultType::ElementType ElementType;
93  typedef const ElementType ReturnType;
94 
96  typedef const ResultType CompositeType;
97 
99  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type LeftOperand;
100 
102  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type RightOperand;
103 
105  typedef MCT LT;
106 
108  typedef typename SelectType< IsComputation<VT>::value, const VRT, VCT >::Type RT;
109  //**********************************************************************************************
110 
111  //**Compilation flags***************************************************************************
115  //**********************************************************************************************
116 
117  //**Constructor*********************************************************************************
123  explicit inline TSMatSVecMultExpr( const MT& mat, const VT& vec )
124  : mat_( mat ) // Left-hand side sparse matrix of the multiplication expression
125  , vec_( vec ) // Right-hand side sparse vector of the multiplication expression
126  {
127  BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
128  }
129  //**********************************************************************************************
130 
131  //**Subscript operator**************************************************************************
137  inline ReturnType operator[]( size_t index ) const {
138  BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
139 
140  typedef typename boost::remove_reference<MCT>::type::ConstIterator MatrixIterator;
141  typedef typename boost::remove_reference<VCT>::type::ConstIterator VectorIterator;
142 
143  MCT A( mat_ ); // Evaluation of the left-hand side sparse matrix operand
144  VCT x( vec_ ); // Evaluation of the right-hand side sparse vector operand
145 
146  BLAZE_INTERNAL_ASSERT( A.rows() == mat_.rows() , "Invalid number of rows" );
147  BLAZE_INTERNAL_ASSERT( A.columns() == mat_.columns(), "Invalid number of columns" );
148  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size() , "Invalid vector size" );
149 
150  ElementType res;
151 
152  const VectorIterator vend( x.end() );
153  VectorIterator velem( x.begin() );
154 
155  if( vec_.size() > 0UL && velem != vend ) {
156  res = A( index, velem->index() ) * velem->value();
157  ++velem;
158  for( ; velem!=vend; ++velem )
159  res += A( index, velem->index() ) * velem->value();
160  }
161  else {
162  reset( res );
163  }
164 
165  return res;
166  }
167  //**********************************************************************************************
168 
169  //**Size function*******************************************************************************
174  inline size_t size() const {
175  return mat_.rows();
176  }
177  //**********************************************************************************************
178 
179  //**NonZeros function***************************************************************************
184  inline size_t nonZeros() const {
185  return mat_.rows();
186  }
187  //**********************************************************************************************
188 
189  //**Left function*******************************************************************************
194  inline LeftOperand leftOperand() const {
195  return mat_;
196  }
197  //**********************************************************************************************
198 
199  //**Right function******************************************************************************
204  inline RightOperand rightOperand() const {
205  return vec_;
206  }
207  //**********************************************************************************************
208 
209  //**********************************************************************************************
215  template< typename T >
216  inline bool isAliased( const T* alias ) const {
218  CanAlias<MT>::value && mat_.isAliased( alias ) ) ||
219  ( !IsComputation<VT>::value && vec_.isAliased( alias ) );
220  }
221  //**********************************************************************************************
222 
223  private:
224  //**Member variables****************************************************************************
227  //**********************************************************************************************
228 
229  //**Default assignment to dense vectors*********************************************************
243  template< typename VT1 > // Type of the target dense vector
244  friend inline typename EnableIf< IsResizable<typename VT1::ElementType> >::Type
246  {
247  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
248 
249  typedef typename boost::remove_reference<LT>::type::ConstIterator MatrixIterator;
250  typedef typename boost::remove_reference<RT>::type::ConstIterator VectorIterator;
251 
252  // Resetting the left-hand side target dense vector
253  reset( ~lhs );
254 
255  // Evaluation of the right-hand side sparse vector operand
256  RT x( rhs.vec_ );
257  if( x.nonZeros() == 0UL ) return;
258 
259  // Evaluation of the left-hand side sparse matrix operand
260  LT A( rhs.mat_ );
261 
262  // Checking the evaluated operators
263  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
264  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
265  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
266  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
267 
268  // Performing the transpose sparse matrix-sparse vector multiplication
269  const VectorIterator vend ( x.end() );
270  VectorIterator velem( x.begin() );
271 
272  for( ; velem!=vend; ++velem )
273  {
274  const MatrixIterator mend ( A.end( velem->index() ) );
275  MatrixIterator melem( A.begin( velem->index() ) );
276 
277  for( ; melem!=mend; ++melem ) {
278  if( isDefault( (~lhs)[melem->index()] ) )
279  (~lhs)[melem->index()] = melem->value() * velem->value();
280  else
281  (~lhs)[melem->index()] += melem->value() * velem->value();
282  }
283  }
284  }
286  //**********************************************************************************************
287 
288  //**Optimized assignment to dense vectors*******************************************************
302  template< typename VT1 > // Type of the target dense vector
303  friend inline typename DisableIf< IsResizable<typename VT1::ElementType> >::Type
305  {
306  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
307 
308  typedef typename boost::remove_reference<LT>::type::ConstIterator MatrixIterator;
309  typedef typename boost::remove_reference<RT>::type::ConstIterator VectorIterator;
310 
311  // Resetting the left-hand side target dense vector
312  reset( ~lhs );
313 
314  // Evaluation of the right-hand side sparse vector operand
315  RT x( rhs.vec_ );
316  if( x.nonZeros() == 0UL ) return;
317 
318  // Evaluation of the left-hand side sparse matrix operand
319  LT A( rhs.mat_ );
320 
321  // Checking the evaluated operators
322  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
323  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
324  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
325  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
326 
327  // Performing the transpose sparse matrix-sparse vector multiplication
328  const VectorIterator vend ( x.end() );
329  VectorIterator velem( x.begin() );
330 
331  for( ; velem!=vend; ++velem )
332  {
333  const MatrixIterator mend ( A.end( velem->index() ) );
334  MatrixIterator melem( A.begin( velem->index() ) );
335 
336  for( ; melem!=mend; ++melem ) {
337  (~lhs)[melem->index()] += melem->value() * velem->value();
338  }
339  }
340  }
342  //**********************************************************************************************
343 
344  //**Assignment to sparse vectors****************************************************************
356  template< typename VT1 > // Type of the target sparse vector
357  friend inline void assign( SparseVector<VT1,false>& lhs, const TSMatSVecMultExpr& rhs )
358  {
359  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
360 
361  typedef typename boost::remove_reference<LT>::type::ConstIterator MatrixIterator;
362  typedef typename boost::remove_reference<RT>::type::ConstIterator VectorIterator;
363 
364  RT x( rhs.vec_ ); // Evaluation of the right-hand side sparse vector operand
365  if( x.nonZeros() == 0UL ) return;
366 
367  LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
368 
369  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
370  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
371  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
372  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
373 
374  DynamicVector<ElementType> tmp( (~lhs).size() );
375  std::vector<bool> indices( (~lhs).size(), false );
376  size_t nonzeros( 0UL );
377 
378  const VectorIterator vend ( x.end() );
379  VectorIterator velem( x.begin() );
380 
381  for( ; velem!=vend; ++velem )
382  {
383  const MatrixIterator mend ( A.end( velem->index() ) );
384  MatrixIterator melem( A.begin( velem->index() ) );
385 
386  for( ; melem!=mend; ++melem ) {
387  if( !indices[melem->index()] ) {
388  indices[melem->index()] = true;
389  ++nonzeros;
390  tmp[melem->index()] = melem->value() * velem->value();
391  }
392  else {
393  tmp[melem->index()] += melem->value() * velem->value();
394  }
395  }
396  }
397 
398  (~lhs).reserve( nonzeros );
399 
400  for( size_t i=0UL; i<(~lhs).size(); ++i ) {
401  if( indices[i] ) {
402  (~lhs).append( i, tmp[i] );
403  }
404  }
405  }
407  //**********************************************************************************************
408 
409  //**Addition assignment to dense vectors********************************************************
422  template< typename VT1 > // Type of the target dense vector
423  friend inline void addAssign( DenseVector<VT1,false>& lhs, const TSMatSVecMultExpr& rhs )
424  {
425  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
426 
427  typedef typename boost::remove_reference<LT>::type::ConstIterator MatrixIterator;
428  typedef typename boost::remove_reference<RT>::type::ConstIterator VectorIterator;
429 
430  // Evaluation of the right-hand side sparse vector operand
431  RT x( rhs.vec_ );
432  if( x.nonZeros() == 0UL ) return;
433 
434  // Evaluation of the left-hand side sparse matrix operand
435  LT A( rhs.mat_ );
436 
437  // Checking the evaluated operators
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  // Performing the transpose sparse matrix-sparse vector multiplication
444  const VectorIterator vend ( x.end() );
445  VectorIterator velem( x.begin() );
446 
447  for( ; velem!=vend; ++velem )
448  {
449  const MatrixIterator mend ( A.end( velem->index() ) );
450  MatrixIterator melem( A.begin( velem->index() ) );
451 
452  for( ; melem!=mend; ++melem ) {
453  (~lhs)[melem->index()] += melem->value() * velem->value();
454  }
455  }
456  }
458  //**********************************************************************************************
459 
460  //**Addition assignment to sparse vectors*******************************************************
461  // No special implementation for the addition assignment to sparse vectors.
462  //**********************************************************************************************
463 
464  //**Subtraction assignment to dense vectors*****************************************************
477  template< typename VT1 > // Type of the target dense vector
478  friend inline void subAssign( DenseVector<VT1,false>& lhs, const TSMatSVecMultExpr& rhs )
479  {
480  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
481 
482  typedef typename boost::remove_reference<LT>::type::ConstIterator MatrixIterator;
483  typedef typename boost::remove_reference<RT>::type::ConstIterator VectorIterator;
484 
485  // Evaluation of the right-hand side sparse vector operand
486  RT x( rhs.vec_ );
487  if( x.nonZeros() == 0UL ) return;
488 
489  // Evaluation of the left-hand side sparse matrix operand
490  LT A( rhs.mat_ );
491 
492  // Checking the evaluated operators
493  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
494  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
495  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
496  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
497 
498  // Performing the transpose sparse matrix-sparse vector multiplication
499  const VectorIterator vend ( x.end() );
500  VectorIterator velem( x.begin() );
501 
502  for( ; velem!=vend; ++velem )
503  {
504  const MatrixIterator mend ( A.end( velem->index() ) );
505  MatrixIterator melem( A.begin( velem->index() ) );
506 
507  for( ; melem!=mend; ++melem ) {
508  (~lhs)[melem->index()] -= melem->value() * velem->value();
509  }
510  }
511  }
513  //**********************************************************************************************
514 
515  //**Subtraction assignment to sparse vectors****************************************************
516  // No special implementation for the subtraction assignment to sparse vectors.
517  //**********************************************************************************************
518 
519  //**Multiplication assignment to dense vectors**************************************************
532  template< typename VT1 > // Type of the target dense vector
533  friend inline void multAssign( DenseVector<VT1,false>& lhs, const TSMatSVecMultExpr& rhs )
534  {
537  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
538 
539  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
540 
541  const ResultType tmp( rhs );
542  multAssign( ~lhs, tmp );
543  }
545  //**********************************************************************************************
546 
547  //**Multiplication assignment to sparse vectors*************************************************
548  // No special implementation for the multiplication assignment to sparse vectors.
549  //**********************************************************************************************
550 
551  //**Compile time checks*************************************************************************
558  //**********************************************************************************************
559 };
560 //*************************************************************************************************
561 
562 
563 
564 
565 //=================================================================================================
566 //
567 // GLOBAL BINARY ARITHMETIC OPERATORS
568 //
569 //=================================================================================================
570 
571 //*************************************************************************************************
602 template< typename T1 // Type of the left-hand side sparse matrix
603  , typename T2 > // Type of the right-hand side sparse vector
604 inline const typename DisableIf< IsMatMatMultExpr<T1>, TSMatSVecMultExpr<T1,T2> >::Type
606 {
607  if( (~mat).columns() != (~vec).size() )
608  throw std::invalid_argument( "Matrix and vector sizes do not match" );
609 
610  return TSMatSVecMultExpr<T1,T2>( ~mat, ~vec );
611 }
612 //*************************************************************************************************
613 
614 } // namespace blaze
615 
616 #endif