[libcxx-commits] [libcxx] [libc++] Minor change to how unordered_set is compared (PR #66692)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Sep 18 12:53:03 PDT 2023
https://github.com/ldionne created https://github.com/llvm/llvm-project/pull/66692
This patch is a melting pot of changes picked up from https://llvm.org/D61878. It adds a few tests checking corner cases of unordered containers comparison and removes an unnecessary check of `std::is_permutation` inside unordered_multiset's `operator==`.
>From c49c73d99a41dc1ff25d9d40a063aa1de694d51d Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Mon, 18 Sep 2023 15:48:39 -0400
Subject: [PATCH] [libc++] Minor change to how unordered_set is compared
This patch is a melting pot of changes picked up from https://llvm.org/D61878.
It adds a few tests checking corner cases of unordered containers comparison
and removes an unnecessary check of `std::is_permutation` inside unordered_multiset's
`operator==`.
---
libcxx/benchmarks/ContainerBenchmarks.h | 31 +++++++++++++++++++
.../unordered_set_operations.bench.cpp | 19 ++++++++++++
libcxx/include/unordered_set | 5 +--
.../unord/unord.multimap/eq.pass.cpp | 27 +++++++++++++++-
.../unord/unord.multiset/eq.pass.cpp | 15 ++++++++-
5 files changed, 91 insertions(+), 6 deletions(-)
diff --git a/libcxx/benchmarks/ContainerBenchmarks.h b/libcxx/benchmarks/ContainerBenchmarks.h
index 5ab6f619b85a8d0..071e46c2a1c6546 100644
--- a/libcxx/benchmarks/ContainerBenchmarks.h
+++ b/libcxx/benchmarks/ContainerBenchmarks.h
@@ -179,6 +179,37 @@ static void BM_Rehash(benchmark::State& st, Container c, GenInputs gen) {
}
}
+template <class Container, class GenInputs>
+static void BM_Compare_same_container(benchmark::State& st, Container, GenInputs gen) {
+ auto in = gen(st.range(0));
+ Container c1(in.begin(), in.end());
+ Container c2 = c1;
+
+ benchmark::DoNotOptimize(&(*c1.begin()));
+ benchmark::DoNotOptimize(&(*c2.begin()));
+ while (st.KeepRunning()) {
+ bool res = c1 == c2;
+ benchmark::DoNotOptimize(&res);
+ benchmark::ClobberMemory();
+ }
+}
+
+template <class Container, class GenInputs>
+static void BM_Compare_different_containers(benchmark::State& st, Container, GenInputs gen) {
+ auto in1 = gen(st.range(0));
+ auto in2 = gen(st.range(0));
+ Container c1(in1.begin(), in1.end());
+ Container c2(in2.begin(), in2.end());
+
+ benchmark::DoNotOptimize(&(*c1.begin()));
+ benchmark::DoNotOptimize(&(*c2.begin()));
+ while (st.KeepRunning()) {
+ bool res = c1 == c2;
+ benchmark::DoNotOptimize(&res);
+ benchmark::ClobberMemory();
+ }
+}
+
} // end namespace ContainerBenchmarks
#endif // BENCHMARK_CONTAINER_BENCHMARKS_H
diff --git a/libcxx/benchmarks/unordered_set_operations.bench.cpp b/libcxx/benchmarks/unordered_set_operations.bench.cpp
index 96aa2e0dfea3be0..d49de576ec9778d 100644
--- a/libcxx/benchmarks/unordered_set_operations.bench.cpp
+++ b/libcxx/benchmarks/unordered_set_operations.bench.cpp
@@ -290,6 +290,25 @@ BENCHMARK_CAPTURE(BM_Rehash,
BENCHMARK_CAPTURE(BM_Rehash, unordered_set_int_arg, std::unordered_set<int>{}, getRandomIntegerInputs<int>)
->Arg(TestNumInputs);
+//----------------------------------------------------------------------------//
+// BM_Compare
+// ---------------------------------------------------------------------------//
+
+BENCHMARK_CAPTURE(
+ BM_Compare_same_container, unordered_set_string, std::unordered_set<std::string>{}, getRandomStringInputs)
+ ->Arg(TestNumInputs);
+
+BENCHMARK_CAPTURE(BM_Compare_same_container, unordered_set_int, std::unordered_set<int>{}, getRandomIntegerInputs<int>)
+ ->Arg(TestNumInputs);
+
+BENCHMARK_CAPTURE(
+ BM_Compare_different_containers, unordered_set_string, std::unordered_set<std::string>{}, getRandomStringInputs)
+ ->Arg(TestNumInputs);
+
+BENCHMARK_CAPTURE(
+ BM_Compare_different_containers, unordered_set_int, std::unordered_set<int>{}, getRandomIntegerInputs<int>)
+ ->Arg(TestNumInputs);
+
///////////////////////////////////////////////////////////////////////////////
BENCHMARK_CAPTURE(BM_InsertDuplicate, unordered_set_int, std::unordered_set<int>{}, getRandomIntegerInputs<int>)
->Arg(TestNumInputs);
diff --git a/libcxx/include/unordered_set b/libcxx/include/unordered_set
index 5e47f12446ff936..6442bef93114956 100644
--- a/libcxx/include/unordered_set
+++ b/libcxx/include/unordered_set
@@ -527,7 +527,6 @@ template <class Value, class Hash, class Pred, class Alloc>
*/
-#include <__algorithm/is_permutation.h>
#include <__assert> // all public C++ headers provide the assertion handler
#include <__availability>
#include <__config>
@@ -1935,9 +1934,7 @@ operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
{
_EqRng __xeq = __x.equal_range(*__i);
_EqRng __yeq = __y.equal_range(*__i);
- if (_VSTD::distance(__xeq.first, __xeq.second) !=
- _VSTD::distance(__yeq.first, __yeq.second) ||
- !_VSTD::is_permutation(__xeq.first, __xeq.second, __yeq.first))
+ if (std::distance(__xeq.first, __xeq.second) != std::distance(__yeq.first, __yeq.second))
return false;
__i = __xeq.second;
}
diff --git a/libcxx/test/std/containers/unord/unord.multimap/eq.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/eq.pass.cpp
index d0e578e190c0a18..2258e31d75b44e2 100644
--- a/libcxx/test/std/containers/unord/unord.multimap/eq.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.multimap/eq.pass.cpp
@@ -221,5 +221,30 @@ int main(int, char**)
}
#endif
- return 0;
+ // Make sure we take into account the number of times that a key repeats into equality.
+ {
+ typedef std::pair<int, char> P;
+ P a[] = {{1, 'a'}, {1, 'b'}, {1, 'd'}, {2, 'b'}};
+ P b[] = {{1, 'a'}, {1, 'b'}, {1, 'b'}, {1, 'd'}, {2, 'b'}};
+
+ std::unordered_multimap<int, char> c1(std::begin(a), std::end(a));
+ std::unordered_multimap<int, char> c2(std::begin(b), std::end(b));
+ assert(testEquality(c1, c2, false));
+ }
+
+ // Make sure we incorporate the values into the equality of the maps.
+ // If we were to compare only the keys (including how many time each key repeats),
+ // the following test would fail cause only the values differ.
+ {
+ typedef std::pair<int, char> P;
+ P a[] = {{1, 'a'}, {1, 'b'}, {1, 'd'}, {2, 'b'}};
+ P b[] = {{1, 'a'}, {1, 'b'}, {1, 'E'}, {2, 'b'}};
+ // ^ different here
+
+ std::unordered_multimap<int, char> c1(std::begin(a), std::end(a));
+ std::unordered_multimap<int, char> c2(std::begin(b), std::end(b));
+ assert(testEquality(c1, c2, false));
+ }
+
+ return 0;
}
diff --git a/libcxx/test/std/containers/unord/unord.multiset/eq.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/eq.pass.cpp
index 22d3207d0ff74a0..c059b461a830789 100644
--- a/libcxx/test/std/containers/unord/unord.multiset/eq.pass.cpp
+++ b/libcxx/test/std/containers/unord/unord.multiset/eq.pass.cpp
@@ -24,6 +24,8 @@
#include "test_macros.h"
#include "min_allocator.h"
+#include "test_comparisons.h"
+
int main(int, char**)
{
{
@@ -178,5 +180,16 @@ int main(int, char**)
}
#endif
- return 0;
+ // Make sure we take into account the number of times that a key repeats into equality.
+ {
+ typedef int P;
+ P a[] = {P(1), P(1), P(1), P(2)};
+ P b[] = {P(1), P(1), P(1), P(1), P(2)};
+
+ std::unordered_multiset<int> c1(std::begin(a), std::end(a));
+ std::unordered_multiset<int> c2(std::begin(b), std::end(b));
+ assert(testEquality(c1, c2, false));
+ }
+
+ return 0;
}
More information about the libcxx-commits
mailing list