All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SVecSVecAddExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_SVECSVECADDEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_SVECSVECADDEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
37 #include <blaze/math/Functions.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 SVECSVECADDEXPR
60 //
61 //=================================================================================================
62 
63 //*************************************************************************************************
70 template< typename VT1 // Type of the left-hand side sparse vector
71  , typename VT2 // Type of the right-hand side sparse vector
72  , bool TF > // Transpose flag
73 class SVecSVecAddExpr : public SparseVector< SVecSVecAddExpr<VT1,VT2,TF>, TF >
74  , private VecVecAddExpr
75  , private Computation
76 {
77  private:
78  //**Type definitions****************************************************************************
79  typedef typename VT1::ResultType RT1;
80  typedef typename VT2::ResultType RT2;
81  typedef typename VT1::ReturnType RN1;
82  typedef typename VT2::ReturnType RN2;
83  typedef typename VT1::CompositeType CT1;
84  typedef typename VT2::CompositeType CT2;
85  typedef typename VT1::TransposeType TT1;
86  typedef typename VT2::TransposeType TT2;
87  //**********************************************************************************************
88 
89  //**Return type evaluation**********************************************************************
91 
96  enum { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
97 
100  //**********************************************************************************************
101 
102  public:
103  //**Type definitions****************************************************************************
106  typedef typename ResultType::TransposeType TransposeType;
107  typedef typename ResultType::ElementType ElementType;
108 
111 
113  typedef const ResultType CompositeType;
114 
116  typedef typename SelectType< IsExpression<VT1>::value, const VT1, const VT1& >::Type LeftOperand;
117 
119  typedef typename SelectType< IsExpression<VT2>::value, const VT2, const VT2& >::Type RightOperand;
120  //**********************************************************************************************
121 
122  //**Constructor*********************************************************************************
125  explicit inline SVecSVecAddExpr( const VT1& lhs, const VT2& rhs )
126  : lhs_( lhs ) // Left-hand side sparse vector of the addition expression
127  , rhs_( rhs ) // Right-hand side sparse vector of the addition expression
128  {
129  BLAZE_INTERNAL_ASSERT( lhs.size() == rhs.size(), "Invalid vector sizes" );
130  }
131  //**********************************************************************************************
132 
133  //**Subscript operator**************************************************************************
139  inline ReturnType operator[]( size_t index ) const {
140  BLAZE_INTERNAL_ASSERT( index < lhs_.size(), "Invalid vector access index" );
141  return lhs_[index] + rhs_[index];
142  }
143  //**********************************************************************************************
144 
145  //**Size function*******************************************************************************
150  inline size_t size() const {
151  return lhs_.size();
152  }
153  //**********************************************************************************************
154 
155  //**NonZeros function***************************************************************************
160  inline size_t nonZeros() const {
161  return min( lhs_.size(), lhs_.nonZeros() + rhs_.nonZeros() );
162  }
163  //**********************************************************************************************
164 
165  //**Left operand access*************************************************************************
170  inline LeftOperand leftOperand() const {
171  return lhs_;
172  }
173  //**********************************************************************************************
174 
175  //**Right operand access************************************************************************
180  inline RightOperand rightOperand() const {
181  return rhs_;
182  }
183  //**********************************************************************************************
184 
185  //**********************************************************************************************
191  template< typename T >
192  inline bool canAlias( const T* alias ) const {
193  return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
194  }
195  //**********************************************************************************************
196 
197  //**********************************************************************************************
203  template< typename T >
204  inline bool isAliased( const T* alias ) const {
205  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
206  }
207  //**********************************************************************************************
208 
209  private:
210  //**Member variables****************************************************************************
213  //**********************************************************************************************
214 
215  //**Default assignment to dense vectors*********************************************************
228  template< typename VT > // Type of the target dense vector
229  friend inline typename EnableIf< IsResizable<typename VT::ElementType> >::Type
230  assign( DenseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
231  {
233 
234  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
235 
236  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
237  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
238 
239  CT1 x( rhs.lhs_ ); // Evaluation of the left-hand side sparse vector operand
240  CT2 y( rhs.rhs_ ); // Evaluation of the right-hand side sparse vector operand
241 
242  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
243  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
244  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
245 
246  const LeftIterator lend( x.end() );
247  const RightIterator rend( y.end() );
248 
249  for( LeftIterator l=x.begin(); l<lend; ++l ) {
250  (~lhs)[l->index()] = l->value();
251  }
252 
253  for( RightIterator r=y.begin(); r<rend; ++r ) {
254  if( isDefault( (~lhs)[r->index()] ) )
255  (~lhs)[r->index()] = r->value();
256  else
257  (~lhs)[r->index()] += r->value();
258  }
259  }
261  //**********************************************************************************************
262 
263  //**Optimized assignment to dense vectors*******************************************************
276  template< typename VT > // Type of the target dense vector
277  friend inline typename DisableIf< IsResizable<typename VT::ElementType> >::Type
278  assign( DenseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
279  {
281 
282  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
283 
284  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
285  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
286 
287  CT1 x( rhs.lhs_ ); // Evaluation of the left-hand side sparse vector operand
288  CT2 y( rhs.rhs_ ); // Evaluation of the right-hand side sparse vector operand
289 
290  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
291  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
292  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
293 
294  const LeftIterator lend( x.end() );
295  const RightIterator rend( y.end() );
296 
297  for( LeftIterator l=x.begin(); l<lend; ++l ) {
298  (~lhs)[l->index()] = l->value();
299  }
300 
301  for( RightIterator r=y.begin(); r<rend; ++r ) {
302  (~lhs)[r->index()] += r->value();
303  }
304  }
306  //**********************************************************************************************
307 
308  //**Assignment to sparse vectors****************************************************************
320  template< typename VT > // Type of the target sparse vector
321  friend inline void assign( SparseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
322  {
324 
325  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
326 
327  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
328  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
329 
330  CT1 x( rhs.lhs_ ); // Evaluation of the left-hand side sparse vector operand
331  CT2 y( rhs.rhs_ ); // Evaluation of the right-hand side sparse vector operand
332 
333  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
334  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
335  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
336 
337  const LeftIterator lend( x.end() );
338  const RightIterator rend( y.end() );
339 
340  LeftIterator l( x.begin() );
341  RightIterator r( y.begin() );
342 
343  while( l != lend && r != rend )
344  {
345  if( l->index() < r->index() ) {
346  (~lhs).append( l->index(), l->value() );
347  ++l;
348  }
349  else if( l->index() > r->index() ) {
350  (~lhs).append( r->index(), r->value() );
351  ++r;
352  }
353  else {
354  (~lhs).append( l->index(), l->value() + r->value() );
355  ++l;
356  ++r;
357  }
358  }
359 
360  while( l != lend ) {
361  (~lhs).append( l->index(), l->value() );
362  ++l;
363  }
364 
365  while( r != rend ) {
366  (~lhs).append( r->index(), r->value() );
367  ++r;
368  }
369  }
371  //**********************************************************************************************
372 
373  //**Addition assignment to dense vectors********************************************************
385  template< typename VT > // Type of the target dense vector
386  friend inline void addAssign( DenseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
387  {
389 
390  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
391 
392  addAssign( ~lhs, rhs.lhs_ );
393  addAssign( ~lhs, rhs.rhs_ );
394  }
396  //**********************************************************************************************
397 
398  //**Addition assignment to sparse vectors*******************************************************
399  // No special implementation for the addition assignment to sparse vectors.
400  //**********************************************************************************************
401 
402  //**Subtraction assignment to dense vectors*****************************************************
414  template< typename VT > // Type of the target dense vector
415  friend inline void subAssign( DenseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
416  {
418 
419  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
420 
421  subAssign( ~lhs, rhs.lhs_ );
422  subAssign( ~lhs, rhs.rhs_ );
423  }
425  //**********************************************************************************************
426 
427  //**Subtraction assignment to sparse vectors****************************************************
428  // No special implementation for the subtraction assignment to sparse vectors.
429  //**********************************************************************************************
430 
431  //**Multiplication assignment to dense vectors**************************************************
443  template< typename VT > // Type of the target dense vector
444  friend inline void multAssign( DenseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
445  {
447 
450  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
451 
452  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
453 
454  const ResultType tmp( rhs );
455  multAssign( ~lhs, tmp );
456  }
458  //**********************************************************************************************
459 
460  //**Multiplication assignment to sparse vectors*************************************************
461  // No special implementation for the multiplication assignment to sparse vectors.
462  //**********************************************************************************************
463 
464  //**Compile time checks*************************************************************************
471  //**********************************************************************************************
472 };
473 //*************************************************************************************************
474 
475 
476 
477 
478 //=================================================================================================
479 //
480 // GLOBAL BINARY ARITHMETIC OPERATORS
481 //
482 //=================================================================================================
483 
484 //*************************************************************************************************
508 template< typename T1 // Type of the left-hand side sparse vector
509  , typename T2 // Type of the right-hand side sparse vector
510  , bool TF > // Transpose flag
511 inline const SVecSVecAddExpr<T1,T2,TF>
513 {
515 
516  if( (~lhs).size() != (~rhs).size() )
517  throw std::invalid_argument( "Vector sizes do not match" );
518 
519  return SVecSVecAddExpr<T1,T2,TF>( ~lhs, ~rhs );
520 }
521 //*************************************************************************************************
522 
523 } // namespace blaze
524 
525 #endif