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>
37 #include <blaze/math/Functions.h>
43 #include <blaze/util/Assert.h>
46 #include <blaze/util/SelectType.h>
47 #include <blaze/util/Types.h>
49 
50 
51 namespace blaze {
52 
53 //=================================================================================================
54 //
55 // CLASS SVECSVECMULTEXPR
56 //
57 //=================================================================================================
58 
59 //*************************************************************************************************
66 template< typename VT1 // Type of the left-hand side sparse vector
67  , typename VT2 // Type of the right-hand side sparse vector
68  , bool TF > // Transpose flag
69 class SVecSVecMultExpr : public SparseVector< SVecSVecMultExpr<VT1,VT2,TF>, TF >
70  , private VecVecMultExpr
71  , private Computation
72 {
73  private:
74  //**Type definitions****************************************************************************
75  typedef typename VT1::ResultType RT1;
76  typedef typename VT2::ResultType RT2;
77  typedef typename VT1::ReturnType RN1;
78  typedef typename VT2::ReturnType RN2;
79  typedef typename VT1::CompositeType CT1;
80  typedef typename VT2::CompositeType CT2;
81  typedef typename VT1::TransposeType TT1;
82  typedef typename VT2::TransposeType TT2;
83  //**********************************************************************************************
84 
85  //**Return type evaluation**********************************************************************
87 
92  enum { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
93 
96  //**********************************************************************************************
97 
98  public:
99  //**Type definitions****************************************************************************
102  typedef typename ResultType::TransposeType TransposeType;
103  typedef typename ResultType::ElementType ElementType;
104 
107 
109  typedef const ResultType CompositeType;
110 
112  typedef typename SelectType< IsExpression<VT1>::value, const VT1, const VT1& >::Type LeftOperand;
113 
115  typedef typename SelectType< IsExpression<VT2>::value, const VT2, const VT2& >::Type RightOperand;
116  //**********************************************************************************************
117 
118  //**Constructor*********************************************************************************
121  explicit inline SVecSVecMultExpr( const VT1& lhs, const VT2& rhs )
122  : lhs_( lhs ) // Left-hand side sparse vector of the multiplication expression
123  , rhs_( rhs ) // Right-hand side sparse vector of the multiplication expression
124  {
125  BLAZE_INTERNAL_ASSERT( lhs.size() == rhs.size(), "Invalid vector sizes" );
126  }
127  //**********************************************************************************************
128 
129  //**Subscript operator**************************************************************************
135  inline ReturnType operator[]( size_t index ) const {
136  BLAZE_INTERNAL_ASSERT( index < lhs_.size(), "Invalid vector access index" );
137  return lhs_[index] * rhs_[index];
138  }
139  //**********************************************************************************************
140 
141  //**Size function*******************************************************************************
146  inline size_t size() const {
147  return lhs_.size();
148  }
149  //**********************************************************************************************
150 
151  //**NonZeros function***************************************************************************
156  inline size_t nonZeros() const {
157  return min( lhs_.nonZeros(), rhs_.nonZeros() );
158  }
159  //**********************************************************************************************
160 
161  //**Left operand access*************************************************************************
166  inline LeftOperand leftOperand() const {
167  return lhs_;
168  }
169  //**********************************************************************************************
170 
171  //**Right operand access************************************************************************
176  inline RightOperand rightOperand() const {
177  return rhs_;
178  }
179  //**********************************************************************************************
180 
181  //**********************************************************************************************
187  template< typename T >
188  inline bool canAlias( const T* alias ) const {
189  return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
190  }
191  //**********************************************************************************************
192 
193  //**********************************************************************************************
199  template< typename T >
200  inline bool isAliased( const T* alias ) const {
201  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
202  }
203  //**********************************************************************************************
204 
205  private:
206  //**Member variables****************************************************************************
209  //**********************************************************************************************
210 
211  //**Assignment to dense vectors*****************************************************************
223  template< typename VT > // Type of the target dense vector
224  friend inline void assign( DenseVector<VT,TF>& lhs, const SVecSVecMultExpr& rhs )
225  {
227 
228  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
229 
230  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
231  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
232 
233  CT1 x( rhs.lhs_ ); // Evaluation of the left-hand side sparse vector operand
234  CT2 y( rhs.rhs_ ); // Evaluation of the right-hand side sparse vector operand
235 
236  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
237  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
238  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
239 
240  const LeftIterator lend( x.end() );
241  const RightIterator rend( y.end() );
242 
243  LeftIterator l( x.begin() );
244  RightIterator r( y.begin() );
245 
246  for( ; l!=lend; ++l ) {
247  while( r!=rend && r->index() < l->index() ) ++r;
248  if( r==rend ) break;
249  if( l->index() == r->index() ) {
250  (~lhs)[l->index()] = l->value() * r->value();
251  ++r;
252  }
253  }
254  }
256  //**********************************************************************************************
257 
258  //**Assignment to sparse vectors****************************************************************
270  template< typename VT > // Type of the target sparse vector
271  friend inline void assign( SparseVector<VT,TF>& lhs, const SVecSVecMultExpr& rhs )
272  {
274 
275  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
276 
277  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
278  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
279 
280  CT1 x( rhs.lhs_ ); // Evaluation of the left-hand side sparse vector operand
281  CT2 y( rhs.rhs_ ); // Evaluation of the right-hand side sparse vector operand
282 
283  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
284  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
285  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
286 
287  const LeftIterator lend( x.end() );
288  const RightIterator rend( y.end() );
289 
290  LeftIterator l( x.begin() );
291  RightIterator r( y.begin() );
292 
293  for( ; l!=lend; ++l ) {
294  while( r!=rend && r->index() < l->index() ) ++r;
295  if( r==rend ) break;
296  if( l->index() == r->index() ) {
297  (~lhs).append( l->index(), l->value() * r->value() );
298  ++r;
299  }
300  }
301  }
303  //**********************************************************************************************
304 
305  //**Addition assignment to dense vectors********************************************************
317  template< typename VT > // Type of the target dense vector
318  friend inline void addAssign( DenseVector<VT,TF>& lhs, const SVecSVecMultExpr& rhs )
319  {
321 
322  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
323 
324  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
325  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
326 
327  CT1 x( rhs.lhs_ ); // Evaluation of the left-hand side sparse vector operand
328  CT2 y( rhs.rhs_ ); // Evaluation of the right-hand side sparse vector operand
329 
330  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
331  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
332  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
333 
334  const LeftIterator lend( x.end() );
335  const RightIterator rend( y.end() );
336 
337  LeftIterator l( x.begin() );
338  RightIterator r( y.begin() );
339 
340  for( ; l!=lend; ++l ) {
341  while( r!=rend && r->index() < l->index() ) ++r;
342  if( r==rend ) break;
343  if( l->index() == r->index() ) {
344  (~lhs)[l->index()] += l->value() * r->value();
345  ++r;
346  }
347  }
348  }
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*****************************************************
368  template< typename VT > // Type of the target dense vector
369  friend inline void subAssign( DenseVector<VT,TF>& lhs, const SVecSVecMultExpr& rhs )
370  {
372 
373  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
374 
375  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
376  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
377 
378  CT1 x( rhs.lhs_ ); // Evaluation of the left-hand side sparse vector operand
379  CT2 y( rhs.rhs_ ); // Evaluation of the right-hand side sparse vector operand
380 
381  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
382  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
383  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
384 
385  const LeftIterator lend( x.end() );
386  const RightIterator rend( y.end() );
387 
388  LeftIterator l( x.begin() );
389  RightIterator r( y.begin() );
390 
391  for( ; l!=lend; ++l ) {
392  while( r!=rend && r->index() < l->index() ) ++r;
393  if( r==rend ) break;
394  if( l->index() == r->index() ) {
395  (~lhs)[l->index()] -= l->value() * r->value();
396  ++r;
397  }
398  }
399  }
401  //**********************************************************************************************
402 
403  //**Subtraction assignment to sparse vectors****************************************************
404  // No special implementation for the subtraction assignment to sparse vectors.
405  //**********************************************************************************************
406 
407  //**Multiplication assignment to dense vectors**************************************************
419  template< typename VT > // Type of the target dense vector
420  friend inline void multAssign( DenseVector<VT,TF>& lhs, const SVecSVecMultExpr& rhs )
421  {
423 
424  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
425 
426  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
427  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
428 
429  CT1 x( rhs.lhs_ ); // Evaluation of the left-hand side sparse vector operand
430  CT2 y( rhs.rhs_ ); // Evaluation of the right-hand side sparse vector operand
431 
432  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
433  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
434  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
435 
436  const LeftIterator lend( x.end() );
437  const RightIterator rend( y.end() );
438 
439  LeftIterator l( x.begin() );
440  RightIterator r( y.begin() );
441 
442  size_t i( 0 );
443 
444  for( ; l!=lend; ++l ) {
445  while( r!=rend && r->index() < l->index() ) ++r;
446  if( r==rend ) break;
447  if( l->index() == r->index() ) {
448  for( ; i<r->index(); ++i )
449  reset( (~lhs)[i] );
450  (~lhs)[l->index()] *= l->value() * r->value();
451  ++r;
452  ++i;
453  }
454  }
455 
456  for( ; i<rhs.size(); ++i )
457  reset( (~lhs)[i] );
458  }
460  //**********************************************************************************************
461 
462  //**Multiplication assignment to sparse vectors*************************************************
474  template< typename VT > // Type of the target sparse vector
475  friend inline void multAssign( SparseVector<VT,TF>& lhs, const SVecSVecMultExpr& rhs )
476  {
478 
479  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
480 
481  typedef typename VT::ConstIterator Iterator1;
482  typedef typename RemoveReference<CT1>::Type::ConstIterator Iterator2;
483  typedef typename RemoveReference<CT2>::Type::ConstIterator Iterator3;
484 
485  CT1 x( rhs.lhs_ ); // Evaluation of the left-hand side sparse vector operand
486  CT2 y( rhs.rhs_ ); // Evaluation of the right-hand side sparse vector operand
487 
488  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
489  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
490  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
491 
492  VT tmp( rhs.size(), rhs.nonZeros() );
493 
494  const Iterator1 end1( (~lhs).end() );
495  const Iterator2 end2( x.end() );
496  const Iterator3 end3( y.end() );
497 
498  Iterator1 i1( (~lhs).begin() );
499  Iterator2 i2( x.begin() );
500  Iterator3 i3( y.begin() );
501 
502  for( ; i1!=end1; ++i1 ) {
503  while( i2!=end2 && i2->index() < i1->index() ) ++i2;
504  if( i2==end2 ) break;
505  while( i3!=end3 && i3->index() < i1->index() ) ++i3;
506  if( i3==end3 ) break;
507  if( i1->index() == i2->index() && i1->index() == i3->index() ) {
508  tmp.append( i1->index(), i1->value() * i2->value() * i3->value() );
509  ++i2;
510  ++i3;
511  }
512  }
513 
514  swap( ~lhs, tmp );
515  }
517  //**********************************************************************************************
518 
519  //**Compile time checks*************************************************************************
526  //**********************************************************************************************
527 };
528 //*************************************************************************************************
529 
530 
531 
532 
533 //=================================================================================================
534 //
535 // GLOBAL BINARY ARITHMETIC OPERATORS
536 //
537 //=================================================================================================
538 
539 //*************************************************************************************************
564 template< typename T1 // Type of the left-hand side sparse vector
565  , typename T2 // Type of the right-hand side sparse vector
566  , bool TF > // Transpose flag
567 inline const SVecSVecMultExpr<T1,T2,TF>
569 {
571 
572  if( (~lhs).size() != (~rhs).size() )
573  throw std::invalid_argument( "Vector sizes do not match" );
574 
575  return SVecSVecMultExpr<T1,T2,TF>( ~lhs, ~rhs );
576 }
577 //*************************************************************************************************
578 
579 } // namespace blaze
580 
581 #endif