• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

STEllAR-GROUP / hpx / #851

16 Dec 2022 12:27PM CUT coverage: 86.568% (+0.2%) from 86.404%
#851

push

StellarBot
Merge #6104

6104: Adding parameters API: measure_iteration r=hkaiser a=hkaiser

- split `get_chunk_size` CP into `measure_iteration` and modified `get_chunk_size`
- introducing a breaking change to `get_chunk_size` and `processing_units_count` customization point, those now expect the time for one iteration

The new APIs are:
```
    template <typename Target, typename F>
    hpx::chrono::steady_duration measure_iteration(
        Target&&, F&&, std::size_t num_tasks);

    template <typename Target>
    std::size_t processing_units_count(
        Target&&, hpx::chrono::steady_duration const&, std::size_t num_tasks);

    template <typename Target>
    std::size_t get_chunk_size(Target&&,
        hpx::chrono::steady_duration const&, std::size_t num_cores,
        std::size_t num_tasks);
```
This also moves all executor parameter objects to `namespace hpx::execution::experimental`. 

Co-authored-by: Hartmut Kaiser <hartmut.kaiser@gmail.com>

209 of 209 new or added lines in 34 files covered. (100.0%)

174475 of 201546 relevant lines covered (86.57%)

1888115.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.41
/libs/core/algorithms/include/hpx/parallel/algorithms/partial_sort.hpp
1
//  Copyright (c) 2020 Francisco Jose Tapia
2
//  Copyright (c) 2021 Akhil J Nair
3
//
4
//  SPDX-License-Identifier: BSL-1.0
5
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
6
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7

8
/// \file parallel/algorithms/partial_sort.hpp
9

10
#pragma once
11

12
#if defined(DOXYGEN)
13
namespace hpx {
14
    // clang-format off
15

16
    ///////////////////////////////////////////////////////////////////////////
17
    /// Places the first middle - first elements from the range [first, last)
18
    /// as sorted with respect to comp into the range [first, middle). The rest
19
    /// of the elements in the range [middle, last) are placed in an unspecified
20
    /// order.
21
    ///
22
    /// \note   Complexity: Approximately (last - first) * log(middle - first)
23
    ///         comparisons.
24
    ///
25
    /// \tparam RandIter    The type of the source begin, middle, and end
26
    ///                     iterators used (deduced). This iterator type must
27
    ///                     meet the requirements of a random access iterator.
28
    /// \tparam Comp        The type of the function/function object to use
29
    ///                     (deduced). Comp defaults to detail::less.
30
    ///
31
    /// \param first        Refers to the beginning of the sequence of elements
32
    ///                     the algorithm will be applied to.
33
    /// \param middle       Refers to the middle of the sequence of elements
34
    ///                     the algorithm will be applied to.
35
    /// \param last         Refers to the end of the sequence of elements the
36
    ///                     algorithm will be applied to.
37
    /// \param comp         comp is a callable object. The return value of the
38
    ///                     INVOKE operation applied to an object of type Comp,
39
    ///                     when contextually converted to bool, yields true if
40
    ///                     the first argument of the call is less than the
41
    ///                     second, and false otherwise. It is assumed that
42
    ///                     comp will not apply any non-constant function
43
    ///                     through the dereferenced iterator. It defaults to
44
    ///                     detail::less.
45
    ///
46
    /// \returns  The \a partial_sort algorithm returns a \a RandIter
47
    ///           that refers to \a last.
48
    ///
49
    template <typename RandIter, typename Comp = hpx::parallel::v1::detail::less>
50
    RandIter partial_sort(RandIter first, RandIter middle, RandIter last,
51
        Comp&& comp = Comp());
52

53
    ///////////////////////////////////////////////////////////////////////////
54
    /// Places the first middle - first elements from the range [first, last)
55
    /// as sorted with respect to comp into the range [first, middle). The rest
56
    /// of the elements in the range [middle, last) are placed in an unspecified
57
    /// order.
58
    ///
59
    /// \note   Complexity: Approximately (last - first) * log(middle - first)
60
    ///         comparisons.
61
    ///
62
    /// \tparam ExPolicy    The type of the execution policy to use (deduced).
63
    ///                     It describes the manner in which the execution
64
    ///                     of the algorithm may be parallelized and the manner
65
    ///                     in which it applies user-provided function objects.
66
    /// \tparam RandIter    The type of the source begin, middle, and end
67
    ///                     iterators used (deduced). This iterator type must
68
    ///                     meet the requirements of a random access iterator.
69
    /// \tparam Comp        The type of the function/function object to use
70
    ///                     (deduced). Comp defaults to detail::less.
71
    ///
72
    /// \param policy       The execution policy to use for the scheduling of
73
    ///                     the iterations.
74
    /// \param first        Refers to the beginning of the sequence of elements
75
    ///                     the algorithm will be applied to.
76
    /// \param middle       Refers to the middle of the sequence of elements
77
    ///                     the algorithm will be applied to.
78
    /// \param last         Refers to the end of the sequence of elements the
79
    ///                     algorithm will be applied to.
80
    /// \param comp         comp is a callable object. The return value of the
81
    ///                     INVOKE operation applied to an object of type Comp,
82
    ///                     when contextually converted to bool, yields true if
83
    ///                     the first argument of the call is less than the
84
    ///                     second, and false otherwise. It is assumed that
85
    ///                     comp will not apply any non-constant function
86
    ///                     through the dereferenced iterator. It defaults to
87
    ///                     detail::less.
88
    ///
89
    /// \returns  The \a partial_sort algorithm returns a
90
    ///           \a hpx::future<RandIter> if the execution policy is of
91
    ///           type \a sequenced_task_policy or
92
    ///           \a parallel_task_policy and returns \a RandIter otherwise.
93
    ///           The iterator returned refers to \a last.
94
    ///
95
    template <typename ExPolicy, typename RandIter,
96
        typename Comp = hpx::parallel::v1::detail::less>
97
    parallel::util::detail::algorithm_result_t<ExPolicy, RandIter> partial_sort(
98
        ExPolicy&& policy, RandIter first, RandIter middle, RandIter last,
99
        Comp&& comp = Comp());
100

101
    // clang-format on
102
}    // namespace hpx
103

104
#else
105

106
#include <hpx/config.hpp>
107
#include <hpx/assert.hpp>
108
#include <hpx/async_local/dataflow.hpp>
109
#include <hpx/concepts/concepts.hpp>
110
#include <hpx/functional/invoke.hpp>
111
#include <hpx/iterator_support/traits/is_iterator.hpp>
112
#include <hpx/parallel/util/detail/sender_util.hpp>
113
#include <hpx/type_support/decay.hpp>
114

115
#include <hpx/algorithms/traits/projected.hpp>
116
#include <hpx/execution/algorithms/detail/predicates.hpp>
117
#include <hpx/execution/executors/execution.hpp>
118
#include <hpx/execution/executors/execution_information.hpp>
119
#include <hpx/execution/executors/execution_parameters.hpp>
120
#include <hpx/executors/exception_list.hpp>
121
#include <hpx/executors/execution_policy.hpp>
122
#include <hpx/parallel/algorithms/detail/dispatch.hpp>
123
#include <hpx/parallel/algorithms/detail/distance.hpp>
124
#include <hpx/parallel/algorithms/detail/is_sorted.hpp>
125
#include <hpx/parallel/algorithms/sort.hpp>
126
#include <hpx/parallel/util/compare_projected.hpp>
127
#include <hpx/parallel/util/detail/algorithm_result.hpp>
128
#include <hpx/parallel/util/detail/chunk_size.hpp>
129
#include <hpx/parallel/util/projection_identity.hpp>
130

131
#include <algorithm>
132
#include <cstddef>
133
#include <cstdint>
134
#include <exception>
135
#include <functional>
136
#include <iterator>
137
#include <list>
138
#include <type_traits>
139
#include <utility>
140

141
namespace hpx { namespace parallel { inline namespace v1 {
142

143
    ///////////////////////////////////////////////////////////////////////////
144
    // sort
145
    namespace detail {
146

147
        /// \cond NOINTERNAL
148

149
        //////////////////////////////////////////////////////////////////////
150
        ///
151
        /// \brief Obtain the position of the most significant bit set in N
152
        ///
153
        /// \param num : Number to examine
154
        ///
155
        /// \return Position of the first bit set
156
        ///
157
        inline constexpr unsigned nbits64(std::uint64_t num) noexcept
49,469✔
158
        {
159
            unsigned nb = 0;
49,469✔
160
            if (num >= (1ull << 32))
49,469✔
161
            {
162
                nb += 32;
×
163
                num = (num >> 32);
×
164
            }
×
165
            if (num >= (1ull << 16))
49,469✔
166
            {
167
                nb += 16;
22✔
168
                num = (num >> 16);
22✔
169
            }
22✔
170
            if (num >= (1ull << 8))
49,469✔
171
            {
172
                nb += 8;
46,329✔
173
                num = (num >> 8);
46,329✔
174
            }
46,329✔
175
            if (num >= (1ull << 4))
49,469✔
176
            {
177
                nb += 4;
13,239✔
178
                num = (num >> 4);
13,239✔
179
            }
13,239✔
180
            if (num >= (1ull << 2))
49,469✔
181
            {
182
                nb += 2;
3,138✔
183
                num = (num >> 2);
3,138✔
184
            }
3,138✔
185
            if (num >= (1ull << 1))
49,469✔
186
            {
187
                nb += 1;
46,361✔
188
                num = (num >> 1);
46,361✔
189
            }
46,361✔
190
            return nb;
49,469✔
191
        }
192

193
        ///////////////////////////////////////////////////////////////////////
194
        ///
195
        /// Receive a range between first and last, obtain 9 values
196
        /// between the elements  including the first and the previous
197
        /// to the last. Obtain the iterator to the mid value and swap
198
        /// with the first position
199
        //
200
        /// \param first    iterator to the first element
201
        /// \param last     iterator to the last element
202
        /// \param comp     object to Comp two elements
203
        ///
204
        template <typename Iter, typename Comp>
205
        inline constexpr void pivot3(
346,865✔
206
            Iter first, Iter last, Comp&& comp) noexcept
207
        {
208
            auto N2 = (last - first) >> 1;
346,865✔
209
            Iter it_val =
210
                mid3(first + 1, first + N2, last - 1, HPX_FORWARD(Comp, comp));
346,865✔
211
#if defined(HPX_HAVE_CXX20_STD_RANGES_ITER_SWAP)
212
            std::ranges::iter_swap(first, it_val);
213
#else
214
            std::iter_swap(first, it_val);
346,865✔
215
#endif
216
        }
346,865✔
217

218
        ///////////////////////////////////////////////////////////////////////
219
        ///
220
        /// This function obtain a pivot in the range and filter the elements
221
        /// according the value of that pivot
222
        ///
223
        /// \param first : iterator to the first element
224
        /// \param end : iterator to the element after the last
225
        /// \param comp : object to Comp two elements
226
        ///
227
        /// \return iterator where is the pivot used in the filtering
228
        ///
229
        template <typename Iter, typename Comp>
230
        constexpr inline Iter filter(Iter first, Iter end, Comp&& comp)
364,253✔
231
        {
232
            std::int64_t nelem = (end - first);
364,253✔
233
            if (nelem > 4096)
364,253✔
234
            {
235
                pivot9(first, end, comp);
17,388✔
236
            }
17,384✔
237
            else
238
            {
239
                pivot3(first, end, comp);
346,865✔
240
            }
241

242
            typename std::iterator_traits<Iter>::value_type const& pivot =
364,249✔
243
                *first;
364,249✔
244

245
            Iter c_first = first + 1, c_last = end - 1;
364,249✔
246
            while (HPX_INVOKE(comp, *c_first, pivot))
856,226✔
247
            {
248
                ++c_first;
491,977✔
249
            }
250
            while (HPX_INVOKE(comp, pivot, *c_last))
887,721✔
251
            {
252
                --c_last;
523,472✔
253
            }
254

255
            while (c_first < c_last)
163,724,738✔
256
            {
257
#if defined(HPX_HAVE_CXX20_STD_RANGES_ITER_SWAP)
258
                std::ranges::iter_swap(c_first++, c_last--);
259
#else
260
                std::iter_swap(c_first++, c_last--);
163,360,489✔
261
#endif
262
                while (HPX_INVOKE(comp, *c_first, pivot))
478,700,333✔
263
                {
264
                    ++c_first;
315,339,844✔
265
                }
266
                while (HPX_INVOKE(comp, pivot, *c_last))
331,011,215✔
267
                {
268
                    --c_last;
167,650,726✔
269
                }
270
            }
271

272
#if defined(HPX_HAVE_CXX20_STD_RANGES_ITER_SWAP)
273
            std::ranges::iter_swap(first, c_last);
274
#else
275
            std::iter_swap(first, c_last);
364,249✔
276
#endif
277
            return c_last;
364,249✔
278
        }
4✔
279

280
        ///////////////////////////////////////////////////////////////////////
281
        ///
282
        /// Internal function to divide and sort the ranges
283
        //
284
        /// \param first : iterator to the first element to be sorted
285
        /// \param middle: iterator defining the last element to be sorted
286
        /// \param end : iterator to the element after the end in the range
287
        /// \param level : level of depth from the top level call
288
        /// \param comp : object for to Comp elements
289
        ///
290
        template <typename Iter, typename Comp>
291
        inline void recursive_partial_sort(
294,557✔
292
            Iter first, Iter middle, Iter end, std::uint32_t level, Comp&& comp)
293
        {
294
            constexpr std::uint32_t nmin = 24;
294,557✔
295
            std::int64_t nelem = end - first;
294,557✔
296
            std::int64_t nmid = middle - first;
294,557✔
297
            if (nelem == 0 || nmid == 0)
294,557✔
298
            {
299
                return;
2,634✔
300
            }
301

302
            if (nelem < nmin)
291,923✔
303
            {
304
                std::sort(first, end, comp);
32,800✔
305
                return;
32,800✔
306
            }
307

308
            if (nmid == 1)
259,123✔
309
            {
310
                for (Iter it = first + 1; it != end; ++it)
150,443✔
311
                {
312
                    if (HPX_INVOKE(comp, *it, *first))
149,102✔
313
                    {
314
#if defined(HPX_HAVE_CXX20_STD_RANGES_ITER_SWAP)
315
                        std::ranges::iter_swap(it, first);
316
#else
317
                        std::iter_swap(it, first);
5,098✔
318
#endif
319
                    }
5,098✔
320
                }
149,102✔
321
                return;
1,341✔
322
            }
323

324
            if (level == 0)
257,782✔
325
            {
326
                std::make_heap(first, end, comp);
×
327
                std::sort_heap(first, middle, comp);
×
328
                return;
×
329
            }
330

331
            Iter c_last = filter(first, end, comp);
257,782✔
332
            if (middle >= c_last)
257,782✔
333
            {
334
                std::sort(first, c_last, comp);
132,802✔
335
                if (middle != c_last)
132,802✔
336
                {
337
                    recursive_partial_sort(c_last + 1, middle, end, level - 1,
260,284✔
338
                        HPX_FORWARD(Comp, comp));
130,142✔
339
                }
130,142✔
340
                return;
132,802✔
341
            }
342

343
            recursive_partial_sort(
124,980✔
344
                first, middle, c_last, level - 1, HPX_FORWARD(Comp, comp));
124,980✔
345
        }
294,557✔
346

347
        ///////////////////////////////////////////////////////////////////////
348
        ///
349
        /// Internal function to divide and sort the ranges
350
        ///
351
        /// \param first : iterator to the first element
352
        /// \param middle: iterator defining the last element to be sorted
353
        /// \param end : iterator to the element after the end in the range
354
        /// \param level : level of depth from the top level call
355
        /// \param comp : object for to Comp elements
356
        ///
357
        struct sort_thread_helper
358
        {
359
            template <typename... Ts>
360
            decltype(auto) operator()(Ts&&... ts) const
89✔
361
            {
362
                return sort_thread(HPX_FORWARD(Ts, ts)...);
89✔
363
            }
364
        };
365

366
        template <typename ExPolicy, typename Iter, typename Comp>
367
        hpx::future<Iter> parallel_partial_sort(ExPolicy&& policy, Iter first,
368
            Iter middle, Iter last, std::uint32_t level, Comp&& comp = Comp());
369

370
        struct parallel_partial_sort_helper
371
        {
372
            template <typename... Ts>
373
            decltype(auto) operator()(Ts&&... ts) const
89✔
374
            {
375
                return parallel_partial_sort(HPX_FORWARD(Ts, ts)...);
89✔
376
            }
377
        };
378

379
        template <typename ExPolicy, typename Iter, typename Comp>
380
        hpx::future<Iter> parallel_partial_sort(ExPolicy&& policy, Iter first,
19,858✔
381
            Iter middle, Iter last, std::uint32_t level, Comp&& comp)
382
        {
383
            std::int64_t nelem = last - first;
19,858✔
384
            std::int64_t nmid = middle - first;
19,858✔
385
            HPX_ASSERT(nelem >= nmid);
19,858✔
386

387
            if (nelem == 0 || nmid == 0)
19,858✔
388
            {
389
                return hpx::make_ready_future(last);
2✔
390
            }
391

392
            if (nmid < 4096 || level < 12)
19,856✔
393
            {
394
                recursive_partial_sort(first, middle, last, level, comp);
19,767✔
395
                return hpx::make_ready_future(last);
19,767✔
396
            }
397

398
            Iter c_last = filter(first, last, comp);
89✔
399
            if (middle >= c_last)
89✔
400
            {
401
                // figure out the chunk size to use
402
                std::size_t const cores =
89✔
403
                    execution::processing_units_count(policy.parameters(),
178✔
404
                        policy.executor(), hpx::chrono::null_duration, nelem);
89✔
405

406
                // number of elements to sort
407
                std::size_t chunk_size = execution::get_chunk_size(
89✔
408
                    policy.parameters(), policy.executor(),
89✔
409
                    hpx::chrono::null_duration, cores, nelem);
410

411
                hpx::future<Iter> left = execution::async_execute(
89✔
412
                    policy.executor(), sort_thread_helper(), policy, first,
89✔
413
                    c_last, comp, chunk_size);
89✔
414

415
                hpx::future<Iter> right;
89✔
416
                if (middle != c_last)
89✔
417
                {
418
                    right = execution::async_execute(policy.executor(),
178✔
419
                        parallel_partial_sort_helper(), policy, c_last + 1,
89✔
420
                        middle, last, level - 1, comp);
89✔
421
                }
89✔
422
                else
423
                {
424
                    right = hpx::make_ready_future(last);
×
425
                }
426

427
                return hpx::dataflow(
89✔
428
                    [last](hpx::future<Iter>&& left,
178✔
429
                        hpx::future<Iter>&& right) -> Iter {
430
                        if (left.has_exception() || right.has_exception())
89✔
431
                        {
432
                            std::list<std::exception_ptr> errors;
×
433
                            if (left.has_exception())
×
434
                                errors.push_back(left.get_exception_ptr());
×
435
                            if (right.has_exception())
×
436
                                errors.push_back(right.get_exception_ptr());
×
437

438
                            throw exception_list(HPX_MOVE(errors));
×
439
                        }
×
440
                        return last;
89✔
441
                    },
×
442
                    HPX_MOVE(left), HPX_MOVE(right));
443
            }
89✔
444

445
            return parallel_partial_sort(HPX_FORWARD(ExPolicy, policy), first,
×
446
                middle, c_last, level - 1, HPX_FORWARD(Comp, comp));
×
447
        }
19,858✔
448
        /// \endcond NOINTERNAL
449
    }    // end namespace detail
450

451
    ///////////////////////////////////////////////////////////////////////////
452
    ///
453
    /// \brief : Rearranges elements such that the range [first, middle)
454
    ///          contains the sorted middle - first smallest elements in the
455
    ///          range [first, end).
456
    ///
457
    /// \param first : iterator to the first element
458
    /// \param middle: iterator defining the last element to be sorted
459
    /// \param end : iterator to the element after the end in the range
460
    /// \param comp : object for to Comp elements
461
    ///
462
    template <typename Iter, typename Sent, typename Comp>
463
    Iter sequential_partial_sort(Iter first, Iter middle, Sent end, Comp&& comp)
19,668✔
464
    {
465
        std::int64_t nelem = parallel::v1::detail::distance(first, end);
19,668✔
466
        HPX_ASSERT(nelem >= 0);
19,668✔
467

468
        std::int64_t nmid = middle - first;
19,668✔
469
        HPX_ASSERT(nmid >= 0 && nmid <= nelem);
19,668✔
470

471
        if (nmid > 1024)
19,668✔
472
        {
473
            if (detail::is_sorted_sequential(first, middle, comp))
1✔
474
            {
475
                return first + nelem;
×
476
            }
477
        }
1✔
478

479
        std::uint32_t level = detail::nbits64(nelem) * 2;
19,668✔
480
        detail::recursive_partial_sort(
19,668✔
481
            first, middle, first + nelem, level, HPX_FORWARD(Comp, comp));
19,668✔
482
        return first + nelem;
19,668✔
483
    }
19,668✔
484

485
    ///////////////////////////////////////////////////////////////////////////
486
    ///
487
    /// \brief : Rearranges elements such that the range [first, middle)
488
    ///          contains the sorted middle - first smallest elements in the
489
    ///          range [first, end).
490
    ///
491
    /// \param first : iterator to the first element
492
    /// \param middle: iterator defining the last element to be sorted
493
    /// \param end : iterator to the element after the end in the range
494
    /// \param comp : object for to Comp elements
495
    ///
496
    template <typename ExPolicy, typename Iter, typename Sent, typename Comp>
497
    hpx::future<Iter> parallel_partial_sort(
19,769✔
498
        ExPolicy&& policy, Iter first, Iter middle, Sent end, Comp&& comp)
499
    {
500
        std::int64_t nelem = parallel::v1::detail::distance(first, end);
19,769✔
501
        HPX_ASSERT(nelem >= 0);
19,769✔
502

503
        std::int64_t nmid = middle - first;
19,769✔
504
        HPX_ASSERT(nmid >= 0 && nmid <= nelem);
19,769✔
505

506
        if (nmid > 1024)
19,769✔
507
        {
508
            if (detail::is_sorted_sequential(first, middle, comp))
91✔
509
            {
510
                return hpx::make_ready_future(first + nelem);
×
511
            }
512
        }
91✔
513

514
        std::uint32_t level = parallel::v1::detail::nbits64(nelem) * 2;
19,769✔
515
        return detail::parallel_partial_sort(HPX_FORWARD(ExPolicy, policy),
39,538✔
516
            first, middle, first + nelem, level, HPX_FORWARD(Comp, comp));
19,769✔
517
    }
19,769✔
518

519
    ///////////////////////////////////////////////////////////////////////
520
    // partial_sort
521
    template <typename RandIter>
522
    struct partial_sort
523
      : public detail::algorithm<partial_sort<RandIter>, RandIter>
524
    {
525
        partial_sort()
39,437✔
526
          : partial_sort::algorithm("partial_sort")
39,437✔
527
        {
39,437✔
528
        }
39,437✔
529

530
        template <typename ExPolicy, typename Iter, typename Sent,
531
            typename Comp, typename Proj>
532
        static Iter sequential(ExPolicy, Iter first, Iter middle, Sent last,
19,668✔
533
            Comp&& comp, Proj&& proj)
534
        {
535
            return sequential_partial_sort(first, middle, last,
39,336✔
536
                util::compare_projected<Comp&, Proj&>(comp, proj));
19,668✔
537
        }
538

539
        template <typename ExPolicy, typename Iter, typename Sent,
540
            typename Comp, typename Proj>
541
        static typename util::detail::algorithm_result<ExPolicy, Iter>::type
542
        parallel(ExPolicy&& policy, Iter first, Iter middle, Sent last,
19,769✔
543
            Comp&& comp, Proj&& proj)
544
        {
545
            typedef util::detail::algorithm_result<ExPolicy, Iter>
546
                algorithm_result;
547

548
            try
549
            {
550
                // call the sort routine and return the right type,
551
                // depending on execution policy
552
                return algorithm_result::get(parallel_partial_sort(
19,769✔
553
                    HPX_FORWARD(ExPolicy, policy), first, middle, last,
19,769✔
554
                    util::compare_projected<Comp&, Proj&>(comp, proj)));
19,769✔
555
            }
×
556
            catch (...)
557
            {
558
                return algorithm_result::get(
×
559
                    detail::handle_exception<ExPolicy, Iter>::call(
×
560
                        std::current_exception()));
×
561
            }
×
562
        }
19,769✔
563
    };
564
}}}    // namespace hpx::parallel::v1
565

566
namespace hpx {
567

568
    inline constexpr struct partial_sort_t final
569
      : hpx::detail::tag_parallel_algorithm<partial_sort_t>
570
    {
571
    private:
572
        // clang-format off
573
        template <typename RandIter,
574
            typename Comp = hpx::parallel::v1::detail::less,
575
            HPX_CONCEPT_REQUIRES_(
576
                hpx::traits::is_iterator<RandIter>::value &&
577
                hpx::is_invocable_v<Comp,
578
                    typename std::iterator_traits<RandIter>::value_type,
579
                    typename std::iterator_traits<RandIter>::value_type
580
                >
581
            )>
582
        // clang-format on
583
        friend RandIter tag_fallback_invoke(hpx::partial_sort_t, RandIter first,
2,114✔
584
            RandIter middle, RandIter last, Comp&& comp = Comp())
585
        {
586
            static_assert(
587
                hpx::traits::is_random_access_iterator<RandIter>::value,
588
                "Requires at least random access iterator.");
589

590
            return parallel::v1::partial_sort<RandIter>().call(
4,228✔
591
                hpx::execution::seq, first, middle, last,
592
                HPX_FORWARD(Comp, comp), parallel::util::projection_identity());
2,114✔
593
        }
594

595
        // clang-format off
596
        template <typename ExPolicy, typename RandIter,
597
            typename Comp = hpx::parallel::v1::detail::less,
598
            HPX_CONCEPT_REQUIRES_(
599
                hpx::is_execution_policy<ExPolicy>::value &&
600
                hpx::traits::is_iterator<RandIter>::value &&
601
                hpx::is_invocable_v<Comp,
602
                    typename std::iterator_traits<RandIter>::value_type,
603
                    typename std::iterator_traits<RandIter>::value_type
604
                >
605
            )>
606
        // clang-format on
607
        friend typename parallel::util::detail::algorithm_result<ExPolicy,
608
            RandIter>::type
609
        tag_fallback_invoke(hpx::partial_sort_t, ExPolicy&& policy,
10,263✔
610
            RandIter first, RandIter middle, RandIter last,
611
            Comp&& comp = Comp())
612
        {
613
            static_assert(
614
                hpx::traits::is_random_access_iterator<RandIter>::value,
615
                "Requires at least random access iterator.");
616

617
            using algorithm_result =
618
                parallel::util::detail::algorithm_result<ExPolicy, RandIter>;
619

620
            return algorithm_result::get(
10,263✔
621
                parallel::v1::partial_sort<RandIter>().call(
20,526✔
622
                    HPX_FORWARD(ExPolicy, policy), first, middle, last,
10,263✔
623
                    HPX_FORWARD(Comp, comp),
10,263✔
624
                    parallel::util::projection_identity()));
625
        }
×
626
    } partial_sort{};
627
}    // namespace hpx
628

629
#endif    // DOXYGEN
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc