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"
1920
2021namespace 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+
2253template <traits::c_instantiation_of<adjacency_matrix> AdjacencyMatrix>
2354requires (traits::c_directed_edge<typename AdjacencyMatrix::edge_type>)
2455struct directed_flat_adjacency_matrix {
@@ -66,9 +97,10 @@ struct directed_flat_adjacency_matrix {
6697 const auto row = self._matrix [vertex_idx];
6798 const auto col = self._matrix .col (vertex_idx);
6899
69- for (auto v_idx = 0uz; v_idx < self._matrix .n_rows (); ++v_idx)
70- deg += static_cast <size_type>(row[v_idx] != invalid_id)
71- + static_cast <size_type>(col[static_cast <std::ptrdiff_t >(v_idx)] != invalid_id);
100+ const auto n_rows_bound = to_diff (self._matrix .n_rows ());
101+ for (auto v_pos = 0z; v_pos < n_rows_bound; ++v_pos)
102+ deg += static_cast <size_type>(row[v_pos] != invalid_id)
103+ + static_cast <size_type>(col[v_pos] != invalid_id);
72104
73105 return deg;
74106 }
@@ -121,7 +153,7 @@ struct directed_flat_adjacency_matrix {
121153 if (r_idx == vertex_idx)
122154 continue ;
123155
124- const auto edge_id = col[static_cast <std:: ptrdiff_t > (r_idx)];
156+ const auto edge_id = col[to_diff (r_idx)];
125157 if (edge_id != invalid_id)
126158 removed_edges.push_back (edge_id);
127159 }
@@ -133,6 +165,10 @@ struct directed_flat_adjacency_matrix {
133165 return removed_edges;
134166 }
135167
168+ static id_type get_entry (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+
136172 static inline void add_edge (
137173 impl_type& self, id_type edge_id, id_type source_id, id_type target_id
138174 ) {
@@ -151,7 +187,7 @@ struct directed_flat_adjacency_matrix {
151187
152188 auto matrix_source_row = self._matrix [to_idx (source_id)];
153189 for (auto [edge_id, target_id] : std::views::zip (edge_ids, target_ids))
154- matrix_source_row[to_idx (target_id)] = edge_id;
190+ matrix_source_row[to_diff (target_id)] = edge_id;
155191 }
156192
157193 static inline void remove_edge (impl_type& self, const edge_type& edge) {
@@ -246,6 +282,10 @@ struct undirected_flat_adjacency_matrix {
246282 return removed_edges;
247283 }
248284
285+ static id_type get_entry (const impl_type& self, id_type source_id, id_type target_id) {
286+ return self._matrix [to_idx (source_id), to_idx (target_id)];
287+ }
288+
249289 static void add_edge (impl_type& self, id_type edge_id, id_type source_id, id_type target_id) {
250290 detail::check_edge_override (self._matrix , source_id, target_id);
251291
@@ -271,7 +311,7 @@ struct undirected_flat_adjacency_matrix {
271311
272312 for (auto [edge_id, target_id] : std::views::zip (edge_ids, target_ids)) {
273313 const auto target_idx = to_idx (target_id);
274- matrix_source_row[target_idx ] = edge_id;
314+ matrix_source_row[to_diff (target_id) ] = edge_id;
275315 if (target_idx != source_idx)
276316 self._matrix [target_idx, source_idx] = edge_id;
277317 }
0 commit comments