All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TDVecTSMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TDVECTSMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TDVECTSMATMULTEXPR_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>
47 #include <blaze/util/Assert.h>
49 #include <blaze/util/DisableIf.h>
50 #include <blaze/util/EnableIf.h>
51 #include <blaze/util/SelectType.h>
52 #include <blaze/util/Types.h>
53 
54 
55 namespace blaze {
56 
57 //=================================================================================================
58 //
59 // CLASS TDVECSMATMULTEXPR
60 //
61 //=================================================================================================
62 
63 //*************************************************************************************************
70 template< typename VT // Type of the left-hand side dense vector
71  , typename MT > // Type of the right-hand side sparse matrix
72 class TDVecTSMatMultExpr : public DenseVector< TDVecTSMatMultExpr<VT,MT>, true >
73  , private Expression
74  , private Computation
75 {
76  private:
77  //**Type definitions****************************************************************************
78  typedef typename VT::ResultType VRT;
79  typedef typename MT::ResultType MRT;
80  typedef typename VT::CompositeType VCT;
81  typedef typename MT::CompositeType MCT;
82  //**********************************************************************************************
83 
84  //**********************************************************************************************
86 
92  enum { useAssign = ( IsComputation<VT>::value || RequiresEvaluation<MT>::value ) };
93  //**********************************************************************************************
94 
95  //**********************************************************************************************
97 
98  template< typename VT2 >
99  struct UseAssign {
100  enum { value = useAssign };
101  };
103  //**********************************************************************************************
104 
105  public:
106  //**Type definitions****************************************************************************
109  typedef typename ResultType::TransposeType TransposeType;
110  typedef typename ResultType::ElementType ElementType;
111  typedef const ElementType ReturnType;
112 
115 
117  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type LeftOperand;
118 
120  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type RightOperand;
121 
123  typedef typename SelectType< IsComputation<VT>::value, const VRT, VCT >::Type LT;
124 
126  typedef MCT RT;
127  //**********************************************************************************************
128 
129  //**Compilation flags***************************************************************************
131  enum { vectorizable = 0 };
132 
134  enum { canAlias = ( !IsComputation<VT>::value ) ||
136  //**********************************************************************************************
137 
138  //**Constructor*********************************************************************************
141  explicit inline TDVecTSMatMultExpr( const VT& vec, const MT& mat )
142  : vec_( vec ) // Left-hand side dense vector of the multiplication expression
143  , mat_( mat ) // Right-hand side sparse matrix of the multiplication expression
144  {
145  BLAZE_INTERNAL_ASSERT( vec_.size() == mat.rows(), "Invalid vector and matrix sizes" );
146  }
147  //**********************************************************************************************
148 
149  //**Subscript operator**************************************************************************
155  inline ReturnType operator[]( size_t index ) const {
156  BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
157 
158  typedef typename boost::remove_reference<MCT>::type::ConstIterator ConstIterator;
159 
160  VCT x( vec_ ); // Evaluation of the left-hand side sparse vector operand
161  MCT A( mat_ ); // Evaluation of the right-hand side sparse matrix operand
162 
163  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size() , "Invalid vector size" );
164  BLAZE_INTERNAL_ASSERT( A.rows() == mat_.rows() , "Invalid number of rows" );
165  BLAZE_INTERNAL_ASSERT( A.columns() == mat_.columns(), "Invalid number of columns" );
166 
167  const ConstIterator end( A.end(index) );
168  ConstIterator element( A.begin(index) );
169  ElementType res;
170 
171  if( element != end ) {
172  res = x[element->index()] * element->value();
173  ++element;
174  for( ; element!=end; ++element )
175  res += x[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_.columns();
192  }
193  //**********************************************************************************************
194 
195  //**Left operand access*************************************************************************
200  inline LeftOperand leftOperand() const {
201  return vec_;
202  }
203  //**********************************************************************************************
204 
205  //**Right operand access************************************************************************
210  inline RightOperand rightOperand() const {
211  return mat_;
212  }
213  //**********************************************************************************************
214 
215  //**********************************************************************************************
221  template< typename T >
222  inline bool isAliased( const T* alias ) const {
223  return ( !IsComputation<VT>::value && vec_.isAliased( alias ) ) ||
225  CanAlias<MT>::value && mat_.isAliased( alias ) );
226  }
227  //**********************************************************************************************
228 
229  private:
230  //**Member variables****************************************************************************
231  LeftOperand vec_;
232  RightOperand mat_;
233  //**********************************************************************************************
234 
235  //**Assignment to dense vectors*****************************************************************
250  template< typename VT2 > // Type of the target dense vector
251  friend inline typename EnableIf< UseAssign<VT2> >::Type
253  {
254  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
255 
256  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
257 
258  if( rhs.mat_.rows() == 0UL ) {
259  reset( ~lhs );
260  return;
261  }
262 
263  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operator
264  RT A( rhs.mat_ ); // Evaluation of the right-hand side sparse matrix operator
265 
266  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
267  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
268  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
269  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
270 
271  for( size_t j=0UL; j<A.columns(); ++j )
272  {
273  const ConstIterator end( A.end(j) );
274  ConstIterator element( A.begin(j) );
275 
276  if( element == end ) {
277  reset( (~lhs)[j] );
278  continue;
279  }
280 
281  (~lhs)[j] = x[element->index()] * element->value();
282  ++element;
283  for( ; element!=end; ++element ) {
284  (~lhs)[j] += x[element->index()] * element->value();
285  }
286  }
287  }
288  //**********************************************************************************************
289 
290  //**Assignment to sparse vectors****************************************************************
305  template< typename VT2 > // Type of the target sparse vector
306  friend inline typename EnableIf< UseAssign<VT2> >::Type
308  {
311  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
312 
313  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
314 
315  const ResultType tmp( rhs );
316  assign( ~lhs, tmp );
317  }
318  //**********************************************************************************************
319 
320  //**Addition assignment to dense vectors********************************************************
335  template< typename VT2 > // Type of the target dense vector
336  friend inline typename EnableIf< UseAssign<VT2> >::Type
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  if( rhs.mat_.rows() == 0UL ) {
344  return;
345  }
346 
347  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operator
348  RT A( rhs.mat_ ); // Evaluation of the right-hand side sparse matrix operator
349 
350  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
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( A.columns() == (~lhs).size() , "Invalid vector size" );
354 
355  for( size_t j=0UL; j<A.columns(); ++j ) {
356  const ConstIterator end( A.end(j) );
357  ConstIterator element( A.begin(j) );
358 
359  for( ; element!=end; ++element ) {
360  (~lhs)[j] += x[element->index()] * element->value();
361  }
362  }
363  }
364  //**********************************************************************************************
365 
366  //**Addition assignment to sparse vectors*******************************************************
367  // No special implementation for the addition assignment to sparse vectors.
368  //**********************************************************************************************
369 
370  //**Subtraction assignment to dense vectors*****************************************************
385  template< typename VT2 > // Type of the target dense vector
386  friend inline typename EnableIf< UseAssign<VT2> >::Type
388  {
389  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
390 
391  typedef typename boost::remove_reference<RT>::type::ConstIterator ConstIterator;
392 
393  if( rhs.mat_.rows() == 0UL ) {
394  return;
395  }
396 
397  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operator
398  RT A( rhs.mat_ ); // Evaluation of the right-hand side sparse matrix operator
399 
400  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
401  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
402  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
403  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
404 
405  for( size_t j=0UL; j<A.columns(); ++j ) {
406  const ConstIterator end( A.end(j) );
407  ConstIterator element( A.begin(j) );
408 
409  for( ; element!=end; ++element ) {
410  (~lhs)[j] -= x[element->index()] * element->value();
411  }
412  }
413  }
414  //**********************************************************************************************
415 
416  //**Subtraction assignment to sparse vectors****************************************************
417  // No special implementation for the subtraction assignment to sparse vectors.
418  //**********************************************************************************************
419 
420  //**Multiplication assignment to dense vectors**************************************************
435  template< typename VT2 > // Type of the target dense vector
436  friend inline typename EnableIf< UseAssign<VT2> >::Type
438  {
441  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
442 
443  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
444 
445  const ResultType tmp( rhs );
446  multAssign( ~lhs, tmp );
447  }
448  //**********************************************************************************************
449 
450  //**Multiplication assignment to sparse vectors*************************************************
451  // No special implementation for the multiplication assignment to sparse vectors.
452  //**********************************************************************************************
453 
454  //**Compile time checks*************************************************************************
461  //**********************************************************************************************
462 };
463 //*************************************************************************************************
464 
465 
466 
467 
468 //=================================================================================================
469 //
470 // GLOBAL BINARY ARITHMETIC OPERATORS
471 //
472 //=================================================================================================
473 
474 //*************************************************************************************************
505 template< typename T1 // Type of the left-hand side dense vector
506  , typename T2 > // Type of the right-hand side sparse matrix
507 inline const typename DisableIf< IsMatMatMultExpr<T2>, TDVecTSMatMultExpr<T1,T2> >::Type
509 {
510  if( (~vec).size() != (~mat).rows() )
511  throw std::invalid_argument( "Vector and matrix sizes do not match" );
512 
513  return TDVecTSMatMultExpr<T1,T2>( ~vec, ~mat );
514 }
515 //*************************************************************************************************
516 
517 } // namespace blaze
518 
519 #endif