DenseMatrix.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_SMP_OPENMP_DENSEMATRIX_H_
36 #define _BLAZE_MATH_SMP_OPENMP_DENSEMATRIX_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <omp.h>
44 #include <blaze/math/Aliases.h>
49 #include <blaze/math/Functions.h>
60 #include <blaze/system/SMP.h>
61 #include <blaze/util/Assert.h>
62 #include <blaze/util/EnableIf.h>
64 #include <blaze/util/mpl/And.h>
65 #include <blaze/util/mpl/Not.h>
66 #include <blaze/util/mpl/Or.h>
68 #include <blaze/util/Types.h>
69 
70 
71 namespace blaze {
72 
73 //=================================================================================================
74 //
75 // PLAIN ASSIGNMENT
76 //
77 //=================================================================================================
78 
79 //*************************************************************************************************
95 template< typename MT1 // Type of the left-hand side dense matrix
96  , bool SO1 // Storage order of the left-hand side dense matrix
97  , typename MT2 // Type of the right-hand side dense matrix
98  , bool SO2 > // Storage order of the right-hand side dense matrix
99 void smpAssign_backend( DenseMatrix<MT1,SO1>& lhs, const DenseMatrix<MT2,SO2>& rhs )
100 {
102 
103  BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
104 
105  typedef ElementType_<MT1> ET1;
106  typedef ElementType_<MT2> ET2;
107  typedef SubmatrixExprTrait_<MT1,aligned> AlignedTarget;
108  typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
109 
110  constexpr bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSIMDCombinable<ET1,ET2>::value );
111  constexpr size_t SIMDSIZE( SIMDTrait< ElementType_<MT1> >::size );
112 
113  const bool lhsAligned( (~lhs).isAligned() );
114  const bool rhsAligned( (~rhs).isAligned() );
115 
116  const int threads( omp_get_num_threads() );
117  const ThreadMapping threadmap( createThreadMapping( threads, ~rhs ) );
118 
119  const size_t addon1 ( ( ( (~rhs).rows() % threadmap.first ) != 0UL )? 1UL : 0UL );
120  const size_t equalShare1( (~rhs).rows() / threadmap.first + addon1 );
121  const size_t rest1 ( equalShare1 & ( SIMDSIZE - 1UL ) );
122  const size_t rowsPerThread( ( simdEnabled && rest1 )?( equalShare1 - rest1 + SIMDSIZE ):( equalShare1 ) );
123 
124  const size_t addon2 ( ( ( (~rhs).columns() % threadmap.second ) != 0UL )? 1UL : 0UL );
125  const size_t equalShare2( (~rhs).columns() / threadmap.second + addon2 );
126  const size_t rest2 ( equalShare2 & ( SIMDSIZE - 1UL ) );
127  const size_t colsPerThread( ( simdEnabled && rest2 )?( equalShare2 - rest2 + SIMDSIZE ):( equalShare2 ) );
128 
129 #pragma omp for schedule(dynamic,1) nowait
130  for( int i=0; i<threads; ++i )
131  {
132  const size_t row ( ( i / threadmap.second ) * rowsPerThread );
133  const size_t column( ( i % threadmap.second ) * colsPerThread );
134 
135  if( row >= (~rhs).rows() || column >= (~rhs).columns() )
136  continue;
137 
138  const size_t m( min( rowsPerThread, (~rhs).rows() - row ) );
139  const size_t n( min( colsPerThread, (~rhs).columns() - column ) );
140 
141  if( simdEnabled && lhsAligned && rhsAligned ) {
142  AlignedTarget target( submatrix<aligned>( ~lhs, row, column, m, n ) );
143  assign( target, submatrix<aligned>( ~rhs, row, column, m, n ) );
144  }
145  else if( simdEnabled && lhsAligned ) {
146  AlignedTarget target( submatrix<aligned>( ~lhs, row, column, m, n ) );
147  assign( target, submatrix<unaligned>( ~rhs, row, column, m, n ) );
148  }
149  else if( simdEnabled && rhsAligned ) {
150  UnalignedTarget target( submatrix<unaligned>( ~lhs, row, column, m, n ) );
151  assign( target, submatrix<aligned>( ~rhs, row, column, m, n ) );
152  }
153  else {
154  UnalignedTarget target( submatrix<unaligned>( ~lhs, row, column, m, n ) );
155  assign( target, submatrix<unaligned>( ~rhs, row, column, m, n ) );
156  }
157  }
158 }
160 //*************************************************************************************************
161 
162 
163 //*************************************************************************************************
179 template< typename MT1 // Type of the left-hand side dense matrix
180  , bool SO1 // Storage order of the left-hand side dense matrix
181  , typename MT2 // Type of the right-hand side sparse matrix
182  , bool SO2 > // Storage order of the right-hand side sparse matrix
183 void smpAssign_backend( DenseMatrix<MT1,SO1>& lhs, const SparseMatrix<MT2,SO2>& rhs )
184 {
186 
187  BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
188 
189  typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
190 
191  const size_t threads( omp_get_num_threads() );
192  const ThreadMapping threadmap( createThreadMapping( threads, ~rhs ) );
193 
194  const size_t addon1 ( ( ( (~rhs).rows() % threadmap.first ) != 0UL )? 1UL : 0UL );
195  const size_t rowsPerThread( (~rhs).rows() / threadmap.first + addon1 );
196 
197  const size_t addon2 ( ( ( (~rhs).columns() % threadmap.second ) != 0UL )? 1UL : 0UL );
198  const size_t colsPerThread( (~rhs).columns() / threadmap.second + addon2 );
199 
200 #pragma omp for schedule(dynamic,1) nowait
201  for( size_t i=0; i<threads; ++i )
202  {
203  const size_t row ( ( i / threadmap.second ) * rowsPerThread );
204  const size_t column( ( i % threadmap.second ) * colsPerThread );
205 
206  if( row >= (~rhs).rows() || column >= (~rhs).columns() )
207  continue;
208 
209  const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
210  const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
211 
212  UnalignedTarget target( submatrix<unaligned>( ~lhs, row, column, m, n ) );
213  assign( target, submatrix<unaligned>( ~rhs, row, column, m, n ) );
214  }
215 }
217 //*************************************************************************************************
218 
219 
220 //*************************************************************************************************
238 template< typename MT1 // Type of the left-hand side dense matrix
239  , bool SO1 // Storage order of the left-hand side dense matrix
240  , typename MT2 // Type of the right-hand side matrix
241  , bool SO2 > // Storage order of the right-hand side matrix
242 inline EnableIf_< And< IsDenseMatrix<MT1>
243  , Or< Not< IsSMPAssignable<MT1> >
244  , Not< IsSMPAssignable<MT2> > > > >
245  smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
246 {
248 
249  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
250  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
251 
252  assign( ~lhs, ~rhs );
253 }
255 //*************************************************************************************************
256 
257 
258 //*************************************************************************************************
276 template< typename MT1 // Type of the left-hand side dense matrix
277  , bool SO1 // Storage order of the left-hand side dense matrix
278  , typename MT2 // Type of the right-hand side matrix
279  , bool SO2 > // Storage order of the right-hand side matrix
280 inline EnableIf_< And< IsDenseMatrix<MT1>, IsSMPAssignable<MT1>, IsSMPAssignable<MT2> > >
281  smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
282 {
284 
285  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT1> );
286  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT2> );
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 
292  {
293  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
294  assign( ~lhs, ~rhs );
295  }
296  else {
297 #pragma omp parallel shared( lhs, rhs )
298  smpAssign_backend( ~lhs, ~rhs );
299  }
300  }
301 }
303 //*************************************************************************************************
304 
305 
306 
307 
308 //=================================================================================================
309 //
310 // ADDITION ASSIGNMENT
311 //
312 //=================================================================================================
313 
314 //*************************************************************************************************
330 template< typename MT1 // Type of the left-hand side dense matrix
331  , bool SO1 // Storage order of the left-hand side dense matrix
332  , typename MT2 // Type of the right-hand side dense matrix
333  , bool SO2 > // Storage order of the right-hand side dense matrix
334 void smpAddAssign_backend( DenseMatrix<MT1,SO1>& lhs, const DenseMatrix<MT2,SO2>& rhs )
335 {
337 
338  BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
339 
340  typedef ElementType_<MT1> ET1;
341  typedef ElementType_<MT2> ET2;
342  typedef SubmatrixExprTrait_<MT1,aligned> AlignedTarget;
343  typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
344 
345  constexpr bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSIMDCombinable<ET1,ET2>::value );
346  constexpr size_t SIMDSIZE( SIMDTrait< ElementType_<MT1> >::size );
347 
348  const bool lhsAligned( (~lhs).isAligned() );
349  const bool rhsAligned( (~rhs).isAligned() );
350 
351  const int threads( omp_get_num_threads() );
352  const ThreadMapping threadmap( createThreadMapping( threads, ~rhs ) );
353 
354  const size_t addon1 ( ( ( (~rhs).rows() % threadmap.first ) != 0UL )? 1UL : 0UL );
355  const size_t equalShare1( (~rhs).rows() / threadmap.first + addon1 );
356  const size_t rest1 ( equalShare1 & ( SIMDSIZE - 1UL ) );
357  const size_t rowsPerThread( ( simdEnabled && rest1 )?( equalShare1 - rest1 + SIMDSIZE ):( equalShare1 ) );
358 
359  const size_t addon2 ( ( ( (~rhs).columns() % threadmap.second ) != 0UL )? 1UL : 0UL );
360  const size_t equalShare2( (~rhs).columns() / threadmap.second + addon2 );
361  const size_t rest2 ( equalShare2 & ( SIMDSIZE - 1UL ) );
362  const size_t colsPerThread( ( simdEnabled && rest2 )?( equalShare2 - rest2 + SIMDSIZE ):( equalShare2 ) );
363 
364 #pragma omp for schedule(dynamic,1) nowait
365  for( int i=0; i<threads; ++i )
366  {
367  const size_t row ( ( i / threadmap.second ) * rowsPerThread );
368  const size_t column( ( i % threadmap.second ) * colsPerThread );
369 
370  if( row >= (~rhs).rows() || column >= (~rhs).columns() )
371  continue;
372 
373  const size_t m( min( rowsPerThread, (~rhs).rows() - row ) );
374  const size_t n( min( colsPerThread, (~rhs).columns() - column ) );
375 
376  if( simdEnabled && lhsAligned && rhsAligned ) {
377  AlignedTarget target( submatrix<aligned>( ~lhs, row, column, m, n ) );
378  addAssign( target, submatrix<aligned>( ~rhs, row, column, m, n ) );
379  }
380  else if( simdEnabled && lhsAligned ) {
381  AlignedTarget target( submatrix<aligned>( ~lhs, row, column, m, n ) );
382  addAssign( target, submatrix<unaligned>( ~rhs, row, column, m, n ) );
383  }
384  else if( simdEnabled && rhsAligned ) {
385  UnalignedTarget target( submatrix<unaligned>( ~lhs, row, column, m, n ) );
386  addAssign( target, submatrix<aligned>( ~rhs, row, column, m, n ) );
387  }
388  else {
389  UnalignedTarget target( submatrix<unaligned>( ~lhs, row, column, m, n ) );
390  addAssign( target, submatrix<unaligned>( ~rhs, row, column, m, n ) );
391  }
392  }
393 }
395 //*************************************************************************************************
396 
397 
398 //*************************************************************************************************
414 template< typename MT1 // Type of the left-hand side dense matrix
415  , bool SO1 // Storage order of the left-hand side dense matrix
416  , typename MT2 // Type of the right-hand side sparse matrix
417  , bool SO2 > // Storage order of the right-hand side sparse matrix
418 void smpAddAssign_backend( DenseMatrix<MT1,SO1>& lhs, const SparseMatrix<MT2,SO2>& rhs )
419 {
421 
422  BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
423 
424  typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
425 
426  const size_t threads( omp_get_num_threads() );
427  const ThreadMapping threadmap( createThreadMapping( threads, ~rhs ) );
428 
429  const size_t addon1 ( ( ( (~rhs).rows() % threadmap.first ) != 0UL )? 1UL : 0UL );
430  const size_t rowsPerThread( (~rhs).rows() / threadmap.first + addon1 );
431 
432  const size_t addon2 ( ( ( (~rhs).columns() % threadmap.second ) != 0UL )? 1UL : 0UL );
433  const size_t colsPerThread( (~rhs).columns() / threadmap.second + addon2 );
434 
435 #pragma omp for schedule(dynamic,1) nowait
436  for( size_t i=0; i<threads; ++i )
437  {
438  const size_t row ( ( i / threadmap.second ) * rowsPerThread );
439  const size_t column( ( i % threadmap.second ) * colsPerThread );
440 
441  if( row >= (~rhs).rows() || column >= (~rhs).columns() )
442  continue;
443 
444  const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
445  const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
446 
447  UnalignedTarget target( submatrix<unaligned>( ~lhs, row, column, m, n ) );
448  addAssign( target, submatrix<unaligned>( ~rhs, row, column, m, n ) );
449  }
450 }
452 //*************************************************************************************************
453 
454 
455 //*************************************************************************************************
473 template< typename MT1 // Type of the left-hand side dense matrix
474  , bool SO1 // Storage order of the left-hand side dense matrix
475  , typename MT2 // Type of the right-hand side matrix
476  , bool SO2 > // Storage order of the right-hand side matrix
477 inline EnableIf_< And< IsDenseMatrix<MT1>
478  , Or< Not< IsSMPAssignable<MT1> >
479  , Not< IsSMPAssignable<MT2> > > > >
480  smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
481 {
483 
484  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
485  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
486 
487  addAssign( ~lhs, ~rhs );
488 }
490 //*************************************************************************************************
491 
492 
493 //*************************************************************************************************
511 template< typename MT1 // Type of the left-hand side dense matrix
512  , bool SO1 // Storage order of the left-hand side dense matrix
513  , typename MT2 // Type of the right-hand side matrix
514  , bool SO2 > // Storage order of the right-hand side matrix
515 inline EnableIf_< And< IsDenseMatrix<MT1>, IsSMPAssignable<MT1>, IsSMPAssignable<MT2> > >
516  smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
517 {
519 
520  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT1> );
521  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT2> );
522 
523  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
524  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
525 
527  {
528  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
529  addAssign( ~lhs, ~rhs );
530  }
531  else {
532 #pragma omp parallel shared( lhs, rhs )
533  smpAddAssign_backend( ~lhs, ~rhs );
534  }
535  }
536 }
538 //*************************************************************************************************
539 
540 
541 
542 
543 //=================================================================================================
544 //
545 // SUBTRACTION ASSIGNMENT
546 //
547 //=================================================================================================
548 
549 //*************************************************************************************************
565 template< typename MT1 // Type of the left-hand side dense matrix
566  , bool SO1 // Storage order of the left-hand side dense matrix
567  , typename MT2 // Type of the right-hand side dense matrix
568  , bool SO2 > // Storage order of the right-hand side dense matrix
569 void smpSubAssign_backend( DenseMatrix<MT1,SO1>& lhs, const DenseMatrix<MT2,SO2>& rhs )
570 {
572 
573  BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
574 
575  typedef ElementType_<MT1> ET1;
576  typedef ElementType_<MT2> ET2;
577  typedef SubmatrixExprTrait_<MT1,aligned> AlignedTarget;
578  typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
579 
580  constexpr bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSIMDCombinable<ET1,ET2>::value );
581  constexpr size_t SIMDSIZE( SIMDTrait< ElementType_<MT1> >::size );
582 
583  const bool lhsAligned( (~lhs).isAligned() );
584  const bool rhsAligned( (~rhs).isAligned() );
585 
586  const int threads( omp_get_num_threads() );
587  const ThreadMapping threadmap( createThreadMapping( threads, ~rhs ) );
588 
589  const size_t addon1 ( ( ( (~rhs).rows() % threadmap.first ) != 0UL )? 1UL : 0UL );
590  const size_t equalShare1( (~rhs).rows() / threadmap.first + addon1 );
591  const size_t rest1 ( equalShare1 & ( SIMDSIZE - 1UL ) );
592  const size_t rowsPerThread( ( simdEnabled && rest1 )?( equalShare1 - rest1 + SIMDSIZE ):( equalShare1 ) );
593 
594  const size_t addon2 ( ( ( (~rhs).columns() % threadmap.second ) != 0UL )? 1UL : 0UL );
595  const size_t equalShare2( (~rhs).columns() / threadmap.second + addon2 );
596  const size_t rest2 ( equalShare2 & ( SIMDSIZE - 1UL ) );
597  const size_t colsPerThread( ( simdEnabled && rest2 )?( equalShare2 - rest2 + SIMDSIZE ):( equalShare2 ) );
598 
599 #pragma omp for schedule(dynamic,1) nowait
600  for( int i=0; i<threads; ++i )
601  {
602  const size_t row ( ( i / threadmap.second ) * rowsPerThread );
603  const size_t column( ( i % threadmap.second ) * colsPerThread );
604 
605  if( row >= (~rhs).rows() || column >= (~rhs).columns() )
606  continue;
607 
608  const size_t m( min( rowsPerThread, (~rhs).rows() - row ) );
609  const size_t n( min( colsPerThread, (~rhs).columns() - column ) );
610 
611  if( simdEnabled && lhsAligned && rhsAligned ) {
612  AlignedTarget target( submatrix<aligned>( ~lhs, row, column, m, n ) );
613  subAssign( target, submatrix<aligned>( ~rhs, row, column, m, n ) );
614  }
615  else if( simdEnabled && lhsAligned ) {
616  AlignedTarget target( submatrix<aligned>( ~lhs, row, column, m, n ) );
617  subAssign( target, submatrix<unaligned>( ~rhs, row, column, m, n ) );
618  }
619  else if( simdEnabled && rhsAligned ) {
620  UnalignedTarget target( submatrix<unaligned>( ~lhs, row, column, m, n ) );
621  subAssign( target, submatrix<aligned>( ~rhs, row, column, m, n ) );
622  }
623  else {
624  UnalignedTarget target( submatrix<unaligned>( ~lhs, row, column, m, n ) );
625  subAssign( target, submatrix<unaligned>( ~rhs, row, column, m, n ) );
626  }
627  }
628 }
630 //*************************************************************************************************
631 
632 
633 //*************************************************************************************************
650 template< typename MT1 // Type of the left-hand side dense matrix
651  , bool SO1 // Storage order of the left-hand side dense matrix
652  , typename MT2 // Type of the right-hand side sparse matrix
653  , bool SO2 > // Storage order of the right-hand side sparse matrix
654 void smpSubAssign_backend( DenseMatrix<MT1,SO1>& lhs, const SparseMatrix<MT2,SO2>& rhs )
655 {
657 
658  BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
659 
660  typedef SubmatrixExprTrait_<MT1,unaligned> UnalignedTarget;
661 
662  const size_t threads( omp_get_num_threads() );
663  const ThreadMapping threadmap( createThreadMapping( threads, ~rhs ) );
664 
665  const size_t addon1 ( ( ( (~rhs).rows() % threadmap.first ) != 0UL )? 1UL : 0UL );
666  const size_t rowsPerThread( (~rhs).rows() / threadmap.first + addon1 );
667 
668  const size_t addon2 ( ( ( (~rhs).columns() % threadmap.second ) != 0UL )? 1UL : 0UL );
669  const size_t colsPerThread( (~rhs).columns() / threadmap.second + addon2 );
670 
671 #pragma omp for schedule(dynamic,1) nowait
672  for( size_t i=0; i<threads; ++i )
673  {
674  const size_t row ( ( i / threadmap.second ) * rowsPerThread );
675  const size_t column( ( i % threadmap.second ) * colsPerThread );
676 
677  if( row >= (~rhs).rows() || column >= (~rhs).columns() )
678  continue;
679 
680  const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
681  const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
682 
683  UnalignedTarget target( submatrix<unaligned>( ~lhs, row, column, m, n ) );
684  subAssign( target, submatrix<unaligned>( ~rhs, row, column, m, n ) );
685  }
686 }
688 //*************************************************************************************************
689 
690 
691 //*************************************************************************************************
709 template< typename MT1 // Type of the left-hand side dense matrix
710  , bool SO1 // Storage order of the left-hand side dense matrix
711  , typename MT2 // Type of the right-hand side matrix
712  , bool SO2 > // Storage order of the right-hand side matrix
713 inline EnableIf_< And< IsDenseMatrix<MT1>
714  , Or< Not< IsSMPAssignable<MT1> >
715  , Not< IsSMPAssignable<MT2> > > > >
716  smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
717 {
719 
720  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
721  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
722 
723  subAssign( ~lhs, ~rhs );
724 }
726 //*************************************************************************************************
727 
728 
729 //*************************************************************************************************
747 template< typename MT1 // Type of the left-hand side dense matrix
748  , bool SO1 // Storage order of the left-hand side dense matrix
749  , typename MT2 // Type of the right-hand side matrix
750  , bool SO2 > // Storage order of the right-hand side matrix
751 inline EnableIf_< And< IsDenseMatrix<MT1>, IsSMPAssignable<MT1>, IsSMPAssignable<MT2> > >
752  smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
753 {
755 
756  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT1> );
757  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT2> );
758 
759  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
760  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
761 
763  {
764  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
765  subAssign( ~lhs, ~rhs );
766  }
767  else {
768 #pragma omp parallel shared( lhs, rhs )
769  smpSubAssign_backend( ~lhs, ~rhs );
770  }
771  }
772 }
774 //*************************************************************************************************
775 
776 
777 
778 
779 //=================================================================================================
780 //
781 // MULTIPLICATION ASSIGNMENT
782 //
783 //=================================================================================================
784 
785 //*************************************************************************************************
801 template< typename MT1 // Type of the left-hand side dense matrix
802  , bool SO1 // Storage order of the left-hand side matrix
803  , typename MT2 // Type of the right-hand side matrix
804  , bool SO2 > // Storage order of the right-hand side matrix
805 inline EnableIf_< IsDenseMatrix<MT1> >
806  smpMultAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
807 {
809 
810  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
811  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
812 
813  multAssign( ~lhs, ~rhs );
814 }
816 //*************************************************************************************************
817 
818 
819 
820 
821 //=================================================================================================
822 //
823 // COMPILE TIME CONSTRAINT
824 //
825 //=================================================================================================
826 
827 //*************************************************************************************************
829 namespace {
830 
832 
833 }
835 //*************************************************************************************************
836 
837 } // namespace blaze
838 
839 #endif
Header file for the implementation of the Submatrix view.
Header file for auxiliary alias declarations.
Header file for mathematical functions.
Header file for the alignment flag values.
Header file for basic type definitions.
EnableIf_< IsDenseMatrix< MT1 > > smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:160
BLAZE_ALWAYS_INLINE size_t size(const Vector< VT, TF > &vector) noexcept
Returns the current size/dimension of the vector.
Definition: Vector.h:261
EnableIf_< IsDenseVector< VT1 > > smpMultAssign(Vector< VT1, TF1 > &lhs, const Vector< VT2, TF2 > &rhs)
Default implementation of the SMP multiplication assignment of a vector to a dense vector...
Definition: DenseVector.h:193
Header file for the And class template.
const ElementType_< MT > min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1755
Header file for the SIMD trait.
EnableIf_< IsDenseMatrix< MT1 > > smpAddAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:129
Header file for the SparseMatrix base class.
Header file for the SMP thread mapping functionality.
Header file for the matrix storage order types.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE(T)
Constraint on the data type.In case the given data type T is SMP-assignable (can be assigned by multi...
Definition: SMPAssignable.h:81
Namespace of the Blaze C++ math library.
Definition: Blaze.h:57
Compile time assertion.
System settings for the shared-memory parallelization.
Header file for the IsSMPAssignable type trait.
EnableIf_< IsDenseMatrix< MT1 > > smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:98
Header file for the Or class template.
Header file for the DenseMatrix base class.
Header file for the Not class template.
BLAZE_ALWAYS_INLINE size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:336
Header file for the serial section implementation.
DisableIf_< Or< IsComputation< MT >, IsTransExpr< MT >, IsDeclExpr< MT > >, RowExprTrait_< MT > > row(Matrix< MT, SO > &matrix, size_t index)
Creating a view on a specific row of the given matrix.
Definition: Row.h:128
Header file for the parallel section implementation.
Header file for the IsDenseMatrix type trait.
DisableIf_< Or< IsComputation< MT >, IsTransExpr< MT >, IsDeclExpr< MT > >, ColumnExprTrait_< MT > > column(Matrix< MT, SO > &matrix, size_t index)
Creating a view on a specific column of the given matrix.
Definition: Column.h:128
Header file for the EnableIf class template.
#define BLAZE_PARALLEL_SECTION
Section for the debugging of the shared-memory parallelization.During the shared-memory parallel (SMP...
Definition: ParallelSection.h:246
bool isSerialSectionActive()
Returns whether a serial section is active or not.
Definition: SerialSection.h:213
Header file for the IsSIMDCombinable type trait.
Header file for the SubmatrixExprTrait class template.
Header file for run time assertion macros.
#define BLAZE_FUNCTION_TRACE
Function trace macro.This macro can be used to reliably trace function calls. In case function tracin...
Definition: FunctionTrace.h:93
BLAZE_ALWAYS_INLINE size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:320
bool isParallelSectionActive()
Returns whether a parallel section is active or not.
Definition: ParallelSection.h:213
#define BLAZE_OPENMP_PARALLEL_MODE
Compilation switch for the OpenMP parallelization.This compilation switch enables/disables the OpenMP...
Definition: SMP.h:67
#define BLAZE_STATIC_ASSERT(expr)
Compile time assertion macro.In case of an invalid compile time expression, a compilation error is cr...
Definition: StaticAssert.h:112
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
Constraint on the data type.
Header file for the function trace functionality.