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>
31 #include <boost/type_traits/remove_reference.hpp>
47 #include <blaze/util/Assert.h>
49 #include <blaze/util/DisableIf.h>
50 #include <blaze/util/EnableIf.h>
51 #include <blaze/util/SelectType.h>
52 #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 Expression
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  //**Compilation flags***************************************************************************
126  //**********************************************************************************************
127 
128  //**Constructor*********************************************************************************
131  explicit inline SVecSVecAddExpr( const VT1& lhs, const VT2& rhs )
132  : lhs_( lhs ) // Left-hand side sparse vector of the addition expression
133  , rhs_( rhs ) // Right-hand side sparse vector of the addition expression
134  {
135  BLAZE_INTERNAL_ASSERT( lhs.size() == rhs.size(), "Invalid vector sizes" );
136  }
137  //**********************************************************************************************
138 
139  //**Subscript operator**************************************************************************
145  inline ReturnType operator[]( size_t index ) const {
146  BLAZE_INTERNAL_ASSERT( index < lhs_.size(), "Invalid vector access index" );
147  return lhs_[index] + rhs_[index];
148  }
149  //**********************************************************************************************
150 
151  //**Size function*******************************************************************************
156  inline size_t size() const {
157  return lhs_.size();
158  }
159  //**********************************************************************************************
160 
161  //**NonZeros function***************************************************************************
166  inline size_t nonZeros() const {
167  return lhs_.nonZeros() + rhs_.nonZeros();
168  }
169  //**********************************************************************************************
170 
171  //**Left operand access*************************************************************************
176  inline LeftOperand leftOperand() const {
177  return lhs_;
178  }
179  //**********************************************************************************************
180 
181  //**Right operand access************************************************************************
186  inline RightOperand rightOperand() const {
187  return rhs_;
188  }
189  //**********************************************************************************************
190 
191  //**********************************************************************************************
197  template< typename T >
198  inline bool isAliased( const T* alias ) const {
200  !RequiresEvaluation<VT1>::value && lhs_.isAliased( alias ) ) ||
202  !RequiresEvaluation<VT2>::value && rhs_.isAliased( alias ) );
203  }
204  //**********************************************************************************************
205 
206  private:
207  //**Member variables****************************************************************************
210  //**********************************************************************************************
211 
212  //**Default assignment to dense vectors*********************************************************
225  template< typename VT > // Type of the target dense vector
226  friend inline typename EnableIf< IsResizable<typename VT::ElementType> >::Type
227  assign( DenseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
228  {
229  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
230 
231  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
232  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
233 
234  CT1 x( rhs.lhs_ ); // Evaluation of the left-hand side sparse vector operand
235  CT2 y( rhs.rhs_ ); // Evaluation of the right-hand side sparse vector operand
236 
237  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
238  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
239  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
240 
241  const LeftIterator lend( x.end() );
242  const RightIterator rend( y.end() );
243 
244  for( LeftIterator l=x.begin(); l<lend; ++l ) {
245  (~lhs)[l->index()] = l->value();
246  }
247 
248  for( RightIterator r=y.begin(); r<rend; ++r ) {
249  if( isDefault( (~lhs)[r->index()] ) )
250  (~lhs)[r->index()] = r->value();
251  else
252  (~lhs)[r->index()] += r->value();
253  }
254  }
256  //**********************************************************************************************
257 
258  //**Optimized assignment to dense vectors*******************************************************
271  template< typename VT > // Type of the target dense vector
272  friend inline typename DisableIf< IsResizable<typename VT::ElementType> >::Type
273  assign( DenseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
274  {
275  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
276 
277  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
278  typedef typename boost::remove_reference<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  for( LeftIterator l=x.begin(); l<lend; ++l ) {
291  (~lhs)[l->index()] = l->value();
292  }
293 
294  for( RightIterator r=y.begin(); r<rend; ++r ) {
295  (~lhs)[r->index()] += r->value();
296  }
297  }
299  //**********************************************************************************************
300 
301  //**Assignment to sparse vectors****************************************************************
313  template< typename VT > // Type of the target sparse vector
314  friend inline void assign( SparseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
315  {
316  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
317 
318  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
319  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
320 
321  CT1 x( rhs.lhs_ ); // Evaluation of the left-hand side sparse vector operand
322  CT2 y( rhs.rhs_ ); // Evaluation of the right-hand side sparse vector operand
323 
324  BLAZE_INTERNAL_ASSERT( x.size() == rhs.lhs_.size(), "Invalid vector size" );
325  BLAZE_INTERNAL_ASSERT( y.size() == rhs.rhs_.size(), "Invalid vector size" );
326  BLAZE_INTERNAL_ASSERT( x.size() == (~lhs).size() , "Invalid vector size" );
327 
328  const LeftIterator lend( x.end() );
329  const RightIterator rend( y.end() );
330 
331  LeftIterator l( x.begin() );
332  RightIterator r( y.begin() );
333 
334  while( l != lend && r != rend )
335  {
336  if( l->index() < r->index() ) {
337  (~lhs).append( l->index(), l->value() );
338  ++l;
339  }
340  else if( l->index() > r->index() ) {
341  (~lhs).append( r->index(), r->value() );
342  ++r;
343  }
344  else {
345  (~lhs).append( l->index(), l->value() + r->value() );
346  ++l;
347  ++r;
348  }
349  }
350 
351  while( l != lend ) {
352  (~lhs).append( l->index(), l->value() );
353  ++l;
354  }
355 
356  while( r != rend ) {
357  (~lhs).append( r->index(), r->value() );
358  ++r;
359  }
360  }
362  //**********************************************************************************************
363 
364  //**Addition assignment to dense vectors********************************************************
376  template< typename VT > // Type of the target dense vector
377  friend inline void addAssign( DenseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
378  {
379  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
380 
381  addAssign( ~lhs, rhs.lhs_ );
382  addAssign( ~lhs, rhs.rhs_ );
383  }
385  //**********************************************************************************************
386 
387  //**Addition assignment to sparse vectors*******************************************************
388  // No special implementation for the addition assignment to sparse vectors.
389  //**********************************************************************************************
390 
391  //**Subtraction assignment to dense vectors*****************************************************
403  template< typename VT > // Type of the target dense vector
404  friend inline void subAssign( DenseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
405  {
406  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
407 
408  subAssign( ~lhs, rhs.lhs_ );
409  subAssign( ~lhs, rhs.rhs_ );
410  }
412  //**********************************************************************************************
413 
414  //**Subtraction assignment to sparse vectors****************************************************
415  // No special implementation for the subtraction assignment to sparse vectors.
416  //**********************************************************************************************
417 
418  //**Multiplication assignment to dense vectors**************************************************
430  template< typename VT > // Type of the target dense vector
431  friend inline void multAssign( DenseVector<VT,TF>& lhs, const SVecSVecAddExpr& rhs )
432  {
435  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename ResultType::CompositeType );
436 
437  BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" );
438 
439  const ResultType tmp( rhs );
440  multAssign( ~lhs, tmp );
441  }
443  //**********************************************************************************************
444 
445  //**Multiplication assignment to sparse vectors*************************************************
446  // No special implementation for the multiplication assignment to sparse vectors.
447  //**********************************************************************************************
448 
449  //**Compile time checks*************************************************************************
456  //**********************************************************************************************
457 };
458 //*************************************************************************************************
459 
460 
461 
462 
463 //=================================================================================================
464 //
465 // GLOBAL BINARY ARITHMETIC OPERATORS
466 //
467 //=================================================================================================
468 
469 //*************************************************************************************************
493 template< typename T1 // Type of the left-hand side sparse vector
494  , typename T2 // Type of the right-hand side sparse vector
495  , bool TF > // Transpose flag
496 inline const SVecSVecAddExpr<T1,T2,TF>
498 {
499  if( (~lhs).size() != (~rhs).size() )
500  throw std::invalid_argument( "Vector sizes do not match" );
501 
502  return SVecSVecAddExpr<T1,T2,TF>( ~lhs, ~rhs );
503 }
504 //*************************************************************************************************
505 
506 } // namespace blaze
507 
508 #endif