All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TSMatSMatSubExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TSMATSMATSUBEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TSMATSMATSUBEXPR_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 TSMATSMATSUBEXPR
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 TSMatSMatSubExpr : public SparseMatrix< TSMatSMatSubExpr<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 TSMatSMatSubExpr( const MT1& lhs, const MT2& rhs )
126  : lhs_( lhs ) // Left-hand side sparse matrix of the subtraction expression
127  , rhs_( rhs ) // Right-hand side sparse matrix of the subtraction 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 TSMatSMatSubExpr& 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  subAssign( ~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*****************************************************
303  template< typename MT > // Type of the target sparse matrix
304  friend inline void assign( SparseMatrix<MT,false>& lhs, const TSMatSMatSubExpr& rhs )
305  {
307 
308  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
309  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
310 
311  typedef typename RT1::OppositeType::ConstIterator LeftIterator;
312  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
313 
314  // Evaluation of the left-hand side sparse matrix operand
315  const typename RT1::OppositeType A( rhs.lhs_ );
316 
317  // Evaluation of the right-hand side sparse matrix operand
318  CT2 B( rhs.rhs_ );
319 
320  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
321  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
322  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
323  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
324  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
325  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
326 
327  for( size_t i=0UL; i<(~lhs).rows(); ++i )
328  {
329  const LeftIterator lend( A.end(i) );
330  const RightIterator rend( B.end(i) );
331 
332  LeftIterator l( A.begin(i) );
333  RightIterator r( B.begin(i) );
334  size_t nonzeros( A.nonZeros(i) + B.nonZeros(i) );
335 
336  for( ; l!=lend && r!=rend; ++l ) {
337  while( r->index() < l->index() && ++r != rend ) {}
338  if( r!=rend && l->index() == r->index() ) {
339  --nonzeros;
340  ++r;
341  }
342  }
343 
344  BLAZE_INTERNAL_ASSERT( nonzeros <= A.columns(), "Invalid number of non-zero elements predicted" );
345 
346  (~lhs).reserve( i, nonzeros );
347 
348  l = A.begin(i);
349  r = B.begin(i);
350 
351  while( l != lend && r != rend )
352  {
353  if( l->index() < r->index() ) {
354  (~lhs).append( i, l->index(), l->value() );
355  ++l;
356  }
357  else if( l->index() > r->index() ) {
358  (~lhs).append( i, r->index(), -r->value() );
359  ++r;
360  }
361  else {
362  (~lhs).append( i, l->index(), l->value()-r->value() );
363  ++l;
364  ++r;
365  }
366  }
367 
368  while( l != lend ) {
369  (~lhs).append( i, l->index(), l->value() );
370  ++l;
371  }
372 
373  while( r != rend ) {
374  (~lhs).append( i, r->index(), -r->value() );
375  ++r;
376  }
377  }
378  }
380  //**********************************************************************************************
381 
382  //**Assignment to column-major sparse matrices**************************************************
395  template< typename MT > // Type of the target sparse matrix
396  friend inline void assign( SparseMatrix<MT,true>& lhs, const TSMatSMatSubExpr& rhs )
397  {
399 
400  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
401  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
402 
403  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
404  typedef typename RT2::OppositeType::ConstIterator RightIterator;
405 
406  // Evaluation of the left-hand side sparse matrix operand
407  CT1 A( rhs.lhs_ );
408 
409  // Evaluation of the right-hand side sparse matrix operand
410  const typename RT2::OppositeType B( rhs.rhs_ );
411 
412  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
413  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
414  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
415  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
416  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
417  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
418 
419  for( size_t j=0UL; j<(~lhs).columns(); ++j )
420  {
421  const LeftIterator lend( A.end(j) );
422  const RightIterator rend( B.end(j) );
423 
424  LeftIterator l( A.begin(j) );
425  RightIterator r( B.begin(j) );
426  size_t nonzeros( A.nonZeros(j) + B.nonZeros(j) );
427 
428  for( ; l!=lend && r!=rend; ++l ) {
429  while( r->index() < l->index() && ++r != rend ) {}
430  if( r!=rend && l->index() == r->index() ) {
431  --nonzeros;
432  ++r;
433  }
434  }
435 
436  BLAZE_INTERNAL_ASSERT( nonzeros <= A.rows(), "Invalid number of non-zero elements predicted" );
437 
438  (~lhs).reserve( j, nonzeros );
439 
440  l = A.begin(j);
441  r = B.begin(j);
442 
443  while( l != lend && r != rend )
444  {
445  if( l->index() < r->index() ) {
446  (~lhs).append( l->index(), j, l->value() );
447  ++l;
448  }
449  else if( l->index() > r->index() ) {
450  (~lhs).append( r->index(), j, -r->value() );
451  ++r;
452  }
453  else {
454  (~lhs).append( l->index(), j, l->value()-r->value() );
455  ++l;
456  ++r;
457  }
458  }
459 
460  while( l != lend ) {
461  (~lhs).append( l->index(), j, l->value() );
462  ++l;
463  }
464 
465  while( r != rend ) {
466  (~lhs).append( r->index(), j, -r->value() );
467  ++r;
468  }
469  }
470  }
472  //**********************************************************************************************
473 
474  //**Addition assignment to dense matrices*******************************************************
487  template< typename MT // Type of the target dense matrix
488  , bool SO > // Storage order of the target dense matrix
489  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const TSMatSMatSubExpr& rhs )
490  {
492 
493  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
494  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
495 
496  addAssign( ~lhs, rhs.lhs_ );
497  subAssign( ~lhs, rhs.rhs_ );
498  }
500  //**********************************************************************************************
501 
502  //**Addition assignment to sparse matrices******************************************************
503  // No special implementation for the addition assignment to sparse matrices.
504  //**********************************************************************************************
505 
506  //**Subtraction assignment to dense matrices****************************************************
519  template< typename MT // Type of the target dense matrix
520  , bool SO > // Storage order of the target dense matrix
521  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TSMatSMatSubExpr& rhs )
522  {
524 
525  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
526  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
527 
528  subAssign( ~lhs, rhs.lhs_ );
529  addAssign( ~lhs, rhs.rhs_ );
530  }
532  //**********************************************************************************************
533 
534  //**Subtraction assignment to sparse matrices***************************************************
535  // No special implementation for the subtraction assignment to sparse matrices.
536  //**********************************************************************************************
537 
538  //**Multiplication assignment to dense matrices*************************************************
539  // No special implementation for the multiplication assignment to dense matrices.
540  //**********************************************************************************************
541 
542  //**Multiplication assignment to sparse matrices************************************************
543  // No special implementation for the multiplication assignment to sparse matrices.
544  //**********************************************************************************************
545 
546  //**Compile time checks*************************************************************************
553  //**********************************************************************************************
554 };
555 //*************************************************************************************************
556 
557 
558 
559 
560 //=================================================================================================
561 //
562 // GLOBAL BINARY ARITHMETIC OPERATORS
563 //
564 //=================================================================================================
565 
566 //*************************************************************************************************
595 template< typename T1 // Type of the left-hand side sparse matrix
596  , typename T2 > // Type of the right-hand side sparse matrix
597 inline const TSMatSMatSubExpr<T1,T2>
599 {
601 
602  if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
603  throw std::invalid_argument( "Matrix sizes do not match" );
604 
605  return TSMatSMatSubExpr<T1,T2>( ~lhs, ~rhs );
606 }
607 //*************************************************************************************************
608 
609 
610 
611 
612 //=================================================================================================
613 //
614 // GLOBAL OPERATORS
615 //
616 //=================================================================================================
617 
618 //*************************************************************************************************
631 template< typename T1 // Type of the left-hand side sparse matrix
632  , typename T2 > // Type of the right-hand side sparse matrix
633 inline typename RowExprTrait< TSMatSMatSubExpr<T1,T2> >::Type
634  row( const TSMatSMatSubExpr<T1,T2>& sm, size_t index )
635 {
637 
638  return row( sm.leftOperand(), index ) - row( sm.rightOperand(), index );
639 }
641 //*************************************************************************************************
642 
643 
644 //*************************************************************************************************
657 template< typename T1 // Type of the left-hand side sparse matrix
658  , typename T2 > // Type of the right-hand side sparse matrix
659 inline typename ColumnExprTrait< TSMatSMatSubExpr<T1,T2> >::Type
660  column( const TSMatSMatSubExpr<T1,T2>& sm, size_t index )
661 {
663 
664  return column( sm.leftOperand(), index ) - column( sm.rightOperand(), index );
665 }
667 //*************************************************************************************************
668 
669 
670 
671 
672 //=================================================================================================
673 //
674 // EXPRESSION TRAIT SPECIALIZATIONS
675 //
676 //=================================================================================================
677 
678 //*************************************************************************************************
680 template< typename MT1, typename MT2 >
681 struct RowExprTrait< TSMatSMatSubExpr<MT1,MT2> >
682 {
683  public:
684  //**********************************************************************************************
685  typedef typename SubExprTrait< typename RowExprTrait<const MT1>::Type
686  , typename RowExprTrait<const MT2>::Type >::Type Type;
687  //**********************************************************************************************
688 };
690 //*************************************************************************************************
691 
692 
693 //*************************************************************************************************
695 template< typename MT1, typename MT2 >
696 struct ColumnExprTrait< TSMatSMatSubExpr<MT1,MT2> >
697 {
698  public:
699  //**********************************************************************************************
700  typedef typename SubExprTrait< typename ColumnExprTrait<const MT1>::Type
701  , typename ColumnExprTrait<const MT2>::Type >::Type Type;
702  //**********************************************************************************************
703 };
705 //*************************************************************************************************
706 
707 } // namespace blaze
708 
709 #endif