All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TSVecDMatMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TSVECDMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TSVECDMATMULTEXPR_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>
50 #include <blaze/util/Assert.h>
52 #include <blaze/util/DisableIf.h>
53 #include <blaze/util/EnableIf.h>
54 #include <blaze/util/SelectType.h>
55 #include <blaze/util/Types.h>
56 
57 
58 namespace blaze {
59 
60 //=================================================================================================
61 //
62 // CLASS TSVECDMATMULTEXPR
63 //
64 //=================================================================================================
65 
66 //*************************************************************************************************
73 template< typename VT // Type of the left-hand side sparse vector
74  , typename MT > // Type of the right-hand side dense matrix
75 class TSVecDMatMultExpr : public DenseVector< TSVecDMatMultExpr<VT,MT>, true >
76  , private Expression
77  , private Computation
78 {
79  private:
80  //**Type definitions****************************************************************************
81  typedef typename VT::ResultType VRT;
82  typedef typename MT::ResultType MRT;
83  typedef typename VT::CompositeType VCT;
84  typedef typename MT::CompositeType MCT;
85  //**********************************************************************************************
86 
87  public:
88  //**Type definitions****************************************************************************
91  typedef typename ResultType::TransposeType TransposeType;
92  typedef typename ResultType::ElementType ElementType;
93  typedef const ElementType ReturnType;
94  typedef const ResultType CompositeType;
95 
97  typedef typename SelectType< IsExpression<VT>::value, const VT, const VT& >::Type LeftOperand;
98 
100  typedef typename SelectType< IsExpression<MT>::value, const MT, const MT& >::Type RightOperand;
101 
103  typedef typename SelectType< IsComputation<VT>::value, const VRT, VCT >::Type LT;
104 
106  typedef MCT RT;
107  //**********************************************************************************************
108 
109  //**Compilation flags***************************************************************************
111  enum { vectorizable = 0 };
112 
115  //**********************************************************************************************
116 
117  //**Constructor*********************************************************************************
123  explicit inline TSVecDMatMultExpr( const VT& vec, const MT& mat )
124  : vec_( vec ) // Left-hand side sparse vector of the multiplication expression
125  , mat_( mat ) // Right-hand side dense matrix of the multiplication expression
126  {
127  BLAZE_INTERNAL_ASSERT( vec_.size() == mat_.rows(), "Invalid vector and matrix sizes" );
128  }
129  //**********************************************************************************************
130 
131  //**Subscript operator**************************************************************************
137  inline ReturnType operator[]( size_t index ) const {
138  BLAZE_INTERNAL_ASSERT( index < mat_.columns(), "Invalid vector access index" );
139 
140  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
141 
142  LT x( vec_ ); // Evaluation of the left-hand side sparse vector operand
143 
144  BLAZE_INTERNAL_ASSERT( x.size() == vec_.size(), "Invalid vector size" );
145 
146  const ConstIterator end( x.end() );
147  ConstIterator element( x.begin() );
148  ElementType res;
149 
150  if( element != end ) {
151  res = element->value() * mat_( element->index(), index );
152  ++element;
153  for( ; element!=end; ++element )
154  res += element->value() * mat_( element->index(), index );
155  }
156  else {
157  reset( res );
158  }
159 
160  return res;
161  }
162  //**********************************************************************************************
163 
164  //**Size function*******************************************************************************
169  inline size_t size() const {
170  return mat_.columns();
171  }
172  //**********************************************************************************************
173 
174  //**Left operand access*************************************************************************
179  inline LeftOperand leftOperand() const {
180  return vec_;
181  }
182  //**********************************************************************************************
183 
184  //**Right operand access************************************************************************
189  inline RightOperand rightOperand() const {
190  return mat_;
191  }
192  //**********************************************************************************************
193 
194  //**********************************************************************************************
200  template< typename T >
201  inline bool isAliased( const T* alias ) const {
203  CanAlias<MT>::value && mat_.isAliased( alias );
204  }
205  //**********************************************************************************************
206 
207  private:
208  //**Member variables****************************************************************************
211  //**********************************************************************************************
212 
213  //**Default assignment to dense vectors*********************************************************
227  template< typename VT2 > // Type of the target dense vector
228  friend inline typename EnableIf< IsResizable<typename VT2::ElementType> >::Type
230  {
231  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
232 
233  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
234 
235  // Evaluation of the left-hand side sparse vector operand
236  LT x( rhs.vec_ );
237  if( x.nonZeros() == 0UL ) {
238  reset( ~lhs );
239  return;
240  }
241 
242  // Evaluation of the right-hand side dense matrix operand
243  RT A( rhs.mat_ );
244 
245  // Checking the evaluated operands
246  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
247  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
248  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
249  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
250 
251  // Performing the sparse vector-dense matrix multiplication
252  const ConstIterator end( x.end() );
253 
254  for( size_t i=0UL; i<(~lhs).size(); ++i )
255  {
256  ConstIterator element( x.begin() );
257 
258  (~lhs)[i] = element->value() * A(element->index(),i);
259  ++element;
260  for( ; element!=end; ++element ) {
261  (~lhs)[i] += element->value() * A(element->index(),i);
262  }
263  }
264  }
266  //**********************************************************************************************
267 
268  //**Optimized assignment to dense vectors*******************************************************
282  template< typename VT2 > // Type of the target dense vector
283  friend inline typename DisableIf< IsResizable<typename VT2::ElementType> >::Type
285  {
286  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
287 
288  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
289 
290  // Resetting the left-hand side target dense vector
291  reset( ~lhs );
292 
293  // Evaluation of the left-hand side sparse vector operand
294  LT x( rhs.vec_ );
295  if( x.nonZeros() == 0UL ) return;
296 
297  // Evaluation of the right-hand side dense matrix operand
298  RT A( rhs.mat_ );
299 
300  // Checking the evaluated operands
301  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
302  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
303  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
304  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
305 
306  // Performing the sparse vector-dense matrix multiplication
307  const ConstIterator end( x.end() );
308  ConstIterator element( x.begin() );
309 
310  for( ; element!=end; ++element ) {
311  for( size_t i=0UL; i<A.columns(); ++i ) {
312  (~lhs)[i] += element->value() * A(element->index(),i);
313  }
314  }
315  }
317  //**********************************************************************************************
318 
319  //**Assignment to sparse vectors****************************************************************
331  template< typename VT2 > // Type of the target sparse vector
332  friend inline void assign( SparseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
333  {
336  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
337 
338  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
339 
340  const ResultType tmp( rhs );
341  assign( ~lhs, tmp );
342  }
344  //**********************************************************************************************
345 
346  //**Addition assignment to dense vectors********************************************************
357  template< typename VT2 > // Type of the target dense vector
358  friend inline void addAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
359  {
360  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
361 
362  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
363 
364  // Evaluation of the left-hand side sparse vector operand
365  LT x( rhs.vec_ );
366  if( x.nonZeros() == 0UL ) return;
367 
368  // Evaluation of the right-hand side dense matrix operand
369  RT A( rhs.mat_ );
370 
371  // Checking the evaluated operands
372  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
373  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
374  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
375  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
376 
377  // Performing the sparse vector-dense matrix multiplication
378  const ConstIterator end( x.end() );
379  ConstIterator element( x.begin() );
380 
381  for( ; element!=end; ++element ) {
382  for( size_t i=0UL; i<A.columns(); ++i ) {
383  (~lhs)[i] += element->value() * A(element->index(),i);
384  }
385  }
386  }
387  //**********************************************************************************************
388 
389  //**Addition assignment to sparse vectors*******************************************************
390  // No special implementation for the addition assignment to sparse vectors.
391  //**********************************************************************************************
392 
393  //**Subtraction assignment to dense vectors*****************************************************
404  template< typename VT2 > // Type of the target dense vector
405  friend inline void subAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
406  {
407  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
408 
409  typedef typename boost::remove_reference<LT>::type::ConstIterator ConstIterator;
410 
411  // Evaluation of the left-hand side sparse vector operand
412  LT x( rhs.vec_ );
413  if( x.nonZeros() == 0UL ) return;
414 
415  // Evaluation of the right-hand side dense matrix operand
416  RT A( rhs.mat_ );
417 
418  // Checking the evaluated operands
419  BLAZE_INTERNAL_ASSERT( x.size() == rhs.vec_.size() , "Invalid vector size" );
420  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.mat_.rows() , "Invalid number of rows" );
421  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.mat_.columns(), "Invalid number of columns" );
422  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).size() , "Invalid vector size" );
423 
424  // Performing the sparse vector-dense matrix multiplication
425  const ConstIterator end( x.end() );
426  ConstIterator element( x.begin() );
427 
428  for( ; element!=end; ++element ) {
429  for( size_t i=0UL; i<A.columns(); ++i ) {
430  (~lhs)[i] -= element->value() * A(element->index(),i);
431  }
432  }
433  }
434  //**********************************************************************************************
435 
436  //**Subtraction assignment to sparse vectors****************************************************
437  // No special implementation for the subtraction assignment to sparse vectors.
438  //**********************************************************************************************
439 
440  //**Multiplication assignment to dense vectors**************************************************
451  template< typename VT2 > // Type of the target dense vector
452  friend inline void multAssign( DenseVector<VT2,true>& lhs, const TSVecDMatMultExpr& rhs )
453  {
456  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
457 
458  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
459 
460  const ResultType tmp( rhs );
461  multAssign( ~lhs, tmp );
462  }
463  //**********************************************************************************************
464 
465  //**Multiplication assignment to sparse vectors*************************************************
466  // No special implementation for the multiplication assignment to sparse vectors.
467  //**********************************************************************************************
468 
469  //**Compile time checks*************************************************************************
476  //**********************************************************************************************
477 };
478 //*************************************************************************************************
479 
480 
481 
482 
483 //=================================================================================================
484 //
485 // GLOBAL BINARY ARITHMETIC OPERATORS
486 //
487 //=================================================================================================
488 
489 //*************************************************************************************************
520 template< typename T1, typename T2 >
521 inline const typename DisableIf< IsMatMatMultExpr<T2>, TSVecDMatMultExpr<T1,T2> >::Type
523 {
524  if( (~vec).size() != (~mat).rows() )
525  throw std::invalid_argument( "Vector and matrix sizes do not match" );
526 
527  return TSVecDMatMultExpr<T1,T2>( ~vec, ~mat );
528 }
529 //*************************************************************************************************
530 
531 
532 
533 
534 //=================================================================================================
535 //
536 // GLOBAL RESTRUCTURING BINARY ARITHMETIC OPERATORS
537 //
538 //=================================================================================================
539 
540 //*************************************************************************************************
553 template< typename T1 // Type of the left-hand side sparse vector
554  , typename T2 // Type of the right-hand side dense matrix
555  , bool SO > // Storage order of the right-hand side dense matrix
556 inline const typename EnableIf< IsMatMatMultExpr<T2>, MultExprTrait<T1,T2> >::Type::Type
558 {
559  return ( vec * (~mat).leftOperand() ) * (~mat).rightOperand();
560 }
561 //*************************************************************************************************
562 
563 } // namespace blaze
564 
565 #endif