All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DMatTDMatAddExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_DMATTDMATADDEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_DMATTDMATADDEXPR_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <stdexcept>
44 #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 DMATTDMATADDEXPR
56 //
57 //=================================================================================================
58 
59 //*************************************************************************************************
66 template< typename MT1 // Type of the left-hand side dense matrix
67  , typename MT2 > // Type of the right-hand side dense matrix
68 class DMatTDMatAddExpr : public DenseMatrix< DMatTDMatAddExpr<MT1,MT2>, false >
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***************************************************************************
118  enum { vectorizable = 0 };
119  //**********************************************************************************************
120 
121  //**Constructor*********************************************************************************
127  explicit inline DMatTDMatAddExpr( const MT1& lhs, const MT2& rhs )
128  : lhs_( lhs ) // Left-hand side dense matrix of the addition expression
129  , rhs_( rhs ) // Right-hand side dense matrix of the addition expression
130  {
131  BLAZE_INTERNAL_ASSERT( lhs.rows() == rhs.rows() , "Invalid number of rows" );
132  BLAZE_INTERNAL_ASSERT( lhs.columns() == rhs.columns(), "Invalid number of columns" );
133  }
134  //**********************************************************************************************
135 
136  //**Access operator*****************************************************************************
143  inline ReturnType operator()( size_t i, size_t j ) const {
144  BLAZE_INTERNAL_ASSERT( i < lhs_.rows() , "Invalid row access index" );
145  BLAZE_INTERNAL_ASSERT( j < lhs_.columns(), "Invalid column access index" );
146  return lhs_(i,j) + rhs_(i,j);
147  }
148  //**********************************************************************************************
149 
150  //**Rows function*******************************************************************************
155  inline size_t rows() const {
156  return lhs_.rows();
157  }
158  //**********************************************************************************************
159 
160  //**Columns function****************************************************************************
165  inline size_t columns() const {
166  return lhs_.columns();
167  }
168  //**********************************************************************************************
169 
170  //**Left operand access*************************************************************************
175  inline LeftOperand leftOperand() const {
176  return lhs_;
177  }
178  //**********************************************************************************************
179 
180  //**Right operand access************************************************************************
185  inline RightOperand rightOperand() const {
186  return rhs_;
187  }
188  //**********************************************************************************************
189 
190  //**********************************************************************************************
196  template< typename T >
197  inline bool canAlias( const T* alias ) const {
198  return ( IsExpression<MT1>::value && ( RequiresEvaluation<MT1>::value ? lhs_.isAliased( alias ) : lhs_.canAlias( alias ) ) ) ||
199  ( IsExpression<MT2>::value && ( RequiresEvaluation<MT2>::value ? rhs_.isAliased( alias ) : rhs_.canAlias( alias ) ) );
200  }
201  //**********************************************************************************************
202 
203  //**********************************************************************************************
209  template< typename T >
210  inline bool isAliased( const T* alias ) const {
211  return ( lhs_.isAliased( alias ) || rhs_.isAliased( alias ) );
212  }
213  //**********************************************************************************************
214 
215  private:
216  //**Member variables****************************************************************************
219  //**********************************************************************************************
220 
221  //**Assignment to dense matrices****************************************************************
233  template< typename MT // Type of the target dense matrix
234  , bool SO2 > // Storage order of the target dense matrix
235  friend inline void assign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
236  {
238 
239  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
240  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
241 
242  // In case non of the two dense operands requires an intermediate evaluation, the
243  // addition expression is assigned directly in a cache-efficient manner.
245  {
246  const size_t m( rhs.rows() );
247  const size_t n( rhs.columns() );
248  const size_t block( 16UL );
249 
250  for( size_t ii=0UL; ii<m; ii+=block ) {
251  const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
252  for( size_t jj=0UL; jj<n; jj+=block ) {
253  const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
254  for( size_t i=ii; i<iend; ++i ) {
255  for( size_t j=jj; j<jend; ++j ) {
256  (~lhs)(i,j) = rhs.lhs_(i,j) + rhs.rhs_(i,j);
257  }
258  }
259  }
260  }
261  }
262 
263  // In case either of the two dense operands requires an intermediate evaluation, the
264  // expression is evaluated in a one- or two-step approach (depending on whether any
265  // of the operands is aliased with the target matrix).
266  else if( !IsExpression<MT1>::value && (~lhs).isAliased( &rhs.lhs_ ) ) {
267  addAssign( ~lhs, rhs.rhs_ );
268  }
269  else if( !IsExpression<MT2>::value && (~lhs).isAliased( &rhs.rhs_ ) ) {
270  addAssign( ~lhs, rhs.lhs_ );
271  }
272  else {
273  assign ( ~lhs, rhs.lhs_ );
274  addAssign( ~lhs, rhs.rhs_ );
275  }
276  }
278  //**********************************************************************************************
279 
280  //**Assignment to sparse matrices***************************************************************
292  template< typename MT // Type of the target sparse matrix
293  , bool SO2 > // Storage order of the target sparse matrix
294  friend inline void assign( SparseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
295  {
297 
298  typedef typename SelectType< SO2, OppositeType, ResultType >::Type TmpType;
299 
305  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename TmpType::CompositeType );
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  const TmpType tmp( rhs );
311  assign( ~lhs, tmp );
312  }
314  //**********************************************************************************************
315 
316  //**Addition assignment to dense matrices*******************************************************
328  template< typename MT // Type of the target dense matrix
329  , bool SO2 > // Storage order of the target dense matrix
330  friend inline void addAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
331  {
333 
334  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
335  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
336 
337  // In case non of the two dense operands requires an intermediate evaluation, the
338  // addition expression is assigned directly in a cache-efficient manner.
339  if( !RequiresEvaluation<MT1>::value && !RequiresEvaluation<MT2>::value )
340  {
341  const size_t m( rhs.rows() );
342  const size_t n( rhs.columns() );
343  const size_t block( 16UL );
344 
345  for( size_t ii=0UL; ii<m; ii+=block ) {
346  const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
347  for( size_t jj=0UL; jj<n; jj+=block ) {
348  const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
349  for( size_t i=ii; i<iend; ++i ) {
350  for( size_t j=jj; j<jend; ++j ) {
351  (~lhs)(i,j) += rhs.lhs_(i,j) + rhs.rhs_(i,j);
352  }
353  }
354  }
355  }
356  }
357 
358  // In case either of the two dense operands requires an intermediate evaluation, the
359  // expression is evaluated in a two-step approach.
360  else
361  {
362  addAssign( ~lhs, rhs.lhs_ );
363  addAssign( ~lhs, rhs.rhs_ );
364  }
365  }
367  //**********************************************************************************************
368 
369  //**Addition assignment to sparse matrices******************************************************
370  // No special implementation for the addition assignment to sparse matrices.
371  //**********************************************************************************************
372 
373  //**Subtraction assignment to dense matrices****************************************************
385  template< typename MT // Type of the target dense matrix
386  , bool SO2 > // Storage order of the target dense matrix
387  friend inline void subAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
388  {
390 
391  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
392  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
393 
394  // In case non of the two dense operands requires an intermediate evaluation, the
395  // addition expression is assigned directly in a cache-efficient manner.
396  if( !RequiresEvaluation<MT1>::value && !RequiresEvaluation<MT2>::value )
397  {
398  const size_t m( rhs.rows() );
399  const size_t n( rhs.columns() );
400  const size_t block( 16UL );
401 
402  for( size_t ii=0UL; ii<m; ii+=block ) {
403  const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
404  for( size_t jj=0UL; jj<n; jj+=block ) {
405  const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
406  for( size_t i=ii; i<iend; ++i ) {
407  for( size_t j=jj; j<jend; ++j ) {
408  (~lhs)(i,j) -= rhs.lhs_(i,j) + rhs.rhs_(i,j);
409  }
410  }
411  }
412  }
413  }
414 
415  // In case either of the two dense operands requires an intermediate evaluation, the
416  // expression is evaluated in a two-step approach.
417  else
418  {
419  subAssign( ~lhs, rhs.lhs_ );
420  subAssign( ~lhs, rhs.rhs_ );
421  }
422  }
424  //**********************************************************************************************
425 
426  //**Subtraction assignment to sparse matrices***************************************************
427  // No special implementation for the subtraction assignment to sparse matrices.
428  //**********************************************************************************************
429 
430  //**Multiplication assignment to dense matrices*************************************************
431  // No special implementation for the multiplication assignment to dense matrices.
432  //**********************************************************************************************
433 
434  //**Multiplication assignment to sparse matrices************************************************
435  // No special implementation for the multiplication assignment to sparse matrices.
436  //**********************************************************************************************
437 
438  //**Compile time checks*************************************************************************
445  //**********************************************************************************************
446 };
447 //*************************************************************************************************
448 
449 
450 
451 
452 //=================================================================================================
453 //
454 // GLOBAL BINARY ARITHMETIC OPERATORS
455 //
456 //=================================================================================================
457 
458 //*************************************************************************************************
487 template< typename T1 // Type of the left-hand side dense matrix
488  , typename T2 > // Type of the right-hand side dense matrix
489 inline const DMatTDMatAddExpr<T1,T2>
491 {
493 
494  if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
495  throw std::invalid_argument( "Matrix sizes do not match" );
496 
497  return DMatTDMatAddExpr<T1,T2>( ~lhs, ~rhs );
498 }
499 //*************************************************************************************************
500 
501 
502 //*************************************************************************************************
531 template< typename T1 // Type of the left-hand side dense matrix
532  , typename T2 > // Type of the right-hand side dense matrix
533 inline const DMatTDMatAddExpr<T2,T1>
535 {
537 
538  if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
539  throw std::invalid_argument( "Matrix sizes do not match" );
540 
541  return DMatTDMatAddExpr<T2,T1>( ~rhs, ~lhs );
542 }
543 //*************************************************************************************************
544 
545 
546 
547 
548 //=================================================================================================
549 //
550 // GLOBAL OPERATORS
551 //
552 //=================================================================================================
553 
554 //*************************************************************************************************
567 template< typename MT1 // Type of the left-hand side dense matrix
568  , typename MT2 > // Type of the right-hand side dense matrix
569 inline typename RowExprTrait< DMatTDMatAddExpr<MT1,MT2> >::Type
570  row( const DMatTDMatAddExpr<MT1,MT2>& dm, size_t index )
571 {
573 
574  return row( dm.leftOperand(), index ) + row( dm.rightOperand(), index );
575 }
577 //*************************************************************************************************
578 
579 
580 //*************************************************************************************************
593 template< typename MT1 // Type of the left-hand side dense matrix
594  , typename MT2 > // Type of the right-hand side dense matrix
595 inline typename ColumnExprTrait< DMatTDMatAddExpr<MT1,MT2> >::Type
596  column( const DMatTDMatAddExpr<MT1,MT2>& dm, size_t index )
597 {
599 
600  return column( dm.leftOperand(), index ) + column( dm.rightOperand(), index );
601 }
603 //*************************************************************************************************
604 
605 
606 
607 
608 //=================================================================================================
609 //
610 // EXPRESSION TRAIT SPECIALIZATIONS
611 //
612 //=================================================================================================
613 
614 //*************************************************************************************************
616 template< typename MT1, typename MT2 >
617 struct RowExprTrait< DMatTDMatAddExpr<MT1,MT2> >
618 {
619  public:
620  //**********************************************************************************************
621  typedef typename AddExprTrait< typename RowExprTrait<const MT1>::Type
622  , typename RowExprTrait<const MT2>::Type >::Type Type;
623  //**********************************************************************************************
624 };
626 //*************************************************************************************************
627 
628 
629 //*************************************************************************************************
631 template< typename MT1, typename MT2 >
632 struct ColumnExprTrait< DMatTDMatAddExpr<MT1,MT2> >
633 {
634  public:
635  //**********************************************************************************************
636  typedef typename AddExprTrait< typename ColumnExprTrait<const MT1>::Type
637  , typename ColumnExprTrait<const MT2>::Type >::Type Type;
638  //**********************************************************************************************
639 };
641 //*************************************************************************************************
642 
643 } // namespace blaze
644 
645 #endif