All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TDVecSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TDVECSMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TDVECSMATMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
31 #include <boost/type_traits/remove_reference.hpp>
40 #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 TDVECSMATMULTEXPR
62 //
63 //=================================================================================================
64 
65 //*************************************************************************************************
72 template< typename VT // Type of the left-hand side dense vector
73  , typename MT > // Type of the right-hand side sparse matrix
74 class TDVecSMatMultExpr : public DenseVector< TDVecSMatMultExpr<VT,MT>, true >
75  , private Expression
76  , private Computation
77 {
78  private:
79  //**Type definitions****************************************************************************
80  typedef typename VT::ResultType VRT;
81  typedef typename MT::ResultType MRT;
82  typedef typename VT::CompositeType VCT;
83  typedef typename MT::CompositeType MCT;
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<VT>::value, const VT, const VT& >::Type LeftOperand;
97 
99  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type RightOperand;
100 
102  typedef typename SelectType< IsComputation<VT>::value, const VRT, VCT >::Type LT;
103 
105  typedef MCT RT;
106  //**********************************************************************************************
107 
108  //**Compilation flags***************************************************************************
110  enum { vectorizable = 0 };
111 
113  enum { canAlias = ( !IsComputation<VT>::value ) ||
115  //**********************************************************************************************
116 
117  //**Constructor*********************************************************************************
120  explicit inline TDVecSMatMultExpr( const VT& vec, const MT& mat )
121  : vec_( vec ) // Left-hand side dense vector of the multiplication expression
122  , mat_( mat ) // Right-hand side sparse matrix of the multiplication expression
123  {
124  BLAZE_INTERNAL_ASSERT( vec_.size() == mat.rows(), "Invalid vector and matrix sizes" );
125  }
126  //**********************************************************************************************
127 
128  //**Subscript operator**************************************************************************
134  inline ReturnType operator[]( size_t index ) const {
135  BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
136 
137  ElementType res;
138 
139  if( vec_.size() != 0UL ) {
140  res = vec_[0UL] * mat_(0UL,index);
141  for( size_t i=1UL; i<vec_.size(); ++i ) {
142  res += vec_[i] * mat_(i,index);
143  }
144  }
145  else {
146  reset( res );
147  }
148 
149  return res;
150  }
151  //**********************************************************************************************
152 
153  //**Size function*******************************************************************************
158  inline size_t size() const {
159  return mat_.columns();
160  }
161  //**********************************************************************************************
162 
163  //**Left operand access*************************************************************************
168  inline LeftOperand leftOperand() const {
169  return vec_;
170  }
171  //**********************************************************************************************
172 
173  //**Right operand access************************************************************************
178  inline RightOperand rightOperand() const {
179  return mat_;
180  }
181  //**********************************************************************************************
182 
183  //**********************************************************************************************
189  template< typename T >
190  inline bool isAliased( const T* alias ) const {
191  return ( !IsComputation<VT>::value && vec_.isAliased( alias ) ) ||
193  CanAlias<MT>::value && mat_.isAliased( alias ) );
194  }
195  //**********************************************************************************************
196 
197  private:
198  //**Member variables****************************************************************************
201  //**********************************************************************************************
202 
203  //**Default assignment to dense vectors*********************************************************
215  template< typename VT2 > // Type of the target dense vector
216  friend inline typename EnableIf< IsResizable<typename VT2::ElementType> >::Type
218  {
219  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
220 
221  if( rhs.mat_.rows() == 0UL ) {
222  reset( ~lhs );
223  return;
224  }
225 
226  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operator
227  RT A( rhs.mat_ ); // Evaluation of the right-hand side sparse matrix operator
228 
229  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
230  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
231  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
232  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
233 
234  for( size_t i=0; i<(~lhs).size(); ++i ) {
235  (~lhs)[i] = x[0UL] * A(0UL,i);
236  for( size_t j=1UL; j<x.size(); ++j ) {
237  (~lhs)[i] += x[j] * A(j,i);
238  }
239  }
240  }
241  //**********************************************************************************************
242 
243  //**Optimized assignment to dense vectors*******************************************************
255  template< typename VT2 > // Type of the target dense vector
256  friend inline typename DisableIf< IsResizable<typename VT2::ElementType> >::Type
258  {
259  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
260 
261  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
262 
263  if( rhs.mat_.rows() == 0UL ) {
264  reset( ~lhs );
265  return;
266  }
267 
268  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operator
269  RT A( rhs.mat_ ); // Evaluation of the right-hand side sparse matrix operator
270 
271  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
272  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
273  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
274  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
275 
276  reset( ~lhs );
277 
278  for( size_t i=0UL; i<x.size(); ++i ) {
279  const ConstIterator end( A.end(i) );
280  ConstIterator element( A.begin(i) );
281  for( ; element!=end; ++element ) {
282  (~lhs)[element->index()] += x[i] * element->value();
283  }
284  }
285  }
286  //**********************************************************************************************
287 
288  //**Assignment to sparse vectors****************************************************************
298  template< typename VT2 > // Type of the target sparse vector
299  friend inline void assign( SparseVector<VT2,true>& lhs, const TDVecSMatMultExpr& rhs )
300  {
303  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
304 
305  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
306 
307  const ResultType tmp( rhs );
308  assign( ~lhs, tmp );
309  }
310  //**********************************************************************************************
311 
312  //**Addition assignment to dense vectors********************************************************
323  template< typename VT2 > // Type of the target dense vector
324  friend inline void addAssign( DenseVector<VT2,true>& lhs, const TDVecSMatMultExpr& rhs )
325  {
326  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
327 
328  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
329 
330  if( rhs.mat_.rows() == 0UL ) {
331  return;
332  }
333 
334  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operator
335  RT A( rhs.mat_ ); // Evaluation of the right-hand side sparse matrix operator
336 
337  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
338  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
339  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
340  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
341 
342  for( size_t i=0UL; i<x.size(); ++i ) {
343  const ConstIterator end( A.end(i) );
344  ConstIterator element( A.begin(i) );
345  for( ; element!=end; ++element ) {
346  (~lhs)[element->index()] += x[i] * element->value();
347  }
348  }
349  }
350  //**********************************************************************************************
351 
352  //**Addition assignment to sparse vectors*******************************************************
353  // No special implementation for the addition assignment to sparse vectors.
354  //**********************************************************************************************
355 
356  //**Subtraction assignment to dense vectors*****************************************************
367  template< typename VT2 > // Type of the target dense vector
368  friend inline void subAssign( DenseVector<VT2,true>& lhs, const TDVecSMatMultExpr& rhs )
369  {
370  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
371 
372  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
373 
374  if( rhs.mat_.rows() == 0UL ) {
375  return;
376  }
377 
378  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operator
379  RT A( rhs.mat_ ); // Evaluation of the right-hand side sparse matrix operator
380 
381  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
382  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
383  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
384  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
385 
386  for( size_t i=0UL; i<x.size(); ++i ) {
387  const ConstIterator end( A.end(i) );
388  ConstIterator element( A.begin(i) );
389  for( ; element!=end; ++element ) {
390  (~lhs)[element->index()] -= x[i] * element->value();
391  }
392  }
393  }
394  //**********************************************************************************************
395 
396  //**Subtraction assignment to sparse vectors****************************************************
397  // No special implementation for the subtraction assignment to sparse vectors.
398  //**********************************************************************************************
399 
400  //**Multiplication assignment to dense vectors**************************************************
411  template< typename VT2 > // Type of the target dense vector
412  friend inline void multAssign( DenseVector<VT2,true>& lhs, const TDVecSMatMultExpr& rhs )
413  {
416  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
417 
418  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
419 
420  const ResultType tmp( rhs );
421  multAssign( ~lhs, tmp );
422  }
423  //**********************************************************************************************
424 
425  //**Multiplication assignment to sparse vectors*************************************************
426  // No special implementation for the multiplication assignment to sparse vectors.
427  //**********************************************************************************************
428 
429  //**Compile time checks*************************************************************************
436  //**********************************************************************************************
437 };
438 //*************************************************************************************************
439 
440 
441 
442 
443 //=================================================================================================
444 //
445 // GLOBAL BINARY ARITHMETIC OPERATORS
446 //
447 //=================================================================================================
448 
449 //*************************************************************************************************
480 template< typename T1 // Type of the left-hand side dense vector
481  , typename T2 > // Type of the right-hand side sparse matrix
482 inline const typename DisableIf< IsMatMatMultExpr<T2>, TDVecSMatMultExpr<T1,T2> >::Type
484 {
485  if( (~vec).size() != (~mat).rows() )
486  throw std::invalid_argument( "Vector and matrix sizes do not match" );
487 
488  return TDVecSMatMultExpr<T1,T2>( ~vec, ~mat );
489 }
490 //*************************************************************************************************
491 
492 
493 
494 
495 //=================================================================================================
496 //
497 // GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
498 //
499 //=================================================================================================
500 
501 //*************************************************************************************************
514 template< typename T1 // Type of the left-hand side dense vector
515  , typename T2 // Type of the right-hand side sparse matrix
516  , bool SO > // Storage order of the right-hand side sparse matrix
517 inline const typename EnableIf< IsMatMatMultExpr<T2>, MultExprTrait<T1,T2> >::Type::Type
519 {
520  return ( vec * (~mat).leftOperand() ) * (~mat).rightOperand();
521 }
522 //*************************************************************************************************
523 
524 } // namespace blaze
525 
526 #endif