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>
47 #include <blaze/util/Assert.h>
49 #include <blaze/util/SelectType.h>
50 #include <blaze/util/Types.h>
52 
53 
54 namespace blaze {
55 
56 //=================================================================================================
57 //
58 // CLASS SMATSMATADDEXPR
59 //
60 //=================================================================================================
61 
62 //*************************************************************************************************
69 template< typename MT1 // Type of the left-hand side sparse matrix
70  , typename MT2 > // Type of the right-hand side sparse matrix
71 class SMatSMatAddExpr : public SparseMatrix< SMatSMatAddExpr<MT1,MT2>, false >
72  , private MatMatAddExpr
73  , private Computation
74 {
75  private:
76  //**Type definitions****************************************************************************
77  typedef typename MT1::ResultType RT1;
78  typedef typename MT2::ResultType RT2;
79  typedef typename MT1::CompositeType CT1;
80  typedef typename MT2::CompositeType CT2;
81  typedef typename MT1::ReturnType RN1;
82  typedef typename MT2::ReturnType RN2;
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::OppositeType OppositeType;
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<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
114 
116  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
117  //**********************************************************************************************
118 
119  //**Constructor*********************************************************************************
125  explicit inline SMatSMatAddExpr( const MT1& lhs, const MT2& rhs )
126  : lhs_( lhs ) // Left-hand side sparse matrix of the addition expression
127  , rhs_( rhs ) // Right-hand side sparse matrix of the addition expression
128  {
129  BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
130  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
131  }
132  //**********************************************************************************************
133 
134  //**Access operator*****************************************************************************
141  inline ReturnType operator()( size_t i, size_t j ) const {
142  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
143  BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
144  return lhs_(i,j) + rhs_(i,j);
145  }
146  //**********************************************************************************************
147 
148  //**Rows function*******************************************************************************
153  inline size_t rows() const {
154  return lhs_.rows();
155  }
156  //**********************************************************************************************
157 
158  //**Columns function****************************************************************************
163  inline size_t columns() const {
164  return lhs_.columns();
165  }
166  //**********************************************************************************************
167 
168  //**NonZeros function***************************************************************************
173  inline size_t nonZeros() const {
174  return lhs_.nonZeros() + rhs_.nonZeros();
175  }
176  //**********************************************************************************************
177 
178  //**NonZeros function***************************************************************************
184  inline size_t nonZeros( size_t i ) const {
185  return lhs_.nonZeros(i) + rhs_.nonZeros(i);
186  }
187  //**********************************************************************************************
188 
189  //**Left operand access*************************************************************************
194  inline LeftOperand leftOperand() const {
195  return lhs_;
196  }
197  //**********************************************************************************************
198 
199  //**Right operand access************************************************************************
204  inline RightOperand rightOperand() const {
205  return rhs_;
206  }
207  //**********************************************************************************************
208 
209  //**********************************************************************************************
215  template< typename T >
216  inline bool canAlias( const T* alias ) const {
217  return ( lhs_.canAlias( alias ) || rhs_.canAlias( alias ) );
218  }
219  //**********************************************************************************************
220 
221  //**********************************************************************************************
227  template< typename T >
228  inline bool isAliased( const T* alias ) const {
229  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
230  }
231  //**********************************************************************************************
232 
233  private:
234  //**Member variables****************************************************************************
237  //**********************************************************************************************
238 
239  //**Assignment to dense matrices****************************************************************
251  template< typename MT // Type of the target dense matrix
252  , bool SO > // Storage order of the target dense matrix
253  friend inline void assign( DenseMatrix<MT,SO>& lhs, const SMatSMatAddExpr& rhs )
254  {
256 
257  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
258  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
259 
260  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
261 
262  assign( ~lhs, rhs.lhs_ );
263 
265  addAssign( ~lhs, rhs.rhs_ );
266  }
267  else
268  {
269  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
270 
271  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
272  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
273  BLAZE_INTERNAL_ASSERT( B.rows() == (~lhs).rows() , "Invalid number of rows" );
274  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
275 
276  for( size_t i=0UL; i<(~lhs).rows(); ++i ) {
277  const RightIterator end( B.end(i) );
278  for( RightIterator element=B.begin(i); element!=end; ++element ) {
279  if( isDefault( (~lhs)(i,element->index()) ) )
280  (~lhs)(i,element->index()) = element->value();
281  else
282  (~lhs)(i,element->index()) += element->value();
283  }
284  }
285  }
286  }
288  //**********************************************************************************************
289 
290  //**Assignment to row-major sparse matrices*****************************************************
302  template< typename MT > // Type of the target sparse matrix
303  friend inline void assign( SparseMatrix<MT,false>& lhs, const SMatSMatAddExpr& rhs )
304  {
306 
307  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
308  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
309 
310  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
311  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
312 
313  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
314  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
315 
316  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
317  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
318  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
319  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
320  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
321  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
322 
323  for( size_t i=0UL; i<(~lhs).rows(); ++i )
324  {
325  const LeftIterator lend( A.end(i) );
326  const RightIterator rend( B.end(i) );
327 
328  LeftIterator l( A.begin(i) );
329  RightIterator r( B.begin(i) );
330  size_t nonzeros( A.nonZeros(i) + B.nonZeros(i) );
331 
332  for( ; l!=lend && r!=rend; ++l ) {
333  while( r->index() < l->index() && ++r != rend ) {}
334  if( r!=rend && l->index() == r->index() ) {
335  --nonzeros;
336  ++r;
337  }
338  }
339 
340  BLAZE_INTERNAL_ASSERT( nonzeros <= A.columns(), "Invalid number of non-zero elements predicted" );
341 
342  (~lhs).reserve( i, nonzeros );
343 
344  l = A.begin(i);
345  r = B.begin(i);
346 
347  while( l != lend && r != rend )
348  {
349  if( l->index() < r->index() ) {
350  (~lhs).append( i, l->index(), l->value() );
351  ++l;
352  }
353  else if( l->index() > r->index() ) {
354  (~lhs).append( i, r->index(), r->value() );
355  ++r;
356  }
357  else {
358  (~lhs).append( i, l->index(), l->value()+r->value() );
359  ++l;
360  ++r;
361  }
362  }
363 
364  while( l != lend ) {
365  (~lhs).append( i, l->index(), l->value() );
366  ++l;
367  }
368 
369  while( r != rend ) {
370  (~lhs).append( i, r->index(), r->value() );
371  ++r;
372  }
373  }
374  }
376  //**********************************************************************************************
377 
378  //**Assignment to column-major sparse matrices**************************************************
390  template< typename MT > // Type of the target sparse matrix
391  friend inline void assign( SparseMatrix<MT,true>& lhs, const SMatSMatAddExpr& rhs )
392  {
394 
395  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
396  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
397 
398  typedef typename RemoveReference<CT1>::Type::ConstIterator LeftIterator;
399  typedef typename RemoveReference<CT2>::Type::ConstIterator RightIterator;
400 
401  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
402  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
403 
404  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
405  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
406  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
407  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
408  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
409  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
410 
411  const size_t m( rhs.rows() );
412  const size_t n( rhs.columns() );
413 
414  // Counting the number of elements per column
415  std::vector<size_t> nonzeros( n, 0UL );
416  for( size_t i=0UL; i<m; ++i )
417  {
418  const LeftIterator lend( A.end(i) );
419  const RightIterator rend( B.end(i) );
420 
421  LeftIterator l( A.begin(i) );
422  RightIterator r( B.begin(i) );
423 
424  while( l != lend && r != rend )
425  {
426  if( l->index() < r->index() ) {
427  ++nonzeros[l->index()];
428  ++l;
429  }
430  else if( l->index() > r->index() ) {
431  ++nonzeros[r->index()];
432  ++r;
433  }
434  else {
435  ++nonzeros[l->index()];
436  ++l;
437  ++r;
438  }
439  }
440 
441  while( l != lend ) {
442  ++nonzeros[l->index()];
443  ++l;
444  }
445 
446  while( r != rend ) {
447  ++nonzeros[r->index()];
448  ++r;
449  }
450  }
451 
452  // Resizing the left-hand side sparse matrix
453  for( size_t j=0UL; j<n; ++j ) {
454  (~lhs).reserve( j, nonzeros[j] );
455  }
456 
457  // Performing the matrix addition
458  for( size_t i=0UL; i<m; ++i )
459  {
460  const LeftIterator lend( A.end(i) );
461  const RightIterator rend( B.end(i) );
462 
463  LeftIterator l( A.begin(i) );
464  RightIterator r( B.begin(i) );
465 
466  while( l != lend && r != rend )
467  {
468  if( l->index() < r->index() ) {
469  (~lhs).append( i, l->index(), l->value() );
470  ++l;
471  }
472  else if( l->index() > r->index() ) {
473  (~lhs).append( i, r->index(), r->value() );
474  ++r;
475  }
476  else {
477  (~lhs).append( i, l->index(), l->value()+r->value() );
478  ++l;
479  ++r;
480  }
481  }
482 
483  while( l != lend ) {
484  (~lhs).append( i, l->index(), l->value() );
485  ++l;
486  }
487 
488  while( r != rend ) {
489  (~lhs).append( i, r->index(), r->value() );
490  ++r;
491  }
492  }
493  }
495  //**********************************************************************************************
496 
497  //**Addition assignment to dense matrices*******************************************************
509  template< typename MT // Type of the target dense matrix
510  , bool SO > // Storage order of the target dense matrix
511  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatAddExpr& rhs )
512  {
514 
515  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
516  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
517 
518  addAssign( ~lhs, rhs.lhs_ );
519  addAssign( ~lhs, rhs.rhs_ );
520  }
522  //**********************************************************************************************
523 
524  //**Addition assignment to sparse matrices******************************************************
525  // No special implementation for the addition assignment to sparse matrices.
526  //**********************************************************************************************
527 
528  //**Subtraction assignment to dense matrices****************************************************
540  template< typename MT // Type of the target dense matrix
541  , bool SO > // Storage order of the target dense matrix
542  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const SMatSMatAddExpr& rhs )
543  {
545 
546  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
547  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
548 
549  subAssign( ~lhs, rhs.lhs_ );
550  subAssign( ~lhs, rhs.rhs_ );
551  }
553  //**********************************************************************************************
554 
555  //**Subtraction assignment to sparse matrices***************************************************
556  // No special implementation for the subtraction assignment to sparse matrices.
557  //**********************************************************************************************
558 
559  //**Multiplication assignment to dense matrices*************************************************
560  // No special implementation for the multiplication assignment to dense matrices.
561  //**********************************************************************************************
562 
563  //**Multiplication assignment to sparse matrices************************************************
564  // No special implementation for the multiplication assignment to sparse matrices.
565  //**********************************************************************************************
566 
567  //**Compile time checks*************************************************************************
574  //**********************************************************************************************
575 };
576 //*************************************************************************************************
577 
578 
579 
580 
581 //=================================================================================================
582 //
583 // GLOBAL BINARY ARITHMETIC OPERATORS
584 //
585 //=================================================================================================
586 
587 //*************************************************************************************************
613 template< typename T1 // Type of the left-hand side sparse matrix
614  , typename T2 > // Type of the right-hand side sparse matrix
615 inline const SMatSMatAddExpr<T1,T2>
617 {
619 
620  if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
621  throw std::invalid_argument( "Matrix sizes do not match" );
622 
623  return SMatSMatAddExpr<T1,T2>( ~lhs, ~rhs );
624 }
625 //*************************************************************************************************
626 
627 
628 
629 
630 //=================================================================================================
631 //
632 // EXPRESSION TRAIT SPECIALIZATIONS
633 //
634 //=================================================================================================
635 
636 //*************************************************************************************************
638 template< typename MT1, typename MT2 >
639 struct RowExprTrait< SMatSMatAddExpr<MT1,MT2> >
640 {
641  public:
642  //**********************************************************************************************
643  typedef typename AddExprTrait< typename RowExprTrait<const MT1>::Type
644  , typename RowExprTrait<const MT2>::Type >::Type Type;
645  //**********************************************************************************************
646 };
648 //*************************************************************************************************
649 
650 
651 //*************************************************************************************************
653 template< typename MT1, typename MT2 >
654 struct ColumnExprTrait< SMatSMatAddExpr<MT1,MT2> >
655 {
656  public:
657  //**********************************************************************************************
658  typedef typename AddExprTrait< typename ColumnExprTrait<const MT1>::Type
659  , typename ColumnExprTrait<const MT2>::Type >::Type Type;
660  //**********************************************************************************************
661 };
663 //*************************************************************************************************
664 
665 } // namespace blaze
666 
667 #endif