26#ifndef LIBSEMIGROUPS_DETAIL_NODE_MANAGER_HPP_
27#define LIBSEMIGROUPS_DETAIL_NODE_MANAGER_HPP_
35#include "libsemigroups/config.hpp"
36#include "libsemigroups/constants.hpp"
37#include "libsemigroups/debug.hpp"
38#include "libsemigroups/exception.hpp"
39#include "libsemigroups/ranges.hpp"
43 template <
typename Node>
50 using node_type = Node;
51 using Perm = std::vector<node_type>;
58 node_type _current_la;
64 static constexpr node_type _id_node = 0;
66 std::vector<node_type> _bckwd;
67 node_type _first_free_node;
68 std::vector<node_type> _forwd;
70 mutable std::vector<node_type> _ident;
71 node_type _last_active_node;
74 std::atomic_uint64_t num_nodes_active;
75 std::atomic_uint64_t num_nodes_defined;
76 std::atomic_uint64_t num_nodes_killed;
78 Stats() : num_nodes_active(), num_nodes_defined(), num_nodes_killed() {
84 num_nodes_defined = 1;
89 Stats(Stats
const& that)
90 : num_nodes_active(that.num_nodes_active.load()),
91 num_nodes_defined(that.num_nodes_defined.load()),
92 num_nodes_killed(that.num_nodes_killed.load()) {}
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()) {}
99 Stats& operator=(Stats
const& that) {
100 num_nodes_active = that.num_nodes_active.load();
101 num_nodes_defined = that.num_nodes_defined.load();
102 num_nodes_killed = that.num_nodes_killed.load();
106 Stats& operator=(Stats&& that) {
107 num_nodes_active = that.num_nodes_active.load();
108 num_nodes_defined = that.num_nodes_defined.load();
109 num_nodes_killed = that.num_nodes_killed.load();
122 NodeManager(NodeManager
const& that);
123 NodeManager(NodeManager&&) =
default;
125 NodeManager& operator=(NodeManager
const& that);
126 NodeManager& operator=(NodeManager&&) =
default;
134 node_type& cursor() {
138 node_type& lookahead_cursor() {
142 node_type
const& lookahead_cursor()
const {
147 inline size_t node_capacity() const noexcept {
148 return _forwd.size();
151 inline node_type first_free_node() const noexcept {
152 return _first_free_node;
155 inline bool has_free_nodes() const noexcept {
160 inline bool is_active_node(node_type c)
const {
161 LIBSEMIGROUPS_ASSERT(c < _ident.size() || c ==
UNDEFINED);
165 [[nodiscard]]
size_t position_of_node(node_type n)
const;
167 inline bool is_valid_node(node_type c)
const noexcept {
168 return c < _forwd.size();
172 inline node_type next_active_node(node_type c)
const {
178 auto cbegin_active_nodes()
const {
179 return rx::begin(ActiveNodesRange(
this));
184 auto cend_active_nodes()
const {
185 return rx::end(ActiveNodesRange(
this));
188 inline uint64_t number_of_nodes_active() const noexcept {
189 return _stats.num_nodes_active;
192 inline uint64_t number_of_nodes_defined() const noexcept {
193 return _stats.num_nodes_defined;
196 inline uint64_t number_of_nodes_killed() const noexcept {
197 return _stats.num_nodes_killed;
200 NodeManager& growth_factor(
float val);
202 float growth_factor() const noexcept {
203 return _growth_factor;
213 inline void union_nodes(node_type min, node_type max) {
214 LIBSEMIGROUPS_ASSERT(is_active_node(min));
215 LIBSEMIGROUPS_ASSERT(is_active_node(max));
216 LIBSEMIGROUPS_ASSERT(max > min);
225 inline node_type find_node(node_type c)
const {
226 LIBSEMIGROUPS_ASSERT(is_valid_node(c));
228 node_type d = _ident[c];
232 node_type e = _ident[d];
239 LIBSEMIGROUPS_ASSERT(is_active_node(c));
243 void add_active_nodes(
size_t);
244 void add_free_nodes(
size_t);
245 void erase_free_nodes();
246 node_type new_active_node();
249 void switch_nodes(node_type
const, node_type
const);
251 void apply_permutation(Perm p);
257 void free_node(node_type
const);
259 constexpr node_type initial_node() const noexcept {
263 [[nodiscard]] node_type max_active_node() const noexcept;
266 void compact(
size_t N);
268 struct ActiveNodesRange {
269 using output_type = node_type;
271 NodeManager
const* _node_manager;
272 output_type _current;
274 ActiveNodesRange() : _node_manager(nullptr), _current(
UNDEFINED) {}
276 explicit ActiveNodesRange(NodeManager
const* nm)
277 : _node_manager(nm), _current(nm->initial_node()) {}
279 output_type get() const noexcept {
283 void next() noexcept {
284 _current = _node_manager->next_active_node(_current);
287 bool at_end() const noexcept {
288 return _node_manager ==
nullptr
289 || _current == _node_manager->first_free_node();
292 size_t size_hint() const noexcept {
293 return _node_manager->number_of_nodes_active();
296 static constexpr bool is_finite =
true;
297 static constexpr bool is_idempotent =
true;
301 ActiveNodesRange active_nodes()
const {
302 return ActiveNodesRange(
this);
305#ifdef LIBSEMIGROUPS_DEBUG
311 void debug_validate_forwd_bckwd()
const;
318#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
321struct rx::is_input_range<
322 typename
libsemigroups::detail::NodeManager<uint32_t>::ActiveNodesRange>
325#include "node-manager.tpp"
Undefined const UNDEFINED
Value for something undefined.
Namespace for everything in the libsemigroups library.
Definition action.hpp:44