22#ifndef LIBSEMIGROUPS_DETAIL_NODE_MANAGER_HPP_
23#define LIBSEMIGROUPS_DETAIL_NODE_MANAGER_HPP_
31#include "libsemigroups/config.hpp"
32#include "libsemigroups/constants.hpp"
33#include "libsemigroups/debug.hpp"
34#include "libsemigroups/exception.hpp"
35#include "libsemigroups/ranges.hpp"
39 template <
typename Node>
46 using node_type = Node;
47 using Perm = std::vector<node_type>;
54 node_type _current_la;
60 static constexpr node_type _id_node = 0;
62 std::vector<node_type> _bckwd;
63 node_type _first_free_node;
64 std::vector<node_type> _forwd;
66 mutable std::vector<node_type> _ident;
67 node_type _last_active_node;
70 std::atomic_uint64_t num_nodes_active;
71 std::atomic_uint64_t num_nodes_defined;
72 std::atomic_uint64_t num_nodes_killed;
75 : num_nodes_active(1), num_nodes_defined(1), num_nodes_killed(0) {}
77 Stats(Stats
const& that)
78 : num_nodes_active(that.num_nodes_active.load()),
79 num_nodes_defined(that.num_nodes_defined.load()),
80 num_nodes_killed(that.num_nodes_killed.load()) {}
83 : num_nodes_active(that.num_nodes_active.load()),
84 num_nodes_defined(that.num_nodes_defined.load()),
85 num_nodes_killed(that.num_nodes_killed.load()) {}
87 Stats& operator=(Stats
const& that) {
88 num_nodes_active = that.num_nodes_active.load();
89 num_nodes_defined = that.num_nodes_defined.load();
90 num_nodes_killed = that.num_nodes_killed.load();
94 Stats& operator=(Stats&& that) {
95 num_nodes_active = that.num_nodes_active.load();
96 num_nodes_defined = that.num_nodes_defined.load();
97 num_nodes_killed = that.num_nodes_killed.load();
109 NodeManager(NodeManager
const& that);
110 NodeManager(NodeManager&&) =
default;
112 NodeManager& operator=(NodeManager
const& that);
113 NodeManager& operator=(NodeManager&&) =
default;
121 node_type& cursor() {
125 node_type& lookahead_cursor() {
129 node_type
const& lookahead_cursor()
const {
134 inline size_t node_capacity() const noexcept {
135 return _forwd.size();
138 inline node_type first_free_node() const noexcept {
139 return _first_free_node;
142 inline bool has_free_nodes() const noexcept {
147 inline bool is_active_node(node_type c)
const {
148 LIBSEMIGROUPS_ASSERT(c < _ident.size() || c ==
UNDEFINED);
152 [[nodiscard]]
size_t position_of_node(node_type n)
const;
154 inline bool is_valid_node(node_type c)
const noexcept {
155 return c < _forwd.size();
159 inline node_type next_active_node(node_type c)
const {
165 auto cbegin_active_nodes()
const {
166 return rx::begin(ActiveNodesRange(
this));
171 auto cend_active_nodes()
const {
172 return rx::end(ActiveNodesRange(
this));
175 inline uint64_t number_of_nodes_active() const noexcept {
176 return _stats.num_nodes_active;
179 inline uint64_t number_of_nodes_defined() const noexcept {
180 return _stats.num_nodes_defined;
183 inline uint64_t number_of_nodes_killed() const noexcept {
184 return _stats.num_nodes_killed;
187 NodeManager& growth_factor(
float val);
189 float growth_factor() const noexcept {
190 return _growth_factor;
200 inline void union_nodes(node_type min, node_type max) {
201 LIBSEMIGROUPS_ASSERT(is_active_node(min));
202 LIBSEMIGROUPS_ASSERT(is_active_node(max));
203 LIBSEMIGROUPS_ASSERT(max > min);
212 inline node_type find_node(node_type c)
const {
213 LIBSEMIGROUPS_ASSERT(is_valid_node(c));
215 node_type d = _ident[c];
219 node_type e = _ident[d];
226 LIBSEMIGROUPS_ASSERT(is_active_node(c));
230 void add_active_nodes(
size_t);
231 void add_free_nodes(
size_t);
232 void erase_free_nodes();
233 node_type new_active_node();
235 void switch_nodes(node_type
const, node_type
const);
237 void apply_permutation(Perm p);
243 void free_node(node_type
const);
249 constexpr node_type initial_node() const noexcept {
254 void compact(
size_t N);
256 struct ActiveNodesRange {
257 using output_type = node_type;
259 NodeManager
const* _node_manager;
260 output_type _current;
262 ActiveNodesRange() : _node_manager(nullptr), _current(
UNDEFINED) {}
264 explicit ActiveNodesRange(NodeManager
const* nm)
265 : _node_manager(nm), _current(nm->initial_node()) {}
267 output_type get() const noexcept {
271 void next() noexcept {
272 _current = _node_manager->next_active_node(_current);
275 bool at_end() const noexcept {
276 return _node_manager ==
nullptr
277 || _current == _node_manager->first_free_node();
280 size_t size_hint() const noexcept {
281 return _node_manager->number_of_nodes_active();
284 static constexpr bool is_finite =
true;
285 static constexpr bool is_idempotent =
true;
289 ActiveNodesRange active_nodes()
const {
290 return ActiveNodesRange(
this);
293#ifdef LIBSEMIGROUPS_DEBUG
299 void debug_validate_forwd_bckwd()
const;
306#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
309struct rx::is_input_range<
310 typename
libsemigroups::detail::NodeManager<uint32_t>::ActiveNodesRange>
313#include "node-manager.tpp"
Undefined const UNDEFINED
Value for something undefined.
Namespace for everything in the libsemigroups library.
Definition action.hpp:44