adjacency_matrix: single edge iterator

This commit is contained in:
Michele Caini
2022-06-21 18:11:36 +02:00
parent 610951771e
commit e4aabc7feb
2 changed files with 23 additions and 85 deletions

2
TODO
View File

@@ -13,8 +13,6 @@ DOC:
* update entity doc when the storage based model is in place
WIP:
* refine graph iterators a little
* add directed/undirected support to dot
* dense_map/set and registry: move ctor/op should be noexcept (op is conditionally noexcept though)
* "replace" organizer with flow
* add storage getter for filters to views and groups

View File

@@ -21,7 +21,7 @@ namespace entt {
namespace internal {
template<typename It>
class row_edge_iterator {
class edge_iterator {
using size_type = std::size_t;
public:
@@ -31,27 +31,29 @@ public:
using difference_type = std::ptrdiff_t;
using iterator_category = std::input_iterator_tag;
constexpr row_edge_iterator() noexcept
constexpr edge_iterator() noexcept
: it{},
vert{},
pos{},
last{} {}
last{},
offset{} {}
constexpr row_edge_iterator(It base, const size_type vertices, const size_type from, const size_type to) noexcept
constexpr edge_iterator(It base, const size_type vertices, const size_type from, const size_type to, const size_type step) noexcept
: it{std::move(base)},
vert{vertices},
pos{from},
last{to} {
for(; pos != last && !it[pos]; ++pos) {}
last{to},
offset{step} {
for(; pos != last && !it[pos]; pos += offset) {}
}
constexpr row_edge_iterator &operator++() noexcept {
for(++pos; pos != last && !it[pos]; ++pos) {}
constexpr edge_iterator &operator++() noexcept {
for(pos += offset; pos != last && !it[pos]; pos += offset) {}
return *this;
}
constexpr row_edge_iterator operator++(int) noexcept {
row_edge_iterator orig = *this;
constexpr edge_iterator operator++(int) noexcept {
edge_iterator orig = *this;
return ++(*this), orig;
}
@@ -64,85 +66,23 @@ public:
}
template<typename Type>
friend constexpr bool operator==(const row_edge_iterator<Type> &, const row_edge_iterator<Type> &) noexcept;
friend constexpr bool operator==(const edge_iterator<Type> &, const edge_iterator<Type> &) noexcept;
private:
It it;
size_type vert;
size_type pos;
size_type last;
size_type offset{};
};
template<typename Container>
[[nodiscard]] inline constexpr bool operator==(const row_edge_iterator<Container> &lhs, const row_edge_iterator<Container> &rhs) noexcept {
[[nodiscard]] inline constexpr bool operator==(const edge_iterator<Container> &lhs, const edge_iterator<Container> &rhs) noexcept {
return lhs.pos == rhs.pos;
}
template<typename Container>
[[nodiscard]] inline constexpr bool operator!=(const row_edge_iterator<Container> &lhs, const row_edge_iterator<Container> &rhs) noexcept {
return !(lhs == rhs);
}
template<typename It>
class col_edge_iterator {
using size_type = std::size_t;
public:
using value_type = std::pair<size_type, size_type>;
using pointer = input_iterator_pointer<value_type>;
using reference = value_type;
using difference_type = std::ptrdiff_t;
using iterator_category = std::input_iterator_tag;
constexpr col_edge_iterator() noexcept
: it{},
vert{},
pos{},
last{} {}
constexpr col_edge_iterator(It base, const size_type vertices, const size_type from, const size_type to) noexcept
: it{std::move(base)},
vert{vertices},
pos{from},
last{to} {
for(; pos != last && !it[pos]; pos += vert) {}
}
constexpr col_edge_iterator &operator++() noexcept {
for(pos += vert; pos != last && !it[pos]; pos += vert) {}
return *this;
}
constexpr col_edge_iterator operator++(int) noexcept {
col_edge_iterator orig = *this;
return ++(*this), orig;
}
[[nodiscard]] constexpr reference operator*() const noexcept {
return *operator->();
}
[[nodiscard]] constexpr pointer operator->() const noexcept {
return std::make_pair<size_type>(pos / vert, pos % vert);
}
template<typename Type>
friend constexpr bool operator==(const col_edge_iterator<Type> &, const col_edge_iterator<Type> &) noexcept;
private:
It it;
size_type vert;
size_type pos;
size_type last;
};
template<typename Container>
[[nodiscard]] inline constexpr bool operator==(const col_edge_iterator<Container> &lhs, const col_edge_iterator<Container> &rhs) noexcept {
return lhs.pos == rhs.pos;
}
template<typename Container>
[[nodiscard]] inline constexpr bool operator!=(const col_edge_iterator<Container> &lhs, const col_edge_iterator<Container> &rhs) noexcept {
[[nodiscard]] inline constexpr bool operator!=(const edge_iterator<Container> &lhs, const edge_iterator<Container> &rhs) noexcept {
return !(lhs == rhs);
}
@@ -177,11 +117,11 @@ public:
/*! @brief Vertex iterator type. */
using vertex_iterator = iota_iterator<vertex_type>;
/*! @brief Edge iterator type. */
using edge_iterator = internal::row_edge_iterator<typename container_type::const_iterator>;
using edge_iterator = internal::edge_iterator<typename container_type::const_iterator>;
/*! @brief Out edge iterator type. */
using out_edge_iterator = internal::row_edge_iterator<typename container_type::const_iterator>;
using out_edge_iterator = edge_iterator;
/*! @brief In edge iterator type. */
using in_edge_iterator = internal::col_edge_iterator<typename container_type::const_iterator>;
using in_edge_iterator = edge_iterator;
/*! @brieg Graph category tag. */
using graph_category = Category;
@@ -307,7 +247,7 @@ public:
[[nodiscard]] iterable_adaptor<edge_iterator> edges() const noexcept {
const auto it = matrix.cbegin();
const auto sz = matrix.size();
return {{it, vert, 0u, sz}, {it, vert, sz, sz}};
return {{it, vert, 0u, sz, 1u}, {it, vert, sz, sz, 1u}};
}
/**
@@ -319,7 +259,7 @@ public:
const auto it = matrix.cbegin();
const auto from = vertex * vert;
const auto to = vertex * vert + vert;
return {{it, vert, from, to}, {it, vert, to, to}};
return {{it, vert, from, to, 1u}, {it, vert, to, to, 1u}};
}
/**
@@ -331,7 +271,7 @@ public:
const auto it = matrix.cbegin();
const auto from = vertex;
const auto to = vert * (vert - 1u) + vertex;
return {{it, vert, from, to}, {it, vert, to, to}};
return {{it, vert, from, to, vert}, {it, vert, to, to, vert}};
}
/**
@@ -366,7 +306,7 @@ public:
}
const auto inserted = !std::exchange(matrix[pos], 1u);
return {edge_iterator{matrix.cbegin(), vert, pos, matrix.size()}, inserted};
return {edge_iterator{matrix.cbegin(), vert, pos, matrix.size(), 1u}, inserted};
}
/**