All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SMatSMatAddExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_SMATSMATADDEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_SMATSMATADDEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
31 #include <boost/type_traits/remove_reference.hpp>
46 #include <blaze/util/Assert.h>
47 #include <blaze/util/SelectType.h>
48 #include <blaze/util/Types.h>
49 
50 
51 namespace blaze {
52 
53 //=================================================================================================
54 //
55 // CLASS SMATSMATADDEXPR
56 //
57 //=================================================================================================
58 
59 //*************************************************************************************************
66 template< typename MT1 // Type of the left-hand side sparse matrix
67  , typename MT2 > // Type of the right-hand side sparse matrix
68 class SMatSMatAddExpr : public SparseMatrix< SMatSMatAddExpr<MT1,MT2>, false >
69  , private Expression
70  , private Computation
71 {
72  private:
73  //**Type definitions****************************************************************************
74  typedef typename MT1::ResultType RT1;
75  typedef typename MT2::ResultType RT2;
76  typedef typename MT1::CompositeType CT1;
77  typedef typename MT2::CompositeType CT2;
78  typedef typename MT1::ReturnType RN1;
79  typedef typename MT2::ReturnType RN2;
80  //**********************************************************************************************
81 
82  //**Return type evaluation**********************************************************************
84 
89  enum { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
90 
93  //**********************************************************************************************
94 
95  public:
96  //**Type definitions****************************************************************************
99  typedef typename ResultType::OppositeType OppositeType;
100  typedef typename ResultType::TransposeType TransposeType;
101  typedef typename ResultType::ElementType ElementType;
102 
105 
107  typedef const ResultType CompositeType;
108 
110  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
111 
113  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
114  //**********************************************************************************************
115 
116  //**Compilation flags***************************************************************************
120  //**********************************************************************************************
121 
122  //**Constructor*********************************************************************************
128  explicit inline SMatSMatAddExpr( const MT1& lhs, const MT2& rhs )
129  : lhs_( lhs ) // Left-hand side sparse matrix of the addition expression
130  , rhs_( rhs ) // Right-hand side sparse matrix of the addition expression
131  {
132  BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
133  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
134  }
135  //**********************************************************************************************
136 
137  //**Access operator*****************************************************************************
144  inline ReturnType operator()( size_t i, size_t j ) const {
145  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
146  BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
147  return lhs_(i,j) + rhs_(i,j);
148  }
149  //**********************************************************************************************
150 
151  //**Rows function*******************************************************************************
156  inline size_t rows() const {
157  return lhs_.rows();
158  }
159  //**********************************************************************************************
160 
161  //**Columns function****************************************************************************
166  inline size_t columns() const {
167  return lhs_.columns();
168  }
169  //**********************************************************************************************
170 
171  //**NonZeros function***************************************************************************
176  inline size_t nonZeros() const {
177  return lhs_.nonZeros() + rhs_.nonZeros();
178  }
179  //**********************************************************************************************
180 
181  //**NonZeros function***************************************************************************
187  inline size_t nonZeros( size_t i ) const {
188  return lhs_.nonZeros(i) + rhs_.nonZeros(i);
189  }
190  //**********************************************************************************************
191 
192  //**Left operand access*************************************************************************
197  inline LeftOperand leftOperand() const {
198  return lhs_;
199  }
200  //**********************************************************************************************
201 
202  //**Right operand access************************************************************************
207  inline RightOperand rightOperand() const {
208  return rhs_;
209  }
210  //**********************************************************************************************
211 
212  //**********************************************************************************************
218  template< typename T >
219  inline bool isAliased( const T* alias ) const {
221  !RequiresEvaluation<MT1>::value && lhs_.isAliased( alias ) ) ||
223  !RequiresEvaluation<MT2>::value && rhs_.isAliased( alias ) );
224  }
225  //**********************************************************************************************
226 
227  private:
228  //**Member variables****************************************************************************
231  //**********************************************************************************************
232 
233  //**Assignment to dense matrices****************************************************************
245  template< typename MT // Type of the target dense matrix
246  , bool SO > // Storage order of the target dense matrix
247  friend inline void assign( DenseMatrix<MT,SO>& lhs, const SMatSMatAddExpr& rhs )
248  {
249  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
250  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
251 
252  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
253 
254  assign( ~lhs, rhs.lhs_ );
255 
257  addAssign( ~lhs, rhs.rhs_ );
258  }
259  else
260  {
261  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
262 
263  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
264  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
265  BLAZE_INTERNAL_ASSERT( B.rows() == (~lhs).rows() , "Invalid number of rows" );
266  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
267 
268  for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
269  const RightIterator end( B.end(i) );
270  for( RightIterator element=B.begin(i); element!=end; ++element ) {
271  if( isDefault( (~lhs)(i,element->index()) ) )
272  (~lhs)(i,element->index()) = element->value();
273  else
274  (~lhs)(i,element->index()) += element->value();
275  }
276  }
277  }
278  }
280  //**********************************************************************************************
281 
282  //**Assignment to row-major sparse matrices*****************************************************
294  template< typename MT > // Type of the target sparse matrix
295  friend inline void assign( SparseMatrix<MT,false>& lhs, const SMatSMatAddExpr& rhs )
296  {
297  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
298  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
299 
300  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
301  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
302 
303  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
304  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
305 
306  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
307  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
308  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
309  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
310  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
311  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
312 
313  for( size_t i=0UL; i<(~lhs).rows(); ++i )
314  {
315  const LeftIterator lend( A.end(i) );
316  const RightIterator rend( B.end(i) );
317 
318  LeftIterator l( A.begin(i) );
319  RightIterator r( B.begin(i) );
320  size_t nonzeros( A.nonZeros(i) + B.nonZeros(i) );
321 
322  for( ; l!=lend && r!=rend; ++l ) {
323  while( r->index() < l->index() && ++r != rend ) {}
324  if( r!=rend && l->index() == r->index() ) {
325  --nonzeros;
326  ++r;
327  }
328  }
329 
330  BLAZE_INTERNAL_ASSERT( nonzeros <= A.columns(), "Invalid number of non-zero elements predicted" );
331 
332  (~lhs).reserve( i, nonzeros );
333 
334  l = A.begin(i);
335  r = B.begin(i);
336 
337  while( l != lend && r != rend )
338  {
339  if( l->index() < r->index() ) {
340  (~lhs).append( i, l->index(), l->value() );
341  ++l;
342  }
343  else if( l->index() > r->index() ) {
344  (~lhs).append( i, r->index(), r->value() );
345  ++r;
346  }
347  else {
348  (~lhs).append( i, l->index(), l->value()+r->value() );
349  ++l;
350  ++r;
351  }
352  }
353 
354  while( l != lend ) {
355  (~lhs).append( i, l->index(), l->value() );
356  ++l;
357  }
358 
359  while( r != rend ) {
360  (~lhs).append( i, r->index(), r->value() );
361  ++r;
362  }
363  }
364  }
366  //**********************************************************************************************
367 
368  //**Assignment to column-major sparse matrices**************************************************
380  template< typename MT > // Type of the target sparse matrix
381  friend inline void assign( SparseMatrix<MT,true>& lhs, const SMatSMatAddExpr& rhs )
382  {
383  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
384  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
385 
386  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
387  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
388 
389  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
390  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
391 
392  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
393  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
394  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
395  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
396  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
397  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
398 
399  const size_t m( rhs.rows() );
400  const size_t n( rhs.columns() );
401 
402  // Counting the number of elements per column
403  std::vector<size_t> nonzeros( n, 0UL );
404  for( size_t i=0UL; i<m; ++i )
405  {
406  const LeftIterator lend( A.end(i) );
407  const RightIterator rend( B.end(i) );
408 
409  LeftIterator l( A.begin(i) );
410  RightIterator r( B.begin(i) );
411 
412  while( l != lend && r != rend )
413  {
414  if( l->index() < r->index() ) {
415  ++nonzeros[l->index()];
416  ++l;
417  }
418  else if( l->index() > r->index() ) {
419  ++nonzeros[r->index()];
420  ++r;
421  }
422  else {
423  ++nonzeros[l->index()];
424  ++l;
425  ++r;
426  }
427  }
428 
429  while( l != lend ) {
430  ++nonzeros[l->index()];
431  ++l;
432  }
433 
434  while( r != rend ) {
435  ++nonzeros[r->index()];
436  ++r;
437  }
438  }
439 
440  // Resizing the left-hand side sparse matrix
441  for( size_t j=0UL; j<n; ++j ) {
442  (~lhs).reserve( j, nonzeros[j] );
443  }
444 
445  // Performing the matrix addition
446  for( size_t i=0UL; i<m; ++i )
447  {
448  const LeftIterator lend( A.end(i) );
449  const RightIterator rend( B.end(i) );
450 
451  LeftIterator l( A.begin(i) );
452  RightIterator r( B.begin(i) );
453 
454  while( l != lend && r != rend )
455  {
456  if( l->index() < r->index() ) {
457  (~lhs).append( i, l->index(), l->value() );
458  ++l;
459  }
460  else if( l->index() > r->index() ) {
461  (~lhs).append( i, r->index(), r->value() );
462  ++r;
463  }
464  else {
465  (~lhs).append( i, l->index(), l->value()+r->value() );
466  ++l;
467  ++r;
468  }
469  }
470 
471  while( l != lend ) {
472  (~lhs).append( i, l->index(), l->value() );
473  ++l;
474  }
475 
476  while( r != rend ) {
477  (~lhs).append( i, r->index(), r->value() );
478  ++r;
479  }
480  }
481  }
483  //**********************************************************************************************
484 
485  //**Addition assignment to dense matrices*******************************************************
497  template< typename MT // Type of the target dense matrix
498  , bool SO > // Storage order of the target dense matrix
499  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatAddExpr& rhs )
500  {
501  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
502  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
503 
504  addAssign( ~lhs, rhs.lhs_ );
505  addAssign( ~lhs, rhs.rhs_ );
506  }
508  //**********************************************************************************************
509 
510  //**Addition assignment to sparse matrices******************************************************
511  // No special implementation for the addition assignment to sparse matrices.
512  //**********************************************************************************************
513 
514  //**Subtraction assignment to dense matrices****************************************************
526  template< typename MT // Type of the target dense matrix
527  , bool SO > // Storage order of the target dense matrix
528  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatAddExpr& rhs )
529  {
530  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
531  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
532 
533  subAssign( ~lhs, rhs.lhs_ );
534  subAssign( ~lhs, rhs.rhs_ );
535  }
537  //**********************************************************************************************
538 
539  //**Subtraction assignment to sparse matrices***************************************************
540  // No special implementation for the subtraction assignment to sparse matrices.
541  //**********************************************************************************************
542 
543  //**Multiplication assignment to dense matrices*************************************************
544  // No special implementation for the multiplication assignment to dense matrices.
545  //**********************************************************************************************
546 
547  //**Multiplication assignment to sparse matrices************************************************
548  // No special implementation for the multiplication assignment to sparse matrices.
549  //**********************************************************************************************
550 
551  //**Compile time checks*************************************************************************
558  //**********************************************************************************************
559 };
560 //*************************************************************************************************
561 
562 
563 
564 
565 //=================================================================================================
566 //
567 // GLOBAL BINARY ARITHMETIC OPERATORS
568 //
569 //=================================================================================================
570 
571 //*************************************************************************************************
597 template< typename T1 // Type of the left-hand side sparse matrix
598  , typename T2 > // Type of the right-hand side sparse matrix
599 inline const SMatSMatAddExpr<T1,T2>
601 {
602  if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
603  throw std::invalid_argument( "Matrix sizes do not match" );
604 
605  return SMatSMatAddExpr<T1,T2>( ~lhs, ~rhs );
606 }
607 //*************************************************************************************************
608 
609 } // namespace blaze
610 
611 #endif