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>
39 #include <blaze/math/shims/Reset.h>
45 #include <blaze/util/Assert.h>
47 #include <blaze/util/DisableIf.h>
48 #include <blaze/util/EnableIf.h>
50 #include <blaze/util/SelectType.h>
51 #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 TVecMatMultExpr
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  //**********************************************************************************************
133 
134  //**Constructor*********************************************************************************
137  explicit inline TDVecTSMatMultExpr( const VT& vec, const MT& mat )
138  : vec_( vec ) // Left-hand side dense vector of the multiplication expression
139  , mat_( mat ) // Right-hand side sparse matrix of the multiplication expression
140  {
141  BLAZE_INTERNAL_ASSERT( vec_.size() == mat.rows(), "Invalid vector and matrix sizes" );
142  }
143  //**********************************************************************************************
144 
145  //**Subscript operator**************************************************************************
151  inline ReturnType operator[]( size_t index ) const {
152  BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
153 
154  typedef typename RemoveReference<MCT>::Type::ConstIterator ConstIterator;
155 
156  VCT x( vec_ ); // Evaluation of the left-hand side sparse vector operand
157  MCT A( mat_ ); // Evaluation of the right-hand side sparse matrix operand
158 
159  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size() , "Invalid vector size" );
160  BLAZE_INTERNAL_ASSERT( A.rows() == mat_.rows() , "Invalid number of rows" );
161  BLAZE_INTERNAL_ASSERT( A.columns() == mat_.columns(), "Invalid number of columns" );
162 
163  const ConstIterator end( A.end(index) );
164  ConstIterator element( A.begin(index) );
165  ElementType res;
166 
167  if( element != end ) {
168  res = x[element->index()] * element->value();
169  ++element;
170  for( ; element!=end; ++element )
171  res += x[element->index()] * element->value();
172  }
173  else {
174  reset( res );
175  }
176 
177  return res;
178  }
179  //**********************************************************************************************
180 
181  //**Size function*******************************************************************************
186  inline size_t size() const {
187  return mat_.columns();
188  }
189  //**********************************************************************************************
190 
191  //**Left operand access*************************************************************************
196  inline LeftOperand leftOperand() const {
197  return vec_;
198  }
199  //**********************************************************************************************
200 
201  //**Right operand access************************************************************************
206  inline RightOperand rightOperand() const {
207  return mat_;
208  }
209  //**********************************************************************************************
210 
211  //**********************************************************************************************
217  template< typename T >
218  inline bool canAlias( const T* alias ) const {
219  return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
220  }
221  //**********************************************************************************************
222 
223  //**********************************************************************************************
229  template< typename T >
230  inline bool isAliased( const T* alias ) const {
231  return ( vec_.isAliased( alias ) || mat_.isAliased( alias ) );
232  }
233  //**********************************************************************************************
234 
235  private:
236  //**Member variables****************************************************************************
237  LeftOperand vec_;
238  RightOperand mat_;
239  //**********************************************************************************************
240 
241  //**Assignment to dense vectors*****************************************************************
256  template< typename VT2 > // Type of the target dense vector
257  friend inline typename EnableIf< UseAssign<VT2> >::Type
259  {
261 
262  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
263 
264  typedef typename RemoveReference<RT>::Type::ConstIterator ConstIterator;
265 
266  if( rhs.mat_.rows() == 0UL ) {
267  reset( ~lhs );
268  return;
269  }
270 
271  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operator
272  RT A( rhs.mat_ ); // Evaluation of the right-hand side sparse matrix operator
273 
274  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
275  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
276  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
277  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
278 
279  for( size_t j=0UL; j<A.columns(); ++j )
280  {
281  const ConstIterator end( A.end(j) );
282  ConstIterator element( A.begin(j) );
283 
284  if( element == end ) {
285  reset( (~lhs)[j] );
286  continue;
287  }
288 
289  (~lhs)[j] = x[element->index()] * element->value();
290  ++element;
291  for( ; element!=end; ++element ) {
292  (~lhs)[j] += x[element->index()] * element->value();
293  }
294  }
295  }
296  //**********************************************************************************************
297 
298  //**Assignment to sparse vectors****************************************************************
313  template< typename VT2 > // Type of the target sparse vector
314  friend inline typename EnableIf< UseAssign<VT2> >::Type
316  {
318 
321  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
322 
323  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
324 
325  const ResultType tmp( rhs );
326  assign( ~lhs, tmp );
327  }
328  //**********************************************************************************************
329 
330  //**Addition assignment to dense vectors********************************************************
345  template< typename VT2 > // Type of the target dense vector
346  friend inline typename EnableIf< UseAssign<VT2> >::Type
348  {
350 
351  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
352 
353  typedef typename RemoveReference<RT>::Type::ConstIterator ConstIterator;
354 
355  if( rhs.mat_.rows() == 0UL ) {
356  return;
357  }
358 
359  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operator
360  RT A( rhs.mat_ ); // Evaluation of the right-hand side sparse matrix operator
361 
362  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
363  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
364  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
365  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
366 
367  for( size_t j=0UL; j<A.columns(); ++j ) {
368  const ConstIterator end( A.end(j) );
369  ConstIterator element( A.begin(j) );
370 
371  for( ; element!=end; ++element ) {
372  (~lhs)[j] += x[element->index()] * element->value();
373  }
374  }
375  }
376  //**********************************************************************************************
377 
378  //**Addition assignment to sparse vectors*******************************************************
379  // No special implementation for the addition assignment to sparse vectors.
380  //**********************************************************************************************
381 
382  //**Subtraction assignment to dense vectors*****************************************************
397  template< typename VT2 > // Type of the target dense vector
398  friend inline typename EnableIf< UseAssign<VT2> >::Type
400  {
402 
403  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
404 
405  typedef typename RemoveReference<RT>::Type::ConstIterator ConstIterator;
406 
407  if( rhs.mat_.rows() == 0UL ) {
408  return;
409  }
410 
411  LT x( rhs.vec_ ); // Evaluation of the left-hand side dense vector operator
412  RT A( rhs.mat_ ); // Evaluation of the right-hand side sparse matrix operator
413 
414  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
415  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
416  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
417  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
418 
419  for( size_t j=0UL; j<A.columns(); ++j ) {
420  const ConstIterator end( A.end(j) );
421  ConstIterator element( A.begin(j) );
422 
423  for( ; element!=end; ++element ) {
424  (~lhs)[j] -= x[element->index()] * element->value();
425  }
426  }
427  }
428  //**********************************************************************************************
429 
430  //**Subtraction assignment to sparse vectors****************************************************
431  // No special implementation for the subtraction assignment to sparse vectors.
432  //**********************************************************************************************
433 
434  //**Multiplication assignment to dense vectors**************************************************
449  template< typename VT2 > // Type of the target dense vector
450  friend inline typename EnableIf< UseAssign<VT2> >::Type
452  {
454 
457  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
458 
459  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
460 
461  const ResultType tmp( rhs );
462  multAssign( ~lhs, tmp );
463  }
464  //**********************************************************************************************
465 
466  //**Multiplication assignment to sparse vectors*************************************************
467  // No special implementation for the multiplication assignment to sparse vectors.
468  //**********************************************************************************************
469 
470  //**Compile time checks*************************************************************************
477  //**********************************************************************************************
478 };
479 //*************************************************************************************************
480 
481 
482 
483 
484 //=================================================================================================
485 //
486 // GLOBAL BINARY ARITHMETIC OPERATORS
487 //
488 //=================================================================================================
489 
490 //*************************************************************************************************
521 template< typename T1 // Type of the left-hand side dense vector
522  , typename T2 > // Type of the right-hand side sparse matrix
523 inline const typename DisableIf< IsMatMatMultExpr<T2>, TDVecTSMatMultExpr<T1,T2> >::Type
525 {
527 
528  if( (~vec).size() != (~mat).rows() )
529  throw std::invalid_argument( "Vector and matrix sizes do not match" );
530 
531  return TDVecTSMatMultExpr<T1,T2>( ~vec, ~mat );
532 }
533 //*************************************************************************************************
534 
535 } // namespace blaze
536 
537 #endif