All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TSVecDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TSVECDMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TSVECDMATMULTEXPR_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>
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 TSVECDMATMULTEXPR
63 //
64 //=================================================================================================
65 
66 //*************************************************************************************************
73 template< typename VT // Type of the left-hand side sparse vector
74  , typename MT > // Type of the right-hand side dense matrix
75 class TSVecDMatMultExpr : public DenseVector< TSVecDMatMultExpr<VT,MT>, true >
76  , private Expression
77  , private Computation
78 {
79  private:
80  //**Type definitions****************************************************************************
81  typedef typename VT::ResultType VRT;
82  typedef typename MT::ResultType MRT;
83  typedef typename VT::CompositeType VCT;
84  typedef typename MT::CompositeType MCT;
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  typedef const ResultType CompositeType;
95 
97  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type LeftOperand;
98 
100  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type RightOperand;
101 
103  typedef typename SelectType< IsComputation<VT>::value, const VRT, VCT >::Type LT;
104 
106  typedef MCT RT;
107  //**********************************************************************************************
108 
109  //**Compilation flags***************************************************************************
111  enum { vectorizable = 0 };
112  //**********************************************************************************************
113 
114  //**Constructor*********************************************************************************
120  explicit inline TSVecDMatMultExpr( const VT& vec, const MT& mat )
121  : vec_( vec ) // Left-hand side sparse vector of the multiplication expression
122  , mat_( mat ) // Right-hand side dense matrix of the multiplication expression
123  {
124  BLAZE_INTERNAL_ASSERT( vec_.size() == mat_.rows(), "Invalid vector and matrix sizes" );
125  }
126  //**********************************************************************************************
127 
128  //**Subscript operator**************************************************************************
134  inline ReturnType operator[]( size_t index ) const {
135  BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
136 
137  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
138 
139  LT x( vec_ ); // Evaluation of the left-hand side sparse vector operand
140 
141  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size(), "Invalid vector size" );
142 
143  const ConstIterator end( x.end() );
144  ConstIterator element( x.begin() );
145  ElementType res;
146 
147  if( element != end ) {
148  res = element->value() * mat_( element->index(), index );
149  ++element;
150  for( ; element!=end; ++element )
151  res += element->value() * mat_( element->index(), index );
152  }
153  else {
154  reset( res );
155  }
156 
157  return res;
158  }
159  //**********************************************************************************************
160 
161  //**Size function*******************************************************************************
166  inline size_t size() const {
167  return mat_.columns();
168  }
169  //**********************************************************************************************
170 
171  //**Left operand access*************************************************************************
176  inline LeftOperand leftOperand() const {
177  return vec_;
178  }
179  //**********************************************************************************************
180 
181  //**Right operand access************************************************************************
186  inline RightOperand rightOperand() const {
187  return mat_;
188  }
189  //**********************************************************************************************
190 
191  //**********************************************************************************************
197  template< typename T >
198  inline bool canAlias( const T* alias ) const {
199  return vec_.isAliased( alias ) || mat_.isAliased( alias );
200  }
201  //**********************************************************************************************
202 
203  //**********************************************************************************************
209  template< typename T >
210  inline bool isAliased( const T* alias ) const {
211  return vec_.isAliased( alias ) || mat_.isAliased( alias );
212  }
213  //**********************************************************************************************
214 
215  private:
216  //**Member variables****************************************************************************
219  //**********************************************************************************************
220 
221  //**Default assignment to dense vectors*********************************************************
235  template< typename VT2 > // Type of the target dense vector
236  friend inline typename EnableIf< IsResizable<typename VT2::ElementType> >::Type
238  {
240 
241  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
242 
243  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
244 
245  // Evaluation of the left-hand side sparse vector operand
246  LT x( rhs.vec_ );
247  if( x.nonZeros() == 0UL ) {
248  reset( ~lhs );
249  return;
250  }
251 
252  // Evaluation of the right-hand side dense matrix operand
253  RT A( rhs.mat_ );
254 
255  // Checking the evaluated operands
256  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
257  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
258  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
259  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
260 
261  // Performing the sparse vector-dense matrix multiplication
262  const ConstIterator end( x.end() );
263 
264  for( size_t i=0UL; i<(~lhs).size(); ++i )
265  {
266  ConstIterator element( x.begin() );
267 
268  (~lhs)[i] = element->value() * A(element->index(),i);
269  ++element;
270  for( ; element!=end; ++element ) {
271  (~lhs)[i] += element->value() * A(element->index(),i);
272  }
273  }
274  }
276  //**********************************************************************************************
277 
278  //**Optimized assignment to dense vectors*******************************************************
292  template< typename VT2 > // Type of the target dense vector
293  friend inline typename DisableIf< IsResizable<typename VT2::ElementType> >::Type
295  {
297 
298  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
299 
300  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
301 
302  // Resetting the left-hand side target dense vector
303  reset( ~lhs );
304 
305  // Evaluation of the left-hand side sparse vector operand
306  LT x( rhs.vec_ );
307  if( x.nonZeros() == 0UL ) return;
308 
309  // Evaluation of the right-hand side dense matrix operand
310  RT A( rhs.mat_ );
311 
312  // Checking the evaluated operands
313  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
314  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
315  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
316  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
317 
318  // Performing the sparse vector-dense matrix multiplication
319  const ConstIterator end( x.end() );
320  ConstIterator element( x.begin() );
321 
322  for( ; element!=end; ++element ) {
323  for( size_t i=0UL; i<A.columns(); ++i ) {
324  (~lhs)[i] += element->value() * A(element->index(),i);
325  }
326  }
327  }
329  //**********************************************************************************************
330 
331  //**Assignment to sparse vectors****************************************************************
343  template< typename VT2 > // Type of the target sparse vector
344  friend inline void assign( SparseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
345  {
347 
350  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
351 
352  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
353 
354  const ResultType tmp( rhs );
355  assign( ~lhs, tmp );
356  }
358  //**********************************************************************************************
359 
360  //**Addition assignment to dense vectors********************************************************
371  template< typename VT2 > // Type of the target dense vector
372  friend inline void addAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
373  {
375 
376  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
377 
378  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
379 
380  // Evaluation of the left-hand side sparse vector operand
381  LT x( rhs.vec_ );
382  if( x.nonZeros() == 0UL ) return;
383 
384  // Evaluation of the right-hand side dense matrix operand
385  RT A( rhs.mat_ );
386 
387  // Checking the evaluated operands
388  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
389  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
390  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
391  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
392 
393  // Performing the sparse vector-dense matrix multiplication
394  const ConstIterator end( x.end() );
395  ConstIterator element( x.begin() );
396 
397  for( ; element!=end; ++element ) {
398  for( size_t i=0UL; i<A.columns(); ++i ) {
399  (~lhs)[i] += element->value() * A(element->index(),i);
400  }
401  }
402  }
403  //**********************************************************************************************
404 
405  //**Addition assignment to sparse vectors*******************************************************
406  // No special implementation for the addition assignment to sparse vectors.
407  //**********************************************************************************************
408 
409  //**Subtraction assignment to dense vectors*****************************************************
420  template< typename VT2 > // Type of the target dense vector
421  friend inline void subAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
422  {
424 
425  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
426 
427  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
428 
429  // Evaluation of the left-hand side sparse vector operand
430  LT x( rhs.vec_ );
431  if( x.nonZeros() == 0UL ) return;
432 
433  // Evaluation of the right-hand side dense matrix operand
434  RT A( rhs.mat_ );
435 
436  // Checking the evaluated operands
437  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
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( A.columns() == (~lhs).size() , "Invalid vector size" );
441 
442  // Performing the sparse vector-dense matrix multiplication
443  const ConstIterator end( x.end() );
444  ConstIterator element( x.begin() );
445 
446  for( ; element!=end; ++element ) {
447  for( size_t i=0UL; i<A.columns(); ++i ) {
448  (~lhs)[i] -= element->value() * A(element->index(),i);
449  }
450  }
451  }
452  //**********************************************************************************************
453 
454  //**Subtraction assignment to sparse vectors****************************************************
455  // No special implementation for the subtraction assignment to sparse vectors.
456  //**********************************************************************************************
457 
458  //**Multiplication assignment to dense vectors**************************************************
469  template< typename VT2 > // Type of the target dense vector
470  friend inline void multAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
471  {
473 
476  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
477 
478  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
479 
480  const ResultType tmp( rhs );
481  multAssign( ~lhs, tmp );
482  }
483  //**********************************************************************************************
484 
485  //**Multiplication assignment to sparse vectors*************************************************
486  // No special implementation for the multiplication assignment to sparse vectors.
487  //**********************************************************************************************
488 
489  //**Compile time checks*************************************************************************
496  //**********************************************************************************************
497 };
498 //*************************************************************************************************
499 
500 
501 
502 
503 //=================================================================================================
504 //
505 // GLOBAL BINARY ARITHMETIC OPERATORS
506 //
507 //=================================================================================================
508 
509 //*************************************************************************************************
540 template< typename T1, typename T2 >
541 inline const typename DisableIf< IsMatMatMultExpr<T2>, TSVecDMatMultExpr<T1,T2> >::Type
543 {
545 
546  if( (~vec).size() != (~mat).rows() )
547  throw std::invalid_argument( "Vector and matrix sizes do not match" );
548 
549  return TSVecDMatMultExpr<T1,T2>( ~vec, ~mat );
550 }
551 //*************************************************************************************************
552 
553 
554 
555 
556 //=================================================================================================
557 //
558 // GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
559 //
560 //=================================================================================================
561 
562 //*************************************************************************************************
575 template< typename T1 // Type of the left-hand side sparse vector
576  , typename T2 // Type of the right-hand side dense matrix
577  , bool SO > // Storage order of the right-hand side dense matrix
578 inline const typename EnableIf< IsMatMatMultExpr<T2>, MultExprTrait<T1,T2> >::Type::Type
580 {
582 
583  return ( vec * (~mat).leftOperand() ) * (~mat).rightOperand();
584 }
585 //*************************************************************************************************
586 
587 } // namespace blaze
588 
589 #endif