All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DMatTDMatSubExpr.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_EXPRESSIONS_DMATTDMATSUBEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_DMATTDMATSUBEXPR_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 DMATTDMATSUBEXPR
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 DMatTDMatSubExpr : public DenseMatrix< DMatTDMatSubExpr<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 DMatTDMatSubExpr( const MT1& lhs, const MT2& rhs )
128  : lhs_( lhs ) // Left-hand side dense matrix of the subtraction expression
129  , rhs_( rhs ) // Right-hand side dense matrix of the subtraction 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 DMatTDMatSubExpr& 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  subAssign( ~lhs, rhs.rhs_ );
254  }
255  else {
256  assign ( ~lhs, rhs.lhs_ );
257  subAssign( ~lhs, rhs.rhs_ );
258  }
259  }
261  //**********************************************************************************************
262 
263  //**Assignment to sparse matrices***************************************************************
275  template< typename MT // Type of the target sparse matrix
276  , bool SO2 > // Storage order of the target sparse matrix
277  friend inline void assign( SparseMatrix<MT,SO2>& lhs, const DMatTDMatSubExpr& rhs )
278  {
279  typedef typename SelectType< SO2, OppositeType, ResultType >::Type TmpType;
280 
286  BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( typename TmpType::CompositeType );
287 
288  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
289  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
290 
291  const TmpType tmp( rhs );
292  assign( ~lhs, tmp );
293  }
295  //**********************************************************************************************
296 
297  //**Addition assignment to dense matrices*******************************************************
310  template< typename MT // Type of the target dense matrix
311  , bool SO2 > // Storage order of the target dense matrix
312  friend inline void addAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatSubExpr& rhs )
313  {
314  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
315  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
316 
317  // In case non of the two dense operands requires an intermediate evaluation, the
318  // addition expression is assigned directly in a cache-efficient manner.
319  if( !RequiresEvaluation<MT1>::value && !RequiresEvaluation<MT2>::value )
320  {
321  const size_t m( rhs.rows() );
322  const size_t n( rhs.columns() );
323  const size_t block( 16UL );
324 
325  for( size_t ii=0UL; ii<m; ii+=block ) {
326  const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
327  for( size_t jj=0UL; jj<n; jj+=block ) {
328  const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
329  for( size_t i=ii; i<iend; ++i ) {
330  for( size_t j=jj; j<jend; ++j ) {
331  (~lhs)(i,j) += rhs.lhs_(i,j) - rhs.rhs_(i,j);
332  }
333  }
334  }
335  }
336  }
337 
338  // In case either of the two dense operands requires an intermediate evaluation, the
339  // expression is evaluated in a two-step approach.
340  else
341  {
342  addAssign( ~lhs, rhs.lhs_ );
343  subAssign( ~lhs, rhs.rhs_ );
344  }
345  }
347  //**********************************************************************************************
348 
349  //**Addition assignment to sparse matrices******************************************************
350  // No special implementation for the addition assignment to sparse matrices.
351  //**********************************************************************************************
352 
353  //**Subtraction assignment to dense matrices****************************************************
366  template< typename MT // Type of the target dense matrix
367  , bool SO2 > // Storage order of the target dense matrix
368  friend inline void subAssign( DenseMatrix<MT,SO2>& lhs, const DMatTDMatSubExpr& rhs )
369  {
370  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == rhs.rows() , "Invalid number of rows" );
371  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == rhs.columns(), "Invalid number of columns" );
372 
373  // In case non of the two dense operands requires an intermediate evaluation, the
374  // addition expression is assigned directly in a cache-efficient manner.
375  if( !RequiresEvaluation<MT1>::value && !RequiresEvaluation<MT2>::value )
376  {
377  const size_t m( rhs.rows() );
378  const size_t n( rhs.columns() );
379  const size_t block( 16UL );
380 
381  for( size_t ii=0UL; ii<m; ii+=block ) {
382  const size_t iend( ( m < ii+block )?( m ):( ii+block ) );
383  for( size_t jj=0UL; jj<n; jj+=block ) {
384  const size_t jend( ( n < jj+block )?( n ):( jj+block ) );
385  for( size_t i=ii; i<iend; ++i ) {
386  for( size_t j=jj; j<jend; ++j ) {
387  (~lhs)(i,j) -= rhs.lhs_(i,j) - rhs.rhs_(i,j);
388  }
389  }
390  }
391  }
392  }
393 
394  // In case either of the two dense operands requires an intermediate evaluation, the
395  // expression is evaluated in a two-step approach.
396  else
397  {
398  subAssign( ~lhs, rhs.lhs_ );
399  addAssign( ~lhs, rhs.rhs_ );
400  }
401  }
403  //**********************************************************************************************
404 
405  //**Subtraction assignment to sparse matrices***************************************************
406  // No special implementation for the subtraction assignment to sparse matrices.
407  //**********************************************************************************************
408 
409  //**Multiplication assignment to dense matrices*************************************************
410  // No special implementation for the multiplication assignment to dense matrices.
411  //**********************************************************************************************
412 
413  //**Multiplication assignment to sparse matrices************************************************
414  // No special implementation for the multiplication assignment to sparse matrices.
415  //**********************************************************************************************
416 
417  //**Compile time checks*************************************************************************
423  //**********************************************************************************************
424 };
425 //*************************************************************************************************
426 
427 
428 
429 
430 //=================================================================================================
431 //
432 // GLOBAL BINARY ARITHMETIC OPERATORS
433 //
434 //=================================================================================================
435 
436 //*************************************************************************************************
465 template< typename T1 // Type of the left-hand side dense matrix
466  , typename T2 > // Type of the right-hand side dense matrix
467 inline const DMatTDMatSubExpr<T1,T2>
469 {
470  if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
471  throw std::invalid_argument( "Matrix sizes do not match" );
472 
473  return DMatTDMatSubExpr<T1,T2>( ~lhs, ~rhs );
474 }
475 //*************************************************************************************************
476 
477 
478 //*************************************************************************************************
507 template< typename T1 // Type of the left-hand side dense matrix
508  , typename T2 > // Type of the right-hand side dense matrix
509 inline const DMatTDMatSubExpr<T1,T2>
511 {
512  if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() )
513  throw std::invalid_argument( "Matrix sizes do not match" );
514 
515  return DMatTDMatSubExpr<T1,T2>( ~lhs, ~rhs );
516 }
517 //*************************************************************************************************
518 
519 } // namespace blaze
520 
521 #endif