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>
31 #include <boost/type_traits/remove_reference.hpp>
40 #include <blaze/math/shims/Reset.h>
49 #include <blaze/util/Assert.h>
51 #include <blaze/util/DisableIf.h>
52 #include <blaze/util/EnableIf.h>
53 #include <blaze/util/SelectType.h>
54 #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 Expression
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  //**Compilation flags***************************************************************************
125  enum { canAlias = ( !IsComputation<VT>::value ) ||
127  //**********************************************************************************************
128 
129  //**Subscript operator**************************************************************************
135  inline ReturnType operator[]( size_t index ) const {
136  BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
137 
138  typedef typename boost::remove_reference<VCT>::type::ConstIterator VectorIterator;
139 
140  VCT x( vec_ ); // Evaluation of the left-hand side sparse vector operand
141  MCT A( mat_ ); // Evaluation of the right-hand side sparse matrix operand
142 
143  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size() , "Invalid vector size" );
144  BLAZE_INTERNAL_ASSERT( A.rows() == mat_.rows() , "Invalid number of rows" );
145  BLAZE_INTERNAL_ASSERT( A.columns() == mat_.columns(), "Invalid number of columns" );
146 
147  const VectorIterator vend( x.end() );
148  VectorIterator velem( x.begin() );
149  ElementType res;
150 
151  if( velem != vend ) {
152  res = velem->value() * A(velem->index(),index);
153  ++velem;
154  for( ; velem!=vend; ++velem ) {
155  res += velem->value() * A(velem->index(),index);
156  }
157  }
158  else {
159  reset( res );
160  }
161 
162  return res;
163  }
164  //**********************************************************************************************
165 
166  //**Size function*******************************************************************************
171  inline size_t size() const {
172  return mat_.columns();
173  }
174  //**********************************************************************************************
175 
176  //**NonZeros function***************************************************************************
181  inline size_t nonZeros() const {
182  return mat_.columns();
183  }
184  //**********************************************************************************************
185 
186  //**Left operand access*************************************************************************
191  inline LeftOperand leftOperand() const {
192  return vec_;
193  }
194  //**********************************************************************************************
195 
196  //**Right operand access************************************************************************
201  inline RightOperand rightOperand() const {
202  return mat_;
203  }
204  //**********************************************************************************************
205 
206  //**********************************************************************************************
212  template< typename T >
213  inline bool isAliased( const T* alias ) const {
214  return ( !IsComputation<VT>::value && vec_.isAliased( alias ) ) ||
216  CanAlias<MT>::value && mat_.isAliased( alias ) );
217  }
218  //**********************************************************************************************
219 
220  private:
221  //**Member variables****************************************************************************
224  //**********************************************************************************************
225 
226  //**Default assignment to dense vectors*********************************************************
240  template< typename VT1 > // Type of the target dense vector
241  friend inline typename EnableIf< IsResizable<typename VT1::ElementType> >::Type
243  {
244  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
245 
246  typedef typename boost::remove_reference<LT>::type::ConstIterator VectorIterator;
247  typedef typename boost::remove_reference<RT>::type::ConstIterator MatrixIterator;
248 
249  // Evaluation of the left-hand side sparse vector operand
250  LT x( rhs.vec_ );
251  if( x.nonZeros() == 0UL ) {
252  reset( ~lhs );
253  return;
254  }
255 
256  // Evaluation of the right-hand side sparse matrix operand
257  RT A( rhs.mat_ );
258 
259  // Checking the evaluated operands
260  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
261  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
262  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
263  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
264 
265  // Performing the sparse vector-sparse matrix multiplication
266  const VectorIterator vend( x.end() );
267 
268  for( size_t i=0UL; i<(~lhs).size(); ++i )
269  {
270  VectorIterator velem( x.begin() );
271 
272  (~lhs)[i] = velem->value() * A(velem->index(),i);
273  ++velem;
274  for( ; velem!=vend; ++velem ) {
275  (~lhs)[i] += velem->value() * A(velem->index(),i);
276  }
277  }
278  }
280  //**********************************************************************************************
281 
282  //**Optimized assignment to dense vectors*******************************************************
296  template< typename VT1 > // Type of the target dense vector
297  friend inline typename DisableIf< IsResizable<typename VT1::ElementType> >::Type
299  {
300  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
301 
302  typedef typename boost::remove_reference<LT>::type::ConstIterator VectorIterator;
303  typedef typename boost::remove_reference<RT>::type::ConstIterator MatrixIterator;
304 
305  // Resetting the left-hand side target dense vector
306  reset( ~lhs );
307 
308  // Evaluation of the left-hand side sparse vector operand
309  LT x( rhs.vec_ );
310  if( x.nonZeros() == 0UL ) return;
311 
312  // Evaluation of the right-hand side sparse matrix operand
313  RT A( rhs.mat_ );
314 
315  // Checking the evaluated operands
316  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
317  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
318  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
319  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
320 
321  // Performing the sparse vector-sparse matrix multiplication
322  const VectorIterator vend( x.end() );
323  VectorIterator velem( x.begin() );
324 
325  for( ; velem!=vend; ++velem )
326  {
327  const MatrixIterator mend( A.end( velem->index() ) );
328  MatrixIterator melem( A.begin( velem->index() ) );
329 
330  for( ; melem!=mend; ++melem ) {
331  (~lhs)[melem->index()] += velem->value() * melem->value();
332  }
333  }
334  }
336  //**********************************************************************************************
337 
338  //**Assignment to sparse vectors****************************************************************
350  template< typename VT1 > // Type of the target sparse vector
351  friend inline void assign( SparseVector<VT1,true>& lhs, const TSVecSMatMultExpr& rhs )
352  {
353  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
354 
355  typedef typename boost::remove_reference<LT>::type::ConstIterator VectorIterator;
356  typedef typename boost::remove_reference<RT>::type::ConstIterator MatrixIterator;
357 
358  // Evaluation of the left-hand side sparse vector operand
359  LT x( rhs.vec_ );
360  if( x.nonZeros() == 0UL ) return;
361 
362  // Evaluation of the right-hand side sparse matrix operand
363  RT A( rhs.mat_ );
364 
365  // Checking the evaluated operands
366  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
367  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
368  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
369  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
370 
371  // Performing the sparse vector-sparse matrix multiplication
372  const VectorIterator vend( x.end() );
373  VectorIterator velem( x.begin() );
374 
375  for( ; velem!=vend; ++velem )
376  {
377  const MatrixIterator mend( A.end( velem->index() ) );
378  MatrixIterator melem( A.begin( velem->index() ) );
379 
380  for( ; melem!=mend; ++melem )
381  {
382  typename VT1::Iterator pos( (~lhs).find( melem->index() ) );
383  if( pos != (~lhs).end() )
384  pos->value() += velem->value() * melem->value();
385  else
386  (~lhs).insert( melem->index(), velem->value() * melem->value() );
387  }
388  }
389  }
391  //**********************************************************************************************
392 
393  //**Addition assignment to dense vectors********************************************************
406  template< typename VT1 > // Type of the target dense vector
407  friend inline void addAssign( DenseVector<VT1,true>& lhs, const TSVecSMatMultExpr& rhs )
408  {
409  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
410 
411  typedef typename boost::remove_reference<LT>::type::ConstIterator VectorIterator;
412  typedef typename boost::remove_reference<RT>::type::ConstIterator MatrixIterator;
413 
414  // Evaluation of the left-hand side sparse vector operand
415  LT x( rhs.vec_ );
416  if( x.nonZeros() == 0UL ) return;
417 
418  // Evaluation of the right-hand side sparse matrix operand
419  RT A( rhs.mat_ );
420 
421  // Checking the evaluated operands
422  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
423  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
424  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
425  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
426 
427  // Performing the sparse vector-sparse matrix multiplication
428  const VectorIterator vend( x.end() );
429  VectorIterator velem( x.begin() );
430 
431  for( ; velem!=vend; ++velem )
432  {
433  const MatrixIterator mend( A.end( velem->index() ) );
434  MatrixIterator melem( A.begin( velem->index() ) );
435 
436  for( ; melem!=mend; ++melem ) {
437  (~lhs)[melem->index()] += velem->value() * melem->value();
438  }
439  }
440  }
442  //**********************************************************************************************
443 
444  //**Addition assignment to sparse vectors*******************************************************
445  // No special implementation for the addition assignment to sparse vectors.
446  //**********************************************************************************************
447 
448  //**Subtraction assignment to dense vectors*****************************************************
461  template< typename VT1 > // Type of the target dense vector
462  friend inline void subAssign( DenseVector<VT1,true>& lhs, const TSVecSMatMultExpr& rhs )
463  {
464  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
465 
466  typedef typename boost::remove_reference<LT>::type::ConstIterator VectorIterator;
467  typedef typename boost::remove_reference<RT>::type::ConstIterator MatrixIterator;
468 
469  // Evaluation of the left-hand side sparse vector operand
470  LT x( rhs.vec_ );
471  if( x.nonZeros() == 0UL ) return;
472 
473  // Evaluation of the right-hand side sparse matrix operand
474  RT A( rhs.mat_ );
475 
476  // Checking the evaluated operands
477  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
478  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
479  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
480  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
481 
482  // Performing the sparse vector-sparse matrix multiplication
483  const VectorIterator vend( x.end() );
484  VectorIterator velem( x.begin() );
485 
486  for( ; velem!=vend; ++velem )
487  {
488  const MatrixIterator mend( A.end( velem->index() ) );
489  MatrixIterator melem( A.begin( velem->index() ) );
490 
491  for( ; melem!=mend; ++melem ) {
492  (~lhs)[melem->index()] -= velem->value() * melem->value();
493  }
494  }
495  }
497  //**********************************************************************************************
498 
499  //**Subtraction assignment to sparse vectors****************************************************
500  // No special implementation for the subtraction assignment to sparse vectors.
501  //**********************************************************************************************
502 
503  //**Multiplication assignment to dense vectors**************************************************
516  template< typename VT1 > // Type of the target dense vector
517  friend inline void multAssign( DenseVector<VT1,true>& lhs, const TSVecSMatMultExpr& rhs )
518  {
521  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
522 
523  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
524 
525  const ResultType tmp( rhs );
526  multAssign( ~lhs, tmp );
527  }
529  //**********************************************************************************************
530 
531  //**Multiplication assignment to sparse vectors*************************************************
532  // No special implementation for the multiplication assignment to sparse vectors.
533  //**********************************************************************************************
534 
535  //**Compile time checks*************************************************************************
542  //**********************************************************************************************
543 };
544 //*************************************************************************************************
545 
546 
547 
548 
549 //=================================================================================================
550 //
551 // GLOBAL BINARY ARITHMETIC OPERATORS
552 //
553 //=================================================================================================
554 
555 //*************************************************************************************************
586 template< typename T1 // Type of the left-hand side sparse vector
587  , typename T2 > // Type of the right-hand side sparse matrix
588 inline const typename DisableIf< IsMatMatMultExpr<T2>, TSVecSMatMultExpr<T1,T2> >::Type
590 {
591  if( (~vec).size() != (~mat).rows() )
592  throw std::invalid_argument( "Vector and matrix sizes do not match" );
593 
594  return TSVecSMatMultExpr<T1,T2>( ~vec, ~mat );
595 }
596 //*************************************************************************************************
597 
598 
599 
600 
601 //=================================================================================================
602 //
603 // GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
604 //
605 //=================================================================================================
606 
607 //*************************************************************************************************
620 template< typename T1 // Type of the left-hand side sparse vector
621  , typename T2 // Type of the right-hand side sparse matrix
622  , bool SO > // Storage order of the right-hand side sparse matrix
623 inline const typename EnableIf< IsMatMatMultExpr<T2>, MultExprTrait<T1,T2> >::Type::Type
625 {
626  return ( vec * (~mat).leftOperand() ) * (~mat).rightOperand();
627 }
628 //*************************************************************************************************
629 
630 } // namespace blaze
631 
632 #endif