From a4eb67ae1cfd4c1ee343a130c92920710bd976d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20M=C3=BCller?= Date: Mon, 18 Nov 2024 20:11:01 +0100 Subject: [PATCH 01/25] implement worst-case linear-time `std::nth_element` --- stl/inc/algorithm | 138 +++++++++++++++--- tests/std/test.lst | 1 + .../GH_000856_nth_element_linear/env.lst | 4 + .../GH_000856_nth_element_linear/test.cpp | 118 +++++++++++++++ 4 files changed, 243 insertions(+), 18 deletions(-) create mode 100644 tests/std/tests/GH_000856_nth_element_linear/env.lst create mode 100644 tests/std/tests/GH_000856_nth_element_linear/test.cpp diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 5ea4e3db6f2..c7a51f54433 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -8265,12 +8265,10 @@ _CONSTEXPR20 void _Guess_median_unchecked(_RanIt _First, _RanIt _Mid, _RanIt _La } template -_CONSTEXPR20 pair<_RanIt, _RanIt> _Partition_by_median_guess_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { +_CONSTEXPR20 pair<_RanIt, _RanIt> _Partition_by_pivot_unchecked( + _RanIt _First, _RanIt _Pfirst, _RanIt _Last, _Pr _Pred) { // partition [_First, _Last) - _RanIt _Mid = _First + ((_Last - _First) >> 1); // shift for codegen - _STD _Guess_median_unchecked(_First, _Mid, _STD _Prev_iter(_Last), _Pred); - _RanIt _Pfirst = _Mid; - _RanIt _Plast = _STD _Next_iter(_Pfirst); + _RanIt _Plast = _STD _Next_iter(_Pfirst); while (_First < _Pfirst && !_DEBUG_LT_PRED(_Pred, *_STD _Prev_iter(_Pfirst), *_Pfirst) && !_Pred(*_Pfirst, *_STD _Prev_iter(_Pfirst))) { @@ -8335,6 +8333,14 @@ _CONSTEXPR20 pair<_RanIt, _RanIt> _Partition_by_median_guess_unchecked(_RanIt _F } } +template +_CONSTEXPR20 pair<_RanIt, _RanIt> _Partition_by_median_guess_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { + _RanIt _Mid = _First + ((_Last - _First) >> 1); // shift for codegen + _STD _Guess_median_unchecked(_First, _Mid, _STD _Prev_iter(_Last), _Pred); + + return _STD _Partition_by_pivot_unchecked(_First, _Mid, _Last, _Pred); +} + template _CONSTEXPR20 void _Sort_unchecked(_RanIt _First, _RanIt _Last, _Iter_diff_t<_RanIt> _Ideal, _Pr _Pred) { // order [_First, _Last) @@ -9320,6 +9326,114 @@ namespace ranges { #endif // _HAS_CXX20 #endif // _HAS_CXX17 +template +_CONSTEXPR20 void _Swap_med5_unchecked(_RanIt _First, _RanIt _Dest, _Pr _Pred) { + _RanIt _Guess = _First; + ++_Guess; + _RanIt _Third = _Guess; + ++_Third; + _STD _Med3_unchecked(_First, _Guess, _Third, _Pred); + + _RanIt _Fourth = _Third; + ++_Fourth; + _RanIt _Fifth = _Fourth; + ++_Fifth; + if (_DEBUG_LT_PRED(_Pred, *_Fifth, *_Fourth)) { + swap(*_Fourth, *_Fifth); // intentional ADL + } + + // we have _First <= _Guess (second) <= _Third and _Fourth <= _Fifth + if (_DEBUG_LT_PRED(_Pred, *_Fifth, *_Guess)) { + if (_DEBUG_LT_PRED(_Pred, *_First, *_Fifth)) { + _Guess = _Fifth; + } else { + _Guess = _First; + } + } else if (_DEBUG_LT_PRED(_Pred, *_Guess, *_Fourth)) { + if (_DEBUG_LT_PRED(_Pred, *_Third, *_Fourth)) { + _Guess = _Third; + } else { + _Guess = _Fourth; + } + } + + swap(*_Dest, *_Guess); // intentional ADL +} + +template +_CONSTEXPR20 void _Nth_element_median_of_medians(_RanIt _First, _RanIt _Nth, _RanIt _Last, _Pr _Pred) { + using _Diff = _Iter_diff_t<_RanIt>; + for (;;) { + auto _Length = _Last - _First; + if (_Length <= _ISORT_MAX) { + _STD _Insertion_sort_unchecked(_First, _Last, _Pred); // sort any remainder + return; + } + + _Diff _MedianCount = _Length / static_cast<_Diff>(5); + auto _MedianLast = _First + _MedianCount; + auto _Current = _First; + for (auto _MedianDest = _First; _MedianDest != _MedianLast; ++_MedianDest) { + _STD _Swap_med5_unchecked(_Current, _MedianDest, _Pred); + _Current += static_cast<_Diff>(5); + } + + auto _MedianMid = _First + (_MedianCount >> 1); + _STD _Nth_element_median_of_medians(_First, _MedianMid, _MedianLast, _Pred); + + // the medians before and after _MedianMid are + // less equal and greater equal _MedianMid, respectively. + // move the ones after _MedianMid near _Last and then partition + // the elements between the medians at front and back by the pivot _MedianMid + _Diff _MedianGreaterCount = (_MedianLast - _MedianMid) - 1; + auto _MedianGreaterFirst = _Last - _MedianGreaterCount; + _STD _Swap_ranges_unchecked(_MedianMid + static_cast<_Diff>(1), _MedianLast, _MedianGreaterFirst); + auto _Middle = _First + ((_Last - _First) >> 1); + swap(*_MedianMid, *_Middle); + + auto _Mid = _STD _Partition_by_pivot_unchecked(_MedianMid, _Middle, _MedianGreaterFirst, _Pred); + + if (_Mid.second <= _Nth) { + _First = _Mid.second; + } else if (_Mid.first <= _Nth) { + return; // _Nth is in the subrange of elements equal to the pivot; done + } else { + _Last = _Mid.first; + } + } +} + +template +_CONSTEXPR20 void _Nth_element_unchecked(_RanIt _First, _RanIt _Nth, _RanIt _Last, _Pr _Pred) { + auto _Ideal = _Last - _First; + + for (;;) { + auto _Length = _Last - _First; + if (_Length <= _ISORT_MAX) { + _STD _Insertion_sort_unchecked(_First, _Last, _Pred); // sort any remainder + return; + } + + if (_Ideal < (_Length >> 1)) { + _STD _Nth_element_median_of_medians(_First, _Nth, _Last, _Pred); + return; + } + + auto _Mid = _STD _Partition_by_median_guess_unchecked(_First, _Last, _Pred); + + if (_Mid.second <= _Nth) { + _First = _Mid.second; + } else if (_Mid.first <= _Nth) { + return; // _Nth is in the subrange of elements equal to the pivot; done + } else { + _Last = _Mid.first; + } + + // processed range should be reduced by 25 % per iteration on average + _Ideal = (_Ideal >> 1) + (_Ideal >> 2); + } +} + _EXPORT_STD template _CONSTEXPR20 void nth_element(_RanIt _First, _RanIt _Nth, _RanIt _Last, _Pr _Pred) { // order Nth element @@ -9332,19 +9446,7 @@ _CONSTEXPR20 void nth_element(_RanIt _First, _RanIt _Nth, _RanIt _Last, _Pr _Pre return; // nothing to do } - while (_ISORT_MAX < _ULast - _UFirst) { // divide and conquer, ordering partition containing Nth - auto _UMid = _STD _Partition_by_median_guess_unchecked(_UFirst, _ULast, _STD _Pass_fn(_Pred)); - - if (_UMid.second <= _UNth) { - _UFirst = _UMid.second; - } else if (_UMid.first <= _UNth) { - return; // _Nth is in the subrange of elements equal to the pivot; done - } else { - _ULast = _UMid.first; - } - } - - _STD _Insertion_sort_unchecked(_UFirst, _ULast, _STD _Pass_fn(_Pred)); // sort any remainder + _STD _Nth_element_unchecked(_UFirst, _UNth, _ULast, _STD _Pass_fn(_Pred)); } _EXPORT_STD template diff --git a/tests/std/test.lst b/tests/std/test.lst index 42163db9973..10085e7409b 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -175,6 +175,7 @@ tests\GH_000625_vector_bool_optimization tests\GH_000685_condition_variable_any tests\GH_000690_overaligned_function tests\GH_000732_hash_reserve +tests\GH_000856_nth_element_linear tests\GH_000890_pow_template tests\GH_000935_complex_numerical_accuracy tests\GH_000940_missing_valarray_copy diff --git a/tests/std/tests/GH_000856_nth_element_linear/env.lst b/tests/std/tests/GH_000856_nth_element_linear/env.lst new file mode 100644 index 00000000000..19f025bd0e6 --- /dev/null +++ b/tests/std/tests/GH_000856_nth_element_linear/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_matrix.lst diff --git a/tests/std/tests/GH_000856_nth_element_linear/test.cpp b/tests/std/tests/GH_000856_nth_element_linear/test.cpp new file mode 100644 index 00000000000..78999a9b5f1 --- /dev/null +++ b/tests/std/tests/GH_000856_nth_element_linear/test.cpp @@ -0,0 +1,118 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include + +#if _HAS_CXX20 +#include +#endif // _HAS_CXX20 + +// clang-format off +constexpr int tunkey_ninther_adversary[] = { + 0, 6, 12, 18, 22, 28, 34, 38, 44, 50, 54, 60, 66, 70, 76, 82, 86, 92, 98, 102, 108, + 114, 118, 124, 130, 134, 140, 146, 150, 156, 162, 166, 172, 178, 182, 188, 194, 198, + 204, 210, 214, 220, 226, 230, 236, 242, 246, 252, 258, 262, 268, 274, 278, 284, 290, + 294, 300, 306, 310, 316, 322, 326, 332, 338, 342, 348, 354, 358, 364, 370, 374, 380, + 386, 390, 396, 402, 406, 412, 418, 422, 428, 434, 438, 444, 450, 454, 460, 466, 470, + 476, 482, 486, 492, 498, 502, 508, 514, 518, 524, 530, 534, 540, 546, 550, 556, 562, + 566, 572, 578, 582, 588, 594, 598, 604, 610, 614, 620, 626, 630, 636, 642, 646, 652, + 658, 662, 668, 674, 678, 1, 7, 13, 684, 19, 23, 29, 690, 35, 39, 45, 694, 51, 55, 61, + 700, 67, 71, 77, 706, 83, 87, 93, 710, 99, 103, 109, 716, 115, 119, 125, 722, 131, 135, + 141, 726, 147, 151, 157, 732, 163, 167, 173, 738, 179, 183, 189, 742, 195, 199, 205, + 748, 211, 215, 221, 754, 227, 231, 237, 758, 243, 247, 253, 764, 259, 263, 269, 770, + 275, 279, 285, 774, 291, 295, 301, 780, 307, 311, 317, 786, 323, 327, 333, 790, 339, + 343, 349, 796, 355, 359, 365, 802, 371, 375, 381, 806, 387, 391, 397, 812, 403, 407, + 413, 818, 419, 423, 429, 822, 435, 439, 445, 828, 451, 455, 461, 834, 467, 471, 477, + 838, 483, 487, 493, 844, 499, 503, 509, 850, 515, 519, 525, 854, 531, 535, 541, 860, + 547, 551, 557, 866, 563, 567, 573, 870, 579, 583, 589, 876, 595, 599, 605, 882, 611, + 615, 621, 886, 627, 631, 637, 892, 643, 647, 653, 898, 659, 663, 669, 902, 675, 679, + 685, 908, 691, 695, 701, 914, 707, 711, 717, 918, 723, 727, 733, 924, 739, 743, 749, + 930, 755, 759, 765, 934, 771, 775, 781, 940, 787, 791, 797, 946, 803, 807, 813, 950, + 819, 823, 829, 956, 835, 839, 845, 962, 851, 855, 861, 966, 867, 871, 877, 972, 883, + 887, 893, 978, 899, 903, 909, 982, 915, 919, 925, 988, 931, 935, 941, 990, 947, 951, + 957, 992, 963, 967, 973, 1024, 979, 983, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, + 1002, 2, 20, 8, 14, 24, 36, 30, 40, 52, 46, 56, 68, 62, 72, 84, 78, 88, 100, 94, 104, + 116, 110, 120, 132, 126, 136, 148, 142, 152, 164, 158, 168, 180, 174, 184, 196, 190, + 200, 212, 206, 216, 228, 222, 232, 244, 238, 248, 260, 254, 264, 276, 270, 280, 292, + 286, 296, 308, 302, 312, 324, 318, 328, 340, 334, 344, 356, 350, 360, 372, 366, 376, + 388, 382, 392, 404, 398, 408, 420, 414, 424, 436, 430, 440, 452, 446, 456, 468, 462, + 472, 484, 478, 488, 500, 494, 504, 516, 510, 520, 532, 526, 536, 548, 542, 552, 564, + 558, 568, 580, 574, 584, 596, 590, 600, 612, 606, 616, 628, 622, 632, 644, 638, 648, + 660, 654, 664, 676, 670, 512, 3, 991, 9, 773, 768, 15, 680, 901, 21, 522, 25, 777, 527, + 31, 692, 965, 37, 528, 41, 960, 778, 47, 686, 905, 53, 538, 57, 936, 543, 63, 696, 1007, + 69, 544, 73, 789, 784, 79, 708, 1014, 85, 554, 89, 793, 559, 95, 702, 969, 101, 560, + 105, 911, 794, 111, 712, 974, 117, 570, 121, 948, 575, 127, 724, 1015, 133, 576, 137, + 805, 800, 143, 718, 917, 149, 586, 153, 809, 591, 159, 728, 1008, 165, 592, 169, 970, + 810, 175, 740, 921, 181, 602, 185, 942, 607, 191, 734, 1009, 197, 608, 201, 821, 816, + 207, 744, 975, 213, 618, 217, 825, 623, 223, 756, 1005, 229, 624, 233, 927, 826, 239, + 750, 984, 245, 634, 249, 952, 639, 255, 760, 1010, 261, 640, 265, 837, 832, 271, 772, + 933, 277, 650, 281, 841, 655, 287, 766, 981, 293, 656, 297, 976, 842, 303, 776, 937, 309, + 666, 313, 964, 671, 319, 788, 1011, 325, 672, 329, 853, 848, 335, 782, 1016, 341, 682, + 345, 857, 687, 351, 792, 985, 357, 688, 361, 943, 858, 367, 804, 1003, 373, 698, 377, + 958, 703, 383, 798, 1017, 389, 704, 393, 869, 864, 399, 808, 949, 405, 714, 409, 873, + 719, 415, 820, 1012, 421, 720, 425, 986, 874, 431, 814, 953, 437, 730, 441, 968, 735, + 447, 824, 1013, 453, 736, 457, 885, 880, 463, 836, 989, 469, 746, 473, 889, 751, 479, + 830, 1006, 485, 752, 489, 959, 890, 495, 840, 1004, 501, 762, 505, 980, 767, 511, 852, 4, + 517, 10, 521, 16, 896, 26, 846, 32, 533, 42, 537, 48, 783, 58, 856, 64, 549, 74, 553, 80, + 906, 90, 868, 96, 565, 106, 569, 112, 799, 122, 862, 128, 581, 138, 585, 144, 912, 154, + 72, 160, 597, 170, 601, 176, 815, 186, 884, 192, 613, 202, 617, 208, 922, 218, 878, 224, + 629, 234, 633, 240, 831, 250, 888, 256, 645, 266, 649, 272, 928, 282, 900, 288, 661, 298, + 665, 304, 847, 314, 894, 320, 677, 330, 681, 336, 938, 346, 904, 352, 693, 362, 697, 368, + 863, 378, 916, 384, 709, 394, 713, 400, 944, 410, 910, 416, 725, 426, 729, 432, 879, 442, + 920, 448, 741, 458, 745, 464, 954, 474, 932, 480, 757, 490, 761, 496, 895, 506, 926, 5, + 11, 17, 27, 33, 43, 49, 59, 65, 75, 81, 91, 97, 107, 113, 123, 129, 139, 145, 155, 161, + 71, 177, 187, 193, 203, 209, 219, 225, 235, 241, 251, 257, 267, 273, 283, 289, 299, 305, + 315, 321, 331, 337, 347, 353, 363, 369, 379, 385, 395, 401, 411, 417, 427, 433, 443, 449, + 459, 465, 475, 481, 491, 497, 507, 513, 523, 529, 539, 545, 555, 561, 571, 577, 587, 593, + 603, 609, 619, 625, 635, 641, 651, 657, 667, 673, 683, 689, 699, 705, 715, 721, 731, 737, + 747, 753, 763, 769, 779, 785, 795, 801, 811, 817, 827, 833, 843, 849, 859, 865, 875, 881, + 891, 897, 907, 913, 923, 929, 939, 945, 955, 961, 971, 977, 987, 1018, 1019, 1020, 1021, 1022, }; +// clang-format on + +using namespace std; + +template +void check_result(const vector& expected, const vector& computed, Diff nth) { + assert(is_permutation(computed.begin(), computed.end(), expected.begin())); + const int val_nth = *(computed.begin() + nth); + assert(*(expected.begin() + nth) == val_nth); + for (auto it = computed.begin(), last = computed.begin() + nth; it < last; ++it) { + assert(*it <= val_nth); + } + for (auto it = computed.begin() + nth; it < computed.end(); ++it) { + assert(*it >= val_nth); + } +} + +template +void test_nth_element_tunkey_adversary(Algorithm alg) { + vector src(begin(tunkey_ninther_adversary), end(tunkey_ninther_adversary)); + + vector sorted = src; + sort(sorted.begin(), sorted.end()); + vector v; + v.reserve(src.size()); + + for (vector::difference_type nth{}, last = src.end() - src.begin(); nth < last; + nth += static_cast::difference_type>(15)) { + v = src; + alg(v, nth); + check_result(sorted, v, nth); + } + v = src; + alg(v, (v.end() - v.begin()) - static_cast::difference_type>(1)); + check_result(sorted, v, (v.end() - v.begin()) - static_cast::difference_type>(1)); +} + +int main() { + test_nth_element_tunkey_adversary( + [](vector& v, vector::difference_type nth) { nth_element(v.begin(), v.begin() + nth, v.end()); }); + +#if _HAS_CXX20 + test_nth_element_tunkey_adversary([](vector& v, vector::difference_type nth) { + ranges::nth_element(v.begin(), v.begin() + nth, v.end()); + }); +#endif +} From 3a03983e7b39518665e392d2dc6ddd0195fb36aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20M=C3=BCller?= Date: Mon, 18 Nov 2024 23:18:42 +0100 Subject: [PATCH 02/25] implement worst-case linear time `std::ranges::nth_element` --- stl/inc/algorithm | 230 +++++++++++++++++++++++++++++++++------------- 1 file changed, 167 insertions(+), 63 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index c7a51f54433..e0cd8d56ba7 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -3641,6 +3641,55 @@ namespace ranges { _EXPORT_STD template using swap_ranges_result = in_in_result<_In1, _In2>; + template + _NODISCARD constexpr swap_ranges_result<_It1, _It2> _Swap_ranges_common( + _It1 _First1, const _Se1 _Last1, _It2 _First2, const _Se2 _Last2) { + _STL_INTERNAL_STATIC_ASSERT(input_iterator<_It1>); + _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se1, _It1>); + _STL_INTERNAL_STATIC_ASSERT(input_iterator<_It2>); + _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se2, _It2>); + _STL_INTERNAL_STATIC_ASSERT(indirectly_swappable<_It1, _It2>); + +#if _USE_STD_VECTOR_ALGORITHMS + using _Elem1 = remove_reference_t>; + using _Elem2 = remove_reference_t>; + if constexpr (same_as<_Elem1, _Elem2> && _Is_trivially_ranges_swappable_v<_Elem1> // + && contiguous_iterator<_It1> && _Sized_or_unreachable_sentinel_for<_Se1, _It1> // + && contiguous_iterator<_It2> && _Sized_or_unreachable_sentinel_for<_Se2, _It2>) { + if (!_STD is_constant_evaluated()) { + constexpr bool _Is_sized1 = sized_sentinel_for<_Se1, _It1>; + constexpr bool _Is_sized2 = sized_sentinel_for<_Se2, _It2>; + const auto _First1_addr = _STD to_address(_First1); + const auto _First2_addr = _STD to_address(_First2); + if constexpr (_Is_sized1 && _Is_sized2) { + const size_t _Count = + (_STD min)(static_cast(_Last1 - _First1), static_cast(_Last2 - _First2)); + const auto _Last1_addr = _First1_addr + _Count; + ::__std_swap_ranges_trivially_swappable_noalias(_First1_addr, _Last1_addr, _First2_addr); + return {_First1 + _Count, _First2 + _Count}; + } else if constexpr (_Is_sized1) { + const auto _Final1 = _RANGES next(_First1, _Last1); + const auto _Last1_addr = _STD to_address(_Final1); + ::__std_swap_ranges_trivially_swappable_noalias(_First1_addr, _Last1_addr, _First2_addr); + return {_Final1, _First2 + (_Last1 - _First1)}; + } else if constexpr (_Is_sized2) { + const auto _Final2 = _RANGES next(_First2, _Last2); + const auto _Last2_addr = _STD to_address(_Final2); + ::__std_swap_ranges_trivially_swappable_noalias(_First2_addr, _Last2_addr, _First1_addr); + return {_First1 + (_Last2 - _First2), _Final2}; + } else { + _STL_ASSERT(false, "Tried to swap_ranges with two unreachable sentinels"); + } + } + } +#endif // _USE_STD_VECTOR_ALGORITHMS + + for (; _First1 != _Last1 && _First2 != _Last2; ++_First1, (void) ++_First2) { + _RANGES iter_swap(_First1, _First2); + } + + return {_STD move(_First1), _STD move(_First2)}; + } class _Swap_ranges_fn { public: template _Se1, input_iterator _It2, sentinel_for<_It2> _Se2> @@ -3650,7 +3699,7 @@ namespace ranges { _STD _Adl_verify_range(_First1, _Last1); _STD _Adl_verify_range(_First2, _Last2); - auto _UResult = _Swap_ranges_unchecked(_RANGES _Unwrap_iter<_Se1>(_STD move(_First1)), + auto _UResult = _RANGES _Swap_ranges_common(_RANGES _Unwrap_iter<_Se1>(_STD move(_First1)), _RANGES _Unwrap_sent<_It1>(_STD move(_Last1)), _RANGES _Unwrap_iter<_Se2>(_STD move(_First2)), _RANGES _Unwrap_sent<_It2>(_STD move(_Last2))); @@ -3666,64 +3715,13 @@ namespace ranges { auto _First1 = _RANGES begin(_Range1); auto _First2 = _RANGES begin(_Range2); - auto _UResult = _Swap_ranges_unchecked(_RANGES _Unwrap_range_iter<_Rng1>(_STD move(_First1)), + auto _UResult = _RANGES _Swap_ranges_common(_RANGES _Unwrap_range_iter<_Rng1>(_STD move(_First1)), _Uend(_Range1), _RANGES _Unwrap_range_iter<_Rng2>(_STD move(_First2)), _Uend(_Range2)); _STD _Seek_wrapped(_First1, _STD move(_UResult.in1)); _STD _Seek_wrapped(_First2, _STD move(_UResult.in2)); return {_STD move(_First1), _STD move(_First2)}; } - - private: - template - _NODISCARD static constexpr swap_ranges_result<_It1, _It2> _Swap_ranges_unchecked( - _It1 _First1, const _Se1 _Last1, _It2 _First2, const _Se2 _Last2) { - _STL_INTERNAL_STATIC_ASSERT(input_iterator<_It1>); - _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se1, _It1>); - _STL_INTERNAL_STATIC_ASSERT(input_iterator<_It2>); - _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se2, _It2>); - _STL_INTERNAL_STATIC_ASSERT(indirectly_swappable<_It1, _It2>); - -#if _USE_STD_VECTOR_ALGORITHMS - using _Elem1 = remove_reference_t>; - using _Elem2 = remove_reference_t>; - if constexpr (same_as<_Elem1, _Elem2> && _Is_trivially_ranges_swappable_v<_Elem1> // - && contiguous_iterator<_It1> && _Sized_or_unreachable_sentinel_for<_Se1, _It1> // - && contiguous_iterator<_It2> && _Sized_or_unreachable_sentinel_for<_Se2, _It2>) { - if (!_STD is_constant_evaluated()) { - constexpr bool _Is_sized1 = sized_sentinel_for<_Se1, _It1>; - constexpr bool _Is_sized2 = sized_sentinel_for<_Se2, _It2>; - const auto _First1_addr = _STD to_address(_First1); - const auto _First2_addr = _STD to_address(_First2); - if constexpr (_Is_sized1 && _Is_sized2) { - const size_t _Count = - (_STD min)(static_cast(_Last1 - _First1), static_cast(_Last2 - _First2)); - const auto _Last1_addr = _First1_addr + _Count; - ::__std_swap_ranges_trivially_swappable_noalias(_First1_addr, _Last1_addr, _First2_addr); - return {_First1 + _Count, _First2 + _Count}; - } else if constexpr (_Is_sized1) { - const auto _Final1 = _RANGES next(_First1, _Last1); - const auto _Last1_addr = _STD to_address(_Final1); - ::__std_swap_ranges_trivially_swappable_noalias(_First1_addr, _Last1_addr, _First2_addr); - return {_Final1, _First2 + (_Last1 - _First1)}; - } else if constexpr (_Is_sized2) { - const auto _Final2 = _RANGES next(_First2, _Last2); - const auto _Last2_addr = _STD to_address(_Final2); - ::__std_swap_ranges_trivially_swappable_noalias(_First2_addr, _Last2_addr, _First1_addr); - return {_First1 + (_Last2 - _First2), _Final2}; - } else { - _STL_ASSERT(false, "Tried to swap_ranges with two unreachable sentinels"); - } - } - } -#endif // _USE_STD_VECTOR_ALGORITHMS - - for (; _First1 != _Last1 && _First2 != _Last2; ++_First1, (void) ++_First2) { - _RANGES iter_swap(_First1, _First2); - } - - return {_STD move(_First1), _STD move(_First2)}; - } }; _EXPORT_STD inline constexpr _Swap_ranges_fn swap_ranges; @@ -8466,14 +8464,12 @@ namespace ranges { template requires sortable<_It, _Pr, _Pj> - _NODISCARD constexpr subrange<_It> _Partition_by_median_guess_common(_It _First, _It _Last, _Pr _Pred, _Pj _Proj) { - // Choose a pivot, partition [_First, _Last) into elements less than pivot, elements equal to pivot, and + _NODISCARD constexpr subrange<_It> _Partition_by_pivot_common( + _It _First, _It _Pfirst, _It _Last, _Pr _Pred, _Pj _Proj) { + // Partition [_First, _Last) into elements less than pivot, elements equal to pivot, and // elements greater than pivot; return the equal partition as a subrange. - _It _Mid = _First + ((_Last - _First) >> 1); // shift for codegen - _RANGES _Guess_median_common(_First, _Mid, _RANGES prev(_Last), _Pred, _Proj); - _It _Pfirst = _Mid; - _It _Plast = _RANGES next(_Pfirst); + _It _Plast = _RANGES next(_Pfirst); while (_First < _Pfirst && !_STD invoke(_Pred, _STD invoke(_Proj, *_RANGES prev(_Pfirst)), _STD invoke(_Proj, *_Pfirst)) @@ -8540,6 +8536,17 @@ namespace ranges { } } + template + requires sortable<_It, _Pr, _Pj> + _NODISCARD constexpr subrange<_It> _Partition_by_median_guess_common(_It _First, _It _Last, _Pr _Pred, _Pj _Proj) { + // Choose a pivot, partition [_First, _Last) into elements less than pivot, elements equal to pivot, and + // elements greater than pivot; return the equal partition as a subrange. + + _It _Mid = _First + ((_Last - _First) >> 1); // shift for codegen + _RANGES _Guess_median_common(_First, _Mid, _RANGES prev(_Last), _Pred, _Proj); + return _RANGES _Partition_by_pivot_common(_First, _Mid, _Last, _Pred, _Proj); + } + class _Sort_fn { public: template _Se, class _Pr = ranges::less, class _Pj = identity> @@ -9514,6 +9521,88 @@ namespace ranges { } private: + template + static constexpr void _Swap_med5(_It _First, _It _Dest, _Pr _Pred, _Pj _Proj) { + _It _Guess = _First; + ++_Guess; + _It _Third = _Guess; + ++_Third; + _RANGES _Med3_common(_First, _Guess, _Third, _Pred, _Proj); + + _It _Fourth = _Third; + ++_Fourth; + _It _Fifth = _Fourth; + ++_Fifth; + if (_STD invoke(_Pred, _STD invoke(_Proj, *_Fifth), _STD invoke(_Proj, *_Fourth))) { + _RANGES iter_swap(_Fourth, _Fifth); + } + + // we have _First <= _Guess (second) <= _Third and _Fourth <= _Fifth + if (_STD invoke(_Pred, _STD invoke(_Proj, *_Fifth), _STD invoke(_Proj, *_Guess))) { + if (_STD invoke(_Pred, _STD invoke(_Proj, *_First), _STD invoke(_Proj, *_Fifth))) { + _Guess = _STD move(_Fifth); + } else { + _Guess = _STD move(_First); + } + } else if (_STD invoke(_Pred, _STD invoke(_Proj, *_Guess), _STD invoke(_Proj, *_Fourth))) { + if (_STD invoke(_Pred, _STD invoke(_Proj, *_Third), _STD invoke(_Proj, *_Fourth))) { + _Guess = _STD move(_Third); + } else { + _Guess = _STD move(_Fourth); + } + } + + _RANGES iter_swap(_Dest, _Guess); + } + + template + static constexpr void _Nth_element_median_of_medians_unchecked( + _It _First, _It _Nth, _It _Last, _Pr _Pred, _Pj _Proj) { + + using _Diff = iter_difference_t<_It>; + for (;;) { + auto _Length = _Last - _First; + if (_Length <= _ISORT_MAX) { + // sort any remainder + _RANGES _Insertion_sort_common(_STD move(_First), _STD move(_Last), _Pred, _Proj); + return; + } + + _Diff _MedianCount = _Length / static_cast<_Diff>(5); + auto _MedianLast = _First + _MedianCount; + auto _Current = _First; + for (auto _MedianDest = _First; _MedianDest != _MedianLast; ++_MedianDest) { + _Swap_med5(_Current, _MedianDest, _Pred, _Proj); + _Current += static_cast<_Diff>(5); + } + + auto _MedianMid = _First + (_MedianCount >> 1); + _Nth_element_median_of_medians_unchecked(_First, _MedianMid, _MedianLast, _Pred, _Proj); + + // the medians before and after _MedianMid are + // less equal and greater equal _MedianMid, respectively. + // move the ones after _MedianMid near _Last and then partition + // the elements between the medians at front and back by the pivot _MedianMid + _Diff _MedianGreaterCount = (_MedianLast - _MedianMid) - 1; + auto _MedianGreaterFirst = _Last - _MedianGreaterCount; + (void) _RANGES _Swap_ranges_common( + _MedianMid + static_cast<_Diff>(1), _STD move(_MedianLast), _MedianGreaterFirst, _Last); + auto _Middle = _First + ((_Last - _First) >> 1); + _RANGES iter_swap(_MedianMid, _Middle); + + subrange<_It> _Mid = _RANGES _Partition_by_pivot_common( + _STD move(_MedianMid), _STD move(_Middle), _STD move(_MedianGreaterFirst), _Pred, _Proj); + + if (_Mid.end() <= _Nth) { + _First = _Mid.end(); + } else if (_Mid.begin() <= _Nth) { + return; // _Nth is in the subrange of elements equal to the pivot; done + } else { + _Last = _Mid.begin(); + } + } + } + template static constexpr void _Nth_element_common(_It _First, _It _Nth, _It _Last, _Pr _Pred, _Pj _Proj) { _STL_INTERNAL_STATIC_ASSERT(random_access_iterator<_It>); @@ -9523,7 +9612,22 @@ namespace ranges { return; // nothing to do } - while (_ISORT_MAX < _Last - _First) { // divide and conquer, ordering partition containing Nth + auto _Ideal = _Last - _First; + + for (;;) { + auto _Length = _Last - _First; + if (_Length <= _ISORT_MAX) { + // sort any remainder + _RANGES _Insertion_sort_common(_STD move(_First), _STD move(_Last), _Pred, _Proj); + return; + } + + if (_Ideal < (_Length >> 1)) { + _Nth_element_median_of_medians_unchecked( + _STD move(_First), _STD move(_Nth), _STD move(_Last), _Pred, _Proj); + return; + } + subrange<_It> _Mid = _RANGES _Partition_by_median_guess_common(_First, _Last, _Pred, _Proj); if (_Mid.end() <= _Nth) { @@ -9533,10 +9637,10 @@ namespace ranges { } else { _Last = _Mid.begin(); } - } - // sort any remainder - _RANGES _Insertion_sort_common(_STD move(_First), _STD move(_Last), _Pred, _Proj); + // processed range should be reduced by 25 % per iteration on average + _Ideal = (_Ideal >> 1) + (_Ideal >> 2); + } } }; From c03a11e61a57512a71e98231d395b0b9f554063b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20M=C3=BCller?= Date: Mon, 18 Nov 2024 23:58:32 +0100 Subject: [PATCH 03/25] add benchmark --- benchmarks/CMakeLists.txt | 1 + benchmarks/src/nth_element.cpp | 123 +++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 benchmarks/src/nth_element.cpp diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index 4e4f47894ed..5f74dbebec6 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -117,6 +117,7 @@ add_benchmark(iota src/iota.cpp) add_benchmark(locale_classic src/locale_classic.cpp) add_benchmark(minmax_element src/minmax_element.cpp) add_benchmark(mismatch src/mismatch.cpp) +add_benchmark(nth_element src/nth_element.cpp) add_benchmark(path_lexically_normal src/path_lexically_normal.cpp) add_benchmark(priority_queue_push_range src/priority_queue_push_range.cpp) add_benchmark(random_integer_generation src/random_integer_generation.cpp) diff --git a/benchmarks/src/nth_element.cpp b/benchmarks/src/nth_element.cpp new file mode 100644 index 00000000000..d31721f7984 --- /dev/null +++ b/benchmarks/src/nth_element.cpp @@ -0,0 +1,123 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +// clang-format off +constexpr int tunkey_ninther_adversary[] = { + 0, 6, 12, 18, 22, 28, 34, 38, 44, 50, 54, 60, 66, 70, 76, 82, 86, 92, 98, 102, 108, + 114, 118, 124, 130, 134, 140, 146, 150, 156, 162, 166, 172, 178, 182, 188, 194, 198, + 204, 210, 214, 220, 226, 230, 236, 242, 246, 252, 258, 262, 268, 274, 278, 284, 290, + 294, 300, 306, 310, 316, 322, 326, 332, 338, 342, 348, 354, 358, 364, 370, 374, 380, + 386, 390, 396, 402, 406, 412, 418, 422, 428, 434, 438, 444, 450, 454, 460, 466, 470, + 476, 482, 486, 492, 498, 502, 508, 514, 518, 524, 530, 534, 540, 546, 550, 556, 562, + 566, 572, 578, 582, 588, 594, 598, 604, 610, 614, 620, 626, 630, 636, 642, 646, 652, + 658, 662, 668, 674, 678, 1, 7, 13, 684, 19, 23, 29, 690, 35, 39, 45, 694, 51, 55, 61, + 700, 67, 71, 77, 706, 83, 87, 93, 710, 99, 103, 109, 716, 115, 119, 125, 722, 131, 135, + 141, 726, 147, 151, 157, 732, 163, 167, 173, 738, 179, 183, 189, 742, 195, 199, 205, + 748, 211, 215, 221, 754, 227, 231, 237, 758, 243, 247, 253, 764, 259, 263, 269, 770, + 275, 279, 285, 774, 291, 295, 301, 780, 307, 311, 317, 786, 323, 327, 333, 790, 339, + 343, 349, 796, 355, 359, 365, 802, 371, 375, 381, 806, 387, 391, 397, 812, 403, 407, + 413, 818, 419, 423, 429, 822, 435, 439, 445, 828, 451, 455, 461, 834, 467, 471, 477, + 838, 483, 487, 493, 844, 499, 503, 509, 850, 515, 519, 525, 854, 531, 535, 541, 860, + 547, 551, 557, 866, 563, 567, 573, 870, 579, 583, 589, 876, 595, 599, 605, 882, 611, + 615, 621, 886, 627, 631, 637, 892, 643, 647, 653, 898, 659, 663, 669, 902, 675, 679, + 685, 908, 691, 695, 701, 914, 707, 711, 717, 918, 723, 727, 733, 924, 739, 743, 749, + 930, 755, 759, 765, 934, 771, 775, 781, 940, 787, 791, 797, 946, 803, 807, 813, 950, + 819, 823, 829, 956, 835, 839, 845, 962, 851, 855, 861, 966, 867, 871, 877, 972, 883, + 887, 893, 978, 899, 903, 909, 982, 915, 919, 925, 988, 931, 935, 941, 990, 947, 951, + 957, 992, 963, 967, 973, 1024, 979, 983, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, + 1002, 2, 20, 8, 14, 24, 36, 30, 40, 52, 46, 56, 68, 62, 72, 84, 78, 88, 100, 94, 104, + 116, 110, 120, 132, 126, 136, 148, 142, 152, 164, 158, 168, 180, 174, 184, 196, 190, + 200, 212, 206, 216, 228, 222, 232, 244, 238, 248, 260, 254, 264, 276, 270, 280, 292, + 286, 296, 308, 302, 312, 324, 318, 328, 340, 334, 344, 356, 350, 360, 372, 366, 376, + 388, 382, 392, 404, 398, 408, 420, 414, 424, 436, 430, 440, 452, 446, 456, 468, 462, + 472, 484, 478, 488, 500, 494, 504, 516, 510, 520, 532, 526, 536, 548, 542, 552, 564, + 558, 568, 580, 574, 584, 596, 590, 600, 612, 606, 616, 628, 622, 632, 644, 638, 648, + 660, 654, 664, 676, 670, 512, 3, 991, 9, 773, 768, 15, 680, 901, 21, 522, 25, 777, 527, + 31, 692, 965, 37, 528, 41, 960, 778, 47, 686, 905, 53, 538, 57, 936, 543, 63, 696, 1007, + 69, 544, 73, 789, 784, 79, 708, 1014, 85, 554, 89, 793, 559, 95, 702, 969, 101, 560, + 105, 911, 794, 111, 712, 974, 117, 570, 121, 948, 575, 127, 724, 1015, 133, 576, 137, + 805, 800, 143, 718, 917, 149, 586, 153, 809, 591, 159, 728, 1008, 165, 592, 169, 970, + 810, 175, 740, 921, 181, 602, 185, 942, 607, 191, 734, 1009, 197, 608, 201, 821, 816, + 207, 744, 975, 213, 618, 217, 825, 623, 223, 756, 1005, 229, 624, 233, 927, 826, 239, + 750, 984, 245, 634, 249, 952, 639, 255, 760, 1010, 261, 640, 265, 837, 832, 271, 772, + 933, 277, 650, 281, 841, 655, 287, 766, 981, 293, 656, 297, 976, 842, 303, 776, 937, 309, + 666, 313, 964, 671, 319, 788, 1011, 325, 672, 329, 853, 848, 335, 782, 1016, 341, 682, + 345, 857, 687, 351, 792, 985, 357, 688, 361, 943, 858, 367, 804, 1003, 373, 698, 377, + 958, 703, 383, 798, 1017, 389, 704, 393, 869, 864, 399, 808, 949, 405, 714, 409, 873, + 719, 415, 820, 1012, 421, 720, 425, 986, 874, 431, 814, 953, 437, 730, 441, 968, 735, + 447, 824, 1013, 453, 736, 457, 885, 880, 463, 836, 989, 469, 746, 473, 889, 751, 479, + 830, 1006, 485, 752, 489, 959, 890, 495, 840, 1004, 501, 762, 505, 980, 767, 511, 852, 4, + 517, 10, 521, 16, 896, 26, 846, 32, 533, 42, 537, 48, 783, 58, 856, 64, 549, 74, 553, 80, + 906, 90, 868, 96, 565, 106, 569, 112, 799, 122, 862, 128, 581, 138, 585, 144, 912, 154, + 72, 160, 597, 170, 601, 176, 815, 186, 884, 192, 613, 202, 617, 208, 922, 218, 878, 224, + 629, 234, 633, 240, 831, 250, 888, 256, 645, 266, 649, 272, 928, 282, 900, 288, 661, 298, + 665, 304, 847, 314, 894, 320, 677, 330, 681, 336, 938, 346, 904, 352, 693, 362, 697, 368, + 863, 378, 916, 384, 709, 394, 713, 400, 944, 410, 910, 416, 725, 426, 729, 432, 879, 442, + 920, 448, 741, 458, 745, 464, 954, 474, 932, 480, 757, 490, 761, 496, 895, 506, 926, 5, + 11, 17, 27, 33, 43, 49, 59, 65, 75, 81, 91, 97, 107, 113, 123, 129, 139, 145, 155, 161, + 71, 177, 187, 193, 203, 209, 219, 225, 235, 241, 251, 257, 267, 273, 283, 289, 299, 305, + 315, 321, 331, 337, 347, 353, 363, 369, 379, 385, 395, 401, 411, 417, 427, 433, 443, 449, + 459, 465, 475, 481, 491, 497, 507, 513, 523, 529, 539, 545, 555, 561, 571, 577, 587, 593, + 603, 609, 619, 625, 635, 641, 651, 657, 667, 673, 683, 689, 699, 705, 715, 721, 731, 737, + 747, 753, 763, 769, 779, 785, 795, 801, 811, 817, 827, 833, 843, 849, 859, 865, 875, 881, + 891, 897, 907, 913, 923, 929, 939, 945, 955, 961, 971, 977, 987, 1018, 1019, 1020, 1021, 1022, }; +// clang-format on + +using namespace std; + +enum class alg_type { std_fn, rng }; + +template +void bm_uniform(benchmark::State& state) { + vector src(state.range()); + mt19937 gen(84710); + uniform_int_distribution dis(1, 580); + ranges::generate(src, [&] { return dis(gen); }); + + vector v; + v.reserve(src.size()); + + for (auto _ : state) { + v = src; + benchmark::DoNotOptimize(v); + if constexpr (Type == alg_type::std_fn) { + nth_element(v.begin(), v.begin() + (v.size() / 2), v.end()); + } else { + ranges::nth_element(v.begin(), v.begin() + (v.size() / 2), v.end()); + } + benchmark::DoNotOptimize(*(v.begin() + (v.size() / 2))); + } +} + +template +void bm_tunkey_adversary(benchmark::State& state) { + vector src(begin(tunkey_ninther_adversary), end(tunkey_ninther_adversary)); + + vector v; + v.reserve(src.size()); + + for (auto _ : state) { + v = src; + benchmark::DoNotOptimize(v); + if constexpr (Type == alg_type::std_fn) { + nth_element(v.begin(), v.begin() + (v.size() >> 1) + (v.size() >> 2), v.end()); + } else { + ranges::nth_element(v.begin(), v.begin() + (v.size() >> 1) + (v.size() >> 2), v.end()); + } + benchmark::DoNotOptimize(*(v.begin() + (v.size() >> 1) + (v.size() >> 2))); + } +} + +BENCHMARK(bm_uniform)->Arg(1024)->Arg(2048)->Arg(4096)->Arg(8192); +BENCHMARK(bm_uniform)->Arg(1024)->Arg(2048)->Arg(4096)->Arg(8192); + +BENCHMARK(bm_tunkey_adversary); +BENCHMARK(bm_tunkey_adversary); + +BENCHMARK_MAIN(); From 6e7c382fdc73cb7e0f650d740fbd7a61495b631c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20M=C3=BCller?= Date: Tue, 19 Nov 2024 14:10:13 +0100 Subject: [PATCH 04/25] fix benchmark compilation on x86 --- benchmarks/src/nth_element.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/benchmarks/src/nth_element.cpp b/benchmarks/src/nth_element.cpp index d31721f7984..addcf784f2e 100644 --- a/benchmarks/src/nth_element.cpp +++ b/benchmarks/src/nth_element.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -75,7 +76,7 @@ enum class alg_type { std_fn, rng }; template void bm_uniform(benchmark::State& state) { - vector src(state.range()); + vector src(static_cast(state.range())); mt19937 gen(84710); uniform_int_distribution dis(1, 580); ranges::generate(src, [&] { return dis(gen); }); From 11026a3185c630db720a3d8b2a1928f672043039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20M=C3=BCller?= Date: Wed, 20 Nov 2024 13:35:06 +0100 Subject: [PATCH 05/25] tunkey -> tukey --- benchmarks/src/nth_element.cpp | 10 +++++----- tests/std/tests/GH_000856_nth_element_linear/test.cpp | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/benchmarks/src/nth_element.cpp b/benchmarks/src/nth_element.cpp index addcf784f2e..8025225050e 100644 --- a/benchmarks/src/nth_element.cpp +++ b/benchmarks/src/nth_element.cpp @@ -9,7 +9,7 @@ #include // clang-format off -constexpr int tunkey_ninther_adversary[] = { +constexpr int tukey_ninther_adversary[] = { 0, 6, 12, 18, 22, 28, 34, 38, 44, 50, 54, 60, 66, 70, 76, 82, 86, 92, 98, 102, 108, 114, 118, 124, 130, 134, 140, 146, 150, 156, 162, 166, 172, 178, 182, 188, 194, 198, 204, 210, 214, 220, 226, 230, 236, 242, 246, 252, 258, 262, 268, 274, 278, 284, 290, @@ -97,8 +97,8 @@ void bm_uniform(benchmark::State& state) { } template -void bm_tunkey_adversary(benchmark::State& state) { - vector src(begin(tunkey_ninther_adversary), end(tunkey_ninther_adversary)); +void bm_tukey_adversary(benchmark::State& state) { + vector src(begin(tukey_ninther_adversary), end(tukey_ninther_adversary)); vector v; v.reserve(src.size()); @@ -118,7 +118,7 @@ void bm_tunkey_adversary(benchmark::State& state) { BENCHMARK(bm_uniform)->Arg(1024)->Arg(2048)->Arg(4096)->Arg(8192); BENCHMARK(bm_uniform)->Arg(1024)->Arg(2048)->Arg(4096)->Arg(8192); -BENCHMARK(bm_tunkey_adversary); -BENCHMARK(bm_tunkey_adversary); +BENCHMARK(bm_tukey_adversary); +BENCHMARK(bm_tukey_adversary); BENCHMARK_MAIN(); diff --git a/tests/std/tests/GH_000856_nth_element_linear/test.cpp b/tests/std/tests/GH_000856_nth_element_linear/test.cpp index 78999a9b5f1..3c229f538bb 100644 --- a/tests/std/tests/GH_000856_nth_element_linear/test.cpp +++ b/tests/std/tests/GH_000856_nth_element_linear/test.cpp @@ -10,7 +10,7 @@ #endif // _HAS_CXX20 // clang-format off -constexpr int tunkey_ninther_adversary[] = { +constexpr int tukey_ninther_adversary[] = { 0, 6, 12, 18, 22, 28, 34, 38, 44, 50, 54, 60, 66, 70, 76, 82, 86, 92, 98, 102, 108, 114, 118, 124, 130, 134, 140, 146, 150, 156, 162, 166, 172, 178, 182, 188, 194, 198, 204, 210, 214, 220, 226, 230, 236, 242, 246, 252, 258, 262, 268, 274, 278, 284, 290, @@ -87,8 +87,8 @@ void check_result(const vector& expected, const vector& computed, Diff } template -void test_nth_element_tunkey_adversary(Algorithm alg) { - vector src(begin(tunkey_ninther_adversary), end(tunkey_ninther_adversary)); +void test_nth_element_tukey_adversary(Algorithm alg) { + vector src(begin(tukey_ninther_adversary), end(tukey_ninther_adversary)); vector sorted = src; sort(sorted.begin(), sorted.end()); @@ -107,11 +107,11 @@ void test_nth_element_tunkey_adversary(Algorithm alg) { } int main() { - test_nth_element_tunkey_adversary( + test_nth_element_tukey_adversary( [](vector& v, vector::difference_type nth) { nth_element(v.begin(), v.begin() + nth, v.end()); }); #if _HAS_CXX20 - test_nth_element_tunkey_adversary([](vector& v, vector::difference_type nth) { + test_nth_element_tukey_adversary([](vector& v, vector::difference_type nth) { ranges::nth_element(v.begin(), v.begin() + nth, v.end()); }); #endif From 53c51c7abac0d9c3ce742e7b0c187e02eca58d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20M=C3=BCller?= Date: Sun, 24 Nov 2024 15:00:56 +0100 Subject: [PATCH 06/25] case --- stl/inc/algorithm | 64 +++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index e0cd8d56ba7..b277232a2e3 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -9377,28 +9377,28 @@ _CONSTEXPR20 void _Nth_element_median_of_medians(_RanIt _First, _RanIt _Nth, _Ra return; } - _Diff _MedianCount = _Length / static_cast<_Diff>(5); - auto _MedianLast = _First + _MedianCount; - auto _Current = _First; - for (auto _MedianDest = _First; _MedianDest != _MedianLast; ++_MedianDest) { - _STD _Swap_med5_unchecked(_Current, _MedianDest, _Pred); + _Diff _Median_count = _Length / static_cast<_Diff>(5); + auto _Median_last = _First + _Median_count; + auto _Current = _First; + for (auto _Median_dest = _First; _Median_dest != _Median_last; ++_Median_dest) { + _STD _Swap_med5_unchecked(_Current, _Median_dest, _Pred); _Current += static_cast<_Diff>(5); } - auto _MedianMid = _First + (_MedianCount >> 1); - _STD _Nth_element_median_of_medians(_First, _MedianMid, _MedianLast, _Pred); + auto _Median_mid = _First + (_Median_count >> 1); + _STD _Nth_element_median_of_medians(_First, _Median_mid, _Median_last, _Pred); - // the medians before and after _MedianMid are - // less equal and greater equal _MedianMid, respectively. - // move the ones after _MedianMid near _Last and then partition - // the elements between the medians at front and back by the pivot _MedianMid - _Diff _MedianGreaterCount = (_MedianLast - _MedianMid) - 1; - auto _MedianGreaterFirst = _Last - _MedianGreaterCount; - _STD _Swap_ranges_unchecked(_MedianMid + static_cast<_Diff>(1), _MedianLast, _MedianGreaterFirst); + // the medians before and after _Median_mid are + // less equal and greater equal _Median_mid, respectively. + // move the ones after _Median_mid near _Last and then partition + // the elements between the medians at front and back by the pivot _Median_mid + _Diff _Median_greater_count = (_Median_last - _Median_mid) - 1; + auto _Median_greater_first = _Last - _Median_greater_count; + _STD _Swap_ranges_unchecked(_Median_mid + static_cast<_Diff>(1), _Median_last, _Median_greater_first); auto _Middle = _First + ((_Last - _First) >> 1); - swap(*_MedianMid, *_Middle); + swap(*_Median_mid, *_Middle); - auto _Mid = _STD _Partition_by_pivot_unchecked(_MedianMid, _Middle, _MedianGreaterFirst, _Pred); + auto _Mid = _STD _Partition_by_pivot_unchecked(_Median_mid, _Middle, _Median_greater_first, _Pred); if (_Mid.second <= _Nth) { _First = _Mid.second; @@ -9568,30 +9568,30 @@ namespace ranges { return; } - _Diff _MedianCount = _Length / static_cast<_Diff>(5); - auto _MedianLast = _First + _MedianCount; - auto _Current = _First; - for (auto _MedianDest = _First; _MedianDest != _MedianLast; ++_MedianDest) { - _Swap_med5(_Current, _MedianDest, _Pred, _Proj); + _Diff _Median_count = _Length / static_cast<_Diff>(5); + auto _Median_last = _First + _Median_count; + auto _Current = _First; + for (auto _Median_dest = _First; _Median_dest != _Median_last; ++_Median_dest) { + _Swap_med5(_Current, _Median_dest, _Pred, _Proj); _Current += static_cast<_Diff>(5); } - auto _MedianMid = _First + (_MedianCount >> 1); - _Nth_element_median_of_medians_unchecked(_First, _MedianMid, _MedianLast, _Pred, _Proj); + auto _Median_mid = _First + (_Median_count >> 1); + _Nth_element_median_of_medians_unchecked(_First, _Median_mid, _Median_last, _Pred, _Proj); - // the medians before and after _MedianMid are - // less equal and greater equal _MedianMid, respectively. - // move the ones after _MedianMid near _Last and then partition - // the elements between the medians at front and back by the pivot _MedianMid - _Diff _MedianGreaterCount = (_MedianLast - _MedianMid) - 1; - auto _MedianGreaterFirst = _Last - _MedianGreaterCount; + // the medians before and after _Median_mid are + // less equal and greater equal _Median_mid, respectively. + // move the ones after _Median_mid near _Last and then partition + // the elements between the medians at front and back by the pivot _Median_mid + _Diff _Median_greater_count = (_Median_last - _Median_mid) - 1; + auto _Median_greater_first = _Last - _Median_greater_count; (void) _RANGES _Swap_ranges_common( - _MedianMid + static_cast<_Diff>(1), _STD move(_MedianLast), _MedianGreaterFirst, _Last); + _Median_mid + static_cast<_Diff>(1), _STD move(_Median_last), _Median_greater_first, _Last); auto _Middle = _First + ((_Last - _First) >> 1); - _RANGES iter_swap(_MedianMid, _Middle); + _RANGES iter_swap(_Median_mid, _Middle); subrange<_It> _Mid = _RANGES _Partition_by_pivot_common( - _STD move(_MedianMid), _STD move(_Middle), _STD move(_MedianGreaterFirst), _Pred, _Proj); + _STD move(_Median_mid), _STD move(_Middle), _STD move(_Median_greater_first), _Pred, _Proj); if (_Mid.end() <= _Nth) { _First = _Mid.end(); From 757e5f9124425179e919bd457b6c9dd21f41869b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20M=C3=BCller?= Date: Sun, 9 Mar 2025 20:11:55 +0100 Subject: [PATCH 07/25] address some review comments --- benchmarks/src/nth_element.cpp | 108 +++++++++++++----- stl/inc/algorithm | 12 ++ .../GH_000856_nth_element_linear/test.cpp | 74 +++++++++++- 3 files changed, 163 insertions(+), 31 deletions(-) diff --git a/benchmarks/src/nth_element.cpp b/benchmarks/src/nth_element.cpp index 8025225050e..250a4616404 100644 --- a/benchmarks/src/nth_element.cpp +++ b/benchmarks/src/nth_element.cpp @@ -9,7 +9,7 @@ #include // clang-format off -constexpr int tukey_ninther_adversary[] = { +constexpr int tukey_ninther_adversary1[] = { 0, 6, 12, 18, 22, 28, 34, 38, 44, 50, 54, 60, 66, 70, 76, 82, 86, 92, 98, 102, 108, 114, 118, 124, 130, 134, 140, 146, 150, 156, 162, 166, 172, 178, 182, 188, 194, 198, 204, 210, 214, 220, 226, 230, 236, 242, 246, 252, 258, 262, 268, 274, 278, 284, 290, @@ -68,6 +68,64 @@ constexpr int tukey_ninther_adversary[] = { 603, 609, 619, 625, 635, 641, 651, 657, 667, 673, 683, 689, 699, 705, 715, 721, 731, 737, 747, 753, 763, 769, 779, 785, 795, 801, 811, 817, 827, 833, 843, 849, 859, 865, 875, 881, 891, 897, 907, 913, 923, 929, 939, 945, 955, 961, 971, 977, 987, 1018, 1019, 1020, 1021, 1022, }; + +constexpr int tukey_ninther_adversary2[] = { 1024, 31, 30, 29, 28, 36, 46, 51, 61, 67, 77, + 82, 92, 98, 108, 118, 123, 133, 139, 149, 154, 164, 170, 180, 190, 195, 205, 211, 221, + 226, 236, 242, 252, 262, 267, 277, 283, 293, 298, 308, 314, 324, 334, 339, 349, 355, 365, + 370, 380, 386, 396, 406, 411, 421, 427, 437, 442, 452, 458, 468, 478, 483, 493, 499, 509, + 514, 524, 530, 540, 550, 555, 565, 571, 581, 586, 596, 602, 612, 622, 627, 637, 643, 653, + 658, 668, 674, 684, 694, 699, 709, 715, 725, 730, 740, 746, 756, 766, 771, 781, 787, 797, + 802, 812, 818, 828, 838, 843, 853, 859, 869, 874, 884, 890, 900, 910, 915, 925, 931, 941, + 946, 956, 962, 972, 982, 987, 997, 1003, 1013, 1018, 343, 523, 127, 529, 86, 539, 358, + 549, 178, 554, 107, 564, 374, 570, 183, 580, 384, 585, 389, 595, 394, 601, 399, 611, 404, + 621, 409, 626, 18, 636, 419, 642, 425, 652, 318, 657, 435, 667, 440, 673, 169, 683, 450, + 693, 224, 698, 256, 708, 179, 714, 66, 724, 234, 729, 487, 739, 189, 745, 34, 755, 502, + 765, 71, 770, 188, 780, 518, 786, 76, 796, 528, 801, 533, 811, 538, 817, 543, 827, 548, + 837, 553, 842, 163, 852, 563, 858, 569, 868, 286, 873, 579, 883, 584, 889, 70, 899, 594, + 909, 219, 914, 97, 924, 235, 930, 91, 940, 462, 945, 631, 955, 173, 961, 241, 971, 646, + 981, 322, 986, 272, 996, 662, 1002, 327, 1012, 672, 1017, 677, 1023, 682, 184, 687, 44, + 692, 80, 697, 703, 390, 347, 707, 193, 713, 718, 534, 276, 723, 26, 728, 734, 32, 200, 738, + 744, 368, 749, 137, 754, 15, 759, 25, 764, 378, 769, 775, 575, 90, 779, 148, 785, 790, 297, + 215, 795, 225, 800, 806, 447, 56, 810, 816, 27, 821, 153, 826, 616, 831, 152, 836, 59, 841, + 847, 472, 632, 851, 116, 857, 862, 430, 214, 867, 647, 872, 878, 106, 251, 882, 888, 21, + 893, 332, 898, 87, 903, 132, 908, 678, 913, 919, 456, 168, 923, 230, 929, 934, 519, 466, + 939, 19, 944, 950, 353, 471, 954, 960, 364, 965, 719, 970, 271, 975, 544, 980, 369, 985, + 991, 210, 491, 995, 282, 1001, 1006, 750, 250, 1011, 121, 1016, 1022, 385, 292, 507, 65, + 512, 255, 102, 776, 395, 45, 159, 287, 522, 260, 591, 791, 405, 117, 204, 307, 49, 265, + 302, 807, 606, 400, 22, 111, 16, 344, 822, 420, 313, 303, 415, 832, 275, 203, 559, 23, 416, + 426, 323, 848, 281, 231, 209, 317, 574, 436, 17, 863, 142, 333, 220, 488, 431, 441, 81, + 879, 75, 590, 451, 663, 328, 446, 894, 296, 375, 600, 261, 904, 457, 348, 605, 337, 610, + 60, 688, 920, 467, 96, 615, 461, 620, 306, 354, 935, 477, 704, 625, 24, 312, 128, 143, 951, + 476, 635, 174, 131, 641, 240, 966, 492, 481, 138, 359, 976, 40, 363, 651, 735, 656, 498, + 379, 992, 20, 497, 39, 560, 666, 508, 112, 1007, 246, 158, 162, 760, 503, 513, 482, 291, + 410, 245, 338, 199, 266, 147, 194, 101, 122, 55, 50, 14, 13, 43, 48, 58, 64, 74, 79, 95, + 105, 115, 120, 130, 136, 146, 151, 167, 177, 187, 192, 202, 208, 218, 223, 239, 249, 259, + 264, 274, 280, 290, 295, 311, 321, 331, 336, 346, 352, 362, 367, 383, 393, 403, 408, 418, + 424, 434, 439, 455, 465, 475, 480, 490, 496, 506, 511, 527, 537, 547, 552, 562, 568, 578, + 583, 599, 609, 619, 624, 634, 640, 650, 655, 671, 681, 691, 696, 706, 712, 722, 727, 743, + 753, 763, 768, 778, 784, 794, 799, 815, 825, 835, 840, 850, 856, 866, 871, 887, 897, 907, + 912, 922, 928, 938, 943, 959, 969, 979, 984, 994, 1000, 1010, 1015, 1021, 1005, 990, 953, + 974, 964, 949, 933, 918, 881, 902, 892, 877, 861, 846, 809, 830, 820, 805, 789, 774, 737, + 758, 748, 733, 717, 702, 665, 686, 676, 661, 645, 630, 593, 614, 604, 589, 573, 558, 521, + 542, 532, 517, 501, 486, 449, 470, 460, 445, 429, 414, 377, 398, 388, 373, 357, 342, 305, + 326, 316, 301, 285, 270, 233, 254, 244, 229, 213, 198, 161, 182, 172, 157, 141, 126, 89, + 110, 100, 85, 69, 54, 12, 38, 11, 10, 9, 8, 53, 84, 99, 125, 156, 171, 197, 228, 243, 269, + 300, 315, 341, 372, 387, 413, 444, 459, 485, 516, 531, 557, 588, 603, 629, 660, 675, 701, + 732, 747, 773, 804, 819, 845, 876, 891, 917, 948, 963, 989, 1020, 1014, 63, 253, 258, 263, + 279, 273, 284, 289, 294, 310, 304, 320, 73, 325, 330, 335, 351, 345, 356, 361, 366, 382, + 376, 392, 88, 397, 402, 407, 423, 417, 428, 433, 438, 454, 448, 464, 109, 469, 474, 479, + 495, 489, 500, 505, 510, 526, 520, 536, 135, 541, 546, 551, 567, 561, 572, 577, 582, 598, + 592, 608, 145, 613, 618, 623, 639, 633, 644, 649, 654, 670, 664, 680, 160, 685, 690, 695, + 711, 705, 716, 721, 726, 742, 736, 752, 181, 757, 762, 767, 783, 777, 788, 793, 798, 814, + 808, 824, 207, 829, 834, 839, 855, 849, 860, 865, 870, 886, 880, 896, 217, 901, 906, 911, + 927, 921, 932, 937, 942, 958, 952, 968, 232, 973, 978, 983, 999, 993, 1004, 1009, 248, 238, + 222, 212, 201, 191, 186, 37, 176, 166, 150, 140, 129, 119, 114, 3, 104, 94, 78, 68, 57, 47, + 42, 6, 7, 4, 5, 2, -1, 33, 35, 41, 52, 62, 72, 83, 93, 103, 113, 124, 134, 144, 155, 165, + 175, 185, 196, 206, 216, 227, 237, 247, 257, 268, 278, 288, 299, 309, 319, 329, 340, 350, + 360, 371, 381, 391, 401, 412, 422, 432, 443, 453, 463, 473, 484, 494, 504, 515, 525, 535, + 545, 556, 566, 576, 587, 597, 607, 617, 628, 638, 648, 659, 669, 679, 689, 700, 710, 720, + 731, 741, 751, 761, 772, 782, 792, 803, 813, 823, 833, 844, 854, 864, 875, 885, 895, 905, + 916, 926, 936, 947, 957, 967, 977, 988, 998, 1008, 1019, }; // clang-format on using namespace std; @@ -75,11 +133,7 @@ using namespace std; enum class alg_type { std_fn, rng }; template -void bm_uniform(benchmark::State& state) { - vector src(static_cast(state.range())); - mt19937 gen(84710); - uniform_int_distribution dis(1, 580); - ranges::generate(src, [&] { return dis(gen); }); +void benchmark_common(benchmark::State& state, vector src) { vector v; v.reserve(src.size()); @@ -87,38 +141,40 @@ void bm_uniform(benchmark::State& state) { for (auto _ : state) { v = src; benchmark::DoNotOptimize(v); + auto mid = v.begin() + (v.size() / 2); if constexpr (Type == alg_type::std_fn) { - nth_element(v.begin(), v.begin() + (v.size() / 2), v.end()); + nth_element(v.begin(), mid, v.end()); } else { - ranges::nth_element(v.begin(), v.begin() + (v.size() / 2), v.end()); + ranges::nth_element(v.begin(), mid, v.end()); } - benchmark::DoNotOptimize(*(v.begin() + (v.size() / 2))); + benchmark::DoNotOptimize(*mid); } } template -void bm_tukey_adversary(benchmark::State& state) { - vector src(begin(tukey_ninther_adversary), end(tukey_ninther_adversary)); - - vector v; - v.reserve(src.size()); +void bm_uniform(benchmark::State& state) { + vector src(static_cast(state.range())); + mt19937 gen(84710); + uniform_int_distribution dis(1, 580); + ranges::generate(src, [&] { return dis(gen); }); + benchmark_common(state, move(src)); +} - for (auto _ : state) { - v = src; - benchmark::DoNotOptimize(v); - if constexpr (Type == alg_type::std_fn) { - nth_element(v.begin(), v.begin() + (v.size() >> 1) + (v.size() >> 2), v.end()); - } else { - ranges::nth_element(v.begin(), v.begin() + (v.size() >> 1) + (v.size() >> 2), v.end()); - } - benchmark::DoNotOptimize(*(v.begin() + (v.size() >> 1) + (v.size() >> 2))); - } +template +void bm_tukey_adversary(benchmark::State& state, const int* const adversary_first, const int* const adversary_last) { + benchmark_common(state, vector(adversary_first, adversary_last)); } BENCHMARK(bm_uniform)->Arg(1024)->Arg(2048)->Arg(4096)->Arg(8192); BENCHMARK(bm_uniform)->Arg(1024)->Arg(2048)->Arg(4096)->Arg(8192); -BENCHMARK(bm_tukey_adversary); -BENCHMARK(bm_tukey_adversary); +BENCHMARK_CAPTURE( + bm_tukey_adversary, adversary1, begin(tukey_ninther_adversary1), end(tukey_ninther_adversary1)); +BENCHMARK_CAPTURE( + bm_tukey_adversary, adversary1, begin(tukey_ninther_adversary1), end(tukey_ninther_adversary1)); +BENCHMARK_CAPTURE( + bm_tukey_adversary, adversary2, begin(tukey_ninther_adversary2), end(tukey_ninther_adversary2)); +BENCHMARK_CAPTURE( + bm_tukey_adversary, adversary2, begin(tukey_ninther_adversary2), end(tukey_ninther_adversary2)); BENCHMARK_MAIN(); diff --git a/stl/inc/algorithm b/stl/inc/algorithm index edcd05d9a82..71d38d0d91d 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -9405,6 +9405,7 @@ _CONSTEXPR20 void _Nth_element_median_of_medians(_RanIt _First, _RanIt _Nth, _Ra return; } + // collect the medians of five at the beginning of the range _Diff _Median_count = _Length / static_cast<_Diff>(5); auto _Median_last = _First + _Median_count; auto _Current = _First; @@ -9413,6 +9414,7 @@ _CONSTEXPR20 void _Nth_element_median_of_medians(_RanIt _First, _RanIt _Nth, _Ra _Current += static_cast<_Diff>(5); } + // find the median of medians auto _Median_mid = _First + (_Median_count >> 1); _STD _Nth_element_median_of_medians(_First, _Median_mid, _Median_last, _Pred); @@ -9423,6 +9425,9 @@ _CONSTEXPR20 void _Nth_element_median_of_medians(_RanIt _First, _RanIt _Nth, _Ra _Diff _Median_greater_count = (_Median_last - _Median_mid) - 1; auto _Median_greater_first = _Last - _Median_greater_count; _STD _Swap_ranges_unchecked(_Median_mid + static_cast<_Diff>(1), _Median_last, _Median_greater_first); + + // swap the median of medians to the middle + // to reduce the number of times it will be moved by the partition function auto _Middle = _First + ((_Last - _First) >> 1); swap(*_Median_mid, *_Middle); @@ -9450,6 +9455,7 @@ _CONSTEXPR20 void _Nth_element_unchecked(_RanIt _First, _RanIt _Nth, _RanIt _Las } if (_Ideal < (_Length >> 1)) { + // fall back to medians-of-medians-of-five algorithm to guarantee O(n) runtime performance _STD _Nth_element_median_of_medians(_First, _Nth, _Last, _Pred); return; } @@ -9596,6 +9602,7 @@ namespace ranges { return; } + // collect the medians of five at the beginning of the range _Diff _Median_count = _Length / static_cast<_Diff>(5); auto _Median_last = _First + _Median_count; auto _Current = _First; @@ -9604,6 +9611,7 @@ namespace ranges { _Current += static_cast<_Diff>(5); } + // find the median of medians auto _Median_mid = _First + (_Median_count >> 1); _Nth_element_median_of_medians_unchecked(_First, _Median_mid, _Median_last, _Pred, _Proj); @@ -9615,6 +9623,9 @@ namespace ranges { auto _Median_greater_first = _Last - _Median_greater_count; (void) _RANGES _Swap_ranges_common( _Median_mid + static_cast<_Diff>(1), _STD move(_Median_last), _Median_greater_first, _Last); + + // swap the median of medians to the middle + // to reduce the number of times it will be moved by the partition function auto _Middle = _First + ((_Last - _First) >> 1); _RANGES iter_swap(_Median_mid, _Middle); @@ -9651,6 +9662,7 @@ namespace ranges { } if (_Ideal < (_Length >> 1)) { + // fall back to medians-of-medians-of-five algorithm to guarantee O(n) runtime performance _Nth_element_median_of_medians_unchecked( _STD move(_First), _STD move(_Nth), _STD move(_Last), _Pred, _Proj); return; diff --git a/tests/std/tests/GH_000856_nth_element_linear/test.cpp b/tests/std/tests/GH_000856_nth_element_linear/test.cpp index 3c229f538bb..550b50f95b4 100644 --- a/tests/std/tests/GH_000856_nth_element_linear/test.cpp +++ b/tests/std/tests/GH_000856_nth_element_linear/test.cpp @@ -10,7 +10,7 @@ #endif // _HAS_CXX20 // clang-format off -constexpr int tukey_ninther_adversary[] = { +constexpr int tukey_ninther_adversary1[] = { 0, 6, 12, 18, 22, 28, 34, 38, 44, 50, 54, 60, 66, 70, 76, 82, 86, 92, 98, 102, 108, 114, 118, 124, 130, 134, 140, 146, 150, 156, 162, 166, 172, 178, 182, 188, 194, 198, 204, 210, 214, 220, 226, 230, 236, 242, 246, 252, 258, 262, 268, 274, 278, 284, 290, @@ -69,6 +69,64 @@ constexpr int tukey_ninther_adversary[] = { 603, 609, 619, 625, 635, 641, 651, 657, 667, 673, 683, 689, 699, 705, 715, 721, 731, 737, 747, 753, 763, 769, 779, 785, 795, 801, 811, 817, 827, 833, 843, 849, 859, 865, 875, 881, 891, 897, 907, 913, 923, 929, 939, 945, 955, 961, 971, 977, 987, 1018, 1019, 1020, 1021, 1022, }; + +constexpr int tukey_ninther_adversary2[] = { 1024, 31, 30, 29, 28, 36, 46, 51, 61, 67, 77, + 82, 92, 98, 108, 118, 123, 133, 139, 149, 154, 164, 170, 180, 190, 195, 205, 211, 221, + 226, 236, 242, 252, 262, 267, 277, 283, 293, 298, 308, 314, 324, 334, 339, 349, 355, 365, + 370, 380, 386, 396, 406, 411, 421, 427, 437, 442, 452, 458, 468, 478, 483, 493, 499, 509, + 514, 524, 530, 540, 550, 555, 565, 571, 581, 586, 596, 602, 612, 622, 627, 637, 643, 653, + 658, 668, 674, 684, 694, 699, 709, 715, 725, 730, 740, 746, 756, 766, 771, 781, 787, 797, + 802, 812, 818, 828, 838, 843, 853, 859, 869, 874, 884, 890, 900, 910, 915, 925, 931, 941, + 946, 956, 962, 972, 982, 987, 997, 1003, 1013, 1018, 343, 523, 127, 529, 86, 539, 358, + 549, 178, 554, 107, 564, 374, 570, 183, 580, 384, 585, 389, 595, 394, 601, 399, 611, 404, + 621, 409, 626, 18, 636, 419, 642, 425, 652, 318, 657, 435, 667, 440, 673, 169, 683, 450, + 693, 224, 698, 256, 708, 179, 714, 66, 724, 234, 729, 487, 739, 189, 745, 34, 755, 502, + 765, 71, 770, 188, 780, 518, 786, 76, 796, 528, 801, 533, 811, 538, 817, 543, 827, 548, + 837, 553, 842, 163, 852, 563, 858, 569, 868, 286, 873, 579, 883, 584, 889, 70, 899, 594, + 909, 219, 914, 97, 924, 235, 930, 91, 940, 462, 945, 631, 955, 173, 961, 241, 971, 646, + 981, 322, 986, 272, 996, 662, 1002, 327, 1012, 672, 1017, 677, 1023, 682, 184, 687, 44, + 692, 80, 697, 703, 390, 347, 707, 193, 713, 718, 534, 276, 723, 26, 728, 734, 32, 200, 738, + 744, 368, 749, 137, 754, 15, 759, 25, 764, 378, 769, 775, 575, 90, 779, 148, 785, 790, 297, + 215, 795, 225, 800, 806, 447, 56, 810, 816, 27, 821, 153, 826, 616, 831, 152, 836, 59, 841, + 847, 472, 632, 851, 116, 857, 862, 430, 214, 867, 647, 872, 878, 106, 251, 882, 888, 21, + 893, 332, 898, 87, 903, 132, 908, 678, 913, 919, 456, 168, 923, 230, 929, 934, 519, 466, + 939, 19, 944, 950, 353, 471, 954, 960, 364, 965, 719, 970, 271, 975, 544, 980, 369, 985, + 991, 210, 491, 995, 282, 1001, 1006, 750, 250, 1011, 121, 1016, 1022, 385, 292, 507, 65, + 512, 255, 102, 776, 395, 45, 159, 287, 522, 260, 591, 791, 405, 117, 204, 307, 49, 265, + 302, 807, 606, 400, 22, 111, 16, 344, 822, 420, 313, 303, 415, 832, 275, 203, 559, 23, 416, + 426, 323, 848, 281, 231, 209, 317, 574, 436, 17, 863, 142, 333, 220, 488, 431, 441, 81, + 879, 75, 590, 451, 663, 328, 446, 894, 296, 375, 600, 261, 904, 457, 348, 605, 337, 610, + 60, 688, 920, 467, 96, 615, 461, 620, 306, 354, 935, 477, 704, 625, 24, 312, 128, 143, 951, + 476, 635, 174, 131, 641, 240, 966, 492, 481, 138, 359, 976, 40, 363, 651, 735, 656, 498, + 379, 992, 20, 497, 39, 560, 666, 508, 112, 1007, 246, 158, 162, 760, 503, 513, 482, 291, + 410, 245, 338, 199, 266, 147, 194, 101, 122, 55, 50, 14, 13, 43, 48, 58, 64, 74, 79, 95, + 105, 115, 120, 130, 136, 146, 151, 167, 177, 187, 192, 202, 208, 218, 223, 239, 249, 259, + 264, 274, 280, 290, 295, 311, 321, 331, 336, 346, 352, 362, 367, 383, 393, 403, 408, 418, + 424, 434, 439, 455, 465, 475, 480, 490, 496, 506, 511, 527, 537, 547, 552, 562, 568, 578, + 583, 599, 609, 619, 624, 634, 640, 650, 655, 671, 681, 691, 696, 706, 712, 722, 727, 743, + 753, 763, 768, 778, 784, 794, 799, 815, 825, 835, 840, 850, 856, 866, 871, 887, 897, 907, + 912, 922, 928, 938, 943, 959, 969, 979, 984, 994, 1000, 1010, 1015, 1021, 1005, 990, 953, + 974, 964, 949, 933, 918, 881, 902, 892, 877, 861, 846, 809, 830, 820, 805, 789, 774, 737, + 758, 748, 733, 717, 702, 665, 686, 676, 661, 645, 630, 593, 614, 604, 589, 573, 558, 521, + 542, 532, 517, 501, 486, 449, 470, 460, 445, 429, 414, 377, 398, 388, 373, 357, 342, 305, + 326, 316, 301, 285, 270, 233, 254, 244, 229, 213, 198, 161, 182, 172, 157, 141, 126, 89, + 110, 100, 85, 69, 54, 12, 38, 11, 10, 9, 8, 53, 84, 99, 125, 156, 171, 197, 228, 243, 269, + 300, 315, 341, 372, 387, 413, 444, 459, 485, 516, 531, 557, 588, 603, 629, 660, 675, 701, + 732, 747, 773, 804, 819, 845, 876, 891, 917, 948, 963, 989, 1020, 1014, 63, 253, 258, 263, + 279, 273, 284, 289, 294, 310, 304, 320, 73, 325, 330, 335, 351, 345, 356, 361, 366, 382, + 376, 392, 88, 397, 402, 407, 423, 417, 428, 433, 438, 454, 448, 464, 109, 469, 474, 479, + 495, 489, 500, 505, 510, 526, 520, 536, 135, 541, 546, 551, 567, 561, 572, 577, 582, 598, + 592, 608, 145, 613, 618, 623, 639, 633, 644, 649, 654, 670, 664, 680, 160, 685, 690, 695, + 711, 705, 716, 721, 726, 742, 736, 752, 181, 757, 762, 767, 783, 777, 788, 793, 798, 814, + 808, 824, 207, 829, 834, 839, 855, 849, 860, 865, 870, 886, 880, 896, 217, 901, 906, 911, + 927, 921, 932, 937, 942, 958, 952, 968, 232, 973, 978, 983, 999, 993, 1004, 1009, 248, 238, + 222, 212, 201, 191, 186, 37, 176, 166, 150, 140, 129, 119, 114, 3, 104, 94, 78, 68, 57, 47, + 42, 6, 7, 4, 5, 2, -1, 33, 35, 41, 52, 62, 72, 83, 93, 103, 113, 124, 134, 144, 155, 165, + 175, 185, 196, 206, 216, 227, 237, 247, 257, 268, 278, 288, 299, 309, 319, 329, 340, 350, + 360, 371, 381, 391, 401, 412, 422, 432, 443, 453, 463, 473, 484, 494, 504, 515, 525, 535, + 545, 556, 566, 576, 587, 597, 607, 617, 628, 638, 648, 659, 669, 679, 689, 700, 710, 720, + 731, 741, 751, 761, 772, 782, 792, 803, 813, 823, 833, 844, 854, 864, 875, 885, 895, 905, + 916, 926, 936, 947, 957, 967, 977, 988, 998, 1008, 1019, }; // clang-format on using namespace std; @@ -87,16 +145,16 @@ void check_result(const vector& expected, const vector& computed, Diff } template -void test_nth_element_tukey_adversary(Algorithm alg) { - vector src(begin(tukey_ninther_adversary), end(tukey_ninther_adversary)); +void test_nth_element(Algorithm alg, const int* const first, const int* const last) { + vector src(first, last); vector sorted = src; sort(sorted.begin(), sorted.end()); vector v; v.reserve(src.size()); - for (vector::difference_type nth{}, last = src.end() - src.begin(); nth < last; - nth += static_cast::difference_type>(15)) { + for (vector::difference_type nth{}, size = src.end() - src.begin(); nth < size; + nth += static_cast::difference_type>(15)) { v = src; alg(v, nth); check_result(sorted, v, nth); @@ -106,6 +164,12 @@ void test_nth_element_tukey_adversary(Algorithm alg) { check_result(sorted, v, (v.end() - v.begin()) - static_cast::difference_type>(1)); } +template +void test_nth_element_tukey_adversary(Algorithm alg) { + test_nth_element(alg, begin(tukey_ninther_adversary1), end(tukey_ninther_adversary1)); + test_nth_element(alg, begin(tukey_ninther_adversary2), end(tukey_ninther_adversary2)); +} + int main() { test_nth_element_tukey_adversary( [](vector& v, vector::difference_type nth) { nth_element(v.begin(), v.begin() + nth, v.end()); }); From 5babd6c221d647100db00d819f0045cc5689d52c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20M=C3=BCller?= Date: Sun, 9 Mar 2025 20:37:21 +0100 Subject: [PATCH 08/25] extend one more comment --- stl/inc/algorithm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 71d38d0d91d..a1a9502d761 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -9422,6 +9422,7 @@ _CONSTEXPR20 void _Nth_element_median_of_medians(_RanIt _First, _RanIt _Nth, _Ra // less equal and greater equal _Median_mid, respectively. // move the ones after _Median_mid near _Last and then partition // the elements between the medians at front and back by the pivot _Median_mid + // so that they do not have to be considered or moved in the partitioning pass. _Diff _Median_greater_count = (_Median_last - _Median_mid) - 1; auto _Median_greater_first = _Last - _Median_greater_count; _STD _Swap_ranges_unchecked(_Median_mid + static_cast<_Diff>(1), _Median_last, _Median_greater_first); @@ -9619,6 +9620,7 @@ namespace ranges { // less equal and greater equal _Median_mid, respectively. // move the ones after _Median_mid near _Last and then partition // the elements between the medians at front and back by the pivot _Median_mid + // so that they do not have to be considered or moved in the partitioning pass. _Diff _Median_greater_count = (_Median_last - _Median_mid) - 1; auto _Median_greater_first = _Last - _Median_greater_count; (void) _RANGES _Swap_ranges_common( From 1b857f995cd035e1d68989ff1a6f125afa866d3e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 23 Apr 2025 02:52:32 -0700 Subject: [PATCH 09/25] Enable clang-format and remove trailing commas for The Adversaries. --- benchmarks/src/nth_element.cpp | 207 ++++++++---------- .../GH_000856_nth_element_linear/test.cpp | 207 ++++++++---------- 2 files changed, 178 insertions(+), 236 deletions(-) diff --git a/benchmarks/src/nth_element.cpp b/benchmarks/src/nth_element.cpp index 250a4616404..d0b541c3829 100644 --- a/benchmarks/src/nth_element.cpp +++ b/benchmarks/src/nth_element.cpp @@ -8,125 +8,96 @@ #include #include -// clang-format off -constexpr int tukey_ninther_adversary1[] = { - 0, 6, 12, 18, 22, 28, 34, 38, 44, 50, 54, 60, 66, 70, 76, 82, 86, 92, 98, 102, 108, - 114, 118, 124, 130, 134, 140, 146, 150, 156, 162, 166, 172, 178, 182, 188, 194, 198, - 204, 210, 214, 220, 226, 230, 236, 242, 246, 252, 258, 262, 268, 274, 278, 284, 290, - 294, 300, 306, 310, 316, 322, 326, 332, 338, 342, 348, 354, 358, 364, 370, 374, 380, - 386, 390, 396, 402, 406, 412, 418, 422, 428, 434, 438, 444, 450, 454, 460, 466, 470, - 476, 482, 486, 492, 498, 502, 508, 514, 518, 524, 530, 534, 540, 546, 550, 556, 562, - 566, 572, 578, 582, 588, 594, 598, 604, 610, 614, 620, 626, 630, 636, 642, 646, 652, - 658, 662, 668, 674, 678, 1, 7, 13, 684, 19, 23, 29, 690, 35, 39, 45, 694, 51, 55, 61, - 700, 67, 71, 77, 706, 83, 87, 93, 710, 99, 103, 109, 716, 115, 119, 125, 722, 131, 135, - 141, 726, 147, 151, 157, 732, 163, 167, 173, 738, 179, 183, 189, 742, 195, 199, 205, - 748, 211, 215, 221, 754, 227, 231, 237, 758, 243, 247, 253, 764, 259, 263, 269, 770, - 275, 279, 285, 774, 291, 295, 301, 780, 307, 311, 317, 786, 323, 327, 333, 790, 339, - 343, 349, 796, 355, 359, 365, 802, 371, 375, 381, 806, 387, 391, 397, 812, 403, 407, - 413, 818, 419, 423, 429, 822, 435, 439, 445, 828, 451, 455, 461, 834, 467, 471, 477, - 838, 483, 487, 493, 844, 499, 503, 509, 850, 515, 519, 525, 854, 531, 535, 541, 860, - 547, 551, 557, 866, 563, 567, 573, 870, 579, 583, 589, 876, 595, 599, 605, 882, 611, - 615, 621, 886, 627, 631, 637, 892, 643, 647, 653, 898, 659, 663, 669, 902, 675, 679, - 685, 908, 691, 695, 701, 914, 707, 711, 717, 918, 723, 727, 733, 924, 739, 743, 749, - 930, 755, 759, 765, 934, 771, 775, 781, 940, 787, 791, 797, 946, 803, 807, 813, 950, - 819, 823, 829, 956, 835, 839, 845, 962, 851, 855, 861, 966, 867, 871, 877, 972, 883, - 887, 893, 978, 899, 903, 909, 982, 915, 919, 925, 988, 931, 935, 941, 990, 947, 951, - 957, 992, 963, 967, 973, 1024, 979, 983, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, - 1002, 2, 20, 8, 14, 24, 36, 30, 40, 52, 46, 56, 68, 62, 72, 84, 78, 88, 100, 94, 104, - 116, 110, 120, 132, 126, 136, 148, 142, 152, 164, 158, 168, 180, 174, 184, 196, 190, - 200, 212, 206, 216, 228, 222, 232, 244, 238, 248, 260, 254, 264, 276, 270, 280, 292, - 286, 296, 308, 302, 312, 324, 318, 328, 340, 334, 344, 356, 350, 360, 372, 366, 376, - 388, 382, 392, 404, 398, 408, 420, 414, 424, 436, 430, 440, 452, 446, 456, 468, 462, - 472, 484, 478, 488, 500, 494, 504, 516, 510, 520, 532, 526, 536, 548, 542, 552, 564, - 558, 568, 580, 574, 584, 596, 590, 600, 612, 606, 616, 628, 622, 632, 644, 638, 648, - 660, 654, 664, 676, 670, 512, 3, 991, 9, 773, 768, 15, 680, 901, 21, 522, 25, 777, 527, - 31, 692, 965, 37, 528, 41, 960, 778, 47, 686, 905, 53, 538, 57, 936, 543, 63, 696, 1007, - 69, 544, 73, 789, 784, 79, 708, 1014, 85, 554, 89, 793, 559, 95, 702, 969, 101, 560, - 105, 911, 794, 111, 712, 974, 117, 570, 121, 948, 575, 127, 724, 1015, 133, 576, 137, - 805, 800, 143, 718, 917, 149, 586, 153, 809, 591, 159, 728, 1008, 165, 592, 169, 970, - 810, 175, 740, 921, 181, 602, 185, 942, 607, 191, 734, 1009, 197, 608, 201, 821, 816, - 207, 744, 975, 213, 618, 217, 825, 623, 223, 756, 1005, 229, 624, 233, 927, 826, 239, - 750, 984, 245, 634, 249, 952, 639, 255, 760, 1010, 261, 640, 265, 837, 832, 271, 772, - 933, 277, 650, 281, 841, 655, 287, 766, 981, 293, 656, 297, 976, 842, 303, 776, 937, 309, - 666, 313, 964, 671, 319, 788, 1011, 325, 672, 329, 853, 848, 335, 782, 1016, 341, 682, - 345, 857, 687, 351, 792, 985, 357, 688, 361, 943, 858, 367, 804, 1003, 373, 698, 377, - 958, 703, 383, 798, 1017, 389, 704, 393, 869, 864, 399, 808, 949, 405, 714, 409, 873, - 719, 415, 820, 1012, 421, 720, 425, 986, 874, 431, 814, 953, 437, 730, 441, 968, 735, - 447, 824, 1013, 453, 736, 457, 885, 880, 463, 836, 989, 469, 746, 473, 889, 751, 479, - 830, 1006, 485, 752, 489, 959, 890, 495, 840, 1004, 501, 762, 505, 980, 767, 511, 852, 4, - 517, 10, 521, 16, 896, 26, 846, 32, 533, 42, 537, 48, 783, 58, 856, 64, 549, 74, 553, 80, - 906, 90, 868, 96, 565, 106, 569, 112, 799, 122, 862, 128, 581, 138, 585, 144, 912, 154, - 72, 160, 597, 170, 601, 176, 815, 186, 884, 192, 613, 202, 617, 208, 922, 218, 878, 224, - 629, 234, 633, 240, 831, 250, 888, 256, 645, 266, 649, 272, 928, 282, 900, 288, 661, 298, - 665, 304, 847, 314, 894, 320, 677, 330, 681, 336, 938, 346, 904, 352, 693, 362, 697, 368, - 863, 378, 916, 384, 709, 394, 713, 400, 944, 410, 910, 416, 725, 426, 729, 432, 879, 442, - 920, 448, 741, 458, 745, 464, 954, 474, 932, 480, 757, 490, 761, 496, 895, 506, 926, 5, - 11, 17, 27, 33, 43, 49, 59, 65, 75, 81, 91, 97, 107, 113, 123, 129, 139, 145, 155, 161, - 71, 177, 187, 193, 203, 209, 219, 225, 235, 241, 251, 257, 267, 273, 283, 289, 299, 305, - 315, 321, 331, 337, 347, 353, 363, 369, 379, 385, 395, 401, 411, 417, 427, 433, 443, 449, - 459, 465, 475, 481, 491, 497, 507, 513, 523, 529, 539, 545, 555, 561, 571, 577, 587, 593, - 603, 609, 619, 625, 635, 641, 651, 657, 667, 673, 683, 689, 699, 705, 715, 721, 731, 737, - 747, 753, 763, 769, 779, 785, 795, 801, 811, 817, 827, 833, 843, 849, 859, 865, 875, 881, - 891, 897, 907, 913, 923, 929, 939, 945, 955, 961, 971, 977, 987, 1018, 1019, 1020, 1021, 1022, }; +constexpr int tukey_ninther_adversary1[] = {0, 6, 12, 18, 22, 28, 34, 38, 44, 50, 54, 60, 66, 70, 76, 82, 86, 92, 98, + 102, 108, 114, 118, 124, 130, 134, 140, 146, 150, 156, 162, 166, 172, 178, 182, 188, 194, 198, 204, 210, 214, 220, + 226, 230, 236, 242, 246, 252, 258, 262, 268, 274, 278, 284, 290, 294, 300, 306, 310, 316, 322, 326, 332, 338, 342, + 348, 354, 358, 364, 370, 374, 380, 386, 390, 396, 402, 406, 412, 418, 422, 428, 434, 438, 444, 450, 454, 460, 466, + 470, 476, 482, 486, 492, 498, 502, 508, 514, 518, 524, 530, 534, 540, 546, 550, 556, 562, 566, 572, 578, 582, 588, + 594, 598, 604, 610, 614, 620, 626, 630, 636, 642, 646, 652, 658, 662, 668, 674, 678, 1, 7, 13, 684, 19, 23, 29, 690, + 35, 39, 45, 694, 51, 55, 61, 700, 67, 71, 77, 706, 83, 87, 93, 710, 99, 103, 109, 716, 115, 119, 125, 722, 131, 135, + 141, 726, 147, 151, 157, 732, 163, 167, 173, 738, 179, 183, 189, 742, 195, 199, 205, 748, 211, 215, 221, 754, 227, + 231, 237, 758, 243, 247, 253, 764, 259, 263, 269, 770, 275, 279, 285, 774, 291, 295, 301, 780, 307, 311, 317, 786, + 323, 327, 333, 790, 339, 343, 349, 796, 355, 359, 365, 802, 371, 375, 381, 806, 387, 391, 397, 812, 403, 407, 413, + 818, 419, 423, 429, 822, 435, 439, 445, 828, 451, 455, 461, 834, 467, 471, 477, 838, 483, 487, 493, 844, 499, 503, + 509, 850, 515, 519, 525, 854, 531, 535, 541, 860, 547, 551, 557, 866, 563, 567, 573, 870, 579, 583, 589, 876, 595, + 599, 605, 882, 611, 615, 621, 886, 627, 631, 637, 892, 643, 647, 653, 898, 659, 663, 669, 902, 675, 679, 685, 908, + 691, 695, 701, 914, 707, 711, 717, 918, 723, 727, 733, 924, 739, 743, 749, 930, 755, 759, 765, 934, 771, 775, 781, + 940, 787, 791, 797, 946, 803, 807, 813, 950, 819, 823, 829, 956, 835, 839, 845, 962, 851, 855, 861, 966, 867, 871, + 877, 972, 883, 887, 893, 978, 899, 903, 909, 982, 915, 919, 925, 988, 931, 935, 941, 990, 947, 951, 957, 992, 963, + 967, 973, 1024, 979, 983, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 2, 20, 8, 14, 24, 36, 30, 40, 52, 46, + 56, 68, 62, 72, 84, 78, 88, 100, 94, 104, 116, 110, 120, 132, 126, 136, 148, 142, 152, 164, 158, 168, 180, 174, 184, + 196, 190, 200, 212, 206, 216, 228, 222, 232, 244, 238, 248, 260, 254, 264, 276, 270, 280, 292, 286, 296, 308, 302, + 312, 324, 318, 328, 340, 334, 344, 356, 350, 360, 372, 366, 376, 388, 382, 392, 404, 398, 408, 420, 414, 424, 436, + 430, 440, 452, 446, 456, 468, 462, 472, 484, 478, 488, 500, 494, 504, 516, 510, 520, 532, 526, 536, 548, 542, 552, + 564, 558, 568, 580, 574, 584, 596, 590, 600, 612, 606, 616, 628, 622, 632, 644, 638, 648, 660, 654, 664, 676, 670, + 512, 3, 991, 9, 773, 768, 15, 680, 901, 21, 522, 25, 777, 527, 31, 692, 965, 37, 528, 41, 960, 778, 47, 686, 905, + 53, 538, 57, 936, 543, 63, 696, 1007, 69, 544, 73, 789, 784, 79, 708, 1014, 85, 554, 89, 793, 559, 95, 702, 969, + 101, 560, 105, 911, 794, 111, 712, 974, 117, 570, 121, 948, 575, 127, 724, 1015, 133, 576, 137, 805, 800, 143, 718, + 917, 149, 586, 153, 809, 591, 159, 728, 1008, 165, 592, 169, 970, 810, 175, 740, 921, 181, 602, 185, 942, 607, 191, + 734, 1009, 197, 608, 201, 821, 816, 207, 744, 975, 213, 618, 217, 825, 623, 223, 756, 1005, 229, 624, 233, 927, 826, + 239, 750, 984, 245, 634, 249, 952, 639, 255, 760, 1010, 261, 640, 265, 837, 832, 271, 772, 933, 277, 650, 281, 841, + 655, 287, 766, 981, 293, 656, 297, 976, 842, 303, 776, 937, 309, 666, 313, 964, 671, 319, 788, 1011, 325, 672, 329, + 853, 848, 335, 782, 1016, 341, 682, 345, 857, 687, 351, 792, 985, 357, 688, 361, 943, 858, 367, 804, 1003, 373, 698, + 377, 958, 703, 383, 798, 1017, 389, 704, 393, 869, 864, 399, 808, 949, 405, 714, 409, 873, 719, 415, 820, 1012, 421, + 720, 425, 986, 874, 431, 814, 953, 437, 730, 441, 968, 735, 447, 824, 1013, 453, 736, 457, 885, 880, 463, 836, 989, + 469, 746, 473, 889, 751, 479, 830, 1006, 485, 752, 489, 959, 890, 495, 840, 1004, 501, 762, 505, 980, 767, 511, 852, + 4, 517, 10, 521, 16, 896, 26, 846, 32, 533, 42, 537, 48, 783, 58, 856, 64, 549, 74, 553, 80, 906, 90, 868, 96, 565, + 106, 569, 112, 799, 122, 862, 128, 581, 138, 585, 144, 912, 154, 72, 160, 597, 170, 601, 176, 815, 186, 884, 192, + 613, 202, 617, 208, 922, 218, 878, 224, 629, 234, 633, 240, 831, 250, 888, 256, 645, 266, 649, 272, 928, 282, 900, + 288, 661, 298, 665, 304, 847, 314, 894, 320, 677, 330, 681, 336, 938, 346, 904, 352, 693, 362, 697, 368, 863, 378, + 916, 384, 709, 394, 713, 400, 944, 410, 910, 416, 725, 426, 729, 432, 879, 442, 920, 448, 741, 458, 745, 464, 954, + 474, 932, 480, 757, 490, 761, 496, 895, 506, 926, 5, 11, 17, 27, 33, 43, 49, 59, 65, 75, 81, 91, 97, 107, 113, 123, + 129, 139, 145, 155, 161, 71, 177, 187, 193, 203, 209, 219, 225, 235, 241, 251, 257, 267, 273, 283, 289, 299, 305, + 315, 321, 331, 337, 347, 353, 363, 369, 379, 385, 395, 401, 411, 417, 427, 433, 443, 449, 459, 465, 475, 481, 491, + 497, 507, 513, 523, 529, 539, 545, 555, 561, 571, 577, 587, 593, 603, 609, 619, 625, 635, 641, 651, 657, 667, 673, + 683, 689, 699, 705, 715, 721, 731, 737, 747, 753, 763, 769, 779, 785, 795, 801, 811, 817, 827, 833, 843, 849, 859, + 865, 875, 881, 891, 897, 907, 913, 923, 929, 939, 945, 955, 961, 971, 977, 987, 1018, 1019, 1020, 1021, 1022}; -constexpr int tukey_ninther_adversary2[] = { 1024, 31, 30, 29, 28, 36, 46, 51, 61, 67, 77, - 82, 92, 98, 108, 118, 123, 133, 139, 149, 154, 164, 170, 180, 190, 195, 205, 211, 221, - 226, 236, 242, 252, 262, 267, 277, 283, 293, 298, 308, 314, 324, 334, 339, 349, 355, 365, - 370, 380, 386, 396, 406, 411, 421, 427, 437, 442, 452, 458, 468, 478, 483, 493, 499, 509, - 514, 524, 530, 540, 550, 555, 565, 571, 581, 586, 596, 602, 612, 622, 627, 637, 643, 653, - 658, 668, 674, 684, 694, 699, 709, 715, 725, 730, 740, 746, 756, 766, 771, 781, 787, 797, - 802, 812, 818, 828, 838, 843, 853, 859, 869, 874, 884, 890, 900, 910, 915, 925, 931, 941, - 946, 956, 962, 972, 982, 987, 997, 1003, 1013, 1018, 343, 523, 127, 529, 86, 539, 358, - 549, 178, 554, 107, 564, 374, 570, 183, 580, 384, 585, 389, 595, 394, 601, 399, 611, 404, - 621, 409, 626, 18, 636, 419, 642, 425, 652, 318, 657, 435, 667, 440, 673, 169, 683, 450, - 693, 224, 698, 256, 708, 179, 714, 66, 724, 234, 729, 487, 739, 189, 745, 34, 755, 502, - 765, 71, 770, 188, 780, 518, 786, 76, 796, 528, 801, 533, 811, 538, 817, 543, 827, 548, - 837, 553, 842, 163, 852, 563, 858, 569, 868, 286, 873, 579, 883, 584, 889, 70, 899, 594, - 909, 219, 914, 97, 924, 235, 930, 91, 940, 462, 945, 631, 955, 173, 961, 241, 971, 646, - 981, 322, 986, 272, 996, 662, 1002, 327, 1012, 672, 1017, 677, 1023, 682, 184, 687, 44, - 692, 80, 697, 703, 390, 347, 707, 193, 713, 718, 534, 276, 723, 26, 728, 734, 32, 200, 738, - 744, 368, 749, 137, 754, 15, 759, 25, 764, 378, 769, 775, 575, 90, 779, 148, 785, 790, 297, - 215, 795, 225, 800, 806, 447, 56, 810, 816, 27, 821, 153, 826, 616, 831, 152, 836, 59, 841, - 847, 472, 632, 851, 116, 857, 862, 430, 214, 867, 647, 872, 878, 106, 251, 882, 888, 21, - 893, 332, 898, 87, 903, 132, 908, 678, 913, 919, 456, 168, 923, 230, 929, 934, 519, 466, - 939, 19, 944, 950, 353, 471, 954, 960, 364, 965, 719, 970, 271, 975, 544, 980, 369, 985, - 991, 210, 491, 995, 282, 1001, 1006, 750, 250, 1011, 121, 1016, 1022, 385, 292, 507, 65, - 512, 255, 102, 776, 395, 45, 159, 287, 522, 260, 591, 791, 405, 117, 204, 307, 49, 265, - 302, 807, 606, 400, 22, 111, 16, 344, 822, 420, 313, 303, 415, 832, 275, 203, 559, 23, 416, - 426, 323, 848, 281, 231, 209, 317, 574, 436, 17, 863, 142, 333, 220, 488, 431, 441, 81, - 879, 75, 590, 451, 663, 328, 446, 894, 296, 375, 600, 261, 904, 457, 348, 605, 337, 610, - 60, 688, 920, 467, 96, 615, 461, 620, 306, 354, 935, 477, 704, 625, 24, 312, 128, 143, 951, - 476, 635, 174, 131, 641, 240, 966, 492, 481, 138, 359, 976, 40, 363, 651, 735, 656, 498, - 379, 992, 20, 497, 39, 560, 666, 508, 112, 1007, 246, 158, 162, 760, 503, 513, 482, 291, - 410, 245, 338, 199, 266, 147, 194, 101, 122, 55, 50, 14, 13, 43, 48, 58, 64, 74, 79, 95, - 105, 115, 120, 130, 136, 146, 151, 167, 177, 187, 192, 202, 208, 218, 223, 239, 249, 259, - 264, 274, 280, 290, 295, 311, 321, 331, 336, 346, 352, 362, 367, 383, 393, 403, 408, 418, - 424, 434, 439, 455, 465, 475, 480, 490, 496, 506, 511, 527, 537, 547, 552, 562, 568, 578, - 583, 599, 609, 619, 624, 634, 640, 650, 655, 671, 681, 691, 696, 706, 712, 722, 727, 743, - 753, 763, 768, 778, 784, 794, 799, 815, 825, 835, 840, 850, 856, 866, 871, 887, 897, 907, - 912, 922, 928, 938, 943, 959, 969, 979, 984, 994, 1000, 1010, 1015, 1021, 1005, 990, 953, - 974, 964, 949, 933, 918, 881, 902, 892, 877, 861, 846, 809, 830, 820, 805, 789, 774, 737, - 758, 748, 733, 717, 702, 665, 686, 676, 661, 645, 630, 593, 614, 604, 589, 573, 558, 521, - 542, 532, 517, 501, 486, 449, 470, 460, 445, 429, 414, 377, 398, 388, 373, 357, 342, 305, - 326, 316, 301, 285, 270, 233, 254, 244, 229, 213, 198, 161, 182, 172, 157, 141, 126, 89, - 110, 100, 85, 69, 54, 12, 38, 11, 10, 9, 8, 53, 84, 99, 125, 156, 171, 197, 228, 243, 269, - 300, 315, 341, 372, 387, 413, 444, 459, 485, 516, 531, 557, 588, 603, 629, 660, 675, 701, - 732, 747, 773, 804, 819, 845, 876, 891, 917, 948, 963, 989, 1020, 1014, 63, 253, 258, 263, - 279, 273, 284, 289, 294, 310, 304, 320, 73, 325, 330, 335, 351, 345, 356, 361, 366, 382, - 376, 392, 88, 397, 402, 407, 423, 417, 428, 433, 438, 454, 448, 464, 109, 469, 474, 479, - 495, 489, 500, 505, 510, 526, 520, 536, 135, 541, 546, 551, 567, 561, 572, 577, 582, 598, - 592, 608, 145, 613, 618, 623, 639, 633, 644, 649, 654, 670, 664, 680, 160, 685, 690, 695, - 711, 705, 716, 721, 726, 742, 736, 752, 181, 757, 762, 767, 783, 777, 788, 793, 798, 814, - 808, 824, 207, 829, 834, 839, 855, 849, 860, 865, 870, 886, 880, 896, 217, 901, 906, 911, - 927, 921, 932, 937, 942, 958, 952, 968, 232, 973, 978, 983, 999, 993, 1004, 1009, 248, 238, - 222, 212, 201, 191, 186, 37, 176, 166, 150, 140, 129, 119, 114, 3, 104, 94, 78, 68, 57, 47, - 42, 6, 7, 4, 5, 2, -1, 33, 35, 41, 52, 62, 72, 83, 93, 103, 113, 124, 134, 144, 155, 165, - 175, 185, 196, 206, 216, 227, 237, 247, 257, 268, 278, 288, 299, 309, 319, 329, 340, 350, - 360, 371, 381, 391, 401, 412, 422, 432, 443, 453, 463, 473, 484, 494, 504, 515, 525, 535, - 545, 556, 566, 576, 587, 597, 607, 617, 628, 638, 648, 659, 669, 679, 689, 700, 710, 720, - 731, 741, 751, 761, 772, 782, 792, 803, 813, 823, 833, 844, 854, 864, 875, 885, 895, 905, - 916, 926, 936, 947, 957, 967, 977, 988, 998, 1008, 1019, }; -// clang-format on +constexpr int tukey_ninther_adversary2[] = {1024, 31, 30, 29, 28, 36, 46, 51, 61, 67, 77, 82, 92, 98, 108, 118, 123, + 133, 139, 149, 154, 164, 170, 180, 190, 195, 205, 211, 221, 226, 236, 242, 252, 262, 267, 277, 283, 293, 298, 308, + 314, 324, 334, 339, 349, 355, 365, 370, 380, 386, 396, 406, 411, 421, 427, 437, 442, 452, 458, 468, 478, 483, 493, + 499, 509, 514, 524, 530, 540, 550, 555, 565, 571, 581, 586, 596, 602, 612, 622, 627, 637, 643, 653, 658, 668, 674, + 684, 694, 699, 709, 715, 725, 730, 740, 746, 756, 766, 771, 781, 787, 797, 802, 812, 818, 828, 838, 843, 853, 859, + 869, 874, 884, 890, 900, 910, 915, 925, 931, 941, 946, 956, 962, 972, 982, 987, 997, 1003, 1013, 1018, 343, 523, + 127, 529, 86, 539, 358, 549, 178, 554, 107, 564, 374, 570, 183, 580, 384, 585, 389, 595, 394, 601, 399, 611, 404, + 621, 409, 626, 18, 636, 419, 642, 425, 652, 318, 657, 435, 667, 440, 673, 169, 683, 450, 693, 224, 698, 256, 708, + 179, 714, 66, 724, 234, 729, 487, 739, 189, 745, 34, 755, 502, 765, 71, 770, 188, 780, 518, 786, 76, 796, 528, 801, + 533, 811, 538, 817, 543, 827, 548, 837, 553, 842, 163, 852, 563, 858, 569, 868, 286, 873, 579, 883, 584, 889, 70, + 899, 594, 909, 219, 914, 97, 924, 235, 930, 91, 940, 462, 945, 631, 955, 173, 961, 241, 971, 646, 981, 322, 986, + 272, 996, 662, 1002, 327, 1012, 672, 1017, 677, 1023, 682, 184, 687, 44, 692, 80, 697, 703, 390, 347, 707, 193, 713, + 718, 534, 276, 723, 26, 728, 734, 32, 200, 738, 744, 368, 749, 137, 754, 15, 759, 25, 764, 378, 769, 775, 575, 90, + 779, 148, 785, 790, 297, 215, 795, 225, 800, 806, 447, 56, 810, 816, 27, 821, 153, 826, 616, 831, 152, 836, 59, 841, + 847, 472, 632, 851, 116, 857, 862, 430, 214, 867, 647, 872, 878, 106, 251, 882, 888, 21, 893, 332, 898, 87, 903, + 132, 908, 678, 913, 919, 456, 168, 923, 230, 929, 934, 519, 466, 939, 19, 944, 950, 353, 471, 954, 960, 364, 965, + 719, 970, 271, 975, 544, 980, 369, 985, 991, 210, 491, 995, 282, 1001, 1006, 750, 250, 1011, 121, 1016, 1022, 385, + 292, 507, 65, 512, 255, 102, 776, 395, 45, 159, 287, 522, 260, 591, 791, 405, 117, 204, 307, 49, 265, 302, 807, 606, + 400, 22, 111, 16, 344, 822, 420, 313, 303, 415, 832, 275, 203, 559, 23, 416, 426, 323, 848, 281, 231, 209, 317, 574, + 436, 17, 863, 142, 333, 220, 488, 431, 441, 81, 879, 75, 590, 451, 663, 328, 446, 894, 296, 375, 600, 261, 904, 457, + 348, 605, 337, 610, 60, 688, 920, 467, 96, 615, 461, 620, 306, 354, 935, 477, 704, 625, 24, 312, 128, 143, 951, 476, + 635, 174, 131, 641, 240, 966, 492, 481, 138, 359, 976, 40, 363, 651, 735, 656, 498, 379, 992, 20, 497, 39, 560, 666, + 508, 112, 1007, 246, 158, 162, 760, 503, 513, 482, 291, 410, 245, 338, 199, 266, 147, 194, 101, 122, 55, 50, 14, 13, + 43, 48, 58, 64, 74, 79, 95, 105, 115, 120, 130, 136, 146, 151, 167, 177, 187, 192, 202, 208, 218, 223, 239, 249, + 259, 264, 274, 280, 290, 295, 311, 321, 331, 336, 346, 352, 362, 367, 383, 393, 403, 408, 418, 424, 434, 439, 455, + 465, 475, 480, 490, 496, 506, 511, 527, 537, 547, 552, 562, 568, 578, 583, 599, 609, 619, 624, 634, 640, 650, 655, + 671, 681, 691, 696, 706, 712, 722, 727, 743, 753, 763, 768, 778, 784, 794, 799, 815, 825, 835, 840, 850, 856, 866, + 871, 887, 897, 907, 912, 922, 928, 938, 943, 959, 969, 979, 984, 994, 1000, 1010, 1015, 1021, 1005, 990, 953, 974, + 964, 949, 933, 918, 881, 902, 892, 877, 861, 846, 809, 830, 820, 805, 789, 774, 737, 758, 748, 733, 717, 702, 665, + 686, 676, 661, 645, 630, 593, 614, 604, 589, 573, 558, 521, 542, 532, 517, 501, 486, 449, 470, 460, 445, 429, 414, + 377, 398, 388, 373, 357, 342, 305, 326, 316, 301, 285, 270, 233, 254, 244, 229, 213, 198, 161, 182, 172, 157, 141, + 126, 89, 110, 100, 85, 69, 54, 12, 38, 11, 10, 9, 8, 53, 84, 99, 125, 156, 171, 197, 228, 243, 269, 300, 315, 341, + 372, 387, 413, 444, 459, 485, 516, 531, 557, 588, 603, 629, 660, 675, 701, 732, 747, 773, 804, 819, 845, 876, 891, + 917, 948, 963, 989, 1020, 1014, 63, 253, 258, 263, 279, 273, 284, 289, 294, 310, 304, 320, 73, 325, 330, 335, 351, + 345, 356, 361, 366, 382, 376, 392, 88, 397, 402, 407, 423, 417, 428, 433, 438, 454, 448, 464, 109, 469, 474, 479, + 495, 489, 500, 505, 510, 526, 520, 536, 135, 541, 546, 551, 567, 561, 572, 577, 582, 598, 592, 608, 145, 613, 618, + 623, 639, 633, 644, 649, 654, 670, 664, 680, 160, 685, 690, 695, 711, 705, 716, 721, 726, 742, 736, 752, 181, 757, + 762, 767, 783, 777, 788, 793, 798, 814, 808, 824, 207, 829, 834, 839, 855, 849, 860, 865, 870, 886, 880, 896, 217, + 901, 906, 911, 927, 921, 932, 937, 942, 958, 952, 968, 232, 973, 978, 983, 999, 993, 1004, 1009, 248, 238, 222, 212, + 201, 191, 186, 37, 176, 166, 150, 140, 129, 119, 114, 3, 104, 94, 78, 68, 57, 47, 42, 6, 7, 4, 5, 2, -1, 33, 35, 41, + 52, 62, 72, 83, 93, 103, 113, 124, 134, 144, 155, 165, 175, 185, 196, 206, 216, 227, 237, 247, 257, 268, 278, 288, + 299, 309, 319, 329, 340, 350, 360, 371, 381, 391, 401, 412, 422, 432, 443, 453, 463, 473, 484, 494, 504, 515, 525, + 535, 545, 556, 566, 576, 587, 597, 607, 617, 628, 638, 648, 659, 669, 679, 689, 700, 710, 720, 731, 741, 751, 761, + 772, 782, 792, 803, 813, 823, 833, 844, 854, 864, 875, 885, 895, 905, 916, 926, 936, 947, 957, 967, 977, 988, 998, + 1008, 1019}; using namespace std; diff --git a/tests/std/tests/GH_000856_nth_element_linear/test.cpp b/tests/std/tests/GH_000856_nth_element_linear/test.cpp index 550b50f95b4..15b55e838cb 100644 --- a/tests/std/tests/GH_000856_nth_element_linear/test.cpp +++ b/tests/std/tests/GH_000856_nth_element_linear/test.cpp @@ -9,125 +9,96 @@ #include #endif // _HAS_CXX20 -// clang-format off -constexpr int tukey_ninther_adversary1[] = { - 0, 6, 12, 18, 22, 28, 34, 38, 44, 50, 54, 60, 66, 70, 76, 82, 86, 92, 98, 102, 108, - 114, 118, 124, 130, 134, 140, 146, 150, 156, 162, 166, 172, 178, 182, 188, 194, 198, - 204, 210, 214, 220, 226, 230, 236, 242, 246, 252, 258, 262, 268, 274, 278, 284, 290, - 294, 300, 306, 310, 316, 322, 326, 332, 338, 342, 348, 354, 358, 364, 370, 374, 380, - 386, 390, 396, 402, 406, 412, 418, 422, 428, 434, 438, 444, 450, 454, 460, 466, 470, - 476, 482, 486, 492, 498, 502, 508, 514, 518, 524, 530, 534, 540, 546, 550, 556, 562, - 566, 572, 578, 582, 588, 594, 598, 604, 610, 614, 620, 626, 630, 636, 642, 646, 652, - 658, 662, 668, 674, 678, 1, 7, 13, 684, 19, 23, 29, 690, 35, 39, 45, 694, 51, 55, 61, - 700, 67, 71, 77, 706, 83, 87, 93, 710, 99, 103, 109, 716, 115, 119, 125, 722, 131, 135, - 141, 726, 147, 151, 157, 732, 163, 167, 173, 738, 179, 183, 189, 742, 195, 199, 205, - 748, 211, 215, 221, 754, 227, 231, 237, 758, 243, 247, 253, 764, 259, 263, 269, 770, - 275, 279, 285, 774, 291, 295, 301, 780, 307, 311, 317, 786, 323, 327, 333, 790, 339, - 343, 349, 796, 355, 359, 365, 802, 371, 375, 381, 806, 387, 391, 397, 812, 403, 407, - 413, 818, 419, 423, 429, 822, 435, 439, 445, 828, 451, 455, 461, 834, 467, 471, 477, - 838, 483, 487, 493, 844, 499, 503, 509, 850, 515, 519, 525, 854, 531, 535, 541, 860, - 547, 551, 557, 866, 563, 567, 573, 870, 579, 583, 589, 876, 595, 599, 605, 882, 611, - 615, 621, 886, 627, 631, 637, 892, 643, 647, 653, 898, 659, 663, 669, 902, 675, 679, - 685, 908, 691, 695, 701, 914, 707, 711, 717, 918, 723, 727, 733, 924, 739, 743, 749, - 930, 755, 759, 765, 934, 771, 775, 781, 940, 787, 791, 797, 946, 803, 807, 813, 950, - 819, 823, 829, 956, 835, 839, 845, 962, 851, 855, 861, 966, 867, 871, 877, 972, 883, - 887, 893, 978, 899, 903, 909, 982, 915, 919, 925, 988, 931, 935, 941, 990, 947, 951, - 957, 992, 963, 967, 973, 1024, 979, 983, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, - 1002, 2, 20, 8, 14, 24, 36, 30, 40, 52, 46, 56, 68, 62, 72, 84, 78, 88, 100, 94, 104, - 116, 110, 120, 132, 126, 136, 148, 142, 152, 164, 158, 168, 180, 174, 184, 196, 190, - 200, 212, 206, 216, 228, 222, 232, 244, 238, 248, 260, 254, 264, 276, 270, 280, 292, - 286, 296, 308, 302, 312, 324, 318, 328, 340, 334, 344, 356, 350, 360, 372, 366, 376, - 388, 382, 392, 404, 398, 408, 420, 414, 424, 436, 430, 440, 452, 446, 456, 468, 462, - 472, 484, 478, 488, 500, 494, 504, 516, 510, 520, 532, 526, 536, 548, 542, 552, 564, - 558, 568, 580, 574, 584, 596, 590, 600, 612, 606, 616, 628, 622, 632, 644, 638, 648, - 660, 654, 664, 676, 670, 512, 3, 991, 9, 773, 768, 15, 680, 901, 21, 522, 25, 777, 527, - 31, 692, 965, 37, 528, 41, 960, 778, 47, 686, 905, 53, 538, 57, 936, 543, 63, 696, 1007, - 69, 544, 73, 789, 784, 79, 708, 1014, 85, 554, 89, 793, 559, 95, 702, 969, 101, 560, - 105, 911, 794, 111, 712, 974, 117, 570, 121, 948, 575, 127, 724, 1015, 133, 576, 137, - 805, 800, 143, 718, 917, 149, 586, 153, 809, 591, 159, 728, 1008, 165, 592, 169, 970, - 810, 175, 740, 921, 181, 602, 185, 942, 607, 191, 734, 1009, 197, 608, 201, 821, 816, - 207, 744, 975, 213, 618, 217, 825, 623, 223, 756, 1005, 229, 624, 233, 927, 826, 239, - 750, 984, 245, 634, 249, 952, 639, 255, 760, 1010, 261, 640, 265, 837, 832, 271, 772, - 933, 277, 650, 281, 841, 655, 287, 766, 981, 293, 656, 297, 976, 842, 303, 776, 937, 309, - 666, 313, 964, 671, 319, 788, 1011, 325, 672, 329, 853, 848, 335, 782, 1016, 341, 682, - 345, 857, 687, 351, 792, 985, 357, 688, 361, 943, 858, 367, 804, 1003, 373, 698, 377, - 958, 703, 383, 798, 1017, 389, 704, 393, 869, 864, 399, 808, 949, 405, 714, 409, 873, - 719, 415, 820, 1012, 421, 720, 425, 986, 874, 431, 814, 953, 437, 730, 441, 968, 735, - 447, 824, 1013, 453, 736, 457, 885, 880, 463, 836, 989, 469, 746, 473, 889, 751, 479, - 830, 1006, 485, 752, 489, 959, 890, 495, 840, 1004, 501, 762, 505, 980, 767, 511, 852, 4, - 517, 10, 521, 16, 896, 26, 846, 32, 533, 42, 537, 48, 783, 58, 856, 64, 549, 74, 553, 80, - 906, 90, 868, 96, 565, 106, 569, 112, 799, 122, 862, 128, 581, 138, 585, 144, 912, 154, - 72, 160, 597, 170, 601, 176, 815, 186, 884, 192, 613, 202, 617, 208, 922, 218, 878, 224, - 629, 234, 633, 240, 831, 250, 888, 256, 645, 266, 649, 272, 928, 282, 900, 288, 661, 298, - 665, 304, 847, 314, 894, 320, 677, 330, 681, 336, 938, 346, 904, 352, 693, 362, 697, 368, - 863, 378, 916, 384, 709, 394, 713, 400, 944, 410, 910, 416, 725, 426, 729, 432, 879, 442, - 920, 448, 741, 458, 745, 464, 954, 474, 932, 480, 757, 490, 761, 496, 895, 506, 926, 5, - 11, 17, 27, 33, 43, 49, 59, 65, 75, 81, 91, 97, 107, 113, 123, 129, 139, 145, 155, 161, - 71, 177, 187, 193, 203, 209, 219, 225, 235, 241, 251, 257, 267, 273, 283, 289, 299, 305, - 315, 321, 331, 337, 347, 353, 363, 369, 379, 385, 395, 401, 411, 417, 427, 433, 443, 449, - 459, 465, 475, 481, 491, 497, 507, 513, 523, 529, 539, 545, 555, 561, 571, 577, 587, 593, - 603, 609, 619, 625, 635, 641, 651, 657, 667, 673, 683, 689, 699, 705, 715, 721, 731, 737, - 747, 753, 763, 769, 779, 785, 795, 801, 811, 817, 827, 833, 843, 849, 859, 865, 875, 881, - 891, 897, 907, 913, 923, 929, 939, 945, 955, 961, 971, 977, 987, 1018, 1019, 1020, 1021, 1022, }; +constexpr int tukey_ninther_adversary1[] = {0, 6, 12, 18, 22, 28, 34, 38, 44, 50, 54, 60, 66, 70, 76, 82, 86, 92, 98, + 102, 108, 114, 118, 124, 130, 134, 140, 146, 150, 156, 162, 166, 172, 178, 182, 188, 194, 198, 204, 210, 214, 220, + 226, 230, 236, 242, 246, 252, 258, 262, 268, 274, 278, 284, 290, 294, 300, 306, 310, 316, 322, 326, 332, 338, 342, + 348, 354, 358, 364, 370, 374, 380, 386, 390, 396, 402, 406, 412, 418, 422, 428, 434, 438, 444, 450, 454, 460, 466, + 470, 476, 482, 486, 492, 498, 502, 508, 514, 518, 524, 530, 534, 540, 546, 550, 556, 562, 566, 572, 578, 582, 588, + 594, 598, 604, 610, 614, 620, 626, 630, 636, 642, 646, 652, 658, 662, 668, 674, 678, 1, 7, 13, 684, 19, 23, 29, 690, + 35, 39, 45, 694, 51, 55, 61, 700, 67, 71, 77, 706, 83, 87, 93, 710, 99, 103, 109, 716, 115, 119, 125, 722, 131, 135, + 141, 726, 147, 151, 157, 732, 163, 167, 173, 738, 179, 183, 189, 742, 195, 199, 205, 748, 211, 215, 221, 754, 227, + 231, 237, 758, 243, 247, 253, 764, 259, 263, 269, 770, 275, 279, 285, 774, 291, 295, 301, 780, 307, 311, 317, 786, + 323, 327, 333, 790, 339, 343, 349, 796, 355, 359, 365, 802, 371, 375, 381, 806, 387, 391, 397, 812, 403, 407, 413, + 818, 419, 423, 429, 822, 435, 439, 445, 828, 451, 455, 461, 834, 467, 471, 477, 838, 483, 487, 493, 844, 499, 503, + 509, 850, 515, 519, 525, 854, 531, 535, 541, 860, 547, 551, 557, 866, 563, 567, 573, 870, 579, 583, 589, 876, 595, + 599, 605, 882, 611, 615, 621, 886, 627, 631, 637, 892, 643, 647, 653, 898, 659, 663, 669, 902, 675, 679, 685, 908, + 691, 695, 701, 914, 707, 711, 717, 918, 723, 727, 733, 924, 739, 743, 749, 930, 755, 759, 765, 934, 771, 775, 781, + 940, 787, 791, 797, 946, 803, 807, 813, 950, 819, 823, 829, 956, 835, 839, 845, 962, 851, 855, 861, 966, 867, 871, + 877, 972, 883, 887, 893, 978, 899, 903, 909, 982, 915, 919, 925, 988, 931, 935, 941, 990, 947, 951, 957, 992, 963, + 967, 973, 1024, 979, 983, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 2, 20, 8, 14, 24, 36, 30, 40, 52, 46, + 56, 68, 62, 72, 84, 78, 88, 100, 94, 104, 116, 110, 120, 132, 126, 136, 148, 142, 152, 164, 158, 168, 180, 174, 184, + 196, 190, 200, 212, 206, 216, 228, 222, 232, 244, 238, 248, 260, 254, 264, 276, 270, 280, 292, 286, 296, 308, 302, + 312, 324, 318, 328, 340, 334, 344, 356, 350, 360, 372, 366, 376, 388, 382, 392, 404, 398, 408, 420, 414, 424, 436, + 430, 440, 452, 446, 456, 468, 462, 472, 484, 478, 488, 500, 494, 504, 516, 510, 520, 532, 526, 536, 548, 542, 552, + 564, 558, 568, 580, 574, 584, 596, 590, 600, 612, 606, 616, 628, 622, 632, 644, 638, 648, 660, 654, 664, 676, 670, + 512, 3, 991, 9, 773, 768, 15, 680, 901, 21, 522, 25, 777, 527, 31, 692, 965, 37, 528, 41, 960, 778, 47, 686, 905, + 53, 538, 57, 936, 543, 63, 696, 1007, 69, 544, 73, 789, 784, 79, 708, 1014, 85, 554, 89, 793, 559, 95, 702, 969, + 101, 560, 105, 911, 794, 111, 712, 974, 117, 570, 121, 948, 575, 127, 724, 1015, 133, 576, 137, 805, 800, 143, 718, + 917, 149, 586, 153, 809, 591, 159, 728, 1008, 165, 592, 169, 970, 810, 175, 740, 921, 181, 602, 185, 942, 607, 191, + 734, 1009, 197, 608, 201, 821, 816, 207, 744, 975, 213, 618, 217, 825, 623, 223, 756, 1005, 229, 624, 233, 927, 826, + 239, 750, 984, 245, 634, 249, 952, 639, 255, 760, 1010, 261, 640, 265, 837, 832, 271, 772, 933, 277, 650, 281, 841, + 655, 287, 766, 981, 293, 656, 297, 976, 842, 303, 776, 937, 309, 666, 313, 964, 671, 319, 788, 1011, 325, 672, 329, + 853, 848, 335, 782, 1016, 341, 682, 345, 857, 687, 351, 792, 985, 357, 688, 361, 943, 858, 367, 804, 1003, 373, 698, + 377, 958, 703, 383, 798, 1017, 389, 704, 393, 869, 864, 399, 808, 949, 405, 714, 409, 873, 719, 415, 820, 1012, 421, + 720, 425, 986, 874, 431, 814, 953, 437, 730, 441, 968, 735, 447, 824, 1013, 453, 736, 457, 885, 880, 463, 836, 989, + 469, 746, 473, 889, 751, 479, 830, 1006, 485, 752, 489, 959, 890, 495, 840, 1004, 501, 762, 505, 980, 767, 511, 852, + 4, 517, 10, 521, 16, 896, 26, 846, 32, 533, 42, 537, 48, 783, 58, 856, 64, 549, 74, 553, 80, 906, 90, 868, 96, 565, + 106, 569, 112, 799, 122, 862, 128, 581, 138, 585, 144, 912, 154, 72, 160, 597, 170, 601, 176, 815, 186, 884, 192, + 613, 202, 617, 208, 922, 218, 878, 224, 629, 234, 633, 240, 831, 250, 888, 256, 645, 266, 649, 272, 928, 282, 900, + 288, 661, 298, 665, 304, 847, 314, 894, 320, 677, 330, 681, 336, 938, 346, 904, 352, 693, 362, 697, 368, 863, 378, + 916, 384, 709, 394, 713, 400, 944, 410, 910, 416, 725, 426, 729, 432, 879, 442, 920, 448, 741, 458, 745, 464, 954, + 474, 932, 480, 757, 490, 761, 496, 895, 506, 926, 5, 11, 17, 27, 33, 43, 49, 59, 65, 75, 81, 91, 97, 107, 113, 123, + 129, 139, 145, 155, 161, 71, 177, 187, 193, 203, 209, 219, 225, 235, 241, 251, 257, 267, 273, 283, 289, 299, 305, + 315, 321, 331, 337, 347, 353, 363, 369, 379, 385, 395, 401, 411, 417, 427, 433, 443, 449, 459, 465, 475, 481, 491, + 497, 507, 513, 523, 529, 539, 545, 555, 561, 571, 577, 587, 593, 603, 609, 619, 625, 635, 641, 651, 657, 667, 673, + 683, 689, 699, 705, 715, 721, 731, 737, 747, 753, 763, 769, 779, 785, 795, 801, 811, 817, 827, 833, 843, 849, 859, + 865, 875, 881, 891, 897, 907, 913, 923, 929, 939, 945, 955, 961, 971, 977, 987, 1018, 1019, 1020, 1021, 1022}; -constexpr int tukey_ninther_adversary2[] = { 1024, 31, 30, 29, 28, 36, 46, 51, 61, 67, 77, - 82, 92, 98, 108, 118, 123, 133, 139, 149, 154, 164, 170, 180, 190, 195, 205, 211, 221, - 226, 236, 242, 252, 262, 267, 277, 283, 293, 298, 308, 314, 324, 334, 339, 349, 355, 365, - 370, 380, 386, 396, 406, 411, 421, 427, 437, 442, 452, 458, 468, 478, 483, 493, 499, 509, - 514, 524, 530, 540, 550, 555, 565, 571, 581, 586, 596, 602, 612, 622, 627, 637, 643, 653, - 658, 668, 674, 684, 694, 699, 709, 715, 725, 730, 740, 746, 756, 766, 771, 781, 787, 797, - 802, 812, 818, 828, 838, 843, 853, 859, 869, 874, 884, 890, 900, 910, 915, 925, 931, 941, - 946, 956, 962, 972, 982, 987, 997, 1003, 1013, 1018, 343, 523, 127, 529, 86, 539, 358, - 549, 178, 554, 107, 564, 374, 570, 183, 580, 384, 585, 389, 595, 394, 601, 399, 611, 404, - 621, 409, 626, 18, 636, 419, 642, 425, 652, 318, 657, 435, 667, 440, 673, 169, 683, 450, - 693, 224, 698, 256, 708, 179, 714, 66, 724, 234, 729, 487, 739, 189, 745, 34, 755, 502, - 765, 71, 770, 188, 780, 518, 786, 76, 796, 528, 801, 533, 811, 538, 817, 543, 827, 548, - 837, 553, 842, 163, 852, 563, 858, 569, 868, 286, 873, 579, 883, 584, 889, 70, 899, 594, - 909, 219, 914, 97, 924, 235, 930, 91, 940, 462, 945, 631, 955, 173, 961, 241, 971, 646, - 981, 322, 986, 272, 996, 662, 1002, 327, 1012, 672, 1017, 677, 1023, 682, 184, 687, 44, - 692, 80, 697, 703, 390, 347, 707, 193, 713, 718, 534, 276, 723, 26, 728, 734, 32, 200, 738, - 744, 368, 749, 137, 754, 15, 759, 25, 764, 378, 769, 775, 575, 90, 779, 148, 785, 790, 297, - 215, 795, 225, 800, 806, 447, 56, 810, 816, 27, 821, 153, 826, 616, 831, 152, 836, 59, 841, - 847, 472, 632, 851, 116, 857, 862, 430, 214, 867, 647, 872, 878, 106, 251, 882, 888, 21, - 893, 332, 898, 87, 903, 132, 908, 678, 913, 919, 456, 168, 923, 230, 929, 934, 519, 466, - 939, 19, 944, 950, 353, 471, 954, 960, 364, 965, 719, 970, 271, 975, 544, 980, 369, 985, - 991, 210, 491, 995, 282, 1001, 1006, 750, 250, 1011, 121, 1016, 1022, 385, 292, 507, 65, - 512, 255, 102, 776, 395, 45, 159, 287, 522, 260, 591, 791, 405, 117, 204, 307, 49, 265, - 302, 807, 606, 400, 22, 111, 16, 344, 822, 420, 313, 303, 415, 832, 275, 203, 559, 23, 416, - 426, 323, 848, 281, 231, 209, 317, 574, 436, 17, 863, 142, 333, 220, 488, 431, 441, 81, - 879, 75, 590, 451, 663, 328, 446, 894, 296, 375, 600, 261, 904, 457, 348, 605, 337, 610, - 60, 688, 920, 467, 96, 615, 461, 620, 306, 354, 935, 477, 704, 625, 24, 312, 128, 143, 951, - 476, 635, 174, 131, 641, 240, 966, 492, 481, 138, 359, 976, 40, 363, 651, 735, 656, 498, - 379, 992, 20, 497, 39, 560, 666, 508, 112, 1007, 246, 158, 162, 760, 503, 513, 482, 291, - 410, 245, 338, 199, 266, 147, 194, 101, 122, 55, 50, 14, 13, 43, 48, 58, 64, 74, 79, 95, - 105, 115, 120, 130, 136, 146, 151, 167, 177, 187, 192, 202, 208, 218, 223, 239, 249, 259, - 264, 274, 280, 290, 295, 311, 321, 331, 336, 346, 352, 362, 367, 383, 393, 403, 408, 418, - 424, 434, 439, 455, 465, 475, 480, 490, 496, 506, 511, 527, 537, 547, 552, 562, 568, 578, - 583, 599, 609, 619, 624, 634, 640, 650, 655, 671, 681, 691, 696, 706, 712, 722, 727, 743, - 753, 763, 768, 778, 784, 794, 799, 815, 825, 835, 840, 850, 856, 866, 871, 887, 897, 907, - 912, 922, 928, 938, 943, 959, 969, 979, 984, 994, 1000, 1010, 1015, 1021, 1005, 990, 953, - 974, 964, 949, 933, 918, 881, 902, 892, 877, 861, 846, 809, 830, 820, 805, 789, 774, 737, - 758, 748, 733, 717, 702, 665, 686, 676, 661, 645, 630, 593, 614, 604, 589, 573, 558, 521, - 542, 532, 517, 501, 486, 449, 470, 460, 445, 429, 414, 377, 398, 388, 373, 357, 342, 305, - 326, 316, 301, 285, 270, 233, 254, 244, 229, 213, 198, 161, 182, 172, 157, 141, 126, 89, - 110, 100, 85, 69, 54, 12, 38, 11, 10, 9, 8, 53, 84, 99, 125, 156, 171, 197, 228, 243, 269, - 300, 315, 341, 372, 387, 413, 444, 459, 485, 516, 531, 557, 588, 603, 629, 660, 675, 701, - 732, 747, 773, 804, 819, 845, 876, 891, 917, 948, 963, 989, 1020, 1014, 63, 253, 258, 263, - 279, 273, 284, 289, 294, 310, 304, 320, 73, 325, 330, 335, 351, 345, 356, 361, 366, 382, - 376, 392, 88, 397, 402, 407, 423, 417, 428, 433, 438, 454, 448, 464, 109, 469, 474, 479, - 495, 489, 500, 505, 510, 526, 520, 536, 135, 541, 546, 551, 567, 561, 572, 577, 582, 598, - 592, 608, 145, 613, 618, 623, 639, 633, 644, 649, 654, 670, 664, 680, 160, 685, 690, 695, - 711, 705, 716, 721, 726, 742, 736, 752, 181, 757, 762, 767, 783, 777, 788, 793, 798, 814, - 808, 824, 207, 829, 834, 839, 855, 849, 860, 865, 870, 886, 880, 896, 217, 901, 906, 911, - 927, 921, 932, 937, 942, 958, 952, 968, 232, 973, 978, 983, 999, 993, 1004, 1009, 248, 238, - 222, 212, 201, 191, 186, 37, 176, 166, 150, 140, 129, 119, 114, 3, 104, 94, 78, 68, 57, 47, - 42, 6, 7, 4, 5, 2, -1, 33, 35, 41, 52, 62, 72, 83, 93, 103, 113, 124, 134, 144, 155, 165, - 175, 185, 196, 206, 216, 227, 237, 247, 257, 268, 278, 288, 299, 309, 319, 329, 340, 350, - 360, 371, 381, 391, 401, 412, 422, 432, 443, 453, 463, 473, 484, 494, 504, 515, 525, 535, - 545, 556, 566, 576, 587, 597, 607, 617, 628, 638, 648, 659, 669, 679, 689, 700, 710, 720, - 731, 741, 751, 761, 772, 782, 792, 803, 813, 823, 833, 844, 854, 864, 875, 885, 895, 905, - 916, 926, 936, 947, 957, 967, 977, 988, 998, 1008, 1019, }; -// clang-format on +constexpr int tukey_ninther_adversary2[] = {1024, 31, 30, 29, 28, 36, 46, 51, 61, 67, 77, 82, 92, 98, 108, 118, 123, + 133, 139, 149, 154, 164, 170, 180, 190, 195, 205, 211, 221, 226, 236, 242, 252, 262, 267, 277, 283, 293, 298, 308, + 314, 324, 334, 339, 349, 355, 365, 370, 380, 386, 396, 406, 411, 421, 427, 437, 442, 452, 458, 468, 478, 483, 493, + 499, 509, 514, 524, 530, 540, 550, 555, 565, 571, 581, 586, 596, 602, 612, 622, 627, 637, 643, 653, 658, 668, 674, + 684, 694, 699, 709, 715, 725, 730, 740, 746, 756, 766, 771, 781, 787, 797, 802, 812, 818, 828, 838, 843, 853, 859, + 869, 874, 884, 890, 900, 910, 915, 925, 931, 941, 946, 956, 962, 972, 982, 987, 997, 1003, 1013, 1018, 343, 523, + 127, 529, 86, 539, 358, 549, 178, 554, 107, 564, 374, 570, 183, 580, 384, 585, 389, 595, 394, 601, 399, 611, 404, + 621, 409, 626, 18, 636, 419, 642, 425, 652, 318, 657, 435, 667, 440, 673, 169, 683, 450, 693, 224, 698, 256, 708, + 179, 714, 66, 724, 234, 729, 487, 739, 189, 745, 34, 755, 502, 765, 71, 770, 188, 780, 518, 786, 76, 796, 528, 801, + 533, 811, 538, 817, 543, 827, 548, 837, 553, 842, 163, 852, 563, 858, 569, 868, 286, 873, 579, 883, 584, 889, 70, + 899, 594, 909, 219, 914, 97, 924, 235, 930, 91, 940, 462, 945, 631, 955, 173, 961, 241, 971, 646, 981, 322, 986, + 272, 996, 662, 1002, 327, 1012, 672, 1017, 677, 1023, 682, 184, 687, 44, 692, 80, 697, 703, 390, 347, 707, 193, 713, + 718, 534, 276, 723, 26, 728, 734, 32, 200, 738, 744, 368, 749, 137, 754, 15, 759, 25, 764, 378, 769, 775, 575, 90, + 779, 148, 785, 790, 297, 215, 795, 225, 800, 806, 447, 56, 810, 816, 27, 821, 153, 826, 616, 831, 152, 836, 59, 841, + 847, 472, 632, 851, 116, 857, 862, 430, 214, 867, 647, 872, 878, 106, 251, 882, 888, 21, 893, 332, 898, 87, 903, + 132, 908, 678, 913, 919, 456, 168, 923, 230, 929, 934, 519, 466, 939, 19, 944, 950, 353, 471, 954, 960, 364, 965, + 719, 970, 271, 975, 544, 980, 369, 985, 991, 210, 491, 995, 282, 1001, 1006, 750, 250, 1011, 121, 1016, 1022, 385, + 292, 507, 65, 512, 255, 102, 776, 395, 45, 159, 287, 522, 260, 591, 791, 405, 117, 204, 307, 49, 265, 302, 807, 606, + 400, 22, 111, 16, 344, 822, 420, 313, 303, 415, 832, 275, 203, 559, 23, 416, 426, 323, 848, 281, 231, 209, 317, 574, + 436, 17, 863, 142, 333, 220, 488, 431, 441, 81, 879, 75, 590, 451, 663, 328, 446, 894, 296, 375, 600, 261, 904, 457, + 348, 605, 337, 610, 60, 688, 920, 467, 96, 615, 461, 620, 306, 354, 935, 477, 704, 625, 24, 312, 128, 143, 951, 476, + 635, 174, 131, 641, 240, 966, 492, 481, 138, 359, 976, 40, 363, 651, 735, 656, 498, 379, 992, 20, 497, 39, 560, 666, + 508, 112, 1007, 246, 158, 162, 760, 503, 513, 482, 291, 410, 245, 338, 199, 266, 147, 194, 101, 122, 55, 50, 14, 13, + 43, 48, 58, 64, 74, 79, 95, 105, 115, 120, 130, 136, 146, 151, 167, 177, 187, 192, 202, 208, 218, 223, 239, 249, + 259, 264, 274, 280, 290, 295, 311, 321, 331, 336, 346, 352, 362, 367, 383, 393, 403, 408, 418, 424, 434, 439, 455, + 465, 475, 480, 490, 496, 506, 511, 527, 537, 547, 552, 562, 568, 578, 583, 599, 609, 619, 624, 634, 640, 650, 655, + 671, 681, 691, 696, 706, 712, 722, 727, 743, 753, 763, 768, 778, 784, 794, 799, 815, 825, 835, 840, 850, 856, 866, + 871, 887, 897, 907, 912, 922, 928, 938, 943, 959, 969, 979, 984, 994, 1000, 1010, 1015, 1021, 1005, 990, 953, 974, + 964, 949, 933, 918, 881, 902, 892, 877, 861, 846, 809, 830, 820, 805, 789, 774, 737, 758, 748, 733, 717, 702, 665, + 686, 676, 661, 645, 630, 593, 614, 604, 589, 573, 558, 521, 542, 532, 517, 501, 486, 449, 470, 460, 445, 429, 414, + 377, 398, 388, 373, 357, 342, 305, 326, 316, 301, 285, 270, 233, 254, 244, 229, 213, 198, 161, 182, 172, 157, 141, + 126, 89, 110, 100, 85, 69, 54, 12, 38, 11, 10, 9, 8, 53, 84, 99, 125, 156, 171, 197, 228, 243, 269, 300, 315, 341, + 372, 387, 413, 444, 459, 485, 516, 531, 557, 588, 603, 629, 660, 675, 701, 732, 747, 773, 804, 819, 845, 876, 891, + 917, 948, 963, 989, 1020, 1014, 63, 253, 258, 263, 279, 273, 284, 289, 294, 310, 304, 320, 73, 325, 330, 335, 351, + 345, 356, 361, 366, 382, 376, 392, 88, 397, 402, 407, 423, 417, 428, 433, 438, 454, 448, 464, 109, 469, 474, 479, + 495, 489, 500, 505, 510, 526, 520, 536, 135, 541, 546, 551, 567, 561, 572, 577, 582, 598, 592, 608, 145, 613, 618, + 623, 639, 633, 644, 649, 654, 670, 664, 680, 160, 685, 690, 695, 711, 705, 716, 721, 726, 742, 736, 752, 181, 757, + 762, 767, 783, 777, 788, 793, 798, 814, 808, 824, 207, 829, 834, 839, 855, 849, 860, 865, 870, 886, 880, 896, 217, + 901, 906, 911, 927, 921, 932, 937, 942, 958, 952, 968, 232, 973, 978, 983, 999, 993, 1004, 1009, 248, 238, 222, 212, + 201, 191, 186, 37, 176, 166, 150, 140, 129, 119, 114, 3, 104, 94, 78, 68, 57, 47, 42, 6, 7, 4, 5, 2, -1, 33, 35, 41, + 52, 62, 72, 83, 93, 103, 113, 124, 134, 144, 155, 165, 175, 185, 196, 206, 216, 227, 237, 247, 257, 268, 278, 288, + 299, 309, 319, 329, 340, 350, 360, 371, 381, 391, 401, 412, 422, 432, 443, 453, 463, 473, 484, 494, 504, 515, 525, + 535, 545, 556, 566, 576, 587, 597, 607, 617, 628, 638, 648, 659, 669, 679, 689, 700, 710, 720, 731, 741, 751, 761, + 772, 782, 792, 803, 813, 823, 833, 844, 854, 864, 875, 885, 895, 905, 916, 926, 936, 947, 957, 967, 977, 988, 998, + 1008, 1019}; using namespace std; From fdc49d6cedc3518af65e5d597c8036fa72136c1c Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 23 Apr 2025 02:56:56 -0700 Subject: [PATCH 10/25] Move using-directives right after header inclusions. --- benchmarks/src/nth_element.cpp | 4 ++-- tests/std/tests/GH_000856_nth_element_linear/test.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/benchmarks/src/nth_element.cpp b/benchmarks/src/nth_element.cpp index d0b541c3829..aa25c89ea15 100644 --- a/benchmarks/src/nth_element.cpp +++ b/benchmarks/src/nth_element.cpp @@ -8,6 +8,8 @@ #include #include +using namespace std; + constexpr int tukey_ninther_adversary1[] = {0, 6, 12, 18, 22, 28, 34, 38, 44, 50, 54, 60, 66, 70, 76, 82, 86, 92, 98, 102, 108, 114, 118, 124, 130, 134, 140, 146, 150, 156, 162, 166, 172, 178, 182, 188, 194, 198, 204, 210, 214, 220, 226, 230, 236, 242, 246, 252, 258, 262, 268, 274, 278, 284, 290, 294, 300, 306, 310, 316, 322, 326, 332, 338, 342, @@ -99,8 +101,6 @@ constexpr int tukey_ninther_adversary2[] = {1024, 31, 30, 29, 28, 36, 46, 51, 61 772, 782, 792, 803, 813, 823, 833, 844, 854, 864, 875, 885, 895, 905, 916, 926, 936, 947, 957, 967, 977, 988, 998, 1008, 1019}; -using namespace std; - enum class alg_type { std_fn, rng }; template diff --git a/tests/std/tests/GH_000856_nth_element_linear/test.cpp b/tests/std/tests/GH_000856_nth_element_linear/test.cpp index 15b55e838cb..c6746796de5 100644 --- a/tests/std/tests/GH_000856_nth_element_linear/test.cpp +++ b/tests/std/tests/GH_000856_nth_element_linear/test.cpp @@ -9,6 +9,8 @@ #include #endif // _HAS_CXX20 +using namespace std; + constexpr int tukey_ninther_adversary1[] = {0, 6, 12, 18, 22, 28, 34, 38, 44, 50, 54, 60, 66, 70, 76, 82, 86, 92, 98, 102, 108, 114, 118, 124, 130, 134, 140, 146, 150, 156, 162, 166, 172, 178, 182, 188, 194, 198, 204, 210, 214, 220, 226, 230, 236, 242, 246, 252, 258, 262, 268, 274, 278, 284, 290, 294, 300, 306, 310, 316, 322, 326, 332, 338, 342, @@ -100,8 +102,6 @@ constexpr int tukey_ninther_adversary2[] = {1024, 31, 30, 29, 28, 36, 46, 51, 61 772, 782, 792, 803, 813, 823, 833, 844, 854, 864, 875, 885, 895, 905, 916, 926, 936, 947, 957, 967, 977, 988, 998, 1008, 1019}; -using namespace std; - template void check_result(const vector& expected, const vector& computed, Diff nth) { assert(is_permutation(computed.begin(), computed.end(), expected.begin())); From 4b71fc627f1580931eb3688fe5fc739ab2839398 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 23 Apr 2025 03:06:07 -0700 Subject: [PATCH 11/25] `benchmark_common()` can take `const vector& src`. --- benchmarks/src/nth_element.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/benchmarks/src/nth_element.cpp b/benchmarks/src/nth_element.cpp index aa25c89ea15..4cc8c1c35d4 100644 --- a/benchmarks/src/nth_element.cpp +++ b/benchmarks/src/nth_element.cpp @@ -104,7 +104,7 @@ constexpr int tukey_ninther_adversary2[] = {1024, 31, 30, 29, 28, 36, 46, 51, 61 enum class alg_type { std_fn, rng }; template -void benchmark_common(benchmark::State& state, vector src) { +void benchmark_common(benchmark::State& state, const vector& src) { vector v; v.reserve(src.size()); @@ -128,7 +128,7 @@ void bm_uniform(benchmark::State& state) { mt19937 gen(84710); uniform_int_distribution dis(1, 580); ranges::generate(src, [&] { return dis(gen); }); - benchmark_common(state, move(src)); + benchmark_common(state, src); } template From 3ba677cb2dd781423391ec4a3168886691804085 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 23 Apr 2025 03:19:58 -0700 Subject: [PATCH 12/25] Pass arrays by const reference, avoid temporary vectors. --- benchmarks/src/nth_element.cpp | 26 ++++++++----------- .../GH_000856_nth_element_linear/test.cpp | 20 +++++++------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/benchmarks/src/nth_element.cpp b/benchmarks/src/nth_element.cpp index 4cc8c1c35d4..ddd8444f32d 100644 --- a/benchmarks/src/nth_element.cpp +++ b/benchmarks/src/nth_element.cpp @@ -103,14 +103,14 @@ constexpr int tukey_ninther_adversary2[] = {1024, 31, 30, 29, 28, 36, 46, 51, 61 enum class alg_type { std_fn, rng }; -template -void benchmark_common(benchmark::State& state, const vector& src) { +template +void benchmark_common(benchmark::State& state, const Src& src) { vector v; - v.reserve(src.size()); + v.reserve(size(src)); for (auto _ : state) { - v = src; + v.assign(begin(src), end(src)); benchmark::DoNotOptimize(v); auto mid = v.begin() + (v.size() / 2); if constexpr (Type == alg_type::std_fn) { @@ -131,21 +131,17 @@ void bm_uniform(benchmark::State& state) { benchmark_common(state, src); } -template -void bm_tukey_adversary(benchmark::State& state, const int* const adversary_first, const int* const adversary_last) { - benchmark_common(state, vector(adversary_first, adversary_last)); +template +void bm_tukey_adversary(benchmark::State& state, const Src& adversary) { + benchmark_common(state, adversary); } BENCHMARK(bm_uniform)->Arg(1024)->Arg(2048)->Arg(4096)->Arg(8192); BENCHMARK(bm_uniform)->Arg(1024)->Arg(2048)->Arg(4096)->Arg(8192); -BENCHMARK_CAPTURE( - bm_tukey_adversary, adversary1, begin(tukey_ninther_adversary1), end(tukey_ninther_adversary1)); -BENCHMARK_CAPTURE( - bm_tukey_adversary, adversary1, begin(tukey_ninther_adversary1), end(tukey_ninther_adversary1)); -BENCHMARK_CAPTURE( - bm_tukey_adversary, adversary2, begin(tukey_ninther_adversary2), end(tukey_ninther_adversary2)); -BENCHMARK_CAPTURE( - bm_tukey_adversary, adversary2, begin(tukey_ninther_adversary2), end(tukey_ninther_adversary2)); +BENCHMARK_CAPTURE(bm_tukey_adversary, adversary1, tukey_ninther_adversary1); +BENCHMARK_CAPTURE(bm_tukey_adversary, adversary1, tukey_ninther_adversary1); +BENCHMARK_CAPTURE(bm_tukey_adversary, adversary2, tukey_ninther_adversary2); +BENCHMARK_CAPTURE(bm_tukey_adversary, adversary2, tukey_ninther_adversary2); BENCHMARK_MAIN(); diff --git a/tests/std/tests/GH_000856_nth_element_linear/test.cpp b/tests/std/tests/GH_000856_nth_element_linear/test.cpp index c6746796de5..7548f2f7771 100644 --- a/tests/std/tests/GH_000856_nth_element_linear/test.cpp +++ b/tests/std/tests/GH_000856_nth_element_linear/test.cpp @@ -115,30 +115,28 @@ void check_result(const vector& expected, const vector& computed, Diff } } -template -void test_nth_element(Algorithm alg, const int* const first, const int* const last) { - vector src(first, last); - - vector sorted = src; +template +void test_nth_element(Algorithm alg, const Src& src) { + vector sorted(begin(src), end(src)); sort(sorted.begin(), sorted.end()); vector v; - v.reserve(src.size()); + v.reserve(size(src)); - for (vector::difference_type nth{}, size = src.end() - src.begin(); nth < size; + for (vector::difference_type nth{}, size = end(src) - begin(src); nth < size; nth += static_cast::difference_type>(15)) { - v = src; + v.assign(begin(src), end(src)); alg(v, nth); check_result(sorted, v, nth); } - v = src; + v.assign(begin(src), end(src)); alg(v, (v.end() - v.begin()) - static_cast::difference_type>(1)); check_result(sorted, v, (v.end() - v.begin()) - static_cast::difference_type>(1)); } template void test_nth_element_tukey_adversary(Algorithm alg) { - test_nth_element(alg, begin(tukey_ninther_adversary1), end(tukey_ninther_adversary1)); - test_nth_element(alg, begin(tukey_ninther_adversary2), end(tukey_ninther_adversary2)); + test_nth_element(alg, tukey_ninther_adversary1); + test_nth_element(alg, tukey_ninther_adversary2); } int main() { From 8c8a87c96447d63d81f165380492f548df08eec5 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 23 Apr 2025 03:22:23 -0700 Subject: [PATCH 13/25] `bm_tukey_adversary` is now redundant with `benchmark_common`. --- benchmarks/src/nth_element.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/benchmarks/src/nth_element.cpp b/benchmarks/src/nth_element.cpp index ddd8444f32d..ac4caae91da 100644 --- a/benchmarks/src/nth_element.cpp +++ b/benchmarks/src/nth_element.cpp @@ -131,17 +131,12 @@ void bm_uniform(benchmark::State& state) { benchmark_common(state, src); } -template -void bm_tukey_adversary(benchmark::State& state, const Src& adversary) { - benchmark_common(state, adversary); -} - BENCHMARK(bm_uniform)->Arg(1024)->Arg(2048)->Arg(4096)->Arg(8192); BENCHMARK(bm_uniform)->Arg(1024)->Arg(2048)->Arg(4096)->Arg(8192); -BENCHMARK_CAPTURE(bm_tukey_adversary, adversary1, tukey_ninther_adversary1); -BENCHMARK_CAPTURE(bm_tukey_adversary, adversary1, tukey_ninther_adversary1); -BENCHMARK_CAPTURE(bm_tukey_adversary, adversary2, tukey_ninther_adversary2); -BENCHMARK_CAPTURE(bm_tukey_adversary, adversary2, tukey_ninther_adversary2); +BENCHMARK_CAPTURE(benchmark_common, adversary1, tukey_ninther_adversary1); +BENCHMARK_CAPTURE(benchmark_common, adversary1, tukey_ninther_adversary1); +BENCHMARK_CAPTURE(benchmark_common, adversary2, tukey_ninther_adversary2); +BENCHMARK_CAPTURE(benchmark_common, adversary2, tukey_ninther_adversary2); BENCHMARK_MAIN(); From 1c74cabfdde95e264a9ea468949d579758b42896 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 23 Apr 2025 03:25:04 -0700 Subject: [PATCH 14/25] Adjust newlines. --- benchmarks/src/nth_element.cpp | 1 - stl/inc/algorithm | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmarks/src/nth_element.cpp b/benchmarks/src/nth_element.cpp index ac4caae91da..f43a6e35e89 100644 --- a/benchmarks/src/nth_element.cpp +++ b/benchmarks/src/nth_element.cpp @@ -105,7 +105,6 @@ enum class alg_type { std_fn, rng }; template void benchmark_common(benchmark::State& state, const Src& src) { - vector v; v.reserve(size(src)); diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 1f12a0bb1ea..fba7fc790d2 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -3950,6 +3950,7 @@ namespace ranges { return {_STD move(_First1), _STD move(_First2)}; } + class _Swap_ranges_fn { public: template _Se1, input_iterator _It2, sentinel_for<_It2> _Se2> From 1c1ddcdb3af6f4272f32dea0cc68e812cd1ded3a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 23 Apr 2025 03:29:43 -0700 Subject: [PATCH 15/25] Drop unnecessary `static_cast::difference_type>` around integer literals. --- tests/std/tests/GH_000856_nth_element_linear/test.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/std/tests/GH_000856_nth_element_linear/test.cpp b/tests/std/tests/GH_000856_nth_element_linear/test.cpp index 7548f2f7771..ddee5ebe5a3 100644 --- a/tests/std/tests/GH_000856_nth_element_linear/test.cpp +++ b/tests/std/tests/GH_000856_nth_element_linear/test.cpp @@ -122,15 +122,14 @@ void test_nth_element(Algorithm alg, const Src& src) { vector v; v.reserve(size(src)); - for (vector::difference_type nth{}, size = end(src) - begin(src); nth < size; - nth += static_cast::difference_type>(15)) { + for (vector::difference_type nth{}, size = end(src) - begin(src); nth < size; nth += 15) { v.assign(begin(src), end(src)); alg(v, nth); check_result(sorted, v, nth); } v.assign(begin(src), end(src)); - alg(v, (v.end() - v.begin()) - static_cast::difference_type>(1)); - check_result(sorted, v, (v.end() - v.begin()) - static_cast::difference_type>(1)); + alg(v, (v.end() - v.begin()) - 1); + check_result(sorted, v, (v.end() - v.begin()) - 1); } template From bfc1bf3f672234f3f63bc56c06921b779eeb0ea3 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 23 Apr 2025 03:36:55 -0700 Subject: [PATCH 16/25] Extract `src_ssize`. --- tests/std/tests/GH_000856_nth_element_linear/test.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/GH_000856_nth_element_linear/test.cpp b/tests/std/tests/GH_000856_nth_element_linear/test.cpp index ddee5ebe5a3..a9475d7b566 100644 --- a/tests/std/tests/GH_000856_nth_element_linear/test.cpp +++ b/tests/std/tests/GH_000856_nth_element_linear/test.cpp @@ -117,19 +117,21 @@ void check_result(const vector& expected, const vector& computed, Diff template void test_nth_element(Algorithm alg, const Src& src) { + const auto src_ssize = end(src) - begin(src); + vector sorted(begin(src), end(src)); sort(sorted.begin(), sorted.end()); vector v; v.reserve(size(src)); - for (vector::difference_type nth{}, size = end(src) - begin(src); nth < size; nth += 15) { + for (vector::difference_type nth{}; nth < src_ssize; nth += 15) { v.assign(begin(src), end(src)); alg(v, nth); check_result(sorted, v, nth); } v.assign(begin(src), end(src)); - alg(v, (v.end() - v.begin()) - 1); - check_result(sorted, v, (v.end() - v.begin()) - 1); + alg(v, src_ssize - 1); + check_result(sorted, v, src_ssize - 1); } template From f36b303367c28a478f902c82c98f0a539e0f7ddd Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 23 Apr 2025 03:40:11 -0700 Subject: [PATCH 17/25] Use 4-arg `is_permutation()`. --- tests/std/tests/GH_000856_nth_element_linear/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/GH_000856_nth_element_linear/test.cpp b/tests/std/tests/GH_000856_nth_element_linear/test.cpp index a9475d7b566..f00b29402c8 100644 --- a/tests/std/tests/GH_000856_nth_element_linear/test.cpp +++ b/tests/std/tests/GH_000856_nth_element_linear/test.cpp @@ -104,7 +104,7 @@ constexpr int tukey_ninther_adversary2[] = {1024, 31, 30, 29, 28, 36, 46, 51, 61 template void check_result(const vector& expected, const vector& computed, Diff nth) { - assert(is_permutation(computed.begin(), computed.end(), expected.begin())); + assert(is_permutation(computed.begin(), computed.end(), expected.begin(), expected.end())); const int val_nth = *(computed.begin() + nth); assert(*(expected.begin() + nth) == val_nth); for (auto it = computed.begin(), last = computed.begin() + nth; it < last; ++it) { From 0340aefea11d0a4e1268e550133349b0cd7aefe1 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 23 Apr 2025 03:45:34 -0700 Subject: [PATCH 18/25] We don't need ``; `` provides `ranges::nth_element` and `ranges::generate`. --- benchmarks/src/nth_element.cpp | 1 - tests/std/tests/GH_000856_nth_element_linear/test.cpp | 4 ---- 2 files changed, 5 deletions(-) diff --git a/benchmarks/src/nth_element.cpp b/benchmarks/src/nth_element.cpp index f43a6e35e89..7c6cc99affb 100644 --- a/benchmarks/src/nth_element.cpp +++ b/benchmarks/src/nth_element.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include using namespace std; diff --git a/tests/std/tests/GH_000856_nth_element_linear/test.cpp b/tests/std/tests/GH_000856_nth_element_linear/test.cpp index f00b29402c8..895a69af5c8 100644 --- a/tests/std/tests/GH_000856_nth_element_linear/test.cpp +++ b/tests/std/tests/GH_000856_nth_element_linear/test.cpp @@ -5,10 +5,6 @@ #include #include -#if _HAS_CXX20 -#include -#endif // _HAS_CXX20 - using namespace std; constexpr int tukey_ninther_adversary1[] = {0, 6, 12, 18, 22, 28, 34, 38, 44, 50, 54, 60, 66, 70, 76, 82, 86, 92, 98, From 124292a5f8f880c90ff92dea3cc54614a79d9f27 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 23 Apr 2025 03:53:48 -0700 Subject: [PATCH 19/25] Extract `computed.begin() + nth` as `mid`. --- tests/std/tests/GH_000856_nth_element_linear/test.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/GH_000856_nth_element_linear/test.cpp b/tests/std/tests/GH_000856_nth_element_linear/test.cpp index 895a69af5c8..c55b38f5d49 100644 --- a/tests/std/tests/GH_000856_nth_element_linear/test.cpp +++ b/tests/std/tests/GH_000856_nth_element_linear/test.cpp @@ -101,12 +101,13 @@ constexpr int tukey_ninther_adversary2[] = {1024, 31, 30, 29, 28, 36, 46, 51, 61 template void check_result(const vector& expected, const vector& computed, Diff nth) { assert(is_permutation(computed.begin(), computed.end(), expected.begin(), expected.end())); - const int val_nth = *(computed.begin() + nth); + const auto mid = computed.begin() + nth; + const int val_nth = *mid; assert(*(expected.begin() + nth) == val_nth); - for (auto it = computed.begin(), last = computed.begin() + nth; it < last; ++it) { + for (auto it = computed.begin(); it < mid; ++it) { assert(*it <= val_nth); } - for (auto it = computed.begin() + nth; it < computed.end(); ++it) { + for (auto it = mid; it < computed.end(); ++it) { assert(*it >= val_nth); } } From 2312ec87b27383c4eebca13f1345c66bcc4d6496 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 23 Apr 2025 04:00:41 -0700 Subject: [PATCH 20/25] Drop unnecessary `reserve()` call. --- tests/std/tests/GH_000856_nth_element_linear/test.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/std/tests/GH_000856_nth_element_linear/test.cpp b/tests/std/tests/GH_000856_nth_element_linear/test.cpp index c55b38f5d49..b599b84757c 100644 --- a/tests/std/tests/GH_000856_nth_element_linear/test.cpp +++ b/tests/std/tests/GH_000856_nth_element_linear/test.cpp @@ -119,7 +119,6 @@ void test_nth_element(Algorithm alg, const Src& src) { vector sorted(begin(src), end(src)); sort(sorted.begin(), sorted.end()); vector v; - v.reserve(size(src)); for (vector::difference_type nth{}; nth < src_ssize; nth += 15) { v.assign(begin(src), end(src)); From 5b30c5cc22fe6c83e0cc8c211fabd3e685eae2f2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 23 Apr 2025 04:19:01 -0700 Subject: [PATCH 21/25] Adjust comments. --- stl/inc/algorithm | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index fba7fc790d2..40a5479c539 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -9780,17 +9780,17 @@ _CONSTEXPR20 void _Nth_element_median_of_medians(_RanIt _First, _RanIt _Nth, _Ra auto _Median_mid = _First + (_Median_count >> 1); _STD _Nth_element_median_of_medians(_First, _Median_mid, _Median_last, _Pred); - // the medians before and after _Median_mid are - // less equal and greater equal _Median_mid, respectively. - // move the ones after _Median_mid near _Last and then partition + // The medians before and after _Median_mid are + // less-equal and greater-equal _Median_mid, respectively. + // Move the ones after _Median_mid near _Last and then partition // the elements between the medians at front and back by the pivot _Median_mid // so that they do not have to be considered or moved in the partitioning pass. _Diff _Median_greater_count = (_Median_last - _Median_mid) - 1; auto _Median_greater_first = _Last - _Median_greater_count; _STD _Swap_ranges_unchecked(_Median_mid + static_cast<_Diff>(1), _Median_last, _Median_greater_first); - // swap the median of medians to the middle - // to reduce the number of times it will be moved by the partition function + // Swap the median of medians to the middle + // to reduce the number of times it will be moved by the partition function. auto _Middle = _First + ((_Last - _First) >> 1); swap(*_Median_mid, *_Middle); @@ -9833,7 +9833,7 @@ _CONSTEXPR20 void _Nth_element_unchecked(_RanIt _First, _RanIt _Nth, _RanIt _Las _Last = _Mid.first; } - // processed range should be reduced by 25 % per iteration on average + // processed range should be reduced by 25% per iteration on average _Ideal = (_Ideal >> 1) + (_Ideal >> 2); } } @@ -9978,9 +9978,9 @@ namespace ranges { auto _Median_mid = _First + (_Median_count >> 1); _Nth_element_median_of_medians_unchecked(_First, _Median_mid, _Median_last, _Pred, _Proj); - // the medians before and after _Median_mid are - // less equal and greater equal _Median_mid, respectively. - // move the ones after _Median_mid near _Last and then partition + // The medians before and after _Median_mid are + // less-equal and greater-equal _Median_mid, respectively. + // Move the ones after _Median_mid near _Last and then partition // the elements between the medians at front and back by the pivot _Median_mid // so that they do not have to be considered or moved in the partitioning pass. _Diff _Median_greater_count = (_Median_last - _Median_mid) - 1; @@ -9988,8 +9988,8 @@ namespace ranges { (void) _RANGES _Swap_ranges_common( _Median_mid + static_cast<_Diff>(1), _STD move(_Median_last), _Median_greater_first, _Last); - // swap the median of medians to the middle - // to reduce the number of times it will be moved by the partition function + // Swap the median of medians to the middle + // to reduce the number of times it will be moved by the partition function. auto _Middle = _First + ((_Last - _First) >> 1); _RANGES iter_swap(_Median_mid, _Middle); @@ -10042,7 +10042,7 @@ namespace ranges { _Last = _Mid.begin(); } - // processed range should be reduced by 25 % per iteration on average + // processed range should be reduced by 25% per iteration on average _Ideal = (_Ideal >> 1) + (_Ideal >> 2); } } From 7fea07393680ee17ca1404d32c7de17f38f0e289 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 23 Apr 2025 03:43:23 -0700 Subject: [PATCH 22/25] Add const. --- stl/inc/algorithm | 40 +++++++++---------- .../GH_000856_nth_element_linear/test.cpp | 9 +++-- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 40a5479c539..ff2fe4e182c 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -9761,23 +9761,23 @@ template _CONSTEXPR20 void _Nth_element_median_of_medians(_RanIt _First, _RanIt _Nth, _RanIt _Last, _Pr _Pred) { using _Diff = _Iter_diff_t<_RanIt>; for (;;) { - auto _Length = _Last - _First; + const auto _Length = _Last - _First; if (_Length <= _ISORT_MAX) { _STD _Insertion_sort_unchecked(_First, _Last, _Pred); // sort any remainder return; } // collect the medians of five at the beginning of the range - _Diff _Median_count = _Length / static_cast<_Diff>(5); - auto _Median_last = _First + _Median_count; - auto _Current = _First; + const _Diff _Median_count = _Length / static_cast<_Diff>(5); + const auto _Median_last = _First + _Median_count; + auto _Current = _First; for (auto _Median_dest = _First; _Median_dest != _Median_last; ++_Median_dest) { _STD _Swap_med5_unchecked(_Current, _Median_dest, _Pred); _Current += static_cast<_Diff>(5); } // find the median of medians - auto _Median_mid = _First + (_Median_count >> 1); + const auto _Median_mid = _First + (_Median_count >> 1); _STD _Nth_element_median_of_medians(_First, _Median_mid, _Median_last, _Pred); // The medians before and after _Median_mid are @@ -9785,16 +9785,16 @@ _CONSTEXPR20 void _Nth_element_median_of_medians(_RanIt _First, _RanIt _Nth, _Ra // Move the ones after _Median_mid near _Last and then partition // the elements between the medians at front and back by the pivot _Median_mid // so that they do not have to be considered or moved in the partitioning pass. - _Diff _Median_greater_count = (_Median_last - _Median_mid) - 1; - auto _Median_greater_first = _Last - _Median_greater_count; + const _Diff _Median_greater_count = (_Median_last - _Median_mid) - 1; + const auto _Median_greater_first = _Last - _Median_greater_count; _STD _Swap_ranges_unchecked(_Median_mid + static_cast<_Diff>(1), _Median_last, _Median_greater_first); // Swap the median of medians to the middle // to reduce the number of times it will be moved by the partition function. - auto _Middle = _First + ((_Last - _First) >> 1); + const auto _Middle = _First + ((_Last - _First) >> 1); swap(*_Median_mid, *_Middle); - auto _Mid = _STD _Partition_by_pivot_unchecked(_Median_mid, _Middle, _Median_greater_first, _Pred); + const auto _Mid = _STD _Partition_by_pivot_unchecked(_Median_mid, _Middle, _Median_greater_first, _Pred); if (_Mid.second <= _Nth) { _First = _Mid.second; @@ -9811,7 +9811,7 @@ _CONSTEXPR20 void _Nth_element_unchecked(_RanIt _First, _RanIt _Nth, _RanIt _Las auto _Ideal = _Last - _First; for (;;) { - auto _Length = _Last - _First; + const auto _Length = _Last - _First; if (_Length <= _ISORT_MAX) { _STD _Insertion_sort_unchecked(_First, _Last, _Pred); // sort any remainder return; @@ -9823,7 +9823,7 @@ _CONSTEXPR20 void _Nth_element_unchecked(_RanIt _First, _RanIt _Nth, _RanIt _Las return; } - auto _Mid = _STD _Partition_by_median_guess_unchecked(_First, _Last, _Pred); + const auto _Mid = _STD _Partition_by_median_guess_unchecked(_First, _Last, _Pred); if (_Mid.second <= _Nth) { _First = _Mid.second; @@ -9958,7 +9958,7 @@ namespace ranges { using _Diff = iter_difference_t<_It>; for (;;) { - auto _Length = _Last - _First; + const auto _Length = _Last - _First; if (_Length <= _ISORT_MAX) { // sort any remainder _RANGES _Insertion_sort_common(_STD move(_First), _STD move(_Last), _Pred, _Proj); @@ -9966,9 +9966,9 @@ namespace ranges { } // collect the medians of five at the beginning of the range - _Diff _Median_count = _Length / static_cast<_Diff>(5); - auto _Median_last = _First + _Median_count; - auto _Current = _First; + const _Diff _Median_count = _Length / static_cast<_Diff>(5); + auto _Median_last = _First + _Median_count; + auto _Current = _First; for (auto _Median_dest = _First; _Median_dest != _Median_last; ++_Median_dest) { _Swap_med5(_Current, _Median_dest, _Pred, _Proj); _Current += static_cast<_Diff>(5); @@ -9983,8 +9983,8 @@ namespace ranges { // Move the ones after _Median_mid near _Last and then partition // the elements between the medians at front and back by the pivot _Median_mid // so that they do not have to be considered or moved in the partitioning pass. - _Diff _Median_greater_count = (_Median_last - _Median_mid) - 1; - auto _Median_greater_first = _Last - _Median_greater_count; + const _Diff _Median_greater_count = (_Median_last - _Median_mid) - 1; + auto _Median_greater_first = _Last - _Median_greater_count; (void) _RANGES _Swap_ranges_common( _Median_mid + static_cast<_Diff>(1), _STD move(_Median_last), _Median_greater_first, _Last); @@ -9993,7 +9993,7 @@ namespace ranges { auto _Middle = _First + ((_Last - _First) >> 1); _RANGES iter_swap(_Median_mid, _Middle); - subrange<_It> _Mid = _RANGES _Partition_by_pivot_common( + const subrange<_It> _Mid = _RANGES _Partition_by_pivot_common( _STD move(_Median_mid), _STD move(_Middle), _STD move(_Median_greater_first), _Pred, _Proj); if (_Mid.end() <= _Nth) { @@ -10018,7 +10018,7 @@ namespace ranges { auto _Ideal = _Last - _First; for (;;) { - auto _Length = _Last - _First; + const auto _Length = _Last - _First; if (_Length <= _ISORT_MAX) { // sort any remainder _RANGES _Insertion_sort_common(_STD move(_First), _STD move(_Last), _Pred, _Proj); @@ -10032,7 +10032,7 @@ namespace ranges { return; } - subrange<_It> _Mid = _RANGES _Partition_by_median_guess_common(_First, _Last, _Pred, _Proj); + const subrange<_It> _Mid = _RANGES _Partition_by_median_guess_common(_First, _Last, _Pred, _Proj); if (_Mid.end() <= _Nth) { _First = _Mid.end(); diff --git a/tests/std/tests/GH_000856_nth_element_linear/test.cpp b/tests/std/tests/GH_000856_nth_element_linear/test.cpp index b599b84757c..f8b0e5d28fc 100644 --- a/tests/std/tests/GH_000856_nth_element_linear/test.cpp +++ b/tests/std/tests/GH_000856_nth_element_linear/test.cpp @@ -99,7 +99,7 @@ constexpr int tukey_ninther_adversary2[] = {1024, 31, 30, 29, 28, 36, 46, 51, 61 1008, 1019}; template -void check_result(const vector& expected, const vector& computed, Diff nth) { +void check_result(const vector& expected, const vector& computed, const Diff nth) { assert(is_permutation(computed.begin(), computed.end(), expected.begin(), expected.end())); const auto mid = computed.begin() + nth; const int val_nth = *mid; @@ -137,11 +137,12 @@ void test_nth_element_tukey_adversary(Algorithm alg) { } int main() { - test_nth_element_tukey_adversary( - [](vector& v, vector::difference_type nth) { nth_element(v.begin(), v.begin() + nth, v.end()); }); + test_nth_element_tukey_adversary([](vector& v, const vector::difference_type nth) { + nth_element(v.begin(), v.begin() + nth, v.end()); + }); #if _HAS_CXX20 - test_nth_element_tukey_adversary([](vector& v, vector::difference_type nth) { + test_nth_element_tukey_adversary([](vector& v, const vector::difference_type nth) { ranges::nth_element(v.begin(), v.begin() + nth, v.end()); }); #endif From e37ab687f882be2be93f7e55bc04a9d988aea0d8 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 23 Apr 2025 05:16:56 -0700 Subject: [PATCH 23/25] `(_Last - _First)` => `_Length` (still valid here) --- stl/inc/algorithm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index ff2fe4e182c..8882cd1dcc1 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -9791,7 +9791,7 @@ _CONSTEXPR20 void _Nth_element_median_of_medians(_RanIt _First, _RanIt _Nth, _Ra // Swap the median of medians to the middle // to reduce the number of times it will be moved by the partition function. - const auto _Middle = _First + ((_Last - _First) >> 1); + const auto _Middle = _First + (_Length >> 1); swap(*_Median_mid, *_Middle); const auto _Mid = _STD _Partition_by_pivot_unchecked(_Median_mid, _Middle, _Median_greater_first, _Pred); @@ -9990,7 +9990,7 @@ namespace ranges { // Swap the median of medians to the middle // to reduce the number of times it will be moved by the partition function. - auto _Middle = _First + ((_Last - _First) >> 1); + auto _Middle = _First + (_Length >> 1); _RANGES iter_swap(_Median_mid, _Middle); const subrange<_It> _Mid = _RANGES _Partition_by_pivot_common( From e4393207fd81058009a0eef5f65cf29b792b599d Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 23 Apr 2025 05:19:57 -0700 Subject: [PATCH 24/25] Add "intentional ADL" comment. --- stl/inc/algorithm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 8882cd1dcc1..6ce2458290f 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -9792,7 +9792,7 @@ _CONSTEXPR20 void _Nth_element_median_of_medians(_RanIt _First, _RanIt _Nth, _Ra // Swap the median of medians to the middle // to reduce the number of times it will be moved by the partition function. const auto _Middle = _First + (_Length >> 1); - swap(*_Median_mid, *_Middle); + swap(*_Median_mid, *_Middle); // intentional ADL const auto _Mid = _STD _Partition_by_pivot_unchecked(_Median_mid, _Middle, _Median_greater_first, _Pred); From 65b4f5690fab34bdab4ff137a7384b07c5314de1 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 23 Apr 2025 05:54:07 -0700 Subject: [PATCH 25/25] Add "by pivot _Pfirst" to comments. Also restore a comment to `_Partition_by_median_guess_unchecked`. --- stl/inc/algorithm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 6ce2458290f..b49c4e041a7 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -8655,7 +8655,7 @@ _CONSTEXPR20 void _Guess_median_unchecked(_RanIt _First, _RanIt _Mid, _RanIt _La template _CONSTEXPR20 pair<_RanIt, _RanIt> _Partition_by_pivot_unchecked( _RanIt _First, _RanIt _Pfirst, _RanIt _Last, _Pr _Pred) { - // partition [_First, _Last) + // partition [_First, _Last) by pivot _Pfirst _RanIt _Plast = _STD _Next_iter(_Pfirst); while (_First < _Pfirst && !_DEBUG_LT_PRED(_Pred, *_STD _Prev_iter(_Pfirst), *_Pfirst) @@ -8723,6 +8723,7 @@ _CONSTEXPR20 pair<_RanIt, _RanIt> _Partition_by_pivot_unchecked( template _CONSTEXPR20 pair<_RanIt, _RanIt> _Partition_by_median_guess_unchecked(_RanIt _First, _RanIt _Last, _Pr _Pred) { + // partition [_First, _Last) _RanIt _Mid = _First + ((_Last - _First) >> 1); // shift for codegen _STD _Guess_median_unchecked(_First, _Mid, _STD _Prev_iter(_Last), _Pred); @@ -8856,7 +8857,7 @@ namespace ranges { requires sortable<_It, _Pr, _Pj> _NODISCARD constexpr subrange<_It> _Partition_by_pivot_common( _It _First, _It _Pfirst, _It _Last, _Pr _Pred, _Pj _Proj) { - // Partition [_First, _Last) into elements less than pivot, elements equal to pivot, and + // Partition [_First, _Last) by pivot _Pfirst into elements less than pivot, elements equal to pivot, and // elements greater than pivot; return the equal partition as a subrange. _It _Plast = _RANGES next(_Pfirst);