All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SMatTSMatAddExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_SMATTSMATADDEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_SMATTSMATADDEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
31 #include <boost/type_traits/remove_reference.hpp>
48 #include <blaze/util/Assert.h>
50 #include <blaze/util/SelectType.h>
51 #include <blaze/util/Types.h>
52 
53 
54 namespace blaze {
55 
56 //=================================================================================================
57 //
58 // CLASS SMATTSMATADDEXPR
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 SMatTSMatAddExpr : public SparseMatrix< SMatTSMatAddExpr<MT1,MT2>, false >
72  , private Expression
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::ReturnType RN1;
80  typedef typename MT2::ReturnType RN2;
81  typedef typename MT1::CompositeType CT1;
82  typedef typename MT2::CompositeType CT2;
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 SMatTSMatAddExpr( 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 SMatTSMatAddExpr& 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 boost::remove_reference<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 j=0UL; j<(~lhs).columns(); ++j ) {
277  const RightIterator end( B.end(j) );
278  for( RightIterator element=B.begin(j); element!=end; ++element ) {
279  if( isDefault( (~lhs)(element->index(),j) ) )
280  (~lhs)(element->index(),j) = element->value();
281  else
282  (~lhs)(element->index(),j) += element->value();
283  }
284  }
285  }
286  }
288  //**********************************************************************************************
289 
290  //**Assignment to sparse matrices***************************************************************
302  template< typename MT > // Type of the target sparse matrix
303  friend inline void assign( SparseMatrix<MT,false>& lhs, const SMatTSMatAddExpr& 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 boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
311  typedef typename RT2::OppositeType::ConstIterator RightIterator;
312 
313  // Evaluation of the left-hand side sparse matrix operand
314  CT1 A( rhs.lhs_ );
315 
316  // Evaluation of the right-hand side sparse matrix operand
317  const typename RT2::OppositeType B( rhs.rhs_ );
318 
319  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
320  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
321  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
322  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
323  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
324  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
325 
326  for( size_t i=0UL; i<(~lhs).rows(); ++i )
327  {
328  const LeftIterator lend( A.end(i) );
329  const RightIterator rend( B.end(i) );
330 
331  LeftIterator l( A.begin(i) );
332  RightIterator r( B.begin(i) );
333  size_t nonzeros( A.nonZeros(i) + B.nonZeros(i) );
334 
335  for( ; l!=lend && r!=rend; ++l ) {
336  while( r->index() < l->index() && ++r != rend ) {}
337  if( r!=rend && l->index() == r->index() ) {
338  --nonzeros;
339  ++r;
340  }
341  }
342 
343  BLAZE_INTERNAL_ASSERT( nonzeros <= A.columns(), "Invalid number of non-zero elements predicted" );
344 
345  (~lhs).reserve( i, nonzeros );
346 
347  l = A.begin(i);
348  r = B.begin(i);
349 
350  while( l != lend && r != rend )
351  {
352  if( l->index() < r->index() ) {
353  (~lhs).append( i, l->index(), l->value() );
354  ++l;
355  }
356  else if( l->index() > r->index() ) {
357  (~lhs).append( i, r->index(), r->value() );
358  ++r;
359  }
360  else {
361  (~lhs).append( i, l->index(), l->value()+r->value() );
362  ++l;
363  ++r;
364  }
365  }
366 
367  while( l != lend ) {
368  (~lhs).append( i, l->index(), l->value() );
369  ++l;
370  }
371 
372  while( r != rend ) {
373  (~lhs).append( i, r->index(), r->value() );
374  ++r;
375  }
376  }
377  }
379  //**********************************************************************************************
380 
381  //**Assignment to sparse matrices***************************************************************
393  template< typename MT > // Type of the target sparse matrix
394  friend inline void assign( SparseMatrix<MT,true>& lhs, const SMatTSMatAddExpr& rhs )
395  {
397 
398  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
399  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
400 
401  typedef typename RT1::OppositeType::ConstIterator LeftIterator;
402  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
403 
404  // Evaluation of the left-hand side sparse matrix operand
405  const typename RT1::OppositeType A( rhs.lhs_ );
406 
407  // Evaluation of the right-hand side sparse matrix operand
408  CT2 B( rhs.rhs_ );
409 
410  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
411  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
412  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
413  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
414  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
415  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
416 
417  for( size_t j=0UL; j<(~lhs).columns(); ++j )
418  {
419  const LeftIterator lend( A.end(j) );
420  const RightIterator rend( B.end(j) );
421 
422  LeftIterator l( A.begin(j) );
423  RightIterator r( B.begin(j) );
424  size_t nonzeros( A.nonZeros(j) + B.nonZeros(j) );
425 
426  for( ; l!=lend && r!=rend; ++l ) {
427  while( r->index() < l->index() && ++r != rend ) {}
428  if( r!=rend && l->index() == r->index() ) {
429  --nonzeros;
430  ++r;
431  }
432  }
433 
434  BLAZE_INTERNAL_ASSERT( nonzeros <= A.rows(), "Invalid number of non-zero elements predicted" );
435 
436  (~lhs).reserve( j, nonzeros );
437 
438  l = A.begin(j);
439  r = B.begin(j);
440 
441  while( l != lend && r != rend )
442  {
443  if( l->index() < r->index() ) {
444  (~lhs).append( l->index(), j, l->value() );
445  ++l;
446  }
447  else if( l->index() > r->index() ) {
448  (~lhs).append( r->index(), j, r->value() );
449  ++r;
450  }
451  else {
452  (~lhs).append( l->index(), j, l->value()+r->value() );
453  ++l;
454  ++r;
455  }
456  }
457 
458  while( l != lend ) {
459  (~lhs).append( l->index(), j, l->value() );
460  ++l;
461  }
462 
463  while( r != rend ) {
464  (~lhs).append( r->index(), j, r->value() );
465  ++r;
466  }
467  }
468  }
470  //**********************************************************************************************
471 
472  //**Addition assignment to dense matrices*******************************************************
485  template< typename MT // Type of the target dense matrix
486  , bool SO > // Storage order of the target dense matrix
487  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const SMatTSMatAddExpr& rhs )
488  {
490 
491  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
492  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
493 
494  addAssign( ~lhs, rhs.lhs_ );
495  addAssign( ~lhs, rhs.rhs_ );
496  }
498  //**********************************************************************************************
499 
500  //**Addition assignment to sparse matrices******************************************************
501  // No special implementation for the addition assignment to sparse matrices.
502  //**********************************************************************************************
503 
504  //**Subtraction assignment to dense matrices****************************************************
517  template< typename MT // Type of the target dense matrix
518  , bool SO > // Storage order of the target dense matrix
519  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const SMatTSMatAddExpr& rhs )
520  {
522 
523  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
524  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
525 
526  subAssign( ~lhs, rhs.lhs_ );
527  subAssign( ~lhs, rhs.rhs_ );
528  }
530  //**********************************************************************************************
531 
532  //**Subtraction assignment to sparse matrices***************************************************
533  // No special implementation for the subtraction assignment to sparse matrices.
534  //**********************************************************************************************
535 
536  //**Multiplication assignment to dense matrices*************************************************
537  // No special implementation for the multiplication assignment to dense matrices.
538  //**********************************************************************************************
539 
540  //**Multiplication assignment to sparse matrices************************************************
541  // No special implementation for the multiplication assignment to sparse matrices.
542  //**********************************************************************************************
543 
544  //**Compile time checks*************************************************************************
551  //**********************************************************************************************
552 };
553 //*************************************************************************************************
554 
555 
556 
557 
558 //=================================================================================================
559 //
560 // GLOBAL BINARY ARITHMETIC OPERATORS
561 //
562 //=================================================================================================
563 
564 //*************************************************************************************************
593 template< typename T1 // Type of the left-hand side sparse matrix
594  , typename T2 > // Type of the right-hand side sparse matrix
595 inline const SMatTSMatAddExpr<T1,T2>
597 {
599 
600  if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
601  throw std::invalid_argument( "Matrix sizes do not match" );
602 
603  return SMatTSMatAddExpr<T1,T2>( ~lhs, ~rhs );
604 }
605 //*************************************************************************************************
606 
607 
608 //*************************************************************************************************
637 template< typename T1 // Type of the left-hand side sparse matrix
638  , typename T2 > // Type of the right-hand side sparse matrix
639 inline const SMatTSMatAddExpr<T2,T1>
641 {
643 
644  if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
645  throw std::invalid_argument( "Matrix sizes do not match" );
646 
647  return SMatTSMatAddExpr<T2,T1>( ~rhs, ~lhs );
648 }
649 //*************************************************************************************************
650 
651 
652 
653 
654 //=================================================================================================
655 //
656 // GLOBAL OPERATORS
657 //
658 //=================================================================================================
659 
660 //*************************************************************************************************
673 template< typename T1 // Type of the left-hand side sparse matrix
674  , typename T2 > // Type of the right-hand side sparse matrix
675 inline typename RowExprTrait< SMatTSMatAddExpr<T1,T2> >::Type
676  row( const SMatTSMatAddExpr<T1,T2>& sm, size_t index )
677 {
679 
680  return row( sm.leftOperand(), index ) + row( sm.rightOperand(), index );
681 }
683 //*************************************************************************************************
684 
685 
686 //*************************************************************************************************
699 template< typename T1 // Type of the left-hand side sparse matrix
700  , typename T2 > // Type of the right-hand side sparse matrix
701 inline typename ColumnExprTrait< SMatTSMatAddExpr<T1,T2> >::Type
702  column( const SMatTSMatAddExpr<T1,T2>& sm, size_t index )
703 {
705 
706  return column( sm.leftOperand(), index ) + column( sm.rightOperand(), index );
707 }
709 //*************************************************************************************************
710 
711 
712 
713 
714 //=================================================================================================
715 //
716 // EXPRESSION TRAIT SPECIALIZATIONS
717 //
718 //=================================================================================================
719 
720 //*************************************************************************************************
722 template< typename MT1, typename MT2 >
723 struct RowExprTrait< SMatTSMatAddExpr<MT1,MT2> >
724 {
725  public:
726  //**********************************************************************************************
727  typedef typename AddExprTrait< typename RowExprTrait<const MT1>::Type
728  , typename RowExprTrait<const MT2>::Type >::Type Type;
729  //**********************************************************************************************
730 };
732 //*************************************************************************************************
733 
734 
735 //*************************************************************************************************
737 template< typename MT1, typename MT2 >
738 struct ColumnExprTrait< SMatTSMatAddExpr<MT1,MT2> >
739 {
740  public:
741  //**********************************************************************************************
742  typedef typename AddExprTrait< typename ColumnExprTrait<const MT1>::Type
743  , typename ColumnExprTrait<const MT2>::Type >::Type Type;
744  //**********************************************************************************************
745 };
747 //*************************************************************************************************
748 
749 } // namespace blaze
750 
751 #endif