From fe8a845f95d0022bb138ee60b88ccc39cd27bbc9 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Fri, 22 Sep 2023 10:21:48 +0200 Subject: [PATCH 1/4] Add non-recursive for_each_chunk_p for champ --- immer/detail/hamts/champ.hpp | 66 ++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/immer/detail/hamts/champ.hpp b/immer/detail/hamts/champ.hpp index 64a8cb82..a6b3930b 100644 --- a/immer/detail/hamts/champ.hpp +++ b/immer/detail/hamts/champ.hpp @@ -12,6 +12,8 @@ #include #include +#include +#include namespace immer { namespace detail { @@ -146,7 +148,8 @@ struct champ champ(node_t* r, size_t sz = 0) : root{r} , size{sz} - {} + { + } champ(const champ& other) : champ{other.root, other.size} @@ -328,6 +331,61 @@ struct champ } } + template + bool for_each_chunk_p(Fn&& fn) const + { + struct State + { + const node_t* const* fst{}; + const node_t* const* lst{}; + }; + + std::array + 1> stack{}; + stack[0] = {&root, &root + 1}; + size_t depth = 0; + + while (true) { + auto fst = stack[depth].fst; + auto lst = stack[depth].lst; + + if (fst == lst) { + if (!depth) + return true; + + depth--; + continue; + } + + const node_t* node = *fst; + + if (depth < max_depth) { + auto datamap = node->datamap(); + if (datamap && + !fn(node->values(), node->values() + node->data_count())) { + return false; + } + + auto nodemap = node->nodemap(); + stack[depth].fst++; + + if (nodemap) { + auto childFst = node->children(); + depth++; + stack[depth].fst = childFst; + stack[depth].lst = childFst + node->children_count(); + } + continue; + } + + if (!fn(node->collisions(), + node->collisions() + node->collision_count())) { + return false; + } + --depth; + } + return true; + } + template void diff(const champ& new_champ, Differ&& differ) const { @@ -1300,13 +1358,15 @@ struct champ , data{a.data} , owned{false} , mutated{false} - {} + { + } sub_result_mut(sub_result a, bool m) : kind{a.kind} , data{a.data} , owned{false} , mutated{m} - {} + { + } sub_result_mut() : kind{kind_t::nothing} , mutated{false} {}; From c77ce827d5dfa254f804e0e3cf212bc4c1cbe282 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sat, 23 Sep 2023 11:49:39 +0200 Subject: [PATCH 2/4] Add some unittest --- test/algorithm.cpp | 7 +++---- test/map/generic.ipp | 31 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/test/algorithm.cpp b/test/algorithm.cpp index 6a785dbd..001cfc6b 100644 --- a/test/algorithm.cpp +++ b/test/algorithm.cpp @@ -110,10 +110,9 @@ TEST_CASE("all_of") do_check(immer::vector{}); do_check(immer::flex_vector{}); do_check(immer::array{}); - // not supported - // do_check(immer::map{}); - // do_check(immer::set{}); - // do_check(immer::table{}); + do_check(immer::map{}); + do_check(immer::set{}); + do_check(immer::table{}); } TEST_CASE("update vectors") diff --git a/test/map/generic.ipp b/test/map/generic.ipp index e9b6cf58..9b949151 100644 --- a/test/map/generic.ipp +++ b/test/map/generic.ipp @@ -263,6 +263,37 @@ TEST_CASE("accumulate") } } +TEST_CASE("all_of") +{ + static const auto n = 666u; + auto v = make_test_map(n); + + static const auto all_identity = [](const auto& keyval) { + return keyval.first == keyval.second; + }; + static const auto all_less_n2 = [](const auto& keyval) { + return keyval.second < n / 2; + }; + + SECTION("All identity (true)") + { + bool result = immer::all_of(v, all_identity); + CHECK(result); + } + + SECTION("Empty (true)") + { + bool result = immer::all_of(make_test_map(0), all_identity); + CHECK(result); + } + + SECTION("All less n/2 (false)") + { + bool result = immer::all_of(v, all_less_n2); + CHECK(!result); + } +} + TEST_CASE("update a lot") { auto v = make_test_map(666u); From 94dc1fc9aa8a5c5c8b144bcaaee1b1f885470a32 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sat, 23 Sep 2023 11:59:39 +0200 Subject: [PATCH 3/4] map all_of test with collisions --- test/map/generic.ipp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/map/generic.ipp b/test/map/generic.ipp index 9b949151..14153c87 100644 --- a/test/map/generic.ipp +++ b/test/map/generic.ipp @@ -271,6 +271,9 @@ TEST_CASE("all_of") static const auto all_identity = [](const auto& keyval) { return keyval.first == keyval.second; }; + static const auto all_less_n = [](const auto& keyval) { + return keyval.second < n; + }; static const auto all_less_n2 = [](const auto& keyval) { return keyval.second < n / 2; }; @@ -292,6 +295,21 @@ TEST_CASE("all_of") bool result = immer::all_of(v, all_less_n2); CHECK(!result); } + + SECTION("All less n w/ collisions (true)") + { + auto vals = make_values_with_collisions(n); + auto s = make_test_map(vals); + bool result = immer::all_of(v, all_less_n); + CHECK(result); + } + SECTION("All less n/2 w/ collisions (false)") + { + auto vals = make_values_with_collisions(n); + auto s = make_test_map(vals); + bool result = immer::all_of(v, all_less_n2); + CHECK(!result); + } } TEST_CASE("update a lot") From 6cd57a26209d2a780d78bb48c0ea05ec8a6615fe Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Thu, 14 Dec 2023 18:24:46 +0100 Subject: [PATCH 4/4] Avoid changes by auto-formatting --- immer/detail/hamts/champ.hpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/immer/detail/hamts/champ.hpp b/immer/detail/hamts/champ.hpp index a6b3930b..9a145f17 100644 --- a/immer/detail/hamts/champ.hpp +++ b/immer/detail/hamts/champ.hpp @@ -148,8 +148,7 @@ struct champ champ(node_t* r, size_t sz = 0) : root{r} , size{sz} - { - } + {} champ(const champ& other) : champ{other.root, other.size} @@ -1358,15 +1357,13 @@ struct champ , data{a.data} , owned{false} , mutated{false} - { - } + {} sub_result_mut(sub_result a, bool m) : kind{a.kind} , data{a.data} , owned{false} , mutated{m} - { - } + {} sub_result_mut() : kind{kind_t::nothing} , mutated{false} {};