All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SVecSVecMultExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_SVECSVECMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_SVECSVECMULTEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
31 #include <boost/type_traits/remove_reference.hpp>
38 #include <blaze/math/Functions.h>
46 #include <blaze/util/Assert.h>
48 #include <blaze/util/SelectType.h>
49 #include <blaze/util/Types.h>
50 
51 
52 namespace blaze {
53 
54 //=================================================================================================
55 //
56 // CLASS SVECSVECMULTEXPR
57 //
58 //=================================================================================================
59 
60 //*************************************************************************************************
67 template< typename VT1 // Type of the left-hand side sparse vector
68  , typename VT2 // Type of the right-hand side sparse vector
69  , bool TF > // Transpose flag
70 class SVecSVecMultExpr : public SparseVector< SVecSVecMultExpr<VT1,VT2,TF>, TF >
71  , private Expression
72  , private Computation
73 {
74  private:
75  //**Type definitions****************************************************************************
76  typedef typename VT1::ResultType RT1;
77  typedef typename VT2::ResultType RT2;
78  typedef typename VT1::ReturnType RN1;
79  typedef typename VT2::ReturnType RN2;
80  typedef typename VT1::CompositeType CT1;
81  typedef typename VT2::CompositeType CT2;
82  typedef typename VT1::TransposeType TT1;
83  typedef typename VT2::TransposeType TT2;
84  //**********************************************************************************************
85 
86  //**Return type evaluation**********************************************************************
88 
93  enum { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
94 
97  //**********************************************************************************************
98 
99  public:
100  //**Type definitions****************************************************************************
103  typedef typename ResultType::TransposeType TransposeType;
104  typedef typename ResultType::ElementType ElementType;
105 
108 
110  typedef const ResultType CompositeType;
111 
113  typedef typename SelectType< IsExpression<VT1>::value, const VT1, const VT1& >::Type LeftOperand;
114 
116  typedef typename SelectType< IsExpression<VT2>::value, const VT2, const VT2& >::Type RightOperand;
117  //**********************************************************************************************
118 
119  //**Compilation flags***************************************************************************
123  //**********************************************************************************************
124 
125  //**Constructor*********************************************************************************
128  explicit inline SVecSVecMultExpr( const VT1& lhs, const VT2& rhs )
129  : lhs_( lhs ) // Left-hand side sparse vector of the multiplication expression
130  , rhs_( rhs ) // Right-hand side sparse vector of the multiplication expression
131  {
132  BLAZE_INTERNAL_ASSERT( lhs.size() == rhs.size(), "Invalid vector sizes" );
133  }
134  //**********************************************************************************************
135 
136  //**Subscript operator**************************************************************************
142  inline ReturnType operator[]( size_t index ) const {
143  BLAZE_INTERNAL_ASSERT( index < lhs_.size(), "Invalid vector access index" );
144  return lhs_[index] * rhs_[index];
145  }
146  //**********************************************************************************************
147 
148  //**Size function*******************************************************************************
153  inline size_t size() const {
154  return lhs_.size();
155  }
156  //**********************************************************************************************
157 
158  //**NonZeros function***************************************************************************
163  inline size_t nonZeros() const {
164  return min( lhs_.nonZeros(), rhs_.nonZeros() );
165  }
166  //**********************************************************************************************
167 
168  //**Left operand access*************************************************************************
173  inline LeftOperand leftOperand() const {
174  return lhs_;
175  }
176  //**********************************************************************************************
177 
178  //**Right operand access************************************************************************
183  inline RightOperand rightOperand() const {
184  return rhs_;
185  }
186  //**********************************************************************************************
187 
188  //**********************************************************************************************
194  template< typename T >
195  inline bool isAliased( const T* alias ) const {
197  !RequiresEvaluation<VT1>::value && lhs_.isAliased( alias ) ) ||
199  !RequiresEvaluation<VT2>::value && rhs_.isAliased( alias ) );
200  }
201  //**********************************************************************************************
202 
203  private:
204  //**Member variables****************************************************************************
207  //**********************************************************************************************
208 
209  //**Assignment to dense vectors*****************************************************************
221  template< typename VT > // Type of the target dense vector
222  friend inline void assign( DenseVector<VT,TF>& lhs, const SVecSVecMultExpr& rhs )
223  {
224  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
225 
226  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
227  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
228 
229  CT1 x( rhs.lhs_ ); // Evaluation of the left-hand side sparse vector operand
230  CT2 y( rhs.rhs_ ); // Evaluation of the right-hand side sparse vector operand
231 
232  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
233  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
234  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
235 
236  const LeftIterator lend( x.end() );
237  const RightIterator rend( y.end() );
238 
239  LeftIterator l( x.begin() );
240  RightIterator r( y.begin() );
241 
242  for( ; l!=lend; ++l ) {
243  while( r!=rend && r->index() < l->index() ) ++r;
244  if( r==rend ) break;
245  if( l->index() == r->index() ) {
246  (~lhs)[l->index()] = l->value() * r->value();
247  ++r;
248  }
249  }
250  }
252  //**********************************************************************************************
253 
254  //**Assignment to sparse vectors****************************************************************
266  template< typename VT > // Type of the target sparse vector
267  friend inline void assign( SparseVector<VT,TF>& lhs, const SVecSVecMultExpr& rhs )
268  {
269  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
270 
271  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
272  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
273 
274  CT1 x( rhs.lhs_ ); // Evaluation of the left-hand side sparse vector operand
275  CT2 y( rhs.rhs_ ); // Evaluation of the right-hand side sparse vector operand
276 
277  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
278  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
279  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
280 
281  const LeftIterator lend( x.end() );
282  const RightIterator rend( y.end() );
283 
284  LeftIterator l( x.begin() );
285  RightIterator r( y.begin() );
286 
287  for( ; l!=lend; ++l ) {
288  while( r!=rend && r->index() < l->index() ) ++r;
289  if( r==rend ) break;
290  if( l->index() == r->index() ) {
291  (~lhs).append( l->index(), l->value() * r->value() );
292  ++r;
293  }
294  }
295  }
297  //**********************************************************************************************
298 
299  //**Addition assignment to dense vectors********************************************************
311  template< typename VT > // Type of the target dense vector
312  friend inline void addAssign( DenseVector<VT,TF>& lhs, const SVecSVecMultExpr& rhs )
313  {
314  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
315 
316  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
317  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
318 
319  CT1 x( rhs.lhs_ ); // Evaluation of the left-hand side sparse vector operand
320  CT2 y( rhs.rhs_ ); // Evaluation of the right-hand side sparse vector operand
321 
322  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
323  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
324  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
325 
326  const LeftIterator lend( x.end() );
327  const RightIterator rend( y.end() );
328 
329  LeftIterator l( x.begin() );
330  RightIterator r( y.begin() );
331 
332  for( ; l!=lend; ++l ) {
333  while( r!=rend && r->index() < l->index() ) ++r;
334  if( r==rend ) break;
335  if( l->index() == r->index() ) {
336  (~lhs)[l->index()] += l->value() * r->value();
337  ++r;
338  }
339  }
340  }
342  //**********************************************************************************************
343 
344  //**Addition assignment to sparse vectors*******************************************************
345  // No special implementation for the addition assignment to sparse vectors.
346  //**********************************************************************************************
347 
348  //**Subtraction assignment to dense vectors*****************************************************
360  template< typename VT > // Type of the target dense vector
361  friend inline void subAssign( DenseVector<VT,TF>& lhs, const SVecSVecMultExpr& rhs )
362  {
363  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
364 
365  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
366  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
367 
368  CT1 x( rhs.lhs_ ); // Evaluation of the left-hand side sparse vector operand
369  CT2 y( rhs.rhs_ ); // Evaluation of the right-hand side sparse vector operand
370 
371  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
372  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
373  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
374 
375  const LeftIterator lend( x.end() );
376  const RightIterator rend( y.end() );
377 
378  LeftIterator l( x.begin() );
379  RightIterator r( y.begin() );
380 
381  for( ; l!=lend; ++l ) {
382  while( r!=rend && r->index() < l->index() ) ++r;
383  if( r==rend ) break;
384  if( l->index() == r->index() ) {
385  (~lhs)[l->index()] -= l->value() * r->value();
386  ++r;
387  }
388  }
389  }
391  //**********************************************************************************************
392 
393  //**Subtraction assignment to sparse vectors****************************************************
394  // No special implementation for the subtraction assignment to sparse vectors.
395  //**********************************************************************************************
396 
397  //**Multiplication assignment to dense vectors**************************************************
409  template< typename VT > // Type of the target dense vector
410  friend inline void multAssign( DenseVector<VT,TF>& lhs, const SVecSVecMultExpr& rhs )
411  {
412  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
413 
414  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
415  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
416 
417  CT1 x( rhs.lhs_ ); // Evaluation of the left-hand side sparse vector operand
418  CT2 y( rhs.rhs_ ); // Evaluation of the right-hand side sparse vector operand
419 
420  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
421  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
422  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
423 
424  const LeftIterator lend( x.end() );
425  const RightIterator rend( y.end() );
426 
427  LeftIterator l( x.begin() );
428  RightIterator r( y.begin() );
429 
430  size_t i( 0 );
431 
432  for( ; l!=lend; ++l ) {
433  while( r!=rend && r->index() < l->index() ) ++r;
434  if( r==rend ) break;
435  if( l->index() == r->index() ) {
436  for( ; i<r->index(); ++i )
437  reset( (~lhs)[i] );
438  (~lhs)[l->index()] *= l->value() * r->value();
439  ++r;
440  ++i;
441  }
442  }
443 
444  for( ; i<rhs.size(); ++i )
445  reset( (~lhs)[i] );
446  }
448  //**********************************************************************************************
449 
450  //**Multiplication assignment to sparse vectors*************************************************
462  template< typename VT > // Type of the target sparse vector
463  friend inline void multAssign( SparseVector<VT,TF>& lhs, const SVecSVecMultExpr& rhs )
464  {
465  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
466 
467  typedef typename VT::ConstIterator Iterator1;
468  typedef typename boost::remove_reference<CT1>::type::ConstIterator Iterator2;
469  typedef typename boost::remove_reference<CT2>::type::ConstIterator Iterator3;
470 
471  CT1 x( rhs.lhs_ ); // Evaluation of the left-hand side sparse vector operand
472  CT2 y( rhs.rhs_ ); // Evaluation of the right-hand side sparse vector operand
473 
474  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
475  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
476  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
477 
478  VT tmp( rhs.size(), rhs.nonZeros() );
479 
480  const Iterator1 end1( (~lhs).end() );
481  const Iterator2 end2( x.end() );
482  const Iterator3 end3( y.end() );
483 
484  Iterator1 i1( (~lhs).begin() );
485  Iterator2 i2( x.begin() );
486  Iterator3 i3( y.begin() );
487 
488  for( ; i1!=end1; ++i1 ) {
489  while( i2!=end2 && i2->index() < i1->index() ) ++i2;
490  if( i2==end2 ) break;
491  while( i3!=end3 && i3->index() < i1->index() ) ++i3;
492  if( i3==end3 ) break;
493  if( i1->index() == i2->index() && i1->index() == i3->index() ) {
494  tmp.append( i1->index(), i1->value() * i2->value() * i3->value() );
495  ++i2;
496  ++i3;
497  }
498  }
499 
500  swap( ~lhs, tmp );
501  }
503  //**********************************************************************************************
504 
505  //**Compile time checks*************************************************************************
512  //**********************************************************************************************
513 };
514 //*************************************************************************************************
515 
516 
517 
518 
519 //=================================================================================================
520 //
521 // GLOBAL BINARY ARITHMETIC OPERATORS
522 //
523 //=================================================================================================
524 
525 //*************************************************************************************************
550 template< typename T1 // Type of the left-hand side sparse vector
551  , typename T2 // Type of the right-hand side sparse vector
552  , bool TF > // Transpose flag
553 inline const SVecSVecMultExpr<T1,T2,TF>
555 {
556  if( (~lhs).size() != (~rhs).size() )
557  throw std::invalid_argument( "Vector sizes do not match" );
558 
559  return SVecSVecMultExpr<T1,T2,TF>( ~lhs, ~rhs );
560 }
561 //*************************************************************************************************
562 
563 } // namespace blaze
564 
565 #endif