[libcxx-commits] [libcxx] [libc++] Speed up set_intersection() by fast-forwarding over ranges of non-matching elements with one-sided binary search. (PR #75230)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Fri May 24 12:17:31 PDT 2024
================
@@ -272,6 +278,234 @@ constexpr void runAllIteratorPermutationsTests() {
static_assert(withAllPermutationsOfInIter1AndInIter2<contiguous_iterator<int*>>());
}
+namespace {
+struct [[nodiscard]] OperationCounts {
+ std::size_t comparisons{};
+ struct PerInput {
+ std::size_t proj{};
+ std::size_t iterator_strides{};
+ std::ptrdiff_t iterator_displacement{};
+
+ // IGNORES proj!
+ [[nodiscard]] constexpr bool operator==(const PerInput& o) const {
+ return iterator_strides == o.iterator_strides && iterator_displacement == o.iterator_displacement;
+ }
+
+ [[nodiscard]] constexpr bool matchesExpectation(const PerInput& expect) {
+ return proj <= expect.proj && iterator_strides <= expect.iterator_strides &&
+ iterator_displacement <= expect.iterator_displacement;
+ }
+ };
+ std::array<PerInput, 2> in;
+
+ [[nodiscard]] constexpr bool matchesExpectation(const OperationCounts& expect) {
+ // __debug_less will perform an additional comparison in an assertion
+ constexpr unsigned comparison_multiplier =
+#if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
+ 2;
+#else
+ 1;
+#endif
+ return comparisons <= comparison_multiplier * expect.comparisons && in[0].matchesExpectation(expect.in[0]) &&
+ in[1].matchesExpectation(expect.in[1]);
+ }
+
+ [[nodiscard]] constexpr bool operator==(const OperationCounts& o) const {
+ return comparisons == o.comparisons && std::ranges::equal(in, o.in);
+ }
+};
+} // namespace
+
+template <template <class...> class In1,
+ template <class...>
+ class In2,
+ class Out,
+ std::size_t N1,
+ std::size_t N2,
+ std::size_t N3>
+constexpr void testSetIntersectionAndReturnOpCounts(
----------------
ldionne wrote:
I think it would be cleaner if this function had the following interface:
```c++
constexpr OperationCounts testSetIntersectionAndReturnOpCounts(array, array, array);
```
Then you can call as:
```c++
pair<OperationCounts, array-of-the-result> actual = testSetIntersectionAndReturnOpCounts(...);
assert(actual.first == expected);
```
I would also change the name to something like `counted_set_intersection`. Potentially use a struct instead of a `pair`.
https://github.com/llvm/llvm-project/pull/75230
More information about the libcxx-commits
mailing list