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

STEllAR-GROUP / hpx / #848

07 Dec 2022 11:00PM CUT coverage: 86.456% (+0.6%) from 85.835%
#848

push

StellarBot
Merge #6096

6096: Forking Boost.Tokenizer r=hkaiser a=hkaiser

- flyby: remove more Boost headers that are not needed anymore

Working towards #3440 

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

525 of 525 new or added lines in 20 files covered. (100.0%)

173087 of 200202 relevant lines covered (86.46%)

1845223.38 hits per line

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

86.34
/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(
349,265✔
206
            Iter first, Iter last, Comp&& comp) noexcept
207
        {
208
            auto N2 = (last - first) >> 1;
349,265✔
209
            Iter it_val =
210
                mid3(first + 1, first + N2, last - 1, HPX_FORWARD(Comp, comp));
349,265✔
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);
349,265✔
215
#endif
216
        }
349,265✔
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)
366,654✔
231
        {
232
            std::int64_t nelem = (end - first);
366,654✔
233
            if (nelem > 4096)
366,654✔
234
            {
235
                pivot9(first, end, comp);
17,389✔
236
            }
17,385✔
237
            else
238
            {
239
                pivot3(first, end, comp);
349,265✔
240
            }
241

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

245
            Iter c_first = first + 1, c_last = end - 1;
366,650✔
246
            while (HPX_INVOKE(comp, *c_first, pivot))
958,616✔
247
            {
248
                ++c_first;
591,966✔
249
            }
250
            while (HPX_INVOKE(comp, pivot, *c_last))
956,060✔
251
            {
252
                --c_last;
589,410✔
253
            }
254

255
            while (c_first < c_last)
163,713,394✔
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,346,744✔
261
#endif
262
                while (HPX_INVOKE(comp, *c_first, pivot))
482,037,883✔
263
                {
264
                    ++c_first;
318,691,139✔
265
                }
266
                while (HPX_INVOKE(comp, pivot, *c_last))
329,417,693✔
267
                {
268
                    --c_last;
166,070,949✔
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);
366,650✔
276
#endif
277
            return c_last;
366,650✔
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(
296,938✔
292
            Iter first, Iter middle, Iter end, std::uint32_t level, Comp&& comp)
293
        {
294
            constexpr std::uint32_t nmin = 24;
296,938✔
295
            std::int64_t nelem = end - first;
296,938✔
296
            std::int64_t nmid = middle - first;
296,938✔
297
            if (nelem == 0 || nmid == 0)
296,938✔
298
            {
299
                return;
2,656✔
300
            }
301

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

308
            if (nmid == 1)
261,553✔
309
            {
310
                for (Iter it = first + 1; it != end; ++it)
151,405✔
311
                {
312
                    if (HPX_INVOKE(comp, *it, *first))
150,040✔
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,004✔
318
#endif
319
                    }
5,004✔
320
                }
150,040✔
321
                return;
1,365✔
322
            }
323

324
            if (level == 0)
260,188✔
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);
260,188✔
332
            if (middle >= c_last)
260,188✔
333
            {
334
                std::sort(first, c_last, comp);
133,199✔
335
                if (middle != c_last)
133,199✔
336
                {
337
                    recursive_partial_sort(c_last + 1, middle, end, level - 1,
261,028✔
338
                        HPX_FORWARD(Comp, comp));
130,514✔
339
                }
130,514✔
340
                return;
133,199✔
341
            }
342

343
            recursive_partial_sort(
126,989✔
344
                first, middle, c_last, level - 1, HPX_FORWARD(Comp, comp));
126,989✔
345
        }
296,938✔
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
90✔
361
            {
362
                return sort_thread(HPX_FORWARD(Ts, ts)...);
90✔
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
90✔
374
            {
375
                return parallel_partial_sort(HPX_FORWARD(Ts, ts)...);
90✔
376
            }
377
        };
378

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

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

392
            if (nmid < 4096 || level < 12)
19,857✔
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);
90✔
399
            if (middle >= c_last)
90✔
400
            {
401
                // figure out the chunk size to use
402
                std::size_t const cores = execution::processing_units_count(
90✔
403
                    policy.parameters(), policy.executor());
90✔
404

405
                // number of elements to sort
406
                std::size_t chunk_size = execution::get_chunk_size(
90✔
407
                    policy.parameters(), policy.executor(),
90✔
408
                    [](std::size_t) { return 0; }, cores, nelem);
409

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

565
namespace hpx {
566

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

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

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

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

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

628
#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