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>
49 #include <blaze/util/Assert.h>
51 #include <blaze/util/DisableIf.h>
52 #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  //**Constructor*********************************************************************************
117  explicit inline TSMatSVecMultExpr( const MT& mat, const VT& vec )
118  : mat_( mat ) // Left-hand side sparse 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<MCT>::type::ConstIterator MatrixIterator;
135  typedef typename boost::remove_reference<VCT>::type::ConstIterator VectorIterator;
136 
137  MCT A( mat_ ); // Evaluation of the left-hand side sparse matrix operand
138  VCT x( vec_ ); // Evaluation of the right-hand side sparse vector operand
139 
140  BLAZE_INTERNAL_ASSERT( A.rows() == mat_.rows() , "Invalid number of rows" );
141  BLAZE_INTERNAL_ASSERT( A.columns() == mat_.columns(), "Invalid number of columns" );
142  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size() , "Invalid vector size" );
143 
144  ElementType res;
145 
146  const VectorIterator vend( x.end() );
147  VectorIterator velem( x.begin() );
148 
149  if( vec_.size() > 0UL && velem != vend ) {
150  res = A( index, velem->index() ) * velem->value();
151  ++velem;
152  for( ; velem!=vend; ++velem )
153  res += A( index, velem->index() ) * velem->value();
154  }
155  else {
156  reset( res );
157  }
158 
159  return res;
160  }
161  //**********************************************************************************************
162 
163  //**Size function*******************************************************************************
168  inline size_t size() const {
169  return mat_.rows();
170  }
171  //**********************************************************************************************
172 
173  //**NonZeros function***************************************************************************
178  inline size_t nonZeros() const {
179  return mat_.rows();
180  }
181  //**********************************************************************************************
182 
183  //**Left function*******************************************************************************
188  inline LeftOperand leftOperand() const {
189  return mat_;
190  }
191  //**********************************************************************************************
192 
193  //**Right function******************************************************************************
198  inline RightOperand rightOperand() const {
199  return vec_;
200  }
201  //**********************************************************************************************
202 
203  //**********************************************************************************************
209  template< typename T >
210  inline bool canAlias( const T* alias ) const {
211  return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
212  }
213  //**********************************************************************************************
214 
215  //**********************************************************************************************
221  template< typename T >
222  inline bool isAliased( const T* alias ) const {
223  return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
224  }
225  //**********************************************************************************************
226 
227  private:
228  //**Member variables****************************************************************************
231  //**********************************************************************************************
232 
233  //**Default assignment to dense vectors*********************************************************
247  template< typename VT1 > // Type of the target dense vector
248  friend inline typename EnableIf< IsResizable<typename VT1::ElementType> >::Type
250  {
252 
253  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
254 
255  typedef typename boost::remove_reference<LT>::type::ConstIterator MatrixIterator;
256  typedef typename boost::remove_reference<RT>::type::ConstIterator VectorIterator;
257 
258  // Resetting the left-hand side target dense vector
259  reset( ~lhs );
260 
261  // Evaluation of the right-hand side sparse vector operand
262  RT x( rhs.vec_ );
263  if( x.nonZeros() == 0UL ) return;
264 
265  // Evaluation of the left-hand side sparse matrix operand
266  LT A( rhs.mat_ );
267 
268  // Checking the evaluated operators
269  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
270  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
271  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
272  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
273 
274  // Performing the transpose sparse matrix-sparse vector multiplication
275  const VectorIterator vend ( x.end() );
276  VectorIterator velem( x.begin() );
277 
278  for( ; velem!=vend; ++velem )
279  {
280  const MatrixIterator mend ( A.end( velem->index() ) );
281  MatrixIterator melem( A.begin( velem->index() ) );
282 
283  for( ; melem!=mend; ++melem ) {
284  if( isDefault( (~lhs)[melem->index()] ) )
285  (~lhs)[melem->index()] = melem->value() * velem->value();
286  else
287  (~lhs)[melem->index()] += melem->value() * velem->value();
288  }
289  }
290  }
292  //**********************************************************************************************
293 
294  //**Optimized assignment to dense vectors*******************************************************
308  template< typename VT1 > // Type of the target dense vector
309  friend inline typename DisableIf< IsResizable<typename VT1::ElementType> >::Type
311  {
313 
314  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
315 
316  typedef typename boost::remove_reference<LT>::type::ConstIterator MatrixIterator;
317  typedef typename boost::remove_reference<RT>::type::ConstIterator VectorIterator;
318 
319  // Resetting the left-hand side target dense vector
320  reset( ~lhs );
321 
322  // Evaluation of the right-hand side sparse vector operand
323  RT x( rhs.vec_ );
324  if( x.nonZeros() == 0UL ) return;
325 
326  // Evaluation of the left-hand side sparse matrix operand
327  LT A( rhs.mat_ );
328 
329  // Checking the evaluated operators
330  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
331  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
332  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
333  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
334 
335  // Performing the transpose sparse matrix-sparse vector multiplication
336  const VectorIterator vend ( x.end() );
337  VectorIterator velem( x.begin() );
338 
339  for( ; velem!=vend; ++velem )
340  {
341  const MatrixIterator mend ( A.end( velem->index() ) );
342  MatrixIterator melem( A.begin( velem->index() ) );
343 
344  for( ; melem!=mend; ++melem ) {
345  (~lhs)[melem->index()] += melem->value() * velem->value();
346  }
347  }
348  }
350  //**********************************************************************************************
351 
352  //**Assignment to sparse vectors****************************************************************
364  template< typename VT1 > // Type of the target sparse vector
365  friend inline void assign( SparseVector<VT1,false>& lhs, const TSMatSVecMultExpr& rhs )
366  {
368 
369  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
370 
371  typedef typename boost::remove_reference<LT>::type::ConstIterator MatrixIterator;
372  typedef typename boost::remove_reference<RT>::type::ConstIterator VectorIterator;
373 
374  RT x( rhs.vec_ ); // Evaluation of the right-hand side sparse vector operand
375  if( x.nonZeros() == 0UL ) return;
376 
377  LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
378 
379  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
380  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
381  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
382  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
383 
384  DynamicVector<ElementType> tmp( (~lhs).size() );
385  std::vector<bool> indices( (~lhs).size(), false );
386  size_t nonzeros( 0UL );
387 
388  const VectorIterator vend ( x.end() );
389  VectorIterator velem( x.begin() );
390 
391  for( ; velem!=vend; ++velem )
392  {
393  const MatrixIterator mend ( A.end( velem->index() ) );
394  MatrixIterator melem( A.begin( velem->index() ) );
395 
396  for( ; melem!=mend; ++melem ) {
397  if( !indices[melem->index()] ) {
398  indices[melem->index()] = true;
399  ++nonzeros;
400  tmp[melem->index()] = melem->value() * velem->value();
401  }
402  else {
403  tmp[melem->index()] += melem->value() * velem->value();
404  }
405  }
406  }
407 
408  (~lhs).reserve( nonzeros );
409 
410  for( size_t i=0UL; i<(~lhs).size(); ++i ) {
411  if( indices[i] ) {
412  (~lhs).append( i, tmp[i] );
413  }
414  }
415  }
417  //**********************************************************************************************
418 
419  //**Addition assignment to dense vectors********************************************************
432  template< typename VT1 > // Type of the target dense vector
433  friend inline void addAssign( DenseVector<VT1,false>& lhs, const TSMatSVecMultExpr& rhs )
434  {
436 
437  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
438 
439  typedef typename boost::remove_reference<LT>::type::ConstIterator MatrixIterator;
440  typedef typename boost::remove_reference<RT>::type::ConstIterator VectorIterator;
441 
442  // Evaluation of the right-hand side sparse vector operand
443  RT x( rhs.vec_ );
444  if( x.nonZeros() == 0UL ) return;
445 
446  // Evaluation of the left-hand side sparse matrix operand
447  LT A( rhs.mat_ );
448 
449  // Checking the evaluated operators
450  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
451  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
452  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
453  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
454 
455  // Performing the transpose sparse matrix-sparse vector multiplication
456  const VectorIterator vend ( x.end() );
457  VectorIterator velem( x.begin() );
458 
459  for( ; velem!=vend; ++velem )
460  {
461  const MatrixIterator mend ( A.end( velem->index() ) );
462  MatrixIterator melem( A.begin( velem->index() ) );
463 
464  for( ; melem!=mend; ++melem ) {
465  (~lhs)[melem->index()] += melem->value() * velem->value();
466  }
467  }
468  }
470  //**********************************************************************************************
471 
472  //**Addition assignment to sparse vectors*******************************************************
473  // No special implementation for the addition assignment to sparse vectors.
474  //**********************************************************************************************
475 
476  //**Subtraction assignment to dense vectors*****************************************************
489  template< typename VT1 > // Type of the target dense vector
490  friend inline void subAssign( DenseVector<VT1,false>& lhs, const TSMatSVecMultExpr& rhs )
491  {
493 
494  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
495 
496  typedef typename boost::remove_reference<LT>::type::ConstIterator MatrixIterator;
497  typedef typename boost::remove_reference<RT>::type::ConstIterator VectorIterator;
498 
499  // Evaluation of the right-hand side sparse vector operand
500  RT x( rhs.vec_ );
501  if( x.nonZeros() == 0UL ) return;
502 
503  // Evaluation of the left-hand side sparse matrix operand
504  LT A( rhs.mat_ );
505 
506  // Checking the evaluated operators
507  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
508  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
509  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
510  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
511 
512  // Performing the transpose sparse matrix-sparse vector multiplication
513  const VectorIterator vend ( x.end() );
514  VectorIterator velem( x.begin() );
515 
516  for( ; velem!=vend; ++velem )
517  {
518  const MatrixIterator mend ( A.end( velem->index() ) );
519  MatrixIterator melem( A.begin( velem->index() ) );
520 
521  for( ; melem!=mend; ++melem ) {
522  (~lhs)[melem->index()] -= melem->value() * velem->value();
523  }
524  }
525  }
527  //**********************************************************************************************
528 
529  //**Subtraction assignment to sparse vectors****************************************************
530  // No special implementation for the subtraction assignment to sparse vectors.
531  //**********************************************************************************************
532 
533  //**Multiplication assignment to dense vectors**************************************************
546  template< typename VT1 > // Type of the target dense vector
547  friend inline void multAssign( DenseVector<VT1,false>& lhs, const TSMatSVecMultExpr& rhs )
548  {
550 
553  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
554 
555  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
556 
557  const ResultType tmp( rhs );
558  multAssign( ~lhs, tmp );
559  }
561  //**********************************************************************************************
562 
563  //**Multiplication assignment to sparse vectors*************************************************
564  // No special implementation for the multiplication assignment to sparse vectors.
565  //**********************************************************************************************
566 
567  //**Compile time checks*************************************************************************
574  //**********************************************************************************************
575 };
576 //*************************************************************************************************
577 
578 
579 
580 
581 //=================================================================================================
582 //
583 // GLOBAL BINARY ARITHMETIC OPERATORS
584 //
585 //=================================================================================================
586 
587 //*************************************************************************************************
618 template< typename T1 // Type of the left-hand side sparse matrix
619  , typename T2 > // Type of the right-hand side sparse vector
620 inline const typename DisableIf< IsMatMatMultExpr<T1>, TSMatSVecMultExpr<T1,T2> >::Type
622 {
624 
625  if( (~mat).columns() != (~vec).size() )
626  throw std::invalid_argument( "Matrix and vector sizes do not match" );
627 
628  return TSMatSVecMultExpr<T1,T2>( ~mat, ~vec );
629 }
630 //*************************************************************************************************
631 
632 } // namespace blaze
633 
634 #endif