- More Documentation

This commit is contained in:
2026-01-12 00:36:39 -05:00
parent 450f725cab
commit ed381c4178
95 changed files with 5631 additions and 1718 deletions

View File

@@ -244,7 +244,7 @@ fennec_add_sources(
include/fennec/math/ext/transform.h
include/fennec/math/detail/_fwd.h
include/fennec/math/detail/_forward.h
include/fennec/math/detail/_math.h
include/fennec/math/detail/_matrix.h
include/fennec/math/detail/_types.h
@@ -297,7 +297,7 @@ fennec_add_sources(
# PLATFORM =============================================================================================================
include/fennec/platform/interface/fwd.h
include/fennec/platform/interface/forward.h
include/fennec/platform/interface/display_server.h
include/fennec/platform/interface/platform.h source/platform/interface/platform.cpp
include/fennec/platform/interface/window.h source/platform/interface/window.cpp
@@ -314,6 +314,7 @@ add_subdirectory(test)
add_library(fennec STATIC
${FENNEC_SOURCES}
include/fennec/rtti/this_t.h
)
add_dependencies(fennec metaprogramming fennec-dependencies)

View File

@@ -78,6 +78,24 @@ fennec Standards:
* Most behaviours should be type independent. Specifically interactions with the core systems of the engine.
- Classes should have banners between each distinct group of definitions, with the access specifier on the following
line. E.G.
```c++
class foo {
// Definitions ============================
public:
using bar = int;
// Constructors & Destructor ==============
public:
foo();
~foo();
};
```
This helps significantly with readability, and it also serves to reduce bugs related to mistakes involving access
specifiers. E.G. in the example above, bar is changed to private, the constructors are still labeled public in the
case the person forgets to update the succeeding access specifiers.
<br><br>
<a id="f1"></a>

View File

@@ -20,6 +20,10 @@
message(STATUS "Compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
fennec_add_definitions(
FENNEC_LONG_COMPILER_NAME="${CMAKE_CXX_COMPILER_ID} ${CMAKE_SYSTEM_NAME} ${CMAKE_SYSTEM_PROCESSOR}"
)
if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
set(FENNEC_COMPILER "GCC")
include("${FENNEC_SOURCE_DIR}/cmake/gcc.cmake")

View File

@@ -45,7 +45,7 @@ namespace fennec
///
/// \details
/// | Property | Value |
/// |:-----------:|:-----------:|
/// |:-----------:|:----------:|
/// | stable | ✅ |
/// | dynamic | ⛔ |
/// | homogeneous | ✅ |
@@ -57,10 +57,11 @@ namespace fennec
/// | find | \f$O(N)\f$ |
/// | insertion | ⛔ |
/// | deletion | ⛔ |
/// | space | \f$O(N)\f$ |
///
/// \tparam ValueT value type
/// \tparam ElemV number of elements
template<typename ValueT, size_t ElemV>
/// \tparam N number of elements
template<typename ValueT, size_t N>
struct array {
// Definitions =========================================================================================================
@@ -69,21 +70,19 @@ public:
/// \name Definitions
/// @{
using value_t = ValueT; ///< Alias for \f$ValueT\f$
using value_t = ValueT; //!< Alias for \f$ValueT\f$
/// @}
// Public Members ======================================================================================================
// Public Member Variables =============================================================================================
public:
/// \name Public Members
/// \name Member Variables
/// @{
///
/// \brief backing c-style array handle
value_t data[ElemV];
value_t data[N]; //!< Backing c-style array handle
/// @}
@@ -96,14 +95,22 @@ public:
/// @{
///
/// \brief returns the number of elements in the array
/// \returns the number of elements in the array
[[nodiscard]] constexpr size_t size() const { return ElemV; }
/// \brief Returns the number of elements in the array.
/// \returns \f$N\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
[[nodiscard]] constexpr size_t size() const { return N; }
///
/// \brief returns **true** when the array is empty
/// \return \f$ElemV == 0\f$
[[nodiscard]] constexpr bool_t is_empty() const { return ElemV == 0; }
/// \brief Returns \f$true\f$ when the array is empty
/// \returns \f$ElemV == 0\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
[[nodiscard]] constexpr bool_t is_empty() const { return N == 0; }
/// @}
@@ -120,58 +127,68 @@ public:
/// \param i index of the element to return
/// \return reference to the requested element
///
/// \par Time-Complexity
/// Constant
/// \par Complexity
/// \f$O(1)\f$
///
/// \par Space-Complexity
/// Constant
constexpr value_t& operator[](size_t i) {
assertd(i < ElemV, "Array Out of Bounds");
assertd(i < N, "Array Out of Bounds");
return data[i];
}
///
/// \brief access specified element
/// \brief Indexed access
/// \details Returns a reference to the element at \c i
/// \param i index of the element to return
/// \return reference to the requested element
///
/// \par Time-Complexity
/// Constant
/// \par Complexity
/// \f$O(1)\f$
///
/// \par Space-Complexity
/// Constant
constexpr const value_t& operator[](size_t i) const {
assertd(i < ElemV, "Array Out of Bounds");
assertd(i < N, "Array Out of Bounds");
return data[i];
}
///
/// \brief Access the first element
/// \returns A reference to the element at \f$elements[0]\f$
/// \returns A reference to \f$data[0]\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t& front() {
return data[0];
}
///
/// \brief Const Access the first element
/// \returns A const-qualified reference to the element at \f$elements[0]\f$
/// \brief Access the first element
/// \returns A const-qualified reference to \f$data[0]\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t& front() const {
return data[0];
}
///
/// \brief Access the first element
/// \returns A reference to the element at \f$elements[ElemV - 1]\f$
/// \returns A reference to \f$data[N - 1]\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t& back() {
return data[ElemV - 1];
return data[N - 1];
}
///
/// \brief Const Access the first element
/// \returns A const-qualified reference to the element at \f$elements[ElemV - 1]\f$
/// \brief Access the last element
/// \returns A const-qualified reference to \f$data[N - 1]\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t& back() const {
return data[ElemV - 1];
return data[N - 1];
}
/// @}
@@ -186,14 +203,22 @@ public:
///
/// \brief Checks if all elements in the arrays are equal
///
/// \par Complexity
/// \f$O(N)\f$
///
friend constexpr bool_t operator==(const array& lhs, const array& rhs) {
return array::_compare(lhs, rhs, make_index_metasequence<ElemV>{});
return array::_compare(lhs, rhs, make_index_metasequence<N>{});
}
///
/// \brief Checks if any element in the arrays is not equal
///
/// \par Complexity
/// \f$O(N)\f$
///
friend constexpr bool_t operator!=(const array& lhs, const array& rhs) {
return not array::_compare(lhs, rhs, make_index_metasequence<ElemV>{});
return not array::_compare(lhs, rhs, make_index_metasequence<N>{});
}
/// @}
@@ -206,39 +231,51 @@ public:
/// @{
///
/// \brief C++ Iterator Specification \f$begin()\f$
/// \returns A pointer to the first element of the array
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t* begin() {
return data;
}
///
/// \brief C++ Iterator Specification \f$end()\f$
/// \returns A pointer to one after the end of the array
constexpr value_t* end() {
return data + ElemV;
}
///
/// \brief Const C++ Iterator Specification \f$begin()\f$
/// \brief C++ Iterator Specification \f$begin()\f$
/// \returns A const-qualified pointer to the first element of the array
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t* begin() const {
return data;
}
///
/// \brief Const C++ Iterator Specification \f$end()\f$
/// \returns A pointer to one after the end of the array
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t* end() {
return data + N;
}
///
/// \brief C++ Iterator Specification \f$end()\f$
/// \returns A const-qualified pointer to one after the end of the array
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t* end() const {
return data + ElemV;
return data + N;
}
/// @}
// Helpers =============================================================================================================
// Private Helpers =====================================================================================================
private:
template<size_t...i>
static bool _compare(const array& lhs, const array& rhs, index_metasequence<i...>) {

View File

@@ -18,7 +18,7 @@
///
/// \file fennec/containers/bintree.h
/// \brief
/// \brief A header containing the definition for an in-array binary tree.
///
///
/// \details
@@ -31,8 +31,10 @@
#ifndef FENNEC_CONTAINERS_BINTREE_H
#define FENNEC_CONTAINERS_BINTREE_H
#include <fennec/containers/deque.h>
#include <fennec/containers/list.h>
#include <fennec/containers/optional.h>
#include <fennec/containers/pair.h>
#include <fennec/containers/traversal.h>
#include <fennec/memory/allocator.h>
@@ -44,7 +46,7 @@ namespace fennec
///
/// \details
/// | Property | Value |
/// |:-----------:|:-----------:|
/// |:-----------:|:----------:|
/// | stable | ⛔ |
/// | dynamic | ✅ |
/// | homogeneous | ✅ |
@@ -56,6 +58,7 @@ namespace fennec
/// | find | \f$O(N)\f$ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
/// | space | \f$O(N)\f$ |
///
/// \tparam TypeT The data type
/// \tparam AllocT An allocator class
@@ -67,6 +70,7 @@ private:
struct node;
public:
/// \name Definitions
/// @{
@@ -74,39 +78,20 @@ public:
using alloc_t = allocator_traits<AllocT>::template rebind<node>; //!< The allocator type
static constexpr size_t npos = -1; //!< null position constant
///
/// \brief Enum representing node side relative to parent
enum side_ : bool {
side_left = false, //!< Left Side
side_right = true //!< Right Side
};
/// @}
friend class iterator;
friend class const_iterator;
private:
struct node {
value_t value;
size_t parent;
size_t child[2];
constexpr node()
: value()
, parent(npos), child{ npos, npos } {
}
template<typename...ArgsT>
constexpr node(size_t p, size_t l, size_t r, ArgsT&&...args)
: value(fennec::forward<ArgsT>(args)...)
, parent(p), child{ l, r } {
}
constexpr ~node() {
parent = npos;
child[0] = npos;
child[1] = npos;
}
size_t& operator[](bool d) {
return child[d];
}
};
using table_t = allocation<node, alloc_t>;
using freed_t = list<size_t, alloc_t>;
@@ -118,6 +103,12 @@ public:
///
/// \brief Default Constructor, initializes an empty tree
///
/// \details The underlying allocation is not initialized.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bintree()
: _table()
, _freed()
@@ -128,6 +119,12 @@ public:
///
/// \brief Move Constructor, takes ownership of a tree
/// \param tree The tree to take ownership of
///
/// \details Takes ownership of the underlying allocation of \f$tree\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bintree(bintree&& tree) noexcept
: _table(fennec::move(tree._table))
, _freed(fennec::move(tree._freed))
@@ -138,15 +135,49 @@ public:
///
/// \brief Copy Constructor, copies a tree
/// \param tree The tree to copy
///
/// \details Copies the contents of \f$tree\f$ into a new tree. Invokes copy constructor.
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr bintree(const bintree& tree)
: _table(tree._table)
, _freed(tree._freed)
, _root(tree._root)
, _size(tree._size) {
: _table(tree._table.capacity())
, _freed()
, _root(nullid)
, _size(0) {
// Visitor for copying
struct {
bintree& self;
const bintree& target;
deque<pair<size_t, size_t>> stack;
uint8_t operator()(const value_t& x, size_t n) {
while (stack.back().second != target.parent(n)) {
stack.pop_back();
}
stack.emplace_back(self.insert(stack.back().first, target.side(n), x), n);
return traversal_control_continue;
}
} visitor = {
.self = *this,
.target = tree
};
tree.template traverse<pre_order>(
visitor, tree._root
);
}
///
/// \brief Destructor, clears the tree
///
/// \details Clears the contents of \f$tree\f$. Invokes destructor.
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr ~bintree() {
clear();
}
@@ -162,24 +193,40 @@ public:
///
/// \returns The number of elements in the tree
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t size() const {
return _size;
}
///
/// \returns \f$true\f$ when there are no elements in the tree, \f$false\f$ otherwise.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const {
return _size == 0;
}
///
/// \returns The capacity of the underlying allocation
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t capacity() const {
return _table.capacity();
}
///
/// \returns The next id to be returned by \f$insert\f$ or \f$emplace\f$.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t next_id() const {
size_t i = _size;
if (not _freed.is_empty()) {
@@ -190,6 +237,10 @@ public:
///
/// \returns The next id to be returned by \f$insert\f$ or \f$emplace\f$.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t root() const {
return _root;
}
@@ -205,58 +256,79 @@ public:
/// @{
///
/// \details \f$O(1)\f$
/// \param i The node id
/// \returns The parent of node \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t parent(size_t i) const {
return i == npos ? npos : _table[i].parent;
}
///
/// \details \f$O(1)\f$
/// \param i The node id
/// \returns The grandparent of node \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t grandparent(size_t i) const {
return parent(parent(i));
}
///
/// \details \f$O(1)\f$
/// \param i The node id
/// \returns The left child of node \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t left(size_t i) const {
return i == npos ? npos : _table[i].child[false];
}
///
/// \details \f$O(1)\f$
/// \param i The node id
/// \returns The right child of node \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t right(size_t i) const {
return i == npos ? npos : _table[i].child[true];
}
///
/// \details \f$O(1)\f$
/// \param i The node id
/// \param dir The direction to go \f$true\f$ for right, \f$false\f$ for left
/// \returns The child in the direction specified by \f$dir\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t child(size_t i, bool dir) const {
return i == npos ? npos : _table[i].child[dir];
}
///
/// \details \f$O(1)\f$
/// \param i The node id
/// \returns \f$true\f$ if \f$i\f$ is the right node of \f$parent(i)\f$, \f$false\f$ otherwise
constexpr bool direction(size_t i) const {
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool side(size_t i) const {
return i == npos ? false : i == right(_parent(i));
}
///
/// \details \f$O(1)\f$
/// \param i The id of the node
/// \returns The id of the sibling of \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t sibling(size_t i) const {
if (i == npos) {
return npos;
@@ -270,9 +342,12 @@ public:
}
///
/// \details \f$O(\log n)\f$
/// \param i The node id
/// \returns The depth of node \f$i\f$
///
/// \par Complexity
/// \f$O(\log n)\f$
///
constexpr size_t depth(size_t i) const {
size_t d = 0;
while (i != npos) {
@@ -283,9 +358,12 @@ public:
}
///
/// \details \f$O(\log n)\f$
/// \param i The node id
/// \returns The id of the left-most node of \f$i\f$
///
/// \par Complexity
/// \f$O(\log n)\f$
///
constexpr size_t left_most(size_t i) const {
if (i >= _table.size()) {
return npos;
@@ -297,9 +375,12 @@ public:
}
///
/// \details \f$O(\log n)\f$
/// \param i The node id
/// \returns The id of the right-most node of \f$i\f$
///
/// \par Complexity
/// \f$O(\log n)\f$
///
constexpr size_t right_most(size_t i) const {
if (i >= _table.size()) {
return npos;
@@ -320,18 +401,25 @@ public:
/// @{
///
/// \details \f$O(1)\f$
/// \param i The node id
/// \returns \f$nullptr\f$ if node \f$i\f$ does not exist, otherwise, a pointer to the value of node \f$i\f$
/// \returns a reference to the value of node \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t& operator[](size_t i) {
assertd(i < _table.size(), "Index out of bounds.");
return _table[i].value;
}
///
/// \details Const Access, \f$O(1)\f$
/// \details Node access
/// \param i The node id
/// \returns \f$nullptr\f$ if node \f$i\f$ does not exist, otherwise, a pointer to the value of node \f$i\f$
/// \returns a reference to the value of node \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t& operator[](size_t i) const {
assertd(i < _table.size(), "Index out of bounds.");
return _table[i].value;
@@ -339,7 +427,9 @@ public:
/// @}
// Modifiers ===========================================================================================================
public:
/// \name Modifiers
/// @{
@@ -349,6 +439,10 @@ public:
/// \param p The parent node
/// \param val The object to move into the new node
/// \returns The id of the new node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert_left(size_t p, value_t&& val) {
return this->_insert_left(p, fennec::forward<value_t>(val));
}
@@ -358,6 +452,10 @@ public:
/// \param p The parent node
/// \param val The object to copy to the new node
/// \returns The id of the new node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert_left(size_t p, const value_t& val) {
return this->_insert_left(p, val);
}
@@ -368,6 +466,10 @@ public:
/// \param p The parent node
/// \param args The arguments to construct the new node with
/// \returns The id of the new node
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr size_t emplace_left(size_t p, ArgsT&&...args) {
return this->_insert_left(p, fennec::forward<ArgsT>(args)...);
@@ -378,6 +480,10 @@ public:
/// \param p The parent node
/// \param val The object to move into the new node
/// \returns The id of the new node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert_right(size_t p, value_t&& val) {
return this->_insert_right(p, fennec::forward<value_t>(val));
}
@@ -387,6 +493,10 @@ public:
/// \param p The parent node
/// \param val The object to copy to the new node
/// \returns The id of the new node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert_right(size_t p, const value_t& val) {
return this->_insert_right(p, val);
}
@@ -397,6 +507,10 @@ public:
/// \param p The parent node
/// \param args The arguments to construct the new node with
/// \returns The id of the new node
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr size_t emplace_right(size_t p, ArgsT&&...args) {
return this->_insert_right(p, fennec::forward<ArgsT>(args)...);
@@ -409,6 +523,10 @@ public:
/// \param sub The root node for the rotation
/// \param dir The direction to rotate, \f$true\f$ for right, \f$false\f$ for left
/// \returns the new root node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t rotate(size_t sub, bool dir) {
if (sub == npos) {
return npos;
@@ -439,6 +557,10 @@ public:
/// \param side The side to insert on
/// \param val The object to move into the new node
/// \returns The id of the new node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert(size_t parent, bool side, value_t&& val) {
return this->_insert(parent, side, fennec::forward<value_t>(val));
}
@@ -449,6 +571,10 @@ public:
/// \param side The side to insert on
/// \param val The object to copy to the new node
/// \returns The id of the new node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert(size_t parent, bool side, const value_t& val) {
return this->_insert(parent, side, val);
}
@@ -460,6 +586,10 @@ public:
/// \param side The side to insert on
/// \param args The arguments to construct the new node with
/// \returns The id of the new node
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr size_t emplace(size_t parent, bool side, ArgsT&&...args) {
return this->_insert(parent, side, fennec::forward<ArgsT>(args)...);
@@ -467,6 +597,10 @@ public:
///
/// \brief Clears the tree, destroying all elements
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void clear() {
list<size_t> queue;
@@ -500,6 +634,35 @@ public:
/// \name Traversal
/// @{
///
/// \details
/// The visitor should accept a reference to a value of type \f$TypeT\f$ and a \f$size_t\f$ 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 \f$uint8_t visit(TypeT&, size_t)\f$
/// \param visit The visiting object
/// \param i The node to start at
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename OrderT, typename VisitorT>
constexpr void traverse(VisitorT&& visit, size_t i) {
OrderT order;
i = order(*this, i);
while (i != npos) {
uint8_t mode = traversal_control_continue;
if (_table[i].value) {
mode = visit(_table[i].value, i);
}
if (mode == traversal_control_break) {
break;
}
i = order[*this, i, mode];
}
}
///
/// \brief Traverse the tree using a specified order and visiting functor
///
@@ -511,8 +674,12 @@ public:
/// \tparam VisitorT The visitor, should fulfill the signature \f$uint8_t visit(TypeT&, size_t)\f$
/// \param visit The visiting object
/// \param i The node to start at
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename OrderT, typename VisitorT>
constexpr void traverse(VisitorT&& visit, size_t i) {
constexpr void traverse(VisitorT&& visit, size_t i) const {
OrderT order;
i = order(*this, i);
while (i != npos) {
@@ -918,6 +1085,10 @@ public:
///
/// \returns an iterator at the first element in pre-order traversal
///
/// \par Complexity
/// \f$O(\log N)\f$
///
iterator begin() {
return iterator(this, _root);
}
@@ -925,12 +1096,20 @@ public:
///
/// \brief C++ Iterator Specification \f$begin()\f$
/// \returns an iterator at the first element in pre-order traversal
///
/// \par Complexity
/// \f$O(\log N)\f$
///
const_iterator begin() const {
return iterator(this, _root);
}
///
/// \returns an iterator at the first element in pre-order traversal
///
/// \par Complexity
/// \f$O(1)\f$
///
iterator end() {
return iterator(this, _root, nullid);
}
@@ -938,20 +1117,26 @@ public:
///
/// \brief C++ Iterator Specification \f$end()\f$
/// \returns an iterator at the first element in pre-order traversal
///
/// \par Complexity
/// \f$O(1)\f$
///
const_iterator end() const {
return iterator(this, _root, nullid);
}
/// @}
// Fields ==============================================================================================================
// Private Member Variables ============================================================================================
private:
table_t _table;
freed_t _freed;
size_t _root, _size;
// Helpers =============================================================================================================
// Private Helpers =====================================================================================================
private:
constexpr size_t _next_free() {
size_t i = _size;
if (not _freed.is_empty()) {
@@ -959,7 +1144,7 @@ private:
_freed.pop_front();
}
if (i >= _table.capacity()) {
_table.creallocate(2 * fennec::max(_table.capacity(), size_t(4)));
_table.reallocate(2 * fennec::max(_table.capacity(), size_t(4)));
}
++_size;
return i;
@@ -1047,6 +1232,35 @@ private:
bool d = i == _right(p);
return _child(p, !d);
}
// Private Definitions =================================================================================================
private:
struct node {
value_t value;
size_t parent;
size_t child[2];
constexpr node()
: value()
, parent(npos), child{ npos, npos } {
}
template<typename...ArgsT>
constexpr node(size_t p, size_t l, size_t r, ArgsT&&...args)
: value(fennec::forward<ArgsT>(args)...)
, parent(p), child{ l, r } {
}
constexpr ~node() {
parent = npos;
child[0] = npos;
child[1] = npos;
}
size_t& operator[](bool d) {
return child[d];
}
};
};
}

View File

@@ -43,8 +43,8 @@ namespace fennec
///
/// \details
/// | Property | Value |
/// |:-----------:|:------------------------------:|
/// | stable | Elements cannot be referenced. |
/// |:-----------:|:----------:|
/// | stable | |
/// | dynamic | ⛔ |
/// | homogeneous | ✅ |
/// | distinct | ⛔ |
@@ -55,6 +55,7 @@ namespace fennec
/// | find | \f$O(N)\f$ |
/// | insertion | ⛔ |
/// | deletion | ⛔ |
/// | space | \f$O(N)\f$ |
///
/// \tparam N The number of bits in the bitfield
template<size_t N>
@@ -62,21 +63,41 @@ struct bitfield {
// Constants ===========================================================================================================
public:
/// \name Constants
/// @{
static constexpr size_t bits = N; //!< The number of bits in the bitfield
static constexpr size_t bytes = (N + 7) / 8; //!< The number of bytes that hold the bitfield
/// @}
// Constructors ========================================================================================================
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Default constructor.
/// \details Initializes all bits with \f$0\f$.
///
/// \par Complexity
/// \f$O(N)\f$
///
/// \brief default constructor, initializes with \f$0\f$
constexpr bitfield()
: _bytes() {
}
///
/// \brief boolean array constructor
/// \brief Boolean array constructor.
/// \param arr An array of boolean values resembling each bit.
/// \details Initializes each bit with the respective boolean value in \f$arr\f$
///
/// \par Complexity
/// \f$O(N)\f$
///
explicit constexpr bitfield(const bool (&arr)[N])
: _bytes() {
for (size_t i = 0; i < arr; ++i) {
@@ -85,8 +106,13 @@ public:
}
///
/// \brief index array constructor
/// \param arr An array of indices values resembling which bits to set.
/// \brief Index array constructor.
/// \param arr An array of indices.
/// \details Sets the bits of each index provided in \f$arr\f$.
///
/// \par Complexity
/// \f$O(N)\f$
///
template<size_t I>
explicit constexpr bitfield(const size_t (&arr)[I])
: _bytes() {
@@ -96,8 +122,13 @@ public:
}
///
/// \brief variadic array constructor
/// \param args A set of indices values resembling which bits to set.
/// \param args A set of indices.
/// \details This substitution assumes \f$ArgsT\ldots\f$ can be taken as an array of indices. <br>
/// Sets the bits of each index provided in \f$args\ldots\f$.
///
/// \par Complexity
/// \f$O(N)\f$
///
template<typename...ArgsT>
constexpr bitfield(ArgsT&&...args)
: _bytes() {
@@ -105,7 +136,15 @@ public:
}
///
/// \param args A set of boolean values resembling each bit.
/// \brief Variadic array constructor
/// \param args A set of boolean values.
/// \details This substitution assumes \f$ArgsT\ldots\f$ can be taken as an array of booleans. <br>
/// Initializes each bit with the respective boolean in \f$args\ldots\f$. <br>
/// Does not necessitate the number of arguments be equal to the number of bits.
///
/// \par Complexity
/// \f$O(N)\f$
///
template<typename...ArgsT> requires((is_bool_v<ArgsT> or is_convertible_v<ArgsT, bool>) and ...)
constexpr bitfield(ArgsT&&...args)
: _bytes() {
@@ -116,6 +155,10 @@ public:
///
/// \brief copy constructor
/// \param bf bitfield to copy
///
/// \par Complexity
/// \f$O(N)\f$
///
bitfield(const bitfield& bf)
: _bytes(bf._bytes) {
}
@@ -123,6 +166,10 @@ public:
///
/// \brief move constructor
/// \param bf bitfield to move
///
/// \par Complexity
/// \f$O(1)\f$
///
bitfield(bitfield&& bf) noexcept
: _bytes(bf._bytes) {
}
@@ -131,22 +178,52 @@ public:
/// \brief destructor
constexpr ~bitfield() = default;
/// @}
// Assignment ==========================================================================================================
public:
/// \name Assignment Operators
/// @{
///
/// \brief copy assignment
/// \param bf bitfield to copy
/// \returns a reference to self
///
/// \par Complexity
/// \f$O(N)\f$
///
bitfield& operator=(const bitfield& bf) = default;
///
/// \brief move assignment
/// \param bf bitfield to move
/// \returns a reference to self
///
/// \par Complexity
/// \f$O(1)\f$
///
bitfield& operator=(bitfield&& bf) noexcept = default;
/// @}
// Access & Modifiers ==================================================================================================
public:
/// \name Access & Modifiers
/// @{
///
/// \brief test a bit
/// \param i the index of the bit
/// \returns the value stored in the bit as a boolean
///
/// \par Complexity
/// \f$O(1)\f$
///
bool test(size_t i) const {
assertd(i < bits, "Index out of Bounds!");
size_t b = i / 8;
@@ -157,6 +234,10 @@ public:
///
/// \brief set a bit
/// \param i the index of the bit
///
/// \par Complexity
/// \f$O(1)\f$
///
void set(size_t i) {
assertd(i < bits, "Index out of Bounds!");
size_t b = i / 8;
@@ -167,6 +248,10 @@ public:
///
/// \brief clear a bit
/// \param i the index of the bit
///
/// \par Complexity
/// \f$O(1)\f$
///
void clear(size_t i) {
assertd(i < bits, "Index out of Bounds!");
size_t b = i / 8;
@@ -177,6 +262,10 @@ public:
///
/// \brief toggle a bit
/// \param i the index of the bit
///
/// \par Complexity
/// \f$O(1)\f$
///
void toggle(size_t i) {
assertd(i < bits, "Index out of Bounds!");
size_t b = i / 8;
@@ -186,8 +275,12 @@ public:
///
/// \brief store \f$v\f$ in bit \f$i\f$
/// \param i
/// \param v
/// \param i the index of the bit
/// \param v the value to store
///
/// \par Complexity
/// \f$O(1)\f$
///
void store(size_t i, bool v) {
assertd(i < bits, "Index out of Bounds!");
size_t b = i / 8;
@@ -198,15 +291,26 @@ public:
///
/// \brief not operator
/// \returns a bitfield containing the bit-wise inverse
///
/// \par Complexity
/// \f$O(N)\f$
///
bitfield operator~() const {
bitfield res = *this;
res._inv_helper(make_index_metasequence_t<bytes>{});
return res;
}
/// @}
// Private Member Variables ============================================================================================
private:
array<uint8_t, bytes> _bytes;
// Private Helpers =====================================================================================================
private:
template<size_t...I>
void _inv_helper(index_metasequence<I...>) {
((_bytes[I] = ~_bytes[I]), ...);

View File

@@ -43,18 +43,19 @@
/// \section fennec_containers_container_section_properties Container Properties
///
/// | Property | Meaning |
/// |:-----------:|:----------------------------------------------------------------------------------------------:|
/// | stable | Any pointer reference to an element remains constant for the lifetime of the data structure. |
/// | dynamic | Memory for this data structure is allocated on the heap. |
/// | homogeneous | The types of all elements are either identical, or inherit the same base type. |
/// | distinct | Elements are guaranteed to be unique in their value. |
/// | ordered | Elements are guaranteed to be in order, such that for any index \f$i\f$, \f$E_i < E_{i + 1}\f$ |
/// | space | The amount of memory allocated with respect to the number of elements, in big-O notation. |
/// | linear | Each element is sequential in terms of access. |
/// | access | The runtime of the access operators and functions, in big-O notation. |
/// | find | The runtime of finding an element in the data structure, in big-O notation. |
/// | insertion | The runtime of inserting an element in the data structure, in big-O notation. |
/// | deletion | The runtime of erasing an element in the data structure, in big-O notation. |
/// |:----------------|:-----------------------------------------------------------------------------------------------|
/// | **stable** | Any pointer reference to an element remains constant for the lifetime of the container. |
/// | **dynamic** | Memory for this container is allocated on the heap. |
/// | **homogeneous** | The types of all elements are either identical, or inherit the same base type. |
/// | **distinct** | Elements are guaranteed to be unique in their value. |
/// | **ordered** | Elements are guaranteed to be in order, such that for any index \f$i\f$, \f$E_i < E_{i + 1}\f$ |
/// | **space** | The amount of memory allocated with respect to the number of elements, in big-O notation. |
/// | **linear** | Each element is sequential in terms of access. |
/// | **access** | The runtime of the access operators and functions, in big-O notation. |
/// | **find** | The runtime of finding an element in the container, in big-O notation. |
/// | **insertion** | The runtime of inserting an element in the container, in big-O notation. |
/// | **deletion** | The runtime of erasing an element in the container, in big-O notation. |
/// | **space** | The space complexity of the container. |
///
///
/// \section fennec_containers_section_cppstdlib C++ Standard Template Library

View File

@@ -59,34 +59,30 @@ namespace fennec
/// | find | \f$O(N)\f$ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
/// | space | \f$O(N)\f$ |
///
/// \tparam TypeT value type
template<typename TypeT, typename AllocT = allocator<TypeT>>
struct deque {
// Definitions =========================================================================================================
public:
using value_t = TypeT; ///< Alias for the value type
class iterator;
private:
struct node {
value_t value;
node *prev, *next;
template<typename...ArgsT>
node(node* prev, node* next, ArgsT&&...args)
: value(fennec::forward<ArgsT>(args)...)
, prev(prev), next(next) {
}
~node() = default;
};
struct node;
public:
/// \name Definitions
/// @{
using value_t = TypeT; //!< Alias for the value type
using alloc_t = allocator_traits<AllocT>::template rebind<node>; //!< The underlying allocator type
using elem_t = node*; //!< The underlying element type
/// @}
class iterator;
// Constructors ========================================================================================================
@@ -95,6 +91,10 @@ public:
///
/// \brief Default Constructor, initializes an empty deque
///
/// \par Complexity
/// \f$O(1)\f$
///
deque()
: _alloc()
, _first(nullptr)
@@ -105,6 +105,10 @@ public:
///
/// \brief Alloc Constructor, initializes an empty deque with the specified allocator
/// \param alloc the allocator to copy
///
/// \par Complexity
/// \f$O(1)\f$
///
deque(const alloc_t& alloc)
: _alloc(alloc)
, _first(nullptr)
@@ -115,6 +119,10 @@ public:
///
/// \brief Copy Constructor
/// \param deque the deque to copy
///
/// \par Complexity
/// \f$O(N)\f$
///
deque(const deque& deque)
: _alloc(deque._alloc)
, _first(nullptr)
@@ -130,6 +138,10 @@ public:
///
/// \brief Deque Move Constructor
/// \param deque the deque to move
///
/// \par Complexity
/// \f$O(1)\f$
///
deque(deque&& deque) noexcept
: _alloc(deque._alloc)
, _first(deque._first)
@@ -141,6 +153,10 @@ public:
///
/// \brief Destructor, calls deque::clear
///
/// \par Complexity
/// \f$O(N)\f$
///
~deque() {
clear();
}
@@ -154,12 +170,20 @@ public:
///
/// \returns \f$true\f$ when the deque is empty, \f$false\f$ otherwise
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const {
return _size == 0;
}
///
/// \returns the number of elements in size()
/// \returns the number of elements in the deque
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t size() const {
return _size;
}
@@ -174,6 +198,10 @@ public:
///
/// \returns a reference to the first element in the deque
///
/// \par Complexity
/// \f$O(1)\f$
///
value_t& front() {
assert(not is_empty(), "Attempted to access an empty deque.");
return _first->value;
@@ -181,6 +209,10 @@ public:
///
/// \returns a const-qualified reference to the first element in the deque
///
/// \par Complexity
/// \f$O(1)\f$
///
const value_t& front() const {
assert(not is_empty(), "Attempted to access an empty deque.");
return _first->value;
@@ -188,6 +220,10 @@ public:
///
/// \returns a reference to the last element in the deque
///
/// \par Complexity
/// \f$O(1)\f$
///
value_t& back() {
assert(not is_empty(), "Attempted to access an empty deque.");
return _last->value;
@@ -195,6 +231,10 @@ public:
///
/// \returns a const-qualified reference to the last element in the deque
///
/// \par Complexity
/// \f$O(1)\f$
///
const value_t& back() const {
assert(not is_empty(), "Attempted to access an empty deque.");
return _last->value;
@@ -211,6 +251,10 @@ public:
///
/// \brief Push Front Move, moves a value to the front of the deque
/// \param elem the value to move
///
/// \par Complexity
/// \f$O(1)\f$
///
void push_front(value_t&& elem) {
this->_push_front(elem);
}
@@ -218,6 +262,10 @@ public:
///
/// \brief Push Front Copy, copies a value to the front of the deque
/// \param elem the value to copy
///
/// \par Complexity
/// \f$O(1)\f$
///
void push_front(const value_t& elem) {
this->_push_front(elem);
}
@@ -226,6 +274,10 @@ public:
/// \brief Emplace Front, constructs a new value at the front of the deque
/// \tparam ArgsT Argument types
/// \param args Arguments used to construct the value
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
void emplace_front(ArgsT&&...args) {
this->_push_front(fennec::forward<ArgsT>(args)...);
@@ -235,6 +287,10 @@ public:
///
/// \brief Push Back Move, moves a value to the back of the deque
/// \param elem the value to move
///
/// \par Complexity
/// \f$O(1)\f$
///
void push_back(value_t&& elem) {
this->_push_back(elem);
}
@@ -242,6 +298,10 @@ public:
///
/// \brief Push Back Copy, copies a value to the back of the deque
/// \param elem the value to copy
///
/// \par Complexity
/// \f$O(1)\f$
///
void push_back(const value_t& elem) {
this->_push_back(elem);
}
@@ -250,6 +310,10 @@ public:
/// \brief Emplace Back, constructs a new value at the back of the deque
/// \tparam ArgsT Argument types
/// \param args Arguments used to construct the value
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
void emplace_back(ArgsT&&...args) {
this->_push_back(fennec::forward<ArgsT>(args)...);
@@ -257,6 +321,10 @@ public:
///
/// \brief Clears the contents of the deque
///
/// \par Complexity
/// \f$O(N)\f$
///
void clear() {
elem_t it = _first;
while (it) {
@@ -272,6 +340,10 @@ public:
///
/// \brief Erase the First Element
///
/// \par Complexity
/// \f$O(1)\f$
///
void pop_front() {
if (_first == nullptr) {
return;
@@ -286,6 +358,10 @@ public:
///
/// \brief Erase the Last Element
///
/// \par Complexity
/// \f$O(1)\f$
///
void pop_back() {
if (_last == nullptr) {
return;
@@ -307,11 +383,16 @@ public:
* TODO: Decide whether you should be able to iterate over a deque
*/
// Private Member Variables ============================================================================================
private:
alloc_t _alloc;
node *_first, *_last;
size_t _size;
// Private Helpers =====================================================================================================
private:
template<typename...ArgsT>
void _push_front(ArgsT&&...args) {
elem_t next = _first;
@@ -337,6 +418,22 @@ private:
}
++_size;
}
// Private Definitions =================================================================================================
private:
struct node {
value_t value;
node *prev, *next;
template<typename...ArgsT>
node(node* prev, node* next, ArgsT&&...args)
: value(fennec::forward<ArgsT>(args)...)
, prev(prev), next(next) {
}
~node() = default;
};
};

View File

@@ -56,6 +56,7 @@ namespace fennec
/// | find | \f$O(N)\f$ |
/// | insertion | \f$O(N)\f$ |
/// | deletion | \f$O(N)\f$ |
/// | space | \f$O(N)\f$ |
///
/// This structure prefers shallow moves and deep copies.
///
@@ -65,8 +66,14 @@ struct dynarray {
// Definitions =========================================================================================================
public:
using value_t = TypeT; ///< Alias for the value type
using alloc_t = Alloc; ///< Alias for the allocator type
/// \name Definitions
/// @{
using value_t = TypeT; //!< Alias for the value type
using alloc_t = Alloc; //!< Alias for the allocator type
/// @}
// Constructors ========================================================================================================
@@ -77,6 +84,10 @@ public:
///
/// \brief Default Constructor, initializes an empty allocation.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr dynarray()
: _alloc(8)
, _size(0) {
@@ -86,16 +97,11 @@ public:
/// \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
/// data.
explicit constexpr dynarray(const alloc_t& alloc)
: _alloc(8, alloc)
, _size(0) {
}
///
/// \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
/// data.
explicit constexpr dynarray(alloc_t&& alloc) noexcept
/// \par Complexity
/// \f$O(1)\f$
///
explicit constexpr dynarray(const alloc_t& alloc)
: _alloc(8, alloc)
, _size(0) {
}
@@ -103,6 +109,10 @@ public:
///
/// \brief Sized Allocation, initializes a dynarray with \f$n\f$ elements using the default constructor.
/// \param n The number of elements.
///
/// \par Complexity
/// \f$O(N)\f$
///
explicit constexpr dynarray(size_t n)
: _alloc(n)
, _size(n)
@@ -118,21 +128,11 @@ public:
/// using the default constructor.
/// \param n The number of elements
/// \param alloc The allocator object to copy
constexpr dynarray(size_t n, const alloc_t& alloc)
: _alloc(n, alloc)
, _size(n) {
value_t* addr = _alloc.data();
for(; n > 0; --n, ++addr) {
fennec::construct(addr);
}
}
///
/// \brief Sized Allocation Alloc Move Constructor, initializes a dynarray with allocator \f$alloc\f$ and \f$n\f$ elements
/// using the default constructor.
/// \param n The number of elements
/// \param alloc The allocator object to copy
constexpr dynarray(size_t n, alloc_t&& alloc)
/// \par Complexity
/// \f$O(N)\f$
///
constexpr dynarray(size_t n, const alloc_t& alloc)
: _alloc(n, alloc)
, _size(n) {
value_t* addr = _alloc.data();
@@ -146,6 +146,10 @@ public:
/// constructed using the copy constructor
/// \param n the number of elements
/// \param val the value to copy
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr dynarray(size_t n, const TypeT& val)
: _alloc(n)
, _size(n) {
@@ -155,15 +159,15 @@ public:
}
}
// This constructor should not be invokable since moving is a single object operation and will cause undefined
// behaviour when moving to multiple elements
constexpr dynarray(size_t n, TypeT&& val) = delete;
///
/// \brief Emplace Constructor
/// \tparam ArgsT A sequence of argument types
/// \param n The number of objects to create
/// \param args The arguments to create each object with
///
/// \par Complexity
/// \f$O(N)\f$
///
template<typename...ArgsT>
constexpr explicit dynarray(size_t n, ArgsT&&...args)
: _alloc(n)
@@ -177,6 +181,10 @@ public:
/// \brief Array Copy Constructor
/// \tparam N The length of the array, automatically deduced
/// \param arr The array to copy
///
/// \par Complexity
/// \f$O(N)\f$
///
template<size_t N>
constexpr dynarray(const TypeT (&arr)[N])
: _alloc(N)
@@ -190,6 +198,10 @@ public:
/// \brief Array Move Constructor
/// \tparam N The length of the array, automatically deduced
/// \param arr The array to move
///
/// \par Complexity
/// \f$O(N)\f$
///
template<size_t N>
constexpr dynarray(TypeT (&&arr)[N])
: _alloc(N)
@@ -204,6 +216,10 @@ public:
/// \tparam OTypeT The other value type
/// \tparam OAlloc The other allocator type
/// \param conv The dynarray to convert
///
/// \par Complexity
/// \f$O(N)\f$
///
template<typename OTypeT, class OAlloc>
constexpr dynarray(const dynarray<OTypeT, OAlloc>& conv)
: _alloc(conv.size())
@@ -218,6 +234,10 @@ public:
/// \brief Initializer List Constructor
/// \param l List of elements to initialize with
/// \param alloc An allocator object to copy
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr dynarray(initializer_list<value_t> l, const alloc_t& alloc = alloc_t())
: _alloc(l.size(), alloc)
, _size(l.size()) {
@@ -230,6 +250,10 @@ public:
///
/// \brief Copy Constructor, uses the copy constructor to copy each element
/// \param arr the dynarray to copy
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr dynarray(const dynarray& arr)
: _alloc(arr._size)
, _size(arr._size) {
@@ -241,6 +265,10 @@ public:
///
/// \brief Move Constructor, takes ownership of the allocation
/// \param arr the dynarray to move
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr dynarray(dynarray&& arr) noexcept
: _alloc(fennec::move(arr._alloc))
, _size(arr._size) {
@@ -249,6 +277,10 @@ public:
///
/// \brief Default Destructor, destructs all elements and frees the underlying allocation
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr ~dynarray() {
value_t* addr = _alloc.data();
if (addr == nullptr) return;
@@ -259,6 +291,13 @@ public:
/// @}
private:
// This constructor should not be invokable since moving is a single object operation and will cause undefined
// behaviour when moving to multiple elements
constexpr dynarray(size_t n, TypeT&& val) = delete;
// Assignment ==========================================================================================================
public:
@@ -269,9 +308,13 @@ public:
/// \brief Copy Assignment Operator
/// \param arr the array to copy
/// \returns A dynarray after having copied each element of \f$arr\f$
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr dynarray& operator=(const dynarray& arr) {
this->clear();
_alloc.creallocate(_size = arr._size);
_alloc.reallocate(_size = arr._size);
for (size_t i = 0; i < _size; ++i) {
fennec::construct(&_alloc[i], fennec::copy(arr[i]));
}
@@ -282,6 +325,10 @@ public:
/// \brief Move Assignment Operator
/// \param arr the array to move
/// \returns A dynarray after having taken ownership of the contents of \f$arr\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr dynarray& operator=(dynarray&& arr) noexcept {
this->clear();
_alloc = fennec::move(arr._alloc);
@@ -295,10 +342,14 @@ public:
/// \tparam N the length of the array
/// \param arr the array to copy
/// \returns A dynarray after having copied each element of \f$arr\f$
///
/// \par Complexity
/// \f$O(N)\f$
///
template<size_t N>
constexpr dynarray& operator=(const TypeT (&arr)[N]) {
this->clear();
_alloc.creallocate(_size = N);
_alloc.reallocate(_size = N);
for (size_t i = 0; i < _size; ++i) {
fennec::construct(&_alloc[i], fennec::copy(arr[i]));
}
@@ -310,10 +361,14 @@ public:
/// \tparam N the length of the array
/// \param arr the array to copy
/// \returns A dynarray after having moved each element of \f$arr\f$
///
/// \par Complexity
/// \f$O(N)\f$
///
template<size_t N>
constexpr dynarray& operator=(TypeT (&&arr)[N]) {
this->clear();
_alloc.creallocate(_size = N);
_alloc.reallocate(_size = N);
for (size_t i = 0; i < _size; ++i) {
fennec::construct(&_alloc[i], fennec::move(arr[i]));
}
@@ -330,18 +385,30 @@ public:
///
/// \returns The size of the dynarray in elements
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t size() const {
return _size;
}
///
/// \returns The current capacity, in elements, of the underlying allocation
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t capacity() const {
return _alloc.capacity();
}
///
/// \returns True when there are no elements active, otherwise false
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const {
return _size == 0;
}
@@ -359,6 +426,10 @@ public:
/// \brief Array Access Operator
/// \param i The index to access
/// \returns A reference to the element at index \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr TypeT& operator[](size_t i) {
assertd(i < _size, "Array Out of Bounds");
return _alloc[i];
@@ -368,6 +439,10 @@ public:
/// \brief Array Access Operator (const)
/// \param i The index to access
/// \returns A const qualified reference to the element at index \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const TypeT& operator[](size_t i) const {
assertd(i < _size, "Array Out of Bounds");
return _alloc[i];
@@ -375,36 +450,60 @@ public:
///
/// \returns Reference to the first element in the dynarray
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr TypeT& front() {
return this->operator[](0);
}
///
/// \returns A const-qualified reference to the first element in the dynarray
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const TypeT& front() const {
return this->operator[](0);
}
///
/// \returns A reference to the last element in the dynarray
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr TypeT& back() {
return this->operator[](size() - 1);
}
///
/// \returns A const-qualified reference to the last element in the dynarray
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const TypeT& back() const {
return this->operator[](size() - 1);
}
///
/// \returns A pointer to the underlying allocation
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr TypeT* data() {
return _alloc.data();
}
///
/// \returns A pointer to the underlying allocation
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const TypeT* data() const {
return _alloc.data();
}
@@ -422,6 +521,10 @@ public:
/// \brief Move Insertion
/// \param i index to insert at
/// \param val the value to initialize with
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void insert(size_t i, TypeT&& val) {
// Grow if the size has reached the capacity of the allocation
@@ -446,6 +549,10 @@ public:
/// \brief Copy Insertion
/// \param i index to insert at
/// \param val the value to initialize with
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void insert(size_t i, const TypeT& val) {
// Grow if the size has reached the capacity of the allocation
@@ -472,6 +579,10 @@ public:
/// \param i index to insert at
/// \param args Arguments to construct with
/// \tparam ArgsT Argument types
///
/// \par Complexity
/// \f$O(N)\f$
///
template<typename...ArgsT>
constexpr void emplace(size_t i, ArgsT&&...args) {
@@ -496,6 +607,10 @@ public:
///
/// \brief Push Back Copy
/// \param val Value to initialize with
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void push_back(const TypeT& val) {
dynarray::insert(_size, val);
}
@@ -503,6 +618,10 @@ public:
///
/// \brief Push Back Move
/// \param val Value to initialize with
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void push_back(TypeT&& val) {
dynarray::insert(_size, fennec::forward<TypeT>(val));
}
@@ -511,6 +630,10 @@ public:
/// \brief Emplace Back
/// \tparam ArgsT Argument Types
/// \param args Arguments to construct with
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr void emplace_back(ArgsT...args) {
dynarray::emplace(_size, fennec::forward<ArgsT>(args)...);
@@ -518,6 +641,10 @@ public:
///
/// \brief Erase last element
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void pop_back() {
fennec::destruct(&_alloc[--_size]);
}
@@ -525,9 +652,15 @@ public:
///
/// \brief Resize the dynarray, invoking the default constructor for all new elements
/// \param n The new size in elements
///
/// \details if \f$n\f$ is less than the current size, any elements that would be removed are destructed
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void resize(size_t n) {
_reduce(n);
_alloc.creallocate(n);
_alloc.reallocate(n);
for (size_t i = _size; i < n; ++i) {
fennec::construct(&_alloc[i]);
@@ -542,9 +675,13 @@ public:
/// \param val The value to fill with
///
/// \details if \f$n\f$ is less than the current size, any elements that would be removed are destructed
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void resize(size_t n, const TypeT& val) {
_reduce(n);
_alloc.creallocate(n);
_alloc.reallocate(n);
for (size_t i = _size; i < n; ++i) {
fennec::construct(&_alloc[i], val);
@@ -558,13 +695,21 @@ public:
/// \param n The new capacity in elements
///
/// \details if \f$n\f$ is less than the current size, any elements that would be removed are destructed
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void reserve(size_t n) {
_reduce(n);
_alloc.creallocate(n);
_alloc.reallocate(n);
}
///
/// \brief Clears the contents of the dynarray, destructing all elements and releasing the allocation.
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void clear() {
_reduce(0);
_alloc.deallocate();
@@ -581,26 +726,42 @@ public:
///
/// \returns A pointer to the first element in the dynarray
constexpr TypeT* begin() { return _alloc.data(); }
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr TypeT* begin() { return _alloc; }
///
/// \brief C++ Iterator Specification \f$begin()\f$
/// \returns A const qualified pointer to the first element in the dynarray
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const TypeT* begin() const { return _alloc; }
///
/// \return A pointer to the address after the last element in the dynarray
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr TypeT* end() { return begin() + _size; }
///
/// \brief C++ Iterator Specification \f$end()\f$
/// \return A const qualified pointer to the address after the last element in the dynarray
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const TypeT* end() const { return begin() + _size; }
/// @}
// Private Members =====================================================================================================
// Public Member Variables =============================================================================================
private:
allocation<value_t, alloc_t> _alloc;
size_t _size;
@@ -611,7 +772,7 @@ private:
// helper to double the capacity of the allocation
constexpr void _grow() {
_alloc.creallocate(_alloc.capacity() * 2);
_alloc.reallocate(_alloc.capacity() * 2);
}
// helper to destruct elements past n

View File

@@ -53,6 +53,7 @@ namespace fennec
/// | find | ⛔ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
/// | space | \f$O(1)\f$ |
struct generic {
// Definitions =========================================================================================================
@@ -68,11 +69,18 @@ private:
using manager_t = void* (*)(uint8_t, void*);
// Constructors ========================================================================================================
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Default Constructor
///
/// \par Complexity
/// \f$O(1)\f$
///
generic()
: _handle(nullptr)
, _manage(nullptr) {
@@ -81,6 +89,10 @@ public:
///
/// \brief Copy Constructor
/// \param gen The generic object to copy
///
/// \par Complexity
/// \f$O(1)\f$
///
generic(const generic& gen)
: _handle(nullptr)
, _manage(gen._manage) {
@@ -92,6 +104,10 @@ public:
///
/// \brief Move Constructor
/// \param gen The generic object to move
///
/// \par Complexity
/// \f$O(1)\f$
///
generic(generic&& gen)
: _handle(gen._handle)
, _manage(gen._manage) {
@@ -103,6 +119,10 @@ public:
/// \brief Value Constructor
/// \tparam T The type of the value
/// \param x The value
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T>
generic(T&& x)
: _handle(new T(fennec::forward<T>(x)))
@@ -114,6 +134,10 @@ public:
/// \tparam T The type to construct
/// \tparam ArgsT The argument types
/// \param args The argument values
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T, typename...ArgsT>
generic(type_identity<T>, ArgsT&&...args)
: _handle(new T(fennec::forward<ArgsT>(args)...))
@@ -126,31 +150,53 @@ public:
reset();
}
/// @}
// Properties ==========================================================================================================
public:
/// \name Properties
/// @{
///
/// \brief runtime type acquisition
/// \returns a runtime type struct referencing the held type
///
/// \par Complexity
/// \f$O(1)\f$
///
type type() const {
return *static_cast<fennec::type*>(_manage(op_type, nullptr));
}
///
/// \returns \f$true\f$ if there is a held value, \f$false\f$ otherwise
///
/// \par Complexity
/// \f$O(1)\f$
///
bool has_value() const {
return _handle != nullptr;
}
/// @}
// Assignment ==========================================================================================================
public:
/// \name Assignment Operators
/// @{
///
/// \brief copy assignment
/// \param gen the generic to copy
/// \returns a reference to self after copying the contents of \f$gen\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
generic& operator=(const generic& gen) {
if (this == &gen) { // self-assignment case
return *this;
@@ -166,6 +212,10 @@ public:
/// \brief move assignment
/// \param gen the generic to move
/// \returns a reference to self after swapping contents with \f$gen\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
generic& operator=(generic&& gen) noexcept {
swap(gen);
return *this;
@@ -176,6 +226,10 @@ public:
/// \tparam T the type of the value
/// \param x the value to assign
/// \returns a reference to self after having assigned \f$x\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T>
generic& operator=(T&& x) {
reset();
@@ -184,17 +238,26 @@ public:
return *this;
}
/// @}
// Insertion & Deletion ================================================================================================
// Modifiers ===========================================================================================================
public:
/// \name Modifiers
/// @{
///
/// \brief emplace value
///
/// \details constructs a new value of type \f$T\f$ using \f$args...\f$
/// \details constructs a new value of type \f$T\f$ using \f$args\ldots\f$
/// \tparam T the type to construct
/// \tparam ArgsT the argument types
/// \param args the argument values
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T, typename...ArgsT>
void emplace(ArgsT&&...args) {
reset();
@@ -205,6 +268,10 @@ public:
///
/// \brief reset value
/// \details clears the held value using the appropriate destructor
///
/// \par Complexity
/// \f$O(1)\f$
///
void reset() {
if (_manage) {
_handle = _manage(op_destroy, _handle);
@@ -212,24 +279,37 @@ public:
}
}
// Utility =============================================================================================================
public:
///
/// \brief C++ 11 Swap Specification
/// \param gen the generic to swap with
///
/// \par Complexity
/// \f$O(1)\f$
///
void swap(generic& gen) noexcept {
fennec::swap(_handle, gen._handle);
fennec::swap(_manage, gen._manage);
}
/// @}
// Casting =============================================================================================================
public:
/// \name Casting
/// @{
///
/// \brief cast value
///
/// \details equivalent to \f$reinterpret_cast\f$
/// \tparam T The type to cast to
/// \returns The contents of generic after having cast to \f$T\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T, typename U = remove_cvref_t<T>>
T cast() {
return static_cast<T>(*static_cast<U*>(_handle));
@@ -239,19 +319,25 @@ public:
/// \details equivalent to \f$reinterpret_cast\f$
/// \tparam T The type to cast to
/// \returns The contents of generic after having cast to \f$T\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T, typename U = remove_cvref_t<T>>
T cast() const {
return static_cast<T>(*static_cast<U*>(_handle));
}
/// @}
// Members =============================================================================================================
// Private Member Variables ============================================================================================
private:
void* _handle;
manager_t _manage;
// Helpers =============================================================================================================
// Private Helpers =====================================================================================================
private:
template<typename T>
static void* _manage_impl(uint8_t op, void* hnd) {

View File

@@ -56,7 +56,7 @@ namespace fennec
///
/// \details
/// | Property | Value |
/// |:-----------:|:----------:|
/// |:-----------:|:--------------:|
/// | stable | ⛔ |
/// | dynamic | ✅ |
/// | homogeneous | ✅ |
@@ -68,6 +68,7 @@ namespace fennec
/// | find | \f$O(1)\f$ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(M)\f$ |
/// | space | \f$O(N + M)\f$ |
///
/// Graphs contain vertices and edges. Graphs are either directed
/// or undirected. This structure allows the creation of both directed and undirected edges. As
@@ -92,13 +93,24 @@ struct graph {
public:
// Definitions =========================================================================================================
using edge_t = EdgeT; ///< Alias for the edge type
using vertex_t = VertexT; ///< Alias for the vertex type
using vertex_pool_t = object_pool<vertex_t>; ///< Alias for a pool of vertices
using edge_map_t = dynarray<map<size_t, size_t>>; ///< Alias for edge mapping
using edge_pool_t = object_pool<edge_t>; ///< Alias for a pool of edges
/// \name Definitions
/// @{
static constexpr size_t npos = -1; ///< Constant for a non-existent vertex
using edge_t = EdgeT; //!< Alias for the edge type
using vertex_t = VertexT; //!< Alias for the vertex type
using vertex_pool_t = object_pool<vertex_t>; //!< Alias for a pool of vertices
using edge_map_t = dynarray<map<size_t, size_t>>; //!< Alias for edge mapping
using edge_pool_t = object_pool<edge_t>; //!< Alias for a pool of edges
/// @}
/// \name Constants
/// @{
static constexpr size_t npos = -1; //!< Constant for a non-existent vertex
/// @}
// Constructors ========================================================================================================
@@ -108,10 +120,18 @@ public:
///
/// \brief Default Constructor, initializes empty graph
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr graph() = default;
///
/// \brief Destructor
///
/// \par Complexity
/// \f$O(N + M)\f$
///
constexpr ~graph() = default;
/// @}
@@ -124,12 +144,20 @@ public:
/// \brief Copy Assignment Operator
/// \param g The graph to copy
/// \returns A reference to this after assigning g
///
/// \par Complexity
/// \f$O(N + M)\f$
///
constexpr graph& operator=(const graph& g) = default;
///
/// \brief Move Assignment Operator
/// \param g The graph to copy
/// \returns A reference to this after assigning g
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr graph& operator=(graph&& g) = default;
/// @}
@@ -142,24 +170,40 @@ public:
///
/// \returns The number of vertices in the graph
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t num_vertices() const {
return _vertex_pool.size();
}
///
/// \returns The number of edges in the graph
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t num_edges() const {
return _edge_pool.size();
}
///
/// \returns The capacity of the vertex pool
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t capacity() const {
return _vertex_pool.capacity();
}
///
/// \returns \f$true\f$ when there are no vertices in the graph, \f$false\f$ otherwise
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const {
return num_vertices() == 0;
}
@@ -169,6 +213,10 @@ public:
/// \param a The first vertex
/// \param b The second vertex
/// \returns \f$true\f$ if the edge exists, \f$false\f$ otherwise
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool exists(size_t a, size_t b) const {
return _edge_map[a][b] != nullptr;
}
@@ -179,6 +227,10 @@ public:
/// \param a The first vertex
/// \param b The second vertex
/// \returns \f$true\f$ if both edges exist, \f$false\f$ otherwise
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_symmetric(size_t a, size_t b) const {
return exists(a, b) and exists(b, a);
}
@@ -188,6 +240,10 @@ public:
/// \param a The first vertex
/// \param b The second vertex
/// \returns \f$true\f$ if both edges exist, \f$false\f$ otherwise
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_undirected(size_t a, size_t b) const {
const auto* e0 = _edge_map[a][b];
const auto* e1 = _edge_map[b][a];
@@ -211,6 +267,10 @@ public:
/// \brief vertex Access Operator
/// \param vertex The id of the vertex
/// \returns A reference to the value stored in the vertex
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr vertex_t& operator[](size_t vertex) {
return _vertex_pool[vertex];
}
@@ -219,6 +279,10 @@ public:
/// \brief vertex Const Access Operator
/// \param vertex The id of the vertex
/// \returns A reference to the value stored in the vertex
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const vertex_t& operator[](size_t vertex) const {
return _vertex_pool[vertex];
}
@@ -228,6 +292,10 @@ public:
/// \param a The id of the first vertex
/// \param b The id of the second vertex
/// \returns A pointer to the value stored in the edge, \f$nullptr\f$ if not found
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr edge_t* operator[](size_t a, size_t b) {
if (is_empty()) {
return nullptr;
@@ -244,6 +312,10 @@ public:
/// \param a The id of the first vertex
/// \param b The id of the second vertex
/// \returns A const-qualified pointer to the value stored in the edge, \f$nullptr\f$ if not found
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const edge_t* operator[](size_t a, size_t b) const {
if (is_empty()) {
return nullptr;
@@ -256,9 +328,13 @@ public:
}
///
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge to \f$x...\f$
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge to \f$x\ldots\f$
/// \param vertex The id of the vertex
/// \returns A list containing all vertices \f$x\f$ with edges from \f$vertex\f$ to \f$x...\f$
/// \returns A list containing all vertices \f$x\f$ with edges from \f$vertex\f$ to \f$x\ldots\f$
///
/// \par Complexity
/// \f$O(M)\f$
///
list<size_t> outgoing(size_t vertex) {
list<size_t> res;
if (is_empty() || vertex >= _edge_map.size()) {
@@ -271,9 +347,13 @@ public:
}
///
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge from \f$x...\f$
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge from \f$x\ldots\f$
/// \param vertex The id of the vertex
/// \returns A list containing all vertices \f$x\f$ with edges from \f$x...\f$ to \f$vertex\f$
/// \returns A list containing all vertices \f$x\f$ with edges from \f$x\ldots\f$ to \f$vertex\f$
///
/// \par Complexity
/// \f$O(M)\f$
///
list<size_t> incoming(size_t vertex) {
list<size_t> res;
if (is_empty() || vertex >= _edge_map.size()) {
@@ -288,9 +368,13 @@ public:
}
///
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge to and from \f$x...\f$
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge to and from \f$x\ldots\f$
/// \param vertex The id of the vertex
/// \returns A list containing all vertices \f$x\f$ that have symmetric edges with \f$vertex\f$
///
/// \par Complexity
/// \f$O(M)\f$
///
list<size_t> symmetric(size_t vertex) {
list<size_t> res;
if (is_empty() || vertex >= _edge_map.size()) {
@@ -305,13 +389,17 @@ public:
}
///
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge to and from \f$x...\f$ and share the same value
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge to and from \f$x\ldots\f$ and share the same value
/// \details
/// "Joined" edges may also be referred to as "undirected." A joined, or undirected, edge may be
/// turned into a directed edge by changing the weight object associated with the edge, or by
/// removing one of the sub-edges.
/// \param vertex The id of the vertex
/// \returns A list containing all vertices \f$x\f$ that have symmetric edges with \f$vertex\f$
///
/// \par Complexity
/// \f$O(M)\f$
///
list<size_t> undirected(size_t vertex) {
list<size_t> res;
if (is_empty() || vertex >= _edge_map.size()) {
@@ -331,6 +419,10 @@ public:
/// Use this when you want to iterate over edges that start from this vertex.
/// \param vertex The id of the vertex
/// \returns A pointer to a map containing edges mapped from this vertex
///
/// \par Complexity
/// \f$O(M)\f$
///
const auto* edges(size_t vertex) {
if (is_empty() || vertex >= _edge_map.size()) {
return nullptr;
@@ -350,6 +442,10 @@ public:
/// \brief Move a new vertex into the graph
/// \param vertex The vertex to move into the graph
/// \returns The id of the new vertex
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert(vertex_t&& vertex) {
return this->_insert(fennec::forward<vertex_t>(vertex));
}
@@ -358,6 +454,10 @@ public:
/// \brief Copy a new vertex into the graph
/// \param vertex The vertex to copy into the graph
/// \returns The id of the new vertex
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert(const vertex_t& vertex) {
return this->_insert(vertex);
}
@@ -367,6 +467,10 @@ public:
/// \tparam ArgsT The types of the arguments
/// \param args The arguments to construct the vertex with
/// \returns The id of the new vertex
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr size_t emplace(ArgsT&&...args) {
return this->_insert(fennec::forward<ArgsT>(args)...);
@@ -375,6 +479,10 @@ public:
///
/// \brief Erase a vertex from the graph
/// \param vertex The id of the vertex to erase
///
/// \par Complexity
/// \f$O(M)\f$
///
constexpr void erase(size_t vertex) {
cut(vertex);
_vertex_pool.erase(vertex);
@@ -386,6 +494,10 @@ public:
/// \param a The first vertex id
/// \param b The second vertex id
/// \param args The arguments to construct the edge with
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr void make_edge(size_t a, size_t b, ArgsT&&...args) {
if (a == b) {
@@ -413,6 +525,10 @@ public:
/// \param a The first vertex id
/// \param b The second vertex id
/// \param args The arguments to construct the edge with
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr void make_edge2(size_t a, size_t b, ArgsT&&...args) {
if (a == b) {
@@ -440,6 +556,10 @@ public:
/// \brief Disconnect an edge from vertex \f$a\f$ to vertex \f$b\f$
/// \param a The first vertex id
/// \param b The second vertex id
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void cut_edge(size_t a, size_t b) {
// Find the edge object
@@ -463,6 +583,10 @@ public:
/// \brief Disconnect both directed edges between vertices \f$a\f$ and \f$b\f$
/// \param a The first vertex id
/// \param b The second vertex id
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void cut_edge2(size_t a, size_t b) {
const auto* ita = _edge_map[a][b];
const auto* itb = _edge_map[a][b];
@@ -478,6 +602,10 @@ public:
///
/// \brief Break *all* edges connected to \f$n\f$
/// \param n The vertex id
///
/// \par Complexity
/// \f$O(M)\f$
///
void cut(size_t n) {
for (const auto it : outgoing(n)) {
cut_edge(n, it);
@@ -489,6 +617,10 @@ public:
///
/// \brief Clear the graph, destructing all vertices and edges.
///
/// \par Complexity
/// \f$O(N + M)\f$
///
void clear() {
_vertex_pool.clear();
_edge_pool.clear();

View File

@@ -61,6 +61,7 @@ namespace fennec
/// | find | \f$O(N)\f$ |
/// | insertion | \f$O(N)\f$ |
/// | deletion | \f$O(N)\f$ |
/// | space | \f$O(N)\f$ |
///
/// \note Access, Insertion, and Deletion are \f$O(N)\f$ using the index pattern,
/// using the iterator pattern yields \f$O(1)\f$ runtime.
@@ -70,20 +71,25 @@ template<class TypeT, class Alloc = allocator<TypeT>>
struct list {
// Definitions =========================================================================================================
private:
struct node;
public:
/// \name Definitions
/// @{
/// \brief Alias for the allocator type, rebound to list nodes
using alloc_t = typename allocator_traits<Alloc>::template rebind<node>;
using value_t = TypeT; ///< Alias for the value type
using value_t = TypeT; //!< Alias for the value type
static constexpr size_t npos = -1; ///< Constant representing a non-existant position
static constexpr size_t npos = -1; //!< Constant representing a non-existant position
class iterator; ///< Iterator type for forward iteration over the list
class const_iterator; ///< Iterator type for forward iteration over a constant list
/// @}
class iterator;
class const_iterator;
private:
using table_t = dynarray<node, alloc_t>;
@@ -98,6 +104,10 @@ public:
///
/// \brief Default Constructor, initializes an empty list.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr list()
: _table(), _freed(), _root(npos), _last(npos), _size(0) {
}
@@ -105,6 +115,10 @@ public:
///
/// \brief Copy Constructor, copies all elements in \f$l\f$ with optimized layout
/// \param l The list to copy
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr list(const list& l)
: list() {
for (const value_t& it : l) {
@@ -116,6 +130,10 @@ public:
///
/// \brief Move Constructor, takes ownership of the list
/// \param l The list to move
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr list(list&& l) noexcept
: _table(fennec::move(l._table))
, _freed(fennec::move(l._freed))
@@ -126,10 +144,12 @@ public:
///
/// \brief Destructor, destructs all elements then releases the allocation.
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr ~list() {
for (size_t i = 0; i < capacity(); ++i) {
_table[i].value = nullopt;
}
clear();
}
/// @}
@@ -137,13 +157,17 @@ public:
// Assignment ==========================================================================================================
public:
/// \name Assignment
/// \name Assignment Operators
/// @{
///
/// \brief Copy Assignment Operator
/// \param l the list to copy
/// \returns \f$this\f$ after having copied all elements of \f$l\f$
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr list& operator=(const list& l) {
this->clear();
for (const value_t& it : l) {
@@ -156,6 +180,10 @@ public:
/// \brief Move Assignment Operator
/// \param l the list to copy
/// \returns \f$this\f$ after having taken ownership over the contents of \f$l\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr list& operator=(list&& l) noexcept {
this->clear();
_table = fennec::move(l._table);
@@ -176,18 +204,30 @@ public:
///
/// \returns The size of the list in elements.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t size() const {
return _size;
}
///
/// \returns The capacity of the list in elements.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t capacity() const {
return _table.size();
}
///
/// \returns \f$true\f$ when the list is empty, \f$false\f$ otherwise.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const {
return _root == npos;
}
@@ -206,7 +246,9 @@ public:
/// \param i Index to access
/// \returns A reference to the element at \f$i\f$
///
/// \details \f$O(N)\f$
/// \par Complexity
/// \f$O(N)\f$
///
constexpr value_t& operator[](int i) {
assertd(i >= 0 && size_t(i) < _size, "Index out of Bounds");
size_t n = _walk(i);
@@ -219,7 +261,9 @@ public:
/// \param i Index to access
/// \returns A const-qualified reference to the element at \f$i\f$
///
/// \details \f$O(N)\f$
/// \par Complexity
/// \f$O(N)\f$
///
constexpr const value_t& operator[](int i) const {
assertd(i >= 0 && size_t(i) < _size, "Index out of Bounds");
size_t n = _walk(i);
@@ -230,6 +274,10 @@ public:
///
/// \brief Access Front Element
/// \returns A reference to the first element in the list
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t& front() {
return *_table[_root].value;
}
@@ -237,6 +285,10 @@ public:
///
/// \brief Const Access Front Element
/// \returns A const-qualified reference to the first element in the list
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t& front() const {
return *_table[_root].value;
}
@@ -244,6 +296,10 @@ public:
///
/// \brief Access Back Element
/// \returns A reference to the last element in the list
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t& back() {
return *_table[_last].value;
}
@@ -251,6 +307,10 @@ public:
///
/// \brief Const Access Back Element
/// \returns A const-qualified reference to the last element in the list
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t& back() const {
return *_table[_last].value;
}
@@ -270,7 +330,9 @@ public:
/// \param x value to copy
/// \returns The id of the inserted node
///
/// \details \f$O(1)\f$
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator insert(const iterator& it, const value_t& x) {
return this->_insert(it._n, x);
}
@@ -281,7 +343,9 @@ public:
/// \param x value to move
/// \returns The id of the inserted node
///
/// \details \f$O(1)\f$
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator insert(const iterator& it, value_t&& x) {
return this->_insert(it._n, fennec::forward<value_t>(x));
}
@@ -292,7 +356,9 @@ public:
/// \param x value to copy
/// \returns The id of the inserted node
///
/// \details \f$O(N)\f$
/// \par Complexity
/// \f$O(N)\f$
///
constexpr iterator insert(size_t i, const value_t& x) {
assert(i <= size(), "Index out of Bounds");
@@ -306,7 +372,9 @@ public:
/// \param x value to move
/// \returns The id of the inserted node
///
/// \details \f$O(N)\f$
/// \par Complexity
/// \f$O(N)\f$
///
constexpr iterator insert(size_t i, value_t&& x) {
assert(i <= size(), "Index out of Bounds");
@@ -321,7 +389,9 @@ public:
/// \param args Arguments to construct with
/// \returns The id of the inserted node
///
/// \details \f$O(N)\f$
/// \par Complexity
/// \f$O(N)\f$
///
template<typename...ArgsT>
constexpr iterator emplace(size_t i, ArgsT&&...args) {
assert(i <= size(), "Index out of Bounds");
@@ -337,7 +407,9 @@ public:
/// \param args Arguments to construct with
/// \returns The id of the inserted node
///
/// \details \f$O(N)\f$
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr iterator emplace(const iterator& it, ArgsT&&...args) {
return this->_insert(it._n, fennec::forward<ArgsT>(args)...);
@@ -347,6 +419,10 @@ public:
/// \brief Push Front Copy
/// \param x Value to copy
/// \returns The id of the inserted node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator push_front(const value_t& x) {
return this->_insert(_root, x);
}
@@ -355,6 +431,10 @@ public:
/// \brief Push Front Move
/// \param x Value to move
/// \returns The id of the inserted node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator push_front(value_t&& x) {
return this->_insert(_root, fennec::forward<value_t>(x));
}
@@ -364,6 +444,10 @@ public:
/// \param args Arguments to construct with
/// \tparam ArgsT Argument types
/// \returns The id of the inserted node
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr iterator emplace_front(ArgsT&&...args) {
return this->_insert(_root, fennec::forward<ArgsT>(args)...);
@@ -373,6 +457,10 @@ public:
/// \brief Push Back Copy
/// \param x Value to copy
/// \returns The id of the inserted node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator push_back(const value_t& x) {
return this->_insert(npos, x);
}
@@ -381,6 +469,10 @@ public:
/// \brief Push Back Move
/// \param x Value to move
/// \returns The id of the inserted node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator push_back(value_t&& x) {
return this->_insert(npos, fennec::forward<value_t>(x));
}
@@ -390,6 +482,10 @@ public:
/// \param args Arguments to construct with
/// \tparam ArgsT Argument types
/// \returns The id of the inserted node
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr iterator emplace_back(ArgsT&&...args) {
return this->_insert(npos, fennec::forward<ArgsT>(args)...);
@@ -398,6 +494,10 @@ public:
///
/// \brief Erase Element
/// \param i Index to erase
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void erase(size_t i) {
assert(i < size(), "Index out of Bounds!");
size_t n = _walk(i);
@@ -407,24 +507,40 @@ public:
///
/// \brief Erase Element
/// \param it Location to Erase
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void erase(const iterator& it) {
this->_erase(it._n);
}
///
/// \brief Pop Front, erases first element
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void pop_front() {
_erase(_root);
}
///
/// \brief Pop Back, erases first element
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void pop_back() {
_erase(_last);
}
///
/// \brief Clears the list, destructing all elements in order
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void clear() {
size_t i = _root;
while (i != npos) {
@@ -432,6 +548,8 @@ public:
i = this->_next(i);
}
_table.clear();
_root = npos;
_size = 0;
}
/// @}
@@ -444,19 +562,31 @@ public:
///
/// \returns An iterator for the first element in the list
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator begin() {
return iterator(this, _root);
}
///
/// \brief C++ Iterator Specification \f$end()\f$
/// \brief C++ Iterator Specification \f$begin()\f$
/// \returns A const iterator for the first element in the list
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const_iterator begin() const {
return const_iterator(this, _root);
}
///
/// \returns An iterator for the end of the list
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator end() {
return iterator(this, npos);
}
@@ -464,12 +594,14 @@ public:
///
/// \brief Const C++ Iterator Specification \f$end()\f$
/// \returns A const iterator for the end of the list
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const_iterator end() const {
return const_iterator(this, npos);
}
/// @}
///
/// \brief C++ Iterator Specification \f$iterator\f$
class iterator {
@@ -613,7 +745,9 @@ public:
}
};
// Members =============================================================================================================
/// @}
// Private Member Variables ============================================================================================
private:
table_t _table;
freed_t _freed;
@@ -622,7 +756,7 @@ private:
friend class iterator;
// Helpers =============================================================================================================
// Private Helpers =====================================================================================================
private:
constexpr void _expand() {
_table.resize(fennec::max(_table.size(), size_t(4)) * 2);

View File

@@ -71,6 +71,7 @@ namespace fennec
/// | find | \f$O(1)\f$ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
/// | space | \f$O(N)\f$ |
///
/// \note These runtimes are amortized, in theory the worst case is \f$O(N)\f$, but that is highly improbable.
///
@@ -83,15 +84,19 @@ struct map {
// Definitions =========================================================================================================
public:
struct key_hash; ///< Hash for node keys
struct key_equals; ///< Comparison for node keys
using key_t = KeyT; ///< The key type
using value_t = ValueT; ///< The value type
using elem_t = pair<KeyT, ValueT>; ///< then node type
using alloc_t = typename allocator_traits<Alloc>::template rebind<elem_t>; ///< Rebinds the allocator type to nodes
using hash_t = Hash; ///< The hash type
using set_t = set<elem_t, key_hash, key_equals, alloc_t>; ///< The underlying set
using iterator = set_t::iterator; ///< Iterator type
/// \name Definitions
/// @{
struct key_hash; //!< Hash for node keys
struct key_equals; //!< Comparison for node keys
using key_t = KeyT; //!< The key type
using value_t = ValueT; //!< The value type
using elem_t = pair<KeyT, ValueT>; //!< then node type
using alloc_t = typename allocator_traits<Alloc>::template rebind<elem_t>; //!< Rebinds the allocator type to nodes
using hash_t = Hash; //!< The hash type
using set_t = set<elem_t, key_hash, key_equals, alloc_t>; //!< The underlying set
using iterator = set_t::iterator; //!< Iterator type
///
/// \brief key hash helper
@@ -118,8 +123,11 @@ public:
}
};
/// @}
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
@@ -136,6 +144,7 @@ public:
// Properties ==========================================================================================================
public:
/// \name Properties
/// @{
@@ -162,6 +171,7 @@ public:
// Access ==============================================================================================================
public:
/// \name Access
/// @{
@@ -170,6 +180,10 @@ public:
/// \brief Key Access Operator
/// \param key Key value to access
/// \returns A pointer to the value associated with \f$key\f$, \f$nullptr\f$ if \f$key\f$ is not present.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t* operator[](const KeyT& key) {
auto it = _set.at(this->_find(key));
return it ? &it->second : nullptr;
@@ -179,6 +193,10 @@ public:
/// \brief Key Const Access Operator
/// \param key Key value to access
/// \returns A const-qualified pointer to the value associated with \f$key\f$, \f$nullptr\f$ if \f$key\f$ is not present.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t* operator[](const KeyT& key) const {
auto it = _set.at(this->_find(key));
return it ? &it->second : nullptr;
@@ -189,6 +207,10 @@ public:
/// \tparam ArgsT Argument Types
/// \param args Arguments to construct the key with
/// \returns A pointer to the value associated with \f$key\f$, \f$nullptr\f$ if \f$key\f$ is not present.
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr value_t* operator[](ArgsT&&...args) {
auto it = _set.at(this->_find(fennec::forward<ArgsT>(args)...));
@@ -200,6 +222,10 @@ public:
/// \tparam ArgsT Argument Type
/// \param args Argument to construct the key with
/// \returns A const-qualified pointer to the value associated with \f$key\f$, \f$nullptr\f$ if \f$key\f$ is not present.
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr const value_t* operator[](ArgsT&&...args) const {
auto it = _set.at(this->_find(fennec::forward<ArgsT>(args)...));
@@ -210,6 +236,7 @@ public:
// Modifiers ===========================================================================================================
public:
/// \name Modifiers
/// @{
@@ -217,6 +244,10 @@ public:
///
/// \brief Key-Value Insertion
/// \param pair a pair containing the key and its value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void insert(elem_t&& pair) {
this->_insert(fennec::forward<elem_t>(pair));
}
@@ -225,6 +256,10 @@ public:
/// \brief Key-Value Insertion
/// \param key key to insert
/// \param args Arguments for constructing the key-value pair
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr void emplace(const KeyT& key, ArgsT&&...args) {
this->_insert(key, fennec::forward<ArgsT>(args)...);
@@ -233,6 +268,10 @@ public:
///
/// \brief Key-Value Insertion
/// \param args Arguments for constructing the key-value pair
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr void emplace(ArgsT&&...args) {
this->_insert(fennec::forward<ArgsT>(args)...);
@@ -241,6 +280,10 @@ public:
///
/// \brief Erase a key
/// \param key key to erase
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void erase(KeyT&& key) {
_set.erase(this->_find(fennec::forward<KeyT>(key)));
}
@@ -248,6 +291,10 @@ public:
///
/// \brief Erase a key
/// \param key key to erase
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void erase(const KeyT& key) {
_set.erase(this->_find(key));
}
@@ -256,6 +303,10 @@ public:
/// \brief Argument Erase
/// \tparam ArgsT Argument Types
/// \param args Arguments to construct a key to erase
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr void erase(ArgsT&&...args) {
_set.erase(this->_find(fennec::forward<ArgsT>(args)...));
@@ -263,6 +314,10 @@ public:
///
/// \brief Clears the map destructing all elements
///
/// \par Complexity
/// \f$O(1)\f$
///
void clear() {
_set.clear();
}
@@ -271,6 +326,7 @@ public:
// Iteration ===========================================================================================================
public:
/// \name Iteration
/// @{
@@ -278,6 +334,10 @@ public:
///
/// \brief C++ Iterator Specification \f$begin()\f$
/// \returns an iterator at the start of the map
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator begin() {
return _set.begin();
}
@@ -286,6 +346,10 @@ public:
///
/// \brief C++ Iterator Specification \f$end()\f$
/// \returns an iterator at the end of the map
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator end() {
return _set.end();
}
@@ -293,9 +357,13 @@ public:
/// @}
// Private Member Variables ============================================================================================
private:
set_t _set;
// Private Helpers =====================================================================================================
private:
template<typename...ArgsT>
set_t::iterator _find(ArgsT&&...args) const {
union U { // Hacky way of avoiding constructing the value, TODO: Check for warnings on other compilers

View File

@@ -54,6 +54,7 @@ namespace fennec
/// | find | \f$O(N)\f$ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
/// | space | \f$O(N)\f$ |
///
/// \tparam TypeT The value type
/// \tparam AllocT The allocator type
@@ -62,28 +63,43 @@ struct object_pool {
// Definitions =========================================================================================================
public:
/// \name Definitions
/// @{
using value_t = TypeT; //!< The held object type
using elem_t = optional<value_t>; //!< The element type
using table_t = dynarray<elem_t, AllocT>; //!< The underlying table type
using freed_t = list<size_t, AllocT>; //!< The underlying free queue
/// @}
class iterator;
class const_iterator;
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Default Constructor, initializes an empty object pool
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr object_pool()
: _size(0) {
}
///
/// \brief Default Destructor, destructs objects then releases the allocation.
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr ~object_pool() = default;
/// @}
@@ -96,18 +112,30 @@ public:
///
/// \returns The number of active objects in the pool
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t size() const {
return _size;
}
///
/// \returns The capacity of the underlying allocation
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t capacity() const {
return _table.capacity();
}
///
/// \returns \f$true\f$ when there are no objects in the pool, \f$false\f$ otherwise
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const {
return size() == 0;
}
@@ -117,6 +145,10 @@ public:
///
/// \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
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t next_id() const {
size_t next = _size;
if (not _freed.is_empty()) {
@@ -136,6 +168,10 @@ public:
/// \brief Array Access Operator
/// \param i id of the object
/// \returns a reference to the object with id \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t& operator[](size_t i) {
assert(i < capacity(), "Index out of Bounds!");
assert(_table[i], "Attempted to access null object.")
@@ -146,6 +182,10 @@ public:
/// \brief Array Const Access Operator
/// \param i id of the object
/// \returns a const-qualified reference to the object with id \f$i\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t& operator[](size_t i) const {
assert(i < capacity(), "Index out of Bounds!");
assert(_table[i], "Attempted to access null object.")
@@ -169,6 +209,10 @@ public:
/// \brief Move Insertion, inserts \f$x\f$ into the pool
/// \param x the object to move
/// \returns An integer corresponding to the id of the node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert(value_t&& x) {
return this->_insert(fennec::forward<value_t>(x));
}
@@ -177,15 +221,23 @@ public:
/// \brief Move Insertion, inserts a copy of \f$x\f$ into the pool
/// \param x the object to copy
/// \returns An integer corresponding to the id of the node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert(const value_t& x) {
return this->_insert(x);
}
///
/// \brief Emplacement, constructs a new object using \f$args...\f$
/// \brief Emplacement, constructs a new object using \f$args\ldots\f$
/// \param args The arguments to construct the new object with
/// \returns An integer corresponding to the id of the node
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr size_t emplace(ArgsT&&...args) {
return this->_insert(fennec::forward<ArgsT>(args)...);
@@ -194,6 +246,10 @@ public:
///
/// \brief Erase an object from the pool
/// \param i The id of the object
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void erase(size_t i) {
_table[i] = nullopt;
_freed.push_back(i);
@@ -202,12 +258,14 @@ public:
///
/// \brief Clear the object pool
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void clear() {
for (auto& it : _table) {
it = nullopt;
}
_size = 0;
_table.clear();
_freed.clear();
_size = 0;
}
/// @}
@@ -217,6 +275,10 @@ public:
///
/// \returns an iterator at the start of the object pool
///
/// \par Complexity
/// \f$O(1)\f$
///
iterator begin() {
return iterator(this, 0);
}
@@ -224,12 +286,20 @@ public:
///
/// \brief C++ Iterator Specification \f$begin()\f$
/// \returns an iterator at the start of the object pool
///
/// \par Complexity
/// \f$O(1)\f$
///
const_iterator begin() const {
return const_iterator(this, 0);
}
///
/// \returns an iterator at the start of the end of the object pool
///
/// \par Complexity
/// \f$O(1)\f$
///
iterator end() {
return iterator(this, _size);
}
@@ -237,6 +307,10 @@ public:
///
/// \brief C++ Iterator Specification \f$end()\f$
/// \returns an iterator at the start of the end of the object pool
///
/// \par Complexity
/// \f$O(1)\f$
///
const_iterator end() const {
return const_iterator(this, _size);
}

View File

@@ -66,6 +66,7 @@ constexpr nullopt_t nullopt_v = {};
/// | find | ⛔ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
/// | space | \f$O(1)\f$ |
///
/// \tparam T
template<typename T>
@@ -73,11 +74,17 @@ struct optional {
// Definitions =========================================================================================================
public:
/// \name Definitions
/// @{
using reference_t = T&; //!< reference type
using pointer_t = T*; //!< pointer type
using const_reference_t = T&; //!< const reference type
using const_pointer_t = const T*; //!< const pointer type
/// @}
// Constructors ========================================================================================================
@@ -86,6 +93,10 @@ public:
///
/// \brief Default Constructor
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional()
: _root(0)
, _set(false) {
@@ -93,6 +104,10 @@ public:
///
/// \brief Default Constructor
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional(nullopt_t)
: _root(0)
, _set(false) {
@@ -101,6 +116,10 @@ public:
///
/// \brief Type Copy Constructor
/// \param val the value to initialize the underlying object with
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional(const T& val)
: _val(val)
, _set(true) {
@@ -109,6 +128,10 @@ public:
///
/// \brief Type Move Constructor
/// \param val the value to initialize the underlying object with
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional(T&& val)
: _val(fennec::forward<T>(val))
, _set(true) {
@@ -117,6 +140,10 @@ public:
///
/// \brief Copy Constructor
/// \param opt the optional to copy
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional(const optional& opt) requires is_copy_assignable_v<T>
: optional() {
_set = opt._set;
@@ -128,6 +155,10 @@ public:
///
/// \brief Move Constructor
/// \param opt the optional to move
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional(optional&& opt) noexcept requires is_move_assignable_v<T>
: optional() {
_set = opt._set;
@@ -141,6 +172,10 @@ public:
/// \brief Emplace Constructor
/// \tparam ArgsT The argument types
/// \param args The argument values
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr optional(ArgsT&&...args)
: _val(fennec::forward<ArgsT>(args)...)
@@ -149,6 +184,10 @@ public:
///
/// \brief destructor
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr ~optional() {
if constexpr(is_fundamental_v<T>) {
return;
@@ -169,12 +208,20 @@ public:
///
/// \brief Implicit Boolean Check
/// \returns \f$true\f$ when there is a value contained
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr operator bool() const {
return _set;
}
///
/// \returns \f$true\f$ when there is no held value, \f$false\f$ otherwise.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const {
return not _set;
}
@@ -184,12 +231,16 @@ public:
// Assignment Operators ================================================================================================
/// \name Assignment
/// \name Assignment Operators
/// @{
///
/// \brief Null Assignment
/// \returns A reference to self
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional& operator=(nullopt_t) {
if constexpr(not is_fundamental_v<T>) {
if (_set) {
@@ -205,6 +256,10 @@ public:
/// \brief Type Copy Assignment
/// \param val The value to set with
/// \returns A reference to self
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional& operator=(const T& val) requires is_copy_constructible_v<T> and is_copy_assignable_v<T> {
if (_set) {
_val = val;
@@ -219,6 +274,10 @@ public:
/// \brief Type Move Assignment
/// \param val The value to set with
/// \returns A reference to self
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional& operator=(T&& val) requires is_move_constructible_v<T> and is_move_assignable_v<T> {
if (_set) {
_val = fennec::forward<T>(val);
@@ -233,6 +292,10 @@ public:
/// \brief Copy Assignment
/// \param opt The optional to copy
/// \returns A reference to self
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional& operator=(const optional& opt) requires is_copy_constructible_v<T> and is_copy_assignable_v<T> {
if (_set != opt._set) {
_set = opt._set;
@@ -252,6 +315,10 @@ public:
/// \brief Move Assignment
/// \param opt The optional to move
/// \returns A reference to self
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr optional& operator=(optional&& opt) noexcept requires is_move_constructible_v<T> and is_move_assignable_v<T> {
if (_set != opt._set) {
_set = opt._set;
@@ -277,12 +344,20 @@ public:
///
/// \returns A pointer to the value, \f$nullptr\f$ if there is no value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr pointer_t operator->() noexcept {
return _set ? &_val : nullptr;
}
///
/// \returns A const-qualified pointer to the value, \f$nullptr\f$ if there is no value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const_pointer_t operator->() const noexcept {
return _set ? &_val : nullptr;
}
@@ -290,6 +365,10 @@ public:
///
/// \brief Dereference Operator
/// \returns A reference to the value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr T& operator*() & noexcept {
assertd(_set, "Attempted to reference the value of an unset optional");
return _val;
@@ -298,6 +377,10 @@ public:
///
/// \brief Const Dereference Operator
/// \returns A const-qualified reference to the value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const T& operator*() const& noexcept {
assertd(_set, "Attempted to reference the value of an unset optional");
return _val;
@@ -306,6 +389,10 @@ public:
///
/// \brief Dereference Operator
/// \returns A reference to the value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr T&& operator*() && noexcept {
assertd(_set, "Attempted to reference the value of an unset optional");
return _val;
@@ -314,6 +401,10 @@ public:
///
/// \brief Const Dereference Operator
/// \returns A const-qualified reference to the value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const T&& operator*() const&& noexcept {
assertd(_set, "Attempted to reference the value of an unset optional");
return _val;
@@ -330,6 +421,10 @@ public:
/// \brief Emplace Assignment, Move overload
/// \param val The object to take ownership of
/// \returns A reference to the held value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr T& emplace(T&& val) {
if (_set) {
_val = fennec::forward<T>(val);
@@ -344,6 +439,10 @@ public:
/// \brief Emplace Assignment, Copy overload
/// \param val The object to copy
/// \returns A reference to the held value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr T& emplace(const T& val) {
if (_set) {
_val = val;
@@ -358,6 +457,10 @@ public:
/// \brief Emplace Assignment
/// \param args The arguments to construct with
/// \returns A reference to the held value
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr T& emplace(ArgsT&&...args) {
if (_set) {
@@ -371,6 +474,10 @@ public:
///
/// \brief Reset the Optional
///
/// \par Complexity
/// \f$O(1)\f$
///
void reset() {
this->operator=(nullopt);
}

View File

@@ -56,34 +56,55 @@ namespace fennec
/// | find | ⛔ |
/// | insertion | ⛔ |
/// | deletion | ⛔ |
/// | space | \f$O(1)\f$ |
///
/// \tparam TypeT0 The type of the first value
/// \tparam TypeT1 The type of the second value
template<typename TypeT0, typename TypeT1>
struct pair {
// Members =============================================================================================================
// Public Member Variables =============================================================================================
public:
/// \name Member Variables
/// @{
TypeT0 first; //!< The first value in the pair
TypeT1 second; //!< The second value in the pair
/// @}
TypeT0 first; ///< The first value in the pair
TypeT1 second; ///< The second value in the pair
// Constructors ========================================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Default Constructor, invokes default constructor for both elements
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr pair() = default;
///
/// \brief Destructor, invokes destructor for both elements
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr ~pair() = default;
///
/// \brief Pair Copy Constructor
/// \param x Value to copy for the first element
/// \param y Value to copy for the first element
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr pair(const TypeT0& x, const TypeT1& y)
: first(x)
, second(y) {
@@ -93,6 +114,10 @@ struct pair {
/// \brief Pair Move Constructor
/// \param x Value to move for the first element
/// \param y Value to move for the first element
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr pair(TypeT0&& x, TypeT1&& y) noexcept
: first(fennec::forward<TypeT0>(x))
, second(fennec::forward<TypeT1>(y)) {
@@ -102,6 +127,10 @@ struct pair {
/// \brief Pair Implicit Constructor
/// \param arg1 Value to initialize the first element
/// \param arg2 Value to initialize the first element
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename Arg1T, typename Arg2T>
constexpr pair(Arg1T&& arg1, Arg2T&& arg2)
: first(fennec::forward<Arg1T>(arg1))
@@ -111,6 +140,10 @@ struct pair {
///
/// \brief Copy Constructor, copies both elements
/// \param pair The pair to copy
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr pair(const pair& pair)
: first(fennec::copy(pair.first))
, second(fennec::copy(pair.second)) {
@@ -119,6 +152,10 @@ struct pair {
///
/// \brief Move Constructor, moves both elements
/// \param pair The pair to move
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr pair(pair&& pair) noexcept
: first(fennec::move(pair.first))
, second(fennec::move(pair.second)) {
@@ -128,6 +165,10 @@ struct pair {
/// \brief Copy Assignment, copies both elements
/// \param pair The pair to copy
/// \returns A reference to self
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr pair& operator=(const pair& pair) {
first = fennec::copy(pair.first);
second = fennec::copy(pair.second);
@@ -138,6 +179,10 @@ struct pair {
/// \brief Move Assignment, moves both elements
/// \param pair The pair to move
/// \returns A reference to self
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr pair& operator=(pair&& pair) {
first = fennec::move(pair.first);
second = fennec::move(pair.second);
@@ -148,6 +193,7 @@ struct pair {
// Comparison ==========================================================================================================
public:
/// \name Comparison
/// @{
@@ -156,6 +202,10 @@ struct pair {
/// \brief Equality Operator
/// \param p Pair to compare with
/// \returns \f$true\f$ when both elements of each pair are equal
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool operator==(const pair& p) const {
return first == p.first and second == p.second;
}
@@ -164,6 +214,10 @@ struct pair {
/// \brief Inequality Operator
/// \param p Pair to compare with
/// \returns \f$true\f$ when either element of each pair are equal
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool operator!=(const pair& p) const {
return first != p.first or second != p.second;
}
@@ -173,6 +227,10 @@ struct pair {
/// \param p Pair to compare with
/// \returns lexical comparison of both elements, i.e. returns \f$true\f$ when the first element is less, or they are
/// equal and the second element is less
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool operator<(const pair& p) const {
return first < p.first or (first == p.first and second < p.second);
}
@@ -182,6 +240,10 @@ struct pair {
/// \param p Pair to compare with
/// \returns lexical comparison of both elements, i.e. returns \f$true\f$ when the first element is less, or they are
/// equal and the second element is less or equal
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool operator<=(const pair& p) const {
return first < p.first or (first == p.first and second <= p.second);
}
@@ -191,6 +253,10 @@ struct pair {
/// \param p Pair to compare with
/// \returns lexical comparison of both elements, i.e. returns \f$true\f$ when the first element is greater, or they are
/// equal and the second element is greater
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool operator>(const pair& p) const {
return first > p.first or (first == p.first and second > p.second);
}
@@ -200,6 +266,10 @@ struct pair {
/// \param p Pair to compare with
/// \returns lexical comparison of both elements, i.e. returns \f$true\f$ when the first element is greater, or they are
/// equal and the second element is greater or equal
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool operator>=(const pair& p) const {
return first > p.first or (first == p.first and second >= p.second);
}

View File

@@ -69,6 +69,7 @@ namespace fennec
/// | find | ⛔ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
/// | space | \f$O(N)\f$ |
///
/// \tparam ValueT The value type
/// \tparam CompareT The compare type, defaults to `fennec::less`
@@ -78,10 +79,16 @@ struct priority_queue {
// Definitions & Constants =============================================================================================
public:
/// \name Definitions
/// @{
using value_t = ValueT; //!< Alias for the value type
using compare_t = CompareT; //!< Alias for the compare type
using alloc_t = allocation<value_t, AllocT>; //!< The underlying allocation type
/// @}
static constexpr size_t npos = -1; //!< value representing a null node
private:
@@ -106,12 +113,20 @@ public:
///
/// \brief default constructor
/// \details initializes an empty queue
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr priority_queue()
: _size(0) {
}
///
/// \brief destructor
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr ~priority_queue() {
while (_size > 0) {
--_size;
@@ -125,18 +140,30 @@ public:
///
/// \returns the size of the queue
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t size() const {
return _size;
}
///
/// \returns the capacity of the underlying allocation
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t capacity() const {
return _table.capacity();
}
///
/// \returns \f$true\f$ if the queue holds no elements
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const {
return size() == 0;
}
@@ -147,6 +174,10 @@ public:
///
/// \returns the value at the front of the queue
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t& front() const {
return _table[0];
}
@@ -158,12 +189,20 @@ public:
///
/// \brief push a new key into the queue
/// \param key the key to insert
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr void push(const value_t& key) {
this->_insert(key);
}
///
/// \param key the key to insert
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr void push(value_t&& key) {
this->_insert(fennec::forward<value_t>(key));
}
@@ -172,6 +211,10 @@ public:
/// \brief emplace a new key into the queue
/// \tparam ArgsT the argument types
/// \param args the argument values
///
/// \par Complexity
/// \f$O(\log N)\f$
///
template<typename...ArgsT>
constexpr void emplace(ArgsT&&...args) {
this->_insert(fennec::forward<ArgsT>(args)...);
@@ -179,6 +222,10 @@ public:
///
/// \brief pop the element at the front of the queue
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr void pop() {
fennec::swap(_table[0], _table[--_size]);
fennec::destruct(&_table[_size]);
@@ -186,14 +233,14 @@ public:
}
// Members =============================================================================================================
// Private Member Variables ============================================================================================
private:
compare_t _compare;
alloc_t _table;
size_t _size;
// Helpers =============================================================================================================
// Private Helpers =====================================================================================================
private:
template<typename...ArgsT>

View File

@@ -57,6 +57,7 @@ namespace fennec
/// | find | \f$O(N)\f$ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
/// | space | \f$O(N)\f$ |
///
/// \tparam TypeT Data type
/// \tparam AllocT Allocator Type
@@ -68,11 +69,24 @@ private:
struct node;
public:
/// \name Definitions
/// @{
using value_t = TypeT; //!< the held value type
using alloc_t = typename allocator_traits<AllocT>::template rebind<node>; //!< the underlying allocator type
/// @}
/// \name Constants
/// @{
static constexpr size_t root = 0; //!< the id of the root node
static constexpr size_t npos = -1; //!< the id of a null node
/// @}
private:
struct node {
value_t value;
@@ -80,7 +94,7 @@ private:
size_t depth, num_children;
constexpr node()
: value(nullopt)
: value()
, parent(npos), child(npos)
, prev(npos), next(npos)
, depth(0), num_children(0) {
@@ -103,6 +117,9 @@ private:
}
};
using table_t = allocation<node, alloc_t>;
using freed_t = list<size_t>;
public:
// Constructors ========================================================================================================
@@ -114,23 +131,36 @@ public:
/// \brief Root Constructor, constructs the root node of the tree
/// \tparam ArgsT The argument types
/// \param args The arguments to construct the root with
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
explicit constexpr rdtree(ArgsT&&...args)
: _table(), _freed(), _size(1) {
_table.creallocate(8);
_table.reallocate(8);
fennec::construct(&_table[0], npos, npos, npos, npos, 0, fennec::forward<ArgsT>(args)...);
}
///
/// \brief Copy Constructor, copies the contents of \f$tree\f$
/// \param tree the rdtree to copy
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr rdtree(const rdtree& tree)
: _table(tree._table), _freed(tree._freed), _size(tree._size) {
// TODO: properly invoke copy constructor for all elements
}
///
/// \brief Move Constructor, takes ownership over the contents of \f$tree\f$
/// \param tree the rdtree to move
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr rdtree(rdtree&& tree) noexcept
: _table(fennec::move(tree._table)), _freed(fennec::move(tree._freed)), _size(tree._size) {
}
@@ -140,14 +170,19 @@ public:
// Assignment ==========================================================================================================
/// \name Assignment
/// \name Assignment Operators
/// @{
///
/// \brief Copy Assignment Operator
/// \param rhs the rdtree to copy
/// \returns \f$this\f$ after copying the contents of \f$rhs\f$
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr rdtree& operator=(const rdtree& rhs) {
// TODO: properly invoke copy constructor for all elements
for (value_t* it : this->_table) {
fennec::destruct(it);
}
@@ -161,6 +196,10 @@ public:
/// \brief Move Assignment Operator
/// \param rhs the rdtree to move
/// \returns \f$this\f$ after taking ownership over the contents of \f$rhs\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr rdtree& operator=(rdtree&& rhs) noexcept {
for (value_t* it : _table) {
fennec::destruct(it);
@@ -180,28 +219,49 @@ public:
///
/// \returns The number of nodes in the tree
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t size() const {
return _size;
}
///
/// \returns The capacity of the underlying allocation
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t capacity() const {
return _table.capacity();
}
///
/// \returns \f$true\f$ when there are no nodes in the tree, \f$false\f$ otherwise
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const {
return _size == 0;
}
/// @}
// Access ==============================================================================================================
/// \name Access
/// @{
///
/// \param i The id of the node to check
/// \returns The id of the parent node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t parent(size_t i) const {
if (i >= _table.capacity()) return npos;
return i == npos ? npos : _table[i].parent;
@@ -211,6 +271,10 @@ public:
/// \param i The id of the node to check
/// \param n The index of the child relative to the parent
/// \returns The id of the child node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t child(size_t i, size_t n = 0) const {
if (i >= _table.capacity() && n != npos) return npos;
size_t c = i == npos ? npos : _table[i].child;
@@ -223,6 +287,10 @@ public:
/// \param i The id of the node to check
/// \param n The index of the child relative to the parent
/// \returns The id of the next node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t next(size_t i, size_t n = 0) const {
if (i >= _table.capacity() && n != npos) return npos;
if (i == npos) {
@@ -248,6 +316,10 @@ public:
/// \param i The id of the node to check
/// \param n The index of the child relative to the parent
/// \returns The id of the previous node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t prev(size_t i, size_t n = 0) const {
if (i >= _table.capacity()) return npos;
if (i == npos) {
@@ -272,6 +344,10 @@ public:
///
/// \param i the node to start at
/// \returns the left-most child of node \f$i\f$
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr size_t left_most(size_t i) const {
if (i >= _table.capacity()) return npos;
size_t n = i;
@@ -289,6 +365,10 @@ public:
///
/// \param i the node to start at
/// \returns the right-most child of node \f$i\f$
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr size_t right_most(size_t i) const {
if (i >= _table.capacity()) return npos;
if ((i = child(i)) == npos) {
@@ -309,6 +389,10 @@ public:
///
/// \param i The id of the node to check
/// \returns The depth of the node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t depth(size_t i) const {
if (i >= _table.capacity()) return npos;
return i == npos ? npos : _table[i].depth;
@@ -317,6 +401,10 @@ public:
///
/// \param i The id of the node to check
/// \returns The number of children the node has
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t num_children(size_t i) const {
if (i >= _table.capacity()) return 0;
return i == npos ? 0 : _table[i].num_children;
@@ -324,6 +412,10 @@ public:
///
/// \returns The next node id were \f$insert\f$ or \f$emplace\f$ to be called
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t next_id() const {
size_t i = _size;
if (not _freed.is_empty()) {
@@ -335,6 +427,10 @@ public:
///
/// \param i The id of the node to access
/// \returns A reference to the value of the node wrapped in an optional
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr value_t& operator[](size_t i) {
return _table[i].value;
}
@@ -342,12 +438,21 @@ public:
///
/// \param i The id of the node to access
/// \returns A const-qualified reference to the value of the node wrapped in an optional
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const value_t& operator[](size_t i) const {
return _table[i].value;
}
/// @}
// Insertion & Deletion ================================================================================================
// Modifiers ===========================================================================================================
/// \name Modifiers
/// @{
///
/// \brief Insertion, creates a node in the tree with parent \f$parent\f$
@@ -355,6 +460,10 @@ public:
/// \param next the next node, as an index relative to the parent, i.e. parent[0] == parent.child, parent[1] == parent.child.next
/// \param val the value to insert
/// \returns the index of the created node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert(size_t parent, size_t next, const value_t& val) {
return this->_insert(parent, next, val);
}
@@ -365,6 +474,10 @@ public:
/// \param next the next node, as an index relative to the parent
/// \param val the value to insert
/// \returns the index of the created node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert(size_t parent, size_t next, value_t&& val) {
return this->_insert(parent, next, fennec::forward<value_t>(val));
}
@@ -375,6 +488,10 @@ public:
/// \param next the next node, as an index relative to the parent
/// \param tree the tree to insert
/// \returns the index of the inserted root
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t insert(size_t parent, size_t next, const rdtree& tree) {
list<pair<size_t, size_t>> visit;
visit.push_front({ root, parent });
@@ -404,6 +521,10 @@ public:
/// \param next the next node, as an index relative to the parent, i.e. parent[0] == parent.child, parent[1] == parent.child.next
/// \param args the args to construct the value to insert
/// \returns the index of the created node
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr size_t emplace(size_t parent, size_t next, ArgsT&&...args) {
return this->_insert(parent, next, fennec::forward<ArgsT>(args)...);
@@ -413,6 +534,10 @@ public:
/// \brief Swap two nodes
/// \param i0 The id of the first node
/// \param i1 The id of the second node
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void swap(size_t i0, size_t i1) {
assertf(i0 != root and i1 != root, "Cannot Swap With Root");
@@ -438,11 +563,14 @@ public:
_erase(i);
}
/// @}
// Traversal ===========================================================================================================
/// \name Traversal
/// @{
///
/// \brief Traverse the tree using a specified order and visiting functor
///
@@ -454,6 +582,10 @@ public:
/// \tparam VisitorT The visitor, should fulfill the signature \f$uint8_t visit(TypeT&, size_t)\f$
/// \param visit The visiting object
/// \param i The node to start at
///
/// \par Complexity
/// \f$O(N)\f$
///
template<typename OrderT, typename VisitorT>
constexpr void traverse(VisitorT&& visit, size_t i = root) {
OrderT order;
@@ -470,6 +602,37 @@ public:
}
}
///
/// \brief Traverse the tree using a specified order and visiting functor
///
/// \details
/// The visitor should accept a reference to a value of type \f$TypeT\f$ and a \f$size_t\f$ 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 \f$uint8_t visit(TypeT&, size_t)\f$
/// \param visit The visiting object
/// \param i The node to start at
///
/// \par Complexity
/// \f$O(N)\f$
///
template<typename OrderT, typename VisitorT>
constexpr void traverse(VisitorT&& visit, size_t i = root) const {
OrderT order;
i = order(*this, i);
while (i != npos) {
uint8_t mode = traversal_control_continue;
if (_table[i].value) {
mode = visit(_table[i].value, i);
}
if (mode == traversal_control_break) {
break;
}
i = order[*this, i, mode];
}
}
///
/// \brief Traverser pattern for breadth-first traversal
struct breadth_first {
@@ -672,14 +835,21 @@ public:
size_t head;
};
/// @}
// Private Member Variables ============================================================================================
private:
allocation<node, alloc_t> _table;
list<size_t> _freed;
table_t _table;
freed_t _freed;
size_t _size;
// Private Helpers =====================================================================================================
private:
void _expand() {
_table.creallocate(_table.capacity() * 2);
_table.reallocate(_table.capacity() * 2);
}
size_t _next_free() {

View File

@@ -69,6 +69,7 @@ namespace fennec
/// | find | \f$O(\log N)\f$ |
/// | insertion | \f$O(\log N)\f$ |
/// | deletion | \f$O(\log N)\f$ |
/// | space | \f$O(N)\f$ |
///
/// \tparam TypeT The type to contain
/// \tparam CompareT Function for comparing two values
@@ -91,11 +92,17 @@ private:
};
public:
/// \name Definitions
/// @{
using value_t = TypeT; //!< the value type
using node_t = pair<TypeT, bool>; //!< the node type
using alloc_t = allocator_traits<AllocT>::template rebind<_node>; //!< underlying alloc type
using compare_t = CompareT; //!< comparison type
/// @}
class iterator;
class const_iterator;
@@ -215,20 +222,33 @@ public:
///
/// \brief Default Constructor, initializes an empty sequence
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr sequence()
: _root(nullptr), _size(0) {
}
///
/// \brief Move Constructor, takes ownership of a sequence
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr sequence(sequence&&) noexcept = default;
///
/// \brief Copy Constructor, copies a sequence
constexpr sequence(const sequence&) = default;
// TODO: properly implement
///
/// \brief Default Destructor, destructs elements *in-order*
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr ~sequence() {
this->clear();
}
@@ -244,6 +264,10 @@ public:
/// \brief Value Find Function, finds the iterator position for \f$val\f$, otherwise returns \f$end()\f$
/// \param val The value to find
/// \returns An iterator at the value
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr iterator find(const value_t& val) {
node node = _root;
while (node) {
@@ -276,12 +300,20 @@ public:
///
/// \returns The number of elements in the sequence
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t size() const {
return _size;
}
///
/// \returns \f$true\f$ when there are no elements in the sequence, \f$false\f$ otherwise.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const {
return _size == 0;
}
@@ -296,6 +328,10 @@ public:
///
/// \brief Move Insertion, moves \f$val\f$ into the sequence
/// \param val The value to insert
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr void insert(value_t&& val) {
node i = _insert_bst(fennec::forward<value_t>(val));
_fix_insert(i);
@@ -304,6 +340,10 @@ public:
///
/// \brief Copy Insertion, inserts a copy of \f$val\f$ into the sequence
/// \param val The value to insert
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr void insert(const value_t& val) {
node i = _insert_bst(val);
_fix_insert(i);
@@ -313,6 +353,10 @@ public:
/// \brief Emplacement, constructs and adds a value into the sequence
/// \tparam ArgsT The argument types
/// \param args The arguments to construct with
///
/// \par Complexity
/// \f$O(\log N)\f$
///
template<typename...ArgsT>
constexpr void emplace(ArgsT&&...args) {
node i = _insert_bst(fennec::forward<ArgsT>(args)...);
@@ -322,12 +366,20 @@ public:
///
/// \brief Erase the specified value from the sequence
/// \param val the value to erase
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr void erase(const value_t& val) {
_erase(find(val)._node);
}
///
/// \brief Destructs all elements, *in-order*, contained in the sequence
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void clear() {
list<node> visit;
for (iterator it = begin(); it != end(); ++it) {
@@ -346,6 +398,10 @@ public:
///
/// \returns An iterator at the smallest element in the sequence
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr iterator begin() {
return sequence::iterator(this, _root);
}
@@ -353,12 +409,20 @@ public:
///
/// \brief C++ Iterator Specification \f$begin()\f$
/// \returns An iterator at the smallest element in the sequence
///
/// \par Complexity
/// \f$O(\log N)\f$
///
constexpr const_iterator begin() const {
return sequence::const_iterator(this, _root);
}
///
/// \returns An iterator after the largest element in the sequence
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator end() {
return sequence::iterator(this, _root, nullptr);
}
@@ -366,6 +430,10 @@ public:
///
/// \brief Const C++ Iterator Specification \f$end()\f$
/// \returns An iterator after the largest element in the sequence
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const_iterator end() const {
return sequence::const_iterator(this, _root, nullptr);
}
@@ -373,24 +441,6 @@ public:
///
/// \brief C++ Iterator Specification \f$iterator\f$
class iterator {
private:
sequence* _seq;
node _head;
node _node;
list<node> _visit;
constexpr iterator(sequence* seq, node start)
: _seq(seq)
, _head(start)
, _node(seq->leftmost(start)) {
}
constexpr iterator(sequence* seq, node root, node start)
: _seq(seq)
, _head(root)
, _node(start) {
}
public:
///
@@ -466,30 +516,30 @@ public:
return lhs._seq != rhs._seq or lhs._node != rhs._node;
}
private:
sequence* _seq;
node _head;
node _node;
list<node> _visit;
constexpr iterator(sequence* seq, node start)
: _seq(seq)
, _head(start)
, _node(seq->leftmost(start)) {
}
constexpr iterator(sequence* seq, node root, node start)
: _seq(seq)
, _head(root)
, _node(start) {
}
friend struct sequence;
};
///
/// \brief C++ Iterator Specification \f$iterator\f$
class const_iterator {
private:
const sequence* _seq;
node _head;
node _node;
list<node> _visit;
constexpr const_iterator(const sequence* seq, node start)
: _seq(seq)
, _head(start)
, _node(seq->leftmost(start)) {
}
constexpr const_iterator(const sequence* seq, node root, node start)
: _seq(seq)
, _head(root)
, _node(start) {
}
public:
///
@@ -565,18 +615,37 @@ public:
return lhs._seq != rhs._seq or lhs._node != rhs._node;
}
private:
const sequence* _seq;
node _head;
node _node;
list<node> _visit;
constexpr const_iterator(const sequence* seq, node start)
: _seq(seq)
, _head(start)
, _node(seq->leftmost(start)) {
}
constexpr const_iterator(const sequence* seq, node root, node start)
: _seq(seq)
, _head(root)
, _node(start) {
}
friend struct sequence;
};
// Fields ==============================================================================================================
// Private Member Variables ============================================================================================
private:
alloc_t _alloc;
node _root;
compare_t _compare;
size_t _size;
// Helpers =============================================================================================================
// Private Helpers =====================================================================================================
private:
template<typename...ArgsT>

View File

@@ -62,32 +62,46 @@ namespace fennec
/// | find | \f$O(1)\f$ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
/// | space | \f$O(N)\f$ |
///
/// \tparam TypeT The type to contain
template<typename TypeT, class Hash = hash<TypeT>, class Equals = equality<TypeT>, class Alloc = allocator<TypeT>>
struct set {
// Definitions =========================================================================================================
private:
struct node;
public:
using alloc_t = typename allocator_traits<Alloc>::template rebind<TypeT>; //!< the allocator type
/// \name Definitions
/// @{
using alloc_t = typename allocator_traits<Alloc>::template rebind<node>; //!< the allocator type
using hash_t = Hash; //!< the hash type
using equal_t = Equals; //!< the equality type
using elem_t = TypeT; //!< the element type
/// @}
/// \name Constants
/// @{
static constexpr double default_load = 0.8; //!< the default load factor for reallocation
/// @}
class iterator;
private:
struct node {
optional<elem_t> value;
int psl;
constexpr node() = default;
constexpr ~node() = default;
};
static constexpr size_t npos = -1;
using table_t = dynarray<node, alloc_t>;
// Constructors ========================================================================================================
public:
@@ -96,8 +110,12 @@ public:
///
/// \brief Default Constructor, initializes empty set
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr set()
: _alloc()
: _table()
, _hash()
, _size(0)
, _sumpsl(0)
@@ -107,8 +125,12 @@ public:
///
/// \brief Hash Copy Constructor, initializes empty set with a hash
/// \param hash the hash object
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr set(const hash_t& hash)
: _alloc()
: _table()
, _hash(hash)
, _size(0)
, _sumpsl(0)
@@ -118,8 +140,12 @@ public:
///
/// \brief Alloc Copy Constructor, initializes empty set with an allocator
/// \param alloc the allocator object
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr set(const alloc_t& alloc)
: _alloc(alloc)
: _table(alloc)
, _hash()
, _size(0)
, _sumpsl(0)
@@ -130,8 +156,12 @@ public:
/// \brief Hash Alloc Copy Constructor, initializes empty set with a hash and allocator
/// \param hash the hash object
/// \param alloc the allocator object
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr set(const hash_t& hash, const alloc_t& alloc)
: _alloc(alloc)
: _table(alloc)
, _hash(hash)
, _size(0)
, _sumpsl(0)
@@ -141,8 +171,12 @@ public:
///
/// \brief Set Copy Constructor
/// \param set Set to copy
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr set(const set& set)
: _alloc(set._alloc)
: _table(set._table)
, _hash(set._hash)
, _size(set._size)
, _sumpsl(set._sumpsl)
@@ -152,8 +186,12 @@ public:
///
/// \brief Set Move Constructor
/// \param set Set to move
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr set(set&& set) noexcept
: _alloc(fennec::move(set._alloc))
: _table(fennec::move(set._table))
, _hash(fennec::move(set._hash))
, _size(fennec::move(set._size))
, _sumpsl(set._sumpsl)
@@ -162,9 +200,13 @@ public:
///
/// \brief Destructor, destructs all elements and releases the allocation
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr ~set() {
for (size_t i = 0; i < capacity(); ++i) {
_alloc[i].value = nullopt;
_table[i].value = nullopt;
}
}
@@ -178,20 +220,32 @@ public:
///
/// \returns Size of the set in elements
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t size() const {
return _size;
}
///
/// \returns \f$true\f$ when the set is empty, \f$false\f$ otherwise
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool is_empty() const {
return _size == 0;
}
///
/// \returns Capacity of the set in elements
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr size_t capacity() const {
return _alloc.size();
return _table.size();
}
/// @}
@@ -206,6 +260,10 @@ public:
/// \brief Find an Element
/// \param val Value to find
/// \returns An iterator at the location of the value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator find(const elem_t& val) const {
if (capacity() == 0) {
return end();
@@ -216,8 +274,8 @@ public:
size_t n = 0;
// Check the first element;
if (_alloc[i].psl >= psl && _alloc[i].value) {
if (_equal(*_alloc[i].value, val)) {
if (_table[i].psl >= psl && _table[i].value) {
if (_equal(*_table[i].value, val)) {
return iterator(this, i);
}
}
@@ -228,16 +286,16 @@ public:
size_t i0 = (i + capacity() - n) % capacity(); // Prevent index underflow
size_t i1 = (i + n) % capacity();
int p0 = psl - n, p1 = psl + n;
bool c0 = p0 >= 0 && _alloc[i0].psl >= p0, c1 = _alloc[i1].psl >= p1; // Check that we are in range
bool c0 = p0 >= 0 && _table[i0].psl >= p0, c1 = _table[i1].psl >= p1; // Check that we are in range
if (c0 && _alloc[i0].value) {
if (_equal(*_alloc[i0].value, val)) {
if (c0 && _table[i0].value) {
if (_equal(*_table[i0].value, val)) {
return iterator(this, i0);
}
}
if (c1 && _alloc[i1].value) {
if (_equal(*_alloc[i1].value, val)) {
if (c1 && _table[i1].value) {
if (_equal(*_table[i1].value, val)) {
return iterator(this, i1);
}
}
@@ -254,6 +312,10 @@ public:
/// \brief Check if a set contains a value
/// \param val Value to check
/// \returns \f$true\f$ if \f$val\f$ can be found, \f$false\f$ otherwise
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr bool contains(const elem_t& val) const {
return this->find(val) != end();
}
@@ -263,23 +325,31 @@ public:
/// \param it Location to access
/// \returns A pointer to the element, \f$nullptr\f$ if not found.
/// The value should not be changed in a manner that will change the hash of the element.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr elem_t* at(const iterator& it) {
if (it == end()) {
return nullptr;
}
if (not _alloc[it._i].value) {
if (not _table[it._i].value) {
return nullptr;
}
return &*_alloc[it._i].value;
return &*_table[it._i].value;
}
///
/// \brief Iterator Const Access
/// \param it Location to access
/// \returns A const-qualified pointer to the element, \f$nullptr\f$ if not found.
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr const elem_t* at(const iterator& it) const {
if (not _alloc[it._i].value) return nullptr;
return &*_alloc[it._i].value;
if (not _table[it._i].value) return nullptr;
return &*_table[it._i].value;
}
/// @}
@@ -293,6 +363,10 @@ public:
/// \brief Move Insertion
/// \param val Value to insert
/// \returns An iterator at the held value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator insert(elem_t&& val) {
return this->_insert(fennec::forward<elem_t>(val));
}
@@ -301,6 +375,10 @@ public:
/// \brief Copy Insertion
/// \param val Value to insert
/// \returns An iterator at the held value
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator insert(const elem_t& val) {
return this->_insert(val);
}
@@ -310,6 +388,10 @@ public:
/// \tparam ArgsT Argument types
/// \param args Arguments to construct with
/// \returns An iterator at the held value
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename...ArgsT>
constexpr iterator emplace(ArgsT&&...args) {
return this->_insert(fennec::forward<ArgsT>(args)...);
@@ -318,24 +400,28 @@ public:
///
/// \brief Element Erase
/// \param it Location to erase
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void erase(iterator it) {
size_t i = it._i;
if (i >= capacity()) {
return;
} // These are separated due to compilers being inconsistent
if (not _alloc[i].value) {
if (not _table[i].value) {
return;
}
_alloc[i].value = nullopt;
_sumpsl -= _alloc[i].psl;
_table[i].value = nullopt;
_sumpsl -= _table[i].psl;
--_size;
size_t p = i;
while (_alloc[i = (i + 1) % capacity()].value) {
if (_alloc[i].psl == 0) break;
while (_table[i = (i + 1) % capacity()].value) {
if (_table[i].psl == 0) break;
fennec::swap(_alloc[p].value, _alloc[i].value);
--_alloc[p].psl, --_sumpsl;
fennec::swap(_table[p].value, _table[i].value);
--_table[p].psl, --_sumpsl;
p = i;
}
}
@@ -343,14 +429,22 @@ public:
///
/// \brief Element Erase
/// \param val Value to erase
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr void erase(const elem_t& val) {
this->erase(this->find(val));
}
///
/// \brief Clear all elements from the set, destructing them
///
/// \par Complexity
/// \f$O(N)\f$
///
constexpr void clear() {
_alloc.clear();
_table.clear();
}
/// @}
@@ -364,9 +458,13 @@ public:
///
/// \brief C++ Iterator Specification \f$begin()\f$
/// \returns An iterator for all elements of the set in no particular order
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator begin() const {
iterator it(this, 0);
if (not _alloc[it._i].value) {
while (not _table[it._i].value) {
++it;
}
return it;
@@ -375,6 +473,10 @@ public:
///
/// \brief C++ Iterator Specification \f$end()\f$
/// \returns An iterator representing the end of the set
///
/// \par Complexity
/// \f$O(1)\f$
///
constexpr iterator end() const {
return iterator(this, npos);
}
@@ -383,6 +485,10 @@ public:
///
/// \brief C++ Iterator Specification \f$iterator\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
class iterator {
public:
///
@@ -397,7 +503,7 @@ public:
/// \returns \f$it\f$ after having moved to the next element in the list
constexpr friend iterator& operator++(iterator& it) {
while (++it._i < it._set->capacity()) {
if (it._set->_alloc[it._i].value) {
if (it._set->_table[it._i].value) {
return it;
}
}
@@ -419,15 +525,15 @@ public:
/// \brief dereference operator
/// \returns a reference to the value pointed by the iterator
constexpr const elem_t& operator*() const {
return *_set->_alloc[_i].value;
return *_set->_table[_i].value;
}
///
/// \brief pointer access operator
/// \returns a pointer to the value pointed by the iterator
constexpr const elem_t* operator->() const {
if (not _set->_alloc[_i].value) return nullptr;
return &*_set->_alloc[_i].value;
if (not _set->_table[_i].value) return nullptr;
return &*_set->_table[_i].value;
}
///
@@ -459,24 +565,33 @@ public:
};
// PRIVATE =============================================================================================================
// Private Member Variables ============================================================================================
private:
table_t _table;
hash_t _hash;
equal_t _equal;
size_t _size;
size_t _sumpsl;
float _load;
// Private Helpers =====================================================================================================
private:
constexpr void _expand() {
set cpy; // Create a new set
cpy._alloc.resize(
fennec::next_prime2(_alloc.capacity())
cpy._table.resize(
fennec::next_prime2(_table.capacity())
);
// rehash
for (size_t i = 0; i < capacity(); ++i) {
if (_alloc[i].value) {
cpy.insert(fennec::move(*_alloc[i].value));
if (_table[i].value) {
cpy.insert(fennec::move(*_table[i].value));
}
}
// Swap buffers
fennec::swap(_alloc, cpy._alloc);
fennec::swap(_table, cpy._table);
}
template<typename...ArgsT>
@@ -488,29 +603,33 @@ private:
elem_t value(fennec::forward<ArgsT>(args)...);
size_t i = _hash(value) % capacity(); // Initial search index
int psl = 0;
while (_alloc[i].value) { // Search for empty cell
if (_equal(*_alloc[i].value, value)) { // Check to see if this element is already inserted
while (_table[i].value) { // Search for empty cell
if (_equal(*_table[i].value, value)) { // Check to see if this element is already inserted
return iterator(this, i);
}
if (psl > _alloc[i].psl) { // When psl is higher, swap
_sumpsl += psl - _alloc[i].psl;
fennec::swap(_alloc[i].psl, psl);
fennec::swap(*_alloc[i].value, value);
if (psl > _table[i].psl) { // When psl is higher, swap
_sumpsl += psl - _table[i].psl;
fennec::swap(_table[i].psl, psl);
fennec::swap(*_table[i].value, value);
}
i = (i + 1) % capacity(); ++psl;
}
_alloc[i].value = fennec::move(value);
_sumpsl += (_alloc[i].psl = psl);
_table[i].value = fennec::move(value);
_sumpsl += (_table[i].psl = psl);
++_size;
return iterator(this, npos);
}
dynarray<node, alloc_t> _alloc;
hash_t _hash;
equal_t _equal;
size_t _size;
size_t _sumpsl;
float _load;
// Private Definitions =================================================================================================
private:
struct node {
optional<elem_t> value;
int psl;
constexpr node() = default;
constexpr ~node() = default;
};
};
}

View File

@@ -37,9 +37,9 @@ namespace fennec
///
/// \brief A set of constants used in the traverser-visitor pattern
enum traversal_control_ {
traversal_control_continue = 0,
traversal_control_break = 1,
traversal_control_jump_over = 2,
traversal_control_continue = 0, //!< Continue to the next element
traversal_control_break = 1, //!< Break the traversal loop
traversal_control_jump_over = 2, //!< Jump over the next element
};
}

View File

@@ -43,7 +43,7 @@ namespace fennec
/// \brief Tuple, holds a collection of values of different types
/// \details
/// | Property | Value |
/// |:-----------:|:-----------:|
/// |:-----------:|:----------:|
/// | stable | ⛔ |
/// | dynamic | ✅ |
/// | homogeneous | ⛔ |
@@ -55,6 +55,7 @@ namespace fennec
/// | find | \f$O(1)\f$ |
/// | insertion | ⛔ |
/// | deletion | ⛔ |
/// | space | \f$O(N)\f$ |
///
/// \tparam TypesT The types to store
template<typename...TypesT> struct tuple;
@@ -86,8 +87,14 @@ constexpr const typename tuple<TypesT...>::template elem_t<i>& get(const tuple<T
template<typename ...TypesT>
struct tuple : public detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)>, TypesT...>
{
struct tuple : public detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)>, TypesT...> {
// Definitions =========================================================================================================
public:
/// \name Definitions
/// @{
using base_t = detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)>, TypesT...>; //!< the base type
template<size_t i>
@@ -95,10 +102,20 @@ struct tuple : public detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)
static constexpr size_t size = sizeof...(TypesT); //!< the number of elements held by the tuple
/// @}
// Constructors & Destructor ===========================================================================================
public:
///
/// \brief tuple constructor
/// \tparam ArgsT The element types
/// \param args The arguments to initialize the tuple with
///
/// \par Complexity
/// \f$O(N)\f$
///
template<typename...ArgsT>
tuple(ArgsT&&...args)
: base_t(fennec::forward<ArgsT>(args)...) {
@@ -107,6 +124,10 @@ struct tuple : public detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)
///
/// \brief copy constructor
/// \param cpy the tuple to copy
///
/// \par Complexity
/// \f$O(N)\f$
///
tuple(const tuple& cpy)
: base_t(cpy) {
}
@@ -114,8 +135,12 @@ struct tuple : public detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)
///
/// \brief move constructor
/// \param mov the tuple to move
///
/// \par Complexity
/// \f$O(N)\f$
///
tuple(tuple&& mov)
: base_t(mov) {
: base_t(fennec::forward<tuple>(mov)) {
}
};

View File

@@ -40,10 +40,10 @@ namespace fennec
{
///
/// \brief A structure that represents a union between \f$TypesT...\f$
/// \brief A structure that represents a union between \f$TypesT\ldots\f$
/// \details
/// | Property | Value |
/// |:-----------:|:-----------:|
/// |:-----------:|:----------:|
/// | stable | ✅ |
/// | dynamic | ⛔ |
/// | homogeneous | ⛔ |
@@ -55,11 +55,13 @@ namespace fennec
/// | find | ⛔ |
/// | insertion | \f$O(1)\f$ |
/// | deletion | \f$O(1)\f$ |
/// | space | \f$O(1)\f$ |
///
/// \tparam TypesT The types to hold in the variant
template<typename...TypesT>
struct variant {
// Assertions ==========================================================================================================
public:
static_assert(
is_unique_v<TypesT...> and // No two types in TypesT... may be equivalent
@@ -69,58 +71,86 @@ struct variant {
);
// Typedefs & Constants ================================================================================================
// Definitions & Constants =============================================================================================
public:
/// \name Constants
/// @{
static constexpr size_t size = max_element_size_v<TypesT...>; //!< size of the variant in bytes
static constexpr size_t nulltype = sizeof...(TypesT); //!< id for a null type
/// @}
// Constructors ========================================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Default Constructor, constructs the first type in \f$TypesT...\f$ that is default constructible
/// \brief Default Constructor, constructs the first type in \f$TypesT\ldots\f$ that is default constructible
///
/// \par Complexity
/// \f$O(1)\f$
///
variant()
: _bytes {}
, _handle(&_bytes)
, _type(nulltype) {
using construct_t = search_element_t<is_default_constructible, TypesT...>;
fennec::construct<construct_t>(_handle);
this->_construct<construct_t>();
}
///
/// \brief Conversion Constructor, constructs the type in \f$TypesT...\f$ that is identical to \f$T\f$
/// \brief Conversion Constructor, constructs the type in \f$TypesT\ldots\f$ that is identical to \f$T\f$
/// or the first that is constructible with \f$T\f$
/// \tparam T The type of the value
/// \param t The value to forward
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T>
variant(T&& t)
: _bytes {}
, _handle(&_bytes)
, _type() {
using same_t = search_element_args<is_same, type_sequence<T>, TypesT...>;
using convert_t = search_element_args<is_constructible, type_sequence<T>, TypesT...>;
using construct_t = conditional_t<is_void_v<same_t>, convert_t, convert_t>;
fennec::construct<construct_t>(_handle, fennec::forward<T>(t));
using same_t = search_element_args<is_same, type_sequence<T>, TypesT...>::type;
using convert_t = search_element_args<is_constructible, type_sequence<T>, TypesT...>::type;
using construct_t = conditional_t<is_void_v<same_t>, convert_t, same_t>;
this->_construct<construct_t>(fennec::forward<T>(t));
}
///
/// \brief Emplace Constructor, constructs a type \f$T\f$ that is in \f$TypesT...\f$ that is constructible with \f$ArgsT...\f$
/// \brief Emplace Constructor, constructs a type \f$T\f$ that is in \f$TypesT\ldots\f$ that is constructible with \f$ArgsT\ldots\f$
/// \tparam ArgsT The arguments of the constructor
/// \param args The argument values
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T, typename...ArgsT>
variant(type_identity<T>, ArgsT&&...args)
: _bytes{}
, _handle(&_bytes)
, _type(nulltype) {
static_assert(contains_element_v<T, TypesT...>, "T must be in TypesT...");
fennec::construct<T>(_handle, fennec::forward<ArgsT>(args)...);
this->_construct<T>(fennec::forward<ArgsT>(args)...);
_type = find_element_v<T>;
}
///
/// \brief Copy Constructor
/// \param v The variant to copy
///
/// \par Complexity
/// \f$O(1)\f$
///
variant(const variant& v)
: _bytes {}
, _handle(&_bytes)
, _type(nulltype) {
if (v._type == nulltype) {
@@ -128,8 +158,8 @@ struct variant {
}
((v._type == find_element_v<TypesT, TypesT...> ?
fennec::construct<TypesT>(_handle, v.get<TypesT>()) :
(0)
this->_construct<TypesT>(v.get<TypesT>()) :
((void)0)
), ...);
_type = v._type;
}
@@ -137,8 +167,13 @@ struct variant {
///
/// \brief Move Constructor
/// \param v The variant to move
///
/// \par Complexity
/// \f$O(1)\f$
///
variant(variant&& v) noexcept
: _bytes {}
, _handle(&_bytes)
, _type() {
if (v._type == nulltype) {
@@ -146,26 +181,41 @@ struct variant {
}
((v._type == find_element_v<TypesT, TypesT...> ?
fennec::construct<TypesT>(_handle, fennec::move(v.get<TypesT>())) :
(0)
this->_construct<TypesT>(fennec::move(v.get<TypesT>())) :
((void)0)
), ...);
_type = v._type;
}
///
/// \brief Destructor, if a type is held, destruct it.
///
/// \par Complexity
/// \f$O(1)\f$
///
~variant() {
_clear();
}
/// @}
// Assignment ==========================================================================================================
public:
/// \name Assignment
/// @{
///
/// \brief value assignment operator
/// \tparam T The type to assign
/// \param t the value to assign
/// \returns a reference to \f$self\f$ after assigning \f$t\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T>
variant& operator=(T&& t) {
@@ -173,10 +223,10 @@ struct variant {
if constexpr((contains_element_v<T, TypesT> or ...)) {
using type_t = remove_reference_t<T>;
if (_type == find_element_v<type_t, TypesT...>) {
*static_cast<type_t*>(_handle) = fennec::forward<T>(t);
*_get<type_t>() = fennec::forward<T>(t);
} else {
_clear();
fennec::construct<type_t>(_handle, fennec::forward<T>(t));
this->_construct<type_t>(fennec::forward<T>(t));
_type = find_element_v<type_t, TypesT...>;
}
return *this;
@@ -186,8 +236,8 @@ struct variant {
bool assigned = false;
if (_type != nulltype) {
((_type == find_element_v<TypesT, TypesT...> ?
(*static_cast<TypesT*>(_handle) = fennec::forward<T>(t), assigned = true) :
(0)
(*_get<TypesT>() = fennec::forward<T>(t), assigned = true) :
((void)0)
), ...);
}
@@ -198,7 +248,7 @@ struct variant {
// Otherwise, destruct, then construct
_clear();
using construct_t = search_element_args<is_constructible, type_sequence<T>, TypesT...>;
fennec::construct<construct_t>(_handle, fennec::forward<T>(t));
this->_construct<construct_t>(fennec::forward<T>(t));
return *this;
}
@@ -207,80 +257,127 @@ struct variant {
/// \tparam T The type to construct
/// \tparam ArgsT the argument types
/// \param args the argument values
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T, typename...ArgsT> requires(contains_element_v<T, TypesT...>)
void emplace(ArgsT&&...args) {
_clear();
fennec::construct<T>(_handle, fennec::forward<ArgsT>(args)...);
this->_construct<T>(fennec::forward<ArgsT>(args)...);
}
///
/// \brief deduced emplace function
/// \tparam ArgsT the argument types
/// \param args the argument values
///
/// \par Complexity
/// \f$O(1)\f$
///
template<size_t I, typename...ArgsT>
void emplace(ArgsT&&...args) {
using type_t = nth_element_t<I, TypesT...>;
_clear();
fennec::construct<type_t>(fennec::forward<ArgsT>(args)...);
this->_construct<type_t>(fennec::forward<ArgsT>(args)...);
}
/// @}
// Access ==============================================================================================================
/// \name Access
/// @{
///
/// \brief get the value of the variant interpreted as \f$T\f$
/// \tparam T the type to interpret as
/// \returns The value interpreted as \f$T\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T> requires(contains_element_v<T, TypesT...>)
T& get() {
return *static_cast<T*>(_handle);
return *_get<T>();
}
///
/// \tparam T the type to interpret as
/// \returns The value interpreted as \f$T\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
template<typename T> requires(contains_element_v<T, TypesT...>)
const T& get() const {
return *static_cast<T*>(_handle);
return *_get<T>();
}
///
/// \tparam T the type to interpret as
/// \returns The value interpreted as \f$T\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
template<size_t I, typename T = nth_element_t<I, TypesT...>> requires(contains_element_v<T, TypesT...>)
T& get() {
return *static_cast<T*>(_handle);
return *_get<T>();
}
///
/// \tparam T the type to interpret as
/// \returns The value interpreted as \f$T\f$
///
/// \par Complexity
/// \f$O(1)\f$
///
template<size_t I, typename T = nth_element_t<I, TypesT...>> requires(contains_element_v<T, TypesT...>)
const T& get() const {
return *static_cast<T*>(_handle);
return *_get<T>();
}
/// @}
// Private Member Variables ============================================================================================
private:
union {
byte_t _bytes[size];
void* _handle;
};
size_t _type;
// Private Helpers =====================================================================================================
private:
template<typename T>
T* _get() const {
return static_cast<T*>(_handle);
}
void _clear() {
if (_type == nulltype) {
return;
}
((_type == find_element_v<TypesT, TypesT...> ?
fennec::destruct<TypesT>(_handle) :
(0)
this->_destruct<TypesT>() :
((void)0)
), ...);
_type = nulltype;
}
template<typename ConstructT, typename...ArgsT>
void _construct(ArgsT&&...args) {
fennec::construct<ConstructT>(_get<ConstructT>(), fennec::forward<ArgsT>(args)...);
}
template<typename DestructT>
void _destruct() {
fennec::destruct(_get<DestructT>());
}
};
}

View File

@@ -32,14 +32,35 @@ struct event;
///
/// \brief Class outlining the interface for an object that listens for events
class event_listener {
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Virtual Destructor
virtual ~event_listener();
/// @}
// Event Handling ======================================================================================================
public:
/// \name Event Handling
/// @{
///
/// \brief event handler callback
/// \param event the event to handle
virtual void handle_event(event* event) = 0;
/// @}
// Private Member Variables ============================================================================================
private:
FENNEC_RTTI_CLASS_ENABLE() {
}
};
@@ -47,12 +68,48 @@ public:
///
/// \brief Main event interface, includes static methods for registering listeners and dispatching events
struct event {
// Constructor & Destructor ============================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Default Constructor
event() = default;
///
/// \brief Copy Constructor
event(const event&) = default;
///
/// \brief Move Constructor
event(event&&) noexcept = default;
///
/// \brief Virtual Destructor
virtual ~event() = default;
/// @}
// Static Event System Interface =======================================================================================
public:
/// \name Event System Interface
/// @{
///
/// \brief Handles the event loop to distribute events.
///
/// \details Blocking
static void handle_events();
///
/// \brief Registers a listener for the event type
///
/// \details Blocking
/// \tparam EventT the event type
/// \param listener the listener to register
template<typename EventT>
@@ -61,20 +118,40 @@ struct event {
}
///
/// \brief removes a listener from the event system
/// \brief Removes a listener from the event system
///
/// \details Blocking
/// \param listener the listener to remove
static void remove_listener(event_listener* listener);
///
/// \brief Dispatch an event at the beginning of the next tick.
///
/// \details Non-Blocking, Lock-Free, Wait-Free
/// \tparam EventT The event type
/// \tparam ArgsT The argument types
/// \param args The arguments to construct the event with
template<typename EventT, typename...ArgsT>
static void dispatch(ArgsT&&...args) {
event::_dispatch(fennec::make_unique<EventT>(fennec::forward<ArgsT>(args)...));
}
///
/// \brief Dispatch an event immediately, on the current thread.
///
/// \details Blocking
/// \tparam EventT The event type
/// \tparam ArgsT The argument types
/// \param args The arguments to construct the event with
template<typename EventT, typename...ArgsT>
static void dispatch_immediate(ArgsT&&...args) {
event::_dispatch_immediate(fennec::make_unique<EventT>(fennec::forward<ArgsT>(args)...));
}
/// @}
// Private Helpers =====================================================================================================
private:
static void _add_listener(event_listener* listener, uint64_t type);
static void _handle_event(unique_ptr<event>& event);

View File

@@ -42,11 +42,12 @@ namespace fennec
///
/// \brief logger class
class logger : public singleton<logger> {
// Logger System Interface =============================================================================================
public:
///
/// \brief default constructor
logger();
~logger();
/// \name System Interface
/// @{
///
/// \brief Log a string to the log file and cout
@@ -92,9 +93,21 @@ public:
inst._cout->println(str);
}
/// @}
// Private Member Variables ============================================================================================
private:
file _logfile;
file* _cout;
// Private Constructors & Destructor ===================================================================================
private:
logger();
~logger();
friend struct singleton;
};
}

View File

@@ -32,6 +32,16 @@
#ifndef FENNEC_CORE_VERSION_H
#define FENNEC_CORE_VERSION_H
#if FENNEC_COMPILER_GCC
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#endif
#if FENNEC_COMPILER_MSVC
#pragma warning(push)
#pragma warning(disable:4201)
#endif
#include <fennec/lang/types.h>
#include <fennec/string/string.h>
@@ -41,20 +51,73 @@ namespace fennec
///
/// \brief simple version struct for drivers and systems
struct version {
uint32_t major = { 1 }; //!< the major version
uint32_t minor = { 0 }; //!< the minor version
uint32_t patch = { 0 }; //!< the patch
string str = { string("") }; //!< string representation of the version
// Public Member Variables =============================================================================================
public:
/// \name Member Variables
/// @{
union {
uint64_t num; //!< long version number
struct {
uint16_t major = { 1 }; //!< the major version
uint16_t minor = { 0 }; //!< the minor version
uint16_t patch = { 0 }; //!< the patch version
uint16_t meta = { 0 }; //!< the meta version, e.g. "rc.1"
};
};
/// @}
// Comparison Operators ================================================================================================
public:
/// \name Comparison Operators
/// @{
///
/// \brief Equality Operator
/// \param lhs The e
friend bool operator==(const version& lhs, const version& rhs) {
return lhs.major == rhs.major and lhs.minor == rhs.minor and lhs.patch == rhs.patch and lhs.str == rhs.str;
return lhs.num == rhs.num;
}
friend bool operator!=(const version& lhs, const version& rhs) {
return lhs.major != rhs.major or lhs.minor != rhs.minor or lhs.patch != rhs.patch or lhs.str != rhs.str;
return lhs.num != rhs.num;
}
///
/// \brief
/// \param lhs
/// \param rhs
/// \return
friend bool operator<(const version& lhs, const version& rhs) {
return lhs.num < rhs.num;
// This generates branching instructions, even in -O4
//return lhs.major < rhs.major or(
// (lhs.major == rhs.major and lhs.minor < rhs.minor) or (
// lhs.minor == rhs.minor and lhs.patch < rhs.patch
// )
//);
}
friend bool operator>(const version& lhs, const version& rhs) {
return lhs.num > rhs.num;
}
/// @}
};
#ifdef FENNEC_COMPILER_GCC
#pragma GCC diagnostic pop
#endif
#if FENNEC_COMPILER_MSVC
#pragma warning(pop)
#endif
}
#endif // FENNEC_CORE_VERSION_H

View File

@@ -56,12 +56,12 @@ namespace fennec
/// </table>
enum fmode_ : uint8_t
{
fmode_read = 0b00000001 ///< Opens file for reading
, fmode_write = 0b00000010 ///< Opens file for writing
, fmode_trunc = 0b00000100 ///< Contents of the file will be destroyed, only compatible with write enabled modes
, fmode_exclusive = 0b00001000 ///< Generates an error if the opened file is not empty
, fmode_binary = 0b00010000 ///< Open in binary mode
, fmode_wide = 0b00100000 ///< Opens a file in wide mode
fmode_read = 0b00000001 //!< Opens file for reading
, fmode_write = 0b00000010 //!< Opens file for writing
, fmode_trunc = 0b00000100 //!< Contents of the file will be destroyed, only compatible with write enabled modes
, fmode_exclusive = 0b00001000 //!< Generates an error if the opened file is not empty
, fmode_binary = 0b00010000 //!< Open in binary mode
, fmode_wide = 0b00100000 //!< Opens a file in wide mode
};
///
@@ -71,12 +71,30 @@ enum fmode_ : uint8_t
/// Use file::get_error() to check if an error is present and return a corresponding string.
/// Use file::clear_error() to clear the errored state.
/// Some operations, specifically file::rename() and file::copy().
/// <br>
/// This file paradigm is to subvert time-of-check time-of-use (TOCTOU) attacks. This involves a threat actor
/// reading that our application checks if a file exists, and replacing the file with another malicious file
/// or symlink between our call to open the file.
class file
{
// Constants ===========================================================================================================
public:
/// \name Constants
/// @{
/// \brief value of an invalid position
static constexpr size_t npos = -1;
/// @}
// Validation Functions ================================================================================================
public:
/// \name Validation Functions
/// @{
///
/// \brief Check if the provided mode bitflags are a valid combination
/// \param mode the bitfield
@@ -93,24 +111,43 @@ public:
|| !(t || x);
}
/// @}
// STD Text Streams ====================================================================================================
public:
/// \name STD Text Streams
/// @{
///
/// \returns the c stdout
/// \returns the c stdout stream
static file& cout();
///
/// \returns the c stdin
/// \returns the c stdin stream
static file& cin();
///
/// \returns the c stderr
/// \returns the c stderr stream
static file& cerr();
/// @}
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief default constructor, initializes an empty stream
/// \brief Default constructor
/// \details Initializes an empty stream
file();
///
/// \brief path constructor, initializes a stream pointing to \f$mode\f$ opened with \f$mode\f$
/// \details Initializes a stream pointing to \f$path\f$ opened with \f$mode\f$
/// \param path the path of the file
/// \param mode the mode to open with
file(const cstring& path, uint8_t mode)
@@ -119,7 +156,7 @@ public:
}
///
/// \brief path constructor, initializes a stream pointing to \f$mode\f$ opened with \f$mode\f$
/// \details Initializes a stream pointing to \f$path\f$ opened with \f$mode\f$
/// \param path the path of the file
/// \param mode the mode to open with
file(const string& path, uint8_t mode)
@@ -128,7 +165,8 @@ public:
}
///
/// \brief path constructor, initializes a stream pointing to \f$mode\f$ opened with \f$mode\f$
/// \brief Path constructor
/// \details Initializes a stream pointing to \f$path\f$ opened with \f$mode\f$
/// \param path the path of the file
/// \param mode the mode to open with
file(const path& path, uint8_t mode)
@@ -137,141 +175,190 @@ public:
}
///
/// \brief default destructor, cleans up an open stream
~file();
///
/// \brief move constructor
/// \brief Move constructor
/// \param file the stream to take ownership of
file(file&& file) noexcept;
///
/// \brief move assignment
/// \brief Destructor
/// \details Flushes and closes an open stream
~file();
///
/// \brief Move assignment
/// \param file the stream to take ownership of
file& operator=(file&& file) noexcept;
///@}
private:
// don't allow copying streams
file(const file&) = delete;
file& operator=(const file&) = delete;
// Properties ==========================================================================================================
public:
/// \name Properties
/// @{
///
/// \returns the path the stream
/// \returns The path the stream
const path& get_path() const {
return _path;
}
///
/// \returns the mode of the stream
/// \returns The mode of the stream
uint8_t mode() const {
return _mode;
}
///
/// \returns true if there is a valid, open stream.
/// \returns \f$true\f$ if there is a valid, open stream.
bool is_open() const {
return _handle != nullptr;
}
/// @}
// File Access =========================================================================================================
public:
/// \name File Access
/// @{
///
/// \brief open a file
/// \param path the path to the file
/// \param mode the mode flags to open the file with
/// \returns false on success, true on error
/// \returns \f$false\f$ on success, \f$true\f$ on error
bool open(const cstring& path, uint8_t mode);
///
/// \brief open a file
/// \param path the path to the file
/// \param mode the mode flags to open the file with
/// \returns false on success, true on error
/// \returns \f$false\f$ on success, \f$true\f$ on error
bool open(const string& path, uint8_t mode);
///
/// \brief open a file
/// \brief Open a file
/// \param path the path to the file
/// \param mode the mode flags to open the file with
/// \returns false on success, true on error
/// \returns \f$false\f$ on success, \f$true\f$ on error
bool open(const path& path, uint8_t mode);
///
/// \brief close a stream
/// \returns false on success, true on error
/// \brief Close a stream
/// \returns \f$false\f$ on success, \f$true\f$ on error
bool close();
///
/// \brief commit the streams buffer to the file
/// \returns false on success, true on error
/// \brief Commit the streams buffer to the file
/// \returns \f$false\f$ on success, \f$true\f$ on error
bool commit();
/// @}
// File Operations =====================================================================================================
public:
/// \name File Operations
/// @{
///
/// \brief closes the stream and erases the file
/// \returns false on success, true on error
/// \returns \f$false\f$ on success, \f$true\f$ on error
bool erase();
///
/// \brief rebinds the stream, copying contents to path, and erasing the old file
/// \param path the new path
/// \returns false on success, true on error
/// \returns \f$false\f$ on success, \f$true\f$ on error
///
/// \details attempts to open a write-only stream at path,
/// attempts to reopen this file as read-only,
/// copies the contents of this file to the new stream,
/// reopen the new stream with the flags of this file and binds to it,
/// closes the old file.
/// \details
/// Copies contents to the new path, and erases the old file.
/// * Attempts to open a write-only stream at path
/// * Attempts to reopen this file as read-only
/// * Copies the contents of this file to the new stream
/// * Reopen the new stream with the flags of this file and binds to it
/// * Closes the old file
bool rename(const cstring& path);
///
/// \brief rebinds the stream, copying contents to path, and erasing the old file
/// \param path the new path
/// \returns false on success, true on error
/// \returns \f$false\f$ on success, \f$true\f$ on error
///
/// \details attempts to open a write-only stream at path,
/// attempts to reopen this file as read-only,
/// copies the contents of this file to the new stream,
/// reopen the new stream with the flags of this file and binds to it,
/// closes the old file.
/// \details
/// Copies contents to the new path, and erases the old file.
/// * Attempts to open a write-only stream at path
/// * Attempts to reopen this file as read-only
/// * Copies the contents of this file to the new stream
/// * Reopen the new stream with the flags of this file and binds to it
/// * Closes the old file
bool rename(const string& path);
///
/// \brief rebinds the stream, copying contents to path, and erasing the old file
/// \brief Rebind the stream.
/// \param path the new path
/// \returns false on success, true on error
/// \returns \f$false\f$ on success, \f$true\f$ on error
///
/// \details attempts to open a write-only stream at path,
/// attempts to reopen this file as read-only,
/// copies the contents of this file to the new stream,
/// reopen the new stream with the flags of this file and binds to it,
/// closes the old file.
/// \details
/// Copies contents to the new path, and erases the old file.
/// * Attempts to open a write-only stream at path
/// * Attempts to reopen this file as read-only
/// * Copies the contents of this file to the new stream
/// * Reopen the new stream with the flags of this file and binds to it
/// * Closes the old file
bool rename(const path& path);
///
/// \brief copies the contents of this file to path.
/// \param path the path to copy to
/// \returns a file at the new path with the copied contents
///
/// \details
/// Copies the contents to a new stream at the provided path.
/// * Attempts to open a write-only stream at path, <br>
/// * Attempts to reopen this file as read-only, <br>
/// * Copies the contents of this file to the new stream, <br>
/// * Reopen the new stream with the flags of this file.
file copy(const cstring& path);
///
/// \brief copies the contents of this file to path.
/// \param path the path to copy to
/// \returns a file at the new path with the copied contents
///
/// \details
/// Copies the contents to a new stream at the provided path.
/// * Attempts to open a write-only stream at path, <br>
/// * Attempts to reopen this file as read-only, <br>
/// * Copies the contents of this file to the new stream, <br>
/// * Reopen the new stream with the flags of this file.
file copy(const string& path);
///
/// \brief copies the contents of this file to path.
/// \brief Copy contents to a new file.
/// \details Copies the contents of the current stream into a new stream bound to the file at the provided path.
/// \param path the path to copy to
/// \returns a file at the new path with the copied contents
///
/// \details
/// Copies the contents to a new stream at the provided path.
/// * Attempts to open a write-only stream at path, <br>
/// * Attempts to reopen this file as read-only, <br>
/// * Copies the contents of this file to the new stream, <br>
/// * Reopen the new stream with the flags of this file.
file copy(const path& path);
/// @}
// File Positioning ====================================================================================================
public:
/// \name File Positioning
/// @{
///
/// \returns the position index in the stream
@@ -291,8 +378,14 @@ public:
/// \returns \f$true\f$ if the stream has reached the end of the file, \f$false\f$ otherwise
bool eof() const;
/// @}
// Binary Read Operations ==============================================================================================
public:
/// \name Binary Read Operations
/// @{
///
/// \brief binary read
@@ -324,8 +417,14 @@ public:
return read(static_cast<void*>(data), sizeof(T), n);
}
/// @}
// Binary Write Operations =============================================================================================
public:
/// \name Binary Write Operations
/// @{
///
/// \brief put a character at the current position in the stream
@@ -389,27 +488,43 @@ public:
return write(static_cast<const void*>(data), sizeof(T), n);
}
/// @}
// Read Operations =====================================================================================================
public:
/// \name Read Operations
/// @{
///
/// \returns the character read at the current position in the stream
/// \details Advances the position by one character
char getc();
///
/// \returns the wide character read at the current position in the stream
/// \details Advances the position by one wide character
wchar_t getwc();
///
/// \returns a string containing all characters from the current position in the stream to the next newline character
/// \returns A string containing the characters from the current position to the next newline character
/// \details Advances the position to the character following the next newline character
string getline();
///
/// \returns a string containing all characters from the current position in the stream to the next newline character
/// \returns A wide string containing the characters from the current position to the next newline character
/// \details Advances the position to the character following the next newline character
wstring getwline();
/// @}
// Printing Operations =================================================================================================
public:
/// \name Print Operations
/// @{
///
/// \param str the string to print
@@ -440,19 +555,28 @@ public:
this->print(cstring(fmt.cstr(), fmt.length()));
}
/// @}
// Error Handling ======================================================================================================
public:
/// \name Error Handling
/// @{
///
/// \returns the current error state of the file
const char* get_error() const { return _error; }
/// \brief Returns the current error state.
/// \returns A string containing the current error.
cstring get_error() const { return { _error, ::strlen(_error) }; }
///
/// \brief clears the errored state
void clear_error() { _error = nullptr; }
/// @}
private:
FILE* _handle;
path _path;

View File

@@ -30,28 +30,38 @@ namespace fennec
///
/// \details This structure makes no guarantees about the validity of a path.
/// Operations do not examine the system's file structure.
struct path
{
public:
struct path {
// Definitions =========================================================================================================
public:
class iterator;
friend class iterator;
// Static Functions ====================================================================================================
// Current Working Director ============================================================================================
public:
/// \name Current Working Directory
/// @{
/// \brief Get the current working directory
/// \returns a path containing the absolute path to the working directory
static path current();
static path get_current();
/// \brief Set the current working directory
/// \param path the path to the new working directory
/// \returns a path containing the absolute path to the working directory
static path current(const path& path);
static path set_current(const path& path);
/// @}
// Constructors ========================================================================================================
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Default Constructor, returns the root of the current working directory
@@ -89,8 +99,18 @@ public:
/// \param p the path to take ownership of
path(path&& p) noexcept : _str(move(p._str)) { }
///
/// \brief Destructor
~path() = default;
/// @}
// Assignment Operators ================================================================================================
public:
/// \name Assignment
/// @{
///
/// \brief C-String Assignment Operator
@@ -138,8 +158,31 @@ public:
return *this;
}
/// @}
// Append Operators ====================================================================================================
// Comparison ==========================================================================================================
public:
/// \name Comparison
/// @{
///
/// \brief path equality operator
/// \param p the path to compare against
/// \returns \f$true\f$ if the paths are identical, \f$false\f$ otherwise. relative paths are not resolved
bool operator==(const path& p) const {
return _str == p._str;
}
/// @}
// Modifiers ===========================================================================================================
public:
/// \name Modifiers
/// @{
///
/// \brief path append operator
@@ -165,13 +208,7 @@ public:
return path(_str + '/' + p._str);
}
///
/// \brief path equality operator
/// \param p the path to compare against
/// \returns \f$true\f$ if the paths are identical, \f$false\f$ otherwise. relative paths are not resolved
bool operator==(const path& p) const {
return _str == p._str;
}
/// @}
///
/// \brief the filename of the current path
@@ -240,7 +277,7 @@ public:
#else
if (_str[0] != '/') {
#endif
working = current();
working = get_current();
}
while (not parse.is_empty()) {
@@ -278,7 +315,11 @@ public:
}
// Iterator ============================================================================================================
// Iteration ===========================================================================================================
public:
/// \name Iteration
/// @{
///
/// \brief C++ Iterator Specification \f$begin()\f$
@@ -386,6 +427,8 @@ public:
friend struct path;
};
/// @}
private:
string _str;
};

View File

@@ -38,6 +38,7 @@
namespace fennec
{
///
/// \brief C++ 20 format specification
/// \tparam ArgsT The argument types

View File

@@ -35,6 +35,7 @@
namespace fennec
{
///
/// \brief helper struct for `fennec::format`
struct format_arg {

View File

@@ -65,12 +65,12 @@ struct tokenizer {
using escseq = escape_sequence*;
using escmap = map<char, escape_sequence*>;
string delimiter; // markers that separate tokens
string operators; // operators are treated as individual tokens
string brackets; // characters that mark brackets
string quotes; // characters that mark a string sequence, entire string sequence is treated as one token
escmap escapes; // characters that mark the start of an escape sequence and validate them
bool numbers; // Anything that resembles a number
string delimiter; //!< markers that separate tokens
string operators; //!< operators are treated as individual tokens
string brackets; //!< characters that mark brackets
string quotes; //!< characters that mark a string sequence, entire string sequence is treated as one token
escmap escapes; //!< characters that mark the start of an escape sequence and validate them
bool numbers; //!< Anything that resembles a number
enum token_ : uint8_t {
token_text = 0,

View File

@@ -67,7 +67,7 @@ namespace fennec::detail
template<size_t N, typename FindT, typename HeadT>
struct _find_element<N, FindT, HeadT> : integral_constant<size_t, is_same_v<FindT, HeadT> ? N : N + 1> {};
template<size_t N, typename FindT, typename HeadT, typename...RestT> requires(is_same_v<FindT, HeadT>)
template<size_t N, typename FindT, typename HeadT, typename...RestT>
struct _find_element<N, FindT, HeadT, RestT...>
: conditional_t<is_same_v<FindT, HeadT>, integral_constant<size_t, N>, _find_element<N + 1, FindT, RestT...>> {};

View File

@@ -21,7 +21,9 @@
/// \brief metaprogramming floating point type info
///
///
/// \details this file is automatically generated for the current build environment
/// \details This file is automatically generated for the current build environment.
///
/// Environment for this build: GNU Linux x86_64
///
/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
@@ -58,30 +60,55 @@
#undef FLT_DENORM_MIN
#undef FLT_ROUND_ERR
/// \brief Does \f$float\f$ have an infinity?
#define FLT_HAS_INFINITY 1
/// \brief Does \f$float\f$ have a quiet NaN?
#define FLT_HAS_QUIET_NAN 1
/// \brief Does \f$float\f$ have a signaling NaN?
#define FLT_HAS_SIGNALING_NAN 1
/// \brief Does \f$float\f$ use denormalization?
#define FLT_HAS_DENORM 1
/// \brief Does \f$float\f$ have loss with denormalization?
#define FLT_HAS_DENORM_LOSS 0
/// \brief What rounding style does \f$float\f$ use?
#define FLT_ROUNDS 1
/// \brief Does \f$float\f$ use the IEEE floating point specification?
#define FLT_IS_IEC559 1
/// \brief The number of mantissa bits in \f$float\f$.
#define FLT_MANT_DIG 24
/// \brief The number of decimal digits guaranteed to be preserved in a \f$float\f$ &rarr; \f$text\f$ &rarr; \f$float\f$.
#define FLT_DIG 6
/// \brief The decimal precision required to serialize and deserialize a \f$float\f$.
#define FLT_DECIMAL_DIG 9
/// \brief The radix, or integer base, used to represent a \f$float\f$.
#define FLT_RADIX 2
/// \brief The minimum negative integer such that \f${FLT_RADIX}^{FLT_MIN_EXP}\f$ results in a normalized \f$float\f$.
#define FLT_MIN_EXP -125
/// \brief The maximum positive integer such that \f${FLT_RADIX}^{FLT_MAX_EXP}\f$ results in a non-infinite \f$float\f$.
#define FLT_MAX_EXP 128
/// \brief The minimum negative integer such that \f${10}^{FLT_MIN_EXP}\f$ results in a normalized \f$float\f$.
#define FLT_MIN_10_EXP -37
/// \brief The maximum positive integer such that \f${10}^{FLT_MAX_EXP}\f$ results in a non-infinite \f$float\f$.
#define FLT_MAX_10_EXP 38
/// \brief Do arithmetics operations with \f$float\f$ trap?
#define FLT_TRAPS 0
/// \brief Do arithmetics operations with \f$float\f$ check for underflow?
#define FLT_TINYNESS_BEFORE 0
/// \brief Smallest positive, finite, normal value of \f$float\f$.
#define FLT_MIN fennec::bit_cast<float>(0x800000)
/// \brief Largest positive, finite value of \f$float\f$.
#define FLT_MAX fennec::bit_cast<float>(0x7f7fffff)
/// \brief The difference between \f$1.0\f$ and the next representable value of \f$float\f$.
#define FLT_EPSILON fennec::bit_cast<float>(0x34000000)
/// \brief A value representing \f$\inf\f$ of type \f$float\f$.
#define FLT_INF fennec::bit_cast<float>(0x7f800000)
/// \brief A value representing \f$NaN\f$ of type \f$float\f$ that does not trap.
#define FLT_QUIET_NAN fennec::bit_cast<float>(0x7fc00000)
/// \brief A value representing \f$NaN\f$ of type \f$float\f$ that traps.
#define FLT_SIGNALING_NAN fennec::bit_cast<float>(0x7fa00000)
/// \brief Smallest positive, finite, subnormal value of \f$float\f$.
#define FLT_DENORM_MIN fennec::bit_cast<float>(0x1)
/// \brief Maximum rounding error of type \f$float\f$.
#define FLT_ROUND_ERR fennec::bit_cast<float>(0x3f000000)
#undef DBL_HAS_INFINITY
@@ -110,30 +137,55 @@
#undef DBL_DENORM_MIN
#undef DBL_ROUND_ERR
/// \brief Does \f$double\f$ have an infinity?
#define DBL_HAS_INFINITY 1
/// \brief Does \f$double\f$ have a quiet NaN?
#define DBL_HAS_QUIET_NAN 1
/// \brief Does \f$double\f$ have a signaling NaN?
#define DBL_HAS_SIGNALING_NAN 1
/// \brief Does \f$double\f$ use denormalization?
#define DBL_HAS_DENORM 1
/// \brief Does \f$double\f$ have loss with denormalization?
#define DBL_HAS_DENORM_LOSS 0
/// \brief What rounding style does \f$double\f$ use?
#define DBL_ROUNDS 1
/// \brief Does \f$double\f$ use the IEEE doubleing point specification?
#define DBL_IS_IEC559 1
/// \brief The number of mantissa bits in \f$double\f$.
#define DBL_MANT_DIG 53
/// \brief The number of decimal digits guaranteed to be preserved in a \f$double\f$ &rarr; \f$text\f$ &rarr; \f$double\f$.
#define DBL_DIG 15
/// \brief The decimal precision required to serialize and deserialize a \f$double\f$.
#define DBL_DECIMAL_DIG 17
/// \brief The radix, or integer base, used to represent a \f$double\f$.
#define DBL_RADIX 2
/// \brief The minimum negative integer such that \f${DBL_RADIX}^{DBL_MIN_EXP}\f$ results in a normalized \f$double\f$.
#define DBL_MIN_EXP -1021
/// \brief The maximum positive integer such that \f${DBL_RADIX}^{DBL_MAX_EXP}\f$ results in a non-infinite \f$double\f$.
#define DBL_MAX_EXP 1024
/// \brief The minimum negative integer such that \f${10}^{DBL_MIN_EXP}\f$ results in a normalized \f$double\f$.
#define DBL_MIN_10_EXP -307
/// \brief The maximum positive integer such that \f${10}^{DBL_MAX_EXP}\f$ results in a non-infinite \f$double\f$.
#define DBL_MAX_10_EXP 308
/// \brief Do arithmetics operations with \f$double\f$ trap?
#define DBL_TRAPS 0
/// \brief Do arithmetics operations with \f$double\f$ check for underflow?
#define DBL_TINYNESS_BEFORE 0
/// \brief Smallest positive, finite, normal value of \f$double\f$.
#define DBL_MIN fennec::bit_cast<double>(0x10000000000000ll)
/// \brief Largest positive, finite value of \f$double\f$.
#define DBL_MAX fennec::bit_cast<double>(0x7fefffffffffffffll)
/// \brief The difference between \f$1.0\f$ and the next representable value of \f$double\f$.
#define DBL_EPSILON fennec::bit_cast<double>(0x3cb0000000000000ll)
/// \brief A value representing \f$\inf\f$ of type \f$double\f$.
#define DBL_INF fennec::bit_cast<double>(0x7ff0000000000000ll)
/// \brief A value representing \f$NaN\f$ of type \f$double\f$ that does not trap.
#define DBL_QUIET_NAN fennec::bit_cast<double>(0x7ff8000000000000ll)
/// \brief A value representing \f$NaN\f$ of type \f$double\f$ that traps.
#define DBL_SIGNALING_NAN fennec::bit_cast<double>(0x7ff4000000000000ll)
/// \brief Smallest positive, finite, subnormal value of \f$double\f$.
#define DBL_DENORM_MIN fennec::bit_cast<double>(0x1ll)
/// \brief Maximum rounding error of type \f$double\f$.
#define DBL_ROUND_ERR fennec::bit_cast<double>(0x3fe0000000000000ll)
#endif // FENNEC_LANG_FLOAT_H

View File

@@ -21,7 +21,9 @@
/// \brief metaprogramming integer type info
///
///
/// \details this file is automatically generated for the current build environment
/// \details This file is automatically generated for the current build environment.
///
/// Environment for this build: GNU Linux x86_64
///
/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
@@ -51,114 +53,212 @@
#undef ULLONG_MIN
#undef ULLONG_MAX
/// \brief Is \f$char\f$ signed?
#define CHAR_IS_SIGNED true
/// \brief Rounding style of type \f$char\f$.
#define CHAR_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$char\f$.
#define CHAR_RADIX_DIG 0x7
/// \brief Number of decimal digits represented by \f$char\f$.
#define CHAR_DIG 0x2
/// \brief Number of decimal digits necessary to differentiate all values of type \f$char\f$.
#define CHAR_DECIMAL_DIG 0x0
/// \brief The radix, or integer base, used to represent a \f$char\f$.
#define CHAR_RADIX 0x2
/// \brief Do arithmetics operations with \f$char\f$ trap?
#define CHAR_TRAPS 0xtrue
/// \brief Smallest finite value of \f$char\f$.
#define CHAR_MIN 0x80
/// \brief Largest finite value of \f$char\f$.
#define CHAR_MAX 0x7f
/// \brief Is \f$wchar_t\f$ signed?
#define WCHAR_IS_SIGNED true
/// \brief Rounding style of type \f$wchar_t\f$.
#define WCHAR_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$wchar_t\f$.
#define WCHAR_RADIX_DIG 0x1f
/// \brief Number of decimal digits represented by \f$wchar_t\f$.
#define WCHAR_DIG 0x9
/// \brief Number of decimal digits necessary to differentiate all values of type \f$wchar_t\f$.
#define WCHAR_DECIMAL_DIG 0x0
/// \brief The radix, or integer base, used to represent a \f$wchar_t\f$.
#define WCHAR_RADIX 0x2
/// \brief Do arithmetics operations with \f$wchar_t\f$ trap?
#define WCHAR_TRAPS 0xtrue
/// \brief Smallest finite value of \f$wchar_t\f$.
#define WCHAR_MIN 0x80000000
/// \brief Largest finite value of \f$wchar_t\f$.
#define WCHAR_MAX 0x7fffffff
/// \brief Is \f$signed char\f$ signed?
#define SCHAR_ROUNDS 0x0
/// \brief Rounding style of type \f$signed char\f$.
#define SCHAR_RADIX_DIG 0x7
/// \brief Number of radix digits represented by \f$signed char\f$.
#define SCHAR_DIG 0x2
/// \brief Number of decimal digits represented by \f$signed char\f$.
#define SCHAR_DECIMAL_DIG 0x0
/// \brief Number of decimal digits necessary to differentiate all values of type \f$signed char\f$.
#define SCHAR_RADIX 0x2
/// \brief Do arithmetics operations with \f$signed char\f$ trap?
#define SCHAR_TRAPS 0xtrue
/// \brief Smallest finite value of \f$signed char\f$.
#define SCHAR_MIN 0x80
/// \brief Largest finite value of \f$signed char\f$.
#define SCHAR_MAX 0x7f
/// \brief Is \f$unsigned char\f$ unsigned?
#define UCHAR_ROUNDS 0x0
/// \brief Rounding style of type \f$unsigned char\f$.
#define UCHAR_RADIX_DIG 0x8
/// \brief Number of radix digits represented by \f$unsigned char\f$.
#define UCHAR_DIG 0x2
/// \brief Number of decimal digits represented by \f$unsigned char\f$.
#define UCHAR_DECIMAL_DIG 0x0
/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned char\f$.
#define UCHAR_RADIX 0x2
/// \brief Do arithmetics operations with \f$unsigned char\f$ trap?
#define UCHAR_TRAPS 0xtrue
/// \brief Smallest finite value of \f$unsigned char\f$.
#define UCHAR_MIN 0x0
/// \brief Largest finite value of \f$unsigned char\f$.
#define UCHAR_MAX 0xff
/// \brief Rounding style of type \f$short\f$.
#define SHORT_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$short\f$.
#define SHORT_RADIX_DIG 0xf
/// \brief Number of decimal digits represented by \f$short\f$.
#define SHORT_DIG 0x4
/// \brief Number of decimal digits necessary to differentiate all values of type \f$short\f$.
#define SHORT_DECIMAL_DIG 0x0
/// \brief The radix, or integer base, used to represent a \f$short\f$.
#define SHORT_RADIX 0x2
/// \brief Do arithmetics operations with \f$short\f$ trap?
#define SHORT_TRAPS 0xtrue
#define SHORT_MIN 0x8000
/// \brief Smallest finite value of \f$short\f$.
#define SHORT_MIN 0xffff8000
/// \brief Largest finite value of \f$short\f$.
#define SHORT_MAX 0x7fff
/// \brief Rounding style of type \f$unsigned short\f$.
#define USHORT_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$unsigned short\f$.
#define USHORT_RADIX_DIG 0x10
/// \brief Number of decimal digits represented by \f$unsigned short\f$.
#define USHORT_DIG 0x4
/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned short\f$.
#define USHORT_DECIMAL_DIG 0x0
/// \brief The radix, or integer base, used to represent a \f$unsigned short\f$.
#define USHORT_RADIX 0x2
/// \brief Do arithmetics operations with \f$unsigned short\f$ trap?
#define USHORT_TRAPS 0xtrue
/// \brief Smallest finite value of \f$unsigned short\f$.
#define USHORT_MIN 0x0
/// \brief Largest finite value of \f$unsigned short\f$.
#define USHORT_MAX 0xffff
/// \brief Rounding style of type \f$int\f$.
#define INT_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$int\f$.
#define INT_RADIX_DIG 0x1f
/// \brief Number of decimal digits represented by \f$int\f$.
#define INT_DIG 0x9
/// \brief Number of decimal digits necessary to differentiate all values of type \f$int\f$.
#define INT_DECIMAL_DIG 0x0
/// \brief The radix, or integer base, used to represent a \f$int\f$.
#define INT_RADIX 0x2
/// \brief Do arithmetics operations with \f$int\f$ trap?
#define INT_TRAPS 0xtrue
/// \brief Smallest finite value of \f$int\f$.
#define INT_MIN 0x80000000
/// \brief Largest finite value of \f$int\f$.
#define INT_MAX 0x7fffffff
/// \brief Rounding style of type \f$unsigned int\f$.
#define UINT_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$unsigned int\f$.
#define UINT_RADIX_DIG 0x20
/// \brief Number of decimal digits represented by \f$unsigned int\f$.
#define UINT_DIG 0x9
/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned int\f$.
#define UINT_DECIMAL_DIG 0x0
/// \brief The radix, or unsigned integer base, used to represent a \f$unsigned int\f$.
#define UINT_RADIX 0x2
/// \brief Do arithmetics operations with \f$unsigned int\f$ trap?
#define UINT_TRAPS 0xtrue
/// \brief Smallest finite value of \f$unsigned int\f$.
#define UINT_MIN 0x0
/// \brief Largest finite value of \f$unsigned int\f$.
#define UINT_MAX 0xffffffff
/// \brief Rounding style of type \f$long int\f$.
#define LONG_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$long int\f$.
#define LONG_RADIX_DIG 0x3f
/// \brief Number of decimal digits represented by \f$long int\f$.
#define LONG_DIG 0x12
/// \brief Number of decimal digits necessary to differentiate all values of type \f$long int\f$.
#define LONG_DECIMAL_DIG 0x0
/// \brief The radix, or long integer base, used to represent a \f$long int\f$.
#define LONG_RADIX 0x2
/// \brief Do arithmetics operations with \f$long int\f$ trap?
#define LONG_TRAPS 0xtrue
/// \brief Smallest finite value of \f$long int\f$.
#define LONG_MIN 0x8000000000000000
/// \brief Largest finite value of \f$long int\f$.
#define LONG_MAX 0x7fffffffffffffff
/// \brief Rounding style of type \f$unsigned long int\f$.
#define ULONG_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$unsigned long int\f$.
#define ULONG_RADIX_DIG 0x40
/// \brief Number of decimal digits represented by \f$unsigned long int\f$.
#define ULONG_DIG 0x13
/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned long int\f$.
#define ULONG_DECIMAL_DIG 0x0
/// \brief The radix, or unsigned long integer base, used to represent a \f$unsigned long int\f$.
#define ULONG_RADIX 0x2
/// \brief Do arithmetics operations with \f$unsigned long int\f$ trap?
#define ULONG_TRAPS 0xtrue
/// \brief Smallest finite value of \f$unsigned long int\f$.
#define ULONG_MIN 0x0
/// \brief Largest finite value of \f$unsigned long int\f$.
#define ULONG_MAX 0xffffffffffffffff
/// \brief Rounding style of type \f$long long\f$.
#define LLONG_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$long long\f$.
#define LLONG_RADIX_DIG 0x3f
/// \brief Number of decimal digits represented by \f$long long\f$.
#define LLONG_DIG 0x12
/// \brief Number of decimal digits necessary to differentiate all values of type \f$long long\f$.
#define LLONG_DECIMAL_DIG 0x0
/// \brief The radix, or long longeger base, used to represent a \f$long long\f$.
#define LLONG_RADIX 0x2
/// \brief Do arithmetics operations with \f$long long\f$ trap?
#define LLONG_TRAPS 0xtrue
/// \brief Smallest finite value of \f$long long\f$.
#define LLONG_MIN 0x8000000000000000
/// \brief Largest finite value of \f$long long\f$.
#define LLONG_MAX 0x7fffffffffffffff
/// \brief Rounding style of type \f$unsigned long long\f$.
#define ULLONG_ROUNDS 0x0
/// \brief Number of radix digits represented by \f$unsigned long long\f$.
#define ULLONG_RADIX_DIG 0x40
/// \brief Number of decimal digits represented by \f$unsigned long long\f$.
#define ULLONG_DIG 0x13
/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned long long\f$.
#define ULLONG_DECIMAL_DIG 0x0
/// \brief The radix, or unsigned long longeger base, used to represent a \f$unsigned long long\f$.
#define ULLONG_RADIX 0x2
/// \brief Do arithmetics operations with \f$unsigned long long\f$ trap?
#define ULLONG_TRAPS 0xtrue
/// \brief Smallest finite value of \f$unsigned long long\f$.
#define ULLONG_MIN 0x0
/// \brief Largest finite value of \f$unsigned long long\f$.
#define ULLONG_MAX 0xffffffffffffffff
#endif // FENNEC_LANG_INTEGER_H

View File

@@ -92,7 +92,7 @@
/// \f$FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE\f$ <br>
/// \f$B FENNEC_BUILTIN_IS_CONSTRUCTIBLE(X, ...)\f$
/// <td width="50%" style="vertical-align: top">
/// Checks if type \f$X\f$ is constructible with args \f$...\f$, such that \f$X::X(...)\f$ exists.
/// Checks if type \f$X\f$ is constructible with args \f$\ldots\f$, such that \f$X::X(...)\f$ exists.
///
/// </table>
///

View File

@@ -222,42 +222,42 @@ enum float_round_style
/// \tparam TypeT Numeric types, may be overloaded for custom types
template<typename TypeT> struct numeric_limits
{
static constexpr bool is_specialized = false; ///< Check if the template is specialized for TypeT
static constexpr bool is_signed = false; ///< Check if TypeT is signed
static constexpr bool is_integer = false; ///< Check if TypeT is of an integral type
static constexpr bool is_exact = false; ///< Check if TypeT is exact in its precision
static constexpr bool has_infinity = false; ///< Check if TypeT can hold a value representing infinity
static constexpr bool has_quiet_nan = false; ///< Check if TypeT can hold a non-signaling nan
static constexpr bool has_signaling_nan = false; ///< Check if TypeT can hold a signaling nan
static constexpr bool has_denorm = false; ///< Check if TypeT denormalizes
static constexpr bool has_denorm_loss = false; ///< Check if TypeT has precision loss when denormalized
static constexpr bool is_iec559 = false; ///< Check if a TypeT representing a float is IEC 559 or IEEE 754
static constexpr bool is_bounded = false; ///< Check if TypeT represents a finite set of values
static constexpr bool is_modulo = false; ///< Check if TypeT can handle modulo arithmetic
static constexpr bool tinyness_before = false; ///< Check if TypeT checks for tinyness before rounding
static constexpr bool traps = false; ///< Check if TypeT can cause operations to trap
static constexpr bool is_specialized = false; //!< Check if the template is specialized for TypeT
static constexpr bool is_signed = false; //!< Check if TypeT is signed
static constexpr bool is_integer = false; //!< Check if TypeT is of an integral type
static constexpr bool is_exact = false; //!< Check if TypeT is exact in its precision
static constexpr bool has_infinity = false; //!< Check if TypeT can hold a value representing infinity
static constexpr bool has_quiet_nan = false; //!< Check if TypeT can hold a non-signaling nan
static constexpr bool has_signaling_nan = false; //!< Check if TypeT can hold a signaling nan
static constexpr bool has_denorm = false; //!< Check if TypeT denormalizes
static constexpr bool has_denorm_loss = false; //!< Check if TypeT has precision loss when denormalized
static constexpr bool is_iec559 = false; //!< Check if a TypeT representing a float is IEC 559 or IEEE 754
static constexpr bool is_bounded = false; //!< Check if TypeT represents a finite set of values
static constexpr bool is_modulo = false; //!< Check if TypeT can handle modulo arithmetic
static constexpr bool tinyness_before = false; //!< Check if TypeT checks for tinyness before rounding
static constexpr bool traps = false; //!< Check if TypeT can cause operations to trap
static constexpr int radix = 0; ///< Get the base representation of the type
static constexpr int digits = 0; ///< Get the number of radix digits TypeT represents
static constexpr int digits10 = 0; ///< Get the number of decimal digits TypeT represents
static constexpr int max_digits10 = 0; ///< Get the maximum number of decimal digits TypeT represents
static constexpr int min_exponent = 0; ///< Get the minimum number of radix digits that represent the exponent of TypeT
static constexpr int min_exponent10 = 0; ///< Get the minimum number of decimal digits that represent the exponent of TypeT
static constexpr int max_exponent = 0; ///< Get the maximum number of radix digits that represent the exponent of TypeT
static constexpr int max_exponent10 = 0; ///< Get the maximum number of decimal digits that represent the exponent of TypeT
static constexpr int radix = 0; //!< Get the base representation of the type
static constexpr int digits = 0; //!< Get the number of radix digits TypeT represents
static constexpr int digits10 = 0; //!< Get the number of decimal digits TypeT represents
static constexpr int max_digits10 = 0; //!< Get the maximum number of decimal digits TypeT represents
static constexpr int min_exponent = 0; //!< Get the minimum number of radix digits that represent the exponent of TypeT
static constexpr int min_exponent10 = 0; //!< Get the minimum number of decimal digits that represent the exponent of TypeT
static constexpr int max_exponent = 0; //!< Get the maximum number of radix digits that represent the exponent of TypeT
static constexpr int max_exponent10 = 0; //!< Get the maximum number of decimal digits that represent the exponent of TypeT
static constexpr float_round_style rounding_style = round_indeterminate; ///< The rounding style of TypeT
static constexpr float_round_style rounding_style = round_indeterminate; //!< The rounding style of TypeT
// This is very poorly named and defined in the C++ Standard so these functions differ
static constexpr TypeT min() { return TypeT(); } ///< \returns the minimum finite value of TypeT
static constexpr TypeT max() { return TypeT(); } ///< \returns the maximum finite value of TypeT
static constexpr TypeT lowest() { return TypeT(); } ///< \returns the smallest positive value of TypeT
static constexpr TypeT epsilon() { return TypeT(); } ///< \returns the difference between 1.0 and the next representable value
static constexpr TypeT round_error() { return TypeT(); } ///< \returns the max rounding error of TypeT
static constexpr TypeT infinity() { return TypeT(); } ///< \returns a value of TypeT holding a positive infinity
static constexpr TypeT quiet_NaN() { return TypeT(); } ///< \returns a value of TypeT holding a quiet NaN
static constexpr TypeT signaling_NaN() { return TypeT(); } ///< \returns a value of TypeT holding a signaling NaN
static constexpr TypeT denorm_min() { return TypeT(); } ///< \returns a value of TypeT holding the smallest positive subnormal
static constexpr TypeT min() { return TypeT(); } //!< \returns the minimum finite value of TypeT
static constexpr TypeT max() { return TypeT(); } //!< \returns the maximum finite value of TypeT
static constexpr TypeT lowest() { return TypeT(); } //!< \returns the smallest positive value of TypeT
static constexpr TypeT epsilon() { return TypeT(); } //!< \returns the difference between 1.0 and the next representable value
static constexpr TypeT round_error() { return TypeT(); } //!< \returns the max rounding error of TypeT
static constexpr TypeT infinity() { return TypeT(); } //!< \returns a value of TypeT holding a positive infinity
static constexpr TypeT quiet_NaN() { return TypeT(); } //!< \returns a value of TypeT holding a quiet NaN
static constexpr TypeT signaling_NaN() { return TypeT(); } //!< \returns a value of TypeT holding a signaling NaN
static constexpr TypeT denorm_min() { return TypeT(); } //!< \returns a value of TypeT holding the smallest positive subnormal
};
// Overload definitions for basic types

View File

@@ -192,6 +192,16 @@
/// \copybrief fennec::ptrdiff_t
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// <tt>\ref fennec::empty_t "empty_t"</tt>
/// <td width="50%" style="vertical-align: top">
/// \copybrief fennec::empty_t
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// <tt>\ref fennec::undefined_t "undefined_t"</tt>
/// <td width="50%" style="vertical-align: top">
/// \copybrief fennec::undefined_t
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// <tt>\ref fennec::void_t "void_t"</tt>
/// <td width="50%" style="vertical-align: top">
/// \copybrief fennec::void_t
@@ -211,28 +221,28 @@ namespace fennec
/// \name Basic Types
/// @{
using bool_t = bool; ///< \brief A conditional type
using bool_t = bool; //!< \brief A conditional type.
using byte_t = unsigned char; ///< \brief A type capable of holding a single byte
using byte_t = unsigned char; //!< \brief A type capable of holding a single byte.
using char_t = char; ///< \brief A type capable of holding an ascii value
using schar_t = signed char; ///< \brief A type with the size of a char, capable of holding a signed 8-bit integer
using uchar_t = unsigned char; ///< \brief A type with the size of a char, capable of holding an unsigned 8-bit integer
using char_t = char; //!< \brief A type capable of holding an ascii value.
using schar_t = signed char; //!< \brief A type with the size of a char, capable of holding a signed 8-bit integer.
using uchar_t = unsigned char; //!< \brief A type with the size of a char, capable of holding an unsigned 8-bit integer.
using short_t = signed short; ///< \brief A signed short type, capable of holding signed 16-bit integer
using ushort_t = unsigned short; ///< \brief An unsigned short type, capable of holding an unsigned signed 16-bit integer
using short_t = signed short; //!< \brief A signed short type, capable of holding signed 16-bit integer.
using ushort_t = unsigned short; //!< \brief An unsigned short type, capable of holding an unsigned signed 16-bit integer.
using int_t = signed int; ///< \brief A signed integer type, size varies by implementation, but typically 32-bit
using uint_t = unsigned int; ///< \brief An unsigned integer type, size varies by implementation, but typically 32-bit
using int_t = signed int; //!< \brief A signed integer type, size varies by implementation, but typically 32-bit.
using uint_t = unsigned int; //!< \brief An unsigned integer type, size varies by implementation, but typically 32-bit.
using long_t = signed long; ///< \brief A signed integer type, with a size of at least 32-bits
using ulong_t = unsigned long; ///< \brief An unsigned integer type, with a size of at least 32-bits
using long_t = signed long; //!< \brief A signed integer type, with a size of at least 32-bits.
using ulong_t = unsigned long; //!< \brief An unsigned integer type, with a size of at least 32-bits.
using llong_t = signed long long; ///< \brief A signed integer type, with a size of 64-bits
using ullong_t = unsigned long long; ///< \brief An unsigned integer type, with a size of 64-bits
using llong_t = signed long long; //!< \brief A signed integer type, with a size of 64-bits.
using ullong_t = unsigned long long; //!< \brief An unsigned integer type, with a size of 64-bits.
using float_t = float; ///< \brief A single-precision floating-point type, typically with a size of 32-bits
using double_t = double; ///< \brief A double-precision floating-point type, typically with a size of 64-bits
using float_t = float; //!< \brief A single-precision floating-point type, typically with a size of 32-bits.
using double_t = double; //!< \brief A double-precision floating-point type, typically with a size of 64-bits.
/// @}
@@ -242,18 +252,18 @@ namespace fennec
/// \name Special Types
/// @{
using nullptr_t = decltype(nullptr); ///< \brief Null Pointer Type
using intptr_t = intptr_t; ///< \brief Signed Integer Capable of Holding a Pointer to void
using uintptr_t = uintptr_t; ///< \brief Unsigned Integer Capable of Holding a Pointer to void
using intmax_t = intmax_t; ///< \brief Maximum Width Signed Integer Type
using uintmax_t = uintmax_t; ///< \brief Maximum Width Unsigned Integer Type
using size_t = size_t; ///< \brief Unsigned Integer Type Returned By \f$sizeof\f$, `sizeof...`, and \f$alignof\f$
using ptrdiff_t = __PTRDIFF_TYPE__; ///< \brief Signed Integer Type Returned by the Subtraction of two Pointers
struct empty_t {};
using nullptr_t = decltype(nullptr); //!< \brief Null Pointer Type.
using intptr_t = intptr_t; //!< \brief Signed Integer Capable of Holding a Pointer to void.
using uintptr_t = uintptr_t; //!< \brief Unsigned Integer Capable of Holding a Pointer to void.
using intmax_t = intmax_t; //!< \brief Maximum Width Signed 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 ptrdiff_t = __PTRDIFF_TYPE__; //!< \brief Signed Integer Type Returned by the Subtraction of two Pointers.
struct empty_t {}; //!< \brief A struct resembling an empty type.
class undefined_t; ///< \brief undefined class for SFINAE
template<typename...> using void_t = void; ///< \brief Void type used for SFINAE
class undefined_t; //!< \brief Undefined class for SFINAE.
template<typename...> using void_t = void; //!< \brief Void type used for SFINAE.
/// @}
@@ -264,15 +274,15 @@ namespace fennec
/// \name Sized Integer Types
/// @{
using int8_t = ::int8_t; ///< \brief Signed 8-bit integer
using int16_t = ::int16_t; ///< \brief Signed 16-bit integer
using int32_t = ::int32_t; ///< \brief Signed 32-bit integer
using int64_t = ::int64_t; ///< \brief Signed 64-bit integer
using int8_t = ::int8_t; //!< \brief Signed 8-bit integer.
using int16_t = ::int16_t; //!< \brief Signed 16-bit integer.
using int32_t = ::int32_t; //!< \brief Signed 32-bit integer.
using int64_t = ::int64_t; //!< \brief Signed 64-bit integer.
using uint8_t = ::uint8_t; ///< \brief Unsigned 8-bit integer
using uint16_t = ::uint16_t; ///< \brief Unsigned 16-bit integer
using uint32_t = ::uint32_t; ///< \brief Unsigned 32-bit integer
using uint64_t = ::uint64_t; ///< \brief Unsigned 64-bit integer
using uint8_t = ::uint8_t; //!< \brief Unsigned 8-bit integer.
using uint16_t = ::uint16_t; //!< \brief Unsigned 16-bit integer.
using uint32_t = ::uint32_t; //!< \brief Unsigned 32-bit integer.
using uint64_t = ::uint64_t; //!< \brief Unsigned 64-bit integer.
/// @}
@@ -282,9 +292,9 @@ namespace fennec
/// \name Sized Floating-Point Types
/// @{
//using float16_t = _Float16; ///< \brief A half-precision floating-point scalar
//using float32_t = _Float32; ///< \brief A single-precision floating-point scalar
//using float64_t = _Float64; ///< \brief A double-precision floating-point scalar
//using float16_t = _Float16; //!< \brief A half-precision floating-point scalar
//using float32_t = _Float32; //!< \brief A single-precision floating-point scalar
//using float64_t = _Float64; //!< \brief A double-precision floating-point scalar
/// @}

View File

@@ -16,8 +16,8 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_MATH_DETAIL_FWD_H
#define FENNEC_MATH_DETAIL_FWD_H
#ifndef FENNEC_MATH_DETAIL_FORWARD_H
#define FENNEC_MATH_DETAIL_FORWARD_H
#include <fennec/math/detail/_types.h>
@@ -36,4 +36,4 @@ template<typename ScalarT, size_t ColsV, size_t RowsV> using mat
}
#endif // FENNEC_MATH_DETAIL_FWD_H
#endif // FENNEC_MATH_DETAIL_FORWARD_H

View File

@@ -19,7 +19,7 @@
#ifndef FENNEC_MATH_DETAIL_MATRIX_H
#define FENNEC_MATH_DETAIL_MATRIX_H
#include <fennec/math/detail/_fwd.h>
#include <fennec/math/detail/_forward.h>
namespace fennec
{

View File

@@ -19,7 +19,7 @@
#ifndef FENNEC_MATH_DETAIL_VECTOR_TRAITS_H
#define FENNEC_MATH_DETAIL_VECTOR_TRAITS_H
#include <fennec/math/detail/_fwd.h>
#include <fennec/math/detail/_forward.h>
#include <fennec/lang/type_traits.h>
#include <fennec/math/swizzle.h>

View File

@@ -546,81 +546,81 @@ namespace fennec
// Rational Constants ==================================================================================================
template<typename genType> constexpr genType zero() { return genType(0); } ///< \returns The value of \f$0\f$
template<typename genType> constexpr genType one() { return genType(1); } ///< \returns The value of \f$1\f$
template<typename genType> constexpr genType one_half() { return genType(0.5); } ///< \returns The value of \f$\frac{1}{2}\f$
template<typename genType> constexpr genType three_over_two() { return genType(1.5); } ///< \returns The value of \f$\frac{3}{2}\f$
template<typename genType> constexpr genType zero() { return genType(0); } //!< \returns The value of \f$0\f$
template<typename genType> constexpr genType one() { return genType(1); } //!< \returns The value of \f$1\f$
template<typename genType> constexpr genType one_half() { return genType(0.5); } //!< \returns The value of \f$\frac{1}{2}\f$
template<typename genType> constexpr genType three_over_two() { return genType(1.5); } //!< \returns The value of \f$\frac{3}{2}\f$
// Irrational Constants ================================================================================================
template<typename genType> constexpr genType one_third() { return 0.33333333333333333333333333333333333333333333333333; } ///< \returns The value of \f$\frac{1}{3}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType two_thirds() { return 0.66666666666666666666666666666666666666666666666666; } ///< \returns The value of \f$\frac{2}{3}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType sqrt_two() { return 1.41421356237309504880168872420969807856967187537694; } ///< \returns The value of \f$\sqrt{2}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType sqrt_three() { return 1.73205080756887729352744634150587236694280525381038; } ///< \returns The value of \f$\sqrt{3}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType sqrt_five() { return 2.23606797749978969640917366873127623544061835961152; } ///< \returns The value of \f$\sqrt{5}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType sqrt_seven() { return 2.64575131106459059050161575363926042571025918308245; } ///< \returns The value of \f$\sqrt{7}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType sqrt_ten() { return 3.16227766016837933199889354443271853371955513932521; } ///< \returns The value of \f$\sqrt{10}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType one_over_sqrt_two() { return 0.70710678118654752440084436210484903928483593768847; } ///< \returns The value of \f$\frac{1}{\sqrt{2}}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType one_over_sqrt_three() { return 0.57735026918962576450914878050195745564760175127012; } ///< \returns The value of \f$\frac{1}{\sqrt{3}}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType one_over_sqrt_five() { return 0.44721359549995793928183473374625524708812367192230; } ///< \returns The value of \f$\frac{1}{\sqrt{5}}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType cbrt_two() { return 1.25992104989487316476721060727822835057025146470150; } ///< \returns The value of \f$\sqrt[3]{2}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType qdrt_two() { return 1.18920711500272106671749997056047591529297209246381; } ///< \returns The value of \f$\sqrt[4]{2}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType two_raised_sqrt_two() { return 2.66514414269022518865029724987313984827421131371465; } ///< \returns The value of \f${2}^{\sqrt{2}}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType one_third() { return 0.33333333333333333333333333333333333333333333333333; } //!< \returns The value of \f$\frac{1}{3}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType two_thirds() { return 0.66666666666666666666666666666666666666666666666666; } //!< \returns The value of \f$\frac{2}{3}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType sqrt_two() { return 1.41421356237309504880168872420969807856967187537694; } //!< \returns The value of \f$\sqrt{2}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType sqrt_three() { return 1.73205080756887729352744634150587236694280525381038; } //!< \returns The value of \f$\sqrt{3}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType sqrt_five() { return 2.23606797749978969640917366873127623544061835961152; } //!< \returns The value of \f$\sqrt{5}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType sqrt_seven() { return 2.64575131106459059050161575363926042571025918308245; } //!< \returns The value of \f$\sqrt{7}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType sqrt_ten() { return 3.16227766016837933199889354443271853371955513932521; } //!< \returns The value of \f$\sqrt{10}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType one_over_sqrt_two() { return 0.70710678118654752440084436210484903928483593768847; } //!< \returns The value of \f$\frac{1}{\sqrt{2}}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType one_over_sqrt_three() { return 0.57735026918962576450914878050195745564760175127012; } //!< \returns The value of \f$\frac{1}{\sqrt{3}}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType one_over_sqrt_five() { return 0.44721359549995793928183473374625524708812367192230; } //!< \returns The value of \f$\frac{1}{\sqrt{5}}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType cbrt_two() { return 1.25992104989487316476721060727822835057025146470150; } //!< \returns The value of \f$\sqrt[3]{2}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType qdrt_two() { return 1.18920711500272106671749997056047591529297209246381; } //!< \returns The value of \f$\sqrt[4]{2}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType two_raised_sqrt_two() { return 2.66514414269022518865029724987313984827421131371465; } //!< \returns The value of \f${2}^{\sqrt{2}}\f$ with the highest precision for \f$genType\f$
// Pi ==================================================================================================================
// Pi & Tau
template<typename genType> constexpr genType pi() { return 3.14159265358979323846264338327950288419716939937510; } ///< \returns The value of \f$\pi\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType tau() { return 6.28318530717958647692528676655900576839433879875021; } ///< \returns The value of \f$\tau\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType pi() { return 3.14159265358979323846264338327950288419716939937510; } //!< \returns The value of \f$\pi\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType tau() { return 6.28318530717958647692528676655900576839433879875021; } //!< \returns The value of \f$\tau\f$ with the highest precision for \f$genType\f$
// Multiples of Pi
template<typename genType> constexpr genType two_pi() { return 6.28318530717958647692528676655900576839433879875021; } ///< \returns The value of \f$2\pi\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType three_pi() { return 9.42477796076937971538793014983850865259150819812531; } ///< \returns The value of \f$3\pi\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType four_pi() { return 12.56637061435917295385057353311801153678867759750042; } ///< \returns The value of \f$4\pi\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType two_pi() { return 6.28318530717958647692528676655900576839433879875021; } //!< \returns The value of \f$2\pi\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType three_pi() { return 9.42477796076937971538793014983850865259150819812531; } //!< \returns The value of \f$3\pi\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType four_pi() { return 12.56637061435917295385057353311801153678867759750042; } //!< \returns The value of \f$4\pi\f$ with the highest precision for \f$genType\f$
// Fractions of Pi
template<typename genType> constexpr genType half_pi() { return 1.57079632679489661923132169163975144209858469968755; } ///< \returns The value of \f$\frac{\pi}{2}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType three_halves_pi() { return 4.71238898038468985769396507491925432629575409906265; } ///< \returns The value of \f$\frac{3\pi}{2}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType half_pi() { return 1.57079632679489661923132169163975144209858469968755; } //!< \returns The value of \f$\frac{\pi}{2}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType three_halves_pi() { return 4.71238898038468985769396507491925432629575409906265; } //!< \returns The value of \f$\frac{3\pi}{2}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType third_pi() { return 1.04719755119659774615421446109316762806572313312503; } ///< \returns The value of \f$\frac{\pi}{3}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType two_thirds_pi() { return 2.09439510239319549230842892218633525613144626625007; } ///< \returns The value of \f$\frac{2\pi}{3}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType four_thirds_pi() { return 4.18879020478639098461685784437267051226289253250014; } ///< \returns The value of \f$\frac{4\pi}{3}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType five_thirds_pi() { return 5.23598775598298873077107230546583814032861566562517; } ///< \returns The value of \f$\frac{5\pi}{3}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType third_pi() { return 1.04719755119659774615421446109316762806572313312503; } //!< \returns The value of \f$\frac{\pi}{3}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType two_thirds_pi() { return 2.09439510239319549230842892218633525613144626625007; } //!< \returns The value of \f$\frac{2\pi}{3}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType four_thirds_pi() { return 4.18879020478639098461685784437267051226289253250014; } //!< \returns The value of \f$\frac{4\pi}{3}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType five_thirds_pi() { return 5.23598775598298873077107230546583814032861566562517; } //!< \returns The value of \f$\frac{5\pi}{3}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType quarter_pi() { return 0.78539816339744830961566084581987572104929234984377; } ///< \returns The value of \f$\frac{\pi}{4}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType three_quarters_pi() { return 2.35619449019234492884698253745962716314787704953132; } ///< \returns The value of \f$\frac{3\pi}{4}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType five_quarters_pi() { return 3.92699081698724154807830422909937860524646174921888; } ///< \returns The value of \f$\frac{5\pi}{4}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType seven_quarters_pi() { return 5.49778714378213816730962592073913004734504644890643; } ///< \returns The value of \f$\frac{7\pi}{4}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType quarter_pi() { return 0.78539816339744830961566084581987572104929234984377; } //!< \returns The value of \f$\frac{\pi}{4}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType three_quarters_pi() { return 2.35619449019234492884698253745962716314787704953132; } //!< \returns The value of \f$\frac{3\pi}{4}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType five_quarters_pi() { return 3.92699081698724154807830422909937860524646174921888; } //!< \returns The value of \f$\frac{5\pi}{4}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType seven_quarters_pi() { return 5.49778714378213816730962592073913004734504644890643; } //!< \returns The value of \f$\frac{7\pi}{4}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType fifth_pi() { return 0.62831853071795864769252867665590057683943387987502; } ///< \returns The value of \f$\frac{\pi}{5}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType two_fifths_pi() { return 1.25663706143591729538505735331180115367886775975004; } ///< \returns The value of \f$\frac{2\pi}{5}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType three_fifths_pi() { return 1.88495559215387594307758602996770173051830163962506; } ///< \returns The value of \f$\frac{3\pi}{5}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType four_fifths_pi() { return 2.51327412287183459077011470662360230735773551950008; } ///< \returns The value of \f$\frac{4\pi}{5}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType six_fifths_pi() { return 3.76991118430775188615517205993540346103660327925012; } ///< \returns The value of \f$\frac{6\pi}{5}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType seven_fifths_pi() { return 4.39822971502571053384770073659130403787603715912514; } ///< \returns The value of \f$\frac{7\pi}{5}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType eight_fifths_pi() { return 5.02654824574366918154022941324720461471547103900016; } ///< \returns The value of \f$\frac{8\pi}{5}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType nine_fifths_pi() { return 5.65486677646162782923275808990310519155490491887519; } ///< \returns The value of \f$\frac{9\pi}{5}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType fifth_pi() { return 0.62831853071795864769252867665590057683943387987502; } //!< \returns The value of \f$\frac{\pi}{5}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType two_fifths_pi() { return 1.25663706143591729538505735331180115367886775975004; } //!< \returns The value of \f$\frac{2\pi}{5}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType three_fifths_pi() { return 1.88495559215387594307758602996770173051830163962506; } //!< \returns The value of \f$\frac{3\pi}{5}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType four_fifths_pi() { return 2.51327412287183459077011470662360230735773551950008; } //!< \returns The value of \f$\frac{4\pi}{5}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType six_fifths_pi() { return 3.76991118430775188615517205993540346103660327925012; } //!< \returns The value of \f$\frac{6\pi}{5}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType seven_fifths_pi() { return 4.39822971502571053384770073659130403787603715912514; } //!< \returns The value of \f$\frac{7\pi}{5}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType eight_fifths_pi() { return 5.02654824574366918154022941324720461471547103900016; } //!< \returns The value of \f$\frac{8\pi}{5}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType nine_fifths_pi() { return 5.65486677646162782923275808990310519155490491887519; } //!< \returns The value of \f$\frac{9\pi}{5}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType sixth_pi() { return 0.52359877559829887307710723054658381403286156656251; } ///< \returns The value of \f$\frac{\pi}{6}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType five_sixths_pi() { return 2.61799387799149436538553615273291907016430783281258; } ///< \returns The value of \f$\frac{5\pi}{6}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType seven_sixths_pi() { return 3.66519142918809211153975061382608669823003096593762; } ///< \returns The value of \f$\frac{7\pi}{6}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType eleven_sixths_pi() { return 5.75958653158128760384817953601242195436147723218769; } ///< \returns The value of \f$\frac{11\pi}{6}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType sixth_pi() { return 0.52359877559829887307710723054658381403286156656251; } //!< \returns The value of \f$\frac{\pi}{6}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType five_sixths_pi() { return 2.61799387799149436538553615273291907016430783281258; } //!< \returns The value of \f$\frac{5\pi}{6}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType seven_sixths_pi() { return 3.66519142918809211153975061382608669823003096593762; } //!< \returns The value of \f$\frac{7\pi}{6}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType eleven_sixths_pi() { return 5.75958653158128760384817953601242195436147723218769; } //!< \returns The value of \f$\frac{11\pi}{6}\f$ with the highest precision for \f$genType\f$
// Reciprocals of Pi
template<typename genType> constexpr genType one_over_pi() { return 0.31830988618379067153776752674502872406891929148091; } ///< \returns The value of \f$\frac{1}{\pi}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType two_over_pi() { return 0.63661977236758134307553505349005744813783858296182; } ///< \returns The value of \f$\frac{2}{\pi}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType one_over_pi() { return 0.31830988618379067153776752674502872406891929148091; } //!< \returns The value of \f$\frac{1}{\pi}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType two_over_pi() { return 0.63661977236758134307553505349005744813783858296182; } //!< \returns The value of \f$\frac{2}{\pi}\f$ with the highest precision for \f$genType\f$
// Exponentiations Pi
template<typename genType> constexpr genType pi_sq() { return 9.86960440108935861883449099987615113531369940724079; } ///< \returns The value of \f${\pi}^{2}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType pi_cb() { return 31.00627668029982017547631506710139520222528856588510; } ///< \returns The value of \f${\pi}^{2}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType pi_sq() { return 9.86960440108935861883449099987615113531369940724079; } //!< \returns The value of \f${\pi}^{2}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType pi_cb() { return 31.00627668029982017547631506710139520222528856588510; } //!< \returns The value of \f${\pi}^{2}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType sqrt_pi() { return 1.77245385090551602729816748334114518279754945612238; } ///< \returns The value of \f$\sqrt{\pi}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType one_over_sqrt_pi() { return 0.56418958354775628694807945156077258584405062932899; } ///< \returns The value of \f$\frac{1}{\sqrt{\pi}}\f$ with the highest precision for \f$genType\f$
template<typename genType> constexpr genType sqrt_two_pi() { return 1.77245385090551602729816748334114518279754945612238; } ///< \returns The value of \f$\sqrt{2\pi}\f$ with the highest precision for \f$genType\f$

View File

@@ -43,7 +43,7 @@
///
///
#include <fennec/math/detail/_fwd.h>
#include <fennec/math/detail/_forward.h>
#include <fennec/math/detail/_matrix.h>
#include <fennec/containers/array.h>
@@ -78,43 +78,43 @@ constexpr vec<scalar, sizeof...(cols)> row(const matrix<scalar, rows, cols...>&
template<typename ScalarT>
using tmat2x2 = mat<ScalarT, 2, 2>; ///< helper for creating 2x2 matrices of the specified type.
template<typename ScalarT> using tmat2x3 = mat<ScalarT, 2, 3>; ///< helper for creating 2x3 matrices of the specified type.
template<typename ScalarT> using tmat2x4 = mat<ScalarT, 2, 4>; ///< helper for creating 2x4 matrices of the specified type.
template<typename ScalarT> using tmat3x2 = mat<ScalarT, 3, 2>; ///< helper for creating 3x2 matrices of the specified type.
template<typename ScalarT> using tmat3x3 = mat<ScalarT, 3, 3>; ///< helper for creating 3x3 matrices of the specified type.
template<typename ScalarT> using tmat3x4 = mat<ScalarT, 3, 4>; ///< helper for creating 3x4 matrices of the specified type.
template<typename ScalarT> using tmat4x2 = mat<ScalarT, 4, 2>; ///< helper for creating 4x2 matrices of the specified type.
template<typename ScalarT> using tmat4x3 = mat<ScalarT, 4, 3>; ///< helper for creating 4x3 matrices of the specified type.
template<typename ScalarT> using tmat4x4 = mat<ScalarT, 4, 4>; ///< helper for creating 4x4 matrices of the specified type.
using tmat2x2 = mat<ScalarT, 2, 2>; //!< helper for creating 2x2 matrices of the specified type.
template<typename ScalarT> using tmat2x3 = mat<ScalarT, 2, 3>; //!< helper for creating 2x3 matrices of the specified type.
template<typename ScalarT> using tmat2x4 = mat<ScalarT, 2, 4>; //!< helper for creating 2x4 matrices of the specified type.
template<typename ScalarT> using tmat3x2 = mat<ScalarT, 3, 2>; //!< helper for creating 3x2 matrices of the specified type.
template<typename ScalarT> using tmat3x3 = mat<ScalarT, 3, 3>; //!< helper for creating 3x3 matrices of the specified type.
template<typename ScalarT> using tmat3x4 = mat<ScalarT, 3, 4>; //!< helper for creating 3x4 matrices of the specified type.
template<typename ScalarT> using tmat4x2 = mat<ScalarT, 4, 2>; //!< helper for creating 4x2 matrices of the specified type.
template<typename ScalarT> using tmat4x3 = mat<ScalarT, 4, 3>; //!< helper for creating 4x3 matrices of the specified type.
template<typename ScalarT> using tmat4x4 = mat<ScalarT, 4, 4>; //!< helper for creating 4x4 matrices of the specified type.
using mat2 = tmat2x2<float_t>; ///< Specification for glsl float matrices
using mat3 = tmat3x3<float_t>; ///< Specification for glsl float matrices
using mat4 = tmat4x4<float_t>; ///< Specification for glsl float matrices
using mat2 = tmat2x2<float_t>; //!< Specification for glsl float matrices
using mat3 = tmat3x3<float_t>; //!< Specification for glsl float matrices
using mat4 = tmat4x4<float_t>; //!< Specification for glsl float matrices
using mat2x2 = tmat2x2<float_t>; ///< Specification for sized glsl float matrices
using mat2x3 = tmat2x3<float_t>; ///< Specification for sized glsl float matrices
using mat2x4 = tmat2x4<float_t>; ///< Specification for sized glsl float matrices
using mat3x2 = tmat3x2<float_t>; ///< Specification for sized glsl float matrices
using mat3x3 = tmat3x3<float_t>; ///< Specification for sized glsl float matrices
using mat3x4 = tmat3x4<float_t>; ///< Specification for sized glsl float matrices
using mat4x2 = tmat4x2<float_t>; ///< Specification for sized glsl float matrices
using mat4x3 = tmat4x3<float_t>; ///< Specification for sized glsl float matrices
using mat4x4 = tmat4x4<float_t>; ///< Specification for sized glsl float matrices
using mat2x2 = tmat2x2<float_t>; //!< Specification for sized glsl float matrices
using mat2x3 = tmat2x3<float_t>; //!< Specification for sized glsl float matrices
using mat2x4 = tmat2x4<float_t>; //!< Specification for sized glsl float matrices
using mat3x2 = tmat3x2<float_t>; //!< Specification for sized glsl float matrices
using mat3x3 = tmat3x3<float_t>; //!< Specification for sized glsl float matrices
using mat3x4 = tmat3x4<float_t>; //!< Specification for sized glsl float matrices
using mat4x2 = tmat4x2<float_t>; //!< Specification for sized glsl float matrices
using mat4x3 = tmat4x3<float_t>; //!< Specification for sized glsl float matrices
using mat4x4 = tmat4x4<float_t>; //!< Specification for sized glsl float matrices
using dmat2 = tmat2x2<double_t>; ///< Specification for glsl double matrices
using dmat3 = tmat3x3<double_t>; ///< Specification for glsl double matrices
using dmat4 = tmat3x3<double_t>; ///< Specification for glsl double matrices
using dmat2 = tmat2x2<double_t>; //!< Specification for glsl double matrices
using dmat3 = tmat3x3<double_t>; //!< Specification for glsl double matrices
using dmat4 = tmat3x3<double_t>; //!< Specification for glsl double matrices
using dmat2x2 = tmat2x2<double_t>; ///< Specification for size glsl double matrices
using dmat2x3 = tmat2x3<double_t>; ///< Specification for size glsl double matrices
using dmat2x4 = tmat2x4<double_t>; ///< Specification for size glsl double matrices
using dmat3x2 = tmat3x2<double_t>; ///< Specification for size glsl double matrices
using dmat3x3 = tmat3x3<double_t>; ///< Specification for size glsl double matrices
using dmat3x4 = tmat3x4<double_t>; ///< Specification for size glsl double matrices
using dmat4x2 = tmat4x2<double_t>; ///< Specification for size glsl double matrices
using dmat4x3 = tmat4x3<double_t>; ///< Specification for size glsl double matrices
using dmat4x4 = tmat4x4<double_t>; ///< Specification for size glsl double matrices
using dmat2x2 = tmat2x2<double_t>; //!< Specification for size glsl double matrices
using dmat2x3 = tmat2x3<double_t>; //!< Specification for size glsl double matrices
using dmat2x4 = tmat2x4<double_t>; //!< Specification for size glsl double matrices
using dmat3x2 = tmat3x2<double_t>; //!< Specification for size glsl double matrices
using dmat3x3 = tmat3x3<double_t>; //!< Specification for size glsl double matrices
using dmat3x4 = tmat3x4<double_t>; //!< Specification for size glsl double matrices
using dmat4x2 = tmat4x2<double_t>; //!< Specification for size glsl double matrices
using dmat4x3 = tmat4x3<double_t>; //!< Specification for size glsl double matrices
using dmat4x4 = tmat4x4<double_t>; //!< Specification for size glsl double matrices
///
@@ -676,7 +676,7 @@ struct matrix
// Helpers =============================================================================================================
// Private Helpers =====================================================================================================
public:

View File

@@ -59,7 +59,7 @@
#include <fennec/lang/types.h>
#include <fennec/math/detail/_fwd.h>
#include <fennec/math/detail/_forward.h>
#include <fennec/math/detail/_types.h>
namespace fennec

View File

@@ -68,10 +68,10 @@ public:
///
/// \name aliases for the size
/// @{
inline static constexpr size_t dimension = sizeof...(IndicesV); ///< \brief dimension of the swizzle
inline static constexpr size_t num_components = sizeof...(IndicesV); ///< \brief number of components
inline static constexpr size_t size = sizeof...(IndicesV); ///< \brief size of the swizzle
inline static constexpr size_t N = sizeof...(IndicesV); ///< \brief size of the swizzle
inline static constexpr size_t dimension = sizeof...(IndicesV); //!< \brief dimension of the swizzle
inline static constexpr size_t num_components = sizeof...(IndicesV); //!< \brief number of components
inline static constexpr size_t size = sizeof...(IndicesV); //!< \brief size of the swizzle
inline static constexpr size_t N = sizeof...(IndicesV); //!< \brief size of the swizzle
/// @}
///

View File

@@ -104,7 +104,7 @@
///
#include <fennec/containers/initializer_list.h>
#include <fennec/math/detail/_fwd.h>
#include <fennec/math/detail/_forward.h>
#include <fennec/math/vector_base.h>
#include <fennec/math/vector_traits.h>
@@ -146,31 +146,31 @@ template<typename ScalarT>
using tvec4 = vec<ScalarT, 4>;
using bvec2 = tvec2<bool_t>; ///< \brief A two-component boolean \ref fennec_math_vector "vector"
using bvec3 = tvec3<bool_t>; ///< \brief A three-component boolean \ref fennec_math_vector "vector"
using bvec4 = tvec4<bool_t>; ///< \brief A four-component boolean \ref fennec_math_vector "vector"
using bvec2 = tvec2<bool_t>; //!< \brief A two-component boolean \ref fennec_math_vector "vector"
using bvec3 = tvec3<bool_t>; //!< \brief A three-component boolean \ref fennec_math_vector "vector"
using bvec4 = tvec4<bool_t>; //!< \brief A four-component boolean \ref fennec_math_vector "vector"
using ivec2 = tvec2<int32_t>; ///< \brief A two-component signed integer \ref fennec_math_vector "vector"
using ivec3 = tvec3<int32_t>; ///< \brief A three-component signed integer \ref fennec_math_vector "vector"
using ivec4 = tvec4<int32_t>; ///< \brief A four-component signed integer \ref fennec_math_vector "vector"
using ivec2 = tvec2<int32_t>; //!< \brief A two-component signed integer \ref fennec_math_vector "vector"
using ivec3 = tvec3<int32_t>; //!< \brief A three-component signed integer \ref fennec_math_vector "vector"
using ivec4 = tvec4<int32_t>; //!< \brief A four-component signed integer \ref fennec_math_vector "vector"
using uvec2 = tvec2<uint32_t>; ///< \brief A two-component unsigned integer \ref fennec_math_vector "vector"
using uvec3 = tvec3<uint32_t>; ///< \brief A three-component unsigned integer \ref fennec_math_vector "vector"
using uvec4 = tvec4<uint32_t>; ///< \brief A four-component unsigned integer \ref fennec_math_vector "vector"
using uvec2 = tvec2<uint32_t>; //!< \brief A two-component unsigned integer \ref fennec_math_vector "vector"
using uvec3 = tvec3<uint32_t>; //!< \brief A three-component unsigned integer \ref fennec_math_vector "vector"
using uvec4 = tvec4<uint32_t>; //!< \brief A four-component unsigned integer \ref fennec_math_vector "vector"
using vec2 = tvec2<float_t>;
///< \brief A two-component single-precision floating-point \ref fennec_math_vector "vector"
//!< \brief A two-component single-precision floating-point \ref fennec_math_vector "vector"
using vec3 = tvec3<float_t>;
///< \brief A three-component single-precision floating-point \ref fennec_math_vector "vector"
//!< \brief A three-component single-precision floating-point \ref fennec_math_vector "vector"
using vec4 = tvec4<float_t>;
///< \brief A four-component single-precision floating-point \ref fennec_math_vector "vector"
//!< \brief A four-component single-precision floating-point \ref fennec_math_vector "vector"
using dvec2 = tvec2<double_t>;
///< \brief A two-component double-precision floating-point \ref fennec_math_vector "vector"
//!< \brief A two-component double-precision floating-point \ref fennec_math_vector "vector"
using dvec3 = tvec3<double_t>;
///< \brief A three-component double-precision floating-point \ref fennec_math_vector "vector"
//!< \brief A three-component double-precision floating-point \ref fennec_math_vector "vector"
using dvec4 = tvec4<double_t>;
///< \brief A four-component double-precision floating-point \ref fennec_math_vector "vector"
//!< \brief A four-component double-precision floating-point \ref fennec_math_vector "vector"
///
@@ -186,9 +186,21 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
static_assert(is_arithmetic_v<ScalarT>);
// Forward Defs ========================================================================================================
// Definitions & Constants =============================================================================================
/// \name Forward Definitions & Constants
/// \name Constants
/// @{
static constexpr size_t dimension = sizeof...(IndicesV); //!< \brief dimension of the swizzle
static constexpr size_t num_components = sizeof...(IndicesV); //!< \brief number of components
static constexpr size_t size = sizeof...(IndicesV); //!< \brief size of the swizzle
static constexpr size_t N = sizeof...(IndicesV); //!< \brief size of the swizzle
/// @}
/// \name Definitions
/// @{
///
@@ -207,14 +219,8 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \brief alias for this type
using vector_t = vector;
// Size Aliases
static constexpr size_t dimension = sizeof...(IndicesV); ///< \brief dimension of the swizzle
static constexpr size_t num_components = sizeof...(IndicesV); ///< \brief number of components
static constexpr size_t size = sizeof...(IndicesV); ///< \brief size of the swizzle
static constexpr size_t N = sizeof...(IndicesV); ///< \brief size of the swizzle
using decay_t = conditional_t<N == 1, scalar_t, vector_t>;
///< Type that the \ref fennec_math_vector "vector" should Decay into
//!< Type that the \ref fennec_math_vector "vector" should Decay into
/// @}
@@ -362,9 +368,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// @}
// Public Member Functions =============================================================================================
// Utility Functions ===================================================================================================
/// \name Public Member Functions
/// \name Utility Functions
/// @{
///
@@ -1096,7 +1102,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// @}
// Helpers =============================================================================================================
// Private Helpers =====================================================================================================
private:
template<size_t IndexV = 0, typename HeadT, typename... TailT>

View File

@@ -20,7 +20,7 @@
#ifndef FENNEC_MATH_VECTOR_BASE_H
#define FENNEC_MATH_VECTOR_BASE_H
#include <fennec/math/detail/_fwd.h>
#include <fennec/math/detail/_forward.h>
#include <fennec/math/swizzle.h>
#include <fennec/math/vector_storage.h>

View File

@@ -334,9 +334,14 @@ public:
/// initialize any values as if they were the provided data type. Any operations present work
/// only on individual bytes.
template<typename T, class AllocT = allocator<T>>
struct allocation
{
struct allocation {
// Definitions =========================================================================================================
public:
/// \name Definitions
/// @{
/// \brief alias for the allocator type
using alloc_t = typename allocator_traits<AllocT>::template rebind<T>;
@@ -349,8 +354,14 @@ public:
/// \brief diff type definition for ptr_traits
using diff_t = ptrdiff_t;
/// @}
// Cosntructors ========================================================================================================
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Default Constructor, initializes internal data to \f$null\f$ and the capacity to \f$0\f$
@@ -363,7 +374,7 @@ public:
/// \param n The number of elements of type \f$T\f$ to allocate for
explicit constexpr allocation(size_t n) noexcept
: _data(nullptr), _capacity(0), _alignment(zero<align_t>()) {
callocate(n);
allocate(n);
}
///
@@ -384,7 +395,7 @@ public:
: _data(nullptr)
, _capacity(0)
, _alignment(align) {
callocate(n, align);
allocate(n, align);
}
///
@@ -421,7 +432,7 @@ public:
, _data(nullptr)
, _capacity(0)
, _alignment(zero<align_t>()) {
callocate(n);
allocate(n);
}
///
@@ -449,7 +460,7 @@ public:
, _data(nullptr)
, _capacity(0)
, _alignment(zero<align_t>()) {
callocate(n, align);
allocate(n, align);
}
///
@@ -499,8 +510,14 @@ public:
}
}
/// @}
// Assignment ==========================================================================================================
public:
/// \name Assignment
/// @{
///
/// \brief Copy Assignment Operator
@@ -527,12 +544,49 @@ public:
return *this;
}
/// @}
// Allocation and Deallocation =========================================================================================
// Properties ==========================================================================================================
public:
/// \name Properties
/// @{
///
/// \brief Getter for the byte size of the allocation.
/// \returns the size of the allocation in bytes
constexpr size_t size() const {
return _capacity * sizeof(T);
}
///
/// \brief Getter for the number of elements \f$n\f$ of type \f$T\f$ that the allocation can hold.
/// \returns the size of the allocation in elements
constexpr size_t capacity() const {
return _capacity;
}
///
/// \brief Getter for the alignment of the allocation.
/// \returns the alignment of the allocation
constexpr align_t alignment() const {
return _alignment;
}
/// @}
// Modifiers ===========================================================================================================
public:
/// \name Modifiers
/// @{
///
/// \brief Allocate a block of memory for the allocation.
/// If there is already an allocated block of memory, the previous allocation is released.
/// \details If there is already an allocated block of memory, the previous allocation is released.
///
///
/// \param n The number of elements of type \f$T\f$ to allocate for
/// \param align The alignment to use
@@ -546,17 +600,6 @@ public:
}
}
///
/// \brief Allocate a block of memory for the allocation.
/// If there is already an allocated block of memory, the previous allocation is released.
///
/// \param n The number of elements of type \f$T\f$ to allocate for
/// \param align The alignment to use
constexpr void callocate(size_t n, align_t align = zero<align_t>()) noexcept {
allocate(n, align);
fennec::memset(static_cast<void*>(_data), 0, _capacity * sizeof(T));
}
///
/// \brief Release the block of memory.
constexpr void deallocate() noexcept {
@@ -596,33 +639,19 @@ public:
}
///
/// \brief Reallocate the block with a new size.
/// Contents are copied to the new allocation.
///
/// \param n The number of elements of type \f$T\f$ to allocate for
/// \param align The alignment to use
constexpr void creallocate(size_t n, align_t align = zero<align_t>()) noexcept {
if (_data == nullptr) {
callocate(n, align);
return;
/// \brief Clear the block of memory, setting all bytes to 0.
constexpr void clear() noexcept {
fennec::memset(static_cast<void*>(_data), 0, _capacity * sizeof(T));
}
value_t* old = _data; size_t old_cap = _capacity;
_data = nullptr;
allocate(n, align);
fennec::memmove(static_cast<void*>(_data), old, min(_capacity, old_cap) * sizeof(T));
if (_capacity > old_cap) {
fennec::memset(static_cast<void*>(_data + old_cap), 0, _capacity - old_cap);
}
_alloc.deallocate(old);
_capacity = n;
}
/// @}
// Access ==============================================================================================================
public:
/// \name Access
/// @{
///
/// \param i The index to access
@@ -654,55 +683,6 @@ public:
return _data;
}
///
/// \returns A pointer to the start of the allocation.
value_t* begin() {
return _data;
}
///
/// \brief Iterator Begin
/// \returns A pointer to the start of the allocation.
const value_t* begin() const {
return _data;
}
///
/// \returns A pointer to the element one after the last.
value_t* end() {
return _data + capacity();
}
///
/// \brief Iterator End
/// \returns A pointer to the element one after the last.
const value_t* end() const {
return _data + capacity();
}
// Modification ========================================================================================================
///
/// \brief Clear the block of memory, setting all bytes to 0.
constexpr void clear() noexcept {
fennec::memset(static_cast<void*>(_data), 0, _capacity * sizeof(T));
}
///
/// \brief Getter for the byte size of the allocation.
/// \returns the size of the allocation in bytes
constexpr size_t size() const {
return _capacity * sizeof(T);
}
///
/// \brief Getter for the number of elements \f$n\f$ of type \f$T\f$ that the allocation can hold.
/// \returns the size of the allocation in elements
constexpr size_t capacity() const {
return _capacity;
}
///
/// \brief Getter for the real pointer to the allocated block of memory
/// \returns Pointer to the allocated memory.
@@ -718,12 +698,33 @@ public:
}
///
/// \brief Getter for the alignment of the allocation.
/// \returns the alignment of the allocation
constexpr align_t alignment() const {
return _alignment;
/// \returns A pointer to the start of the allocation.
value_t* begin() {
return _data;
}
///
/// \brief C++ Iterator Begin
/// \returns A pointer to the start of the allocation.
const value_t* begin() const {
return _data;
}
///
/// \returns A pointer to the element one after the last.
value_t* end() {
return _data + capacity();
}
///
/// \brief C++ Iterator End
/// \returns A pointer to the element one after the last.
const value_t* end() const {
return _data + capacity();
}
/// @}
private:
alloc_t _alloc; // Allocator object
value_t* _data; // Handle for the memory block

View File

@@ -84,9 +84,14 @@ struct default_delete<TypeT[]>
/// \tparam TypeT
/// \tparam DeleteT
template<typename TypeT, class DeleteT = default_delete<TypeT>>
class unique_ptr
{
class unique_ptr {
// Definitions =========================================================================================================
public:
/// \name Definitions
/// @{
/// \brief the element type
using element_t = TypeT;
@@ -99,6 +104,15 @@ public:
/// \brief the deleter
using delete_t = DeleteT;
/// @}
// Constructors ========================================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Default Constructor, creates a unique_ptr that owns nothing.
constexpr unique_ptr() : unique_ptr(nullptr) {}
@@ -140,7 +154,14 @@ public:
reset();
}
constexpr unique_ptr& operator=(const unique_ptr&) = delete;
/// @}
// Assignment ==========================================================================================================
public:
/// \name Assignment
/// @{
///
/// \brief move constructor
@@ -152,6 +173,75 @@ public:
return *this;
}
/// @}
private:
constexpr unique_ptr& operator=(const unique_ptr&) = delete;
// Properties ==========================================================================================================
public:
/// \name Properties
/// @{
///
/// \returns \f$true\f$ if there is not a held pointer, \f$false\f$ otherwise
bool is_empty() {
return _handle == nullptr;
}
///
/// \brief implicit boolean conversion
/// \returns \f$true\f$ if there is a held pointer, \f$false\f$ otherwise
operator bool() const {
return _handle != nullptr;
}
/// @}
// Access ==============================================================================================================
public:
/// \name Access
/// @{
///
/// \returns a reference to the held pointer
pointer_t get() const {
return _handle;
}
///
/// \returns the held object for access
pointer_t operator->() {
return _handle;
}
///
/// \brief access operator
/// \returns the held object for access
const_pointer_t operator->() const {
return _handle;
}
///
/// \brief dereference operator
/// \returns a reference to the held value
element_t& operator*() const {
return *_handle;
}
/// @}
// Modifiers ===========================================================================================================
public:
/// \name Modifiers
/// @{
///
/// \brief reset the pointer, destroying the held object
/// \param ptr the new pointer to own
@@ -180,44 +270,7 @@ public:
return retval;
}
///
/// \returns a reference to the held pointer
pointer_t get() const {
return _handle;
}
///
/// \returns \f$true\f$ if there is not a held pointer, \f$false\f$ otherwise
bool is_empty() {
return _handle == nullptr;
}
///
/// \returns the held object for access
pointer_t operator->() {
return _handle;
}
///
/// \brief access operator
/// \returns the held object for access
const_pointer_t operator->() const {
return _handle;
}
///
/// \brief implicit boolean conversion
/// \returns \f$true\f$ if there is a held pointer, \f$false\f$ otherwise
operator bool() const {
return _handle != nullptr;
}
///
/// \brief dereference operator
/// \returns a reference to the held value
element_t& operator*() const {
return *_handle;
}
/// @}
private:
delete_t _delete;

View File

@@ -33,7 +33,7 @@
#include <fennec/containers/bitfield.h>
#include <fennec/platform/interface/fwd.h>
#include <fennec/platform/interface/forward.h>
#include <fennec/platform/interface/window.h>
#include <fennec/renderers/interface/gfxcontext.h>
@@ -55,9 +55,12 @@ class display_server;
/// must provide a constructor that accepts a `DisplayT*`. `DisplayT::ctx_registry::register_type` must then be
/// called for the \f$gfxcontext\f$ implementation.
class display_server : public type_registry<display_server, platform*> {
// Typedefs/Constants/Enums ============================================================================================
// Definitions & Constants =============================================================================================
public:
/// \name Definitions
/// @{
///
/// \brief enum representing features to test support for against the display server
enum feature_ : uint32_t {
@@ -96,10 +99,20 @@ public:
using featureset_t = bitfield<feature_count>; //!< a bitset holding the supported feature set
/// @}
// Public Members ======================================================================================================
// Public Member Variables =============================================================================================
public:
platform* const platform; //!< the parent platform
// Constructors ========================================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief display server constructor
/// \param p the parent platform
@@ -109,8 +122,16 @@ public:
///
/// \brief base destructor
virtual ~display_server() {
}
virtual ~display_server() = default;
/// @}
// Properties ==========================================================================================================
public:
/// \name Properties
/// @{
///
/// \brief feature support checking function
@@ -120,6 +141,19 @@ public:
return features.test(feature);
}
///
/// \returns \f$true\f$ if connected to the display server, \f$false\f$ otherwise
virtual bool connected() const = 0;
/// @}
// Operations ==========================================================================================================
public:
/// \name Operations
/// @{
///
/// \brief create a new window with the specified configuration and parent
/// \param cfg the configuration
@@ -135,10 +169,6 @@ public:
/// \brief disconnect from the display server
virtual void disconnect() = 0;
///
/// \returns \f$true\f$ if connected to the display server, \f$false\f$ otherwise
virtual bool connected() const = 0;
///
/// \brief dispatch the current context to the display server
virtual void dispatch() = 0;
@@ -153,10 +183,14 @@ public:
return gfx_context.get();
}
/// @}
// Protected Member Variables ==========================================================================================
protected:
featureset_t features; //!< the feature set of the display server
unique_ptr<gfxcontext> gfx_context; //!< the graphics context of the display server
private:
FENNEC_RTTI_CLASS_ENABLE() {
}
};

View File

@@ -16,8 +16,8 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_PLATFORM_INTERFACE_FWD_H
#define FENNEC_PLATFORM_INTERFACE_FWD_H
#ifndef FENNEC_PLATFORM_INTERFACE_FORWARD_H
#define FENNEC_PLATFORM_INTERFACE_FORWARD_H
namespace fennec
{
@@ -31,4 +31,4 @@ class gfxsurface; // Handles the GFX surface of a window for a specific gfxc
}
#endif // FENNEC_PLATFORM_INTERFACE_FWD_H
#endif // FENNEC_PLATFORM_INTERFACE_FORWARD_H

View File

@@ -64,10 +64,25 @@ namespace fennec
///
/// \brief Main platform class
class platform : public singleton<platform*> {
// Definitions =========================================================================================================
public:
/// \name Definitions
/// @{
using shared_object = struct shared_object; //!< handle for shared object code
using symbol = void*; //!< handle for a symbol loaded from a shared object
/// @}
// Constructors & Destructors ==========================================================================================
public:
/// \name Constructors & Destructors
/// @{
///
/// \brief constructor
platform();
@@ -76,8 +91,31 @@ public:
/// \brief destructor
virtual ~platform() = default;
private:
platform(const platform&) = delete;
/// @}
// Initialization ======================================================================================================
public:
/// \name Initialization
/// @{
virtual void initialize(); //!< Initialize Drivers and Contexts
virtual void shutdown(); //!< Close Drivers and Contexts
/// @}
// Shared Objects ======================================================================================================
public:
/// \name Shared Objects
/// @{
///
/// \brief shared object linker
/// \param file the name of the shared object to link
@@ -96,10 +134,23 @@ public:
/// \returns a reference to the symbol
virtual symbol find_symbol(shared_object* obj, const cstring& name) = 0;
virtual void initialize(); //!< Initialize Drivers and Contexts
virtual void shutdown(); //!< Close Drivers and Contexts
/// @}
virtual window_manager& get_window_manager() const { return *wmanager; }
// Window Management ===================================================================================================
public:
/// \name Window Management
/// @{
///
/// \brief Returns the window manager for the platform
/// \returns Reference to the window manager.
virtual window_manager& get_window_manager() const {
return *wmanager;
}
/// @}
protected:
unique_ptr<window_manager> wmanager; //!< the window manager

View File

@@ -31,7 +31,7 @@
#ifndef FENNEC_PLATFORM_INTERFACE_WINDOW_H
#define FENNEC_PLATFORM_INTERFACE_WINDOW_H
#include <fennec/platform/interface/fwd.h>
#include <fennec/platform/interface/forward.h>
#include <fennec/math/ext/rect.h>
@@ -49,6 +49,10 @@ namespace fennec
class window {
// Definitions =========================================================================================================
public:
/// \name Definitions
/// @{
///
/// \brief window mode
enum mode_ : uint8_t {
@@ -127,9 +131,15 @@ public:
double_t fractional_scaling; //!< current fractional scaling factor
};
/// @}
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief window constructor
@@ -142,9 +152,15 @@ public:
/// \brief base destructor
virtual ~window();
/// @}
// Properties ==========================================================================================================
public:
/// \name Properties
/// @{
///
/// \returns the current configuration of the window
@@ -162,18 +178,33 @@ public:
/// \returns the underlying handle of the window
virtual void* get_native_handle() = 0;
/// @}
// Positional Info =====================================================================================================
public:
/// \name Screen Bounds
/// @{
///
/// \returns the size of the window
const ivec2& get_size() const { return state.rect.size; }
const ivec2& get_size() const {
return state.rect.size;
}
///
/// \returns the position of the window
const ivec2& get_position() const { return state.rect.position; }
const ivec2& get_position() const {
return state.rect.position;
}
///
/// \returns the bounds of the window
const irect& get_bounds() const {
return state.rect;
}
///
/// \returns the width of the window
@@ -191,9 +222,15 @@ public:
/// \returns the y position of the window
int get_pos_y() const { return state.rect.position.y; }
/// @}
// Status ==============================================================================================================
public:
/// \name Status
/// @{
///
/// \brief tests if the window is visible
@@ -215,9 +252,15 @@ public:
/// \returns \f$true\f$ if the window is suspended, \f$false\f$ otherwise
bool is_suspended() const { return state.flags.test(state_suspended); }
/// @}
// Behaviour ===========================================================================================================
public:
/// \name Behaviour Flags
/// @{
///
/// \brief tests a specific flag
@@ -322,10 +365,15 @@ public:
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
bool set_no_focus(bool val) { return set_flag(flag_no_focus, val); }
/// @}
// Window Management Functions =========================================================================================
// Initialization & Update =============================================================================================
public:
/// \name Initialization & Update
/// @{
virtual void initialize() = 0; //!< initialization function
virtual void shutdown() = 0; //!< shutdown function
@@ -333,6 +381,10 @@ public:
virtual void begin_frame(); //!< start a frame for the window, setting the correct graphics context
virtual void end_frame(); //!< end a frame for the window, swapping the underlying buffers
/// @}
// Protected Member Variables ==========================================================================================
protected:
display_server* const server; //!< the display server the window belongs to
window* const parent; //!< the parent window

View File

@@ -24,12 +24,23 @@ namespace fennec
{
class linux_platform : public unix_platform {
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor ================================================================================
/// @{
/// \brief constructor
linux_platform()
: unix_platform() {
}
/// @}
//
void initialize() override; //!< platform initialization
void shutdown() override; //!< platform shutdown

View File

@@ -40,7 +40,12 @@ namespace fennec
///
/// \brief wayland egl context
class wayland_eglcontext : public eglcontext {
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
/// \brief constructor
/// \param display the display server
explicit wayland_eglcontext(display_server* display);
@@ -48,11 +53,23 @@ public:
/// \brief destructor
~wayland_eglcontext();
/// @}
// Operations ==========================================================================================================
public:
/// \name Operations
/// @{
/// \brief create a surface for a window
/// \param window the window
/// \returns a new surface for the window
gfxsurface* create_surface(window* window) override;
/// @}
// Private Member Variables ============================================================================================
private:
FENNEC_RTTI_CLASS_ENABLE(eglcontext) {
wayland_server::ctx_registry::register_type<wayland_eglcontext>();

View File

@@ -33,7 +33,7 @@
#define LATFORM_LINUX_WAYLAND_EGL_SURFACE_H
#include <fennec/platform/opengl/egl/surface.h>
#include <fennec/platform/linux/wayland/fwd.h>
#include <fennec/platform/linux/wayland/forward.h>
namespace fennec
{
@@ -41,7 +41,13 @@ namespace fennec
///
/// \brief wayland egl surface
class wayland_eglsurface : public eglsurface {
// Constructors ========================================================================================================
public:
/// \name Constructors & Destructor
/// @{
/// \brief constructor
/// \param win the wayland window
/// \param ctx the egl context
@@ -50,10 +56,22 @@ public:
/// \brief destructor
~wayland_eglsurface();
/// @}
// Operations ==========================================================================================================
public:
/// \name Operations
/// @{
///
/// \brief resize the surface
/// \param size the new size
void resize(const ivec2& size) override;
/// @}
private:
};

View File

@@ -17,7 +17,7 @@
// =====================================================================================================================
///
/// \file fennec/platform/linux/wayland/fwd.h
/// \file fennec/platform/linux/wayland/forward.h
/// \brief
///
///
@@ -29,8 +29,8 @@
///
#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_FWD_H
#define FENNEC_PLATFORM_LINUX_WAYLAND_FWD_H
#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_FORWARD_H
#define FENNEC_PLATFORM_LINUX_WAYLAND_FORWARD_H
namespace fennec
{
@@ -40,4 +40,4 @@ class wayland_window;
}
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_FWD_H
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_FORWARD_H

View File

@@ -31,7 +31,7 @@
#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_SERVER_H
#define FENNEC_PLATFORM_LINUX_WAYLAND_SERVER_H
#include <fennec/platform/linux/wayland/fwd.h>
#include <fennec/platform/linux/wayland/forward.h>
#include <fennec/platform/interface/display_server.h>
#if FENNEC_HAS_LIBDECOR
@@ -56,7 +56,13 @@ namespace fennec
///
/// \brief Class for handling the Wayland Display Server
class wayland_server : public display_server_base<wayland_server, wayland_window> {
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
/// \brief constructor
/// \param p the platform
explicit wayland_server(fennec::platform* p);
@@ -64,6 +70,15 @@ public:
/// \brief destructor
~wayland_server() override;
/// @}
// Operations ==========================================================================================================
public:
/// \name Operations
/// @{
void connect() override; //!< connect to wayland
void disconnect() override; //!< disconnect from wayland
bool connected() const override; //!< check if connected to wayland \returns \f$true\f$ if connected, \f$false\f$ otherwise
@@ -79,8 +94,9 @@ public:
/// \returns the native wl_display handle
void* get_native_handle() override { return display; }
/// @}
// Fields ==============================================================================================================
// Private Member Variables ============================================================================================
private:
wl_display* display;
wl_registry* registry;
@@ -96,6 +112,7 @@ private:
// Listeners ===========================================================================================================
private:
static void _wl_registry_listen_global(void*, wl_registry*, uint32_t, const char*, uint32_t);
static void _wl_registry_on_global_remove(void*, wl_registry*, uint32_t);

View File

@@ -31,7 +31,7 @@
#ifndef FENNEC_PLATFORM_LINUX_WAYLAND_WINDOW_H
#define FENNEC_PLATFORM_LINUX_WAYLAND_WINDOW_H
#include <fennec/platform/linux/wayland/fwd.h>
#include <fennec/platform/linux/wayland/forward.h>
#include <fennec/platform/interface/window.h>
#ifndef FENNEC_DOXYGEN
@@ -55,21 +55,32 @@ namespace fennec
///
/// \brief Class for handling a Wayland window
class wayland_window : public window_base<wayland_server> {
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief constructor
/// \param server the display server
/// \param cfg the configuration
/// \param parent the parent window
wayland_window(display_server* server, const config& cfg, window* parent);
///
/// \brief destructor
~wayland_window();
void initialize() override; //!< initialize the window
void shutdown() override; //!< shutdown the window
/// @}
/// \returns the native wl_surface handle
void* get_native_handle() override;
// Behaviour Flags =====================================================================================================
public:
/// \name Behaviour Flags
/// @{
///
/// \brief sets a specific flag
@@ -78,8 +89,25 @@ public:
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
bool set_flag(uint8_t flag, bool val) override;
/// @}
// Fields ==============================================================================================================
// Initialization & Update =============================================================================================
public:
/// \name Initialization & Update
/// @{
void initialize() override; //!< initialize the window
void shutdown() override; //!< shutdown the window
/// \returns the native wl_surface handle
void* get_native_handle() override;
/// @}
// Private Member Variables ============================================================================================
private:
wl_surface* surface;
xdg_surface* xdgsurface;
@@ -92,12 +120,13 @@ private:
#endif
// Helpers =============================================================================================================
// Private Helpers =====================================================================================================
private:
void _update_size(const ivec2& size);
// Listeners ===========================================================================================================
private:
static void _wl_surface_listen_enter(void*, wl_surface*, wl_output*);
static void _wl_surface_listen_leave(void*, wl_surface*, wl_output*);

View File

@@ -41,16 +41,31 @@
namespace fennec
{
///
/// \brief base egl context with platform-independent behaviour
class eglcontext : public glcontext {
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief constructor
/// \param display the corresponding display server
eglcontext(display_server* display);
///
/// \brief destructor
~eglcontext();
/// @}
//
///
/// \returns \f$true\f$ if the context is valid, \f$false\f$ otherwise
bool is_valid() override;

View File

@@ -17,7 +17,7 @@
// =====================================================================================================================
///
/// \file fennec/platform/opengl/egl/fwd.h
/// \file fennec/platform/opengl/egl/forward.h
/// \brief
///
///
@@ -29,8 +29,8 @@
///
#ifndef FENNEC_PLATFORM_OPENGL_EGL_FWD_H
#define FENNEC_PLATFORM_OPENGL_EGL_FWD_H
#ifndef FENNEC_PLATFORM_OPENGL_EGL_FORWARD_H
#define FENNEC_PLATFORM_OPENGL_EGL_FORWARD_H
namespace fennec
{
@@ -40,4 +40,4 @@ class eglsurface;
}
#endif // FENNEC_PLATFORM_OPENGL_EGL_FWD_H
#endif // FENNEC_PLATFORM_OPENGL_EGL_FORWARD_H

View File

@@ -33,7 +33,7 @@
#define FENNEC_PLATFORM_OPENGL_EGL_SURFACE_H
#include <fennec/platform/opengl/glad/egl.h>
#include <fennec/platform/opengl/egl/fwd.h>
#include <fennec/platform/opengl/egl/forward.h>
#include <fennec/renderers/interface/gfxsurface.h>
@@ -42,17 +42,37 @@ namespace fennec
{
/// \brief base egl surface with platform-independent behaviour
class eglsurface : public gfxsurface {
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
/// \brief constructor
/// \param win the associated window
/// \param ctx the associated context
/// \param eglwindow the create egl window
eglsurface(fennec::window* win, eglcontext* ctx, void* eglwindow);
///
/// \brief Destructor
~eglsurface();
// Operations ==========================================================================================================
public:
/// \name Operations
/// @{
void make_current() override; //!< makes this surface the current target of the context
void swap() override; //!< swaps the front and back buffers
/// @}
// Protected Member Variables ==========================================================================================
protected:
void* _eglwindow; //!< the underlying handle to the window
EGLSurface _eglsurface; //!< the handle for the surface

View File

@@ -25,13 +25,27 @@ namespace fennec
{
/// \brief base unix platform for generic unix functionality
class unix_platform : public platform {
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief constructor
explicit unix_platform()
: platform() {
}
/// @}
// Shared Objects ======================================================================================================
public:
/// \name Shared Objects
/// @{
///
/// \brief shared object linker
/// \param file the name of the shared object to link
@@ -50,7 +64,13 @@ public:
/// \returns a reference to the symbol
symbol find_symbol(shared_object* obj, const cstring& name) override;
/// @}
// Private Member Variables ============================================================================================
private:
FENNEC_RTTI_CLASS_ENABLE(platform) {
}
};

View File

@@ -32,10 +32,11 @@
#ifndef FENNEC_PLATFORM_WINDOWMANAGER_H
#define FENNEC_PLATFORM_WINDOWMANAGER_H
#include <fennec/platform/interface/fwd.h>
#include <fennec/platform/interface/forward.h>
#include <fennec/memory/pointers.h>
#include <fennec/containers/object_pool.h>
#include <fennec/containers/variant.h>
#include <fennec/platform/interface/window.h>
#include <fennec/threading/lock_guard.h>
#include <fennec/threading/mpscq.h>
@@ -50,20 +51,33 @@ using window_id = size_t; //!< type representing an id for a window
///
/// \brief class for handling display servers and windows
class window_manager {
// Definitions =========================================================================================================
// Definitions & Constants =============================================================================================
public:
/// \name Constants
/// @{
static constexpr window_id nullid = -1; //!< constant representing a null window
/// @}
private:
enum command_ : uint8_t {
command_set_flag = 0,
command_resize
};
struct flag_val {
uint8_t index;
bool val;
};
using cmd_data_t = variant<flag_val, ivec2>;
struct command {
uint8_t cmd;
window_id win;
void* data;
cmd_data_t data;
};
static constexpr size_t max_commands = 512;
@@ -78,6 +92,9 @@ private:
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief constructor
/// \param platform the platform
@@ -87,73 +104,379 @@ public:
/// \brief destructor
~window_manager();
/// @}
private:
window_manager(const window_manager&) = delete;
// Thread-Specific Functions ===========================================================================================
// Initialization & Update =============================================================================================
public:
void initialize(); //!< initialize the window system
void shutdown(); //!< shutdown the window system
void dispatch(); //!< dispatch the commands to the system
/// \name Initialization & Update
/// @{
///
/// \brief Initialization
///
/// \details Initializes the windowing system on the current thread.
void initialize();
///
/// \brief Shutdown
///
/// \details Shuts down the windowing system, must be called on the same thread as `window_manager::initialize`.
void shutdown();
///
/// \brief Command Dispatch
///
/// \details Dispatches commands to the server, must be called on the same thread as `window_manager::initialize`.
void dispatch();
/// @}
// Operations ==========================================================================================================
public:
/// \name Operations
/// @{
///
/// \brief Create a new window.
///
/// \details Must be called on the same thread as `window_manager::initialize`.
/// \param config The configuration for the new window.
/// \param parent The parent window.
window_id create_window(const config& config, window_id parent = nullid);
void begin(window_id window);
void end(window_id window);
///
/// \brief Start a frame for a window.
/// \param window The window.
///
/// \details Begins a new frame for the specified window. This will make the context and surface associated with
/// this window the new current context. Must be called on the same thread as `window_manager::initialize`.
void begin_frame(window_id window);
///
/// \brief Ends a frame for the window.
/// \param window The window.
///
/// \details Ends the current frame for the specified window. This will swap the front and back buffers for the
/// window. Must be called on the same thread as `window_manager::initialize`.
void end_frame(window_id window);
///
/// \brief Closes a window.
/// \param window The window.
///
/// \details Closes the window, cleaning up the surface associated with the window.
void close(window_id window);
/// @}
// Thread-Safe Functions ===============================================================================================
// Window Properties ===================================================================================================
public:
/// \name Window Properties
/// @{
///
/// \param window The window.
/// \returns the parent window
window_id get_parent(window_id window) const {
lock_guard guard(_lock);
return _parent(window);
}
///
/// \param window The window.
/// \returns the nearest top-level window in the hierarchy
window_id get_root(window_id window) const {
lock_guard guard(_lock);
return _root(window);
}
/// @}
// Window Bounds =======================================================================================================
public:
/// \name Window Bounds
/// @{
///
/// \param window The window.
/// \returns the size of the window
ivec2 get_size(window_id window) const {
lock_guard guard(_lock);
return _get_size(window);
}
///
/// \param window The window.
/// \returns the position of the window
ivec2 get_position(window_id window) const {
lock_guard guard(_lock);
return _get_position(window);
}
bool is_visible(window_id window) const { lock_guard guard(_lock); return _check_state(window, window::state_visible); }
bool is_child(window_id window) const { lock_guard guard(_lock); return _check_state(window, window::state_child); }
bool is_running(window_id window) const { lock_guard guard(_lock); return _check_state(window, window::state_running); }
bool is_suspended(window_id window) const { lock_guard guard(_lock); return _check_state(window, window::state_suspended); }
///
/// \param window The window.
/// \returns the bounds of the window
irect get_bounds(window_id window) const {
lock_guard guard(_lock);
return _get_bounds(window);
}
/// @}
// Window Status =======================================================================================================
public:
/// \name Window Status
/// @{
///
/// \brief tests if the window is visible
///
/// \param window The window.
/// \returns \f$true\f$ if the window is visible, \f$false\f$ otherwise
bool is_visible(window_id window) const {
lock_guard guard(_lock);
return _check_state(window, window::state_visible);
}
///
/// \brief tests if the window is a child
///
/// \param window The window.
/// \returns \f$true\f$ if the window is a child, \f$false\f$ otherwise
bool is_child(window_id window) const {
lock_guard guard(_lock);
return _check_state(window, window::state_child);
}
///
/// \brief tests if the window is running
///
/// \param window The window.
/// \returns \f$true\f$ if the window is running, \f$false\f$ otherwise
bool is_running(window_id window) const {
lock_guard guard(_lock);
return _check_state(window, window::state_running);
}
///
/// \brief tests if the window is suspended
///
/// \param window The window.
/// \returns \f$true\f$ if the window is suspended, \f$false\f$ otherwise
bool is_suspended(window_id window) const {
lock_guard guard(_lock);
return _check_state(window, window::state_suspended);
}
/// @}
// Window Behaviour Flags ==============================================================================================
public:
/// \name Window Behaviour Flags
/// @{
///
/// \brief tests a specific flag
///
/// \param window The window.
/// \param flag the flag from `window::flag_`
/// \returns \f$true\f$ if the flag is set, \f$false\f$ otherwise
bool get_flag(window_id window, uint8_t flag) {
lock_guard guard(_lock);
return _get_flag(window, flag);
}
bool is_always_on_top(window_id window) { return get_flag(window, window::flag_always_on_top); }
bool is_borderless(window_id window) { return get_flag(window, window::flag_borderless); }
bool is_modal(window_id window) { return get_flag(window, window::flag_modal); }
bool is_passing_mouse(window_id window) { return get_flag(window, window::flag_pass_mouse); }
bool is_popup(window_id window) { return get_flag(window, window::flag_popup); }
bool is_resizable(window_id window) { return get_flag(window, window::flag_resizable); }
bool is_transparent(window_id window) { return get_flag(window, window::flag_transparent); }
bool is_no_focus(window_id window) { return get_flag(window, window::flag_no_focus); }
///
/// \brief check if the window is flagged to always be on top of other windows
///
/// \param window The window.
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
bool is_always_on_top(window_id window) {
return get_flag(window, window::flag_always_on_top);
}
///
/// \brief check if the window is flagged to have no window decorations
///
/// \param window The window.
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
bool is_borderless(window_id window) {
return get_flag(window, window::flag_borderless);
}
///
/// \brief check if the window is flagged to be modal
///
/// \param window The window.
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
bool is_modal(window_id window) {
return get_flag(window, window::flag_modal);
}
///
/// \brief check if the window is flagged to pass mouse input to windows underneath from the same application
///
/// \param window The window.
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
bool is_passing_mouse(window_id window) {
return get_flag(window, window::flag_pass_mouse);
}
///
/// \brief check if the window is flagged as a popup
///
/// \param window The window.
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
bool is_popup(window_id window) {
return get_flag(window, window::flag_popup);
}
///
/// \brief check if the window is flagged to be resizable
///
/// \param window The window.
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
bool is_resizable(window_id window) {
return get_flag(window, window::flag_resizable);
}
///
/// \brief check if the window is flagged to be transparent
///
/// \param window The window.
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
bool is_transparent(window_id window) {
return get_flag(window, window::flag_transparent);
}
///
/// \brief check if the window is flagged to be unfocusable
///
/// \param window The window.
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
bool is_no_focus(window_id window) {
return get_flag(window, window::flag_no_focus);
}
bool set_flag(window_id window, uint8_t flag, bool val);
///
/// \brief sets a specific flag
///
/// \param window The window.
/// \param flag the flag from `window::flag_`
/// \param val the value to set the flag to
void set_flag(window_id window, uint8_t flag, bool val) {
lock_guard guard(_lock);
bool set_always_on_top(window_id window, bool val) { return set_flag(window, window::flag_always_on_top, val); }
bool set_borderless(window_id window, bool val) { return set_flag(window, window::flag_borderless, val); }
bool set_modal(window_id window, bool val) { return set_flag(window, window::flag_modal, val); }
bool set_passing_mouse(window_id window, bool val) { return set_flag(window, window::flag_pass_mouse, val); }
bool set_popup(window_id window, bool val) { return set_flag(window, window::flag_popup, val); }
bool set_resizable(window_id window, bool val) { return set_flag(window, window::flag_resizable, val); }
bool set_transparent(window_id window, bool val) { return set_flag(window, window::flag_transparent, val); }
bool set_no_focus(window_id window, bool val) { return set_flag(window, window::flag_no_focus, val); }
_commands.push(command {
.cmd = command_set_flag,
.win = window,
.data = flag_val{ .index = flag, .val = val }
});
}
///
/// \brief sets whether to always be on top of other windows
///
/// \param window The window.
/// \param val the value to set the flag to
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
void set_always_on_top(window_id window, bool val) {
return set_flag(window, window::flag_always_on_top, val);
}
///
/// \brief sets whether to have no window decorations
///
/// \param window The window.
/// \param val the value to set the flag to
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
void set_borderless(window_id window, bool val) {
return set_flag(window, window::flag_borderless, val);
}
///
/// \brief sets whether to be modal
///
/// \param window The window.
/// \param val the value to set the flag to
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
void set_modal(window_id window, bool val) {
return set_flag(window, window::flag_modal, val);
}
///
/// \brief sets whether to pass mouse input to windows underneath from the same application
///
/// \param window The window.
/// \param val the value to set the flag to
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
void set_passing_mouse(window_id window, bool val) {
return set_flag(window, window::flag_pass_mouse, val);
}
///
/// \brief sets whether the window is a popup
///
/// \param window The window.
/// \param val the value to set the flag to
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
void set_popup(window_id window, bool val) {
return set_flag(window, window::flag_popup, val);
}
///
/// \brief sets whether to be resizable
///
/// \param window The window.
/// \param val the value to set the flag to
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
void set_resizable(window_id window, bool val) {
return set_flag(window, window::flag_resizable, val);
}
///
/// \brief sets whetherto be transparent
///
/// \param window The window.
/// \param val the value to set the flag to
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
void set_transparent(window_id window, bool val) {
return set_flag(window, window::flag_transparent, val);
}
///
/// \brief sets whether to be unfocusable
///
/// \param window The window.
/// \param val the value to set the flag to
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
void set_no_focus(window_id window, bool val) {
return set_flag(window, window::flag_no_focus, val);
}
/// @}
// Private Member Variables ============================================================================================
private:
mutable mutex _lock;
thread::id _thread;
@@ -163,12 +486,14 @@ private:
command_queue_t _commands;
// Private Helpers =====================================================================================================
private:
window_id _parent(window_id id) const;
window_id _root(window_id id) const;
ivec2 _get_size(window_id id) const;
ivec2 _get_position(window_id id) const;
irect _get_bounds(window_id id) const;
bool _check_state(window_id id, uint8_t state) const;

View File

@@ -31,7 +31,7 @@
#ifndef FENNEC_RENDERERS_INTERFACE_GFXCONTEXT_H
#define FENNEC_RENDERERS_INTERFACE_GFXCONTEXT_H
#include <fennec/platform/interface/fwd.h>
#include <fennec/platform/interface/forward.h>
#include <fennec/core/version.h>
#include <fennec/lang/types.h>
@@ -44,32 +44,76 @@
namespace fennec
{
///
/// \brief Interface resembling a broader context for a graphics API
class gfxcontext {
public:
using handle_t = uint32_t;
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Context Constructor
/// \param display The display server this context was created from
gfxcontext(display_server* display)
: display(display)
, version(0, 0, 0, string("")) {
, version() {
}
///
/// \brief Virtual Destructor
virtual ~gfxcontext() = default;
gfxcontext& operator=(const gfxcontext&) = delete;
gfxcontext& operator=(gfxcontext&&) = delete;
/// @}
// Properties ==========================================================================================================
public:
/// \name Properties
/// @{
///
/// \returns \f$true\f$ if this
virtual bool is_valid() = 0;
///
/// \returns A version struct containing the version of the graphics API.
virtual const version& get_version() const { return version; }
/// @}
// Operations ==========================================================================================================
public:
/// \name Operations
/// @{
///
/// \brief Create a surface under the context of the graphics API for the provided window.
/// \param window The window to create a surface for.
/// \returns A new graphics surface for the API.
virtual gfxsurface* create_surface(window* window) = 0;
virtual const version& get_version() const { return version; };
/// @}
// Protected Member Variables ==========================================================================================
protected:
display_server* display;
version version;
display_server* const display; //!< The display server this context was created from.
version version; //!< The version of the underlying graphics API.
FENNEC_RTTI_CLASS_ENABLE() {
}
// Assignment Operators ================================================================================================
private:
gfxcontext& operator=(const gfxcontext&) = delete;
gfxcontext& operator=(gfxcontext&&) = delete;
};
}

View File

@@ -37,22 +37,61 @@
namespace fennec
{
///
/// \brief Interface representing a renderable surface for a graphics API.
class gfxsurface {
public:
virtual ~gfxsurface() = default;
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Graphics Surface Constructor.
/// \param win The window the surface belongs to.
/// \param ctx The graphics context the surface belongs to.
gfxsurface(window* win, gfxcontext* ctx)
: window(win), context(ctx) {
}
///
/// \brief Virtual Destructor
virtual ~gfxsurface() = default;
/// @}
// Properties ==========================================================================================================
public:
// Operations ==========================================================================================================
public:
/// \name Operations
/// @{
///
/// \brief Make this surface, and the context that it belongs to, the current rendering target for the graphics API.
virtual void make_current() = 0;
///
/// \brief Swap the surface's front & back buffers.
virtual void swap() = 0;
///
/// \brief Resize the backing buffers of the surface.
/// \param size The new size.
virtual void resize(const ivec2& size) = 0;
/// @}
// Protected Member Variables ==========================================================================================
protected:
window* window;
gfxcontext* context;
window* const window; //!< The window the surface belongs to.
gfxcontext* const context; //!< The graphics context the surface belongs to.
};
}

View File

@@ -16,11 +16,24 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file fennec/renderers/opengl/lib/buffer.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_RENDERERS_OPENGL_LIB_BUFFER_H
#define FENNEC_RENDERERS_OPENGL_LIB_BUFFER_H
#include <fennec/math/common.h>
#include <fennec/renderers/opengl/lib/fwd.h>
#include <fennec/renderers/opengl/lib/forward.h>
#include <fennec/renderers/opengl/lib/enum.h>
namespace fennec
@@ -29,27 +42,120 @@ namespace fennec
namespace gl
{
template<GLbitfield FlagsV, GLboolean ImmutableV> using vertex_buffer = buffer<VERTEX, FlagsV, ImmutableV>;
template<GLbitfield FlagsV, GLboolean ImmutableV> using element_buffer = buffer<ELEMENT, FlagsV, ImmutableV>;
template<GLbitfield FlagsV, GLboolean ImmutableV> using uniform_buffer = buffer<UNIFORM, FlagsV, ImmutableV>;
template<GLbitfield FlagsV, GLboolean ImmutableV> using shader_storage_buffer = buffer<SHADER_STORAGE, FlagsV, ImmutableV>;
template<GLbitfield FlagsV, GLboolean ImmutableV> using query_buffer = buffer<QUERY, FlagsV, ImmutableV>;
template<GLbitfield FlagsV, GLboolean ImmutableV> using texture_buffer = buffer<TEXTURE, FlagsV, ImmutableV>;
template<GLbitfield FlagsV, GLboolean ImmutableV> using transform_feedback_buffer = buffer<TRANSFORM_FEEDBACK, FlagsV, ImmutableV>;
template<GLbitfield FlagsV, GLboolean ImmutableV> using atomic_counter_buffer = buffer<ATOMIC_COUNTER, FlagsV, ImmutableV>;
template<GLbitfield FlagsV, GLboolean ImmutableV> using parameter_buffer = buffer<PARAMETER, FlagsV, ImmutableV>;
template<GLbitfield FlagsV, GLboolean ImmutableV> using indirect_draw_buffer = buffer<INDIRECT_DRAW, FlagsV, ImmutableV>;
template<GLbitfield FlagsV, GLboolean ImmutableV> using indirect_dispatch_buffer = buffer<INDIRECT_DISPATCH, FlagsV, ImmutableV>;
template<GLbitfield FlagsV, GLboolean ImmutableV> using copy_read_buffer = buffer<COPY_READ, FlagsV, ImmutableV>;
template<GLbitfield FlagsV, GLboolean ImmutableV> using copy_write_buffer = buffer<COPY_WRITE, FlagsV, ImmutableV>;
template<GLbitfield FlagsV, GLboolean ImmutableV> using pixel_pack_buffer = buffer<PIXEL_PACK, FlagsV, ImmutableV>;
template<GLbitfield FlagsV, GLboolean ImmutableV> using pixel_unpack_buffer = buffer<PIXEL_UNPACK, FlagsV, ImmutableV>;
///
/// \brief Vertex Buffer Alias
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
/// \tparam ImmutableV Mutability
template<GLbitfield FlagsV, GLboolean ImmutableV>
using vertex_buffer = buffer<VERTEX, FlagsV, ImmutableV>;
///
/// \brief Vertex Buffer Alias
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
/// \tparam ImmutableV Mutability
template<GLbitfield FlagsV, GLboolean ImmutableV>
using element_buffer = buffer<ELEMENT, FlagsV, ImmutableV>;
///
/// \brief Vertex Buffer Alias
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
/// \tparam ImmutableV Mutability
template<GLbitfield FlagsV, GLboolean ImmutableV>
using uniform_buffer = buffer<UNIFORM, FlagsV, ImmutableV>;
///
/// \brief Vertex Buffer Alias
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
/// \tparam ImmutableV Mutability
template<GLbitfield FlagsV, GLboolean ImmutableV>
using shader_storage_buffer = buffer<SHADER_STORAGE, FlagsV, ImmutableV>;
///
/// \brief Vertex Buffer Alias
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
/// \tparam ImmutableV Mutability
template<GLbitfield FlagsV, GLboolean ImmutableV>
using query_buffer = buffer<QUERY, FlagsV, ImmutableV>;
///
/// \brief Vertex Buffer Alias
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
/// \tparam ImmutableV Mutability
template<GLbitfield FlagsV, GLboolean ImmutableV>
using texture_buffer = buffer<TEXTURE, FlagsV, ImmutableV>;
///
/// \brief Vertex Buffer Alias
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
/// \tparam ImmutableV Mutability
template<GLbitfield FlagsV, GLboolean ImmutableV>
using transform_feedback_buffer = buffer<TRANSFORM_FEEDBACK, FlagsV, ImmutableV>;
///
/// \brief Vertex Buffer Alias
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
/// \tparam ImmutableV Mutability
template<GLbitfield FlagsV, GLboolean ImmutableV>
using atomic_counter_buffer = buffer<ATOMIC_COUNTER, FlagsV, ImmutableV>;
///
/// \brief Vertex Buffer Alias
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
/// \tparam ImmutableV Mutability
template<GLbitfield FlagsV, GLboolean ImmutableV>
using parameter_buffer = buffer<PARAMETER, FlagsV, ImmutableV>;
///
/// \brief Vertex Buffer Alias
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
/// \tparam ImmutableV Mutability
template<GLbitfield FlagsV, GLboolean ImmutableV>
using indirect_draw_buffer = buffer<INDIRECT_DRAW, FlagsV, ImmutableV>;
///
/// \brief Vertex Buffer Alias
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
/// \tparam ImmutableV Mutability
template<GLbitfield FlagsV, GLboolean ImmutableV>
using indirect_dispatch_buffer = buffer<INDIRECT_DISPATCH, FlagsV, ImmutableV>;
///
/// \brief Vertex Buffer Alias
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
/// \tparam ImmutableV Mutability
template<GLbitfield FlagsV, GLboolean ImmutableV>
using copy_read_buffer = buffer<COPY_READ, FlagsV, ImmutableV>;
///
/// \brief Vertex Buffer Alias
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
/// \tparam ImmutableV Mutability
template<GLbitfield FlagsV, GLboolean ImmutableV>
using copy_write_buffer = buffer<COPY_WRITE, FlagsV, ImmutableV>;
///
/// \brief Vertex Buffer Alias
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
/// \tparam ImmutableV Mutability
template<GLbitfield FlagsV, GLboolean ImmutableV>
using pixel_pack_buffer = buffer<PIXEL_PACK, FlagsV, ImmutableV>;
///
/// \brief Vertex Buffer Alias
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
/// \tparam ImmutableV Mutability
template<GLbitfield FlagsV, GLboolean ImmutableV>
using pixel_unpack_buffer = buffer<PIXEL_UNPACK, FlagsV, ImmutableV>;
///
/// \brief
/// \tparam TypeV The buffer type, see \ref fennec::gl::buffer_types "buffer_types"
/// \tparam FlagsV The buffer flags, see \ref fennec::gl::buffer_map_flags "buffer_map_flags"
/// \tparam ImmutableV Mutability
template<GLenum TypeV, GLbitfield FlagsV, GLboolean ImmutableV>
class buffer {
// HELPER FUNCTIONS ====================================================================================================
// Private Helpers =====================================================================================================
private:
static constexpr GLenum get_mutable_traits() {
GLenum res;
@@ -76,33 +182,105 @@ private:
}
// CONSTANTS ===========================================================================================================
// Constants ===========================================================================================================
public:
/// \name Constants
/// @{
///
/// \brief Enum value containing the buffer type.
/// \see fennec::gl::buffer_types
static constexpr GLenum type = TypeV;
///
/// \brief Boolean value representing whether this buffer is immutable.
/// \note Immutable buffers may not be resized.
static constexpr GLboolean immutable = ImmutableV;
///
/// \brief Bitfield value containing the buffer flags.
/// \see fennec::gl::buffer_map_flags
static constexpr GLbitfield flags = FlagsV;
///
/// \brief Boolean value representing whether this buffer has indexed binding targets.
/// \note Indexed buffer types must be bound to an indexed binding target to be used in shaders.
/// \see fennec::gl::buffer::bind
/// \see fennec::gl::buffer::bind_range
static constexpr GLboolean indexed = type == ATOMIC_COUNTER or type == SHADER_STORAGE or type == TRANSFORM_FEEDBACK or type == UNIFORM;
///
/// \brief Boolean value representing whether this buffer is mapped for reading.
/// \note Not to be confused with `read()`, which is specifically for dynamic buffers.
/// \see fennec::gl::buffer::map
static constexpr GLboolean map_read = flags & READ;
///
/// \brief Boolean value representing whether this buffer is mapped for writing.
/// \note Not to be confused with `write()`, which is specifically for dynamic buffers.
/// \see fennec::gl::buffer::map
static constexpr GLboolean map_write = flags & WRITE;
///
/// \brief Boolean value representing whether this buffer is mapped
/// \see fennec::gl::buffer::map
static constexpr GLboolean mapped = map_read or map_write;
///
/// \brief Boolean value representing whether this buffer is dynamic.
/// \note This allows use of the dynamic `read()` and `write()` functions.
/// \see fennec::gl::buffer::read
/// \see fennec::gl::buffer::write
static constexpr GLboolean dynamic = flags & DYNAMIC;
///
/// \brief Boolean value representing whether this buffer is persistent, i.e. can be used while mapped.
/// \see fennec::gl::buffer::map
static constexpr GLboolean persistent = flags & PERSISTENT;
///
/// \brief Boolean value representing whether this buffer is coherent when mapped.
/// \see fennec::gl::buffer::map
static constexpr GLboolean coherent = flags & COHERENT;
///
/// \brief Boolean value representing whether this buffers memory is on the client.
/// \note This is only a hint for the driver, which may be ignored.
static constexpr GLboolean client = flags & CLIENT;
///
/// \brief Enum value containing the mutable usage traits.
/// \see fennec::gl::buffer::immutable
static constexpr GLenum usage = get_mutable_traits();
static_assert(not persistent or persistent == mapped);
static_assert(not coherent or coherent == persistent);
/// @}
// CONSTRUCTORS & ASSIGNMENT ===========================================================================================
// Assertions ==========================================================================================================
public:
constexpr buffer(const void* data, GLsizeiptr size)
static_assert(not persistent or persistent == mapped, "Persistent buffer must be mappable.");
static_assert(not coherent or coherent == persistent, "Coherent buffer must be persistent.");
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Buffer Data Constructor
/// \param data Data to upload to the buffer, may be \f$nullptr\f$.
/// \param size Size of the buffer.
buffer(const void* data, GLsizeiptr size)
: _handle()
, _size(size) {
, _size(size)
, _data(nullptr)
, _mapflags(0) {
glGenBuffers(1, &_handle);
start();
use();
if constexpr(immutable) {
glBufferStorage(type, _size, data, flags);
} else {
@@ -110,34 +288,84 @@ public:
}
}
constexpr buffer(buffer&& buff) noexcept
///
/// \brief Buffer Move Constructor
/// \param buff The buffer to take ownership of
buffer(buffer&& buff) noexcept
: _handle(buff)
, _size(buff._size)
, _mapping(nullptr) {
, _data(nullptr)
, _mapflags(0) {
}
constexpr buffer& operator=(buffer&& buff) noexcept {
///
/// \brief Buffer Destructor
///
/// \details Cleans up buffer data and object
~buffer() {
glDeleteBuffers(1, &_handle);
_handle = buff._handle;
_size = buff._size;
}
/// @}
private:
buffer(const buffer&) = delete;
// Assignment ==========================================================================================================
public:
/// \name Assignment
/// @{
///
/// \brief Buffer Move Assignment
/// \param buff The buffer to take ownership of.
/// \returns A reference to self after having taken ownership of \f$buff\f$.
buffer& operator=(buffer&& buff) noexcept {
fennec::swap(_handle, buff._handle);
fennec::swap(_size, buff._size);
return *this;
}
constexpr buffer(const buffer&) = delete;
constexpr buffer& operator=(const buffer&) = delete;
/// @}
// OBJECT FUNCTIONS ====================================================================================================
private:
buffer& operator=(const buffer&) = delete;
constexpr void start() const {
// Use & Binding =======================================================================================================
public:
/// \name Use & Binding
/// @{
///
/// \brief Use this buffer for buffer operations.
void use() const {
glBindBuffer(type, _handle);
}
constexpr void end() const {
glBindBuffer(type, NULL);
///
/// \brief Bind this buffer to an indexed target.
///
/// \param i The index to bind to.
/// \see fennec::gl::buffer::type.
void bind(GLuint i) {
static_assert(indexed, "Buffer must have an indexed binding target.");
glBindBufferBase(type, i, _handle);
}
constexpr void bind(GLuint i, GLsizeiptr size = -1, GLintptr offset = 0) {
///
/// \brief Bind a range of this buffer to an indexed target.
/// \param i The index to bind to.
/// \param size The size of the range to bind.
/// \param offset The offset of the range to bind.
void bind_range(GLuint i, GLsizeiptr size = -1, GLintptr offset = 0) {
static_assert(indexed, "Buffer must have an indexed binding target.");
offset = max(offset, GLintptr(0));
size = size < 0 ? _size : size;
size = min(size, _size - offset);
@@ -145,40 +373,83 @@ public:
glBindBufferRange(type, i, _handle, offset, size);
}
/// @}
// BASIC BUFFER FUNCTIONS ==============================================================================================
constexpr void resize(GLsizei size) requires(not immutable) {
unmap();
glBufferData(type, _size = size, nullptr, usage);
// Mapping =============================================================================================================
public:
/// \name Mapping
/// @{
///
/// \brief Map a range of the buffer to be used by the client.
/// \param access The access specifiers.
/// \param size The size of the range to map.
/// \param offset The offset of the range to map.
/// \return
void* map(GLbitfield access, GLsizeiptr size = -1, GLintptr offset = 0) {
if (_data) {
return _data;
}
constexpr void* map(GLbitfield access, GLsizeiptr size, GLintptr offset = 0) {
if (_mapping) {
return _mapping;
}
offset = max(offset, GLintptr(0));
size = size < 0 ? _size : size;
size = min(size, _size - offset);
if (size <= 0) return nullptr;
return _mapping = glMapBufferRange(type, offset, size, _mapflags = access);
return _data = glMapBufferRange(type, offset, size, _mapflags = flags | access);
}
constexpr void unmap() {
///
/// \brief Release the mapping of the buffer.
void unmap() {
glUnmapBuffer(type);
_mapping = nullptr;
_data = nullptr;
}
constexpr void clear(GLsizeiptr size = -1, GLintptr offset = 0, const void* data = nullptr, GLenum data_type = BYTE, GLenum format = R, GLenum internal = R8) {
/// @}
// Operations ==========================================================================================================
public:
///
/// \brief Resize the buffer.
///
/// \param size The new size for the buffer.
/// \note Buffer must be mutable. Clears buffer with zeroes.
/// \see fennec::gl::buffer::immutable
void resize(GLsizei size) requires(not immutable) {
unmap();
glBufferData(type, _size = size, nullptr, usage);
}
///
/// \brief Clear the buffer.
/// \param size The number of elements to clear
/// \param offset The offset into the buffer to begin clearing.
/// \param value The value to clear with. Must be a pointer to an object of appropriate size for the type and format.
/// \param value_type The type of the data.
/// \param format The format of the data.
/// \param internal The assumed internal format of the buffer.
void clear(GLsizeiptr size = -1, GLintptr offset = 0, const void* value = nullptr, GLenum value_type = BYTE, GLenum format = R, GLenum internal = R8) {
offset = max(offset, GLintptr(0));
size = size < 0 ? _size : size;
size = min(size, _size - offset);
if (size <= 0) return;
glClearBufferSubData(type, internal, offset, size, format, data_type, data);
glClearBufferSubData(type, internal, offset, size, format, value_type, value);
}
///
/// \brief Copy data from another buffer.
/// \tparam OTypeV The type of the buffer to copy from.
/// \tparam OFlagsV The flags of the buffer being copied from.
/// \tparam OImmutableV The mutability of the buffer being copied from.
/// \param cpy The buffer to copy.
/// \param size The size of the region to copy
/// \param write_offset The offset into this buffer to begin writing at.
/// \param read_offset The offset into \f$cpy\f$ to begin reading from.
template<GLenum OTypeV, GLbitfield OFlagsV, GLboolean OImmutableV>
constexpr void copy(const buffer<OTypeV, OFlagsV, OImmutableV>& cpy, GLsizeiptr size = -1, GLintptr write_offset = 0, GLintptr read_offset = 0) {
void copy(const buffer<OTypeV, OFlagsV, OImmutableV>& cpy, GLsizeiptr size = -1, GLintptr write_offset = 0, GLintptr read_offset = 0) {
write_offset = max(write_offset, GLintptr(0));
read_offset = max(read_offset, GLintptr(0));
size = size < 0 ? _size : size;
@@ -192,8 +463,13 @@ public:
glBindBuffer(COPY_WRITE, NULL);
}
constexpr void read(void* data, GLsizeiptr size, GLintptr offset = 0) const {
static_assert((dynamic or persistent) and not (client or coherent));
///
/// \brief Read data from the buffer.
/// \param data The handle to the client buffer to read into.
/// \param size The size of the region to read.
/// \param offset The offset into the buffer to begin reading from.
void read(void* data, GLsizeiptr size, GLintptr offset = 0) const {
static_assert(dynamic);
offset = max(offset, GLintptr(0));
size = size < 0 ? _size : size;
size = min(size, _size - offset);
@@ -201,8 +477,13 @@ public:
glGetBufferSubData(type, offset, size, data);
}
constexpr void write(const void* data, GLsizeiptr size, GLintptr offset = 0) {
static_assert((dynamic or persistent) and not (client or coherent));
///
/// \brief Write data to the buffer.
/// \param data The handle to the client buffer to write from.
/// \param size The size of the region to write.
/// \param offset The offset into the buffer to begin writing at.
void write(const void* data, GLsizeiptr size, GLintptr offset = 0) {
static_assert(dynamic);
offset = max(offset, GLintptr(0));
size = size < 0 ? _size : size;
size = min(size, _size - offset);
@@ -210,8 +491,13 @@ public:
glBufferSubData(type, offset, size, data);
}
constexpr void flush(GLsizeiptr size = -1, GLintptr offset = 0) {
if (not _mapping) return;
///
/// \brief Flush a range of the buffer.
/// \param size The size of the range.
/// \param offset The offset of the range.
/// \note The buffer must be mapped with the \ref fennec::gl::buffer_map_flags::EXPLICIT_FLUSH "EXPLICIT_FLUSH" flag.
void flush(GLsizeiptr size = -1, GLintptr offset = 0) {
if (not _data) return;
if (not (_mapflags & EXPLICIT_FLUSH)) return;
offset = max(offset, GLintptr(0));
size = size < 0 ? _size : size;
@@ -220,7 +506,7 @@ public:
glFlushMappedBufferRange(type, offset, size);
}
constexpr void invalidate(GLsizeiptr size, GLintptr offset = 0) {
void invalidate(GLsizeiptr size, GLintptr offset = 0) {
offset = max(offset, GLintptr(0));
size = size < 0 ? _size : size;
size = min(size, _size - offset);
@@ -232,14 +518,14 @@ public:
// TYPED FUNCTIONS =====================================================================================================
template<typename TypeT>
constexpr TypeT* map(GLbitfield access, GLsizeiptr n, GLintptr offset = 0) {
TypeT* map(GLbitfield access, GLsizeiptr n, GLintptr offset = 0) {
return static_cast<TypeT*>(map(access, n * sizeof(TypeT), offset * sizeof(TypeT)));
}
private:
GLuint _handle;
GLsizeiptr _size;
void* _mapping;
void* _data;
GLbitfield _mapflags;
};

View File

@@ -16,10 +16,22 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file fennec/renderers/opengl/lib/enum.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_RENDERERS_OPENGL_LIB_ENUM_H
#define FENNEC_RENDERERS_OPENGL_LIB_ENUM_H
#include <fennec/renderers/opengl/lib/fwd.h>
#include <fennec/renderers/opengl/lib/forward.h>
namespace fennec
{
@@ -27,287 +39,343 @@ namespace fennec
namespace gl
{
enum buffer_ : GLenum {
VERTEX = GL_ARRAY_BUFFER,
ELEMENT = GL_ELEMENT_ARRAY_BUFFER,
UNIFORM = GL_UNIFORM_BUFFER,
SHADER_STORAGE = GL_SHADER_STORAGE_BUFFER,
QUERY = GL_QUERY_BUFFER,
TEXTURE = GL_TEXTURE_BUFFER,
TRANSFORM_FEEDBACK = GL_TRANSFORM_FEEDBACK_BUFFER,
ATOMIC_COUNTER = GL_ATOMIC_COUNTER_BUFFER,
PARAMETER = GL_PARAMETER_BUFFER,
INDIRECT_DRAW = GL_DRAW_INDIRECT_BUFFER, INDIRECT_DISPATCH = GL_DISPATCH_INDIRECT_BUFFER,
COPY_READ = GL_COPY_READ_BUFFER, COPY_WRITE = GL_COPY_WRITE_BUFFER,
PIXEL_PACK = GL_PIXEL_PACK_BUFFER, PIXEL_UNPACK = GL_PIXEL_UNPACK_BUFFER,
// Buffer Types ========================================================================================================
///
/// \brief OpenGL Buffer Types
enum buffer_types : GLenum {
VERTEX = GL_ARRAY_BUFFER, //!< Vertex Buffer
ELEMENT = GL_ELEMENT_ARRAY_BUFFER, //!< Element Array Buffer
UNIFORM = GL_UNIFORM_BUFFER, //!< Uniform Buffer
SHADER_STORAGE = GL_SHADER_STORAGE_BUFFER, //!< Shader Storage Buffer
QUERY = GL_QUERY_BUFFER, //!< Query Buffer
BUFFER_TEXTURE = GL_TEXTURE_BUFFER, //!< Texture Buffer
TRANSFORM_FEEDBACK = GL_TRANSFORM_FEEDBACK_BUFFER, //!< Transform Feedback Buffer
ATOMIC_COUNTER = GL_ATOMIC_COUNTER_BUFFER, //!< Atomic Counter Buffer
PARAMETER = GL_PARAMETER_BUFFER, //!< Parameter Buffer
INDIRECT_DRAW = GL_DRAW_INDIRECT_BUFFER, //!< Indirect Draw Buffer
INDIRECT_DISPATCH = GL_DISPATCH_INDIRECT_BUFFER, //!< Indirect Dispatch Buffer
COPY_READ = GL_COPY_READ_BUFFER, //!< Copy Read Buffer
COPY_WRITE = GL_COPY_WRITE_BUFFER, //!< Copy Write Buffer
PIXEL_PACK = GL_PIXEL_PACK_BUFFER, //!< Pixel Pack Buffer
PIXEL_UNPACK = GL_PIXEL_UNPACK_BUFFER, //!< Pixel Unpack Buffer
};
enum buffer_flag_ : GLbitfield {
READ = GL_MAP_READ_BIT,
WRITE = GL_MAP_WRITE_BIT,
DYNAMIC = GL_DYNAMIC_STORAGE_BIT,
PERSISTENT = GL_MAP_PERSISTENT_BIT,
COHERENT = GL_MAP_COHERENT_BIT,
CLIENT = GL_CLIENT_STORAGE_BIT,
EXPLICIT_FLUSH = GL_MAP_FLUSH_EXPLICIT_BIT,
INVALIDATE = GL_MAP_INVALIDATE_BUFFER_BIT,
// Buffer Flags ========================================================================================================
///
/// \brief OpenGL Buffer Flags
enum buffer_map_flags : GLbitfield {
READ = GL_MAP_READ_BIT, //!< Buffer Read Flag
WRITE = GL_MAP_WRITE_BIT, //!< Buffer Write Flag
DYNAMIC = GL_DYNAMIC_STORAGE_BIT, //!< Dynamic Buffer Flag
PERSISTENT = GL_MAP_PERSISTENT_BIT, //!< Persistent Buffer Flag
COHERENT = GL_MAP_COHERENT_BIT, //!< Coherent Buffer Flag
CLIENT = GL_CLIENT_STORAGE_BIT, //!< Client Allocated Buffer Flag
EXPLICIT_FLUSH = GL_MAP_FLUSH_EXPLICIT_BIT, //!< Explicit Flush Flag
INVALIDATE = GL_MAP_INVALIDATE_BUFFER_BIT, //!< Invalidation Flag
};
enum access_ : GLbitfield {
READ_ONLY = GL_READ_ONLY,
WRITE_ONLY = GL_WRITE_ONLY,
READ_WRITE = GL_READ_WRITE,
// Buffer Access =======================================================================================================
///
/// \brief OpenGL Buffer Access
enum buffer_access : GLbitfield {
READ_ONLY = GL_READ_ONLY, //!< Read Only Flag
WRITE_ONLY = GL_WRITE_ONLY, //!< Write Only Flag
READ_WRITE = GL_READ_WRITE, //!< Read & Write Flag
};
enum texture_ : GLenum {
TEX_1D = GL_TEXTURE_1D,
TEX_1D_ARRAY = GL_TEXTURE_1D_ARRAY,
TEX_2D = GL_TEXTURE_2D,
TEX_2D_ARRAY = GL_TEXTURE_2D_ARRAY,
TEX_2D_MS = GL_TEXTURE_2D_MULTISAMPLE,
TEX_2D_MS_ARRAY = GL_TEXTURE_2D_MULTISAMPLE_ARRAY,
TEX_RECT = GL_TEXTURE_RECTANGLE,
// Texture Types =======================================================================================================
TEX_CUBEMAP = GL_TEXTURE_CUBE_MAP,
TEX_CUBEMAP_ARRAY = GL_TEXTURE_CUBE_MAP_ARRAY,
TEX_3D = GL_TEXTURE_3D,
TEX_BUFFER = GL_TEXTURE_BUFFER,
///
/// \brief OpenGL Texture Types
enum texture_types : GLenum {
TEXTURE_1D = GL_TEXTURE_1D, //!< 1D Texture
TEXTURE_1D_ARRAY = GL_TEXTURE_1D_ARRAY, //!< 1D Texture Array
TEXTURE_2D = GL_TEXTURE_2D, //!< 2D Texture
TEXTURE_2D_ARRAY = GL_TEXTURE_2D_ARRAY, //!< 2D Texture Array
TEXTURE_2D_MS = GL_TEXTURE_2D_MULTISAMPLE, //!< 2D Multisampled Texture
TEXTURE_2D_MS_ARRAY = GL_TEXTURE_2D_MULTISAMPLE_ARRAY, //!< 2D Multisampled Texture Array
TEXTURE_RECTANGLE = GL_TEXTURE_RECTANGLE, //!< 2D Texture Rectangle
CUBEMAP = GL_TEXTURE_CUBE_MAP, //!< Cubemap
CUBEMAP_ARRAY = GL_TEXTURE_CUBE_MAP_ARRAY, //!< Cubemap Array
TEXTURE_3D = GL_TEXTURE_3D, //!< 3D Texture
};
enum type_ : GLenum {
BOOL = GL_BOOL,
BVEC2 = GL_BOOL_VEC2,
BVEC3 = GL_BOOL_VEC3,
BVEC4 = GL_BOOL_VEC4,
BYTE = GL_BYTE,
SHORT = GL_SHORT,
INT = GL_INT,
IVEC2 = GL_INT_VEC2,
IVEC3 = GL_INT_VEC3,
IVEC4 = GL_INT_VEC4,
// Built-In Types ======================================================================================================
UBYTE = GL_UNSIGNED_BYTE,
USHORT = GL_UNSIGNED_SHORT,
UINT = GL_UNSIGNED_INT,
UVEC2 = GL_UNSIGNED_INT_VEC2,
UVEC3 = GL_UNSIGNED_INT_VEC3,
UVEC4 = GL_UNSIGNED_INT_VEC4,
///
/// \brief OpenGL Built-In Types
enum types : GLenum {
HALF = GL_HALF_FLOAT,
FLOAT = GL_FLOAT,
VEC2 = GL_FLOAT_VEC2,
VEC3 = GL_FLOAT_VEC3,
VEC4 = GL_FLOAT_VEC4,
DOUBLE = GL_DOUBLE,
DVEC2 = GL_DOUBLE_VEC2,
DVEC3 = GL_DOUBLE_VEC3,
DVEC4 = GL_DOUBLE_VEC4,
// Basic Types ---------------------------------------------------------------------------------------------------------
UBYTE332 = GL_UNSIGNED_BYTE_3_3_2,
UBYTE233R = GL_UNSIGNED_BYTE_2_3_3_REV,
USHORT565 = GL_UNSIGNED_SHORT_5_6_5,
USHORT565R = GL_UNSIGNED_SHORT_5_6_5_REV,
USHORT4444 = GL_UNSIGNED_SHORT_4_4_4_4,
USHORT4444R = GL_UNSIGNED_SHORT_4_4_4_4_REV,
USHORT5551 = GL_UNSIGNED_SHORT_5_5_5_1,
USHORT1555R = GL_UNSIGNED_SHORT_1_5_5_5_REV,
UINT8888 = GL_UNSIGNED_INT_8_8_8_8,
UINT8888R = GL_UNSIGNED_INT_8_8_8_8_REV,
UINTAAA2 = GL_UNSIGNED_INT_10_10_10_2,
UINT2AAAR = GL_UNSIGNED_INT_2_10_10_10_REV,
UINT24_8 = GL_UNSIGNED_INT_24_8,
BOOL = GL_BOOL, //!< Boolean Type
BYTE = GL_BYTE, //!< Byte Type
UBYTE = GL_UNSIGNED_BYTE, //!< Unsigned Byte Type
SHORT = GL_SHORT, //!< Short Type
USHORT = GL_UNSIGNED_SHORT, //!< Unsigned Short Type
INT = GL_INT, //!< Integer Type
UINT = GL_UNSIGNED_INT, //!< Unsigned Integer Type
HALF = GL_HALF_FLOAT, //!< Half Precision Floating Point Type
FLOAT = GL_FLOAT, //!< Floating Point Type
DOUBLE = GL_DOUBLE, //!< Double Precision Floating Point Type
UINTABBFR = GL_UNSIGNED_INT_10F_11F_11F_REV,
UINT5999R = GL_UNSIGNED_INT_5_9_9_9_REV,
FLOAT32UINT24 = GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
SAMPLER_1D = GL_SAMPLER_1D,
SAMPLER_1D_V = GL_SAMPLER_1D_ARRAY,
SHADOW_SAMPLER_1D = GL_SAMPLER_1D_SHADOW,
SHADOW_SAMPLER_1D_V = GL_SAMPLER_1D_ARRAY_SHADOW,
// Vector Types --------------------------------------------------------------------------------------------------------
SAMPLER_2D = GL_SAMPLER_2D,
SAMPLER_2D_V = GL_SAMPLER_2D_ARRAY,
SAMPLER_RECT_2D = GL_SAMPLER_2D_RECT,
SAMPLER_2D_MS = GL_SAMPLER_2D_MULTISAMPLE,
SAMPLER_2D_MS_V = GL_SAMPLER_2D_MULTISAMPLE_ARRAY,
SHADOW_SAMPLER_2D = GL_SAMPLER_2D_SHADOW,
SHADOW_SAMPLER_2D_V = GL_SAMPLER_2D_ARRAY_SHADOW,
SHADOW_SAMPLER_RECT_2D = GL_SAMPLER_2D_RECT_SHADOW,
SAMPLER_CUBEMAP = GL_SAMPLER_CUBE,
SHADOW_SAMPLER_CUBEMAP = GL_SAMPLER_CUBE_SHADOW,
SAMPLER_3D = GL_SAMPLER_3D,
SAMPLER_BUFFER = GL_SAMPLER_BUFFER,
BVEC2 = GL_BOOL_VEC2, //!< 2D Boolean Vector Type
BVEC3 = GL_BOOL_VEC3, //!< 3D Boolean Vector Type
BVEC4 = GL_BOOL_VEC4, //!< 4D Boolean Vector Type
ISAMPLER_1D = GL_INT_SAMPLER_1D,
ISAMPLER_1D_V = GL_INT_SAMPLER_1D_ARRAY,
ISAMPLER_2D = GL_INT_SAMPLER_2D,
ISAMPLER_2D_V = GL_INT_SAMPLER_2D_ARRAY,
ISAMPLER_RECT_2D = GL_INT_SAMPLER_2D_RECT,
ISAMPLER_2D_MS = GL_INT_SAMPLER_2D_MULTISAMPLE,
ISAMPLER_2D_MS_V = GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY,
ISAMPLER_CUBEMAP = GL_INT_SAMPLER_CUBE,
ISAMPLER_3D = GL_INT_SAMPLER_3D,
ISAMPLER_BUFFER = GL_INT_SAMPLER_BUFFER,
IVEC2 = GL_INT_VEC2, //!< 2D Integer Vector Type
IVEC3 = GL_INT_VEC3, //!< 3D Integer Vector Type
IVEC4 = GL_INT_VEC4, //!< 4D Integer Vector Type
USAMPLER_1D = GL_INT_SAMPLER_1D,
USAMPLER_1D_V = GL_INT_SAMPLER_1D_ARRAY,
USAMPLER_2D = GL_INT_SAMPLER_2D,
USAMPLER_2D_V = GL_INT_SAMPLER_2D_ARRAY,
USAMPLER_RECT_2D = GL_INT_SAMPLER_2D_RECT,
USAMPLER_2D_MS = GL_INT_SAMPLER_2D_MULTISAMPLE,
USAMPLER_2D_MS_V = GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY,
USAMPLER_CUBEMAP = GL_INT_SAMPLER_CUBE,
USAMPLER_3D = GL_INT_SAMPLER_3D,
USAMPLER_BUFFER = GL_INT_SAMPLER_BUFFER,
UVEC2 = GL_UNSIGNED_INT_VEC2, //!< 2D Unsigned Integer Vector Type
UVEC3 = GL_UNSIGNED_INT_VEC3, //!< 3D Unsigned Integer Vector Type
UVEC4 = GL_UNSIGNED_INT_VEC4, //!< 4D Unsigned Integer Vector Type
IMAGE_1D = GL_IMAGE_1D,
IMAGE_1D_V = GL_IMAGE_1D_ARRAY,
IMAGE_2D = GL_IMAGE_2D,
IMAGE_2D_V = GL_IMAGE_2D_ARRAY,
IMAGE_RECT_2D = GL_IMAGE_2D_RECT,
IMAGE_2D_MS = GL_IMAGE_2D_MULTISAMPLE,
IMAGE_2D_MS_V = GL_IMAGE_2D_MULTISAMPLE_ARRAY,
IMAGE_CUBEMAP = GL_IMAGE_CUBE,
IMAGE_3D = GL_IMAGE_3D,
IMAGE_BUFFER = GL_IMAGE_BUFFER,
VEC2 = GL_FLOAT_VEC2, //!< 2D Floating Point Vector Type
VEC3 = GL_FLOAT_VEC3, //!< 3D Floating Point Vector Type
VEC4 = GL_FLOAT_VEC4, //!< 4D Floating Point Vector Type
IIMAGE_1D = GL_INT_IMAGE_1D,
IIMAGE_1D_V = GL_INT_IMAGE_1D_ARRAY,
IIMAGE_2D = GL_INT_IMAGE_2D,
IIMAGE_2D_V = GL_INT_IMAGE_2D_ARRAY,
IIMAGE_RECT_2D = GL_INT_IMAGE_2D_RECT,
IIMAGE_2D_MS = GL_INT_IMAGE_2D_MULTISAMPLE,
IIMAGE_2D_MS_V = GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY,
IIMAGE_CUBEMAP = GL_INT_IMAGE_CUBE,
IIMAGE_3D = GL_INT_IMAGE_3D,
IIMAGE_BUFFER = GL_INT_IMAGE_BUFFER,
DVEC2 = GL_DOUBLE_VEC2, //!< 2D Double Precision Floating Point Type
DVEC3 = GL_DOUBLE_VEC3, //!< 3D Double Precision Floating Point Type
DVEC4 = GL_DOUBLE_VEC4, //!< 4D Double Precision Floating Point Type
UIMAGE_1D = GL_UNSIGNED_INT_IMAGE_1D,
UIMAGE_1D_V = GL_UNSIGNED_INT_IMAGE_1D_ARRAY,
UIMAGE_2D = GL_UNSIGNED_INT_IMAGE_2D,
UIMAGE_2D_V = GL_UNSIGNED_INT_IMAGE_2D_ARRAY,
UIMAGE_RECT_2D = GL_UNSIGNED_INT_IMAGE_2D_RECT,
UIMAGE_2D_MS = GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE,
UIMAGE_2D_MS_V = GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY,
UIMAGE_CUBEMAP = GL_UNSIGNED_INT_IMAGE_CUBE,
UIMAGE_3D = GL_UNSIGNED_INT_IMAGE_3D,
UIMAGE_BUFFER = GL_UNSIGNED_INT_IMAGE_BUFFER,
AtomicCounter = GL_UNSIGNED_INT_ATOMIC_COUNTER,
// Packed Types --------------------------------------------------------------------------------------------------------
UBYTE332 = GL_UNSIGNED_BYTE_3_3_2, //!< Packed RGB Type with 3 Red, 3 Green, and 2 Blue bits.
UBYTE233R = GL_UNSIGNED_BYTE_2_3_3_REV, //!< Packed BGR Type with 3 Red, 3 Green, and 2 Blue bits.
USHORT565 = GL_UNSIGNED_SHORT_5_6_5, //!< Packed RGB Type with 5 Red, 6 Green, and 5 Blue bits.
USHORT565R = GL_UNSIGNED_SHORT_5_6_5_REV, //!< Packed BGR Type with 5 Red, 6 Green, and 5 Blue bits.
USHORT4444 = GL_UNSIGNED_SHORT_4_4_4_4, //!< Packed RGBA Type with 4 Red, 4 Green, 4 Blue, and 4 Alpha bits.
USHORT4444R = GL_UNSIGNED_SHORT_4_4_4_4_REV, //!< Packed BGRA Type with 4 Red, 4 Green, 4 Blue, and 4 Alpha bits.
USHORT5551 = GL_UNSIGNED_SHORT_5_5_5_1, //!< Packed RGBA Type with 5 Red, 5 Green, 5 Blue, and 1 Alpha bits.
USHORT1555R = GL_UNSIGNED_SHORT_1_5_5_5_REV, //!< Packed BGRA Type with 5 Red, 5 Green, 5 Blue, and 1 Alpha bits.
UINT8888 = GL_UNSIGNED_INT_8_8_8_8, //!< Packed RGBA Type with 8 Red, 8 Green, 8 Blue, and 8 Alpha bits.
UINT8888R = GL_UNSIGNED_INT_8_8_8_8_REV, //!< Packed BGRA Type with 8 Red, 8 Green, 8 Blue, and 8 Alpha bits.
UINT5999R = GL_UNSIGNED_INT_5_9_9_9_REV, //!< Packed BGRA Type with 9 Red, 9 Green, 9 Blue, and 5 Alpha bits.
UINTAAA2 = GL_UNSIGNED_INT_10_10_10_2, //!< Packed RGBA Type with 10 Red, 10 Green, 10 Blue, and 2 Alpha bits.
UINT2AAAR = GL_UNSIGNED_INT_2_10_10_10_REV, //!< Packed BGRA Type with 10 Red, 10 Green, 10 Blue, and 2 Alpha bits.
UINT24_8 = GL_UNSIGNED_INT_24_8, //!< Packed DS Type with 24 Depth and 8 Stencil bits.
FLOAT32UINT24 = GL_FLOAT_32_UNSIGNED_INT_24_8_REV, //!< Packed DS Type with 32 Depth and 8 Stencil bits.
UINTABBFR = GL_UNSIGNED_INT_10F_11F_11F_REV, //!< Packed ZXY Type with 10 X, 11 Y, and 11 Z bits.
// Samplers Types ------------------------------------------------------------------------------------------------------
SAMPLER_1D = GL_SAMPLER_1D, //!< 1D Texture Sampler
SAMPLER_1D_ARRAY = GL_SAMPLER_1D_ARRAY, //!< 1D Texture Sampler Array
SHADOW_SAMPLER_1D = GL_SAMPLER_1D_SHADOW, //!< 1D Shadow Texture Sampler
SHADOW_SAMPLER_1D_ARRAY = GL_SAMPLER_1D_ARRAY_SHADOW, //!< 1D Shadow Texture Sampler Array
SAMPLER_2D = GL_SAMPLER_2D, //!< 2D Texture Sampler
SAMPLER_2D_ARRAY = GL_SAMPLER_2D_ARRAY, //!< 2D Texture Sampler Array
SAMPLER_RECT_2D = GL_SAMPLER_2D_RECT, //!< 2D Texture Rectangle Sampler
SAMPLER_2D_MS = GL_SAMPLER_2D_MULTISAMPLE, //!< 2D Multi-Sampled Texture Sampler
SAMPLER_2D_MS_ARRAY = GL_SAMPLER_2D_MULTISAMPLE_ARRAY, //!< 2D Multi-Sampled Texture Sampler Array
SHADOW_SAMPLER_2D = GL_SAMPLER_2D_SHADOW, //!< 2D Shadow Texture Sampler
SHADOW_SAMPLER_2D_ARRAY = GL_SAMPLER_2D_ARRAY_SHADOW, //!< 2D Shadow Texture Sampler Array
SHADOW_SAMPLER_RECT_2D = GL_SAMPLER_2D_RECT_SHADOW, //!< 2D Shadow Texture Rectangle Sampler
CUBEMAP_SAMPLER = GL_SAMPLER_CUBE, //!< Cubemap Sampler
CUBEMAP_SAMPLER_ARRAY = GL_SAMPLER_CUBE_MAP_ARRAY, //!< Cubemap Sampler Array
SHADOW_CUBEMAP_SAMPLER = GL_SAMPLER_CUBE_SHADOW, //!< Shadow Cubemap Sampler
SHADOW_CUBEMAP_SAMPLER_ARRAY = GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW, //!< Shadow Cubemap Sampler Array
SAMPLER_3D = GL_SAMPLER_3D, //!< 3D Texture Sampler
BUFFER_SAMPLER = GL_SAMPLER_BUFFER, //!< Buffer Texture Sampler
ISAMPLER_1D = GL_INT_SAMPLER_1D, //!< 1D Integer Texture Sampler
ISAMPLER_1D_ARRAY = GL_INT_SAMPLER_1D_ARRAY, //!< 1D Integer Texture Sampler Array
ISAMPLER_2D = GL_INT_SAMPLER_2D, //!< 2D Integer Texture Sampler
ISAMPLER_2D_ARRAY = GL_INT_SAMPLER_2D_ARRAY, //!< 2D Integer Texture Sampler Array
ISAMPLER_RECT_2D = GL_INT_SAMPLER_2D_RECT, //!< 2D Integer Texture Rectangle Sampler
ISAMPLER_2D_MS = GL_INT_SAMPLER_2D_MULTISAMPLE, //!< 2D Integer Multi-Sampled Texture Sampler
ISAMPLER_2D_MS_ARRAY = GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, //!< 2D Integer Multi-Sampled Texture Sampler Array
ISAMPLER_3D = GL_INT_SAMPLER_3D, //!< 3D Integer Texture Sampler
BUFFER_ISAMPLER = GL_INT_SAMPLER_BUFFER, //!< Integer Buffer Texture Sampler
CUBEMAP_ISAMPLER = GL_INT_SAMPLER_CUBE, //!< Integer Cubemap Sampler
CUBEMAP_ISAMPLER_ARRAY = GL_INT_SAMPLER_CUBE_MAP_ARRAY, //!< Integer Cubemap Sampler Array
USAMPLER_1D = GL_UNSIGNED_INT_SAMPLER_1D, //!< 1D Unsigned Integer Texture Sampler
USAMPLER_1D_ARRAY = GL_UNSIGNED_INT_SAMPLER_1D_ARRAY, //!< 1D Unsigned Integer Texture Sampler Array
USAMPLER_2D = GL_UNSIGNED_INT_SAMPLER_2D, //!< 2D Unsigned Integer Texture Sampler
USAMPLER_2D_ARRAY = GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, //!< 2D Unsigned Integer Texture Sampler Array
USAMPLER_RECT_2D = GL_UNSIGNED_INT_SAMPLER_2D_RECT, //!< 2D Unsigned Integer Texture Rectangle Sampler
USAMPLER_2D_MS = GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, //!< 2D Unsigned Integer Multi-Sampled Texture Sampler
USAMPLER_2D_MS_ARRAY = GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, //!< 2D Unsigned Integer Multi-Sampled Texture Sampler Array
USAMPLER_3D = GL_UNSIGNED_INT_SAMPLER_3D, //!< 3D Unsigned Integer Texture Sampler
BUFFER_USAMPLER = GL_UNSIGNED_INT_SAMPLER_BUFFER, //!< Unsigned Integer Buffer Texture Sampler
CUBEMAP_USAMPLER = GL_UNSIGNED_INT_SAMPLER_CUBE, //!< Unsigned Integer Cubemap Sampler
CUBEMAP_USAMPLER_ARRAY = GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY, //!< Unsigned Integer Cubemap Sampler Array
// Image Types ---------------------------------------------------------------------------------------------------------
IMAGE_1D = GL_IMAGE_1D, //!< 1D Image
IMAGE_1D_ARRAY = GL_IMAGE_1D_ARRAY, //!< 1D Image Array
IMAGE_2D = GL_IMAGE_2D, //!< 2D Image
IMAGE_2D_ARRAY = GL_IMAGE_2D_ARRAY, //!< 2D Image Array
IMAGE_RECT_2D = GL_IMAGE_2D_RECT, //!< 2D Image Rectangle
IMAGE_2D_MS = GL_IMAGE_2D_MULTISAMPLE, //!< 2D Multi-Sampled Image
IMAGE_2D_MS_ARRAY = GL_IMAGE_2D_MULTISAMPLE_ARRAY, //!< 2D Multi-Sampled Image Array
IMAGE_3D = GL_IMAGE_3D, //!< 3D Image
IMAGE_BUFFER = GL_IMAGE_BUFFER, //!< Image Buffer
IMAGE_CUBEMAP = GL_IMAGE_CUBE, //!< Cubemap Image
IMAGE_CUBEMAP_ARRAY = GL_IMAGE_CUBE_MAP_ARRAY, //!< Cubemap Image Array
IIMAGE_1D = GL_INT_IMAGE_1D, //!< 1D Integer Image
IIMAGE_1D_ARRAY = GL_INT_IMAGE_1D_ARRAY, //!< 1D Integer Image Array
IIMAGE_2D = GL_INT_IMAGE_2D, //!< 2D Integer Image
IIMAGE_2D_ARRAY = GL_INT_IMAGE_2D_ARRAY, //!< 2D Integer Image Array
IIMAGE_RECT_2D = GL_INT_IMAGE_2D_RECT, //!< 2D Integer Image Rectangle
IIMAGE_2D_MS = GL_INT_IMAGE_2D_MULTISAMPLE, //!< 2D Multi-Sampled Integer Image
IIMAGE_2D_MS_ARRAY = GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY, //!< 2D Multi-Sampled Integer Image Array
IIMAGE_3D = GL_INT_IMAGE_3D, //!< 3D Integer Image
IIMAGE_BUFFER = GL_INT_IMAGE_BUFFER, //!< Integer Image Buffer
IIMAGE_CUBEMAP = GL_INT_IMAGE_CUBE, //!< Integer Cubemap Image
UIMAGE_1D = GL_UNSIGNED_INT_IMAGE_1D, //!< 1D Unsigned Integer Image
UIMAGE_1D_ARRAY = GL_UNSIGNED_INT_IMAGE_1D_ARRAY, //!< 1D Unsigned Integer Image Array
UIMAGE_2D = GL_UNSIGNED_INT_IMAGE_2D, //!< 2D Unsigned Integer Image
UIMAGE_2D_ARRAY = GL_UNSIGNED_INT_IMAGE_2D_ARRAY, //!< 2D Unsigned Integer Image Array
UIMAGE_RECT_2D = GL_UNSIGNED_INT_IMAGE_2D_RECT, //!< 2D Unsigned Integer Image Rectangle
UIMAGE_2D_MS = GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE, //!< 2D Multi-Sampled Unsigned Integer Image
UIMAGE_2D_MS_ARRAY = GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY, //!< 2D Multi-Sampled Unsigned Integer Image Array
UIMAGE_3D = GL_UNSIGNED_INT_IMAGE_3D, //!< 3D Unsigned Integer Image
UIMAGE_BUFFER = GL_UNSIGNED_INT_IMAGE_BUFFER, //!< Unsigned Integer Image Buffer
UIMAGE_CUBEMAP = GL_UNSIGNED_INT_IMAGE_CUBE, //!< Unsigned Integer Cubemap Image
UINT_ATOMIC_COUNTER = GL_UNSIGNED_INT_ATOMIC_COUNTER, //!< Atomic Counter
};
enum component_ : GLenum {
ZERO = GL_ZERO,
ONE = GL_ONE,
R = GL_RED,
G = GL_GREEN,
B = GL_BLUE,
A = GL_ALPHA,
RGB = GL_RGB,
BGR = GL_BGR,
RGBA = GL_RGBA,
BGRA = GL_BGRA,
RI = GL_RED_INTEGER,
GI = GL_GREEN_INTEGER,
BI = GL_BLUE_INTEGER,
AI = GL_ALPHA_INTEGER,
RGBI = GL_RGB_INTEGER,
BGRI = GL_BGR_INTEGER,
RGBAI = GL_RGBA_INTEGER,
BGRAI = GL_BGRA_INTEGER,
STENCIL = GL_STENCIL_INDEX,
DEPTH = GL_DEPTH_COMPONENT,
DEPTH_STENCIL = GL_DEPTH_STENCIL,
///
/// \brief OpenGL Pixel Components
enum pixel_components : GLenum {
ZERO = GL_ZERO, //!< Interpret as 0
ONE = GL_ONE, //!< Interpret as 1
R = GL_RED, //!< Red Component
G = GL_GREEN, //!< Green Component
B = GL_BLUE, //!< Blue Component
A = GL_ALPHA, //!< Alpha Component
RGB = GL_RGB, //!< Combined Red-Green-Blue
BGR = GL_BGR, //!< Combined Blue-Green-Red
RGBA = GL_RGBA, //!< Combined Red-Green-Blue-Alpha
BGRA = GL_BGRA, //!< Combined Blue-Green-Red-Alpha
R_INT = GL_RED_INTEGER, //!< Integral Red Component
G_INT = GL_GREEN_INTEGER, //!< Integral Green Component
B_INT = GL_BLUE_INTEGER, //!< Integral Blue Component
A_INT = GL_ALPHA_INTEGER_EXT, //!< Integral Alpha Component
RGB_INT = GL_RGB_INTEGER, //!< Combined Red-Green-Blue
BGR_INT = GL_BGR_INTEGER, //!< Combined Blue-Green-Red
RGBA_INT = GL_RGBA_INTEGER, //!< Combined Red-Green-Blue-Alpha
BGRA_INT = GL_BGRA_INTEGER, //!< Combined Blue-Green-Red-Alpha
STENCIL = GL_STENCIL_INDEX, //!< Stencil Component
DEPTH = GL_DEPTH_COMPONENT, //!< Depth Component
DEPTH_STENCIL = GL_DEPTH_STENCIL, //!< Combined Depth-Stencil
};
enum format_ : GLint {
R8 = GL_R8,
R8_SNORM = GL_R8_SNORM,
R16 = GL_R16,
R16_SNORM = GL_R16_SNORM,
///
/// \brief OpenGL Color Formats
/// \note UNORM formats are integers interpreted in the normalized range \f$[0.0, 1.0]\f$
/// \note SNORM formats are integers interpreted in the normalized range \f$[-1.0, 1.0]\f$
enum pixel_formats : GLint {
R8_UNORM = GL_R8, //!< 8-Bit Unsigned Normalized Single Component Color
R8_SNORM = GL_R8_SNORM, //!< 8-Bit Signed Normalized Single Component Color
R16_UNORM = GL_R16, //!< 16-Bit Unsigned Normalized Single Component Color
R16_SNORM = GL_R16_SNORM, //!< 16-Bit Signed Normalized Single Component Color
RG8 = GL_RG8,
RG8_SNORM = GL_RG8_SNORM,
RG16 = GL_RG16,
RG16_SNORM = GL_RG16_SNORM,
RG8_UNORM = GL_RG8, //!< 8-Bit Unsigned Normalized Two Component Color
RG8_SNORM = GL_RG8_SNORM, //!< 8-Bit Signed Normalized Two Component Color
RG16_UNORM = GL_RG16, //!< 16-Bit Unsigned Normalized Two Component Color
RG16_SNORM = GL_RG16_SNORM, //!< 16-Bit Signed Normalized Two Component Color
RGB332 = GL_R3_G3_B2,
RGB4 = GL_RGB4,
RGB5 = GL_RGB5,
RGB8 = GL_RGB8,
RGB8_SNORM = GL_RGB8_SNORM,
RGB10 = GL_RGB10,
RGB12 = GL_RGB12,
RGB16 = GL_RGB16,
RGB16_SNORM = GL_RGB16_SNORM,
RGB4_UNORM = GL_RGB4, //!< 4-Bit Unsigned Normalized Three Component Color
RGB5_UNORM = GL_RGB5, //!< 5-Bit Unsigned Normalized Three Component Color
RGB8_UNORM = GL_RGB8, //!< 8-Bit Unsigned Normalized Three Component Color
RGB8_SNORM = GL_RGB8_SNORM, //!< 8-Bit Signed Normalized Three Component Color
RGB10_UNORM = GL_RGB10, //!< 10-Bit Unsigned Normalized Three Component Color
RGB12_UNORM = GL_RGB12, //!< 12-Bit Unsigned Normalized Three Component Color
RGB16_UNORM = GL_RGB16, //!< 16-Bit Unsigned Normalized Three Component Color
RGB16_SNORM = GL_RGB16_SNORM, //!< 16-Bit Signed Normalized Three Component Color
RGBA2 = GL_RGBA2,
RGBA4 = GL_RGBA4,
RGB5_A1 = GL_RGB5_A1,
RGBA8 = GL_RGBA8,
RGBA8_SNORM = GL_RGBA8_SNORM,
RGB10_A2 = GL_RGB10_A2,
RGB10_A2UI = GL_RGB10_A2UI,
RGBA12 = GL_RGBA12,
RGBA16 = GL_RGBA16,
RGB332_UNORM = GL_R3_G3_B2, //!< Packed 8-Bit Unsigned Normalized Three Component Color
SRGB8 = GL_SRGB8,
SRGBA8 = GL_SRGB8_ALPHA8,
RGBA2_UNORM = GL_RGBA2, //!< 2-Bit Unsigned Normalized Four Component Color
RGBA4_UNORM = GL_RGBA4, //!< 4-Bit Unsigned Normalized Four Component Color
RGBA8_UNORM = GL_RGBA8, //!< 8-Bit Unsigned Normalized Four Component Color
RGBA8_SNORM = GL_RGBA8_SNORM, //!< 8-Bit Unsigned Normalized Four Signed Normalized Component Color
RGBA12_UNORM = GL_RGBA12, //!< 12-Bit Unsigned Normalized Four Component Color
RGBA16_UNORM = GL_RGBA16, //!< 16-Bit Unsigned Normalized Four Component Color
R16F = GL_R16F,
RG16F = GL_RG16F,
RGB16F = GL_RGB16F,
RGBA16F = GL_RGBA16F,
RGB5_A1_UNORM = GL_RGB5_A1, //!< Packed 16-Bit Unsigned Normalized Four Component Color
RGB10_A2_UNORM = GL_RGB10_A2, //!< Packed 32-Bit Unsigned Normalized Four Component Color
R32F = GL_R32F,
RG32F = GL_RG32F,
RGB32F = GL_RGB32F,
RGBA32F = GL_RGBA32F,
SRGB8 = GL_SRGB8, //!< 8-Bit sRGB Color
SRGBA8 = GL_SRGB8_ALPHA8, //!< 8-Bit sRGB Color With Linear Alpha
R8I = GL_R8I,
RG8I = GL_RG8I,
RGB8I = GL_RGB8I,
RGBA8I = GL_RGBA8I,
R16_FLOAT = GL_R16F, //!< 16-Bit Floating-Point Single Component Color
RG16_FLOAT = GL_RG16F, //!< 16-Bit Floating-Point Two Component Color
RGB16_FLOAT = GL_RGB16F, //!< 16-Bit Floating-Point Three Component Color
RGBA16_FLOAT = GL_RGBA16F, //!< 16-Bit Floating-Point Four Component Color
R16I = GL_R16I,
RG16I = GL_RG16I,
RGB16I = GL_RGB16I,
RGBA16I = GL_RGBA16I,
R32_FLOAT = GL_R32F, //!< 32-Bit Floating-Point Single Component Color
RG32_FLOAT = GL_RG32F, //!< 32-Bit Floating-Point Two Component Color
RGB32_FLOAT = GL_RGB32F, //!< 32-Bit Floating-Point Three Component Color
RGBA32_FLOAT = GL_RGBA32F, //!< 32-Bit Floating-Point Four Component Color
R32I = GL_R32I,
RG32I = GL_RG32I,
RGB32I = GL_RGB32I,
RGBA32I = GL_RGBA32I,
R8_INT = GL_R8I, //!< 8-Bit Integral Single Component Color
RG8_INT = GL_RG8I, //!< 8-Bit Integral Two Component Color
RGB8_INT = GL_RGB8I, //!< 8-Bit Integral Three Component Color
RGBA8_INT = GL_RGBA8I, //!< 8-Bit Integral Four Component Color
R8UI = GL_R8UI,
RG8UI = GL_RG8UI,
RGB8UI = GL_RGB8UI,
RGBA8UI = GL_RGBA8UI,
R16_INT = GL_R16I, //!< 16-Bit Integral Single Component Color
RG16_INT = GL_RG16I, //!< 16-Bit Integral Two Component Color
RGB16_INT = GL_RGB16I, //!< 16-Bit Integral Three Component Color
RGBA16_INT = GL_RGBA16I, //!< 16-Bit Integral Four Component Color
R16UI = GL_R16UI,
RG16UI = GL_RG16UI,
RGB16UI = GL_RGB16UI,
RGBA16UI = GL_RGBA16UI,
R32_INT = GL_R32I, //!< 32-Bit Integral Single Component Color
RG32_INT = GL_RG32I, //!< 32-Bit Integral Two Component Color
RGB32_INT = GL_RGB32I, //!< 32-Bit Integral Three Component Color
RGBA32_INT = GL_RGBA32I, //!< 32-Bit Integral Four Component Color
R32UI = GL_R32UI,
RG32UI = GL_RG32UI,
RGB32UI = GL_RGB32UI,
RGBA32UI = GL_RGBA32UI,
R8_UINT = GL_R8UI, //!< 8-Bit Unsigned Integral Single Component Color
RG8_UINT = GL_RG8UI, //!< 8-Bit Unsigned Integral Two Component Color
RGB8_UINT = GL_RGB8UI, //!< 8-Bit Unsigned Integral Three Component Color
RGBA8_UINT = GL_RGBA8UI, //!< 8-Bit Unsigned Integral Four Component Color
RGB_DXT1 = GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
RGBA_DXT1 = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
RGBA_DXT3 = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
RGBA_DXT5 = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
R16_UINT = GL_R16UI, //!< 16-Bit Unsigned Integral Single Component Color
RG16_UINT = GL_RG16UI, //!< 16-Bit Unsigned Integral Two Component Color
RGB16_UINT = GL_RGB16UI, //!< 16-Bit Unsigned Integral Three Component Color
RGBA16_UINT = GL_RGBA16UI, //!< 16-Bit Unsigned Integral Four Component Color
RGB10_A2_UINT = GL_RGB10_A2UI, //!< Packed 32-Bit Unsigned Integral Four Component Color
SRGB_DXT1 = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT,
SRGBA_DXT1 = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
SRGBA_DXT3 = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,
SRGBA_DXT5 = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,
R32UI = GL_R32UI, //!< 32-Bit Unsigned Integral Single Component Color
RG32UI = GL_RG32UI, //!< 32-Bit Unsigned Integral Two Component Color
RGB32UI = GL_RGB32UI, //!< 32-Bit Unsigned Integral Three Component Color
RGBA32UI = GL_RGBA32UI, //!< 32-Bit Unsigned Integral Four Component Color
RGB_DXT1 = GL_COMPRESSED_RGB_S3TC_DXT1_EXT, //!< Compressed RGB DXT1 Color
RGBA_DXT1 = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, //!< Compressed RGBA DXT1 Color
RGBA_DXT3 = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, //!< Compressed RGBA DXT3 Color
RGBA_DXT5 = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, //!< Compressed RGBA DXT5 Color
SRGB_DXT1 = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, //!< Compressed sRGB DXT1 Color
SRGBA_DXT1 = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, //!< Compressed sRGBA DXT1 Color
SRGBA_DXT3 = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, //!< Compressed sRGBA DXT3 Color
SRGBA_DXT5 = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, //!< Compressed sRGBA DXT5 Color
};
}

View File

@@ -16,8 +16,20 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_RENDERERS_OPENGL_LIB_FWD_H
#define FENNEC_RENDERERS_OPENGL_LIB_FWD_H
///
/// \file fennec/renderers/opengl/lib/forward.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_RENDERERS_OPENGL_LIB_FORWARD_H
#define FENNEC_RENDERERS_OPENGL_LIB_FORWARD_H
#include <fennec/platform/opengl/glad/gl.h>
@@ -35,4 +47,4 @@ template<GLenum TypeV, GLint FormatV, GLboolean ImmutableV> class texture;
}
#endif // FENNEC_RENDERERS_OPENGL_LIB_FWD_H
#endif // FENNEC_RENDERERS_OPENGL_LIB_FORWARD_H

View File

@@ -16,6 +16,18 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file fennec/renderers/opengl/lib/texture.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_RENDERERS_OPENGL_LIB_TEXTURE_H
#define FENNEC_RENDERERS_OPENGL_LIB_TEXTURE_H
@@ -56,23 +68,23 @@ namespace fennec
namespace gl
{
template<GLint FormatV, GLboolean ImmutableV> using texture1d = texture<TEX_1D, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using texture1d_array = texture<TEX_1D_ARRAY, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using texture2d = texture<TEX_2D, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using texture2d_array = texture<TEX_2D_ARRAY, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using texture_rect = texture<TEX_RECT, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using texture2d_ms = texture<TEX_2D_MS, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using texture2d_ms_array = texture<TEX_2D_MS_ARRAY, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using cubemap = texture<TEX_CUBEMAP, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using cubemap_array = texture<TEX_CUBEMAP_ARRAY, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using texture3d = texture<TEX_3D, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using buffer_texture = texture<TEX_BUFFER, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using texture1d = texture<TEXTURE_1D, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using texture1d_array = texture<TEXTURE_1D_ARRAY, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using texture2d = texture<TEXTURE_2D, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using texture2d_array = texture<TEXTURE_2D_ARRAY, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using texture_rect = texture<TEXTURE_RECTANGLE, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using texture2d_ms = texture<TEXTURE_2D_MS, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using texture2d_ms_array = texture<TEXTURE_2D_MS_ARRAY, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using cubemap = texture<CUBEMAP, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using cubemap_array = texture<CUBEMAP_ARRAY, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using texture3d = texture<TEXTURE_3D, FormatV, ImmutableV>;
template<GLint FormatV, GLboolean ImmutableV> using buffer_texture = texture<BUFFER_TEXTURE, FormatV, ImmutableV>;
///
/// \brief Wrapper for OpenGL Texture Objects
/// \tparam TypeV The type of the texture
/// \tparam FormatV The internal format of the texels
/// \tparam ImmutableV Whether the texture is immutable, i.e. cannot be resized after creation
/// \tparam FormatV The internal pixel format
/// \tparam ImmutableV Mutability
///
/// \details Immutable textures require EXT_texture_storage or ARB_texture_storage
/// Immutable multisample textures require ARB_texture_storage_multisample of OES_texture_storage_multisample_2d_array
@@ -85,14 +97,14 @@ public:
static constexpr GLenum type = TypeV;
static constexpr GLint format = FormatV;
static constexpr GLboolean immutable = ImmutableV;
static constexpr GLboolean is_rect = type == TEX_RECT;
static constexpr GLboolean is_buffered = type == TEX_BUFFER;
static constexpr GLboolean sampled = type == TEX_2D_MS or type == TEX_2D_MS_ARRAY;
static constexpr GLboolean cubemap = type == TEX_CUBEMAP or type == TEX_CUBEMAP_ARRAY;
static constexpr GLboolean is_1d = type == TEX_1D or type == TEX_1D_ARRAY;
static constexpr GLboolean is_2d = sampled or is_rect or type == TEX_2D or type == TEX_2D_ARRAY or cubemap;
static constexpr GLboolean is_array = TypeV == TEX_1D_ARRAY or TypeV == TEX_2D_ARRAY or type == TEX_2D_MS_ARRAY or type == TEX_CUBEMAP_ARRAY;
static constexpr GLboolean is_3d = TypeV == TEX_3D;
static constexpr GLboolean is_rect = type == TEXTURE_RECTANGLE;
static constexpr GLboolean is_buffered = type == BUFFER_TEXTURE;
static constexpr GLboolean sampled = type == TEXTURE_2D_MS or type == TEXTURE_2D_MS_ARRAY;
static constexpr GLboolean cubemap = type == CUBEMAP or type == CUBEMAP_ARRAY;
static constexpr GLboolean is_1d = type == TEXTURE_1D or type == TEXTURE_1D_ARRAY;
static constexpr GLboolean is_2d = sampled or is_rect or type == TEXTURE_2D or type == TEXTURE_2D_ARRAY or cubemap;
static constexpr GLboolean is_array = type == TEXTURE_1D_ARRAY or type == TEXTURE_2D_ARRAY or type == TEXTURE_2D_MS_ARRAY or type == CUBEMAP_ARRAY;
static constexpr GLboolean is_3d = type == TEXTURE_3D;
static constexpr GLboolean has_mipmaps = not(sampled or is_rect or is_buffered);
static constexpr GLboolean use_1d = is_1d and not is_array;
@@ -290,17 +302,13 @@ public:
// Basic Functions =====================================================================================================
void start() {
void use() {
glBindTexture(type, _handle);
}
void end() {
glBindTexture(type, NULL);
}
void bind(GLint i) {
glActiveTexture(GL_TEXTURE0 + i);
start();
use();
}
void genmips() {

View File

@@ -16,6 +16,18 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file fennec/renderers/opengl/lib/vertex_array.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_RENDERERS_OPENGL_LIB_VERTEX_ARRAY_H
#define FENNEC_RENDERERS_OPENGL_LIB_VERTEX_ARRAY_H
@@ -39,14 +51,10 @@ public:
glDeleteVertexArrays(1, &_handle);
}
constexpr void start() const {
constexpr void use() const {
glBindVertexArray(_handle);
}
constexpr void end() const {
glBindVertexArray(NULL);
}
constexpr void set_attribute(GLuint i, GLenum type, GLint n, GLintptr offset, GLboolean normalized = false) {
glVertexAttribFormat(i, n, type, normalized, offset);
glEnableVertexAttribArray(i);

View File

@@ -46,6 +46,10 @@ struct app_info : private VkApplicationInfo {
// Constructors & Destructor ===========================================================================================
public:
/// \name Constructors & Destructor
/// @{
///
/// \brief Create a Vulkan application information structure
/// \param app_name the name of the application, this cstring must exist for the lifetime of this object
@@ -86,37 +90,58 @@ public:
/// \brief Destructor
~app_info() noexcept = default;
/// @}
// Assignment Operators ================================================================================================
public:
/// \name Assignment Operators
/// @{
///
/// \brief Copy Assignment
app_info& operator=(const app_info&) noexcept = default;
/// \param info The app_info object to move
/// \returns A reference to self
app_info& operator=(const app_info& info) noexcept = default;
///
/// \brief Move Assignment
app_info& operator=(app_info&&) noexcept = default;
/// \param info The app_info object to move
/// \returns A reference to self
app_info& operator=(app_info&& info) noexcept = default;
/// @}
// Implicit Conversions ================================================================================================
public:
/// \name Implicit Conversions
/// @{
///
/// \returns \f$this\f$ as if it were a pointer to the underlying type, \f$VkApplicationInfo\f$.
operator VkApplicationInfo*() noexcept {
return this;
}
///
/// \brief Implicit Pointer Conversion
/// \returns \f$this\f$ as if it were a pointer to the underlying type, \f$VkApplicationInfo\f$.
operator const VkApplicationInfo*() const noexcept {
return this;
}
/// @}
// Properties ==========================================================================================================
public:
/// \name Properties
/// @{
///
/// \returns A cstring containing the application name
cstring get_app_name() const {
@@ -202,8 +227,10 @@ public:
pNext = nullptr;
}
/// @}
// Private Members =====================================================================================================
// Private Member Variables ============================================================================================
private:
};

View File

@@ -32,7 +32,7 @@
#ifndef FENNEC_PLATFORM_VULKAN_VKCONTEXT_H
#define FENNEC_PLATFORM_VULKAN_VKCONTEXT_H
#include <fennec/platform/interface/fwd.h>
#include <fennec/platform/interface/forward.h>
#include <fennec/renderers/interface/gfxcontext.h>
namespace fennec

View File

@@ -18,14 +18,8 @@
#ifndef FENNEC_RTTI_DETAIL_THIS_T_H
#define FENNEC_RTTI_DETAIL_THIS_T_H
#include <fennec/lang/type_transforms.h>
#define FENNEC_DEFINE_THIS_T \
private: \
struct _this_t_tag {}; \
constexpr auto _this_t_helper() -> decltype(fennec::detail::_this::writer<_this_t_tag, decltype(this)>{}, void()) {} \
public: \
using this_t = fennec::detail::_this::read<_this_t_tag>
#include <fennec/lang/type_transforms.h>
namespace fennec::detail
{

View File

@@ -36,8 +36,12 @@
#include <fennec/rtti/type.h>
#include <fennec/rtti/typelist.h>
#include <fennec/rtti/detail/_this_t.h>
#include <fennec/rtti/this_t.h>
///
/// \brief Enable the class of the current scope for Run-Time Type Information
///
/// \details Any base classes that need to be reflected on should be included as parameters.
#define FENNEC_RTTI_CLASS_ENABLE(...) \
public: \
/*! \name RTTI */ \
@@ -47,7 +51,6 @@ public: \
using super_class_list = fennec::typelist<__VA_ARGS__>; \
/*! \brief Getter for the object type */ \
virtual inline fennec::type get_type() const { return fennec::type::get_from_instance(this); } \
/*! \brief Definition of \f$this\_t\f$, used for RTTI */ \
FENNEC_DEFINE_THIS_T; \
/*! @} */ \
private: \

View File

@@ -0,0 +1,47 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file this_t.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_RTTI_THIS_T_H
#define FENNEC_RTTI_THIS_T_H
#include <fennec/rtti/detail/_this_t.h>
///
/// \brief Deduces the type of the current class / struct scope and aliases it as \f$this\_t\f$.
#define FENNEC_DEFINE_THIS_T \
private: \
struct _this_t_tag {}; \
constexpr auto _this_t_helper() -> decltype(fennec::detail::_this::writer<_this_t_tag, decltype(this)>{}, void()) {} \
public: \
/*! \brief Definition of \f$this\_t\f$, used for RTTI */ \
using this_t = fennec::detail::_this::read<_this_t_tag>
#endif // FENNEC_RTTI_THIS_T_H

View File

@@ -31,7 +31,7 @@ namespace fennec
class component {
public:
// MEMBERS =============================================================================================================
// Public Member Variables =============================================================================================
public:
///
/// \brief reference to the

View File

@@ -165,7 +165,7 @@ public:
return _global;
}
// Fields ==============================================================================================================
// Private Member Variables ============================================================================================
private:
bool _mobility;
vec2 _position;
@@ -175,7 +175,7 @@ private:
mat3 _local, _global;
// Helpers =============================================================================================================
// Private Helpers =====================================================================================================
constexpr void _recalculate(const mat3& parent) {
_local = fennec::rotation(_rotation);

View File

@@ -42,7 +42,7 @@ namespace fennec
struct scene_node {
// Public Members ======================================================================================================
// Public Member Variables =============================================================================================
public:
scene* const scene;
const size_t id;

View File

@@ -269,7 +269,7 @@ public:
///
/// \brief String Equality
/// \param str the string to compare against
/// \returns True if all characters are equal, false otherwise
/// \returns \f$true\f$ if all characters are equal, \f$false\f$ otherwise
template<size_t n>
constexpr bool operator==(const char (&str)[n]) const {
return compare(cstring(str)) == 0;
@@ -278,11 +278,18 @@ public:
///
/// \brief String Equality
/// \param str the string to compare against
/// \returns True if all characters are equal, false otherwise
/// \returns \f$true\f$ if all characters are equal, \f$false\f$ otherwise
constexpr bool operator==(const cstring& str) const {
return compare(str) == 0;
}
///
/// \brief nullptr Equality
/// \returns \f$true\f$ if there is no held string, \f$false\f$ otherwise.
constexpr bool operator==(nullptr_t) const {
return _cstr == nullptr;
}
///
/// \brief Finds the index of the first occurrence of \f$c\f$ in the string
/// \param c the character to find

View File

@@ -42,7 +42,11 @@ using string = _string<>;
template<typename AllocT>
struct _string
{
// Definitions =========================================================================================================
public:
static constexpr size_t npos = -1; //!< null position
using char_t = char; //!< the character type
using alloc_t = allocation<char, AllocT>; //!< the allocator type
@@ -61,7 +65,7 @@ public:
/// \param n the number of characters
/// \param c the character to fill with
///
/// \details adds additional character for null termination.
/// \details Adds additional character for null termination.
constexpr _string(size_t n, char c = '\0')
: _str(n + 1) {
fennec::memset(_str, c, n);
@@ -80,7 +84,7 @@ public:
/// \param c the character to fill with
/// \param alloc The allocator to use
///
/// \details adds additional character for null termination.
/// \details Adds additional character for null termination.
constexpr _string(size_t n, char c, const alloc_t& alloc)
: _str(n + 1, alloc) {
fennec::memset(_str, c, n);
@@ -149,7 +153,7 @@ public:
/// \param cstr The C-Style string to assign.
/// \returns A reference to self
constexpr _string& operator=(const cstring& cstr) {
_str.callocate(cstr.capacity());
_str.allocate(cstr.capacity());
fennec::memcpy(_str, cstr, cstr.capacity());
return *this;
}
@@ -404,7 +408,7 @@ public:
}
n = fennec::min(n, size() - i);
_string res;
res._str.callocate(n + 1);
res._str.allocate(n + 1);
fennec::memcpy(res.data(), _str + i, n);
return res;
}
@@ -418,7 +422,7 @@ public:
/// \brief Resizes the underlying allocation to hold \f$n\f$ characters and a null terminator.
/// \param n The new size of the string
constexpr void resize(size_t n) {
_str.creallocate(n + 1);
_str.reallocate(n + 1);
_str[size()] = '\0';
}
@@ -431,7 +435,7 @@ public:
return _string(1, c);
}
_string res;
res._str.callocate(capacity() + 1);
res._str.allocate(capacity() + 1);
fennec::memcpy(res.data(), _str, size());
res[size()] = c;
return res;
@@ -456,7 +460,7 @@ public:
return _string(cstr);
}
_string res;
res._str.callocate(size() + cstr.size() + 1);
res._str.allocate(size() + cstr.size() + 1);
fennec::memcpy(res.data(), _str, size());
fennec::memcpy(res.data() + size(), cstr, cstr.size());
return res;
@@ -474,7 +478,7 @@ public:
return _string(*this);
}
_string res;
res._str.callocate(size() + str.size() + 1);
res._str.allocate(size() + str.size() + 1);
fennec::memcpy(res.data(), _str, size());
fennec::memcpy(res.data() + size(), str.data(), str.size());
return res;
@@ -486,11 +490,11 @@ public:
/// \returns \f$this\f$ string containing an additional character \f$c\f$.
constexpr _string& operator+=(char c) {
if (_str == nullptr) {
_str.callocate(2);
_str.allocate(2);
_str[0] = c;
return *this;
}
_str.creallocate(capacity() + 1);
_str.reallocate(capacity() + 1);
_str[size() - 1] = c;
return *this;
}
@@ -503,7 +507,7 @@ public:
return *this = cstr;
}
size_t middle = size();
_str.creallocate(middle + cstr.size() + 1);
_str.reallocate(middle + cstr.size() + 1);
fennec::memcpy(_str + middle, cstr, cstr.size());
return *this;
}
@@ -520,7 +524,7 @@ public:
return *this;
}
size_t middle = size();
_str.creallocate(middle + str.size() + 1);
_str.reallocate(middle + str.size() + 1);
fennec::memcpy(_str + middle, str.data(), str.size());
return *this;
}

View File

@@ -266,6 +266,13 @@ public:
return compare(str) == 0;
}
///
/// \brief nullptr Equality
/// \returns \f$true\f$ if there is no held string, \f$false\f$ otherwise.
constexpr bool operator==(nullptr_t) const {
return _cstr == nullptr;
}
///
/// \brief Finds the index of the first occurrence of \f$c\f$ in the string
/// \param c the character to find

View File

@@ -142,7 +142,7 @@ public:
/// \param cstr The C-Style string to assign.
/// \returns A reference to self
constexpr _wstring& operator=(const wcstring& cstr) {
_str.callocate(cstr.capacity());
_str.allocate(cstr.capacity());
fennec::memcpy(_str, cstr, cstr.capacity());
return *this;
}
@@ -397,7 +397,7 @@ public:
}
n = fennec::min(n, size() - i);
_wstring res;
res._str.callocate(n + 1);
res._str.allocate(n + 1);
fennec::wmemcpy(res.data(), _str + i, n);
return res;
}
@@ -411,7 +411,7 @@ public:
/// \brief Resizes the underlying allocation to hold \f$n\f$ characters and a null terminator.
/// \param n The new size of the string
constexpr void resize(size_t n) {
_str.creallocate(n + 1);
_str.reallocate(n + 1);
_str[size()] = '\0';
}
@@ -424,7 +424,7 @@ public:
return _wstring(1, c);
}
_wstring res;
res._str.callocate(capacity() + 1);
res._str.allocate(capacity() + 1);
fennec::wmemcpy(res.data(), _str, size());
res[size()] = c;
return res;
@@ -447,7 +447,7 @@ public:
return _wstring(cstr);
}
_wstring res;
res._str.callocate(size() + cstr.size() + 1);
res._str.allocate(size() + cstr.size() + 1);
fennec::wmemcpy(res.data(), _str, size());
fennec::wmemcpy(res.data() + size(), cstr, cstr.size());
return res;
@@ -465,7 +465,7 @@ public:
return _wstring(*this);
}
_wstring res;
res._str.callocate(size() + str.size() + 1);
res._str.allocate(size() + str.size() + 1);
fennec::wmemcpy(res.data(), _str, size());
fennec::wmemcpy(res.data() + size(), str.data(), str.size());
return res;
@@ -477,11 +477,11 @@ public:
/// \returns \f$this\f$ string containing an additional character \f$c\f$.
constexpr _wstring& operator+=(wchar_t c) {
if (_str == nullptr) {
_str.callocate(2);
_str.allocate(2);
_str[0] = c;
return *this;
}
_str.creallocate(capacity() + 1);
_str.reallocate(capacity() + 1);
_str[size() - 1] = c;
return *this;
}
@@ -494,7 +494,7 @@ public:
return *this = cstr;
}
size_t middle = size();
_str.creallocate(middle + cstr.size() + 1);
_str.reallocate(middle + cstr.size() + 1);
fennec::wmemcpy(_str + middle, cstr, cstr.size());
return *this;
}
@@ -511,7 +511,7 @@ public:
return *this;
}
size_t middle = size();
_str.creallocate(middle + str.size() + 1);
_str.reallocate(middle + str.size() + 1);
fennec::wmemcpy(_str + middle, str.data(), str.size());
return *this;
}

View File

@@ -26,165 +26,268 @@ inline void float_h()
{
std::ofstream out("fennec/lang/float.h");
out << "// =====================================================================================================================" << std::endl;
out << "// fennec, a free and open source game engine" << std::endl;
out << "// Copyright © 2025 - 2026 Medusa Slockbower" << std::endl;
out << "//" << std::endl;
out << "// This program is free software: you can redistribute it and/or modify" << std::endl;
out << "// it under the terms of the GNU General Public License as published by" << std::endl;
out << "// the Free Software Foundation, either version 3 of the License, or" << std::endl;
out << "// (at your option) any later version." << std::endl;
out << "//" << std::endl;
out << "// This program is distributed in the hope that it will be useful," << std::endl;
out << "// but WITHOUT ANY WARRANTY; without even the implied warranty of" << std::endl;
out << "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" << std::endl;
out << "// GNU General Public License for more details." << std::endl;
out << "//" << std::endl;
out << "// You should have received a copy of the GNU General Public License" << std::endl;
out << "// along with this program. If not, see <https://www.gnu.org/licenses/>." << std::endl;
out << "// =====================================================================================================================" << std::endl;
out << "// =====================================================================================================================" << '\n';
out << "// fennec, a free and open source game engine" << '\n';
out << "// Copyright © 2025 - 2026 Medusa Slockbower" << '\n';
out << "//" << '\n';
out << "// This program is free software: you can redistribute it and/or modify" << '\n';
out << "// it under the terms of the GNU General Public License as published by" << '\n';
out << "// the Free Software Foundation, either version 3 of the License, or" << '\n';
out << "// (at your option) any later version." << '\n';
out << "//" << '\n';
out << "// This program is distributed in the hope that it will be useful," << '\n';
out << "// but WITHOUT ANY WARRANTY; without even the implied warranty of" << '\n';
out << "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" << '\n';
out << "// GNU General Public License for more details." << '\n';
out << "//" << '\n';
out << "// You should have received a copy of the GNU General Public License" << '\n';
out << "// along with this program. If not, see <https://www.gnu.org/licenses/>." << '\n';
out << "// =====================================================================================================================" << '\n';
out << "" << std::endl;
out << "" << '\n';
out << "///" << std::endl;
out << "/// \\file fennec/lang/float.h" << std::endl;
out << "/// \\brief metaprogramming floating point type info" << std::endl;
out << "///" << std::endl;
out << "///" << std::endl;
out << "/// \\details this file is automatically generated for the current build environment" << std::endl;
out << "///" << std::endl;
out << "/// \\copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))" << std::endl;
out << "///" << std::endl;
out << "///" << std::endl;
out << "///" << '\n';
out << "/// \\file fennec/lang/float.h" << '\n';
out << "/// \\brief metaprogramming floating point type info" << '\n';
out << "///" << '\n';
out << "///" << '\n';
out << "/// \\details This file is automatically generated for the current build environment." << '\n';
out << "///" << '\n';
out << "/// Environment for this build: " FENNEC_LONG_COMPILER_NAME << '\n';
out << "///" << '\n';
out << "/// \\copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))" << '\n';
out << "///" << '\n';
out << "///" << '\n';
out << "" << std::endl;
out << "" << '\n';
out << "#ifndef FENNEC_LANG_FLOAT_H" << std::endl;
out << "#define FENNEC_LANG_FLOAT_H" << std::endl;
out << "#ifndef FENNEC_LANG_FLOAT_H" << '\n';
out << "#define FENNEC_LANG_FLOAT_H" << '\n';
out << "" << std::endl;
out << "" << '\n';
out << "#include <fennec/lang/bits.h>" << std::endl;
out << "#include <fennec/lang/bits.h>" << '\n';
out << "" << std::endl;
out << "" << '\n';
// MAYBE TODO: Generate info without C++ STDLIB to compile natively on platforms without support
out << "#undef FLT_HAS_INFINITY" << std::endl;
out << "#undef FLT_HAS_QUIET_NAN" << std::endl;
out << "#undef FLT_HAS_SIGNALING_NAN" << std::endl;
out << "#undef FLT_HAS_DENORM" << std::endl;
out << "#undef FLT_HAS_DENORM_LOSS" << std::endl;
out << "#undef FLT_ROUNDS" << std::endl;
out << "#undef FLT_IS_IEC559" << std::endl;
out << "#undef FLT_MANT_DIG" << std::endl;
out << "#undef FLT_DIG" << std::endl;
out << "#undef FLT_DECIMAL_DIG" << std::endl;
out << "#undef FLT_RADIX" << std::endl;
out << "#undef FLT_MIN_EXP" << std::endl;
out << "#undef FLT_MAX_EXP" << std::endl;
out << "#undef FLT_MIN_10_EXP" << std::endl;
out << "#undef FLT_MAX_10_EXP" << std::endl;
out << "#undef FLT_TRAPS" << std::endl;
out << "#undef FLT_TINYNESS_BEFORE" << std::endl;
out << "#undef FLT_MIN" << std::endl;
out << "#undef FLT_MAX" << std::endl;
out << "#undef FLT_EPSILON" << std::endl;
out << "#undef FLT_INF" << std::endl;
out << "#undef FLT_QUIET_NAN" << std::endl;
out << "#undef FLT_SIGNALING_NAN" << std::endl;
out << "#undef FLT_DENORM_MIN" << std::endl;
out << "#undef FLT_ROUND_ERR" << std::endl;
out << "#undef FLT_HAS_INFINITY" << '\n';
out << "#undef FLT_HAS_QUIET_NAN" << '\n';
out << "#undef FLT_HAS_SIGNALING_NAN" << '\n';
out << "#undef FLT_HAS_DENORM" << '\n';
out << "#undef FLT_HAS_DENORM_LOSS" << '\n';
out << "#undef FLT_ROUNDS" << '\n';
out << "#undef FLT_IS_IEC559" << '\n';
out << "#undef FLT_MANT_DIG" << '\n';
out << "#undef FLT_DIG" << '\n';
out << "#undef FLT_DECIMAL_DIG" << '\n';
out << "#undef FLT_RADIX" << '\n';
out << "#undef FLT_MIN_EXP" << '\n';
out << "#undef FLT_MAX_EXP" << '\n';
out << "#undef FLT_MIN_10_EXP" << '\n';
out << "#undef FLT_MAX_10_EXP" << '\n';
out << "#undef FLT_TRAPS" << '\n';
out << "#undef FLT_TINYNESS_BEFORE" << '\n';
out << "#undef FLT_MIN" << '\n';
out << "#undef FLT_MAX" << '\n';
out << "#undef FLT_EPSILON" << '\n';
out << "#undef FLT_INF" << '\n';
out << "#undef FLT_QUIET_NAN" << '\n';
out << "#undef FLT_SIGNALING_NAN" << '\n';
out << "#undef FLT_DENORM_MIN" << '\n';
out << "#undef FLT_ROUND_ERR" << '\n';
out << "" << std::endl;
out << "#define FLT_HAS_INFINITY " << std::dec << std::numeric_limits<float>::has_infinity << std::endl;
out << "#define FLT_HAS_QUIET_NAN " << std::dec << std::numeric_limits<float>::has_quiet_NaN << std::endl;
out << "#define FLT_HAS_SIGNALING_NAN " << std::dec << std::numeric_limits<float>::has_signaling_NaN << std::endl;
out << "#define FLT_HAS_DENORM " << std::dec << std::numeric_limits<float>::has_denorm << std::endl;
out << "#define FLT_HAS_DENORM_LOSS " << std::dec << std::numeric_limits<float>::has_denorm_loss << std::endl;
out << "#define FLT_ROUNDS " << std::dec << std::numeric_limits<float>::round_style << std::endl;
out << "#define FLT_IS_IEC559 " << std::dec << std::numeric_limits<float>::is_iec559 << std::endl;
out << "#define FLT_MANT_DIG " << std::dec << std::numeric_limits<float>::digits << std::endl;
out << "#define FLT_DIG " << std::dec << std::numeric_limits<float>::digits10 << std::endl;
out << "#define FLT_DECIMAL_DIG " << std::dec << std::numeric_limits<float>::max_digits10 << std::endl;
out << "#define FLT_RADIX " << std::dec << std::numeric_limits<float>::radix << std::endl;
out << "#define FLT_MIN_EXP " << std::dec << std::numeric_limits<float>::min_exponent << std::endl;
out << "#define FLT_MAX_EXP " << std::dec << std::numeric_limits<float>::max_exponent << std::endl;
out << "#define FLT_MIN_10_EXP " << std::dec << std::numeric_limits<float>::min_exponent10 << std::endl;
out << "#define FLT_MAX_10_EXP " << std::dec << std::numeric_limits<float>::max_exponent10 << std::endl;
out << "#define FLT_TRAPS " << std::dec << std::numeric_limits<float>::traps << std::endl;
out << "#define FLT_TINYNESS_BEFORE " << std::dec << std::numeric_limits<float>::tinyness_before << std::endl;
out << "" << '\n';
out << "#define FLT_MIN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::min() ) << ")" << std::endl;
out << "#define FLT_MAX " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::max() ) << ")" << std::endl;
out << "#define FLT_EPSILON " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::epsilon() ) << ")" << std::endl;
out << "#define FLT_INF " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::infinity() ) << ")" << std::endl;
out << "#define FLT_QUIET_NAN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::quiet_NaN() ) << ")" << std::endl;
out << "#define FLT_SIGNALING_NAN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::signaling_NaN()) << ")" << std::endl;
out << "#define FLT_DENORM_MIN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::denorm_min() ) << ")" << std::endl;
out << "#define FLT_ROUND_ERR " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::round_error() ) << ")" << std::endl;
out << "" << std::endl;
out << R"(/// \brief Does \f$float\f$ have an infinity?)" << '\n';
out << "#define FLT_HAS_INFINITY " << std::dec << std::numeric_limits<float>::has_infinity << '\n';
out << "#undef DBL_HAS_INFINITY" << std::endl;
out << "#undef DBL_HAS_QUIET_NAN" << std::endl;
out << "#undef DBL_HAS_SIGNALING_NAN" << std::endl;
out << "#undef DBL_HAS_DENORM" << std::endl;
out << "#undef DBL_HAS_DENORM_LOSS" << std::endl;
out << "#undef DBL_ROUNDS" << std::endl;
out << "#undef DBL_IS_IEC559" << std::endl;
out << "#undef DBL_MANT_DIG" << std::endl;
out << "#undef DBL_DIG" << std::endl;
out << "#undef DBL_DECIMAL_DIG" << std::endl;
out << "#undef DBL_RADIX" << std::endl;
out << "#undef DBL_MIN_EXP" << std::endl;
out << "#undef DBL_MAX_EXP" << std::endl;
out << "#undef DBL_MIN_10_EXP" << std::endl;
out << "#undef DBL_MAX_10_EXP" << std::endl;
out << "#undef DBL_TRAPS" << std::endl;
out << "#undef DBL_TINYNESS_BEFORE" << std::endl;
out << "#undef DBL_MIN" << std::endl;
out << "#undef DBL_MAX" << std::endl;
out << "#undef DBL_EPSILON" << std::endl;
out << "#undef DBL_INF" << std::endl;
out << "#undef DBL_QUIET_NAN" << std::endl;
out << "#undef DBL_SIGNALING_NAN" << std::endl;
out << "#undef DBL_DENORM_MIN" << std::endl;
out << "#undef DBL_ROUND_ERR" << std::endl;
out << R"(/// \brief Does \f$float\f$ have a quiet NaN?)" << '\n';
out << "#define FLT_HAS_QUIET_NAN " << std::dec << std::numeric_limits<float>::has_quiet_NaN << '\n';
out << "" << std::endl;
out << R"(/// \brief Does \f$float\f$ have a signaling NaN?)" << '\n';
out << "#define FLT_HAS_SIGNALING_NAN " << std::dec << std::numeric_limits<float>::has_signaling_NaN << '\n';
out << "#define DBL_HAS_INFINITY " << std::dec << std::numeric_limits<double>::has_infinity << std::endl;
out << "#define DBL_HAS_QUIET_NAN " << std::dec << std::numeric_limits<double>::has_quiet_NaN << std::endl;
out << "#define DBL_HAS_SIGNALING_NAN " << std::dec << std::numeric_limits<double>::has_signaling_NaN << std::endl;
out << "#define DBL_HAS_DENORM " << std::dec << std::numeric_limits<double>::has_denorm << std::endl;
out << "#define DBL_HAS_DENORM_LOSS " << std::dec << std::numeric_limits<double>::has_denorm_loss << std::endl;
out << "#define DBL_ROUNDS " << std::dec << std::numeric_limits<double>::round_style << std::endl;
out << "#define DBL_IS_IEC559 " << std::dec << std::numeric_limits<double>::is_iec559 << std::endl;
out << "#define DBL_MANT_DIG " << std::dec << std::numeric_limits<double>::digits << std::endl;
out << "#define DBL_DIG " << std::dec << std::numeric_limits<double>::digits10 << std::endl;
out << "#define DBL_DECIMAL_DIG " << std::dec << std::numeric_limits<double>::max_digits10 << std::endl;
out << "#define DBL_RADIX " << std::dec << std::numeric_limits<double>::radix << std::endl;
out << "#define DBL_MIN_EXP " << std::dec << std::numeric_limits<double>::min_exponent << std::endl;
out << "#define DBL_MAX_EXP " << std::dec << std::numeric_limits<double>::max_exponent << std::endl;
out << "#define DBL_MIN_10_EXP " << std::dec << std::numeric_limits<double>::min_exponent10 << std::endl;
out << "#define DBL_MAX_10_EXP " << std::dec << std::numeric_limits<double>::max_exponent10 << std::endl;
out << "#define DBL_TRAPS " << std::dec << std::numeric_limits<double>::traps << std::endl;
out << "#define DBL_TINYNESS_BEFORE " << std::dec << std::numeric_limits<double>::tinyness_before << std::endl;
out << R"(/// \brief Does \f$float\f$ use denormalization?)" << '\n';
out << "#define FLT_HAS_DENORM " << std::dec << std::numeric_limits<float>::has_denorm << '\n';
out << "#define DBL_MIN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::min() ) << "ll)" << std::endl;
out << "#define DBL_MAX " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::max() ) << "ll)" << std::endl;
out << "#define DBL_EPSILON " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::epsilon() ) << "ll)" << std::endl;
out << "#define DBL_INF " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::infinity() ) << "ll)" << std::endl;
out << "#define DBL_QUIET_NAN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::quiet_NaN() ) << "ll)" << std::endl;
out << "#define DBL_SIGNALING_NAN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::signaling_NaN()) << "ll)" << std::endl;
out << "#define DBL_DENORM_MIN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::denorm_min() ) << "ll)" << std::endl;
out << "#define DBL_ROUND_ERR " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::round_error() ) << "ll)" << std::endl;
out << R"(/// \brief Does \f$float\f$ have loss with denormalization?)" << '\n';
out << "#define FLT_HAS_DENORM_LOSS " << std::dec << std::numeric_limits<float>::has_denorm_loss << '\n';
out << "" << std::endl;
out << R"(/// \brief What rounding style does \f$float\f$ use?)" << '\n';
out << "#define FLT_ROUNDS " << std::dec << std::numeric_limits<float>::round_style << '\n';
out << "#endif // FENNEC_LANG_FLOAT_H" << std::endl;
out << R"(/// \brief Does \f$float\f$ use the IEEE floating point specification?)" << '\n';
out << "#define FLT_IS_IEC559 " << std::dec << std::numeric_limits<float>::is_iec559 << '\n';
out << R"(/// \brief The number of mantissa bits in \f$float\f$.)" << '\n';
out << "#define FLT_MANT_DIG " << std::dec << std::numeric_limits<float>::digits << '\n';
out << R"(/// \brief The number of decimal digits guaranteed to be preserved in a \f$float\f$ &rarr; \f$text\f$ &rarr; \f$float\f$.)" << '\n';
out << "#define FLT_DIG " << std::dec << std::numeric_limits<float>::digits10 << '\n';
out << R"(/// \brief The decimal precision required to serialize and deserialize a \f$float\f$.)" << '\n';
out << "#define FLT_DECIMAL_DIG " << std::dec << std::numeric_limits<float>::max_digits10 << '\n';
out << R"(/// \brief The radix, or integer base, used to represent a \f$float\f$.)" << '\n';
out << "#define FLT_RADIX " << std::dec << std::numeric_limits<float>::radix << '\n';
out << R"(/// \brief The minimum negative integer such that \f${FLT_RADIX}^{FLT_MIN_EXP}\f$ results in a normalized \f$float\f$.)" << '\n';
out << "#define FLT_MIN_EXP " << std::dec << std::numeric_limits<float>::min_exponent << '\n';
out << R"(/// \brief The maximum positive integer such that \f${FLT_RADIX}^{FLT_MAX_EXP}\f$ results in a non-infinite \f$float\f$.)" << '\n';
out << "#define FLT_MAX_EXP " << std::dec << std::numeric_limits<float>::max_exponent << '\n';
out << R"(/// \brief The minimum negative integer such that \f${10}^{FLT_MIN_EXP}\f$ results in a normalized \f$float\f$.)" << '\n';
out << "#define FLT_MIN_10_EXP " << std::dec << std::numeric_limits<float>::min_exponent10 << '\n';
out << R"(/// \brief The maximum positive integer such that \f${10}^{FLT_MAX_EXP}\f$ results in a non-infinite \f$float\f$.)" << '\n';
out << "#define FLT_MAX_10_EXP " << std::dec << std::numeric_limits<float>::max_exponent10 << '\n';
out << R"(/// \brief Do arithmetics operations with \f$float\f$ trap?)" << '\n';
out << "#define FLT_TRAPS " << std::dec << std::numeric_limits<float>::traps << '\n';
out << R"(/// \brief Do arithmetics operations with \f$float\f$ check for underflow?)" << '\n';
out << "#define FLT_TINYNESS_BEFORE " << std::dec << std::numeric_limits<float>::tinyness_before << '\n';
out << R"(/// \brief Smallest positive, finite, normal value of \f$float\f$.)" << '\n';
out << "#define FLT_MIN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::min() ) << ")" << '\n';
out << R"(/// \brief Largest positive, finite value of \f$float\f$.)" << '\n';
out << "#define FLT_MAX " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::max() ) << ")" << '\n';
out << R"(/// \brief The difference between \f$1.0\f$ and the next representable value of \f$float\f$.)" << '\n';
out << "#define FLT_EPSILON " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::epsilon() ) << ")" << '\n';
out << R"(/// \brief A value representing \f$\inf\f$ of type \f$float\f$.)" << '\n';
out << "#define FLT_INF " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::infinity() ) << ")" << '\n';
out << R"(/// \brief A value representing \f$NaN\f$ of type \f$float\f$ that does not trap.)" << '\n';
out << "#define FLT_QUIET_NAN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::quiet_NaN() ) << ")" << '\n';
out << R"(/// \brief A value representing \f$NaN\f$ of type \f$float\f$ that traps.)" << '\n';
out << "#define FLT_SIGNALING_NAN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::signaling_NaN()) << ")" << '\n';
out << R"(/// \brief Smallest positive, finite, subnormal value of \f$float\f$.)" << '\n';
out << "#define FLT_DENORM_MIN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::denorm_min() ) << ")" << '\n';
out << R"(/// \brief Maximum rounding error of type \f$float\f$.)" << '\n';
out << "#define FLT_ROUND_ERR " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::round_error() ) << ")" << '\n';
out << "" << '\n';
out << "#undef DBL_HAS_INFINITY" << '\n';
out << "#undef DBL_HAS_QUIET_NAN" << '\n';
out << "#undef DBL_HAS_SIGNALING_NAN" << '\n';
out << "#undef DBL_HAS_DENORM" << '\n';
out << "#undef DBL_HAS_DENORM_LOSS" << '\n';
out << "#undef DBL_ROUNDS" << '\n';
out << "#undef DBL_IS_IEC559" << '\n';
out << "#undef DBL_MANT_DIG" << '\n';
out << "#undef DBL_DIG" << '\n';
out << "#undef DBL_DECIMAL_DIG" << '\n';
out << "#undef DBL_RADIX" << '\n';
out << "#undef DBL_MIN_EXP" << '\n';
out << "#undef DBL_MAX_EXP" << '\n';
out << "#undef DBL_MIN_10_EXP" << '\n';
out << "#undef DBL_MAX_10_EXP" << '\n';
out << "#undef DBL_TRAPS" << '\n';
out << "#undef DBL_TINYNESS_BEFORE" << '\n';
out << "#undef DBL_MIN" << '\n';
out << "#undef DBL_MAX" << '\n';
out << "#undef DBL_EPSILON" << '\n';
out << "#undef DBL_INF" << '\n';
out << "#undef DBL_QUIET_NAN" << '\n';
out << "#undef DBL_SIGNALING_NAN" << '\n';
out << "#undef DBL_DENORM_MIN" << '\n';
out << "#undef DBL_ROUND_ERR" << '\n';
out << "" << '\n';
out << R"(/// \brief Does \f$double\f$ have an infinity?)" << '\n';
out << "#define DBL_HAS_INFINITY " << std::dec << std::numeric_limits<double>::has_infinity << '\n';
out << R"(/// \brief Does \f$double\f$ have a quiet NaN?)" << '\n';
out << "#define DBL_HAS_QUIET_NAN " << std::dec << std::numeric_limits<double>::has_quiet_NaN << '\n';
out << R"(/// \brief Does \f$double\f$ have a signaling NaN?)" << '\n';
out << "#define DBL_HAS_SIGNALING_NAN " << std::dec << std::numeric_limits<double>::has_signaling_NaN << '\n';
out << R"(/// \brief Does \f$double\f$ use denormalization?)" << '\n';
out << "#define DBL_HAS_DENORM " << std::dec << std::numeric_limits<double>::has_denorm << '\n';
out << R"(/// \brief Does \f$double\f$ have loss with denormalization?)" << '\n';
out << "#define DBL_HAS_DENORM_LOSS " << std::dec << std::numeric_limits<double>::has_denorm_loss << '\n';
out << R"(/// \brief What rounding style does \f$double\f$ use?)" << '\n';
out << "#define DBL_ROUNDS " << std::dec << std::numeric_limits<double>::round_style << '\n';
out << R"(/// \brief Does \f$double\f$ use the IEEE doubleing point specification?)" << '\n';
out << "#define DBL_IS_IEC559 " << std::dec << std::numeric_limits<double>::is_iec559 << '\n';
out << R"(/// \brief The number of mantissa bits in \f$double\f$.)" << '\n';
out << "#define DBL_MANT_DIG " << std::dec << std::numeric_limits<double>::digits << '\n';
out << R"(/// \brief The number of decimal digits guaranteed to be preserved in a \f$double\f$ &rarr; \f$text\f$ &rarr; \f$double\f$.)" << '\n';
out << "#define DBL_DIG " << std::dec << std::numeric_limits<double>::digits10 << '\n';
out << R"(/// \brief The decimal precision required to serialize and deserialize a \f$double\f$.)" << '\n';
out << "#define DBL_DECIMAL_DIG " << std::dec << std::numeric_limits<double>::max_digits10 << '\n';
out << R"(/// \brief The radix, or integer base, used to represent a \f$double\f$.)" << '\n';
out << "#define DBL_RADIX " << std::dec << std::numeric_limits<double>::radix << '\n';
out << R"(/// \brief The minimum negative integer such that \f${DBL_RADIX}^{DBL_MIN_EXP}\f$ results in a normalized \f$double\f$.)" << '\n';
out << "#define DBL_MIN_EXP " << std::dec << std::numeric_limits<double>::min_exponent << '\n';
out << R"(/// \brief The maximum positive integer such that \f${DBL_RADIX}^{DBL_MAX_EXP}\f$ results in a non-infinite \f$double\f$.)" << '\n';
out << "#define DBL_MAX_EXP " << std::dec << std::numeric_limits<double>::max_exponent << '\n';
out << R"(/// \brief The minimum negative integer such that \f${10}^{DBL_MIN_EXP}\f$ results in a normalized \f$double\f$.)" << '\n';
out << "#define DBL_MIN_10_EXP " << std::dec << std::numeric_limits<double>::min_exponent10 << '\n';
out << R"(/// \brief The maximum positive integer such that \f${10}^{DBL_MAX_EXP}\f$ results in a non-infinite \f$double\f$.)" << '\n';
out << "#define DBL_MAX_10_EXP " << std::dec << std::numeric_limits<double>::max_exponent10 << '\n';
out << R"(/// \brief Do arithmetics operations with \f$double\f$ trap?)" << '\n';
out << "#define DBL_TRAPS " << std::dec << std::numeric_limits<double>::traps << '\n';
out << R"(/// \brief Do arithmetics operations with \f$double\f$ check for underflow?)" << '\n';
out << "#define DBL_TINYNESS_BEFORE " << std::dec << std::numeric_limits<double>::tinyness_before << '\n';
out << R"(/// \brief Smallest positive, finite, normal value of \f$double\f$.)" << '\n';
out << "#define DBL_MIN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::min() ) << "ll)" << '\n';
out << R"(/// \brief Largest positive, finite value of \f$double\f$.)" << '\n';
out << "#define DBL_MAX " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::max() ) << "ll)" << '\n';
out << R"(/// \brief The difference between \f$1.0\f$ and the next representable value of \f$double\f$.)" << '\n';
out << "#define DBL_EPSILON " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::epsilon() ) << "ll)" << '\n';
out << R"(/// \brief A value representing \f$\inf\f$ of type \f$double\f$.)" << '\n';
out << "#define DBL_INF " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::infinity() ) << "ll)" << '\n';
out << R"(/// \brief A value representing \f$NaN\f$ of type \f$double\f$ that does not trap.)" << '\n';
out << "#define DBL_QUIET_NAN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::quiet_NaN() ) << "ll)" << '\n';
out << R"(/// \brief A value representing \f$NaN\f$ of type \f$double\f$ that traps.)" << '\n';
out << "#define DBL_SIGNALING_NAN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::signaling_NaN()) << "ll)" << '\n';
out << R"(/// \brief Smallest positive, finite, subnormal value of \f$double\f$.)" << '\n';
out << "#define DBL_DENORM_MIN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::denorm_min() ) << "ll)" << '\n';
out << R"(/// \brief Maximum rounding error of type \f$double\f$.)" << '\n';
out << "#define DBL_ROUND_ERR " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::round_error() ) << "ll)" << '\n';
out << "" << '\n';
out << "#endif // FENNEC_LANG_FLOAT_H" << '\n';
out.close();

View File

@@ -26,218 +26,425 @@ inline void integer_h()
std::ofstream out("fennec/lang/integer.h");
out << "// =====================================================================================================================" << std::endl;
out << "// fennec, a free and open source game engine" << std::endl;
out << "// Copyright © 2025 - 2026 Medusa Slockbower" << std::endl;
out << "//" << std::endl;
out << "// This program is free software: you can redistribute it and/or modify" << std::endl;
out << "// it under the terms of the GNU General Public License as published by" << std::endl;
out << "// the Free Software Foundation, either version 3 of the License, or" << std::endl;
out << "// (at your option) any later version." << std::endl;
out << "//" << std::endl;
out << "// This program is distributed in the hope that it will be useful," << std::endl;
out << "// but WITHOUT ANY WARRANTY; without even the implied warranty of" << std::endl;
out << "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" << std::endl;
out << "// GNU General Public License for more details." << std::endl;
out << "//" << std::endl;
out << "// You should have received a copy of the GNU General Public License" << std::endl;
out << "// along with this program. If not, see <https://www.gnu.org/licenses/>." << std::endl;
out << "// =====================================================================================================================" << std::endl;
out << "// =====================================================================================================================" << '\n';
out << "// fennec, a free and open source game engine" << '\n';
out << "// Copyright © 2025 - 2026 Medusa Slockbower" << '\n';
out << "//" << '\n';
out << "// This program is free software: you can redistribute it and/or modify" << '\n';
out << "// it under the terms of the GNU General Public License as published by" << '\n';
out << "// the Free Software Foundation, either version 3 of the License, or" << '\n';
out << "// (at your option) any later version." << '\n';
out << "//" << '\n';
out << "// This program is distributed in the hope that it will be useful," << '\n';
out << "// but WITHOUT ANY WARRANTY; without even the implied warranty of" << '\n';
out << "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" << '\n';
out << "// GNU General Public License for more details." << '\n';
out << "//" << '\n';
out << "// You should have received a copy of the GNU General Public License" << '\n';
out << "// along with this program. If not, see <https://www.gnu.org/licenses/>." << '\n';
out << "// =====================================================================================================================" << '\n';
out << "" << std::endl;
out << "" << '\n';
out << "///" << std::endl;
out << "/// \\file fennec/lang/integer.h" << std::endl;
out << "/// \\brief metaprogramming integer type info" << std::endl;
out << "///" << std::endl;
out << "///" << std::endl;
out << "/// \\details this file is automatically generated for the current build environment" << std::endl;
out << "///" << std::endl;
out << "/// \\copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))" << std::endl;
out << "///" << std::endl;
out << "///" << std::endl;
out << "///" << '\n';
out << "/// \\file fennec/lang/integer.h" << '\n';
out << "/// \\brief metaprogramming integer type info" << '\n';
out << "///" << '\n';
out << "///" << '\n';
out << "/// \\details This file is automatically generated for the current build environment." << '\n';
out << "///" << '\n';
out << "/// Environment for this build: " FENNEC_LONG_COMPILER_NAME << '\n';
out << "///" << '\n';
out << "/// \\copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))" << '\n';
out << "///" << '\n';
out << "///" << '\n';
out << "" << std::endl;
out << "" << '\n';
out << "#ifndef FENNEC_LANG_INTEGER_H" << std::endl;
out << "#define FENNEC_LANG_INTEGER_H" << std::endl;
out << "#ifndef FENNEC_LANG_INTEGER_H" << '\n';
out << "#define FENNEC_LANG_INTEGER_H" << '\n';
out << "" << std::endl;
out << "" << '\n';
out << "#undef CHAR_MIN" << std::endl;
out << "#undef CHAR_MAX" << std::endl;
out << "#undef WCHAR_MIN" << std::endl;
out << "#undef WCHAR_MAX" << std::endl;
out << "#undef SCHAR_MIN" << std::endl;
out << "#undef SCHAR_MAX" << std::endl;
out << "#undef UCHAR_MIN" << std::endl;
out << "#undef UCHAR_MAX" << std::endl;
out << "#undef INT_MIN" << std::endl;
out << "#undef INT_MAX" << std::endl;
out << "#undef UINT_MIN" << std::endl;
out << "#undef UINT_MAX" << std::endl;
out << "#undef LONG_MIN" << std::endl;
out << "#undef LONG_MAX" << std::endl;
out << "#undef ULONG_MIN" << std::endl;
out << "#undef ULONG_MAX" << std::endl;
out << "#undef LLONG_MIN" << std::endl;
out << "#undef LLONG_MAX" << std::endl;
out << "#undef ULLONG_MIN" << std::endl;
out << "#undef ULLONG_MAX" << std::endl;
out << "#undef CHAR_MIN" << '\n';
out << "#undef CHAR_MAX" << '\n';
out << "#undef WCHAR_MIN" << '\n';
out << "#undef WCHAR_MAX" << '\n';
out << "#undef SCHAR_MIN" << '\n';
out << "#undef SCHAR_MAX" << '\n';
out << "#undef UCHAR_MIN" << '\n';
out << "#undef UCHAR_MAX" << '\n';
out << "#undef INT_MIN" << '\n';
out << "#undef INT_MAX" << '\n';
out << "#undef UINT_MIN" << '\n';
out << "#undef UINT_MAX" << '\n';
out << "#undef LONG_MIN" << '\n';
out << "#undef LONG_MAX" << '\n';
out << "#undef ULONG_MIN" << '\n';
out << "#undef ULONG_MAX" << '\n';
out << "#undef LLONG_MIN" << '\n';
out << "#undef LLONG_MAX" << '\n';
out << "#undef ULLONG_MIN" << '\n';
out << "#undef ULLONG_MAX" << '\n';
out << "" << std::endl;
out << "" << '\n';
// TODO: Fix this to generate info without using the c++stdlib for platforms without this available.
out << "#define CHAR_IS_SIGNED " << std::boolalpha << std::numeric_limits<char>::is_signed << std::endl;
out << R"(/// \brief Is \f$char\f$ signed?)" << '\n';
out << "#define CHAR_IS_SIGNED " << std::boolalpha << std::numeric_limits<char>::is_signed << '\n';
out << "#define CHAR_ROUNDS " << "0x" << std::hex << (int)std::numeric_limits<char>::round_style << std::endl;
out << "#define CHAR_RADIX_DIG " << "0x" << std::hex << (int)std::numeric_limits<char>::digits << std::endl;
out << "#define CHAR_DIG " << "0x" << std::hex << (int)std::numeric_limits<char>::digits10 << std::endl;
out << "#define CHAR_DECIMAL_DIG " << "0x" << std::hex << (int)std::numeric_limits<char>::max_digits10 << std::endl;
out << "#define CHAR_RADIX " << "0x" << std::hex << (int)std::numeric_limits<char>::radix << std::endl;
out << "#define CHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<char>::traps << std::endl;
out << R"(/// \brief Rounding style of type \f$char\f$.)" << '\n';
out << "#define CHAR_ROUNDS " << "0x" << std::hex << (int)std::numeric_limits<char>::round_style << '\n';
out << "#define CHAR_MIN " << "0x" << std::hex << (0xFF & +std::numeric_limits<char>::min()) << std::endl;
out << "#define CHAR_MAX " << "0x" << std::hex << (0xFF & +std::numeric_limits<char>::max()) << std::endl;
out << R"(/// \brief Number of radix digits represented by \f$char\f$.)" << '\n';
out << "#define CHAR_RADIX_DIG " << "0x" << std::hex << (int)std::numeric_limits<char>::digits << '\n';
out << "" << std::endl;
out << R"(/// \brief Number of decimal digits represented by \f$char\f$.)" << '\n';
out << "#define CHAR_DIG " << "0x" << std::hex << (int)std::numeric_limits<char>::digits10 << '\n';
out << "#define WCHAR_IS_SIGNED " << std::boolalpha << std::numeric_limits<wchar_t>::is_signed << std::endl;
out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$char\f$.)" << '\n';
out << "#define CHAR_DECIMAL_DIG " << "0x" << std::hex << (int)std::numeric_limits<char>::max_digits10 << '\n';
out << "#define WCHAR_ROUNDS " << "0x" << std::hex << std::numeric_limits<wchar_t>::round_style << std::endl;
out << "#define WCHAR_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<wchar_t>::digits << std::endl;
out << "#define WCHAR_DIG " << "0x" << std::hex << std::numeric_limits<wchar_t>::digits10 << std::endl;
out << "#define WCHAR_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<wchar_t>::max_digits10 << std::endl;
out << "#define WCHAR_RADIX " << "0x" << std::hex << std::numeric_limits<wchar_t>::radix << std::endl;
out << "#define WCHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<wchar_t>::traps << std::endl;
out << R"(/// \brief The radix, or integer base, used to represent a \f$char\f$.)" << '\n';
out << "#define CHAR_RADIX " << "0x" << std::hex << (int)std::numeric_limits<char>::radix << '\n';
out << "#define WCHAR_MIN " << "0x" << std::hex << +std::numeric_limits<wchar_t>::min() << std::endl;
out << "#define WCHAR_MAX " << "0x" << std::hex << +std::numeric_limits<wchar_t>::max() << std::endl;
out << R"(/// \brief Do arithmetics operations with \f$char\f$ trap?)" << '\n';
out << "#define CHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<char>::traps << '\n';
out << "" << std::endl;
out << "#define SCHAR_ROUNDS " << "0x" << std::hex << (int)std::numeric_limits<signed char>::round_style << std::endl;
out << "#define SCHAR_RADIX_DIG " << "0x" << std::hex << (int)std::numeric_limits<signed char>::digits << std::endl;
out << "#define SCHAR_DIG " << "0x" << std::hex << (int)std::numeric_limits<signed char>::digits10 << std::endl;
out << "#define SCHAR_DECIMAL_DIG " << "0x" << std::hex << (int)std::numeric_limits<signed char>::max_digits10 << std::endl;
out << "#define SCHAR_RADIX " << "0x" << std::hex << (int)std::numeric_limits<signed char>::radix << std::endl;
out << "#define SCHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<signed char>::traps << std::endl;
out << R"(/// \brief Smallest finite value of \f$char\f$.)" << '\n';
out << "#define CHAR_MIN " << "0x" << std::hex << (0xFF & +std::numeric_limits<char>::min()) << '\n';
out << "#define SCHAR_MIN " << "0x" << std::hex << (0xFF & +std::numeric_limits<signed char>::min()) << std::endl;
out << "#define SCHAR_MAX " << "0x" << std::hex << (0xFF & +std::numeric_limits<signed char>::max()) << std::endl;
out << R"(/// \brief Largest finite value of \f$char\f$.)" << '\n';
out << "#define CHAR_MAX " << "0x" << std::hex << (0xFF & +std::numeric_limits<char>::max()) << '\n';
out << "" << std::endl;
out << "#define UCHAR_ROUNDS " << "0x" << std::hex << std::numeric_limits<unsigned char>::round_style << std::endl;
out << "#define UCHAR_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<unsigned char>::digits << std::endl;
out << "#define UCHAR_DIG " << "0x" << std::hex << std::numeric_limits<unsigned char>::digits10 << std::endl;
out << "#define UCHAR_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned char>::max_digits10 << std::endl;
out << "#define UCHAR_RADIX " << "0x" << std::hex << std::numeric_limits<unsigned char>::radix << std::endl;
out << "#define UCHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<unsigned char>::traps << std::endl;
out << "" << '\n';
out << "#define UCHAR_MIN " << "0x" << std::hex << (0xFF & +std::numeric_limits<unsigned char>::min()) << std::endl;
out << "#define UCHAR_MAX " << "0x" << std::hex << (0xFF & +std::numeric_limits<unsigned char>::max()) << std::endl;
out << "" << std::endl;
out << R"(/// \brief Is \f$wchar_t\f$ signed?)" << '\n';
out << "#define WCHAR_IS_SIGNED " << std::boolalpha << std::numeric_limits<wchar_t>::is_signed << '\n';
out << "#define SHORT_ROUNDS " << "0x" << std::hex << std::numeric_limits<short>::round_style << std::endl;
out << "#define SHORT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<short>::digits << std::endl;
out << "#define SHORT_DIG " << "0x" << std::hex << std::numeric_limits<short>::digits10 << std::endl;
out << "#define SHORT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<short>::max_digits10 << std::endl;
out << "#define SHORT_RADIX " << "0x" << std::hex << std::numeric_limits<short>::radix << std::endl;
out << "#define SHORT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<short>::traps << std::endl;
out << R"(/// \brief Rounding style of type \f$wchar_t\f$.)" << '\n';
out << "#define WCHAR_ROUNDS " << "0x" << std::hex << std::numeric_limits<wchar_t>::round_style << '\n';
out << "#define SHORT_MIN " << "0x" << std::hex << std::numeric_limits<short>::min() << std::endl;
out << "#define SHORT_MAX " << "0x" << std::hex << std::numeric_limits<short>::max() << std::endl;
out << R"(/// \brief Number of radix digits represented by \f$wchar_t\f$.)" << '\n';
out << "#define WCHAR_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<wchar_t>::digits << '\n';
out << "" << std::endl;
out << R"(/// \brief Number of decimal digits represented by \f$wchar_t\f$.)" << '\n';
out << "#define WCHAR_DIG " << "0x" << std::hex << std::numeric_limits<wchar_t>::digits10 << '\n';
out << "#define USHORT_ROUNDS " << "0x" << std::hex << std::numeric_limits<unsigned short>::round_style << std::endl;
out << "#define USHORT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<unsigned short>::digits << std::endl;
out << "#define USHORT_DIG " << "0x" << std::hex << std::numeric_limits<unsigned short>::digits10 << std::endl;
out << "#define USHORT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned short>::max_digits10 << std::endl;
out << "#define USHORT_RADIX " << "0x" << std::hex << std::numeric_limits<unsigned short>::radix << std::endl;
out << "#define USHORT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<unsigned short>::traps << std::endl;
out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$wchar_t\f$.)" << '\n';
out << "#define WCHAR_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<wchar_t>::max_digits10 << '\n';
out << "#define USHORT_MIN " << "0x" << std::hex << std::numeric_limits<unsigned short>::min() << std::endl;
out << "#define USHORT_MAX " << "0x" << std::hex << std::numeric_limits<unsigned short>::max() << std::endl;
out << R"(/// \brief The radix, or integer base, used to represent a \f$wchar_t\f$.)" << '\n';
out << "#define WCHAR_RADIX " << "0x" << std::hex << std::numeric_limits<wchar_t>::radix << '\n';
out << "" << std::endl;
out << R"(/// \brief Do arithmetics operations with \f$wchar_t\f$ trap?)" << '\n';
out << "#define WCHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<wchar_t>::traps << '\n';
out << "#define INT_ROUNDS " << "0x" << std::hex << std::numeric_limits<int>::round_style << std::endl;
out << "#define INT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<int>::digits << std::endl;
out << "#define INT_DIG " << "0x" << std::hex << std::numeric_limits<int>::digits10 << std::endl;
out << "#define INT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<int>::max_digits10 << std::endl;
out << "#define INT_RADIX " << "0x" << std::hex << std::numeric_limits<int>::radix << std::endl;
out << "#define INT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<int>::traps << std::endl;
out << "#define INT_MIN " << "0x" << std::hex << std::numeric_limits<int>::min() << std::endl;
out << "#define INT_MAX " << "0x" << std::hex << std::numeric_limits<int>::max() << std::endl;
out << R"(/// \brief Smallest finite value of \f$wchar_t\f$.)" << '\n';
out << "#define WCHAR_MIN " << "0x" << std::hex << +std::numeric_limits<wchar_t>::min() << '\n';
out << "" << std::endl;
out << R"(/// \brief Largest finite value of \f$wchar_t\f$.)" << '\n';
out << "#define WCHAR_MAX " << "0x" << std::hex << +std::numeric_limits<wchar_t>::max() << '\n';
out << "#define UINT_ROUNDS " << "0x" << std::hex << std::numeric_limits<unsigned int>::round_style << std::endl;
out << "#define UINT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<unsigned int>::digits << std::endl;
out << "#define UINT_DIG " << "0x" << std::hex << std::numeric_limits<unsigned int>::digits10 << std::endl;
out << "#define UINT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned int>::max_digits10 << std::endl;
out << "#define UINT_RADIX " << "0x" << std::hex << std::numeric_limits<unsigned int>::radix << std::endl;
out << "#define UINT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<unsigned int>::traps << std::endl;
out << "#define UINT_MIN " << "0x" << std::hex << std::numeric_limits<unsigned int>::min() << std::endl;
out << "#define UINT_MAX " << "0x" << std::hex << std::numeric_limits<unsigned int>::max() << std::endl;
out << "" << '\n';
out << "" << std::endl;
out << "#define LONG_ROUNDS " << "0x" << std::hex << std::numeric_limits<long int>::round_style << std::endl;
out << "#define LONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<long int>::digits << std::endl;
out << "#define LONG_DIG " << "0x" << std::hex << std::numeric_limits<long int>::digits10 << std::endl;
out << "#define LONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<long int>::max_digits10 << std::endl;
out << "#define LONG_RADIX " << "0x" << std::hex << std::numeric_limits<long int>::radix << std::endl;
out << "#define LONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<long int>::traps << std::endl;
out << R"(/// \brief Is \f$signed char\f$ signed?)" << '\n';
out << "#define SCHAR_ROUNDS " << "0x" << std::hex << (int)std::numeric_limits<signed char>::round_style << '\n';
out << "#define LONG_MIN " << "0x" << std::hex << std::numeric_limits<long int>::min() << std::endl;
out << "#define LONG_MAX " << "0x" << std::hex << std::numeric_limits<long int>::max() << std::endl;
out << R"(/// \brief Rounding style of type \f$signed char\f$.)" << '\n';
out << "#define SCHAR_RADIX_DIG " << "0x" << std::hex << (int)std::numeric_limits<signed char>::digits << '\n';
out << "" << std::endl;
out << R"(/// \brief Number of radix digits represented by \f$signed char\f$.)" << '\n';
out << "#define SCHAR_DIG " << "0x" << std::hex << (int)std::numeric_limits<signed char>::digits10 << '\n';
out << "#define ULONG_ROUNDS " << "0x" << std::hex << std::numeric_limits<unsigned long int>::round_style << std::endl;
out << "#define ULONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long int>::digits << std::endl;
out << "#define ULONG_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long int>::digits10 << std::endl;
out << "#define ULONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long int>::max_digits10 << std::endl;
out << "#define ULONG_RADIX " << "0x" << std::hex << std::numeric_limits<unsigned long int>::radix << std::endl;
out << "#define ULONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<unsigned long int>::traps << std::endl;
out << R"(/// \brief Number of decimal digits represented by \f$signed char\f$.)" << '\n';
out << "#define SCHAR_DECIMAL_DIG " << "0x" << std::hex << (int)std::numeric_limits<signed char>::max_digits10 << '\n';
out << "#define ULONG_MIN " << "0x" << std::hex << std::numeric_limits<unsigned long int>::min() << std::endl;
out << "#define ULONG_MAX " << "0x" << std::hex << std::numeric_limits<unsigned long int>::max() << std::endl;
out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$signed char\f$.)" << '\n';
out << "#define SCHAR_RADIX " << "0x" << std::hex << (int)std::numeric_limits<signed char>::radix << '\n';
out << "" << std::endl;
out << R"(/// \brief Do arithmetics operations with \f$signed char\f$ trap?)" << '\n';
out << "#define SCHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<signed char>::traps << '\n';
out << "#define LLONG_ROUNDS " << "0x" << std::hex << std::numeric_limits<long long>::round_style << std::endl;
out << "#define LLONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<long long>::digits << std::endl;
out << "#define LLONG_DIG " << "0x" << std::hex << std::numeric_limits<long long>::digits10 << std::endl;
out << "#define LLONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<long long>::max_digits10 << std::endl;
out << "#define LLONG_RADIX " << "0x" << std::hex << std::numeric_limits<long long>::radix << std::endl;
out << "#define LLONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<long long>::traps << std::endl;
out << "#define LLONG_MIN " << "0x" << std::hex << std::numeric_limits<long long>::min() << std::endl;
out << "#define LLONG_MAX " << "0x" << std::hex << std::numeric_limits<long long>::max() << std::endl;
out << R"(/// \brief Smallest finite value of \f$signed char\f$.)" << '\n';
out << "#define SCHAR_MIN " << "0x" << std::hex << (0xFF & +std::numeric_limits<signed char>::min()) << '\n';
out << "" << std::endl;
out << R"(/// \brief Largest finite value of \f$signed char\f$.)" << '\n';
out << "#define SCHAR_MAX " << "0x" << std::hex << (0xFF & +std::numeric_limits<signed char>::max()) << '\n';
out << "#define ULLONG_ROUNDS " << "0x" << std::hex << std::numeric_limits<unsigned long long>::round_style << std::endl;
out << "#define ULLONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long long>::digits << std::endl;
out << "#define ULLONG_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long long>::digits10 << std::endl;
out << "#define ULLONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long long>::max_digits10 << std::endl;
out << "#define ULLONG_RADIX " << "0x" << std::hex << std::numeric_limits<unsigned long long>::radix << std::endl;
out << "#define ULLONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<unsigned long long>::traps << std::endl;
out << "#define ULLONG_MIN " << "0x" << std::hex << std::numeric_limits<unsigned long long>::min() << std::endl;
out << "#define ULLONG_MAX " << "0x" << std::hex << std::numeric_limits<unsigned long long>::max() << std::endl;
out << "" << '\n';
out << "" << std::endl;
out << "#endif // FENNEC_LANG_INTEGER_H" << std::endl;
out << R"(/// \brief Is \f$unsigned char\f$ unsigned?)" << '\n';
out << "#define UCHAR_ROUNDS " << "0x" << std::hex << (int)std::numeric_limits<unsigned char>::round_style << '\n';
out << R"(/// \brief Rounding style of type \f$unsigned char\f$.)" << '\n';
out << "#define UCHAR_RADIX_DIG " << "0x" << std::hex << (int)std::numeric_limits<unsigned char>::digits << '\n';
out << R"(/// \brief Number of radix digits represented by \f$unsigned char\f$.)" << '\n';
out << "#define UCHAR_DIG " << "0x" << std::hex << (int)std::numeric_limits<unsigned char>::digits10 << '\n';
out << R"(/// \brief Number of decimal digits represented by \f$unsigned char\f$.)" << '\n';
out << "#define UCHAR_DECIMAL_DIG " << "0x" << std::hex << (int)std::numeric_limits<unsigned char>::max_digits10 << '\n';
out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned char\f$.)" << '\n';
out << "#define UCHAR_RADIX " << "0x" << std::hex << (int)std::numeric_limits<unsigned char>::radix << '\n';
out << R"(/// \brief Do arithmetics operations with \f$unsigned char\f$ trap?)" << '\n';
out << "#define UCHAR_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<unsigned char>::traps << '\n';
out << R"(/// \brief Smallest finite value of \f$unsigned char\f$.)" << '\n';
out << "#define UCHAR_MIN " << "0x" << std::hex << (0xFF & +std::numeric_limits<unsigned char>::min()) << '\n';
out << R"(/// \brief Largest finite value of \f$unsigned char\f$.)" << '\n';
out << "#define UCHAR_MAX " << "0x" << std::hex << (0xFF & +std::numeric_limits<unsigned char>::max()) << '\n';
out << "" << '\n';
out << R"(/// \brief Rounding style of type \f$short\f$.)" << '\n';
out << "#define SHORT_ROUNDS " << "0x" << std::hex << std::numeric_limits<short>::round_style << '\n';
out << R"(/// \brief Number of radix digits represented by \f$short\f$.)" << '\n';
out << "#define SHORT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<short>::digits << '\n';
out << R"(/// \brief Number of decimal digits represented by \f$short\f$.)" << '\n';
out << "#define SHORT_DIG " << "0x" << std::hex << std::numeric_limits<short>::digits10 << '\n';
out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$short\f$.)" << '\n';
out << "#define SHORT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<short>::max_digits10 << '\n';
out << R"(/// \brief The radix, or integer base, used to represent a \f$short\f$.)" << '\n';
out << "#define SHORT_RADIX " << "0x" << std::hex << std::numeric_limits<short>::radix << '\n';
out << R"(/// \brief Do arithmetics operations with \f$short\f$ trap?)" << '\n';
out << "#define SHORT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<short>::traps << '\n';
out << R"(/// \brief Smallest finite value of \f$short\f$.)" << '\n';
out << "#define SHORT_MIN " << "0x" << std::hex << +std::numeric_limits<short>::min() << '\n';
out << R"(/// \brief Largest finite value of \f$short\f$.)" << '\n';
out << "#define SHORT_MAX " << "0x" << std::hex << +std::numeric_limits<short>::max() << '\n';
out << "" << '\n';
out << R"(/// \brief Rounding style of type \f$unsigned short\f$.)" << '\n';
out << "#define USHORT_ROUNDS " << "0x" << std::hex << std::numeric_limits<unsigned short>::round_style << '\n';
out << R"(/// \brief Number of radix digits represented by \f$unsigned short\f$.)" << '\n';
out << "#define USHORT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<unsigned short>::digits << '\n';
out << R"(/// \brief Number of decimal digits represented by \f$unsigned short\f$.)" << '\n';
out << "#define USHORT_DIG " << "0x" << std::hex << std::numeric_limits<unsigned short>::digits10 << '\n';
out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned short\f$.)" << '\n';
out << "#define USHORT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned short>::max_digits10 << '\n';
out << R"(/// \brief The radix, or integer base, used to represent a \f$unsigned short\f$.)" << '\n';
out << "#define USHORT_RADIX " << "0x" << std::hex << std::numeric_limits<unsigned short>::radix << '\n';
out << R"(/// \brief Do arithmetics operations with \f$unsigned short\f$ trap?)" << '\n';
out << "#define USHORT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<unsigned short>::traps << '\n';
out << R"(/// \brief Smallest finite value of \f$unsigned short\f$.)" << '\n';
out << "#define USHORT_MIN " << "0x" << std::hex << +std::numeric_limits<unsigned short>::min() << '\n';
out << R"(/// \brief Largest finite value of \f$unsigned short\f$.)" << '\n';
out << "#define USHORT_MAX " << "0x" << std::hex << +std::numeric_limits<unsigned short>::max() << '\n';
out << "" << '\n';
out << R"(/// \brief Rounding style of type \f$int\f$.)" << '\n';
out << "#define INT_ROUNDS " << "0x" << std::hex << std::numeric_limits<int>::round_style << '\n';
out << R"(/// \brief Number of radix digits represented by \f$int\f$.)" << '\n';
out << "#define INT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<int>::digits << '\n';
out << R"(/// \brief Number of decimal digits represented by \f$int\f$.)" << '\n';
out << "#define INT_DIG " << "0x" << std::hex << std::numeric_limits<int>::digits10 << '\n';
out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$int\f$.)" << '\n';
out << "#define INT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<int>::max_digits10 << '\n';
out << R"(/// \brief The radix, or integer base, used to represent a \f$int\f$.)" << '\n';
out << "#define INT_RADIX " << "0x" << std::hex << std::numeric_limits<int>::radix << '\n';
out << R"(/// \brief Do arithmetics operations with \f$int\f$ trap?)" << '\n';
out << "#define INT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<int>::traps << '\n';
out << R"(/// \brief Smallest finite value of \f$int\f$.)" << '\n';
out << "#define INT_MIN " << "0x" << std::hex << +std::numeric_limits<int>::min() << '\n';
out << R"(/// \brief Largest finite value of \f$int\f$.)" << '\n';
out << "#define INT_MAX " << "0x" << std::hex << +std::numeric_limits<int>::max() << '\n';
out << "" << '\n';
out << R"(/// \brief Rounding style of type \f$unsigned int\f$.)" << '\n';
out << "#define UINT_ROUNDS " << "0x" << std::hex << std::numeric_limits<unsigned int>::round_style << '\n';
out << R"(/// \brief Number of radix digits represented by \f$unsigned int\f$.)" << '\n';
out << "#define UINT_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<unsigned int>::digits << '\n';
out << R"(/// \brief Number of decimal digits represented by \f$unsigned int\f$.)" << '\n';
out << "#define UINT_DIG " << "0x" << std::hex << std::numeric_limits<unsigned int>::digits10 << '\n';
out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned int\f$.)" << '\n';
out << "#define UINT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned int>::max_digits10 << '\n';
out << R"(/// \brief The radix, or unsigned integer base, used to represent a \f$unsigned int\f$.)" << '\n';
out << "#define UINT_RADIX " << "0x" << std::hex << std::numeric_limits<unsigned int>::radix << '\n';
out << R"(/// \brief Do arithmetics operations with \f$unsigned int\f$ trap?)" << '\n';
out << "#define UINT_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<unsigned int>::traps << '\n';
out << R"(/// \brief Smallest finite value of \f$unsigned int\f$.)" << '\n';
out << "#define UINT_MIN " << "0x" << std::hex << +std::numeric_limits<unsigned int>::min() << '\n';
out << R"(/// \brief Largest finite value of \f$unsigned int\f$.)" << '\n';
out << "#define UINT_MAX " << "0x" << std::hex << +std::numeric_limits<unsigned int>::max() << '\n';
out << "" << '\n';
out << R"(/// \brief Rounding style of type \f$long int\f$.)" << '\n';
out << "#define LONG_ROUNDS " << "0x" << std::hex << std::numeric_limits<long int>::round_style << '\n';
out << R"(/// \brief Number of radix digits represented by \f$long int\f$.)" << '\n';
out << "#define LONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<long int>::digits << '\n';
out << R"(/// \brief Number of decimal digits represented by \f$long int\f$.)" << '\n';
out << "#define LONG_DIG " << "0x" << std::hex << std::numeric_limits<long int>::digits10 << '\n';
out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$long int\f$.)" << '\n';
out << "#define LONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<long int>::max_digits10 << '\n';
out << R"(/// \brief The radix, or long integer base, used to represent a \f$long int\f$.)" << '\n';
out << "#define LONG_RADIX " << "0x" << std::hex << std::numeric_limits<long int>::radix << '\n';
out << R"(/// \brief Do arithmetics operations with \f$long int\f$ trap?)" << '\n';
out << "#define LONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<long int>::traps << '\n';
out << R"(/// \brief Smallest finite value of \f$long int\f$.)" << '\n';
out << "#define LONG_MIN " << "0x" << std::hex << +std::numeric_limits<long int>::min() << '\n';
out << R"(/// \brief Largest finite value of \f$long int\f$.)" << '\n';
out << "#define LONG_MAX " << "0x" << std::hex << +std::numeric_limits<long int>::max() << '\n';
out << "" << '\n';
out << R"(/// \brief Rounding style of type \f$unsigned long int\f$.)" << '\n';
out << "#define ULONG_ROUNDS " << "0x" << std::hex << std::numeric_limits<unsigned long int>::round_style << '\n';
out << R"(/// \brief Number of radix digits represented by \f$unsigned long int\f$.)" << '\n';
out << "#define ULONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long int>::digits << '\n';
out << R"(/// \brief Number of decimal digits represented by \f$unsigned long int\f$.)" << '\n';
out << "#define ULONG_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long int>::digits10 << '\n';
out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned long int\f$.)" << '\n';
out << "#define ULONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long int>::max_digits10 << '\n';
out << R"(/// \brief The radix, or unsigned long integer base, used to represent a \f$unsigned long int\f$.)" << '\n';
out << "#define ULONG_RADIX " << "0x" << std::hex << std::numeric_limits<unsigned long int>::radix << '\n';
out << R"(/// \brief Do arithmetics operations with \f$unsigned long int\f$ trap?)" << '\n';
out << "#define ULONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<unsigned long int>::traps << '\n';
out << R"(/// \brief Smallest finite value of \f$unsigned long int\f$.)" << '\n';
out << "#define ULONG_MIN " << "0x" << std::hex << +std::numeric_limits<unsigned long int>::min() << '\n';
out << R"(/// \brief Largest finite value of \f$unsigned long int\f$.)" << '\n';
out << "#define ULONG_MAX " << "0x" << std::hex << +std::numeric_limits<unsigned long int>::max() << '\n';
out << "" << '\n';
out << R"(/// \brief Rounding style of type \f$long long\f$.)" << '\n';
out << "#define LLONG_ROUNDS " << "0x" << std::hex << std::numeric_limits<long long>::round_style << '\n';
out << R"(/// \brief Number of radix digits represented by \f$long long\f$.)" << '\n';
out << "#define LLONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<long long>::digits << '\n';
out << R"(/// \brief Number of decimal digits represented by \f$long long\f$.)" << '\n';
out << "#define LLONG_DIG " << "0x" << std::hex << std::numeric_limits<long long>::digits10 << '\n';
out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$long long\f$.)" << '\n';
out << "#define LLONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<long long>::max_digits10 << '\n';
out << R"(/// \brief The radix, or long longeger base, used to represent a \f$long long\f$.)" << '\n';
out << "#define LLONG_RADIX " << "0x" << std::hex << std::numeric_limits<long long>::radix << '\n';
out << R"(/// \brief Do arithmetics operations with \f$long long\f$ trap?)" << '\n';
out << "#define LLONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<long long>::traps << '\n';
out << R"(/// \brief Smallest finite value of \f$long long\f$.)" << '\n';
out << "#define LLONG_MIN " << "0x" << std::hex << +std::numeric_limits<long long>::min() << '\n';
out << R"(/// \brief Largest finite value of \f$long long\f$.)" << '\n';
out << "#define LLONG_MAX " << "0x" << std::hex << +std::numeric_limits<long long>::max() << '\n';
out << "" << '\n';
out << R"(/// \brief Rounding style of type \f$unsigned long long\f$.)" << '\n';
out << "#define ULLONG_ROUNDS " << "0x" << std::hex << std::numeric_limits<unsigned long long>::round_style << '\n';
out << R"(/// \brief Number of radix digits represented by \f$unsigned long long\f$.)" << '\n';
out << "#define ULLONG_RADIX_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long long>::digits << '\n';
out << R"(/// \brief Number of decimal digits represented by \f$unsigned long long\f$.)" << '\n';
out << "#define ULLONG_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long long>::digits10 << '\n';
out << R"(/// \brief Number of decimal digits necessary to differentiate all values of type \f$unsigned long long\f$.)" << '\n';
out << "#define ULLONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long long>::max_digits10 << '\n';
out << R"(/// \brief The radix, or unsigned long longeger base, used to represent a \f$unsigned long long\f$.)" << '\n';
out << "#define ULLONG_RADIX " << "0x" << std::hex << std::numeric_limits<unsigned long long>::radix << '\n';
out << R"(/// \brief Do arithmetics operations with \f$unsigned long long\f$ trap?)" << '\n';
out << "#define ULLONG_TRAPS " << "0x" << std::boolalpha << std::numeric_limits<unsigned long long>::traps << '\n';
out << R"(/// \brief Smallest finite value of \f$unsigned long long\f$.)" << '\n';
out << "#define ULLONG_MIN " << "0x" << std::hex << +std::numeric_limits<unsigned long long>::min() << '\n';
out << R"(/// \brief Largest finite value of \f$unsigned long long\f$.)" << '\n';
out << "#define ULLONG_MAX " << "0x" << std::hex << +std::numeric_limits<unsigned long long>::max() << '\n';
out << "" << '\n';
out << "#endif // FENNEC_LANG_INTEGER_H" << '\n';
out.close();

View File

@@ -37,7 +37,7 @@ path path::current() {
#include <unistd.h>
#include <linux/limits.h>
path path::current() {
path path::get_current() {
char cstr[PATH_MAX];
if (getcwd(cstr, sizeof(cstr)) == nullptr) {
return path("");
@@ -45,11 +45,11 @@ path path::current() {
return path(cstring(cstr, strlen(cstr)));
}
path path::current(const path& path) {
path path::set_current(const path& path) {
if (chdir(path._str.cstr())) {
return fennec::path("");
}
return current();
return get_current();
}
#endif

View File

@@ -76,10 +76,10 @@ void* operator new[](fennec::size_t size, fennec::align_t align, const fennec::n
#endif
// Allocation functions
void* operator new (fennec::size_t size) { return ::malloc(size); }
void* operator new[](fennec::size_t size) { return ::malloc(size); }
void* operator new (fennec::size_t size, const fennec::nothrow_t&) { return ::malloc(size); }
void* operator new[](fennec::size_t size, const fennec::nothrow_t&) { return ::malloc(size); }
void* operator new (fennec::size_t size) { return ::calloc(size, 1); }
void* operator new[](fennec::size_t size) { return ::calloc(size, 1); }
void* operator new (fennec::size_t size, const fennec::nothrow_t&) { return ::calloc(size, 1); }
void* operator new[](fennec::size_t size, const fennec::nothrow_t&) { return ::calloc(size, 1); }
// Deallocation Functions
void operator delete (void* ptr, fennec::size_t) noexcept { ::free(ptr); }

View File

@@ -245,7 +245,7 @@ bool wayland_window::set_flag(uint8_t flag, bool value) {
}
// Helpers =============================================================================================================
// Private Helpers =====================================================================================================
void wayland_window::_update_size(const ivec2& size) {
//bool size_changed = any(notEqual(size, state.rect.size));

View File

@@ -107,8 +107,8 @@ eglcontext::eglcontext(display_server* display)
version.major = _eglvmajor;
version.minor = _eglvminor;
version.patch = 0;
version.str = format("{} v{}.{}", egl_translate_type(_eglctype), _eglvmajor, _eglvminor);
logger::log(format("Created OpenGL Context: {}", version.str));
version.meta = _eglctype;
logger::log(format("Created OpenGL Context: {} v{}.{}", egl_translate_type(version.meta), version.major, version.minor));
}
eglcontext::~eglcontext() {
@@ -138,7 +138,7 @@ eglcontext::~eglcontext() {
version.major = 0;
version.minor = 0;
version.patch = 0;
version.str = "";
version.meta = 0;
}
bool eglcontext::is_valid() {

View File

@@ -109,7 +109,7 @@ window_id window_manager::create_window(const window::config& config, window_id
return id;
}
void window_manager::begin(window_id window) {
void window_manager::begin_frame(window_id window) {
if (not _display) {
return;
}
@@ -120,7 +120,7 @@ void window_manager::begin(window_id window) {
_windows[window]->begin_frame();
}
void window_manager::end(window_id window) {
void window_manager::end_frame(window_id window) {
if (not _display) {
return;
}
@@ -160,6 +160,10 @@ ivec2 window_manager::_get_position(window_id id) const {
return _windows[id]->get_position();
}
irect window_manager::_get_bounds(window_id id) const {
return _windows[id]->get_bounds();
}
bool window_manager::_check_state(window_id id, uint8_t state) const {
switch (state) {
case window::state_running: return _windows[id]->is_running();

View File

@@ -11,6 +11,7 @@ add_executable(fennec-test
tests/test_threading.h
tests/test_core.h
tests/core/test_event.h
tests/core/test_version.h
)
target_compile_definitions(fennec-test PUBLIC FENNEC_TEST_CWD="${CMAKE_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME}"

View File

@@ -0,0 +1,52 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_TEST_CORE_VERSION_H
#define FENNEC_TEST_CORE_VERSION_H
#include <fennec/core/version.h>
#include "../../test.h"
namespace fennec::test
{
inline void fennec_test_core_version() {
fennec_test_run((version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }) == (version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }), true);
fennec_test_run((version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }) == (version{ .major = 1, .minor = 0, .patch = 1, .meta = 0 }), false);
fennec_test_spacer(1);
fennec_test_run((version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }) != (version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }), false);
fennec_test_run((version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }) != (version{ .major = 1, .minor = 0, .patch = 1, .meta = 0 }), true);
fennec_test_spacer(1);
fennec_test_run((version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }) < (version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }), false);
fennec_test_run((version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }) < (version{ .major = 1, .minor = 0, .patch = 1, .meta = 0 }), true);
fennec_test_spacer(1);
fennec_test_run((version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }) > (version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }), false);
fennec_test_run((version{ .major = 1, .minor = 0, .patch = 0, .meta = 0 }) > (version{ .major = 1, .minor = 0, .patch = 1, .meta = 0 }), false);
}
}
#endif // FENNEC_TEST_CORE_VERSION_H

View File

@@ -20,7 +20,7 @@
#ifndef FENNEC_TEST_MATRIX_H
#define FENNEC_TEST_MATRIX_H
#include <fennec/math/detail/_fwd.h>
#include <fennec/math/detail/_forward.h>
#include <fennec/math/matrix.h>

View File

@@ -20,18 +20,22 @@
#define FENNEC_TEST_CORE_H
#include "../test.h"
#include "core/test_event.h"
#include "core/test_version.h"
namespace fennec::test
{
inline void fennec_test_core() {
fennec_test_subheader("version");
fennec_test_spacer(2);
fennec_test_core_version();
fennec_test_spacer(3);
fennec_test_subheader("events");
fennec_test_spacer(2);
fennec_test_core_event();
fennec_test_spacer(3);
}
}

View File

@@ -33,10 +33,10 @@ namespace fennec::test
fennec_test_spacer(1);
fennec_test_run(path::current(), path(FENNEC_TEST_CWD));
fennec_test_run(path::get_current(), path(FENNEC_TEST_CWD));
fennec_test_run(path("../" FENNEC_BUILD_NAME "/./test.sh").absolute(), path(FENNEC_TEST_CWD) / "test.sh");
fennec_test_run(path("./test/../test.sh").absolute(), path(FENNEC_TEST_CWD) / "test.sh");
fennec_test_run(path::current().parent(), path("../").absolute());
fennec_test_run(path::get_current().parent(), path("../").absolute());
fennec_test_spacer(2);

View File

@@ -51,8 +51,8 @@ inline void fennec_test_platform() {
while (wm.is_running(window)) {
wm.begin(window);
wm.end(window);
wm.begin_frame(window);
wm.end_frame(window);
wm.dispatch();
}