From f7a15b7136d8153e577607e8305005347f586764 Mon Sep 17 00:00:00 2001 From: Ahajha Date: Tue, 1 Oct 2024 00:57:55 -0400 Subject: [PATCH 1/2] Fail if duplicate keys are present --- include/frozen/bits/pmh.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/frozen/bits/pmh.h b/include/frozen/bits/pmh.h index 1bb4021..688c730 100644 --- a/include/frozen/bits/pmh.h +++ b/include/frozen/bits/pmh.h @@ -103,6 +103,11 @@ pmh_buckets constexpr make_pmh_buckets(const carray & items, bool rejected = false; for (std::size_t i = 0; i < items.size(); ++i) { auto & bucket = result.buckets[hash(key(items[i]), static_cast(result.seed)) % M]; + for (const auto item_index : bucket) { + if (key(items[item_index]) == key(items[i])) { + (void)"Duplicate keys present, check your input data"; exit(1); + } + } if (bucket.size() >= result_t::bucket_max) { rejected = true; break; From 52bb2dd5b2f8b61d7ee016e38cdb31c7485de989 Mon Sep 17 00:00:00 2001 From: Ahajha Date: Tue, 1 Oct 2024 09:30:21 -0400 Subject: [PATCH 2/2] Incorporate review feedback --- include/frozen/bits/pmh.h | 35 +++++++++++++++++++++++----------- include/frozen/unordered_map.h | 2 +- include/frozen/unordered_set.h | 2 +- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/include/frozen/bits/pmh.h b/include/frozen/bits/pmh.h index 688c730..3689fe2 100644 --- a/include/frozen/bits/pmh.h +++ b/include/frozen/bits/pmh.h @@ -90,11 +90,26 @@ struct pmh_buckets { } }; -template +inline void check(const char[]) {} + +template +constexpr void +check_for_duplicate_keys(const carray &items, + const Bucket & bucket, Key const &key, + KeyType const ¤t_key, KeyEqual const &keyequal) { + for (const auto item_index : bucket) { + if (keyequal(key(items[item_index]), current_key)) { + check("Duplicate keys present, check your input data"); + } + } +} + +template pmh_buckets constexpr make_pmh_buckets(const carray & items, Hash const & hash, Key const & key, - PRG & prg) { + PRG & prg, + KeyEqual const & keyequal) { using result_t = pmh_buckets; // Continue until all items are placed without exceeding bucket_max while (1) { @@ -102,12 +117,9 @@ pmh_buckets constexpr make_pmh_buckets(const carray & items, result.seed = prg(); bool rejected = false; for (std::size_t i = 0; i < items.size(); ++i) { - auto & bucket = result.buckets[hash(key(items[i]), static_cast(result.seed)) % M]; - for (const auto item_index : bucket) { - if (key(items[item_index]) == key(items[i])) { - (void)"Duplicate keys present, check your input data"; exit(1); - } - } + const auto & current_key = key(items[i]); + auto & bucket = result.buckets[hash(current_key, static_cast(result.seed)) % M]; + check_for_duplicate_keys(items, bucket, key, current_key, keyequal); if (bucket.size() >= result_t::bucket_max) { rejected = true; break; @@ -189,14 +201,15 @@ struct pmh_tables : private Hasher { }; // Make pmh tables for given items, hash function, prg, etc. -template +template pmh_tables constexpr make_pmh_tables(const carray & items, Hash const &hash, Key const &key, - PRG prg) { + PRG prg, + KeyEqual const &keyequal) { // Step 1: Place all of the keys into buckets - auto step_one = make_pmh_buckets(items, hash, key, prg); + auto step_one = make_pmh_buckets(items, hash, key, prg, keyequal); // Step 2: Sort the buckets to process the ones with the most items first. auto buckets = step_one.get_sorted_buckets(); diff --git a/include/frozen/unordered_map.h b/include/frozen/unordered_map.h index 6f7b4a0..8c5a8a1 100644 --- a/include/frozen/unordered_map.h +++ b/include/frozen/unordered_map.h @@ -84,7 +84,7 @@ class unordered_map : private KeyEqual { , items_{items} , tables_{ bits::make_pmh_tables( - items_, hash, bits::GetKey{}, default_prg_t{})} {} + items_, hash, bits::GetKey{}, default_prg_t{}, equal)} {} explicit constexpr unordered_map(container_type items) : unordered_map{items, Hash{}, KeyEqual{}} {} diff --git a/include/frozen/unordered_set.h b/include/frozen/unordered_set.h index 81bca6c..5848cb4 100644 --- a/include/frozen/unordered_set.h +++ b/include/frozen/unordered_set.h @@ -78,7 +78,7 @@ class unordered_set : private KeyEqual { : KeyEqual{equal} , keys_{keys} , tables_{bits::make_pmh_tables( - keys_, hash, bits::Get{}, default_prg_t{})} {} + keys_, hash, bits::Get{}, default_prg_t{}, equal)} {} explicit constexpr unordered_set(container_type keys) : unordered_set{keys, Hash{}, KeyEqual{}} {}