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>
40 #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>
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 MatVecMultExpr
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  //**********************************************************************************************
135 
136  //**Constructor*********************************************************************************
142  explicit inline DMatSVecMultExpr( const MT& mat, const VT& vec )
143  : mat_( mat ) // Left-hand side dense matrix of the multiplication expression
144  , vec_( vec ) // Right-hand side sparse vector of the multiplication expression
145  {
146  BLAZE_INTERNAL_ASSERT( mat_.columns() == vec_.size(), "Invalid matrix and vector sizes" );
147  }
148  //**********************************************************************************************
149 
150  //**Subscript operator**************************************************************************
156  inline ReturnType operator[]( size_t index ) const {
157  BLAZE_INTERNAL_ASSERT( index < mat_.rows(), "Invalid vector access index" );
158 
159  typedef typename RemoveReference<VCT>::Type::ConstIterator ConstIterator;
160 
161  VCT x( vec_ ); // Evaluation of the right-hand side sparse vector operand
162 
163  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size(), "Invalid vector size" );
164 
165  ConstIterator element( x.begin() );
166  ElementType res;
167 
168  if( element != x.end() ) {
169  res = mat_( index, element->index() ) * element->value();
170  ++element;
171  for( ; element!=x.end(); ++element )
172  res += mat_( index, element->index() ) * element->value();
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_.rows();
189  }
190  //**********************************************************************************************
191 
192  //**Left function*******************************************************************************
197  inline LeftOperand leftOperand() const {
198  return mat_;
199  }
200  //**********************************************************************************************
201 
202  //**Right function******************************************************************************
207  inline RightOperand rightOperand() const {
208  return vec_;
209  }
210  //**********************************************************************************************
211 
212  //**********************************************************************************************
218  template< typename T >
219  inline bool canAlias( const T* alias ) const {
220  return mat_.isAliased( alias ) || vec_.isAliased( alias );
221  }
222  //**********************************************************************************************
223 
224  //**********************************************************************************************
230  template< typename T >
231  inline bool isAliased( const T* alias ) const {
232  return mat_.isAliased( alias ) || vec_.isAliased( alias );
233  }
234  //**********************************************************************************************
235 
236  private:
237  //**Member variables****************************************************************************
240  //**********************************************************************************************
241 
242  //**Assignment to dense vectors*****************************************************************
257  template< typename VT1 > // Type of the target dense vector
258  friend inline typename EnableIf< UseAssign<VT1> >::Type
260  {
262 
263  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
264 
265  typedef typename RemoveReference<RT>::Type::ConstIterator ConstIterator;
266 
267  // Evaluation of the right-hand side sparse vector operand
268  RT x( rhs.vec_ );
269  if( x.nonZeros() == 0UL ) {
270  reset( ~lhs );
271  return;
272  }
273 
274  // Evaluation of the left-hand side dense matrix operand
275  LT A( rhs.mat_ );
276 
277  // Checking the evaluated operands
278  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
279  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
280  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
281  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
282 
283  // Performing the dense matrix-sparse vector multiplication
284  const ConstIterator end( x.end() );
285 
286  for( size_t i=0UL; i<(~lhs).size(); ++i )
287  {
288  ConstIterator element( x.begin() );
289 
290  (~lhs)[i] = A( i, element->index() ) * element->value();
291  ++element;
292  for( ; element!=end; ++element )
293  (~lhs)[i] += A( i, element->index() ) * element->value();
294  }
295  }
297  //**********************************************************************************************
298 
299  //**Assignment to sparse vectors****************************************************************
314  template< typename VT1 > // Type of the target sparse vector
315  friend inline typename EnableIf< UseAssign<VT1> >::Type
317  {
319 
322  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
323 
324  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
325 
326  const ResultType tmp( rhs );
327  assign( ~lhs, tmp );
328  }
330  //**********************************************************************************************
331 
332  //**Addition assignment to dense vectors********************************************************
347  template< typename VT1 > // Type of the target dense vector
348  friend inline typename EnableIf< UseAssign<VT1> >::Type
349  addAssign( DenseVector<VT1,false>& lhs, const DMatSVecMultExpr& rhs )
350  {
352 
353  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
354 
355  typedef typename RemoveReference<RT>::Type::ConstIterator ConstIterator;
356 
357  // Evaluation of the right-hand side sparse vector operand
358  RT x( rhs.vec_ );
359  if( x.nonZeros() == 0UL ) return;
360 
361  // Evaluation of the left-hand side dense matrix operand
362  LT A( rhs.mat_ );
363 
364  // Checking the evaluated operands
365  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
366  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
367  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
368  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
369 
370  // Performing the dense matrix-sparse vector multiplication
371  const ConstIterator end( x.end() );
372 
373  for( size_t i=0UL; i<(~lhs).size(); ++i )
374  {
375  ConstIterator element( x.begin() );
376 
377  for( ; element!=end; ++element ) {
378  (~lhs)[i] += A( i, element->index() ) * element->value();
379  }
380  }
381  }
383  //**********************************************************************************************
384 
385  //**Addition assignment to sparse vectors*******************************************************
386  // No special implementation for the addition assignment to sparse vectors.
387  //**********************************************************************************************
388 
389  //**Subtraction assignment to dense vectors*****************************************************
404  template< typename VT1 > // Type of the target dense vector
405  friend inline typename EnableIf< UseAssign<VT1> >::Type
406  subAssign( DenseVector<VT1,false>& lhs, const DMatSVecMultExpr& rhs )
407  {
409 
410  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
411 
412  typedef typename RemoveReference<RT>::Type::ConstIterator ConstIterator;
413 
414  // Evaluation of the right-hand side sparse vector operand
415  RT x( rhs.vec_ );
416  if( x.nonZeros() == 0UL ) return;
417 
418  // Evaluation of the left-hand side dense matrix operand
419  LT A( rhs.mat_ );
420 
421  // Checking the evaluated operands
422  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
423  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
424  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
425  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).size() , "Invalid vector size" );
426 
427  // Performing the dense matrix-sparse vector multiplication
428  const ConstIterator end( x.end() );
429 
430  for( size_t i=0UL; i<(~lhs).size(); ++i )
431  {
432  ConstIterator element( x.begin() );
433 
434  for( ; element!=end; ++element ) {
435  (~lhs)[i] -= A( i, element->index() ) * element->value();
436  }
437  }
438  }
440  //**********************************************************************************************
441 
442  //**Subtraction assignment to sparse vectors****************************************************
443  // No special implementation for the subtraction assignment to sparse vectors.
444  //**********************************************************************************************
445 
446  //**Multiplication assignment to dense vectors**************************************************
461  template< typename VT1 > // Type of the target dense vector
462  friend inline typename EnableIf< UseAssign<VT1> >::Type
463  multAssign( DenseVector<VT1,false>& lhs, const DMatSVecMultExpr& rhs )
464  {
466 
469  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
470 
471  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
472 
473  const ResultType tmp( rhs );
474  multAssign( ~lhs, tmp );
475  }
477  //**********************************************************************************************
478 
479  //**Addition assignment to sparse vectors*******************************************************
480  // No special implementation for the multiplication assignment to sparse vectors.
481  //**********************************************************************************************
482 
483  //**Compile time checks*************************************************************************
490  //**********************************************************************************************
491 };
492 //*************************************************************************************************
493 
494 
495 
496 
497 //=================================================================================================
498 //
499 // GLOBAL BINARY ARITHMETIC OPERATORS
500 //
501 //=================================================================================================
502 
503 //*************************************************************************************************
535 template< typename T1 // Type of the left-hand side dense matrix
536  , typename T2 > // Type of the right-hand side sparse vector
537 inline const typename DisableIf< IsMatMatMultExpr<T1>, DMatSVecMultExpr<T1,T2> >::Type
539 {
541 
542  if( (~mat).columns() != (~vec).size() )
543  throw std::invalid_argument( "Matrix and vector sizes do not match" );
544 
545  return DMatSVecMultExpr<T1,T2>( ~mat, ~vec );
546 }
547 //*************************************************************************************************
548 
549 
550 
551 
552 //=================================================================================================
553 //
554 // GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
555 //
556 //=================================================================================================
557 
558 //*************************************************************************************************
571 template< typename T1 // Type of the left-hand side dense matrix
572  , bool SO // Storage order of the left-hand side dense matrix
573  , typename T2 > // Type of the right-hand side sparse vector
574 inline const typename EnableIf< IsMatMatMultExpr<T1>, MultExprTrait<T1,T2> >::Type::Type
576 {
578 
579  return (~mat).leftOperand() * ( (~mat).rightOperand() * vec );
580 }
581 //*************************************************************************************************
582 
583 } // namespace blaze
584 
585 #endif