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>
42 #include <blaze/util/Assert.h>
44 #include <blaze/util/SelectType.h>
45 #include <blaze/util/Types.h>
46 
47 
48 namespace blaze {
49 
50 //=================================================================================================
51 //
52 // CLASS DMATTDMATADDEXPR
53 //
54 //=================================================================================================
55 
56 //*************************************************************************************************
63 template< typename MT1 // Type of the left-hand side dense matrix
64  , typename MT2 > // Type of the right-hand side dense matrix
65 class DMatTDMatAddExpr : public DenseMatrix< DMatTDMatAddExpr<MT1,MT2>, false >
66  , private Expression
67  , private Computation
68 {
69  private:
70  //**Type definitions****************************************************************************
71  typedef typename MT1::ResultType RT1;
72  typedef typename MT2::ResultType RT2;
73  typedef typename MT1::ReturnType RN1;
74  typedef typename MT2::ReturnType RN2;
75  typedef typename MT1::CompositeType CT1;
76  typedef typename MT2::CompositeType CT2;
77  //**********************************************************************************************
78 
79  //**Return type evaluation**********************************************************************
81 
86  enum { returnExpr = !IsTemporary<RN1>::value && !IsTemporary<RN2>::value };
87 
90  //**********************************************************************************************
91 
92  public:
93  //**Type definitions****************************************************************************
96  typedef typename ResultType::OppositeType OppositeType;
97  typedef typename ResultType::TransposeType TransposeType;
98  typedef typename ResultType::ElementType ElementType;
99 
102 
104  typedef const ResultType CompositeType;
105 
107  typedef typename SelectType< IsExpression<MT1>::value, const MT1, const MT1& >::Type LeftOperand;
108 
110  typedef typename SelectType< IsExpression<MT2>::value, const MT2, const MT2& >::Type RightOperand;
111  //**********************************************************************************************
112 
113  //**Compilation flags***************************************************************************
115  enum { vectorizable = 0 };
116 
118  enum { canAlias = IsExpression<MT1>::value || IsExpression<MT2>::value };
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 isAliased( const T* alias ) const {
198  return ( IsExpression<MT1>::value && lhs_.isAliased( alias ) ) ||
199  ( IsExpression<MT2>::value && rhs_.isAliased( alias ) );
200  }
201  //**********************************************************************************************
202 
203  private:
204  //**Member variables****************************************************************************
207  //**********************************************************************************************
208 
209  //**Assignment to dense matrices****************************************************************
221  template< typename MT // Type of the target dense matrix
222  , bool SO2 > // Storage order of the target dense matrix
223  friend inline void assign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
224  {
225  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
226  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
227 
228  // In case non of the two dense operands requires an intermediate evaluation, the
229  // addition expression is assigned directly in a cache-efficient manner.
231  {
232  const size_t m( rhs.rows() );
233  const size_t n( rhs.columns() );
234  const size_t block( 16UL );
235 
236  for( size_t ii=0UL; ii<m; ii+=block ) {
237  const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
238  for( size_t jj=0UL; jj<n; jj+=block ) {
239  const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
240  for( size_t i=ii; i<iend; ++i ) {
241  for( size_t j=jj; j<jend; ++j ) {
242  (~lhs)(i,j) = rhs.lhs_(i,j) + rhs.rhs_(i,j);
243  }
244  }
245  }
246  }
247  }
248 
249  // In case either of the two dense operands requires an intermediate evaluation, the
250  // expression is evaluated in a one- or two-step approach (depending on whether any
251  // of the operands is aliased with the target matrix).
252  else if( !IsExpression<MT1>::value && (~lhs).isAliased( &rhs.lhs_ ) ) {
253  addAssign( ~lhs, rhs.rhs_ );
254  }
255  else if( !IsExpression<MT2>::value && (~lhs).isAliased( &rhs.rhs_ ) ) {
256  addAssign( ~lhs, rhs.lhs_ );
257  }
258  else {
259  assign ( ~lhs, rhs.lhs_ );
260  addAssign( ~lhs, rhs.rhs_ );
261  }
262  }
264  //**********************************************************************************************
265 
266  //**Assignment to sparse matrices***************************************************************
278  template< typename MT // Type of the target sparse matrix
279  , bool SO2 > // Storage order of the target sparse matrix
280  friend inline void assign( SparseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
281  {
282  typedef typename SelectType< SO2, OppositeType, ResultType >::Type TmpType;
283 
289  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename TmpType::CompositeType );
290 
291  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
292  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
293 
294  const TmpType tmp( rhs );
295  assign( ~lhs, tmp );
296  }
298  //**********************************************************************************************
299 
300  //**Addition assignment to dense matrices*******************************************************
312  template< typename MT // Type of the target dense matrix
313  , bool SO2 > // Storage order of the target dense matrix
314  friend inline void addAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
315  {
316  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
317  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
318 
319  // In case non of the two dense operands requires an intermediate evaluation, the
320  // addition expression is assigned directly in a cache-efficient manner.
321  if( !RequiresEvaluation<MT1>::value && !RequiresEvaluation<MT2>::value )
322  {
323  const size_t m( rhs.rows() );
324  const size_t n( rhs.columns() );
325  const size_t block( 16UL );
326 
327  for( size_t ii=0UL; ii<m; ii+=block ) {
328  const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
329  for( size_t jj=0UL; jj<n; jj+=block ) {
330  const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
331  for( size_t i=ii; i<iend; ++i ) {
332  for( size_t j=jj; j<jend; ++j ) {
333  (~lhs)(i,j) += rhs.lhs_(i,j) + rhs.rhs_(i,j);
334  }
335  }
336  }
337  }
338  }
339 
340  // In case either of the two dense operands requires an intermediate evaluation, the
341  // expression is evaluated in a two-step approach.
342  else
343  {
344  addAssign( ~lhs, rhs.lhs_ );
345  addAssign( ~lhs, rhs.rhs_ );
346  }
347  }
349  //**********************************************************************************************
350 
351  //**Addition assignment to sparse matrices******************************************************
352  // No special implementation for the addition assignment to sparse matrices.
353  //**********************************************************************************************
354 
355  //**Subtraction assignment to dense matrices****************************************************
367  template< typename MT // Type of the target dense matrix
368  , bool SO2 > // Storage order of the target dense matrix
369  friend inline void subAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatAddExpr& rhs )
370  {
371  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
372  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
373 
374  // In case non of the two dense operands requires an intermediate evaluation, the
375  // addition expression is assigned directly in a cache-efficient manner.
376  if( !RequiresEvaluation<MT1>::value && !RequiresEvaluation<MT2>::value )
377  {
378  const size_t m( rhs.rows() );
379  const size_t n( rhs.columns() );
380  const size_t block( 16UL );
381 
382  for( size_t ii=0UL; ii<m; ii+=block ) {
383  const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
384  for( size_t jj=0UL; jj<n; jj+=block ) {
385  const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
386  for( size_t i=ii; i<iend; ++i ) {
387  for( size_t j=jj; j<jend; ++j ) {
388  (~lhs)(i,j) -= rhs.lhs_(i,j) + rhs.rhs_(i,j);
389  }
390  }
391  }
392  }
393  }
394 
395  // In case either of the two dense operands requires an intermediate evaluation, the
396  // expression is evaluated in a two-step approach.
397  else
398  {
399  subAssign( ~lhs, rhs.lhs_ );
400  subAssign( ~lhs, rhs.rhs_ );
401  }
402  }
404  //**********************************************************************************************
405 
406  //**Subtraction assignment to sparse matrices***************************************************
407  // No special implementation for the subtraction assignment to sparse matrices.
408  //**********************************************************************************************
409 
410  //**Multiplication assignment to dense matrices*************************************************
411  // No special implementation for the multiplication assignment to dense matrices.
412  //**********************************************************************************************
413 
414  //**Multiplication assignment to sparse matrices************************************************
415  // No special implementation for the multiplication assignment to sparse matrices.
416  //**********************************************************************************************
417 
418  //**Compile time checks*************************************************************************
425  //**********************************************************************************************
426 };
427 //*************************************************************************************************
428 
429 
430 
431 
432 //=================================================================================================
433 //
434 // GLOBAL BINARY ARITHMETIC OPERATORS
435 //
436 //=================================================================================================
437 
438 //*************************************************************************************************
467 template< typename T1 // Type of the left-hand side dense matrix
468  , typename T2 > // Type of the right-hand side dense matrix
469 inline const DMatTDMatAddExpr<T1,T2>
471 {
472  if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
473  throw std::invalid_argument( "Matrix sizes do not match" );
474 
475  return DMatTDMatAddExpr<T1,T2>( ~lhs, ~rhs );
476 }
477 //*************************************************************************************************
478 
479 
480 //*************************************************************************************************
509 template< typename T1 // Type of the left-hand side dense matrix
510  , typename T2 > // Type of the right-hand side dense matrix
511 inline const DMatTDMatAddExpr<T2,T1>
513 {
514  if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
515  throw std::invalid_argument( "Matrix sizes do not match" );
516 
517  return DMatTDMatAddExpr<T2,T1>( ~rhs, ~lhs );
518 }
519 //*************************************************************************************************
520 
521 } // namespace blaze
522 
523 #endif