- Missing functionality and documentation
This commit is contained in:
@@ -48,7 +48,7 @@ PROJECT_NAME = fennec
|
|||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = 1.0.2
|
PROJECT_NUMBER =
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||||
# for a project that appears at the top of each page and should give viewer a
|
# for a project that appears at the top of each page and should give viewer a
|
||||||
@@ -129,7 +129,7 @@ BRIEF_MEMBER_DESC = YES
|
|||||||
# brief descriptions will be completely suppressed.
|
# brief descriptions will be completely suppressed.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
REPEAT_BRIEF = YES
|
REPEAT_BRIEF = NO
|
||||||
|
|
||||||
# This tag implements a quasi-intelligent brief description abbreviator that is
|
# This tag implements a quasi-intelligent brief description abbreviator that is
|
||||||
# used to form the text in various listings. Each string in this list, if found
|
# used to form the text in various listings. Each string in this list, if found
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ BRIEF_MEMBER_DESC = YES
|
|||||||
# brief descriptions will be completely suppressed.
|
# brief descriptions will be completely suppressed.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
REPEAT_BRIEF = YES
|
REPEAT_BRIEF = NO
|
||||||
|
|
||||||
# This tag implements a quasi-intelligent brief description abbreviator that is
|
# This tag implements a quasi-intelligent brief description abbreviator that is
|
||||||
# used to form the text in various listings. Each string in this list, if found
|
# used to form the text in various listings. Each string in this list, if found
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \file array.h
|
/// \file array.h
|
||||||
/// \brief statically allocated array wrapper
|
/// \brief A header containing the definition for a static/stack allocated array
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// \details
|
/// \details
|
||||||
@@ -132,11 +132,13 @@ struct array
|
|||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief
|
/// \brief Checks if all elements in the arrays are equal
|
||||||
friend constexpr bool_t operator==(const array& lhs, const array& rhs) {
|
friend constexpr bool_t operator==(const array& lhs, const array& rhs) {
|
||||||
return array::_compare(lhs, rhs, make_index_sequence<ElemV>{});
|
return array::_compare(lhs, rhs, make_index_sequence<ElemV>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Checks if any element in the arrays is not equal
|
||||||
friend constexpr bool_t operator!=(const array& lhs, const array& rhs) {
|
friend constexpr bool_t operator!=(const array& lhs, const array& rhs) {
|
||||||
return not array::_compare(lhs, rhs, make_index_sequence<ElemV>{});
|
return not array::_compare(lhs, rhs, make_index_sequence<ElemV>{});
|
||||||
}
|
}
|
||||||
@@ -150,12 +152,14 @@ struct array
|
|||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
|
/// \brief C++ Iterator Specification `begin()`
|
||||||
/// \returns A pointer to the first element of the array
|
/// \returns A pointer to the first element of the array
|
||||||
constexpr ValueT* begin() {
|
constexpr ValueT* begin() {
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
/// \brief C++ Iterator Specification `end()`
|
||||||
/// \returns A pointer to one after the end of the array
|
/// \returns A pointer to one after the end of the array
|
||||||
constexpr ValueT* end() {
|
constexpr ValueT* end() {
|
||||||
return elements + ElemV;
|
return elements + ElemV;
|
||||||
@@ -164,12 +168,14 @@ struct array
|
|||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
|
/// \brief Const C++ Iterator Specification `begin()`
|
||||||
/// \returns A const-qualified pointer to the first element of the array
|
/// \returns A const-qualified pointer to the first element of the array
|
||||||
constexpr const ValueT* begin() const {
|
constexpr const ValueT* begin() const {
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
/// \brief Const C++ Iterator Specification `end()`
|
||||||
/// \returns A const-qualified pointer to one after the end of the array
|
/// \returns A const-qualified pointer to one after the end of the array
|
||||||
constexpr const ValueT* end() const {
|
constexpr const ValueT* end() const {
|
||||||
return elements + ElemV;
|
return elements + ElemV;
|
||||||
|
|||||||
@@ -16,6 +16,18 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file deque.h
|
||||||
|
/// \brief A header containing the definition for a double-ended queue
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
#ifndef FENNEC_CONTAINERS_DEQUE_H
|
#ifndef FENNEC_CONTAINERS_DEQUE_H
|
||||||
#define FENNEC_CONTAINERS_DEQUE_H
|
#define FENNEC_CONTAINERS_DEQUE_H
|
||||||
|
|
||||||
@@ -54,7 +66,7 @@ struct deque {
|
|||||||
|
|
||||||
// Definitions =========================================================================================================
|
// Definitions =========================================================================================================
|
||||||
public:
|
public:
|
||||||
using value_t = TypeT;
|
using value_t = TypeT; ///< Alias for the value type
|
||||||
class iterator;
|
class iterator;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \file dynarray.h
|
/// \file dynarray.h
|
||||||
/// \brief dynamically allocated array wrapper
|
/// \brief A header containing the definition for a dynamically allocated array
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// \details
|
/// \details
|
||||||
@@ -40,7 +40,7 @@ namespace fennec
|
|||||||
|
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// \brief Wrapper for dynamically sized arrays
|
/// \brief Wrapper for dynamically sized and allocated arrays
|
||||||
/// \details
|
/// \details
|
||||||
/// | Property | Value |
|
/// | Property | Value |
|
||||||
/// |:----------:|:----------:|
|
/// |:----------:|:----------:|
|
||||||
@@ -56,6 +56,8 @@ namespace fennec
|
|||||||
/// | insertion | \f$O(N)\f$ |
|
/// | insertion | \f$O(N)\f$ |
|
||||||
/// | deletion | \f$O(N)\f$ |
|
/// | deletion | \f$O(N)\f$ |
|
||||||
///
|
///
|
||||||
|
/// This structure prefers shallow moves and deep copies.
|
||||||
|
///
|
||||||
/// \tparam TypeT value type
|
/// \tparam TypeT value type
|
||||||
template<class TypeT, class Alloc = allocator<TypeT>>
|
template<class TypeT, class Alloc = allocator<TypeT>>
|
||||||
class dynarray {
|
class dynarray {
|
||||||
@@ -63,8 +65,8 @@ public:
|
|||||||
|
|
||||||
// Definitions =========================================================================================================
|
// Definitions =========================================================================================================
|
||||||
|
|
||||||
using element_t = TypeT;
|
using value_t = TypeT; ///< Alias for the value type
|
||||||
using alloc_t = Alloc;
|
using alloc_t = Alloc; ///< Alias for the allocator type
|
||||||
|
|
||||||
|
|
||||||
// Constructors ========================================================================================================
|
// Constructors ========================================================================================================
|
||||||
@@ -83,7 +85,7 @@ public:
|
|||||||
/// \brief Alloc Constructor, initialize empty allocation with allocator instance.
|
/// \brief Alloc Constructor, initialize empty allocation with allocator instance.
|
||||||
/// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some
|
/// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some
|
||||||
/// data.
|
/// data.
|
||||||
constexpr dynarray(const alloc_t& alloc)
|
explicit constexpr dynarray(const alloc_t& alloc)
|
||||||
: _alloc(8, alloc)
|
: _alloc(8, alloc)
|
||||||
, _size(0) {
|
, _size(0) {
|
||||||
}
|
}
|
||||||
@@ -92,19 +94,19 @@ public:
|
|||||||
/// \brief Alloc Move Constructor, initialize empty allocation with allocator instance.
|
/// \brief Alloc Move Constructor, initialize empty allocation with allocator instance.
|
||||||
/// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some
|
/// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some
|
||||||
/// data.
|
/// data.
|
||||||
constexpr dynarray(alloc_t&& alloc) noexcept
|
explicit constexpr dynarray(alloc_t&& alloc) noexcept
|
||||||
: _alloc(8, alloc)
|
: _alloc(8, alloc)
|
||||||
, _size(0) {
|
, _size(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Sized Allocation, create an allocation of size `n` elements,
|
/// \brief Sized Allocation, initializes a dynarray with `n` elements using the default constructor.
|
||||||
/// initialized with the default constructor.
|
/// \param n The number of elements.
|
||||||
constexpr dynarray(size_t n)
|
explicit constexpr dynarray(size_t n)
|
||||||
: _alloc(n)
|
: _alloc(n)
|
||||||
, _size(n)
|
, _size(n)
|
||||||
{
|
{
|
||||||
element_t* addr = _alloc.data();
|
value_t* addr = _alloc.data();
|
||||||
for(; n > 0; --n, ++addr) {
|
for(; n > 0; --n, ++addr) {
|
||||||
fennec::construct(addr);
|
fennec::construct(addr);
|
||||||
}
|
}
|
||||||
@@ -118,7 +120,7 @@ public:
|
|||||||
constexpr dynarray(size_t n, const alloc_t& alloc)
|
constexpr dynarray(size_t n, const alloc_t& alloc)
|
||||||
: _alloc(n, alloc)
|
: _alloc(n, alloc)
|
||||||
, _size(n) {
|
, _size(n) {
|
||||||
element_t* addr = _alloc.data();
|
value_t* addr = _alloc.data();
|
||||||
for(; n > 0; --n, ++addr) {
|
for(; n > 0; --n, ++addr) {
|
||||||
fennec::construct(addr);
|
fennec::construct(addr);
|
||||||
}
|
}
|
||||||
@@ -132,7 +134,7 @@ public:
|
|||||||
constexpr dynarray(size_t n, alloc_t&& alloc)
|
constexpr dynarray(size_t n, alloc_t&& alloc)
|
||||||
: _alloc(n, alloc)
|
: _alloc(n, alloc)
|
||||||
, _size(n) {
|
, _size(n) {
|
||||||
element_t* addr = _alloc.data();
|
value_t* addr = _alloc.data();
|
||||||
for(; n > 0; --n, ++addr) {
|
for(; n > 0; --n, ++addr) {
|
||||||
fennec::construct(addr);
|
fennec::construct(addr);
|
||||||
}
|
}
|
||||||
@@ -142,10 +144,11 @@ public:
|
|||||||
/// \brief Sized Allocation Copy Constructor, Create an allocation of size `n` elements, with each element
|
/// \brief Sized Allocation Copy Constructor, Create an allocation of size `n` elements, with each element
|
||||||
/// constructed using the copy constructor
|
/// constructed using the copy constructor
|
||||||
/// \param n the number of elements
|
/// \param n the number of elements
|
||||||
|
/// \param val the value to copy
|
||||||
constexpr dynarray(size_t n, const TypeT& val)
|
constexpr dynarray(size_t n, const TypeT& val)
|
||||||
: _alloc(n)
|
: _alloc(n)
|
||||||
, _size(n) {
|
, _size(n) {
|
||||||
element_t* addr = _alloc.data();
|
value_t* addr = _alloc.data();
|
||||||
for(; n > 0; --n, ++addr) {
|
for(; n > 0; --n, ++addr) {
|
||||||
fennec::construct(addr, val);
|
fennec::construct(addr, val);
|
||||||
}
|
}
|
||||||
@@ -161,7 +164,7 @@ public:
|
|||||||
/// \param n The number of objects to create
|
/// \param n The number of objects to create
|
||||||
/// \param args The arguments to create each object with
|
/// \param args The arguments to create each object with
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
constexpr dynarray(size_t n, ArgsT&&...args)
|
constexpr explicit dynarray(size_t n, ArgsT&&...args)
|
||||||
: _alloc(n)
|
: _alloc(n)
|
||||||
, _size(n) {
|
, _size(n) {
|
||||||
for(; n > 0; --n) {
|
for(; n > 0; --n) {
|
||||||
@@ -183,15 +186,16 @@ public:
|
|||||||
///
|
///
|
||||||
/// \brief Move Constructor, takes ownership of the allocation
|
/// \brief Move Constructor, takes ownership of the allocation
|
||||||
/// \param arr the dynarray to move
|
/// \param arr the dynarray to move
|
||||||
constexpr dynarray(dynarray&& arr)
|
constexpr dynarray(dynarray&& arr) noexcept
|
||||||
: _alloc(fennec::move(arr._alloc))
|
: _alloc(fennec::move(arr._alloc))
|
||||||
, _size(arr._size) {
|
, _size(arr._size) {
|
||||||
|
arr._size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Default Destructor, destructs all elements and frees the underlying allocation
|
/// \brief Default Destructor, destructs all elements and frees the underlying allocation
|
||||||
constexpr ~dynarray() {
|
constexpr ~dynarray() {
|
||||||
element_t* addr = _alloc.data();
|
value_t* addr = _alloc.data();
|
||||||
if (addr == nullptr) return;
|
if (addr == nullptr) return;
|
||||||
for(int n = _size; n > 0; --n, ++addr) {
|
for(int n = _size; n > 0; --n, ++addr) {
|
||||||
fennec::destruct(addr);
|
fennec::destruct(addr);
|
||||||
@@ -200,6 +204,37 @@ public:
|
|||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
// Assignment ==========================================================================================================
|
||||||
|
|
||||||
|
/// \name Properties
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Assignment Operator
|
||||||
|
/// \param arr the array to copy
|
||||||
|
/// \returns A dynarray after having copied each element of `arr`
|
||||||
|
constexpr dynarray& operator=(const dynarray& arr) {
|
||||||
|
this->clear();
|
||||||
|
_alloc.creallocate(_size = arr._size);
|
||||||
|
for (size_t i = 0; i < _size; ++i) {
|
||||||
|
fennec::construct(&_alloc[i], fennec::copy(arr[i]));
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Assignment Operator
|
||||||
|
/// \param arr the array to move
|
||||||
|
/// \returns A dynarray after having taken ownership of the contents of `arr`
|
||||||
|
constexpr dynarray& operator=(dynarray&& arr) noexcept {
|
||||||
|
this->clear();
|
||||||
|
_alloc = fennec::move(arr._alloc);
|
||||||
|
_size = arr._size;
|
||||||
|
arr._size = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
// Properties ==========================================================================================================
|
// Properties ==========================================================================================================
|
||||||
|
|
||||||
@@ -397,6 +432,15 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Clears the contents of the dynarray, destructing all elements and releasing the allocation.
|
||||||
|
constexpr void clear() {
|
||||||
|
while (_size > 0) {
|
||||||
|
fennec::destruct(&_alloc[--_size]);
|
||||||
|
}
|
||||||
|
_alloc.deallocate();
|
||||||
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
@@ -432,7 +476,7 @@ private:
|
|||||||
_alloc.creallocate(_alloc.capacity() * 2);
|
_alloc.creallocate(_alloc.capacity() * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
allocation<element_t, alloc_t> _alloc;
|
allocation<value_t, alloc_t> _alloc;
|
||||||
size_t _size;
|
size_t _size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,18 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file graph.h
|
||||||
|
/// \brief A header containing the definition for a graph of vertices connected by edges
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
#ifndef FENNEC_CONTAINERS_GRAPH_H
|
#ifndef FENNEC_CONTAINERS_GRAPH_H
|
||||||
#define FENNEC_CONTAINERS_GRAPH_H
|
#define FENNEC_CONTAINERS_GRAPH_H
|
||||||
|
|
||||||
@@ -28,19 +40,19 @@
|
|||||||
/*
|
/*
|
||||||
* With the directed tree we were able to cheat a little, the structure has more rules to it which allows
|
* With the directed tree we were able to cheat a little, the structure has more rules to it which allows
|
||||||
* tighter constraints. A graph is basically no rules whatsoever. Some variants, such as weighted graphs, assign
|
* tighter constraints. A graph is basically no rules whatsoever. Some variants, such as weighted graphs, assign
|
||||||
* properties or rules to connections which can simply be an extension to this graph.
|
* properties or rules to edges which can simply be an extension to this graph.
|
||||||
*
|
*
|
||||||
* The most effective way to do this is to have a dynarray of lists, however this results in double the
|
* The most effective way to do this is to have a dynarray of lists, however this results in double the
|
||||||
* memory being used. This can also result in two connection objects being created.
|
* memory being used. This can also result in two edge objects being created.
|
||||||
*
|
*
|
||||||
* There is no nice way to avoid the problem of mapping pins to connections
|
* There is no nice way to avoid the problem of mapping vertices to edges
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Graph Data Structure, describes sets of arbitrarily connected nodes
|
/// \brief Graph Data Structure, describes sets of arbitrarily connected vertices
|
||||||
///
|
///
|
||||||
/// \details
|
/// \details
|
||||||
/// | Property | Value |
|
/// | Property | Value |
|
||||||
@@ -57,44 +69,41 @@ namespace fennec
|
|||||||
/// | insertion | \f$O(1)\f$ |
|
/// | insertion | \f$O(1)\f$ |
|
||||||
/// | deletion | \f$O(N)\f$ |
|
/// | deletion | \f$O(N)\f$ |
|
||||||
///
|
///
|
||||||
/// Graphs contain nodes (sometimes called vertices) and connections. Graphs are either directed
|
/// Graphs contain vertices and edges. Graphs are either directed
|
||||||
/// or undirected. This structure allows the creation of both directed and undirected connections. As
|
/// or undirected. This structure allows the creation of both directed and undirected edges. As
|
||||||
/// far as what that means; a directed graph means that connections have direction, where there are connections
|
/// far as what that means; a directed graph means that edges have direction, where there are edges
|
||||||
/// that are "to" and "from," rather than "between" which is used in undirected graphs.
|
/// that are "to" and "from," rather than "between" which is used in undirected graphs.
|
||||||
///
|
///
|
||||||
/// An undirected graph is connected if there is a path between every pair of nodes in the graph.
|
/// An undirected graph is connected if there is a path between every pair of vertices in the graph.
|
||||||
///
|
///
|
||||||
/// A directed graph is weakly connected if replacing all of its directed connections with undirected connections would
|
/// A directed graph is weakly connected if replacing all of its directed edges with undirected edges would
|
||||||
/// produce a connected graph. We will call this "disjointed"
|
/// produce a connected graph. We will call this "disjointed"
|
||||||
///
|
///
|
||||||
/// A directed graph is semi-connected if there is a directed path p for `u` → `v` *or* `v` → `u` for every
|
/// A directed graph is semi-connected if there is a directed path p for `u` → `v` *or* `v` → `u` for every
|
||||||
/// pair of nodes `u, v`. We will call this "unilateral"
|
/// pair of vertices `u, v`. We will call this "unilateral"
|
||||||
///
|
///
|
||||||
/// A directed graph is strongly-connected if there is a directed path p for `u` → `v` *and* `v` → `u` for every pair
|
/// A directed graph is strongly-connected if there is a directed path p for `u` → `v` *and* `v` → `u` for every pair
|
||||||
/// of nodes `u, v`. We will call this "connected"
|
/// of vertices `u, v`. We will call this "connected"
|
||||||
///
|
///
|
||||||
/// \tparam NodeT The type associated with each node
|
/// \tparam VertexT The type associated with each vertex
|
||||||
/// \tparam WeightT The type associated with each connection
|
/// \tparam EdgeT The type associated with each edge
|
||||||
template<typename NodeT, typename WeightT = nullptr_t>
|
template<typename VertexT, typename EdgeT = empty_t>
|
||||||
struct graph {
|
struct graph {
|
||||||
public:
|
public:
|
||||||
// Definitions =========================================================================================================
|
// Definitions =========================================================================================================
|
||||||
|
|
||||||
/// \name Definitions
|
using edge_t = EdgeT; ///< Alias for the edge type
|
||||||
/// @{
|
using vertex_t = VertexT; ///< Alias for the vertex type
|
||||||
using weight_t = WeightT;
|
using vertex_pool_t = object_pool<vertex_t>; ///< Alias for a pool of vertices
|
||||||
using node_t = NodeT;
|
using edge_map_t = dynarray<map<size_t, size_t>>; ///< Alias for edge mapping
|
||||||
using conn_map_t = dynarray<map<size_t, size_t>>;
|
using edge_pool_t = object_pool<edge_t>; ///< Alias for a pool of edges
|
||||||
using node_pool_t = object_pool<node_t>;
|
|
||||||
using conn_pool_t = object_pool<weight_t>;
|
|
||||||
|
|
||||||
static constexpr size_t npos = -1;
|
static constexpr size_t npos = -1; ///< Constant for a non-existent vertex
|
||||||
/// @}
|
|
||||||
|
|
||||||
|
|
||||||
// Constructors ========================================================================================================
|
// Constructors ========================================================================================================
|
||||||
|
|
||||||
/// \name Constructors
|
/// \name Constructors & Destructor
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -132,30 +141,63 @@ public:
|
|||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns The number of nodes in the graph
|
/// \returns The number of vertices in the graph
|
||||||
constexpr size_t num_nodes() const {
|
constexpr size_t num_vertices() const {
|
||||||
return _node_pool.size();
|
return _vertex_pool.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns The number of connections in the graph
|
/// \returns The number of edges in the graph
|
||||||
constexpr size_t num_connections() const {
|
constexpr size_t num_edges() const {
|
||||||
return _conn_pool.size();
|
return _conn_pool.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns The capacity of the node pool
|
/// \returns The capacity of the vertex pool
|
||||||
constexpr size_t capacity() const {
|
constexpr size_t capacity() const {
|
||||||
return _node_pool.capacity();
|
return _vertex_pool.capacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns `true` when there are no nodes in the graph, `false` otherwise
|
/// \returns `true` when there are no vertices in the graph, `false` otherwise
|
||||||
constexpr bool empty() const {
|
constexpr bool empty() const {
|
||||||
return num_nodes() == 0;
|
return num_vertices() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: connected, disjoint, unilateral
|
///
|
||||||
|
/// \brief Checks if there exists an edge `e` that starts from `a` and ends at `b`
|
||||||
|
/// \param a The first vertex
|
||||||
|
/// \param b The second vertex
|
||||||
|
/// \returns `true` if the edge exists, `false` otherwise
|
||||||
|
constexpr bool exists(size_t a, size_t b) const {
|
||||||
|
return _conn_map[a][b] != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Checks if there exists an edge `e0` that starts from `a` and ends at `b` and `e1` that starts from `b`
|
||||||
|
/// and ends at `a`
|
||||||
|
/// \param a The first vertex
|
||||||
|
/// \param b The second vertex
|
||||||
|
/// \returns `true` if both edges exist, `false` otherwise
|
||||||
|
constexpr bool is_symmetric(size_t a, size_t b) const {
|
||||||
|
return exists(a, b) and exists(b, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Checks if there exists an edge `e` between `a` and `b`
|
||||||
|
/// \param a The first vertex
|
||||||
|
/// \param b The second vertex
|
||||||
|
/// \returns `true` if both edges exist, `false` otherwise
|
||||||
|
constexpr bool is_undirected(size_t a, size_t b) const {
|
||||||
|
const auto* e0 = _conn_map[a][b];
|
||||||
|
const auto* e1 = _conn_map[b][a];
|
||||||
|
if (not (e0 != nullptr && e1 != nullptr)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return *e0 == *e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: connected, disjoint, unilateral, get_component
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
@@ -166,31 +208,31 @@ public:
|
|||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Node Access Operator
|
/// \brief vertex Access Operator
|
||||||
/// \param node The id of the node
|
/// \param vertex The id of the vertex
|
||||||
/// \returns A reference to the value stored in the node
|
/// \returns A reference to the value stored in the vertex
|
||||||
constexpr node_t& operator[](size_t node) {
|
constexpr vertex_t& operator[](size_t vertex) {
|
||||||
return _node_pool[node];
|
return _vertex_pool[vertex];
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Node Const Access Operator
|
/// \brief vertex Const Access Operator
|
||||||
/// \param node The id of the node
|
/// \param vertex The id of the vertex
|
||||||
/// \returns A reference to the value stored in the node
|
/// \returns A reference to the value stored in the vertex
|
||||||
constexpr const node_t& operator[](size_t node) const {
|
constexpr const vertex_t& operator[](size_t vertex) const {
|
||||||
return _node_pool[node];
|
return _vertex_pool[vertex];
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Connection Access Operator
|
/// \brief edge Access Operator
|
||||||
/// \param a The id of the first node
|
/// \param a The id of the first vertex
|
||||||
/// \param b The id of the second node
|
/// \param b The id of the second vertex
|
||||||
/// \returns A pointer to the value stored in the connection, `nullptr` if not found
|
/// \returns A pointer to the value stored in the edge, `nullptr` if not found
|
||||||
constexpr weight_t* operator[](size_t a, size_t b) {
|
constexpr edge_t* operator[](size_t a, size_t b) {
|
||||||
if (empty()) {
|
if (empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
weight_t* it = _conn_map[a][b];
|
edge_t* it = _conn_map[a][b];
|
||||||
if (it) {
|
if (it) {
|
||||||
return _conn_pool[*it];
|
return _conn_pool[*it];
|
||||||
}
|
}
|
||||||
@@ -198,15 +240,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Connection Const Access Operator
|
/// \brief edge Const Access Operator
|
||||||
/// \param a The id of the first node
|
/// \param a The id of the first vertex
|
||||||
/// \param b The id of the second node
|
/// \param b The id of the second vertex
|
||||||
/// \returns A const-qualified pointer to the value stored in the connection, `nullptr` if not found
|
/// \returns A const-qualified pointer to the value stored in the edge, `nullptr` if not found
|
||||||
constexpr const weight_t* operator[](size_t a, size_t b) const {
|
constexpr const edge_t* operator[](size_t a, size_t b) const {
|
||||||
if (empty()) {
|
if (empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
const weight_t* it = _conn_map[a][b];
|
const edge_t* it = _conn_map[a][b];
|
||||||
if (it) {
|
if (it) {
|
||||||
return _conn_pool[*it];
|
return _conn_pool[*it];
|
||||||
}
|
}
|
||||||
@@ -214,31 +256,31 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Getter for a list of nodes that `node` has outgoing connections to
|
/// \brief Getter for a list of vertices `x` that `vertex` has an edge to `x...`
|
||||||
/// \param node The id of the node
|
/// \param vertex The id of the vertex
|
||||||
/// \returns A list containing all nodes `x` with connections from `node` to `x...`
|
/// \returns A list containing all vertices `x` with edges from `vertex` to `x...`
|
||||||
list<size_t> outgoing(size_t node) {
|
list<size_t> outgoing(size_t vertex) {
|
||||||
list<size_t> res;
|
list<size_t> res;
|
||||||
if (empty() || node >= _conn_map.size()) {
|
if (empty() || vertex >= _conn_map.size()) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
for (const auto& it : _conn_map[node]) {
|
for (const auto& it : _conn_map[vertex]) {
|
||||||
res.push_back(it.first);
|
res.push_back(it.first);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Getter for a list of nodes that `node` has incoming connections from
|
/// \brief Getter for a list of vertices `x` that `vertex` has an edge from `x...`
|
||||||
/// \param node The id of the node
|
/// \param vertex The id of the vertex
|
||||||
/// \returns A list containing all nodes `x` with connections from `x...` to `node`
|
/// \returns A list containing all vertices `x` with edges from `x...` to `vertex`
|
||||||
list<size_t> incoming(size_t node) {
|
list<size_t> incoming(size_t vertex) {
|
||||||
list<size_t> res;
|
list<size_t> res;
|
||||||
if (empty() || node >= _conn_map.size()) {
|
if (empty() || vertex >= _conn_map.size()) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
for (size_t n = 0; n < _conn_map.size(); ++n) {
|
for (size_t n = 0; n < _conn_map.size(); ++n) {
|
||||||
if (_conn_map[n][node]) {
|
if (_conn_map[n][vertex]) {
|
||||||
res.push_back(n);
|
res.push_back(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,16 +288,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Getter for a list of nodes `x` that `node` has a connection to and from `x...`
|
/// \brief Getter for a list of vertices `x` that `vertex` has an edge to and from `x...`
|
||||||
/// \param node The id of the node
|
/// \param vertex The id of the vertex
|
||||||
/// \returns A list containing all nodes `x` that have symmetric connections with `node`
|
/// \returns A list containing all vertices `x` that have symmetric edges with `vertex`
|
||||||
list<size_t> symmetric(size_t node) {
|
list<size_t> symmetric(size_t vertex) {
|
||||||
list<size_t> res;
|
list<size_t> res;
|
||||||
if (empty() || node >= _conn_map.size()) {
|
if (empty() || vertex >= _conn_map.size()) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
for (const auto& it : _conn_map[node]) {
|
for (const auto& it : _conn_map[vertex]) {
|
||||||
if (_conn_map[it.first][node]) {
|
if (_conn_map[it.first][vertex]) {
|
||||||
res.push_back(it.first);
|
res.push_back(it.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -263,20 +305,21 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Getter for a list of nodes `x` that `node` has a connection to and from `x...` and share the same weight
|
/// \brief Getter for a list of vertices `x` that `vertex` has an edge to and from `x...` and share the same value
|
||||||
/// "Joined" connections may also be referred to as "undirected." A joined, or undirected, connection may be
|
/// \details
|
||||||
/// turned into a directed connection by changing the weight object associated with the connection, or by
|
/// "Joined" edges may also be referred to as "undirected." A joined, or undirected, edge may be
|
||||||
/// removing one of the sub-connections.
|
/// turned into a directed edge by changing the weight object associated with the edge, or by
|
||||||
/// \param node The id of the node
|
/// removing one of the sub-edges.
|
||||||
/// \returns A list containing all nodes `x` that have symmetric connections with `node`
|
/// \param vertex The id of the vertex
|
||||||
list<size_t> joined(size_t node) {
|
/// \returns A list containing all vertices `x` that have symmetric edges with `vertex`
|
||||||
|
list<size_t> undirected(size_t vertex) {
|
||||||
list<size_t> res;
|
list<size_t> res;
|
||||||
if (empty() || node >= _conn_map.size()) {
|
if (empty() || vertex >= _conn_map.size()) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
for (const auto& it : _conn_map[node]) {
|
for (const auto& it : _conn_map[vertex]) {
|
||||||
const auto* at = _conn_map[it.first][node];
|
const auto* at = _conn_map[it.first][vertex];
|
||||||
if (at == &it.second) {
|
if (at != nullptr && *at == it.second) {
|
||||||
res.push_back(it.first);
|
res.push_back(it.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -284,15 +327,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Getter for the internal storage of mapped connections from this node
|
/// \brief Getter for the internal storage of mapped edges from this vertex.
|
||||||
/// Use this when you want to iterate over connections that start from this node.
|
/// Use this when you want to iterate over edges that start from this vertex.
|
||||||
/// \param node The id of the node
|
/// \param vertex The id of the vertex
|
||||||
/// \returns A pointer to a map containing connections mapped from this node
|
/// \returns A pointer to a map containing edges mapped from this vertex
|
||||||
const auto* connections(size_t node) {
|
const auto* edges(size_t vertex) {
|
||||||
if (empty() || node >= _conn_map.size()) {
|
if (empty() || vertex >= _conn_map.size()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return &_conn_map[node];
|
return &_conn_map[vertex];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
@@ -304,60 +347,60 @@ public:
|
|||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Move a new node into the graph
|
/// \brief Move a new vertex into the graph
|
||||||
/// \param node The node to move into the graph
|
/// \param vertex The vertex to move into the graph
|
||||||
/// \returns The id of the new node
|
/// \returns The id of the new vertex
|
||||||
constexpr size_t insert(node_t&& node) {
|
constexpr size_t insert(vertex_t&& vertex) {
|
||||||
return this->_insert(fennec::forward<node_t>(node));
|
return this->_insert(fennec::forward<vertex_t>(vertex));
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Copy a new node into the graph
|
/// \brief Copy a new vertex into the graph
|
||||||
/// \param node The node to copy into the graph
|
/// \param vertex The vertex to copy into the graph
|
||||||
/// \returns The id of the new node
|
/// \returns The id of the new vertex
|
||||||
constexpr size_t insert(const node_t& node) {
|
constexpr size_t insert(const vertex_t& vertex) {
|
||||||
return this->_insert(node);
|
return this->_insert(vertex);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Construct a new node in the graph
|
/// \brief Construct a new vertex in the graph
|
||||||
/// \tparam ArgsT The types of the arguments
|
/// \tparam ArgsT The types of the arguments
|
||||||
/// \param args The arguments to construct the node with
|
/// \param args The arguments to construct the vertex with
|
||||||
/// \returns The id of the new node
|
/// \returns The id of the new vertex
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
constexpr size_t emplace(ArgsT&&...args) {
|
constexpr size_t emplace(ArgsT&&...args) {
|
||||||
return this->_insert(fennec::forward<ArgsT>(args)...);
|
return this->_insert(fennec::forward<ArgsT>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Erase a node from the graph
|
/// \brief Erase a vertex from the graph
|
||||||
/// \param node The id of the node to erase
|
/// \param vertex The id of the vertex to erase
|
||||||
constexpr void erase(size_t node) {
|
constexpr void erase(size_t vertex) {
|
||||||
disconnect(node);
|
cut(vertex);
|
||||||
_node_pool.erase(node);
|
_vertex_pool.erase(vertex);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Form a connection from node `a` to node `b`
|
/// \brief Form an edge from vertex `a` to vertex `b`
|
||||||
/// \tparam ArgsT The argument types
|
/// \tparam ArgsT The argument types
|
||||||
/// \param a The first node id
|
/// \param a The first vertex id
|
||||||
/// \param b The second node id
|
/// \param b The second vertex id
|
||||||
/// \param args The arguments to construct the connection with
|
/// \param args The arguments to construct the edge with
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
constexpr void connect(size_t a, size_t b, ArgsT&&...args) {
|
constexpr void make_edge(size_t a, size_t b, ArgsT&&...args) {
|
||||||
if (a == b) {
|
if (a == b) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_conn_map.size() < _node_pool.capacity()) {
|
if (_conn_map.size() < _vertex_pool.capacity()) {
|
||||||
_conn_map.resize(_node_pool.capacity());
|
_conn_map.resize(_vertex_pool.capacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = _conn_map[a][b];
|
auto it = _conn_map[a][b];
|
||||||
size_t conn;
|
size_t conn;
|
||||||
if (it != nullptr) {
|
if (it != nullptr) {
|
||||||
conn = *it;
|
conn = *it;
|
||||||
_conn_pool[conn] = node_t(fennec::forward<ArgsT>(args)...);
|
_conn_pool[conn] = vertex_t(fennec::forward<ArgsT>(args)...);
|
||||||
} else {
|
} else {
|
||||||
conn = _conn_pool.emplace(fennec::forward<ArgsT>(args)...);
|
conn = _conn_pool.emplace(fennec::forward<ArgsT>(args)...);
|
||||||
}
|
}
|
||||||
@@ -365,26 +408,26 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Form a bidirectional connection between node `a` and node `b`
|
/// \brief Form an undirected edge between vertex `a` and vertex `b`
|
||||||
/// \tparam ArgsT The argument types
|
/// \tparam ArgsT The argument types
|
||||||
/// \param a The first node id
|
/// \param a The first vertex id
|
||||||
/// \param b The second node id
|
/// \param b The second vertex id
|
||||||
/// \param args The arguments to construct the connection with
|
/// \param args The arguments to construct the edge with
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
constexpr void connect2(size_t a, size_t b, ArgsT&&...args) {
|
constexpr void make_edge2(size_t a, size_t b, ArgsT&&...args) {
|
||||||
if (a == b) {
|
if (a == b) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_conn_map.size() < _node_pool.capacity()) {
|
if (_conn_map.size() < _vertex_pool.capacity()) {
|
||||||
_conn_map.resize(_node_pool.capacity());
|
_conn_map.resize(_vertex_pool.capacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = _conn_map[a][b];
|
auto it = _conn_map[a][b];
|
||||||
size_t conn;
|
size_t conn;
|
||||||
if (it != nullptr) {
|
if (it != nullptr) {
|
||||||
conn = *it;
|
conn = *it;
|
||||||
_conn_pool[conn] = node_t(fennec::forward<ArgsT>(args)...);
|
_conn_pool[conn] = vertex_t(fennec::forward<ArgsT>(args)...);
|
||||||
} else {
|
} else {
|
||||||
conn = _conn_pool.emplace(fennec::forward<ArgsT>(args)...);
|
conn = _conn_pool.emplace(fennec::forward<ArgsT>(args)...);
|
||||||
}
|
}
|
||||||
@@ -394,69 +437,78 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Disconnect a connection from node `a` to node `b`
|
/// \brief Disconnect an edge from vertex `a` to vertex `b`
|
||||||
/// \param a The first node id
|
/// \param a The first vertex id
|
||||||
/// \param b The second node id
|
/// \param b The second vertex id
|
||||||
constexpr void disconnect(size_t a, size_t b) {
|
constexpr void cut_edge(size_t a, size_t b) {
|
||||||
|
|
||||||
// Find the connection object
|
// Find the edge object
|
||||||
const auto* it = _conn_map[a][b];
|
const auto* it = _conn_map[a][b];
|
||||||
if (not it) {
|
if (not it) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
size_t c = *it;
|
size_t c = *it;
|
||||||
|
|
||||||
// Check if bi-directional
|
// Check if undirected
|
||||||
const auto* at = _conn_map[b][a];
|
const auto* at = _conn_map[b][a];
|
||||||
if (not at || *at != c) {
|
if (not at || *at != c) {
|
||||||
_conn_pool.erase(c);
|
_conn_pool.erase(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Erase the connection mapping
|
// Erase the edge mapping
|
||||||
_conn_map[a].erase(b);
|
_conn_map[a].erase(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Disconnect a bidirectional connection between nodes `a` and `b`
|
/// \brief Disconnect both directed edges between vertices `a` and `b`
|
||||||
/// \param a The first node id
|
/// \param a The first vertex id
|
||||||
/// \param b The second node id
|
/// \param b The second vertex id
|
||||||
constexpr void disconnect2(size_t a, size_t b) {
|
constexpr void cut_edge2(size_t a, size_t b) {
|
||||||
const auto* it = _conn_map[a][b];
|
const auto* ita = _conn_map[a][b];
|
||||||
if (not it) {
|
const auto* itb = _conn_map[a][b];
|
||||||
|
if (not (ita || itb)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
size_t c = *it;
|
if (ita) _conn_pool.erase(*ita);
|
||||||
_conn_pool.erase(c);
|
if (itb) _conn_pool.erase(*itb);
|
||||||
_conn_map[a].erase(b);
|
_conn_map[a].erase(b);
|
||||||
_conn_map[b].erase(a);
|
_conn_map[b].erase(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Break *all* connections to and from `n`
|
/// \brief Break *all* edges to and from `n`
|
||||||
/// \param n The node id
|
/// \param n The vertex id
|
||||||
void disconnect(size_t n) {
|
void cut(size_t n) {
|
||||||
for (const auto it : outgoing(n)) {
|
for (const auto it : outgoing(n)) {
|
||||||
disconnect(n, it);
|
cut_edge(n, it);
|
||||||
}
|
}
|
||||||
for (const auto it : incoming(n)) {
|
for (const auto it : incoming(n)) {
|
||||||
disconnect(it, n);
|
cut_edge(it, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Clear the graph, destructing all vertices and edges.
|
||||||
|
void clear() {
|
||||||
|
_vertex_pool.clear();
|
||||||
|
_conn_pool.clear();
|
||||||
|
_conn_map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
// Connections =========================================================================================================
|
// edges =========================================================================================================
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
node_pool_t _node_pool;
|
vertex_pool_t _vertex_pool;
|
||||||
conn_pool_t _conn_pool;
|
edge_pool_t _conn_pool;
|
||||||
conn_map_t _conn_map;
|
edge_map_t _conn_map;
|
||||||
|
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
size_t _insert(ArgsT&&...args) {
|
size_t _insert(ArgsT&&...args) {
|
||||||
return _node_pool.emplace(fennec::forward<ArgsT>(args)...);
|
return _vertex_pool.emplace(fennec::forward<ArgsT>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \file list.h
|
/// \file list.h
|
||||||
/// \brief List of elements
|
/// \brief A header containing the definition for a linked list of values
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// \details
|
/// \details
|
||||||
@@ -72,9 +72,12 @@ private:
|
|||||||
struct node;
|
struct node;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using alloc_t = typename allocator_traits<Alloc>::template rebind<TypeT>;
|
///< Alias for the allocator type, rebound to list nodes
|
||||||
|
using alloc_t = typename allocator_traits<Alloc>::template rebind<node>;
|
||||||
|
|
||||||
using value_t = TypeT;
|
using value_t = TypeT;
|
||||||
using elem_t = node;
|
using elem_t = node;
|
||||||
|
|
||||||
static constexpr size_t npos = -1;
|
static constexpr size_t npos = -1;
|
||||||
|
|
||||||
class iterator;
|
class iterator;
|
||||||
@@ -92,6 +95,28 @@ public:
|
|||||||
: _table(), _freed(), _root(npos), _last(npos), _size(0) {
|
: _table(), _freed(), _root(npos), _last(npos), _size(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Constructor, copies all elements in `l` with optimized layout
|
||||||
|
/// \param l The list to copy
|
||||||
|
constexpr list(const list& l)
|
||||||
|
: list() {
|
||||||
|
for (const value_t& it : l) {
|
||||||
|
this->push_back(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Constructor, takes ownership of the list
|
||||||
|
/// \param l The list to move
|
||||||
|
constexpr list(list&& l) noexcept
|
||||||
|
: _table(fennec::move(l._table))
|
||||||
|
, _freed(fennec::move(l._freed))
|
||||||
|
, _root(l._root)
|
||||||
|
, _last(l._last)
|
||||||
|
, _size(l._size) {
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Destructor, destructs all elements then releases the allocation.
|
/// \brief Destructor, destructs all elements then releases the allocation.
|
||||||
constexpr ~list() {
|
constexpr ~list() {
|
||||||
@@ -102,6 +127,37 @@ public:
|
|||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
// Assignment ==========================================================================================================
|
||||||
|
|
||||||
|
/// \name Assignment
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Assignment Operator
|
||||||
|
/// \param l the list to copy
|
||||||
|
/// \returns `this` after having copied all elements of `l`
|
||||||
|
constexpr list& operator=(const list& l) {
|
||||||
|
this->clear();
|
||||||
|
for (const value_t& it : l) {
|
||||||
|
this->push_back(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Assignment Operator
|
||||||
|
/// \param l the list to copy
|
||||||
|
/// \returns `this` after having taken ownership over the contents of `l`
|
||||||
|
constexpr list& operator=(list&& l) noexcept {
|
||||||
|
this->clear();
|
||||||
|
_table = fennec::move(l._table);
|
||||||
|
_freed = fennec::move(l._freed);
|
||||||
|
_root = l._root; _last = l._last;
|
||||||
|
_size = l._size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
// Properties ==========================================================================================================
|
// Properties ==========================================================================================================
|
||||||
|
|
||||||
/// \name Properties
|
/// \name Properties
|
||||||
@@ -324,10 +380,54 @@ public:
|
|||||||
_erase(_last);
|
_erase(_last);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Clears the list, destructing all elements in order
|
||||||
|
constexpr void clear() {
|
||||||
|
size_t i = _root;
|
||||||
|
while (i != npos) {
|
||||||
|
fennec::destruct(_table[i]);
|
||||||
|
i = this->_next(i);
|
||||||
|
}
|
||||||
|
_table.deallocate(_table);
|
||||||
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
// ITERATOR ============================================================================================================
|
// ITERATOR ============================================================================================================
|
||||||
|
|
||||||
|
/// \name Iteration
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `begin()`
|
||||||
|
/// \returns An iterator for the first element in the list
|
||||||
|
constexpr iterator begin() {
|
||||||
|
return iterator(this, _root);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `end()`
|
||||||
|
/// \returns An iterator for the end of the list
|
||||||
|
constexpr iterator end() {
|
||||||
|
return iterator(this, npos);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Const C++ Iterator Specification `begin()`
|
||||||
|
/// \returns A const iterator for the first element in the list
|
||||||
|
constexpr const_iterator begin() const {
|
||||||
|
return const_iterator(this, _root);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Const C++ Iterator Specification `end()`
|
||||||
|
/// \returns A const iterator for the end of the list
|
||||||
|
constexpr const_iterator end() const {
|
||||||
|
return const_iterator(this, npos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Iterator Class
|
/// \brief Iterator Class
|
||||||
class iterator {
|
class iterator {
|
||||||
@@ -428,35 +528,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \name Iteration
|
|
||||||
/// @{
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \returns An iterator for the first element in the list
|
|
||||||
constexpr iterator begin() {
|
|
||||||
return iterator(this, _root);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \returns An iterator for the end of the list
|
|
||||||
constexpr iterator end() {
|
|
||||||
return iterator(this, npos);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \returns A const iterator for the first element in the list
|
|
||||||
constexpr const_iterator begin() const {
|
|
||||||
return const_iterator(this, _root);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \returns A const iterator for the end of the list
|
|
||||||
constexpr const_iterator end() const {
|
|
||||||
return const_iterator(this, npos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
allocation<elem_t, alloc_t> _table;
|
allocation<elem_t, alloc_t> _table;
|
||||||
dynarray<size_t> _freed;
|
dynarray<size_t> _freed;
|
||||||
|
|||||||
@@ -16,6 +16,18 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file map.h
|
||||||
|
/// \brief A header containing the definition for a mapping of keys to values
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
#ifndef FENNEC_CONTAINERS_MAP_H
|
#ifndef FENNEC_CONTAINERS_MAP_H
|
||||||
#define FENNEC_CONTAINERS_MAP_H
|
#define FENNEC_CONTAINERS_MAP_H
|
||||||
|
|
||||||
@@ -235,6 +247,12 @@ public:
|
|||||||
_set.erase(this->_find(fennec::forward<ArgsT>(args)...));
|
_set.erase(this->_find(fennec::forward<ArgsT>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Clears the set, destructing all elements
|
||||||
|
void clear() {
|
||||||
|
_set.clear();
|
||||||
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
@@ -243,10 +261,17 @@ public:
|
|||||||
/// \name Iteration
|
/// \name Iteration
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `begin()`
|
||||||
|
/// \returns an iterator at the start of the map
|
||||||
constexpr iterator begin() {
|
constexpr iterator begin() {
|
||||||
return _set.begin();
|
return _set.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `end()`
|
||||||
|
/// \returns an iterator at the end of the map
|
||||||
constexpr iterator end() {
|
constexpr iterator end() {
|
||||||
return _set.end();
|
return _set.end();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,18 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file multiset.h
|
||||||
|
/// \brief A header containing the definition for a set of repeating values
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
#ifndef FENNEC_CONTAINERS_MULTISET_H
|
#ifndef FENNEC_CONTAINERS_MULTISET_H
|
||||||
#define FENNEC_CONTAINERS_MULTISET_H
|
#define FENNEC_CONTAINERS_MULTISET_H
|
||||||
|
|
||||||
@@ -385,6 +397,29 @@ public:
|
|||||||
|
|
||||||
// ITERATOR ============================================================================================================
|
// ITERATOR ============================================================================================================
|
||||||
|
|
||||||
|
/// \name Iteration
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `begin()`
|
||||||
|
/// \returns An iterator for all elements of the set in no particular order
|
||||||
|
constexpr iterator begin() const {
|
||||||
|
iterator it(this, 0);
|
||||||
|
if (not _alloc[it._i].value) {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief C++ Iterator Specification `end()`
|
||||||
|
/// \returns An iterator representing the end of the set
|
||||||
|
constexpr iterator end() const {
|
||||||
|
return iterator(this, npos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Class for Iterating the Set
|
/// \brief Class for Iterating the Set
|
||||||
class iterator {
|
class iterator {
|
||||||
@@ -492,27 +527,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \name Iteration
|
|
||||||
/// @{
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \returns An iterator for all elements of the set in no particular order
|
|
||||||
constexpr iterator begin() const {
|
|
||||||
iterator it(this, 0);
|
|
||||||
if (not _alloc[it._i].value) {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \returns An iterator representing the end of the set
|
|
||||||
constexpr iterator end() const {
|
|
||||||
return iterator(this, npos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
|
||||||
|
|
||||||
|
|
||||||
// PRIVATE =============================================================================================================
|
// PRIVATE =============================================================================================================
|
||||||
|
|
||||||
@@ -536,7 +550,7 @@ private:
|
|||||||
|
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
constexpr void _insert(ArgsT&&...args) {
|
constexpr void _insert(ArgsT&&...args) {
|
||||||
if (_size == 0 or double(_size) / capacity() >= _load) { // expand when full
|
if (_size == 0 or static_cast<double>(_size) / capacity() >= _load) { // expand when full
|
||||||
_expand();
|
_expand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,18 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file object_pool.h
|
||||||
|
/// \brief A header containing the definition for a pool of objects associated by ids
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
#ifndef FENNEC_CONTAINERS_OBJECT_POOL_H
|
#ifndef FENNEC_CONTAINERS_OBJECT_POOL_H
|
||||||
#define FENNEC_CONTAINERS_OBJECT_POOL_H
|
#define FENNEC_CONTAINERS_OBJECT_POOL_H
|
||||||
|
|
||||||
@@ -32,14 +44,36 @@ namespace fennec
|
|||||||
/// \tparam AllocT The allocator type
|
/// \tparam AllocT The allocator type
|
||||||
template<typename TypeT, typename AllocT = allocator<TypeT>>
|
template<typename TypeT, typename AllocT = allocator<TypeT>>
|
||||||
struct object_pool {
|
struct object_pool {
|
||||||
|
|
||||||
|
// Definitions =========================================================================================================
|
||||||
public:
|
public:
|
||||||
using value_t = TypeT;
|
using value_t = TypeT;
|
||||||
using elem_t = optional<TypeT>;
|
using elem_t = optional<TypeT>;
|
||||||
using table_t = dynarray<elem_t, AllocT>;
|
using table_t = dynarray<elem_t, AllocT>;
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors & Destructor ===========================================================================================
|
||||||
|
|
||||||
|
/// \name Constructors & Destructor
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Default Constructor, initializes an empty object pool
|
||||||
constexpr object_pool()
|
constexpr object_pool()
|
||||||
: _size(0) {
|
: _size(0) {
|
||||||
};
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Default Destructor, destructs objects then releases the allocation.
|
||||||
|
constexpr ~object_pool() = default;
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
// Properties ==========================================================================================================
|
||||||
|
|
||||||
|
/// \name Properties
|
||||||
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns The number of active objects in the pool
|
/// \returns The number of active objects in the pool
|
||||||
@@ -53,30 +87,81 @@ public:
|
|||||||
return _table.capacity();
|
return _table.capacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns `true` when there are no objects in the pool, `false` otherwise
|
||||||
constexpr bool empty() const {
|
constexpr bool empty() const {
|
||||||
return size() == 0;
|
return size() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Retrieve the next id `i` that would be assigned to an object `o` were it added to the object pool
|
||||||
|
///
|
||||||
|
/// \details This can be useful if there are constant members that need to be assigned at construction.
|
||||||
|
/// \returns The id of the next inserted node
|
||||||
|
constexpr size_t next_id() const {
|
||||||
|
size_t next = _size;
|
||||||
|
if (not _freed.empty()) {
|
||||||
|
next = _freed.front();
|
||||||
|
}
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
// Access ==============================================================================================================
|
||||||
|
|
||||||
|
/// \name Access
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Array Access Operator
|
||||||
|
/// \param i id of the object
|
||||||
|
/// \returns a reference to the object with id `i`
|
||||||
constexpr value_t& operator[](size_t i) {
|
constexpr value_t& operator[](size_t i) {
|
||||||
assert(i < capacity(), "Index out of Bounds!");
|
assert(i < capacity(), "Index out of Bounds!");
|
||||||
assert(_table[i], "Attempted to access Null Object.");
|
assert(_table[i], "Attempted to access Null Object.");
|
||||||
return *_table[i];
|
return *_table[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Array Const Access Operator
|
||||||
|
/// \param i id of the object
|
||||||
|
/// \returns a const-qualified reference to the object with id `i`
|
||||||
constexpr const value_t& operator[](size_t i) const {
|
constexpr const value_t& operator[](size_t i) const {
|
||||||
assert(i < capacity(), "Index out of Bounds!");
|
assert(i < capacity(), "Index out of Bounds!");
|
||||||
assert(_table[i], "Attempted to access Null Object.");
|
assert(_table[i], "Attempted to access Null Object.");
|
||||||
return *_table[i];
|
return *_table[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
// Modifiers ===========================================================================================================
|
||||||
|
|
||||||
|
/// \name Modifiers
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Insertion, inserts `x` into the pool
|
||||||
|
/// \param x the object to move
|
||||||
|
/// \returns An integer corresponding to the id of the node
|
||||||
constexpr size_t insert(value_t&& x) {
|
constexpr size_t insert(value_t&& x) {
|
||||||
return this->_insert(fennec::forward<value_t>(x));
|
return this->_insert(fennec::forward<value_t>(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Insertion, inserts a copy of `x` into the pool
|
||||||
|
/// \param x the object to copy
|
||||||
|
/// \returns An integer corresponding to the id of the node
|
||||||
constexpr size_t insert(const value_t& x) {
|
constexpr size_t insert(const value_t& x) {
|
||||||
return this->_insert(x);
|
return this->_insert(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Insertion, inserts a copy of `x` into the pool
|
||||||
|
/// \param x the object to copy
|
||||||
|
/// \returns An integer corresponding to the id of the node
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
constexpr size_t emplace(ArgsT&&...args) {
|
constexpr size_t emplace(ArgsT&&...args) {
|
||||||
return this->_insert(fennec::forward<ArgsT>(args)...);
|
return this->_insert(fennec::forward<ArgsT>(args)...);
|
||||||
@@ -88,14 +173,6 @@ public:
|
|||||||
--_size;
|
--_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr size_t next_id() const {
|
|
||||||
size_t next = _size;
|
|
||||||
if (not _freed.empty()) {
|
|
||||||
next = _freed.front();
|
|
||||||
}
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
dynarray<elem_t, AllocT> _table;
|
dynarray<elem_t, AllocT> _table;
|
||||||
list<size_t> _freed;
|
list<size_t> _freed;
|
||||||
|
|||||||
@@ -16,6 +16,18 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file optional.h
|
||||||
|
/// \brief A header containing the definition for a container with an optionally present variable
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
#ifndef FENNEC_CONTAINERS_OPTIONAL_H
|
#ifndef FENNEC_CONTAINERS_OPTIONAL_H
|
||||||
#define FENNEC_CONTAINERS_OPTIONAL_H
|
#define FENNEC_CONTAINERS_OPTIONAL_H
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,18 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file pair.h
|
||||||
|
/// \brief A header containing the definition for a container holding a pair of values
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
#ifndef FENNEC_CONTAINERS_PAIR_H
|
#ifndef FENNEC_CONTAINERS_PAIR_H
|
||||||
#define FENNEC_CONTAINERS_PAIR_H
|
#define FENNEC_CONTAINERS_PAIR_H
|
||||||
|
|
||||||
@@ -30,13 +42,21 @@ namespace fennec
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Struct for holding a pair of values
|
/// \brief Struct for holding a pair of values
|
||||||
/// \tparam T0 The type of the first value
|
/// \tparam TypeT0 The type of the first value
|
||||||
/// \tparam T1 The type of the second value
|
/// \tparam TypeT1 The type of the second value
|
||||||
template<typename T0, typename T1>
|
template<typename TypeT0, typename TypeT1>
|
||||||
struct pair {
|
struct pair {
|
||||||
|
|
||||||
|
// Members =============================================================================================================
|
||||||
|
|
||||||
|
TypeT0 first; ///< The first value in the pair
|
||||||
|
TypeT1 second; ///< The second value in the pair
|
||||||
|
|
||||||
// Constructors ========================================================================================================
|
// Constructors ========================================================================================================
|
||||||
|
|
||||||
|
/// \name Constructors & Destructor
|
||||||
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Default Constructor, invokes default constructor for both elements
|
/// \brief Default Constructor, invokes default constructor for both elements
|
||||||
constexpr pair() = default;
|
constexpr pair() = default;
|
||||||
@@ -49,7 +69,7 @@ struct pair {
|
|||||||
/// \brief Pair Copy Constructor
|
/// \brief Pair Copy Constructor
|
||||||
/// \param x Value to copy for the first element
|
/// \param x Value to copy for the first element
|
||||||
/// \param y Value to copy for the first element
|
/// \param y Value to copy for the first element
|
||||||
constexpr pair(const T0& x, const T1& y)
|
constexpr pair(const TypeT0& x, const TypeT1& y)
|
||||||
: first(x)
|
: first(x)
|
||||||
, second(y) {
|
, second(y) {
|
||||||
}
|
}
|
||||||
@@ -58,9 +78,9 @@ struct pair {
|
|||||||
/// \brief Pair Move Constructor
|
/// \brief Pair Move Constructor
|
||||||
/// \param x Value to move for the first element
|
/// \param x Value to move for the first element
|
||||||
/// \param y Value to move for the first element
|
/// \param y Value to move for the first element
|
||||||
constexpr pair(T0&& x, T1&& y) noexcept
|
constexpr pair(TypeT0&& x, TypeT1&& y) noexcept
|
||||||
: first(fennec::forward<T0>(x))
|
: first(fennec::forward<TypeT0>(x))
|
||||||
, second(fennec::forward<T1>(y)) {
|
, second(fennec::forward<TypeT1>(y)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -89,9 +109,14 @@ struct pair {
|
|||||||
/// \brief Move Assignment, moves both elements
|
/// \brief Move Assignment, moves both elements
|
||||||
constexpr pair& operator=(pair&&) noexcept = default;
|
constexpr pair& operator=(pair&&) noexcept = default;
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
// Comparison ==========================================================================================================
|
// Comparison ==========================================================================================================
|
||||||
|
|
||||||
|
/// \name Comparison
|
||||||
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Equality Operator
|
/// \brief Equality Operator
|
||||||
/// \param p Pair to compare with
|
/// \param p Pair to compare with
|
||||||
@@ -144,18 +169,15 @@ struct pair {
|
|||||||
return first > p.first or (first == p.first and second >= p.second);
|
return first > p.first or (first == p.first and second >= p.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Members =============================================================================================================
|
/// @}
|
||||||
|
|
||||||
T0 first;
|
|
||||||
T1 second;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T0, typename T1>
|
template<typename TypeT0, typename TypeT1>
|
||||||
struct hash<pair<T0, T1>> : hash<T0>, hash<T1> {
|
struct hash<pair<TypeT0, TypeT1>> : hash<TypeT0>, hash<TypeT1> {
|
||||||
constexpr size_t operator()(const pair<T0, T1>& p) const {
|
constexpr size_t operator()(const pair<TypeT0, TypeT1>& p) const {
|
||||||
return fennec::pair_hash( // pair the hashes of both elements
|
return fennec::pair_hash( // pair the hashes of both elements
|
||||||
hash<T0>::operator()(p.first),
|
hash<TypeT0>::operator()(p.first),
|
||||||
hash<T1>::operator()(p.second)
|
hash<TypeT1>::operator()(p.second)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,6 +16,18 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file rdtree.h
|
||||||
|
/// \brief A header containing the definition for a tree with a root and directed edges
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
#ifndef FENNEC_CONTAINERS_RDTREE_H
|
#ifndef FENNEC_CONTAINERS_RDTREE_H
|
||||||
#define FENNEC_CONTAINERS_RDTREE_H
|
#define FENNEC_CONTAINERS_RDTREE_H
|
||||||
|
|
||||||
@@ -50,6 +62,13 @@ protected:
|
|||||||
size_t parent, child, prev, next;
|
size_t parent, child, prev, next;
|
||||||
size_t depth, num_children;
|
size_t depth, num_children;
|
||||||
|
|
||||||
|
constexpr node()
|
||||||
|
: value(nullopt)
|
||||||
|
, parent(npos), child(npos)
|
||||||
|
, prev(npos), next(npos)
|
||||||
|
, depth(0), num_children(0) {
|
||||||
|
}
|
||||||
|
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
constexpr node(size_t p, size_t c, size_t v, size_t n, size_t d, ArgsT&&...args)
|
constexpr node(size_t p, size_t c, size_t v, size_t n, size_t d, ArgsT&&...args)
|
||||||
: value(fennec::forward<ArgsT>(args)...)
|
: value(fennec::forward<ArgsT>(args)...)
|
||||||
@@ -62,7 +81,7 @@ protected:
|
|||||||
child = npos;
|
child = npos;
|
||||||
prev = npos;
|
prev = npos;
|
||||||
next = npos;
|
next = npos;
|
||||||
depth = npos;
|
depth = 0;
|
||||||
num_children = 0;
|
num_children = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -71,24 +90,46 @@ public:
|
|||||||
|
|
||||||
// Constructors ========================================================================================================
|
// Constructors ========================================================================================================
|
||||||
|
|
||||||
|
/// \name Constructors & Destructor
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Root Constructor, constructs the root node of the tree
|
||||||
|
/// \tparam ArgsT The argument types
|
||||||
|
/// \param args The arguments to construct the root with
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
explicit constexpr rdtree(ArgsT&&...args)
|
explicit constexpr rdtree(ArgsT&&...args)
|
||||||
: _table(), _freed(), _size(1) {
|
: _table(), _freed(), _size(1) {
|
||||||
_table.callocate(8);
|
_table.creallocate(8);
|
||||||
fennec::construct(&_table[0], npos, npos, npos, npos, 0, fennec::forward<ArgsT>(args)...);
|
fennec::construct(&_table[0], npos, npos, npos, npos, 0, fennec::forward<ArgsT>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Constructor, copies the contents of `tree`
|
||||||
|
/// \param tree the rdtree to copy
|
||||||
constexpr rdtree(const rdtree& tree)
|
constexpr rdtree(const rdtree& tree)
|
||||||
: _table(tree._table), _freed(tree._freed), _size(tree._size) {
|
: _table(tree._table), _freed(tree._freed), _size(tree._size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Constructor, takes ownership over the contents of `tree`
|
||||||
|
/// \param tree the rdtree to move
|
||||||
constexpr rdtree(rdtree&& tree) noexcept
|
constexpr rdtree(rdtree&& tree) noexcept
|
||||||
: _table(fennec::move(tree._table)), _freed(fennec::move(tree._freed)), _size(tree._size) {
|
: _table(fennec::move(tree._table)), _freed(fennec::move(tree._freed)), _size(tree._size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
// Assignment ==========================================================================================================
|
// Assignment ==========================================================================================================
|
||||||
|
|
||||||
|
/// \name Assignment
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Copy Assignment Operator
|
||||||
|
/// \param rhs the rdtree to copy
|
||||||
|
/// \returns `this` after copying the contents of `rhs`
|
||||||
constexpr rdtree& operator=(const rdtree& rhs) {
|
constexpr rdtree& operator=(const rdtree& rhs) {
|
||||||
for (value_t* it : this->_table) {
|
for (value_t* it : this->_table) {
|
||||||
fennec::destruct(it);
|
fennec::destruct(it);
|
||||||
@@ -99,6 +140,10 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Move Assignment Operator
|
||||||
|
/// \param rhs the rdtree to move
|
||||||
|
/// \returns `this` after taking ownership over the contents of `rhs`
|
||||||
constexpr rdtree& operator=(rdtree&& rhs) noexcept {
|
constexpr rdtree& operator=(rdtree&& rhs) noexcept {
|
||||||
for (value_t* it : _table) {
|
for (value_t* it : _table) {
|
||||||
fennec::destruct(it);
|
fennec::destruct(it);
|
||||||
@@ -109,17 +154,27 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
// Properties ==========================================================================================================
|
// Properties ==========================================================================================================
|
||||||
|
|
||||||
|
/// \name Properties
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns The number of nodes in the tree
|
||||||
constexpr size_t size() const {
|
constexpr size_t size() const {
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns The capacity of the underlying allocation
|
||||||
constexpr size_t capacity() const {
|
constexpr size_t capacity() const {
|
||||||
return _table.capacity();
|
return _table.capacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns `true` when there are no nodes in the tree, `false` otherwise
|
||||||
constexpr bool empty() const {
|
constexpr bool empty() const {
|
||||||
return _size == 0;
|
return _size == 0;
|
||||||
}
|
}
|
||||||
@@ -347,6 +402,30 @@ public:
|
|||||||
|
|
||||||
// Traversal ===========================================================================================================
|
// Traversal ===========================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Traverse the tree using a specified order and visiting functor
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// The visitor should accept a reference to a value of type `TypeT` and a `size_t` which contains the node's id.
|
||||||
|
/// The visitor should return one of the following values in the `fennec::traversal_control_` enum
|
||||||
|
///
|
||||||
|
/// \tparam OrderT The order with which to traverse the tree.
|
||||||
|
/// \tparam VisitorT The visitor, should fulfill the signature `uint8_t visit(TypeT&, size_t)`
|
||||||
|
/// \param visit The visiting object
|
||||||
|
/// \param i The node to start at
|
||||||
|
template<typename OrderT, typename VisitorT>
|
||||||
|
void traverse(VisitorT&& visit, size_t i = root) {
|
||||||
|
OrderT order;
|
||||||
|
i = order(*this, i);
|
||||||
|
while (i != npos) {
|
||||||
|
uint8_t mode = visit(*_table[i].value, i);
|
||||||
|
if (mode == traversal_control_break) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i = order[*this, i, mode];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct pre_order {
|
struct pre_order {
|
||||||
list<size_t> visit;
|
list<size_t> visit;
|
||||||
size_t head;
|
size_t head;
|
||||||
@@ -457,19 +536,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename OrderT, typename VisitorT>
|
|
||||||
void traverse(VisitorT&& visit, size_t i = root) {
|
|
||||||
OrderT order;
|
|
||||||
i = order(*this, i);
|
|
||||||
while (i != npos) {
|
|
||||||
uint8_t mode = visit(*_table[i].value, i);
|
|
||||||
if (mode == traversal_control_break) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i = order[*this, i, mode];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
allocation<node, alloc_t> _table;
|
allocation<node, alloc_t> _table;
|
||||||
|
|||||||
@@ -16,12 +16,23 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file set.h
|
||||||
|
/// \brief A header containing the definition for a set of unique values
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
#ifndef FENNEC_CONTAINERS_SET_H
|
#ifndef FENNEC_CONTAINERS_SET_H
|
||||||
#define FENNEC_CONTAINERS_SET_H
|
#define FENNEC_CONTAINERS_SET_H
|
||||||
|
|
||||||
// https://programming.guide/robin-hood-hashing.html
|
// https://programming.guide/robin-hood-hashing.html
|
||||||
|
|
||||||
#include <fennec/containers/multiset.h>
|
|
||||||
#include <fennec/containers/optional.h>
|
#include <fennec/containers/optional.h>
|
||||||
#include <fennec/containers/set.h>
|
#include <fennec/containers/set.h>
|
||||||
#include <fennec/lang/compare.h>
|
#include <fennec/lang/compare.h>
|
||||||
@@ -94,6 +105,7 @@ public:
|
|||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Hash Copy Constructor, initializes empty set with a hash
|
/// \brief Hash Copy Constructor, initializes empty set with a hash
|
||||||
|
/// \param hash the hash object
|
||||||
constexpr set(const hash_t& hash)
|
constexpr set(const hash_t& hash)
|
||||||
: _alloc()
|
: _alloc()
|
||||||
, _hash(hash)
|
, _hash(hash)
|
||||||
@@ -102,18 +114,9 @@ public:
|
|||||||
, _load(default_load) {
|
, _load(default_load) {
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Hash Move Constructor, initializes empty set with a hash
|
|
||||||
constexpr set(hash_t&& hash) noexcept
|
|
||||||
: _alloc()
|
|
||||||
, _hash(hash)
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Alloc Copy Constructor, initializes empty set with an allocator
|
/// \brief Alloc Copy Constructor, initializes empty set with an allocator
|
||||||
|
/// \param alloc the allocator object
|
||||||
constexpr set(const alloc_t& alloc)
|
constexpr set(const alloc_t& alloc)
|
||||||
: _alloc(alloc)
|
: _alloc(alloc)
|
||||||
, _hash()
|
, _hash()
|
||||||
@@ -122,18 +125,10 @@ public:
|
|||||||
, _load(default_load) {
|
, _load(default_load) {
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Alloc Move Constructor, initializes empty set with an allocator
|
|
||||||
constexpr set(alloc_t&& alloc) noexcept
|
|
||||||
: _alloc(alloc)
|
|
||||||
, _hash()
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Hash Alloc Copy Constructor, initializes empty set with a hash and allocator
|
/// \brief Hash Alloc Copy Constructor, initializes empty set with a hash and allocator
|
||||||
|
/// \param hash the hash object
|
||||||
|
/// \param alloc the allocator object
|
||||||
constexpr set(const hash_t& hash, const alloc_t& alloc)
|
constexpr set(const hash_t& hash, const alloc_t& alloc)
|
||||||
: _alloc(alloc)
|
: _alloc(alloc)
|
||||||
, _hash(hash)
|
, _hash(hash)
|
||||||
@@ -142,36 +137,6 @@ public:
|
|||||||
, _load(default_load) {
|
, _load(default_load) {
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Hash Copy Alloc Move Constructor, initializes empty set with a hash and allocator
|
|
||||||
constexpr set(const hash_t& hash, alloc_t&& alloc) noexcept
|
|
||||||
: _alloc(alloc)
|
|
||||||
, _hash(hash)
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Hash Move Alloc Move Constructor, initializes empty set with a hash and allocator
|
|
||||||
constexpr set(hash_t&& hash, alloc_t&& alloc) noexcept
|
|
||||||
: _alloc(alloc)
|
|
||||||
, _hash(hash)
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Hash Move Alloc Copy Constructor, initializes empty set with a hash and allocator
|
|
||||||
constexpr set(hash_t&& hash, const alloc_t& alloc) noexcept
|
|
||||||
: _alloc(alloc)
|
|
||||||
, _hash(hash)
|
|
||||||
, _size(0)
|
|
||||||
, _sumpsl(0)
|
|
||||||
, _load(default_load) {
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Set Copy Constructor
|
/// \brief Set Copy Constructor
|
||||||
/// \param set Set to copy
|
/// \param set Set to copy
|
||||||
@@ -225,7 +190,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \returns Capacity of the set in elements
|
/// \returns Capacity of the set in elements
|
||||||
constexpr size_t capacity() const {
|
constexpr size_t capacity() const {
|
||||||
return _alloc.capacity();
|
return _alloc.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
@@ -320,21 +285,21 @@ public:
|
|||||||
|
|
||||||
// Modifiers ===========================================================================================================
|
// Modifiers ===========================================================================================================
|
||||||
|
|
||||||
/// \name Properties
|
/// \name Modifiers
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Move Insertion
|
/// \brief Move Insertion
|
||||||
/// \param val Value to insert
|
/// \param val Value to insert
|
||||||
constexpr iterator insert(elem_t&& val) {
|
constexpr iterator insert(elem_t&& val) {
|
||||||
return fennec::move(this->_insert(fennec::forward<elem_t>(val)));
|
return this->_insert(fennec::forward<elem_t>(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Copy Insertion
|
/// \brief Copy Insertion
|
||||||
/// \param val Value to insert
|
/// \param val Value to insert
|
||||||
constexpr iterator insert(const elem_t& val) {
|
constexpr iterator insert(const elem_t& val) {
|
||||||
return fennec::move(this->_insert(val));
|
return this->_insert(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -343,7 +308,7 @@ public:
|
|||||||
/// \param args Arguments to construct with
|
/// \param args Arguments to construct with
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
constexpr iterator emplace(ArgsT&&...args) {
|
constexpr iterator emplace(ArgsT&&...args) {
|
||||||
return fennec::move(this->_insert(fennec::forward<ArgsT>(args)...));
|
return this->_insert(fennec::forward<ArgsT>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -378,11 +343,40 @@ public:
|
|||||||
this->erase(this->find(val));
|
this->erase(this->find(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief
|
||||||
|
constexpr void clear() {
|
||||||
|
for (size_t i = 0; i < _alloc.capacity(); ++i) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
// ITERATOR ============================================================================================================
|
// ITERATOR ============================================================================================================
|
||||||
|
|
||||||
|
/// \name Iteration
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns An iterator for all elements of the set in no particular order
|
||||||
|
constexpr iterator begin() const {
|
||||||
|
iterator it(this, 0);
|
||||||
|
if (not _alloc[it._i].value) {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns An iterator representing the end of the set
|
||||||
|
constexpr iterator end() const {
|
||||||
|
return iterator(this, npos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Class for Iterating the Set
|
/// \brief Class for Iterating the Set
|
||||||
class iterator {
|
class iterator {
|
||||||
@@ -438,34 +432,13 @@ public:
|
|||||||
friend set;
|
friend set;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \name Iteration
|
|
||||||
/// @{
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \returns An iterator for all elements of the set in no particular order
|
|
||||||
constexpr iterator begin() const {
|
|
||||||
iterator it(this, 0);
|
|
||||||
if (not _alloc[it._i].value) {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \returns An iterator representing the end of the set
|
|
||||||
constexpr iterator end() const {
|
|
||||||
return iterator(this, npos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
|
||||||
|
|
||||||
|
|
||||||
// PRIVATE =============================================================================================================
|
// PRIVATE =============================================================================================================
|
||||||
|
|
||||||
private:
|
private:
|
||||||
constexpr void _expand() {
|
constexpr void _expand() {
|
||||||
set cpy; // Create a new set
|
set cpy; // Create a new set
|
||||||
cpy._alloc.callocate(
|
cpy._alloc.resize(
|
||||||
fennec::next_prime2(_alloc.capacity())
|
fennec::next_prime2(_alloc.capacity())
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -506,7 +479,7 @@ private:
|
|||||||
return iterator(this, npos);
|
return iterator(this, npos);
|
||||||
}
|
}
|
||||||
|
|
||||||
allocation<node, alloc_t> _alloc;
|
dynarray<node, alloc_t> _alloc;
|
||||||
hash_t _hash;
|
hash_t _hash;
|
||||||
equal_t _equal;
|
equal_t _equal;
|
||||||
size_t _size;
|
size_t _size;
|
||||||
|
|||||||
@@ -16,16 +16,30 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file traversal.h
|
||||||
|
/// \brief a header containing constants and utilities related to traversal
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
#ifndef FENNEC_CONTAINERS_TRAVERSAL_H
|
#ifndef FENNEC_CONTAINERS_TRAVERSAL_H
|
||||||
#define FENNEC_CONTAINERS_TRAVERSAL_H
|
#define FENNEC_CONTAINERS_TRAVERSAL_H
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief A set of constants used in the traverser-visitor pattern
|
||||||
enum traversal_control_ {
|
enum traversal_control_ {
|
||||||
traversal_control_continue = 0,
|
traversal_control_continue = 0,
|
||||||
traversal_control_jump_over,
|
traversal_control_break = 1,
|
||||||
traversal_control_break
|
traversal_control_jump_over = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,18 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
// =====================================================================================================================
|
// =====================================================================================================================
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \file tuple.h
|
||||||
|
/// \brief A header containing the definition for a container with multiple values of differing types
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
#ifndef FENNEC_CONTAINERS_TUPLE_H
|
#ifndef FENNEC_CONTAINERS_TUPLE_H
|
||||||
#define FENNEC_CONTAINERS_TUPLE_H
|
#define FENNEC_CONTAINERS_TUPLE_H
|
||||||
|
|
||||||
|
|||||||
@@ -249,6 +249,7 @@ namespace fennec
|
|||||||
using uintmax_t = uintmax_t; ///< \brief Maximum Width Unsigned Integer Type
|
using uintmax_t = uintmax_t; ///< \brief Maximum Width Unsigned Integer Type
|
||||||
using size_t = size_t; ///< \brief Unsigned Integer Type Returned By `sizeof`, `sizeof...`, and `alignof`
|
using size_t = size_t; ///< \brief Unsigned Integer Type Returned By `sizeof`, `sizeof...`, and `alignof`
|
||||||
using ptrdiff_t = __PTRDIFF_TYPE__; ///< \brief Signed Integer Type Returned by the Subtraction of two Pointers
|
using ptrdiff_t = __PTRDIFF_TYPE__; ///< \brief Signed Integer Type Returned by the Subtraction of two Pointers
|
||||||
|
struct empty_t {};
|
||||||
|
|
||||||
|
|
||||||
class undefined_t; ///< \brief undefined class for SFINAE
|
class undefined_t; ///< \brief undefined class for SFINAE
|
||||||
|
|||||||
Reference in New Issue
Block a user