All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DMatSVecMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_DMATSVECMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_DMATSVECMULTEXPR_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 DMATSVECMULTEXPR
62 //
63 //=================================================================================================
64 
65 //*************************************************************************************************
72 template< typename MT // Type of the left-hand side dense matrix
73  , typename VT > // Type of the right-hand side sparse vector
74 class DMatSVecMultExpr : public DenseVector< DMatSVecMultExpr<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  //**********************************************************************************************
88 
95  //**********************************************************************************************
96 
97  //**********************************************************************************************
99 
100  template< typename VT2 >
101  struct UseAssign {
102  enum { value = useAssign };
103  };
105  //**********************************************************************************************
106 
107  public:
108  //**Type definitions****************************************************************************
111  typedef typename ResultType::TransposeType TransposeType;
112  typedef typename ResultType::ElementType ElementType;
113  typedef const ElementType ReturnType;
114 
117 
119  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type LeftOperand;
120 
122  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type RightOperand;
123 
125  typedef MCT LT;
126 
128  typedef typename SelectType< IsComputation<VT>::value, const VRT, VCT >::Type RT;
129  //**********************************************************************************************
130 
131  //**Compilation flags***************************************************************************
133  enum { vectorizable = 0 };
134 
137  //**********************************************************************************************
138 
139  //**Constructor*********************************************************************************
145  explicit inline DMatSVecMultExpr( const MT& mat, const VT& vec )
146  : mat_( mat ) // Left-hand side dense matrix of the multiplication expression
147  , vec_( vec ) // Right-hand side sparse vector of the multiplication expression
148  {
149  BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
150  }
151  //**********************************************************************************************
152 
153  //**Subscript operator**************************************************************************
159  inline ReturnType operator[]( size_t index ) const {
160  BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
161 
162  typedef typename boost::remove_reference<VCT>::type::ConstIterator ConstIterator;
163 
164  VCT x( vec_ ); // Evaluation of the right-hand side sparse vector operand
165 
166  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size(), "Invalid vector size" );
167 
168  ConstIterator element( x.begin() );
169  ElementType res;
170 
171  if( element != x.end() ) {
172  res = mat_( index, element->index() ) * element->value();
173  ++element;
174  for( ; element!=x.end(); ++element )
175  res += mat_( index, element->index() ) * element->value();
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_.rows();
192  }
193  //**********************************************************************************************
194 
195  //**Left function*******************************************************************************
200  inline LeftOperand leftOperand() const {
201  return mat_;
202  }
203  //**********************************************************************************************
204 
205  //**Right function******************************************************************************
210  inline RightOperand rightOperand() const {
211  return vec_;
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****************************************************************************
232  //**********************************************************************************************
233 
234  //**Assignment to dense vectors*****************************************************************
249  template< typename VT1 > // Type of the target dense vector
250  friend inline typename EnableIf< UseAssign<VT1> >::Type
252  {
253  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
254 
255  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
256 
257  // Evaluation of the right-hand side sparse vector operand
258  RT x( rhs.vec_ );
259  if( x.nonZeros() == 0UL ) {
260  reset( ~lhs );
261  return;
262  }
263 
264  // Evaluation of the left-hand side dense matrix operand
265  LT A( rhs.mat_ );
266 
267  // Checking the evaluated operands
268  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
269  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
270  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
271  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
272 
273  // Performing the dense matrix-sparse vector multiplication
274  const ConstIterator end( x.end() );
275 
276  for( size_t i=0UL; i<(~lhs).size(); ++i )
277  {
278  ConstIterator element( x.begin() );
279 
280  (~lhs)[i] = A( i, element->index() ) * element->value();
281  ++element;
282  for( ; element!=end; ++element )
283  (~lhs)[i] += A( i, element->index() ) * element->value();
284  }
285  }
287  //**********************************************************************************************
288 
289  //**Assignment to sparse vectors****************************************************************
304  template< typename VT1 > // Type of the target sparse vector
305  friend inline typename EnableIf< UseAssign<VT1> >::Type
307  {
310  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
311 
312  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
313 
314  const ResultType tmp( rhs );
315  assign( ~lhs, tmp );
316  }
318  //**********************************************************************************************
319 
320  //**Addition assignment to dense vectors********************************************************
335  template< typename VT1 > // Type of the target dense vector
336  friend inline typename EnableIf< UseAssign<VT1> >::Type
337  addAssign( DenseVector<VT1,false>& lhs, const DMatSVecMultExpr& rhs )
338  {
339  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
340 
341  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
342 
343  // Evaluation of the right-hand side sparse vector operand
344  RT x( rhs.vec_ );
345  if( x.nonZeros() == 0UL ) return;
346 
347  // Evaluation of the left-hand side dense matrix operand
348  LT A( rhs.mat_ );
349 
350  // Checking the evaluated operands
351  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
352  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
353  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
354  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
355 
356  // Performing the dense matrix-sparse vector multiplication
357  const ConstIterator end( x.end() );
358 
359  for( size_t i=0UL; i<(~lhs).size(); ++i )
360  {
361  ConstIterator element( x.begin() );
362 
363  for( ; element!=end; ++element ) {
364  (~lhs)[i] += A( i, element->index() ) * element->value();
365  }
366  }
367  }
369  //**********************************************************************************************
370 
371  //**Addition assignment to sparse vectors*******************************************************
372  // No special implementation for the addition assignment to sparse vectors.
373  //**********************************************************************************************
374 
375  //**Subtraction assignment to dense vectors*****************************************************
390  template< typename VT1 > // Type of the target dense vector
391  friend inline typename EnableIf< UseAssign<VT1> >::Type
392  subAssign( DenseVector<VT1,false>& lhs, const DMatSVecMultExpr& rhs )
393  {
394  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
395 
396  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
397 
398  // Evaluation of the right-hand side sparse vector operand
399  RT x( rhs.vec_ );
400  if( x.nonZeros() == 0UL ) return;
401 
402  // Evaluation of the left-hand side dense matrix operand
403  LT A( rhs.mat_ );
404 
405  // Checking the evaluated operands
406  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
407  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
408  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
409  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
410 
411  // Performing the dense matrix-sparse vector multiplication
412  const ConstIterator end( x.end() );
413 
414  for( size_t i=0UL; i<(~lhs).size(); ++i )
415  {
416  ConstIterator element( x.begin() );
417 
418  for( ; element!=end; ++element ) {
419  (~lhs)[i] -= A( i, element->index() ) * element->value();
420  }
421  }
422  }
424  //**********************************************************************************************
425 
426  //**Subtraction assignment to sparse vectors****************************************************
427  // No special implementation for the subtraction assignment to sparse vectors.
428  //**********************************************************************************************
429 
430  //**Multiplication assignment to dense vectors**************************************************
445  template< typename VT1 > // Type of the target dense vector
446  friend inline typename EnableIf< UseAssign<VT1> >::Type
447  multAssign( DenseVector<VT1,false>& lhs, const DMatSVecMultExpr& rhs )
448  {
451  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
452 
453  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
454 
455  const ResultType tmp( rhs );
456  multAssign( ~lhs, tmp );
457  }
459  //**********************************************************************************************
460 
461  //**Addition assignment to sparse vectors*******************************************************
462  // No special implementation for the multiplication assignment to sparse vectors.
463  //**********************************************************************************************
464 
465  //**Compile time checks*************************************************************************
472  //**********************************************************************************************
473 };
474 //*************************************************************************************************
475 
476 
477 
478 
479 //=================================================================================================
480 //
481 // GLOBAL BINARY ARITHMETIC OPERATORS
482 //
483 //=================================================================================================
484 
485 //*************************************************************************************************
517 template< typename T1 // Type of the left-hand side dense matrix
518  , typename T2 > // Type of the right-hand side sparse vector
519 inline const typename DisableIf< IsMatMatMultExpr<T1>, DMatSVecMultExpr<T1,T2> >::Type
521 {
522  if( (~mat).columns() != (~vec).size() )
523  throw std::invalid_argument( "Matrix and vector sizes do not match" );
524 
525  return DMatSVecMultExpr<T1,T2>( ~mat, ~vec );
526 }
527 //*************************************************************************************************
528 
529 
530 
531 
532 //=================================================================================================
533 //
534 // GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
535 //
536 //=================================================================================================
537 
538 //*************************************************************************************************
551 template< typename T1 // Type of the left-hand side dense matrix
552  , bool SO // Storage order of the left-hand side dense matrix
553  , typename T2 > // Type of the right-hand side sparse vector
554 inline const typename EnableIf< IsMatMatMultExpr<T1>, MultExprTrait<T1,T2> >::Type::Type
556 {
557  return (~mat).leftOperand() * ( (~mat).rightOperand() * vec );
558 }
559 //*************************************************************************************************
560 
561 } // namespace blaze
562 
563 #endif