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>
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>
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  //**********************************************************************************************
134 
135  //**Constructor*********************************************************************************
141  explicit inline TSVecTDMatMultExpr( const VT& vec, const MT& mat )
142  : vec_( vec ) // Left-hand side sparse vector of the multiplication expression
143  , mat_( mat ) // Right-hand side dense matrix of the multiplication expression
144  {
145  BLAZE_INTERNAL_ASSERT( vec_.size() == mat_.rows(), "Invalid vector and matrix sizes" );
146  }
147  //**********************************************************************************************
148 
149  //**Subscript operator**************************************************************************
155  inline ReturnType operator[]( size_t index ) const {
156  BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
157 
158  typedef typename boost::remove_reference<VCT>::type::ConstIterator ConstIterator;
159 
160  VCT x( vec_ ); // Evaluation of the left-hand side sparse vector operand
161 
162  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size(), "Invalid vector size" );
163 
164  const ConstIterator end( x.end() );
165  ConstIterator element( x.begin() );
166  ElementType res;
167 
168  if( element != end ) {
169  res = element->value() * mat_( element->index(), index );
170  ++element;
171  for( ; element!=end; ++element )
172  res += element->value() * mat_( element->index(), index );
173  }
174  else {
175  reset( res );
176  }
177 
178  return res;
179  }
180  //**********************************************************************************************
181 
182  //**Size function*******************************************************************************
187  inline size_t size() const {
188  return mat_.columns();
189  }
190  //**********************************************************************************************
191 
192  //**Left operand access*************************************************************************
197  inline LeftOperand leftOperand() const {
198  return vec_;
199  }
200  //**********************************************************************************************
201 
202  //**Right operand access************************************************************************
207  inline RightOperand rightOperand() const {
208  return mat_;
209  }
210  //**********************************************************************************************
211 
212  //**********************************************************************************************
218  template< typename T >
219  inline bool canAlias( const T* alias ) const {
220  return vec_.isAliased( alias ) || mat_.isAliased( alias );
221  }
222  //**********************************************************************************************
223 
224  //**********************************************************************************************
230  template< typename T >
231  inline bool isAliased( const T* alias ) const {
232  return vec_.isAliased( alias ) || mat_.isAliased( alias );
233  }
234  //**********************************************************************************************
235 
236  private:
237  //**Member variables****************************************************************************
238  LeftOperand vec_;
239  RightOperand mat_;
240  //**********************************************************************************************
241 
242  //**Assignment to dense vectors*****************************************************************
258  template< typename VT2 > // Type of the target dense vector
259  friend inline typename EnableIf< UseAssign<VT2> >::Type
261  {
263 
264  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
265 
266  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
267 
268  // Evaluation of the left-hand side sparse vector operand
269  LT x( rhs.vec_ );
270  if( x.nonZeros() == 0UL ) {
271  reset( ~lhs );
272  return;
273  }
274 
275  // Evaluation of the right-hand side dense matrix operand
276  RT A( rhs.mat_ );
277 
278  // Checking the evaluated operands
279  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
280  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
281  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
282  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
283 
284  // Performing the sparse vector-dense matrix multiplication
285  const ConstIterator end( x.end() );
286 
287  for( size_t i=0UL; i<(~lhs).size(); ++i )
288  {
289  ConstIterator element( x.begin() );
290 
291  (~lhs)[i] = element->value() * A(element->index(),i);
292  ++element;
293  for( ; element!=end; ++element ) {
294  (~lhs)[i] += element->value() * A(element->index(),i);
295  }
296  }
297  }
299  //**********************************************************************************************
300 
301  //**Assignment to sparse vectors****************************************************************
314  template< typename VT2 > // Type of the target sparse vector
315  friend inline void assign( SparseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
316  {
318 
321  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
322 
323  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
324 
325  const ResultType tmp( rhs );
326  assign( ~lhs, tmp );
327  }
329  //**********************************************************************************************
330 
331  //**Addition assignment to dense vectors********************************************************
342  template< typename VT2 > // Type of the target dense vector
343  friend inline void addAssign( DenseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
344  {
346 
347  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
348 
349  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
350 
351  // Evaluation of the left-hand side sparse vector operand
352  LT x( rhs.vec_ );
353  if( x.nonZeros() == 0UL ) return;
354 
355  // Evaluation of the right-hand side dense matrix operand
356  RT A( rhs.mat_ );
357 
358  // Checking the evaluated operands
359  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
360  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
361  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
362  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
363 
364  // Performing the sparse vector-dense matrix multiplication
365  const ConstIterator end( x.end() );
366  ConstIterator element( x.begin() );
367 
368  for( ; element!=end; ++element ) {
369  for( size_t i=0UL; i<A.columns(); ++i ) {
370  (~lhs)[i] += element->value() * A(element->index(),i);
371  }
372  }
373  }
374  //**********************************************************************************************
375 
376  //**Addition assignment to sparse vectors*******************************************************
377  // No special implementation for the addition assignment to sparse vectors.
378  //**********************************************************************************************
379 
380  //**Subtraction assignment to dense vectors*****************************************************
391  template< typename VT2 > // Type of the target dense vector
392  friend inline void subAssign( DenseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
393  {
395 
396  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
397 
398  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
399 
400  // Evaluation of the left-hand side sparse vector operand
401  LT x( rhs.vec_ );
402  if( x.nonZeros() == 0UL ) return;
403 
404  // Evaluation of the right-hand side dense matrix operand
405  RT A( rhs.mat_ );
406 
407  // Checking the evaluated operands
408  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
409  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
410  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
411  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
412 
413  // Performing the sparse vector-dense matrix multiplication
414  const ConstIterator end( x.end() );
415  ConstIterator element( x.begin() );
416 
417  for( ; element!=end; ++element ) {
418  for( size_t i=0UL; i<A.columns(); ++i ) {
419  (~lhs)[i] -= element->value() * A(element->index(),i);
420  }
421  }
422  }
423  //**********************************************************************************************
424 
425  //**Subtraction assignment to sparse vectors****************************************************
426  // No special implementation for the subtraction assignment to sparse vectors.
427  //**********************************************************************************************
428 
429  //**Multiplication assignment to dense vectors**************************************************
440  template< typename VT2 > // Type of the target dense vector
441  friend inline void multAssign( DenseVector<VT2,true>& lhs, const TSVecTDMatMultExpr& rhs )
442  {
444 
447  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
448 
449  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
450 
451  const ResultType tmp( rhs );
452  multAssign( ~lhs, tmp );
453  }
454  //**********************************************************************************************
455 
456  //**Multiplication assignment to sparse vectors*************************************************
457  // No special implementation for the multiplication assignment to sparse vectors.
458  //**********************************************************************************************
459 
460  //**Compile time checks*************************************************************************
467  //**********************************************************************************************
468 };
469 //*************************************************************************************************
470 
471 
472 
473 
474 //=================================================================================================
475 //
476 // GLOBAL BINARY ARITHMETIC OPERATORS
477 //
478 //=================================================================================================
479 
480 //*************************************************************************************************
511 template< typename T1, typename T2 >
512 inline const typename DisableIf< IsMatMatMultExpr<T2>, TSVecTDMatMultExpr<T1,T2> >::Type
514 {
516 
517  if( (~vec).size() != (~mat).rows() )
518  throw std::invalid_argument( "Vector and matrix sizes do not match" );
519 
520  return TSVecTDMatMultExpr<T1,T2>( ~vec, ~mat );
521 }
522 //*************************************************************************************************
523 
524 } // namespace blaze
525 
526 #endif