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>
48 #include <blaze/util/Assert.h>
50 #include <blaze/util/DisableIf.h>
51 #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  //**********************************************************************************************
112 
113  //**Constructor*********************************************************************************
119  explicit inline TSMatDVecMultExpr( const MT& mat, const VT& vec )
120  : mat_( mat ) // Left-hand side sparse matrix of the multiplication expression
121  , vec_( vec ) // Right-hand side dense vector of the multiplication expression
122  {
123  BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
124  }
125  //**********************************************************************************************
126 
127  //**Subscript operator**************************************************************************
133  inline ReturnType operator[]( size_t index ) const {
134  BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
135 
136  ElementType res;
137 
138  if( vec_.size() > 0UL ) {
139  res = mat_(index,0UL) * vec_[0UL];
140  for( size_t j=1UL; j<vec_.size(); ++j )
141  res += mat_(index,j) * vec_[j];
142  }
143  else {
144  reset( res );
145  }
146 
147  return res;
148  }
149  //**********************************************************************************************
150 
151  //**Size function*******************************************************************************
156  inline size_t size() const {
157  return mat_.rows();
158  }
159  //**********************************************************************************************
160 
161  //**Left function*******************************************************************************
166  inline LeftOperand leftOperand() const {
167  return mat_;
168  }
169  //**********************************************************************************************
170 
171  //**Right function******************************************************************************
176  inline RightOperand rightOperand() const {
177  return vec_;
178  }
179  //**********************************************************************************************
180 
181  //**********************************************************************************************
187  template< typename T >
188  inline bool canAlias( const T* alias ) const {
189  return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
190  }
191  //**********************************************************************************************
192 
193  //**********************************************************************************************
199  template< typename T >
200  inline bool isAliased( const T* alias ) const {
201  return ( mat_.isAliased( alias ) || vec_.isAliased( alias ) );
202  }
203  //**********************************************************************************************
204 
205  private:
206  //**Member variables****************************************************************************
209  //**********************************************************************************************
210 
211  //**Default assignment to dense vectors*********************************************************
225  template< typename VT1 > // Type of the target dense vector
226  friend inline typename EnableIf< IsResizable<typename VT1::ElementType> >::Type
228  {
230 
231  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
232 
233  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
234 
235  reset( ~lhs );
236 
237  if( rhs.mat_.columns() == 0UL ) return;
238 
239  LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
240  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
241 
242  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
243  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
244  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
245  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
246 
247  for( size_t j=0UL; j<A.columns(); ++j )
248  {
249  ConstIterator element( A.begin(j) );
250  const ConstIterator end( A.end(j) );
251 
252  for( ; element!=end; ++element ) {
253  if( isDefault( (~lhs)[element->index()] ) )
254  (~lhs)[element->index()] = element->value() * x[j];
255  else
256  (~lhs)[element->index()] += element->value() * x[j];
257  }
258  }
259  }
261  //**********************************************************************************************
262 
263  //**Optimized assignment to dense vectors*******************************************************
277  template< typename VT1 > // Type of the target dense vector
278  friend inline typename DisableIf< IsResizable<typename VT1::ElementType> >::Type
280  {
282 
283  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
284 
285  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
286 
287  reset( ~lhs );
288 
289  if( rhs.mat_.columns() == 0UL ) return;
290 
291  LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
292  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
293 
294  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
295  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
296  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
297  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
298 
299  for( size_t j=0UL; j<A.columns(); ++j )
300  {
301  ConstIterator element( A.begin(j) );
302  const ConstIterator end( A.end(j) );
303 
304  for( ; element!=end; ++element ) {
305  (~lhs)[element->index()] += element->value() * x[j];
306  }
307  }
308  }
310  //**********************************************************************************************
311 
312  //**Assignment to sparse vectors****************************************************************
324  template< typename VT1 > // Type of the target sparse vector
325  friend inline void assign( SparseVector<VT1,false>& lhs, const TSMatDVecMultExpr& rhs )
326  {
328 
331  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
332 
333  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
334 
335  const ResultType tmp( rhs );
336  assign( ~lhs, tmp );
337  }
339  //**********************************************************************************************
340 
341  //**Addition assignment to dense vectors********************************************************
356  template< typename VT1 > // Type of the target dense vector
357  friend inline void addAssign( DenseVector<VT1,false>& lhs, const TSMatDVecMultExpr& rhs )
358  {
360 
361  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
362 
363  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
364 
365  if( rhs.mat_.columns() == 0UL ) return;
366 
367  LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
368  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
369 
370  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
371  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
372  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
373  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
374 
375  for( size_t j=0UL; j<A.columns(); ++j )
376  {
377  ConstIterator element( A.begin(j) );
378  const ConstIterator end( A.end(j) );
379 
380  for( ; element!=end; ++element ) {
381  (~lhs)[element->index()] += element->value() * x[j];
382  }
383  }
384  }
386  //**********************************************************************************************
387 
388  //**Addition assignment to sparse vectors*******************************************************
389  // No special implementation for the addition assignment to sparse vectors.
390  //**********************************************************************************************
391 
392  //**Subtraction assignment to dense vectors*****************************************************
407  template< typename VT1 > // Type of the target dense vector
408  friend inline void subAssign( DenseVector<VT1,false>& lhs, const TSMatDVecMultExpr& rhs )
409  {
411 
412  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
413 
414  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
415 
416  if( rhs.mat_.columns() == 0UL ) return;
417 
418  LT A( rhs.mat_ ); // Evaluation of the left-hand side sparse matrix operand
419  RT x( rhs.vec_ ); // Evaluation of the right-hand side dense vector operand
420 
421  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
422  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
423  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
424  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
425 
426  for( size_t j=0UL; j<A.columns(); ++j )
427  {
428  ConstIterator element( A.begin(j) );
429  const ConstIterator end( A.end(j) );
430 
431  for( ; element!=end; ++element ) {
432  (~lhs)[element->index()] -= element->value() * x[j];
433  }
434  }
435  }
437  //**********************************************************************************************
438 
439  //**Subtraction assignment to sparse vectors****************************************************
440  // No special implementation for the subtraction assignment to sparse vectors.
441  //**********************************************************************************************
442 
443  //**Multiplication assignment to dense vectors**************************************************
458  template< typename VT1 > // Type of the target dense vector
459  friend inline void multAssign( DenseVector<VT1,false>& lhs, const TSMatDVecMultExpr& rhs )
460  {
462 
465  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
466 
467  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
468 
469  const ResultType tmp( rhs );
470  multAssign( ~lhs, tmp );
471  }
473  //**********************************************************************************************
474 
475  //**Multiplication assignment to sparse vectors*************************************************
476  // No special implementation for the multiplication assignment to sparse vectors.
477  //**********************************************************************************************
478 
479  //**Compile time checks*************************************************************************
486  //**********************************************************************************************
487 };
488 //*************************************************************************************************
489 
490 
491 
492 
493 //=================================================================================================
494 //
495 // GLOBAL BINARY ARITHMETIC OPERATORS
496 //
497 //=================================================================================================
498 
499 //*************************************************************************************************
530 template< typename T1 // Type of the left-hand side sparse matrix
531  , typename T2 > // Type of the right-hand side dense vector
532 inline const typename DisableIf< IsMatMatMultExpr<T1>, TSMatDVecMultExpr<T1,T2> >::Type
534 {
536 
537  if( (~mat).columns() != (~vec).size() )
538  throw std::invalid_argument( "Matrix and vector sizes do not match" );
539 
540  return TSMatDVecMultExpr<T1,T2>( ~mat, ~vec );
541 }
542 //*************************************************************************************************
543 
544 } // namespace blaze
545 
546 #endif