From 4de835547ad99824e7646dfcb46be52be13df9ec Mon Sep 17 00:00:00 2001 From: SpectraL519 Date: Tue, 30 Dec 2025 16:23:53 +0100 Subject: [PATCH 1/2] comment :) --- include/hgl/impl/incidence_list.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/hgl/impl/incidence_list.hpp b/include/hgl/impl/incidence_list.hpp index f0b41cf..4060ddc 100644 --- a/include/hgl/impl/incidence_list.hpp +++ b/include/hgl/impl/incidence_list.hpp @@ -289,7 +289,7 @@ class incidence_list final { gl_attr_force_inline void bind_tail( const types::id_type vertex_id, const types::id_type hyperedge_id ) noexcept { - // TODO: validate if minor_id is not in head + // TODO: validate if minor_id is not in head - if yes, unbind const auto [major_id, minor_id] = layout_tag::majmin(vertex_id, hyperedge_id); this->_unique_insert(this->_major_storage[major_id].tail, minor_id); } @@ -297,7 +297,7 @@ class incidence_list final { gl_attr_force_inline void bind_head( const types::id_type vertex_id, const types::id_type hyperedge_id ) noexcept { - // TODO: validate if minor_id is not in tail + // TODO: validate if minor_id is not in tail - if yes, unbind const auto [major_id, minor_id] = layout_tag::majmin(vertex_id, hyperedge_id); this->_unique_insert(this->_major_storage[major_id].head, minor_id); } From 1633d11a5d49056d5bce924fc87413e75bb71470 Mon Sep 17 00:00:00 2001 From: SpectraL519 Date: Tue, 30 Dec 2025 17:08:52 +0100 Subject: [PATCH 2/2] working implementation --- include/hgl/impl/incidence_list.hpp | 4 +- tests/source/hgl/test_incidence_list.cpp | 60 ++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/include/hgl/impl/incidence_list.hpp b/include/hgl/impl/incidence_list.hpp index 4060ddc..b9a5171 100644 --- a/include/hgl/impl/incidence_list.hpp +++ b/include/hgl/impl/incidence_list.hpp @@ -289,16 +289,16 @@ class incidence_list final { gl_attr_force_inline void bind_tail( const types::id_type vertex_id, const types::id_type hyperedge_id ) noexcept { - // TODO: validate if minor_id is not in head - if yes, unbind const auto [major_id, minor_id] = layout_tag::majmin(vertex_id, hyperedge_id); + this->_remove_no_align(this->_major_storage[major_id].head, minor_id); this->_unique_insert(this->_major_storage[major_id].tail, minor_id); } gl_attr_force_inline void bind_head( const types::id_type vertex_id, const types::id_type hyperedge_id ) noexcept { - // TODO: validate if minor_id is not in tail - if yes, unbind const auto [major_id, minor_id] = layout_tag::majmin(vertex_id, hyperedge_id); + this->_remove_no_align(this->_major_storage[major_id].tail, minor_id); this->_unique_insert(this->_major_storage[major_id].head, minor_id); } diff --git a/tests/source/hgl/test_incidence_list.cpp b/tests/source/hgl/test_incidence_list.cpp index fc10e9a..8598803 100644 --- a/tests/source/hgl/test_incidence_list.cpp +++ b/tests/source/hgl/test_incidence_list.cpp @@ -783,6 +783,36 @@ TEST_CASE_FIXTURE( CHECK(std::ranges::contains(vertices, constants::id1)); } +TEST_CASE_FIXTURE( + test_bf_directed_vertex_major_incidence_list, + "binding methods should rebind the elements if they are already bound" +) { + sut_type sut{constants::n_vertices, constants::n_hyperedges}; + constexpr auto vertex_id = constants::id1, hyperedge_id = constants::id2; + + REQUIRE_FALSE(sut.are_bound(vertex_id, hyperedge_id)); + REQUIRE_FALSE(sut.is_head(vertex_id, hyperedge_id)); + REQUIRE_FALSE(sut.is_head(vertex_id, hyperedge_id)); + + // initial bind + sut.bind_head(vertex_id, hyperedge_id); + CHECK(sut.are_bound(vertex_id, hyperedge_id)); + CHECK(sut.is_head(vertex_id, hyperedge_id)); + CHECK_FALSE(sut.is_tail(vertex_id, hyperedge_id)); + + // rebind tail + sut.bind_tail(vertex_id, hyperedge_id); + CHECK(sut.are_bound(vertex_id, hyperedge_id)); + CHECK(sut.is_tail(vertex_id, hyperedge_id)); + CHECK_FALSE(sut.is_head(vertex_id, hyperedge_id)); + + // rebind head + sut.bind_head(vertex_id, hyperedge_id); + CHECK(sut.are_bound(vertex_id, hyperedge_id)); + CHECK(sut.is_head(vertex_id, hyperedge_id)); + CHECK_FALSE(sut.is_tail(vertex_id, hyperedge_id)); +} + TEST_CASE_FIXTURE( test_bf_directed_vertex_major_incidence_list, "unbind should erase the hyperedge id from a proper vertex entry" @@ -1104,6 +1134,36 @@ TEST_CASE_FIXTURE( CHECK(std::ranges::contains(hyperedges, constants::id1)); } +TEST_CASE_FIXTURE( + test_bf_directed_vertex_major_incidence_list, + "binding methods should rebind the elements if they are already bound" +) { + sut_type sut{constants::n_vertices, constants::n_hyperedges}; + constexpr auto vertex_id = constants::id1, hyperedge_id = constants::id2; + + REQUIRE_FALSE(sut.are_bound(vertex_id, hyperedge_id)); + REQUIRE_FALSE(sut.is_head(vertex_id, hyperedge_id)); + REQUIRE_FALSE(sut.is_head(vertex_id, hyperedge_id)); + + // initial bind + sut.bind_head(vertex_id, hyperedge_id); + CHECK(sut.are_bound(vertex_id, hyperedge_id)); + CHECK(sut.is_head(vertex_id, hyperedge_id)); + CHECK_FALSE(sut.is_tail(vertex_id, hyperedge_id)); + + // rebind tail + sut.bind_tail(vertex_id, hyperedge_id); + CHECK(sut.are_bound(vertex_id, hyperedge_id)); + CHECK(sut.is_tail(vertex_id, hyperedge_id)); + CHECK_FALSE(sut.is_head(vertex_id, hyperedge_id)); + + // rebind head + sut.bind_head(vertex_id, hyperedge_id); + CHECK(sut.are_bound(vertex_id, hyperedge_id)); + CHECK(sut.is_head(vertex_id, hyperedge_id)); + CHECK_FALSE(sut.is_tail(vertex_id, hyperedge_id)); +} + TEST_CASE_FIXTURE( test_bf_directed_vertex_major_incidence_list, "unbind should clear the corresponding bit" ) {