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>
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 TSMATTSMATSUBEXPR
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 TSMatTSMatSubExpr : public SparseMatrix< TSMatTSMatSubExpr<MT1,MT2>, true >
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::ReturnType RN1;
77  typedef typename MT2::ReturnType RN2;
78  typedef typename MT1::CompositeType CT1;
79  typedef typename MT2::CompositeType CT2;
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 TSMatTSMatSubExpr( const MT1& lhs, const MT2& rhs )
129  : lhs_( lhs ) // Left-hand side sparse matrix of the subtraction expression
130  , rhs_( rhs ) // Right-hand side sparse matrix of the subtraction 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****************************************************************
246  template< typename MT // Type of the target dense matrix
247  , bool SO > // Storage order of the target dense matrix
248  friend inline void assign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatSubExpr& rhs )
249  {
250  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
251  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
252 
253  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
254 
255  assign( ~lhs, rhs.lhs_ );
256 
258  subAssign( ~lhs, rhs.rhs_ );
259  }
260  else
261  {
262  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
263 
264  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
265  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
266  BLAZE_INTERNAL_ASSERT( B.rows() == (~lhs).rows() , "Invalid number of rows" );
267  BLAZE_INTERNAL_ASSERT( B.columns() == (~lhs).columns() , "Invalid number of columns" );
268 
269  for( size_t j=0UL; j<(~lhs).columns(); ++j ) {
270  const RightIterator end( B.end(j) );
271  for( RightIterator element=B.begin(j); element!=end; ++element ) {
272  if( isDefault( (~lhs)(element->index(),j) ) )
273  (~lhs)(element->index(),j) = -element->value();
274  else
275  (~lhs)(element->index(),j) -= element->value();
276  }
277  }
278  }
279  }
281  //**********************************************************************************************
282 
283  //**Assignment to row-major sparse matrices*****************************************************
296  template< typename MT > // Type of the target sparse matrix
297  friend inline void assign( SparseMatrix<MT,false>& lhs, const TSMatTSMatSubExpr& rhs )
298  {
299  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
300  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
301 
302  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
303  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
304 
305  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
306  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
307 
308  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
309  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
310  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
311  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
312  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
313  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
314 
315  const size_t m( rhs.rows() );
316  const size_t n( rhs.columns() );
317 
318  // Counting the number of elements per column
319  std::vector<size_t> nonzeros( m, 0UL );
320  for( size_t j=0UL; j<n; ++j )
321  {
322  const LeftIterator lend( A.end(j) );
323  const RightIterator rend( B.end(j) );
324 
325  LeftIterator l( A.begin(j) );
326  RightIterator r( B.begin(j) );
327 
328  while( l != lend && r != rend )
329  {
330  if( l->index() < r->index() ) {
331  ++nonzeros[l->index()];
332  ++l;
333  }
334  else if( l->index() > r->index() ) {
335  ++nonzeros[r->index()];
336  ++r;
337  }
338  else {
339  ++nonzeros[l->index()];
340  ++l;
341  ++r;
342  }
343  }
344 
345  while( l != lend ) {
346  ++nonzeros[l->index()];
347  ++l;
348  }
349 
350  while( r != rend ) {
351  ++nonzeros[r->index()];
352  ++r;
353  }
354  }
355 
356  // Resizing the left-hand side sparse matrix
357  for( size_t i=0UL; i<m; ++i ) {
358  (~lhs).reserve( i, nonzeros[i] );
359  }
360 
361  // Performing the matrix subtraction
362  for( size_t j=0UL; j<n; ++j )
363  {
364  const LeftIterator lend( A.end(j) );
365  const RightIterator rend( B.end(j) );
366 
367  LeftIterator l( A.begin(j) );
368  RightIterator r( B.begin(j) );
369 
370  while( l != lend && r != rend )
371  {
372  if( l->index() < r->index() ) {
373  (~lhs).append( l->index(), j, l->value() );
374  ++l;
375  }
376  else if( l->index() > r->index() ) {
377  (~lhs).append( r->index(), j, -r->value() );
378  ++r;
379  }
380  else {
381  (~lhs).append( l->index(), j, l->value()-r->value() );
382  ++l;
383  ++r;
384  }
385  }
386 
387  while( l != lend ) {
388  (~lhs).append( l->index(), j, l->value() );
389  ++l;
390  }
391 
392  while( r != rend ) {
393  (~lhs).append( r->index(), j, -r->value() );
394  ++r;
395  }
396  }
397  }
399  //**********************************************************************************************
400 
401  //**Assignment to column-major sparse matrices**************************************************
414  template< typename MT > // Type of the target sparse matrix
415  friend inline void assign( SparseMatrix<MT,true>& lhs, const TSMatTSMatSubExpr& rhs )
416  {
417  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
418  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
419 
420  typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
421  typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
422 
423  CT1 A( rhs.lhs_ ); // Evaluation of the left-hand side sparse matrix operand
424  CT2 B( rhs.rhs_ ); // Evaluation of the right-hand side sparse matrix operand
425 
426  BLAZE_INTERNAL_ASSERT( A.rows() == rhs.lhs_.rows() , "Invalid number of rows" );
427  BLAZE_INTERNAL_ASSERT( A.columns() == rhs.lhs_.columns(), "Invalid number of columns" );
428  BLAZE_INTERNAL_ASSERT( B.rows() == rhs.rhs_.rows() , "Invalid number of rows" );
429  BLAZE_INTERNAL_ASSERT( B.columns() == rhs.rhs_.columns(), "Invalid number of columns" );
430  BLAZE_INTERNAL_ASSERT( A.rows() == (~lhs).rows() , "Invalid number of rows" );
431  BLAZE_INTERNAL_ASSERT( A.columns() == (~lhs).columns() , "Invalid number of columns" );
432 
433  for( size_t j=0UL; j<(~lhs).columns(); ++j )
434  {
435  const LeftIterator lend( A.end(j) );
436  const RightIterator rend( B.end(j) );
437 
438  LeftIterator l( A.begin(j) );
439  RightIterator r( B.begin(j) );
440  size_t nonzeros( A.nonZeros(j) + B.nonZeros(j) );
441 
442  for( ; l!=lend && r!=rend; ++l ) {
443  while( r->index() < l->index() && ++r != rend ) {}
444  if( r!=rend && l->index() == r->index() ) {
445  --nonzeros;
446  ++r;
447  }
448  }
449 
450  BLAZE_INTERNAL_ASSERT( nonzeros <= A.rows(), "Invalid number of non-zero elements predicted" );
451 
452  (~lhs).reserve( j, nonzeros );
453 
454  l = A.begin(j);
455  r = B.begin(j);
456 
457  while( l != lend && r != rend )
458  {
459  if( l->index() < r->index() ) {
460  (~lhs).append( l->index(), j, l->value() );
461  ++l;
462  }
463  else if( l->index() > r->index() ) {
464  (~lhs).append( r->index(), j, -r->value() );
465  ++r;
466  }
467  else {
468  (~lhs).append( l->index(), j, l->value()-r->value() );
469  ++l;
470  ++r;
471  }
472  }
473 
474  while( l != lend ) {
475  (~lhs).append( l->index(), j, l->value() );
476  ++l;
477  }
478 
479  while( r != rend ) {
480  (~lhs).append( r->index(), j, -r->value() );
481  ++r;
482  }
483  }
484  }
486  //**********************************************************************************************
487 
488  //**Addition assignment to dense matrices*******************************************************
501  template< typename MT // Type of the target dense matrix
502  , bool SO > // Storage order of the target dense matrix
503  friend inline void addAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatSubExpr& rhs )
504  {
505  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
506  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
507 
508  addAssign( ~lhs, rhs.lhs_ );
509  subAssign( ~lhs, rhs.rhs_ );
510  }
512  //**********************************************************************************************
513 
514  //**Addition assignment to sparse matrices******************************************************
515  // No special implementation for the addition assignment to sparse matrices.
516  //**********************************************************************************************
517 
518  //**Subtraction assignment to dense matrices****************************************************
531  template< typename MT // Type of the target dense matrix
532  , bool SO > // Storage order of the target dense matrix
533  friend inline void subAssign( DenseMatrix<MT,SO>& lhs, const TSMatTSMatSubExpr& rhs )
534  {
535  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
536  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
537 
538  subAssign( ~lhs, rhs.lhs_ );
539  addAssign( ~lhs, rhs.rhs_ );
540  }
542  //**********************************************************************************************
543 
544  //**Subtraction assignment to sparse matrices***************************************************
545  // No special implementation for the subtraction assignment to sparse matrices.
546  //**********************************************************************************************
547 
548  //**Multiplication assignment to dense matrices*************************************************
549  // No special implementation for the multiplication assignment to dense matrices.
550  //**********************************************************************************************
551 
552  //**Multiplication assignment to sparse matrices************************************************
553  // No special implementation for the multiplication assignment to sparse matrices.
554  //**********************************************************************************************
555 
556  //**Compile time checks*************************************************************************
563  //**********************************************************************************************
564 };
565 //*************************************************************************************************
566 
567 
568 
569 
570 //=================================================================================================
571 //
572 // GLOBAL BINARY ARITHMETIC OPERATORS
573 //
574 //=================================================================================================
575 
576 //*************************************************************************************************
603 template< typename T1 // Type of the left-hand side sparse matrix
604  , typename T2 > // Type of the right-hand side sparse matrix
605 inline const TSMatTSMatSubExpr<T1,T2>
607 {
608  if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
609  throw std::invalid_argument( "Matrix sizes do not match" );
610 
611  return TSMatTSMatSubExpr<T1,T2>( ~lhs, ~rhs );
612 }
613 //*************************************************************************************************
614 
615 } // namespace blaze
616 
617 #endif