Blaze  3.6
DenseVector.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_SMP_HPX_DENSEVECTOR_H_
36 #define _BLAZE_MATH_SMP_HPX_DENSEVECTOR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <hpx/include/parallel_for_loop.hpp>
44 #include <blaze/math/Aliases.h>
55 #include <blaze/system/SMP.h>
57 #include <blaze/util/Assert.h>
58 #include <blaze/util/EnableIf.h>
61 #include <blaze/util/Types.h>
62 
63 
64 namespace blaze {
65 
66 //=================================================================================================
67 //
68 // HPX-BASED ASSIGNMENT KERNELS
69 //
70 //=================================================================================================
71 
72 //*************************************************************************************************
89 template< typename VT1 // Type of the left-hand side dense vector
90  , bool TF1 // Transpose flag of the left-hand side dense vector
91  , typename VT2 // Type of the right-hand side dense vector
92  , bool TF2 // Transpose flag of the right-hand side dense vector
93  , typename OP > // Type of the assignment operation
94 void hpxAssign( DenseVector<VT1,TF1>& lhs, const DenseVector<VT2,TF2>& rhs, OP op )
95 {
96  using hpx::parallel::for_loop;
97  using hpx::parallel::execution::par;
98 
100 
101  using ET1 = ElementType_t<VT1>;
102  using ET2 = ElementType_t<VT2>;
103 
104  constexpr bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSIMDCombinable_v<ET1,ET2> );
105  constexpr size_t SIMDSIZE( SIMDTrait< ElementType_t<VT1> >::size );
106 
107  const bool lhsAligned( (~lhs).isAligned() );
108  const bool rhsAligned( (~rhs).isAligned() );
109 
110  const size_t threads ( getNumThreads() );
111  const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
112  const size_t equalShare ( (~lhs).size() / threads + addon );
113  const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
114  const size_t sizePerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
115 
116  for_loop( par, size_t(0), threads, [&](int i)
117  {
118  const size_t index( i*sizePerThread );
119 
120  if( index >= (~lhs).size() )
121  return;
122 
123  const size_t size( min( sizePerThread, (~lhs).size() - index ) );
124 
125  if( simdEnabled && lhsAligned && rhsAligned ) {
126  auto target( subvector<aligned>( ~lhs, index, size, unchecked ) );
127  const auto source( subvector<aligned>( ~rhs, index, size, unchecked ) );
128  op( target, source );
129  }
130  else if( simdEnabled && lhsAligned ) {
131  auto target( subvector<aligned>( ~lhs, index, size, unchecked ) );
132  const auto source( subvector<unaligned>( ~rhs, index, size, unchecked ) );
133  op( target, source );
134  }
135  else if( simdEnabled && rhsAligned ) {
136  auto target( subvector<unaligned>( ~lhs, index, size, unchecked ) );
137  const auto source( subvector<aligned>( ~rhs, index, size, unchecked ) );
138  op( target, source );
139  }
140  else {
141  auto target( subvector<unaligned>( ~lhs, index, size, unchecked ) );
142  const auto source( subvector<unaligned>( ~rhs, index, size, unchecked ) );
143  op( target, source );
144  }
145  } );
146 }
148 //*************************************************************************************************
149 
150 
151 //*************************************************************************************************
168 template< typename VT1 // Type of the left-hand side dense vector
169  , bool TF1 // Transpose flag of the left-hand side dense vector
170  , typename VT2 // Type of the right-hand side sparse vector
171  , bool TF2 // Transpose flag of the right-hand side sparse vector
172  , typename OP > // Type of the assignment operation
173 void hpxAssign( DenseVector<VT1,TF1>& lhs, const SparseVector<VT2,TF2>& rhs, OP op )
174 {
175  using hpx::parallel::for_loop;
176  using hpx::parallel::execution::par;
177 
179 
180  const size_t threads ( getNumThreads() );
181  const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
182  const size_t sizePerThread( (~lhs).size() / threads + addon );
183 
184  for_loop( par, size_t(0), threads, [&](int i)
185  {
186  const size_t index( i*sizePerThread );
187 
188  if( index < (~lhs).size() )
189  return;
190 
191  const size_t size( min( sizePerThread, (~lhs).size() - index ) );
192  auto target( subvector<unaligned>( ~lhs, index, size, unchecked ) );
193  const auto source( subvector<unaligned>( ~rhs, index, size, unchecked ) );
194  op( target, source );
195  } );
196 }
198 //*************************************************************************************************
199 
200 
201 
202 
203 //=================================================================================================
204 //
205 // PLAIN ASSIGNMENT
206 //
207 //=================================================================================================
208 
209 //*************************************************************************************************
227 template< typename VT1 // Type of the left-hand side dense vector
228  , bool TF1 // Transpose flag of the left-hand side dense vector
229  , typename VT2 // Type of the right-hand side vector
230  , bool TF2 > // Transpose flag of the right-hand side vector
231 inline auto smpAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
232  -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
233 {
235 
236  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
237 
238  assign( ~lhs, ~rhs );
239 }
241 //*************************************************************************************************
242 
243 
244 //*************************************************************************************************
262 template< typename VT1 // Type of the left-hand side dense vector
263  , bool TF1 // Transpose flag of the left-hand side dense vector
264  , typename VT2 // Type of the right-hand side vector
265  , bool TF2 > // Transpose flag of the right-hand side vector
266 inline auto smpAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
267  -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
268 {
270 
271  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT1> );
272  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT2> );
273 
274  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
275 
276  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
277  assign( ~lhs, ~rhs );
278  }
279  else {
280  hpxAssign( ~lhs, ~rhs, []( auto& a, const auto& b ){ assign( a, b ); } );
281  }
282 }
284 //*************************************************************************************************
285 
286 
287 
288 
289 //=================================================================================================
290 //
291 // ADDITION ASSIGNMENT
292 //
293 //=================================================================================================
294 
295 //*************************************************************************************************
313 template< typename VT1 // Type of the left-hand side dense vector
314  , bool TF1 // Transpose flag of the left-hand side dense vector
315  , typename VT2 // Type of the right-hand side vector
316  , bool TF2 > // Transpose flag of the right-hand side vector
317 inline auto smpAddAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
318  -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
319 {
321 
322  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
323 
324  addAssign( ~lhs, ~rhs );
325 }
327 //*************************************************************************************************
328 
329 
330 //*************************************************************************************************
348 template< typename VT1 // Type of the left-hand side dense vector
349  , bool TF1 // Transpose flag of the left-hand side dense vector
350  , typename VT2 // Type of the right-hand side vector
351  , bool TF2 > // Transpose flag of the right-hand side vector
352 inline auto smpAddAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
353  -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
354 {
356 
357  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT1> );
358  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT2> );
359 
360  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
361 
362  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
363  addAssign( ~lhs, ~rhs );
364  }
365  else {
366  hpxAssign( ~lhs, ~rhs, []( auto& a, const auto& b ){ addAssign( a, b ); } );
367  }
368 }
370 //*************************************************************************************************
371 
372 
373 
374 
375 //=================================================================================================
376 //
377 // SUBTRACTION ASSIGNMENT
378 //
379 //=================================================================================================
380 
381 //*************************************************************************************************
399 template< typename VT1 // Type of the left-hand side dense vector
400  , bool TF1 // Transpose flag of the left-hand side dense vector
401  , typename VT2 // Type of the right-hand side vector
402  , bool TF2 > // Transpose flag of the right-hand side vector
403 inline auto smpSubAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
404  -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
405 {
407 
408  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
409 
410  subAssign( ~lhs, ~rhs );
411 }
413 //*************************************************************************************************
414 
415 
416 //*************************************************************************************************
434 template< typename VT1 // Type of the left-hand side dense vector
435  , bool TF1 // Transpose flag of the left-hand side dense vector
436  , typename VT2 // Type of the right-hand side vector
437  , bool TF2 > // Transpose flag of the right-hand side vector
438 inline auto smpSubAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
439  -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
440 {
442 
443  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT1> );
444  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT2> );
445 
446  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
447 
448  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
449  subAssign( ~lhs, ~rhs );
450  }
451  else {
452  hpxAssign( ~lhs, ~rhs, []( auto& a, const auto& b ){ subAssign( a, b ); } );
453  }
454 }
456 //*************************************************************************************************
457 
458 
459 
460 
461 //=================================================================================================
462 //
463 // MULTIPLICATION ASSIGNMENT
464 //
465 //=================================================================================================
466 
467 //*************************************************************************************************
485 template< typename VT1 // Type of the left-hand side dense vector
486  , bool TF1 // Transpose flag of the left-hand side dense vector
487  , typename VT2 // Type of the right-hand side vector
488  , bool TF2 > // Transpose flag of the right-hand side vector
489 inline auto smpMultAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
490  -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
491 {
493 
494  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
495 
496  multAssign( ~lhs, ~rhs );
497 }
499 //*************************************************************************************************
500 
501 
502 //*************************************************************************************************
520 template< typename VT1 // Type of the left-hand side dense vector
521  , bool TF1 // Transpose flag of the left-hand side dense vector
522  , typename VT2 // Type of the right-hand side vector
523  , bool TF2 > // Transpose flag of the right-hand side vector
524 inline auto smpMultAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
525  -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
526 {
528 
529  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT1> );
530  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT2> );
531 
532  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
533 
534  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
535  multAssign( ~lhs, ~rhs );
536  }
537  else {
538  hpxAssign( ~lhs, ~rhs, []( auto& a, const auto& b ){ multAssign( a, b ); } );
539  }
540 }
542 //*************************************************************************************************
543 
544 
545 
546 
547 //=================================================================================================
548 //
549 // DIVISION ASSIGNMENT
550 //
551 //=================================================================================================
552 
553 //*************************************************************************************************
571 template< typename VT1 // Type of the left-hand side dense vector
572  , bool TF1 // Transpose flag of the left-hand side dense vector
573  , typename VT2 // Type of the right-hand side vector
574  , bool TF2 > // Transpose flag of the right-hand side vector
575 inline auto smpDivAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
576  -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
577 {
579 
580  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
581 
582  divAssign( ~lhs, ~rhs );
583 }
585 //*************************************************************************************************
586 
587 
588 //*************************************************************************************************
606 template< typename VT1 // Type of the left-hand side dense vector
607  , bool TF1 // Transpose flag of the left-hand side dense vector
608  , typename VT2 // Type of the right-hand side vector
609  , bool TF2 > // Transpose flag of the right-hand side vector
610 inline auto smpDivAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
611  -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
612 {
614 
615  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT1> );
616  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT2> );
617 
618  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
619 
620  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
621  divAssign( ~lhs, ~rhs );
622  }
623  else {
624  hpxAssign( ~lhs, ~rhs, []( auto& a, const auto& b ){ divAssign( a, b ); } );
625  }
626 }
628 //*************************************************************************************************
629 
630 
631 
632 
633 //=================================================================================================
634 //
635 // COMPILE TIME CONSTRAINTS
636 //
637 //=================================================================================================
638 
639 //*************************************************************************************************
641 namespace {
642 
644 
645 }
647 //*************************************************************************************************
648 
649 } // namespace blaze
650 
651 #endif
Header file for auxiliary alias declarations.
Headerfile for the generic min algorithm.
Header file for basic type definitions.
Header file for the SparseVector base class.
constexpr Unchecked unchecked
Global Unchecked instance.The blaze::unchecked instance is an optional token for the creation of view...
Definition: Check.h:138
Header file for the DenseVector base class.
Header file for the SIMD trait.
auto smpDivAssign(Vector< VT1, TF1 > &lhs, const Vector< VT2, TF2 > &rhs) -> EnableIf_t< IsDenseVector_v< VT1 > >
Default implementation of the SMP division assignment of a vector to a dense vector.
Definition: DenseVector.h:220
#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
#define BLAZE_HPX_PARALLEL_MODE
Compilation switch for the HPX parallelization.This compilation switch enables/disables the paralleli...
Definition: SMP.h:96
Header file for the implementation of the Subvector view.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:58
Compile time assertion.
System settings for the shared-memory parallelization.
Header file for the IsSMPAssignable type trait.
decltype(auto) min(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the componentwise minimum of the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1162
Header file for the serial section implementation.
Header file for the EnableIf class template.
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 run time assertion macros.
auto smpAddAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:131
#define BLAZE_FUNCTION_TRACE
Function trace macro.This macro can be used to reliably trace function calls. In case function tracin...
Definition: FunctionTrace.h:94
constexpr size_t size(const Matrix< MT, SO > &matrix) noexcept
Returns the total number of elements of the matrix.
Definition: Matrix.h:530
auto smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:100
Header file for the IsDenseVector type trait.
auto smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:162
Header file for SMP utility functions.
#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,...
Definition: Assert.h:101
auto smpMultAssign(Vector< VT1, TF1 > &lhs, const Vector< VT2, TF2 > &rhs) -> EnableIf_t< IsDenseVector_v< VT1 > >
Default implementation of the SMP multiplication assignment of a vector to a dense vector.
Definition: DenseVector.h:191
BLAZE_ALWAYS_INLINE size_t getNumThreads()
Returns the number of threads used for thread parallel operations.
Definition: Functions.h:77
Constraint on the data type.
Header file for the function trace functionality.