From cec8e9f3320fe714e6768b932cfd181d7c850210 Mon Sep 17 00:00:00 2001 From: lhamot Date: Wed, 26 Mar 2025 10:05:25 +0100 Subject: [PATCH 01/17] Optimize is_sorted algo --- includes/rah2/algo_sort.hpp | 76 +++++++++++++++++++++++++------------ test/test_helpers.hpp | 2 +- 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/includes/rah2/algo_sort.hpp b/includes/rah2/algo_sort.hpp index 23828ab..855580e 100644 --- a/includes/rah2/algo_sort.hpp +++ b/includes/rah2/algo_sort.hpp @@ -29,20 +29,21 @@ namespace RAH2_NS typename Sentinel, RAH2_STD::enable_if_t< forward_iterator && sentinel_for>* = nullptr> - ForwardIterator operator()(ForwardIterator first, Sentinel last) const + constexpr ForwardIterator operator()(ForwardIterator first, Sentinel last) const { if (first == last) { return first; } ForwardIterator next = first; - - while (++next != last) + ++next; + while (next != last) { if (*next < *first) return next; - first = next; + ++first; + ++next; } return next; } @@ -53,7 +54,7 @@ namespace RAH2_NS typename Compare, typename Proj = RAH2_NS::details::identity, RAH2_STD::enable_if_t>* = nullptr> - ForwardIterator + constexpr ForwardIterator operator()(ForwardIterator first, Sentinel last, Compare compare, Proj proj = {}) const { auto pred_proj = @@ -83,7 +84,7 @@ namespace RAH2_NS typename Compare, typename Proj = RAH2_NS::details::identity, RAH2_STD::enable_if_t>* = nullptr> - auto operator()(ForwardRange&& r, Compare compare, Proj proj = {}) const + constexpr auto operator()(ForwardRange&& r, Compare compare, Proj proj = {}) const { return (*this)( RAH2_NS::ranges::begin(r), @@ -93,7 +94,7 @@ namespace RAH2_NS } template - auto operator()(ForwardRange&& r) const + constexpr auto operator()(ForwardRange&& r) const { return (*this)(RAH2_NS::ranges::begin(r), RAH2_NS::ranges::end(r)); } @@ -111,7 +112,7 @@ namespace RAH2_NS typename Comp = RAH2_NS::ranges::less, // RAH2_STD::indirect_strict_weak_order> typename Proj = RAH2_NS::details::identity, RAH2_STD::enable_if_t && sentinel_for>* = nullptr> - constexpr bool operator()(I first, S last, Comp comp = {}, Proj proj = {}) const + constexpr bool operator()(I first, S last, Comp comp, Proj proj = {}) const { return RAH2_NS::ranges::is_sorted_until( RAH2_STD::move(first), @@ -126,7 +127,7 @@ namespace RAH2_NS typename Comp = RAH2_NS::ranges::less, // RAH2_STD::indirect_strict_weak_order, Proj>> typename Proj = RAH2_NS::details::identity, RAH2_STD::enable_if_t>* = nullptr> - constexpr bool operator()(R&& r, Comp comp = {}, Proj proj = {}) const + constexpr bool operator()(R&& r, Comp comp, Proj proj = {}) const { return (*this)( RAH2_NS::ranges::begin(r), @@ -134,6 +135,29 @@ namespace RAH2_NS RAH2_STD::move(comp), RAH2_STD::move(proj)); } + + template < + typename I, // RAH2_STD::forward_iterator + typename S, // RAH2_STD::sentinel_for + typename Comp = RAH2_NS::ranges::less, // RAH2_STD::indirect_strict_weak_order> + typename Proj = RAH2_NS::details::identity, + RAH2_STD::enable_if_t && sentinel_for>* = nullptr> + constexpr bool operator()(I first, S last) const + { + return RAH2_NS::ranges::is_sorted_until( + RAH2_STD::move(first), RAH2_STD::move(last)) + == last; + } + + template < + typename R, // ranges::forward_range + typename Comp = RAH2_NS::ranges::less, // RAH2_STD::indirect_strict_weak_order, Proj>> + typename Proj = RAH2_NS::details::identity, + RAH2_STD::enable_if_t>* = nullptr> + constexpr bool operator()(R&& r) const + { + return (*this)(RAH2_NS::ranges::begin(r), RAH2_NS::ranges::end(r)); + } }; } // namespace niebloids @@ -1044,8 +1068,9 @@ namespace RAH2_NS auto lasti = result; while ((lasti - first) > 5) { - auto&& midValue(RAH2_NS::ranges::median( - *first, *(first + (lasti - first) / 2), *(lasti - 1))); + auto&& midValue( + RAH2_NS::ranges::median( + *first, *(first + (lasti - first) / 2), *(lasti - 1))); RandomAccessIterator const midPos( RAH2_NS::ranges::get_partition(first, lasti, RAH2_STD::move(midValue))); @@ -1088,8 +1113,9 @@ namespace RAH2_NS auto lasti = result; while ((lasti - first) > 5) { - auto const midValue(RAH2_NS::ranges::median( - *first, *(first + (lasti - first) / 2), *(lasti - 1), pred_proj)); + auto const midValue( + RAH2_NS::ranges::median( + *first, *(first + (lasti - first) / 2), *(lasti - 1), pred_proj)); RandomAccessIterator const midPos( RAH2_NS::ranges::get_partition(first, lasti, midValue, pred_proj)); @@ -1136,11 +1162,12 @@ namespace RAH2_NS { while (((last - first) > details::kQuickSortLimit) && (kRecursionCount > 0)) { - RandomAccessIterator const position(RAH2_NS::ranges::get_partition( - first, - last, - RAH2_STD::forward(RAH2_NS::ranges::median( - *first, *(first + (last - first) / 2), *(last - 1))))); + RandomAccessIterator const position( + RAH2_NS::ranges::get_partition( + first, + last, + RAH2_STD::forward(RAH2_NS::ranges::median( + *first, *(first + (last - first) / 2), *(last - 1))))); quick_sort_impl_helper( position, last, --kRecursionCount); @@ -1157,12 +1184,13 @@ namespace RAH2_NS { while (((last - first) > details::kQuickSortLimit) && (kRecursionCount > 0)) { - RandomAccessIterator const position(RAH2_NS::ranges::get_partition( - first, - last, - RAH2_STD::forward(RAH2_NS::ranges::median( - *first, *(first + (last - first) / 2), *(last - 1), compare)), - compare)); + RandomAccessIterator const position( + RAH2_NS::ranges::get_partition( + first, + last, + RAH2_STD::forward(RAH2_NS::ranges::median( + *first, *(first + (last - first) / 2), *(last - 1), compare)), + compare)); quick_sort_impl_helper( position, last, --kRecursionCount, compare); diff --git a/test/test_helpers.hpp b/test/test_helpers.hpp index bf0d1eb..79493a6 100644 --- a/test/test_helpers.hpp +++ b/test/test_helpers.hpp @@ -1308,7 +1308,7 @@ std::chrono::nanoseconds compute_duration( #endif } -constexpr static auto PerfTolerency = 5.; +constexpr static auto PerfTolerency = 4.; template auto compare_duration( From 0e59f566d4cbf73270f8e8f15800a9a03df500b6 Mon Sep 17 00:00:00 2001 From: lhamot Date: Wed, 26 Mar 2025 14:23:11 +0100 Subject: [PATCH 02/17] Better perf test for lower_bound (better func times. Not too long, not too short) --- test/test_algo4.cpp | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/test/test_algo4.cpp b/test/test_algo4.cpp index 82b8400..92d3e7c 100644 --- a/test/test_algo4.cpp +++ b/test/test_algo4.cpp @@ -579,8 +579,8 @@ struct test_sample_ auto result = RAH2_NS::ranges::sample( RAH2_NS::ranges::begin(in), RAH2_NS::ranges::end(in), out.begin(), 3, g); CHECK(result == out.begin() + 3); - CHECK(RAH2_NS::ranges::none_of( - out.begin(), out.begin() + 3, [](auto v) { return v == 0; })); + CHECK( + RAH2_NS::ranges::none_of(out.begin(), out.begin() + 3, [](auto v) { return v == 0; })); } { @@ -588,8 +588,8 @@ struct test_sample_ RAH2_STD::vector out{0, 0, 0, 0, 0, 0, 4, 5}; auto result = RAH2_NS::ranges::sample(in, out.begin(), 3, g); CHECK(result == out.begin() + 3); - CHECK(RAH2_NS::ranges::none_of( - out.begin(), out.begin() + 3, [](auto v) { return v == 0; })); + CHECK( + RAH2_NS::ranges::none_of(out.begin(), out.begin() + 3, [](auto v) { return v == 0; })); } testSuite.test_case("empty"); @@ -2839,8 +2839,8 @@ struct test_nth_element_ CHECK(RAH2_NS::ranges::all_of(out.begin(), midle, [](auto const& v) { return v < 5; })); auto after_middle = midle; ++after_middle; - CHECK(RAH2_NS::ranges::all_of( - after_middle, out.end(), [](auto const& v) { return v > 5; })); + CHECK( + RAH2_NS::ranges::all_of(after_middle, out.end(), [](auto const& v) { return v > 5; })); CHECK_EQUAL(midle->i, 5); } @@ -2880,12 +2880,12 @@ struct test_nth_element_ auto midle = RAH2_NS::ranges::next(out.begin(), 2); auto result = RAH2_NS::ranges::nth_element(out, midle, comp_64, &Coord::x); CHECK(result == out.end()); - CHECK(RAH2_NS::ranges::all_of( - out.begin(), midle, [](auto v) { return v > 3; }, &Coord::x)); + CHECK(RAH2_NS::ranges::all_of(out.begin(), midle, [](auto v) { return v > 3; }, &Coord::x)); auto after_middle = midle; ++after_middle; - CHECK(RAH2_NS::ranges::all_of( - after_middle, out.end(), [](auto v) { return v < 3; }, &Coord::x)); + CHECK( + RAH2_NS::ranges::all_of( + after_middle, out.end(), [](auto v) { return v < 3; }, &Coord::x)); CHECK(midle->x == 3); } } @@ -3048,10 +3048,23 @@ struct test_lower_bound_ in2.push_back(Coord{1, 3}); auto r2 = make_test_view_adapter(in2); - auto const RangeTypeMultiplier = - RAH2_NS::derived_from ? 100 : 1; + auto const IterSized = + (CS == Common && RAH2_NS::derived_from) + || (CS == Sentinel && Sized); - auto const RangeSizedMultiplier = Sized ? 10 : 1; +#ifdef _DEBUG + auto const IterSizedMultiplier = + IterSized && RAH2_NS::derived_from ? + 1000 * RELEASE_MULTIPLIER : + 1; + auto const RangeSizedMultiplier = + Sized && RAH2_NS::derived_from ? + 1000 * RELEASE_MULTIPLIER : + 1; +#else + auto const IterSizedMultiplier = IterSized ? 1000 * RELEASE_MULTIPLIER : 1; + auto const RangeSizedMultiplier = Sized ? 1000 * RELEASE_MULTIPLIER : 1; +#endif COMPARE_DURATION_TO_STD_ALGO_AND_RANGES( CS == Common, @@ -3059,7 +3072,7 @@ struct test_lower_bound_ range_type, [&] { - for (auto i = 0; i < RangeTypeMultiplier * RangeSizedMultiplier; ++i) + for (auto i = 0; i < IterSizedMultiplier; ++i) { auto iter = STD::lower_bound(fwd(r1.begin()), r1.end(), Coord{3, 4}); assert((*iter == Coord{3, 4})); @@ -3070,7 +3083,7 @@ struct test_lower_bound_ range_type, [&] { - for (auto i = 0; i < RangeTypeMultiplier * RangeSizedMultiplier; ++i) + for (auto i = 0; i < RangeSizedMultiplier; ++i) { auto iter = STD::lower_bound(r2, 1, comp_64, &Coord::x); assert((*iter == Coord{1, 4})); From 17136322ded476514d237a8f333e7fb307eddbba Mon Sep 17 00:00:00 2001 From: lhamot Date: Wed, 26 Mar 2025 15:26:57 +0100 Subject: [PATCH 03/17] Optimize binary_search --- includes/rah2/base_algorithm.hpp | 27 +++++++++++++-------------- test/test_algo4.cpp | 24 +++++++++++++++++------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/includes/rah2/base_algorithm.hpp b/includes/rah2/base_algorithm.hpp index bd3edc7..99a27af 100644 --- a/includes/rah2/base_algorithm.hpp +++ b/includes/rah2/base_algorithm.hpp @@ -4365,7 +4365,7 @@ namespace RAH2_NS operator()(ForwardIterator first, Sentinel last, T const& value) const { // To do: This can be made slightly faster by not using lower_bound. - ForwardIterator i(RAH2_NS::ranges::lower_bound(first, last, value)); + auto i = RAH2_NS::ranges::lower_bound(first, last, value); // Note that we always express value comparisons in terms of < or ==. return ((i != last) && !(value < *i)); } @@ -4373,7 +4373,11 @@ namespace RAH2_NS template RAH2_NODISCARD constexpr bool operator()(Range&& range, T const& value) const { - return (*this)(RAH2_NS::ranges::begin(range), RAH2_NS::ranges::end(range), value); + auto last = RAH2_NS::ranges::end(range); + // To do: This can be made slightly faster by not using lower_bound. + auto i = RAH2_NS::ranges::lower_bound(range, value); + // Note that we always express value comparisons in terms of < or ==. + return ((i != last) && !(value < *i)); } /// binary_search @@ -4400,29 +4404,24 @@ namespace RAH2_NS Compare compare, Proj proj = {}) const { - auto pred_proj = - details::wrap_pred_value_proj(RAH2_STD::move(compare), RAH2_STD::move(proj)); - // To do: This can be made slightly faster by not using lower_bound. - ForwardIterator i(RAH2_NS::ranges::lower_bound(first, last, value, compare, proj)); - return ((i != last) && !pred_proj(value, *i)); + auto i = RAH2_NS::ranges::lower_bound(first, last, value, compare, proj); + return ((i != last) && !compare(value, RAH2_STD::ref(proj)(*i))); } template < typename Range, typename T, typename Compare, - class Proj = RAH2_NS::details::identity, + typename Proj = RAH2_NS::details::identity, RAH2_STD::enable_if_t>* = nullptr> RAH2_NODISCARD constexpr bool operator()(Range&& range, T const& value, Compare compare, Proj proj = {}) const { - return (*this)( - RAH2_NS::ranges::begin(range), - RAH2_NS::ranges::end(range), - value, - RAH2_STD::move(compare), - RAH2_STD::move(proj)); + auto last = RAH2_NS::ranges::end(range); + // To do: This can be made slightly faster by not using lower_bound. + auto i = RAH2_NS::ranges::lower_bound(range, value, compare, proj); + return (i != last) && !compare(value, RAH2_STD::ref(proj)(*i)); } }; } // namespace niebloids diff --git a/test/test_algo4.cpp b/test/test_algo4.cpp index 92d3e7c..2667992 100644 --- a/test/test_algo4.cpp +++ b/test/test_algo4.cpp @@ -3307,13 +3307,23 @@ struct test_binary_search_ } auto r2 = make_test_view_adapter(in2); - auto const RangeMultiplier = Sized ? 50 * RELEASE_MULTIPLIER : 1; + auto const IterSized = + (CS == Common && RAH2_NS::derived_from) + || (CS == Sentinel && Sized); - auto const IterMultiplier = - (Sized - and (CS == CommonOrSent::Sentinel or RAH2_NS::derived_from)) ? - 50 * (RELEASE_MULTIPLIER > 1 ? 10 : 1) : +#ifdef _DEBUG + auto const IterSizedMultiplier = + IterSized && RAH2_NS::derived_from ? + 1000 * RELEASE_MULTIPLIER : 1; + auto const RangeSizedMultiplier = + Sized && RAH2_NS::derived_from ? + 1000 * RELEASE_MULTIPLIER : + 1; +#else + auto const IterSizedMultiplier = IterSized ? 1000 * RELEASE_MULTIPLIER : 1; + auto const RangeSizedMultiplier = Sized ? 1000 * RELEASE_MULTIPLIER : 1; +#endif COMPARE_DURATION_TO_STD_ALGO_AND_RANGES( CS == Common, @@ -3321,7 +3331,7 @@ struct test_binary_search_ range_type, [&] { - for (auto i = 0; i < IterMultiplier; ++i) + for (auto i = 0; i < IterSizedMultiplier; ++i) { auto found = STD::binary_search(fwd(r1.begin()), r1.end(), Coord{3, 4}); CHECK(found); @@ -3332,7 +3342,7 @@ struct test_binary_search_ range_type, [&] { - for (auto i = 0; i < RangeMultiplier; ++i) + for (auto i = 0; i < RangeSizedMultiplier; ++i) { auto found = STD::binary_search(r2, 1, comp_64, &Coord::x); CHECK(found); From d06387a9c91255aeef265c15c6523a90ea133f2c Mon Sep 17 00:00:00 2001 From: lhamot Date: Wed, 26 Mar 2025 16:12:00 +0100 Subject: [PATCH 04/17] Optimize move_backward --- includes/rah2/base_algorithm.hpp | 48 ++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/includes/rah2/base_algorithm.hpp b/includes/rah2/base_algorithm.hpp index 99a27af..02a56ed 100644 --- a/includes/rah2/base_algorithm.hpp +++ b/includes/rah2/base_algorithm.hpp @@ -1305,27 +1305,59 @@ namespace RAH2_NS typename S1, typename I2, RAH2_STD::enable_if_t and RAH2_NS::contiguous_iterator - and RAH2_NS::contiguous_iterator + RAH2_NS::contiguous_iterator and RAH2_NS::contiguous_iterator and RAH2_STD::is_trivially_copyable>::value and RAH2_NS::is_same_v, RAH2_NS::iter_value_t>)>* = nullptr> constexpr copy_backward_result impl(I1 first, S1 last, I2 result) const { - I1 const last1{RAH2_NS::ranges::next(first, RAH2_STD::move(last))}; - for (I1 i{last1}; i != first;) + size_t item_count = 0; + I1 last1 = first; + for (; last1 != last; ++last1, ++item_count) + ; + I1 i = last1; + for (auto u = item_count / 4; u != 0; --u) + { + *--result = *--i; + *--result = *--i; + *--result = *--i; *--result = *--i; + } + for (auto u = item_count % 4; u != 0; --u) + { + *--result = *--i; + } return {RAH2_STD::move(last1), RAH2_STD::move(result)}; } + template < + typename I1, + typename S1, + typename I2, + RAH2_STD::enable_if_t< + not(RAH2_NS::sized_sentinel_for) + and (RAH2_NS::contiguous_iterator and RAH2_NS::contiguous_iterator and RAH2_STD::is_trivially_copyable>::value and RAH2_NS::is_same_v, RAH2_NS::iter_value_t>)>* = + nullptr> + constexpr copy_backward_result impl(I1 first, S1 last, I2 result) const + { + size_t item_count = 0; + I1 last1 = first; + for (; last1 != last; ++last1, ++item_count) + ; + memmove( + &(*(result - item_count)), + &(*first), + item_count * sizeof(RAH2_NS::iter_value_t)); + return {last1, result - item_count}; + } + template < typename I1, typename S1, typename I2, RAH2_STD::enable_if_t<( - RAH2_NS::sized_sentinel_for and RAH2_NS::contiguous_iterator - and RAH2_NS::contiguous_iterator - and RAH2_STD::is_trivially_copyable>::value - and RAH2_NS::is_same_v, RAH2_NS::iter_value_t>)>* = nullptr> + RAH2_NS::sized_sentinel_for + and (RAH2_NS::contiguous_iterator and RAH2_NS::contiguous_iterator and RAH2_STD::is_trivially_copyable>::value and RAH2_NS::is_same_v, RAH2_NS::iter_value_t>))>* = + nullptr> constexpr copy_backward_result impl(I1 first, S1 last, I2 result) const { auto const item_count = RAH2_NS::ranges::distance(first, last); From 619e54709d30556bccf8c037948cdde797856fa5 Mon Sep 17 00:00:00 2001 From: lhamot Date: Wed, 26 Mar 2025 18:31:08 +0100 Subject: [PATCH 05/17] Optimize algo count --- includes/rah2/base_algorithm.hpp | 125 ++++++++++++++++++++++++------- 1 file changed, 100 insertions(+), 25 deletions(-) diff --git a/includes/rah2/base_algorithm.hpp b/includes/rah2/base_algorithm.hpp index 02a56ed..786418b 100644 --- a/includes/rah2/base_algorithm.hpp +++ b/includes/rah2/base_algorithm.hpp @@ -1421,14 +1421,9 @@ namespace RAH2_NS { struct count_fn { - template < - typename I, - typename S, - class T, - class Proj = RAH2_NS::details::identity, - RAH2_STD::enable_if_t && sentinel_for>* = nullptr> + template constexpr RAH2_NS::iter_difference_t - operator()(I first_w, S last_w, T const& value, Proj proj) const + impl(I first_w, S last_w, T const& value, Proj proj) const { auto first_last = details::unwrap(RAH2_STD::move(first_w), RAH2_STD::move(last_w)); @@ -1443,43 +1438,123 @@ namespace RAH2_NS return counter; } + template + constexpr RAH2_NS::iter_difference_t + impl_n(I first_w, N len, T const& value, Proj proj) const + { + auto first_last = details::unwrap_begin(RAH2_STD::move(first_w)); + auto first = RAH2_STD::move(first_last.iterator); + RAH2_NS::iter_difference_t counter = 0; + RAH2_FOR_N(len, { + if (RAH2_INVOKE_1(proj, *first) == value) + ++counter; + ++first; + }); + return counter; + } + + template + constexpr RAH2_NS::iter_difference_t impl(I first_w, S last_w, T const& value) const + { + auto first_last = + details::unwrap(RAH2_STD::move(first_w), RAH2_STD::move(last_w)); + auto first = RAH2_STD::move(first_last.iterator); + auto last = RAH2_STD::move(first_last.sentinel); + RAH2_NS::iter_difference_t counter = 0; + for (; first != last; ++first) + counter += (*first == value); + return counter; + } + + template + constexpr RAH2_NS::iter_difference_t impl_n(I first_w, N len, T const& value) const + { + auto first_last = details::unwrap_begin(RAH2_STD::move(first_w)); + auto first = RAH2_STD::move(first_last.iterator); + RAH2_NS::iter_difference_t counter = 0; + RAH2_FOR_N(len, { + counter += (*first == value); + ++first; + }); + return counter; + } + + template < + typename I, + typename S, + class T, + class Proj = RAH2_NS::details::identity, + RAH2_STD::enable_if_t< + input_iterator && sentinel_for && !sized_sentinel_for>* = nullptr> + constexpr RAH2_NS::iter_difference_t + operator()(I first_w, S last_w, T const& value, Proj proj) const + { + return impl(first_w, last_w, value, proj); + } + + template < + typename I, + typename S, + class T, + class Proj = RAH2_NS::details::identity, + RAH2_STD::enable_if_t && sized_sentinel_for>* = nullptr> + constexpr RAH2_NS::iter_difference_t + operator()(I first_w, S last_w, T const& value, Proj proj) const + { + return impl_n(first_w, RAH2_NS::ranges::distance(first_w, last_w), value, proj); + } + template < typename R, class T, class Proj = RAH2_NS::details::identity, - RAH2_STD::enable_if_t>* = nullptr> + RAH2_STD::enable_if_t && sized_range>* = nullptr> constexpr range_difference_t operator()(R&& r, T const& value, Proj proj) const { - return (*this)( - RAH2_NS::ranges::begin(r), - RAH2_NS::ranges::end(r), - value, - RAH2_STD::move(proj)); + return impl_n(RAH2_NS::ranges::begin(r), RAH2_NS::ranges::size(r), value, proj); + } + template < + typename R, + class T, + class Proj = RAH2_NS::details::identity, + RAH2_STD::enable_if_t && !sized_range>* = nullptr> + constexpr range_difference_t operator()(R&& r, T const& value, Proj proj) const + { + return impl(RAH2_NS::ranges::begin(r), RAH2_NS::ranges::end(r), value, proj); } template < typename I, typename S, class T, - RAH2_STD::enable_if_t && sentinel_for>* = nullptr> + RAH2_STD::enable_if_t< + input_iterator && sentinel_for && !sized_sentinel_for>* = nullptr> constexpr RAH2_NS::iter_difference_t operator()(I first_w, S last_w, T const& value) const { - auto first_last = - details::unwrap(RAH2_STD::move(first_w), RAH2_STD::move(last_w)); - auto first = RAH2_STD::move(first_last.iterator); - auto last = RAH2_STD::move(first_last.sentinel); - RAH2_NS::iter_difference_t counter = 0; - for (; first != last; ++first) - if (*first == value) - ++counter; - return counter; + return impl(first_w, last_w, value); } - template >* = nullptr> + template < + typename I, + typename S, + class T, + RAH2_STD::enable_if_t && sized_sentinel_for>* = nullptr> + constexpr RAH2_NS::iter_difference_t + operator()(I first_w, S last_w, T const& value) const + { + return impl_n(first_w, RAH2_NS::ranges::distance(first_w, last_w), value); + } + + template && sized_range>* = nullptr> constexpr range_difference_t operator()(R&& r, T const& value) const { - return (*this)(RAH2_NS::ranges::begin(r), RAH2_NS::ranges::end(r), value); + return impl_n(RAH2_NS::ranges::begin(r), RAH2_NS::ranges::size(r), value); + } + template && !sized_range>* = nullptr> + constexpr range_difference_t operator()(R&& r, T const& value) const + { + return impl(RAH2_NS::ranges::begin(r), RAH2_NS::ranges::end(r), value); } }; } // namespace niebloids From d63b863081a23768ada45ec752e24186cd6c2cc6 Mon Sep 17 00:00:00 2001 From: lhamot Date: Thu, 27 Mar 2025 10:39:44 +0100 Subject: [PATCH 06/17] Optimize move_backward --- includes/rah2/base_algorithm.hpp | 82 ++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 19 deletions(-) diff --git a/includes/rah2/base_algorithm.hpp b/includes/rah2/base_algorithm.hpp index 786418b..9c67fb4 100644 --- a/includes/rah2/base_algorithm.hpp +++ b/includes/rah2/base_algorithm.hpp @@ -1193,38 +1193,86 @@ namespace RAH2_NS { struct move_backward_fn { + template < + typename It, + typename Sent, + std::enable_if_t>* = nullptr> + static auto advance_and_count(It& it, Sent sent) + { + auto dist = std::ranges::distance(it, sent); + std::ranges::advance(it, sent); + return dist; + } - RAH2_EXT_WARNING_PUSH + template < + typename It, + typename Sent, + std::enable_if_t>* = nullptr> + static auto advance_and_count(It& it, Sent sent) + { + std::iter_difference_t dist = 0; + while (it != sent) + { + ++it; + ++dist; + } + return dist; + } -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic ignored "-Wstringop-overflow" -#endif template < typename I1, typename S1, typename I2, RAH2_STD::enable_if_t and RAH2_NS::contiguous_iterator - and RAH2_NS::contiguous_iterator - and RAH2_STD::is_trivially_copyable>::value + RAH2_NS::contiguous_iterator and RAH2_NS::contiguous_iterator + and RAH2_STD::is_trivially_move_assignable>::value and RAH2_NS::is_same_v, RAH2_NS::iter_value_t>)>* = nullptr> constexpr move_backward_result impl(I1 first, S1 last, I2 result) const { - I1 const last1{RAH2_NS::ranges::next(first, RAH2_STD::move(last))}; - for (I1 i{last1}; i != first;) + I1 last1 = first; + size_t const item_count = advance_and_count(last1, last); + I1 i = last1; + for (auto u = item_count / 4; u != 0; --u) + { + *--result = RAH2_MOV(*--i); + *--result = RAH2_MOV(*--i); + *--result = RAH2_MOV(*--i); *--result = RAH2_MOV(*--i); + } + for (auto u = item_count % 4; u != 0; --u) + { + *--result = RAH2_MOV(*--i); + } return {RAH2_STD::move(last1), RAH2_STD::move(result)}; } + template < + typename I1, + typename S1, + typename I2, + RAH2_STD::enable_if_t< + not(RAH2_NS::sized_sentinel_for) + and (RAH2_NS::contiguous_iterator and RAH2_NS::contiguous_iterator and RAH2_STD::is_trivially_move_assignable>::value and RAH2_NS::is_same_v, RAH2_NS::iter_value_t>)>* = + nullptr> + constexpr move_backward_result impl(I1 first, S1 last, I2 result) const + { + I1 last1 = first; + size_t const item_count = advance_and_count(last1, last); + memmove( + &(*(result - item_count)), + &(*first), + item_count * sizeof(RAH2_NS::iter_value_t)); + return {last1, result - item_count}; + } + template < typename I1, typename S1, typename I2, RAH2_STD::enable_if_t<( - RAH2_NS::sized_sentinel_for and RAH2_NS::contiguous_iterator - and RAH2_NS::contiguous_iterator - and RAH2_STD::is_trivially_copyable>::value - and RAH2_NS::is_same_v, RAH2_NS::iter_value_t>)>* = nullptr> + RAH2_NS::sized_sentinel_for + and (RAH2_NS::contiguous_iterator and RAH2_NS::contiguous_iterator and RAH2_STD::is_trivially_move_assignable>::value and RAH2_NS::is_same_v, RAH2_NS::iter_value_t>))>* = + nullptr> constexpr move_backward_result impl(I1 first, S1 last, I2 result) const { auto const item_count = RAH2_NS::ranges::distance(first, last); @@ -1256,15 +1304,11 @@ namespace RAH2_NS unwraped_out.wrap_iterator(RAH2_STD::move(ret.out))}; } - RAH2_EXT_WARNING_POP - template < typename R, typename I, - RAH2_STD::enable_if_t< - RAH2_NS::ranges::bidirectional_range && RAH2_NS::bidirectional_iterator>* = nullptr> - constexpr RAH2_NS::ranges::move_backward_result, I> - operator()(R&& r, I result) const + RAH2_STD::enable_if_t && bidirectional_iterator>* = nullptr> + constexpr move_backward_result, I> operator()(R&& r, I result) const { return (*this)( RAH2_NS::ranges::begin(r), RAH2_NS::ranges::end(r), RAH2_STD::move(result)); From f2102a02057842872df6d678edc8d149fc78bf5e Mon Sep 17 00:00:00 2001 From: lhamot Date: Mon, 31 Mar 2025 14:03:18 +0200 Subject: [PATCH 07/17] Optimize partition point --- includes/rah2/algorithm.hpp | 62 ++++++++++++++++++++++++++----------- test/test_algo4.cpp | 26 ++++++++++++---- 2 files changed, 64 insertions(+), 24 deletions(-) diff --git a/includes/rah2/algorithm.hpp b/includes/rah2/algorithm.hpp index 1e37bab..64730d4 100644 --- a/includes/rah2/algorithm.hpp +++ b/includes/rah2/algorithm.hpp @@ -1410,25 +1410,18 @@ namespace RAH2_NS { struct partition_point_fn { - template < - typename ForwardIt, - typename Sentinel, - typename UnaryPredicate, - typename Proj = RAH2_NS::details::identity, - RAH2_STD::enable_if_t>* = nullptr> - constexpr ForwardIt - operator()(ForwardIt first, Sentinel last, UnaryPredicate pred, Proj proj = {}) const + template + inline constexpr ForwardIt impl(ForwardIt first, N length, UnaryPredicate pred) const { - auto pred_proj = - details::wrap_pred_proj(RAH2_STD::move(pred), RAH2_STD::move(proj)); - - for (auto length = RAH2_NS::ranges::distance(first, last); 0 < length;) + while (length > 0) { - auto half = length / 2; - auto middle = RAH2_STD::next(first, half); - if (pred_proj(*middle)) + auto const half = length / 2; + auto middle = first; + RAH2_NS::ranges::advance(middle, half); + if (pred(*middle)) { - first = RAH2_STD::next(middle); + first = middle; + ++first; length -= (half + 1); } else @@ -1438,12 +1431,29 @@ namespace RAH2_NS return first; } + template < + typename ForwardIt, + typename Sentinel, + typename UnaryPredicate, + typename Proj = RAH2_NS::details::identity, + RAH2_STD::enable_if_t>* = nullptr> + inline constexpr ForwardIt + operator()(ForwardIt first, Sentinel last, UnaryPredicate pred, Proj proj = {}) const + { + auto pred_proj = + details::wrap_pred_proj(RAH2_STD::move(pred), RAH2_STD::move(proj)); + auto length = RAH2_NS::ranges::distance(first, last); + return impl(RAH2_STD::move(first), length, RAH2_STD::move(pred_proj)); + } + template < typename ForwardRange, typename UnaryPredicate, typename Proj = RAH2_NS::details::identity, - RAH2_STD::enable_if_t>* = nullptr> - constexpr borrowed_iterator_t + RAH2_STD::enable_if_t< + RAH2_NS::ranges::range + && !RAH2_NS::ranges::sized_range>* = nullptr> + inline constexpr borrowed_iterator_t operator()(ForwardRange&& range, UnaryPredicate pred, Proj proj = {}) const { return (*this)( @@ -1452,6 +1462,22 @@ namespace RAH2_NS RAH2_STD::move(pred), RAH2_STD::move(proj)); } + + template < + typename ForwardRange, + typename UnaryPredicate, + typename Proj = RAH2_NS::details::identity, + RAH2_STD::enable_if_t< + RAH2_NS::ranges::range + && RAH2_NS::ranges::sized_range>* = nullptr> + inline constexpr borrowed_iterator_t + operator()(ForwardRange&& range, UnaryPredicate pred, Proj proj = {}) const + { + auto pred_proj = + details::wrap_pred_proj(RAH2_STD::move(pred), RAH2_STD::move(proj)); + auto length = RAH2_NS::ranges::size(range); + return impl(RAH2_NS::ranges::begin(range), length, RAH2_STD::move(pred_proj)); + } }; } // namespace niebloids diff --git a/test/test_algo4.cpp b/test/test_algo4.cpp index 2667992..e898da1 100644 --- a/test/test_algo4.cpp +++ b/test/test_algo4.cpp @@ -1681,12 +1681,26 @@ struct test_partition_point_ template void test_perf(char const* range_type) { - size_t PerfMultiplier = - (RAH2_NS::derived_from && Sized) ? 100llu : - 10llu; + auto const IterSized = + (CS == Common && RAH2_NS::derived_from) + || (CS == Sentinel && Sized); + +#ifdef _DEBUG + auto const IterSizedMultiplier = + IterSized && RAH2_NS::derived_from ? + 1000 * RELEASE_MULTIPLIER : + 1; + auto const RangeSizedMultiplier = + Sized && RAH2_NS::derived_from ? + 1000 * RELEASE_MULTIPLIER : + 1; +#else + auto const IterSizedMultiplier = IterSized ? 1000 * RELEASE_MULTIPLIER : 1; + auto const RangeSizedMultiplier = Sized ? 1000 * RELEASE_MULTIPLIER : 1; +#endif testSuite.test_case("perf"); - RAH2_STD::vector in(10000000llu * RELEASE_MULTIPLIER, Coord{1, 2}); + RAH2_STD::vector in(1000000llu * RELEASE_MULTIPLIER, Coord{1, 2}); in.push_back(Coord{3, 4}); auto r1 = make_test_view_adapter(in); @@ -1696,7 +1710,7 @@ struct test_partition_point_ range_type, [&] { - for (size_t i = 0; i < PerfMultiplier; ++i) + for (int i = 0; i < IterSizedMultiplier; ++i) { auto iter = STD::partition_point( fwd(r1.begin()), r1.end(), [](auto c) { return c.x < 3; }); @@ -1708,7 +1722,7 @@ struct test_partition_point_ range_type, [&] { - for (size_t i = 0; i < PerfMultiplier; ++i) + for (int i = 0; i < RangeSizedMultiplier; ++i) { auto iter = STD::partition_point(r1, [](int64_t c) { return c < 3; }, &Coord::x); assert((*iter == Coord{3, 4})); From 733aec8739fc903df446c24b38c7f17127bed353 Mon Sep 17 00:00:00 2001 From: lhamot Date: Mon, 31 Mar 2025 15:37:14 +0200 Subject: [PATCH 08/17] Optimize rotate --- includes/rah2/base_algorithm.hpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/includes/rah2/base_algorithm.hpp b/includes/rah2/base_algorithm.hpp index 9c67fb4..dc6b75f 100644 --- a/includes/rah2/base_algorithm.hpp +++ b/includes/rah2/base_algorithm.hpp @@ -1196,11 +1196,11 @@ namespace RAH2_NS template < typename It, typename Sent, - std::enable_if_t>* = nullptr> + RAH2_STD::enable_if_t>* = nullptr> static auto advance_and_count(It& it, Sent sent) { - auto dist = std::ranges::distance(it, sent); - std::ranges::advance(it, sent); + auto dist = RAH2_NS::ranges::distance(it, sent); + RAH2_NS::ranges::advance(it, sent); return dist; } @@ -1210,7 +1210,7 @@ namespace RAH2_NS std::enable_if_t>* = nullptr> static auto advance_and_count(It& it, Sent sent) { - std::iter_difference_t dist = 0; + RAH2_NS::iter_difference_t dist = 0; while (it != sent) { ++it; @@ -5925,7 +5925,7 @@ namespace RAH2_NS { template subrange - operator()(ForwardIterator first, ForwardIterator middle, ForwardSentinel last) const + impl(ForwardIterator first, ForwardIterator middle, ForwardSentinel last) const { if (middle != first) { @@ -5966,6 +5966,21 @@ namespace RAH2_NS return {last_it, last_it}; } + template + subrange + operator()(ForwardIterator first, ForwardIterator middle, ForwardSentinel last) const + { + auto last2 = RAH2_NS::ranges::next(first, last); + auto middle_u = details::unwrap(RAH2_STD::move(middle), last2); + auto first_last = details::unwrap(RAH2_STD::move(first), RAH2_STD::move(last2)); + auto res = impl( + RAH2_MOV(first_last.iterator), + RAH2_MOV(middle_u.iterator), + RAH2_MOV(first_last.sentinel)); + return { + first_last.wrap_iterator(res.begin()), first_last.wrap_iterator(res.end())}; + } + template borrowed_subrange_t operator()(ForwardRange&& range, iterator_t middle) const From 9cdc4ce361f152069afa08a5a45fbba9a78cb26f Mon Sep 17 00:00:00 2001 From: lhamot Date: Tue, 1 Apr 2025 13:40:26 +0200 Subject: [PATCH 09/17] Optimize sample --- includes/rah2/algorithm.hpp | 105 +++++++++++++++++++++++++------ includes/rah2/base_algorithm.hpp | 56 ++++++++--------- test/test_algo4.cpp | 46 +++++++++++--- 3 files changed, 151 insertions(+), 56 deletions(-) diff --git a/includes/rah2/algorithm.hpp b/includes/rah2/algorithm.hpp index 64730d4..8ab0834 100644 --- a/includes/rah2/algorithm.hpp +++ b/includes/rah2/algorithm.hpp @@ -1102,10 +1102,10 @@ namespace RAH2_NS S last, RAH2_NS::iter_difference_t input_size, O out, - RAH2_NS::iter_difference_t n, + RAH2_NS::iter_difference_t output_size, Gen&& gen) const { - if (n == 0 or input_size == 0) + if (output_size == 0 or input_size == 0) { return out; } @@ -1116,7 +1116,7 @@ namespace RAH2_NS auto out_iter = details::unwrap_begin(RAH2_STD::move(out)); auto out2 = out_iter.iterator; - n = std::min(n, input_size); + auto n = std::min(output_size, input_size); for (; input_size > 0; ++first2, (void)--input_size) { uniform_int_distrib distrib( @@ -1132,7 +1132,13 @@ namespace RAH2_NS return out_iter.wrap_iterator(RAH2_STD::move(out2)); } - template + template < + typename DistibType, + typename I, + typename S, + typename O, + class Gen, + std::enable_if_t>* = nullptr> inline constexpr O sample_unsized_impl( I first, S last, O out, RAH2_NS::iter_difference_t n, Gen&& gen) const { @@ -1165,13 +1171,37 @@ namespace RAH2_NS return out + sample_size; } + template < + typename DistibType, + typename I, + typename S, + typename O, + class Gen, + std::enable_if_t && RAH2_NS::forward_iterator>* = nullptr> + inline constexpr O sample_unsized_impl( + I first, S last, O out, RAH2_NS::iter_difference_t n, Gen&& gen) const + { + auto last1 = first; + auto const input_size = details::advance_and_count(last1, last); + if (input_size < std::numeric_limits::max()) + { + return this->sample_sized_impl( + first, RAH2_MOV(last1), input_size, RAH2_MOV(out), n, RAH2_MOV(gen)); + } + else + { + return this->sample_sized_impl( + first, RAH2_MOV(last1), input_size, RAH2_MOV(out), n, RAH2_MOV(gen)); + } + } + template < typename I, typename S, typename O, class Gen, RAH2_STD::enable_if_t || RAH2_NS::sized_sentinel_for)>* = nullptr> + RAH2_NS::sized_sentinel_for && !RAH2_NS::random_access_iterator)>* = nullptr> inline constexpr O operator()(I first, S last, O out, RAH2_NS::iter_difference_t n, Gen&& gen) const { @@ -1193,37 +1223,72 @@ namespace RAH2_NS typename O, class Gen, RAH2_STD::enable_if_t< - RAH2_NS::forward_iterator || RAH2_NS::sized_sentinel_for>* = nullptr> + RAH2_NS::sized_sentinel_for && !RAH2_NS::random_access_iterator>* = nullptr> inline constexpr O operator()(I first, S last, O out, RAH2_NS::iter_difference_t n, Gen&& gen) const { - auto input_size = RAH2_NS::ranges::distance(first, last); - return this->sample_sized_impl( - RAH2_MOV(first), RAH2_MOV(last), input_size, RAH2_MOV(out), n, RAH2_MOV(gen)); + auto last1 = first; + size_t const input_size = details::advance_and_count(last1, last); + if (input_size < std::numeric_limits::max()) + { + return this->sample_sized_impl( + RAH2_MOV(first), + RAH2_MOV(last1), + input_size, + RAH2_MOV(out), + n, + RAH2_FWD(gen)); + } + else + { + return this->sample_sized_impl( + RAH2_MOV(first), + RAH2_MOV(last1), + input_size, + RAH2_MOV(out), + n, + RAH2_FWD(gen)); + } } template < typename R, typename O, class Gen, - RAH2_STD::enable_if_t>* = nullptr> + RAH2_STD::enable_if_t< + RAH2_NS::ranges::sized_range && !RAH2_NS::random_access_iterator>* = nullptr> inline constexpr O operator()(R&& r, O out, range_difference_t n, Gen&& gen) const { - auto input_size = RAH2_NS::ranges::size(r); - return this->sample_sized_impl( - RAH2_NS::ranges::begin(r), - RAH2_NS::ranges::end(r), - input_size, - RAH2_MOV(out), - n, - RAH2_MOV(gen)); + auto const input_size = RAH2_NS::ranges::size(r); + auto const last1 = RAH2_NS::ranges::next(RAH2_NS::ranges::begin(r), input_size); + if (input_size < std::numeric_limits::max()) + { + return this->sample_sized_impl( + RAH2_NS::ranges::begin(r), + RAH2_MOV(last1), + input_size, + RAH2_MOV(out), + n, + RAH2_FWD(gen)); + } + else + { + return this->sample_sized_impl( + RAH2_NS::ranges::begin(r), + RAH2_MOV(last1), + input_size, + RAH2_MOV(out), + n, + RAH2_FWD(gen)); + } } template < typename R, typename O, class Gen, - RAH2_STD::enable_if_t>* = nullptr> + RAH2_STD::enable_if_t && !RAH2_NS::random_access_iterator)>* = nullptr> inline constexpr O operator()(R&& r, O out, range_difference_t n, Gen&& gen) const { return (*this)( @@ -1231,7 +1296,7 @@ namespace RAH2_NS RAH2_NS::ranges::end(r), RAH2_MOV(out), n, - RAH2_MOV(gen)); + RAH2_FWD(gen)); } }; } // namespace niebloids diff --git a/includes/rah2/base_algorithm.hpp b/includes/rah2/base_algorithm.hpp index dc6b75f..cbf315d 100644 --- a/includes/rah2/base_algorithm.hpp +++ b/includes/rah2/base_algorithm.hpp @@ -1186,6 +1186,32 @@ namespace RAH2_NS /// constexpr niebloids::copy_n_fn copy_n{}; + namespace details + { + template < + typename It, + typename Sent, + RAH2_STD::enable_if_t>* = nullptr> + static auto advance_and_count(It& it, Sent sent) + { + auto dist = RAH2_NS::ranges::distance(it, sent); + RAH2_NS::ranges::advance(it, sent); + return dist; + } + + template >* = nullptr> + static auto advance_and_count(It& it, Sent sent) + { + RAH2_NS::iter_difference_t dist = 0; + while (it != sent) + { + ++it; + ++dist; + } + return dist; + } + } // namespace details + template using move_backward_result = RAH2_NS::ranges::in_out_result; @@ -1193,32 +1219,6 @@ namespace RAH2_NS { struct move_backward_fn { - template < - typename It, - typename Sent, - RAH2_STD::enable_if_t>* = nullptr> - static auto advance_and_count(It& it, Sent sent) - { - auto dist = RAH2_NS::ranges::distance(it, sent); - RAH2_NS::ranges::advance(it, sent); - return dist; - } - - template < - typename It, - typename Sent, - std::enable_if_t>* = nullptr> - static auto advance_and_count(It& it, Sent sent) - { - RAH2_NS::iter_difference_t dist = 0; - while (it != sent) - { - ++it; - ++dist; - } - return dist; - } - template < typename I1, typename S1, @@ -1230,7 +1230,7 @@ namespace RAH2_NS constexpr move_backward_result impl(I1 first, S1 last, I2 result) const { I1 last1 = first; - size_t const item_count = advance_and_count(last1, last); + size_t const item_count = details::advance_and_count(last1, last); I1 i = last1; for (auto u = item_count / 4; u != 0; --u) { @@ -1257,7 +1257,7 @@ namespace RAH2_NS constexpr move_backward_result impl(I1 first, S1 last, I2 result) const { I1 last1 = first; - size_t const item_count = advance_and_count(last1, last); + size_t const item_count = details::advance_and_count(last1, last); memmove( &(*(result - item_count)), &(*first), diff --git a/test/test_algo4.cpp b/test/test_algo4.cpp index e898da1..1a112f9 100644 --- a/test/test_algo4.cpp +++ b/test/test_algo4.cpp @@ -565,6 +565,11 @@ void test_shift_right() template struct test_sample_ { + using OutTag = std::conditional< + RAH2_NS::derived_from, + Tag, + RAH2_NS::random_access_iterator_tag>::type; + template void test() { @@ -621,10 +626,11 @@ struct test_sample_ in_.push_back(i % 15); } auto in = make_test_view_adapter(in_); - RAH2_STD::vector out; - out.resize(1000000 * RELEASE_MULTIPLIER); - out.emplace_back(); - out.emplace_back(); + RAH2_STD::vector out_; + out_.resize(1000000 * RELEASE_MULTIPLIER); + out_.emplace_back(); + out_.emplace_back(); + auto out = make_test_view_adapter(out_); COMPARE_DURATION_TO_STD_ALGO_17_AND_RANGES( CS == Common, @@ -640,6 +646,20 @@ struct test_sample_ g); DONT_OPTIM(result); }); + COMPARE_DURATION_TO_STD_ALGO_17_AND_RANGES( + CS == Common, + "sample_iter_smallout", + range_type, + [&] + { + auto result = STD::sample( + fwd(RAH2_NS::ranges::begin(in)), + RAH2_NS::ranges::end(in), + out.begin(), + 100 * RELEASE_MULTIPLIER, + g); + DONT_OPTIM(result); + }); } #endif @@ -651,10 +671,11 @@ struct test_sample_ } auto in2 = make_test_view_adapter(in2_); - RAH2_STD::vector out2; - out2.resize(1000000 * RELEASE_MULTIPLIER); - out2.emplace_back(); - out2.emplace_back(); + RAH2_STD::vector out2_; + out2_.resize(1000000 * RELEASE_MULTIPLIER); + out2_.emplace_back(); + out2_.emplace_back(); + auto out2 = make_test_view_adapter(out2_); COMPARE_DURATION_TO_STD_RANGES( "sample_range", @@ -666,6 +687,15 @@ struct test_sample_ STD::sample(in2, out2.begin(), 1000000 * RELEASE_MULTIPLIER, g); DONT_OPTIM(result2); })); + COMPARE_DURATION_TO_STD_RANGES( + "sample_range_smallout", + range_type, + ( + [&] + { + auto result2 = STD::sample(in2, out2.begin(), 100 * RELEASE_MULTIPLIER, g); + DONT_OPTIM(result2); + })); } } static constexpr bool do_test = true; From 2e8aed8fbb94783c4e85a87921035cfca57b03bc Mon Sep 17 00:00:00 2001 From: lhamot Date: Tue, 1 Apr 2025 13:50:58 +0200 Subject: [PATCH 10/17] Rename some std:: into RAH2_STD --- includes/rah2/algorithm.hpp | 26 ++++++++++++++------------ includes/rah2/base_algorithm.hpp | 17 ++++++++++------- includes/rah2/ranges.hpp | 4 ++-- test/TestSuite.hpp | 2 +- test/test_algo3.cpp | 4 ++-- test/test_helpers.hpp | 4 ++-- 6 files changed, 31 insertions(+), 26 deletions(-) diff --git a/includes/rah2/algorithm.hpp b/includes/rah2/algorithm.hpp index 8ab0834..0fc2677 100644 --- a/includes/rah2/algorithm.hpp +++ b/includes/rah2/algorithm.hpp @@ -1116,7 +1116,7 @@ namespace RAH2_NS auto out_iter = details::unwrap_begin(RAH2_STD::move(out)); auto out2 = out_iter.iterator; - auto n = std::min(output_size, input_size); + auto n = RAH2_STD::min(output_size, input_size); for (; input_size > 0; ++first2, (void)--input_size) { uniform_int_distrib distrib( @@ -1138,7 +1138,7 @@ namespace RAH2_NS typename S, typename O, class Gen, - std::enable_if_t>* = nullptr> + RAH2_STD::enable_if_t>* = nullptr> inline constexpr O sample_unsized_impl( I first, S last, O out, RAH2_NS::iter_difference_t n, Gen&& gen) const { @@ -1177,13 +1177,14 @@ namespace RAH2_NS typename S, typename O, class Gen, - std::enable_if_t && RAH2_NS::forward_iterator>* = nullptr> + RAH2_STD::enable_if_t< + !RAH2_NS::random_access_iterator && RAH2_NS::forward_iterator>* = nullptr> inline constexpr O sample_unsized_impl( I first, S last, O out, RAH2_NS::iter_difference_t n, Gen&& gen) const { auto last1 = first; auto const input_size = details::advance_and_count(last1, last); - if (input_size < std::numeric_limits::max()) + if (input_size < RAH2_STD::numeric_limits::max()) { return this->sample_sized_impl( first, RAH2_MOV(last1), input_size, RAH2_MOV(out), n, RAH2_MOV(gen)); @@ -1229,7 +1230,7 @@ namespace RAH2_NS { auto last1 = first; size_t const input_size = details::advance_and_count(last1, last); - if (input_size < std::numeric_limits::max()) + if (input_size < RAH2_STD::numeric_limits::max()) { return this->sample_sized_impl( RAH2_MOV(first), @@ -1261,7 +1262,7 @@ namespace RAH2_NS { auto const input_size = RAH2_NS::ranges::size(r); auto const last1 = RAH2_NS::ranges::next(RAH2_NS::ranges::begin(r), input_size); - if (input_size < std::numeric_limits::max()) + if (input_size < RAH2_STD::numeric_limits::max()) { return this->sample_sized_impl( RAH2_NS::ranges::begin(r), @@ -1944,9 +1945,9 @@ namespace RAH2_NS { V new_val(*first); if (pred_proj(new_val, result.min)) - result.min = std::move(new_val); + result.min = RAH2_MOV(new_val); else if (pred_proj(result.max, new_val)) - result.max = std::move(new_val); + result.max = RAH2_MOV(new_val); } return result; } @@ -2765,7 +2766,8 @@ namespace RAH2_NS typename RandomAccessIterator, typename Sentinel, typename UniformRandomNumberGenerator, - std::enable_if_t>* = nullptr> + RAH2_STD::enable_if_t< + not RAH2_NS::sized_sentinel_for>* = nullptr> void operator()( RandomAccessIterator first, Sentinel last, UniformRandomNumberGenerator&& urng) const { @@ -2775,7 +2777,7 @@ namespace RAH2_NS typename RandomAccessIterator, typename Sentinel, typename UniformRandomNumberGenerator, - std::enable_if_t>* = nullptr> + RAH2_STD::enable_if_t>* = nullptr> void operator()( RandomAccessIterator first, Sentinel last, UniformRandomNumberGenerator&& urng) const { @@ -2786,7 +2788,7 @@ namespace RAH2_NS template < typename RandomRange, typename UniformRandomNumberGenerator, - std::enable_if_t>* = nullptr> + RAH2_STD::enable_if_t>* = nullptr> void operator()(RandomRange&& range, UniformRandomNumberGenerator&& urng) const { dispatch_n( @@ -2795,7 +2797,7 @@ namespace RAH2_NS template < typename RandomRange, typename UniformRandomNumberGenerator, - std::enable_if_t>* = nullptr> + RAH2_STD::enable_if_t>* = nullptr> void operator()(RandomRange&& range, UniformRandomNumberGenerator&& urng) const { (*this)( diff --git a/includes/rah2/base_algorithm.hpp b/includes/rah2/base_algorithm.hpp index cbf315d..035b8a6 100644 --- a/includes/rah2/base_algorithm.hpp +++ b/includes/rah2/base_algorithm.hpp @@ -137,7 +137,7 @@ namespace RAH2_NS RAH2_STD::enable_if_t && RAH2_NS::contiguous_iterator && RAH2_NS::is_same_v, RAH2_NS::iter_value_t> - and std::is_trivially_move_assignable>::value)>* = nullptr> + and RAH2_STD::is_trivially_move_assignable>::value)>* = nullptr> constexpr RAH2_NS::ranges::move_result impl_n(I first, N len, O result) const { RAH2_FOR_N(len, { @@ -154,7 +154,7 @@ namespace RAH2_NS RAH2_STD::enable_if_t< RAH2_NS::contiguous_iterator && RAH2_NS::contiguous_iterator && RAH2_NS::is_same_v, RAH2_NS::iter_value_t> - and std::is_trivially_move_assignable>::value>* = nullptr> + and RAH2_STD::is_trivially_move_assignable>::value>* = nullptr> constexpr RAH2_NS::ranges::move_result impl_n(I first, N len, O result) const { memcpy(&(*result), &(*first), len * sizeof(RAH2_NS::iter_value_t)); @@ -1199,7 +1199,10 @@ namespace RAH2_NS return dist; } - template >* = nullptr> + template < + typename It, + typename Sent, + RAH2_STD::enable_if_t>* = nullptr> static auto advance_and_count(It& it, Sent sent) { RAH2_NS::iter_difference_t dist = 0; @@ -2228,7 +2231,7 @@ namespace RAH2_NS typename O, typename S, typename F, - std::enable_if_t>* = nullptr> + RAH2_STD::enable_if_t>* = nullptr> constexpr O operator()(O first, S last, F&& gen) const { return generate_n(first, RAH2_NS::ranges::distance(first, last), RAH2_FWD(gen)); @@ -2238,7 +2241,7 @@ namespace RAH2_NS typename O, typename S, typename F, - std::enable_if_t>* = nullptr> + RAH2_STD::enable_if_t>* = nullptr> constexpr O operator()(O first, S last, F&& gen) const { for (; first != last; ++first) @@ -2248,13 +2251,13 @@ namespace RAH2_NS return first; } - template >* = nullptr> + template >* = nullptr> constexpr borrowed_iterator_t operator()(R&& r, F&& gen) const { return (*this)(RAH2_NS::ranges::begin(r), RAH2_NS::ranges::end(r), RAH2_FWD(gen)); } - template >* = nullptr> + template >* = nullptr> constexpr borrowed_iterator_t operator()(R&& r, F&& gen) const { return generate_n( diff --git a/includes/rah2/ranges.hpp b/includes/rah2/ranges.hpp index 7d7bd5f..6960456 100644 --- a/includes/rah2/ranges.hpp +++ b/includes/rah2/ranges.hpp @@ -914,7 +914,7 @@ namespace RAH2_NS { return range_.begin(); } - template >* = nullptr> + template >* = nullptr> auto begin() const { return range_.begin(); @@ -923,7 +923,7 @@ namespace RAH2_NS { return range_.end(); } - template >* = nullptr> + template >* = nullptr> auto end() const { return range_.end(); diff --git a/test/TestSuite.hpp b/test/TestSuite.hpp index 329f32e..1b85629 100644 --- a/test/TestSuite.hpp +++ b/test/TestSuite.hpp @@ -42,7 +42,7 @@ struct TestSuite void addTest(RAH2_STD::string const& group, RAH2_STD::string const& name, std::function test) { - testMap.emplace(group + " - " + name, std::move(test)); + testMap.emplace(group + " - " + name, RAH2_MOV(test)); } char const* currentTest = nullptr; diff --git a/test/test_algo3.cpp b/test/test_algo3.cpp index ddea29b..e24b842 100644 --- a/test/test_algo3.cpp +++ b/test/test_algo3.cpp @@ -175,13 +175,13 @@ struct test_search_ assert(RAH2_STD::distance(haystack.begin(), found5.end()) == 4); } - template >>* = nullptr> + template >>* = nullptr> static auto get_begin(I&& i) -> decltype(std::forward(i)) { return std::forward(i); } - template >>* = nullptr> + template >>* = nullptr> static auto get_begin(I&& i) -> decltype(i.begin()) { return i.begin(); diff --git a/test/test_helpers.hpp b/test/test_helpers.hpp index 79493a6..4f4dd78 100644 --- a/test/test_helpers.hpp +++ b/test/test_helpers.hpp @@ -459,7 +459,7 @@ class test_view_adapter test_view_adapter() = default; explicit test_view_adapter(Range r) - : base_(std::move(r)) + : base_(RAH2_MOV(r)) { } @@ -797,7 +797,7 @@ struct check_size } static intptr_t get_stop_iter() { - return std::numeric_limits::max(); + return RAH2_STD::numeric_limits::max(); } }; From 79657f738b1acfab4132501352288db0dbeb55e6 Mon Sep 17 00:00:00 2001 From: lhamot Date: Tue, 1 Apr 2025 13:53:39 +0200 Subject: [PATCH 11/17] Add missing "typename" --- test/test_algo4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_algo4.cpp b/test/test_algo4.cpp index 1a112f9..d3dd8b5 100644 --- a/test/test_algo4.cpp +++ b/test/test_algo4.cpp @@ -565,7 +565,7 @@ void test_shift_right() template struct test_sample_ { - using OutTag = std::conditional< + using OutTag = typename RAH2_STD::conditional< RAH2_NS::derived_from, Tag, RAH2_NS::random_access_iterator_tag>::type; From 91ef72d84cc67b5d6abc397649f98d95605aefd4 Mon Sep 17 00:00:00 2001 From: lhamot Date: Wed, 2 Apr 2025 10:14:49 +0200 Subject: [PATCH 12/17] fix rotate --- includes/rah2/base_algorithm.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/includes/rah2/base_algorithm.hpp b/includes/rah2/base_algorithm.hpp index 035b8a6..97faf9e 100644 --- a/includes/rah2/base_algorithm.hpp +++ b/includes/rah2/base_algorithm.hpp @@ -5974,6 +5974,10 @@ namespace RAH2_NS operator()(ForwardIterator first, ForwardIterator middle, ForwardSentinel last) const { auto last2 = RAH2_NS::ranges::next(first, last); + if (middle == last) + { + return {first, last2}; + } auto middle_u = details::unwrap(RAH2_STD::move(middle), last2); auto first_last = details::unwrap(RAH2_STD::move(first), RAH2_STD::move(last2)); auto res = impl( From 829ca4186153162acd72c86c1accbfc4c06494e2 Mon Sep 17 00:00:00 2001 From: lhamot Date: Wed, 2 Apr 2025 11:10:44 +0200 Subject: [PATCH 13/17] fix cmake for eastl --- .github/workflows/cmake_eastl.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/cmake_eastl.yml b/.github/workflows/cmake_eastl.yml index f601ab5..4ce8f81 100644 --- a/.github/workflows/cmake_eastl.yml +++ b/.github/workflows/cmake_eastl.yml @@ -31,6 +31,10 @@ jobs: repository: electronicarts/EASTL path: eastl submodules: true + - name: Setup cmake + uses: jwlawson/actions-setup-cmake@v2 + with: + cmake-version: '3.31.x' - name: Configure CMake EASTL working-directory: ${{github.workspace}}/eastl run: cmake -B ${{github.workspace}}/eastl/build -DCMAKE_BUILD_TYPE=${{matrix.BUILD_TYPE}} -DCMAKE_CXX_STANDARD=${{matrix.cppstd}} -D CMAKE_C_COMPILER=${{matrix.compiler.c}} -D CMAKE_CXX_COMPILER=${{matrix.compiler.cpp}} From 4350ae6fb2c8cb545ae7d27ec39615c23126be66 Mon Sep 17 00:00:00 2001 From: lhamot Date: Wed, 2 Apr 2025 11:15:51 +0200 Subject: [PATCH 14/17] fix --- includes/rah2/base_algorithm.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/includes/rah2/base_algorithm.hpp b/includes/rah2/base_algorithm.hpp index 97faf9e..fc88eb2 100644 --- a/includes/rah2/base_algorithm.hpp +++ b/includes/rah2/base_algorithm.hpp @@ -154,7 +154,8 @@ namespace RAH2_NS RAH2_STD::enable_if_t< RAH2_NS::contiguous_iterator && RAH2_NS::contiguous_iterator && RAH2_NS::is_same_v, RAH2_NS::iter_value_t> - and RAH2_STD::is_trivially_move_assignable>::value>* = nullptr> + and RAH2_STD::is_trivially_move_assignable>::value + and RAH2_NS::is_trivially_copyable_v>>* = nullptr> constexpr RAH2_NS::ranges::move_result impl_n(I first, N len, O result) const { memcpy(&(*result), &(*first), len * sizeof(RAH2_NS::iter_value_t)); From 0aa9d939bf200990e3a521688081a09b7601f398 Mon Sep 17 00:00:00 2001 From: lhamot Date: Wed, 2 Apr 2025 11:20:01 +0200 Subject: [PATCH 15/17] fix --- includes/rah2/base_algorithm.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/includes/rah2/base_algorithm.hpp b/includes/rah2/base_algorithm.hpp index fc88eb2..751cdd0 100644 --- a/includes/rah2/base_algorithm.hpp +++ b/includes/rah2/base_algorithm.hpp @@ -137,7 +137,8 @@ namespace RAH2_NS RAH2_STD::enable_if_t && RAH2_NS::contiguous_iterator && RAH2_NS::is_same_v, RAH2_NS::iter_value_t> - and RAH2_STD::is_trivially_move_assignable>::value)>* = nullptr> + and RAH2_STD::is_trivially_move_assignable>::value + and RAH2_NS::is_trivially_copyable_v>)>* = nullptr> constexpr RAH2_NS::ranges::move_result impl_n(I first, N len, O result) const { RAH2_FOR_N(len, { From fe078f5fc9f74541e2323233a747c003bd666a65 Mon Sep 17 00:00:00 2001 From: lhamot Date: Wed, 2 Apr 2025 11:24:32 +0200 Subject: [PATCH 16/17] fix --- includes/rah2/base_algorithm.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/includes/rah2/base_algorithm.hpp b/includes/rah2/base_algorithm.hpp index 751cdd0..0f35dc6 100644 --- a/includes/rah2/base_algorithm.hpp +++ b/includes/rah2/base_algorithm.hpp @@ -1231,6 +1231,7 @@ namespace RAH2_NS RAH2_STD::enable_if_t and RAH2_NS::contiguous_iterator and RAH2_STD::is_trivially_move_assignable>::value + and RAH2_NS::is_trivially_copyable_v> and RAH2_NS::is_same_v, RAH2_NS::iter_value_t>)>* = nullptr> constexpr move_backward_result impl(I1 first, S1 last, I2 result) const { @@ -1257,7 +1258,7 @@ namespace RAH2_NS typename I2, RAH2_STD::enable_if_t< not(RAH2_NS::sized_sentinel_for) - and (RAH2_NS::contiguous_iterator and RAH2_NS::contiguous_iterator and RAH2_STD::is_trivially_move_assignable>::value and RAH2_NS::is_same_v, RAH2_NS::iter_value_t>)>* = + and (RAH2_NS::contiguous_iterator and RAH2_NS::contiguous_iterator and RAH2_NS::is_same_v, RAH2_NS::iter_value_t> and RAH2_STD::is_trivially_move_assignable>::value and RAH2_NS::is_trivially_copyable_v>)>* = nullptr> constexpr move_backward_result impl(I1 first, S1 last, I2 result) const { @@ -1276,7 +1277,7 @@ namespace RAH2_NS typename I2, RAH2_STD::enable_if_t<( RAH2_NS::sized_sentinel_for - and (RAH2_NS::contiguous_iterator and RAH2_NS::contiguous_iterator and RAH2_STD::is_trivially_move_assignable>::value and RAH2_NS::is_same_v, RAH2_NS::iter_value_t>))>* = + and (RAH2_NS::contiguous_iterator and RAH2_NS::contiguous_iterator and RAH2_STD::is_trivially_move_assignable>::value and RAH2_NS::is_trivially_copyable_v> and RAH2_NS::is_same_v, RAH2_NS::iter_value_t>))>* = nullptr> constexpr move_backward_result impl(I1 first, S1 last, I2 result) const { From 41176de150034a5d6623e964a2b482c60b5cf895 Mon Sep 17 00:00:00 2001 From: lhamot Date: Wed, 2 Apr 2025 12:36:07 +0200 Subject: [PATCH 17/17] Better coverage --- test/test_algo3.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/test_algo3.cpp b/test/test_algo3.cpp index e24b842..943257f 100644 --- a/test/test_algo3.cpp +++ b/test/test_algo3.cpp @@ -2943,6 +2943,19 @@ struct test_swap_ CHECK(out == (RAH2_STD::vector{1, 2, 3, 4, 5})); CHECK(in_ == (RAH2_STD::vector{10, 11, 12})); } + { + RAH2_STD::vector in_(1000); + in_[3] = 12; + auto in = make_test_view_adapter(in_); + RAH2_STD::vector out(1000); + out[4] = 79; + auto result = RAH2_NS::ranges::swap_ranges( + RAH2_NS::ranges::begin(in), RAH2_NS::ranges::end(in), out.begin(), out.end()); + CHECK(result.in2 == out.begin() + in_.size()); + CHECK(result.in1 == in.end()); + CHECK_EQUAL(out[3], 12); + CHECK_EQUAL(in_[4], 79); + } { testSuite.test_case("range");