Skip to content

Commit 742b5ba

Browse files
committed
wip: flat incidence matrix impl
1 parent 112a859 commit 742b5ba

11 files changed

Lines changed: 2337 additions & 81 deletions

File tree

include/gl/impl/adjacency_matrix.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,17 +107,17 @@ class adjacency_matrix final {
107107
}
108108

109109
[[nodiscard]] gl_attr_force_inline bool has_edge(id_type source_id, id_type target_id) const {
110-
return this->_matrix[to_idx(source_id)][to_idx(target_id)] != invalid_id;
110+
return specialized_impl::get_edge_id(*this, source_id, target_id) != invalid_id;
111111
}
112112

113113
[[nodiscard]] bool has_edge(const edge_type& edge) const {
114-
return this->_matrix[to_idx(edge.source())][to_idx(edge.target())] == edge.id();
114+
return specialized_impl::get_edge_id(*this, edge.source(), edge.target()) == edge.id();
115115
}
116116

117117
[[nodiscard]] std::optional<edge_type> get_edge(id_type source_id, id_type target_id) const
118118
requires(traits::c_has_empty_properties<edge_type>)
119119
{
120-
const auto edge_id = this->_matrix[to_idx(source_id)][to_idx(target_id)];
120+
const auto edge_id = specialized_impl::get_edge_id(*this, source_id, target_id);
121121
if (edge_id == invalid_id)
122122
return std::nullopt;
123123
return std::make_optional<edge_type>(edge_id, source_id, target_id);
@@ -128,7 +128,7 @@ class adjacency_matrix final {
128128
) const
129129
requires(traits::c_has_non_empty_properties<edge_type>)
130130
{
131-
const auto edge_id = this->_matrix[to_idx(source_id)][to_idx(target_id)];
131+
const auto edge_id = specialized_impl::get_edge_id(*this, source_id, target_id);
132132
if (edge_id == invalid_id)
133133
return std::nullopt;
134134
return std::make_optional<edge_type>(
@@ -139,7 +139,7 @@ class adjacency_matrix final {
139139
[[nodiscard]] std::vector<edge_type> get_edges(id_type source_id, id_type target_id) const
140140
requires(traits::c_has_empty_properties<edge_type>)
141141
{
142-
const auto edge_id = this->_matrix[to_idx(source_id)][to_idx(target_id)];
142+
const auto edge_id = specialized_impl::get_edge_id(*this, source_id, target_id);
143143
if (edge_id == invalid_id)
144144
return std::vector<edge_type>();
145145
return std::vector<edge_type>{
@@ -152,7 +152,7 @@ class adjacency_matrix final {
152152
) const
153153
requires(traits::c_has_non_empty_properties<edge_type>)
154154
{
155-
const auto edge_id = this->_matrix[to_idx(source_id)][to_idx(target_id)];
155+
const auto edge_id = specialized_impl::get_edge_id(*this, source_id, target_id);
156156
if (edge_id == invalid_id)
157157
return std::vector<edge_type>();
158158
return std::vector<edge_type>{

include/gl/impl/specialized/adjacency_matrix.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ struct directed_adjacency_matrix {
165165
return removed_edges;
166166
}
167167

168+
static id_type get_edge_id(const impl_type& self, id_type source_id, id_type target_id) {
169+
return self._matrix[to_idx(source_id)][to_idx(target_id)];
170+
}
171+
168172
static inline void add_edge(
169173
impl_type& self, id_type edge_id, id_type source_id, id_type target_id
170174
) {
@@ -285,6 +289,10 @@ struct undirected_adjacency_matrix {
285289
return removed_edges;
286290
}
287291

292+
static id_type get_edge_id(const impl_type& self, id_type source_id, id_type target_id) {
293+
return self._matrix[to_idx(source_id)][to_idx(target_id)];
294+
}
295+
288296
static void add_edge(impl_type& self, id_type edge_id, id_type source_id, id_type target_id) {
289297
detail::check_edge_override(self._matrix, source_id, target_id);
290298

include/gl/impl/specialized/flat_adjacency_matrix.hpp

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#pragma once
66

7+
#include "gl/attributes/diagnostics.hpp"
78
#include "gl/constants.hpp"
89
#include "gl/decl/impl_tags.hpp"
910
#include "gl/graph_traits.hpp"
@@ -19,6 +20,36 @@
1920

2021
namespace gl::impl::specialized {
2122

23+
namespace detail {
24+
25+
template <traits::c_id_type IdType>
26+
[[nodiscard]] auto& strict_get(flat_matrix<IdType>& id_matrix, const auto& edge) {
27+
// get the edge and validate the address
28+
const auto [source_id, target_id] = edge.incident_vertices();
29+
auto& edge_id = id_matrix[to_idx(source_id), to_idx(target_id)];
30+
if (edge.id() != edge_id)
31+
throw std::invalid_argument(std::format(
32+
"Got invalid edge [id = {} | vertices = ({}, {})]", edge.id(), source_id, target_id
33+
));
34+
35+
return edge_id;
36+
}
37+
38+
template <traits::c_id_type IdType>
39+
inline void check_edge_override(
40+
const flat_matrix<IdType>& id_matrix, const IdType source_id, const IdType target_id
41+
) {
42+
if (const auto edge_id = id_matrix[to_idx(source_id), to_idx(target_id)]; edge_id != invalid_id)
43+
throw std::logic_error(std::format(
44+
"Cannot override an existing edge: [id = {}, vertices = ({}, {})]",
45+
edge_id,
46+
source_id,
47+
target_id
48+
));
49+
}
50+
51+
} // namespace detail
52+
2253
template <traits::c_instantiation_of<adjacency_matrix> AdjacencyMatrix>
2354
requires(traits::c_directed_edge<typename AdjacencyMatrix::edge_type>)
2455
struct directed_flat_adjacency_matrix {
@@ -133,6 +164,10 @@ struct directed_flat_adjacency_matrix {
133164
return removed_edges;
134165
}
135166

167+
static id_type get_edge_id(const impl_type& self, id_type source_id, id_type target_id) {
168+
return self._matrix[to_idx(source_id), to_idx(target_id)];
169+
}
170+
136171
static inline void add_edge(
137172
impl_type& self, id_type edge_id, id_type source_id, id_type target_id
138173
) {
@@ -151,7 +186,7 @@ struct directed_flat_adjacency_matrix {
151186

152187
auto matrix_source_row = self._matrix[to_idx(source_id)];
153188
for (auto [edge_id, target_id] : std::views::zip(edge_ids, target_ids))
154-
matrix_source_row[to_idx(target_id)] = edge_id;
189+
matrix_source_row[to_diff(target_id)] = edge_id;
155190
}
156191

157192
static inline void remove_edge(impl_type& self, const edge_type& edge) {
@@ -246,6 +281,10 @@ struct undirected_flat_adjacency_matrix {
246281
return removed_edges;
247282
}
248283

284+
static id_type get_edge_id(const impl_type& self, id_type source_id, id_type target_id) {
285+
return self._matrix[to_idx(source_id), to_idx(target_id)];
286+
}
287+
249288
static void add_edge(impl_type& self, id_type edge_id, id_type source_id, id_type target_id) {
250289
detail::check_edge_override(self._matrix, source_id, target_id);
251290

@@ -271,7 +310,7 @@ struct undirected_flat_adjacency_matrix {
271310

272311
for (auto [edge_id, target_id] : std::views::zip(edge_ids, target_ids)) {
273312
const auto target_idx = to_idx(target_id);
274-
matrix_source_row[target_idx] = edge_id;
313+
matrix_source_row[to_diff(target_id)] = edge_id;
275314
if (target_idx != source_idx)
276315
self._matrix[target_idx, source_idx] = edge_id;
277316
}

include/gl/types/core.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "gl/attributes/force_inline.hpp"
88

99
#include <concepts>
10+
#include <cstddef>
1011
#include <cstdint>
1112
#include <optional>
1213
#include <utility>
@@ -27,6 +28,11 @@ concept c_id_type = std::unsigned_integral<T>;
2728
return static_cast<size_type>(id);
2829
}
2930

31+
// TODO: replace static_cast calls with to_diff
32+
[[nodiscard]] gl_attr_force_inline constexpr std::ptrdiff_t to_diff(std::integral auto i) noexcept {
33+
return static_cast<std::ptrdiff_t>(i);
34+
}
35+
3036
template <typename T>
3137
using homogeneous_pair = std::pair<T, T>;
3238

0 commit comments

Comments
 (0)