All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TSVecSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TSVECSMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TSVECSMATMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
39 #include <blaze/math/shims/Reset.h>
47 #include <blaze/util/Assert.h>
49 #include <blaze/util/DisableIf.h>
50 #include <blaze/util/EnableIf.h>
52 #include <blaze/util/SelectType.h>
53 #include <blaze/util/Types.h>
55 
56 
57 namespace blaze {
58 
59 //=================================================================================================
60 //
61 // CLASS TSVECSMATMULTEXPR
62 //
63 //=================================================================================================
64 
65 //*************************************************************************************************
72 template< typename VT // Type of the left-hand side sparse vector
73  , typename MT > // Type of the right-hand side sparse matrix
74 class TSVecSMatMultExpr : public SparseVector< TSVecSMatMultExpr<VT,MT>, true >
75  , private TVecMatMultExpr
76  , private Computation
77 {
78  private:
79  //**Type definitions****************************************************************************
80  typedef typename VT::ResultType VRT;
81  typedef typename MT::ResultType MRT;
82  typedef typename VT::CompositeType VCT;
83  typedef typename MT::CompositeType MCT;
84  //**********************************************************************************************
85 
86  public:
87  //**Type definitions****************************************************************************
90  typedef typename ResultType::TransposeType TransposeType;
91  typedef typename ResultType::ElementType ElementType;
92  typedef const ElementType ReturnType;
93  typedef const ResultType CompositeType;
94 
96  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type LeftOperand;
97 
99  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type RightOperand;
100 
102  typedef typename SelectType< IsComputation<VT>::value, const VRT, VCT >::Type LT;
103 
105  typedef MCT RT;
106  //**********************************************************************************************
107 
108  public:
109  //**Constructor*********************************************************************************
115  explicit inline TSVecSMatMultExpr( const VT& vec, const MT& mat )
116  : vec_( vec ) // Left-hand side sparse vector of the multiplication expression
117  , mat_( mat ) // Right-hand side sparse matrix of the multiplication expression
118  {
119  BLAZE_INTERNAL_ASSERT( vec_.size() == mat_.rows(), "Invalid vector and matrix sizes" );
120  }
121  //**********************************************************************************************
122 
123  //**Subscript operator**************************************************************************
129  inline ReturnType operator[]( size_t index ) const {
130  BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
131 
132  typedef typename RemoveReference<VCT>::Type::ConstIterator VectorIterator;
133 
134  VCT x( vec_ ); // Evaluation of the left-hand side sparse vector operand
135  MCT A( mat_ ); // Evaluation of the right-hand side sparse matrix operand
136 
137  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size() , "Invalid vector size" );
138  BLAZE_INTERNAL_ASSERT( A.rows() == mat_.rows() , "Invalid number of rows" );
139  BLAZE_INTERNAL_ASSERT( A.columns() == mat_.columns(), "Invalid number of columns" );
140 
141  const VectorIterator vend( x.end() );
142  VectorIterator velem( x.begin() );
143  ElementType res;
144 
145  if( velem != vend ) {
146  res = velem->value() * A(velem->index(),index);
147  ++velem;
148  for( ; velem!=vend; ++velem ) {
149  res += velem->value() * A(velem->index(),index);
150  }
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_.columns();
167  }
168  //**********************************************************************************************
169 
170  //**NonZeros function***************************************************************************
175  inline size_t nonZeros() const {
176  return mat_.columns();
177  }
178  //**********************************************************************************************
179 
180  //**Left operand access*************************************************************************
185  inline LeftOperand leftOperand() const {
186  return vec_;
187  }
188  //**********************************************************************************************
189 
190  //**Right operand access************************************************************************
195  inline RightOperand rightOperand() const {
196  return mat_;
197  }
198  //**********************************************************************************************
199 
200  //**********************************************************************************************
206  template< typename T >
207  inline bool canAlias( const T* alias ) const {
208  return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
209  }
210  //**********************************************************************************************
211 
212  //**********************************************************************************************
218  template< typename T >
219  inline bool isAliased( const T* alias ) const {
220  return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
221  }
222  //**********************************************************************************************
223 
224  private:
225  //**Member variables****************************************************************************
228  //**********************************************************************************************
229 
230  //**Default assignment to dense vectors*********************************************************
244  template< typename VT1 > // Type of the target dense vector
245  friend inline typename EnableIf< IsResizable<typename VT1::ElementType> >::Type
247  {
249 
250  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
251 
252  typedef typename RemoveReference<LT>::Type::ConstIterator VectorIterator;
253  typedef typename RemoveReference<RT>::Type::ConstIterator MatrixIterator;
254 
255  // Evaluation of the left-hand side sparse vector operand
256  LT x( rhs.vec_ );
257  if( x.nonZeros() == 0UL ) {
258  reset( ~lhs );
259  return;
260  }
261 
262  // Evaluation of the right-hand side sparse matrix operand
263  RT A( rhs.mat_ );
264 
265  // Checking the evaluated operands
266  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
267  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
268  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
269  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
270 
271  // Performing the sparse vector-sparse matrix multiplication
272  const VectorIterator vend( x.end() );
273 
274  for( size_t i=0UL; i<(~lhs).size(); ++i )
275  {
276  VectorIterator velem( x.begin() );
277 
278  (~lhs)[i] = velem->value() * A(velem->index(),i);
279  ++velem;
280  for( ; velem!=vend; ++velem ) {
281  (~lhs)[i] += velem->value() * A(velem->index(),i);
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  {
307 
308  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
309 
310  typedef typename RemoveReference<LT>::Type::ConstIterator VectorIterator;
311  typedef typename RemoveReference<RT>::Type::ConstIterator MatrixIterator;
312 
313  // Resetting the left-hand side target dense vector
314  reset( ~lhs );
315 
316  // Evaluation of the left-hand side sparse vector operand
317  LT x( rhs.vec_ );
318  if( x.nonZeros() == 0UL ) return;
319 
320  // Evaluation of the right-hand side sparse matrix operand
321  RT A( rhs.mat_ );
322 
323  // Checking the evaluated operands
324  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
325  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
326  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
327  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
328 
329  // Performing the sparse vector-sparse matrix multiplication
330  const VectorIterator vend( x.end() );
331  VectorIterator velem( x.begin() );
332 
333  for( ; velem!=vend; ++velem )
334  {
335  const MatrixIterator mend( A.end( velem->index() ) );
336  MatrixIterator melem( A.begin( velem->index() ) );
337 
338  for( ; melem!=mend; ++melem ) {
339  (~lhs)[melem->index()] += velem->value() * melem->value();
340  }
341  }
342  }
344  //**********************************************************************************************
345 
346  //**Assignment to sparse vectors****************************************************************
358  template< typename VT1 > // Type of the target sparse vector
359  friend inline void assign( SparseVector<VT1,true>& lhs, const TSVecSMatMultExpr& rhs )
360  {
362 
363  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
364 
365  typedef typename RemoveReference<LT>::Type::ConstIterator VectorIterator;
366  typedef typename RemoveReference<RT>::Type::ConstIterator MatrixIterator;
367 
368  // Evaluation of the left-hand side sparse vector operand
369  LT x( rhs.vec_ );
370  if( x.nonZeros() == 0UL ) return;
371 
372  // Evaluation of the right-hand side sparse matrix operand
373  RT A( rhs.mat_ );
374 
375  // Checking the evaluated operands
376  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
377  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
378  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
379  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
380 
381  // Performing the sparse vector-sparse matrix multiplication
382  const VectorIterator vend( x.end() );
383  VectorIterator velem( x.begin() );
384 
385  for( ; velem!=vend; ++velem )
386  {
387  const MatrixIterator mend( A.end( velem->index() ) );
388  MatrixIterator melem( A.begin( velem->index() ) );
389 
390  for( ; melem!=mend; ++melem )
391  {
392  typename VT1::Iterator pos( (~lhs).find( melem->index() ) );
393  if( pos != (~lhs).end() )
394  pos->value() += velem->value() * melem->value();
395  else
396  (~lhs).insert( melem->index(), velem->value() * melem->value() );
397  }
398  }
399  }
401  //**********************************************************************************************
402 
403  //**Addition assignment to dense vectors********************************************************
416  template< typename VT1 > // Type of the target dense vector
417  friend inline void addAssign( DenseVector<VT1,true>& lhs, const TSVecSMatMultExpr& rhs )
418  {
420 
421  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
422 
423  typedef typename RemoveReference<LT>::Type::ConstIterator VectorIterator;
424  typedef typename RemoveReference<RT>::Type::ConstIterator MatrixIterator;
425 
426  // Evaluation of the left-hand side sparse vector operand
427  LT x( rhs.vec_ );
428  if( x.nonZeros() == 0UL ) return;
429 
430  // Evaluation of the right-hand side sparse matrix operand
431  RT A( rhs.mat_ );
432 
433  // Checking the evaluated operands
434  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
435  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
436  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
437  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
438 
439  // Performing the sparse vector-sparse matrix multiplication
440  const VectorIterator vend( x.end() );
441  VectorIterator velem( x.begin() );
442 
443  for( ; velem!=vend; ++velem )
444  {
445  const MatrixIterator mend( A.end( velem->index() ) );
446  MatrixIterator melem( A.begin( velem->index() ) );
447 
448  for( ; melem!=mend; ++melem ) {
449  (~lhs)[melem->index()] += velem->value() * melem->value();
450  }
451  }
452  }
454  //**********************************************************************************************
455 
456  //**Addition assignment to sparse vectors*******************************************************
457  // No special implementation for the addition assignment to sparse vectors.
458  //**********************************************************************************************
459 
460  //**Subtraction assignment to dense vectors*****************************************************
473  template< typename VT1 > // Type of the target dense vector
474  friend inline void subAssign( DenseVector<VT1,true>& lhs, const TSVecSMatMultExpr& rhs )
475  {
477 
478  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
479 
480  typedef typename RemoveReference<LT>::Type::ConstIterator VectorIterator;
481  typedef typename RemoveReference<RT>::Type::ConstIterator MatrixIterator;
482 
483  // Evaluation of the left-hand side sparse vector operand
484  LT x( rhs.vec_ );
485  if( x.nonZeros() == 0UL ) return;
486 
487  // Evaluation of the right-hand side sparse matrix operand
488  RT A( rhs.mat_ );
489 
490  // Checking the evaluated operands
491  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
492  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
493  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
494  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
495 
496  // Performing the sparse vector-sparse matrix multiplication
497  const VectorIterator vend( x.end() );
498  VectorIterator velem( x.begin() );
499 
500  for( ; velem!=vend; ++velem )
501  {
502  const MatrixIterator mend( A.end( velem->index() ) );
503  MatrixIterator melem( A.begin( velem->index() ) );
504 
505  for( ; melem!=mend; ++melem ) {
506  (~lhs)[melem->index()] -= velem->value() * melem->value();
507  }
508  }
509  }
511  //**********************************************************************************************
512 
513  //**Subtraction assignment to sparse vectors****************************************************
514  // No special implementation for the subtraction assignment to sparse vectors.
515  //**********************************************************************************************
516 
517  //**Multiplication assignment to dense vectors**************************************************
530  template< typename VT1 > // Type of the target dense vector
531  friend inline void multAssign( DenseVector<VT1,true>& lhs, const TSVecSMatMultExpr& rhs )
532  {
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 vector
603  , typename T2 > // Type of the right-hand side sparse matrix
604 inline const typename DisableIf< IsMatMatMultExpr<T2>, TSVecSMatMultExpr<T1,T2> >::Type
606 {
608 
609  if( (~vec).size() != (~mat).rows() )
610  throw std::invalid_argument( "Vector and matrix sizes do not match" );
611 
612  return TSVecSMatMultExpr<T1,T2>( ~vec, ~mat );
613 }
614 //*************************************************************************************************
615 
616 
617 
618 
619 //=================================================================================================
620 //
621 // GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
622 //
623 //=================================================================================================
624 
625 //*************************************************************************************************
638 template< typename T1 // Type of the left-hand side sparse vector
639  , typename T2 // Type of the right-hand side sparse matrix
640  , bool SO > // Storage order of the right-hand side sparse matrix
641 inline const typename EnableIf< IsMatMatMultExpr<T2>, MultExprTrait<T1,T2> >::Type::Type
643 {
645 
646  return ( vec * (~mat).leftOperand() ) * (~mat).rightOperand();
647 }
648 //*************************************************************************************************
649 
650 } // namespace blaze
651 
652 #endif