Skip to content

Commit e393eee

Browse files
committed
wip: hgl alignment
1 parent 6cafb00 commit e393eee

13 files changed

Lines changed: 243 additions & 104 deletions

include/gl/util/ranges.hpp

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,127 @@ template <std::ranges::forward_range R>
3939
return std::ranges::all_of(range, [&k](const auto& val) { return val == k; });
4040
}
4141

42+
// --- C++20 Concat View Utility ---
43+
44+
namespace detail {
45+
46+
template <std::ranges::view V1, std::ranges::view V2>
47+
class concat_view : public std::ranges::view_interface<concat_view<V1, V2>> {
48+
public:
49+
concat_view() = default;
50+
51+
constexpr concat_view(V1 v1, V2 v2) : _v1(std::move(v1)), _v2(std::move(v2)) {}
52+
53+
class sentinel {
54+
public:
55+
sentinel() = default;
56+
57+
constexpr explicit sentinel(std::ranges::sentinel_t<V2> end2) : _end2(std::move(end2)) {}
58+
59+
constexpr auto end2() const {
60+
return _end2;
61+
}
62+
63+
private:
64+
std::ranges::sentinel_t<V2> _end2;
65+
friend class concat_view;
66+
};
67+
68+
class iterator {
69+
public:
70+
using difference_type = std::
71+
common_type_t<std::ranges::range_difference_t<V1>, std::ranges::range_difference_t<V2>>;
72+
using value_type =
73+
std::common_type_t<std::ranges::range_value_t<V1>, std::ranges::range_value_t<V2>>;
74+
using reference = std::common_reference_t<
75+
std::ranges::range_reference_t<V1>,
76+
std::ranges::range_reference_t<V2>>;
77+
using iterator_category = std::forward_iterator_tag;
78+
using iterator_concept = std::forward_iterator_tag;
79+
80+
iterator() = default;
81+
82+
constexpr iterator(
83+
std::ranges::iterator_t<V1> it1,
84+
std::ranges::sentinel_t<V1> end1,
85+
std::ranges::iterator_t<V2> it2
86+
)
87+
: _it1(std::move(it1)), _end1(std::move(end1)), _it2(std::move(it2)) {}
88+
89+
constexpr reference operator*() const {
90+
if (_it1 != _end1)
91+
return *_it1;
92+
return *_it2;
93+
}
94+
95+
constexpr iterator& operator++() {
96+
if (_it1 != _end1) {
97+
++_it1;
98+
}
99+
else {
100+
++_it2;
101+
}
102+
return *this;
103+
}
104+
105+
constexpr iterator operator++(int) {
106+
iterator tmp = *this;
107+
++*this;
108+
return tmp;
109+
}
110+
111+
constexpr bool operator==(const iterator& other) const {
112+
return _it1 == other._it1 && _it2 == other._it2;
113+
}
114+
115+
constexpr bool operator==(const sentinel& s) const {
116+
return _it1 == _end1 && _it2 == s.end2();
117+
}
118+
119+
private:
120+
std::ranges::iterator_t<V1> _it1;
121+
std::ranges::sentinel_t<V1> _end1;
122+
std::ranges::iterator_t<V2> _it2;
123+
};
124+
125+
constexpr iterator begin() {
126+
return iterator(std::ranges::begin(_v1), std::ranges::end(_v1), std::ranges::begin(_v2));
127+
}
128+
129+
constexpr iterator begin() const
130+
requires std::ranges::range<const V1> && std::ranges::range<const V2>
131+
{
132+
return iterator(std::ranges::begin(_v1), std::ranges::end(_v1), std::ranges::begin(_v2));
133+
}
134+
135+
constexpr sentinel end() {
136+
return sentinel(std::ranges::end(_v2));
137+
}
138+
139+
constexpr sentinel end() const
140+
requires std::ranges::range<const V1> && std::ranges::range<const V2>
141+
{
142+
return sentinel(std::ranges::end(_v2));
143+
}
144+
145+
private:
146+
V1 _v1;
147+
V2 _v2;
148+
};
149+
150+
struct concat_fn {
151+
template <std::ranges::viewable_range R1, std::ranges::viewable_range R2>
152+
constexpr auto operator()(R1&& r1, R2&& r2) const {
153+
return concat_view<std::views::all_t<R1>, std::views::all_t<R2>>(
154+
std::views::all(std::forward<R1>(r1)), std::views::all(std::forward<R2>(r2))
155+
);
156+
}
157+
};
158+
159+
} // namespace detail
160+
161+
/// @brief Concatenates two ranges sequentially into a single view.
162+
/// @todo replace with `std::views::concat`
163+
inline constexpr detail::concat_fn concat{};
164+
42165
} // namespace gl::util

include/hgl/conversion.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,8 +322,11 @@ requires std::same_as<typename G::traits_type::implementation_tag, gl::impl::fla
322322

323323
template <gl::traits::c_undirected_graph G>
324324
[[nodiscard]] G incidence_graph(const traits::c_undirected_hypergraph auto& h) {
325+
using g_id_type = typename G::id_type;
326+
325327
G g{h.order() + h.size()};
326-
const auto align_edge_id = [shift = h.order()](const auto eid) -> gl::default_id_type {
328+
const auto align_edge_id =
329+
[shift = static_cast<g_id_type>(h.order())](const auto eid) -> g_id_type {
327330
return eid + shift;
328331
};
329332

@@ -349,7 +352,8 @@ template <gl::traits::c_directed_graph G>
349352
using g_id_type = typename G::id_type;
350353

351354
G g{h.order() + h.size()};
352-
const auto align_edge_id = [shift = h.order()](const auto eid) -> gl::default_id_type {
355+
const auto align_edge_id =
356+
[shift = static_cast<g_id_type>(h.order())](const auto eid) -> g_id_type {
353357
return eid + shift;
354358
};
355359

include/hgl/impl/flat_incidence_list.hpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44

55
#pragma once
66

7-
#include "gl/types/core.hpp"
87
#include "hgl/constants.hpp"
98
#include "hgl/decl/impl_tags.hpp"
109
#include "hgl/directional_tags.hpp"
1110
#include "hgl/impl/layout_tags.hpp"
1211
#include "hgl/types.hpp"
12+
#include "hgl/util.hpp"
1313

1414
#include <algorithm>
1515
#include <concepts>
@@ -498,10 +498,11 @@ class flat_incidence_list<hgl::bf_directed_t, ImplTag> final {
498498
if constexpr (std::same_as<Projection, std::identity>) {
499499
// TODO: use std::views::concat (C++26)
500500
// NOTE: This is safe because the range operator | creates an owning view over the array
501-
return std::array<storage_const_segment_type, 2uz>{
502-
this->_tail_storage[idx], this->_head_storage[idx]
503-
}
504-
| std::views::join;
501+
// return std::array<storage_const_segment_type, 2uz>{
502+
// this->_tail_storage[idx], this->_head_storage[idx]
503+
// }
504+
// | std::views::join;
505+
return util::concat(this->_tail_storage[idx], this->_head_storage[idx]);
505506
}
506507
else {
507508
return std::invoke(storage_proj, this)[idx];
@@ -545,10 +546,11 @@ class flat_incidence_list<hgl::bf_directed_t, ImplTag> final {
545546
[[nodiscard]] gl_attr_force_inline auto _get(const id_type id) const noexcept {
546547
if constexpr (Element == layout_tag::major_element) { // get major
547548
const auto idx = to_idx(id);
548-
return std::array<storage_const_segment_type, 2uz>{
549-
this->_tail_storage[idx], this->_head_storage[idx]
550-
}
551-
| std::views::join;
549+
// return std::array<storage_const_segment_type, 2uz>{
550+
// this->_tail_storage[idx], this->_head_storage[idx]
551+
// }
552+
// | std::views::join;
553+
return util::concat(this->_tail_storage[idx], this->_head_storage[idx]);
552554
}
553555
else { // get minor
554556
return std::views::iota(initial_id_v<id_type>, this->_tail_storage.size())

include/hgl/impl/flat_incidence_matrix.hpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -115,19 +115,19 @@ class flat_incidence_matrix<hgl::undirected_t, ImplTag> final {
115115

116116
gl_attr_force_inline void bind(const id_type vertex_id, const id_type hyperedge_id) noexcept {
117117
const auto [major_id, minor_id] = layout_tag::majmin(vertex_id, hyperedge_id);
118-
this->_matrix[to_idx(major_id)][to_idx(minor_id)] = true;
118+
this->_matrix[to_idx(major_id), to_idx(minor_id)] = true;
119119
}
120120

121121
gl_attr_force_inline void unbind(const id_type vertex_id, const id_type hyperedge_id) noexcept {
122122
const auto [major_id, minor_id] = layout_tag::majmin(vertex_id, hyperedge_id);
123-
this->_matrix[to_idx(major_id)][to_idx(minor_id)] = false;
123+
this->_matrix[to_idx(major_id), to_idx(minor_id)] = false;
124124
}
125125

126126
[[nodiscard]] gl_attr_force_inline bool are_bound(
127127
const id_type vertex_id, const id_type hyperedge_id
128128
) const noexcept {
129129
const auto [major_id, minor_id] = layout_tag::majmin(vertex_id, hyperedge_id);
130-
return this->_matrix[to_idx(major_id)][to_idx(minor_id)];
130+
return this->_matrix[to_idx(major_id), to_idx(minor_id)];
131131
}
132132

133133
// --- comparison ---
@@ -353,40 +353,40 @@ class flat_incidence_matrix<hgl::bf_directed_t, ImplTag> final {
353353
const id_type vertex_id, const id_type hyperedge_id
354354
) noexcept {
355355
const auto [major_id, minor_id] = layout_tag::majmin(vertex_id, hyperedge_id);
356-
this->_matrix[to_idx(major_id)][to_idx(minor_id)] = bf_incidence::backward;
356+
this->_matrix[to_idx(major_id), to_idx(minor_id)] = bf_incidence::backward;
357357
}
358358

359359
gl_attr_force_inline void bind_head(
360360
const id_type vertex_id, const id_type hyperedge_id
361361
) noexcept {
362362
const auto [major_id, minor_id] = layout_tag::majmin(vertex_id, hyperedge_id);
363-
this->_matrix[to_idx(major_id)][to_idx(minor_id)] = bf_incidence::forward;
363+
this->_matrix[to_idx(major_id), to_idx(minor_id)] = bf_incidence::forward;
364364
}
365365

366366
gl_attr_force_inline void unbind(const id_type vertex_id, const id_type hyperedge_id) noexcept {
367367
const auto [major_id, minor_id] = layout_tag::majmin(vertex_id, hyperedge_id);
368-
this->_matrix[to_idx(major_id)][to_idx(minor_id)] = bf_incidence::none;
368+
this->_matrix[to_idx(major_id), to_idx(minor_id)] = bf_incidence::none;
369369
}
370370

371371
[[nodiscard]] gl_attr_force_inline bool are_bound(
372372
const id_type vertex_id, const id_type hyperedge_id
373373
) const noexcept {
374374
const auto [major_id, minor_id] = layout_tag::majmin(vertex_id, hyperedge_id);
375-
return this->_matrix[to_idx(major_id)][to_idx(minor_id)] != bf_incidence::none;
375+
return this->_matrix[to_idx(major_id), to_idx(minor_id)] != bf_incidence::none;
376376
}
377377

378378
[[nodiscard]] gl_attr_force_inline bool is_tail(
379379
const id_type vertex_id, const id_type hyperedge_id
380380
) const noexcept {
381381
const auto [major_id, minor_id] = layout_tag::majmin(vertex_id, hyperedge_id);
382-
return this->_matrix[to_idx(major_id)][to_idx(minor_id)] == bf_incidence::backward;
382+
return this->_matrix[to_idx(major_id), to_idx(minor_id)] == bf_incidence::backward;
383383
}
384384

385385
[[nodiscard]] gl_attr_force_inline bool is_head(
386386
const id_type vertex_id, const id_type hyperedge_id
387387
) const noexcept {
388388
const auto [major_id, minor_id] = layout_tag::majmin(vertex_id, hyperedge_id);
389-
return this->_matrix[to_idx(major_id)][to_idx(minor_id)] == bf_incidence::forward;
389+
return this->_matrix[to_idx(major_id), to_idx(minor_id)] == bf_incidence::forward;
390390
}
391391

392392
// --- comparison ---

include/hgl/impl/incidence_list.hpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "hgl/directional_tags.hpp"
1111
#include "hgl/impl/layout_tags.hpp"
1212
#include "hgl/types.hpp"
13+
#include "hgl/util.hpp"
1314

1415
#include <algorithm>
1516
#include <concepts>
@@ -481,10 +482,11 @@ class incidence_list<hgl::bf_directed_t, ImplTag> final {
481482
[[nodiscard]] gl_attr_force_inline auto _get(const id_type id) const noexcept {
482483
if constexpr (Element == layout_tag::major_element) { // get major
483484
const auto idx = to_idx(id);
484-
return std::array<std::span<const minor_element_type>, 2>{
485-
this->_tail_storage[idx], this->_head_storage[idx]
486-
}
487-
| std::views::join;
485+
// return std::array<std::span<const minor_element_type>, 2>{
486+
// this->_tail_storage[idx], this->_head_storage[idx]
487+
// }
488+
// | std::views::join;
489+
return util::concat(this->_tail_storage[idx], this->_head_storage[idx]);
488490
}
489491
else { // get minor
490492
return std::views::iota(initial_id_v<id_type>, this->_tail_storage.size())

include/hgl/util.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
namespace hgl::util {
1010

1111
using gl::util::all_equal;
12+
using gl::util::concat;
1213
using gl::util::deref_view;
1314
using gl::util::is_constant;
1415
using gl::util::range_size;

tests/include/testing/common/wrn.hpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22

33
#if defined(__clang__) || defined(__GNUC__)
44

5-
#define DOCTEST_PRAGMA(x) _Pragma(#x)
5+
#define TEST_PRAGMA(x) _Pragma(#x)
66

7-
#define DOCTEST_SUPPRESS_WARNING_BEGIN(w) \
8-
DOCTEST_PRAGMA(GCC diagnostic push) \
9-
DOCTEST_PRAGMA(GCC diagnostic ignored w)
7+
#define TEST_SUPPRESS_WARNING_BEGIN(w) \
8+
TEST_PRAGMA(GCC diagnostic push) \
9+
TEST_PRAGMA(GCC diagnostic ignored w)
1010

11-
#define DOCTEST_SUPPRESS_WARNING_END DOCTEST_PRAGMA(GCC diagnostic pop)
11+
#define TEST_SUPPRESS_WARNING_END TEST_PRAGMA(GCC diagnostic pop)
1212

1313
#else
1414

15-
#define DOCTEST_SUPPRESS_WARNING_BEGIN(w)
16-
#define DOCTEST_SUPPRESS_WARNING_END
15+
#define TEST_SUPPRESS_WARNING_BEGIN(w)
16+
#define TEST_SUPPRESS_WARNING_END
1717

1818
#endif

tests/source/gl/test_flat_jagged_vector.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ TEST_CASE_FIXTURE(
9292
sut.push_back({1, 2, 3});
9393
sut.push_back({4, 5});
9494

95-
DOCTEST_SUPPRESS_WARNING_BEGIN("-Wself-move");
95+
TEST_SUPPRESS_WARNING_BEGIN("-Wself-move");
9696
sut = std::move(sut);
97-
DOCTEST_SUPPRESS_WARNING_END;
97+
TEST_SUPPRESS_WARNING_END;
9898

9999
CHECK_EQ(sut.size(), 2uz);
100100
CHECK_EQ(sut.data_size(), 5uz);

tests/source/gl/test_flat_matrix.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@ TEST_CASE_FIXTURE(
9898
sut.push_row({1, 2, 3});
9999
sut.push_row({4, 5, 6});
100100

101-
DOCTEST_SUPPRESS_WARNING_BEGIN("-Wself-move");
101+
TEST_SUPPRESS_WARNING_BEGIN("-Wself-move");
102102
sut = std::move(sut);
103-
DOCTEST_SUPPRESS_WARNING_END;
103+
TEST_SUPPRESS_WARNING_END;
104104

105105
CHECK_EQ(sut.size(), 2uz);
106106
CHECK_EQ(sut.n_rows(), 2uz);

0 commit comments

Comments
 (0)