All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TSMatTSMatSubExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_TSMATTSMATSUBEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_TSMATTSMATSUBEXPR_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 TSMATTSMATSUBEXPR
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 TSMatTSMatSubExpr : public SparseMatrix< TSMatTSMatSubExpr<MT1,MT2>, true >
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 TSMatTSMatSubExpr( 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****************************************************************
252  template< typename MT // Type of the target dense matrix
253  , bool SO > // Storage order of the target dense matrix
254  friend inline void assign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatSubExpr& rhs )
255  {
257 
258  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
259  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
260 
261  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
262 
263  assign( ~lhs, rhs.lhs_ );
264 
266  subAssign( ~lhs, rhs.rhs_ );
267  }
268  else
269  {
270  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
271 
272  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
273  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
274  BLAZE_INTERNAL_ASSERT( B.rows() == (~lhs).rows() , "Invalid number of rows" );
275  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
276 
277  for( size_t j=0UL; j<(~lhs).columns(); ++j ) {
278  const RightIterator end( B.end(j) );
279  for( RightIterator element=B.begin(j); element!=end; ++element ) {
280  if( isDefault( (~lhs)(element->index(),j) ) )
281  (~lhs)(element->index(),j) = -element->value();
282  else
283  (~lhs)(element->index(),j) -= element->value();
284  }
285  }
286  }
287  }
289  //**********************************************************************************************
290 
291  //**Assignment to row-major sparse matrices*****************************************************
304  template< typename MT > // Type of the target sparse matrix
305  friend inline void assign( SparseMatrix<MT,false>& lhs, const TSMatTSMatSubExpr& rhs )
306  {
308 
309  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
310  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
311 
312  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
313  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
314 
315  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
316  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
317 
318  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
319  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
320  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
321  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
322  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
323  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
324 
325  const size_t m( rhs.rows() );
326  const size_t n( rhs.columns() );
327 
328  // Counting the number of elements per column
329  std::vector<size_t> nonzeros( m, 0UL );
330  for( size_t j=0UL; j<n; ++j )
331  {
332  const LeftIterator lend( A.end(j) );
333  const RightIterator rend( B.end(j) );
334 
335  LeftIterator l( A.begin(j) );
336  RightIterator r( B.begin(j) );
337 
338  while( l != lend && r != rend )
339  {
340  if( l->index() < r->index() ) {
341  ++nonzeros[l->index()];
342  ++l;
343  }
344  else if( l->index() > r->index() ) {
345  ++nonzeros[r->index()];
346  ++r;
347  }
348  else {
349  ++nonzeros[l->index()];
350  ++l;
351  ++r;
352  }
353  }
354 
355  while( l != lend ) {
356  ++nonzeros[l->index()];
357  ++l;
358  }
359 
360  while( r != rend ) {
361  ++nonzeros[r->index()];
362  ++r;
363  }
364  }
365 
366  // Resizing the left-hand side sparse matrix
367  for( size_t i=0UL; i<m; ++i ) {
368  (~lhs).reserve( i, nonzeros[i] );
369  }
370 
371  // Performing the matrix subtraction
372  for( size_t j=0UL; j<n; ++j )
373  {
374  const LeftIterator lend( A.end(j) );
375  const RightIterator rend( B.end(j) );
376 
377  LeftIterator l( A.begin(j) );
378  RightIterator r( B.begin(j) );
379 
380  while( l != lend && r != rend )
381  {
382  if( l->index() < r->index() ) {
383  (~lhs).append( l->index(), j, l->value() );
384  ++l;
385  }
386  else if( l->index() > r->index() ) {
387  (~lhs).append( r->index(), j, -r->value() );
388  ++r;
389  }
390  else {
391  (~lhs).append( l->index(), j, l->value()-r->value() );
392  ++l;
393  ++r;
394  }
395  }
396 
397  while( l != lend ) {
398  (~lhs).append( l->index(), j, l->value() );
399  ++l;
400  }
401 
402  while( r != rend ) {
403  (~lhs).append( r->index(), j, -r->value() );
404  ++r;
405  }
406  }
407  }
409  //**********************************************************************************************
410 
411  //**Assignment to column-major sparse matrices**************************************************
424  template< typename MT > // Type of the target sparse matrix
425  friend inline void assign( SparseMatrix<MT,true>& lhs, const TSMatTSMatSubExpr& rhs )
426  {
428 
429  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
430  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
431 
432  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
433  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
434 
435  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
436  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
437 
438  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
439  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
440  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
441  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
442  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
443  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
444 
445  for( size_t j=0UL; j<(~lhs).columns(); ++j )
446  {
447  const LeftIterator lend( A.end(j) );
448  const RightIterator rend( B.end(j) );
449 
450  LeftIterator l( A.begin(j) );
451  RightIterator r( B.begin(j) );
452  size_t nonzeros( A.nonZeros(j) + B.nonZeros(j) );
453 
454  for( ; l!=lend && r!=rend; ++l ) {
455  while( r->index() < l->index() && ++r != rend ) {}
456  if( r!=rend && l->index() == r->index() ) {
457  --nonzeros;
458  ++r;
459  }
460  }
461 
462  BLAZE_INTERNAL_ASSERT( nonzeros <= A.rows(), "Invalid number of non-zero elements predicted" );
463 
464  (~lhs).reserve( j, nonzeros );
465 
466  l = A.begin(j);
467  r = B.begin(j);
468 
469  while( l != lend && r != rend )
470  {
471  if( l->index() < r->index() ) {
472  (~lhs).append( l->index(), j, l->value() );
473  ++l;
474  }
475  else if( l->index() > r->index() ) {
476  (~lhs).append( r->index(), j, -r->value() );
477  ++r;
478  }
479  else {
480  (~lhs).append( l->index(), j, l->value()-r->value() );
481  ++l;
482  ++r;
483  }
484  }
485 
486  while( l != lend ) {
487  (~lhs).append( l->index(), j, l->value() );
488  ++l;
489  }
490 
491  while( r != rend ) {
492  (~lhs).append( r->index(), j, -r->value() );
493  ++r;
494  }
495  }
496  }
498  //**********************************************************************************************
499 
500  //**Addition assignment to dense matrices*******************************************************
513  template< typename MT // Type of the target dense matrix
514  , bool SO > // Storage order of the target dense matrix
515  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatSubExpr& rhs )
516  {
518 
519  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
520  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
521 
522  addAssign( ~lhs, rhs.lhs_ );
523  subAssign( ~lhs, rhs.rhs_ );
524  }
526  //**********************************************************************************************
527 
528  //**Addition assignment to sparse matrices******************************************************
529  // No special implementation for the addition assignment to sparse matrices.
530  //**********************************************************************************************
531 
532  //**Subtraction assignment to dense matrices****************************************************
545  template< typename MT // Type of the target dense matrix
546  , bool SO > // Storage order of the target dense matrix
547  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatSubExpr& rhs )
548  {
550 
551  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
552  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
553 
554  subAssign( ~lhs, rhs.lhs_ );
555  addAssign( ~lhs, rhs.rhs_ );
556  }
558  //**********************************************************************************************
559 
560  //**Subtraction assignment to sparse matrices***************************************************
561  // No special implementation for the subtraction assignment to sparse matrices.
562  //**********************************************************************************************
563 
564  //**Multiplication assignment to dense matrices*************************************************
565  // No special implementation for the multiplication assignment to dense matrices.
566  //**********************************************************************************************
567 
568  //**Multiplication assignment to sparse matrices************************************************
569  // No special implementation for the multiplication assignment to sparse matrices.
570  //**********************************************************************************************
571 
572  //**Compile time checks*************************************************************************
579  //**********************************************************************************************
580 };
581 //*************************************************************************************************
582 
583 
584 
585 
586 //=================================================================================================
587 //
588 // GLOBAL BINARY ARITHMETIC OPERATORS
589 //
590 //=================================================================================================
591 
592 //*************************************************************************************************
619 template< typename T1 // Type of the left-hand side sparse matrix
620  , typename T2 > // Type of the right-hand side sparse matrix
621 inline const TSMatTSMatSubExpr<T1,T2>
623 {
625 
626  if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
627  throw std::invalid_argument( "Matrix sizes do not match" );
628 
629  return TSMatTSMatSubExpr<T1,T2>( ~lhs, ~rhs );
630 }
631 //*************************************************************************************************
632 
633 
634 
635 
636 //=================================================================================================
637 //
638 // GLOBAL OPERATORS
639 //
640 //=================================================================================================
641 
642 //*************************************************************************************************
655 template< typename T1 // Type of the left-hand side sparse matrix
656  , typename T2 > // Type of the right-hand side sparse matrix
657 inline typename RowExprTrait< TSMatTSMatSubExpr<T1,T2> >::Type
658  row( const TSMatTSMatSubExpr<T1,T2>& sm, size_t index )
659 {
661 
662  return row( sm.leftOperand(), index ) - row( sm.rightOperand(), index );
663 }
665 //*************************************************************************************************
666 
667 
668 //*************************************************************************************************
681 template< typename T1 // Type of the left-hand side sparse matrix
682  , typename T2 > // Type of the right-hand side sparse matrix
683 inline typename ColumnExprTrait< TSMatTSMatSubExpr<T1,T2> >::Type
684  column( const TSMatTSMatSubExpr<T1,T2>& sm, size_t index )
685 {
687 
688  return column( sm.leftOperand(), index ) - column( sm.rightOperand(), index );
689 }
691 //*************************************************************************************************
692 
693 
694 
695 
696 //=================================================================================================
697 //
698 // EXPRESSION TRAIT SPECIALIZATIONS
699 //
700 //=================================================================================================
701 
702 //*************************************************************************************************
704 template< typename MT1, typename MT2 >
705 struct RowExprTrait< TSMatTSMatSubExpr<MT1,MT2> >
706 {
707  public:
708  //**********************************************************************************************
709  typedef typename SubExprTrait< typename RowExprTrait<const MT1>::Type
710  , typename RowExprTrait<const MT2>::Type >::Type Type;
711  //**********************************************************************************************
712 };
714 //*************************************************************************************************
715 
716 
717 //*************************************************************************************************
719 template< typename MT1, typename MT2 >
720 struct ColumnExprTrait< TSMatTSMatSubExpr<MT1,MT2> >
721 {
722  public:
723  //**********************************************************************************************
724  typedef typename SubExprTrait< typename ColumnExprTrait<const MT1>::Type
725  , typename ColumnExprTrait<const MT2>::Type >::Type Type;
726  //**********************************************************************************************
727 };
729 //*************************************************************************************************
730 
731 } // namespace blaze
732 
733 #endif