All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TSMatDVecMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TSMATDVECMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TSMATDVECMULTEXPR_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>
53 #include <blaze/util/SelectType.h>
54 #include <blaze/util/Types.h>
55 
56 
57 namespace blaze {
58 
59 //=================================================================================================
60 //
61 // CLASS TSMATDVECMULTEXPR
62 //
63 //=================================================================================================
64 
65 //*************************************************************************************************
72 template< typename MT // Type of the left-hand side sparse matrix
73  , typename VT > // Type of the right-hand side dense vector
74 class TSMatDVecMultExpr : public DenseVector< TSMatDVecMultExpr<MT,VT>, false >
75  , private Expression
76  , private Computation
77 {
78  private:
79  //**Type definitions****************************************************************************
80  typedef typename MT::ResultType MRT;
81  typedef typename VT::ResultType VRT;
82  typedef typename MT::CompositeType MCT;
83  typedef typename VT::CompositeType VCT;
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<MT>::value, const MT, const MT& >::Type LeftOperand;
97 
99  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type RightOperand;
100 
102  typedef MCT LT;
103 
105  typedef typename SelectType< IsComputation<VT>::value, const VRT, VCT >::Type RT;
106  //**********************************************************************************************
107 
108  //**Compilation flags***************************************************************************
110  enum { vectorizable = 0 };
111 
115  //**********************************************************************************************
116 
117  //**Constructor*********************************************************************************
123  explicit inline TSMatDVecMultExpr( const MT& mat, const VT& vec )
124  : mat_( mat ) // Left-hand side sparse matrix of the multiplication expression
125  , vec_( vec ) // Right-hand side dense vector of the multiplication expression
126  {
127  BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
128  }
129  //**********************************************************************************************
130 
131  //**Subscript operator**************************************************************************
137  inline ReturnType operator[]( size_t index ) const {
138  BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
139 
140  ElementType res;
141 
142  if( vec_.size() > 0UL ) {
143  res = mat_(index,0UL) * vec_[0UL];
144  for( size_t j=1UL; j<vec_.size(); ++j )
145  res += mat_(index,j) * vec_[j];
146  }
147  else {
148  reset( res );
149  }
150 
151  return res;
152  }
153  //**********************************************************************************************
154 
155  //**Size function*******************************************************************************
160  inline size_t size() const {
161  return mat_.rows();
162  }
163  //**********************************************************************************************
164 
165  //**Left function*******************************************************************************
170  inline LeftOperand leftOperand() const {
171  return mat_;
172  }
173  //**********************************************************************************************
174 
175  //**Right function******************************************************************************
180  inline RightOperand rightOperand() const {
181  return vec_;
182  }
183  //**********************************************************************************************
184 
185  //**********************************************************************************************
191  template< typename T >
192  inline bool isAliased( const T* alias ) const {
194  CanAlias<MT>::value && mat_.isAliased( alias ) ) ||
195  ( !IsComputation<VT>::value && vec_.isAliased( alias ) );
196  }
197  //**********************************************************************************************
198 
199  private:
200  //**Member variables****************************************************************************
203  //**********************************************************************************************
204 
205  //**Default assignment to dense vectors*********************************************************
219  template< typename VT1 > // Type of the target dense vector
220  friend inline typename EnableIf< IsResizable<typename VT1::ElementType> >::Type
222  {
223  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
224 
225  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
226 
227  reset( ~lhs );
228 
229  if( rhs.mat_.columns() == 0UL ) return;
230 
231  LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
232  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
233 
234  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
235  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
236  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
237  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
238 
239  for( size_t j=0UL; j<A.columns(); ++j )
240  {
241  ConstIterator element( A.begin(j) );
242  const ConstIterator end( A.end(j) );
243 
244  for( ; element!=end; ++element ) {
245  if( isDefault( (~lhs)[element->index()] ) )
246  (~lhs)[element->index()] = element->value() * x[j];
247  else
248  (~lhs)[element->index()] += element->value() * x[j];
249  }
250  }
251  }
253  //**********************************************************************************************
254 
255  //**Optimized assignment to dense vectors*******************************************************
269  template< typename VT1 > // Type of the target dense vector
270  friend inline typename DisableIf< IsResizable<typename VT1::ElementType> >::Type
272  {
273  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
274 
275  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
276 
277  reset( ~lhs );
278 
279  if( rhs.mat_.columns() == 0UL ) return;
280 
281  LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
282  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
283 
284  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
285  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
286  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
287  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
288 
289  for( size_t j=0UL; j<A.columns(); ++j )
290  {
291  ConstIterator element( A.begin(j) );
292  const ConstIterator end( A.end(j) );
293 
294  for( ; element!=end; ++element ) {
295  (~lhs)[element->index()] += element->value() * x[j];
296  }
297  }
298  }
300  //**********************************************************************************************
301 
302  //**Assignment to sparse vectors****************************************************************
314  template< typename VT1 > // Type of the target sparse vector
315  friend inline void assign( SparseVector<VT1,false>& lhs, const TSMatDVecMultExpr& rhs )
316  {
319  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
320 
321  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
322 
323  const ResultType tmp( rhs );
324  assign( ~lhs, tmp );
325  }
327  //**********************************************************************************************
328 
329  //**Addition assignment to dense vectors********************************************************
344  template< typename VT1 > // Type of the target dense vector
345  friend inline void addAssign( DenseVector<VT1,false>& lhs, const TSMatDVecMultExpr& rhs )
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  if( rhs.mat_.columns() == 0UL ) return;
352 
353  LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
354  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
355 
356  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
357  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
358  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
359  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
360 
361  for( size_t j=0UL; j<A.columns(); ++j )
362  {
363  ConstIterator element( A.begin(j) );
364  const ConstIterator end( A.end(j) );
365 
366  for( ; element!=end; ++element ) {
367  (~lhs)[element->index()] += element->value() * x[j];
368  }
369  }
370  }
372  //**********************************************************************************************
373 
374  //**Addition assignment to sparse vectors*******************************************************
375  // No special implementation for the addition assignment to sparse vectors.
376  //**********************************************************************************************
377 
378  //**Subtraction assignment to dense vectors*****************************************************
393  template< typename VT1 > // Type of the target dense vector
394  friend inline void subAssign( DenseVector<VT1,false>& lhs, const TSMatDVecMultExpr& rhs )
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  if( rhs.mat_.columns() == 0UL ) return;
401 
402  LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
403  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
404 
405  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
406  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
407  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
408  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
409 
410  for( size_t j=0UL; j<A.columns(); ++j )
411  {
412  ConstIterator element( A.begin(j) );
413  const ConstIterator end( A.end(j) );
414 
415  for( ; element!=end; ++element ) {
416  (~lhs)[element->index()] -= element->value() * x[j];
417  }
418  }
419  }
421  //**********************************************************************************************
422 
423  //**Subtraction assignment to sparse vectors****************************************************
424  // No special implementation for the subtraction assignment to sparse vectors.
425  //**********************************************************************************************
426 
427  //**Multiplication assignment to dense vectors**************************************************
442  template< typename VT1 > // Type of the target dense vector
443  friend inline void multAssign( DenseVector<VT1,false>& lhs, const TSMatDVecMultExpr& rhs )
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  }
455  //**********************************************************************************************
456 
457  //**Multiplication assignment to sparse vectors*************************************************
458  // No special implementation for the multiplication assignment to sparse vectors.
459  //**********************************************************************************************
460 
461  //**Compile time checks*************************************************************************
468  //**********************************************************************************************
469 };
470 //*************************************************************************************************
471 
472 
473 
474 
475 //=================================================================================================
476 //
477 // GLOBAL BINARY ARITHMETIC OPERATORS
478 //
479 //=================================================================================================
480 
481 //*************************************************************************************************
512 template< typename T1 // Type of the left-hand side sparse matrix
513  , typename T2 > // Type of the right-hand side dense vector
514 inline const typename DisableIf< IsMatMatMultExpr<T1>, TSMatDVecMultExpr<T1,T2> >::Type
516 {
517  if( (~mat).columns() != (~vec).size() )
518  throw std::invalid_argument( "Matrix and vector sizes do not match" );
519 
520  return TSMatDVecMultExpr<T1,T2>( ~mat, ~vec );
521 }
522 //*************************************************************************************************
523 
524 } // namespace blaze
525 
526 #endif