All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TSVecTDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TSVECTDMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TSVECTDMATMULTEXPR_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>
48 #include <blaze/util/Assert.h>
50 #include <blaze/util/DisableIf.h>
51 #include <blaze/util/EnableIf.h>
52 #include <blaze/util/SelectType.h>
53 #include <blaze/util/Types.h>
54 
55 
56 namespace blaze {
57 
58 //=================================================================================================
59 //
60 // CLASS TSVECDMATMULTEXPR
61 //
62 //=================================================================================================
63 
64 //*************************************************************************************************
71 template< typename VT // Type of the left-hand side sparse vector
72  , typename MT > // Type of the right-hand side dense matrix
73 class TSVecTDMatMultExpr : public DenseVector< TSVecTDMatMultExpr<VT,MT>, true >
74  , private Expression
75  , private Computation
76 {
77  private:
78  //**Type definitions****************************************************************************
79  typedef typename VT::ResultType VRT;
80  typedef typename MT::ResultType MRT;
81  typedef typename VT::CompositeType VCT;
82  typedef typename MT::CompositeType MCT;
83  //**********************************************************************************************
84 
85  //**********************************************************************************************
87 
93  enum { useAssign = ( IsComputation<VT>::value || RequiresEvaluation<MT>::value ) };
94  //**********************************************************************************************
95 
96  //**********************************************************************************************
98 
99  template< typename VT2 >
100  struct UseAssign {
101  enum { value = useAssign };
102  };
104  //**********************************************************************************************
105 
106  public:
107  //**Type definitions****************************************************************************
110  typedef typename ResultType::TransposeType TransposeType;
111  typedef typename ResultType::ElementType ElementType;
112  typedef const ElementType ReturnType;
113 
116 
118  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type LeftOperand;
119 
121  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type RightOperand;
122 
124  typedef typename SelectType< IsComputation<VT>::value, const VRT, VCT >::Type LT;
125 
127  typedef MCT RT;
128  //**********************************************************************************************
129 
130  //**Compilation flags***************************************************************************
132  enum { vectorizable = 0 };
133 
136  //**********************************************************************************************
137 
138  //**Constructor*********************************************************************************
144  explicit inline TSVecTDMatMultExpr( const VT& vec, const MT& mat )
145  : vec_( vec ) // Left-hand side sparse vector of the multiplication expression
146  , mat_( mat ) // Right-hand side dense matrix of the multiplication expression
147  {
148  BLAZE_INTERNAL_ASSERT( vec_.size() == mat_.rows(), "Invalid vector and matrix sizes" );
149  }
150  //**********************************************************************************************
151 
152  //**Subscript operator**************************************************************************
158  inline ReturnType operator[]( size_t index ) const {
159  BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
160 
161  typedef typename boost::remove_reference<VCT>::type::ConstIterator ConstIterator;
162 
163  VCT x( vec_ ); // Evaluation of the left-hand side sparse vector operand
164 
165  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size(), "Invalid vector size" );
166 
167  const ConstIterator end( x.end() );
168  ConstIterator element( x.begin() );
169  ElementType res;
170 
171  if( element != end ) {
172  res = element->value() * mat_( element->index(), index );
173  ++element;
174  for( ; element!=end; ++element )
175  res += element->value() * mat_( element->index(), index );
176  }
177  else {
178  reset( res );
179  }
180 
181  return res;
182  }
183  //**********************************************************************************************
184 
185  //**Size function*******************************************************************************
190  inline size_t size() const {
191  return mat_.columns();
192  }
193  //**********************************************************************************************
194 
195  //**Left operand access*************************************************************************
200  inline LeftOperand leftOperand() const {
201  return vec_;
202  }
203  //**********************************************************************************************
204 
205  //**Right operand access************************************************************************
210  inline RightOperand rightOperand() const {
211  return mat_;
212  }
213  //**********************************************************************************************
214 
215  //**********************************************************************************************
221  template< typename T >
222  inline bool isAliased( const T* alias ) const {
224  CanAlias<MT>::value && mat_.isAliased( alias );
225  }
226  //**********************************************************************************************
227 
228  private:
229  //**Member variables****************************************************************************
230  LeftOperand vec_;
231  RightOperand mat_;
232  //**********************************************************************************************
233 
234  //**Assignment to dense vectors*****************************************************************
250  template< typename VT2 > // Type of the target dense vector
251  friend inline typename EnableIf< UseAssign<VT2> >::Type
253  {
254  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
255 
256  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
257 
258  // Evaluation of the left-hand side sparse vector operand
259  LT x( rhs.vec_ );
260  if( x.nonZeros() == 0UL ) {
261  reset( ~lhs );
262  return;
263  }
264 
265  // Evaluation of the right-hand side dense matrix operand
266  RT A( rhs.mat_ );
267 
268  // Checking the evaluated operands
269  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
270  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
271  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
272  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
273 
274  // Performing the sparse vector-dense matrix multiplication
275  const ConstIterator end( x.end() );
276 
277  for( size_t i=0UL; i<(~lhs).size(); ++i )
278  {
279  ConstIterator element( x.begin() );
280 
281  (~lhs)[i] = element->value() * A(element->index(),i);
282  ++element;
283  for( ; element!=end; ++element ) {
284  (~lhs)[i] += element->value() * A(element->index(),i);
285  }
286  }
287  }
289  //**********************************************************************************************
290 
291  //**Assignment to sparse vectors****************************************************************
304  template< typename VT2 > // Type of the target sparse vector
305  friend inline void assign( SparseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
306  {
309  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
310 
311  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
312 
313  const ResultType tmp( rhs );
314  assign( ~lhs, tmp );
315  }
317  //**********************************************************************************************
318 
319  //**Addition assignment to dense vectors********************************************************
330  template< typename VT2 > // Type of the target dense vector
331  friend inline void addAssign( DenseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
332  {
333  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
334 
335  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
336 
337  // Evaluation of the left-hand side sparse vector operand
338  LT x( rhs.vec_ );
339  if( x.nonZeros() == 0UL ) return;
340 
341  // Evaluation of the right-hand side dense matrix operand
342  RT A( rhs.mat_ );
343 
344  // Checking the evaluated operands
345  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
346  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
347  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
348  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
349 
350  // Performing the sparse vector-dense matrix multiplication
351  const ConstIterator end( x.end() );
352  ConstIterator element( x.begin() );
353 
354  for( ; element!=end; ++element ) {
355  for( size_t i=0UL; i<A.columns(); ++i ) {
356  (~lhs)[i] += element->value() * A(element->index(),i);
357  }
358  }
359  }
360  //**********************************************************************************************
361 
362  //**Addition assignment to sparse vectors*******************************************************
363  // No special implementation for the addition assignment to sparse vectors.
364  //**********************************************************************************************
365 
366  //**Subtraction assignment to dense vectors*****************************************************
377  template< typename VT2 > // Type of the target dense vector
378  friend inline void subAssign( DenseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
379  {
380  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
381 
382  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
383 
384  // Evaluation of the left-hand side sparse vector operand
385  LT x( rhs.vec_ );
386  if( x.nonZeros() == 0UL ) return;
387 
388  // Evaluation of the right-hand side dense matrix operand
389  RT A( rhs.mat_ );
390 
391  // Checking the evaluated operands
392  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
393  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
394  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
395  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
396 
397  // Performing the sparse vector-dense matrix multiplication
398  const ConstIterator end( x.end() );
399  ConstIterator element( x.begin() );
400 
401  for( ; element!=end; ++element ) {
402  for( size_t i=0UL; i<A.columns(); ++i ) {
403  (~lhs)[i] -= element->value() * A(element->index(),i);
404  }
405  }
406  }
407  //**********************************************************************************************
408 
409  //**Subtraction assignment to sparse vectors****************************************************
410  // No special implementation for the subtraction assignment to sparse vectors.
411  //**********************************************************************************************
412 
413  //**Multiplication assignment to dense vectors**************************************************
424  template< typename VT2 > // Type of the target dense vector
425  friend inline void multAssign( DenseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
426  {
429  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
430 
431  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
432 
433  const ResultType tmp( rhs );
434  multAssign( ~lhs, tmp );
435  }
436  //**********************************************************************************************
437 
438  //**Multiplication assignment to sparse vectors*************************************************
439  // No special implementation for the multiplication assignment to sparse vectors.
440  //**********************************************************************************************
441 
442  //**Compile time checks*************************************************************************
449  //**********************************************************************************************
450 };
451 //*************************************************************************************************
452 
453 
454 
455 
456 //=================================================================================================
457 //
458 // GLOBAL BINARY ARITHMETIC OPERATORS
459 //
460 //=================================================================================================
461 
462 //*************************************************************************************************
493 template< typename T1, typename T2 >
494 inline const typename DisableIf< IsMatMatMultExpr<T2>, TSVecTDMatMultExpr<T1,T2> >::Type
496 {
497  if( (~vec).size() != (~mat).rows() )
498  throw std::invalid_argument( "Vector and matrix sizes do not match" );
499 
500  return TSVecTDMatMultExpr<T1,T2>( ~vec, ~mat );
501 }
502 //*************************************************************************************************
503 
504 } // namespace blaze
505 
506 #endif