- More Documentation
- Vulkan Configuration Implementations - Fixed build errors on GCC and Clang
This commit is contained in:
@@ -88,7 +88,6 @@ fennec_add_sources(
|
||||
include/fennec/core/logger.h source/core/logger.cpp
|
||||
|
||||
include/fennec/core/version.h
|
||||
include/fennec/core/system.h
|
||||
|
||||
|
||||
|
||||
@@ -150,12 +149,14 @@ fennec_add_sources(
|
||||
include/fennec/lang/declval.h
|
||||
include/fennec/lang/function.h
|
||||
include/fennec/lang/hashing.h
|
||||
include/fennec/lang/integer.h
|
||||
include/fennec/lang/intrinsics.h
|
||||
include/fennec/lang/limits.h
|
||||
include/fennec/lang/numeric_transforms.h
|
||||
include/fennec/lang/metasequences.h
|
||||
include/fennec/lang/ranges.h
|
||||
include/fennec/lang/static_constructor.h
|
||||
include/fennec/lang/system.h
|
||||
include/fennec/lang/type_identity.h
|
||||
include/fennec/lang/type_operators.h
|
||||
include/fennec/lang/type_sequences.h
|
||||
@@ -163,7 +164,6 @@ fennec_add_sources(
|
||||
include/fennec/lang/type_transforms.h
|
||||
include/fennec/lang/types.h
|
||||
include/fennec/lang/utility.h
|
||||
include/fennec/lang/integer.h
|
||||
|
||||
include/fennec/lang/assert.h source/lang/assert.cpp
|
||||
|
||||
@@ -179,14 +179,15 @@ fennec_add_sources(
|
||||
|
||||
|
||||
# RTTI =================================================================================================================
|
||||
include/fennec/rtti/typeid.h
|
||||
include/fennec/rtti/type_data.h
|
||||
include/fennec/rtti/type.h
|
||||
include/fennec/rtti/enable.h
|
||||
include/fennec/rtti/forward.h
|
||||
include/fennec/rtti/typelist.h
|
||||
include/fennec/rtti/type_registry.h
|
||||
include/fennec/rtti/enable.h
|
||||
include/fennec/rtti/singleton.h
|
||||
include/fennec/rtti/this_t.h
|
||||
include/fennec/rtti/type.h
|
||||
include/fennec/rtti/type_data.h
|
||||
include/fennec/rtti/type_registry.h
|
||||
include/fennec/rtti/typeid.h
|
||||
include/fennec/rtti/typelist.h
|
||||
|
||||
|
||||
include/fennec/rtti/detail/_constants.h
|
||||
@@ -268,6 +269,7 @@ fennec_add_sources(
|
||||
include/fennec/string/locale.h
|
||||
include/fennec/string/cstring.h
|
||||
include/fennec/string/string.h
|
||||
include/fennec/string/string_view.h
|
||||
|
||||
include/fennec/string/detail/_ctype.h
|
||||
|
||||
@@ -314,7 +316,9 @@ add_subdirectory(test)
|
||||
|
||||
add_library(fennec STATIC
|
||||
${FENNEC_SOURCES}
|
||||
include/fennec/rtti/this_t.h
|
||||
include/fennec/renderers/vulkan/lib/logical_device.h
|
||||
include/fennec/renderers/vulkan/lib/physical_device_properties.h
|
||||
include/fennec/renderers/vulkan/lib/physical_device_features.h
|
||||
)
|
||||
|
||||
add_dependencies(fennec metaprogramming fennec-dependencies)
|
||||
|
||||
@@ -155,7 +155,6 @@ is also a viable IDE but involves some extra setup.
|
||||
|------------------------------|----------------------------------------------------------------------------------------------------------|
|
||||
| C/C++ Compiler | GCC/G++ is the compiler that fennec is designed around, however, Clang, MSVC, and MinGW may also be used |
|
||||
| CMake | The build manager used by the engine |
|
||||
| Volk<sup>[*](#opt)</sup> | The Vulkan loader Volk, includes necessary headers for Vulkan. |
|
||||
| A build system | Any build system will work, however, `build.sh` uses Ninja by default. |
|
||||
| A memory debugger | Any memory debugger will work, however, `test.sh` uses Valgrind by default. |
|
||||
| Doxygen<sup>[*](#opt)</sup> | Doxygen is required for building the documentation for fennec. |
|
||||
|
||||
@@ -18,11 +18,22 @@
|
||||
|
||||
# this script handles functionality related to the build process and its info
|
||||
|
||||
# Acquire the build name
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} FENNEC_BUILD_NAME)
|
||||
message(STATUS "Build: ${FENNEC_BUILD_NAME}")
|
||||
|
||||
# Add build name to the compile definitions
|
||||
fennec_add_definitions(FENNEC_BUILD_NAME="${FENNEC_BUILD_NAME}")
|
||||
|
||||
# Check if building for debug
|
||||
if(${FENNEC_BUILD_NAME} MATCHES "debug")
|
||||
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_RELEASE=false)
|
||||
fennec_add_definitions(FENNEC_RELEASE=false FENNEC_DEBUG=true)
|
||||
|
||||
# Release with debug info
|
||||
elseif(${FENNEC_BUILD_NAME} MATCHES "relwithdebinfo")
|
||||
fennec_add_definitions(FENNEC_RELEASE=true FENNEC_DEBUG=true)
|
||||
|
||||
# Any others are considered release without debugging
|
||||
else()
|
||||
list(APPEND FENNEC_COMPILE_DEFINITIONS FENNEC_RELEASE=true)
|
||||
fennec_add_definitions(FENNEC_RELEASE=true FENNEC_DEBUG=false)
|
||||
endif()
|
||||
38
cmake/clang.cmake
Normal file
38
cmake/clang.cmake
Normal file
@@ -0,0 +1,38 @@
|
||||
# ======================================================================================================================
|
||||
# fennec, a free and open source game engine
|
||||
# Copyright © 2025 - 2026 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/>.
|
||||
# ======================================================================================================================
|
||||
|
||||
# this script sets flags and variables for llvm compilers
|
||||
|
||||
# Receive all warnings and treat as errors
|
||||
add_compile_options("-Wall" "-Wextra" "-pedantic" "-Werror" "-fms-extensions")
|
||||
|
||||
# Use relative directories to hide the user's directory
|
||||
fennec_add_compile_options("-ffile-prefix-map=${FENNEC_SOURCE_DIR}=.")
|
||||
|
||||
# Disable STDLIB, Exceptions, and RTTI, we implement our own. Also include diagnostics and pthread.
|
||||
fennec_add_link_options("-nostdlib" "-fno-exceptions" "-fno-rtti" "-fdiagnostics-all-candidates" "-pthread")
|
||||
|
||||
# Base definitions for Clang
|
||||
fennec_add_definitions(
|
||||
_GLIBCXX_INCLUDE_NEXT_C_HEADERS=1
|
||||
FENNEC_COMPILER_CLANG=1
|
||||
FENNEC_GLIBC=1
|
||||
FENNEC_NO_INLINE=[[clang::noinline]]
|
||||
FENNEC_FUNCTION_NAME=__PRETTY_FUNCTION__
|
||||
)
|
||||
|
||||
@@ -18,13 +18,27 @@
|
||||
|
||||
# this script finds the compiler being used
|
||||
|
||||
# Send a message letting us know the compiler and its version
|
||||
message(STATUS "Compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
|
||||
|
||||
# Add definitions for the compiler
|
||||
fennec_add_definitions(
|
||||
FENNEC_LONG_COMPILER_NAME="${CMAKE_CXX_COMPILER_ID} ${CMAKE_SYSTEM_NAME} ${CMAKE_SYSTEM_PROCESSOR}"
|
||||
)
|
||||
|
||||
# GCC
|
||||
if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
|
||||
set(FENNEC_COMPILER "GCC")
|
||||
include("${FENNEC_SOURCE_DIR}/cmake/gcc.cmake")
|
||||
set(FENNEC_COMPILER "GCC")
|
||||
include("${FENNEC_SOURCE_DIR}/cmake/gcc.cmake")
|
||||
endif()
|
||||
|
||||
# Clang
|
||||
if(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
|
||||
set(FENNEC_COMPILER "Clang")
|
||||
include("${FENNEC_SOURCE_DIR}/cmake/clang.cmake")
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
# TODO: MSVC & MinGW
|
||||
|
||||
|
||||
@@ -18,15 +18,20 @@
|
||||
|
||||
# this script sets flags and variables for gnu and gnu-like compilers
|
||||
|
||||
# Receive all warnings and treat as errors
|
||||
add_compile_options("-Wall" "-Wextra" "-pedantic" "-Werror" "-fms-extensions")
|
||||
|
||||
# Use relative directories to hide the user's directory
|
||||
fennec_add_compile_options("-ffile-prefix-map=${FENNEC_SOURCE_DIR}=.")
|
||||
|
||||
# Disable STDLIB, Exceptions, and RTTI, we implement our own. Also include diagnostics and pthread.
|
||||
fennec_add_link_options("-nostdlib" "-fno-exceptions" "-fno-rtti" "-fdiagnostics-all-candidates" "-pthread")
|
||||
|
||||
# Base definitions for GCC
|
||||
fennec_add_definitions(
|
||||
_GLIBCXX_INCLUDE_NEXT_C_HEADERS=1
|
||||
FENNEC_COMPILER_GCC=1
|
||||
FENNEC_GLIBC=1
|
||||
FENNEC_NO_INLINE=[[gnu::noinline]]
|
||||
FENNEC_FUNCTION_NAME=__PRETTY_FUNCTION__
|
||||
)
|
||||
|
||||
@@ -33,9 +33,11 @@ macro(fennec_check_platform)
|
||||
include/fennec/platform/linux/platform.h source/platform/linux/platform.cpp
|
||||
)
|
||||
|
||||
# Add display and graphics for client builds.
|
||||
if(FENNEC_USER_CLIENT)
|
||||
include("${FENNEC_SOURCE_DIR}/cmake/wayland.cmake")
|
||||
|
||||
fennec_init_graphics()
|
||||
fennec_check_wayland()
|
||||
fennec_init_graphics()
|
||||
endif()
|
||||
|
||||
@@ -18,9 +18,10 @@
|
||||
|
||||
find_package(OpenGL)
|
||||
|
||||
# Check if EGL is desired
|
||||
if(FENNEC_GRAPHICS_WANT_EGL)
|
||||
fennec_add_sources(
|
||||
include/fennec/platform/opengl/egl/fwd.h
|
||||
include/fennec/platform/opengl/egl/forward.h
|
||||
include/fennec/platform/opengl/egl/error.h
|
||||
include/fennec/platform/opengl/egl/context.h source/platform/opengl/egl/context.cpp
|
||||
include/fennec/platform/opengl/egl/surface.h source/platform/opengl/egl/surface.cpp
|
||||
@@ -29,15 +30,24 @@ if(FENNEC_GRAPHICS_WANT_EGL)
|
||||
)
|
||||
endif()
|
||||
|
||||
# Check that we found OpenGL
|
||||
if(TARGET OpenGL::GL)
|
||||
|
||||
# Link & add definitions for OpenGL
|
||||
fennec_add_link_libraries(OpenGL::GL)
|
||||
fennec_add_definitions(FENNEC_GRAPHICS_OPENGL=1)
|
||||
|
||||
# Cmake Definition for OpenGL detection
|
||||
set(FENNEC_FOUND_OPENGL TRUE)
|
||||
|
||||
# Add OpenGL sources
|
||||
fennec_add_sources(
|
||||
include/fennec/platform/opengl/glad/gl.h source/platform/opengl/glad/gl.c
|
||||
|
||||
include/fennec/renderers/opengl/glcontext.h source/renderers/opengl/glcontext.cpp
|
||||
)
|
||||
else()
|
||||
|
||||
# OpenGL is required if included.
|
||||
message(FATAL_ERROR "No Suitable OpenGL implementation found.")
|
||||
endif()
|
||||
@@ -28,7 +28,7 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
include("${FENNEC_SOURCE_DIR}/cmake/linux.cmake")
|
||||
endif ()
|
||||
|
||||
# Graphics APIs
|
||||
# Include graphics APIs Second time for any platform specific requirements
|
||||
macro(fennec_init_graphics)
|
||||
include("${FENNEC_SOURCE_DIR}/cmake/opengl.cmake")
|
||||
include("${FENNEC_SOURCE_DIR}/cmake/vulkan.cmake")
|
||||
|
||||
@@ -18,12 +18,15 @@
|
||||
|
||||
# this script contains the main version
|
||||
|
||||
# Fennec Version Definition
|
||||
# These should only get updated whenever a new release occurs
|
||||
set(FENNEC_VERSION_MAJOR 0)
|
||||
set(FENNEC_VERSION_MINOR 1)
|
||||
set(FENNEC_VERSION_PATCH 0)
|
||||
set(FENNEC_VERSION_STRING "${FENNEC_VERSION_MAJOR}.${FENNEC_VERSION_MINOR}.${FENNEC_VERSION_PATCH}")
|
||||
math(EXPR FENNEC_VERSION_NUM "(${FENNEC_VERSION_MAJOR} << 16) | (${FENNEC_VERSION_MINOR} << 8) | ${FENNEC_VERSION_PATCH}")
|
||||
|
||||
# Define the versions for compilation
|
||||
list(APPEND FENNEC_COMPILE_DEFINITIONS
|
||||
FENNEC_VERSION_MAJOR=${FENNEC_VERSION_MAJOR}
|
||||
FENNEC_VERSION_MINOR=${FENNEC_VERSION_MINOR}
|
||||
|
||||
@@ -16,24 +16,41 @@
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
# ======================================================================================================================
|
||||
|
||||
find_package(Vulkan COMPONENTS glslang volk)
|
||||
find_package(Vulkan COMPONENTS glslang)
|
||||
|
||||
# MoltenVK for Apple Products
|
||||
if(FENNEC_GRAPHICS_WANT_MOLTENVK)
|
||||
find_package(Vulkan COMPONENTS MoltenVK)
|
||||
endif()
|
||||
|
||||
if( TARGET Vulkan::Headers AND TARGET Vulkan::volk # Base Headers and Meta-Loader
|
||||
|
||||
# Headers and Loaders
|
||||
if( TARGET Vulkan::Headers # Base Headers and Meta-Loader
|
||||
AND TARGET Vulkan::glslang # GLSL Compilation
|
||||
AND (NOT FENNEC_GRAPHICS_WANT_MOLTENVK OR TARGET Vulkan::MoltenVK)
|
||||
)
|
||||
fennec_add_link_libraries(Vulkan::volk Vulkan::glslang)
|
||||
# Link & Define Vulkan Libraries
|
||||
fennec_add_link_libraries(Vulkan::glslang)
|
||||
fennec_add_definitions(FENNEC_GRAPHICS_VULKAN=1)
|
||||
|
||||
fennec_add_sources(
|
||||
include/fennec/renderers/vulkan/lib/app_info.h
|
||||
include/fennec/renderers/vulkan/lib/instance.h
|
||||
# Cmake Definition for Vulkan detection
|
||||
set(FENNEC_FOUND_VULKAN TRUE)
|
||||
|
||||
include/fennec/renderers/vulkan/vkcontext.h include/fennec/renderers/vulkan/vkcontext.cpp
|
||||
# Add Vulkan Sources
|
||||
fennec_add_sources(
|
||||
include/fennec/renderers/vulkan/lib/forward.h
|
||||
|
||||
include/fennec/renderers/vulkan/lib/app_info.h
|
||||
include/fennec/renderers/vulkan/lib/debug.h
|
||||
include/fennec/renderers/vulkan/lib/enum.h
|
||||
include/fennec/renderers/vulkan/lib/instance.h
|
||||
include/fennec/renderers/vulkan/lib/physical_device.h
|
||||
include/fennec/renderers/vulkan/lib/surface.h
|
||||
|
||||
include/fennec/platform/vulkan/volk/volk.h source/platform/vulkan/volk/volk.c
|
||||
|
||||
include/fennec/renderers/vulkan/vkcontext.h source/renderers/vulkan/vkcontext.cpp
|
||||
include/fennec/renderers/vulkan/vksurface.h source/renderers/vulkan/vksurface.cpp
|
||||
)
|
||||
else()
|
||||
message(WARNING "No Suitable Vulkan implementation found.")
|
||||
|
||||
@@ -70,11 +70,12 @@ macro(fennec_check_wayland)
|
||||
NAMES wayland-egl libwayland-egl
|
||||
)
|
||||
|
||||
|
||||
# Check that we have found everything needed for Wayland
|
||||
if( (WAYLAND_CLIENT_INCLUDE_DIR AND WAYLAND_CLIENT_LIBRARY AND WAYLAND_SCANNER)
|
||||
AND (WAYLAND_EGL_INCLUDE_DIR AND WAYLAND_EGL_LIBRARY))
|
||||
message(STATUS "Found Wayland: ${WAYLAND_CLIENT_LIBRARY}")
|
||||
|
||||
# Wayland Directories
|
||||
set(WAYLAND_PROTOCOLS_DIR ${FENNEC_SOURCE_DIR}/include/fennec/platform/linux/wayland/lib/protocols)
|
||||
set(WAYLAND_HEADERS_DIR ${FENNEC_SOURCE_DIR}/include/fennec/platform/linux/wayland/lib/headers)
|
||||
set(WAYLAND_SOURCES_DIR ${FENNEC_SOURCE_DIR}/source/platform/linux/wayland/lib/sources)
|
||||
@@ -117,7 +118,7 @@ macro(fennec_check_wayland)
|
||||
include/fennec/platform/linux/wayland/lib/loader.h source/platform/linux/wayland/lib/loader.cpp
|
||||
|
||||
# Fennec Files
|
||||
include/fennec/platform/linux/wayland/fwd.h
|
||||
include/fennec/platform/linux/wayland/forward.h
|
||||
include/fennec/platform/linux/wayland/server.h source/platform/linux/wayland/server.cpp
|
||||
include/fennec/platform/linux/wayland/window.h source/platform/linux/wayland/window.cpp
|
||||
|
||||
@@ -126,6 +127,12 @@ macro(fennec_check_wayland)
|
||||
include/fennec/platform/linux/wayland/egl/surface.h source/platform/linux/wayland/egl/surface.cpp
|
||||
)
|
||||
|
||||
if(FENNEC_FOUND_VULKAN)
|
||||
fennec_add_sources(
|
||||
include/fennec/platform/linux/wayland/vulkan/context.h source/platform/linux/wayland/vulkan/context.cpp
|
||||
)
|
||||
endif ()
|
||||
|
||||
fennec_add_definitions(
|
||||
FENNEC_HAS_WAYLAND=1
|
||||
FENNEC_LIB_WAYLAND="${WAYLAND_CLIENT_LIBRARY}"
|
||||
|
||||
@@ -283,7 +283,8 @@ TAB_SIZE = 4
|
||||
# with the commands \{ and \} for these it is advised to use the version @{ and
|
||||
# @} or use a double escape (\\{ and \\})
|
||||
|
||||
ALIASES =
|
||||
ALIASES = emph{1}="\f$\textbf{\1}\f$" \
|
||||
math{1}="\f$\1\f$"
|
||||
|
||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
|
||||
# only. Doxygen will then generate output that is more tailored for C. For
|
||||
|
||||
@@ -44,20 +44,19 @@ namespace fennec
|
||||
/// \brief Data Structure that defines a compile-time allocated array
|
||||
///
|
||||
/// \details
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:----------:|
|
||||
/// | stable | ✅ |
|
||||
/// | dynamic | ⛔ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | linear | ✅ |
|
||||
/// | access | \f$O(1)\f$ |
|
||||
/// | find | \f$O(N)\f$ |
|
||||
/// | insertion | ⛔ |
|
||||
/// | deletion | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:-----------:|
|
||||
/// | stable | ✅ |
|
||||
/// | dynamic | ⛔ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | linear | ✅ |
|
||||
/// | space | \emph{O(N)} |
|
||||
/// | access | \emph{O(1)} |
|
||||
/// | find | \emph{O(N)} |
|
||||
/// | insertion | ⛔ |
|
||||
/// | deletion | ⛔ |
|
||||
///
|
||||
/// \tparam ValueT value type
|
||||
/// \tparam N number of elements
|
||||
@@ -70,7 +69,7 @@ public:
|
||||
/// \name Definitions
|
||||
/// @{
|
||||
|
||||
using value_t = ValueT; //!< Alias for \f$ValueT\f$
|
||||
using value_t = ValueT; //!< Alias for \emph{ValueT}
|
||||
|
||||
/// @}
|
||||
|
||||
@@ -96,21 +95,21 @@ public:
|
||||
|
||||
///
|
||||
/// \brief Returns the number of elements in the array.
|
||||
/// \returns \f$N\f$
|
||||
/// \returns \emph{N}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
[[nodiscard]] constexpr size_t size() const { return N; }
|
||||
constexpr size_t size() const { return N; }
|
||||
|
||||
///
|
||||
/// \brief Returns \f$true\f$ when the array is empty
|
||||
/// \returns \f$ElemV == 0\f$
|
||||
/// \brief Returns \emph{true} when the array is empty
|
||||
/// \returns \math{\textbf{ElemV} == 0}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
[[nodiscard]] constexpr bool_t is_empty() const { return N == 0; }
|
||||
constexpr bool_t is_empty() const { return N == 0; }
|
||||
|
||||
/// @}
|
||||
|
||||
@@ -128,7 +127,7 @@ public:
|
||||
/// \return reference to the requested element
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr value_t& operator[](size_t i) {
|
||||
assertd(i < N, "Array Out of Bounds");
|
||||
@@ -142,7 +141,7 @@ public:
|
||||
/// \return reference to the requested element
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const value_t& operator[](size_t i) const {
|
||||
assertd(i < N, "Array Out of Bounds");
|
||||
@@ -150,10 +149,10 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns A reference to \f$data[0]\f$
|
||||
/// \returns A reference to \math{\textbf{data}[0]}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr value_t& front() {
|
||||
return data[0];
|
||||
@@ -161,20 +160,20 @@ public:
|
||||
|
||||
///
|
||||
/// \brief Access the first element
|
||||
/// \returns A const-qualified reference to \f$data[0]\f$
|
||||
/// \returns A const-qualified reference to \math{\textbf{data}[0]}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const value_t& front() const {
|
||||
return data[0];
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns A reference to \f$data[N - 1]\f$
|
||||
/// \returns A reference to \math{\textbf{data}[\textbf{N} - 1]}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr value_t& back() {
|
||||
return data[N - 1];
|
||||
@@ -182,10 +181,10 @@ public:
|
||||
|
||||
///
|
||||
/// \brief Access the last element
|
||||
/// \returns A const-qualified reference to \f$data[N - 1]\f$
|
||||
/// \returns A const-qualified reference to \math{\textbf{data}[\textbf{N} - 1]}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const value_t& back() const {
|
||||
return data[N - 1];
|
||||
@@ -205,7 +204,7 @@ public:
|
||||
/// \brief Checks if all elements in the arrays are equal
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
friend constexpr bool_t operator==(const array& lhs, const array& rhs) {
|
||||
return array::_compare(lhs, rhs, make_index_metasequence<N>{});
|
||||
@@ -215,7 +214,7 @@ public:
|
||||
/// \brief Checks if any element in the arrays is not equal
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
friend constexpr bool_t operator!=(const array& lhs, const array& rhs) {
|
||||
return not array::_compare(lhs, rhs, make_index_metasequence<N>{});
|
||||
@@ -234,18 +233,18 @@ public:
|
||||
/// \returns A pointer to the first element of the array
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr value_t* begin() {
|
||||
return data;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$begin()\f$
|
||||
/// \brief C++ Iterator Specification \emph{begin()}
|
||||
/// \returns A const-qualified pointer to the first element of the array
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const value_t* begin() const {
|
||||
return data;
|
||||
@@ -255,18 +254,18 @@ public:
|
||||
/// \returns A pointer to one after the end of the array
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr value_t* end() {
|
||||
return data + N;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$end()\f$
|
||||
/// \brief C++ Iterator Specification \emph{end()}
|
||||
/// \returns A const-qualified pointer to one after the end of the array
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const value_t* end() const {
|
||||
return data + N;
|
||||
|
||||
@@ -31,34 +31,34 @@
|
||||
#ifndef FENNEC_CONTAINERS_BINTREE_H
|
||||
#define FENNEC_CONTAINERS_BINTREE_H
|
||||
|
||||
#include <fennec/memory/allocator.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>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief Structure defining a binary tree
|
||||
/// \brief Structure defining an in-array binary tree
|
||||
///
|
||||
/// \details
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | linear | ⛔ |
|
||||
/// | access | \f$O(1)\f$ |
|
||||
/// | find | \f$O(N)\f$ |
|
||||
/// | insertion | \f$O(1)\f$ |
|
||||
/// | deletion | \f$O(1)\f$ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:-----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | linear | ⛔ |
|
||||
/// | space | \emph{O(N)} |
|
||||
/// | access | \emph{O(1)} |
|
||||
/// | find | \emph{O(N)} |
|
||||
/// | insertion | \emph{O(1)} |
|
||||
/// | deletion | \emph{O(1)} |
|
||||
///
|
||||
/// \tparam TypeT The data type
|
||||
/// \tparam AllocT An allocator class
|
||||
@@ -107,7 +107,7 @@ public:
|
||||
/// \details The underlying allocation is not initialized.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bintree()
|
||||
: _table()
|
||||
@@ -120,10 +120,10 @@ 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$
|
||||
/// \details Takes ownership of the underlying allocation of \emph{tree}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bintree(bintree&& tree) noexcept
|
||||
: _table(fennec::move(tree._table))
|
||||
@@ -136,10 +136,10 @@ 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.
|
||||
/// \details Copies the contents of \emph{tree} into a new tree. Invokes copy constructor.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr bintree(const bintree& tree)
|
||||
: _table(tree._table.capacity())
|
||||
@@ -173,10 +173,10 @@ public:
|
||||
///
|
||||
/// \brief Destructor, clears the tree
|
||||
///
|
||||
/// \details Clears the contents of \f$tree\f$. Invokes destructor.
|
||||
/// \details Clears the contents of \emph{tree}. Invokes destructor.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr ~bintree() {
|
||||
clear();
|
||||
@@ -195,17 +195,17 @@ public:
|
||||
/// \returns The number of elements in the tree
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns \f$true\f$ when there are no elements in the tree, \f$false\f$ otherwise.
|
||||
/// \returns \emph{true} when there are no elements in the tree, \emph{false} otherwise.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool is_empty() const {
|
||||
return _size == 0;
|
||||
@@ -215,17 +215,17 @@ public:
|
||||
/// \returns The capacity of the underlying allocation
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t capacity() const {
|
||||
return _table.capacity();
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns The next id to be returned by \f$insert\f$ or \f$emplace\f$.
|
||||
/// \returns The next id to be returned by `bintree::insert` or `bintree::emplace`.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t next_id() const {
|
||||
size_t i = _size;
|
||||
@@ -236,10 +236,10 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns The next id to be returned by \f$insert\f$ or \f$emplace\f$.
|
||||
/// \returns The next id to be returned by `bintree::insert` or `bintree::emplace`.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t root() const {
|
||||
return _root;
|
||||
@@ -257,10 +257,10 @@ public:
|
||||
|
||||
///
|
||||
/// \param i The node id
|
||||
/// \returns The parent of node \f$i\f$
|
||||
/// \returns The parent of node \emph{i}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t parent(size_t i) const {
|
||||
return i == npos ? npos : _table[i].parent;
|
||||
@@ -268,10 +268,10 @@ public:
|
||||
|
||||
///
|
||||
/// \param i The node id
|
||||
/// \returns The grandparent of node \f$i\f$
|
||||
/// \returns The grandparent of node \emph{i}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t grandparent(size_t i) const {
|
||||
return parent(parent(i));
|
||||
@@ -279,10 +279,10 @@ public:
|
||||
|
||||
///
|
||||
/// \param i The node id
|
||||
/// \returns The left child of node \f$i\f$
|
||||
/// \returns The left child of node \emph{i}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t left(size_t i) const {
|
||||
return i == npos ? npos : _table[i].child[false];
|
||||
@@ -290,10 +290,10 @@ public:
|
||||
|
||||
///
|
||||
/// \param i The node id
|
||||
/// \returns The right child of node \f$i\f$
|
||||
/// \returns The right child of node \emph{i}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t right(size_t i) const {
|
||||
return i == npos ? npos : _table[i].child[true];
|
||||
@@ -301,11 +301,11 @@ public:
|
||||
|
||||
///
|
||||
/// \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$
|
||||
/// \param dir The direction to go \emph{true} for right, \emph{false} for left
|
||||
/// \returns The child in the direction specified by \emph{dir}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t child(size_t i, bool dir) const {
|
||||
return i == npos ? npos : _table[i].child[dir];
|
||||
@@ -313,10 +313,10 @@ public:
|
||||
|
||||
///
|
||||
/// \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
|
||||
/// \returns \emph{true} if \emph{i} is the right node of \emph{parent(i)}, \emph{false} otherwise
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool side(size_t i) const {
|
||||
return i == npos ? false : i == right(_parent(i));
|
||||
@@ -324,10 +324,10 @@ public:
|
||||
|
||||
///
|
||||
/// \param i The id of the node
|
||||
/// \returns The id of the sibling of \f$i\f$
|
||||
/// \returns The id of the sibling of \emph{i}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t sibling(size_t i) const {
|
||||
if (i == npos) {
|
||||
@@ -337,16 +337,16 @@ public:
|
||||
return npos;
|
||||
}
|
||||
size_t p = _parent(i);
|
||||
bool d = i == _right(p);
|
||||
const bool d = i == _right(p);
|
||||
return _child(p, !d);
|
||||
}
|
||||
|
||||
///
|
||||
/// \param i The node id
|
||||
/// \returns The depth of node \f$i\f$
|
||||
/// \returns The depth of node \emph{i}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(\log n)\f$
|
||||
/// \emph{O(\log n)}
|
||||
///
|
||||
constexpr size_t depth(size_t i) const {
|
||||
size_t d = 0;
|
||||
@@ -359,10 +359,10 @@ public:
|
||||
|
||||
///
|
||||
/// \param i The node id
|
||||
/// \returns The id of the left-most node of \f$i\f$
|
||||
/// \returns The id of the left-most node of \emph{i}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(\log n)\f$
|
||||
/// \emph{O(\log n)}
|
||||
///
|
||||
constexpr size_t left_most(size_t i) const {
|
||||
if (i >= _table.size()) {
|
||||
@@ -376,10 +376,10 @@ public:
|
||||
|
||||
///
|
||||
/// \param i The node id
|
||||
/// \returns The id of the right-most node of \f$i\f$
|
||||
/// \returns The id of the right-most node of \emph{i}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(\log n)\f$
|
||||
/// \emph{O(\log n)}
|
||||
///
|
||||
constexpr size_t right_most(size_t i) const {
|
||||
if (i >= _table.size()) {
|
||||
@@ -402,10 +402,10 @@ public:
|
||||
|
||||
///
|
||||
/// \param i The node id
|
||||
/// \returns a reference to the value of node \f$i\f$
|
||||
/// \returns a reference to the value of node \emph{i}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr value_t& operator[](size_t i) {
|
||||
assertd(i < _table.size(), "Index out of bounds.");
|
||||
@@ -415,10 +415,10 @@ public:
|
||||
///
|
||||
/// \details Node access
|
||||
/// \param i The node id
|
||||
/// \returns a reference to the value of node \f$i\f$
|
||||
/// \returns a reference to the value of node \emph{i}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const value_t& operator[](size_t i) const {
|
||||
assertd(i < _table.size(), "Index out of bounds.");
|
||||
@@ -435,40 +435,40 @@ public:
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \details If the left node of \f$p\f$ already exists, the move assignment operator is used instead
|
||||
/// \details If the left node of \emph{p} already exists, the move assignment operator is used instead
|
||||
/// \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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t insert_left(size_t p, value_t&& val) {
|
||||
return this->_insert_left(p, fennec::forward<value_t>(val));
|
||||
}
|
||||
|
||||
///
|
||||
/// \details If the left node of \f$p\f$ already exists, the copy assignment operator is used instead
|
||||
/// \details If the left node of \emph{p} already exists, the copy assignment operator is used instead
|
||||
/// \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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t insert_left(size_t p, const value_t& val) {
|
||||
return this->_insert_left(p, val);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Left Insertion, constructs a new node as the left child of \f$p\f$
|
||||
/// \details If the left node of \f$p\f$ already exists, the move assignment operator is used instead
|
||||
/// \brief Left Insertion, constructs a new node as the left child of \emph{p}
|
||||
/// \details If the left node of \emph{p} already exists, the move assignment operator is used instead
|
||||
/// \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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr size_t emplace_left(size_t p, ArgsT&&...args) {
|
||||
@@ -476,40 +476,40 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \details If the right node of \f$p\f$ already exists, the move assignment operator is used instead
|
||||
/// \details If the right node of \emph{p} already exists, the move assignment operator is used instead
|
||||
/// \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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t insert_right(size_t p, value_t&& val) {
|
||||
return this->_insert_right(p, fennec::forward<value_t>(val));
|
||||
}
|
||||
|
||||
///
|
||||
/// \details If the right node of \f$p\f$ already exists, the copy assignment operator is used instead
|
||||
/// \details If the right node of \emph{p} already exists, the copy assignment operator is used instead
|
||||
/// \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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t insert_right(size_t p, const value_t& val) {
|
||||
return this->_insert_right(p, val);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Right Insertion, constructs a new node as the right child of \f$p\f$
|
||||
/// \details If the right node of \f$p\f$ already exists, the move assignment operator is used instead
|
||||
/// \brief Right Insertion, constructs a new node as the right child of \emph{p}
|
||||
/// \details If the right node of \emph{p} already exists, the move assignment operator is used instead
|
||||
/// \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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr size_t emplace_right(size_t p, ArgsT&&...args) {
|
||||
@@ -519,21 +519,21 @@ public:
|
||||
|
||||
|
||||
///
|
||||
/// \brief Perform a Tree Rotation at \f$i\f$ in the specified direction
|
||||
/// \brief Perform a Tree Rotation at \emph{i} in the specified direction
|
||||
/// \param sub The root node for the rotation
|
||||
/// \param dir The direction to rotate, \f$true\f$ for right, \f$false\f$ for left
|
||||
/// \param dir The direction to rotate, \emph{true} for right, \emph{false} for left
|
||||
/// \returns the new root node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t rotate(size_t sub, bool dir) {
|
||||
if (sub == npos) {
|
||||
return npos;
|
||||
}
|
||||
size_t sub_parent = _parent(sub);
|
||||
size_t new_root = _child(sub, not dir);
|
||||
size_t new_child = _child(new_root, dir);
|
||||
const size_t sub_parent = _parent(sub);
|
||||
const size_t new_root = _child(sub, not dir);
|
||||
const size_t new_child = _child(new_root, dir);
|
||||
|
||||
_child(sub, not dir) = new_child;
|
||||
if (new_child != npos) {
|
||||
@@ -552,43 +552,43 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \details If the child of \f$p\f$ already exists, the move assignment operator is used instead
|
||||
/// \details If the child of \emph{p} already exists, the move assignment operator is used instead
|
||||
/// \param parent The parent node
|
||||
/// \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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t insert(size_t parent, bool side, value_t&& val) {
|
||||
return this->_insert(parent, side, fennec::forward<value_t>(val));
|
||||
}
|
||||
|
||||
///
|
||||
/// \details If the child of \f$p\f$ already exists, the copy assignment operator is used instead
|
||||
/// \details If the child of \emph{p} already exists, the copy assignment operator is used instead
|
||||
/// \param parent The parent node
|
||||
/// \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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t insert(size_t parent, bool side, const value_t& val) {
|
||||
return this->_insert(parent, side, val);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Insertion, constructs a new node as the child of \f$p\f$
|
||||
/// \details If the child of \f$p\f$ already exists, the move assignment operator is used instead
|
||||
/// \brief Insertion, constructs a new node as the child of \emph{p}
|
||||
/// \details If the child of \emph{p} already exists, the move assignment operator is used instead
|
||||
/// \param parent The parent node
|
||||
/// \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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr size_t emplace(size_t parent, bool side, ArgsT&&...args) {
|
||||
@@ -599,7 +599,7 @@ public:
|
||||
/// \brief Clears the tree, destroying all elements
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr void clear() {
|
||||
list<size_t> queue;
|
||||
@@ -636,16 +636,16 @@ public:
|
||||
|
||||
///
|
||||
/// \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 accept a reference to a value of type \emph{TypeT} and a \emph{size_t} which contains the node's id.
|
||||
/// The visitor should return one of the following values in the `fennec::traversal_control_` enum
|
||||
///
|
||||
/// \tparam OrderT The order with which to traverse the tree.
|
||||
/// \tparam VisitorT The visitor, should fulfill the signature \f$uint8_t visit(TypeT&, size_t)\f$
|
||||
/// \tparam VisitorT The visitor, should fulfill the signature \emph{uint8_t visit(TypeT&, size_t)}
|
||||
/// \param visit The visiting object
|
||||
/// \param i The node to start at
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename OrderT, typename VisitorT>
|
||||
constexpr void traverse(VisitorT&& visit, size_t i) {
|
||||
@@ -667,16 +667,16 @@ 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 accept a reference to a value of type \emph{TypeT} and a \emph{size_t} which contains the node's id.
|
||||
/// The visitor should return one of the following values in the `fennec::traversal_control_` enum
|
||||
///
|
||||
/// \tparam OrderT The order with which to traverse the tree.
|
||||
/// \tparam VisitorT The visitor, should fulfill the signature \f$uint8_t visit(TypeT&, size_t)\f$
|
||||
/// \tparam VisitorT The visitor, should fulfill the signature \emph{uint8_t visit(TypeT&, size_t)}
|
||||
/// \param visit The visiting object
|
||||
/// \param i The node to start at
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename OrderT, typename VisitorT>
|
||||
constexpr void traverse(VisitorT&& visit, size_t i) const {
|
||||
@@ -717,9 +717,9 @@ public:
|
||||
return npos;
|
||||
}
|
||||
|
||||
size_t lft = tree.left(tree.parent(node));
|
||||
size_t nxt = lft == node ? tree.right(tree.parent(node)) : npos;
|
||||
size_t chd = tree.left(node);
|
||||
const size_t lft = tree.left(tree.parent(node));
|
||||
const size_t nxt = lft == node ? tree.right(tree.parent(node)) : npos;
|
||||
const size_t chd = tree.left(node);
|
||||
|
||||
if (nxt != npos && node != head) {
|
||||
visit.push_front(nxt);
|
||||
@@ -769,7 +769,7 @@ public:
|
||||
}
|
||||
|
||||
size_t nxt = tree.right(tree.parent(node));
|
||||
size_t chd = tree.left(node);
|
||||
const size_t chd = tree.left(node);
|
||||
nxt = node == nxt ? npos : nxt;
|
||||
|
||||
if (nxt != npos && node != head) {
|
||||
@@ -792,7 +792,7 @@ public:
|
||||
|
||||
private:
|
||||
list<size_t> visit;
|
||||
size_t head;
|
||||
size_t head = { 0 };
|
||||
};
|
||||
|
||||
///
|
||||
@@ -819,9 +819,9 @@ public:
|
||||
return npos;
|
||||
}
|
||||
|
||||
size_t parent = tree.parent(node);
|
||||
size_t pright = tree.right(parent);
|
||||
size_t next = tree.left_most(tree.right(node));
|
||||
const size_t parent = tree.parent(node);
|
||||
const size_t pright = tree.right(parent);
|
||||
const size_t next = tree.left_most(tree.right(node));
|
||||
|
||||
if (node != pright && parent != npos) {
|
||||
visit.push_front(parent);
|
||||
@@ -843,7 +843,7 @@ public:
|
||||
|
||||
private:
|
||||
list<size_t> visit;
|
||||
size_t head;
|
||||
size_t head = { 0 };
|
||||
};
|
||||
|
||||
///
|
||||
@@ -870,15 +870,15 @@ public:
|
||||
return npos;
|
||||
}
|
||||
|
||||
size_t parent = tree.parent(node);
|
||||
size_t pright = tree.right(parent);
|
||||
const size_t parent = tree.parent(node);
|
||||
const size_t right = tree.right(parent);
|
||||
|
||||
if (node == pright) {
|
||||
if (node == right) {
|
||||
if (parent != npos) {
|
||||
visit.push_front(parent);
|
||||
}
|
||||
} else if (pright != npos) {
|
||||
visit.push_front(this->_successor(tree, pright));
|
||||
} else if (right != npos) {
|
||||
visit.push_front(this->_successor(tree, right));
|
||||
}
|
||||
|
||||
if (not visit.is_empty()) {
|
||||
@@ -894,7 +894,7 @@ public:
|
||||
|
||||
private:
|
||||
list<size_t> visit;
|
||||
size_t head;
|
||||
size_t head = { 0 };
|
||||
|
||||
constexpr size_t _successor(const bintree& tree, size_t n) {
|
||||
size_t s = tree.left_most(n);
|
||||
@@ -919,7 +919,7 @@ public:
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$iterator\f$
|
||||
/// \brief C++ Iterator Specification \emph{iterator}
|
||||
/// \details Performs pre-order traversal
|
||||
class iterator {
|
||||
|
||||
@@ -954,7 +954,7 @@ public:
|
||||
|
||||
///
|
||||
/// \brief iterator pre-increment operator
|
||||
/// \returns A reference to self after having stepped to the next node
|
||||
/// \returns A reference to \emph{this} after having stepped to the next node
|
||||
iterator& operator++() {
|
||||
return _n = _order[*_tree, _n, traversal_control_continue], *this;
|
||||
}
|
||||
@@ -988,7 +988,7 @@ public:
|
||||
///
|
||||
/// \brief iterator equality operator
|
||||
/// \param it the iterator to compare with
|
||||
/// \returns \f$true\f$ if iterators are identical, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if iterators are identical, \emph{false} otherwise
|
||||
constexpr bool operator==(const iterator& it) {
|
||||
return _tree == it._tree and _n == it._n;
|
||||
}
|
||||
@@ -996,7 +996,7 @@ public:
|
||||
///
|
||||
/// \brief iterator inequality operator
|
||||
/// \param it the iterator to compare with
|
||||
/// \returns \f$true\f$ if iterators are different, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if iterators are different, \emph{false} otherwise
|
||||
constexpr bool operator!=(const iterator& it) {
|
||||
return _tree != it._tree or _n != it._n;
|
||||
}
|
||||
@@ -1009,7 +1009,7 @@ public:
|
||||
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$iterator\f$
|
||||
/// \brief C++ Iterator Specification \emph{iterator}
|
||||
/// \details Performs pre-order traversal
|
||||
class const_iterator {
|
||||
|
||||
@@ -1044,7 +1044,7 @@ public:
|
||||
|
||||
///
|
||||
/// \brief iterator pre-increment operator
|
||||
/// \returns A reference to self after having stepped to the next node
|
||||
/// \returns A reference to \emph{this} after having stepped to the next node
|
||||
const_iterator& operator++() {
|
||||
return _n = _order[*_tree, _n, traversal_control_continue], *this;
|
||||
}
|
||||
@@ -1064,7 +1064,7 @@ public:
|
||||
///
|
||||
/// \brief iterator equality operator
|
||||
/// \param it the iterator to compare with
|
||||
/// \returns \f$true\f$ if iterators are identical, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if iterators are identical, \emph{false} otherwise
|
||||
constexpr bool operator==(const iterator& it) {
|
||||
return _tree == it._tree and _n == it._n;
|
||||
}
|
||||
@@ -1072,7 +1072,7 @@ public:
|
||||
///
|
||||
/// \brief iterator inequality operator
|
||||
/// \param it the iterator to compare with
|
||||
/// \returns \f$true\f$ if iterators are different, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if iterators are different, \emph{false} otherwise
|
||||
constexpr bool operator!=(const iterator& it) {
|
||||
return _tree != it._tree or _n != it._n;
|
||||
}
|
||||
@@ -1087,18 +1087,18 @@ public:
|
||||
/// \returns an iterator at the first element in pre-order traversal
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(\log N)\f$
|
||||
/// \emph{O(\log N)}
|
||||
///
|
||||
iterator begin() {
|
||||
return iterator(this, _root);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$begin()\f$
|
||||
/// \brief C++ Iterator Specification \emph{begin()}
|
||||
/// \returns an iterator at the first element in pre-order traversal
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(\log N)\f$
|
||||
/// \emph{O(\log N)}
|
||||
///
|
||||
const_iterator begin() const {
|
||||
return iterator(this, _root);
|
||||
@@ -1108,18 +1108,18 @@ public:
|
||||
/// \returns an iterator at the first element in pre-order traversal
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
iterator end() {
|
||||
return iterator(this, _root, nullid);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$end()\f$
|
||||
/// \brief C++ Iterator Specification \emph{end()}
|
||||
/// \returns an iterator at the first element in pre-order traversal
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
const_iterator end() const {
|
||||
return iterator(this, _root, nullid);
|
||||
@@ -1228,8 +1228,8 @@ private:
|
||||
}
|
||||
|
||||
constexpr size_t& _sibling(size_t i) {
|
||||
size_t p = _parent(i);
|
||||
bool d = i == _right(p);
|
||||
const size_t p = _parent(i);
|
||||
const bool d = i == _right(p);
|
||||
return _child(p, !d);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,10 +31,11 @@
|
||||
#ifndef FENNEC_CONTAINERS_BITFIELD_H
|
||||
#define FENNEC_CONTAINERS_BITFIELD_H
|
||||
|
||||
#include <fennec/containers/array.h>
|
||||
#include <fennec/lang/types.h>
|
||||
#include <fennec/lang/utility.h>
|
||||
|
||||
#include <fennec/containers/array.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
@@ -42,20 +43,19 @@ namespace fennec
|
||||
/// \brief Bitfield Container with basic Bit Ops
|
||||
///
|
||||
/// \details
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ⛔ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | linear | ✅ |
|
||||
/// | access | \f$O(1)\f$ |
|
||||
/// | find | \f$O(N)\f$ |
|
||||
/// | insertion | ⛔ |
|
||||
/// | deletion | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:-----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ⛔ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | linear | ✅ |
|
||||
/// | space | \emph{O(N)} |
|
||||
/// | access | \emph{O(1)} |
|
||||
/// | find | \emph{O(N)} |
|
||||
/// | insertion | ⛔ |
|
||||
/// | deletion | ⛔ |
|
||||
///
|
||||
/// \tparam N The number of bits in the bitfield
|
||||
template<size_t N>
|
||||
@@ -81,10 +81,10 @@ public:
|
||||
|
||||
///
|
||||
/// \brief Default constructor.
|
||||
/// \details Initializes all bits with \f$0\f$.
|
||||
/// \details Initializes all bits with \emph{0}.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr bitfield()
|
||||
: _bytes() {
|
||||
@@ -93,10 +93,10 @@ public:
|
||||
///
|
||||
/// \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$
|
||||
/// \details Initializes each bit with the respective boolean value in \emph{arr}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
explicit constexpr bitfield(const bool (&arr)[N])
|
||||
: _bytes() {
|
||||
@@ -108,10 +108,10 @@ public:
|
||||
///
|
||||
/// \brief Index array constructor.
|
||||
/// \param arr An array of indices.
|
||||
/// \details Sets the bits of each index provided in \f$arr\f$.
|
||||
/// \details Sets the bits of each index provided in \emph{arr}.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
template<size_t I>
|
||||
explicit constexpr bitfield(const size_t (&arr)[I])
|
||||
@@ -123,11 +123,11 @@ public:
|
||||
|
||||
///
|
||||
/// \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$.
|
||||
/// \details This substitution assumes \emph{ArgsT...} can be taken as an array of indices. <br>
|
||||
/// Sets the bits of each index provided in \emph{args...}.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr bitfield(ArgsT&&...args)
|
||||
@@ -138,12 +138,12 @@ public:
|
||||
///
|
||||
/// \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>
|
||||
/// \details This substitution assumes \emph{ArgsT...} can be taken as an array of booleans. <br>
|
||||
/// Initializes each bit with the respective boolean in \emph{args...}. <br>
|
||||
/// Does not necessitate the number of arguments be equal to the number of bits.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
template<typename...ArgsT> requires((is_bool_v<ArgsT> or is_convertible_v<ArgsT, bool>) and ...)
|
||||
constexpr bitfield(ArgsT&&...args)
|
||||
@@ -157,7 +157,7 @@ public:
|
||||
/// \param bf bitfield to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
bitfield(const bitfield& bf)
|
||||
: _bytes(bf._bytes) {
|
||||
@@ -168,7 +168,7 @@ public:
|
||||
/// \param bf bitfield to move
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
bitfield(bitfield&& bf) noexcept
|
||||
: _bytes(bf._bytes) {
|
||||
@@ -190,20 +190,20 @@ public:
|
||||
///
|
||||
/// \brief copy assignment
|
||||
/// \param bf bitfield to copy
|
||||
/// \returns a reference to self
|
||||
/// \returns a reference to \emph{this}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
bitfield& operator=(const bitfield& bf) = default;
|
||||
|
||||
///
|
||||
/// \brief move assignment
|
||||
/// \param bf bitfield to move
|
||||
/// \returns a reference to self
|
||||
/// \returns a reference to \emph{this}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
bitfield& operator=(bitfield&& bf) noexcept = default;
|
||||
|
||||
@@ -222,12 +222,12 @@ public:
|
||||
/// \returns the value stored in the bit as a boolean
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
bool test(size_t i) const {
|
||||
assertd(i < bits, "Index out of Bounds!");
|
||||
size_t b = i / 8;
|
||||
size_t o = i % 8;
|
||||
const size_t o = i % 8;
|
||||
return _bytes[b] & (1 << o);
|
||||
}
|
||||
|
||||
@@ -236,12 +236,12 @@ public:
|
||||
/// \param i the index of the bit
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
void set(size_t i) {
|
||||
assertd(i < bits, "Index out of Bounds!");
|
||||
size_t b = i / 8;
|
||||
size_t o = i % 8;
|
||||
const size_t o = i % 8;
|
||||
_bytes[b] |= (1 << o);
|
||||
}
|
||||
|
||||
@@ -250,12 +250,12 @@ public:
|
||||
/// \param i the index of the bit
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
void clear(size_t i) {
|
||||
assertd(i < bits, "Index out of Bounds!");
|
||||
size_t b = i / 8;
|
||||
size_t o = i % 8;
|
||||
const size_t o = i % 8;
|
||||
_bytes[b] &= ~(1 << o);
|
||||
}
|
||||
|
||||
@@ -264,27 +264,27 @@ public:
|
||||
/// \param i the index of the bit
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
void toggle(size_t i) {
|
||||
assertd(i < bits, "Index out of Bounds!");
|
||||
size_t b = i / 8;
|
||||
size_t o = i % 8;
|
||||
const size_t o = i % 8;
|
||||
_bytes[b] ^= (1 << o);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief store \f$v\f$ in bit \f$i\f$
|
||||
/// \brief store \emph{v} in bit \emph{i}
|
||||
/// \param i the index of the bit
|
||||
/// \param v the value to store
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
void store(size_t i, bool v) {
|
||||
assertd(i < bits, "Index out of Bounds!");
|
||||
size_t b = i / 8;
|
||||
size_t o = i % 8;
|
||||
const size_t o = i % 8;
|
||||
(_bytes[b] &= ~((1 << o))) |= ((v << o));
|
||||
}
|
||||
|
||||
@@ -293,7 +293,7 @@ public:
|
||||
/// \returns a bitfield containing the bit-wise inverse
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
bitfield operator~() const {
|
||||
bitfield res = *this;
|
||||
|
||||
@@ -42,20 +42,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 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. |
|
||||
/// | Property | Meaning |
|
||||
/// |:----------------|:-------------------------------------------------------------------------------------------------------------------|
|
||||
/// | **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 \math{i}, \math{\textbf{E}_i < \textbf{E}_{i + 1}} |
|
||||
/// | **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. |
|
||||
///
|
||||
///
|
||||
/// \section fennec_containers_section_cppstdlib C++ Standard Template Library
|
||||
|
||||
@@ -33,8 +33,6 @@
|
||||
|
||||
#include <fennec/memory/allocator.h>
|
||||
|
||||
// TODO: Document
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
@@ -46,20 +44,19 @@ namespace fennec
|
||||
/// This behaves the similar to fennec::list, however it does not allow arbitrary access, insertion, or deletion.
|
||||
/// It is one of the few data structures in this library that is stable, i.e. pointers to elements do not change.
|
||||
///
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:----------:|
|
||||
/// | stable | ✅ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | linear | ⛔ |
|
||||
/// | access | \f$O(1)\f$ |
|
||||
/// | find | \f$O(N)\f$ |
|
||||
/// | insertion | \f$O(1)\f$ |
|
||||
/// | deletion | \f$O(1)\f$ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:-----------:|
|
||||
/// | stable | ✅ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | linear | ⛔ |
|
||||
/// | space | \emph{O(N)} |
|
||||
/// | access | \emph{O(1)} |
|
||||
/// | find | \emph{O(N)} |
|
||||
/// | insertion | \emph{O(1)} |
|
||||
/// | deletion | \emph{O(1)} |
|
||||
///
|
||||
/// \tparam TypeT value type
|
||||
template<typename TypeT, typename AllocT = allocator<TypeT>>
|
||||
@@ -93,7 +90,7 @@ public:
|
||||
/// \brief Default Constructor, initializes an empty deque
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
deque()
|
||||
: _alloc()
|
||||
@@ -107,7 +104,7 @@ public:
|
||||
/// \param alloc the allocator to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
deque(const alloc_t& alloc)
|
||||
: _alloc(alloc)
|
||||
@@ -121,7 +118,7 @@ public:
|
||||
/// \param deque the deque to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
deque(const deque& deque)
|
||||
: _alloc(deque._alloc)
|
||||
@@ -140,7 +137,7 @@ public:
|
||||
/// \param deque the deque to move
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
deque(deque&& deque) noexcept
|
||||
: _alloc(deque._alloc)
|
||||
@@ -155,7 +152,7 @@ public:
|
||||
/// \brief Destructor, calls deque::clear
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
~deque() {
|
||||
clear();
|
||||
@@ -169,10 +166,10 @@ public:
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \returns \f$true\f$ when the deque is empty, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} when the deque is empty, \emph{false} otherwise
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool is_empty() const {
|
||||
return _size == 0;
|
||||
@@ -182,7 +179,7 @@ public:
|
||||
/// \returns the number of elements in the deque
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t size() const {
|
||||
return _size;
|
||||
@@ -200,7 +197,7 @@ public:
|
||||
/// \returns a reference to the first element in the deque
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
value_t& front() {
|
||||
assert(not is_empty(), "Attempted to access an empty deque.");
|
||||
@@ -211,7 +208,7 @@ public:
|
||||
/// \returns a const-qualified reference to the first element in the deque
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
const value_t& front() const {
|
||||
assert(not is_empty(), "Attempted to access an empty deque.");
|
||||
@@ -222,7 +219,7 @@ public:
|
||||
/// \returns a reference to the last element in the deque
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
value_t& back() {
|
||||
assert(not is_empty(), "Attempted to access an empty deque.");
|
||||
@@ -233,7 +230,7 @@ public:
|
||||
/// \returns a const-qualified reference to the last element in the deque
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
const value_t& back() const {
|
||||
assert(not is_empty(), "Attempted to access an empty deque.");
|
||||
@@ -253,7 +250,7 @@ public:
|
||||
/// \param elem the value to move
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
void push_front(value_t&& elem) {
|
||||
this->_push_front(elem);
|
||||
@@ -264,7 +261,7 @@ public:
|
||||
/// \param elem the value to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
void push_front(const value_t& elem) {
|
||||
this->_push_front(elem);
|
||||
@@ -276,7 +273,7 @@ public:
|
||||
/// \param args Arguments used to construct the value
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
void emplace_front(ArgsT&&...args) {
|
||||
@@ -289,7 +286,7 @@ public:
|
||||
/// \param elem the value to move
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
void push_back(value_t&& elem) {
|
||||
this->_push_back(elem);
|
||||
@@ -300,7 +297,7 @@ public:
|
||||
/// \param elem the value to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
void push_back(const value_t& elem) {
|
||||
this->_push_back(elem);
|
||||
@@ -312,7 +309,7 @@ public:
|
||||
/// \param args Arguments used to construct the value
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
void emplace_back(ArgsT&&...args) {
|
||||
@@ -323,7 +320,7 @@ public:
|
||||
/// \brief Clears the contents of the deque
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
void clear() {
|
||||
elem_t it = _first;
|
||||
@@ -342,7 +339,7 @@ public:
|
||||
/// \brief Erase the First Element
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
void pop_front() {
|
||||
if (_first == nullptr) {
|
||||
@@ -360,7 +357,7 @@ public:
|
||||
/// \brief Erase the Last Element
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
void pop_back() {
|
||||
if (_last == nullptr) {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#ifndef FENNEC_CONTAINERS_DETAIL_TUPLE_H
|
||||
#define FENNEC_CONTAINERS_DETAIL_TUPLE_H
|
||||
|
||||
#include <fennec/lang/metasequences.h>
|
||||
#include <fennec/lang/utility.h>
|
||||
|
||||
@@ -28,8 +29,11 @@ namespace fennec::detail
|
||||
template <size_t I, typename T>
|
||||
struct _tuple_leaf
|
||||
{
|
||||
template <typename ArgT>
|
||||
constexpr _tuple_leaf(ArgT&& arg) : value(fennec::forward<ArgT>(arg)) {}
|
||||
constexpr _tuple_leaf(_tuple_leaf&&) noexcept = default;
|
||||
constexpr _tuple_leaf(const _tuple_leaf&) = default;
|
||||
|
||||
template <typename ArgT> requires(not is_same_v<remove_cvref_t<ArgT>, _tuple_leaf>)
|
||||
constexpr explicit _tuple_leaf(ArgT&& arg) : value(fennec::forward<ArgT>(arg)) {}
|
||||
|
||||
constexpr ~_tuple_leaf() = default;
|
||||
|
||||
@@ -45,8 +49,11 @@ struct _tuple;
|
||||
template <size_t...IndicesV, typename...TypesT>
|
||||
struct _tuple<index_metasequence<IndicesV...>, TypesT...> : _tuple_leaf<IndicesV, TypesT>...
|
||||
{
|
||||
constexpr _tuple(_tuple&&) noexcept = default;
|
||||
constexpr _tuple(const _tuple&) = default;
|
||||
|
||||
template <typename...ArgsT>
|
||||
constexpr _tuple(ArgsT&&... args)
|
||||
constexpr explicit _tuple(ArgsT&&... args)
|
||||
: _tuple_leaf<IndicesV, TypesT>(fennec::forward<ArgsT>(args))... {
|
||||
}
|
||||
|
||||
|
||||
@@ -31,10 +31,13 @@
|
||||
#ifndef FENNEC_CONTAINERS_DYNARRAY_H
|
||||
#define FENNEC_CONTAINERS_DYNARRAY_H
|
||||
|
||||
#include <fennec/containers/initializer_list.h>
|
||||
#include <fennec/lang/utility.h>
|
||||
|
||||
#include <fennec/memory/allocator.h>
|
||||
#include <fennec/memory/new.h>
|
||||
|
||||
#include <fennec/containers/initializer_list.h>
|
||||
|
||||
#include <fennec/format/formatter.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
@@ -43,20 +46,19 @@ namespace fennec
|
||||
///
|
||||
/// \brief Wrapper for dynamically sized and allocated arrays
|
||||
/// \details
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | linear | ✅ |
|
||||
/// | access | \f$O(1)\f$ |
|
||||
/// | find | \f$O(N)\f$ |
|
||||
/// | insertion | \f$O(N)\f$ |
|
||||
/// | deletion | \f$O(N)\f$ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:-----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | linear | ✅ |
|
||||
/// | space | \emph{O(N)} |
|
||||
/// | access | \emph{O(1)} |
|
||||
/// | find | \emph{O(N)} |
|
||||
/// | insertion | \emph{O(N)} |
|
||||
/// | deletion | \emph{O(N)} |
|
||||
///
|
||||
/// This structure prefers shallow moves and deep copies.
|
||||
///
|
||||
@@ -86,7 +88,7 @@ public:
|
||||
/// \brief Default Constructor, initializes an empty allocation.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr dynarray()
|
||||
: _alloc(8)
|
||||
@@ -99,7 +101,7 @@ public:
|
||||
/// data.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
explicit constexpr dynarray(const alloc_t& alloc)
|
||||
: _alloc(8, alloc)
|
||||
@@ -107,11 +109,11 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Sized Allocation, initializes a dynarray with \f$n\f$ elements using the default constructor.
|
||||
/// \brief Sized Allocation, initializes a dynarray with \emph{n} elements using the default constructor.
|
||||
/// \param n The number of elements.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
explicit constexpr dynarray(size_t n)
|
||||
: _alloc(n)
|
||||
@@ -124,13 +126,13 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Sized Allocation Alloc Constructor, initializes a dynarray with allocator \f$alloc\f$ and \f$n\f$ elements
|
||||
/// \brief Sized Allocation Alloc Constructor, initializes a dynarray with allocator \emph{alloc} and \emph{n} elements
|
||||
/// using the default constructor.
|
||||
/// \param n The number of elements
|
||||
/// \param alloc The allocator object to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr dynarray(size_t n, const alloc_t& alloc)
|
||||
: _alloc(n, alloc)
|
||||
@@ -142,13 +144,13 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Sized Allocation Copy Constructor, Create an allocation of size \f$n\f$ elements, with each element
|
||||
/// \brief Sized Allocation Copy Constructor, Create an allocation of size \emph{n} elements, with each element
|
||||
/// constructed using the copy constructor
|
||||
/// \param n the number of elements
|
||||
/// \param val the value to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr dynarray(size_t n, const TypeT& val)
|
||||
: _alloc(n)
|
||||
@@ -166,7 +168,7 @@ public:
|
||||
/// \param args The arguments to create each object with
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr explicit dynarray(size_t n, ArgsT&&...args)
|
||||
@@ -183,7 +185,7 @@ public:
|
||||
/// \param arr The array to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
template<size_t N>
|
||||
constexpr dynarray(const TypeT (&arr)[N])
|
||||
@@ -200,7 +202,7 @@ public:
|
||||
/// \param arr The array to move
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
template<size_t N>
|
||||
constexpr dynarray(TypeT (&&arr)[N])
|
||||
@@ -212,13 +214,13 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Conversion Constructor, copies elements of conv as this \f$value_t\f$
|
||||
/// \brief Conversion Constructor, copies elements of conv as this \emph{value_t}
|
||||
/// \tparam OTypeT The other value type
|
||||
/// \tparam OAlloc The other allocator type
|
||||
/// \param conv The dynarray to convert
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
template<typename OTypeT, class OAlloc>
|
||||
constexpr dynarray(const dynarray<OTypeT, OAlloc>& conv)
|
||||
@@ -236,7 +238,7 @@ public:
|
||||
/// \param alloc An allocator object to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr dynarray(initializer_list<value_t> l, const alloc_t& alloc = alloc_t())
|
||||
: _alloc(l.size(), alloc)
|
||||
@@ -252,7 +254,7 @@ public:
|
||||
/// \param arr the dynarray to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr dynarray(const dynarray& arr)
|
||||
: _alloc(arr._size)
|
||||
@@ -267,7 +269,7 @@ public:
|
||||
/// \param arr the dynarray to move
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr dynarray(dynarray&& arr) noexcept
|
||||
: _alloc(fennec::move(arr._alloc))
|
||||
@@ -279,7 +281,7 @@ public:
|
||||
/// \brief Default Destructor, destructs all elements and frees the underlying allocation
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr ~dynarray() {
|
||||
value_t* addr = _alloc.data();
|
||||
@@ -292,10 +294,6 @@ 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 ==========================================================================================================
|
||||
@@ -307,10 +305,10 @@ public:
|
||||
///
|
||||
/// \brief Copy Assignment Operator
|
||||
/// \param arr the array to copy
|
||||
/// \returns A dynarray after having copied each element of \f$arr\f$
|
||||
/// \returns A dynarray after having copied each element of \emph{arr}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr dynarray& operator=(const dynarray& arr) {
|
||||
this->clear();
|
||||
@@ -324,10 +322,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$
|
||||
/// \returns A dynarray after having taken ownership of the contents of \emph{arr}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr dynarray& operator=(dynarray&& arr) noexcept {
|
||||
this->clear();
|
||||
@@ -341,10 +339,10 @@ public:
|
||||
/// \brief Array Copy Assignment Operator
|
||||
/// \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$
|
||||
/// \returns A dynarray after having copied each element of \emph{arr}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
template<size_t N>
|
||||
constexpr dynarray& operator=(const TypeT (&arr)[N]) {
|
||||
@@ -360,10 +358,10 @@ public:
|
||||
/// \brief Array Copy Assignment Operator
|
||||
/// \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$
|
||||
/// \returns A dynarray after having moved each element of \emph{arr}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
template<size_t N>
|
||||
constexpr dynarray& operator=(TypeT (&&arr)[N]) {
|
||||
@@ -387,7 +385,7 @@ public:
|
||||
/// \returns The size of the dynarray in elements
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t size() const {
|
||||
return _size;
|
||||
@@ -397,7 +395,7 @@ public:
|
||||
/// \returns The current capacity, in elements, of the underlying allocation
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t capacity() const {
|
||||
return _alloc.capacity();
|
||||
@@ -407,7 +405,7 @@ public:
|
||||
/// \returns True when there are no elements active, otherwise false
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool is_empty() const {
|
||||
return _size == 0;
|
||||
@@ -425,10 +423,10 @@ public:
|
||||
///
|
||||
/// \brief Array Access Operator
|
||||
/// \param i The index to access
|
||||
/// \returns A reference to the element at index \f$i\f$
|
||||
/// \returns A reference to the element at index \emph{i}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr TypeT& operator[](size_t i) {
|
||||
assertd(i < _size, "Array Out of Bounds");
|
||||
@@ -438,10 +436,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$
|
||||
/// \returns A const qualified reference to the element at index \emph{i}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const TypeT& operator[](size_t i) const {
|
||||
assertd(i < _size, "Array Out of Bounds");
|
||||
@@ -452,7 +450,7 @@ public:
|
||||
/// \returns Reference to the first element in the dynarray
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr TypeT& front() {
|
||||
return this->operator[](0);
|
||||
@@ -462,7 +460,7 @@ public:
|
||||
/// \returns A const-qualified reference to the first element in the dynarray
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const TypeT& front() const {
|
||||
return this->operator[](0);
|
||||
@@ -472,7 +470,7 @@ public:
|
||||
/// \returns A reference to the last element in the dynarray
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr TypeT& back() {
|
||||
return this->operator[](size() - 1);
|
||||
@@ -482,7 +480,7 @@ public:
|
||||
/// \returns A const-qualified reference to the last element in the dynarray
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const TypeT& back() const {
|
||||
return this->operator[](size() - 1);
|
||||
@@ -492,7 +490,7 @@ public:
|
||||
/// \returns A pointer to the underlying allocation
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr TypeT* data() {
|
||||
return _alloc.data();
|
||||
@@ -502,7 +500,7 @@ public:
|
||||
/// \returns A pointer to the underlying allocation
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const TypeT* data() const {
|
||||
return _alloc.data();
|
||||
@@ -523,7 +521,7 @@ public:
|
||||
/// \param val the value to initialize with
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr void insert(size_t i, TypeT&& val) {
|
||||
|
||||
@@ -535,8 +533,8 @@ public:
|
||||
// Move the data if we are not inserting at the end of the array
|
||||
if((i = min(i, _size)) < _size) {
|
||||
fennec::memmove(
|
||||
(void*)(_alloc.data() + i + 1)
|
||||
, (void*)(_alloc.data() + i)
|
||||
static_cast<void*>(_alloc.data() + i + 1)
|
||||
, static_cast<void*>(_alloc.data() + i)
|
||||
, (_size - i) * sizeof(TypeT));
|
||||
}
|
||||
|
||||
@@ -551,7 +549,7 @@ public:
|
||||
/// \param val the value to initialize with
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr void insert(size_t i, const TypeT& val) {
|
||||
|
||||
@@ -563,8 +561,8 @@ public:
|
||||
// Move the data if we are not inserting at the end of the array
|
||||
if((i = min(i, _size)) < _size) {
|
||||
fennec::memmove(
|
||||
(void*)(_alloc.data() + i),
|
||||
(void*)(_alloc.data() + i + 1),
|
||||
static_cast<void*>(_alloc.data() + i),
|
||||
static_cast<void*>(_alloc.data() + i + 1),
|
||||
(_size - i) * sizeof(TypeT)
|
||||
);
|
||||
}
|
||||
@@ -581,7 +579,7 @@ public:
|
||||
/// \tparam ArgsT Argument types
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr void emplace(size_t i, ArgsT&&...args) {
|
||||
@@ -594,8 +592,8 @@ public:
|
||||
// Move the data if we are not inserting at the end of the array
|
||||
if((i = min(i, _size)) < _size) {
|
||||
fennec::memmove(
|
||||
(void*)(_alloc.data() + i)
|
||||
, (void*)(_alloc.data() + i + 1)
|
||||
static_cast<void*>(_alloc.data() + i)
|
||||
, static_cast<void*>(_alloc.data() + i + 1)
|
||||
, (_size - i) * sizeof(TypeT));
|
||||
}
|
||||
|
||||
@@ -609,7 +607,7 @@ public:
|
||||
/// \param val Value to initialize with
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr void push_back(const TypeT& val) {
|
||||
dynarray::insert(_size, val);
|
||||
@@ -620,7 +618,7 @@ public:
|
||||
/// \param val Value to initialize with
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr void push_back(TypeT&& val) {
|
||||
dynarray::insert(_size, fennec::forward<TypeT>(val));
|
||||
@@ -632,7 +630,7 @@ public:
|
||||
/// \param args Arguments to construct with
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr void emplace_back(ArgsT...args) {
|
||||
@@ -643,7 +641,7 @@ public:
|
||||
/// \brief Erase last element
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr void pop_back() {
|
||||
fennec::destruct(&_alloc[--_size]);
|
||||
@@ -653,10 +651,10 @@ 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
|
||||
/// \details if \emph{n} is less than the current size, any elements that would be removed are destructed
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr void resize(size_t n) {
|
||||
_reduce(n);
|
||||
@@ -674,10 +672,10 @@ public:
|
||||
/// \param n The new size in elements
|
||||
/// \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
|
||||
/// \details if \emph{n} is less than the current size, any elements that would be removed are destructed
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr void resize(size_t n, const TypeT& val) {
|
||||
_reduce(n);
|
||||
@@ -694,10 +692,10 @@ public:
|
||||
/// \brief Reserve the array, allocating new space without initialization
|
||||
/// \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
|
||||
/// \details if \emph{n} is less than the current size, any elements that would be removed are destructed
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr void reserve(size_t n) {
|
||||
_reduce(n);
|
||||
@@ -708,7 +706,7 @@ public:
|
||||
/// \brief Clears the contents of the dynarray, destructing all elements and releasing the allocation.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr void clear() {
|
||||
_reduce(0);
|
||||
@@ -728,16 +726,16 @@ public:
|
||||
/// \returns A pointer to the first element in the dynarray
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr TypeT* begin() { return _alloc; }
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$begin()\f$
|
||||
/// \brief C++ Iterator Specification \emph{begin()}
|
||||
/// \returns A const qualified pointer to the first element in the dynarray
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const TypeT* begin() const { return _alloc; }
|
||||
|
||||
@@ -746,16 +744,16 @@ public:
|
||||
/// \return A pointer to the address after the last element in the dynarray
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr TypeT* end() { return begin() + _size; }
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$end()\f$
|
||||
/// \brief C++ Iterator Specification \emph{end()}
|
||||
/// \return A const qualified pointer to the address after the last element in the dynarray
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const TypeT* end() const { return begin() + _size; }
|
||||
|
||||
@@ -783,6 +781,27 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Formatter for `fennec::dynarray`
|
||||
/// \tparam T The element type.
|
||||
template<typename T>
|
||||
struct formatter<dynarray<T>> {
|
||||
///
|
||||
/// \brief format function
|
||||
/// \param str the string argument
|
||||
/// \returns the formatted version of \emph{str}
|
||||
string operator()(const format_arg& fmt, const dynarray<T>& arr) const {
|
||||
string res = string("[ ");
|
||||
for (auto& it : arr) {
|
||||
res += ' ';
|
||||
res += base(fmt, it);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static constexpr formatter<T> base = {};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_CONTAINERS_DYNARRAY_H
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#define FENNEC_CONTAINERS_GENERIC_H
|
||||
|
||||
#include <fennec/memory/allocator.h>
|
||||
|
||||
#include <fennec/rtti/type.h>
|
||||
|
||||
namespace fennec
|
||||
@@ -40,20 +41,19 @@ namespace fennec
|
||||
///
|
||||
/// \brief A struct capable of holding a single object of any type
|
||||
/// \details
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:----------:|
|
||||
/// | stable | ✅ |
|
||||
/// | dynamic | ⛔ |
|
||||
/// | homogeneous | ⛔ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | space | \f$O(1)\f$ |
|
||||
/// | linear | ✅ |
|
||||
/// | access | \f$O(1)\f$ |
|
||||
/// | find | ⛔ |
|
||||
/// | insertion | \f$O(1)\f$ |
|
||||
/// | deletion | \f$O(1)\f$ |
|
||||
/// | space | \f$O(1)\f$ |
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:-----------:|
|
||||
/// | stable | ✅ |
|
||||
/// | dynamic | ⛔ |
|
||||
/// | homogeneous | ⛔ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | linear | ✅ |
|
||||
/// | space | \emph{O(1)} |
|
||||
/// | access | \emph{O(1)} |
|
||||
/// | find | ⛔ |
|
||||
/// | insertion | \emph{O(1)} |
|
||||
/// | deletion | \emph{O(1)} |
|
||||
struct generic {
|
||||
|
||||
// Definitions =========================================================================================================
|
||||
@@ -79,7 +79,7 @@ public:
|
||||
/// \brief Default Constructor
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
generic()
|
||||
: _handle(nullptr)
|
||||
@@ -91,7 +91,7 @@ public:
|
||||
/// \param gen The generic object to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
generic(const generic& gen)
|
||||
: _handle(nullptr)
|
||||
@@ -106,7 +106,7 @@ public:
|
||||
/// \param gen The generic object to move
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
generic(generic&& gen)
|
||||
: _handle(gen._handle)
|
||||
@@ -121,7 +121,7 @@ public:
|
||||
/// \param x The value
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename T>
|
||||
generic(T&& x)
|
||||
@@ -136,7 +136,7 @@ public:
|
||||
/// \param args The argument values
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename T, typename...ArgsT>
|
||||
generic(type_identity<T>, ArgsT&&...args)
|
||||
@@ -164,17 +164,17 @@ public:
|
||||
/// \returns a runtime type struct referencing the held type
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
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
|
||||
/// \returns \emph{true} if there is a held value, \emph{false} otherwise
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
bool has_value() const {
|
||||
return _handle != nullptr;
|
||||
@@ -192,10 +192,10 @@ public:
|
||||
///
|
||||
/// \brief copy assignment
|
||||
/// \param gen the generic to copy
|
||||
/// \returns a reference to self after copying the contents of \f$gen\f$
|
||||
/// \returns a reference to \emph{this} after copying the contents of \emph{gen}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
generic& operator=(const generic& gen) {
|
||||
if (this == &gen) { // self-assignment case
|
||||
@@ -211,10 +211,10 @@ public:
|
||||
///
|
||||
/// \brief move assignment
|
||||
/// \param gen the generic to move
|
||||
/// \returns a reference to self after swapping contents with \f$gen\f$
|
||||
/// \returns a reference to \emph{this} after swapping contents with \emph{gen}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
generic& operator=(generic&& gen) noexcept {
|
||||
swap(gen);
|
||||
@@ -225,10 +225,10 @@ public:
|
||||
/// \brief value assignment
|
||||
/// \tparam T the type of the value
|
||||
/// \param x the value to assign
|
||||
/// \returns a reference to self after having assigned \f$x\f$
|
||||
/// \returns a reference to \emph{this} after having assigned \emph{x}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename T>
|
||||
generic& operator=(T&& x) {
|
||||
@@ -250,13 +250,13 @@ public:
|
||||
///
|
||||
/// \brief emplace value
|
||||
///
|
||||
/// \details constructs a new value of type \f$T\f$ using \f$args\ldots\f$
|
||||
/// \details constructs a new value of type \emph{T} using \emph{args\ldots}
|
||||
/// \tparam T the type to construct
|
||||
/// \tparam ArgsT the argument types
|
||||
/// \param args the argument values
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename T, typename...ArgsT>
|
||||
void emplace(ArgsT&&...args) {
|
||||
@@ -270,7 +270,7 @@ public:
|
||||
/// \details clears the held value using the appropriate destructor
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
void reset() {
|
||||
if (_manage) {
|
||||
@@ -284,7 +284,7 @@ public:
|
||||
/// \param gen the generic to swap with
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
void swap(generic& gen) noexcept {
|
||||
fennec::swap(_handle, gen._handle);
|
||||
@@ -303,12 +303,12 @@ public:
|
||||
///
|
||||
/// \brief cast value
|
||||
///
|
||||
/// \details equivalent to \f$reinterpret_cast\f$
|
||||
/// \details equivalent to \emph{reinterpret_cast}
|
||||
/// \tparam T The type to cast to
|
||||
/// \returns The contents of generic after having cast to \f$T\f$
|
||||
/// \returns The contents of generic after having cast to \emph{T}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename T, typename U = remove_cvref_t<T>>
|
||||
T cast() {
|
||||
@@ -316,12 +316,12 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \details equivalent to \f$reinterpret_cast\f$
|
||||
/// \details equivalent to \emph{reinterpret_cast}
|
||||
/// \tparam T The type to cast to
|
||||
/// \returns The contents of generic after having cast to \f$T\f$
|
||||
/// \returns The contents of generic after having cast to \emph{T}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename T, typename U = remove_cvref_t<T>>
|
||||
T cast() const {
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include <fennec/containers/list.h>
|
||||
#include <fennec/containers/map.h>
|
||||
#include <fennec/containers/object_pool.h>
|
||||
#include <fennec/containers/set.h>
|
||||
|
||||
/*
|
||||
* With the directed tree we were able to cheat a little, the structure has more rules to it which allows
|
||||
@@ -55,20 +54,19 @@ namespace fennec
|
||||
/// \brief Graph Data Structure, describes sets of arbitrarily connected vertices
|
||||
///
|
||||
/// \details
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:--------------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | linear | ✅ |
|
||||
/// | access | \f$O(1)\f$ |
|
||||
/// | find | \f$O(1)\f$ |
|
||||
/// | insertion | \f$O(1)\f$ |
|
||||
/// | deletion | \f$O(M)\f$ |
|
||||
/// | space | \f$O(N + M)\f$ |
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:---------------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | linear | ✅ |
|
||||
/// | space | \emph{O(N + M)} |
|
||||
/// | access | \emph{O(1)} |
|
||||
/// | find | \emph{O(1)} |
|
||||
/// | insertion | \emph{O(1)} |
|
||||
/// | deletion | \emph{O(M)} |
|
||||
///
|
||||
/// Graphs contain vertices and edges. Graphs are either directed
|
||||
/// or undirected. This structure allows the creation of both directed and undirected edges. As
|
||||
@@ -80,11 +78,11 @@ namespace fennec
|
||||
/// A directed graph is weakly connected if replacing all of its directed edges with undirected edges would
|
||||
/// produce a connected graph. We will call this "disjointed"
|
||||
///
|
||||
/// A directed graph is semi-connected if there is a directed path p for \f$u\f$ → \f$v\f$ *or* \f$v\f$ → \f$u\f$ for every
|
||||
/// pair of vertices \f$[u, v]\f$. We will call this "unilateral"
|
||||
/// A directed graph is semi-connected if there is a directed path p for \emph{u} → \emph{v} *or* \emph{v} → \emph{u} for every
|
||||
/// pair of vertices \emph{[u, v]}. We will call this "unilateral"
|
||||
///
|
||||
/// A directed graph is strongly-connected if there is a directed path p for \f$u\f$ → \f$v\f$ *and* \f$v\f$ → \f$u\f$ for every pair
|
||||
/// of vertices \f$[u, v]\f$. We will call this "connected"
|
||||
/// A directed graph is strongly-connected if there is a directed path p for \emph{u} → \emph{v} *and* \emph{v} → \emph{u} for every pair
|
||||
/// of vertices \emph{[u, v]}. We will call this "connected"
|
||||
///
|
||||
/// \tparam VertexT The type associated with each vertex
|
||||
/// \tparam EdgeT The type associated with each edge
|
||||
@@ -122,7 +120,7 @@ public:
|
||||
/// \brief Default Constructor, initializes empty graph
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr graph() = default;
|
||||
|
||||
@@ -130,7 +128,7 @@ public:
|
||||
/// \brief Destructor
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N + M)\f$
|
||||
/// \math{\textbf{O(N} + \textbf{M)}}
|
||||
///
|
||||
constexpr ~graph() = default;
|
||||
|
||||
@@ -146,7 +144,7 @@ public:
|
||||
/// \returns A reference to this after assigning g
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N + M)\f$
|
||||
/// \math{\textbf{O(N} + \textbf{M)}}
|
||||
///
|
||||
constexpr graph& operator=(const graph& g) = default;
|
||||
|
||||
@@ -156,7 +154,7 @@ public:
|
||||
/// \returns A reference to this after assigning g
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr graph& operator=(graph&& g) = default;
|
||||
|
||||
@@ -172,7 +170,7 @@ public:
|
||||
/// \returns The number of vertices in the graph
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t num_vertices() const {
|
||||
return _vertex_pool.size();
|
||||
@@ -182,7 +180,7 @@ public:
|
||||
/// \returns The number of edges in the graph
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t num_edges() const {
|
||||
return _edge_pool.size();
|
||||
@@ -192,57 +190,57 @@ public:
|
||||
/// \returns The capacity of the vertex pool
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
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
|
||||
/// \returns \emph{true} when there are no vertices in the graph, \emph{false} otherwise
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool is_empty() const {
|
||||
return num_vertices() == 0;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Checks if there exists an edge \f$e\f$ that starts from \f$a\f$ and ends at \f$b\f$
|
||||
/// \brief Checks if there exists an edge \math{e} that starts from \emph{a} and ends at \emph{b}
|
||||
/// \param a The first vertex
|
||||
/// \param b The second vertex
|
||||
/// \returns \f$true\f$ if the edge exists, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the edge exists, \emph{false} otherwise
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool exists(size_t a, size_t b) const {
|
||||
return _edge_map[a][b] != nullptr;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Checks if there exists an edge \f$e0\f$ that starts from \f$a\f$ and ends at \f$b\f$ and \f$e1\f$ that starts from \f$b\f$
|
||||
/// and ends at \f$a\f$
|
||||
/// \brief Checks if there exists an edge \math{e_0} that starts from \emph{a} and ends at \emph{b} and \math{e_1} that starts from \emph{b}
|
||||
/// and ends at \emph{a}
|
||||
/// \param a The first vertex
|
||||
/// \param b The second vertex
|
||||
/// \returns \f$true\f$ if both edges exist, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if both edges exist, \emph{false} otherwise
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool is_symmetric(size_t a, size_t b) const {
|
||||
return exists(a, b) and exists(b, a);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Checks if there exists an edge \f$e\f$ between \f$a\f$ and \f$b\f$
|
||||
/// \brief Checks if there exists an edge \math{e} between \emph{a} and \emph{b}
|
||||
/// \param a The first vertex
|
||||
/// \param b The second vertex
|
||||
/// \returns \f$true\f$ if both edges exist, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if both edges exist, \emph{false} otherwise
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool is_undirected(size_t a, size_t b) const {
|
||||
const auto* e0 = _edge_map[a][b];
|
||||
@@ -269,7 +267,7 @@ public:
|
||||
/// \returns A reference to the value stored in the vertex
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr vertex_t& operator[](size_t vertex) {
|
||||
return _vertex_pool[vertex];
|
||||
@@ -281,7 +279,7 @@ public:
|
||||
/// \returns A reference to the value stored in the vertex
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const vertex_t& operator[](size_t vertex) const {
|
||||
return _vertex_pool[vertex];
|
||||
@@ -291,10 +289,10 @@ public:
|
||||
/// \brief edge Access Operator
|
||||
/// \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
|
||||
/// \returns A pointer to the value stored in the edge, \emph{nullptr} if not found
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr edge_t* operator[](size_t a, size_t b) {
|
||||
if (is_empty()) {
|
||||
@@ -311,10 +309,10 @@ public:
|
||||
/// \brief edge Const Access Operator
|
||||
/// \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
|
||||
/// \returns A const-qualified pointer to the value stored in the edge, \emph{nullptr} if not found
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const edge_t* operator[](size_t a, size_t b) const {
|
||||
if (is_empty()) {
|
||||
@@ -328,12 +326,12 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge to \f$x\ldots\f$
|
||||
/// \brief Getter for a list of vertices \emph{X} that \emph{vertex} has an edge to \emph{X...}
|
||||
/// \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\ldots\f$
|
||||
/// \returns A list containing all vertices \emph{X} with edges from \emph{vertex} to \emph{X...}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(M)\f$
|
||||
/// \emph{O(M)}
|
||||
///
|
||||
list<size_t> outgoing(size_t vertex) {
|
||||
list<size_t> res;
|
||||
@@ -347,12 +345,12 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge from \f$x\ldots\f$
|
||||
/// \brief Getter for a list of vertices \emph{X} that \emph{vertex} has an edge from \emph{X...}
|
||||
/// \param vertex The id of the vertex
|
||||
/// \returns A list containing all vertices \f$x\f$ with edges from \f$x\ldots\f$ to \f$vertex\f$
|
||||
/// \returns A list containing all vertices \emph{X} with edges from \emph{X...} to \emph{vertex}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(M)\f$
|
||||
/// \emph{O(M)}
|
||||
///
|
||||
list<size_t> incoming(size_t vertex) {
|
||||
list<size_t> res;
|
||||
@@ -368,12 +366,12 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Getter for a list of vertices \f$x\f$ that \f$vertex\f$ has an edge to and from \f$x\ldots\f$
|
||||
/// \brief Getter for a list of vertices \emph{X} that \emph{vertex} has an edge to and from \emph{X...}
|
||||
/// \param vertex The id of the vertex
|
||||
/// \returns A list containing all vertices \f$x\f$ that have symmetric edges with \f$vertex\f$
|
||||
/// \returns A list containing all vertices \emph{X} that have symmetric edges with \emph{vertex}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(M)\f$
|
||||
/// \emph{O(M)}
|
||||
///
|
||||
list<size_t> symmetric(size_t vertex) {
|
||||
list<size_t> res;
|
||||
@@ -389,16 +387,16 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \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
|
||||
/// \brief Getter for a list of vertices \emph{X} that \emph{vertex} has an edge to and from \emph{X...} 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$
|
||||
/// \returns A list containing all vertices \emph{X} that have symmetric edges with \emph{vertex}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(M)\f$
|
||||
/// \emph{O(M)}
|
||||
///
|
||||
list<size_t> undirected(size_t vertex) {
|
||||
list<size_t> res;
|
||||
@@ -421,7 +419,7 @@ public:
|
||||
/// \returns A pointer to a map containing edges mapped from this vertex
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(M)\f$
|
||||
/// \emph{O(M)}
|
||||
///
|
||||
const auto* edges(size_t vertex) {
|
||||
if (is_empty() || vertex >= _edge_map.size()) {
|
||||
@@ -444,7 +442,7 @@ public:
|
||||
/// \returns The id of the new vertex
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t insert(vertex_t&& vertex) {
|
||||
return this->_insert(fennec::forward<vertex_t>(vertex));
|
||||
@@ -456,7 +454,7 @@ public:
|
||||
/// \returns The id of the new vertex
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t insert(const vertex_t& vertex) {
|
||||
return this->_insert(vertex);
|
||||
@@ -469,7 +467,7 @@ public:
|
||||
/// \returns The id of the new vertex
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr size_t emplace(ArgsT&&...args) {
|
||||
@@ -481,7 +479,7 @@ public:
|
||||
/// \param vertex The id of the vertex to erase
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(M)\f$
|
||||
/// \emph{O(M)}
|
||||
///
|
||||
constexpr void erase(size_t vertex) {
|
||||
cut(vertex);
|
||||
@@ -489,14 +487,14 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Form an edge from vertex \f$a\f$ to vertex \f$b\f$
|
||||
/// \brief Form an edge from vertex \emph{a} to vertex \emph{b}
|
||||
/// \tparam ArgsT The argument types
|
||||
/// \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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr void make_edge(size_t a, size_t b, ArgsT&&...args) {
|
||||
@@ -508,7 +506,7 @@ public:
|
||||
_edge_map.resize(_vertex_pool.capacity());
|
||||
}
|
||||
|
||||
auto it = _edge_map[a][b];
|
||||
const auto it = _edge_map[a][b];
|
||||
size_t conn;
|
||||
if (it != nullptr) {
|
||||
conn = *it;
|
||||
@@ -520,14 +518,14 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Form an undirected edge between vertex \f$a\f$ and vertex \f$b\f$
|
||||
/// \brief Form an undirected edge between vertex \emph{a} and vertex \emph{b}
|
||||
/// \tparam ArgsT The argument types
|
||||
/// \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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr void make_edge2(size_t a, size_t b, ArgsT&&...args) {
|
||||
@@ -539,7 +537,7 @@ public:
|
||||
_edge_map.resize(_vertex_pool.capacity());
|
||||
}
|
||||
|
||||
auto it = _edge_map[a][b];
|
||||
const auto it = _edge_map[a][b];
|
||||
size_t conn;
|
||||
if (it != nullptr) {
|
||||
conn = *it;
|
||||
@@ -553,12 +551,12 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Disconnect an edge from vertex \f$a\f$ to vertex \f$b\f$
|
||||
/// \brief Disconnect an edge from vertex \emph{a} to vertex \emph{b}
|
||||
/// \param a The first vertex id
|
||||
/// \param b The second vertex id
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr void cut_edge(size_t a, size_t b) {
|
||||
|
||||
@@ -580,12 +578,12 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Disconnect both directed edges between vertices \f$a\f$ and \f$b\f$
|
||||
/// \brief Disconnect both directed edges between vertices \emph{a} and \emph{b}
|
||||
/// \param a The first vertex id
|
||||
/// \param b The second vertex id
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr void cut_edge2(size_t a, size_t b) {
|
||||
const auto* ita = _edge_map[a][b];
|
||||
@@ -600,11 +598,11 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Break *all* edges connected to \f$n\f$
|
||||
/// \brief Break *all* edges connected to \emph{n}
|
||||
/// \param n The vertex id
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(M)\f$
|
||||
/// \emph{O(M)}
|
||||
///
|
||||
void cut(size_t n) {
|
||||
for (const auto it : outgoing(n)) {
|
||||
@@ -619,7 +617,7 @@ public:
|
||||
/// \brief Clear the graph, destructing all vertices and edges.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N + M)\f$
|
||||
/// \emph{O(N + M)}
|
||||
///
|
||||
void clear() {
|
||||
_vertex_pool.clear();
|
||||
|
||||
@@ -44,7 +44,7 @@ using std::initializer_list;
|
||||
|
||||
///
|
||||
/// \param inls the initializer list
|
||||
/// \returns A const qualified pointer to the first element in \f$inls\f$
|
||||
/// \returns A const qualified pointer to the first element in \emph{inls}
|
||||
template<typename T>
|
||||
constexpr const T* begin(initializer_list<T> inls) noexcept {
|
||||
return inls.begin();
|
||||
@@ -52,7 +52,7 @@ constexpr const T* begin(initializer_list<T> inls) noexcept {
|
||||
|
||||
///
|
||||
/// \param inls the initializer list
|
||||
/// \returns A const qualified pointer to one past the last element in \f$inls\f$
|
||||
/// \returns A const qualified pointer to one past the last element in \emph{inls}
|
||||
template<typename T>
|
||||
constexpr const T* end(initializer_list<T> inls) noexcept {
|
||||
return inls.end();
|
||||
|
||||
@@ -48,23 +48,22 @@ namespace fennec
|
||||
/// This data-structure behaves like a linked list, but does not use pointers. Instead, it is in-array. This creates the
|
||||
/// following properties:
|
||||
///
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | linear | ✅ |
|
||||
/// | access | \f$O(N)\f$ |
|
||||
/// | find | \f$O(N)\f$ |
|
||||
/// | insertion | \f$O(N)\f$ |
|
||||
/// | deletion | \f$O(N)\f$ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:-----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | linear | ✅ |
|
||||
/// | space | \emph{O(N)} |
|
||||
/// | access | \emph{O(N)} |
|
||||
/// | find | \emph{O(N)} |
|
||||
/// | insertion | \emph{O(N)} |
|
||||
/// | deletion | \emph{O(N)} |
|
||||
///
|
||||
/// \note Access, Insertion, and Deletion are \f$O(N)\f$ using the index pattern,
|
||||
/// using the iterator pattern yields \f$O(1)\f$ runtime.
|
||||
/// \note Access, Insertion, and Deletion are \emph{O(N)} using the index pattern,
|
||||
/// using the iterator pattern yields \emph{O(1)} runtime.
|
||||
///
|
||||
/// \tparam TypeT value type
|
||||
template<class TypeT, class Alloc = allocator<TypeT>>
|
||||
@@ -106,18 +105,18 @@ public:
|
||||
/// \brief Default Constructor, initializes an empty list.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr list()
|
||||
: _table(), _freed(), _root(npos), _last(npos), _size(0) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Copy Constructor, copies all elements in \f$l\f$ with optimized layout
|
||||
/// \brief Copy Constructor, copies all elements in \emph{l} with optimized layout
|
||||
/// \param l The list to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr list(const list& l)
|
||||
: list() {
|
||||
@@ -132,7 +131,7 @@ public:
|
||||
/// \param l The list to move
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr list(list&& l) noexcept
|
||||
: _table(fennec::move(l._table))
|
||||
@@ -146,7 +145,7 @@ public:
|
||||
/// \brief Destructor, destructs all elements then releases the allocation.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr ~list() {
|
||||
clear();
|
||||
@@ -163,10 +162,10 @@ public:
|
||||
///
|
||||
/// \brief Copy Assignment Operator
|
||||
/// \param l the list to copy
|
||||
/// \returns \f$this\f$ after having copied all elements of \f$l\f$
|
||||
/// \returns \emph{this} after having copied all elements of \emph{l}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr list& operator=(const list& l) {
|
||||
this->clear();
|
||||
@@ -179,10 +178,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$
|
||||
/// \returns \emph{this} after having taken ownership over the contents of \emph{l}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr list& operator=(list&& l) noexcept {
|
||||
this->clear();
|
||||
@@ -206,7 +205,7 @@ public:
|
||||
/// \returns The size of the list in elements.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t size() const {
|
||||
return _size;
|
||||
@@ -216,17 +215,17 @@ public:
|
||||
/// \returns The capacity of the list in elements.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t capacity() const {
|
||||
return _table.size();
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns \f$true\f$ when the list is empty, \f$false\f$ otherwise.
|
||||
/// \returns \emph{true} when the list is empty, \emph{false} otherwise.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool is_empty() const {
|
||||
return _root == npos;
|
||||
@@ -244,10 +243,10 @@ public:
|
||||
///
|
||||
/// \brief Array Access Operator
|
||||
/// \param i Index to access
|
||||
/// \returns A reference to the element at \f$i\f$
|
||||
/// \returns A reference to the element at \emph{i}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr value_t& operator[](int i) {
|
||||
assertd(i >= 0 && size_t(i) < _size, "Index out of Bounds");
|
||||
@@ -259,10 +258,10 @@ public:
|
||||
///
|
||||
/// \brief Const Array Access Operator
|
||||
/// \param i Index to access
|
||||
/// \returns A const-qualified reference to the element at \f$i\f$
|
||||
/// \returns A const-qualified reference to the element at \emph{i}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr const value_t& operator[](int i) const {
|
||||
assertd(i >= 0 && size_t(i) < _size, "Index out of Bounds");
|
||||
@@ -276,7 +275,7 @@ public:
|
||||
/// \returns A reference to the first element in the list
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr value_t& front() {
|
||||
return *_table[_root].value;
|
||||
@@ -287,7 +286,7 @@ public:
|
||||
/// \returns A const-qualified reference to the first element in the list
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const value_t& front() const {
|
||||
return *_table[_root].value;
|
||||
@@ -298,7 +297,7 @@ public:
|
||||
/// \returns A reference to the last element in the list
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr value_t& back() {
|
||||
return *_table[_last].value;
|
||||
@@ -309,7 +308,7 @@ public:
|
||||
/// \returns A const-qualified reference to the last element in the list
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const value_t& back() const {
|
||||
return *_table[_last].value;
|
||||
@@ -331,7 +330,7 @@ public:
|
||||
/// \returns The id of the inserted node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr iterator insert(const iterator& it, const value_t& x) {
|
||||
return this->_insert(it._n, x);
|
||||
@@ -344,7 +343,7 @@ public:
|
||||
/// \returns The id of the inserted node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr iterator insert(const iterator& it, value_t&& x) {
|
||||
return this->_insert(it._n, fennec::forward<value_t>(x));
|
||||
@@ -357,7 +356,7 @@ public:
|
||||
/// \returns The id of the inserted node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr iterator insert(size_t i, const value_t& x) {
|
||||
assert(i <= size(), "Index out of Bounds");
|
||||
@@ -373,7 +372,7 @@ public:
|
||||
/// \returns The id of the inserted node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr iterator insert(size_t i, value_t&& x) {
|
||||
assert(i <= size(), "Index out of Bounds");
|
||||
@@ -390,7 +389,7 @@ public:
|
||||
/// \returns The id of the inserted node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr iterator emplace(size_t i, ArgsT&&...args) {
|
||||
@@ -408,7 +407,7 @@ public:
|
||||
/// \returns The id of the inserted node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr iterator emplace(const iterator& it, ArgsT&&...args) {
|
||||
@@ -421,7 +420,7 @@ public:
|
||||
/// \returns The id of the inserted node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr iterator push_front(const value_t& x) {
|
||||
return this->_insert(_root, x);
|
||||
@@ -433,7 +432,7 @@ public:
|
||||
/// \returns The id of the inserted node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr iterator push_front(value_t&& x) {
|
||||
return this->_insert(_root, fennec::forward<value_t>(x));
|
||||
@@ -446,7 +445,7 @@ public:
|
||||
/// \returns The id of the inserted node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr iterator emplace_front(ArgsT&&...args) {
|
||||
@@ -459,7 +458,7 @@ public:
|
||||
/// \returns The id of the inserted node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr iterator push_back(const value_t& x) {
|
||||
return this->_insert(npos, x);
|
||||
@@ -471,7 +470,7 @@ public:
|
||||
/// \returns The id of the inserted node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr iterator push_back(value_t&& x) {
|
||||
return this->_insert(npos, fennec::forward<value_t>(x));
|
||||
@@ -484,7 +483,7 @@ public:
|
||||
/// \returns The id of the inserted node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr iterator emplace_back(ArgsT&&...args) {
|
||||
@@ -496,11 +495,11 @@ public:
|
||||
/// \param i Index to erase
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr void erase(size_t i) {
|
||||
assert(i < size(), "Index out of Bounds!");
|
||||
size_t n = _walk(i);
|
||||
const size_t n = _walk(i);
|
||||
_erase(n);
|
||||
}
|
||||
|
||||
@@ -509,7 +508,7 @@ public:
|
||||
/// \param it Location to Erase
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr void erase(const iterator& it) {
|
||||
this->_erase(it._n);
|
||||
@@ -519,7 +518,7 @@ public:
|
||||
/// \brief Pop Front, erases first element
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr void pop_front() {
|
||||
_erase(_root);
|
||||
@@ -529,7 +528,7 @@ public:
|
||||
/// \brief Pop Back, erases first element
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr void pop_back() {
|
||||
_erase(_last);
|
||||
@@ -539,7 +538,7 @@ public:
|
||||
/// \brief Clears the list, destructing all elements in order
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr void clear() {
|
||||
size_t i = _root;
|
||||
@@ -564,18 +563,18 @@ public:
|
||||
/// \returns An iterator for the first element in the list
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr iterator begin() {
|
||||
return iterator(this, _root);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$begin()\f$
|
||||
/// \brief C++ Iterator Specification \emph{begin()}
|
||||
/// \returns A const iterator for the first element in the list
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const_iterator begin() const {
|
||||
return const_iterator(this, _root);
|
||||
@@ -585,25 +584,25 @@ public:
|
||||
/// \returns An iterator for the end of the list
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr iterator end() {
|
||||
return iterator(this, npos);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Const C++ Iterator Specification \f$end()\f$
|
||||
/// \brief Const C++ Iterator Specification \emph{end()}
|
||||
/// \returns A const iterator for the end of the list
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const_iterator end() const {
|
||||
return const_iterator(this, npos);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$iterator\f$
|
||||
/// \brief C++ Iterator Specification \emph{iterator}
|
||||
class iterator {
|
||||
public:
|
||||
///
|
||||
@@ -615,7 +614,7 @@ public:
|
||||
///
|
||||
/// \brief prefix increment operator
|
||||
/// \param rhs the iterator to increment
|
||||
/// \returns \f$rhs\f$ after having moved to the next element in the list
|
||||
/// \returns \emph{rhs} after having moved to the next element in the list
|
||||
constexpr friend iterator& operator++(iterator& rhs) {
|
||||
rhs._n = rhs._list->_next(rhs._n);
|
||||
return rhs;
|
||||
@@ -624,7 +623,7 @@ public:
|
||||
///
|
||||
/// \brief postfix increment operator
|
||||
/// \param lhs the iterator to increment
|
||||
/// \returns \f$lhs\f$ before having moved to the next element in the list
|
||||
/// \returns \emph{lhs} before having moved to the next element in the list
|
||||
constexpr friend iterator operator++(iterator& lhs, int) {
|
||||
iterator prev = lhs;
|
||||
++lhs;
|
||||
@@ -648,7 +647,7 @@ public:
|
||||
///
|
||||
/// \brief iterator equality operator
|
||||
/// \param it the iterator to compare with
|
||||
/// \returns \f$true\f$ if the iterators are identical, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the iterators are identical, \emph{false} otherwise
|
||||
constexpr bool operator==(const iterator& it) {
|
||||
return _list == it._list and _n == it._n;
|
||||
}
|
||||
@@ -656,7 +655,7 @@ public:
|
||||
///
|
||||
/// \brief iterator inequality operator
|
||||
/// \param it the iterator to compare with
|
||||
/// \returns \f$true\f$ if the iterators are different, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the iterators are different, \emph{false} otherwise
|
||||
constexpr bool operator!=(const iterator& it) {
|
||||
return _list != it._list or _n != it._n;
|
||||
}
|
||||
@@ -685,7 +684,7 @@ public:
|
||||
///
|
||||
/// \brief prefix increment operator
|
||||
/// \param rhs the iterator to increment
|
||||
/// \returns \f$rhs\f$ after having moved to the next element in the list
|
||||
/// \returns \emph{rhs} after having moved to the next element in the list
|
||||
constexpr friend const_iterator& operator++(const_iterator& rhs) {
|
||||
if (rhs._list->_next(rhs._n) < rhs._list->capacity()) {
|
||||
return rhs;
|
||||
@@ -697,7 +696,7 @@ public:
|
||||
///
|
||||
/// \brief postfix increment operator
|
||||
/// \param lhs the iterator to increment
|
||||
/// \returns \f$lhs\f$ before having moved to the next element in the list
|
||||
/// \returns \emph{lhs} before having moved to the next element in the list
|
||||
constexpr friend const_iterator operator++(const_iterator& lhs, int) {
|
||||
const_iterator prev = lhs;
|
||||
++lhs;
|
||||
@@ -721,7 +720,7 @@ public:
|
||||
///
|
||||
/// \brief iterator equality operator
|
||||
/// \param it the iterator to compare with
|
||||
/// \returns \f$true\f$ if the iterators are identical, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the iterators are identical, \emph{false} otherwise
|
||||
constexpr bool operator==(const const_iterator& it) {
|
||||
return _list == it._list and _n == it._n;
|
||||
}
|
||||
@@ -729,7 +728,7 @@ public:
|
||||
///
|
||||
/// \brief iterator inequality operator
|
||||
/// \param it the iterator to compare with
|
||||
/// \returns \f$true\f$ if the iterators are different, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the iterators are different, \emph{false} otherwise
|
||||
constexpr bool operator!=(const const_iterator& it) {
|
||||
return _list != it._list or _n != it._n;
|
||||
}
|
||||
@@ -800,7 +799,7 @@ private:
|
||||
|
||||
constexpr size_t _next_free() {
|
||||
if (not _freed.is_empty()) {
|
||||
size_t n = _freed.back();
|
||||
const size_t n = _freed.back();
|
||||
_freed.pop_back();
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -56,24 +56,23 @@ namespace fennec
|
||||
*/
|
||||
|
||||
///
|
||||
/// \brief Data Structure defining a mapping of \f$key\f$ \f$KeyT\f$ to \f$value\f$ \f$ValueT\f$
|
||||
/// \brief Data Structure defining a mapping of \emph{key} \emph{KeyT} to \emph{value} \emph{ValueT}
|
||||
/// \details
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ✅ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | linear | ⛔ |
|
||||
/// | access | \f$O(1)\f$ |
|
||||
/// | find | \f$O(1)\f$ |
|
||||
/// | insertion | \f$O(1)\f$ |
|
||||
/// | deletion | \f$O(1)\f$ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:-----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ✅ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | linear | ⛔ |
|
||||
/// | space | \emph{O(N)} |
|
||||
/// | access | \emph{O(1)} |
|
||||
/// | find | \emph{O(1)} |
|
||||
/// | insertion | \emph{O(1)} |
|
||||
/// | deletion | \emph{O(1)} |
|
||||
///
|
||||
/// \note These runtimes are amortized, in theory the worst case is \f$O(N)\f$, but that is highly improbable.
|
||||
/// \note These runtimes are amortized, in theory the worst case is \emph{O(N)}, but that is highly improbable.
|
||||
///
|
||||
/// \tparam KeyT The Key Type
|
||||
/// \tparam ValueT The Value Type
|
||||
@@ -102,7 +101,7 @@ public:
|
||||
/// \brief key hash helper
|
||||
struct key_hash : hash_t {
|
||||
///
|
||||
/// \brief C++ 11 Hash Specification \f$operator()\f$
|
||||
/// \brief C++ 11 Hash Specification \emph{operator()}
|
||||
/// \param p the pair to hash
|
||||
/// \returns the hash of the key
|
||||
constexpr size_t operator()(const elem_t& p) const {
|
||||
@@ -114,10 +113,10 @@ public:
|
||||
/// \brief key comparison helper
|
||||
struct key_equals : equality<KeyT> {
|
||||
///
|
||||
/// \brief C++ 11 Compare Specification \f$operator()\f$
|
||||
/// \brief C++ 11 Compare Specification \emph{operator()}
|
||||
/// \param a the first pair
|
||||
/// \param b the second pair
|
||||
/// \returns \f$true\f$ if the keys are equal, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the keys are equal, \emph{false} otherwise
|
||||
constexpr bool operator()(const elem_t& a, const elem_t& b) const {
|
||||
return equality<KeyT>::operator()(a.first, b.first);
|
||||
}
|
||||
@@ -156,7 +155,7 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns \f$true\f$ when there are no elements in the set, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} when there are no elements in the set, \emph{false} otherwise
|
||||
constexpr size_t is_empty() const {
|
||||
return _set.size();
|
||||
}
|
||||
@@ -179,10 +178,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.
|
||||
/// \returns A pointer to the value associated with \emph{key}, \emph{nullptr} if \emph{key} is not present.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr value_t* operator[](const KeyT& key) {
|
||||
auto it = _set.at(this->_find(key));
|
||||
@@ -192,10 +191,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.
|
||||
/// \returns A const-qualified pointer to the value associated with \emph{key}, \emph{nullptr} if \emph{key} is not present.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const value_t* operator[](const KeyT& key) const {
|
||||
auto it = _set.at(this->_find(key));
|
||||
@@ -206,10 +205,10 @@ public:
|
||||
/// \brief Argument Key Access Operator
|
||||
/// \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.
|
||||
/// \returns A pointer to the value associated with \emph{key}, \emph{nullptr} if \emph{key} is not present.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr value_t* operator[](ArgsT&&...args) {
|
||||
@@ -221,10 +220,10 @@ public:
|
||||
/// \brief Argument Key Const Access Operator
|
||||
/// \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.
|
||||
/// \returns A const-qualified pointer to the value associated with \emph{key}, \emph{nullptr} if \emph{key} is not present.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr const value_t* operator[](ArgsT&&...args) const {
|
||||
@@ -246,7 +245,7 @@ public:
|
||||
/// \param pair a pair containing the key and its value
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr void insert(elem_t&& pair) {
|
||||
this->_insert(fennec::forward<elem_t>(pair));
|
||||
@@ -258,7 +257,7 @@ public:
|
||||
/// \param args Arguments for constructing the key-value pair
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr void emplace(const KeyT& key, ArgsT&&...args) {
|
||||
@@ -270,7 +269,7 @@ public:
|
||||
/// \param args Arguments for constructing the key-value pair
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr void emplace(ArgsT&&...args) {
|
||||
@@ -282,7 +281,7 @@ public:
|
||||
/// \param key key to erase
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr void erase(KeyT&& key) {
|
||||
_set.erase(this->_find(fennec::forward<KeyT>(key)));
|
||||
@@ -293,7 +292,7 @@ public:
|
||||
/// \param key key to erase
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr void erase(const KeyT& key) {
|
||||
_set.erase(this->_find(key));
|
||||
@@ -305,7 +304,7 @@ public:
|
||||
/// \param args Arguments to construct a key to erase
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr void erase(ArgsT&&...args) {
|
||||
@@ -316,7 +315,7 @@ public:
|
||||
/// \brief Clears the map destructing all elements
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
void clear() {
|
||||
_set.clear();
|
||||
@@ -332,11 +331,11 @@ public:
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$begin()\f$
|
||||
/// \brief C++ Iterator Specification \emph{begin()}
|
||||
/// \returns an iterator at the start of the map
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr iterator begin() {
|
||||
return _set.begin();
|
||||
@@ -344,11 +343,11 @@ public:
|
||||
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$end()\f$
|
||||
/// \brief C++ Iterator Specification \emph{end()}
|
||||
/// \returns an iterator at the end of the map
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr iterator end() {
|
||||
return _set.end();
|
||||
|
||||
@@ -41,20 +41,19 @@ namespace fennec
|
||||
///
|
||||
/// \brief Struct which holds a pool of objects associated with ids
|
||||
/// \details
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | linear | ⛔ |
|
||||
/// | access | \f$O(1)\f$ |
|
||||
/// | find | \f$O(N)\f$ |
|
||||
/// | insertion | \f$O(1)\f$ |
|
||||
/// | deletion | \f$O(1)\f$ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:-----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | linear | ⛔ |
|
||||
/// | space | \emph{O(N)} |
|
||||
/// | access | \emph{O(1)} |
|
||||
/// | find | \emph{O(N)} |
|
||||
/// | insertion | \emph{O(1)} |
|
||||
/// | deletion | \emph{O(1)} |
|
||||
///
|
||||
/// \tparam TypeT The value type
|
||||
/// \tparam AllocT The allocator type
|
||||
@@ -88,7 +87,7 @@ public:
|
||||
/// \brief Default Constructor, initializes an empty object pool
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr object_pool()
|
||||
: _size(0) {
|
||||
@@ -98,7 +97,7 @@ public:
|
||||
/// \brief Default Destructor, destructs objects then releases the allocation.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr ~object_pool() = default;
|
||||
|
||||
@@ -114,7 +113,7 @@ public:
|
||||
/// \returns The number of active objects in the pool
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t size() const {
|
||||
return _size;
|
||||
@@ -124,30 +123,30 @@ public:
|
||||
/// \returns The capacity of the underlying allocation
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t capacity() const {
|
||||
return _table.capacity();
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns \f$true\f$ when there are no objects in the pool, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} when there are no objects in the pool, \emph{false} otherwise
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool is_empty() const {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Retrieve the next id \f$i\f$ that would be assigned to an object \f$o\f$ were it added to the object pool
|
||||
/// \brief Retrieve the next id \emph{i} that would be assigned to an object \math{o} were it added to the object pool
|
||||
///
|
||||
/// \details This can be useful if there are constant members that need to be assigned at construction.
|
||||
/// \returns The id of the next inserted node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t next_id() const {
|
||||
size_t next = _size;
|
||||
@@ -167,10 +166,10 @@ public:
|
||||
///
|
||||
/// \brief Array Access Operator
|
||||
/// \param i id of the object
|
||||
/// \returns a reference to the object with id \f$i\f$
|
||||
/// \returns a reference to the object with id \emph{i}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr value_t& operator[](size_t i) {
|
||||
assert(i < capacity(), "Index out of Bounds!");
|
||||
@@ -181,10 +180,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$
|
||||
/// \returns a const-qualified reference to the object with id \emph{i}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const value_t& operator[](size_t i) const {
|
||||
assert(i < capacity(), "Index out of Bounds!");
|
||||
@@ -206,24 +205,24 @@ public:
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \brief Move Insertion, inserts \f$x\f$ into the pool
|
||||
/// \brief Move Insertion, inserts \emph{x} 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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t insert(value_t&& x) {
|
||||
return this->_insert(fennec::forward<value_t>(x));
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Move Insertion, inserts a copy of \f$x\f$ into the pool
|
||||
/// \brief Move Insertion, inserts a copy of \emph{x} 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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t insert(const value_t& x) {
|
||||
return this->_insert(x);
|
||||
@@ -231,12 +230,12 @@ public:
|
||||
|
||||
|
||||
///
|
||||
/// \brief Emplacement, constructs a new object using \f$args\ldots\f$
|
||||
/// \brief Emplacement, constructs a new object using \emph{args...}
|
||||
/// \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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr size_t emplace(ArgsT&&...args) {
|
||||
@@ -248,7 +247,7 @@ public:
|
||||
/// \param i The id of the object
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr void erase(size_t i) {
|
||||
_table[i] = nullopt;
|
||||
@@ -260,7 +259,7 @@ public:
|
||||
/// \brief Clear the object pool
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr void clear() {
|
||||
_table.clear();
|
||||
@@ -277,18 +276,18 @@ public:
|
||||
/// \returns an iterator at the start of the object pool
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
iterator begin() {
|
||||
return iterator(this, 0);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$begin()\f$
|
||||
/// \brief C++ Iterator Specification \emph{begin()}
|
||||
/// \returns an iterator at the start of the object pool
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
const_iterator begin() const {
|
||||
return const_iterator(this, 0);
|
||||
@@ -298,25 +297,25 @@ public:
|
||||
/// \returns an iterator at the start of the end of the object pool
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
iterator end() {
|
||||
return iterator(this, _size);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$end()\f$
|
||||
/// \brief C++ Iterator Specification \emph{end()}
|
||||
/// \returns an iterator at the start of the end of the object pool
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
const_iterator end() const {
|
||||
return const_iterator(this, _size);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$iterator\f$
|
||||
/// \brief C++ Iterator Specification \emph{iterator}
|
||||
class iterator {
|
||||
public:
|
||||
///
|
||||
@@ -337,18 +336,18 @@ public:
|
||||
///
|
||||
/// \brief copy assignment
|
||||
/// \param it the iterator to copy
|
||||
/// \returns a reference to self after having copied \f$it\f$
|
||||
/// \returns a reference to \emph{this} after having copied \emph{it}
|
||||
iterator& operator=(const iterator& it) = default;
|
||||
|
||||
///
|
||||
/// \brief move assignment
|
||||
/// \param it the iterator to move
|
||||
/// \returns a reference to self after having moved \f$it\f$
|
||||
/// \returns a reference to \emph{this} after having moved \emph{it}
|
||||
iterator& operator=(iterator&& it) noexcept = default;
|
||||
|
||||
///
|
||||
/// \brief postfix increment operator
|
||||
/// \returns \f$it\f$ before having been incremented
|
||||
/// \returns \emph{it} before having been incremented
|
||||
friend iterator operator++(iterator& it, int) {
|
||||
iterator ret = it;
|
||||
++it.curr;
|
||||
@@ -358,7 +357,7 @@ public:
|
||||
|
||||
///
|
||||
/// \brief prefix increment operator
|
||||
/// \returns \f$it\f$ after having moved to the next element
|
||||
/// \returns \emph{it} after having moved to the next element
|
||||
friend iterator& operator++(iterator& it) {
|
||||
++it.curr;
|
||||
it._fix();
|
||||
@@ -382,7 +381,7 @@ public:
|
||||
///
|
||||
/// \brief iterator equality operator
|
||||
/// \param it the iterator to compare with
|
||||
/// \returns \f$true\f$ if the iterators are identical, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the iterators are identical, \emph{false} otherwise
|
||||
bool operator==(const iterator& it) {
|
||||
return pool == it.pool and curr == it.curr;
|
||||
}
|
||||
@@ -390,7 +389,7 @@ public:
|
||||
///
|
||||
/// \brief iterator inequality operator
|
||||
/// \param it the iterator to compare with
|
||||
/// \returns \f$true\f$ if the iterators are different, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the iterators are different, \emph{false} otherwise
|
||||
bool operator!=(const iterator& it) {
|
||||
return pool != it.pool or curr != it.curr;
|
||||
}
|
||||
@@ -414,7 +413,7 @@ public:
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$const_iterator\f$
|
||||
/// \brief C++ Iterator Specification \emph{const_iterator}
|
||||
class const_iterator {
|
||||
public:
|
||||
///
|
||||
@@ -435,18 +434,18 @@ public:
|
||||
///
|
||||
/// \brief copy assignment
|
||||
/// \param it the iterator to copy
|
||||
/// \returns a reference to self after having copied \f$it\f$
|
||||
/// \returns a reference to \emph{this} after having copied \emph{it}
|
||||
const_iterator& operator=(const const_iterator& it) = default;
|
||||
|
||||
///
|
||||
/// \brief move assignment
|
||||
/// \param it the iterator to move
|
||||
/// \returns a reference to self after having moved \f$it\f$
|
||||
/// \returns a reference to \emph{this} after having moved \emph{it}
|
||||
const_iterator& operator=(const_iterator&& it) noexcept = default;
|
||||
|
||||
///
|
||||
/// \brief postfix increment operator
|
||||
/// \returns \f$it\f$ before having been incremented
|
||||
/// \returns \emph{it} before having been incremented
|
||||
friend const_iterator operator++(const_iterator& it, int) {
|
||||
const_iterator ret = it;
|
||||
++it.curr;
|
||||
@@ -456,7 +455,7 @@ public:
|
||||
|
||||
///
|
||||
/// \brief prefix increment operator
|
||||
/// \returns \f$it\f$ after having moved to the next element
|
||||
/// \returns \emph{it} after having moved to the next element
|
||||
friend const_iterator& operator++(const_iterator& it) {
|
||||
++it.curr;
|
||||
it._fix();
|
||||
@@ -480,7 +479,7 @@ public:
|
||||
///
|
||||
/// \brief iterator equality operator
|
||||
/// \param it the iterator to compare with
|
||||
/// \returns \f$true\f$ if the iterators are identical, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the iterators are identical, \emph{false} otherwise
|
||||
bool operator==(const const_iterator& it) {
|
||||
return pool == it.pool and curr == it.curr;
|
||||
}
|
||||
@@ -488,7 +487,7 @@ public:
|
||||
///
|
||||
/// \brief iterator inequality operator
|
||||
/// \param it the iterator to compare with
|
||||
/// \returns \f$true\f$ if the iterators are different, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the iterators are different, \emph{false} otherwise
|
||||
bool operator!=(const const_iterator& it) {
|
||||
return pool != it.pool or curr != it.curr;
|
||||
}
|
||||
|
||||
@@ -39,34 +39,33 @@
|
||||
namespace fennec
|
||||
{
|
||||
///
|
||||
/// \brief struct to represent a \f$null\f$ `fennec::optional`
|
||||
/// \brief struct to represent a \emph{null} `fennec::optional`
|
||||
struct nullopt_t {};
|
||||
|
||||
///
|
||||
/// \brief value representing a \f$null\f$ `fennec::optional`
|
||||
/// \brief value representing a \emph{null} `fennec::optional`
|
||||
constexpr nullopt_t nullopt_v = {};
|
||||
|
||||
///
|
||||
/// \brief alias for representing a \f$null\f$ `fennec::optional`
|
||||
/// \brief alias for representing a \emph{null} `fennec::optional`
|
||||
#define nullopt nullopt_v
|
||||
|
||||
///
|
||||
/// \brief Structure to hold an optional value.
|
||||
/// \details
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:----------:|
|
||||
/// | stable | ✅ |
|
||||
/// | dynamic | ⛔ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | linear | ⛔ |
|
||||
/// | access | \f$O(1)\f$ |
|
||||
/// | find | ⛔ |
|
||||
/// | insertion | \f$O(1)\f$ |
|
||||
/// | deletion | \f$O(1)\f$ |
|
||||
/// | space | \f$O(1)\f$ |
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:-----------:|
|
||||
/// | stable | ✅ |
|
||||
/// | dynamic | ⛔ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | linear | ⛔ |
|
||||
/// | space | \emph{O(1)} |
|
||||
/// | access | \emph{O(1)} |
|
||||
/// | find | ⛔ |
|
||||
/// | insertion | \emph{O(1)} |
|
||||
/// | deletion | \emph{O(1)} |
|
||||
///
|
||||
/// \tparam T
|
||||
template<typename T>
|
||||
@@ -95,7 +94,7 @@ public:
|
||||
/// \brief Default Constructor
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr optional()
|
||||
: _root(0)
|
||||
@@ -106,7 +105,7 @@ public:
|
||||
/// \brief Default Constructor
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr optional(nullopt_t)
|
||||
: _root(0)
|
||||
@@ -118,7 +117,7 @@ public:
|
||||
/// \param val the value to initialize the underlying object with
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr optional(const T& val)
|
||||
: _val(val)
|
||||
@@ -130,7 +129,7 @@ public:
|
||||
/// \param val the value to initialize the underlying object with
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr optional(T&& val)
|
||||
: _val(fennec::forward<T>(val))
|
||||
@@ -142,7 +141,7 @@ public:
|
||||
/// \param opt the optional to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr optional(const optional& opt) requires is_copy_assignable_v<T>
|
||||
: optional() {
|
||||
@@ -157,7 +156,7 @@ public:
|
||||
/// \param opt the optional to move
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr optional(optional&& opt) noexcept requires is_move_assignable_v<T>
|
||||
: optional() {
|
||||
@@ -174,7 +173,7 @@ public:
|
||||
/// \param args The argument values
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr optional(ArgsT&&...args)
|
||||
@@ -186,7 +185,7 @@ public:
|
||||
/// \brief destructor
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr ~optional() {
|
||||
if constexpr(is_fundamental_v<T>) {
|
||||
@@ -207,20 +206,20 @@ public:
|
||||
|
||||
///
|
||||
/// \brief Implicit Boolean Check
|
||||
/// \returns \f$true\f$ when there is a value contained
|
||||
/// \returns \emph{true} when there is a value contained
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr operator bool() const {
|
||||
return _set;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns \f$true\f$ when there is no held value, \f$false\f$ otherwise.
|
||||
/// \returns \emph{true} when there is no held value, \emph{false} otherwise.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool is_empty() const {
|
||||
return not _set;
|
||||
@@ -236,10 +235,10 @@ public:
|
||||
|
||||
///
|
||||
/// \brief Null Assignment
|
||||
/// \returns A reference to self
|
||||
/// \returns A reference to \emph{this}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr optional& operator=(nullopt_t) {
|
||||
if constexpr(not is_fundamental_v<T>) {
|
||||
@@ -255,10 +254,10 @@ public:
|
||||
///
|
||||
/// \brief Type Copy Assignment
|
||||
/// \param val The value to set with
|
||||
/// \returns A reference to self
|
||||
/// \returns A reference to \emph{this}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr optional& operator=(const T& val) requires is_copy_constructible_v<T> and is_copy_assignable_v<T> {
|
||||
if (_set) {
|
||||
@@ -273,10 +272,10 @@ public:
|
||||
///
|
||||
/// \brief Type Move Assignment
|
||||
/// \param val The value to set with
|
||||
/// \returns A reference to self
|
||||
/// \returns A reference to \emph{this}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr optional& operator=(T&& val) requires is_move_constructible_v<T> and is_move_assignable_v<T> {
|
||||
if (_set) {
|
||||
@@ -291,10 +290,10 @@ public:
|
||||
///
|
||||
/// \brief Copy Assignment
|
||||
/// \param opt The optional to copy
|
||||
/// \returns A reference to self
|
||||
/// \returns A reference to \emph{this}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr optional& operator=(const optional& opt) requires is_copy_constructible_v<T> and is_copy_assignable_v<T> {
|
||||
if (_set != opt._set) {
|
||||
@@ -314,10 +313,10 @@ public:
|
||||
///
|
||||
/// \brief Move Assignment
|
||||
/// \param opt The optional to move
|
||||
/// \returns A reference to self
|
||||
/// \returns A reference to \emph{this}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr optional& operator=(optional&& opt) noexcept requires is_move_constructible_v<T> and is_move_assignable_v<T> {
|
||||
if (_set != opt._set) {
|
||||
@@ -343,20 +342,20 @@ public:
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \returns A pointer to the value, \f$nullptr\f$ if there is no value
|
||||
/// \returns A pointer to the value, \emph{nullptr} if there is no value
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
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
|
||||
/// \returns A const-qualified pointer to the value, \emph{nullptr} if there is no value
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const_pointer_t operator->() const noexcept {
|
||||
return _set ? &_val : nullptr;
|
||||
@@ -367,7 +366,7 @@ public:
|
||||
/// \returns A reference to the value
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr T& operator*() & noexcept {
|
||||
assertd(_set, "Attempted to reference the value of an unset optional");
|
||||
@@ -379,7 +378,7 @@ public:
|
||||
/// \returns A const-qualified reference to the value
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const T& operator*() const& noexcept {
|
||||
assertd(_set, "Attempted to reference the value of an unset optional");
|
||||
@@ -391,7 +390,7 @@ public:
|
||||
/// \returns A reference to the value
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr T&& operator*() && noexcept {
|
||||
assertd(_set, "Attempted to reference the value of an unset optional");
|
||||
@@ -403,7 +402,7 @@ public:
|
||||
/// \returns A const-qualified reference to the value
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const T&& operator*() const&& noexcept {
|
||||
assertd(_set, "Attempted to reference the value of an unset optional");
|
||||
@@ -423,7 +422,7 @@ public:
|
||||
/// \returns A reference to the held value
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr T& emplace(T&& val) {
|
||||
if (_set) {
|
||||
@@ -441,7 +440,7 @@ public:
|
||||
/// \returns A reference to the held value
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr T& emplace(const T& val) {
|
||||
if (_set) {
|
||||
@@ -459,7 +458,7 @@ public:
|
||||
/// \returns A reference to the held value
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr T& emplace(ArgsT&&...args) {
|
||||
@@ -476,7 +475,7 @@ public:
|
||||
/// \brief Reset the Optional
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
void reset() {
|
||||
this->operator=(nullopt);
|
||||
|
||||
@@ -43,20 +43,19 @@ namespace fennec
|
||||
///
|
||||
/// \brief Struct for holding a pair of values
|
||||
/// \details
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:----------:|
|
||||
/// | stable | ✅ |
|
||||
/// | dynamic | ⛔ |
|
||||
/// | homogeneous | ⛔ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | linear | ✅ |
|
||||
/// | access | \f$O(1)\f$ |
|
||||
/// | find | ⛔ |
|
||||
/// | insertion | ⛔ |
|
||||
/// | deletion | ⛔ |
|
||||
/// | space | \f$O(1)\f$ |
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:-----------:|
|
||||
/// | stable | ✅ |
|
||||
/// | dynamic | ⛔ |
|
||||
/// | homogeneous | ⛔ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | linear | ✅ |
|
||||
/// | space | \emph{O(1)} |
|
||||
/// | access | \emph{O(1)} |
|
||||
/// | find | ⛔ |
|
||||
/// | insertion | ⛔ |
|
||||
/// | deletion | ⛔ |
|
||||
///
|
||||
/// \tparam TypeT0 The type of the first value
|
||||
/// \tparam TypeT1 The type of the second value
|
||||
@@ -85,7 +84,7 @@ public:
|
||||
/// \brief Default Constructor, invokes default constructor for both elements
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr pair() = default;
|
||||
|
||||
@@ -93,7 +92,7 @@ public:
|
||||
/// \brief Destructor, invokes destructor for both elements
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr ~pair() = default;
|
||||
|
||||
@@ -103,7 +102,7 @@ public:
|
||||
/// \param y Value to copy for the first element
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr pair(const TypeT0& x, const TypeT1& y)
|
||||
: first(x)
|
||||
@@ -116,7 +115,7 @@ public:
|
||||
/// \param y Value to move for the first element
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr pair(TypeT0&& x, TypeT1&& y) noexcept
|
||||
: first(fennec::forward<TypeT0>(x))
|
||||
@@ -129,7 +128,7 @@ public:
|
||||
/// \param arg2 Value to initialize the first element
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename Arg1T, typename Arg2T>
|
||||
constexpr pair(Arg1T&& arg1, Arg2T&& arg2)
|
||||
@@ -142,7 +141,7 @@ public:
|
||||
/// \param pair The pair to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr pair(const pair& pair)
|
||||
: first(fennec::copy(pair.first))
|
||||
@@ -154,7 +153,7 @@ public:
|
||||
/// \param pair The pair to move
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr pair(pair&& pair) noexcept
|
||||
: first(fennec::move(pair.first))
|
||||
@@ -164,10 +163,10 @@ public:
|
||||
///
|
||||
/// \brief Copy Assignment, copies both elements
|
||||
/// \param pair The pair to copy
|
||||
/// \returns A reference to self
|
||||
/// \returns A reference to \emph{this}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr pair& operator=(const pair& pair) {
|
||||
first = fennec::copy(pair.first);
|
||||
@@ -178,10 +177,10 @@ public:
|
||||
///
|
||||
/// \brief Move Assignment, moves both elements
|
||||
/// \param pair The pair to move
|
||||
/// \returns A reference to self
|
||||
/// \returns A reference to \emph{this}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr pair& operator=(pair&& pair) {
|
||||
first = fennec::move(pair.first);
|
||||
@@ -201,10 +200,10 @@ public:
|
||||
///
|
||||
/// \brief Equality Operator
|
||||
/// \param p Pair to compare with
|
||||
/// \returns \f$true\f$ when both elements of each pair are equal
|
||||
/// \returns \emph{true} when both elements of each pair are equal
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool operator==(const pair& p) const {
|
||||
return first == p.first and second == p.second;
|
||||
@@ -213,10 +212,10 @@ public:
|
||||
///
|
||||
/// \brief Inequality Operator
|
||||
/// \param p Pair to compare with
|
||||
/// \returns \f$true\f$ when either element of each pair are equal
|
||||
/// \returns \emph{true} when either element of each pair are equal
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool operator!=(const pair& p) const {
|
||||
return first != p.first or second != p.second;
|
||||
@@ -225,11 +224,11 @@ public:
|
||||
///
|
||||
/// \brief Less Than Operator
|
||||
/// \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
|
||||
/// \returns lexical comparison of both elements, i.e. returns \emph{true} when the first element is less, or they are
|
||||
/// equal and the second element is less
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool operator<(const pair& p) const {
|
||||
return first < p.first or (first == p.first and second < p.second);
|
||||
@@ -238,11 +237,11 @@ public:
|
||||
///
|
||||
/// \brief Less Equal Operator
|
||||
/// \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
|
||||
/// \returns lexical comparison of both elements, i.e. returns \emph{true} when the first element is less, or they are
|
||||
/// equal and the second element is less or equal
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool operator<=(const pair& p) const {
|
||||
return first < p.first or (first == p.first and second <= p.second);
|
||||
@@ -251,11 +250,11 @@ public:
|
||||
///
|
||||
/// \brief Greater Than Operator
|
||||
/// \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
|
||||
/// \returns lexical comparison of both elements, i.e. returns \emph{true} when the first element is greater, or they are
|
||||
/// equal and the second element is greater
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool operator>(const pair& p) const {
|
||||
return first > p.first or (first == p.first and second > p.second);
|
||||
@@ -264,11 +263,11 @@ public:
|
||||
///
|
||||
/// \brief Greater Equal Operator
|
||||
/// \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
|
||||
/// \returns lexical comparison of both elements, i.e. returns \emph{true} when the first element is greater, or they are
|
||||
/// equal and the second element is greater or equal
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool operator>=(const pair& p) const {
|
||||
return first > p.first or (first == p.first and second >= p.second);
|
||||
@@ -284,9 +283,9 @@ public:
|
||||
template<typename TypeT0, typename TypeT1>
|
||||
struct hash<pair<TypeT0, TypeT1>> : hash<TypeT0>, hash<TypeT1> {
|
||||
///
|
||||
/// \brief C++ 11 Hash Specification \f$operator()\f$
|
||||
/// \brief C++ 11 Hash Specification \emph{operator()}
|
||||
/// \param p The pair to hash
|
||||
/// \returns a pairing of the hashes of both elements of \f$p\f$ using `fennec::pair_hash`
|
||||
/// \returns a pairing of the hashes of both elements of \emph{p} using `fennec::pair_hash`
|
||||
constexpr size_t operator()(const pair<TypeT0, TypeT1>& p) const {
|
||||
return fennec::pair_hash( // pair the hashes of both elements
|
||||
hash<TypeT0>::operator()(p.first),
|
||||
|
||||
@@ -56,20 +56,20 @@ namespace fennec
|
||||
///
|
||||
/// \brief a priority queue data structure implemented using a binary heap
|
||||
/// \details
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ✅ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | linear | ✅ |
|
||||
/// | access | \f$O(1)\f$ |
|
||||
/// | find | ⛔ |
|
||||
/// | insertion | \f$O(1)\f$ |
|
||||
/// | deletion | \f$O(1)\f$ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:-----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ✅ |
|
||||
/// | space | \emph{O(N)} |
|
||||
/// | linear | ✅ |
|
||||
/// | access | \emph{O(1)} |
|
||||
/// | find | ⛔ |
|
||||
/// | insertion | \emph{O(1)} |
|
||||
/// | deletion | \emph{O(1)} |
|
||||
/// | space | \emph{O(N)} |
|
||||
///
|
||||
/// \tparam ValueT The value type
|
||||
/// \tparam CompareT The compare type, defaults to `fennec::less`
|
||||
@@ -115,7 +115,7 @@ public:
|
||||
/// \details initializes an empty queue
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr priority_queue()
|
||||
: _size(0) {
|
||||
@@ -125,7 +125,7 @@ public:
|
||||
/// \brief destructor
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr ~priority_queue() {
|
||||
while (_size > 0) {
|
||||
@@ -142,7 +142,7 @@ public:
|
||||
/// \returns the size of the queue
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t size() const {
|
||||
return _size;
|
||||
@@ -152,17 +152,17 @@ public:
|
||||
/// \returns the capacity of the underlying allocation
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t capacity() const {
|
||||
return _table.capacity();
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns \f$true\f$ if the queue holds no elements
|
||||
/// \returns \emph{true} if the queue holds no elements
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool is_empty() const {
|
||||
return size() == 0;
|
||||
@@ -176,7 +176,7 @@ public:
|
||||
/// \returns the value at the front of the queue
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const value_t& front() const {
|
||||
return _table[0];
|
||||
@@ -191,7 +191,7 @@ public:
|
||||
/// \param key the key to insert
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(\log N)\f$
|
||||
/// \emph{O(\log N)}
|
||||
///
|
||||
constexpr void push(const value_t& key) {
|
||||
this->_insert(key);
|
||||
@@ -201,7 +201,7 @@ public:
|
||||
/// \param key the key to insert
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(\log N)\f$
|
||||
/// \emph{O(\log N)}
|
||||
///
|
||||
constexpr void push(value_t&& key) {
|
||||
this->_insert(fennec::forward<value_t>(key));
|
||||
@@ -213,7 +213,7 @@ public:
|
||||
/// \param args the argument values
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(\log N)\f$
|
||||
/// \emph{O(\log N)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr void emplace(ArgsT&&...args) {
|
||||
@@ -224,7 +224,7 @@ public:
|
||||
/// \brief pop the element at the front of the queue
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(\log N)\f$
|
||||
/// \emph{O(\log N)}
|
||||
///
|
||||
constexpr void pop() {
|
||||
fennec::swap(_table[0], _table[--_size]);
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#define FENNEC_CONTAINERS_RDTREE_H
|
||||
|
||||
#include <fennec/containers/list.h>
|
||||
#include <fennec/containers/optional.h>
|
||||
#include <fennec/containers/deque.h>
|
||||
#include <fennec/containers/traversal.h>
|
||||
#include <fennec/containers/pair.h>
|
||||
|
||||
@@ -44,20 +44,19 @@ namespace fennec
|
||||
///
|
||||
/// \brief Rooted-Directed Tree
|
||||
/// \details
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | linear | ⛔ |
|
||||
/// | access | \f$O(1)\f$ |
|
||||
/// | find | \f$O(N)\f$ |
|
||||
/// | insertion | \f$O(1)\f$ |
|
||||
/// | deletion | \f$O(1)\f$ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:-----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | linear | ⛔ |
|
||||
/// | space | \emph{O(N)} |
|
||||
/// | access | \emph{O(1)} |
|
||||
/// | find | \emph{O(N)} |
|
||||
/// | insertion | \emph{O(1)} |
|
||||
/// | deletion | \emph{O(1)} |
|
||||
///
|
||||
/// \tparam TypeT Data type
|
||||
/// \tparam AllocT Allocator Type
|
||||
@@ -133,7 +132,7 @@ public:
|
||||
/// \param args The arguments to construct the root with
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
explicit constexpr rdtree(ArgsT&&...args)
|
||||
@@ -143,23 +142,62 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Copy Constructor, copies the contents of \f$tree\f$
|
||||
/// \brief Copy Constructor, copies the contents of \emph{tree}
|
||||
/// \param tree the rdtree to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr rdtree(const rdtree& tree)
|
||||
: _table(tree._table), _freed(tree._freed), _size(tree._size) {
|
||||
// TODO: properly invoke copy constructor for all elements
|
||||
constexpr rdtree(const rdtree& tree) {
|
||||
_table.reallocate(tree.size());
|
||||
|
||||
// Stack used for depth-first traversal
|
||||
deque<size_t> visit;
|
||||
deque<size_t> stack;
|
||||
|
||||
// Push the root to the visit queue if the tree isn't empty
|
||||
if (not tree.is_empty()) {
|
||||
stack.push_back(npos);
|
||||
visit.push_back(root);
|
||||
}
|
||||
|
||||
// Iterate
|
||||
while (not visit.is_empty()) {
|
||||
|
||||
// Pop the next node
|
||||
const size_t node = visit.front();
|
||||
visit.pop_front();
|
||||
|
||||
// Get the next node and the child
|
||||
const size_t next = tree.next(node);
|
||||
const size_t child = tree.child(node);
|
||||
|
||||
// Fix stack
|
||||
while (tree.depth(node) < stack.size()) {
|
||||
stack.pop_back();
|
||||
}
|
||||
|
||||
// Add this node
|
||||
stack.push_back(insert(stack.back(), npos, tree[node]));
|
||||
|
||||
// Push the next node
|
||||
if (next != npos) {
|
||||
visit.push_front(next);
|
||||
}
|
||||
|
||||
// Push the child
|
||||
if (child != npos) {
|
||||
visit.push_front(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Move Constructor, takes ownership over the contents of \f$tree\f$
|
||||
/// \brief Move Constructor, takes ownership over the contents of \emph{tree}
|
||||
/// \param tree the rdtree to move
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr rdtree(rdtree&& tree) noexcept
|
||||
: _table(fennec::move(tree._table)), _freed(fennec::move(tree._freed)), _size(tree._size) {
|
||||
@@ -176,10 +214,10 @@ public:
|
||||
///
|
||||
/// \brief Copy Assignment Operator
|
||||
/// \param rhs the rdtree to copy
|
||||
/// \returns \f$this\f$ after copying the contents of \f$rhs\f$
|
||||
/// \returns \emph{this} after copying the contents of \emph{rhs}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr rdtree& operator=(const rdtree& rhs) {
|
||||
// TODO: properly invoke copy constructor for all elements
|
||||
@@ -195,10 +233,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$
|
||||
/// \returns \emph{this} after taking ownership over the contents of \emph{rhs}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr rdtree& operator=(rdtree&& rhs) noexcept {
|
||||
for (value_t* it : _table) {
|
||||
@@ -221,7 +259,7 @@ public:
|
||||
/// \returns The number of nodes in the tree
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t size() const {
|
||||
return _size;
|
||||
@@ -231,17 +269,17 @@ public:
|
||||
/// \returns The capacity of the underlying allocation
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t capacity() const {
|
||||
return _table.capacity();
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns \f$true\f$ when there are no nodes in the tree, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} when there are no nodes in the tree, \emph{false} otherwise
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool is_empty() const {
|
||||
return _size == 0;
|
||||
@@ -260,7 +298,7 @@ public:
|
||||
/// \returns The id of the parent node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t parent(size_t i) const {
|
||||
if (i >= _table.capacity()) return npos;
|
||||
@@ -273,11 +311,11 @@ public:
|
||||
/// \returns The id of the child node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
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;
|
||||
const size_t c = i == npos ? npos : _table[i].child;
|
||||
if (n != 0)
|
||||
return next(c, n == npos ? npos : n - 1);
|
||||
return c;
|
||||
@@ -289,7 +327,7 @@ public:
|
||||
/// \returns The id of the next node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t next(size_t i, size_t n = 0) const {
|
||||
if (i >= _table.capacity() && n != npos) return npos;
|
||||
@@ -297,7 +335,7 @@ public:
|
||||
return npos;
|
||||
}
|
||||
|
||||
size_t org = i;
|
||||
const size_t org = i;
|
||||
size_t nxt = _table[i].next;
|
||||
while (nxt != npos) {
|
||||
i = nxt;
|
||||
@@ -318,7 +356,7 @@ public:
|
||||
/// \returns The id of the previous node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t prev(size_t i, size_t n = 0) const {
|
||||
if (i >= _table.capacity()) return npos;
|
||||
@@ -326,7 +364,7 @@ public:
|
||||
return npos;
|
||||
}
|
||||
|
||||
size_t org = i;
|
||||
const size_t org = i;
|
||||
size_t prv = _table[i].prev;
|
||||
while (prv != npos) {
|
||||
i = prv;
|
||||
@@ -343,10 +381,10 @@ public:
|
||||
|
||||
///
|
||||
/// \param i the node to start at
|
||||
/// \returns the left-most child of node \f$i\f$
|
||||
/// \returns the left-most child of node \emph{i}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(\log N)\f$
|
||||
/// \emph{O(\log N)}
|
||||
///
|
||||
constexpr size_t left_most(size_t i) const {
|
||||
if (i >= _table.capacity()) return npos;
|
||||
@@ -355,7 +393,7 @@ public:
|
||||
return i;
|
||||
}
|
||||
while (true) {
|
||||
size_t p = n;
|
||||
const size_t p = n;
|
||||
if ((n = child(n)) == npos) {
|
||||
return p;
|
||||
}
|
||||
@@ -364,10 +402,10 @@ public:
|
||||
|
||||
///
|
||||
/// \param i the node to start at
|
||||
/// \returns the right-most child of node \f$i\f$
|
||||
/// \returns the right-most child of node \emph{i}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(\log N)\f$
|
||||
/// \emph{O(\log N)}
|
||||
///
|
||||
constexpr size_t right_most(size_t i) const {
|
||||
if (i >= _table.capacity()) return npos;
|
||||
@@ -391,7 +429,7 @@ public:
|
||||
/// \returns The depth of the node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t depth(size_t i) const {
|
||||
if (i >= _table.capacity()) return npos;
|
||||
@@ -403,7 +441,7 @@ public:
|
||||
/// \returns The number of children the node has
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t num_children(size_t i) const {
|
||||
if (i >= _table.capacity()) return 0;
|
||||
@@ -411,10 +449,10 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns The next node id were \f$insert\f$ or \f$emplace\f$ to be called
|
||||
/// \returns The next node id were \emph{insert} or \emph{emplace} to be called
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t next_id() const {
|
||||
size_t i = _size;
|
||||
@@ -429,7 +467,7 @@ public:
|
||||
/// \returns A reference to the value of the node wrapped in an optional
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr value_t& operator[](size_t i) {
|
||||
return _table[i].value;
|
||||
@@ -440,7 +478,7 @@ public:
|
||||
/// \returns A const-qualified reference to the value of the node wrapped in an optional
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const value_t& operator[](size_t i) const {
|
||||
return _table[i].value;
|
||||
@@ -455,28 +493,28 @@ public:
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \brief Insertion, creates a node in the tree with parent \f$parent\f$
|
||||
/// \param parent the parent node, if \f$npos\f$ sets the value of the root node
|
||||
/// \brief Insertion, creates a node in the tree with parent \emph{parent}
|
||||
/// \param parent the parent node, if \emph{npos} sets the value of the root node
|
||||
/// \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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t insert(size_t parent, size_t next, const value_t& val) {
|
||||
return this->_insert(parent, next, val);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Insertion, creates a node in the tree with parent \f$parent\f$
|
||||
/// \param parent the parent node, if \f$npos\f$ sets the value of the root node
|
||||
/// \brief Insertion, creates a node in the tree with parent \emph{parent}
|
||||
/// \param parent the parent node, if \emph{npos} sets the value of the root node
|
||||
/// \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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t insert(size_t parent, size_t next, value_t&& val) {
|
||||
return this->_insert(parent, next, fennec::forward<value_t>(val));
|
||||
@@ -484,13 +522,13 @@ public:
|
||||
|
||||
///
|
||||
/// \brief tree insertion, copies the contents of tree into self with the root at the specified node location
|
||||
/// \param parent the parent node, if \f$npos\f$ sets the value of the root node
|
||||
/// \param parent the parent node, if \emph{npos} sets the value of the root node
|
||||
/// \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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t insert(size_t parent, size_t next, const rdtree& tree) {
|
||||
list<pair<size_t, size_t>> visit;
|
||||
@@ -516,14 +554,14 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Insertion, creates a node in the tree with parent \f$parent\f$
|
||||
/// \param parent the parent node, if \f$npos\f$ sets the value of the root node
|
||||
/// \brief Insertion, creates a node in the tree with parent \emph{parent}
|
||||
/// \param parent the parent node, if \emph{npos} sets the value of the root node
|
||||
/// \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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr size_t emplace(size_t parent, size_t next, ArgsT&&...args) {
|
||||
@@ -536,7 +574,7 @@ public:
|
||||
/// \param i1 The id of the second node
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr void swap(size_t i0, size_t i1) {
|
||||
assertf(i0 != root and i1 != root, "Cannot Swap With Root");
|
||||
@@ -575,16 +613,16 @@ 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 accept a reference to a value of type \emph{TypeT} and a \emph{size_t} which contains the node's id.
|
||||
/// The visitor should return one of the following values in the `fennec::traversal_control_` enum
|
||||
///
|
||||
/// \tparam OrderT The order with which to traverse the tree.
|
||||
/// \tparam VisitorT The visitor, should fulfill the signature \f$uint8_t visit(TypeT&, size_t)\f$
|
||||
/// \tparam VisitorT The visitor, should fulfill the signature \emph{uint8_t visit(TypeT&, size_t)}
|
||||
/// \param visit The visiting object
|
||||
/// \param i The node to start at
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
template<typename OrderT, typename VisitorT>
|
||||
constexpr void traverse(VisitorT&& visit, size_t i = root) {
|
||||
@@ -606,16 +644,16 @@ 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 accept a reference to a value of type \emph{TypeT} and a \emph{size_t} which contains the node's id.
|
||||
/// The visitor should return one of the following values in the `fennec::traversal_control_` enum
|
||||
///
|
||||
/// \tparam OrderT The order with which to traverse the tree.
|
||||
/// \tparam VisitorT The visitor, should fulfill the signature \f$uint8_t visit(TypeT&, size_t)\f$
|
||||
/// \tparam VisitorT The visitor, should fulfill the signature \emph{uint8_t visit(TypeT&, size_t)}
|
||||
/// \param visit The visiting object
|
||||
/// \param i The node to start at
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
template<typename OrderT, typename VisitorT>
|
||||
constexpr void traverse(VisitorT&& visit, size_t i = root) const {
|
||||
@@ -657,8 +695,8 @@ public:
|
||||
return npos;
|
||||
}
|
||||
|
||||
size_t nxt = tree.next(node);
|
||||
size_t chd = tree.next(node);
|
||||
const size_t nxt = tree.next(node);
|
||||
const size_t chd = tree.next(node);
|
||||
|
||||
if (nxt != npos && node != head) {
|
||||
visit.push_front(nxt);
|
||||
@@ -680,7 +718,7 @@ public:
|
||||
|
||||
private:
|
||||
list<size_t> visit;
|
||||
size_t head;
|
||||
size_t head = npos;
|
||||
};
|
||||
|
||||
///
|
||||
@@ -707,8 +745,8 @@ public:
|
||||
return npos;
|
||||
}
|
||||
|
||||
size_t nxt = tree.next(node);
|
||||
size_t chd = tree.child(node);
|
||||
const size_t nxt = tree.next(node);
|
||||
const size_t chd = tree.child(node);
|
||||
|
||||
if (nxt != npos && node != head) {
|
||||
visit.push_front(nxt);
|
||||
@@ -730,7 +768,7 @@ public:
|
||||
|
||||
private:
|
||||
list<size_t> visit;
|
||||
size_t head;
|
||||
size_t head = npos;
|
||||
};
|
||||
|
||||
///
|
||||
@@ -757,8 +795,8 @@ public:
|
||||
return npos;
|
||||
}
|
||||
|
||||
size_t prnt = tree.parent(node);
|
||||
size_t next = tree.next(node);
|
||||
const size_t prnt = tree.parent(node);
|
||||
const size_t next = tree.next(node);
|
||||
if (node != head) {
|
||||
if (tree.child(prnt) == node) {
|
||||
visit.push_back(prnt);
|
||||
@@ -782,7 +820,7 @@ public:
|
||||
|
||||
private:
|
||||
list<size_t> visit;
|
||||
size_t head;
|
||||
size_t head = npos;
|
||||
};
|
||||
|
||||
///
|
||||
@@ -809,8 +847,8 @@ public:
|
||||
return npos;
|
||||
}
|
||||
|
||||
size_t prnt = tree.parent(node);
|
||||
size_t next = tree.next(node);
|
||||
const size_t prnt = tree.parent(node);
|
||||
const size_t next = tree.next(node);
|
||||
|
||||
if (node != head) {
|
||||
if (next != npos) {
|
||||
@@ -832,7 +870,7 @@ public:
|
||||
|
||||
private:
|
||||
list<size_t> visit;
|
||||
size_t head;
|
||||
size_t head = npos;
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
||||
@@ -56,20 +56,19 @@ namespace fennec
|
||||
/// \details
|
||||
/// This data-structure behaves like an ordered-set, but does not use pointers, instead storing the table in-array
|
||||
///
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:---------------:|
|
||||
/// | stable | ✅ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ✅ |
|
||||
/// | ordered | ✅ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | linear | ✅ |
|
||||
/// | access | \f$O(\log N)\f$ |
|
||||
/// | find | \f$O(\log N)\f$ |
|
||||
/// | insertion | \f$O(\log N)\f$ |
|
||||
/// | deletion | \f$O(\log N)\f$ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:----------------:|
|
||||
/// | stable | ✅ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ✅ |
|
||||
/// | ordered | ✅ |
|
||||
/// | linear | ✅ |
|
||||
/// | space | \emph{O(N)} |
|
||||
/// | access | \emph{O(\log N)} |
|
||||
/// | find | \emph{O(\log N)} |
|
||||
/// | insertion | \emph{O(\log N)} |
|
||||
/// | deletion | \emph{O(\log N)} |
|
||||
///
|
||||
/// \tparam TypeT The type to contain
|
||||
/// \tparam CompareT Function for comparing two values
|
||||
@@ -141,27 +140,27 @@ private:
|
||||
|
||||
// Member Access Helpers
|
||||
|
||||
constexpr value_t& _key(node n) {
|
||||
static constexpr value_t& _key(node n) {
|
||||
return n->key;
|
||||
}
|
||||
|
||||
constexpr bool& _color(node n) {
|
||||
static constexpr bool& _color(node n) {
|
||||
return n->color;
|
||||
}
|
||||
|
||||
constexpr node& _parent(node n) {
|
||||
static constexpr node& _parent(node n) {
|
||||
return n->parent;
|
||||
}
|
||||
|
||||
constexpr node& _child(node n, bool dir) {
|
||||
static constexpr node& _child(node n, bool dir) {
|
||||
return n->child[dir];
|
||||
}
|
||||
|
||||
constexpr node& _left(node n) {
|
||||
static constexpr node& _left(node n) {
|
||||
return n->child[dir_left];
|
||||
}
|
||||
|
||||
constexpr node& _right(node n) {
|
||||
static constexpr node& _right(node n) {
|
||||
return n->child[dir_right];
|
||||
}
|
||||
|
||||
@@ -174,7 +173,7 @@ private:
|
||||
}
|
||||
|
||||
constexpr bool color(node n) {
|
||||
return n ? n->color : (bool)black;
|
||||
return n ? n->color : bool(black);
|
||||
}
|
||||
|
||||
constexpr node parent(node n) {
|
||||
@@ -224,7 +223,7 @@ public:
|
||||
/// \brief Default Constructor, initializes an empty sequence
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr sequence()
|
||||
: _root(nullptr), _size(0) {
|
||||
@@ -234,7 +233,7 @@ public:
|
||||
/// \brief Move Constructor, takes ownership of a sequence
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr sequence(sequence&&) noexcept = default;
|
||||
|
||||
@@ -247,7 +246,7 @@ public:
|
||||
/// \brief Default Destructor, destructs elements *in-order*
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr ~sequence() {
|
||||
this->clear();
|
||||
@@ -261,12 +260,12 @@ public:
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \brief Value Find Function, finds the iterator position for \f$val\f$, otherwise returns \f$end()\f$
|
||||
/// \brief Value Find Function, finds the iterator position for \emph{val}, otherwise returns \emph{end()}
|
||||
/// \param val The value to find
|
||||
/// \returns An iterator at the value
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(\log N)\f$
|
||||
/// \emph{O(\log N)}
|
||||
///
|
||||
constexpr iterator find(const value_t& val) {
|
||||
node node = _root;
|
||||
@@ -285,7 +284,7 @@ public:
|
||||
///
|
||||
/// \brief Value Contains Function, checks if the sequence contains a value
|
||||
/// \param val The value to find
|
||||
/// \returns \f$true\f$ if \f$val\f$ is in the sequence, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if \emph{val} is in the sequence, \emph{false} otherwise
|
||||
bool contains(const value_t& val) {
|
||||
return find(val) != end();
|
||||
}
|
||||
@@ -302,17 +301,17 @@ public:
|
||||
/// \returns The number of elements in the sequence
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns \f$true\f$ when there are no elements in the sequence, \f$false\f$ otherwise.
|
||||
/// \returns \emph{true} when there are no elements in the sequence, \emph{false} otherwise.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool is_empty() const {
|
||||
return _size == 0;
|
||||
@@ -326,11 +325,11 @@ public:
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \brief Move Insertion, moves \f$val\f$ into the sequence
|
||||
/// \brief Move Insertion, moves \emph{val} into the sequence
|
||||
/// \param val The value to insert
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(\log N)\f$
|
||||
/// \emph{O(\log N)}
|
||||
///
|
||||
constexpr void insert(value_t&& val) {
|
||||
node i = _insert_bst(fennec::forward<value_t>(val));
|
||||
@@ -338,11 +337,11 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Copy Insertion, inserts a copy of \f$val\f$ into the sequence
|
||||
/// \brief Copy Insertion, inserts a copy of \emph{val} into the sequence
|
||||
/// \param val The value to insert
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(\log N)\f$
|
||||
/// \emph{O(\log N)}
|
||||
///
|
||||
constexpr void insert(const value_t& val) {
|
||||
node i = _insert_bst(val);
|
||||
@@ -355,7 +354,7 @@ public:
|
||||
/// \param args The arguments to construct with
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(\log N)\f$
|
||||
/// \emph{O(\log N)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr void emplace(ArgsT&&...args) {
|
||||
@@ -368,7 +367,7 @@ public:
|
||||
/// \param val the value to erase
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(\log N)\f$
|
||||
/// \emph{O(\log N)}
|
||||
///
|
||||
constexpr void erase(const value_t& val) {
|
||||
_erase(find(val)._node);
|
||||
@@ -378,7 +377,7 @@ public:
|
||||
/// \brief Destructs all elements, *in-order*, contained in the sequence
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr void clear() {
|
||||
list<node> visit;
|
||||
@@ -400,18 +399,18 @@ public:
|
||||
/// \returns An iterator at the smallest element in the sequence
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(\log N)\f$
|
||||
/// \emph{O(\log N)}
|
||||
///
|
||||
constexpr iterator begin() {
|
||||
return sequence::iterator(this, _root);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$begin()\f$
|
||||
/// \brief C++ Iterator Specification \emph{begin()}
|
||||
/// \returns An iterator at the smallest element in the sequence
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(\log N)\f$
|
||||
/// \emph{O(\log N)}
|
||||
///
|
||||
constexpr const_iterator begin() const {
|
||||
return sequence::const_iterator(this, _root);
|
||||
@@ -421,32 +420,32 @@ public:
|
||||
/// \returns An iterator after the largest element in the sequence
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr iterator end() {
|
||||
return sequence::iterator(this, _root, nullptr);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Const C++ Iterator Specification \f$end()\f$
|
||||
/// \brief Const C++ Iterator Specification \emph{end()}
|
||||
/// \returns An iterator after the largest element in the sequence
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const_iterator end() const {
|
||||
return sequence::const_iterator(this, _root, nullptr);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$iterator\f$
|
||||
/// \brief C++ Iterator Specification \emph{iterator}
|
||||
class iterator {
|
||||
public:
|
||||
|
||||
///
|
||||
/// \brief prefix increment operator
|
||||
/// \param it the iterator to increment
|
||||
/// \returns \f$it\f$ after having moved to the next element in the list
|
||||
/// \returns \emph{it} after having moved to the next element in the list
|
||||
friend iterator& operator++(iterator& it) {
|
||||
if (it._node == nullptr) {
|
||||
return it;
|
||||
@@ -477,7 +476,7 @@ public:
|
||||
///
|
||||
/// \brief postfix increment operator
|
||||
/// \param it the iterator to increment
|
||||
/// \returns \f$it\f$ before having moved to the next element in the list
|
||||
/// \returns \emph{it} before having moved to the next element in the list
|
||||
friend iterator operator++(iterator& it, int) {
|
||||
iterator prev = it;
|
||||
++it;
|
||||
@@ -502,7 +501,7 @@ public:
|
||||
/// \brief iterator equality operator
|
||||
/// \param lhs the iterator
|
||||
/// \param rhs the iterator to compare with
|
||||
/// \returns \f$true\f$ if the iterators are identical, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the iterators are identical, \emph{false} otherwise
|
||||
constexpr friend bool operator==(const iterator& lhs, const iterator& rhs) {
|
||||
return lhs._seq == rhs._seq and lhs._node == rhs._node;
|
||||
}
|
||||
@@ -511,7 +510,7 @@ public:
|
||||
/// \brief iterator inequality operator
|
||||
/// \param lhs the iterator
|
||||
/// \param rhs the iterator to compare with
|
||||
/// \returns \f$true\f$ if the iterators are different, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the iterators are different, \emph{false} otherwise
|
||||
constexpr friend bool operator!=(const iterator& lhs, const iterator& rhs) {
|
||||
return lhs._seq != rhs._seq or lhs._node != rhs._node;
|
||||
}
|
||||
@@ -538,14 +537,14 @@ public:
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$iterator\f$
|
||||
/// \brief C++ Iterator Specification \emph{iterator}
|
||||
class const_iterator {
|
||||
public:
|
||||
|
||||
///
|
||||
/// \brief prefix increment operator
|
||||
/// \param it the iterator to increment
|
||||
/// \returns \f$it\f$ after having moved to the next element in the list
|
||||
/// \returns \emph{it} after having moved to the next element in the list
|
||||
friend const_iterator& operator++(const_iterator& it) {
|
||||
if (it._node == nullptr) {
|
||||
return it;
|
||||
@@ -576,7 +575,7 @@ public:
|
||||
///
|
||||
/// \brief postfix increment operator
|
||||
/// \param it the iterator to increment
|
||||
/// \returns \f$it\f$ before having moved to the next element in the list
|
||||
/// \returns \emph{it} before having moved to the next element in the list
|
||||
friend const_iterator operator++(const_iterator& it, int) {
|
||||
const_iterator prev = it;
|
||||
++it;
|
||||
@@ -601,7 +600,7 @@ public:
|
||||
/// \brief iterator equality operator
|
||||
/// \param lhs the iterator
|
||||
/// \param rhs the iterator to compare with
|
||||
/// \returns \f$true\f$ if the iterators are identical, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the iterators are identical, \emph{false} otherwise
|
||||
constexpr friend bool operator==(const const_iterator& lhs, const const_iterator& rhs) {
|
||||
return lhs._seq == rhs._seq and lhs._node == rhs._node;
|
||||
}
|
||||
@@ -610,7 +609,7 @@ public:
|
||||
/// \brief iterator inequality operator
|
||||
/// \param lhs the iterator
|
||||
/// \param rhs the iterator to compare with
|
||||
/// \returns \f$true\f$ if the iterators are different, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the iterators are different, \emph{false} otherwise
|
||||
constexpr friend bool operator!=(const const_iterator& lhs, const const_iterator& rhs) {
|
||||
return lhs._seq != rhs._seq or lhs._node != rhs._node;
|
||||
}
|
||||
|
||||
@@ -49,20 +49,19 @@ namespace fennec
|
||||
/// \details
|
||||
/// This data-structure behaves like a set, but does not use pointers, instead storing the table in-array
|
||||
///
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ✅ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | linear | ✅ |
|
||||
/// | access | \f$O(1)\f$ |
|
||||
/// | find | \f$O(1)\f$ |
|
||||
/// | insertion | \f$O(1)\f$ |
|
||||
/// | deletion | \f$O(1)\f$ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:-----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ✅ |
|
||||
/// | distinct | ✅ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | linear | ✅ |
|
||||
/// | space | \emph{O(N)} |
|
||||
/// | access | \emph{O(1)} |
|
||||
/// | find | \emph{O(1)} |
|
||||
/// | insertion | \emph{O(1)} |
|
||||
/// | deletion | \emph{O(1)} |
|
||||
///
|
||||
/// \tparam TypeT The type to contain
|
||||
template<typename TypeT, class Hash = hash<TypeT>, class Equals = equality<TypeT>, class Alloc = allocator<TypeT>>
|
||||
@@ -112,7 +111,7 @@ public:
|
||||
/// \brief Default Constructor, initializes empty set
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr set()
|
||||
: _table()
|
||||
@@ -127,7 +126,7 @@ public:
|
||||
/// \param hash the hash object
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr set(const hash_t& hash)
|
||||
: _table()
|
||||
@@ -142,7 +141,7 @@ public:
|
||||
/// \param alloc the allocator object
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr set(const alloc_t& alloc)
|
||||
: _table(alloc)
|
||||
@@ -158,7 +157,7 @@ public:
|
||||
/// \param alloc the allocator object
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr set(const hash_t& hash, const alloc_t& alloc)
|
||||
: _table(alloc)
|
||||
@@ -173,7 +172,7 @@ public:
|
||||
/// \param set Set to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr set(const set& set)
|
||||
: _table(set._table)
|
||||
@@ -188,7 +187,7 @@ public:
|
||||
/// \param set Set to move
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr set(set&& set) noexcept
|
||||
: _table(fennec::move(set._table))
|
||||
@@ -202,7 +201,7 @@ public:
|
||||
/// \brief Destructor, destructs all elements and releases the allocation
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr ~set() {
|
||||
for (size_t i = 0; i < capacity(); ++i) {
|
||||
@@ -222,17 +221,17 @@ public:
|
||||
/// \returns Size of the set in elements
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns \f$true\f$ when the set is empty, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} when the set is empty, \emph{false} otherwise
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool is_empty() const {
|
||||
return _size == 0;
|
||||
@@ -242,7 +241,7 @@ public:
|
||||
/// \returns Capacity of the set in elements
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr size_t capacity() const {
|
||||
return _table.size();
|
||||
@@ -262,7 +261,7 @@ public:
|
||||
/// \returns An iterator at the location of the value
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr iterator find(const elem_t& val) const {
|
||||
if (capacity() == 0) {
|
||||
@@ -311,10 +310,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
|
||||
/// \returns \emph{true} if \emph{val} can be found, \emph{false} otherwise
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr bool contains(const elem_t& val) const {
|
||||
return this->find(val) != end();
|
||||
@@ -323,11 +322,11 @@ public:
|
||||
///
|
||||
/// \brief Iterator Access
|
||||
/// \param it Location to access
|
||||
/// \returns A pointer to the element, \f$nullptr\f$ if not found.
|
||||
/// \returns A pointer to the element, \emph{nullptr} 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$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr elem_t* at(const iterator& it) {
|
||||
if (it == end()) {
|
||||
@@ -342,10 +341,10 @@ public:
|
||||
///
|
||||
/// \brief Iterator Const Access
|
||||
/// \param it Location to access
|
||||
/// \returns A const-qualified pointer to the element, \f$nullptr\f$ if not found.
|
||||
/// \returns A const-qualified pointer to the element, \emph{nullptr} if not found.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr const elem_t* at(const iterator& it) const {
|
||||
if (not _table[it._i].value) return nullptr;
|
||||
@@ -365,7 +364,7 @@ public:
|
||||
/// \returns An iterator at the held value
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr iterator insert(elem_t&& val) {
|
||||
return this->_insert(fennec::forward<elem_t>(val));
|
||||
@@ -377,7 +376,7 @@ public:
|
||||
/// \returns An iterator at the held value
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr iterator insert(const elem_t& val) {
|
||||
return this->_insert(val);
|
||||
@@ -390,7 +389,7 @@ public:
|
||||
/// \returns An iterator at the held value
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
constexpr iterator emplace(ArgsT&&...args) {
|
||||
@@ -402,7 +401,7 @@ public:
|
||||
/// \param it Location to erase
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr void erase(iterator it) {
|
||||
size_t i = it._i;
|
||||
@@ -431,7 +430,7 @@ public:
|
||||
/// \param val Value to erase
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr void erase(const elem_t& val) {
|
||||
this->erase(this->find(val));
|
||||
@@ -441,7 +440,7 @@ public:
|
||||
/// \brief Clear all elements from the set, destructing them
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
constexpr void clear() {
|
||||
_table.clear();
|
||||
@@ -456,11 +455,11 @@ public:
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$begin()\f$
|
||||
/// \brief C++ Iterator Specification \emph{begin()}
|
||||
/// \returns An iterator for all elements of the set in no particular order
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr iterator begin() const {
|
||||
iterator it(this, 0);
|
||||
@@ -471,11 +470,11 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$end()\f$
|
||||
/// \brief C++ Iterator Specification \emph{end()}
|
||||
/// \returns An iterator representing the end of the set
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
constexpr iterator end() const {
|
||||
return iterator(this, npos);
|
||||
@@ -484,10 +483,10 @@ public:
|
||||
/// @}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$iterator\f$
|
||||
/// \brief C++ Iterator Specification \emph{iterator}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
class iterator {
|
||||
public:
|
||||
@@ -500,7 +499,7 @@ public:
|
||||
///
|
||||
/// \brief prefix increment operator
|
||||
/// \param it the iterator to increment
|
||||
/// \returns \f$it\f$ after having moved to the next element in the list
|
||||
/// \returns \emph{it} 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->_table[it._i].value) {
|
||||
@@ -514,7 +513,7 @@ public:
|
||||
///
|
||||
/// \brief postfix increment operator
|
||||
/// \param it the iterator to increment
|
||||
/// \returns \f$it\f$ before having moved to the next element in the list
|
||||
/// \returns \emph{it} before having moved to the next element in the list
|
||||
constexpr friend iterator operator++(iterator& it, int) {
|
||||
iterator prev = it;
|
||||
++it;
|
||||
@@ -539,7 +538,7 @@ public:
|
||||
///
|
||||
/// \brief iterator equality operator
|
||||
/// \param it the iterator to compare with
|
||||
/// \returns \f$true\f$ if the iterators are identical, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the iterators are identical, \emph{false} otherwise
|
||||
constexpr bool operator==(const iterator& it) const {
|
||||
return _set == it._set and _i == it._i;
|
||||
}
|
||||
@@ -547,7 +546,7 @@ public:
|
||||
///
|
||||
/// \brief iterator inequality operator
|
||||
/// \param it the iterator to compare with
|
||||
/// \returns \f$true\f$ if the iterators are different, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the iterators are different, \emph{false} otherwise
|
||||
constexpr bool operator!=(const iterator& it) const {
|
||||
return _set != it._set or _i != it._i;
|
||||
}
|
||||
|
||||
@@ -42,20 +42,19 @@ namespace fennec
|
||||
///
|
||||
/// \brief Tuple, holds a collection of values of different types
|
||||
/// \details
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ⛔ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | linear | ✅ |
|
||||
/// | access | \f$O(1)\f$ |
|
||||
/// | find | \f$O(1)\f$ |
|
||||
/// | insertion | ⛔ |
|
||||
/// | deletion | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:-----------:|
|
||||
/// | stable | ⛔ |
|
||||
/// | dynamic | ✅ |
|
||||
/// | homogeneous | ⛔ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | linear | ✅ |
|
||||
/// | space | \emph{O(N)} |
|
||||
/// | access | \emph{O(1)} |
|
||||
/// | find | \emph{O(1)} |
|
||||
/// | insertion | ⛔ |
|
||||
/// | deletion | ⛔ |
|
||||
///
|
||||
/// \tparam TypesT The types to store
|
||||
template<typename...TypesT> struct tuple;
|
||||
@@ -65,7 +64,7 @@ template<typename...TypesT> struct tuple;
|
||||
/// \tparam i the index
|
||||
/// \tparam TypesT the types held in the tuple
|
||||
/// \param x the tuple
|
||||
/// \returns the \f$i\f$th element of the tuple
|
||||
/// \returns the \emph{i}th element of the tuple
|
||||
template<size_t i, typename...TypesT>
|
||||
constexpr typename tuple<TypesT...>::template elem_t<i>& get(tuple<TypesT...>& x) {
|
||||
using elem_t = typename tuple<TypesT...>::template elem_t<i>;
|
||||
@@ -77,7 +76,7 @@ constexpr typename tuple<TypesT...>::template elem_t<i>& get(tuple<TypesT...>& x
|
||||
/// \tparam i the index
|
||||
/// \tparam TypesT the types held in the tuple
|
||||
/// \param x the tuple
|
||||
/// \returns the \f$i\f$th element of the tuple
|
||||
/// \returns the \emph{i}th element of the tuple
|
||||
template<size_t i, typename...TypesT>
|
||||
constexpr const typename tuple<TypesT...>::template elem_t<i>& get(const tuple<TypesT...>& x) {
|
||||
using elem_t = typename tuple<TypesT...>::template elem_t<i>;
|
||||
@@ -98,7 +97,7 @@ public:
|
||||
using base_t = detail::_tuple<make_index_metasequence_t<sizeof...(TypesT)>, TypesT...>; //!< the base type
|
||||
|
||||
template<size_t i>
|
||||
using elem_t = typename nth_element<i, TypesT...>::type; //!< helper for getting the \f$i\f$th element
|
||||
using elem_t = typename nth_element<i, TypesT...>::type; //!< helper for getting the \emph{i}th element
|
||||
|
||||
static constexpr size_t size = sizeof...(TypesT); //!< the number of elements held by the tuple
|
||||
|
||||
@@ -114,7 +113,7 @@ public:
|
||||
/// \param args The arguments to initialize the tuple with
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
template<typename...ArgsT>
|
||||
tuple(ArgsT&&...args)
|
||||
@@ -126,7 +125,7 @@ public:
|
||||
/// \param cpy the tuple to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
tuple(const tuple& cpy)
|
||||
: base_t(cpy) {
|
||||
@@ -137,7 +136,7 @@ public:
|
||||
/// \param mov the tuple to move
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(N)\f$
|
||||
/// \emph{O(N)}
|
||||
///
|
||||
tuple(tuple&& mov)
|
||||
: base_t(fennec::forward<tuple>(mov)) {
|
||||
|
||||
@@ -40,22 +40,21 @@ namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief A structure that represents a union between \f$TypesT\ldots\f$
|
||||
/// \brief A structure that represents a union between \emph{TypesT\ldots}
|
||||
/// \details
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:----------:|
|
||||
/// | stable | ✅ |
|
||||
/// | dynamic | ⛔ |
|
||||
/// | homogeneous | ⛔ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | space | \f$O(N)\f$ |
|
||||
/// | linear | ⛔ |
|
||||
/// | access | \f$O(1)\f$ |
|
||||
/// | find | ⛔ |
|
||||
/// | insertion | \f$O(1)\f$ |
|
||||
/// | deletion | \f$O(1)\f$ |
|
||||
/// | space | \f$O(1)\f$ |
|
||||
/// | Property | Value |
|
||||
/// |:-----------:|:-----------:|
|
||||
/// | stable | ✅ |
|
||||
/// | dynamic | ⛔ |
|
||||
/// | homogeneous | ⛔ |
|
||||
/// | distinct | ⛔ |
|
||||
/// | ordered | ⛔ |
|
||||
/// | linear | ⛔ |
|
||||
/// | space | \emph{O(1)} |
|
||||
/// | access | \emph{O(1)} |
|
||||
/// | find | ⛔ |
|
||||
/// | insertion | \emph{O(1)} |
|
||||
/// | deletion | \emph{O(1)} |
|
||||
///
|
||||
/// \tparam TypesT The types to hold in the variant
|
||||
template<typename...TypesT>
|
||||
@@ -90,10 +89,10 @@ public:
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \brief Default Constructor, constructs the first type in \f$TypesT\ldots\f$ that is default constructible
|
||||
/// \brief Default Constructor, constructs the first type in \emph{TypesT...} that is default constructible
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
variant()
|
||||
: _bytes {}
|
||||
@@ -104,13 +103,13 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \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$
|
||||
/// \brief Conversion Constructor, constructs the type in \emph{TypesT...} that is identical to \emph{T}
|
||||
/// or the first that is constructible with \emph{T}
|
||||
/// \tparam T The type of the value
|
||||
/// \param t The value to forward
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename T>
|
||||
variant(T&& t)
|
||||
@@ -124,12 +123,12 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Emplace Constructor, constructs a type \f$T\f$ that is in \f$TypesT\ldots\f$ that is constructible with \f$ArgsT\ldots\f$
|
||||
/// \brief Emplace Constructor, constructs a type \emph{T} that is in \emph{TypesT...} that is constructible with \emph{ArgsT...}
|
||||
/// \tparam ArgsT The arguments of the constructor
|
||||
/// \param args The argument values
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename T, typename...ArgsT>
|
||||
variant(type_identity<T>, ArgsT&&...args)
|
||||
@@ -146,7 +145,7 @@ public:
|
||||
/// \param v The variant to copy
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
variant(const variant& v)
|
||||
: _bytes {}
|
||||
@@ -169,7 +168,7 @@ public:
|
||||
/// \param v The variant to move
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
variant(variant&& v) noexcept
|
||||
: _bytes {}
|
||||
@@ -191,7 +190,7 @@ public:
|
||||
/// \brief Destructor, if a type is held, destruct it.
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
~variant() {
|
||||
_clear();
|
||||
@@ -211,10 +210,10 @@ public:
|
||||
/// \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$
|
||||
/// \returns a reference to \emph{self} after assigning \emph{t}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename T>
|
||||
variant& operator=(T&& t) {
|
||||
@@ -259,7 +258,7 @@ public:
|
||||
/// \param args the argument values
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename T, typename...ArgsT> requires(contains_element_v<T, TypesT...>)
|
||||
void emplace(ArgsT&&...args) {
|
||||
@@ -273,7 +272,7 @@ public:
|
||||
/// \param args the argument values
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<size_t I, typename...ArgsT>
|
||||
void emplace(ArgsT&&...args) {
|
||||
@@ -291,12 +290,12 @@ public:
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \brief get the value of the variant interpreted as \f$T\f$
|
||||
/// \brief get the value of the variant interpreted as \emph{T}
|
||||
/// \tparam T the type to interpret as
|
||||
/// \returns The value interpreted as \f$T\f$
|
||||
/// \returns The value interpreted as \emph{T}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename T> requires(contains_element_v<T, TypesT...>)
|
||||
T& get() {
|
||||
@@ -305,10 +304,10 @@ public:
|
||||
|
||||
///
|
||||
/// \tparam T the type to interpret as
|
||||
/// \returns The value interpreted as \f$T\f$
|
||||
/// \returns The value interpreted as \emph{T}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<typename T> requires(contains_element_v<T, TypesT...>)
|
||||
const T& get() const {
|
||||
@@ -317,10 +316,10 @@ public:
|
||||
|
||||
///
|
||||
/// \tparam T the type to interpret as
|
||||
/// \returns The value interpreted as \f$T\f$
|
||||
/// \returns The value interpreted as \emph{T}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<size_t I, typename T = nth_element_t<I, TypesT...>> requires(contains_element_v<T, TypesT...>)
|
||||
T& get() {
|
||||
@@ -329,10 +328,10 @@ public:
|
||||
|
||||
///
|
||||
/// \tparam T the type to interpret as
|
||||
/// \returns The value interpreted as \f$T\f$
|
||||
/// \returns The value interpreted as \emph{T}
|
||||
///
|
||||
/// \par Complexity
|
||||
/// \f$O(1)\f$
|
||||
/// \emph{O(1)}
|
||||
///
|
||||
template<size_t I, typename T = nth_element_t<I, TypesT...>> requires(contains_element_v<T, TypesT...>)
|
||||
const T& get() const {
|
||||
|
||||
@@ -32,9 +32,11 @@
|
||||
#ifndef FENNEC_CORE_LOGGER_H
|
||||
#define FENNEC_CORE_LOGGER_H
|
||||
|
||||
#include <fennec/containers/pair.h>
|
||||
#include <fennec/filesystem/file.h>
|
||||
#include <fennec/rtti/singleton.h>
|
||||
#include <fennec/containers/tuple.h>
|
||||
#include <fennec/lang/system.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
@@ -43,6 +45,31 @@ namespace fennec
|
||||
/// \brief logger class
|
||||
class logger : public singleton<logger> {
|
||||
|
||||
// Definitions =========================================================================================================
|
||||
public:
|
||||
|
||||
///
|
||||
/// \brief Log Severities
|
||||
enum severity : uint32_t {
|
||||
info = 0,
|
||||
alert,
|
||||
warning,
|
||||
error,
|
||||
fatal,
|
||||
};
|
||||
|
||||
static const pair<cstring, cstring>& severity_color(uint32_t severity) {
|
||||
static constexpr pair<cstring, cstring> colors[] = {
|
||||
{ "\033[0m", "\033[0m" }, // severity_info
|
||||
{ "\033[36m", "\033[0m" }, // severity_alert
|
||||
{ "\033[33m", "\033[0m" }, // severity_warning
|
||||
{ "\033[31m", "\033[0m" }, // severity_error
|
||||
{ "\033[1;31m", "\033[0m" }, // severity_fatal
|
||||
};
|
||||
return colors[severity];
|
||||
}
|
||||
|
||||
|
||||
// Logger System Interface =============================================================================================
|
||||
public:
|
||||
|
||||
@@ -54,7 +81,8 @@ public:
|
||||
/// \param str the string to log
|
||||
/// \param _line the line of the log call
|
||||
/// \param _file the file log was called in
|
||||
static void log(const cstring& str,
|
||||
static void log(uint32_t severity,
|
||||
const cstring& str,
|
||||
uint32_t _line = FENNEC_BUILTIN_LINE(),
|
||||
const char* _file = FENNEC_BUILTIN_FILE()
|
||||
) {
|
||||
@@ -66,9 +94,12 @@ public:
|
||||
inst._logfile.println(str);
|
||||
}
|
||||
|
||||
const auto& color = severity_color(severity);
|
||||
inst._cout->print(color.first);
|
||||
inst._cout->print(cstring(_file, strlen(_file)));
|
||||
inst._cout->printf("({}): ", _line);
|
||||
inst._cout->println(str);
|
||||
inst._cout->print(str);
|
||||
inst._cout->println(color.second);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -76,7 +107,8 @@ public:
|
||||
/// \param str the string to log
|
||||
/// \param _line the line of the log call
|
||||
/// \param _file the file log was called in
|
||||
static void log(const string& str,
|
||||
static void log(uint32_t severity,
|
||||
const string& str,
|
||||
uint32_t _line = FENNEC_BUILTIN_LINE(),
|
||||
const char* _file = FENNEC_BUILTIN_FILE()
|
||||
) {
|
||||
@@ -88,9 +120,13 @@ public:
|
||||
inst._logfile.println(str);
|
||||
}
|
||||
|
||||
|
||||
const auto& color = severity_color(severity);
|
||||
inst._cout->print(color.first);
|
||||
inst._cout->print(cstring(_file, strlen(_file)));
|
||||
inst._cout->printf("({}): ", _line);
|
||||
inst._cout->println(str);
|
||||
inst._cout->print(str);
|
||||
inst._cout->println(color.second);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
@@ -37,6 +37,12 @@
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
#endif
|
||||
|
||||
#if FENNEC_COMPILER_CLANG
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wgnu-anonymous-struct"
|
||||
#pragma clang diagnostic ignored "-Wnested-anon-types"
|
||||
#endif
|
||||
|
||||
#if FENNEC_COMPILER_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4201)
|
||||
@@ -59,13 +65,13 @@ public:
|
||||
/// @{
|
||||
|
||||
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"
|
||||
};
|
||||
uint64_t num; //!< long version number
|
||||
};
|
||||
|
||||
/// @}
|
||||
@@ -114,6 +120,10 @@ public:
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef FENNEC_COMPILER_CLANG
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#if FENNEC_COMPILER_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
@@ -39,19 +39,19 @@ namespace fennec
|
||||
/// <tr><th style="vertical-align: top">Flags
|
||||
/// <th style="vertical-align: top">Description
|
||||
///
|
||||
/// <tr><td style="vertical-align: top">\f$read\f$
|
||||
/// <tr><td style="vertical-align: top">\emph{read}
|
||||
/// <td style="vertical-align: top">Opens file as read-only, reading from start
|
||||
///
|
||||
/// <tr><td style="vertical-align: top">\f$write\f$
|
||||
/// <tr><td style="vertical-align: top">\emph{write}
|
||||
/// <td style="vertical-align: top">Opens file as write-only, writing to end
|
||||
///
|
||||
/// <tr><td style="vertical-align: top">\f$read | write\f$
|
||||
/// <tr><td style="vertical-align: top">\emph{read | write}
|
||||
/// <td style="vertical-align: top">Opens file as read-write, reading from start
|
||||
///
|
||||
/// <tr><td style="vertical-align: top">\f$write | trunc\f$
|
||||
/// <tr><td style="vertical-align: top">\emph{write | trunc}
|
||||
/// <td style="vertical-align: top">Opens file as write-only, destroying contents
|
||||
///
|
||||
/// <tr><td style="vertical-align: top">\f$read | write | trunc\f$
|
||||
/// <tr><td style="vertical-align: top">\emph{read | write | trunc}
|
||||
/// <td style="vertical-align: top">Opens file as read-write, destroying contents
|
||||
/// </table>
|
||||
enum fmode_ : uint8_t
|
||||
@@ -147,7 +147,7 @@ public:
|
||||
file();
|
||||
|
||||
///
|
||||
/// \details Initializes a stream pointing to \f$path\f$ opened with \f$mode\f$
|
||||
/// \details Initializes a stream pointing to \emph{path} opened with \emph{mode}
|
||||
/// \param path the path of the file
|
||||
/// \param mode the mode to open with
|
||||
file(const cstring& path, uint8_t mode)
|
||||
@@ -156,7 +156,7 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \details Initializes a stream pointing to \f$path\f$ opened with \f$mode\f$
|
||||
/// \details Initializes a stream pointing to \emph{path} opened with \emph{mode}
|
||||
/// \param path the path of the file
|
||||
/// \param mode the mode to open with
|
||||
file(const string& path, uint8_t mode)
|
||||
@@ -166,7 +166,7 @@ public:
|
||||
|
||||
///
|
||||
/// \brief Path constructor
|
||||
/// \details Initializes a stream pointing to \f$path\f$ opened with \f$mode\f$
|
||||
/// \details Initializes a stream pointing to \emph{path} opened with \emph{mode}
|
||||
/// \param path the path of the file
|
||||
/// \param mode the mode to open with
|
||||
file(const path& path, uint8_t mode)
|
||||
@@ -179,23 +179,39 @@ public:
|
||||
/// \param file the stream to take ownership of
|
||||
file(file&& file) noexcept;
|
||||
|
||||
///
|
||||
/// \brief Copy Constructor
|
||||
/// \details Deleted, no semantics for copying a stream. Holding multiple copies of a stream will cause conflicts.
|
||||
file(const file&) = delete;
|
||||
|
||||
///
|
||||
/// \brief Destructor
|
||||
/// \details Flushes and closes an open stream
|
||||
~file();
|
||||
|
||||
///@}
|
||||
|
||||
|
||||
// Assignment ==========================================================================================================
|
||||
public:
|
||||
|
||||
/// \name Assignment
|
||||
/// @{
|
||||
|
||||
|
||||
///
|
||||
/// \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;
|
||||
///
|
||||
/// \brief Copy Assignment
|
||||
/// \details Deleted, no semantics for copying a stream. Holding multiple copies of a stream will cause conflicts.
|
||||
/// \returns Deleted
|
||||
file& operator=(const file&) = delete;
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
// Properties ==========================================================================================================
|
||||
public:
|
||||
@@ -216,7 +232,7 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns \f$true\f$ if there is a valid, open stream.
|
||||
/// \returns \emph{true} if there is a valid, open stream.
|
||||
bool is_open() const {
|
||||
return _handle != nullptr;
|
||||
}
|
||||
@@ -233,30 +249,30 @@ public:
|
||||
///
|
||||
/// \param path the path to the file
|
||||
/// \param mode the mode flags to open the file with
|
||||
/// \returns \f$false\f$ on success, \f$true\f$ on error
|
||||
/// \returns \emph{false} on success, \emph{true} on error
|
||||
bool open(const cstring& path, uint8_t mode);
|
||||
|
||||
///
|
||||
/// \param path the path to the file
|
||||
/// \param mode the mode flags to open the file with
|
||||
/// \returns \f$false\f$ on success, \f$true\f$ on error
|
||||
/// \returns \emph{false} on success, \emph{true} on error
|
||||
bool open(const string& 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 \f$false\f$ on success, \f$true\f$ on error
|
||||
/// \returns \emph{false} on success, \emph{true} on error
|
||||
bool open(const path& path, uint8_t mode);
|
||||
|
||||
///
|
||||
/// \brief Close a stream
|
||||
/// \returns \f$false\f$ on success, \f$true\f$ on error
|
||||
/// \returns \emph{false} on success, \emph{true} on error
|
||||
bool close();
|
||||
|
||||
///
|
||||
/// \brief Commit the streams buffer to the file
|
||||
/// \returns \f$false\f$ on success, \f$true\f$ on error
|
||||
/// \returns \emph{false} on success, \emph{true} on error
|
||||
bool commit();
|
||||
|
||||
/// @}
|
||||
@@ -270,12 +286,12 @@ public:
|
||||
|
||||
///
|
||||
/// \brief closes the stream and erases the file
|
||||
/// \returns \f$false\f$ on success, \f$true\f$ on error
|
||||
/// \returns \emph{false} on success, \emph{true} on error
|
||||
bool erase();
|
||||
|
||||
///
|
||||
/// \param path the new path
|
||||
/// \returns \f$false\f$ on success, \f$true\f$ on error
|
||||
/// \returns \emph{false} on success, \emph{true} on error
|
||||
///
|
||||
/// \details
|
||||
/// Copies contents to the new path, and erases the old file.
|
||||
@@ -288,7 +304,7 @@ public:
|
||||
|
||||
///
|
||||
/// \param path the new path
|
||||
/// \returns \f$false\f$ on success, \f$true\f$ on error
|
||||
/// \returns \emph{false} on success, \emph{true} on error
|
||||
///
|
||||
/// \details
|
||||
/// Copies contents to the new path, and erases the old file.
|
||||
@@ -302,7 +318,7 @@ public:
|
||||
///
|
||||
/// \brief Rebind the stream.
|
||||
/// \param path the new path
|
||||
/// \returns \f$false\f$ on success, \f$true\f$ on error
|
||||
/// \returns \emph{false} on success, \emph{true} on error
|
||||
///
|
||||
/// \details
|
||||
/// Copies contents to the new path, and erases the old file.
|
||||
@@ -366,16 +382,16 @@ public:
|
||||
|
||||
///
|
||||
/// \param i the new index to move to
|
||||
/// \returns \f$false\f$ on success, \f$true\f$ otherwise
|
||||
/// \returns \emph{false} on success, \emph{true} otherwise
|
||||
bool set_pos(size_t i);
|
||||
|
||||
///
|
||||
/// \brief return to the start of the stream
|
||||
/// \returns \f$false\f$ on success, \f$true\f$ otherwise
|
||||
/// \returns \emph{false} on success, \emph{true} otherwise
|
||||
bool rewind();
|
||||
|
||||
///
|
||||
/// \returns \f$true\f$ if the stream has reached the end of the file, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the stream has reached the end of the file, \emph{false} otherwise
|
||||
bool eof() const;
|
||||
|
||||
/// @}
|
||||
@@ -429,13 +445,13 @@ public:
|
||||
///
|
||||
/// \brief put a character at the current position in the stream
|
||||
/// \param c the character to put
|
||||
/// \returns \f$false\f$ on success, \f$true\f$ otherwise
|
||||
/// \returns \emph{false} on success, \emph{true} otherwise
|
||||
bool putc(char c);
|
||||
|
||||
///
|
||||
/// \brief put a wide character at the current position in the stream
|
||||
/// \param c the character to put
|
||||
/// \returns \f$false\f$ on success, \f$true\f$ otherwise
|
||||
/// \returns \emph{false} on success, \emph{true} otherwise
|
||||
bool putwc(wchar_t c);
|
||||
|
||||
///
|
||||
@@ -551,7 +567,7 @@ public:
|
||||
/// \param args the argument values
|
||||
template<typename...ArgsT>
|
||||
void printf(const cstring& str, ArgsT&&...args) {
|
||||
string fmt = fennec::format(str, fennec::forward<ArgsT>(args)...);
|
||||
const string fmt = fennec::format(str, fennec::forward<ArgsT>(args)...);
|
||||
this->print(cstring(fmt.cstr(), fmt.length()));
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ public:
|
||||
///
|
||||
/// \brief C-String Assignment Operator
|
||||
/// \param str the cstring to assign
|
||||
/// \returns a reference to \f$this\f$ after assigning \f$p\f$
|
||||
/// \returns a reference to \emph{this} after assigning \emph{p}
|
||||
template<size_t n>
|
||||
path& operator=(const char (&str)[n]) {
|
||||
_str = str;
|
||||
@@ -125,7 +125,7 @@ public:
|
||||
///
|
||||
/// \brief C-String Assignment Operator
|
||||
/// \param p the cstring to assign
|
||||
/// \returns a reference to \f$this\f$ after assigning \f$p\f$
|
||||
/// \returns a reference to \emph{this} after assigning \emph{p}
|
||||
path& operator=(const cstring& p) {
|
||||
_str = p;
|
||||
return *this;
|
||||
@@ -134,7 +134,7 @@ public:
|
||||
///
|
||||
/// \brief String Assignment Operator
|
||||
/// \param p the cstring to assign
|
||||
/// \returns a reference to \f$this\f$ after assigning \f$p\f$
|
||||
/// \returns a reference to \emph{this} after assigning \emph{p}
|
||||
path& operator=(const string& p) {
|
||||
_str = p;
|
||||
return *this;
|
||||
@@ -143,7 +143,7 @@ public:
|
||||
///
|
||||
/// \brief Path Copy Assignment Operator
|
||||
/// \param p the path to copy
|
||||
/// \returns a reference to \f$this\f$ after copying \f$p\f$
|
||||
/// \returns a reference to \emph{this} after copying \emph{p}
|
||||
path& operator=(const path& p) {
|
||||
_str = p._str;
|
||||
return *this;
|
||||
@@ -152,7 +152,7 @@ public:
|
||||
///
|
||||
/// \brief Path Move Assignment Operator
|
||||
/// \param p the path to take ownership of
|
||||
/// \returns a reference to \f$this\f$ after taking ownership of \f$p\f$
|
||||
/// \returns a reference to \emph{this} after taking ownership of \emph{p}
|
||||
path& operator=(path&& p) noexcept {
|
||||
_str = move(p._str);
|
||||
return *this;
|
||||
@@ -170,7 +170,7 @@ public:
|
||||
///
|
||||
/// \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
|
||||
/// \returns \emph{true} if the paths are identical, \emph{false} otherwise. relative paths are not resolved
|
||||
bool operator==(const path& p) const {
|
||||
return _str == p._str;
|
||||
}
|
||||
@@ -187,7 +187,7 @@ public:
|
||||
///
|
||||
/// \brief path append operator
|
||||
/// \param str the filename to append
|
||||
/// \returns a path containing the current path followed by \f$str\f$
|
||||
/// \returns a path containing the current path followed by \emph{str}
|
||||
path operator/(const cstring& str) const {
|
||||
return path(_str + '/' + str);
|
||||
}
|
||||
@@ -195,7 +195,7 @@ public:
|
||||
///
|
||||
/// \brief path append operator
|
||||
/// \param str the filename to append
|
||||
/// \returns a path containing the current path followed by \f$str\f$
|
||||
/// \returns a path containing the current path followed by \emph{str}
|
||||
path operator/(const string& str) const {
|
||||
return path(_str + '/' + str);
|
||||
}
|
||||
@@ -203,7 +203,7 @@ public:
|
||||
///
|
||||
/// \brief path append operator
|
||||
/// \param p the path to append
|
||||
/// \returns a path containing the current path followed by \f$p\f$
|
||||
/// \returns a path containing the current path followed by \emph{p}
|
||||
path operator/(const path& p) const {
|
||||
return path(_str + '/' + p._str);
|
||||
}
|
||||
@@ -214,7 +214,7 @@ public:
|
||||
/// \brief the filename of the current path
|
||||
/// \returns a string containing a copy of the filename
|
||||
string filename() const {
|
||||
size_t i = _str.rfind('/');
|
||||
const size_t i = _str.rfind('/');
|
||||
return _str.substring(i + 1);
|
||||
}
|
||||
|
||||
@@ -227,9 +227,9 @@ public:
|
||||
const char* cstr() const { return _str.cstr(); }
|
||||
|
||||
///
|
||||
/// \returns \f$true\f$ if the path is empty or points to root
|
||||
/// \returns \emph{true} if the path is empty or points to root
|
||||
bool is_empty() {
|
||||
size_t size = _str.size();
|
||||
const size_t size = _str.size();
|
||||
if (size == 0) return true;
|
||||
#if FENNEC_PLATFORM_WINDOWS
|
||||
return (_str[1] == ':' && size == 3);
|
||||
@@ -322,21 +322,21 @@ public:
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$begin()\f$
|
||||
/// \brief C++ Iterator Specification \emph{begin()}
|
||||
/// \returns an iterator at the first filename in the path
|
||||
iterator begin() const {
|
||||
return iterator(this, 0);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$end()\f$
|
||||
/// \brief C++ Iterator Specification \emph{end()}
|
||||
/// \returns an iterator to the end of the path
|
||||
iterator end() const {
|
||||
return iterator(this, _str.size());
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$iterator\f$
|
||||
/// \brief C++ Iterator Specification \emph{iterator}
|
||||
class iterator {
|
||||
public:
|
||||
///
|
||||
@@ -363,7 +363,7 @@ public:
|
||||
|
||||
///
|
||||
/// \brief prefix increment operator
|
||||
/// \returns \f$self\f$ after having moved to the next element in the list
|
||||
/// \returns \emph{self} after having moved to the next element in the list
|
||||
constexpr iterator& operator++() {
|
||||
_pos = min(_str->find('/', _pos) + 1, _str->size());
|
||||
return *this;
|
||||
@@ -371,9 +371,9 @@ public:
|
||||
|
||||
///
|
||||
/// \brief postfix increment operator
|
||||
/// \returns \f$self\f$ before having moved to the next element in the list
|
||||
/// \returns \emph{self} before having moved to the next element in the list
|
||||
constexpr iterator operator++(int) {
|
||||
iterator it = *this;
|
||||
const iterator it = *this;
|
||||
this->operator++();
|
||||
return it;
|
||||
}
|
||||
@@ -381,7 +381,7 @@ public:
|
||||
///
|
||||
/// \brief iterator equality operator
|
||||
/// \param rhs the iterator to compare with
|
||||
/// \returns \f$true\f$ if the iterators are identical, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the iterators are identical, \emph{false} otherwise
|
||||
constexpr bool operator==(const iterator& rhs) const {
|
||||
return _str == rhs._str and _pos == rhs._pos;
|
||||
}
|
||||
@@ -389,7 +389,7 @@ public:
|
||||
///
|
||||
/// \brief iterator inequality operator
|
||||
/// \param rhs the iterator to compare with
|
||||
/// \returns \f$true\f$ if the iterators are different, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the iterators are different, \emph{false} otherwise
|
||||
constexpr bool operator!=(const iterator& rhs) const {
|
||||
return _str != rhs._str or _pos != rhs._pos;
|
||||
}
|
||||
|
||||
@@ -60,6 +60,8 @@ string format(const cstring& str, ArgsT&&...args) {
|
||||
.type = '\0',
|
||||
};
|
||||
|
||||
static_assert(argc > 0, "fennec::format may not accept 0 arguments");
|
||||
|
||||
// empty case
|
||||
if constexpr(argc == 0) {
|
||||
return str;
|
||||
|
||||
@@ -48,9 +48,9 @@ struct formatter {
|
||||
///
|
||||
/// \brief default format function
|
||||
///
|
||||
/// \details throws a static assertion
|
||||
/// \details Fails an assertion, the formatter is not implemented for the provided type
|
||||
/// \returns empty string
|
||||
string operator()(const format_arg&, const T&) {
|
||||
string operator()(const format_arg&, const T&) const {
|
||||
static_assert(false, "Formatter not implemented for the provided type.");
|
||||
return string("");
|
||||
}
|
||||
@@ -59,6 +59,8 @@ struct formatter {
|
||||
|
||||
// strings =============================================================================================================
|
||||
|
||||
// TODO: String formatting
|
||||
|
||||
///
|
||||
/// \brief formatter of a character array
|
||||
/// \tparam N the number of characters
|
||||
@@ -67,8 +69,8 @@ struct formatter<char[N]> {
|
||||
///
|
||||
/// \brief format function
|
||||
/// \param str the string argument
|
||||
/// \returns the formatted version of \f$str\f$
|
||||
string operator()(const format_arg&, const char (&str)[N]) {
|
||||
/// \returns the formatted version of \emph{str}
|
||||
string operator()(const format_arg&, const char (&str)[N]) const {
|
||||
return string(str);
|
||||
}
|
||||
};
|
||||
@@ -81,8 +83,8 @@ struct formatter<const char[N]> {
|
||||
///
|
||||
/// \brief format function
|
||||
/// \param str the string argument
|
||||
/// \returns the formatted version of \f$str\f$
|
||||
string operator()(const format_arg&, const char (&str)[N]) {
|
||||
/// \returns the formatted version of \emph{str}
|
||||
string operator()(const format_arg&, const char (&str)[N]) const {
|
||||
return string(str);
|
||||
}
|
||||
};
|
||||
@@ -94,8 +96,8 @@ struct formatter<cstring> {
|
||||
///
|
||||
/// \brief format function
|
||||
/// \param str the string argument
|
||||
/// \returns the formatted version of \f$str\f$
|
||||
string operator()(const format_arg&, const cstring& str) {
|
||||
/// \returns the formatted version of \emph{str}
|
||||
string operator()(const format_arg&, const cstring& str) const {
|
||||
return str;
|
||||
}
|
||||
};
|
||||
@@ -107,8 +109,8 @@ struct formatter<string> {
|
||||
///
|
||||
/// \brief format function
|
||||
/// \param str the string argument
|
||||
/// \returns the formatted version of \f$str\f$
|
||||
string operator()(const format_arg&, const string& str) {
|
||||
/// \returns the formatted version of \emph{str}
|
||||
string operator()(const format_arg&, const string& str) const {
|
||||
return str;
|
||||
}
|
||||
};
|
||||
@@ -124,12 +126,12 @@ struct formatter<IntT> {
|
||||
/// \brief format function
|
||||
/// \param fmt the format specification
|
||||
/// \param x the integral argument
|
||||
/// \returns the formatted version of \f$x\f$
|
||||
string operator()(const format_arg& fmt, IntT x) {
|
||||
/// \returns the formatted version of \emph{x}
|
||||
string operator()(const format_arg& fmt, IntT x) const {
|
||||
char digits[128] = {};
|
||||
auto chk = fennec::to_chars(digits, digits + sizeof(digits), fennec::abs(x), fmt.base);
|
||||
assertf(chk != nullptr, "fennec::format error, to_chars error");
|
||||
size_t len = chk - digits;
|
||||
const size_t len = chk - digits;
|
||||
|
||||
// handle uppercase
|
||||
if (fmt.upper) {
|
||||
@@ -163,8 +165,8 @@ struct formatter<IntT> {
|
||||
memset(res.data(), fmt.fill, explen - len);
|
||||
break;
|
||||
case '^':
|
||||
size_t bef = fill / 2 + has_sign + prefix;
|
||||
size_t aft = explen - bef;
|
||||
const size_t bef = fill / 2 + has_sign + prefix;
|
||||
const size_t aft = explen - bef;
|
||||
memcpy(res.data() + bef, digits, len);
|
||||
sign = fmt.fill == '0' ? 0 : bef - 1 - prefix;
|
||||
memset(res.data(), fmt.fill, bef);
|
||||
@@ -200,8 +202,8 @@ struct formatter<BoolT> {
|
||||
/// \brief format function
|
||||
/// \param fmt the format specification
|
||||
/// \param x the boolean argument
|
||||
/// \returns the formatted version of \f$x\f$
|
||||
string operator()(const format_arg& fmt, BoolT x) {
|
||||
/// \returns the formatted version of \emph{x}
|
||||
string operator()(const format_arg& fmt, BoolT x) const {
|
||||
if (fmt.type == 's' or fmt.type == '\0') {
|
||||
return x ? string("true") : string("false");
|
||||
}
|
||||
@@ -218,8 +220,8 @@ struct formatter<FloatT> {
|
||||
/// \brief format function
|
||||
/// \param fmt the format specification
|
||||
/// \param x the float argument
|
||||
/// \returns the formatted version of \f$x\f$
|
||||
string operator()(const format_arg& fmt, FloatT x) {
|
||||
/// \returns the formatted version of \emph{x}
|
||||
string operator()(const format_arg& fmt, FloatT x) const {
|
||||
|
||||
// nan & inf cases
|
||||
if (fennec::isnan(x)) {
|
||||
@@ -267,8 +269,8 @@ struct formatter<FloatT> {
|
||||
memset(res.data(), fmt.fill, explen - len);
|
||||
break;
|
||||
case '^':
|
||||
size_t bef = fill / 2 + has_sign + prefix;
|
||||
size_t aft = explen - bef;
|
||||
const size_t bef = fill / 2 + has_sign + prefix;
|
||||
const size_t aft = explen - bef;
|
||||
memcpy(res.data() + bef, digits, len);
|
||||
sign = fmt.fill == '0' ? 0 : bef - 1 - prefix;
|
||||
memset(res.data(), fmt.fill, bef);
|
||||
|
||||
@@ -94,8 +94,8 @@ private:
|
||||
list<token> res;
|
||||
priority_queue<pair<size_t, uint8_t>> idx;
|
||||
|
||||
for (char c : delimiter) {
|
||||
size_t i = 0;
|
||||
for (const char c : delimiter) {
|
||||
const size_t i = 0;
|
||||
while (i != line.size()) {
|
||||
size_t n = line.find(c, i);
|
||||
// TODO
|
||||
|
||||
@@ -48,18 +48,18 @@
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// assert(expr, desc)
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Make an assertion with expression \f$expr\f$ and provide a description \f$desc\f$. Only halts in debug mode.
|
||||
/// Make an assertion with expression \emph{expr} and provide a description \emph{desc}. Only halts in debug mode.
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// assertf(expr, desc)
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Make an assertion with expression \f$expr\f$ and provide a description \f$desc\f$. Always halts.
|
||||
/// Make an assertion with expression \emph{expr} and provide a description \emph{desc}. Always halts.
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// assertd(expr, desc)
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Make an assertion, ***only in debug mode***, with expression \f$expr\f$ and provide a description \f$desc\f$.
|
||||
/// This should be used when the branching caused by \f$assert\f$ would hinder performance in release mode.
|
||||
/// Make an assertion, ***only in debug mode***, with expression \emph{expr} and provide a description \emph{desc}.
|
||||
/// This should be used when the branching caused by \emph{assert} would hinder performance in release mode.
|
||||
///
|
||||
/// </table>
|
||||
///
|
||||
@@ -92,7 +92,7 @@ void _assert(const char (&expr)[ExprL],
|
||||
/// \param description the description of the assertion
|
||||
#define assert(expression, description) \
|
||||
if(not(expression)) [[unlikely]] { \
|
||||
_assert(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description, not FENNEC_RELEASE); \
|
||||
_assert(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description, FENNEC_DEBUG); \
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
@@ -116,7 +116,7 @@ constexpr ToT bit_cast(const FromT& from) {
|
||||
/// \param arr the array of bytes to modify
|
||||
/// \param mask the mask to and against arr
|
||||
/// \param n the number of bytes
|
||||
/// \returns the pointer \f$arr\f$
|
||||
/// \returns the pointer \emph{arr}
|
||||
constexpr void* bit_and(void* arr, const void* mask, size_t n) {
|
||||
if (arr == mask) {
|
||||
return arr;
|
||||
|
||||
@@ -33,23 +33,23 @@ namespace fennec
|
||||
template<typename T0, typename T1 = T0> struct equality;
|
||||
|
||||
///
|
||||
/// \brief Implementations for two types that have a common equality operator \f$==\f$
|
||||
/// \brief Implementations for two types that have a common equality operator \math{=}
|
||||
/// \tparam T0 The first type
|
||||
/// \tparam T1 The second type
|
||||
template<typename T0, typename T1> requires has_equals_v<T0, T1>
|
||||
struct equality<T0, T1> {
|
||||
///
|
||||
/// \brief operator to test the two values
|
||||
/// \param x the value of type \f$T0\f$
|
||||
/// \param y the value of type \f$T1\f$
|
||||
/// \returns \f$true\f$ if equal, \f$false\f$ otherwise
|
||||
/// \param x the value of type \emph{T0}
|
||||
/// \param y the value of type \emph{T1}
|
||||
/// \returns \emph{true} if equal, \emph{false} otherwise
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return x == y;
|
||||
}
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Implementations for two types that have a common less operator \f$<\f$
|
||||
/// \brief Implementations for two types that have a common less operator \math{<}
|
||||
/// \tparam T0 The first type
|
||||
/// \tparam T1 The second type
|
||||
template<typename T0, typename T1> requires(not has_equals_v<T0, T1>
|
||||
@@ -57,16 +57,16 @@ template<typename T0, typename T1> requires(not has_equals_v<T0, T1>
|
||||
struct equality<T0, T1> {
|
||||
///
|
||||
/// \brief operator to test the two values
|
||||
/// \param x the value of type \f$T0\f$
|
||||
/// \param y the value of type \f$T1\f$
|
||||
/// \returns \f$true\f$ if equal, \f$false\f$ otherwise
|
||||
/// \param x the value of type \emph{T0}
|
||||
/// \param y the value of type \emph{T1}
|
||||
/// \returns \emph{true} if equal, \emph{false} otherwise
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return not(x < y) and not(y < x);
|
||||
}
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Implementations for two types that have a common greater operator \f$>\f$
|
||||
/// \brief Implementations for two types that have a common greater operator \math{>}
|
||||
/// \tparam T0 The first type
|
||||
/// \tparam T1 The second type
|
||||
template<typename T0, typename T1> requires(not(has_equals_v<T0, T1>)
|
||||
@@ -75,9 +75,9 @@ template<typename T0, typename T1> requires(not(has_equals_v<T0, T1>)
|
||||
struct equality<T0, T1> {
|
||||
///
|
||||
/// \brief operator to test the two values
|
||||
/// \param x the value of type \f$T0\f$
|
||||
/// \param y the value of type \f$T1\f$
|
||||
/// \returns \f$true\f$ if equal, \f$false\f$ otherwise
|
||||
/// \param x the value of type \emph{T0}
|
||||
/// \param y the value of type \emph{T1}
|
||||
/// \returns \emph{true} if equal, \emph{false} otherwise
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return not(x > y) and not(y > x);
|
||||
}
|
||||
@@ -93,16 +93,16 @@ struct equality<T0, T1> {
|
||||
template<typename T0, typename T1 = T0> struct inequality;
|
||||
|
||||
///
|
||||
/// \brief Implementations for two types that have a common inequality operator \f$\neq\f$
|
||||
/// \brief Implementations for two types that have a common inequality operator \math{\neq}
|
||||
/// \tparam T0 The first type
|
||||
/// \tparam T1 The second type
|
||||
template<typename T0, typename T1> requires has_nequals_v<T0, T1>
|
||||
struct inequality<T0, T1> {
|
||||
///
|
||||
/// \brief operator to test the two values
|
||||
/// \param x the value of type \f$T0\f$
|
||||
/// \param y the value of type \f$T1\f$
|
||||
/// \returns \f$true\f$ if not equal, \f$false\f$ otherwise
|
||||
/// \param x the value of type \emph{T0}
|
||||
/// \param y the value of type \emph{T1}
|
||||
/// \returns \emph{true} if not equal, \emph{false} otherwise
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return x != y;
|
||||
}
|
||||
@@ -110,48 +110,48 @@ struct inequality<T0, T1> {
|
||||
|
||||
|
||||
///
|
||||
/// \brief Implementations for two types that have a common equality operator \f$==\f$
|
||||
/// \brief Implementations for two types that have a common equality operator \math{=}
|
||||
/// \tparam T0 The first type
|
||||
/// \tparam T1 The second type
|
||||
template<typename T0, typename T1> requires has_equals_v<T0, T1>
|
||||
struct inequality<T0, T1> {
|
||||
///
|
||||
/// \brief operator to test the two values
|
||||
/// \param x the value of type \f$T0\f$
|
||||
/// \param y the value of type \f$T1\f$
|
||||
/// \returns \f$true\f$ if not equal, \f$false\f$ otherwise
|
||||
/// \param x the value of type \emph{T0}
|
||||
/// \param y the value of type \emph{T1}
|
||||
/// \returns \emph{true} if not equal, \emph{false} otherwise
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return not (x == y);
|
||||
}
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Implementations for two types that have a common less operator \f$<\f$
|
||||
/// \brief Implementations for two types that have a common less operator \math{<}
|
||||
/// \tparam T0 The first type
|
||||
/// \tparam T1 The second type
|
||||
template<typename T0, typename T1> requires has_less_v<T0, T1> and has_less_v<T1, T0>
|
||||
struct inequality<T0, T1> {
|
||||
///
|
||||
/// \brief operator to test the two values
|
||||
/// \param x the value of type \f$T0\f$
|
||||
/// \param y the value of type \f$T1\f$
|
||||
/// \returns \f$true\f$ if not equal, \f$false\f$ otherwise
|
||||
/// \param x the value of type \emph{T0}
|
||||
/// \param y the value of type \emph{T1}
|
||||
/// \returns \emph{true} if not equal, \emph{false} otherwise
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return (x < y) or (y < x);
|
||||
}
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Implementations for two types that have a common greater operator \f$>\f$
|
||||
/// \brief Implementations for two types that have a common greater operator \math{>}
|
||||
/// \tparam T0 The first type
|
||||
/// \tparam T1 The second type
|
||||
template<typename T0, typename T1> requires has_greater_v<T0, T1> and has_greater_v<T1, T0>
|
||||
struct inequality<T0, T1> {
|
||||
///
|
||||
/// \brief operator to test the two values
|
||||
/// \param x the value of type \f$T0\f$
|
||||
/// \param y the value of type \f$T1\f$
|
||||
/// \returns \f$true\f$ if not equal, \f$false\f$ otherwise
|
||||
/// \param x the value of type \emph{T0}
|
||||
/// \param y the value of type \emph{T1}
|
||||
/// \returns \emph{true} if not equal, \emph{false} otherwise
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return (x > y) or (y > x);
|
||||
}
|
||||
@@ -161,16 +161,16 @@ struct inequality<T0, T1> {
|
||||
// less ================================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Struct to test if a value of type \f$T0\f$ is less than a value of type \f$T1\f$
|
||||
/// \brief Struct to test if a value of type \emph{T0} is less than a value of type \emph{T1}
|
||||
/// \tparam T0 The first type
|
||||
/// \tparam T1 The second type
|
||||
template<typename T0, typename T1 = T0> requires has_less_v<T0, T1>
|
||||
struct less {
|
||||
///
|
||||
/// \brief operator to test the two values
|
||||
/// \param x the value of type \f$T0\f$
|
||||
/// \param y the value of type \f$T1\f$
|
||||
/// \returns \f$true\f$ if less, \f$false\f$ otherwise
|
||||
/// \param x the value of type \emph{T0}
|
||||
/// \param y the value of type \emph{T1}
|
||||
/// \returns \emph{true} if less, \emph{false} otherwise
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return x < y;
|
||||
}
|
||||
@@ -180,16 +180,16 @@ struct less {
|
||||
// less_equal ==========================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Struct to test if a value of type \f$T0\f$ is less than or equal to a value of type \f$T1\f$
|
||||
/// \brief Struct to test if a value of type \emph{T0} is less than or equal to a value of type \emph{T1}
|
||||
/// \tparam T0 The first type
|
||||
/// \tparam T1 The second type
|
||||
template<typename T0, typename T1 = T0> requires has_less_equals_v<T0, T1>
|
||||
struct less_equals {
|
||||
///
|
||||
/// \brief operator to test the two values
|
||||
/// \param x the value of type \f$T0\f$
|
||||
/// \param y the value of type \f$T1\f$
|
||||
/// \returns \f$true\f$ if less than or equal, \f$false\f$ otherwise
|
||||
/// \param x the value of type \emph{T0}
|
||||
/// \param y the value of type \emph{T1}
|
||||
/// \returns \emph{true} if less than or equal, \emph{false} otherwise
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return x <= y;
|
||||
}
|
||||
@@ -199,16 +199,16 @@ struct less_equals {
|
||||
// greater =============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Struct to test if a value of type \f$T0\f$ is greater than a value of type \f$T1\f$
|
||||
/// \brief Struct to test if a value of type \emph{T0} is greater than a value of type \emph{T1}
|
||||
/// \tparam T0 The first type
|
||||
/// \tparam T1 The second type
|
||||
template<typename T0, typename T1 = T0> requires has_greater_v<T0, T1>
|
||||
struct greater {
|
||||
///
|
||||
/// \brief operator to test the two values
|
||||
/// \param x the value of type \f$T0\f$
|
||||
/// \param y the value of type \f$T1\f$
|
||||
/// \returns \f$true\f$ if greater, \f$false\f$ otherwise
|
||||
/// \param x the value of type \emph{T0}
|
||||
/// \param y the value of type \emph{T1}
|
||||
/// \returns \emph{true} if greater, \emph{false} otherwise
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return x > y;
|
||||
}
|
||||
@@ -218,16 +218,16 @@ struct greater {
|
||||
// less_equal ==========================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Struct to test if a value of type \f$T0\f$ is greater than or equal to a value of type \f$T1\f$
|
||||
/// \brief Struct to test if a value of type \emph{T0} is greater than or equal to a value of type \emph{T1}
|
||||
/// \tparam T0 The first type
|
||||
/// \tparam T1 The second type
|
||||
template<typename T0, typename T1 = T0> requires has_greater_equals_v<T0, T1>
|
||||
struct greater_equals {
|
||||
///
|
||||
/// \brief operator to test the two values
|
||||
/// \param x the value of type \f$T0\f$
|
||||
/// \param y the value of type \f$T1\f$
|
||||
/// \returns \f$true\f$ if greater than or equal, \f$false\f$ otherwise
|
||||
/// \param x the value of type \emph{T0}
|
||||
/// \param y the value of type \emph{T1}
|
||||
/// \returns \emph{true} if greater than or equal, \emph{false} otherwise
|
||||
constexpr bool operator()(const T0& x, const T1& y) const {
|
||||
return x >= y;
|
||||
}
|
||||
|
||||
@@ -77,8 +77,8 @@ namespace fennec
|
||||
/// \details Selects between \p TrueT and \p FalseT based on the boolean value \p b.
|
||||
/// The chosen type is stored in `fennec::conditional::type`.
|
||||
/// \tparam B the value of the condition
|
||||
/// \tparam TrueT type to use when \f$B == true\f$
|
||||
/// \tparam FalseT type to use when \f$B == false\f$
|
||||
/// \tparam TrueT type to use when \math{\textbf{B} = \textbf{true}}
|
||||
/// \tparam FalseT type to use when \math{\textbf{B} = \textbf{false}}
|
||||
template<bool B, typename TrueT, typename FalseT>
|
||||
struct conditional;
|
||||
|
||||
@@ -90,12 +90,12 @@ using conditional_t
|
||||
= typename conditional<B, TrueT, FalseT>::type;
|
||||
|
||||
#ifndef FENNEC_DOXYGEN
|
||||
// specialization of fennec::conditional for \f$true\f$ case
|
||||
// specialization of fennec::conditional for \emph{true} case
|
||||
template<typename T, typename F>
|
||||
struct conditional<true, T, F> : type_identity<T>{};
|
||||
|
||||
|
||||
// specialization of fennec::conditional for \f$false\f$ case
|
||||
// specialization of fennec::conditional for \emph{false} case
|
||||
template<typename T, typename F>
|
||||
struct conditional<false, T, F> : type_identity<F>{};
|
||||
#endif
|
||||
@@ -103,13 +103,13 @@ struct conditional<false, T, F> : type_identity<F>{};
|
||||
// fennec::detect ======================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Detect whether \f$DetectT<ArgsT...>\f$ is a valid type
|
||||
/// \brief Detect whether \emph{DetectT<ArgsT...>} is a valid type
|
||||
///
|
||||
/// \details Selects \f$DetectT<ArgsT...>\f$ if it exists, otherwise selects \f$DefaultT\f$ The chosen type is stored in `fennec::detect::type` and
|
||||
/// a boolean value is stored in `fennec::detect::is_detected` representing whether \f$DetectT<ArgsT...>\f$ is found.
|
||||
/// \details Selects \emph{DetectT<ArgsT...>} if it exists, otherwise selects \emph{DefaultT} The chosen type is stored in `fennec::detect::type` and
|
||||
/// a boolean value is stored in `fennec::detect::is_detected` representing whether \emph{DetectT<ArgsT...>} is found.
|
||||
/// \tparam DefaultT Default type
|
||||
/// \tparam DetectT Type to detect
|
||||
/// \tparam ArgsT Any template arguments for \f$DetectT<ArgsT>\f$
|
||||
/// \tparam ArgsT Any template arguments for \emph{DetectT<ArgsT>}
|
||||
template<typename DefaultT, template<typename...> typename DetectT, typename...ArgsT>
|
||||
struct detect
|
||||
{
|
||||
@@ -140,7 +140,7 @@ struct detect<DefaultT, DetectT, ArgsT...>
|
||||
///
|
||||
/// \brief Leverage SFINAE to conditionally enable a function or class at compile-time
|
||||
///
|
||||
/// \details If \f$B\f$ is \f$true\f$, define a public member type \f$type\f$. Otherwise, there is no member. <br>
|
||||
/// \details If \emph{B} is \emph{true}, define a public member type \emph{type}. Otherwise, there is no member. <br>
|
||||
/// **Example Usage**
|
||||
/// \code{.cpp}
|
||||
/// template<typename TypeT,
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace fennec
|
||||
///
|
||||
/// \brief Metaprogramming helper for testing values of type T
|
||||
/// \tparam T the type
|
||||
/// \returns a metavalue of type \f$T\f$
|
||||
/// \returns a metavalue of type \emph{T}
|
||||
template<typename T> auto declval() noexcept -> decltype(detail::_declval<T>(0)) {
|
||||
static_assert(detail::_declval_protector<T>{}, "declval must not be used");
|
||||
return detail::_declval<T>(0);
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#ifndef FENNEC_LANG_DETAIL_TYPE_TRAITS_H
|
||||
#define FENNEC_LANG_DETAIL_TYPE_TRAITS_H
|
||||
|
||||
#include <fennec/lang/ranges.h>
|
||||
#include <fennec/lang/constants.h>
|
||||
#include <fennec/lang/declval.h>
|
||||
|
||||
@@ -82,6 +81,12 @@ namespace fennec::detail
|
||||
template<typename> struct _is_rvalue_reference : false_type {};
|
||||
template<typename T> struct _is_rvalue_reference<T&&> : true_type {};
|
||||
|
||||
template<typename> struct _is_bounded_array : false_type {};
|
||||
template<typename T, size_t N> struct _is_bounded_array<T[N]> : true_type {};
|
||||
|
||||
template<typename> struct _is_unbounded_array : false_type {};
|
||||
template<typename T> struct _is_unbounded_array<T[]> : true_type {};
|
||||
|
||||
template<typename T> struct _is_complete {
|
||||
template<typename U>
|
||||
static auto test(U*) -> bool_constant<sizeof(U) == sizeof(U)>;
|
||||
@@ -105,13 +110,37 @@ namespace fennec::detail
|
||||
using type = decltype(test<T>(0));
|
||||
};
|
||||
|
||||
template<typename ContainerT>
|
||||
auto _begin(ContainerT& c) noexcept(noexcept(c.begin())) -> decltype(c.begin()) {
|
||||
return c.begin();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
auto _begin(T (&arr)[N]) -> T* {
|
||||
return arr[0];
|
||||
}
|
||||
|
||||
void _begin(...);
|
||||
|
||||
template<typename ContainerT>
|
||||
auto _end(ContainerT& c) noexcept(noexcept(c.end())) -> decltype(c.end()) {
|
||||
return c.end();
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
auto _end(T (&arr)[N]) -> T* {
|
||||
return arr[N - 1];
|
||||
}
|
||||
|
||||
void _end(...);
|
||||
|
||||
// https://stackoverflow.com/questions/13830158/how-to-write-a-trait-which-checks-whether-a-type-is-iterable
|
||||
template<typename T>
|
||||
auto _is_iterable(int) -> decltype(
|
||||
fennec::begin(declval<T&>()) != fennec::end(declval<T&>()),
|
||||
detail::_begin(declval<T&>()) != detail::_end(declval<T&>()),
|
||||
void(),
|
||||
++declval<decltype(fennec::begin(declval<T&>()))&>(),
|
||||
void(*fennec::begin(declval<T&>())),
|
||||
++declval<decltype(detail::_begin(declval<T&>()))&>(),
|
||||
void(*detail::_begin(declval<T&>())),
|
||||
true_type{}
|
||||
);
|
||||
|
||||
@@ -130,6 +159,20 @@ namespace fennec::detail
|
||||
auto _is_indexable(...) -> false_type;
|
||||
|
||||
|
||||
// https://stackoverflow.com/a/31409532
|
||||
template<typename T>
|
||||
auto _is_iterator(...) -> decltype(
|
||||
declval<T>() != declval<T>(),
|
||||
void(),
|
||||
++declval<T>(),
|
||||
*declval<T>(),
|
||||
true_type{}
|
||||
);
|
||||
|
||||
template<typename T>
|
||||
auto _is_iterator(...) -> false_type;
|
||||
|
||||
|
||||
|
||||
template<typename T>
|
||||
auto _is_mappable(int) -> decltype(
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
///
|
||||
/// \details This file is automatically generated for the current build environment.
|
||||
///
|
||||
/// Environment for this build: GNU Linux x86_64
|
||||
/// Environment for this build: Clang Linux x86_64
|
||||
///
|
||||
/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
@@ -60,55 +60,55 @@
|
||||
#undef FLT_DENORM_MIN
|
||||
#undef FLT_ROUND_ERR
|
||||
|
||||
/// \brief Does \f$float\f$ have an infinity?
|
||||
/// \brief Does \emph{float} have an infinity?
|
||||
#define FLT_HAS_INFINITY 1
|
||||
/// \brief Does \f$float\f$ have a quiet NaN?
|
||||
/// \brief Does \emph{float} have a quiet NaN?
|
||||
#define FLT_HAS_QUIET_NAN 1
|
||||
/// \brief Does \f$float\f$ have a signaling NaN?
|
||||
/// \brief Does \emph{float} have a signaling NaN?
|
||||
#define FLT_HAS_SIGNALING_NAN 1
|
||||
/// \brief Does \f$float\f$ use denormalization?
|
||||
/// \brief Does \emph{float} use denormalization?
|
||||
#define FLT_HAS_DENORM 1
|
||||
/// \brief Does \f$float\f$ have loss with denormalization?
|
||||
/// \brief Does \emph{float} have loss with denormalization?
|
||||
#define FLT_HAS_DENORM_LOSS 0
|
||||
/// \brief What rounding style does \f$float\f$ use?
|
||||
/// \brief What rounding style does \emph{float} use?
|
||||
#define FLT_ROUNDS 1
|
||||
/// \brief Does \f$float\f$ use the IEEE floating point specification?
|
||||
/// \brief Does \emph{float} use the IEEE floating point specification?
|
||||
#define FLT_IS_IEC559 1
|
||||
/// \brief The number of mantissa bits in \f$float\f$.
|
||||
/// \brief The number of mantissa bits in \emph{float}.
|
||||
#define FLT_MANT_DIG 24
|
||||
/// \brief The number of decimal digits guaranteed to be preserved in a \f$float\f$ → \f$text\f$ → \f$float\f$.
|
||||
/// \brief The number of decimal digits guaranteed to be preserved in a \emph{float} → \emph{text} → \emph{float}.
|
||||
#define FLT_DIG 6
|
||||
/// \brief The decimal precision required to serialize and deserialize a \f$float\f$.
|
||||
/// \brief The decimal precision required to serialize and deserialize a \emph{float}.
|
||||
#define FLT_DECIMAL_DIG 9
|
||||
/// \brief The radix, or integer base, used to represent a \f$float\f$.
|
||||
/// \brief The radix, or integer base, used to represent a \emph{float}.
|
||||
#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$.
|
||||
/// \brief The minimum negative integer such that \math{\textbf{FLT_RADIX}^\textbf{FLT_MIN_EXP}} results in a normalized \emph{float}.
|
||||
#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$.
|
||||
/// \brief The maximum positive integer such that \math{\textbf{FLT_RADIX}^\textbf{FLT_MAX_EXP}} results in a non-infinite \emph{float}.
|
||||
#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$.
|
||||
/// \brief The minimum negative integer such that \math{{10}^\textbf{FLT_MIN_EXP}} results in a normalized \emph{float}.
|
||||
#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$.
|
||||
/// \brief The maximum positive integer such that \math{{10}^\textbf{FLT_MAX_EXP}} results in a non-infinite \emph{float}.
|
||||
#define FLT_MAX_10_EXP 38
|
||||
/// \brief Do arithmetics operations with \f$float\f$ trap?
|
||||
/// \brief Do arithmetics operations with \emph{float} trap?
|
||||
#define FLT_TRAPS 0
|
||||
/// \brief Do arithmetics operations with \f$float\f$ check for underflow?
|
||||
/// \brief Do arithmetics operations with \emph{float} check for underflow?
|
||||
#define FLT_TINYNESS_BEFORE 0
|
||||
/// \brief Smallest positive, finite, normal value of \f$float\f$.
|
||||
/// \brief Smallest positive, finite, normal value of \emph{float}.
|
||||
#define FLT_MIN fennec::bit_cast<float>(0x800000)
|
||||
/// \brief Largest positive, finite value of \f$float\f$.
|
||||
/// \brief Largest positive, finite value of \emph{float}.
|
||||
#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$.
|
||||
/// \brief The difference between \emph{1.0} and the next representable value of \emph{float}.
|
||||
#define FLT_EPSILON fennec::bit_cast<float>(0x34000000)
|
||||
/// \brief A value representing \f$\inf\f$ of type \f$float\f$.
|
||||
/// \brief A value representing \emph{\inf} of type \emph{float}.
|
||||
#define FLT_INF fennec::bit_cast<float>(0x7f800000)
|
||||
/// \brief A value representing \f$NaN\f$ of type \f$float\f$ that does not trap.
|
||||
/// \brief A value representing \emph{NaN} of type \emph{float} 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.
|
||||
/// \brief A value representing \emph{NaN} of type \emph{float} that traps.
|
||||
#define FLT_SIGNALING_NAN fennec::bit_cast<float>(0x7fa00000)
|
||||
/// \brief Smallest positive, finite, subnormal value of \f$float\f$.
|
||||
/// \brief Smallest positive, finite, subnormal value of \emph{float}.
|
||||
#define FLT_DENORM_MIN fennec::bit_cast<float>(0x1)
|
||||
/// \brief Maximum rounding error of type \f$float\f$.
|
||||
/// \brief Maximum rounding error of type \emph{float}.
|
||||
#define FLT_ROUND_ERR fennec::bit_cast<float>(0x3f000000)
|
||||
|
||||
#undef DBL_HAS_INFINITY
|
||||
@@ -137,55 +137,55 @@
|
||||
#undef DBL_DENORM_MIN
|
||||
#undef DBL_ROUND_ERR
|
||||
|
||||
/// \brief Does \f$double\f$ have an infinity?
|
||||
/// \brief Does \emph{double} have an infinity?
|
||||
#define DBL_HAS_INFINITY 1
|
||||
/// \brief Does \f$double\f$ have a quiet NaN?
|
||||
/// \brief Does \emph{double} have a quiet NaN?
|
||||
#define DBL_HAS_QUIET_NAN 1
|
||||
/// \brief Does \f$double\f$ have a signaling NaN?
|
||||
/// \brief Does \emph{double} have a signaling NaN?
|
||||
#define DBL_HAS_SIGNALING_NAN 1
|
||||
/// \brief Does \f$double\f$ use denormalization?
|
||||
/// \brief Does \emph{double} use denormalization?
|
||||
#define DBL_HAS_DENORM 1
|
||||
/// \brief Does \f$double\f$ have loss with denormalization?
|
||||
/// \brief Does \emph{double} have loss with denormalization?
|
||||
#define DBL_HAS_DENORM_LOSS 0
|
||||
/// \brief What rounding style does \f$double\f$ use?
|
||||
/// \brief What rounding style does \emph{double} use?
|
||||
#define DBL_ROUNDS 1
|
||||
/// \brief Does \f$double\f$ use the IEEE doubleing point specification?
|
||||
/// \brief Does \emph{double} use the IEEE doubleing point specification?
|
||||
#define DBL_IS_IEC559 1
|
||||
/// \brief The number of mantissa bits in \f$double\f$.
|
||||
/// \brief The number of mantissa bits in \emph{double}.
|
||||
#define DBL_MANT_DIG 53
|
||||
/// \brief The number of decimal digits guaranteed to be preserved in a \f$double\f$ → \f$text\f$ → \f$double\f$.
|
||||
/// \brief The number of decimal digits guaranteed to be preserved in a \emph{double} → \emph{text} → \emph{double}.
|
||||
#define DBL_DIG 15
|
||||
/// \brief The decimal precision required to serialize and deserialize a \f$double\f$.
|
||||
/// \brief The decimal precision required to serialize and deserialize a \emph{double}.
|
||||
#define DBL_DECIMAL_DIG 17
|
||||
/// \brief The radix, or integer base, used to represent a \f$double\f$.
|
||||
/// \brief The radix, or integer base, used to represent a \emph{double}.
|
||||
#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$.
|
||||
/// \brief The minimum negative integer such that \math{\textbf{DBL_RADIX}^\textbf{DBL_MIN_EXP}} results in a normalized \emph{double}.
|
||||
#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$.
|
||||
/// \brief The maximum positive integer such that \math{\textbf{DBL_RADIX}^\textbf{DBL_MAX_EXP}} results in a non-infinite \emph{double}.
|
||||
#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$.
|
||||
/// \brief The minimum negative integer such that \math{{10}^\textbf{DBL_MIN_EXP}} results in a normalized \emph{double}.
|
||||
#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$.
|
||||
/// \brief The maximum positive integer such that \math{{10}^\textbf{DBL_MAX_EXP}} results in a non-infinite \emph{double}.
|
||||
#define DBL_MAX_10_EXP 308
|
||||
/// \brief Do arithmetics operations with \f$double\f$ trap?
|
||||
/// \brief Do arithmetics operations with \emph{double} trap?
|
||||
#define DBL_TRAPS 0
|
||||
/// \brief Do arithmetics operations with \f$double\f$ check for underflow?
|
||||
/// \brief Do arithmetics operations with \emph{double} check for underflow?
|
||||
#define DBL_TINYNESS_BEFORE 0
|
||||
/// \brief Smallest positive, finite, normal value of \f$double\f$.
|
||||
/// \brief Smallest positive, finite, normal value of \emph{double}.
|
||||
#define DBL_MIN fennec::bit_cast<double>(0x10000000000000ll)
|
||||
/// \brief Largest positive, finite value of \f$double\f$.
|
||||
/// \brief Largest positive, finite value of \emph{double}.
|
||||
#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$.
|
||||
/// \brief The difference between \emph{1.0} and the next representable value of \emph{double}.
|
||||
#define DBL_EPSILON fennec::bit_cast<double>(0x3cb0000000000000ll)
|
||||
/// \brief A value representing \f$\inf\f$ of type \f$double\f$.
|
||||
/// \brief A value representing \emph{\inf} of type \emph{double}.
|
||||
#define DBL_INF fennec::bit_cast<double>(0x7ff0000000000000ll)
|
||||
/// \brief A value representing \f$NaN\f$ of type \f$double\f$ that does not trap.
|
||||
/// \brief A value representing \emph{NaN} of type \emph{double} 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.
|
||||
/// \brief A value representing \emph{NaN} of type \emph{double} that traps.
|
||||
#define DBL_SIGNALING_NAN fennec::bit_cast<double>(0x7ff4000000000000ll)
|
||||
/// \brief Smallest positive, finite, subnormal value of \f$double\f$.
|
||||
/// \brief Smallest positive, finite, subnormal value of \emph{double}.
|
||||
#define DBL_DENORM_MIN fennec::bit_cast<double>(0x1ll)
|
||||
/// \brief Maximum rounding error of type \f$double\f$.
|
||||
/// \brief Maximum rounding error of type \emph{double}.
|
||||
#define DBL_ROUND_ERR fennec::bit_cast<double>(0x3fe0000000000000ll)
|
||||
|
||||
#endif // FENNEC_LANG_FLOAT_H
|
||||
|
||||
@@ -85,18 +85,18 @@ public:
|
||||
///
|
||||
/// \brief copy assignment
|
||||
/// \param func the function to copy
|
||||
/// \returns a reference to self
|
||||
/// \returns a reference to \emph{this}
|
||||
constexpr function& operator=(const function& func) = default;
|
||||
|
||||
///
|
||||
/// \brief move assignment
|
||||
/// \param func the function to capture
|
||||
/// \returns a reference to self
|
||||
/// \returns a reference to \emph{this}
|
||||
constexpr function& operator=(function&& func) = default;
|
||||
|
||||
///
|
||||
/// \brief null assignment
|
||||
/// \returns a reference to self
|
||||
/// \returns a reference to \emph{this}
|
||||
constexpr function& operator=(nullptr_t) {
|
||||
call = nullptr;
|
||||
return *this;
|
||||
@@ -105,7 +105,7 @@ public:
|
||||
///
|
||||
/// \brief function assignment
|
||||
/// \param func the function to capture
|
||||
/// \returns a reference to self
|
||||
/// \returns a reference to \emph{this}
|
||||
constexpr function& operator=(ReturnT (*func)(ArgsT...)) {
|
||||
call = func;
|
||||
return *this;
|
||||
@@ -113,7 +113,7 @@ public:
|
||||
|
||||
///
|
||||
/// \brief implicit bool check
|
||||
/// \returns \f$true\f$ if a function is captured, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if a function is captured, \emph{false} otherwise
|
||||
constexpr operator bool() const noexcept {
|
||||
return call != nullptr;
|
||||
}
|
||||
|
||||
@@ -66,11 +66,11 @@ struct hash<PtrT*> : hash<uintptr_t> {
|
||||
/// \param ptr the pointer to hash
|
||||
/// \returns an integer hash for the value
|
||||
constexpr size_t operator()(PtrT* ptr) const {
|
||||
return hash<uintptr_t>::operator()((uintptr_t)(const void*)ptr);
|
||||
return hash<uintptr_t>::operator()(fennec::bit_cast<uintptr_t>(ptr));
|
||||
}
|
||||
};
|
||||
|
||||
// Float
|
||||
/// \brief Hashing for `float`
|
||||
template<>
|
||||
struct hash<float> : hash<uint32_t> {
|
||||
using type_t = float; //!< the type of the hash
|
||||
@@ -82,6 +82,7 @@ struct hash<float> : hash<uint32_t> {
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Hashing for `double`
|
||||
template<>
|
||||
struct hash<double> : hash<uint64_t> {
|
||||
using type_t = double; //!< the type of the hash
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
///
|
||||
/// \details This file is automatically generated for the current build environment.
|
||||
///
|
||||
/// Environment for this build: GNU Linux x86_64
|
||||
/// Environment for this build: Clang Linux x86_64
|
||||
///
|
||||
/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
@@ -53,212 +53,212 @@
|
||||
#undef ULLONG_MIN
|
||||
#undef ULLONG_MAX
|
||||
|
||||
/// \brief Is \f$char\f$ signed?
|
||||
/// \brief Is \emph{char} 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$.
|
||||
/// \brief Rounding style of type \emph{char}.
|
||||
#define CHAR_ROUNDS 0
|
||||
/// \brief Number of radix digits represented by \emph{char}.
|
||||
#define CHAR_RADIX_DIG 0x7
|
||||
/// \brief Number of decimal digits represented by \f$char\f$.
|
||||
/// \brief Number of decimal digits represented by \emph{char}.
|
||||
#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$.
|
||||
/// \brief Number of decimal digits necessary to differentiate all values of type \emph{char}.
|
||||
#define CHAR_DECIMAL_DIG 0
|
||||
/// \brief The radix, or integer base, used to represent a \emph{char}.
|
||||
#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$.
|
||||
/// \brief Do arithmetics operations with \emph{char} trap?
|
||||
#define CHAR_TRAPS true
|
||||
/// \brief Smallest finite value of \emph{char}.
|
||||
#define CHAR_MIN -0x80
|
||||
/// \brief Largest finite value of \emph{char}.
|
||||
#define CHAR_MAX 0x7f
|
||||
|
||||
/// \brief Is \f$wchar_t\f$ signed?
|
||||
/// \brief Is \emph{wchar_t} 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$.
|
||||
/// \brief Rounding style of type \emph{wchar_t}.
|
||||
#define WCHAR_ROUNDS 0
|
||||
/// \brief Number of radix digits represented by \emph{wchar_t}.
|
||||
#define WCHAR_RADIX_DIG 0x1f
|
||||
/// \brief Number of decimal digits represented by \f$wchar_t\f$.
|
||||
/// \brief Number of decimal digits represented by \emph{wchar_t}.
|
||||
#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$.
|
||||
/// \brief Number of decimal digits necessary to differentiate all values of type \emph{wchar_t}.
|
||||
#define WCHAR_DECIMAL_DIG 0
|
||||
/// \brief The radix, or integer base, used to represent a \emph{wchar_t}.
|
||||
#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 Do arithmetics operations with \emph{wchar_t} trap?
|
||||
#define WCHAR_TRAPS true
|
||||
/// \brief Smallest finite value of \emph{wchar_t}.
|
||||
#define WCHAR_MIN - 0x0
|
||||
/// \brief Largest finite value of \emph{wchar_t}.
|
||||
#define WCHAR_MAX 0xffff
|
||||
|
||||
/// \brief Is \f$signed char\f$ signed?
|
||||
#define SCHAR_ROUNDS 0x0
|
||||
/// \brief Rounding style of type \f$signed char\f$.
|
||||
/// \brief Rounding style of type \emph{signed char}.
|
||||
#define SCHAR_ROUNDS 0
|
||||
/// \brief Number of radix digits represented by \emph{signed char}.
|
||||
#define SCHAR_RADIX_DIG 0x7
|
||||
/// \brief Number of radix digits represented by \f$signed char\f$.
|
||||
/// \brief Number of decimal digits represented by \emph{signed char}.
|
||||
#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$.
|
||||
/// \brief Number of decimal digits necessary to differentiate all values of type \emph{signed char}.
|
||||
#define SCHAR_DECIMAL_DIG 0
|
||||
/// \brief The radix, or integer base, used to represent a \emph{signed char}.
|
||||
#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$.
|
||||
/// \brief Do arithmetics operations with \emph{signed char} trap?
|
||||
#define SCHAR_TRAPS true
|
||||
/// \brief Smallest finite value of \emph{signed char}.
|
||||
#define SCHAR_MIN -0x80
|
||||
/// \brief Largest finite value of \emph{signed char}.
|
||||
#define SCHAR_MAX 0x7f
|
||||
|
||||
/// \brief Is \f$unsigned char\f$ unsigned?
|
||||
#define UCHAR_ROUNDS 0x0
|
||||
/// \brief Rounding style of type \f$unsigned char\f$.
|
||||
/// \brief Rounding style of type \emph{unsigned char}.
|
||||
#define UCHAR_ROUNDS 0
|
||||
/// \brief Number of radix digits represented by \emph{unsigned char}.
|
||||
#define UCHAR_RADIX_DIG 0x8
|
||||
/// \brief Number of radix digits represented by \f$unsigned char\f$.
|
||||
/// \brief Number of decimal digits represented by \emph{unsigned char}.
|
||||
#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$.
|
||||
/// \brief Number of decimal digits necessary to differentiate all values of type \emph{unsigned char}.
|
||||
#define UCHAR_DECIMAL_DIG 0
|
||||
/// \brief The radix, or integer base, used to represent an \emph{unsigned char}.
|
||||
#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$.
|
||||
/// \brief Do arithmetics operations with \emph{unsigned char} trap?
|
||||
#define UCHAR_TRAPS true
|
||||
/// \brief Smallest finite value of \emph{unsigned char}.
|
||||
#define UCHAR_MIN 0x0
|
||||
/// \brief Largest finite value of \f$unsigned char\f$.
|
||||
/// \brief Largest finite value of \emph{unsigned char}.
|
||||
#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$.
|
||||
/// \brief Rounding style of type \emph{short}.
|
||||
#define SHORT_ROUNDS 0
|
||||
/// \brief Number of radix digits represented by \emph{short}.
|
||||
#define SHORT_RADIX_DIG 0xf
|
||||
/// \brief Number of decimal digits represented by \f$short\f$.
|
||||
/// \brief Number of decimal digits represented by \emph{short}.
|
||||
#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$.
|
||||
/// \brief Number of decimal digits necessary to differentiate all values of type \emph{short}.
|
||||
#define SHORT_DECIMAL_DIG 0
|
||||
/// \brief The radix, or integer base, used to represent a \emph{short}.
|
||||
#define SHORT_RADIX 0x2
|
||||
/// \brief Do arithmetics operations with \f$short\f$ trap?
|
||||
#define SHORT_TRAPS 0xtrue
|
||||
/// \brief Smallest finite value of \f$short\f$.
|
||||
#define SHORT_MIN 0xffff8000
|
||||
/// \brief Largest finite value of \f$short\f$.
|
||||
/// \brief Do arithmetics operations with \emph{short} trap?
|
||||
#define SHORT_TRAPS true
|
||||
/// \brief Smallest finite value of \emph{short}.
|
||||
#define SHORT_MIN 0x8000
|
||||
/// \brief Largest finite value of \emph{short}.
|
||||
#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$.
|
||||
/// \brief Rounding style of type \emph{unsigned short}.
|
||||
#define USHORT_ROUNDS 0
|
||||
/// \brief Number of radix digits represented by \emph{unsigned short}.
|
||||
#define USHORT_RADIX_DIG 0x10
|
||||
/// \brief Number of decimal digits represented by \f$unsigned short\f$.
|
||||
/// \brief Number of decimal digits represented by \emph{unsigned short}.
|
||||
#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$.
|
||||
/// \brief Number of decimal digits necessary to differentiate all values of type \emph{unsigned short}.
|
||||
#define USHORT_DECIMAL_DIG 0
|
||||
/// \brief The radix, or integer base, used to represent an \emph{unsigned short}.
|
||||
#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$.
|
||||
/// \brief Do arithmetics operations with \emph{unsigned short} trap?
|
||||
#define USHORT_TRAPS true
|
||||
/// \brief Smallest finite value of \emph{unsigned short}.
|
||||
#define USHORT_MIN 0
|
||||
/// \brief Largest finite value of \emph{unsigned short}.
|
||||
#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$.
|
||||
/// \brief Rounding style of type \emph{int}.
|
||||
#define INT_ROUNDS 0
|
||||
/// \brief Number of radix digits represented by \emph{int}.
|
||||
#define INT_RADIX_DIG 0x1f
|
||||
/// \brief Number of decimal digits represented by \f$int\f$.
|
||||
/// \brief Number of decimal digits represented by \emph{int}.
|
||||
#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$.
|
||||
/// \brief Number of decimal digits necessary to differentiate all values of type \emph{int}.
|
||||
#define INT_DECIMAL_DIG 0
|
||||
/// \brief The radix, or integer base, used to represent an \emph{int}.
|
||||
#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$.
|
||||
/// \brief Do arithmetics operations with \emph{int} trap?
|
||||
#define INT_TRAPS true
|
||||
/// \brief Smallest finite value of \emph{int}.
|
||||
#define INT_MIN 0x80000000
|
||||
/// \brief Largest finite value of \f$int\f$.
|
||||
/// \brief Largest finite value of \emph{int}.
|
||||
#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$.
|
||||
/// \brief Rounding style of type \emph{unsigned int}.
|
||||
#define UINT_ROUNDS 0
|
||||
/// \brief Number of radix digits represented by \emph{unsigned int}.
|
||||
#define UINT_RADIX_DIG 0x20
|
||||
/// \brief Number of decimal digits represented by \f$unsigned int\f$.
|
||||
/// \brief Number of decimal digits represented by \emph{unsigned int}.
|
||||
#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$.
|
||||
/// \brief Number of decimal digits necessary to differentiate all values of type \emph{unsigned int}.
|
||||
#define UINT_DECIMAL_DIG 0
|
||||
/// \brief The radix, or integer base, used to represent an \emph{unsigned int}.
|
||||
#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$.
|
||||
/// \brief Do arithmetics operations with \emph{unsigned int} trap?
|
||||
#define UINT_TRAPS true
|
||||
/// \brief Smallest finite value of \emph{unsigned int}.
|
||||
#define UINT_MIN 0
|
||||
/// \brief Largest finite value of \emph{unsigned int}.
|
||||
#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$.
|
||||
/// \brief Rounding style of type \emph{long int}.
|
||||
#define LONG_ROUNDS 0
|
||||
/// \brief Number of radix digits represented by \emph{long int}.
|
||||
#define LONG_RADIX_DIG 0x3f
|
||||
/// \brief Number of decimal digits represented by \f$long int\f$.
|
||||
/// \brief Number of decimal digits represented by \emph{long int}.
|
||||
#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$.
|
||||
/// \brief Number of decimal digits necessary to differentiate all values of type \emph{long int}.
|
||||
#define LONG_DECIMAL_DIG 0
|
||||
/// \brief The radix, or integer base, used to represent a \emph{long int}.
|
||||
#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$.
|
||||
/// \brief Do arithmetics operations with \emph{long int} trap?
|
||||
#define LONG_TRAPS true
|
||||
/// \brief Smallest finite value of \emph{long int}.
|
||||
#define LONG_MIN 0x8000000000000000
|
||||
/// \brief Largest finite value of \f$long int\f$.
|
||||
/// \brief Largest finite value of \emph{long int}.
|
||||
#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$.
|
||||
/// \brief Rounding style of type \emph{unsigned long int}.
|
||||
#define ULONG_ROUNDS 0
|
||||
/// \brief Number of radix digits represented by \emph{unsigned long int}.
|
||||
#define ULONG_RADIX_DIG 0x40
|
||||
/// \brief Number of decimal digits represented by \f$unsigned long int\f$.
|
||||
/// \brief Number of decimal digits represented by \emph{unsigned long int}.
|
||||
#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$.
|
||||
/// \brief Number of decimal digits necessary to differentiate all values of type \emph{unsigned long int}.
|
||||
#define ULONG_DECIMAL_DIG 0
|
||||
/// \brief The radix, or integer base, used to represent an \emph{unsigned long int}.
|
||||
#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$.
|
||||
/// \brief Do arithmetics operations with \emph{unsigned long int} trap?
|
||||
#define ULONG_TRAPS true
|
||||
/// \brief Smallest finite value of \emph{unsigned long int}.
|
||||
#define ULONG_MIN 0
|
||||
/// \brief Largest finite value of \emph{unsigned long int}.
|
||||
#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$.
|
||||
/// \brief Rounding style of type \emph{long long}.
|
||||
#define LLONG_ROUNDS 0
|
||||
/// \brief Number of radix digits represented by \emph{long long}.
|
||||
#define LLONG_RADIX_DIG 0x3f
|
||||
/// \brief Number of decimal digits represented by \f$long long\f$.
|
||||
/// \brief Number of decimal digits represented by \emph{long long}.
|
||||
#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$.
|
||||
/// \brief Number of decimal digits necessary to differentiate all values of type \emph{long long}.
|
||||
#define LLONG_DECIMAL_DIG 0
|
||||
/// \brief The radix, or integer base, used to represent a \emph{long long}.
|
||||
#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$.
|
||||
/// \brief Do arithmetics operations with \emph{long long} trap?
|
||||
#define LLONG_TRAPS true
|
||||
/// \brief Smallest finite value of \emph{long long}.
|
||||
#define LLONG_MIN 0x8000000000000000
|
||||
/// \brief Largest finite value of \f$long long\f$.
|
||||
/// \brief Largest finite value of \emph{long long}.
|
||||
#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$.
|
||||
/// \brief Rounding style of type \emph{unsigned long long}.
|
||||
#define ULLONG_ROUNDS 0
|
||||
/// \brief Number of radix digits represented by \emph{unsigned long long}.
|
||||
#define ULLONG_RADIX_DIG 0x40
|
||||
/// \brief Number of decimal digits represented by \f$unsigned long long\f$.
|
||||
/// \brief Number of decimal digits represented by \emph{unsigned long long}.
|
||||
#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$.
|
||||
/// \brief Number of decimal digits necessary to differentiate all values of type \emph{unsigned long long}.
|
||||
#define ULLONG_DECIMAL_DIG 0
|
||||
/// \brief The radix, or integer base, used to represent an \emph{unsigned long long}.
|
||||
#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$.
|
||||
/// \brief Do arithmetics operations with \emph{unsigned long long} trap?
|
||||
#define ULLONG_TRAPS true
|
||||
/// \brief Smallest finite value of \emph{unsigned long long}.
|
||||
#define ULLONG_MIN 0
|
||||
/// \brief Largest finite value of \emph{unsigned long long}.
|
||||
#define ULLONG_MAX 0xffffffffffffffff
|
||||
|
||||
#endif // FENNEC_LANG_INTEGER_H
|
||||
|
||||
@@ -40,59 +40,59 @@
|
||||
/// <tr><th style="vertical-align: top">Syntax
|
||||
/// <th style="vertical-align: top">Description
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \f$FENNEC_HAS_BUILTIN_BIT_CAST\f$ <br>
|
||||
/// \f$Y FENNEC_BUILTIN_BIT_CAST(X)\f$
|
||||
/// \emph{FENNEC_HAS_BUILTIN_BIT_CAST} <br>
|
||||
/// \emph{Y FENNEC_BUILTIN_BIT_CAST(X)}
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// An intrinsic for doing a bitwise cast without using \f$reinterpret_cast\f$.
|
||||
/// An intrinsic for doing a bitwise cast without using \emph{reinterpret_cast}.
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \f$FENNEC_HAS_BUILTIN_ADDRESSOF\f$ <br>
|
||||
/// \f$Y FENNEC_BUILTIN_ADDRESSOF(X)\f$
|
||||
/// \emph{FENNEC_HAS_BUILTIN_ADDRESSOF} <br>
|
||||
/// \emph{Y FENNEC_BUILTIN_ADDRESSOF(X)}
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Obtains the true address of an object in circumstances where \f$operator&\f$ is overloaded.
|
||||
/// Obtains the true address of an object in circumstances where \emph{operator&} is overloaded.
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \f$FENNEC_HAS_BUILTIN_IS_CONVERTIBLE\f$ <br>
|
||||
/// \f$B FENNEC_BUILTIN_IS_CONVERTIBLE(X, Y)\f$
|
||||
/// \emph{FENNEC_HAS_BUILTIN_IS_CONVERTIBLE} <br>
|
||||
/// \emph{B FENNEC_BUILTIN_IS_CONVERTIBLE(X, Y)}
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Checks if type \f$X\f$ can be converted to type \f$Y\f$.
|
||||
/// Checks if type \emph{X} can be converted to type \emph{Y}.
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \f$FENNEC_HAS_BUILTIN_IS_EMPTY\f$ <br>
|
||||
/// \f$B FENNEC_BUILTIN_IS_EMPTY(X)\f$
|
||||
/// \emph{FENNEC_HAS_BUILTIN_IS_EMPTY} <br>
|
||||
/// \emph{B FENNEC_BUILTIN_IS_EMPTY(X)}
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Checks if type \f$X\f$ stores no data.
|
||||
/// Checks if type \emph{X} stores no data.
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \f$FENNEC_HAS_BUILTIN_IS_POLYMORPHIC\f$ <br>
|
||||
/// \f$B FENNEC_BUILTIN_IS_POLYMORPHIC(X)\f$
|
||||
/// \emph{FENNEC_HAS_BUILTIN_IS_POLYMORPHIC} <br>
|
||||
/// \emph{B FENNEC_BUILTIN_IS_POLYMORPHIC(X)}
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Checks if type \f$X\f$ is polymorphic, this is for classes only thus checks only for subtyping
|
||||
/// Checks if type \emph{X} is polymorphic, this is for classes only thus checks only for subtyping
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \f$FENNEC_HAS_BUILTIN_IS_FINAL\f$ <br>
|
||||
/// \f$B FENNEC_BUILTIN_IS_FINAL(X)\f$
|
||||
/// \emph{FENNEC_HAS_BUILTIN_IS_FINAL} <br>
|
||||
/// \emph{B FENNEC_BUILTIN_IS_FINAL(X)}
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Checks if type \f$X\f$ is final, meaning a function or class cannot be derived from.
|
||||
/// Checks if type \emph{X} is final, meaning a function or class cannot be derived from.
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \f$FENNEC_HAS_BUILTIN_IS_ABSTRACT\f$ <br>
|
||||
/// \f$B FENNEC_BUILTIN_IS_ABSTRACT(X)\f$
|
||||
/// \emph{FENNEC_HAS_BUILTIN_IS_ABSTRACT} <br>
|
||||
/// \emph{B FENNEC_BUILTIN_IS_ABSTRACT(X)}
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Opposite of \f$FENNEC_BUILTIN_IS_FINAL\f$, checks if abstract, meaning \f$X\f$ has at least one pure virtual function.
|
||||
/// Opposite of \emph{FENNEC_BUILTIN_IS_FINAL}, checks if abstract, meaning \emph{X} has at least one pure virtual function.
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \f$FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT\f$ <br>
|
||||
/// \f$B FENNEC_BUILTIN_IS_STANDARD_LAYOUT(X)\f$
|
||||
/// \emph{FENNEC_HAS_BUILTIN_IS_STANDARD_LAYOUT} <br>
|
||||
/// \emph{B FENNEC_BUILTIN_IS_STANDARD_LAYOUT(X)}
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Checks if \f$X\f$ has a standard layout, here is [full criteria](https://www.cppreference.com/w/cpp/language/classes.html#Standard-layout_class)
|
||||
/// Checks if \emph{X} has a standard layout, here is [full criteria](https://www.cppreference.com/w/cpp/language/classes.html#Standard-layout_class)
|
||||
/// for this trait
|
||||
///
|
||||
/// <tr><td width="50%" style="vertical-align: top"> <br>
|
||||
/// \f$FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE\f$ <br>
|
||||
/// \f$B FENNEC_BUILTIN_IS_CONSTRUCTIBLE(X, ...)\f$
|
||||
/// \emph{FENNEC_HAS_BUILTIN_IS_CONSTRUCTIBLE} <br>
|
||||
/// \emph{B FENNEC_BUILTIN_IS_CONSTRUCTIBLE(X, ...)}
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// Checks if type \f$X\f$ is constructible with args \f$\ldots\f$, such that \f$X::X(...)\f$ exists.
|
||||
/// Checks if type \emph{X} is constructible with args \emph{\ldots}, such that \emph{X::X(...)} exists.
|
||||
///
|
||||
/// </table>
|
||||
///
|
||||
@@ -242,8 +242,16 @@
|
||||
|
||||
// Difficult and Inconsistent without intrinsics
|
||||
#if __has_builtin(__has_trivial_destructor)
|
||||
# define FENNEC_HAS_BUILTIN_HAS_TRIVIAL_DESTRUCTOR 1
|
||||
# define FENNEC_BUILTIN_HAS_TRIVIAL_DESTRUCTOR(type) __has_trivial_destructor(type)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_HAS_TRIVIAL_DESTRUCTOR 0
|
||||
#endif
|
||||
|
||||
// Difficult and Inconsistent without intrinsics
|
||||
#if __has_builtin(__is_trivially_destructible)
|
||||
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE 1
|
||||
# define FENNEC_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE(type) __has_trivial_destructor(type)
|
||||
# define FENNEC_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE(type) __is_trivially_destructible(type)
|
||||
#else
|
||||
# define FENNEC_HAS_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE 0
|
||||
#endif
|
||||
|
||||
@@ -231,7 +231,7 @@ template<typename TypeT> struct numeric_limits
|
||||
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_iec559 = false; //!< Check if TypeT represents an 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
|
||||
@@ -260,500 +260,515 @@ template<typename TypeT> struct numeric_limits
|
||||
static constexpr TypeT denorm_min() { return TypeT(); } //!< \returns a value of TypeT holding the smallest positive subnormal
|
||||
};
|
||||
|
||||
// Overload definitions for basic types
|
||||
|
||||
// Overload for the builtin floating point type
|
||||
// Overloads ===========================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Definition for type \emph{float}.
|
||||
template<> struct numeric_limits<float>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr bool is_integer = false;
|
||||
static constexpr bool is_exact = false;
|
||||
static constexpr bool has_infinity = FLT_HAS_INFINITY;
|
||||
static constexpr bool has_quiet_nan = FLT_HAS_QUIET_NAN;
|
||||
static constexpr bool has_signaling_nan = FLT_HAS_SIGNALING_NAN;
|
||||
static constexpr bool has_denorm = FLT_HAS_DENORM;
|
||||
static constexpr bool has_denorm_loss = FLT_HAS_DENORM_LOSS;
|
||||
static constexpr bool is_iec559 = FLT_IS_IEC559;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = false;
|
||||
static constexpr bool tinyness_before = FLT_TINYNESS_BEFORE;
|
||||
static constexpr bool traps = FLT_TRAPS;
|
||||
static constexpr bool is_specialized = true; //!< Check if the template is specialized for float
|
||||
static constexpr bool is_signed = true; //!< Check if float is signed
|
||||
static constexpr bool is_integer = false; //!< Check if float is of an integral type
|
||||
static constexpr bool is_exact = false; //!< Check if float is exact in its precision
|
||||
static constexpr bool has_infinity = FLT_HAS_INFINITY; //!< Check if float can hold a value representing infinity
|
||||
static constexpr bool has_quiet_nan = FLT_HAS_QUIET_NAN; //!< Check if float can hold a non-signaling nan
|
||||
static constexpr bool has_signaling_nan = FLT_HAS_SIGNALING_NAN; //!< Check if float can hold a signaling nan
|
||||
static constexpr bool has_denorm = FLT_HAS_DENORM; //!< Check if float denormalizes
|
||||
static constexpr bool has_denorm_loss = FLT_HAS_DENORM_LOSS; //!< Check if float has precision loss when denormalized
|
||||
static constexpr bool is_iec559 = FLT_IS_IEC559; //!< Check if float represents an IEC 559 or IEEE 754
|
||||
static constexpr bool is_bounded = true; //!< Check if float represents a finite set of values
|
||||
static constexpr bool is_modulo = false; //!< Check if float can handle modulo arithmetic
|
||||
static constexpr bool tinyness_before = FLT_TINYNESS_BEFORE; //!< Check if float checks for tinyness before rounding
|
||||
static constexpr bool traps = FLT_TRAPS; //!< Check if float can cause operations to trap
|
||||
|
||||
static constexpr int digits = FLT_MANT_DIG;
|
||||
static constexpr int digits10 = FLT_DIG;
|
||||
static constexpr int max_digits10 = FLT_DECIMAL_DIG;
|
||||
static constexpr int radix = FLT_RADIX;
|
||||
static constexpr int min_exponent = FLT_MIN_EXP;
|
||||
static constexpr int min_exponent10 = FLT_MIN_10_EXP;
|
||||
static constexpr int max_exponent = FLT_MAX_EXP;
|
||||
static constexpr int max_exponent10 = FLT_MAX_10_EXP;
|
||||
static constexpr int digits = FLT_MANT_DIG; //!< Get the base representation of the type
|
||||
static constexpr int digits10 = FLT_DIG; //!< Get the number of radix digits float represents
|
||||
static constexpr int max_digits10 = FLT_DECIMAL_DIG; //!< Get the number of decimal digits float represents
|
||||
static constexpr int radix = FLT_RADIX; //!< Get the maximum number of decimal digits float represents
|
||||
static constexpr int min_exponent = FLT_MIN_EXP; //!< Get the minimum number of radix digits that represent the exponent of float
|
||||
static constexpr int min_exponent10 = FLT_MIN_10_EXP; //!< Get the minimum number of decimal digits that represent the exponent of float
|
||||
static constexpr int max_exponent = FLT_MAX_EXP; //!< Get the maximum number of radix digits that represent the exponent of float
|
||||
static constexpr int max_exponent10 = FLT_MAX_10_EXP; //!< Get the maximum number of decimal digits that represent the exponent of float
|
||||
|
||||
static constexpr float min() { return -FLT_MAX; }
|
||||
static constexpr float max() { return FLT_MAX; }
|
||||
static constexpr float lowest() { return FLT_MIN; }
|
||||
static constexpr float epsilon() { return FLT_EPSILON; }
|
||||
static constexpr float round_error() { return FLT_ROUND_ERR; }
|
||||
static constexpr float infinity() { return FLT_INF; }
|
||||
static constexpr float quiet_NaN() { return FLT_QUIET_NAN; }
|
||||
static constexpr float signaling_NaN() { return FLT_SIGNALING_NAN; }
|
||||
static constexpr float denorm_min() { return FLT_DENORM_MIN; }
|
||||
static constexpr float min() { return -FLT_MAX; } //!< \returns the minimum finite value of float
|
||||
static constexpr float max() { return FLT_MAX; } //!< \returns the maximum finite value of float
|
||||
static constexpr float lowest() { return FLT_MIN; } //!< \returns the smallest positive value of float
|
||||
static constexpr float epsilon() { return FLT_EPSILON; } //!< \returns the difference between 1.0 and the next representable value
|
||||
static constexpr float round_error() { return FLT_ROUND_ERR; } //!< \returns the max rounding error of float
|
||||
static constexpr float infinity() { return FLT_INF; } //!< \returns a value of float holding a positive infinity
|
||||
static constexpr float quiet_NaN() { return FLT_QUIET_NAN; } //!< \returns a value of float holding a quiet NaN
|
||||
static constexpr float signaling_NaN() { return FLT_SIGNALING_NAN; } //!< \returns a value of float holding a signaling NaN
|
||||
static constexpr float denorm_min() { return FLT_DENORM_MIN; } //!< \returns a value of float holding the smallest positive subnormal
|
||||
};
|
||||
|
||||
// Overload for the bultin double precision floating point type
|
||||
|
||||
///
|
||||
/// \brief Definition for type \emph{double}.
|
||||
template<> struct numeric_limits<double>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr bool is_integer = false;
|
||||
static constexpr bool is_exact = false;
|
||||
static constexpr bool has_infinity = DBL_HAS_INFINITY;
|
||||
static constexpr bool has_quiet_nan = DBL_HAS_QUIET_NAN;
|
||||
static constexpr bool has_signaling_nan = DBL_HAS_SIGNALING_NAN;
|
||||
static constexpr bool has_denorm = DBL_HAS_DENORM;
|
||||
static constexpr bool has_denorm_loss = DBL_HAS_DENORM_LOSS;
|
||||
static constexpr bool is_iec559 = DBL_IS_IEC559;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = false;
|
||||
static constexpr bool tinyness_before = DBL_TINYNESS_BEFORE;
|
||||
static constexpr bool traps = DBL_TRAPS;
|
||||
static constexpr bool is_specialized = true; //!< Check if the template is specialized for double
|
||||
static constexpr bool is_signed = true; //!< Check if double is signed
|
||||
static constexpr bool is_integer = false; //!< Check if double is of an integral type
|
||||
static constexpr bool is_exact = false; //!< Check if double is exact in its precision
|
||||
static constexpr bool has_infinity = DBL_HAS_INFINITY; //!< Check if double can hold a value representing infinity
|
||||
static constexpr bool has_quiet_nan = DBL_HAS_QUIET_NAN; //!< Check if double can hold a non-signaling nan
|
||||
static constexpr bool has_signaling_nan = DBL_HAS_SIGNALING_NAN; //!< Check if double can hold a signaling nan
|
||||
static constexpr bool has_denorm = DBL_HAS_DENORM; //!< Check if double denormalizes
|
||||
static constexpr bool has_denorm_loss = DBL_HAS_DENORM_LOSS; //!< Check if double has precision loss when denormalized
|
||||
static constexpr bool is_iec559 = DBL_IS_IEC559; //!< Check if double represents an IEC 559 or IEEE 754
|
||||
static constexpr bool is_bounded = true; //!< Check if double represents a finite set of values
|
||||
static constexpr bool is_modulo = false; //!< Check if double can handle modulo arithmetic
|
||||
static constexpr bool tinyness_before = DBL_TINYNESS_BEFORE; //!< Check if double checks for tinyness before rounding
|
||||
static constexpr bool traps = DBL_TRAPS; //!< Check if double can cause operations to trap
|
||||
|
||||
static constexpr int digits = DBL_MANT_DIG;
|
||||
static constexpr int digits10 = DBL_DIG;
|
||||
static constexpr int max_digits10 = DBL_DECIMAL_DIG;
|
||||
static constexpr int radix = DBL_RADIX;
|
||||
static constexpr int min_exponent = DBL_MIN_EXP;
|
||||
static constexpr int min_exponent10 = DBL_MIN_10_EXP;
|
||||
static constexpr int max_exponent = DBL_MAX_EXP;
|
||||
static constexpr int max_exponent10 = DBL_MAX_10_EXP;
|
||||
static constexpr int digits = DBL_MANT_DIG; //!< Get the base representation of the type
|
||||
static constexpr int digits10 = DBL_DIG; //!< Get the number of radix digits double represents
|
||||
static constexpr int max_digits10 = DBL_DECIMAL_DIG; //!< Get the number of decimal digits double represents
|
||||
static constexpr int radix = DBL_RADIX; //!< Get the maximum number of decimal digits double represents
|
||||
static constexpr int min_exponent = DBL_MIN_EXP; //!< Get the minimum number of radix digits that represent the exponent of double
|
||||
static constexpr int min_exponent10 = DBL_MIN_10_EXP; //!< Get the minimum number of decimal digits that represent the exponent of double
|
||||
static constexpr int max_exponent = DBL_MAX_EXP; //!< Get the maximum number of radix digits that represent the exponent of double
|
||||
static constexpr int max_exponent10 = DBL_MAX_10_EXP; //!< Get the maximum number of decimal digits that represent the exponent of double
|
||||
|
||||
static constexpr double min() { return -DBL_MAX; }
|
||||
static constexpr double max() { return DBL_MAX; }
|
||||
static constexpr double lowest() { return DBL_MIN; }
|
||||
static constexpr double epsilon() { return DBL_EPSILON; }
|
||||
static constexpr double round_error() { return DBL_ROUND_ERR; }
|
||||
static constexpr double infinity() { return DBL_INF; }
|
||||
static constexpr double quiet_NaN() { return DBL_QUIET_NAN; }
|
||||
static constexpr double signaling_NaN() { return DBL_SIGNALING_NAN; }
|
||||
static constexpr double denorm_min() { return DBL_DENORM_MIN; }
|
||||
static constexpr double min() { return -DBL_MAX; } //!< \returns the minimum finite value of double
|
||||
static constexpr double max() { return DBL_MAX; } //!< \returns the maximum finite value of double
|
||||
static constexpr double lowest() { return DBL_MIN; } //!< \returns the smallest positive value of double
|
||||
static constexpr double epsilon() { return DBL_EPSILON; } //!< \returns the difference between 1.0 and the next representable value
|
||||
static constexpr double round_error() { return DBL_ROUND_ERR; } //!< \returns the max rounding error of double
|
||||
static constexpr double infinity() { return DBL_INF; } //!< \returns a value of double holding a positive infinity
|
||||
static constexpr double quiet_NaN() { return DBL_QUIET_NAN; } //!< \returns a value of double holding a quiet NaN
|
||||
static constexpr double signaling_NaN() { return DBL_SIGNALING_NAN; } //!< \returns a value of double holding a signaling NaN
|
||||
static constexpr double denorm_min() { return DBL_DENORM_MIN; } //!< \returns a value of double holding the smallest positive subnormal
|
||||
};
|
||||
|
||||
// Overload for the builtin char type
|
||||
///
|
||||
/// \brief Definition for type \emph{char}.
|
||||
template<> struct numeric_limits<char>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = CHAR_IS_SIGNED;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
static constexpr bool is_specialized = true; //!< Check if the template is specialized for char
|
||||
static constexpr bool is_signed = CHAR_IS_SIGNED; //!< Check if char is signed
|
||||
static constexpr bool is_integer = true; //!< Check if char is of an integral type
|
||||
static constexpr bool is_exact = true; //!< Check if char is exact in its precision
|
||||
static constexpr bool has_infinity = false; //!< Check if char can hold a value representing infinity
|
||||
static constexpr bool has_quiet_nan = false; //!< Check if char can hold a non-signaling nan
|
||||
static constexpr bool has_signaling_nan = false; //!< Check if char can hold a signaling nan
|
||||
static constexpr bool has_denorm = false; //!< Check if char denormalizes
|
||||
static constexpr bool has_denorm_loss = false; //!< Check if char has precision loss when denormalized
|
||||
static constexpr bool is_iec559 = false; //!< Check if char represents an IEC 559 or IEEE 754
|
||||
static constexpr bool is_bounded = true; //!< Check if char represents a finite set of values
|
||||
static constexpr bool is_modulo = true; //!< Check if char can handle modulo arithmetic
|
||||
static constexpr bool tinyness_before = false; //!< Check if char checks for tinyness before rounding
|
||||
static constexpr bool traps = true; //!< Check if char can cause operations to trap
|
||||
|
||||
static constexpr int digits = CHAR_RADIX_DIG;
|
||||
static constexpr int digits10 = CHAR_DIG;
|
||||
static constexpr int max_digits10 = CHAR_DECIMAL_DIG;
|
||||
static constexpr int radix = CHAR_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
static constexpr int digits = CHAR_RADIX_DIG; //!< Get the base representation of the type
|
||||
static constexpr int digits10 = CHAR_DIG; //!< Get the number of radix digits char represents
|
||||
static constexpr int max_digits10 = CHAR_DECIMAL_DIG; //!< Get the number of decimal digits char represents
|
||||
static constexpr int radix = CHAR_RADIX; //!< Get the maximum number of decimal digits char represents
|
||||
static constexpr int min_exponent = 0; //!< Get the minimum number of radix digits that represent the exponent of char
|
||||
static constexpr int min_exponent10 = 0; //!< Get the minimum number of decimal digits that represent the exponent of char
|
||||
static constexpr int max_exponent = 0; //!< Get the maximum number of radix digits that represent the exponent of char
|
||||
static constexpr int max_exponent10 = 0; //!< Get the maximum number of decimal digits that represent the exponent of char
|
||||
|
||||
static constexpr char min() { return static_cast<char>(CHAR_MIN); }
|
||||
static constexpr char max() { return CHAR_MAX; }
|
||||
static constexpr char lowest() { return 1; }
|
||||
static constexpr char epsilon() { return 1; }
|
||||
static constexpr char round_error() { return 0; }
|
||||
static constexpr char infinity() { return 0; }
|
||||
static constexpr char quiet_NaN() { return 0; }
|
||||
static constexpr char signaling_NaN() { return 0; }
|
||||
static constexpr char denorm_min() { return 0; }
|
||||
static constexpr char min() { return CHAR_MIN; } //!< \returns the minimum finite value of char
|
||||
static constexpr char max() { return CHAR_MAX; } //!< \returns the maximum finite value of char
|
||||
static constexpr char lowest() { return 1; } //!< \returns the smallest positive value of char
|
||||
static constexpr char epsilon() { return 1; } //!< \returns the difference between 1.0 and the next representable value
|
||||
static constexpr char round_error() { return 0; } //!< \returns the max rounding error of char
|
||||
static constexpr char infinity() { return 0; } //!< \returns a value of char holding a positive infinity
|
||||
static constexpr char quiet_NaN() { return 0; } //!< \returns a value of char holding a quiet NaN
|
||||
static constexpr char signaling_NaN() { return 0; } //!< \returns a value of char holding a signaling NaN
|
||||
static constexpr char denorm_min() { return 0; } //!< \returns a value of char holding the smallest positive subnormal
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
///
|
||||
/// \brief Definition for type \emph{signed char}.
|
||||
template<> struct numeric_limits<signed char>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
static constexpr bool is_specialized = true; //!< Check if the template is specialized for signed char
|
||||
static constexpr bool is_signed = true; //!< Check if signed char is signed
|
||||
static constexpr bool is_integer = true; //!< Check if signed char is of an integral type
|
||||
static constexpr bool is_exact = true; //!< Check if signed char is exact in its precision
|
||||
static constexpr bool has_infinity = false; //!< Check if signed char can hold a value representing infinity
|
||||
static constexpr bool has_quiet_nan = false; //!< Check if signed char can hold a non-signaling nan
|
||||
static constexpr bool has_signaling_nan = false; //!< Check if signed char can hold a signaling nan
|
||||
static constexpr bool has_denorm = false; //!< Check if signed char denormalizes
|
||||
static constexpr bool has_denorm_loss = false; //!< Check if signed char has precision loss when denormalized
|
||||
static constexpr bool is_iec559 = false; //!< Check if signed char represents an IEC 559 or IEEE 754
|
||||
static constexpr bool is_bounded = true; //!< Check if signed char represents a finite set of values
|
||||
static constexpr bool is_modulo = true; //!< Check if signed char can handle modulo arithmetic
|
||||
static constexpr bool tinyness_before = false; //!< Check if signed char checks for tinyness before rounding
|
||||
static constexpr bool traps = true; //!< Check if signed char can cause operations to trap
|
||||
|
||||
static constexpr int digits = SCHAR_RADIX_DIG;
|
||||
static constexpr int digits10 = SCHAR_DIG;
|
||||
static constexpr int max_digits10 = SCHAR_DECIMAL_DIG;
|
||||
static constexpr int radix = SCHAR_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
static constexpr int digits = SCHAR_RADIX_DIG; //!< Get the base representation of the type
|
||||
static constexpr int digits10 = SCHAR_DIG; //!< Get the number of radix digits signed char represents
|
||||
static constexpr int max_digits10 = SCHAR_DECIMAL_DIG; //!< Get the number of decimal digits signed char represents
|
||||
static constexpr int radix = SCHAR_RADIX; //!< Get the maximum number of decimal digits signed char represents
|
||||
static constexpr int min_exponent = 0; //!< Get the minimum number of radix digits that represent the exponent of signed char
|
||||
static constexpr int min_exponent10 = 0; //!< Get the minimum number of decimal digits that represent the exponent of signed char
|
||||
static constexpr int max_exponent = 0; //!< Get the maximum number of radix digits that represent the exponent of signed char
|
||||
static constexpr int max_exponent10 = 0; //!< Get the maximum number of decimal digits that represent the exponent of signed char
|
||||
|
||||
static constexpr signed char min() { return static_cast<signed char>(SCHAR_MIN); }
|
||||
static constexpr signed char max() { return SCHAR_MAX; }
|
||||
static constexpr signed char lowest() { return 1; }
|
||||
static constexpr signed char epsilon() { return 1; }
|
||||
static constexpr signed char round_error() { return 0; }
|
||||
static constexpr signed char infinity() { return 0; }
|
||||
static constexpr signed char quiet_NaN() { return 0; }
|
||||
static constexpr signed char signaling_NaN() { return 0; }
|
||||
static constexpr signed char denorm_min() { return 0; }
|
||||
static constexpr signed char min() { return SCHAR_MIN; } //!< \returns the minimum finite value of signed char
|
||||
static constexpr signed char max() { return SCHAR_MAX; } //!< \returns the maximum finite value of signed char
|
||||
static constexpr signed char lowest() { return 1; } //!< \returns the smallest positive value of signed char
|
||||
static constexpr signed char epsilon() { return 1; } //!< \returns the difference between 1.0 and the next representable value
|
||||
static constexpr signed char round_error() { return 0; } //!< \returns the max rounding error of signed char
|
||||
static constexpr signed char infinity() { return 0; } //!< \returns a value of signed char holding a positive infinity
|
||||
static constexpr signed char quiet_NaN() { return 0; } //!< \returns a value of signed char holding a quiet NaN
|
||||
static constexpr signed char signaling_NaN() { return 0; } //!< \returns a value of signed char holding a signaling NaN
|
||||
static constexpr signed char denorm_min() { return 0; } //!< \returns a value of signed char holding the smallest positive subnormal
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
///
|
||||
/// \brief Definition for type \emph{unsigned char}.
|
||||
template<> struct numeric_limits<unsigned char>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = false;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
static constexpr bool is_specialized = true; //!< Check if the template is specialized for unsigned char
|
||||
static constexpr bool is_signed = false; //!< Check if unsigned char is unsigned
|
||||
static constexpr bool is_integer = true; //!< Check if unsigned char is of an integral type
|
||||
static constexpr bool is_exact = true; //!< Check if unsigned char is exact in its precision
|
||||
static constexpr bool has_infinity = false; //!< Check if unsigned char can hold a value representing infinity
|
||||
static constexpr bool has_quiet_nan = false; //!< Check if unsigned char can hold a non-signaling nan
|
||||
static constexpr bool has_signaling_nan = false; //!< Check if unsigned char can hold a signaling nan
|
||||
static constexpr bool has_denorm = false; //!< Check if unsigned char denormalizes
|
||||
static constexpr bool has_denorm_loss = false; //!< Check if unsigned char has precision loss when denormalized
|
||||
static constexpr bool is_iec559 = false; //!< Check if unsigned char represents an IEC 559 or IEEE 754
|
||||
static constexpr bool is_bounded = true; //!< Check if unsigned char represents a finite set of values
|
||||
static constexpr bool is_modulo = true; //!< Check if unsigned char can handle modulo arithmetic
|
||||
static constexpr bool tinyness_before = false; //!< Check if unsigned char checks for tinyness before rounding
|
||||
static constexpr bool traps = true; //!< Check if unsigned char can cause operations to trap
|
||||
|
||||
static constexpr int digits = UCHAR_RADIX_DIG;
|
||||
static constexpr int digits10 = UCHAR_DIG;
|
||||
static constexpr int max_digits10 = UCHAR_DECIMAL_DIG;
|
||||
static constexpr int radix = UCHAR_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
static constexpr int digits = UCHAR_RADIX_DIG; //!< Get the base representation of the type
|
||||
static constexpr int digits10 = UCHAR_DIG; //!< Get the number of radix digits unsigned char represents
|
||||
static constexpr int max_digits10 = UCHAR_DECIMAL_DIG; //!< Get the number of decimal digits unsigned char represents
|
||||
static constexpr int radix = UCHAR_RADIX; //!< Get the maximum number of decimal digits unsigned char represents
|
||||
static constexpr int min_exponent = 0; //!< Get the minimum number of radix digits that represent the exponent of unsigned char
|
||||
static constexpr int min_exponent10 = 0; //!< Get the minimum number of decimal digits that represent the exponent of unsigned char
|
||||
static constexpr int max_exponent = 0; //!< Get the maximum number of radix digits that represent the exponent of unsigned char
|
||||
static constexpr int max_exponent10 = 0; //!< Get the maximum number of decimal digits that represent the exponent of unsigned char
|
||||
|
||||
static constexpr unsigned char min() { return UCHAR_MIN; }
|
||||
static constexpr unsigned char max() { return UCHAR_MAX; }
|
||||
static constexpr unsigned char lowest() { return 1; }
|
||||
static constexpr unsigned char epsilon() { return 1; }
|
||||
static constexpr unsigned char round_error() { return 0; }
|
||||
static constexpr unsigned char infinity() { return 0; }
|
||||
static constexpr unsigned char quiet_NaN() { return 0; }
|
||||
static constexpr unsigned char signaling_NaN() { return 0; }
|
||||
static constexpr unsigned char denorm_min() { return 0; }
|
||||
static constexpr unsigned char min() { return UCHAR_MIN; } //!< \returns the minimum finite value of unsigned char
|
||||
static constexpr unsigned char max() { return UCHAR_MAX; } //!< \returns the maximum finite value of unsigned char
|
||||
static constexpr unsigned char lowest() { return 1; } //!< \returns the smallest positive value of unsigned char
|
||||
static constexpr unsigned char epsilon() { return 1; } //!< \returns the difference between 1.0 and the next representable value
|
||||
static constexpr unsigned char round_error() { return 0; } //!< \returns the max rounding error of unsigned char
|
||||
static constexpr unsigned char infinity() { return 0; } //!< \returns a value of unsigned char holding a positive infinity
|
||||
static constexpr unsigned char quiet_NaN() { return 0; } //!< \returns a value of unsigned char holding a quiet NaN
|
||||
static constexpr unsigned char signaling_NaN() { return 0; } //!< \returns a value of unsigned char holding a signaling NaN
|
||||
static constexpr unsigned char denorm_min() { return 0; } //!< \returns a value of unsigned char holding the smallest positive subnormal
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
///
|
||||
/// \brief Definition for type \emph{short}.
|
||||
template<> struct numeric_limits<short>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
static constexpr bool is_specialized = true; //!< Check if the template is specialized for short
|
||||
static constexpr bool is_signed = true; //!< Check if short is signed
|
||||
static constexpr bool is_integer = true; //!< Check if short is of an integral type
|
||||
static constexpr bool is_exact = true; //!< Check if short is exact in its precision
|
||||
static constexpr bool has_infinity = false; //!< Check if short can hold a value representing infinity
|
||||
static constexpr bool has_quiet_nan = false; //!< Check if short can hold a non-signaling nan
|
||||
static constexpr bool has_signaling_nan = false; //!< Check if short can hold a signaling nan
|
||||
static constexpr bool has_denorm = false; //!< Check if short denormalizes
|
||||
static constexpr bool has_denorm_loss = false; //!< Check if short has precision loss when denormalized
|
||||
static constexpr bool is_iec559 = false; //!< Check if short represents an IEC 559 or IEEE 754
|
||||
static constexpr bool is_bounded = true; //!< Check if short represents a finite set of values
|
||||
static constexpr bool is_modulo = true; //!< Check if short can handle modulo arithmetic
|
||||
static constexpr bool tinyness_before = false; //!< Check if short checks for tinyness before rounding
|
||||
static constexpr bool traps = true; //!< Check if short can cause operations to trap
|
||||
|
||||
static constexpr int digits = SHORT_RADIX_DIG;
|
||||
static constexpr int digits10 = SHORT_DIG;
|
||||
static constexpr int max_digits10 = SHORT_DECIMAL_DIG;
|
||||
static constexpr int radix = SHORT_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
static constexpr int digits = SHORT_RADIX_DIG; //!< Get the base representation of the type
|
||||
static constexpr int digits10 = SHORT_DIG; //!< Get the number of radix digits short represents
|
||||
static constexpr int max_digits10 = SHORT_DECIMAL_DIG; //!< Get the number of decimal digits short represents
|
||||
static constexpr int radix = SHORT_RADIX; //!< Get the maximum number of decimal digits short represents
|
||||
static constexpr int min_exponent = 0; //!< Get the minimum number of radix digits that represent the exponent of short
|
||||
static constexpr int min_exponent10 = 0; //!< Get the minimum number of decimal digits that represent the exponent of short
|
||||
static constexpr int max_exponent = 0; //!< Get the maximum number of radix digits that represent the exponent of short
|
||||
static constexpr int max_exponent10 = 0; //!< Get the maximum number of decimal digits that represent the exponent of short
|
||||
|
||||
static constexpr short min() { return static_cast<short>(SHORT_MIN); }
|
||||
static constexpr short max() { return SHORT_MAX; }
|
||||
static constexpr short lowest() { return 1; }
|
||||
static constexpr short epsilon() { return 1; }
|
||||
static constexpr short round_error() { return 0; }
|
||||
static constexpr short infinity() { return 0; }
|
||||
static constexpr short quiet_NaN() { return 0; }
|
||||
static constexpr short signaling_NaN() { return 0; }
|
||||
static constexpr short denorm_min() { return 0; }
|
||||
static constexpr short min() { return static_cast<short>(SHORT_MIN); } //!< \returns the minimum finite value of short
|
||||
static constexpr short max() { return SHORT_MAX; } //!< \returns the maximum finite value of short
|
||||
static constexpr short lowest() { return 1; } //!< \returns the smallest positive value of short
|
||||
static constexpr short epsilon() { return 1; } //!< \returns the difference between 1.0 and the next representable value
|
||||
static constexpr short round_error() { return 0; } //!< \returns the max rounding error of short
|
||||
static constexpr short infinity() { return 0; } //!< \returns a value of short holding a positive infinity
|
||||
static constexpr short quiet_NaN() { return 0; } //!< \returns a value of short holding a quiet NaN
|
||||
static constexpr short signaling_NaN() { return 0; } //!< \returns a value of short holding a signaling NaN
|
||||
static constexpr short denorm_min() { return 0; } //!< \returns a value of short holding the smallest positive subnormal
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
///
|
||||
/// \brief Definition for type \emph{unsigned short}.
|
||||
template<> struct numeric_limits<unsigned short>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = false;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
static constexpr bool is_specialized = true; //!< Check if the template is specialized for signed short
|
||||
static constexpr bool is_signed = false; //!< Check if unsigned short is signed
|
||||
static constexpr bool is_integer = true; //!< Check if unsigned short is of an integral type
|
||||
static constexpr bool is_exact = true; //!< Check if unsigned short is exact in its precision
|
||||
static constexpr bool has_infinity = false; //!< Check if unsigned short can hold a value representing infinity
|
||||
static constexpr bool has_quiet_nan = false; //!< Check if unsigned short can hold a non-signaling nan
|
||||
static constexpr bool has_signaling_nan = false; //!< Check if unsigned short can hold a signaling nan
|
||||
static constexpr bool has_denorm = false; //!< Check if unsigned short denormalizes
|
||||
static constexpr bool has_denorm_loss = false; //!< Check if unsigned short has precision loss when denormalized
|
||||
static constexpr bool is_iec559 = false; //!< Check if unsigned short represents an IEC 559 or IEEE 754
|
||||
static constexpr bool is_bounded = true; //!< Check if unsigned short represents a finite set of values
|
||||
static constexpr bool is_modulo = true; //!< Check if unsigned short can handle modulo arithmetic
|
||||
static constexpr bool tinyness_before = false; //!< Check if unsigned short checks for tinyness before rounding
|
||||
static constexpr bool traps = true; //!< Check if unsigned short can cause operations to trap
|
||||
|
||||
static constexpr int digits = USHORT_RADIX_DIG;
|
||||
static constexpr int digits10 = USHORT_DIG;
|
||||
static constexpr int max_digits10 = USHORT_DECIMAL_DIG;
|
||||
static constexpr int radix = USHORT_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
static constexpr int digits = USHORT_RADIX_DIG; //!< Get the base representation of the type
|
||||
static constexpr int digits10 = USHORT_DIG; //!< Get the number of radix digits unsigned short represents
|
||||
static constexpr int max_digits10 = USHORT_DECIMAL_DIG; //!< Get the number of decimal digits unsigned short represents
|
||||
static constexpr int radix = USHORT_RADIX; //!< Get the maximum number of decimal digits unsigned short represents
|
||||
static constexpr int min_exponent = 0; //!< Get the minimum number of radix digits that represent the exponent of unsigned short
|
||||
static constexpr int min_exponent10 = 0; //!< Get the minimum number of decimal digits that represent the exponent of unsigned short
|
||||
static constexpr int max_exponent = 0; //!< Get the maximum number of radix digits that represent the exponent of unsigned short
|
||||
static constexpr int max_exponent10 = 0; //!< Get the maximum number of decimal digits that represent the exponent of unsigned short
|
||||
|
||||
static constexpr unsigned short min() { return USHORT_MIN; }
|
||||
static constexpr unsigned short max() { return USHORT_MAX; }
|
||||
static constexpr unsigned short lowest() { return 1; }
|
||||
static constexpr unsigned short epsilon() { return 1; }
|
||||
static constexpr unsigned short round_error() { return 0; }
|
||||
static constexpr unsigned short infinity() { return 0; }
|
||||
static constexpr unsigned short quiet_NaN() { return 0; }
|
||||
static constexpr unsigned short signaling_NaN() { return 0; }
|
||||
static constexpr unsigned short denorm_min() { return 0; }
|
||||
static constexpr unsigned short min() { return USHORT_MIN; } //!< \returns the minimum finite value of unsigned short
|
||||
static constexpr unsigned short max() { return USHORT_MAX; } //!< \returns the maximum finite value of unsigned short
|
||||
static constexpr unsigned short lowest() { return 1; } //!< \returns the smallest positive value of unsigned short
|
||||
static constexpr unsigned short epsilon() { return 1; } //!< \returns the difference between 1.0 and the next representable value
|
||||
static constexpr unsigned short round_error() { return 0; } //!< \returns the max rounding error of unsigned short
|
||||
static constexpr unsigned short infinity() { return 0; } //!< \returns a value of unsigned short holding a positive infinity
|
||||
static constexpr unsigned short quiet_NaN() { return 0; } //!< \returns a value of unsigned short holding a quiet NaN
|
||||
static constexpr unsigned short signaling_NaN() { return 0; } //!< \returns a value of unsigned short holding a signaling NaN
|
||||
static constexpr unsigned short denorm_min() { return 0; } //!< \returns a value of unsigned short holding the smallest positive subnormal
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
///
|
||||
/// \brief Definition for type \emph{int}.
|
||||
template<> struct numeric_limits<int>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
static constexpr bool is_specialized = true; //!< Check if the template is specialized for int
|
||||
static constexpr bool is_signed = true; //!< Check if int is signed
|
||||
static constexpr bool is_integer = true; //!< Check if int is of an integral type
|
||||
static constexpr bool is_exact = true; //!< Check if int is exact in its precision
|
||||
static constexpr bool has_infinity = false; //!< Check if int can hold a value representing infinity
|
||||
static constexpr bool has_quiet_nan = false; //!< Check if int can hold a non-signaling nan
|
||||
static constexpr bool has_signaling_nan = false; //!< Check if int can hold a signaling nan
|
||||
static constexpr bool has_denorm = false; //!< Check if int denormalizes
|
||||
static constexpr bool has_denorm_loss = false; //!< Check if int has precision loss when denormalized
|
||||
static constexpr bool is_iec559 = false; //!< Check if int represents an IEC 559 or IEEE 754
|
||||
static constexpr bool is_bounded = true; //!< Check if int represents a finite set of values
|
||||
static constexpr bool is_modulo = true; //!< Check if int can handle modulo arithmetic
|
||||
static constexpr bool tinyness_before = false; //!< Check if int checks for tinyness before rounding
|
||||
static constexpr bool traps = true; //!< Check if int can cause operations to trap
|
||||
|
||||
static constexpr int digits = INT_RADIX_DIG;
|
||||
static constexpr int digits10 = INT_DIG;
|
||||
static constexpr int max_digits10 = INT_DECIMAL_DIG;
|
||||
static constexpr int radix = INT_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
static constexpr int digits = INT_RADIX_DIG; //!< Get the base representation of the type
|
||||
static constexpr int digits10 = INT_DIG; //!< Get the number of radix digits int represents
|
||||
static constexpr int max_digits10 = INT_DECIMAL_DIG; //!< Get the number of decimal digits int represents
|
||||
static constexpr int radix = INT_RADIX; //!< Get the maximum number of decimal digits int represents
|
||||
static constexpr int min_exponent = 0; //!< Get the minimum number of radix digits that represent the exponent of int
|
||||
static constexpr int min_exponent10 = 0; //!< Get the minimum number of decimal digits that represent the exponent of int
|
||||
static constexpr int max_exponent = 0; //!< Get the maximum number of radix digits that represent the exponent of int
|
||||
static constexpr int max_exponent10 = 0; //!< Get the maximum number of decimal digits that represent the exponent of int
|
||||
|
||||
static constexpr int min() { return INT_MIN; }
|
||||
static constexpr int max() { return INT_MAX; }
|
||||
static constexpr int lowest() { return 1; }
|
||||
static constexpr int epsilon() { return 1; }
|
||||
static constexpr int round_error() { return 0; }
|
||||
static constexpr int infinity() { return 0; }
|
||||
static constexpr int quiet_NaN() { return 0; }
|
||||
static constexpr int signaling_NaN() { return 0; }
|
||||
static constexpr int denorm_min() { return 0; }
|
||||
static constexpr int min() { return INT_MIN; } //!< \returns the minimum finite value of int
|
||||
static constexpr int max() { return INT_MAX; } //!< \returns the maximum finite value of int
|
||||
static constexpr int lowest() { return 1; } //!< \returns the smallest positive value of int
|
||||
static constexpr int epsilon() { return 1; } //!< \returns the difference between 1.0 and the next representable value
|
||||
static constexpr int round_error() { return 0; } //!< \returns the max rounding error of int
|
||||
static constexpr int infinity() { return 0; } //!< \returns a value of int holding a positive infinity
|
||||
static constexpr int quiet_NaN() { return 0; } //!< \returns a value of int holding a quiet NaN
|
||||
static constexpr int signaling_NaN() { return 0; } //!< \returns a value of int holding a signaling NaN
|
||||
static constexpr int denorm_min() { return 0; } //!< \returns a value of int holding the smallest positive subnormal
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
///
|
||||
/// \brief Definition for type \emph{unsigned int}.
|
||||
template<> struct numeric_limits<unsigned int>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = false;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
static constexpr bool is_specialized = true; //!< Check if the template is specialized for unsigned int
|
||||
static constexpr bool is_signed = false; //!< Check if unsigned int is signed
|
||||
static constexpr bool is_integer = true; //!< Check if unsigned int is of an integral type
|
||||
static constexpr bool is_exact = true; //!< Check if unsigned int is exact in its precision
|
||||
static constexpr bool has_infinity = false; //!< Check if unsigned int can hold a value representing infinity
|
||||
static constexpr bool has_quiet_nan = false; //!< Check if unsigned int can hold a non-signaling nan
|
||||
static constexpr bool has_signaling_nan = false; //!< Check if unsigned int can hold a signaling nan
|
||||
static constexpr bool has_denorm = false; //!< Check if unsigned int denormalizes
|
||||
static constexpr bool has_denorm_loss = false; //!< Check if unsigned int has precision loss when denormalized
|
||||
static constexpr bool is_iec559 = false; //!< Check if unsigned int represents an IEC 559 or IEEE 754
|
||||
static constexpr bool is_bounded = true; //!< Check if unsigned int represents a finite set of values
|
||||
static constexpr bool is_modulo = true; //!< Check if unsigned int can handle modulo arithmetic
|
||||
static constexpr bool tinyness_before = false; //!< Check if unsigned int checks for tinyness before rounding
|
||||
static constexpr bool traps = true; //!< Check if unsigned int can cause operations to trap
|
||||
|
||||
static constexpr int digits = UINT_RADIX_DIG;
|
||||
static constexpr int digits10 = UINT_DIG;
|
||||
static constexpr int max_digits10 = UINT_DECIMAL_DIG;
|
||||
static constexpr int radix = UINT_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
static constexpr int digits = UINT_RADIX_DIG; //!< Get the base representation of the type
|
||||
static constexpr int digits10 = UINT_DIG; //!< Get the number of radix digits unsigned int represents
|
||||
static constexpr int max_digits10 = UINT_DECIMAL_DIG; //!< Get the number of decimal digits unsigned int represents
|
||||
static constexpr int radix = UINT_RADIX; //!< Get the maximum number of decimal digits unsigned int represents
|
||||
static constexpr int min_exponent = 0; //!< Get the minimum number of radix digits that represent the exponent of unsigned int
|
||||
static constexpr int min_exponent10 = 0; //!< Get the minimum number of decimal digits that represent the exponent of unsigned int
|
||||
static constexpr int max_exponent = 0; //!< Get the maximum number of radix digits that represent the exponent of unsigned int
|
||||
static constexpr int max_exponent10 = 0; //!< Get the maximum number of decimal digits that represent the exponent of unsigned int
|
||||
|
||||
static constexpr unsigned int min() { return UINT_MIN; }
|
||||
static constexpr unsigned int max() { return UINT_MAX; }
|
||||
static constexpr unsigned int lowest() { return 1; }
|
||||
static constexpr unsigned int epsilon() { return 1; }
|
||||
static constexpr unsigned int round_error() { return 0; }
|
||||
static constexpr unsigned int infinity() { return 0; }
|
||||
static constexpr unsigned int quiet_NaN() { return 0; }
|
||||
static constexpr unsigned int signaling_NaN() { return 0; }
|
||||
static constexpr unsigned int denorm_min() { return 0; }
|
||||
static constexpr unsigned int min() { return UINT_MIN; } //!< \returns the minimum finite value of unsigned int
|
||||
static constexpr unsigned int max() { return UINT_MAX; } //!< \returns the maximum finite value of unsigned int
|
||||
static constexpr unsigned int lowest() { return 1; } //!< \returns the smallest positive value of unsigned int
|
||||
static constexpr unsigned int epsilon() { return 1; } //!< \returns the difference between 1.0 and the next representable value
|
||||
static constexpr unsigned int round_error() { return 0; } //!< \returns the max rounding error of unsigned int
|
||||
static constexpr unsigned int infinity() { return 0; } //!< \returns a value of unsigned int holding a positive infinity
|
||||
static constexpr unsigned int quiet_NaN() { return 0; } //!< \returns a value of unsigned int holding a quiet NaN
|
||||
static constexpr unsigned int signaling_NaN() { return 0; } //!< \returns a value of unsigned int holding a signaling NaN
|
||||
static constexpr unsigned int denorm_min() { return 0; } //!< \returns a value of unsigned int holding the smallest positive subnormal
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
///
|
||||
/// \brief Definition for type \emph{long int}.
|
||||
template<> struct numeric_limits<long int>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
static constexpr bool is_specialized = true; //!< Check if the template is specialized for long int
|
||||
static constexpr bool is_signed = true; //!< Check if long int is signed
|
||||
static constexpr bool is_integer = true; //!< Check if long int is of an integral type
|
||||
static constexpr bool is_exact = true; //!< Check if long int is exact in its precision
|
||||
static constexpr bool has_infinity = false; //!< Check if long int can hold a value representing infinity
|
||||
static constexpr bool has_quiet_nan = false; //!< Check if long int can hold a non-signaling nan
|
||||
static constexpr bool has_signaling_nan = false; //!< Check if long int can hold a signaling nan
|
||||
static constexpr bool has_denorm = false; //!< Check if long int denormalizes
|
||||
static constexpr bool has_denorm_loss = false; //!< Check if long int has precision loss when denormalized
|
||||
static constexpr bool is_iec559 = false; //!< Check if long int represents an IEC 559 or IEEE 754
|
||||
static constexpr bool is_bounded = true; //!< Check if long int represents a finite set of values
|
||||
static constexpr bool is_modulo = true; //!< Check if long int can handle modulo arithmetic
|
||||
static constexpr bool tinyness_before = false; //!< Check if long int checks for tinyness before rounding
|
||||
static constexpr bool traps = true; //!< Check if long int can cause operations to trap
|
||||
|
||||
static constexpr int digits = LONG_RADIX_DIG;
|
||||
static constexpr int digits10 = LONG_DIG;
|
||||
static constexpr int max_digits10 = LONG_DECIMAL_DIG;
|
||||
static constexpr int radix = LONG_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
static constexpr int digits = LONG_RADIX_DIG; //!< Get the base representation of the type
|
||||
static constexpr int digits10 = LONG_DIG; //!< Get the number of radix digits long int represents
|
||||
static constexpr int max_digits10 = LONG_DECIMAL_DIG; //!< Get the number of decimal digits long int represents
|
||||
static constexpr int radix = LONG_RADIX; //!< Get the maximum number of decimal digits long int represents
|
||||
static constexpr int min_exponent = 0; //!< Get the minimum number of radix digits that represent the exponent of long int
|
||||
static constexpr int min_exponent10 = 0; //!< Get the minimum number of decimal digits that represent the exponent of long int
|
||||
static constexpr int max_exponent = 0; //!< Get the maximum number of radix digits that represent the exponent of long int
|
||||
static constexpr int max_exponent10 = 0; //!< Get the maximum number of decimal digits that represent the exponent of long int
|
||||
|
||||
static constexpr long int min() { return LONG_MIN; }
|
||||
static constexpr long int max() { return LONG_MAX; }
|
||||
static constexpr long int lowest() { return 1; }
|
||||
static constexpr long int epsilon() { return 1; }
|
||||
static constexpr long int round_error() { return 0; }
|
||||
static constexpr long int infinity() { return 0; }
|
||||
static constexpr long int quiet_NaN() { return 0; }
|
||||
static constexpr long int signaling_NaN() { return 0; }
|
||||
static constexpr long int denorm_min() { return 0; }
|
||||
static constexpr long int min() { return LONG_MIN; } //!< \returns the minimum finite value of long int
|
||||
static constexpr long int max() { return LONG_MAX; } //!< \returns the maximum finite value of long int
|
||||
static constexpr long int lowest() { return 1; } //!< \returns the smallest positive value of long int
|
||||
static constexpr long int epsilon() { return 1; } //!< \returns the difference between 1.0 and the next representable value
|
||||
static constexpr long int round_error() { return 0; } //!< \returns the max rounding error of long int
|
||||
static constexpr long int infinity() { return 0; } //!< \returns a value of long int holding a positive infinity
|
||||
static constexpr long int quiet_NaN() { return 0; } //!< \returns a value of long int holding a quiet NaN
|
||||
static constexpr long int signaling_NaN() { return 0; } //!< \returns a value of long int holding a signaling NaN
|
||||
static constexpr long int denorm_min() { return 0; } //!< \returns a value of long int holding the smallest positive subnormal
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
///
|
||||
/// \brief Definition for type \emph{unsigned long int}.
|
||||
template<> struct numeric_limits<unsigned long int>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = false;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
static constexpr bool is_specialized = true; //!< Check if the template is specialized for unsigned long int
|
||||
static constexpr bool is_signed = false; //!< Check if unsigned long int is signed
|
||||
static constexpr bool is_integer = true; //!< Check if unsigned long int is of an integral type
|
||||
static constexpr bool is_exact = true; //!< Check if unsigned long int is exact in its precision
|
||||
static constexpr bool has_infinity = false; //!< Check if unsigned long int can hold a value representing infinity
|
||||
static constexpr bool has_quiet_nan = false; //!< Check if unsigned long int can hold a non-signaling nan
|
||||
static constexpr bool has_signaling_nan = false; //!< Check if unsigned long int can hold a signaling nan
|
||||
static constexpr bool has_denorm = false; //!< Check if unsigned long int denormalizes
|
||||
static constexpr bool has_denorm_loss = false; //!< Check if unsigned long int has precision loss when denormalized
|
||||
static constexpr bool is_iec559 = false; //!< Check if unsigned long int represents an IEC 559 or IEEE 754
|
||||
static constexpr bool is_bounded = true; //!< Check if unsigned long int represents a finite set of values
|
||||
static constexpr bool is_modulo = true; //!< Check if unsigned long int can handle modulo arithmetic
|
||||
static constexpr bool tinyness_before = false; //!< Check if unsigned long int checks for tinyness before rounding
|
||||
static constexpr bool traps = true; //!< Check if unsigned long int can cause operations to trap
|
||||
|
||||
static constexpr int digits = ULONG_RADIX_DIG;
|
||||
static constexpr int digits10 = ULONG_DIG;
|
||||
static constexpr int max_digits10 = ULONG_DECIMAL_DIG;
|
||||
static constexpr int radix = ULONG_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
static constexpr int digits = ULONG_RADIX_DIG; //!< Get the base representation of the type
|
||||
static constexpr int digits10 = ULONG_DIG; //!< Get the number of radix digits unsigned long int represents
|
||||
static constexpr int max_digits10 = ULONG_DECIMAL_DIG; //!< Get the number of decimal digits unsigned long int represents
|
||||
static constexpr int radix = ULONG_RADIX; //!< Get the maximum number of decimal digits unsigned long int represents
|
||||
static constexpr int min_exponent = 0; //!< Get the minimum number of radix digits that represent the exponent of unsigned long int
|
||||
static constexpr int min_exponent10 = 0; //!< Get the minimum number of decimal digits that represent the exponent of unsigned long int
|
||||
static constexpr int max_exponent = 0; //!< Get the maximum number of radix digits that represent the exponent of unsigned long int
|
||||
static constexpr int max_exponent10 = 0; //!< Get the maximum number of decimal digits that represent the exponent of unsigned long int
|
||||
|
||||
static constexpr unsigned long min() { return ULONG_MIN; }
|
||||
static constexpr unsigned long max() { return ULONG_MAX; }
|
||||
static constexpr unsigned long lowest() { return 1; }
|
||||
static constexpr unsigned long epsilon() { return 1; }
|
||||
static constexpr unsigned long round_error() { return 0; }
|
||||
static constexpr unsigned long infinity() { return 0; }
|
||||
static constexpr unsigned long quiet_NaN() { return 0; }
|
||||
static constexpr unsigned long signaling_NaN() { return 0; }
|
||||
static constexpr unsigned long denorm_min() { return 0; }
|
||||
static constexpr unsigned long min() { return ULONG_MIN; } //!< \returns the minimum finite value of unsigned long int
|
||||
static constexpr unsigned long max() { return ULONG_MAX; } //!< \returns the maximum finite value of unsigned long int
|
||||
static constexpr unsigned long lowest() { return 1; } //!< \returns the smallest positive value of unsigned long int
|
||||
static constexpr unsigned long epsilon() { return 1; } //!< \returns the difference between 1.0 and the next representable value
|
||||
static constexpr unsigned long round_error() { return 0; } //!< \returns the max rounding error of unsigned long int
|
||||
static constexpr unsigned long infinity() { return 0; } //!< \returns a value of unsigned long int holding a positive infinity
|
||||
static constexpr unsigned long quiet_NaN() { return 0; } //!< \returns a value of unsigned long int holding a quiet NaN
|
||||
static constexpr unsigned long signaling_NaN() { return 0; } //!< \returns a value of unsigned long int holding a signaling NaN
|
||||
static constexpr unsigned long denorm_min() { return 0; } //!< \returns a value of unsigned long int holding the smallest positive subnormal
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
///
|
||||
/// \brief Definition for type \emph{long long}.
|
||||
template<> struct numeric_limits<long long>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = true;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
static constexpr bool is_specialized = true; //!< Check if the template is specialized for long long
|
||||
static constexpr bool is_signed = true; //!< Check if long long is signed
|
||||
static constexpr bool is_integer = true; //!< Check if long long is of an integral type
|
||||
static constexpr bool is_exact = true; //!< Check if long long is exact in its precision
|
||||
static constexpr bool has_infinity = false; //!< Check if long long can hold a value representing infinity
|
||||
static constexpr bool has_quiet_nan = false; //!< Check if long long can hold a non-signaling nan
|
||||
static constexpr bool has_signaling_nan = false; //!< Check if long long can hold a signaling nan
|
||||
static constexpr bool has_denorm = false; //!< Check if long long denormalizes
|
||||
static constexpr bool has_denorm_loss = false; //!< Check if long long has precision loss when denormalized
|
||||
static constexpr bool is_iec559 = false; //!< Check if long long represents an IEC 559 or IEEE 754
|
||||
static constexpr bool is_bounded = true; //!< Check if long long represents a finite set of values
|
||||
static constexpr bool is_modulo = true; //!< Check if long long can handle modulo arithmetic
|
||||
static constexpr bool tinyness_before = false; //!< Check if long long checks for tinyness before rounding
|
||||
static constexpr bool traps = true; //!< Check if long long can cause operations to trap
|
||||
|
||||
static constexpr int digits = LLONG_RADIX_DIG;
|
||||
static constexpr int digits10 = LLONG_DIG;
|
||||
static constexpr int max_digits10 = LLONG_DECIMAL_DIG;
|
||||
static constexpr int radix = LLONG_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
static constexpr int digits = LLONG_RADIX_DIG; //!< Get the base representation of the type
|
||||
static constexpr int digits10 = LLONG_DIG; //!< Get the number of radix digits long long represents
|
||||
static constexpr int max_digits10 = LLONG_DECIMAL_DIG; //!< Get the number of decimal digits long long represents
|
||||
static constexpr int radix = LLONG_RADIX; //!< Get the maximum number of decimal digits long long represents
|
||||
static constexpr int min_exponent = 0; //!< Get the minimum number of radix digits that represent the exponent of long long
|
||||
static constexpr int min_exponent10 = 0; //!< Get the minimum number of decimal digits that represent the exponent of long long
|
||||
static constexpr int max_exponent = 0; //!< Get the maximum number of radix digits that represent the exponent of long long
|
||||
static constexpr int max_exponent10 = 0; //!< Get the maximum number of decimal digits that represent the exponent of long long
|
||||
|
||||
static constexpr long long min() { return LLONG_MIN; }
|
||||
static constexpr long long max() { return LLONG_MAX; }
|
||||
static constexpr long long lowest() { return 1; }
|
||||
static constexpr long long epsilon() { return 1; }
|
||||
static constexpr long long round_error() { return 0; }
|
||||
static constexpr long long infinity() { return 0; }
|
||||
static constexpr long long quiet_NaN() { return 0; }
|
||||
static constexpr long long signaling_NaN() { return 0; }
|
||||
static constexpr long long denorm_min() { return 0; }
|
||||
static constexpr long long min() { return LLONG_MIN; } //!< \returns the minimum finite value of long long
|
||||
static constexpr long long max() { return LLONG_MAX; } //!< \returns the maximum finite value of long long
|
||||
static constexpr long long lowest() { return 1; } //!< \returns the smallest positive value of long long
|
||||
static constexpr long long epsilon() { return 1; } //!< \returns the difference between 1.0 and the next representable value
|
||||
static constexpr long long round_error() { return 0; } //!< \returns the max rounding error of long long
|
||||
static constexpr long long infinity() { return 0; } //!< \returns a value of long long holding a positive infinity
|
||||
static constexpr long long quiet_NaN() { return 0; } //!< \returns a value of long long holding a quiet NaN
|
||||
static constexpr long long signaling_NaN() { return 0; } //!< \returns a value of long long holding a signaling NaN
|
||||
static constexpr long long denorm_min() { return 0; } //!< \returns a value of long long holding the smallest positive subnormal
|
||||
};
|
||||
|
||||
// Overload for the builtin signed char type
|
||||
///
|
||||
/// \brief Definition for type \emph{unsigned long long}.
|
||||
template<> struct numeric_limits<unsigned long long>
|
||||
{
|
||||
static constexpr bool is_specialized = true;
|
||||
static constexpr bool is_signed = false;
|
||||
static constexpr bool is_integer = true;
|
||||
static constexpr bool is_exact = true;
|
||||
static constexpr bool has_infinity = false;
|
||||
static constexpr bool has_quiet_nan = false;
|
||||
static constexpr bool has_signaling_nan = false;
|
||||
static constexpr bool has_denorm = false;
|
||||
static constexpr bool has_denorm_loss = false;
|
||||
static constexpr bool is_iec559 = false;
|
||||
static constexpr bool is_bounded = true;
|
||||
static constexpr bool is_modulo = true;
|
||||
static constexpr bool tinyness_before = false;
|
||||
static constexpr bool traps = true;
|
||||
static constexpr bool is_specialized = true; //!< Check if the template is specialized for unsigned long long
|
||||
static constexpr bool is_signed = false; //!< Check if unsigned long long is signed
|
||||
static constexpr bool is_integer = true; //!< Check if unsigned long long is of an integral type
|
||||
static constexpr bool is_exact = true; //!< Check if unsigned long long is exact in its precision
|
||||
static constexpr bool has_infinity = false; //!< Check if unsigned long long can hold a value representing infinity
|
||||
static constexpr bool has_quiet_nan = false; //!< Check if unsigned long long can hold a non-signaling nan
|
||||
static constexpr bool has_signaling_nan = false; //!< Check if unsigned long long can hold a signaling nan
|
||||
static constexpr bool has_denorm = false; //!< Check if unsigned long long denormalizes
|
||||
static constexpr bool has_denorm_loss = false; //!< Check if unsigned long long has precision loss when denormalized
|
||||
static constexpr bool is_iec559 = false; //!< Check if unsigned long long represents an IEC 559 or IEEE 754
|
||||
static constexpr bool is_bounded = true; //!< Check if unsigned long long represents a finite set of values
|
||||
static constexpr bool is_modulo = true; //!< Check if unsigned long long can handle modulo arithmetic
|
||||
static constexpr bool tinyness_before = false; //!< Check if unsigned long long checks for tinyness before rounding
|
||||
static constexpr bool traps = true; //!< Check if unsigned long long can cause operations to trap
|
||||
|
||||
static constexpr int digits = ULLONG_RADIX_DIG;
|
||||
static constexpr int digits10 = ULLONG_DIG;
|
||||
static constexpr int max_digits10 = ULLONG_DECIMAL_DIG;
|
||||
static constexpr int radix = ULLONG_RADIX;
|
||||
static constexpr int min_exponent = 0;
|
||||
static constexpr int min_exponent10 = 0;
|
||||
static constexpr int max_exponent = 0;
|
||||
static constexpr int max_exponent10 = 0;
|
||||
static constexpr int digits = ULLONG_RADIX_DIG; //!< Get the base representation of the type
|
||||
static constexpr int digits10 = ULLONG_DIG; //!< Get the number of radix digits unsigned long long represents
|
||||
static constexpr int max_digits10 = ULLONG_DECIMAL_DIG; //!< Get the number of decimal digits unsigned long long represents
|
||||
static constexpr int radix = ULLONG_RADIX; //!< Get the maximum number of decimal digits unsigned long long represents
|
||||
static constexpr int min_exponent = 0; //!< Get the minimum number of radix digits that represent the exponent of unsigned long long
|
||||
static constexpr int min_exponent10 = 0; //!< Get the minimum number of decimal digits that represent the exponent of unsigned long long
|
||||
static constexpr int max_exponent = 0; //!< Get the maximum number of radix digits that represent the exponent of unsigned long long
|
||||
static constexpr int max_exponent10 = 0; //!< Get the maximum number of decimal digits that represent the exponent of unsigned long long
|
||||
|
||||
static constexpr unsigned long long min() { return ULLONG_MIN; }
|
||||
static constexpr unsigned long long max() { return ULLONG_MAX; }
|
||||
static constexpr unsigned long long lowest() { return 1; }
|
||||
static constexpr unsigned long long epsilon() { return 1; }
|
||||
static constexpr unsigned long long round_error() { return 0; }
|
||||
static constexpr unsigned long long infinity() { return 0; }
|
||||
static constexpr unsigned long long quiet_NaN() { return 0; }
|
||||
static constexpr unsigned long long signaling_NaN() { return 0; }
|
||||
static constexpr unsigned long long denorm_min() { return 0; }
|
||||
static constexpr unsigned long long min() { return ULLONG_MIN; } //!< \returns the minimum finite value of unsigned long long
|
||||
static constexpr unsigned long long max() { return ULLONG_MAX; } //!< \returns the maximum finite value of unsigned long long
|
||||
static constexpr unsigned long long lowest() { return 1; } //!< \returns the smallest positive value of unsigned long long
|
||||
static constexpr unsigned long long epsilon() { return 1; } //!< \returns the difference between 1.0 and the next representable value
|
||||
static constexpr unsigned long long round_error() { return 0; } //!< \returns the max rounding error of unsigned long long
|
||||
static constexpr unsigned long long infinity() { return 0; } //!< \returns a value of unsigned long long holding a positive infinity
|
||||
static constexpr unsigned long long quiet_NaN() { return 0; } //!< \returns a value of unsigned long long holding a quiet NaN
|
||||
static constexpr unsigned long long signaling_NaN() { return 0; } //!< \returns a value of unsigned long long holding a signaling NaN
|
||||
static constexpr unsigned long long denorm_min() { return 0; } //!< \returns a value of unsigned long long holding the smallest positive subnormal
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace fennec
|
||||
///
|
||||
/// \brief metaprogramming sequence
|
||||
///
|
||||
/// \details Stores a sequence of values of type \f$ValueT\f$ as a template pack.
|
||||
/// \details Stores a sequence of values of type \emph{ValueT} as a template pack.
|
||||
/// You can access the parameter pack in another template function, i.e.
|
||||
/// \code{cpp}
|
||||
/// template<typename TypeT, TypeT...Values>
|
||||
@@ -138,7 +138,7 @@ struct integer_metasequence : metasequence<IntT, Values...>
|
||||
|
||||
|
||||
///
|
||||
/// \brief generate a fennec::integer_metasequence \f$\left[\,0\,\ldots\,N\,\right)\f$
|
||||
/// \brief generate a fennec::integer_metasequence \math{\left[\,0\,\ldots\,N\,\right)}
|
||||
///
|
||||
/// \details
|
||||
/// \tparam IntT type of the values, must satisfy `fennec::is_integral<T>`
|
||||
@@ -177,7 +177,7 @@ template<size_t...Indices> struct index_metasequence : integer_metasequence<size
|
||||
|
||||
|
||||
///
|
||||
/// \brief generate a fennec::index_metasequence \f$\left[\,0\,\ldots\,N\,\right)\f$
|
||||
/// \brief generate a fennec::index_metasequence \math{\left[\,0\,\ldots\,N\,\right)}
|
||||
///
|
||||
/// \details
|
||||
/// \tparam T type of the values, must satisfy `fennec::is_integral<T>`
|
||||
|
||||
@@ -32,12 +32,13 @@
|
||||
#define FENNEC_LANG_RANGES_H
|
||||
|
||||
#include <fennec/lang/types.h>
|
||||
#include <fennec/lang/type_traits.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$begin()\f$
|
||||
/// \brief C++ Iterator Specification \emph{begin()}
|
||||
/// \tparam ContainerT the container type
|
||||
/// \param c the container to iterate on
|
||||
/// \returns an iterator at the start of the container
|
||||
@@ -47,7 +48,7 @@ inline constexpr auto begin(ContainerT& c) noexcept(noexcept(c.begin())) -> decl
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$begin()\f$
|
||||
/// \brief C++ Iterator Specification \emph{begin()}
|
||||
/// \tparam ContainerT the container type
|
||||
/// \param c the container to iterate on
|
||||
/// \returns an iterator at the start of the container
|
||||
@@ -57,7 +58,7 @@ inline constexpr auto begin(const ContainerT& c) noexcept(noexcept(c.begin())) -
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$begin()\f$
|
||||
/// \brief C++ Iterator Specification \emph{begin()}
|
||||
/// \tparam T the element type
|
||||
/// \tparam N the bounds of the array
|
||||
/// \param arr a bounded array to iterate on
|
||||
@@ -69,7 +70,7 @@ inline constexpr T* begin(T (&arr)[N]) noexcept {
|
||||
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$end()\f$
|
||||
/// \brief C++ Iterator Specification \emph{end()}
|
||||
/// \tparam ContainerT the container type
|
||||
/// \param c the container to iterate on
|
||||
/// \returns an iterator at the end of the container
|
||||
@@ -79,7 +80,7 @@ inline constexpr auto end(ContainerT& c) noexcept(noexcept(c.end())) -> decltype
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$end()\f$
|
||||
/// \brief C++ Iterator Specification \emph{end()}
|
||||
/// \tparam ContainerT the container type
|
||||
/// \param c the container to iterate on
|
||||
/// \returns an iterator at the end of the container
|
||||
@@ -89,7 +90,7 @@ inline constexpr auto end(const ContainerT& c) noexcept(noexcept(c.end())) -> de
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \f$end()\f$
|
||||
/// \brief C++ Iterator Specification \emph{end()}
|
||||
/// \tparam T the element type
|
||||
/// \tparam N the bounds of the array
|
||||
/// \param arr a bounded array to iterate on
|
||||
@@ -99,6 +100,129 @@ inline constexpr T* end(T (&arr)[N]) noexcept {
|
||||
return arr + N;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Range for array types.
|
||||
/// \tparam TypeT The base type.
|
||||
///
|
||||
/// \note Operates on the range \emph{[first, last)}.
|
||||
template<typename TypeT>
|
||||
struct range {
|
||||
TypeT* first; //!< The first element
|
||||
TypeT* last; //!< The last element
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \emph{begin()}
|
||||
/// \returns A pointer to the start of the array
|
||||
TypeT* begin() const {
|
||||
return first;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \emph{end()}
|
||||
/// \returns A pointer to the start of the array
|
||||
TypeT* end() const {
|
||||
return last;
|
||||
}
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Range for iterators.
|
||||
/// \tparam IteratorT The iterator type.
|
||||
///
|
||||
/// \note Operates on the range \emph{[first, last)}.
|
||||
template<typename IteratorT> requires(is_iterable_v<IteratorT>)
|
||||
struct range<IteratorT> {
|
||||
IteratorT first; //!< The first element
|
||||
IteratorT last; //!< The last element
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \emph{begin()}
|
||||
/// \returns A pointer to the start of the array
|
||||
IteratorT& begin() const {
|
||||
return first;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \emph{end()}
|
||||
/// \returns A pointer to the start of the array
|
||||
IteratorT& end() const {
|
||||
return last;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// \brief Proxy Struct for fulfilling the C++ 11 Iterator Specification
|
||||
template<typename ScalarT>
|
||||
struct counter {
|
||||
ScalarT val; //!< The held value
|
||||
|
||||
///
|
||||
/// \brief Pre-Increment
|
||||
/// \returns A reference to \emph{this} after incrementing \emph{val}.
|
||||
counter& operator++() {
|
||||
++val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Post-Increment
|
||||
/// \returns A counter with the previously held value.
|
||||
counter operator++(int) {
|
||||
++val;
|
||||
return { val - 1 };
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Equality Operator
|
||||
/// \param ctr The counter to compare with
|
||||
/// \returns \math{{val}_{this} = {val}_{ctr}}
|
||||
bool operator==(const counter& ctr) const {
|
||||
return val == ctr.val;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Equality Operator
|
||||
/// \param ctr The counter to compare with
|
||||
/// \returns \math{{val}_{this} \neq {val}_{ctr}}
|
||||
bool operator!=(const counter& ctr) const {
|
||||
return val != ctr.val;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Dereference Operator
|
||||
/// \returns \emph{val}
|
||||
ScalarT operator*() const {
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// \brief Range for scalar types.
|
||||
/// \tparam ScalarT The scalar type.
|
||||
///
|
||||
/// \note Operates on the range \emph{[first, last)}.
|
||||
template<typename ScalarT> requires(is_scalar_v<ScalarT>)
|
||||
struct range<ScalarT> {
|
||||
ScalarT first; //!< The starting value
|
||||
ScalarT last; //!< The last value
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \emph{begin()}
|
||||
/// \returns A `fennec::counter` containing \emph{first}
|
||||
counter<ScalarT> begin() const {
|
||||
return { first };
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief C++ Iterator Specification \emph{begin()}
|
||||
/// \returns A `fennec::counter` containing \emph{last}
|
||||
counter<ScalarT> end() const {
|
||||
return { last };
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_LANG_RANGES_H
|
||||
@@ -1,6 +1,6 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 - 2026 Medusa Slockbower
|
||||
// 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
|
||||
@@ -16,32 +16,29 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_CORE_SYSTEM_H
|
||||
#define FENNEC_CORE_SYSTEM_H
|
||||
#include <fennec/string/string.h>
|
||||
///
|
||||
/// \file system.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_LANG_SYSTEM_H
|
||||
#define FENNEC_LANG_SYSTEM_H
|
||||
|
||||
#include <fennec/lang/detail/_stdlib.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
class system {
|
||||
public:
|
||||
using tick_f = void (*)(system*, double);
|
||||
using frame_f = void (*)(system*, size_t);
|
||||
|
||||
const string name;
|
||||
const tick_f tick;
|
||||
const frame_f frame;
|
||||
|
||||
system(const cstring& name, tick_f tick, frame_f frame)
|
||||
: name(name), tick(tick), frame(frame) {
|
||||
}
|
||||
|
||||
virtual ~system() = default;
|
||||
|
||||
virtual void init() = 0;
|
||||
virtual void shutdown() = 0;
|
||||
};
|
||||
using ::system;
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_CORE_SYSTEM_H
|
||||
#endif // FENNEC_LANG_SYSTEM_H
|
||||
@@ -102,7 +102,7 @@ template<size_t n, typename...TypesT> using nth_element_t = nth_element<n, Types
|
||||
// fennec::replace_first_element =======================================================================================
|
||||
|
||||
///
|
||||
/// \brief Take a Template with a Pack `ClassT<ArgsT...>` and replace the first \f$ArgT\f$ of `ArgsT...` with \f$SubT\f$
|
||||
/// \brief Take a Template with a Pack `ClassT<ArgsT...>` and replace the first \emph{ArgT} of \emph{ArgsT...} with \emph{SubT}
|
||||
template<typename ClassT, typename SubT> struct replace_first_element { };
|
||||
|
||||
#ifndef FENNEC_DOXYGEN
|
||||
@@ -134,7 +134,7 @@ template<typename...Ts> constexpr size_t max_element_size_v = max_element_size<T
|
||||
// fennec::find_element ================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Finds the index of \f$T\f$ in \f$Ts\f$, if \f$T\f$ is not found, results in `sizeof...(Ts)`
|
||||
/// \brief Finds the index of \emph{T} in \emph{Ts}, if \emph{T} is not found, results in `sizeof...(Ts)`
|
||||
/// \tparam T The type to find
|
||||
/// \tparam Ts The type sequence to check
|
||||
template<typename T, typename...Ts> struct find_element : detail::_find_element<0, T, Ts...> {};
|
||||
@@ -180,7 +180,7 @@ struct search_element_args<SearchT, type_sequence<ArgsT...>, TypesT...>
|
||||
// fennec::contains_element ============================================================================================
|
||||
|
||||
///
|
||||
/// \brief Checks if the type sequence `Ts...` contains \f$T\f$
|
||||
/// \brief Checks if the type sequence \emph{Ts...} contains \emph{T}
|
||||
/// \tparam T The type to find
|
||||
/// \tparam Ts The type sequence to check
|
||||
template<typename T, typename...Ts> struct contains_element : bool_constant<(is_same_v<T, Ts> or ...)> {};
|
||||
|
||||
@@ -436,7 +436,7 @@ namespace fennec
|
||||
|
||||
///
|
||||
/// \brief metaprogramming helper for determining if a function is consteval
|
||||
/// \returns \f$true\f$ if under `consteval`, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if under `consteval`, \emph{false} otherwise
|
||||
constexpr inline bool is_constant_evaluated() noexcept {
|
||||
if consteval {
|
||||
return true;
|
||||
@@ -461,7 +461,7 @@ template<typename T> struct is_void
|
||||
: detail::_is_void<remove_cvref_t<T>>{};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_void<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_void_v = is_void<T>::value;
|
||||
|
||||
@@ -478,7 +478,7 @@ template<typename T> struct is_null_pointer
|
||||
: detail::_is_null_pointer<remove_cvref_t<T>>{};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_null_pointer<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_null_pointer_v = is_null_pointer<T>::value;
|
||||
|
||||
@@ -495,7 +495,7 @@ template<typename T> struct is_bool
|
||||
: detail::_is_bool<remove_cvref_t<T>>{};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_bool<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_bool_v = is_bool<T>::value;
|
||||
|
||||
@@ -512,7 +512,7 @@ template<typename T> struct is_integral
|
||||
: detail::_is_integral<remove_cvref_t<T>> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_integral<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_integral_v = is_integral<T>::value;
|
||||
|
||||
@@ -529,7 +529,7 @@ template<typename T> struct is_floating_point
|
||||
: detail::_is_floating_point<remove_cvref_t<T>>{};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_floating_point<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_floating_point_v = is_floating_point<T> {};
|
||||
|
||||
@@ -564,7 +564,7 @@ template<typename T> struct is_array<T[]>
|
||||
#endif
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_array<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_array_v = is_array<T>::value;
|
||||
|
||||
@@ -641,7 +641,7 @@ template<typename T> struct is_pointer
|
||||
: detail::_is_pointer<remove_cvref_t<T>>{};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_pointer<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_pointer_v = is_pointer<T> {};
|
||||
|
||||
@@ -652,13 +652,13 @@ template<typename T> constexpr bool_t is_pointer_v = is_pointer<T> {};
|
||||
///
|
||||
/// \brief Check if \p T is of a floating point type
|
||||
///
|
||||
/// \details Checks if type \f$T\f$ is a floating point type and store it in `is_same::value`.
|
||||
/// \details Checks if type \emph{T} is a floating point type and store it in `is_same::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_lvalue_reference
|
||||
: detail::_is_lvalue_reference<T>{};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_floating_point<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_lvalue_reference_v = is_lvalue_reference<T> {};
|
||||
|
||||
@@ -669,13 +669,13 @@ template<typename T> constexpr bool_t is_lvalue_reference_v = is_lvalue_referenc
|
||||
///
|
||||
/// \brief Check if \p T is of a floating point type
|
||||
///
|
||||
/// \details Checks if type \f$T\f$ is a floating point type and store it in `is_same::value`.
|
||||
/// \details Checks if type \emph{T} is a floating point type and store it in `is_same::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_rvalue_reference
|
||||
: detail::_is_rvalue_reference<T>{};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_floating_point<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_rvalue_reference_v = is_rvalue_reference<T> {};
|
||||
|
||||
@@ -686,13 +686,13 @@ template<typename T> constexpr bool_t is_rvalue_reference_v = is_rvalue_referenc
|
||||
///
|
||||
/// \brief Check if \p T is a pointer to a member function
|
||||
///
|
||||
/// \details Checks if type \f$T\f$ is pointer to a member function and store it in `is_member_function_pointer::value`.
|
||||
/// \details Checks if type \emph{T} is pointer to a member function and store it in `is_member_function_pointer::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_member_function_pointer
|
||||
: bool_constant<FENNEC_BUILTIN_IS_MEMBER_FUNCTION_POINTER(T)> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_member_function_pointer<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_member_function_pointer_v = is_member_function_pointer<T> {};
|
||||
|
||||
@@ -703,13 +703,13 @@ template<typename T> constexpr bool_t is_member_function_pointer_v = is_member_f
|
||||
///
|
||||
/// \brief Check if \p T is a pointer to a member object
|
||||
///
|
||||
/// \details Checks if type \f$T\f$ is pointer to a member object and store it in `is_member_object_pointer::value`.
|
||||
/// \details Checks if type \emph{T} is pointer to a member object and store it in `is_member_object_pointer::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_member_object_pointer
|
||||
: bool_constant<FENNEC_BUILTIN_IS_MEMBER_OBJECT_POINTER(T)> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_member_object_pointer<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_member_object_pointer_v = is_member_object_pointer<T> {};
|
||||
|
||||
@@ -725,13 +725,13 @@ template<typename T> constexpr bool_t is_member_object_pointer_v = is_member_obj
|
||||
///
|
||||
/// \brief Check if \p T is an arithmetic type
|
||||
///
|
||||
/// \details Checks if type \f$T\f$ is a built-in type with arithmetic operators and store it in `is_same::value`.
|
||||
/// \details Checks if type \emph{T} is a built-in type with arithmetic operators and store it in `is_same::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_arithmetic
|
||||
: bool_constant<is_integral_v<T> or is_floating_point_v<T>>{};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_arithmetic<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_arithmetic_v = is_arithmetic<T>::value;
|
||||
|
||||
@@ -745,7 +745,7 @@ template<typename T> struct is_fundamental
|
||||
: bool_constant<is_arithmetic_v<T> or is_void_v<T> or is_null_pointer_v<T>>{};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_fundamental<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_fundamental_v = is_fundamental<T>::value;
|
||||
|
||||
@@ -756,13 +756,13 @@ template<typename T> constexpr bool_t is_fundamental_v = is_fundamental<T>::valu
|
||||
///
|
||||
/// \brief Check if \p T is an arithmetic type
|
||||
///
|
||||
/// \details Checks if type \f$T\f$ is a built-in type with arithmetic operators and store it in `is_scalar::value`.
|
||||
/// \details Checks if type \emph{T} is a built-in type with arithmetic operators and store it in `is_scalar::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_scalar
|
||||
: bool_constant<is_arithmetic_v<T> or is_enum_v<T> or is_pointer_v<T>>{};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_scalar<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_scalar_v = is_scalar<T>::value;
|
||||
|
||||
@@ -773,12 +773,12 @@ template<typename T> constexpr bool_t is_scalar_v = is_scalar<T>::value;
|
||||
///
|
||||
/// \brief Check if \p T is an object
|
||||
///
|
||||
/// \details Checks if type \f$T\f$ is an object and store it in `is_object::value`.
|
||||
/// \details Checks if type \emph{T} is an object and store it in `is_object::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_object : bool_constant<FENNEC_BUILTIN_IS_OBJECT(T)> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_object<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_object_v = is_object<T>::value;
|
||||
|
||||
@@ -789,12 +789,12 @@ template<typename T> constexpr bool_t is_object_v = is_object<T>::value;
|
||||
///
|
||||
/// \brief Check if \p T is a object compound type
|
||||
///
|
||||
/// \details Checks if type \f$T\f$ is an object and store it in `is_compound::value`.
|
||||
/// \details Checks if type \emph{T} is an object and store it in `is_compound::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_compound : bool_constant<not is_fundamental_v<T>> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_compound<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_compound_v = is_compound<T>::value;
|
||||
|
||||
@@ -805,13 +805,13 @@ template<typename T> constexpr bool_t is_compound_v = is_compound<T>::value;
|
||||
///
|
||||
/// \brief Check if \p T is of a reference type
|
||||
///
|
||||
/// \details Checks if type \f$T\f$ is a reference type and store it in `is_reference::value`.
|
||||
/// \details Checks if type \emph{T} is a reference type and store it in `is_reference::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_reference
|
||||
: detail::_is_reference<T>{};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_reference<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_reference_v = is_reference<T> {};
|
||||
|
||||
@@ -822,13 +822,13 @@ template<typename T> constexpr bool_t is_reference_v = is_reference<T> {};
|
||||
///
|
||||
/// \brief Check if \p T is a pointer to a member
|
||||
///
|
||||
/// \details Checks if type \f$T\f$ is pointer to a member and store it in `is_member_function_pointer::value`.
|
||||
/// \details Checks if type \emph{T} is pointer to a member and store it in `is_member_function_pointer::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_member_pointer
|
||||
: bool_constant<FENNEC_BUILTIN_IS_MEMBER_POINTER(T)> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_member_function_pointer<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_member_pointer_v = is_member_pointer<T> {};
|
||||
|
||||
@@ -844,13 +844,13 @@ template<typename T> constexpr bool_t is_member_pointer_v = is_member_pointer<T>
|
||||
///
|
||||
/// \brief Check if \p T is of a const type
|
||||
///
|
||||
/// \details Checks if type \f$T\f$ is a const type and store it in `is_same::value`.
|
||||
/// \details Checks if type \emph{T} is a const type and store it in `is_same::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_const
|
||||
: detail::_is_const<T>{};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_const<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_const_v = is_const<T> {};
|
||||
|
||||
@@ -861,13 +861,13 @@ template<typename T> constexpr bool_t is_const_v = is_const<T> {};
|
||||
///
|
||||
/// \brief Check if \p T is of a volatile type
|
||||
///
|
||||
/// \details Checks if type \f$T\f$ is a volatile type and store it in `is_same::value`.
|
||||
/// \details Checks if type \emph{T} is a volatile type and store it in `is_same::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_volatile
|
||||
: detail::_is_volatile<T>{};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_volatile<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_volatile_v = is_volatile<T> {};
|
||||
|
||||
@@ -876,9 +876,9 @@ template<typename T> constexpr bool_t is_volatile_v = is_volatile<T> {};
|
||||
// fennec::is_trivial --------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if type \f$T\f$ is trivial
|
||||
/// \brief Check if type \emph{T} is trivial
|
||||
///
|
||||
/// \details Checks if \f$T\f$
|
||||
/// \details Checks if \emph{T}
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_trivial : bool_constant<FENNEC_BUILTIN_IS_TRIVIAL(T)> {};
|
||||
|
||||
@@ -892,9 +892,9 @@ template<typename T> constexpr bool_t is_trivial_v = is_trivial<T>{};
|
||||
// fennec::is_trivially_copyable ---------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if type \f$T\f$ is trivially_copyable
|
||||
/// \brief Check if type \emph{T} is trivially_copyable
|
||||
///
|
||||
/// \details Checks if \f$T\f$
|
||||
/// \details Checks if \emph{T}
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_trivially_copyable : bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_COPYABLE(T)> {};
|
||||
|
||||
@@ -908,9 +908,9 @@ template<typename T> constexpr bool_t is_trivially_copyable_v = is_trivially_cop
|
||||
// fennec::is_standard_layout ------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if type \f$T\f$ is standard_layout
|
||||
/// \brief Check if type \emph{T} is standard_layout
|
||||
///
|
||||
/// \details Checks if \f$T\f$
|
||||
/// \details Checks if \emph{T}
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_standard_layout : bool_constant<FENNEC_BUILTIN_IS_STANDARD_LAYOUT(T)> {};
|
||||
|
||||
@@ -924,9 +924,9 @@ template<typename T> constexpr bool_t is_standard_layout_v = is_standard_layout<
|
||||
// fennec::has_unique_object_representations ---------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if type \f$T\f$ has unique object representations
|
||||
/// \brief Check if type \emph{T} has unique object representations
|
||||
///
|
||||
/// \details Checks if \f$T\f$
|
||||
/// \details Checks if \emph{T}
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct has_unique_object_representations
|
||||
: bool_constant<FENNEC_BUILTIN_HAS_UNIQUE_OBJECT_REPRESENTATIONS(remove_cv_t<T>)> {};
|
||||
@@ -941,9 +941,9 @@ template<typename T> constexpr bool_t has_unique_object_representations_v = has_
|
||||
// fennec::is_empty ----------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if type \f$T\f$ is empty
|
||||
/// \brief Check if type \emph{T} is empty
|
||||
///
|
||||
/// \details Checks if \f$T\f$
|
||||
/// \details Checks if \emph{T}
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_empty : bool_constant<FENNEC_BUILTIN_IS_EMPTY(T)> {};
|
||||
|
||||
@@ -957,9 +957,9 @@ template<typename T> constexpr bool_t is_empty_v = is_empty<T>{};
|
||||
// fennec::is_polymorphic ----------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if type \f$T\f$ is polymorphic
|
||||
/// \brief Check if type \emph{T} is polymorphic
|
||||
///
|
||||
/// \details Checks if \f$T\f$
|
||||
/// \details Checks if \emph{T}
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_polymorphic : bool_constant<FENNEC_BUILTIN_IS_POLYMORPHIC(T)> {};
|
||||
|
||||
@@ -973,9 +973,9 @@ template<typename T> constexpr bool_t is_polymorphic_v = is_polymorphic<T>{};
|
||||
// fennec::is_abstract -------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if type \f$T\f$ is abstract
|
||||
/// \brief Check if type \emph{T} is abstract
|
||||
///
|
||||
/// \details Checks if \f$T\f$
|
||||
/// \details Checks if \emph{T}
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_abstract : bool_constant<FENNEC_BUILTIN_IS_ABSTRACT(T)> {};
|
||||
|
||||
@@ -989,9 +989,9 @@ template<typename T> constexpr bool_t is_abstract_v = is_abstract<T>{};
|
||||
// fennec::is_complete -------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if type \f$T\f$ is complete
|
||||
/// \brief Check if type \emph{T} is complete
|
||||
///
|
||||
/// \details Checks if \f$T\f$
|
||||
/// \details Checks if \emph{T}
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_complete : detail::_is_complete<T>::type {};
|
||||
|
||||
@@ -1005,9 +1005,9 @@ template<typename T> constexpr bool_t is_complete_v = is_complete<T>{};
|
||||
// fennec::is_final -------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if type \f$T\f$ is final
|
||||
/// \brief Check if type \emph{T} is final
|
||||
///
|
||||
/// \details Checks if \f$T\f$
|
||||
/// \details Checks if \emph{T}
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_final : bool_constant<FENNEC_BUILTIN_IS_FINAL(T)> {};
|
||||
|
||||
@@ -1021,9 +1021,9 @@ template<typename T> constexpr bool_t is_final_v = is_final<T>{};
|
||||
// fennec::is_aggregate -------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if type \f$T\f$ is aggregate
|
||||
/// \brief Check if type \emph{T} is aggregate
|
||||
///
|
||||
/// \details Checks if \f$T\f$
|
||||
/// \details Checks if \emph{T}
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_aggregate : bool_constant<FENNEC_BUILTIN_IS_AGGREGATE(T)> {};
|
||||
|
||||
@@ -1040,13 +1040,13 @@ template<typename T> constexpr bool_t is_aggregate_v = is_aggregate<T>{};
|
||||
///
|
||||
/// \brief Check if \p T is of a signed integral
|
||||
///
|
||||
/// \details Checks if type \f$T\f$ is a signed type i.e. `T(-1) < T(0)` and stores it in `is_same::value`.
|
||||
/// \details Checks if type \emph{T} is a signed type i.e. \math{\textbf{T(-1)} < \textbf{T(0)}} and stores it in `is_same::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_signed
|
||||
: detail::_is_signed<remove_cvref_t<T>> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_signed<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_signed_v = is_signed<T>::value;
|
||||
|
||||
@@ -1058,13 +1058,13 @@ template<typename T> constexpr bool_t is_signed_v = is_signed<T>::value;
|
||||
///
|
||||
/// \brief Check if \p T is of an unsigned integral
|
||||
///
|
||||
/// \details Checks if type \f$T\f$ is an unsigned type i.e. `T(-1) > T(0)` and stores it in `is_same::value`.
|
||||
/// \details Checks if type \emph{T} is an unsigned type i.e. \math{\textbf{T(-1)} > \textbf{T(0)}} and stores it in `is_same::value`.
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_unsigned
|
||||
: detail::_is_unsigned<remove_cvref_t<T>> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_unsigned<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_unsigned_v = is_unsigned<T>::value;
|
||||
|
||||
@@ -1072,16 +1072,6 @@ template<typename T> struct is_unsigned
|
||||
|
||||
// fennec::is_bounded_array --------------------------------------------------------------------------------------------
|
||||
|
||||
#if FENNEC_HAS_BUILTIN_BOUNDED_ARRAY
|
||||
|
||||
///
|
||||
/// \brief Check if \p T is of a bounded array type
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_bounded_array
|
||||
: bool_constant<FENNEC_BUILTIN_IS_BOUNDED_ARRAY(T)> {};
|
||||
|
||||
#else
|
||||
|
||||
///
|
||||
/// \brief Check if \p T is of an bounded type
|
||||
/// \tparam T type to check
|
||||
@@ -1092,10 +1082,8 @@ template<typename T> struct is_bounded_array
|
||||
template<typename T, size_t N> struct is_bounded_array<T[N]>
|
||||
: true_type {};
|
||||
|
||||
#endif
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_bounded_array<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_bounded_array_v = is_bounded_array<T>::value;
|
||||
|
||||
@@ -1103,16 +1091,6 @@ template<typename T> constexpr bool_t is_bounded_array_v = is_bounded_array<T>::
|
||||
|
||||
// fennec::is_unbounded_array ------------------------------------------------------------------------------------------
|
||||
|
||||
#if FENNEC_HAS_BUILTIN_UNBOUNDED_ARRAY
|
||||
|
||||
///
|
||||
/// \brief Check if \p T is of a unbounded array type
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_unbounded_array
|
||||
: bool_constant<FENNEC_BUILTIN_IS_UNBOUNDED_ARRAY(T)> {};
|
||||
|
||||
#else
|
||||
|
||||
///
|
||||
/// \brief Check if \p T is of an unbounded type
|
||||
/// \tparam T type to check
|
||||
@@ -1123,10 +1101,8 @@ template<typename T> struct is_unbounded_array
|
||||
template<typename T> struct is_unbounded_array<T[]>
|
||||
: true_type {};
|
||||
|
||||
#endif
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_unbounded_array<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_unbounded_array_v = is_unbounded_array<T>::value;
|
||||
|
||||
@@ -1163,7 +1139,7 @@ struct is_scoped_enum<T>
|
||||
#endif
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_scoped_enum<T>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_scoped_enum_v = is_scoped_enum<T>::value;
|
||||
|
||||
@@ -1177,9 +1153,9 @@ template<typename T> constexpr bool_t is_scoped_enum_v = is_scoped_enum<T>::valu
|
||||
// fennec::is_convertible ----------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if type \f$T0\f$ can be converted \f$T1\f$
|
||||
/// \brief Check if type \emph{T0} can be converted \emph{T1}
|
||||
///
|
||||
/// \details Checks if \f$TypeT0\f$
|
||||
/// \details Checks if \emph{TypeT0}
|
||||
/// \tparam FromT First type
|
||||
/// \tparam ToT Second type
|
||||
template<typename FromT, typename ToT> struct is_convertible
|
||||
@@ -1196,8 +1172,8 @@ template<typename FromT, typename ToT> constexpr bool_t is_convertible_v = is_co
|
||||
// fennec::is_constructible --------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ can be constructed with `ArgsT,` i.e. `ClassT(ArgsT...)`.
|
||||
/// This may be read as "is \f$ClassT\f$ constructible with \f$ArgsT\f$"
|
||||
/// \brief Check if \emph{ClassT} can be constructed with \emph{ArgsT...}, i.e. `ClassT(ArgsT...)`.
|
||||
/// This may be read as "is \emph{ClassT} constructible with \emph{ArgsT}"
|
||||
/// \tparam ClassT The class type to test
|
||||
/// \tparam ArgsT The arguments for the specific constructor
|
||||
template<typename ClassT, typename...ArgsT> struct is_constructible
|
||||
@@ -1212,7 +1188,7 @@ template<typename ClassT, typename...ArgsT> constexpr bool_t is_constructible_v
|
||||
// fennec::is_trivially_constructible ----------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is trivially constructible
|
||||
/// \brief Check if \emph{ClassT} is trivially constructible
|
||||
/// \tparam ClassT The class type to test
|
||||
/// \tparam ArgsT The arguments for the specific constructor
|
||||
template<typename ClassT, typename...ArgsT> struct is_trivially_constructible
|
||||
@@ -1227,7 +1203,7 @@ template<typename ClassT> constexpr bool_t is_trivially_constructible_v = is_tri
|
||||
// fennec::is_nothrow_constructible ------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is nothrow constructible
|
||||
/// \brief Check if \emph{ClassT} is nothrow constructible
|
||||
/// \tparam ClassT The class type to test
|
||||
/// \tparam ArgsT The arguments for the specific constructor
|
||||
template<typename ClassT, typename...ArgsT> struct is_nothrow_constructible
|
||||
@@ -1242,7 +1218,7 @@ template<typename ClassT> constexpr bool_t is_nothrow_constructible_v = is_nothr
|
||||
// fennec::is_default_constructible ------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is default constructible
|
||||
/// \brief Check if \emph{ClassT} is default constructible
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_default_constructible
|
||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT)> {};
|
||||
@@ -1256,7 +1232,7 @@ template<typename ClassT> constexpr bool_t is_default_constructible_v = is_defau
|
||||
// fennec::is_trivially_default_constructible --------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is trivially default constructible
|
||||
/// \brief Check if \emph{ClassT} is trivially default constructible
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_trivially_default_constructible
|
||||
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_CONSTRUCTIBLE(ClassT)> {};
|
||||
@@ -1270,7 +1246,7 @@ template<typename ClassT> constexpr bool_t is_trivially_default_constructible_v
|
||||
// fennec::is_nothrow_default_constructible --------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is nothrow default constructible
|
||||
/// \brief Check if \emph{ClassT} is nothrow default constructible
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_nothrow_default_constructible
|
||||
: bool_constant<FENNEC_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE(ClassT)> {};
|
||||
@@ -1284,7 +1260,7 @@ template<typename ClassT> constexpr bool_t is_nothrow_default_constructible_v =
|
||||
// fennec::is_copy_constructible ---------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is copy constructible
|
||||
/// \brief Check if \emph{ClassT} is copy constructible
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_copy_constructible
|
||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
|
||||
@@ -1298,7 +1274,7 @@ template<typename ClassT, typename...ArgsT> constexpr bool_t is_copy_constructib
|
||||
// fennec::is_trivially_copy_constructible -----------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is trivially copy constructible
|
||||
/// \brief Check if \emph{ClassT} is trivially copy constructible
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_trivially_copy_constructible
|
||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
|
||||
@@ -1312,7 +1288,7 @@ template<typename ClassT> struct is_trivially_copy_constructible
|
||||
// fennec::is_nothrow_copy_constructible -------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is nothrow copy constructible
|
||||
/// \brief Check if \emph{ClassT} is nothrow copy constructible
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_nothrow_copy_constructible
|
||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
|
||||
@@ -1326,7 +1302,7 @@ template<typename ClassT, typename...ArgsT> constexpr bool_t is_nothrow_copy_con
|
||||
// fennec::is_move_constructible ---------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is move constructible
|
||||
/// \brief Check if \emph{ClassT} is move constructible
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_move_constructible
|
||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_rvalue_reference_t<ClassT>)> {};
|
||||
@@ -1340,7 +1316,7 @@ template<typename ClassT, typename...ArgsT> constexpr bool_t is_move_constructib
|
||||
// fennec::is_trivially_move_constructible -----------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is trivially move constructible
|
||||
/// \brief Check if \emph{ClassT} is trivially move constructible
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_trivially_move_constructible
|
||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
|
||||
@@ -1354,7 +1330,7 @@ template<typename ClassT> struct is_trivially_move_constructible
|
||||
// fennec::is_nothrow_move_constructible -------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is nothrow move constructible
|
||||
/// \brief Check if \emph{ClassT} is nothrow move constructible
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_nothrow_move_constructible
|
||||
: bool_constant<FENNEC_BUILTIN_IS_CONSTRUCTIBLE(ClassT, add_lvalue_reference_t<const ClassT>)> {};
|
||||
@@ -1368,7 +1344,7 @@ template<typename ClassT, typename...ArgsT> constexpr bool_t is_nothrow_move_con
|
||||
// fennec::is_assignable -----------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is assignable
|
||||
/// \brief Check if \emph{ClassT} is assignable
|
||||
/// \tparam ClassAT The class type to test
|
||||
/// \tparam ClassBT The arguments for the specific constructor
|
||||
template<typename ClassAT, typename ClassBT> struct is_assignable
|
||||
@@ -1383,7 +1359,7 @@ template<typename ClassAT, typename ClassBT> constexpr bool_t is_assignable_v =
|
||||
// fennec::is_trivially_assignable -------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is trivially assignable
|
||||
/// \brief Check if \emph{ClassT} is trivially assignable
|
||||
/// \tparam ClassAT The class type to test
|
||||
/// \tparam ClassBT The arguments for the specific constructor
|
||||
template<typename ClassAT, typename ClassBT> struct is_trivially_assignable
|
||||
@@ -1399,7 +1375,7 @@ template<typename ClassAT, typename ClassBT> constexpr bool_t is_trivially_assig
|
||||
// fennec::is_nothrow_assignable ---------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is nothrow assignable
|
||||
/// \brief Check if \emph{ClassT} is nothrow assignable
|
||||
/// \tparam ClassAT The class type to test
|
||||
/// \tparam ClassBT The arguments for the specific constructor
|
||||
template<typename ClassAT, typename ClassBT> struct is_nothrow_assignable
|
||||
@@ -1414,7 +1390,7 @@ template<typename ClassAT, typename ClassBT> constexpr bool_t is_nothrow_assigna
|
||||
// fennec::is_copy_assignable ------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is copy assignable
|
||||
/// \brief Check if \emph{ClassT} is copy assignable
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_copy_assignable
|
||||
: bool_constant<FENNEC_BUILTIN_IS_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_lvalue_reference_t<const ClassT>)> {};
|
||||
@@ -1428,7 +1404,7 @@ template<typename ClassT> constexpr bool_t is_copy_assignable_v = is_copy_assign
|
||||
// fennec::is_trivially_copy_assignable --------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is trivially_copy assignable
|
||||
/// \brief Check if \emph{ClassT} is trivially_copy assignable
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_trivially_copy_assignable
|
||||
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_lvalue_reference_t<const ClassT>)> {};
|
||||
@@ -1442,7 +1418,7 @@ template<typename ClassT> constexpr bool_t is_trivially_copy_assignable_v = is_t
|
||||
// fennec::is_nothrow_copy_assignable ----------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is nothrow_copy assignable
|
||||
/// \brief Check if \emph{ClassT} is nothrow_copy assignable
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_nothrow_copy_assignable
|
||||
: bool_constant<FENNEC_BUILTIN_IS_NOTHROW_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_lvalue_reference_t<const ClassT>)> {};
|
||||
@@ -1456,7 +1432,7 @@ template<typename ClassT> constexpr bool_t is_nothrow_copy_assignable_v = is_not
|
||||
// fennec::is_move_assignable ------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is move assignable
|
||||
/// \brief Check if \emph{ClassT} is move assignable
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_move_assignable
|
||||
: bool_constant<FENNEC_BUILTIN_IS_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_rvalue_reference_t<ClassT>)> {};
|
||||
@@ -1470,7 +1446,7 @@ template<typename ClassT> constexpr bool_t is_move_assignable_v = is_move_assign
|
||||
// fennec::is_trivially_move_assignable --------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is trivially_move assignable
|
||||
/// \brief Check if \emph{ClassT} is trivially_move assignable
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_trivially_move_assignable
|
||||
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_rvalue_reference_t<ClassT>)> {};
|
||||
@@ -1484,7 +1460,7 @@ template<typename ClassT> constexpr bool_t is_trivially_move_assignable_v = is_t
|
||||
// fennec::is_nothrow_move_assignable --------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is nothrow_move assignable
|
||||
/// \brief Check if \emph{ClassT} is nothrow_move assignable
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_nothrow_move_assignable
|
||||
: bool_constant<FENNEC_BUILTIN_IS_NOTHROW_ASSIGNABLE(add_lvalue_reference_t<ClassT>, add_rvalue_reference_t<ClassT>)> {};
|
||||
@@ -1498,7 +1474,7 @@ template<typename ClassT> constexpr bool_t is_nothrow_move_assignable_v = is_not
|
||||
// fennec::is_destructible ---------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is destructible
|
||||
/// \brief Check if \emph{ClassT} is destructible
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_destructible
|
||||
: detail::_is_destructible<ClassT>::type {};
|
||||
@@ -1512,10 +1488,14 @@ template<typename ClassT> constexpr bool_t is_destructible_v = is_destructible<C
|
||||
// fennec::is_trivially_destructible -----------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is trivially destructible
|
||||
/// \brief Check if \emph{ClassT} is trivially destructible
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_trivially_destructible
|
||||
#if FENNEC_HAS_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE
|
||||
: bool_constant<FENNEC_BUILTIN_IS_TRIVIALLY_DESTRUCTIBLE(ClassT)> {};
|
||||
#else
|
||||
: bool_constant<FENNEC_BUILTIN_HAS_TRIVIAL_DESTRUCTOR(ClassT)> {};
|
||||
#endif
|
||||
|
||||
///
|
||||
/// \brief Shorthand for `is_trivially_destructible<ClassT, ArgsT...>::value`
|
||||
@@ -1526,7 +1506,7 @@ template<typename ClassT> constexpr bool_t is_trivially_destructible_v = is_triv
|
||||
// fennec::is_nothrow_destructible -------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$ClassT\f$ is nothrow destructible
|
||||
/// \brief Check if \emph{ClassT} is nothrow destructible
|
||||
/// \tparam ClassT The class type to test
|
||||
template<typename ClassT> struct is_nothrow_destructible
|
||||
: detail::_is_nothrow_destructible<ClassT>::type {};
|
||||
@@ -1547,7 +1527,7 @@ template<typename ClassT> constexpr bool_t is_nothrow_destructible_v = is_nothro
|
||||
///
|
||||
/// \brief Check if the two types are identical
|
||||
///
|
||||
/// \details Checks if \f$T0\f$ and \f$T1\f$ are identical and store it in `is_same::value`
|
||||
/// \details Checks if \emph{T0} and \emph{T1} are identical and store it in `is_same::value`
|
||||
/// \tparam T0 first type to check
|
||||
/// \tparam T1 second type to check
|
||||
template<typename T0, typename T1> struct is_same : false_type {};
|
||||
@@ -1556,7 +1536,7 @@ template<typename T0, typename T1> struct is_same : false_type {};
|
||||
template<typename T> struct is_same<T, T> : true_type {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_same<T0, T1>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam T0 first type to check
|
||||
/// \tparam T1 second type to check
|
||||
template<typename T0, typename T1> constexpr bool_t is_same_v = is_same<T0, T1> {};
|
||||
@@ -1566,9 +1546,9 @@ template<typename T0, typename T1> constexpr bool_t is_same_v = is_same<T0, T1>
|
||||
// fennec::is_base_of --------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if \f$Derived\f$ has a base type of \f$Base\f$
|
||||
/// \brief Check if \emph{Derived} has a base type of \emph{Base}
|
||||
///
|
||||
/// \details Checks if \f$Base\f$ is a base type of \f$Derived\f$ and stores it in `is_base_of::value`
|
||||
/// \details Checks if \emph{Base} is a base type of \emph{Derived} and stores it in `is_base_of::value`
|
||||
/// \tparam Base base type to check
|
||||
/// \tparam Derived derived type to check
|
||||
template<typename Base, typename Derived> struct is_base_of : bool_constant<
|
||||
@@ -1576,7 +1556,7 @@ template<typename Base, typename Derived> struct is_base_of : bool_constant<
|
||||
> {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for ```is_base_of<T0, T1>::value```
|
||||
/// \brief Shorthand for `(.*?)`
|
||||
/// \tparam Base base type to check
|
||||
/// \tparam Derived derived type to check
|
||||
template<typename Base, typename Derived> constexpr bool_t is_base_of_v = is_base_of<Base, Derived> {};
|
||||
@@ -1586,9 +1566,9 @@ template<typename Base, typename Derived> constexpr bool_t is_base_of_v = is_bas
|
||||
// fennec::is_iterable -------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if type \f$T\f$ is iterable
|
||||
/// \brief Check if type \emph{T} is iterable
|
||||
///
|
||||
/// \details Checks if \f$T\f$
|
||||
/// \details Checks if \emph{Base} is iterable and stores it in `is_base_of::value`
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_iterable : decltype(detail::_is_iterable<T>(0)) {};
|
||||
|
||||
@@ -1599,12 +1579,28 @@ template<typename T> constexpr bool_t is_iterable_v = is_iterable<T>{};
|
||||
|
||||
|
||||
|
||||
// fennec::is_iterator -------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if type \emph{T} is an iterator
|
||||
///
|
||||
/// \details Checks if \emph{T} is an iterator and stores it in `is_base_of::value`
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_iterator : decltype(detail::_is_iterator<T>(0)) {};
|
||||
|
||||
///
|
||||
/// \brief Shorthand for `is_iterator<TypeT0, TypeT1>::value`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool_t is_iterator_v = is_iterator<T>{};
|
||||
|
||||
|
||||
|
||||
// fennec::is_indexable ------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if type \f$T\f$ is indexable
|
||||
/// \brief Check if type \emph{T} is indexable
|
||||
///
|
||||
/// \details Checks if \f$T\f$
|
||||
/// \details Checks if \emph{T}
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_indexable : decltype(detail::_is_indexable<T>(0)) {};
|
||||
|
||||
@@ -1618,9 +1614,9 @@ template<typename T> constexpr bool_t is_indexable_v = is_indexable<T>{};
|
||||
// fennec::is_mappable -------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Check if type \f$T\f$ is mappable
|
||||
/// \brief Check if type \emph{T} is mappable
|
||||
///
|
||||
/// \details Checks if \f$T\f$
|
||||
/// \details Checks if \emph{T}
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct is_mappable : decltype(detail::_is_mappable<T>(0)) {};
|
||||
|
||||
|
||||
@@ -194,9 +194,9 @@ template<typename T> using decay_t = typename decay<T>::type;
|
||||
// Pointer Conversions =================================================================================================
|
||||
|
||||
///
|
||||
/// \brief adds a pointer level to \f$T\f$
|
||||
/// \brief adds a pointer level to \emph{T}
|
||||
///
|
||||
/// \details adds a pointer to the provided type such that \f$T\f$ becomes \f$T*\f$
|
||||
/// \details adds a pointer to the provided type such that \emph{T} becomes \emph{T*}
|
||||
/// \tparam T Resultant Type
|
||||
template<typename T> struct add_pointer : detail::_add_pointer<T>{};
|
||||
|
||||
@@ -206,9 +206,9 @@ template<typename T> using add_pointer_t = typename add_pointer<T>::type;
|
||||
|
||||
|
||||
///
|
||||
/// \brief removes a pointer level from \f$T\f$
|
||||
/// \brief removes a pointer level from \emph{T}
|
||||
///
|
||||
/// \details removes a pointer from the provided type such that \f$T*\f$ becomes \f$T\f$
|
||||
/// \details removes a pointer from the provided type such that \emph{T*} becomes \emph{T}
|
||||
/// \tparam T Resultant Type
|
||||
template<typename T> struct remove_pointer : detail::_remove_pointer<T> {};
|
||||
|
||||
@@ -218,9 +218,9 @@ template<typename T> using remove_pointer_t = typename remove_pointer<T>::type;
|
||||
|
||||
|
||||
///
|
||||
/// \brief removes all pointer levels from \f$T\f$
|
||||
/// \brief removes all pointer levels from \emph{T}
|
||||
///
|
||||
/// \details removes all pointers from the provided type such that \f$T*\f$, \f$T**\f$, etc. becomes \f$T\f$
|
||||
/// \details removes all pointers from the provided type such that \emph{T*}, \emph{T**}, etc. becomes \emph{T}
|
||||
/// \tparam T Resultant Type
|
||||
template<typename T> struct strip_pointers : conditional_t<
|
||||
detail::_is_pointer<T>::value,
|
||||
@@ -237,9 +237,9 @@ template<typename T> using strip_pointers_t = strip_pointers<T>::type;
|
||||
// Reference Conversions ===============================================================================================
|
||||
|
||||
///
|
||||
/// \brief add a reference to \f$T\f$
|
||||
/// \brief add a reference to \emph{T}
|
||||
///
|
||||
/// \details adds a pointer to the provided type such that \f$T\f$ becomes \f$T\&\f$
|
||||
/// \details adds a pointer to the provided type such that \emph{T} becomes \emph{T\&}
|
||||
/// \tparam T Resultant Type
|
||||
template<typename T> struct add_reference : type_identity<T&> {};
|
||||
|
||||
@@ -249,9 +249,9 @@ template<typename T> using add_reference_t = typename add_reference<T>::type;
|
||||
|
||||
|
||||
///
|
||||
/// \brief add a lvalue reference to \f$T\f$
|
||||
/// \brief add a lvalue reference to \emph{T}
|
||||
///
|
||||
/// \details adds a lvalue reference to the provided type such that \f$T\f$ becomes \f$T\&\f$
|
||||
/// \details adds a lvalue reference to the provided type such that \emph{T} becomes \emph{T\&}
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct add_lvalue_reference : detail::_add_lvalue_reference<T> {};
|
||||
|
||||
@@ -261,9 +261,9 @@ template<typename T> using add_lvalue_reference_t = typename add_lvalue_referen
|
||||
|
||||
|
||||
///
|
||||
/// \brief add a rvalue reference to \f$T\f$
|
||||
/// \brief add a rvalue reference to \emph{T}
|
||||
///
|
||||
/// \details adds a rvalue reference to the provided type such that \f$T\f$ becomes \f$T\&\&\f$
|
||||
/// \details adds a rvalue reference to the provided type such that \emph{T} becomes \emph{T\&\&}
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct add_rvalue_reference : detail::_add_rvalue_reference<T> {};
|
||||
|
||||
@@ -273,9 +273,9 @@ template<typename T> using add_rvalue_reference_t = typename add_rvalue_referen
|
||||
|
||||
|
||||
///
|
||||
/// \brief remove a reference from \f$T\f$
|
||||
/// \brief remove a reference from \emph{T}
|
||||
///
|
||||
/// \details removes references from the provided type such that \f$T\&\f$ and \f$T\&\&\f$ become \f$T\f$
|
||||
/// \details removes references from the provided type such that \emph{T\&} and \emph{T\&\&} become \emph{T}
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct remove_reference : type_identity<T> {};
|
||||
|
||||
@@ -294,9 +294,9 @@ template<typename T> using remove_reference_t = typename remove_reference<T>::t
|
||||
// Const & Volatile Conversions ========================================================================================
|
||||
|
||||
///
|
||||
/// \brief add the const qualifier to the provided type \f$T\f$
|
||||
/// \brief add the const qualifier to the provided type \emph{T}
|
||||
///
|
||||
/// \details adds const qualification to the provided type such that \f$T\f$ becomes \f$const\quad T\f$
|
||||
/// \details adds const qualification to the provided type such that \emph{T} becomes \emph{const\quad T}
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct add_const : detail::_add_const<T> {};
|
||||
|
||||
@@ -306,9 +306,9 @@ template<typename T> using add_const_t = typename add_const<T>::type;
|
||||
|
||||
|
||||
///
|
||||
/// \brief remove the const qualifier from the provided type \f$T\f$
|
||||
/// \brief remove the const qualifier from the provided type \emph{T}
|
||||
///
|
||||
/// \details removes const qualification from the provided type such that \f$const\quad T\f$ becomes \f$T\f$
|
||||
/// \details removes const qualification from the provided type such that \emph{const\quad T} becomes \emph{T}
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct remove_const : detail::_remove_const<T> {};
|
||||
|
||||
@@ -319,9 +319,9 @@ template<typename T> using remove_const_t = typename remove_const<T>::type;
|
||||
|
||||
|
||||
///
|
||||
/// \brief add the volatile qualifier to the provided type \f$T\f$
|
||||
/// \brief add the volatile qualifier to the provided type \emph{T}
|
||||
///
|
||||
/// \details removes references from the provided type such that \f$T\f$ becomes \f$volatile\quad T\f$
|
||||
/// \details removes references from the provided type such that \emph{T} becomes \emph{volatile\quad T}
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct add_volatile : detail::_add_volatile<T> {};
|
||||
|
||||
@@ -331,9 +331,9 @@ template<typename T> using add_volatile_t = typename add_volatile<T>::type;
|
||||
|
||||
|
||||
///
|
||||
/// \brief remove the volatile qualifier from the provided type \f$T\f$
|
||||
/// \brief remove the volatile qualifier from the provided type \emph{T}
|
||||
///
|
||||
/// \details removes references from the provided type such that \f$volatile\quad T\f$ becomes \f$T\f$
|
||||
/// \details removes references from the provided type such that \emph{volatile\quad T} becomes \emph{T}
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct remove_volatile : detail::_remove_volatile<T> {};
|
||||
|
||||
@@ -344,10 +344,10 @@ template<typename T> using remove_volatile_t = typename remove_volatile<T>::type
|
||||
|
||||
|
||||
///
|
||||
/// \brief remove the volatile qualifier from the provided type \f$T\f$
|
||||
/// \brief remove the volatile qualifier from the provided type \emph{T}
|
||||
///
|
||||
/// \details removes references from the provided type such that \f$T\f$, \f$const\quad T\f$, and \f$volatile\quad T\f$
|
||||
/// become \f$const volatile T\f$
|
||||
/// \details removes references from the provided type such that \emph{T}, \emph{const\quad T}, and \emph{volatile\quad T}
|
||||
/// become \emph{const volatile T}
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct add_cv : detail::_add_cv<T> {};
|
||||
|
||||
@@ -358,10 +358,10 @@ template<typename T> using add_cv_t = typename add_cv<T>::type;
|
||||
|
||||
|
||||
///
|
||||
/// \brief remove the const and volatile qualifiers from the provided type \f$T\f$
|
||||
/// \brief remove the const and volatile qualifiers from the provided type \emph{T}
|
||||
///
|
||||
/// \details removes const and volatile from the provided type such that \f$const\quad T\f$, \f$volatile\quad T\f$, and
|
||||
/// \f$const\quad volatile\quad T\f$ become \f$T\f$
|
||||
/// \details removes const and volatile from the provided type such that \emph{const\quad T}, \emph{volatile\quad T}, and
|
||||
/// \emph{const\quad volatile\quad T} become \emph{T}
|
||||
/// \tparam T Reference Type
|
||||
template<typename T> struct remove_cv : detail::_remove_cv<T> {};
|
||||
|
||||
@@ -372,7 +372,7 @@ template<typename T> using remove_cv_t = typename remove_cv<T>::type;
|
||||
|
||||
|
||||
///
|
||||
/// \brief add a reference and the const volatile qualifiers from the provided type \f$T\f$
|
||||
/// \brief add a reference and the const volatile qualifiers from the provided type \emph{T}
|
||||
///
|
||||
/// \details adds references and const volatile qualifiers to the provided type.
|
||||
/// \tparam T Reference Type
|
||||
@@ -385,7 +385,7 @@ template<typename T> using add_cvref_t = typename add_cvref<T>::type;
|
||||
|
||||
|
||||
///
|
||||
/// \brief removes references as well as the const and volatile qualifiers from the provided type \f$T\f$
|
||||
/// \brief removes references as well as the const and volatile qualifiers from the provided type \emph{T}
|
||||
///
|
||||
/// \details removes const and volatile from the provided type such that
|
||||
/// \tparam T Reference Type
|
||||
@@ -399,7 +399,7 @@ template<typename T> using remove_cvref_t = typename remove_cvref<T>::type;
|
||||
|
||||
|
||||
///
|
||||
/// \brief removes references and pointers as well as the const and volatile qualifiers from the provided type \f$T\f$
|
||||
/// \brief removes references and pointers as well as the const and volatile qualifiers from the provided type \emph{T}
|
||||
///
|
||||
/// \details removes const and volatile from the provided type such that
|
||||
/// \tparam T Reference Type
|
||||
|
||||
@@ -84,10 +84,10 @@ template<typename T> constexpr T&& forward(remove_reference_t<T>&& x) noexcept {
|
||||
#endif
|
||||
|
||||
|
||||
/// \brief Copies \f$v\f$ to a new object of `decay_t<T>`
|
||||
/// \brief Copies \emph{v} to a new object of `decay_t<T>`
|
||||
/// \tparam T The type
|
||||
/// \param v The object
|
||||
/// \returns A stack allocated copy of \f$v\f$ in `decay_t<T>`
|
||||
/// \returns A stack allocated copy of \emph{v} in `decay_t<T>`
|
||||
template<typename T> constexpr decay_t<T> decay_copy(T&& v) {
|
||||
return fennec::forward<T>(v);
|
||||
}
|
||||
|
||||
@@ -295,11 +295,11 @@ namespace fennec
|
||||
// Sign ================================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns \f$1\f$ if \f$x > 0\f$, \f$0\f$ if \f$x = 0\f$, or \f$-1\f$ if \f$x<0\f$
|
||||
/// \brief Returns \math{1} if \math{x > 0}, \math{0} if \math{x = 0}, or \math{-1} if \math{x<0}
|
||||
///
|
||||
/// \returns \f$1\f$ if \f$x > 0\f$, \f$0\f$ if \f$x = 0\f$, or \f$-1\f$ if \f$x<0\f$ <br><br>
|
||||
/// \returns \math{1} if \math{x > 0}, \math{0} if \math{x = 0}, or \math{-1} if \math{x<0} <br><br>
|
||||
/// \details We can express this as, <br><br>
|
||||
/// \f$\text{sign}(x) = \text{sgn}(x) = \left\{\begin{array}{lr} -1 & x < 0, \\ 0 & x = 0, \\ 1 & x > 0.\end{array}\right.\f$ <br><br>
|
||||
/// \math{\text{sign}(x) = \text{sgn}(x) = \left\{\begin{array}{lr} -1 & x < 0, \\ 0 & x = 0, \\ 1 & x > 0.\end{array}\right.} <br><br>
|
||||
///
|
||||
/// \param x input value
|
||||
template<typename genType>
|
||||
@@ -311,11 +311,11 @@ constexpr genType sign(genType x) {
|
||||
// Absolute Value ======================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns \f$x\f$ if \f$x \ge 0\f$, otherwise it returns \f$-x\f$
|
||||
/// \brief Returns \math{x} if \math{x \ge 0}, otherwise returns \math{-x}
|
||||
///
|
||||
/// \returns \f$x\f$ if \f$x \ge 0\f$, otherwise it returns \f$-x\f$. <br> <br>
|
||||
/// \returns \math{x} if \math{x \ge 0}, otherwise it returns \math{-x}. <br> <br>
|
||||
/// \details We can express this as, <br> <br>
|
||||
/// \f$\text{abs}(x)=\left|x\right|\f$.<br> <br>
|
||||
/// \math{\text{abs}(x)=\left|x\right|}.<br> <br>
|
||||
///
|
||||
/// \param x input value
|
||||
template<typename genType>
|
||||
@@ -337,11 +337,11 @@ constexpr genType abs(genType x) {
|
||||
// Floor ===============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns a value equal to the nearest integer that is less than or equal to \f$x\f$
|
||||
/// \brief Returns a value equal to the nearest integer that is less than or equal to \math{x}
|
||||
///
|
||||
/// \returns a value equal to the nearest integer that is less than or equal to \f$x\f$ <br> <br>
|
||||
/// \returns a value equal to the nearest integer that is less than or equal to \math{x} <br> <br>
|
||||
/// \details We can express this as,<br> <br>
|
||||
/// \f$\text{floor}(x)=\lfloor x\rfloor\f$<br> <br>
|
||||
/// \math{\text{floor}(x)=\lfloor x\rfloor}<br> <br>
|
||||
///
|
||||
/// \param x input value
|
||||
template<typename genType>
|
||||
@@ -354,11 +354,11 @@ constexpr genType floor(genType x) {
|
||||
// Ceil ================================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns a value equal to the nearest integer that is greater than or equal to \f$x\f$
|
||||
/// \brief Returns a value equal to the nearest integer that is greater than or equal to \math{x}
|
||||
///
|
||||
/// \returns a value equal to the nearest integer that is greater than or equal to \f$x\f$ <br> <br>
|
||||
/// \returns a value equal to the nearest integer that is greater than or equal to \math{x} <br> <br>
|
||||
/// \details We can express this as, <br> <br>
|
||||
/// \f$\text{ceil}(x)=\lceil{x}\rceil\f$ <br> <br>
|
||||
/// \math{\text{ceil}(x)=\lceil{x}\rceil} <br> <br>
|
||||
///
|
||||
/// \param x input value
|
||||
template<typename genType>
|
||||
@@ -371,12 +371,12 @@ constexpr genType ceil(genType x) {
|
||||
// Round ===============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns a value equal to the nearest integer. In C++, a fractional part of \f$0.5\f$ will always round up.
|
||||
/// \brief Returns a value equal to the nearest integer. In C++, a fractional part of \math{0.5} will always round up.
|
||||
///
|
||||
/// \returns a value equal to the nearest integer.<br> <br>
|
||||
/// \details In C++, a fractional part of \f$0.5\f$ will always round up.<br> <br>
|
||||
/// \details In C++, a fractional part of \math{0.5} will always round up.<br> <br>
|
||||
/// We can express this as, <br> <br>
|
||||
/// \f$\text{round}(x) = \text{sgn}(x) \cdot \lfloor \left| x \right| + 0.5 \rfloor\f$<br> <br>
|
||||
/// \math{\text{round}(x) = \text{sgn}(x) \cdot \lfloor \left| x \right| + 0.5 \rfloor}<br> <br>
|
||||
///
|
||||
/// \param x input value
|
||||
template<typename genType> constexpr genType round(genType x) {
|
||||
@@ -388,11 +388,11 @@ template<typename genType> constexpr genType round(genType x) {
|
||||
// Trunc ===============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns a value equal to the nearest integer that is less than or equal to \f$x\f$
|
||||
/// \brief Returns a value equal to the nearest integer that is less than or equal to \math{x}
|
||||
///
|
||||
/// \returns a value equal to the nearest integer that is less than or equal to \f$x\f$ <br> <br>
|
||||
/// \returns a value equal to the nearest integer that is less than or equal to \math{x} <br> <br>
|
||||
/// \details We can express this as, <br> <br>
|
||||
/// \f$\text{trunc}(x) = \text{sgn}(x) \cdot \lceil \left| x \right| - 0.5 \rceil\f$<br> <br>
|
||||
/// \math{\text{trunc}(x) = \text{sgn}(x) \cdot \lceil \left| x \right| - 0.5 \rceil}<br> <br>
|
||||
///
|
||||
/// \param x input value
|
||||
template<typename genType>
|
||||
@@ -405,13 +405,13 @@ constexpr genType trunc(genType x) {
|
||||
// Round Even ==========================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns a value equal to the nearest integer. In C++, a fractional part of \f$0.5\f$ will always
|
||||
/// \brief Returns a value equal to the nearest integer. In C++, a fractional part of \math{0.5} will always
|
||||
/// round to the nearest even integer.
|
||||
///
|
||||
/// \returns a value equal to the nearest integer.<br> <br>
|
||||
/// \details In C++, a fractional part of \f$0.5\f$ will always round to the nearest even integer.<br> <br>
|
||||
/// \details In C++, a fractional part of \math{0.5} will always round to the nearest even integer.<br> <br>
|
||||
/// We can express this as,<br> <br>
|
||||
/// \f$\text{roundEven}() = \begin{cases}\lfloor{x}\rfloor + \text{mod}(\lfloor{x}\rfloor, 2.0) & \text{fract}(x) = 0.5, \\ \text{round}(x) \end{cases}\f$<br> <br>
|
||||
/// \math{\text{roundEven}() = \begin{cases}\lfloor{x}\rfloor + \text{mod}(\lfloor{x}\rfloor, 2.0) & \text{fract}(x) = 0.5, \\ \text{round}(x) \end{cases}}<br> <br>
|
||||
///
|
||||
/// \param x input value
|
||||
template<typename genType>
|
||||
@@ -451,11 +451,11 @@ constexpr genType roundEven(genType x) {
|
||||
// Fract ===============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns \f$x - floor(x)\f$
|
||||
/// \brief Returns \math{x - floor(x)}
|
||||
///
|
||||
/// \returns \f$x - \text{floor}(x)\f$ <br> <br>
|
||||
/// \returns \math{x - \text{floor}(x)} <br> <br>
|
||||
/// \details We can express this as, <br> <br>
|
||||
/// \f$\text{fract}(x)=x-\text{floor}\f$<br> <br>
|
||||
/// \math{\text{fract}(x)=x-\text{floor}}<br> <br>
|
||||
///
|
||||
/// \param x input value
|
||||
template<typename genType>
|
||||
@@ -467,11 +467,11 @@ constexpr genType fract(genType x) {
|
||||
// Mod =================================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Modulus. Returns \f$x-y\cdot floor (x/y)\f$
|
||||
/// \brief Modulus. Returns \math{x-y\cdot floor (x/y)}
|
||||
///
|
||||
/// \returns \f$x-y\cdot\text{floor}(x/y)\f$ <br> <br>
|
||||
/// \returns \math{x-y\cdot\text{floor}(x/y)} <br> <br>
|
||||
/// \details We can express this as, <br> <br>
|
||||
/// \f$\text{fract}(x)=x-\text{floor}(\frac{x}{y})\f$<br> <br>
|
||||
/// \math{\text{fract}(x)=x-\text{floor}(\frac{x}{y})}<br> <br>
|
||||
///
|
||||
/// \param x dividend
|
||||
/// \param y divisor
|
||||
@@ -484,11 +484,11 @@ constexpr genType mod(genType x, genType y) {
|
||||
// ModF ================================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns the fractional part of \f$x\f$ and stores the integral part in \f$i\f$.
|
||||
/// \brief Returns the fractional part of \math{x} and stores the integral part in \math{i}.
|
||||
///
|
||||
/// \returns the fractional part of \f$x\f$ and stores the integral part in \f$i\f$. <br> <br>
|
||||
/// \returns the fractional part of \math{x} and stores the integral part in \math{i}. <br> <br>
|
||||
/// \details We can express this as, <br> <br>
|
||||
/// \f$\text{modf}(x) = \text{trunc}(x),\, i := \text{fract}(x)\f$ <br> <br>
|
||||
/// \math{\text{modf}(x) = \text{trunc}(x),\, i := \text{fract}(x)} <br> <br>
|
||||
///
|
||||
/// \param x input value
|
||||
/// \param i integral out
|
||||
@@ -501,14 +501,14 @@ constexpr genType modf(genType x, genType& i) {
|
||||
// Is NaN ==============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns **true** if \f$x\f$ holds a NaN. Returns **false** otherwise.
|
||||
/// \brief Returns **true** if \math{x} holds a NaN. Returns **false** otherwise.
|
||||
///
|
||||
/// \returns **true** if \f$x\f$ holds a NaN. Returns **false** otherwise. <br> <br>
|
||||
/// \details \f$NaN\f$ is a concept unique to computing. It strictly means, and more specifically,
|
||||
/// \returns **true** if \math{x} holds a NaN. Returns **false** otherwise. <br> <br>
|
||||
/// \details \math{NaN} is a concept unique to computing. It strictly means, and more specifically,
|
||||
/// floating point values can only represent *real* numbers. This is why some functions,
|
||||
/// like \ref fennec::sqrt "sqrt()", return \f$NaN\f$ when an expression would return
|
||||
/// a value in a different coordinate space. There are other cases, such as \f$\frac{1}{x}\f$,
|
||||
/// where \f$x=0\f$ is undefined, and respectively the return value is also \f$NaN\f$. <br> <br>
|
||||
/// like \ref fennec::sqrt "sqrt()", return \math{NaN} when an expression would return
|
||||
/// a value in a different coordinate space. There are other cases, such as \math{\frac{1}{x}},
|
||||
/// where \math{x=0} is undefined, and respectively the return value is also \math{NaN}. <br> <br>
|
||||
///
|
||||
/// To learn more, see [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754) <br> <br>
|
||||
///
|
||||
@@ -522,10 +522,10 @@ constexpr genBType isnan(genType x) {
|
||||
// Is Inf ==============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns **true** if \f$x\f$ holds a positive or negative infinity. Returns **false** otherwise. <br> <br>
|
||||
/// \brief Returns **true** if \math{x} holds a positive or negative infinity. Returns **false** otherwise. <br> <br>
|
||||
///
|
||||
/// \returns **true** if \f$x\f$ holds a positive or negative infinity. Returns **false** otherwise.
|
||||
/// \details \f$\inf\f$, or \f$\infty\f$, is used to express any function that is boundless, endless, or larger
|
||||
/// \returns **true** if \math{x} holds a positive or negative infinity. Returns **false** otherwise.
|
||||
/// \details \math{\inf}, or \math{\infty}, is used to express any function that is boundless, endless, or larger
|
||||
/// than any natural number. This function has applications in Set Theory and Mathematical Analysis. <br> <br>
|
||||
///
|
||||
/// \param x input value
|
||||
@@ -553,13 +553,13 @@ constexpr genIType floatBitsToInt(genType x) {
|
||||
/// \returns a signed or unsigned integer value representing the encoding of a floating-point value.
|
||||
/// The float value's bit-level representation is preserved. <br> <br>
|
||||
/// \details we can express this in set theory, i.e. <br> <br>
|
||||
/// let \f$B\f$ be a set, such that, \f$B=\left\lbrace{b_{0},...b_{32}}\right\rbrace\f$ and \f$b_{i} \in S\f$ where \f$S=\left\lbrace{0, 1}\right\rbrace\f$<br>
|
||||
/// let \f$m_B=\frac{b_{0}}{2^1}+\cdots +\frac{b_{i}}{2^{i+1}}+\cdots +\frac{b_{22}}{2^{23}}\begin{cases}1&\end{cases}\f$<br>
|
||||
/// let \f$p_B=b_{23}\cdot 2^0+\cdots +b_i\cdot 2^{i-23}+\cdots +b_{30}\cdot 2^7-127\f$<br>
|
||||
/// let \f$s_B=\begin{cases}-1,&b_{31}=1 \\ 1\end{cases}\f$<br> <br>
|
||||
/// then, \f$x_B=s_B m_B 2^{p_B}\f$<br>
|
||||
/// and, \f$i_B=-b_{31} 2^{31}+\sum_{i=0}^{30}{a_i 2^i}\f$<br>
|
||||
/// and, \f$u_B=\sum_{i=0}^{31}{a_i 2^i}\f$<br> <br>
|
||||
/// let \math{B} be a set, such that, \math{B=\left\lbrace{b_{0},...b_{32}}\right\rbrace} and \math{b_{i} \in S} where \math{S=\left\lbrace{0, 1}\right\rbrace}<br>
|
||||
/// let \math{m_B=\frac{b_{0}}{2^1}+\cdots +\frac{b_{i}}{2^{i+1}}+\cdots +\frac{b_{22}}{2^{23}}\begin{cases}1&\end{cases}}<br>
|
||||
/// let \math{p_B=b_{23}\cdot 2^0+\cdots +b_i\cdot 2^{i-23}+\cdots +b_{30}\cdot 2^7-127}<br>
|
||||
/// let \math{s_B=\begin{cases}-1,&b_{31}=1 \\ 1\end{cases}}<br> <br>
|
||||
/// then, \math{x_B=s_B m_B 2^{p_B}}<br>
|
||||
/// and, \math{i_B=-b_{31} 2^{31}+\sum_{i=0}^{30}{a_i 2^i}}<br>
|
||||
/// and, \math{u_B=\sum_{i=0}^{31}{a_i 2^i}}<br> <br>
|
||||
///
|
||||
/// \param x value to convert
|
||||
template<typename genType, typename genUType = uint_t> requires(is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and sizeof(genType) == sizeof(genUType))
|
||||
@@ -581,13 +581,13 @@ constexpr genType intBitsToFloat(genIType x) {
|
||||
///
|
||||
/// \returns a floating-point value corresponding to a signed or unsigned integer encoding of a floating-point value. <br> <br>
|
||||
/// \details we can express this in set theory, i.e. <br> <br>
|
||||
/// let \f$B\f$ be a set, such that, \f$B=\left\lbrace{b_{0},...b_{32}}\right\rbrace\f$ and \f$b_{i} \in S\f$ where \f$S=\left\lbrace{0, 1}\right\rbrace\f$<br>
|
||||
/// let \f$m_B=\frac{b_{0}}{2^1}+\cdots +\frac{b_{i}}{2^{i+1}}+\cdots +\frac{b_{22}}{2^{23}}\begin{cases}1&\end{cases}\f$<br>
|
||||
/// let \f$p_B=b_{23}\cdot 2^0+\cdots +b_i\cdot 2^{i-23}+\cdots +b_{30}\cdot 2^7-127\f$<br>
|
||||
/// let \f$s_B=\begin{cases}-1,&b_{31}=1 \\ 1\end{cases}\f$<br> <br>
|
||||
/// then, \f$x_B=s_B m_B 2^{p_B}\f$<br>
|
||||
/// and, \f$i_B=-b_{31} 2^31+\sum_{i=0}^{30}{a_i 2^i}\f$<br>
|
||||
/// and, \f$u_B=\sum_{i=0}^{31}{a_i 2^i}\f$<br> <br>
|
||||
/// let \math{B} be a set, such that, \math{B=\left\lbrace{b_{0},...b_{32}}\right\rbrace} and \math{b_{i} \in S} where \math{S=\left\lbrace{0, 1}\right\rbrace}<br>
|
||||
/// let \math{m_B=\frac{b_{0}}{2^1}+\cdots +\frac{b_{i}}{2^{i+1}}+\cdots +\frac{b_{22}}{2^{23}}\begin{cases}1&\end{cases}}<br>
|
||||
/// let \math{p_B=b_{23}\cdot 2^0+\cdots +b_i\cdot 2^{i-23}+\cdots +b_{30}\cdot 2^7-127}<br>
|
||||
/// let \math{s_B=\begin{cases}-1,&b_{31}=1 \\ 1\end{cases}}<br> <br>
|
||||
/// then, \math{x_B=s_B m_B 2^{p_B}}<br>
|
||||
/// and, \math{i_B=-b_{31} 2^31+\sum_{i=0}^{30}{a_i 2^i}}<br>
|
||||
/// and, \math{u_B=\sum_{i=0}^{31}{a_i 2^i}}<br> <br>
|
||||
///
|
||||
/// \param x value to convert
|
||||
template<typename genType = float_t, typename genUType = uint_t> requires(is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and sizeof(genType) == sizeof(genUType))
|
||||
@@ -600,9 +600,9 @@ constexpr genType uintBitsToFloat(genUType x) {
|
||||
// fma =================================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Computes and returns \f$a \cdot b + c\f$. <br> <br>
|
||||
/// \brief Computes and returns \math{a \cdot b + c}. <br> <br>
|
||||
///
|
||||
/// \returns \f$a \cdot b + c\f$.
|
||||
/// \returns \math{a \cdot b + c}.
|
||||
/// \details In C++, this function will use the [fused multiply-add](https://en.wikipedia.org/wiki/Multiply%E2%80%93accumulate_operation),
|
||||
/// when the instruction is present on the target architecture. <br> <br>
|
||||
///
|
||||
@@ -619,16 +619,16 @@ constexpr genType fma(genType a, genType b, genType c) {
|
||||
// frexp ===============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Splits \f$x\f$ into a floating-point significand in the range \f$[0.5,1.0]\f$, and an integral exponent of two,
|
||||
/// such that \f$x=sig \cdot 2^{exp}\f$.
|
||||
/// \brief Splits \math{x} into a floating-point significand in the range \math{[0.5,1.0]}, and an integral exponent of two,
|
||||
/// such that \math{x=sig \cdot 2^{exp}}.
|
||||
///
|
||||
/// \returns The significand of the expression.<br> <br>
|
||||
/// \details The significand is returned by the function and the exponent is returned in the parameter \f$exp\f$.
|
||||
/// \details The significand is returned by the function and the exponent is returned in the parameter \math{exp}.
|
||||
/// For a floating-point value of zero, the significand and exponent are both zero. If an implementation
|
||||
/// supports signed zero, an input value of minus zero should return a significand of minus zero. For a
|
||||
/// floating-point value that is an infinity or is not a number, the results are undefined. If the input
|
||||
/// \f$x\f$ is a vector, this operation is performed in a component-wise manner; the value returned by the
|
||||
/// function and the value written to \f$exp\f$ are vectors with the same number of components as \f$x\f$. <br> <br>
|
||||
/// \math{x} is a vector, this operation is performed in a component-wise manner; the value returned by the
|
||||
/// function and the value written to \math{exp} are vectors with the same number of components as \math{x}. <br> <br>
|
||||
///
|
||||
/// \param x The floating-point value to split
|
||||
/// \param exp The variable to store the exponent in
|
||||
@@ -642,11 +642,11 @@ constexpr genType frexp(genType x, genIType& exp) {
|
||||
// ldexp ===============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Builds a floating-point number from \f$x\f$ and the corresponding integral exponent of two in \f$exp\f$
|
||||
/// \brief Builds a floating-point number from \math{x} and the corresponding integral exponent of two in \math{exp}
|
||||
///
|
||||
/// \returns \f${x}\cdot{2^{exp}}\f$
|
||||
/// \returns \math{{x}\cdot{2^{exp}}}
|
||||
/// \details Builds a floating-point number from x and the corresponding integral exponent of two in exp,
|
||||
/// returning: \f${x}\cdot{2^{exp}}\f$. If this product is too large to be represented in the floating-point
|
||||
/// returning: \math{{x}\cdot{2^{exp}}}. If this product is too large to be represented in the floating-point
|
||||
/// type, the result is undefined. If exp is greater than +128 (single-precision) or +1024 (double-precision),
|
||||
/// the value returned is undefined. If exp is less than -126 (single-precision) or -1022 (double-precision),
|
||||
/// the value returned may be flushed to zero. Additionally, splitting the value into a significand and
|
||||
@@ -676,14 +676,14 @@ constexpr genType ldexp(genType x, genIType exp) {
|
||||
// Min =================================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns \f$y\f$ if \f$x<y;\f$ otherwise it returns \f$x\f$
|
||||
/// \brief Returns \math{y} if \math{x<y;} otherwise it returns \math{x}
|
||||
///
|
||||
/// \returns \f$y\f$ if \f$x<y\f$, otherwise it returns \f$x\f$<br> <br>
|
||||
/// \returns \math{y} if \math{x<y}, otherwise it returns \math{x}<br> <br>
|
||||
/// \details We can express this as,<br> <br>
|
||||
/// \f$\text{min}(x, y)=\begin{cases}y, & y < x \\ x\end{cases}\f$<br> <br>
|
||||
/// \math{\text{min}(x, y)=\begin{cases}y, & y < x \\ x\end{cases}}<br> <br>
|
||||
///
|
||||
/// \param x input value \f$x\f$
|
||||
/// \param y input value \f$y\f$
|
||||
/// \param x input value \math{x}
|
||||
/// \param y input value \math{y}
|
||||
template<typename genType>
|
||||
constexpr genType min(genType x, genType y) {
|
||||
return (y < x) ? y : x;
|
||||
@@ -693,11 +693,11 @@ constexpr genType min(genType x, genType y) {
|
||||
// Max =================================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns \f$y\f$ if \f$y<x\f$, otherwise it returns \f$x\f$
|
||||
/// \brief Returns \math{y} if \math{y<x}, otherwise it returns \math{x}
|
||||
///
|
||||
/// \returns \f$y\f$ if \f$y<x\f$, otherwise it returns \f$x\f$<br> <br>
|
||||
/// \returns \math{y} if \math{y<x}, otherwise it returns \math{x}<br> <br>
|
||||
/// \details We can express this as,<br> <br>
|
||||
/// \f$\text{max}(x, y)=\begin{cases}y, & x < y \\ x\end{cases}\f$<br> <br>
|
||||
/// \math{\text{max}(x, y)=\begin{cases}y, & x < y \\ x\end{cases}}<br> <br>
|
||||
///
|
||||
/// \param x first input value
|
||||
/// \param y second input value
|
||||
@@ -710,11 +710,11 @@ constexpr genType max(genType x, genType y) {
|
||||
// Clamp ===============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns \f$min (max (x, minVal), maxVal)\f$
|
||||
/// \brief Returns \math{min (max (x, minVal), maxVal)}
|
||||
///
|
||||
/// \returns \f$\text{min}(\text{max}(x, minVal), maxVal)\f$. Results are undefined if \f$minVal > maxVal\f$<br> <br>
|
||||
/// \returns \math{\text{min}(\text{max}(x, minVal), maxVal)}. Results are undefined if \math{minVal > maxVal}<br> <br>
|
||||
/// \details We can express this as, <br> <br>
|
||||
/// \f$\text{clamp}(x, min, max)=\begin{cases}min, & x < min \\ x \\ max, & x > max\end{cases}\f$<br> <br>
|
||||
/// \math{\text{clamp}(x, min, max)=\begin{cases}min, & x < min \\ x \\ max, & x > max\end{cases}}<br> <br>
|
||||
///
|
||||
/// \param x input value
|
||||
/// \param minVal minimum value
|
||||
@@ -738,13 +738,13 @@ constexpr genType clamp(genType x, genType minVal, genType maxVal) {
|
||||
// Step ================================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns \f$0.0\f$ if \f$x<edge\f$, otherwise, it returns \f$1.0\f$
|
||||
/// \brief Returns \math{0.0} if \math{x<edge}, otherwise, it returns \math{1.0}
|
||||
///
|
||||
/// \returns \f$0.0\f$ if \f$x<edge\f$, otherwise, it returns \f$1.0\f$<br> <br>
|
||||
/// \returns \math{0.0} if \math{x<edge}, otherwise, it returns \math{1.0}<br> <br>
|
||||
/// \details We can express this as, <br> <br>
|
||||
/// \f$\text{step}(edge, x)=\begin{cases}0.0 & x < edge \\ 1.0 \end{cases}\f$<br> <br>
|
||||
/// \math{\text{step}(edge, x)=\begin{cases}0.0 & x < edge \\ 1.0 \end{cases}}<br> <br>
|
||||
///
|
||||
/// \param edge The \f$x\f$ coordinate of the discontinuity
|
||||
/// \param edge The \math{x} coordinate of the discontinuity
|
||||
/// \param x The coordinate of the sample location
|
||||
template<typename genType> requires(is_floating_point_v<genType>)
|
||||
constexpr genType step(genType edge, genType x) {
|
||||
@@ -755,11 +755,11 @@ constexpr genType step(genType edge, genType x) {
|
||||
// Smoothstep ==========================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns \f$0.0\f$ if \f$x\le edge0\f$ and \f$1.0\f$ if \f$x\ge edge1\f$, and performs smooth Hermite
|
||||
/// interpolation between \f$0\f$ and \f$1\f$ when \f$edge0<x<edge1\f$.
|
||||
/// \brief Returns \math{0.0} if \math{x\le edge0} and \math{1.0} if \math{x\ge edge1}, and performs smooth Hermite
|
||||
/// interpolation between \math{0} and \math{1} when \math{edge0<x<edge1}.
|
||||
///
|
||||
/// \returns \f$0.0\f$ if \f$x\le edge0\f$ and \f$1.0\f$ if \f$x\ge edge1\f$, and performs smooth Hermite
|
||||
/// interpolation between \f$0\f$ and \f$1\f$ when \f$edge0<x<edge1\f$. <br> <br>
|
||||
/// \returns \math{0.0} if \math{x\le edge0} and \math{1.0} if \math{x\ge edge1}, and performs smooth Hermite
|
||||
/// interpolation between \math{0} and \math{1} when \math{edge0<x<edge1}. <br> <br>
|
||||
/// \details This is useful in cases where you would want a threshold function with a smooth transition.<br> <br>
|
||||
/// This is equivalent to: <br> <br>
|
||||
/// \code{.glsl}
|
||||
@@ -767,13 +767,13 @@ constexpr genType step(genType edge, genType x) {
|
||||
/// t = clamp((x - edge0) / (edge1 - edge0), 0, 1);
|
||||
/// return t * t * (3 - 2 * t);
|
||||
/// \endcode<br>
|
||||
/// Results are undefined if \f$edge0\ge edge1\f$. <br> <br>
|
||||
/// Results are undefined if \math{edge0\ge edge1}. <br> <br>
|
||||
/// We can express this as,<br> <br>
|
||||
/// \f$\text{smoothstep}(e_0, e_1, x)=\begin{cases}0, & {x}\le{e_0} \\ 3{\frac{x-e_0}{e_1-e_0}}^{2} - 2{\frac{x-e_0}{e_1-e_0}}^{3}, & {e_0}\le{x}\le{e_1} \\ 1, & {1}\le{e_x}\end{cases}\f$<br> <br>
|
||||
/// \math{\text{smoothstep}(e_0, e_1, x)=\begin{cases}0, & {x}\le{e_0} \\ 3{\frac{x-e_0}{e_1-e_0}}^{2} - 2{\frac{x-e_0}{e_1-e_0}}^{3}, & {e_0}\le{x}\le{e_1} \\ 1, & {1}\le{e_x}\end{cases}}<br> <br>
|
||||
///
|
||||
/// \param edge0 \f$x\f$ value where the function returns \f$0.0\f$
|
||||
/// \param edge1 \f$x\f$ value where the function returns \f$1.0\f$
|
||||
/// \param x \f$x\f$ coordinate input
|
||||
/// \param edge0 \math{x} value where the function returns \math{0.0}
|
||||
/// \param edge1 \math{x} value where the function returns \math{1.0}
|
||||
/// \param x \math{x} coordinate input
|
||||
template<typename genType> requires(is_floating_point_v<genType>)
|
||||
constexpr genType smoothstep(genType edge0, genType edge1, genType x) {
|
||||
genType t = fennec::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f); return t * t * (3 - 2 * t);
|
||||
@@ -783,13 +783,13 @@ constexpr genType smoothstep(genType edge0, genType edge1, genType x) {
|
||||
// Mix =================================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns the linear blend of \f$x\f$ and \f$y\f$, i.e., \f$x \cdot (1-a) + y \cdot a\f$
|
||||
/// \brief Returns the linear blend of \math{x} and \math{y}, i.e., \math{x \cdot (1-a) + y \cdot a}
|
||||
///
|
||||
/// \returns the linear blend of \f$x\f$ and \f$y\f$, i.e., \f$x \cdot (1-a) + y \cdot a\f$<br> <br>
|
||||
/// \returns the linear blend of \math{x} and \math{y}, i.e., \math{x \cdot (1-a) + y \cdot a}<br> <br>
|
||||
/// \details We can express this as,<br> <br>
|
||||
/// \f$\text{mix}(x, y, a)=x+a \cdot (y - x)\f$<br> <br>
|
||||
/// \math{\text{mix}(x, y, a)=x+a \cdot (y - x)}<br> <br>
|
||||
/// The reason for the difference between the mathematical definition and the glsl definition is
|
||||
/// due to floating-point precision errors. Multiplying \f$x\f$ and \f$y\f$ separately preserves
|
||||
/// due to floating-point precision errors. Multiplying \math{x} and \math{y} separately preserves
|
||||
/// their precision before the addition happens.
|
||||
///
|
||||
/// \param x First value
|
||||
@@ -806,14 +806,14 @@ constexpr genType mix(genType x, genType y, genType a) {
|
||||
///
|
||||
/// \brief Selects which value to return. For Vectors, when the boolean is a scalar, it selects the vector, otherwise, each component is selected.
|
||||
///
|
||||
/// \returns \f$x\f$ when \f$a=T\f$, otherwise returns \f$y\f$
|
||||
/// \returns \math{x} when \math{a=T}, otherwise returns \math{y}
|
||||
/// \details Selects which value to return. For Vectors, when the boolean is a scalar,
|
||||
/// it selects the vector, otherwise, each component is selected. <br> <br>
|
||||
/// This implementation uses the ternary operator:<br>
|
||||
/// \code{.cpp}return a ? x : y;\endcode
|
||||
/// Which will get reduced down to a conditional move instruction over branching.<br> <br>
|
||||
/// We can express this as,<br> <br>
|
||||
/// \f$\text{mix}(x, y, A) = \begin{cases} x, & A=T \\ y & A=F \end{cases}\f$<br> <br>
|
||||
/// \math{\text{mix}(x, y, A) = \begin{cases} x, & A=T \\ y & A=F \end{cases}}<br> <br>
|
||||
///
|
||||
/// \param x True Value
|
||||
/// \param y False Value
|
||||
|
||||
@@ -19,10 +19,37 @@
|
||||
#ifndef FENNEC_MATH_DETAIL_MATH_H
|
||||
#define FENNEC_MATH_DETAIL_MATH_H
|
||||
|
||||
|
||||
// Handle including C math.h
|
||||
// Unfortunately, each compiler needs its own if case in the macro chain below
|
||||
|
||||
#if FENNEC_COMPILER_CLANG // Clang
|
||||
|
||||
// Temporarily disable macro redefinition warning
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wbuiltin-macro-redefined"
|
||||
|
||||
// Undefine __cpluscplus macro to force using the C header
|
||||
#pragma push_macro("__cplusplus")
|
||||
#undef __cplusplus
|
||||
|
||||
// Include math.h
|
||||
#include <math.h>
|
||||
|
||||
// Restore __cpluscplus definition and macro redefinition warning
|
||||
#pragma pop_macro("__cplusplus")
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
|
||||
#elif FENNEC_COMPILER_GCC // GCC
|
||||
|
||||
// This definition tells GCC to just use the C header, thanks GCC!!!
|
||||
#ifndef _GLIBCXX_INCLUDE_NEXT_C_HEADERS
|
||||
#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
#undef div
|
||||
#undef acos
|
||||
|
||||
@@ -97,10 +97,10 @@ namespace fennec
|
||||
// pow =================================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns \f$x\f$ raised to the \f$y\f$ power, i.e., \f$x^y\f$.
|
||||
/// \brief Returns \math{x} raised to the \math{y} power, i.e., \math{x^y}.
|
||||
///
|
||||
/// \returns \f$x\f$ raised to the \f$y\f$ power, i.e., \f$x^y\f$.<br><br>
|
||||
/// \details Results are undefined if \f$x<0\f$. <br><br>Results are undefined if \f$x=0\f$ and \f${y}\le{0}\f$.<br><br>
|
||||
/// \returns \math{x} raised to the \math{y} power, i.e., \math{x^y}.<br><br>
|
||||
/// \details Results are undefined if \math{x<0}. <br><br>Results are undefined if \math{x=0} and \math{{y}\le{0}}.<br><br>
|
||||
///
|
||||
/// \param x the base
|
||||
/// \param y the exponent
|
||||
@@ -113,9 +113,9 @@ constexpr genType pow(genType x, genType y) {
|
||||
// exp =================================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns the natural exponentiation of \f$x\f$, i.e., \f$e^x\f$
|
||||
/// \brief Returns the natural exponentiation of \math{x}, i.e., \math{e^x}
|
||||
///
|
||||
/// \returns the natural exponentiation of \f$x\f$, i.e., \f$e^x\f$.<br><br>
|
||||
/// \returns the natural exponentiation of \math{x}, i.e., \math{e^x}.<br><br>
|
||||
///
|
||||
/// \param x the exponent
|
||||
template<typename genType>
|
||||
@@ -127,9 +127,9 @@ constexpr genType exp(genType x) {
|
||||
// exp2 ================================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns 2 raised to the \f$x\f$ power, i.e., \f$e^x\f$
|
||||
/// \brief Returns 2 raised to the \math{x} power, i.e., \math{e^x}
|
||||
///
|
||||
/// \returns 2 raised to the \f$x\f$ power, i.e., \f$e^x\f$<br><br>
|
||||
/// \returns 2 raised to the \math{x} power, i.e., \math{e^x}<br><br>
|
||||
///
|
||||
/// \param x the exponent
|
||||
template<typename genType> constexpr genType exp2(genType x) {
|
||||
@@ -140,10 +140,10 @@ template<typename genType> constexpr genType exp2(genType x) {
|
||||
// log =================================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns the natural logarithm of \f$x\f$.
|
||||
/// \brief Returns the natural logarithm of \math{x}.
|
||||
///
|
||||
/// \returns the natural logarithm of \f$x\f$, i.e., returns the value \f$y\f$ which satisfies the equation \f$x=e^y\f$.<br><br>
|
||||
/// \details Results are undefined if \f${x}\le{0}\f$.<br><br>
|
||||
/// \returns the natural logarithm of \math{x}, i.e., returns the value \math{y} which satisfies the equation \math{x=e^y}.<br><br>
|
||||
/// \details Results are undefined if \math{{x}\le{0}}.<br><br>
|
||||
///
|
||||
/// \param x the input value
|
||||
template<typename genType> constexpr genType log(genType x) {
|
||||
@@ -154,11 +154,11 @@ template<typename genType> constexpr genType log(genType x) {
|
||||
// log2 ================================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns the base 2 logarithm of \f$x\f$.
|
||||
/// \brief Returns the base 2 logarithm of \math{x}.
|
||||
///
|
||||
/// \returns the base 2 logarithm of \f$x\f$, i.e., returns the value \f$y\f$ which satisfies the equation
|
||||
/// \f$x=2^y\f$. <br><br>
|
||||
/// \details Results are undefined if \f${x}\le{0}\f$. <br><br>
|
||||
/// \returns the base 2 logarithm of \math{x}, i.e., returns the value \math{y} which satisfies the equation
|
||||
/// \math{x=2^y}. <br><br>
|
||||
/// \details Results are undefined if \math{{x}\le{0}}. <br><br>
|
||||
///
|
||||
/// \param x the input value
|
||||
template<typename genType> constexpr genType log2(genType x) {
|
||||
@@ -169,10 +169,10 @@ template<typename genType> constexpr genType log2(genType x) {
|
||||
// sqrt ================================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns \f$\sqrt{x}\f$.
|
||||
/// \brief Returns \math{\sqrt{x}}.
|
||||
///
|
||||
/// \returns \f$\sqrt{x}\f$. <br><br>
|
||||
/// \details Results are undefined if \f$x<0\f$<br><br>
|
||||
/// \returns \math{\sqrt{x}}. <br><br>
|
||||
/// \details Results are undefined if \math{x<0}<br><br>
|
||||
///
|
||||
/// \param x the input value
|
||||
template<typename genType> constexpr genType sqrt(genType x) {
|
||||
@@ -183,10 +183,10 @@ template<typename genType> constexpr genType sqrt(genType x) {
|
||||
// inversesqrt =========================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns \f$\frac{1}{\sqrt{x}}\f$.
|
||||
/// \brief Returns \math{\frac{1}{\sqrt{x}}}.
|
||||
///
|
||||
/// \returns \f$\frac{1}{\sqrt{x}}\f$.<br><br>
|
||||
/// \details Results are undefined if \f$x<0\f$.<br><br>
|
||||
/// \returns \math{\frac{1}{\sqrt{x}}}.<br><br>
|
||||
/// \details Results are undefined if \math{x<0}.<br><br>
|
||||
///
|
||||
/// \param x the input value
|
||||
template<typename genType> constexpr genType inversesqrt(genType x) {
|
||||
|
||||
@@ -546,148 +546,148 @@ 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 \math{0}
|
||||
template<typename genType> constexpr genType one() { return genType(1); } //!< \returns The value of \math{1}
|
||||
template<typename genType> constexpr genType one_half() { return genType(0.5); } //!< \returns The value of \math{\frac{1}{2}}
|
||||
template<typename genType> constexpr genType three_over_two() { return genType(1.5); } //!< \returns The value of \math{\frac{3}{2}}
|
||||
|
||||
|
||||
|
||||
// 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 \math{\frac{1}{3}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType two_thirds() { return 0.66666666666666666666666666666666666666666666666666; } //!< \returns The value of \math{\frac{2}{3}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType sqrt_two() { return 1.41421356237309504880168872420969807856967187537694; } //!< \returns The value of \math{\sqrt{2}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType sqrt_three() { return 1.73205080756887729352744634150587236694280525381038; } //!< \returns The value of \math{\sqrt{3}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType sqrt_five() { return 2.23606797749978969640917366873127623544061835961152; } //!< \returns The value of \math{\sqrt{5}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType sqrt_seven() { return 2.64575131106459059050161575363926042571025918308245; } //!< \returns The value of \math{\sqrt{7}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType sqrt_ten() { return 3.16227766016837933199889354443271853371955513932521; } //!< \returns The value of \math{\sqrt{10}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType one_over_sqrt_two() { return 0.70710678118654752440084436210484903928483593768847; } //!< \returns The value of \math{\frac{1}{\sqrt{2}}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType one_over_sqrt_three() { return 0.57735026918962576450914878050195745564760175127012; } //!< \returns The value of \math{\frac{1}{\sqrt{3}}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType one_over_sqrt_five() { return 0.44721359549995793928183473374625524708812367192230; } //!< \returns The value of \math{\frac{1}{\sqrt{5}}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType cbrt_two() { return 1.25992104989487316476721060727822835057025146470150; } //!< \returns The value of \math{\sqrt[3]{2}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType qdrt_two() { return 1.18920711500272106671749997056047591529297209246381; } //!< \returns The value of \math{\sqrt[4]{2}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType two_raised_sqrt_two() { return 2.66514414269022518865029724987313984827421131371465; } //!< \returns The value of \math{{2}^{\sqrt{2}}} with the highest precision for \emph{genType}
|
||||
|
||||
|
||||
|
||||
// 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 \math{\pi} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType tau() { return 6.28318530717958647692528676655900576839433879875021; } //!< \returns The value of \math{\tau} with the highest precision for \emph{genType}
|
||||
|
||||
// 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 \math{2\pi} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType three_pi() { return 9.42477796076937971538793014983850865259150819812531; } //!< \returns The value of \math{3\pi} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType four_pi() { return 12.56637061435917295385057353311801153678867759750042; } //!< \returns The value of \math{4\pi} with the highest precision for \emph{genType}
|
||||
|
||||
// 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 \math{\frac{\pi}{2}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType three_halves_pi() { return 4.71238898038468985769396507491925432629575409906265; } //!< \returns The value of \math{\frac{3\pi}{2}} with the highest precision for \emph{genType}
|
||||
|
||||
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 \math{\frac{\pi}{3}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType two_thirds_pi() { return 2.09439510239319549230842892218633525613144626625007; } //!< \returns The value of \math{\frac{2\pi}{3}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType four_thirds_pi() { return 4.18879020478639098461685784437267051226289253250014; } //!< \returns The value of \math{\frac{4\pi}{3}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType five_thirds_pi() { return 5.23598775598298873077107230546583814032861566562517; } //!< \returns The value of \math{\frac{5\pi}{3}} with the highest precision for \emph{genType}
|
||||
|
||||
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 \math{\frac{\pi}{4}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType three_quarters_pi() { return 2.35619449019234492884698253745962716314787704953132; } //!< \returns The value of \math{\frac{3\pi}{4}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType five_quarters_pi() { return 3.92699081698724154807830422909937860524646174921888; } //!< \returns The value of \math{\frac{5\pi}{4}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType seven_quarters_pi() { return 5.49778714378213816730962592073913004734504644890643; } //!< \returns The value of \math{\frac{7\pi}{4}} with the highest precision for \emph{genType}
|
||||
|
||||
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 \math{\frac{\pi}{5}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType two_fifths_pi() { return 1.25663706143591729538505735331180115367886775975004; } //!< \returns The value of \math{\frac{2\pi}{5}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType three_fifths_pi() { return 1.88495559215387594307758602996770173051830163962506; } //!< \returns The value of \math{\frac{3\pi}{5}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType four_fifths_pi() { return 2.51327412287183459077011470662360230735773551950008; } //!< \returns The value of \math{\frac{4\pi}{5}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType six_fifths_pi() { return 3.76991118430775188615517205993540346103660327925012; } //!< \returns The value of \math{\frac{6\pi}{5}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType seven_fifths_pi() { return 4.39822971502571053384770073659130403787603715912514; } //!< \returns The value of \math{\frac{7\pi}{5}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType eight_fifths_pi() { return 5.02654824574366918154022941324720461471547103900016; } //!< \returns The value of \math{\frac{8\pi}{5}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType nine_fifths_pi() { return 5.65486677646162782923275808990310519155490491887519; } //!< \returns The value of \math{\frac{9\pi}{5}} with the highest precision for \emph{genType}
|
||||
|
||||
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 \math{\frac{\pi}{6}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType five_sixths_pi() { return 2.61799387799149436538553615273291907016430783281258; } //!< \returns The value of \math{\frac{5\pi}{6}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType seven_sixths_pi() { return 3.66519142918809211153975061382608669823003096593762; } //!< \returns The value of \math{\frac{7\pi}{6}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType eleven_sixths_pi() { return 5.75958653158128760384817953601242195436147723218769; } //!< \returns The value of \math{\frac{11\pi}{6}} with the highest precision for \emph{genType}
|
||||
|
||||
|
||||
|
||||
|
||||
// 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 \math{\frac{1}{\pi}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType two_over_pi() { return 0.63661977236758134307553505349005744813783858296182; } //!< \returns The value of \math{\frac{2}{\pi}} with the highest precision for \emph{genType}
|
||||
|
||||
// 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 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$
|
||||
template<typename genType> constexpr genType one_over_sqrt_two_pi() { return 0.39894228040143267793994605993438186847585863116493; } ///< \returns The value of \f$\frac{1}{\sqrt{2\pi}}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType cbrt_pi() { return 1.46459188756152326302014252726379039173859685562793; } ///< \returns The value of \f$\sqrt[3]{\pi}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType pi_sq() { return 9.86960440108935861883449099987615113531369940724079; } //!< \returns The value of \math{{\pi}^{2}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType pi_cb() { return 31.00627668029982017547631506710139520222528856588510; } //!< \returns The value of \math{{\pi}^{2}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType sqrt_pi() { return 1.77245385090551602729816748334114518279754945612238; } ///< \returns The value of \math{\sqrt{\pi}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType one_over_sqrt_pi() { return 0.56418958354775628694807945156077258584405062932899; } ///< \returns The value of \math{\frac{1}{\sqrt{\pi}}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType sqrt_two_pi() { return 1.77245385090551602729816748334114518279754945612238; } ///< \returns The value of \math{\sqrt{2\pi}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType one_over_sqrt_two_pi() { return 0.39894228040143267793994605993438186847585863116493; } ///< \returns The value of \math{\frac{1}{\sqrt{2\pi}}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType cbrt_pi() { return 1.46459188756152326302014252726379039173859685562793; } ///< \returns The value of \math{\sqrt[3]{\pi}} with the highest precision for \emph{genType}
|
||||
|
||||
|
||||
|
||||
// e ===================================================================================================================
|
||||
|
||||
// Multiples and Reciprocal
|
||||
template<typename genType> constexpr genType e() { return 2.71828182845904523536028747135266249775724709369995; } ///< \returns The value of \f$e\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType half_e() { return 1.35914091422952261768014373567633124887862354684997; } ///< \returns The value of \f$\frac{e}{2}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType two_e() { return 5.43656365691809047072057494270532499551449418739991; } ///< \returns The value of \f$2e\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType one_over_e() { return 0.36787944117144232159552377016146086744581113103176; } ///< \returns The value of \f$\frac{1}{e}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType e() { return 2.71828182845904523536028747135266249775724709369995; } ///< \returns The value of \math{e} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType half_e() { return 1.35914091422952261768014373567633124887862354684997; } ///< \returns The value of \math{\frac{e}{2}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType two_e() { return 5.43656365691809047072057494270532499551449418739991; } ///< \returns The value of \math{2e} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType one_over_e() { return 0.36787944117144232159552377016146086744581113103176; } ///< \returns The value of \math{\frac{1}{e}} with the highest precision for \emph{genType}
|
||||
|
||||
// Exponentiations of e
|
||||
template<typename genType> constexpr genType e_sq() { return 7.38905609893065022723042746057500781318031557055184; } ///< \returns The value of \f$e^2\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType e_cb() { return 20.08553692318766774092852965458171789698790783855415; } ///< \returns The value of \f$e^3\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType sqrt_e() { return 1.64872127070012814684865078781416357165377610071014; } ///< \returns The value of \f$\sqrt{e}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType one_over_sqrt_e() { return 0.60653065971263342360379953499118045344191813548718; } ///< \returns The value of \f$\frac{1}{\sqrt{e}}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType e_raised_two() { return 7.38905609893065022723042746057500781318031557055184; } ///< \returns The value of \f$e^e\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType e_raised_e() { return 15.15426224147926418976043027262991190552854853685613; } ///< \returns The value of \f$e^e\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType e_raised_neg_e() { return 0.065988035845312537076790187596846424938577048252796; } ///< \returns The value of \f$e^-e\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType e_sq() { return 7.38905609893065022723042746057500781318031557055184; } ///< \returns The value of \math{e^2} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType e_cb() { return 20.08553692318766774092852965458171789698790783855415; } ///< \returns The value of \math{e^3} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType sqrt_e() { return 1.64872127070012814684865078781416357165377610071014; } ///< \returns The value of \math{\sqrt{e}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType one_over_sqrt_e() { return 0.60653065971263342360379953499118045344191813548718; } ///< \returns The value of \math{\frac{1}{\sqrt{e}}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType e_raised_two() { return 7.38905609893065022723042746057500781318031557055184; } ///< \returns The value of \math{e^e} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType e_raised_e() { return 15.15426224147926418976043027262991190552854853685613; } ///< \returns The value of \math{e^e} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType e_raised_neg_e() { return 0.065988035845312537076790187596846424938577048252796; } ///< \returns The value of \math{e^-e} with the highest precision for \emph{genType}
|
||||
|
||||
// Exponentiations of e by Pi
|
||||
template<typename genType> constexpr genType e_raised_pi() { return 23.14069263277926900572908636794854738026610624260021; } ///< \returns The value of \f${e}^{ \pi}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType e_raised_neg_pi() { return 0.04321391826377224977441773717172801127572810981063; } ///< \returns The value of \f${e}^{-\pi}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType e_raised_half_pi() { return 4.81047738096535165547303566670383312639017087466453; } ///< \returns The value of \f${e}^{\frac{ \pi}{2}}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType e_raised_neg_half_pi() { return 0.20787957635076190854695561983497877003387784163176; } ///< \returns The value of \f${e}^{\frac{-\pi}{2}}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType e_raised_pi() { return 23.14069263277926900572908636794854738026610624260021; } ///< \returns The value of \math{{e}^{ \pi}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType e_raised_neg_pi() { return 0.04321391826377224977441773717172801127572810981063; } ///< \returns The value of \math{{e}^{-\pi}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType e_raised_half_pi() { return 4.81047738096535165547303566670383312639017087466453; } ///< \returns The value of \math{{e}^{\frac{ \pi}{2}}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType e_raised_neg_half_pi() { return 0.20787957635076190854695561983497877003387784163176; } ///< \returns The value of \math{{e}^{\frac{-\pi}{2}}} with the highest precision for \emph{genType}
|
||||
|
||||
// Exponentiations of e by Gamma
|
||||
template<typename genType> constexpr genType e_raised_gamma() { return 1.78107241799019798523650410310717954916964521430343; } ///< \returns The value of \f${e}^{ \gamma}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType e_raised_neg_gamma() { return 0.56145948356688516982414321479088078676571038692515; } ///< \returns The value of \f${e}^{-\gamma}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType e_raised_gamma() { return 1.78107241799019798523650410310717954916964521430343; } ///< \returns The value of \math{{e}^{ \gamma}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType e_raised_neg_gamma() { return 0.56145948356688516982414321479088078676571038692515; } ///< \returns The value of \math{{e}^{-\gamma}} with the highest precision for \emph{genType}
|
||||
|
||||
|
||||
|
||||
// Catalan's Constant ==================================================================================================
|
||||
|
||||
template<typename genType> constexpr genType G() { return 0.91596559417721901505460351493238411077414937428167; } ///< \returns The value of \f$G\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType one_over_G() { return 1.09174406370390610145415947333389232498605012140824; } ///< \returns The value of \f$\frac{1}{G}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType G_over_pi() { return 0.29156090403081878013838445646839491886406615398583; } ///< \returns The value of \f$\frac{G}{\pi}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType pi_over_G() { return 3.42981513013245864263455323784799901211670795530093; } ///< \returns The value of \f$\frac{\pi}{G}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType G() { return 0.91596559417721901505460351493238411077414937428167; } ///< \returns The value of \math{G} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType one_over_G() { return 1.09174406370390610145415947333389232498605012140824; } ///< \returns The value of \math{\frac{1}{G}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType G_over_pi() { return 0.29156090403081878013838445646839491886406615398583; } ///< \returns The value of \math{\frac{G}{\pi}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType pi_over_G() { return 3.42981513013245864263455323784799901211670795530093; } ///< \returns The value of \math{\frac{\pi}{G}} with the highest precision for \emph{genType}
|
||||
|
||||
|
||||
|
||||
// Gamma ===============================================================================================================
|
||||
|
||||
template<typename genType> constexpr genType y() { return 0.57721566490153286060651209008240243104215933593992; } ///< \returns The value of \f$\gamma\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType one_over_y() { return 1.73245471460063347358302531586082968115577655226680; } ///< \returns The value of \f$\frac{1}{\gamma}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType y() { return 0.57721566490153286060651209008240243104215933593992; } ///< \returns The value of \math{\gamma} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType one_over_y() { return 1.73245471460063347358302531586082968115577655226680; } ///< \returns The value of \math{\frac{1}{\gamma}} with the highest precision for \emph{genType}
|
||||
|
||||
|
||||
|
||||
// Logarithms ==========================================================================================================
|
||||
|
||||
template<typename genType> constexpr genType log_two() { return 0.69314718055994530941723212145817656807550013436025; } ///< \returns The value of \f$\log{2}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType log_three() { return 1.09861228866810969139524523692252570464749055782274; } ///< \returns The value of \f$\log{3}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType log_five() { return 1.60943791243410037460075933322618763952560135426851; } ///< \returns The value of \f$\log{5}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType log_seven() { return 1.94591014905531330510535274344317972963708472958186; } ///< \returns The value of \f$\log{7}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType log_ten() { return 2.30258509299404568401799145468436420760110148862877; } ///< \returns The value of \f$\log{10}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType one_over_log_ten() { return 0.43429448190325182765112891891660508229439700580366; } ///< \returns The value of \f$\frac{1}{\log{10}}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType log_two_over_log_three() { return 0.63092975357145743709952711434276085429958564013188; } ///< \returns The value of \f$\frac{\log{2}}{\log{3}}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType log_log_two() { return -0.36651292058166432701243915823266946945426344783711; } ///< \returns The value of \f$\log{\log{2}}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType log_pi() { return 1.14472988584940017414342735135305871164729481291531; } ///< \returns The value of \f$\log{\pi}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType log_sqrt_two() { return 0.91893853320467274178032973640561763986139747363778; } ///< \returns The value of \f$\log{\sqrt{2}}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType log_gamma() { return -0.54953931298164482233766176880290778833069898126306; } ///< \returns The value of \f$\log{\gamma}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType log_phi() { return 0.48121182505960344749775891342436842313518433438566; } ///< \returns The value of \f$\log{\phi}\f$ with the highest precision for \f$genType\f$
|
||||
template<typename genType> constexpr genType log_two() { return 0.69314718055994530941723212145817656807550013436025; } ///< \returns The value of \math{\log{2}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType log_three() { return 1.09861228866810969139524523692252570464749055782274; } ///< \returns The value of \math{\log{3}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType log_five() { return 1.60943791243410037460075933322618763952560135426851; } ///< \returns The value of \math{\log{5}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType log_seven() { return 1.94591014905531330510535274344317972963708472958186; } ///< \returns The value of \math{\log{7}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType log_ten() { return 2.30258509299404568401799145468436420760110148862877; } ///< \returns The value of \math{\log{10}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType one_over_log_ten() { return 0.43429448190325182765112891891660508229439700580366; } ///< \returns The value of \math{\frac{1}{\log{10}}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType log_two_over_log_three() { return 0.63092975357145743709952711434276085429958564013188; } ///< \returns The value of \math{\frac{\log{2}}{\log{3}}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType log_log_two() { return -0.36651292058166432701243915823266946945426344783711; } ///< \returns The value of \math{\log{\log{2}}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType log_pi() { return 1.14472988584940017414342735135305871164729481291531; } ///< \returns The value of \math{\log{\pi}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType log_sqrt_two() { return 0.91893853320467274178032973640561763986139747363778; } ///< \returns The value of \math{\log{\sqrt{2}}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType log_gamma() { return -0.54953931298164482233766176880290778833069898126306; } ///< \returns The value of \math{\log{\gamma}} with the highest precision for \emph{genType}
|
||||
template<typename genType> constexpr genType log_phi() { return 0.48121182505960344749775891342436842313518433438566; } ///< \returns The value of \math{\log{\phi}} with the highest precision for \emph{genType}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ constexpr genType sqnorm(const qua<genType>& q) {
|
||||
///
|
||||
/// \brief Norm Function
|
||||
/// \param q The Quaternion
|
||||
/// \returns The Hamilton Tensor of \f$q\f$
|
||||
/// \returns The Hamilton Tensor of \emph{q}
|
||||
template<typename genType>
|
||||
constexpr genType norm(const qua<genType>& q) {
|
||||
return fennec::sqrt(sqnorm(q));
|
||||
@@ -61,7 +61,7 @@ constexpr genType norm(const qua<genType>& q) {
|
||||
///
|
||||
/// \brief Unit Function (Versor)
|
||||
/// \param q The Quaternion
|
||||
/// \returns A Quaternion of \f$q\f$ with norm \f$1\f$
|
||||
/// \returns A Quaternion of \emph{q} with norm \math{1}
|
||||
template<typename genType>
|
||||
constexpr qua<genType> unit(const qua<genType>& q) {
|
||||
genType n = fennec::norm(q);
|
||||
@@ -71,7 +71,7 @@ constexpr qua<genType> unit(const qua<genType>& q) {
|
||||
///
|
||||
/// \brief Reciprocal Function
|
||||
/// \param q The Quaternion
|
||||
/// \returns The quaternion \f${q}^{-1}\f$
|
||||
/// \returns The quaternion \math{\textbf{q}^{-1}}
|
||||
template<typename genType>
|
||||
constexpr qua<genType> reciprocal(const qua<genType>& q) {
|
||||
return ~q / fennec::sqnorm(q);
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
// Constructors ========================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Default Constructor, creates a quaternion such that the real part is \f$1\f$ and all others are \f$0\f$
|
||||
/// \brief Default Constructor, creates a quaternion such that the real part is \math{1} and all others are \math{0}
|
||||
constexpr quaternion() {
|
||||
data = { 0, 0, 0, 1 };
|
||||
}
|
||||
@@ -107,9 +107,9 @@ public:
|
||||
///
|
||||
/// \brief Component Constructor
|
||||
/// \param w The scalar component
|
||||
/// \param x The coefficient of the \f$i\f$ component
|
||||
/// \param y The coefficient of the \f$j\f$ component
|
||||
/// \param z The coefficient of the \f$k\f$ component
|
||||
/// \param x The coefficient of the \emph{i} component
|
||||
/// \param y The coefficient of the \emph{j} component
|
||||
/// \param z The coefficient of the \emph{k} component
|
||||
constexpr quaternion(scalar_t w, scalar_t x, scalar_t y, scalar_t z) {
|
||||
data = { x, y, z, w };
|
||||
}
|
||||
@@ -160,7 +160,7 @@ public:
|
||||
///
|
||||
/// \brief Copy Assignment Operator
|
||||
/// \param q The quaternion to copy
|
||||
/// \returns a reference to self
|
||||
/// \returns a reference to \emph{this}
|
||||
constexpr quat_t& operator=(const quat_t& q) {
|
||||
data = q.data;
|
||||
return *this;
|
||||
@@ -169,7 +169,7 @@ public:
|
||||
///
|
||||
/// \brief Move Assignment Operator
|
||||
/// \param q The quaternion to move
|
||||
/// \returns a reference to self
|
||||
/// \returns a reference to \emph{this}
|
||||
constexpr quat_t& operator=(quat_t&& q) noexcept {
|
||||
data = q.data;
|
||||
return *this;
|
||||
@@ -182,7 +182,7 @@ public:
|
||||
/// \brief Equality Operator
|
||||
/// \param lhs the left hand side of the expression
|
||||
/// \param rhs the right hand side of the expression
|
||||
/// \returns \f$true\f$ when all components of \f$lhs\f$ and \f$rhs\f$ are equal, false otherwise
|
||||
/// \returns \emph{true} when all components of \emph{lhs} and \emph{rhs} are equal, false otherwise
|
||||
constexpr friend bool operator==(const quat_t& lhs, const quat_t& rhs) {
|
||||
return lhs.data == rhs.data;
|
||||
}
|
||||
@@ -191,7 +191,7 @@ public:
|
||||
/// \brief Inequality Operator
|
||||
/// \param lhs the left hand side of the expression
|
||||
/// \param rhs the right hand side of the expression
|
||||
/// \returns \f$true\f$ when any component of \f$lhs\f$ and \f$rhs\f$ are not equal, false otherwise
|
||||
/// \returns \emph{true} when any component of \emph{lhs} and \emph{rhs} are not equal, false otherwise
|
||||
constexpr friend bool operator!=(const quat_t& lhs, const quat_t& rhs) {
|
||||
return lhs.data != rhs.data;
|
||||
}
|
||||
@@ -202,7 +202,7 @@ public:
|
||||
///
|
||||
/// \brief Unary Negation Operator
|
||||
/// \param rhs The quaternion to negate
|
||||
/// \returns A quaternion with each component of \f$rhs\f$ negated.
|
||||
/// \returns A quaternion with each component of \emph{rhs} negated.
|
||||
constexpr friend quat_t operator-(const quat_t& rhs) {
|
||||
return quat_t(-rhs.w, -rhs.x, -rhs.y, -rhs.z);
|
||||
}
|
||||
@@ -210,7 +210,7 @@ public:
|
||||
///
|
||||
/// \brief Unary Conjugation Operator
|
||||
/// \param rhs The quaternion to conjugate
|
||||
/// \returns A quaternion with each vector component of \f$rhs\f$ negated.
|
||||
/// \returns A quaternion with each vector component of \emph{rhs} negated.
|
||||
constexpr friend quat_t operator~(const quat_t& rhs) {
|
||||
return quat_t(rhs.w, -rhs.x, -rhs.y, -rhs.z);
|
||||
}
|
||||
@@ -222,7 +222,7 @@ public:
|
||||
/// \brief Quaternion-Scalar Multiplication Operator
|
||||
/// \param lhs The quaternion
|
||||
/// \param rhs The scalar
|
||||
/// \returns A quaternion with each component of \f$lhs\f$ multiplied by \f$rhs\f$
|
||||
/// \returns A quaternion with each component of \emph{lhs} multiplied by \emph{rhs}
|
||||
constexpr friend quat_t operator*(const quat_t& lhs, scalar_t rhs) {
|
||||
return quat_t(lhs.w * rhs, lhs.x * rhs, lhs.y * rhs, lhs.z * rhs);
|
||||
}
|
||||
@@ -231,7 +231,7 @@ public:
|
||||
/// \brief Scalar-Quaternion Multiplication Operator
|
||||
/// \param lhs The scalar
|
||||
/// \param rhs The quaternion
|
||||
/// \returns A quaternion with each component of \f$rhs\f$ multiplied by \f$lhs\f$
|
||||
/// \returns A quaternion with each component of \emph{rhs} multiplied by \emph{lhs}
|
||||
constexpr friend quat_t operator*(scalar_t lhs, const quat_t& rhs) {
|
||||
return quat_t(lhs * rhs.w, lhs * rhs.x, lhs * rhs.y, lhs * rhs.z);
|
||||
}
|
||||
@@ -240,7 +240,7 @@ public:
|
||||
/// \brief Quaternion-Scalar Division Operator
|
||||
/// \param lhs The quaternion
|
||||
/// \param rhs The scalar
|
||||
/// \returns A quaternion with each component of \f$lhs\f$ divided by \f$rhs\f$
|
||||
/// \returns A quaternion with each component of \emph{lhs} divided by \emph{rhs}
|
||||
constexpr friend quat_t operator/(const quat_t& lhs, scalar_t rhs) {
|
||||
return quat_t(lhs.w / rhs, lhs.x / rhs, lhs.y / rhs, lhs.z / rhs);
|
||||
}
|
||||
@@ -249,7 +249,7 @@ public:
|
||||
/// \brief Scalar-Quaternion Division Operator
|
||||
/// \param lhs The scalar
|
||||
/// \param rhs The quaternion
|
||||
/// \returns A quaternion with each component of \f$rhs\f$ divided by \f$lhs\f$
|
||||
/// \returns A quaternion with each component of \emph{rhs} divided by \emph{lhs}
|
||||
constexpr friend quat_t operator/(scalar_t lhs, const quat_t& rhs) {
|
||||
return quat_t(lhs / rhs.w, lhs / rhs.x, lhs / rhs.y, lhs / rhs.z);
|
||||
}
|
||||
@@ -261,7 +261,7 @@ public:
|
||||
/// \brief Quaternion-Scalar Multiplication Assignment Operator
|
||||
/// \param lhs The quaternion
|
||||
/// \param rhs The scalar
|
||||
/// \returns \f$lhs\f$ with each component multiplied by \f$rhs\f$
|
||||
/// \returns \emph{lhs} with each component multiplied by \emph{rhs}
|
||||
constexpr friend quat_t& operator*=(quat_t& lhs, scalar_t rhs) {
|
||||
lhs.x *= rhs;
|
||||
lhs.y *= rhs;
|
||||
@@ -274,7 +274,7 @@ public:
|
||||
/// \brief Quaternion-Scalar Division Assignment Operator
|
||||
/// \param lhs The quaternion
|
||||
/// \param rhs The scalar
|
||||
/// \returns \f$lhs\f$ with each component divided by \f$rhs\f$
|
||||
/// \returns \emph{lhs} with each component divided by \emph{rhs}
|
||||
constexpr friend quat_t& operator/=(const quat_t& lhs, scalar_t rhs) {
|
||||
lhs.x /= rhs;
|
||||
lhs.y /= rhs;
|
||||
@@ -290,7 +290,7 @@ public:
|
||||
/// \brief Quaternion-Vector Multiplication Operator
|
||||
/// \param q the quaternion
|
||||
/// \param v the vector
|
||||
/// \returns the linear algebraic product of \f$q\f$ and \f$v\f$
|
||||
/// \returns the linear algebraic product of \emph{q} and \emph{v}
|
||||
constexpr friend vec3_t operator*(const quat_t& q, const vec3_t& v) {
|
||||
const vec3_t u = q.xyz;
|
||||
const vec3_t uv = fennec::cross(u, v);
|
||||
@@ -302,7 +302,7 @@ public:
|
||||
/// \brief Vector-Quaternion Multiplication Operator
|
||||
/// \param v the vector
|
||||
/// \param q the quaternion
|
||||
/// \returns the linear algebraic product of \f$v\f$ and \f$q\f$
|
||||
/// \returns the linear algebraic product of \emph{v} and \emph{q}
|
||||
constexpr friend vec3_t operator*(const vec3_t& v, const quat_t& q) {
|
||||
return fennec::reciprocal(q) * v;
|
||||
}
|
||||
@@ -311,7 +311,7 @@ public:
|
||||
/// \brief Quaternion-Vector Multiplication Operator
|
||||
/// \param q the quaternion
|
||||
/// \param v the vector
|
||||
/// \returns the linear algebraic product of \f$q\f$ and \f$v\f$
|
||||
/// \returns the linear algebraic product of \emph{q} and \emph{v}
|
||||
constexpr friend vec4_t operator*(const quat_t& q, const vec4_t& v) {
|
||||
return vec4_t(q * v.xyz, v.w);
|
||||
}
|
||||
@@ -320,7 +320,7 @@ public:
|
||||
/// \brief Vector-Quaternion Multiplication Operator
|
||||
/// \param v the vector
|
||||
/// \param q the quaternion
|
||||
/// \returns the linear algebraic product of \f$v\f$ and \f$q\f$
|
||||
/// \returns the linear algebraic product of \emph{v} and \emph{q}
|
||||
constexpr friend vec4_t operator*(const vec4_t& v, const quat_t& q) {
|
||||
return fennec::reciprocal(q) * v;
|
||||
}
|
||||
@@ -332,7 +332,7 @@ public:
|
||||
/// \brief Quaternion-Quaternion Addition Operator
|
||||
/// \param lhs the left hand side
|
||||
/// \param rhs the right hand side
|
||||
/// \returns the component-wise sum of \f$lhs\f$ and \f$rhs\f$
|
||||
/// \returns the component-wise sum of \emph{lhs} and \emph{rhs}
|
||||
constexpr friend quat_t operator+(const quat_t& lhs, const quat_t& rhs) {
|
||||
return quat_t(
|
||||
lhs.w + rhs.w,
|
||||
@@ -346,7 +346,7 @@ public:
|
||||
/// \brief Quaternion-Quaternion Subtraction Operator
|
||||
/// \param lhs the left hand side
|
||||
/// \param rhs the right hand side
|
||||
/// \returns the component-wise difference of \f$lhs\f$ and \f$rhs\f$
|
||||
/// \returns the component-wise difference of \emph{lhs} and \emph{rhs}
|
||||
constexpr friend quat_t operator-(const quat_t& lhs, const quat_t& rhs) {
|
||||
return quat_t(
|
||||
lhs.w - rhs.w,
|
||||
@@ -360,7 +360,7 @@ public:
|
||||
/// \brief Quaternion-Quaternion Multiplication Operator
|
||||
/// \param lhs the left hand side
|
||||
/// \param rhs the right hand side
|
||||
/// \returns the linear algebraic product of \f$lhs\f$ and \f$rhs\f$
|
||||
/// \returns the linear algebraic product of \emph{lhs} and \emph{rhs}
|
||||
constexpr friend quat_t operator*(const quat_t& lhs, const quat_t& rhs) {
|
||||
return quat_t(
|
||||
lhs.w*rhs.w - lhs.x*rhs.x - lhs.y*rhs.y - lhs.z * rhs.z,
|
||||
@@ -377,7 +377,7 @@ public:
|
||||
/// \brief Quaternion-Quaternion Addition Assignment Operator
|
||||
/// \param lhs the left hand side
|
||||
/// \param rhs the right hand side
|
||||
/// \returns the component-wise sum of \f$lhs\f$ and \f$rhs\f$ stored in \f$lhs\f$
|
||||
/// \returns the component-wise sum of \emph{lhs} and \emph{rhs} stored in \emph{lhs}
|
||||
constexpr friend quat_t& operator+=(quat_t& lhs, const quat_t& rhs) {
|
||||
lhs.w += rhs.w;
|
||||
lhs.x += rhs.x;
|
||||
@@ -390,7 +390,7 @@ public:
|
||||
/// \brief Quaternion-Quaternion Subtraction Assignment Operator
|
||||
/// \param lhs the left hand side
|
||||
/// \param rhs the right hand side
|
||||
/// \returns the component-wise difference of \f$lhs\f$ and \f$rhs\f$ stored in \f$lhs\f$
|
||||
/// \returns the component-wise difference of \emph{lhs} and \emph{rhs} stored in \emph{lhs}
|
||||
constexpr friend quat_t& operator-=(quat_t& lhs, const quat_t& rhs) {
|
||||
lhs.w -= rhs.w;
|
||||
lhs.x -= rhs.x;
|
||||
@@ -403,7 +403,7 @@ public:
|
||||
/// \brief Quaternion-Quaternion Multiplication Assignment Operator
|
||||
/// \param lhs the left hand side
|
||||
/// \param rhs the right hand side
|
||||
/// \returns the linear algebraic product of \f$lhs\f$ and \f$rhs\f$ stored in \f$lhs\f$
|
||||
/// \returns the linear algebraic product of \emph{lhs} and \emph{rhs} stored in \emph{lhs}
|
||||
constexpr friend quat_t& operator*=(quat_t& lhs, const quat_t& rhs) {
|
||||
return lhs = lhs * rhs;
|
||||
}
|
||||
|
||||
@@ -118,14 +118,14 @@ namespace fennec
|
||||
// dot -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Returns the dot product of \f$x\f$ and \f$y\f$, i.e., \f$x_0 \cdot y_0 + x_1 \cdot y_1 + \ldots\f$
|
||||
/// \brief Returns the dot product of \math{x} and \math{y}, i.e., \math{x_0 \cdot y_0 + x_1 \cdot y_1 + \ldots}
|
||||
///
|
||||
/// \returns the dot product of \f$x\f$ and \f$y\f$, i.e., \f$x_0 \cdot y_0 + x_0 \cdot y_0 + \ldots\f$ <br><br>
|
||||
/// \returns the dot product of \math{x} and \math{y}, i.e., \math{x_0 \cdot y_0 + x_0 \cdot y_0 + \ldots} <br><br>
|
||||
/// \details we can represent this in linear algebra as the following, <br><br>
|
||||
/// let \f$X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]\f$ <br>
|
||||
/// let \f$Y=\left[\begin{array}\\ y_0 \\ y_1 \\ \vdots \\ y_N \end{array}\right]\f$ <br><br>
|
||||
/// let \math{X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]} <br>
|
||||
/// let \math{Y=\left[\begin{array}\\ y_0 \\ y_1 \\ \vdots \\ y_N \end{array}\right]} <br><br>
|
||||
///
|
||||
/// then \f$\text{dot}(X, Y)=X \cdot Y^T\f$ <br><br>
|
||||
/// then \math{\text{dot}(X, Y)=X \cdot Y^T} <br><br>
|
||||
///
|
||||
/// \param x first vector
|
||||
/// \param y second vector
|
||||
@@ -138,13 +138,13 @@ constexpr genType dot(const vector<genType, i...>& x, const vector<genType, i...
|
||||
// length2 -------------------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Returns the squared length of vector \f$x\f$, i.e., \f$x_0^2 + x_1^2 + \ldots\f$
|
||||
/// \brief Returns the squared length of vector \math{x}, i.e., \math{x_0^2 + x_1^2 + \ldots}
|
||||
///
|
||||
/// \returns the squared length of vector \f$x\f$, i.e., \f$x_0^2 + x_1^2 + \ldots\f$ <br><br>
|
||||
/// \returns the squared length of vector \math{x}, i.e., \math{x_0^2 + x_1^2 + \ldots} <br><br>
|
||||
/// \details we can represent this in linear algebra as the following, <br><br>
|
||||
/// let \f$X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]\f$ <br><br>
|
||||
/// let \math{X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]} <br><br>
|
||||
///
|
||||
/// then \f$\text{length2}(X)=X \cdot X^T\f$ <br><br>
|
||||
/// then \math{\text{length2}(X)=X \cdot X^T} <br><br>
|
||||
///
|
||||
/// \param x the vector
|
||||
template<typename genType, size_t...i>
|
||||
@@ -156,13 +156,13 @@ constexpr genType length2(const vector<genType, i...>& x) {
|
||||
// length --------------------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Returns the length of vector \f$x\f$, i.e., \f$\sqrt{x_0^2 + x_1^2 + \ldots}\f$
|
||||
/// \brief Returns the length of vector \math{x}, i.e., \math{\sqrt{x_0^2 + x_1^2 + \ldots}}
|
||||
///
|
||||
/// \returns the length of vector \f$x\f$, i.e., \f$\sqrt{x_0^2 + x_1^2 + \ldots}\f$<br><br>
|
||||
/// \returns the length of vector \math{x}, i.e., \math{\sqrt{x_0^2 + x_1^2 + \ldots}}<br><br>
|
||||
/// \details we can represent this in linear algebra as the following, <br><br>
|
||||
/// let \f$X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]\f$ <br><br>
|
||||
/// let \math{X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]} <br><br>
|
||||
///
|
||||
/// then, \f$\text{length}(X)=\left|\left|X\right|\right|\f$ <br><br>
|
||||
/// then, \math{\text{length}(X)=\left|\left|X\right|\right|} <br><br>
|
||||
///
|
||||
/// \param x the vector
|
||||
template<typename genType, size_t...i>
|
||||
@@ -174,14 +174,14 @@ constexpr genType length(const vector<genType, i...>& x) {
|
||||
// distance ------------------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Returns the length of vector \f$x\f$, i.e., \f$\sqrt{x_0^2 + x_1^2 + \ldots}\f$
|
||||
/// \brief Returns the length of vector \math{x}, i.e., \math{\sqrt{x_0^2 + x_1^2 + \ldots}}
|
||||
///
|
||||
/// \returns the distance between \f$p_0\f$ and \f$p_1\f$, i.e., \f$\left|{p_1-p_0}\right|\f$
|
||||
/// \returns the distance between \math{p_0} and \math{p_1}, i.e., \math{\left|{p_1-p_0}\right|}
|
||||
/// \details we can represent this in linear algebra as the following, <br><br>
|
||||
/// let \f$X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]\f$ <br>
|
||||
/// let \f$Y=\left[\begin{array}\\ y_0 \\ y_1 \\ \vdots \\ y_N \end{array}\right]\f$ <br><br>
|
||||
/// let \math{X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]} <br>
|
||||
/// let \math{Y=\left[\begin{array}\\ y_0 \\ y_1 \\ \vdots \\ y_N \end{array}\right]} <br><br>
|
||||
///
|
||||
/// then \f$\text{distance}(X, Y)=\left|\left|Y-X\right|\right|\f$ <br><br>
|
||||
/// then \math{\text{distance}(X, Y)=\left|\left|Y-X\right|\right|} <br><br>
|
||||
///
|
||||
/// \param p0 first vector
|
||||
/// \param p1 second vector
|
||||
@@ -194,16 +194,16 @@ constexpr genType distance(const vector<genType, i...>& p0, const vector<genType
|
||||
// cross ---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Returns the cross product of \f$x\f$ and \f$y\f$, i.e.,
|
||||
/// \f$\left({x_1 \cdot y_2 - y_1 \cdot x_2, x_2 \cdot y_0 - y_2 \cdot x_0, x_0 \cdot y_1 - y_0 \cdot x_1}\right)\f$
|
||||
/// \brief Returns the cross product of \math{x} and \math{y}, i.e.,
|
||||
/// \math{\left({x_1 \cdot y_2 - y_1 \cdot x_2, x_2 \cdot y_0 - y_2 \cdot x_0, x_0 \cdot y_1 - y_0 \cdot x_1}\right)}
|
||||
///
|
||||
/// \returns the cross product of \f$x\f$ and \f$y\f$, i.e.,
|
||||
/// \f$\left({x_1 \cdot y_2 - y_1 \cdot x_2, x_2 \cdot y_0 - y_2 \cdot x_0, x_0 \cdot y_1 - y_0 \cdot x_1}\right)\f$ <br><br>
|
||||
/// \returns the cross product of \math{x} and \math{y}, i.e.,
|
||||
/// \math{\left({x_1 \cdot y_2 - y_1 \cdot x_2, x_2 \cdot y_0 - y_2 \cdot x_0, x_0 \cdot y_1 - y_0 \cdot x_1}\right)} <br><br>
|
||||
/// \details we can represent this in linear algebra as the following, <br><br>
|
||||
/// let \f$X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]\f$ <br>
|
||||
/// let \f$Y=\left[\begin{array}\\ y_0 \\ y_1 \\ \vdots \\ y_N \end{array}\right]\f$ <br><br>
|
||||
/// let \math{X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]} <br>
|
||||
/// let \math{Y=\left[\begin{array}\\ y_0 \\ y_1 \\ \vdots \\ y_N \end{array}\right]} <br><br>
|
||||
///
|
||||
/// then \f$\text{cross}(X, Y)=X \times Y\f$ <br><br>
|
||||
/// then \math{\text{cross}(X, Y)=X \times Y} <br><br>
|
||||
///
|
||||
/// \param x first vector
|
||||
/// \param y second vector
|
||||
@@ -216,13 +216,13 @@ constexpr vector<genType, i...> cross(const vector<genType, i...>& x, const vect
|
||||
// normalize -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief Returns a vector in the same direction as \f$x\f$, but with a length of \f$1\f$, i.e.
|
||||
/// \brief Returns a vector in the same direction as \math{x}, but with a length of \math{1}, i.e.
|
||||
///
|
||||
/// \returns a vector in the same direction as \f$x\f$, but with a length of \f$1\f$, i.e.\f$\frac{x}{||x||}\f$<br><br>
|
||||
/// \returns a vector in the same direction as \math{x}, but with a length of \math{1}, i.e.\math{\frac{x}{||x||}}<br><br>
|
||||
/// \details we can represent this in linear algebra as the following, <br><br>
|
||||
/// let \f$X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]\f$ <br><br>
|
||||
/// let \math{X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]} <br><br>
|
||||
///
|
||||
/// then, \f$\text{length}(X)=\frac{X}{\left|\left|X\right|\right|}\f$ <br><br>
|
||||
/// then, \math{\text{length}(X)=\frac{X}{\left|\left|X\right|\right|}} <br><br>
|
||||
///
|
||||
/// \param x
|
||||
template<typename genType, size_t...i>
|
||||
@@ -234,9 +234,9 @@ constexpr vector<genType, i...> normalize(const vector<genType, i...>& x) {
|
||||
// faceforward ---------------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief If \f$\text{dot}(Nref, I)<0\f$ return \f$N\f$, otherwise return \f$-N\f$.
|
||||
/// \brief If \math{\text{dot}(Nref, I)<0} return \math{N}, otherwise return \math{-N}.
|
||||
///
|
||||
/// \returns \f$N\f$ if \f$\text{dot}(Nref,I)<0\f$, otherwise, returns \f$-N\f$.<br><br>
|
||||
/// \returns \math{N} if \math{\text{dot}(Nref,I)<0}, otherwise, returns \math{-N}.<br><br>
|
||||
///
|
||||
/// \param N the vector
|
||||
/// \param I the incident
|
||||
@@ -250,11 +250,11 @@ constexpr vector<genType, i...> faceforward(const vector<genType, i...>& N, cons
|
||||
// reflect -------------------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief For the incident vector \f$I\f$ and surface orientation \f$N\f$, returns the reflection direction.
|
||||
/// \brief For the incident vector \math{I} and surface orientation \math{N}, returns the reflection direction.
|
||||
///
|
||||
/// \returns The reflection direction, given the incident vector \f$I\f$ and surface orientation \f$N\f$ <br><br>
|
||||
/// \returns The reflection direction, given the incident vector \math{I} and surface orientation \math{N} <br><br>
|
||||
/// \details We can express this as, <br><br>
|
||||
/// \f$\text{reflect}(I, N) = I - 2 N \cdot \text{dot}(N, I)\f$ <br><br>
|
||||
/// \math{\text{reflect}(I, N) = I - 2 N \cdot \text{dot}(N, I)} <br><br>
|
||||
///
|
||||
/// \param I the incident
|
||||
/// \param N the surface orientation
|
||||
@@ -266,13 +266,13 @@ constexpr vector<genType, i...> reflect(const vector<genType, i...>& I, const ve
|
||||
// refract -------------------------------------------------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// \brief For the incident vector \f$I\f$ and surface normal \f$N\f$, and the ratio of indices of refraction \f$eta\f$,
|
||||
/// \brief For the incident vector \math{I} and surface normal \math{N}, and the ratio of indices of refraction \math{eta},
|
||||
/// return the refraction vector.
|
||||
///
|
||||
/// \returns The refraction vector, given the incident vector \f$I\f$, surface normal \f$N\f$, and ratio \f$eta\f$.<br><br>
|
||||
/// \returns The refraction vector, given the incident vector \math{I}, surface normal \math{N}, and ratio \math{eta}.<br><br>
|
||||
/// \details The result is computed by the refraction equation, <br><br>
|
||||
/// let \f$k=1.0-eta^2 \cdot (1.0 - \text{dot}(N, I)^2)\f$ <br>
|
||||
/// then, \f$\text{refract}(I, N, eta)=\begin{cases} 0.0 & k<0.0, \\ eta \cdot I - N \cdot (eta \cdot \text{dot}(N, I) + \sqrt{k}) \end{cases}\f$ <br><br>
|
||||
/// let \math{k=1.0-eta^2 \cdot (1.0 - \text{dot}(N, I)^2)} <br>
|
||||
/// then, \math{\text{refract}(I, N, eta)=\begin{cases} 0.0 & k<0.0, \\ eta \cdot I - N \cdot (eta \cdot \text{dot}(N, I) + \sqrt{k}) \end{cases}} <br><br>
|
||||
///
|
||||
/// \param I the incident
|
||||
/// \param N the surface normal
|
||||
|
||||
@@ -56,10 +56,10 @@ namespace fennec
|
||||
|
||||
|
||||
///
|
||||
/// \brief returns a **copy** of the column \f$i\f$ of matrix \f$m\f$
|
||||
/// \brief returns a **copy** of the column \emph{i} of matrix \emph{m}
|
||||
/// \param m the matrix
|
||||
/// \param i the index of the row
|
||||
/// \returns a **copy** of the column at index \f$i\f$
|
||||
/// \returns a **copy** of the column at index \emph{i}
|
||||
template<typename scalar, size_t rows, size_t...cols>
|
||||
constexpr vec<scalar, rows> column(const matrix<scalar, rows, cols...>& m, size_t i) noexcept {
|
||||
return m[i];
|
||||
@@ -67,10 +67,10 @@ constexpr vec<scalar, rows> column(const matrix<scalar, rows, cols...>& m, size_
|
||||
|
||||
|
||||
///
|
||||
/// \brief returns a **copy** of the row \f$i\f$ of matrix \f$m\f$
|
||||
/// \brief returns a **copy** of the row \emph{i} of matrix \emph{m}
|
||||
/// \param m the matrix
|
||||
/// \param i the index of the row
|
||||
/// \returns a **copy** of the row at index \f$i\f$
|
||||
/// \returns a **copy** of the row at index \emph{i}
|
||||
template<typename scalar, size_t rows, size_t...cols>
|
||||
constexpr vec<scalar, sizeof...(cols)> row(const matrix<scalar, rows, cols...>& m, size_t i) noexcept {
|
||||
return vec<scalar, sizeof...(cols)>(m[cols][i]...);
|
||||
@@ -118,7 +118,7 @@ using dmat4x4 = tmat4x4<double_t>; //!< Specification for size glsl double matri
|
||||
|
||||
|
||||
///
|
||||
/// \brief Multiply matrix \f$x\f$ by matrix \f$y\f$ component-wise.
|
||||
/// \brief Multiply matrix \emph{x} by matrix \emph{y} component-wise.
|
||||
/// \details Multiply matrix x by matrix y component-wise, i.e., result[i][j] is the scalar product of x[i][j] and y[i][j].<br><br>
|
||||
/// Note: to get linear algebraic matrix multiplication, use
|
||||
/// the multiply operator (*)
|
||||
@@ -131,14 +131,14 @@ constexpr matrix<scalar, rows, cols...> matrixCompMult(const matrix<scalar, rows
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Performs a linear algebraic multiply, multiplying \f$c\f$ by the components of \f$r\f$, producing a matrix.
|
||||
/// \brief Performs a linear algebraic multiply, multiplying \emph{c} by the components of \emph{r}, producing a matrix.
|
||||
///
|
||||
/// \details Treats the first parameter \f$c\f$ as a column vector (matrix
|
||||
/// with one column) and the second parameter \f$r\f$ as a row
|
||||
/// \details Treats the first parameter \emph{c} as a column vector (matrix
|
||||
/// with one column) and the second parameter \emph{r} as a row
|
||||
/// vector (matrix with one row) and does a linear algebraic
|
||||
/// matrix multiply \f$c \cross r\f$, yielding a matrix whose number of
|
||||
/// rows is the number of components in \f$c\f$ and whose
|
||||
/// number of columns is the number of components in \f$r\f$.
|
||||
/// matrix multiply \emph{c \cross r}, yielding a matrix whose number of
|
||||
/// rows is the number of components in \emph{c} and whose
|
||||
/// number of columns is the number of components in \emph{r}.
|
||||
/// \param c the column vector
|
||||
/// \param r the row vector
|
||||
/// \returns the resulting matrix produced by the linear algebraic product
|
||||
@@ -150,9 +150,9 @@ constexpr matrix<scalar, sizeof...(s0), s1...> outerProduct(const vector<scalar,
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief get the transpose of \f$m\f$
|
||||
/// \brief get the transpose of \emph{m}
|
||||
/// \param m the matrix to transpose
|
||||
/// \returns a matrix that is the transpose of \f$m\f$
|
||||
/// \returns a matrix that is the transpose of \emph{m}
|
||||
/// \details The input matrix m is not modified.
|
||||
template<typename scalar, size_t rows, size_t...cols>
|
||||
constexpr mat<scalar, rows, sizeof...(cols)> transpose(const matrix<scalar, rows, cols...>& m) noexcept {
|
||||
@@ -160,7 +160,7 @@ constexpr mat<scalar, rows, sizeof...(cols)> transpose(const matrix<scalar, rows
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Returns the determinant of \f$m\f$.
|
||||
/// \brief Returns the determinant of \emph{m}.
|
||||
/// \returns the determinant of m.
|
||||
template<typename scalar, size_t rows, size_t...cols>
|
||||
constexpr scalar determinant(const matrix<scalar, rows, cols...>&) noexcept {
|
||||
@@ -169,8 +169,8 @@ constexpr scalar determinant(const matrix<scalar, rows, cols...>&) noexcept {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Returns the determinant of \f$m\f$.
|
||||
/// \returns \f$m^{-1}\f$
|
||||
/// \brief Returns the determinant of \emph{m}.
|
||||
/// \returns \math{\textbf{m}^{-1}}
|
||||
template<typename scalar, size_t rows, size_t...cols>
|
||||
constexpr matrix<scalar, rows, cols...> inverse(const matrix<scalar, rows, cols...>&) noexcept {
|
||||
static_assert(false, "implementation undefined");
|
||||
@@ -295,7 +295,7 @@ struct matrix
|
||||
/// \brief scalar constructor, initializes a diagonal matrix with a scale of \p s
|
||||
///
|
||||
/// \details
|
||||
/// This function creates a diagonal matrix such that ```vec3(2.0f)``` would result in a matrix
|
||||
/// This function creates a diagonal matrix such that `(.*?)` would result in a matrix
|
||||
/// <table>
|
||||
/// <caption id="fennec_table_matrix_diagonal"></caption>
|
||||
/// <tr><th> <th> 0 <th> 1 <th> 2
|
||||
@@ -359,17 +359,17 @@ struct matrix
|
||||
///
|
||||
/// \details
|
||||
/// \param i the index
|
||||
/// \returns the column at index \f$i\f$
|
||||
/// \returns the column at index \emph{i}
|
||||
constexpr column_t& operator[](size_t i) {
|
||||
return data[i];
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief returns the column at index \f$i\f$
|
||||
/// \brief returns the column at index \emph{i}
|
||||
///
|
||||
/// \details
|
||||
/// \param i the index
|
||||
/// \returns the column at index \f$i\f$
|
||||
/// \returns the column at index \emph{i}
|
||||
constexpr const column_t& operator[](size_t i) const {
|
||||
return data[i];
|
||||
}
|
||||
@@ -378,7 +378,7 @@ struct matrix
|
||||
/// \details
|
||||
/// \param i the column
|
||||
/// \param j the row
|
||||
/// \returns the element in column \f$i\f$, row \f$j\f$
|
||||
/// \returns the element in column \emph{i}, row \emph{j}
|
||||
constexpr scalar_t& operator[](size_t i, size_t j) {
|
||||
return data[i][j];
|
||||
}
|
||||
@@ -389,7 +389,7 @@ struct matrix
|
||||
/// \details
|
||||
/// \param i the column
|
||||
/// \param j the row
|
||||
/// \returns the element in column \f$i\f$, row \f$j\f$
|
||||
/// \returns the element in column \emph{i}, row \emph{j}
|
||||
constexpr scalar_t operator[](size_t i, size_t j) const {
|
||||
return data[i][j];
|
||||
}
|
||||
@@ -610,7 +610,7 @@ struct matrix
|
||||
/// \brief performs a linear algebraic multiply
|
||||
/// \param lhs the matrix
|
||||
/// \param rhs the vector
|
||||
/// \returns a vector containing the dot products of \f$rhs\f$ with each row of \f$lhs\f$
|
||||
/// \returns a vector containing the dot products of \emph{rhs} with each row of \emph{lhs}
|
||||
constexpr friend column_t operator*(const matrix_t& lhs, const row_t& rhs) {
|
||||
return _mul(lhs, rhs);
|
||||
}
|
||||
@@ -619,7 +619,7 @@ struct matrix
|
||||
/// \brief performs a linear algebraic multiply
|
||||
/// \param lhs the vector
|
||||
/// \param rhs the matrix
|
||||
/// \returns a vector containing the dot products of \f$lhs\f$ with each column of \f$rhs\f$
|
||||
/// \returns a vector containing the dot products of \emph{lhs} with each column of \emph{rhs}
|
||||
constexpr friend row_t operator*(const column_t& lhs, const matrix_t& rhs) {
|
||||
return row_t(fennec::dot(fennec::column(rhs, ColIndicesV), lhs) ...);
|
||||
}
|
||||
@@ -637,7 +637,7 @@ struct matrix
|
||||
/// \brief matrix comparison operator
|
||||
/// \param lhs the first matrix
|
||||
/// \param rhs the second matrix
|
||||
/// \returns a boolean value that contains \f$true\f$ when all components of \f$lhs\f$ and \f$rhs\f$ are equal and \f$false\f$ otherwise
|
||||
/// \returns a boolean value that contains \emph{true} when all components of \emph{lhs} and \emph{rhs} are equal and \emph{false} otherwise
|
||||
constexpr friend bool operator==(const matrix_t& lhs, const matrix_t& rhs) {
|
||||
return lhs.data == rhs.data;
|
||||
}
|
||||
@@ -646,7 +646,7 @@ struct matrix
|
||||
/// \brief matrix comparison operator
|
||||
/// \param lhs the first matrix
|
||||
/// \param rhs the second matrix
|
||||
/// \returns a boolean value that contains \f$true\f$ when all components of \f$lhs\f$ and \f$rhs\f$ are not equal and \f$false\f$ otherwise
|
||||
/// \returns a boolean value that contains \emph{true} when all components of \emph{lhs} and \emph{rhs} are not equal and \emph{false} otherwise
|
||||
constexpr friend bool operator!=(const matrix_t& lhs, const matrix_t& rhs) {
|
||||
return lhs.data != rhs.data;
|
||||
}
|
||||
@@ -666,7 +666,7 @@ struct matrix
|
||||
///
|
||||
/// \brief performs a linear algebraic matrix multiplication assignment
|
||||
/// \param rhs the columns to multiply with
|
||||
/// \returns a reference to self
|
||||
/// \returns a reference to \emph{this}
|
||||
template<size_t ORowsV, size_t...OColIndicesV> requires(columns == ORowsV)
|
||||
constexpr matrix<scalar_t, RowsV, OColIndicesV...>& operator*=(const matrix<scalar_t, ORowsV, OColIndicesV...>& rhs) {
|
||||
return *this = *this * rhs;
|
||||
@@ -682,7 +682,7 @@ public:
|
||||
|
||||
///
|
||||
/// \param mat the matrix to transpose
|
||||
/// \returns \f$m^T\f$
|
||||
/// \returns \math{\textbf{m}^T}
|
||||
static constexpr matrix_t transpose(const transpose_t& mat) {
|
||||
return matrix_t(fennec::row(mat, ColIndicesV)...);
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
/// \ref fennec_vector_not "bool not(bvec x)"<br>
|
||||
/// <td width="50%" style="vertical-align: top">
|
||||
/// \details
|
||||
/// \returns the component-wise logical complement of \f$x\f$. <br>
|
||||
/// \returns the component-wise logical complement of \math{x}. <br>
|
||||
/// \param x the boolean vector to inverse <br>
|
||||
///
|
||||
/// </table>
|
||||
@@ -189,9 +189,9 @@ constexpr vector<genBType, i...> notEqual(const vector<genType, i...>& x, const
|
||||
|
||||
|
||||
///
|
||||
/// \brief Returns \f$true\f$ if any component of \f$x\f$ is \f$true\f$
|
||||
/// \brief Returns \math{true} if any component of \math{x} is \math{true}
|
||||
///
|
||||
/// \returns \f$true\f$ if any component of \f$x\f$ is \f$true\f$
|
||||
/// \returns \math{true} if any component of \math{x} is \math{true}
|
||||
/// \param x the boolean vector to test
|
||||
template<typename genBType = bool_t, size_t...i>
|
||||
constexpr genBType any(const vector<genBType, i...>& x) {
|
||||
@@ -199,9 +199,9 @@ constexpr genBType any(const vector<genBType, i...>& x) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Returns \f$true\f$ if all components of \f$x\f$ are \f$true\f$
|
||||
/// \brief Returns \math{true} if all components of \math{x} are \math{true}
|
||||
///
|
||||
/// \returns \f$true\f$ if all components of \f$x\f$ are \f$true\f$
|
||||
/// \returns \math{true} if all components of \math{x} are \math{true}
|
||||
/// \param x the boolean vector to test
|
||||
template<typename genBType = bool_t, size_t...i>
|
||||
constexpr genBType all(const vector<genBType, i...>& x) {
|
||||
@@ -210,10 +210,10 @@ constexpr genBType all(const vector<genBType, i...>& x) {
|
||||
|
||||
///
|
||||
/// \anchor fennec_vector_not
|
||||
/// \brief Returns the component-wise logical complement of \f$x\f$.
|
||||
/// \brief Returns the component-wise logical complement of \math{x}.
|
||||
///
|
||||
/// \details
|
||||
/// \returns the component-wise logical complement of \f$x\f$.
|
||||
/// \returns the component-wise logical complement of \math{x}.
|
||||
/// \param x the boolean vector to inverse
|
||||
template<typename genBType = bool_t, size_t...i>
|
||||
constexpr vector<genBType, i...> operator not(const vector<genBType, i...>& x) {
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
///
|
||||
/// \code #include <fennec/math/scalar.h> \endcode
|
||||
///
|
||||
/// The fennecLibrary considers any type that passes ```is_arithmetic<T>``` to be a \ref scalar "Scalar." Bools are
|
||||
/// The fennecLibrary considers any type that passes `(.*?)` to be a \ref scalar "Scalar." Bools are
|
||||
/// supported as a logical type.
|
||||
///
|
||||
/// The GLSL Specification, and fennecrespectively, defines the following scalar types:
|
||||
|
||||
@@ -157,13 +157,13 @@ namespace fennec
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \brief Converts \f$degrees\f$ to \f$radians\f$, i.e., \f$degrees\cdot\frac{180}{\pi}\f$
|
||||
/// \brief Converts \emph{degrees} to \emph{radians}, i.e., \math{degrees\cdot\frac{180}{\pi}}
|
||||
///
|
||||
/// \returns the angle \f$\theta\f$ in \f$radians\f$ <br><br>
|
||||
/// \details Converts \f$degrees\f$ to \f$radians\f$, i.e., \f$degrees\cdot\frac{180}{\pi}\f$ <br><br>
|
||||
/// \returns the angle \math{\theta} in \math{radians} <br><br>
|
||||
/// \details Converts \emph{degrees} to \emph{radians}, i.e., \math{degrees\cdot\frac{180}{\pi}} <br><br>
|
||||
///
|
||||
/// \tparam genType floating point type
|
||||
/// \param degrees the angle \f$\theta\f$ in \f$degrees\f$
|
||||
/// \param degrees the angle \math{\theta} in \math{degrees}
|
||||
template<typename genType>
|
||||
constexpr genType radians(genType degrees) {
|
||||
return genType(degrees * 0.01745329251994329576923690768489);
|
||||
@@ -171,13 +171,13 @@ constexpr genType radians(genType degrees) {
|
||||
|
||||
|
||||
///
|
||||
/// \brief Converts \f$radians\f$ to \f$degrees\f$, i.e., \f$radians\cdot\frac{\pi}{180}\f$
|
||||
/// \brief Converts \emph{radians} to \emph{degrees}, i.e., \math{radians\cdot\frac{\pi}{180}}
|
||||
///
|
||||
/// \returns the angle \f$\theta\f$ in \f$degrees\f$ <br><br>
|
||||
/// \details Converts \f$radians\f$ to \f$degrees\f$, i.e., \f$radians\cdot\frac{\pi}{180}\f$ <br><br>
|
||||
/// \returns the angle \math{\theta} in \emph{degrees} <br><br>
|
||||
/// \details Converts \emph{radians} to \emph{degrees}, i.e., \math{radians\cdot\frac{\pi}{180}} <br><br>
|
||||
///
|
||||
/// \tparam genType floating point type
|
||||
/// \param radians the angle \f$\theta\f$ in \f$radians\f$
|
||||
/// \param radians the angle \math{\theta} in \emph{radians}
|
||||
template<typename genType>
|
||||
constexpr genType degrees(genType radians) {
|
||||
return genType(radians * 57.29577951308232087679815481410517);
|
||||
@@ -195,11 +195,11 @@ constexpr genType degrees(genType radians) {
|
||||
///
|
||||
/// \brief The standard trigonometric sine
|
||||
///
|
||||
/// \returns the sine of \f$\theta\f$ in the range \f$\left[-1,\,1\right]\f$ <br><br>
|
||||
/// \returns the sine of \math{\theta} in the range \math{\left[-1,\,1\right]} <br><br>
|
||||
/// \details The standard trigonometric sine <br><br>
|
||||
///
|
||||
/// \tparam genType floating point type
|
||||
/// \param x the angle \f$\theta\f$ in \f$radians\f$
|
||||
/// \param x the angle \math{\theta} in \math{radians}
|
||||
template<typename genType>
|
||||
constexpr genType sin(genType x) {
|
||||
return ::sin(x);
|
||||
@@ -209,11 +209,11 @@ constexpr genType sin(genType x) {
|
||||
///
|
||||
/// \brief The Standard Trigonometric Cosine
|
||||
///
|
||||
/// \returns the cosine of \f$\theta\f$ in the range \f$\left[-1,\,1\right]\f$ <br><br>
|
||||
/// \returns the cosine of \math{\theta} in the range \math{\left[-1,\,1\right]} <br><br>
|
||||
/// \details The Standard Trigonometric Cosine <br><br>
|
||||
///
|
||||
/// \tparam genType floating point type
|
||||
/// \param x the angle \f$\theta\f$ in \f$radians\f$
|
||||
/// \param x the angle \math{\theta} in \emph{radians}
|
||||
template<typename genType>
|
||||
constexpr genType cos(genType x) {
|
||||
return ::cos(x);
|
||||
@@ -223,11 +223,11 @@ constexpr genType cos(genType x) {
|
||||
///
|
||||
/// \brief The Standard Trigonometric Tangent
|
||||
///
|
||||
/// \returns The Tangent of \f$\theta\f$ in the Range \f$\left[-\inf,\,\inf\right]\f$<br><br>
|
||||
/// \returns The Tangent of \math{\theta} in the Range \math{\left[-\inf,\,\inf\right]}<br><br>
|
||||
/// \details The Standard Trigonometric Tangent <br><br>
|
||||
///
|
||||
/// \tparam genType floating point type
|
||||
/// \param x The Angle \f$\theta\f$ in \f$radians\f$
|
||||
/// \param x The Angle \math{\theta} in \math{radians}
|
||||
template<typename genType>
|
||||
constexpr genType tan(genType x) {
|
||||
return ::tan(x);
|
||||
@@ -241,14 +241,14 @@ constexpr genType tan(genType x) {
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \brief Arc Sine. Returns an angle \f$\theta\f$ whose sine is /a x.
|
||||
/// \brief Arc Sine. Returns an angle \math{\theta} whose sine is /a x.
|
||||
///
|
||||
/// \returns an angle \f$\theta\f$ whose sine is /a x. <br><br>
|
||||
/// \returns an angle \math{\theta} whose sine is /a x. <br><br>
|
||||
/// \details Arc Sine. The range of values returned by this functions is
|
||||
/// \f$\left[-\pi/2,\pi/2\right]\f$. Results are undefined if \f$\left|x\right|\,>\,1\f$. <br><br>
|
||||
/// \math{\left[-\pi/2,\pi/2\right]}. Results are undefined if \math{\left|x\right|\,>\,1}. <br><br>
|
||||
///
|
||||
/// \tparam genType floating point type
|
||||
/// \param x The Sine Value produced by \f$\theta\f$
|
||||
/// \param x The Sine Value produced by \math{\theta}
|
||||
template<typename genType>
|
||||
constexpr genType asin(genType x) {
|
||||
return ::asin(x);
|
||||
@@ -256,14 +256,14 @@ constexpr genType asin(genType x) {
|
||||
|
||||
|
||||
///
|
||||
/// \brief Arc Cosine. Returns an angle \f$\theta\f$ whose cosine is /a x.
|
||||
/// \brief Arc Cosine. Returns an angle \math{\theta} whose cosine is /a x.
|
||||
///
|
||||
/// \returns an angle \f$\theta\f$ whose cosine is /a x.
|
||||
/// \returns an angle \math{\theta} whose cosine is /a x.
|
||||
/// \details Arc Cosine. The range of values returned by this functions is
|
||||
/// \f$\left[0,\pi\right]\f$. Results are undefined if \f$\left|x\right|\,>\,1\f$.
|
||||
/// \math{\left[0,\pi\right]}. Results are undefined if \math{\left|x\right|\,>\,1}.
|
||||
///
|
||||
/// \tparam genType floating point type
|
||||
/// \param x The Cosine Value produced by \f$\theta\f$
|
||||
/// \param x The Cosine Value produced by \math{\theta}
|
||||
template<typename genType>
|
||||
constexpr genType acos(genType x) {
|
||||
return ::acos(x);
|
||||
@@ -271,14 +271,14 @@ constexpr genType acos(genType x) {
|
||||
|
||||
|
||||
///
|
||||
/// \brief Arc Tangent. Returns an angle \f$\theta\f$ whose tangent is /a y_over_x.
|
||||
/// \brief Arc Tangent. Returns an angle \math{\theta} whose tangent is /a y_over_x.
|
||||
///
|
||||
/// \returns an angle \f$\theta\f$ whose tangent is /a y_over_x.
|
||||
/// \returns an angle \math{\theta} whose tangent is /a y_over_x.
|
||||
/// \details Arc Tangent. The range of values returned by this functions is
|
||||
/// \f$\left[\frac{-\pi}{2},\frac{\pi}{2}\right]\f$. Results are undefined if \f$\left|x\right|\,>\,1\f$.
|
||||
/// \math{\left[\frac{-\pi}{2},\frac{\pi}{2}\right]}. Results are undefined if \math{\left|x\right|\,>\,1}.
|
||||
///
|
||||
/// \tparam genType floating point type
|
||||
/// \param y_over_x The Cosine Value produced by \f$\theta\f$
|
||||
/// \param y_over_x The Cosine Value produced by \math{\theta}
|
||||
template<typename genType>
|
||||
constexpr genType atan(genType y_over_x) {
|
||||
return ::atan(y_over_x);
|
||||
@@ -286,15 +286,15 @@ constexpr genType atan(genType y_over_x) {
|
||||
|
||||
|
||||
///
|
||||
/// \brief Arc Tangent. Returns an angle whose tangent is \f$\frac{y}{x}\f$.
|
||||
/// \brief Arc Tangent. Returns an angle whose tangent is \math{\frac{y}{x}}.
|
||||
///
|
||||
/// \returns an angle whose tangent is \f$\frac{y}{x}\f$. <br><br>
|
||||
/// \returns an angle whose tangent is \math{\frac{y}{x}}. <br><br>
|
||||
/// \details Arc Tangent. The signs of \a x and \a y are used to determine what quadrant the angle is in.
|
||||
/// The range of values returned by this functions is \f$\left[-\pi,\pi\right]\f$ <br><br>
|
||||
/// The range of values returned by this functions is \math{\left[-\pi,\pi\right]} <br><br>
|
||||
///
|
||||
/// \tparam genType floating point type
|
||||
/// \param y The Sine Value produced by \f$\theta\f$
|
||||
/// \param x The Cosine Value produced by \f$\theta\f$
|
||||
/// \param y The Sine Value produced by \math{\theta}
|
||||
/// \param x The Cosine Value produced by \math{\theta}
|
||||
template<typename genType>
|
||||
constexpr genType atan(genType y, genType x) {
|
||||
return ::atan2(y, x);
|
||||
@@ -310,12 +310,12 @@ constexpr genType atan(genType y, genType x) {
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \brief Returns the Hyperbolic Sine Function, \f$\frac{{e}^{x}-{e}^{-x}}{2}\f$
|
||||
/// \brief Returns the Hyperbolic Sine Function, \math{\frac{{e}^{x}-{e}^{-x}}{2}}
|
||||
///
|
||||
/// \returns The Hyperbolic Sine of \f$x\f$, \f$\frac{{e}^{x}-{e}^{-x}}{2}\f$ <br><br>
|
||||
/// \returns The Hyperbolic Sine of \math{x}, \math{\frac{{e}^{x}-{e}^{-x}}{2}} <br><br>
|
||||
///
|
||||
/// \tparam genType floating point type
|
||||
/// \param x The Hyperbolic Angle \f$\alpha\f$
|
||||
/// \param x The Hyperbolic Angle \math{\alpha}
|
||||
template<typename genType>
|
||||
constexpr genType sinh(genType x) {
|
||||
return ::sinh(x);
|
||||
@@ -323,11 +323,11 @@ constexpr genType sinh(genType x) {
|
||||
|
||||
|
||||
///
|
||||
/// \brief Returns the Hyperbolic Cosine Function, \f$\frac{{e}^{x}+{e}^{-x}}{2}\f$
|
||||
/// \brief Returns the Hyperbolic Cosine Function, \math{\frac{{e}^{x}+{e}^{-x}}{2}}
|
||||
///
|
||||
/// \returns The Hyperbolic Cosine of \f$x\f$, \f$\frac{{e}^{x}+{e}^{-x}}{2}\f$ <br><br>
|
||||
/// \returns The Hyperbolic Cosine of \math{x}, \math{\frac{{e}^{x}+{e}^{-x}}{2}} <br><br>
|
||||
///
|
||||
/// \param x The Hyperbolic Angle \f$\alpha\f$
|
||||
/// \param x The Hyperbolic Angle \math{\alpha}
|
||||
template<typename genType>
|
||||
constexpr genType cosh(genType x) {
|
||||
return ::cosh(x);
|
||||
@@ -335,11 +335,11 @@ constexpr genType cosh(genType x) {
|
||||
|
||||
|
||||
///
|
||||
/// \brief Returns the Hyperbolic Tangent Function, \f$\frac{\text{sinh}(x)}{\text{cosh}(x)}\f$
|
||||
/// \brief Returns the Hyperbolic Tangent Function, \math{\frac{\text{sinh}(x)}{\text{cosh}(x)}}
|
||||
///
|
||||
/// \returns The Hyperbolic Tangent of \f$x\f$, \f$\frac{{e}^{x}+{e}^{-x}}{2}\f$ <br><br>
|
||||
/// \returns The Hyperbolic Tangent of \math{x}, \math{\frac{{e}^{x}+{e}^{-x}}{2}} <br><br>
|
||||
///
|
||||
/// \param x The Hyperbolic Angle \f$\alpha\f$
|
||||
/// \param x The Hyperbolic Angle \math{\alpha}
|
||||
template<typename genType, size_t...i>
|
||||
constexpr genType tanh(genType x) {
|
||||
return ::tanh(x);
|
||||
@@ -355,10 +355,10 @@ constexpr genType tanh(genType x) {
|
||||
///
|
||||
/// \brief The Inverse Hyperbolic Sine Function
|
||||
///
|
||||
/// \returns the value \f$y\f$ that fulfills \f$x=\text{sinh}(y)\f$ <br><br>
|
||||
/// \returns the value \math{y} that fulfills \math{x=\text{sinh}(y)} <br><br>
|
||||
/// \details The Inverse Hyperbolic Sine Function <br><br>
|
||||
///
|
||||
/// \param x the hyperbolic angle \f$\alpha\f$
|
||||
/// \param x the hyperbolic angle \math{\alpha}
|
||||
template<typename genType, size_t...i>
|
||||
constexpr genType asinh(genType x) {
|
||||
return ::asinh(x);
|
||||
@@ -368,10 +368,10 @@ constexpr genType asinh(genType x) {
|
||||
///
|
||||
/// \brief The Inverse Hyperbolic Cosine Function
|
||||
///
|
||||
/// \returns the value \f$y\f$ that fulfills \f$x=\text{cosh}(y)\f$ <br><br>
|
||||
/// \returns the value \math{y} that fulfills \math{x=\text{cosh}(y)} <br><br>
|
||||
/// \details The Inverse Hyperbolic Cosine Function <br><br>
|
||||
///
|
||||
/// \param x the hyperbolic angle \f$\alpha\f$
|
||||
/// \param x the hyperbolic angle \math{\alpha}
|
||||
template<typename genType, size_t...i>
|
||||
constexpr genType acosh(genType x) {
|
||||
return ::acosh(x);
|
||||
@@ -381,10 +381,10 @@ constexpr genType acosh(genType x) {
|
||||
///
|
||||
/// \brief The Inverse Hyperbolic Tangent Function
|
||||
///
|
||||
/// \returns the value \f$y\f$ that fulfills \f$x=\text{atanh}(y)\f$ <br><br>
|
||||
/// \returns the value \math{y} that fulfills \math{x=\text{atanh}(y)} <br><br>
|
||||
/// \details The Inverse Hyperbolic Tangent Function <br><br>
|
||||
///
|
||||
/// \param x The Hyperbolic Angle \f$\alpha\f$
|
||||
/// \param x The Hyperbolic Angle \math{\alpha}
|
||||
template<typename genType, size_t...i>
|
||||
constexpr genType atanh(genType x) {
|
||||
return ::atanh(x);
|
||||
|
||||
@@ -46,33 +46,33 @@
|
||||
/// <table width="100%" class="fieldtable" id="table_fennec_math_vector_types">
|
||||
/// <tr><th>Type <th>Corresponding Type <th>Brief
|
||||
/// <tr><th colspan=3 style="text-align: center;">Floats
|
||||
/// <tr><td>``\f$vec2\f$`` <td>\ref fennec::vec2 <td>\copybrief fennec::vec2
|
||||
/// <tr><td>``\f$vec3\f$`` <td>\ref fennec::vec3 <td>\copybrief fennec::vec3
|
||||
/// <tr><td>``\f$vec4\f$`` <td>\ref fennec::vec4 <td>\copybrief fennec::vec4
|
||||
/// <tr><td>``\emph{vec2}`` <td>\ref fennec::vec2 <td>\copybrief fennec::vec2
|
||||
/// <tr><td>``\emph{vec3}`` <td>\ref fennec::vec3 <td>\copybrief fennec::vec3
|
||||
/// <tr><td>``\emph{vec4}`` <td>\ref fennec::vec4 <td>\copybrief fennec::vec4
|
||||
/// <tr><th colspan=3 style="text-align: center;">Doubles
|
||||
/// <tr><td>``\f$dvec2\f$``<td>\ref fennec::dvec2 <td>\copybrief fennec::dvec2
|
||||
/// <tr><td>``\f$dvec3\f$``<td>\ref fennec::dvec3 <td>\copybrief fennec::dvec3
|
||||
/// <tr><td>``\f$dvec4\f$``<td>\ref fennec::dvec4 <td>\copybrief fennec::dvec4
|
||||
/// <tr><td>``\emph{dvec2}``<td>\ref fennec::dvec2 <td>\copybrief fennec::dvec2
|
||||
/// <tr><td>``\emph{dvec3}``<td>\ref fennec::dvec3 <td>\copybrief fennec::dvec3
|
||||
/// <tr><td>``\emph{dvec4}``<td>\ref fennec::dvec4 <td>\copybrief fennec::dvec4
|
||||
/// <tr><th colspan=3 style="text-align: center;">Booleans
|
||||
/// <tr><td>``\f$bvec2\f$`` <td>\ref fennec::bvec2 <td>\copybrief fennec::bvec2
|
||||
/// <tr><td>``\f$bvec3\f$`` <td>\ref fennec::bvec3 <td>\copybrief fennec::bvec3
|
||||
/// <tr><td>``\f$bvec4\f$`` <td>\ref fennec::bvec4 <td>\copybrief fennec::bvec4
|
||||
/// <tr><td>``\emph{bvec2}`` <td>\ref fennec::bvec2 <td>\copybrief fennec::bvec2
|
||||
/// <tr><td>``\emph{bvec3}`` <td>\ref fennec::bvec3 <td>\copybrief fennec::bvec3
|
||||
/// <tr><td>``\emph{bvec4}`` <td>\ref fennec::bvec4 <td>\copybrief fennec::bvec4
|
||||
/// <tr><th colspan=3 style="text-align: center;">Integers
|
||||
/// <tr><td>``\f$ivec2\f$`` <td>\ref fennec::ivec2 <td>\copybrief fennec::ivec2
|
||||
/// <tr><td>``\f$ivec3\f$`` <td>\ref fennec::ivec3 <td>\copybrief fennec::ivec3
|
||||
/// <tr><td>``\f$ivec4\f$`` <td>\ref fennec::ivec4 <td>\copybrief fennec::ivec4
|
||||
/// <tr><td>``\emph{ivec2}`` <td>\ref fennec::ivec2 <td>\copybrief fennec::ivec2
|
||||
/// <tr><td>``\emph{ivec3}`` <td>\ref fennec::ivec3 <td>\copybrief fennec::ivec3
|
||||
/// <tr><td>``\emph{ivec4}`` <td>\ref fennec::ivec4 <td>\copybrief fennec::ivec4
|
||||
/// <tr><th colspan=3 style="text-align: center;">Unsigned Integers
|
||||
/// <tr><td>``\f$uvec2\f$`` <td>\ref fennec::uvec2 <td>\copybrief fennec::uvec2
|
||||
/// <tr><td>``\f$uvec3\f$`` <td>\ref fennec::uvec3 <td>\copybrief fennec::uvec3
|
||||
/// <tr><td>``\f$uvec4\f$`` <td>\ref fennec::uvec4 <td>\copybrief fennec::uvec4
|
||||
/// <tr><td>``\emph{uvec2}`` <td>\ref fennec::uvec2 <td>\copybrief fennec::uvec2
|
||||
/// <tr><td>``\emph{uvec3}`` <td>\ref fennec::uvec3 <td>\copybrief fennec::uvec3
|
||||
/// <tr><td>``\emph{uvec4}`` <td>\ref fennec::uvec4 <td>\copybrief fennec::uvec4
|
||||
/// </table>
|
||||
///
|
||||
///
|
||||
///
|
||||
/// \section vector_components Components
|
||||
///
|
||||
/// Vectors are usually made up of one to four components, named ``\f$x\f$``, ``\f$y\f$``, ``\f$z\f$``, and ``\f$w\f$``.
|
||||
/// Each component also has aliases for usage in colors ``\f$rgba\f$``, and texture coordinates ``\f$stpq\f$``. Accessing a
|
||||
/// Vectors are usually made up of one to four components, named \math{x}, \math{y}, \math{z}, and \math{w}.
|
||||
/// Each component also has aliases for usage in colors \math{rgba}, and texture coordinates \math{stpq}. Accessing a
|
||||
/// component outside the vector will cause an error at compile time, for example:
|
||||
///
|
||||
/// \code{.cpp}
|
||||
@@ -93,9 +93,9 @@
|
||||
/// The fennec \ref fennec_math_vector allows for the "swizzling" of vectors. Each component in the vector can be
|
||||
/// used in any combination, with up to 4 components, to create another vector. For example, <br><br>
|
||||
///
|
||||
/// let \f$V = (0, 1, 2)\f$
|
||||
/// then \f$V.xy = (0, 1)\f$
|
||||
/// and \f$V.zy = (2, 1)\f$
|
||||
/// let \math{V = (0, 1, 2)}
|
||||
/// then \math{V.xy = (0, 1)}
|
||||
/// and \math{V.zy = (2, 1)}
|
||||
///
|
||||
/// \section section_vectors_more More Info
|
||||
/// - \subpage fennec_math_vector_traits
|
||||
@@ -125,22 +125,22 @@ using vec = decltype(detail::_gen_vector<vector, ScalarT>(make_index_metasequenc
|
||||
|
||||
|
||||
///
|
||||
/// \brief Shorthand for creating a 2-element \ref fennec::vector, ```vec<ScalarT, 2>```
|
||||
/// \details Shorthand for creating a 2-element \ref fennec::vector, ```vec<ScalarT, 2>```
|
||||
/// \brief Shorthand for creating a 2-element \ref fennec::vector, `(.*?)`
|
||||
/// \details Shorthand for creating a 2-element \ref fennec::vector, `(.*?)`
|
||||
/// \tparam ScalarT The type of the Components
|
||||
template<typename ScalarT>
|
||||
using tvec2 = vec<ScalarT, 2>;
|
||||
|
||||
///
|
||||
/// \brief Shorthand for creating a 3-element \ref fennec::vector, ```vec<ScalarT, 3>```
|
||||
/// \details Shorthand for creating a 3-element \ref fennec::vector, ```vec<ScalarT, 3>```
|
||||
/// \brief Shorthand for creating a 3-element \ref fennec::vector, `(.*?)`
|
||||
/// \details Shorthand for creating a 3-element \ref fennec::vector, `(.*?)`
|
||||
/// \tparam ScalarT The type of the Components
|
||||
template<typename ScalarT>
|
||||
using tvec3 = vec<ScalarT, 3>;
|
||||
|
||||
///
|
||||
/// \brief Shorthand for creating a 4-element \ref fennec::vector, ```vec<ScalarT, 4>```
|
||||
/// \details Shorthand for creating a 4-element \ref fennec::vector, ```vec<ScalarT, 4>```
|
||||
/// \brief Shorthand for creating a 4-element \ref fennec::vector, `(.*?)`
|
||||
/// \details Shorthand for creating a 4-element \ref fennec::vector, `(.*?)`
|
||||
/// \tparam ScalarT The type of the Components
|
||||
template<typename ScalarT>
|
||||
using tvec4 = vec<ScalarT, 4>;
|
||||
@@ -377,7 +377,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \brief decay implementation
|
||||
///
|
||||
/// \details
|
||||
/// \returns scalar if \f$N==1\f$, otherwise, \ref fennec_math_vector "vector"
|
||||
/// \returns scalar if \math{N==1}, otherwise, \ref fennec_math_vector "vector"
|
||||
decay_t decay() {
|
||||
return static_cast<const decay_t&>(*this);
|
||||
}
|
||||
@@ -418,7 +418,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \brief copy assignment
|
||||
///
|
||||
/// \details
|
||||
/// \returns A reference to \c this, after having set \p lhs, such that \f$lhs_i=rhs_i\f$
|
||||
/// \returns A reference to \c this, after having set \p lhs, such that \math{lhs_i=rhs_i}
|
||||
/// \param rhs vector to copy
|
||||
constexpr vector_t& operator=(const vector_t& rhs) {
|
||||
return ((data[IndicesV] = rhs[IndicesV]), ..., *this);
|
||||
@@ -428,7 +428,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \brief move assignment
|
||||
///
|
||||
/// \details
|
||||
/// \returns A reference to \c this, after having set \p lhs, such that \f$lhs_i=rhs_i\f$
|
||||
/// \returns A reference to \c this, after having set \p lhs, such that \math{lhs_i=rhs_i}
|
||||
/// \param rhs vector to move
|
||||
constexpr vector_t& operator=(vector_t&& rhs) noexcept {
|
||||
return ((data[IndicesV] = fennec::move(rhs[IndicesV])), ..., *this);
|
||||
@@ -474,7 +474,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" addition operator
|
||||
///
|
||||
/// \details
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i+rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i+rhs_i}
|
||||
/// \param lhs left hand side
|
||||
/// \param rhs right hand side
|
||||
constexpr friend vector_t operator+(scalar_t lhs, const vector_t& rhs) {
|
||||
@@ -485,7 +485,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" subtraction operator
|
||||
///
|
||||
/// \details
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i-rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i-rhs_i}
|
||||
/// \param lhs left hand side
|
||||
/// \param rhs right hand side
|
||||
constexpr friend vector_t operator-(scalar_t lhs, const vector_t& rhs) {
|
||||
@@ -496,7 +496,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" multiplication operator
|
||||
///
|
||||
/// \details
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i={lhs_i}\cdot{rhs_i}\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i={lhs_i}\cdot{rhs_i}}
|
||||
/// \param lhs left hand side
|
||||
/// \param rhs right hand side
|
||||
constexpr friend vector_t operator*(scalar_t lhs, const vector_t& rhs) {
|
||||
@@ -507,7 +507,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" division operator
|
||||
///
|
||||
/// \details
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=\frac{lhs_i}{rhs_i}\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=\frac{lhs_i}{rhs_i}}
|
||||
/// \param lhs left hand side
|
||||
/// \param rhs right hand side
|
||||
constexpr friend vector_t operator/(scalar_t lhs, const vector_t& rhs) {
|
||||
@@ -518,7 +518,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" integer modulus operator
|
||||
///
|
||||
/// \details
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\%rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\%rhs_i}
|
||||
/// \param lhs left hand side
|
||||
/// \param rhs right hand side
|
||||
constexpr friend vector_t operator%(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
|
||||
@@ -536,7 +536,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" addition operator
|
||||
///
|
||||
/// \details
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i+rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i+rhs_i}
|
||||
/// \param lhs left hand side
|
||||
/// \param rhs right hand side
|
||||
constexpr friend vector_t operator+(const vector_t& lhs, scalar_t rhs) {
|
||||
@@ -549,7 +549,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs left hand side
|
||||
/// \param rhs right hand side
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i-rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i-rhs_i}
|
||||
constexpr friend vector_t operator-(const vector_t& lhs, scalar_t rhs) {
|
||||
return vector_t((lhs[IndicesV] - rhs)...);
|
||||
}
|
||||
@@ -560,7 +560,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs left hand side
|
||||
/// \param rhs right hand side
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i={lhs_i}\cdot{rhs_i}\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i={lhs_i}\cdot{rhs_i}}
|
||||
constexpr friend vector_t operator*(const vector_t& lhs, scalar_t rhs) {
|
||||
return vector_t((lhs[IndicesV] * rhs)...);
|
||||
}
|
||||
@@ -571,7 +571,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs left hand side
|
||||
/// \param rhs right hand side
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=\frac{lhs_i}{rhs_i}\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=\frac{lhs_i}{rhs_i}}
|
||||
constexpr friend vector_t operator/(const vector_t& lhs, scalar_t rhs) {
|
||||
return vector((lhs[IndicesV] / rhs)...);
|
||||
}
|
||||
@@ -582,7 +582,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs left hand side
|
||||
/// \param rhs right hand side
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\%rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\%rhs_i}
|
||||
constexpr friend vector_t operator%(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
|
||||
return vector((lhs[IndicesV] % rhs)...);
|
||||
}
|
||||
@@ -600,7 +600,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i+rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i+rhs_i}
|
||||
constexpr friend vector_t& operator+=(vector_t& lhs, scalar_t rhs) {
|
||||
return ((lhs[IndicesV] += rhs), ..., lhs);
|
||||
}
|
||||
@@ -611,7 +611,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i-rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i-rhs_i}
|
||||
constexpr friend vector_t& operator-=(vector_t& lhs, scalar_t rhs) {
|
||||
return ((lhs[IndicesV] -= rhs), ..., lhs);
|
||||
}
|
||||
@@ -622,7 +622,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i={lhs_i}\cdot{rhs_i}\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i={lhs_i}\cdot{rhs_i}}
|
||||
constexpr friend vector_t& operator*=(vector_t& lhs, scalar_t rhs) {
|
||||
return ((lhs[IndicesV] *= rhs), ..., lhs);
|
||||
}
|
||||
@@ -633,7 +633,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=\frac{lhs_i}{rhs_i}\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=\frac{lhs_i}{rhs_i}}
|
||||
constexpr friend vector_t& operator/=(vector_t& lhs, scalar_t rhs) {
|
||||
return ((lhs[IndicesV] /= rhs), ..., lhs);
|
||||
}
|
||||
@@ -644,7 +644,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\%rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\%rhs_i}
|
||||
constexpr friend vector_t& operator%=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
|
||||
return ((lhs[IndicesV] %= rhs), ..., lhs);
|
||||
}
|
||||
@@ -661,7 +661,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
///
|
||||
/// \details
|
||||
/// \param x the vector
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=-x_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=-x_i}
|
||||
constexpr friend vector_t operator-(const vector_t& x) {
|
||||
return vector((-x[IndicesV])...);
|
||||
}
|
||||
@@ -672,7 +672,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i+rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i+rhs_i}
|
||||
constexpr friend vector_t operator+(const vector_t& lhs, const vector_t& rhs) {
|
||||
return vector((lhs[IndicesV] + rhs[IndicesV])...);
|
||||
}
|
||||
@@ -683,7 +683,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i-rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i-rhs_i}
|
||||
constexpr friend vector_t operator-(const vector_t& lhs, const vector_t& rhs) {
|
||||
return vector((lhs[IndicesV] - rhs[IndicesV])...);
|
||||
}
|
||||
@@ -694,7 +694,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i={lhs_i}\cdot{rhs_i}\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i={lhs_i}\cdot{rhs_i}}
|
||||
constexpr friend vector_t operator*(const vector_t& lhs, const vector_t& rhs) {
|
||||
return vector((lhs[IndicesV] * rhs[IndicesV])...);
|
||||
}
|
||||
@@ -703,7 +703,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" division operator
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=\frac{lhs_i}{rhs_i}\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=\frac{lhs_i}{rhs_i}}
|
||||
constexpr friend vector_t operator/(const vector_t& lhs, const vector_t& rhs) {
|
||||
return vector((lhs[IndicesV] / rhs[IndicesV])...);
|
||||
}
|
||||
@@ -714,7 +714,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\%rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\%rhs_i}
|
||||
constexpr friend vector_t operator%(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
|
||||
return vector((lhs[IndicesV] % rhs[IndicesV])...);
|
||||
}
|
||||
@@ -732,7 +732,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i+rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i+rhs_i}
|
||||
constexpr friend vector_t& operator+=(vector_t& lhs, const vector_t& rhs) {
|
||||
return ((lhs[IndicesV] += rhs[IndicesV]), ..., lhs);
|
||||
}
|
||||
@@ -743,7 +743,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i-rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i-rhs_i}
|
||||
constexpr friend vector_t& operator-=(vector_t& lhs, const vector_t& rhs) {
|
||||
return ((lhs[IndicesV] -= rhs[IndicesV]), ..., lhs);
|
||||
}
|
||||
@@ -754,7 +754,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i={lhs_i}\cdot{rhs_i}\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i={lhs_i}\cdot{rhs_i}}
|
||||
constexpr friend vector_t& operator*=(vector_t& lhs, const vector_t& rhs) {
|
||||
return ((lhs[IndicesV] *= rhs[IndicesV]), ..., lhs);
|
||||
}
|
||||
@@ -765,7 +765,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=\frac{lhs_i}{rhs_i}\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=\frac{lhs_i}{rhs_i}}
|
||||
constexpr friend vector_t& operator/=(vector_t& lhs, const vector_t& rhs) {
|
||||
return ((lhs[IndicesV] /= rhs[IndicesV]), ..., lhs);
|
||||
}
|
||||
@@ -776,7 +776,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\%rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\%rhs_i}
|
||||
constexpr friend vector_t& operator%=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
|
||||
return ((lhs[IndicesV] %= rhs[IndicesV]), ..., lhs);
|
||||
}
|
||||
@@ -793,7 +793,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
///
|
||||
/// \details
|
||||
/// \param x the vector
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=!x_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=!x_i}
|
||||
constexpr friend vector_t operator!(const vector_t& x) {
|
||||
return vector_t(!x[IndicesV]...);
|
||||
}
|
||||
@@ -804,7 +804,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\&\&rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\&\&rhs_i}
|
||||
constexpr friend vector_t operator&&(const vector_t& lhs, scalar_t rhs) requires(is_bool_v<scalar_t>) {
|
||||
return vector_t((lhs[IndicesV] && rhs)...);
|
||||
}
|
||||
@@ -813,7 +813,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" logical and operator
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\&\&rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\&\&rhs_i}
|
||||
constexpr friend vector_t operator&&(const vector_t& lhs, const vector_t& rhs) requires(is_bool_v<scalar_t>) {
|
||||
return vector_t((lhs[IndicesV] && rhs[IndicesV])...);
|
||||
}
|
||||
@@ -824,7 +824,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\|\|rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\|\|rhs_i}
|
||||
constexpr friend vector_t operator||(const vector_t& lhs, scalar_t rhs) requires(is_bool_v<scalar_t>) {
|
||||
return vector_t((lhs[IndicesV] || rhs)...);
|
||||
}
|
||||
@@ -835,7 +835,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\|\|rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\|\|rhs_i}
|
||||
constexpr friend vector_t operator||(const vector_t& lhs, const vector_t& rhs) requires(is_bool_v<scalar_t>) {
|
||||
return vector_t((lhs[IndicesV] || rhs[IndicesV])...);
|
||||
}
|
||||
@@ -853,7 +853,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\&rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\&rhs_i}
|
||||
constexpr friend vector_t operator&(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>) {
|
||||
return vector_t((lhs[IndicesV] & rhs)...);
|
||||
}
|
||||
@@ -864,7 +864,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\&rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\&rhs_i}
|
||||
constexpr friend vector_t operator&(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
|
||||
return vector_t((lhs[IndicesV] & rhs)...);
|
||||
}
|
||||
@@ -875,7 +875,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\&rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\&rhs_i}
|
||||
constexpr friend vector_t operator&=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
|
||||
return ((lhs[IndicesV] &= rhs), ..., lhs);
|
||||
}
|
||||
@@ -886,7 +886,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\&rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\&rhs_i}
|
||||
constexpr friend vector_t operator&(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<
|
||||
scalar_t>) {
|
||||
return vector_t((lhs[IndicesV] & rhs[IndicesV])...);
|
||||
@@ -898,7 +898,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\&rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\&rhs_i}
|
||||
constexpr friend vector_t operator&=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
|
||||
return ((lhs[IndicesV] &= rhs[IndicesV]), ..., lhs);
|
||||
}
|
||||
@@ -910,7 +910,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i|rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i|rhs_i}
|
||||
constexpr friend vector_t operator|(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>) {
|
||||
return vector_t((lhs[IndicesV] | rhs)...);
|
||||
}
|
||||
@@ -921,7 +921,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i|rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i|rhs_i}
|
||||
constexpr friend vector_t operator|(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
|
||||
return vector_t((lhs[IndicesV] | rhs)...);
|
||||
}
|
||||
@@ -932,7 +932,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i|rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i|rhs_i}
|
||||
constexpr friend vector_t operator|=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
|
||||
return ((lhs[IndicesV] |= rhs), ..., lhs);
|
||||
}
|
||||
@@ -943,7 +943,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i|rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i|rhs_i}
|
||||
constexpr friend vector_t operator|(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<
|
||||
scalar_t>) {
|
||||
return vector_t((lhs[IndicesV] | rhs[IndicesV])...);
|
||||
@@ -955,7 +955,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \details
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i|rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i|rhs_i}
|
||||
constexpr friend vector_t operator|=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
|
||||
return ((lhs[IndicesV] |= rhs[IndicesV]), ..., lhs);
|
||||
}
|
||||
@@ -965,7 +965,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" bitwise xor operator
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\^rhs_i}
|
||||
constexpr friend vector_t operator^(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
|
||||
return vector_t((lhs ^ rhs[IndicesV])...);
|
||||
}
|
||||
@@ -974,7 +974,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise xor operator
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\^rhs_i}
|
||||
constexpr friend vector_t operator^(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
|
||||
return vector_t((lhs[IndicesV] ^ rhs)...);
|
||||
}
|
||||
@@ -983,7 +983,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise xor assignment operator
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\^rhs_i}
|
||||
constexpr friend vector_t operator^=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
|
||||
return ((lhs[IndicesV] ^= rhs), ..., lhs);
|
||||
}
|
||||
@@ -992,7 +992,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise xor operator
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\^rhs_i}
|
||||
constexpr friend vector_t operator^(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<
|
||||
scalar_t>) {
|
||||
return vector_t((lhs[IndicesV] ^ rhs[IndicesV])...);
|
||||
@@ -1002,7 +1002,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise xor assignment operator
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i\^rhs_i}
|
||||
constexpr friend vector_t operator^=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
|
||||
return ((lhs[IndicesV] ^= rhs[IndicesV]), ..., lhs);
|
||||
}
|
||||
@@ -1012,7 +1012,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" bitwise left-shift operator
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i<<rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i<<rhs_i}
|
||||
constexpr friend vector_t operator<<(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
|
||||
return vector_t((lhs << rhs[IndicesV])...);
|
||||
}
|
||||
@@ -1021,7 +1021,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift operator
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i<<rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i<<rhs_i}
|
||||
constexpr friend vector_t operator<<(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
|
||||
return vector_t((lhs[IndicesV] << rhs)...);
|
||||
}
|
||||
@@ -1030,7 +1030,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift assignment operator
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i<<=rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i<<=rhs_i}
|
||||
constexpr friend vector_t operator<<=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
|
||||
return ((lhs[IndicesV] <<= rhs), ..., lhs);
|
||||
}
|
||||
@@ -1039,7 +1039,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or operator
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i<<rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i<<rhs_i}
|
||||
constexpr friend vector_t operator<<(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
|
||||
return vector_t((lhs[IndicesV] << rhs[IndicesV])...);
|
||||
}
|
||||
@@ -1048,7 +1048,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i<<=rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i<<=rhs_i}
|
||||
constexpr friend vector_t operator<<=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
|
||||
return ((lhs[IndicesV] <<= rhs[IndicesV]), ..., lhs);
|
||||
}
|
||||
@@ -1058,7 +1058,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" bitwise or operator
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i>>rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i>>rhs_i}
|
||||
constexpr friend vector_t operator>>(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
|
||||
return vector_t((lhs >> rhs[IndicesV])...);
|
||||
}
|
||||
@@ -1067,7 +1067,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i>>rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i>>rhs_i}
|
||||
constexpr friend vector_t operator>>(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
|
||||
return vector_t((lhs[IndicesV] >> rhs)...);
|
||||
}
|
||||
@@ -1076,7 +1076,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift assignment operator
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i>>=rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i>>=rhs_i}
|
||||
constexpr friend vector_t operator>>=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
|
||||
return ((lhs[IndicesV] >>= rhs), ..., lhs);
|
||||
}
|
||||
@@ -1085,7 +1085,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or operator
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i>>rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i>>rhs_i}
|
||||
constexpr friend vector_t operator>>(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
|
||||
return vector_t((lhs[IndicesV] >> rhs[IndicesV])...);
|
||||
}
|
||||
@@ -1094,7 +1094,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
|
||||
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator
|
||||
/// \param lhs Left Hand Side of the Expression
|
||||
/// \param rhs Right Hand Side of the Expression
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i>>=rhs_i\f$
|
||||
/// \returns A \ref fennec_math_vector "vector" \a v such that, \math{v_i=lhs_i>>=rhs_i}
|
||||
constexpr friend vector_t operator>>=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
|
||||
return ((lhs[IndicesV] >>= rhs[IndicesV]), ..., lhs);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
#endif
|
||||
|
||||
#if FENNEC_COMPILER_CLANG
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wgnu-anonymous-struct"
|
||||
#pragma clang diagnostic ignored "-Wnested-anon-types"
|
||||
#endif
|
||||
|
||||
#if FENNEC_COMPILER_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4201)
|
||||
@@ -617,4 +623,12 @@ namespace fennec::detail
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef FENNEC_COMPILER_CLANG
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#if FENNEC_COMPILER_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // FENNEC_MATH_VECTOR_STORAGE_H
|
||||
|
||||
@@ -74,17 +74,17 @@ namespace fennec
|
||||
template<typename T> struct is_vector : detail::_is_vector_helper<remove_cvref_t<T>>{};
|
||||
|
||||
///
|
||||
/// \brief shorthand for ```is_vector<T>::value```
|
||||
/// \brief shorthand for `(.*?)`
|
||||
/// \tparam T type to check
|
||||
template<typename T> constexpr bool is_vector_v = is_vector<T>::value;
|
||||
|
||||
///
|
||||
/// \brief Get the number of Components in \p T, returns 1 for types that pass ```is_arithmetic<T>```, returns \ref vector::N for \ref vector "Vector" Types, and returns 0 for all other cases
|
||||
/// \brief Get the number of Components in \p T, returns 1 for types that pass `(.*?)`, returns \ref vector::N for \ref vector "Vector" Types, and returns 0 for all other cases
|
||||
/// \tparam T type to check
|
||||
template<typename T> struct component_count : detail::_component_count_helper<remove_cvref_t<T>>{};
|
||||
|
||||
///
|
||||
/// \brief shorthand for ```component_count<T>::value```
|
||||
/// \brief shorthand for `(.*?)`
|
||||
/// \tparam T type to get the component count of
|
||||
template<typename T> constexpr size_t component_count_v = component_count<T>::value;
|
||||
|
||||
@@ -97,7 +97,7 @@ template<typename...Ts> struct total_component_count : integral_constant<size_t,
|
||||
template<> struct total_component_count<> : integral_constant<size_t, 0>{};
|
||||
|
||||
///
|
||||
/// \brief shorthand for ```component_count<T>::value```
|
||||
/// \brief shorthand for `(.*?)`
|
||||
/// \tparam Ts types to accumulate the count of
|
||||
template<typename...Ts> constexpr size_t total_component_count_v = total_component_count<Ts...>::value;
|
||||
|
||||
|
||||
@@ -122,15 +122,10 @@ public:
|
||||
/// \brief Alias for the size of allocations. Will use `Alloc::size_t` if present
|
||||
using size_t = typename _size<Alloc, pointer_t>::type;
|
||||
|
||||
// TODO: Document propagation
|
||||
using propagate_on_container_copy_assignment = detect_t<false_type, _propagate_on_containter_copy_assignment, Alloc>;
|
||||
using propagate_on_container_move_assignment = detect_t<false_type, _propagate_on_containter_move_assignment, Alloc>;
|
||||
using propagate_on_container_swap = detect_t<false_type, _propagate_on_containter_swap, Alloc>;
|
||||
|
||||
/// \brief Checks if this allocator type is always equal to another allocator of similar type
|
||||
using is_always_equal = detect_t<false_type, _is_always_equal, Alloc>;
|
||||
|
||||
/// \brief Rebinds the allocator type to produce an element type of type \f$TypeT\f$
|
||||
/// \brief Rebinds the allocator type to produce an element type of type \emph{TypeT}
|
||||
template<typename TypeT> using rebind = typename _rebind<Alloc, TypeT>::type;
|
||||
|
||||
// TODO: allocator_traits static functions
|
||||
@@ -138,7 +133,7 @@ public:
|
||||
|
||||
|
||||
///
|
||||
/// \brief Allocator implementation, uses \f$new\f$ and \f$delete\f$ operators.
|
||||
/// \brief Allocator implementation, uses \emph{new} and \emph{delete} operators.
|
||||
/// \tparam T The data type to allocate
|
||||
template<typename T>
|
||||
class allocator
|
||||
@@ -166,39 +161,39 @@ public:
|
||||
|
||||
///
|
||||
/// \brief Copy Assignment
|
||||
/// \returns A reference to self
|
||||
/// \returns A reference to \emph{this}
|
||||
constexpr allocator& operator=(const allocator&) = default;
|
||||
|
||||
///
|
||||
/// \brief Equality operator
|
||||
/// \returns \f$true\f$
|
||||
/// \returns \emph{true}
|
||||
constexpr bool_t operator==(const allocator&) {
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Inequality operator
|
||||
/// \returns \f$false\f$
|
||||
/// \returns \emph{false}
|
||||
constexpr bool_t operator!=(const allocator&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Equality operator for allocators of same type but with different data type
|
||||
/// \returns \f$false\f$
|
||||
/// \returns \emph{false}
|
||||
template<typename U> constexpr bool_t operator==(const allocator<U>&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Inequality operator for allocators of same type but with different data type
|
||||
/// \returns \f$true\f$
|
||||
/// \returns \emph{true}
|
||||
template<typename U> constexpr bool_t operator!=(const allocator<U>&) {
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Allocate a block of memory large enough to hold \f$n\f$ elements of type \f$T\f$
|
||||
/// \brief Allocate a block of memory large enough to hold \emph{n} elements of type \emph{T}
|
||||
/// \param n The number of elements
|
||||
/// \returns A pointer to the allocated block
|
||||
constexpr T* allocate(size_t n) {
|
||||
@@ -206,7 +201,7 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Allocate a block of memory large enough to hold \f$n\f$ elements of type \f$T\f$
|
||||
/// \brief Allocate a block of memory large enough to hold \emph{n} elements of type \emph{T}
|
||||
/// \param n The number of elements
|
||||
/// \param align The alignment
|
||||
/// \returns A pointer to the allocated block
|
||||
@@ -215,14 +210,14 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Deallocate a block of memory with type \f$T\f$
|
||||
/// \brief Deallocate a block of memory with type \emph{T}
|
||||
/// \param ptr The block to release
|
||||
constexpr void deallocate(T* ptr) {
|
||||
return ::operator delete(ptr);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Deallocate a block of memory with type \f$T\f$
|
||||
/// \brief Deallocate a block of memory with type \emph{T}
|
||||
/// \param ptr The block to release
|
||||
/// \param align The alignment
|
||||
constexpr void deallocate(T* ptr, align_t align) {
|
||||
@@ -232,7 +227,7 @@ public:
|
||||
|
||||
|
||||
///
|
||||
/// \brief Allocator implementation, uses \f$new\f$ and \f$delete\f$ operators.
|
||||
/// \brief Allocator implementation, uses \emph{new} and \emph{delete} operators.
|
||||
/// \tparam T The data type to allocate
|
||||
template<typename T>
|
||||
class allocator<T[]>
|
||||
@@ -260,40 +255,40 @@ public:
|
||||
|
||||
///
|
||||
/// \brief Copy Assignment
|
||||
/// \returns A reference to self
|
||||
/// \returns A reference to \emph{this}
|
||||
constexpr allocator& operator=(const allocator&) = default;
|
||||
|
||||
|
||||
///
|
||||
/// \brief Equality operator
|
||||
/// \returns \f$true\f$
|
||||
/// \returns \emph{true}
|
||||
constexpr bool_t operator==(const allocator&) {
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Inequality operator
|
||||
/// \returns \f$false\f$
|
||||
/// \returns \emph{false}
|
||||
constexpr bool_t operator!=(const allocator&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Equality operator for allocators of same type but with different data type
|
||||
/// \returns \f$false\f$
|
||||
/// \returns \emph{false}
|
||||
template<typename U> constexpr bool_t operator==(const allocator<U>&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Inequality operator for allocators of same type but with different data type
|
||||
/// \returns \f$true\f$
|
||||
/// \returns \emph{true}
|
||||
template<typename U> constexpr bool_t operator!=(const allocator<U>&) {
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Allocate a block of memory large enough to hold \f$n\f$ elements of type \f$T\f$
|
||||
/// \brief Allocate a block of memory large enough to hold \emph{n} elements of type \emph{T}
|
||||
/// \param n The number of elements
|
||||
/// \returns A pointer to the allocated block
|
||||
constexpr T* allocate(size_t n) {
|
||||
@@ -301,7 +296,7 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Allocate a block of memory large enough to hold \f$n\f$ elements of type \f$T\f$
|
||||
/// \brief Allocate a block of memory large enough to hold \emph{n} elements of type \emph{T}
|
||||
/// \param n The number of elements
|
||||
/// \param align The alignment
|
||||
/// \returns A pointer to the allocated block
|
||||
@@ -310,14 +305,14 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Deallocate a block of memory with type \f$T\f$
|
||||
/// \brief Deallocate a block of memory with type \emph{T}
|
||||
/// \param ptr The block to release
|
||||
constexpr void deallocate(T* ptr) {
|
||||
return ::operator delete[](ptr);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Deallocate a block of memory with type \f$T\f$
|
||||
/// \brief Deallocate a block of memory with type \emph{T}
|
||||
/// \param ptr The block to release
|
||||
/// \param align The alignment
|
||||
constexpr void deallocate(T* ptr, align_t align) {
|
||||
@@ -364,14 +359,14 @@ public:
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \brief Default Constructor, initializes internal data to \f$null\f$ and the capacity to \f$0\f$
|
||||
/// \brief Default Constructor, initializes internal data to \emph{null} and the capacity to \emph{0}
|
||||
constexpr allocation() noexcept
|
||||
: _data(nullptr), _capacity(0), _alignment(zero<align_t>()) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Sized Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes
|
||||
/// \param n The number of elements of type \f$T\f$ to allocate for
|
||||
/// \param n The number of elements of type \emph{T} to allocate for
|
||||
explicit constexpr allocation(size_t n) noexcept
|
||||
: _data(nullptr), _capacity(0), _alignment(zero<align_t>()) {
|
||||
allocate(n);
|
||||
@@ -389,7 +384,7 @@ public:
|
||||
|
||||
///
|
||||
/// \brief Sized Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes
|
||||
/// \param n The number of elements of type \f$T\f$ to allocate for
|
||||
/// \param n The number of elements of type \emph{T} to allocate for
|
||||
/// \param align The alignment of the allocation
|
||||
constexpr allocation(size_t n, align_t align) noexcept
|
||||
: _data(nullptr)
|
||||
@@ -413,7 +408,7 @@ public:
|
||||
/// \brief Allocator Constructor
|
||||
/// \param alloc The allocation object to copy.
|
||||
///
|
||||
/// \details This constructor should be used when the type \f$AllocT\f$ needs internal data.
|
||||
/// \details This constructor should be used when the type \emph{AllocT} needs internal data.
|
||||
explicit constexpr allocation(const alloc_t& alloc) noexcept
|
||||
: _alloc(alloc)
|
||||
, _data(nullptr)
|
||||
@@ -423,10 +418,10 @@ public:
|
||||
|
||||
///
|
||||
/// \brief Sized Allocator Constructor
|
||||
/// \param n The number of elements of type \f$T\f$ to allocate for
|
||||
/// \param n The number of elements of type \emph{T} to allocate for
|
||||
/// \param alloc The allocation object to copy.
|
||||
///
|
||||
/// \details This constructor should be used when the type \f$AllocT\f$ needs internal data.
|
||||
/// \details This constructor should be used when the type \emph{AllocT} needs internal data.
|
||||
constexpr allocation(size_t n, const alloc_t& alloc) noexcept
|
||||
: _alloc(alloc)
|
||||
, _data(nullptr)
|
||||
@@ -442,7 +437,7 @@ public:
|
||||
/// \param n the number of elements
|
||||
/// \param alloc The allocation object to copy.
|
||||
///
|
||||
/// \details This constructor should be used when the type \f$AllocT\f$ needs internal data.
|
||||
/// \details This constructor should be used when the type \emph{AllocT} needs internal data.
|
||||
constexpr allocation(const T* data, size_t n, const alloc_t& alloc)
|
||||
: allocation(n, alloc) {
|
||||
fennec::memmove(static_cast<void*>(_data), data, n);
|
||||
@@ -450,11 +445,11 @@ public:
|
||||
|
||||
///
|
||||
/// \brief Sized Allocator Constructor
|
||||
/// \param n The number of elements of type \f$T\f$ to allocate for
|
||||
/// \param n The number of elements of type \emph{T} to allocate for
|
||||
/// \param align The alignment of the allocation
|
||||
/// \param alloc The allocation object to copy.
|
||||
///
|
||||
/// \details This constructor should be used when the type \f$AllocT\f$ needs internal data.
|
||||
/// \details This constructor should be used when the type \emph{AllocT} needs internal data.
|
||||
constexpr allocation(size_t n, align_t align, const alloc_t& alloc) noexcept
|
||||
: _alloc(alloc)
|
||||
, _data(nullptr)
|
||||
@@ -471,7 +466,7 @@ public:
|
||||
/// \param align The alignment of the allocation
|
||||
/// \param alloc The allocation object to copy.
|
||||
///
|
||||
/// \details This constructor should be used when the type \f$AllocT\f$ needs internal data.
|
||||
/// \details This constructor should be used when the type \emph{AllocT} needs internal data.
|
||||
constexpr allocation(const T* data, size_t n, align_t align, const alloc_t& alloc)
|
||||
: allocation(n, align, alloc) {
|
||||
fennec::memmove(_data, data, n);
|
||||
@@ -489,7 +484,7 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Move Constructor, moves the data in \f$alloc\f$ to the new object and cleans \f$alloc\f$ so that it
|
||||
/// \brief Move Constructor, moves the data in \emph{alloc} to the new object and cleans \emph{alloc} so that it
|
||||
/// can safely destruct
|
||||
/// \param alloc The allocation to move
|
||||
constexpr allocation(allocation&& alloc) noexcept
|
||||
@@ -522,7 +517,7 @@ public:
|
||||
///
|
||||
/// \brief Copy Assignment Operator
|
||||
/// \param alloc the allocation to copy
|
||||
/// \returns a reference to \f$this\f$
|
||||
/// \returns a reference to \emph{this}
|
||||
constexpr allocation& operator=(const allocation& alloc) {
|
||||
allocation::allocate(alloc.capacity(), alloc.alignment());
|
||||
fennec::memmove(_data, alloc, size());
|
||||
@@ -532,7 +527,7 @@ public:
|
||||
///
|
||||
/// \brief Move Assignment Operator
|
||||
/// \param alloc the allocation to copy
|
||||
/// \returns a reference to \f$this\f$
|
||||
/// \returns a reference to \emph{this}
|
||||
constexpr allocation& operator=(allocation&& alloc) noexcept {
|
||||
|
||||
// Copy contents
|
||||
@@ -561,7 +556,7 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Getter for the number of elements \f$n\f$ of type \f$T\f$ that the allocation can hold.
|
||||
/// \brief Getter for the number of elements \emph{n} of type \emph{T} that the allocation can hold.
|
||||
/// \returns the size of the allocation in elements
|
||||
constexpr size_t capacity() const {
|
||||
return _capacity;
|
||||
@@ -588,7 +583,7 @@ public:
|
||||
/// \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 n The number of elements of type \emph{T} to allocate for
|
||||
/// \param align The alignment to use
|
||||
constexpr void allocate(size_t n, align_t align = zero<align_t>()) noexcept {
|
||||
deallocate();
|
||||
@@ -620,7 +615,7 @@ 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 n The number of elements of type \emph{T} to allocate for
|
||||
/// \param align The alignment to use
|
||||
constexpr void reallocate(size_t n, align_t align = zero<align_t>()) noexcept {
|
||||
if (_data == nullptr) {
|
||||
@@ -628,7 +623,8 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
value_t* old = _data; size_t old_cap = _capacity;
|
||||
value_t* old = _data;
|
||||
const size_t old_cap = _capacity;
|
||||
_data = nullptr;
|
||||
allocate(n, align);
|
||||
|
||||
@@ -655,7 +651,7 @@ public:
|
||||
|
||||
///
|
||||
/// \param i The index to access
|
||||
/// \returns a reference to the value at position \f$i\f$ in the allocation
|
||||
/// \returns a reference to the value at position \emph{i} in the allocation
|
||||
constexpr value_t& operator[](size_t i) {
|
||||
assertd(i < capacity(), "Array Out of Bounds");
|
||||
return _data[i];
|
||||
@@ -664,7 +660,7 @@ public:
|
||||
///
|
||||
/// \brief Array Access Operator
|
||||
/// \param i The index to access
|
||||
/// \returns a reference to the value at position \f$i\f$ in the allocation
|
||||
/// \returns a reference to the value at position \emph{i} in the allocation
|
||||
constexpr const value_t& operator[](size_t i) const {
|
||||
assertd(i < capacity(), "Array Out of Bounds");
|
||||
return _data[i];
|
||||
|
||||
@@ -89,27 +89,27 @@ public:
|
||||
///
|
||||
/// \brief Array Access Operator
|
||||
/// \param i the index to access
|
||||
/// \returns a reference to the byte at \f$i\f$
|
||||
/// \returns a reference to the byte at \emph{i}
|
||||
constexpr byte_t& operator[](int i) {
|
||||
assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
|
||||
assertd(i >= 0 && (size_t)i < _size, "Array Out of Bounds");
|
||||
assertd(i >= 0 && size_t(i) < _size, "Array Out of Bounds");
|
||||
return _arr[i];
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Const Array Access Operator
|
||||
/// \param i the index to access
|
||||
/// \returns a copy of the byte at \f$i\f$
|
||||
/// \returns a copy of the byte at \emph{i}
|
||||
constexpr byte_t operator[](int i) const {
|
||||
assertd(not _const, "Attempted to Access Const-Qualified Memory as Non-Const");
|
||||
assertd(i >= 0 && (size_t)i < _size, "Array Out of Bounds");
|
||||
assertd(i >= 0 && size_t(i) < _size, "Array Out of Bounds");
|
||||
return _carr[i];
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Cast Function
|
||||
/// \tparam T type to cast to
|
||||
/// \returns a pointer to the underlying buffer interpreted as an array of \f$T\f$
|
||||
/// \returns a pointer to the underlying buffer interpreted as an array of \emph{T}
|
||||
template<typename T>
|
||||
constexpr T* cast() {
|
||||
void* temp = _arr;
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
///
|
||||
/// \brief Const Cast Function
|
||||
/// \tparam T type to cast to
|
||||
/// \returns a pointer to the underlying buffer interpreted as an array of \f$T\f$
|
||||
/// \returns a pointer to the underlying buffer interpreted as an array of \emph{T}
|
||||
template<typename T>
|
||||
constexpr const T* cast() const {
|
||||
const void* temp = _carr;
|
||||
@@ -166,8 +166,8 @@ struct hash<byte_array> {
|
||||
h *= m;
|
||||
}
|
||||
|
||||
const uint8_t* b = (const uint8_t*)x;
|
||||
switch (n & 7) {
|
||||
const uint8_t* b = reinterpret_cast<const uint8_t*>(x);
|
||||
switch (n & 0x7) {
|
||||
case 7: h ^= uint64_t(b[6]) << 48; __attribute__((fallthrough));
|
||||
case 6: h ^= uint64_t(b[5]) << 40; __attribute__((fallthrough));
|
||||
case 5: h ^= uint64_t(b[4]) << 32; __attribute__((fallthrough));
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
// addressof ===========================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Returns the address of an object regardless of whether the `&` operators is implemented.
|
||||
/// \tparam TypeT The type of the objects
|
||||
@@ -48,24 +50,45 @@ constexpr TypeT* addressof(TypeT& obj) {
|
||||
return FENNEC_BUILTIN_ADDRESSOF(obj);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// memchr ==============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Finds the first occurence of ```static_cast<uint8_t>(ch)``` in the first \f$n\f$ bytes
|
||||
/// \brief Finds the first occurrence of `static_cast<uint8_t>(ch)` in the first \emph{n} bytes
|
||||
/// \param arr Pointer to the object, interpreted as an array of bytes
|
||||
/// \param ch The byte to search for
|
||||
/// \param n The number of bytes to search
|
||||
/// \returns A pointer to the location of \f$ch\f$, otherwise \f$nullptr\f$ if \f$ch\f$ is not found.
|
||||
using ::memchr;
|
||||
using ::wmemchr;
|
||||
/// \returns A pointer to the location of \emph{ch}, otherwise \emph{nullptr} if \emph{ch} is not found.
|
||||
constexpr const void* memchr(const void* arr, int ch, size_t n) {
|
||||
return ::memchr(arr, ch, n);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Compares the bytes of \f$lhs\f$ with \f$rhs\f$.
|
||||
/// \brief Finds the first occurrence of `static_cast<wchar_t>(ch)` in the first \emph{n} characters
|
||||
/// \param arr Pointer to the object, interpreted as an array of \emph{wchar_t}
|
||||
/// \param ch The byte to search for
|
||||
/// \param n The number of characters to search
|
||||
/// \returns A pointer to the location of \emph{ch}, otherwise \emph{nullptr} if \emph{ch} is not found.
|
||||
constexpr const wchar_t* wmemchr(const wchar_t* arr, wchar_t ch, size_t n) {
|
||||
return ::wmemchr(arr, ch, n);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// memcmp ==============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Compares the bytes of \emph{lhs} with \emph{rhs}.
|
||||
/// \param lhs The first object, interpreted as an array of bytes
|
||||
/// \param rhs The second object, interpreted as an array of bytes
|
||||
/// \param n The number of bytes to parse
|
||||
/// \returns \f$0\f$ if the first \f$n\f$ bytes of \f$lhs\f$ and \f$rhs\f$ are equivalent. Otherwise, returns \f$1\f$
|
||||
/// for the first byte \f$b\f$ where \f$lhs[b] > \f$ rhs[b]\f$, and \f$-1\f$ for \f$
|
||||
using ::memcmp;
|
||||
using ::wmemcmp;
|
||||
/// \returns \math{0} if the first \emph{n} bytes of \emph{lhs} and \emph{rhs} are equivalent. Otherwise, returns a positive value
|
||||
/// for the first byte \math{b} where \math{\textbf{lhs}[b] > \textbf{rhs}[b]}, and a negative value
|
||||
/// for the first byte \math{b} where \math{\textbf{lhs}[b] < \textbf{rhs}[b]}
|
||||
constexpr int memcmp(const void* lhs, const void* rhs, size_t n) {
|
||||
return ::memcmp(lhs, rhs, n);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Safe version of memcmp
|
||||
@@ -73,26 +96,58 @@ using ::wmemcmp;
|
||||
/// \param rhs The second object, interpreted as an array of bytes
|
||||
/// \param n0 The size, in bytes, of lhs
|
||||
/// \param n1 The size, in bytes, of rhs
|
||||
/// \returns \f$0\f$ if the first \f$min(n0, n1)\f$ bytes of \f$lhs\f$ and \f$rhs\f$ are equivalent. Otherwise, returns \f$1\f$
|
||||
/// for the first byte \f$b\f$ where \f$lhs[b] > \f$ rhs[b]\f$, and \f$-1\f$ for \f$
|
||||
/// \returns \math{0} if the first \emph{min(n0, n1)} bytes of \emph{lhs} and \emph{rhs} are equivalent. Otherwise, returns a positive value
|
||||
/// for the first byte \math{b} where \math{\textbf{lhs}[b] > \textbf{rhs}[b]}, and a negative value
|
||||
/// for the first byte \math{b} where \math{\textbf{lhs}[b] < \textbf{rhs}[b]}
|
||||
constexpr int memcmp_s(const void* lhs, size_t n0, const void* rhs, size_t n1) {
|
||||
return memcmp(lhs, rhs, n0 < n1 ? n0 : n1);
|
||||
return ::memcmp(lhs, rhs, n0 < n1 ? n0 : n1);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// \brief Compares the characters of \emph{lhs} with \emph{rhs}.
|
||||
/// \param lhs The first object, interpreted as an array of \emph{wchar_t}
|
||||
/// \param rhs The second object, interpreted as an array of \emph{wchar_t}
|
||||
/// \param n The number of characters to parse
|
||||
/// \returns \emph{0} if the first \emph{n} characters of \emph{lhs} and \emph{rhs} are equivalent. Otherwise, returns a positive value
|
||||
/// for the first character \math{c} where \math{\textbf{lhs}[c] > \textbf{rhs}[c]}, and a negative value
|
||||
/// for the first character \math{c} where \math{\textbf{lhs}[c] < \textbf{rhs}[c]}
|
||||
constexpr int wmemcmp(const wchar_t* lhs, const wchar_t* rhs, size_t n) {
|
||||
return ::wmemcmp(lhs, rhs, n);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Copies the first \f$n\f$ bytes of \f$src\f$ to \f$dst\f$.
|
||||
/// \brief Safe version of memcmp
|
||||
/// \param lhs The first object, interpreted as an array of \emph{wchar_t}
|
||||
/// \param rhs The second object, interpreted as an array of \emph{wchar_t}
|
||||
/// \param n0 The size, in characters, of lhs
|
||||
/// \param n1 The size, in characters, of rhs
|
||||
/// \returns \emph{0} if the first \emph{min(n0, n1)} character of \emph{lhs} and \emph{rhs} are equivalent. Otherwise, returns a positive value
|
||||
/// for the first character \math{c} where \math{\textbf{lhs}[c] > \textbf{rhs}[c]}, and a negative value
|
||||
/// for the first character \math{c} where \math{\textbf{lhs}[c] < \textbf{rhs}[c]}
|
||||
constexpr int wmemcmp_s(const wchar_t* lhs, size_t n0, const wchar_t* rhs, size_t n1) {
|
||||
return ::wmemcmp(lhs, rhs, n0 < n1 ? n0 : n1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// memcmp ==============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Copies the first \emph{n} bytes of \emph{src} to \emph{dst}.
|
||||
/// \param dst The destination object, interpreted as an array of bytes
|
||||
/// \param src The source object, interpreted as an array of bytes
|
||||
/// \param n The number of bytes to copy
|
||||
/// \returns \f$dst\f$
|
||||
/// \returns \emph{dst}
|
||||
///
|
||||
/// \details memcpy does not do any checking for whether \f$dst\f$ and \f$src\f$ overlap. Let \f$k\f$ be the number of
|
||||
/// bytes of which \f$dst\f$ and \f$src\f$. If \f$k > 0 & src < dst\f$ then the first \f$k\f$ elements of
|
||||
/// \f$src\f$ will be repeated in \f$dst\f$ with a period of \f$k\f$.
|
||||
/// \details memcpy does not do any checking for whether \emph{dst} and \emph{src} overlap. Let \math{k} be the offset
|
||||
/// by which \emph{dst} and \emph{src} overlap. If \math{k > 0 & \textbf{src} < \textbf{dst}} then the first \math{k} elements of
|
||||
/// \emph{src} will be repeated in \emph{dst} with a period of \math{k}.
|
||||
///
|
||||
/// A full mathematical proof of this function is possible in Set Theory.
|
||||
using ::memcpy;
|
||||
using ::wmemcpy;
|
||||
constexpr void* memcpy(void* dst, const void* src, size_t n) {
|
||||
return ::memcpy(dst, src, n);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Safe version of memcpy
|
||||
@@ -100,19 +155,64 @@ using ::wmemcpy;
|
||||
/// \param src The source object, interpreted as an array of bytes
|
||||
/// \param n0 The size, in bytes, of dst
|
||||
/// \param n1 The size, in bytes, of src
|
||||
/// \returns \f$dst\f$
|
||||
/// \returns \emph{dst}
|
||||
///
|
||||
/// \details memcpy does not do any checking for whether \emph{dst} and \emph{src} overlap. Let \math{k} be the offset
|
||||
/// by which \emph{dst} and \emph{src} overlap. If \math{k > 0 & \textbf{src} < \textbf{dst}} then the first \math{k} elements of
|
||||
/// \emph{src} will be repeated in \emph{dst} with a period of \math{k}.
|
||||
///
|
||||
/// A full mathematical proof of this function is possible in Set Theory.
|
||||
constexpr void* memcpy_s(void* dst, size_t n0, const void* src, size_t n1) {
|
||||
return memcpy(dst, src, n0 < n1 ? n0 : n1);
|
||||
return ::memcpy(dst, src, n0 < n1 ? n0 : n1);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// \brief Copies the first \emph{n} characters of \emph{src} to \emph{dst}.
|
||||
/// \param dst The destination object, interpreted as an array of \emph{wchar_t}
|
||||
/// \param src The source object, interpreted as an array of \emph{wchar_t}
|
||||
/// \param n The number of characters to copy
|
||||
/// \returns \emph{dst}
|
||||
///
|
||||
/// \details wmemcpy does not do any checking for whether \emph{dst} and \emph{src} overlap. Let \math{k} be the offset
|
||||
/// by which \emph{dst} and \emph{src} overlap. If \math{k > 0 & \textbf{src} < \textbf{dst}} then the first \math{k} elements of
|
||||
/// \emph{src} will be repeated in \emph{dst} with a period of \math{k}.
|
||||
///
|
||||
/// A full mathematical proof of this function is possible in Set Theory.
|
||||
constexpr void* wmemcpy(wchar_t* dst, const wchar_t* src, size_t n) {
|
||||
return ::wmemcpy(dst, src, n);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Copies the first \f$n\f$ bytes of \f$src\f$ to \f$dst\f$, with overlap correction..
|
||||
/// \brief Safe version of wmemcpy
|
||||
/// \param dst The destination object, interpreted as an array of \emph{wchar_t}
|
||||
/// \param src The source object, interpreted as an array of \emph{wchar_t}
|
||||
/// \param n0 The size, in characters, of dst
|
||||
/// \param n1 The size, in characters, of src
|
||||
/// \returns \emph{dst}
|
||||
///
|
||||
/// \details wmemcpy does not do any checking for whether \emph{dst} and \emph{src} overlap. Let \math{k} be the offset
|
||||
/// by which \emph{dst} and \emph{src} overlap. If \math{k > 0 & \textbf{src} < \textbf{dst}} then the first \math{k} elements of
|
||||
/// \emph{src} will be repeated in \emph{dst} with a period of \math{k}.
|
||||
///
|
||||
/// A full mathematical proof of this function is possible in Set Theory.
|
||||
constexpr void* wmemcpy_s(wchar_t* dst, size_t n0, const wchar_t* src, size_t n1) {
|
||||
return ::wmemcpy(dst, src, n0 < n1 ? n0 : n1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// memmove =============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Copies the first \emph{n} bytes of \emph{src} to \emph{dst}, with overlap correction.
|
||||
/// \param dst The destination object, interpreted as an array of bytes
|
||||
/// \param src The source object, interpreted as an array of bytes
|
||||
/// \param n The number of bytes to copy
|
||||
/// \returns \f$dst\f$
|
||||
using ::memmove;
|
||||
using ::wmemmove;
|
||||
/// \returns \emph{dst}
|
||||
constexpr void* memmove(void* dst, const void* src, size_t n) {
|
||||
return ::memmove(dst, src, n);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Safe version of memmove
|
||||
@@ -120,19 +220,54 @@ using ::wmemmove;
|
||||
/// \param src The source object, interpreted as an array of bytes
|
||||
/// \param n0 The size, in bytes, of dst
|
||||
/// \param n1 The size, in bytes, of src
|
||||
/// \returns \f$dst\f$
|
||||
/// \returns \emph{dst}
|
||||
constexpr void* memmove_s(void* dst, size_t n0, const void* src, size_t n1) {
|
||||
return memmove(dst, src, n0 < n1 ? n0 : n1);
|
||||
return ::memmove(dst, src, n0 < n1 ? n0 : n1);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// \brief Copies the first \emph{n} characters of \emph{src} to \emph{dst}, with overlap correction.
|
||||
/// \param dst The destination object, interpreted as an array of \emph{wchar_t}
|
||||
/// \param src The source object, interpreted as an array of \emph{wchar_t}
|
||||
/// \param n The number of characters to copy
|
||||
/// \returns \emph{dst}
|
||||
constexpr void* wmemmove(wchar_t* dst, const wchar_t* src, size_t n) {
|
||||
return ::wmemmove(dst, src, n);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Sets all bytes of \f$dst\f$ to \f$ch\f$, interpreted as an \f$uint8_t\f$
|
||||
/// \brief Safe version of wmemmove
|
||||
/// \param dst The destination object, interpreted as an array of \emph{wchar_t}
|
||||
/// \param src The source object, interpreted as an array of \emph{wchar_t}
|
||||
/// \param n0 The size, in characters, of dst
|
||||
/// \param n1 The size, in characters, of src
|
||||
/// \returns \emph{dst}
|
||||
constexpr wchar_t* wmemmove_s(wchar_t* dst, size_t n0, const wchar_t* src, size_t n1) {
|
||||
return ::wmemmove(dst, src, n0 < n1 ? n0 : n1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// memset ==============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief Sets all bytes of \emph{dst} to \emph{ch}, interpreted as an \emph{uint8_t}
|
||||
/// \param dst The destination object, interpreted as an array of bytes
|
||||
/// \param ch The value, interpreted as an \f$uint8\_t\f$
|
||||
/// \param ch The value, interpreted as an \emph{uint8_t}
|
||||
/// \param n The number of bytes to set
|
||||
/// \returns \f$dst\f$
|
||||
using ::memset;
|
||||
using ::wmemset;
|
||||
constexpr void memset(void* dst, int ch, size_t n) {
|
||||
::memset(dst, ch, n);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Sets all characters of \emph{dst} to \emph{ch}
|
||||
/// \param dst The destination object, interpreted as an array of \emph{wchar_t}
|
||||
/// \param ch The value, interpreted as an \emph{uint8_t}
|
||||
/// \param n The number of characters to set
|
||||
constexpr void wmemset(wchar_t* dst, wchar_t ch, size_t n) {
|
||||
::wmemset(dst, ch, n);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
// see https://git.mslockbo.org/mslockbo/fennec/src/commit/0eeb7ae3cff9d78e98dc5d9fc09bcb98b10986b9 for previous
|
||||
// implementation
|
||||
|
||||
#if FENNEC_COMPILER_GCC
|
||||
#if FENNEC_GLIBC
|
||||
#ifndef __OPTIMIZE__
|
||||
# define __OPTIMIZE__
|
||||
#else
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#if FENNEC_COMPILER_GCC
|
||||
#if FENNEC_GLIBC
|
||||
#ifndef FENNEC_OPTIMIZE_FOUND
|
||||
#undef __OPTIMIZE__
|
||||
#endif
|
||||
|
||||
@@ -54,7 +54,7 @@ struct nothrow_t
|
||||
size_t pagesize();
|
||||
|
||||
///
|
||||
/// \brief Default construct the object of type \f$TypeT\f$ at \f$ptr\f$
|
||||
/// \brief Default construct the object of type \emph{TypeT} at \emph{ptr}
|
||||
/// \tparam TypeT the type to construct
|
||||
/// \param ptr the pointer to the object to construct
|
||||
template<typename TypeT> void construct(TypeT* ptr) {
|
||||
@@ -62,7 +62,7 @@ template<typename TypeT> void construct(TypeT* ptr) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Copy construct the object of type \f$TypeT\f$ at \f$ptr\f$
|
||||
/// \brief Copy construct the object of type \emph{TypeT} at \emph{ptr}
|
||||
/// \tparam TypeT the type to construct
|
||||
/// \param ptr the pointer to the object to construct
|
||||
/// \param val the value to copy
|
||||
@@ -71,7 +71,7 @@ template<typename TypeT> void construct(TypeT* ptr, const TypeT& val) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Move construct the object of type \f$TypeT\f$ at \f$ptr\f$
|
||||
/// \brief Move construct the object of type \emph{TypeT} at \emph{ptr}
|
||||
/// \tparam TypeT the type to construct
|
||||
/// \param ptr the pointer to the object to construct
|
||||
/// \param val the value to take ownership of
|
||||
@@ -80,7 +80,7 @@ template<typename TypeT> void construct(TypeT* ptr, TypeT&& val) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Variadic construct the object of type \f$TypeT\f$ at \f$ptr\f$
|
||||
/// \brief Variadic construct the object of type \emph{TypeT} at \emph{ptr}
|
||||
/// \tparam TypeT the type to construct
|
||||
/// \tparam ArgsT the argument types
|
||||
/// \param ptr the pointer to the object to construct
|
||||
@@ -90,7 +90,7 @@ template<typename TypeT, typename...ArgsT> void construct(TypeT* ptr, ArgsT&&...
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Destruct the object of type \f$TypeT\f$ at \f$ptr\f$
|
||||
/// \brief Destruct the object of type \emph{TypeT} at \emph{ptr}
|
||||
/// \tparam TypeT the type to destruct
|
||||
/// \param ptr the pointer to the object to destruct
|
||||
template<typename TypeT> void destruct(TypeT* ptr) {
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief Struct for wrapping C++ \f$delete\f$
|
||||
/// \brief Struct for wrapping C++ \emph{delete}
|
||||
/// \tparam TypeT The type of the buffer to be deleted
|
||||
template<typename TypeT>
|
||||
struct default_delete
|
||||
@@ -42,7 +42,7 @@ struct default_delete
|
||||
constexpr default_delete(const default_delete<ConvT>&) noexcept {}
|
||||
|
||||
///
|
||||
/// \brief Function Call Operator, calls \f$delete\f$ on \f$ptr\f$
|
||||
/// \brief Function Call Operator, calls \emph{delete} on \emph{ptr}
|
||||
/// \param ptr Memory resource to delete
|
||||
constexpr void operator()(TypeT* ptr) const noexcept {
|
||||
static_assert(not is_void_v<TypeT>, "cannot delete a pointer to an incomplete type");
|
||||
@@ -67,7 +67,7 @@ struct default_delete<TypeT[]>
|
||||
constexpr default_delete(const default_delete<ConvT(*)[]>&) noexcept {}
|
||||
|
||||
///
|
||||
/// \brief Function Call Operator, calls \f$delete\f$ on \f$ptr\f$
|
||||
/// \brief Function Call Operator, calls \emph{delete} on \emph{ptr}
|
||||
/// \param ptr Memory resource to delete
|
||||
template<class ArrT> requires requires { is_convertible_v<ArrT(*)[], TypeT(*)[]> == true; }
|
||||
constexpr void operator()(TypeT* ptr) const noexcept {
|
||||
@@ -122,7 +122,7 @@ public:
|
||||
constexpr unique_ptr(nullptr_t) noexcept : unique_ptr(nullptr, delete_t()) {}
|
||||
|
||||
///
|
||||
/// \brief Pointer Constructor, creates a unique_ptr that owns \f$ptr\f$ with deleter \f$del\f$
|
||||
/// \brief Pointer Constructor, creates a unique_ptr that owns \emph{ptr} with deleter \emph{del}
|
||||
/// \param ptr The resource to own
|
||||
/// \param del The deleter
|
||||
explicit constexpr unique_ptr(pointer_t ptr, const delete_t& del = delete_t())
|
||||
@@ -138,14 +138,16 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Move Constructor, transfers ownership from \f$other\f$
|
||||
/// \brief Move Constructor, transfers ownership from \emph{other}
|
||||
/// \param other The unique_ptr to take ownership from
|
||||
template<typename DerivedT> requires(is_base_of_v<TypeT, DerivedT>)
|
||||
constexpr unique_ptr(unique_ptr<DerivedT>&& other)
|
||||
: _handle(other.release()) {
|
||||
}
|
||||
|
||||
// Delete copy constructor
|
||||
///
|
||||
/// \brief Copy Constructor
|
||||
/// \details Deleted
|
||||
constexpr unique_ptr(const unique_ptr&) = delete;
|
||||
|
||||
///
|
||||
@@ -166,18 +168,21 @@ public:
|
||||
///
|
||||
/// \brief move constructor
|
||||
/// \param r the pointer to take ownership of
|
||||
/// \returns a reference to self
|
||||
/// \returns a reference to \emph{this}
|
||||
constexpr unique_ptr& operator=(unique_ptr&& r) noexcept {
|
||||
_delete = r._delete;
|
||||
fennec::swap(_handle, r._handle);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
private:
|
||||
///
|
||||
/// \brief Copy Assignment
|
||||
/// \details Deleted
|
||||
/// \returns Deleted
|
||||
constexpr unique_ptr& operator=(const unique_ptr&) = delete;
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
// Properties ==========================================================================================================
|
||||
public:
|
||||
@@ -186,14 +191,14 @@ public:
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \returns \f$true\f$ if there is not a held pointer, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if there is not a held pointer, \emph{false} 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
|
||||
/// \returns \emph{true} if there is a held pointer, \emph{false} otherwise
|
||||
operator bool() const {
|
||||
return _handle != nullptr;
|
||||
}
|
||||
@@ -278,11 +283,11 @@ private:
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Creates a unique pointer holding an object of type \f$TypeT\f$
|
||||
/// \brief Creates a unique pointer holding an object of type \emph{TypeT}
|
||||
/// \tparam TypeT The type
|
||||
/// \tparam ArgsT The constructor arguments, automatically deduced
|
||||
/// \param args The constructor arguments
|
||||
/// \returns A unique pointer holding a heap allocated object of type \f$TypeT\f$ constructed with arguments \f$args\f$
|
||||
/// \returns A unique pointer holding a heap allocated object of type \emph{TypeT} constructed with arguments \emph{args}
|
||||
template<typename TypeT, typename...ArgsT>
|
||||
unique_ptr<TypeT> make_unique(ArgsT&&...args) {
|
||||
return unique_ptr<TypeT>(new TypeT(fennec::forward<ArgsT>(args)...));
|
||||
|
||||
@@ -51,9 +51,9 @@ class display_server;
|
||||
///
|
||||
/// \details An implementation for a display server should inherit `display_server_base` and note the following:
|
||||
///
|
||||
/// For a server type \f$DisplayT\f$; any \f$gfxcontext\f$ implementation that wishes to implement \f$DisplayT\f$
|
||||
/// must provide a constructor that accepts a `DisplayT*`. `DisplayT::ctx_registry::register_type` must then be
|
||||
/// called for the \f$gfxcontext\f$ implementation.
|
||||
/// For a server type \emph{DisplayT}; any `gfxcontext` implementation that wishes to implement \emph{DisplayT}
|
||||
/// must provide a constructor that accepts a \emph{DisplayT*}. `DisplayT::ctx_registry::register_type()` must then be
|
||||
/// called for the `gfxcontext` implementation.
|
||||
class display_server : public type_registry<display_server, platform*> {
|
||||
// Definitions & Constants =============================================================================================
|
||||
public:
|
||||
@@ -136,13 +136,13 @@ public:
|
||||
///
|
||||
/// \brief feature support checking function
|
||||
/// \param feature the feature to check
|
||||
/// \returns \f$true\f$ if the feature is supported, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the feature is supported, \emph{false} otherwise
|
||||
bool has_feature(uint32_t feature) const {
|
||||
return features.test(feature);
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns \f$true\f$ if connected to the display server, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if connected to the display server, \emph{false} otherwise
|
||||
virtual bool connected() const = 0;
|
||||
|
||||
/// @}
|
||||
|
||||
@@ -87,14 +87,16 @@ public:
|
||||
/// \brief constructor
|
||||
platform();
|
||||
|
||||
///
|
||||
/// \brief Copy Constructor
|
||||
/// \details Deleted, no semantics for copying a platform
|
||||
platform(const platform&) = delete;
|
||||
|
||||
///
|
||||
/// \brief destructor
|
||||
virtual ~platform() = default;
|
||||
|
||||
|
||||
private:
|
||||
platform(const platform&) = delete;
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
|
||||
@@ -164,15 +164,21 @@ public:
|
||||
|
||||
///
|
||||
/// \returns the current configuration of the window
|
||||
const config& get_config() const { return cfg; }
|
||||
const config& get_config() const {
|
||||
return cfg;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns the parent window
|
||||
window* get_parent() const { return parent; }
|
||||
window* get_parent() const {
|
||||
return parent;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns the nearest top-level window in the hierarchy
|
||||
window* get_root() const { return root; }
|
||||
window* get_root() const {
|
||||
return root;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns the underlying handle of the window
|
||||
@@ -208,19 +214,29 @@ public:
|
||||
|
||||
///
|
||||
/// \returns the width of the window
|
||||
int get_width() const { return state.rect.size.x; }
|
||||
int get_width() const {
|
||||
return state.rect.size.x;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns the height of the window
|
||||
int get_height() const { return state.rect.size.y; }
|
||||
int get_height() const {
|
||||
return state.rect.size.y;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns the x position of the window
|
||||
int get_pos_x() const { return state.rect.position.x; }
|
||||
int get_pos_x() const {
|
||||
return state.rect.position.x;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns the y position of the window
|
||||
int get_pos_y() const { return state.rect.position.y; }
|
||||
int get_pos_y() const {
|
||||
return state.rect.position.y;
|
||||
}
|
||||
|
||||
virtual void set_size(const ivec2& size) = 0;
|
||||
|
||||
/// @}
|
||||
|
||||
@@ -234,22 +250,22 @@ public:
|
||||
|
||||
///
|
||||
/// \brief tests if the window is visible
|
||||
/// \returns \f$true\f$ if the window is visible, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the window is visible, \emph{false} otherwise
|
||||
bool is_visible() const { return state.flags.test(state_visible); }
|
||||
|
||||
///
|
||||
/// \brief tests if the window is a child
|
||||
/// \returns \f$true\f$ if the window is a child, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the window is a child, \emph{false} otherwise
|
||||
bool is_child() const { return state.flags.test(state_child); }
|
||||
|
||||
///
|
||||
/// \brief tests if the window is running
|
||||
/// \returns \f$true\f$ if the window is running, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the window is running, \emph{false} otherwise
|
||||
bool is_running() const { return state.flags.test(state_running); }
|
||||
|
||||
///
|
||||
/// \brief tests if the window is suspended
|
||||
/// \returns \f$true\f$ if the window is suspended, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the window is suspended, \emph{false} otherwise
|
||||
bool is_suspended() const { return state.flags.test(state_suspended); }
|
||||
|
||||
/// @}
|
||||
@@ -265,48 +281,48 @@ public:
|
||||
///
|
||||
/// \brief tests a specific flag
|
||||
/// \param flag the flag from `window::flag_`
|
||||
/// \returns \f$true\f$ if the flag is set, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the flag is set, \emph{false} otherwise
|
||||
bool get_flag(uint8_t flag) const { return cfg.flags.test(flag); }
|
||||
|
||||
|
||||
///
|
||||
/// \brief check if the window is flagged to always be on top of other windows
|
||||
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if set, \emph{false} otherwise
|
||||
bool is_always_on_top() const { return get_flag(flag_always_on_top); }
|
||||
|
||||
///
|
||||
/// \brief check if the window is flagged to have no window decorations
|
||||
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if set, \emph{false} otherwise
|
||||
bool is_borderless() const { return get_flag(flag_borderless); }
|
||||
|
||||
///
|
||||
/// \brief check if the window is flagged to be modal
|
||||
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if set, \emph{false} otherwise
|
||||
bool is_modal() const { return get_flag(flag_modal); }
|
||||
|
||||
///
|
||||
/// \brief check if the window is flagged to pass mouse input to windows underneath from the same application
|
||||
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if set, \emph{false} otherwise
|
||||
bool is_passing_mouse() const { return get_flag(flag_pass_mouse); }
|
||||
|
||||
///
|
||||
/// \brief check if the window is flagged as a popup
|
||||
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if set, \emph{false} otherwise
|
||||
bool is_popup() const { return get_flag(flag_popup); }
|
||||
|
||||
///
|
||||
/// \brief check if the window is flagged to be resizable
|
||||
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if set, \emph{false} otherwise
|
||||
bool is_resizable() const { return get_flag(flag_resizable); }
|
||||
|
||||
///
|
||||
/// \brief check if the window is flagged to be transparent
|
||||
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if set, \emph{false} otherwise
|
||||
bool is_transparent() const { return get_flag(flag_transparent); }
|
||||
|
||||
///
|
||||
/// \brief check if the window is flagged to be unfocusable
|
||||
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if set, \emph{false} otherwise
|
||||
bool is_no_focus() const { return get_flag(flag_no_focus); }
|
||||
|
||||
|
||||
@@ -314,55 +330,55 @@ public:
|
||||
/// \brief sets a specific flag
|
||||
/// \param flag the flag from `window::flag_`
|
||||
/// \param val the value to set the flag to
|
||||
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} on success, \emph{false} otherwise
|
||||
virtual bool set_flag(uint8_t flag, bool val) = 0;
|
||||
|
||||
///
|
||||
/// \brief sets whether to always be on top of other windows
|
||||
/// \param val the value to set the flag to
|
||||
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} on success, \emph{false} otherwise
|
||||
bool set_always_on_top(bool val) { return set_flag(flag_always_on_top, val); }
|
||||
|
||||
///
|
||||
/// \brief sets whether to have no window decorations
|
||||
/// \param val the value to set the flag to
|
||||
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} on success, \emph{false} otherwise
|
||||
bool set_borderless(bool val) { return set_flag(flag_borderless, val); }
|
||||
|
||||
///
|
||||
/// \brief sets whether to be modal
|
||||
/// \param val the value to set the flag to
|
||||
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} on success, \emph{false} otherwise
|
||||
bool set_modal(bool val) { return set_flag(flag_modal, val); }
|
||||
|
||||
///
|
||||
/// \brief sets whether to pass mouse input to windows underneath from the same application
|
||||
/// \param val the value to set the flag to
|
||||
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} on success, \emph{false} otherwise
|
||||
bool set_passing_mouse(bool val) { return set_flag(flag_pass_mouse, val); }
|
||||
|
||||
///
|
||||
/// \brief sets whether the window is a popup
|
||||
/// \param val the value to set the flag to
|
||||
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} on success, \emph{false} otherwise
|
||||
bool set_popup(bool val) { return set_flag(flag_popup, val); }
|
||||
|
||||
///
|
||||
/// \brief sets whether to be resizable
|
||||
/// \param val the value to set the flag to
|
||||
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} on success, \emph{false} otherwise
|
||||
bool set_resizable(bool val) { return set_flag(flag_resizable, val); }
|
||||
|
||||
///
|
||||
/// \brief sets whetherto be transparent
|
||||
/// \param val the value to set the flag to
|
||||
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} on success, \emph{false} otherwise
|
||||
bool set_transparent(bool val) { return set_flag(flag_transparent, val); }
|
||||
|
||||
///
|
||||
/// \brief sets whether to be unfocusable
|
||||
/// \param val the value to set the flag to
|
||||
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} on success, \emph{false} otherwise
|
||||
bool set_no_focus(bool val) { return set_flag(flag_no_focus, val); }
|
||||
|
||||
/// @}
|
||||
@@ -385,10 +401,12 @@ public:
|
||||
|
||||
|
||||
// Protected Member Variables ==========================================================================================
|
||||
public:
|
||||
display_server* const server; //!< the display server the window belongs to
|
||||
window* const parent; //!< the parent window
|
||||
window* const root; //!< the nearest top-level window in the hierarchy
|
||||
|
||||
protected:
|
||||
display_server* const server; //!< the display server the window belongs to
|
||||
window* const parent; //!< the parent window
|
||||
window* root; //!< the nearest top-level window in the hierarchy
|
||||
config cfg; //!< the current configuration
|
||||
state state; //!< the current state
|
||||
unique_ptr<gfxsurface> gfx_surface; //!< the corresponding graphics surface
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief Platform Implementation for Linux-Based Operating Systems
|
||||
class linux_platform : public unix_platform {
|
||||
|
||||
// Constructors & Destructor ===========================================================================================
|
||||
@@ -31,7 +33,7 @@ public:
|
||||
/// \name Constructors & Destructor ================================================================================
|
||||
/// @{
|
||||
|
||||
/// \brief constructor
|
||||
/// \brief Linux Platform Constructor
|
||||
linux_platform()
|
||||
: unix_platform() {
|
||||
}
|
||||
@@ -39,11 +41,18 @@ public:
|
||||
/// @}
|
||||
|
||||
|
||||
//
|
||||
// Initialization ======================================================================================================
|
||||
|
||||
/// \name Initialization
|
||||
/// @{
|
||||
|
||||
void initialize() override; //!< platform initialization
|
||||
void shutdown() override; //!< platform shutdown
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
private:
|
||||
FENNEC_RTTI_CLASS_ENABLE(unix_platform) {
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Generated by wayland-scanner 1.24.0 */
|
||||
/* Generated by wayland-scanner 1.25.0 */
|
||||
|
||||
#ifndef WAYLAND_CLIENT_PROTOCOL_H
|
||||
#define WAYLAND_CLIENT_PROTOCOL_H
|
||||
@@ -841,23 +841,9 @@ extern const struct wl_interface wl_subcompositor_interface;
|
||||
* hidden, or if a NULL wl_buffer is applied. These rules apply
|
||||
* recursively through the tree of surfaces.
|
||||
*
|
||||
* The behaviour of a wl_surface.commit request on a sub-surface
|
||||
* depends on the sub-surface's mode. The possible modes are
|
||||
* synchronized and desynchronized, see methods
|
||||
* wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
|
||||
* mode caches the wl_surface state to be applied when the parent's
|
||||
* state gets applied, and desynchronized mode applies the pending
|
||||
* wl_surface state directly. A sub-surface is initially in the
|
||||
* synchronized mode.
|
||||
*
|
||||
* Sub-surfaces also have another kind of state, which is managed by
|
||||
* wl_subsurface requests, as opposed to wl_surface requests. This
|
||||
* state includes the sub-surface position relative to the parent
|
||||
* surface (wl_subsurface.set_position), and the stacking order of
|
||||
* the parent and its sub-surfaces (wl_subsurface.place_above and
|
||||
* .place_below). This state is applied when the parent surface's
|
||||
* wl_surface state is applied, regardless of the sub-surface's mode.
|
||||
* As the exception, set_sync and set_desync are effective immediately.
|
||||
* A sub-surface can be in one of two modes. The possible modes are
|
||||
* synchronized and desynchronized, see methods wl_subsurface.set_sync and
|
||||
* wl_subsurface.set_desync.
|
||||
*
|
||||
* The main surface can be thought to be always in desynchronized mode,
|
||||
* since it does not have a parent in the sub-surfaces sense.
|
||||
@@ -869,6 +855,15 @@ extern const struct wl_interface wl_subcompositor_interface;
|
||||
* synchronized mode, and then assume that all its child and grand-child
|
||||
* sub-surfaces are synchronized, too, without explicitly setting them.
|
||||
*
|
||||
* If a surface behaves as in synchronized mode, it is effectively
|
||||
* synchronized, otherwise it is effectively desynchronized.
|
||||
*
|
||||
* A sub-surface is initially in the synchronized mode.
|
||||
*
|
||||
* The wl_subsurface interface has requests which modify double-buffered
|
||||
* state of the parent surface (wl_subsurface.set_position, .place_above and
|
||||
* .place_below).
|
||||
*
|
||||
* Destroying a sub-surface takes effect immediately. If you need to
|
||||
* synchronize the removal of a sub-surface to the parent surface update,
|
||||
* unmap the sub-surface first by attaching a NULL wl_buffer, update parent,
|
||||
@@ -899,23 +894,9 @@ extern const struct wl_interface wl_subcompositor_interface;
|
||||
* hidden, or if a NULL wl_buffer is applied. These rules apply
|
||||
* recursively through the tree of surfaces.
|
||||
*
|
||||
* The behaviour of a wl_surface.commit request on a sub-surface
|
||||
* depends on the sub-surface's mode. The possible modes are
|
||||
* synchronized and desynchronized, see methods
|
||||
* wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
|
||||
* mode caches the wl_surface state to be applied when the parent's
|
||||
* state gets applied, and desynchronized mode applies the pending
|
||||
* wl_surface state directly. A sub-surface is initially in the
|
||||
* synchronized mode.
|
||||
*
|
||||
* Sub-surfaces also have another kind of state, which is managed by
|
||||
* wl_subsurface requests, as opposed to wl_surface requests. This
|
||||
* state includes the sub-surface position relative to the parent
|
||||
* surface (wl_subsurface.set_position), and the stacking order of
|
||||
* the parent and its sub-surfaces (wl_subsurface.place_above and
|
||||
* .place_below). This state is applied when the parent surface's
|
||||
* wl_surface state is applied, regardless of the sub-surface's mode.
|
||||
* As the exception, set_sync and set_desync are effective immediately.
|
||||
* A sub-surface can be in one of two modes. The possible modes are
|
||||
* synchronized and desynchronized, see methods wl_subsurface.set_sync and
|
||||
* wl_subsurface.set_desync.
|
||||
*
|
||||
* The main surface can be thought to be always in desynchronized mode,
|
||||
* since it does not have a parent in the sub-surfaces sense.
|
||||
@@ -927,6 +908,15 @@ extern const struct wl_interface wl_subcompositor_interface;
|
||||
* synchronized mode, and then assume that all its child and grand-child
|
||||
* sub-surfaces are synchronized, too, without explicitly setting them.
|
||||
*
|
||||
* If a surface behaves as in synchronized mode, it is effectively
|
||||
* synchronized, otherwise it is effectively desynchronized.
|
||||
*
|
||||
* A sub-surface is initially in the synchronized mode.
|
||||
*
|
||||
* The wl_subsurface interface has requests which modify double-buffered
|
||||
* state of the parent surface (wl_subsurface.set_position, .place_above and
|
||||
* .place_below).
|
||||
*
|
||||
* Destroying a sub-surface takes effect immediately. If you need to
|
||||
* synchronize the removal of a sub-surface to the parent surface update,
|
||||
* unmap the sub-surface first by attaching a NULL wl_buffer, update parent,
|
||||
@@ -1307,6 +1297,7 @@ wl_callback_destroy(struct wl_callback *wl_callback)
|
||||
|
||||
#define WL_COMPOSITOR_CREATE_SURFACE 0
|
||||
#define WL_COMPOSITOR_CREATE_REGION 1
|
||||
#define WL_COMPOSITOR_RELEASE 2
|
||||
|
||||
|
||||
/**
|
||||
@@ -1317,6 +1308,10 @@ wl_callback_destroy(struct wl_callback *wl_callback)
|
||||
* @ingroup iface_wl_compositor
|
||||
*/
|
||||
#define WL_COMPOSITOR_CREATE_REGION_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_wl_compositor
|
||||
*/
|
||||
#define WL_COMPOSITOR_RELEASE_SINCE_VERSION 7
|
||||
|
||||
/** @ingroup iface_wl_compositor */
|
||||
static inline void
|
||||
@@ -1377,6 +1372,18 @@ wl_compositor_create_region(struct wl_compositor *wl_compositor)
|
||||
return (struct wl_region *) id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_compositor
|
||||
*
|
||||
* This request destroys the wl_compositor. This has no effect on any other objects.
|
||||
*/
|
||||
static inline void
|
||||
wl_compositor_release(struct wl_compositor *wl_compositor)
|
||||
{
|
||||
wl_proxy_marshal_flags((struct wl_proxy *) wl_compositor,
|
||||
WL_COMPOSITOR_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_compositor), WL_MARSHAL_FLAG_DESTROY);
|
||||
}
|
||||
|
||||
#define WL_SHM_POOL_CREATE_BUFFER 0
|
||||
#define WL_SHM_POOL_DESTROY 1
|
||||
#define WL_SHM_POOL_RESIZE 2
|
||||
@@ -1516,7 +1523,8 @@ enum wl_shm_error {
|
||||
*
|
||||
* The drm format codes match the macros defined in drm_fourcc.h, except
|
||||
* argb8888 and xrgb8888. The formats actually supported by the compositor
|
||||
* will be reported by the format event.
|
||||
* will be reported by the format event. See drm_fourcc.h for more detailed
|
||||
* format descriptions.
|
||||
*
|
||||
* For all wl_shm formats and unless specified in another protocol
|
||||
* extension, pre-multiplied alpha is used for pixel values.
|
||||
@@ -1978,6 +1986,86 @@ enum wl_shm_format {
|
||||
* 2x2 subsampled Cr:Cb plane 10 bits per channel packed
|
||||
*/
|
||||
WL_SHM_FORMAT_P030 = 0x30333050,
|
||||
/**
|
||||
* [47:0] R:G:B 16:16:16 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_RGB161616 = 0x38344752,
|
||||
/**
|
||||
* [47:0] B:G:R 16:16:16 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_BGR161616 = 0x38344742,
|
||||
/**
|
||||
* [15:0] R 16 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_R16F = 0x48202052,
|
||||
/**
|
||||
* [31:0] G:R 16:16 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_GR1616F = 0x48205247,
|
||||
/**
|
||||
* [47:0] B:G:R 16:16:16 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_BGR161616F = 0x48524742,
|
||||
/**
|
||||
* [31:0] R 32 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_R32F = 0x46202052,
|
||||
/**
|
||||
* [63:0] R:G 32:32 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_GR3232F = 0x46205247,
|
||||
/**
|
||||
* [95:0] R:G:B 32:32:32 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_BGR323232F = 0x46524742,
|
||||
/**
|
||||
* [127:0] R:G:B:A 32:32:32:32 little endian
|
||||
*/
|
||||
WL_SHM_FORMAT_ABGR32323232F = 0x46384241,
|
||||
/**
|
||||
* 2x1 subsampled Cr:Cb plane
|
||||
*/
|
||||
WL_SHM_FORMAT_NV20 = 0x3032564e,
|
||||
/**
|
||||
* non-subsampled Cr:Cb plane
|
||||
*/
|
||||
WL_SHM_FORMAT_NV30 = 0x3033564e,
|
||||
/**
|
||||
* 2x2 subsampled Cb (1) and Cr (2) planes 10 bits per channel
|
||||
*/
|
||||
WL_SHM_FORMAT_S010 = 0x30313053,
|
||||
/**
|
||||
* 2x1 subsampled Cb (1) and Cr (2) planes 10 bits per channel
|
||||
*/
|
||||
WL_SHM_FORMAT_S210 = 0x30313253,
|
||||
/**
|
||||
* non-subsampled Cb (1) and Cr (2) planes 10 bits per channel
|
||||
*/
|
||||
WL_SHM_FORMAT_S410 = 0x30313453,
|
||||
/**
|
||||
* 2x2 subsampled Cb (1) and Cr (2) planes 12 bits per channel
|
||||
*/
|
||||
WL_SHM_FORMAT_S012 = 0x32313053,
|
||||
/**
|
||||
* 2x1 subsampled Cb (1) and Cr (2) planes 12 bits per channel
|
||||
*/
|
||||
WL_SHM_FORMAT_S212 = 0x32313253,
|
||||
/**
|
||||
* non-subsampled Cb (1) and Cr (2) planes 12 bits per channel
|
||||
*/
|
||||
WL_SHM_FORMAT_S412 = 0x32313453,
|
||||
/**
|
||||
* 2x2 subsampled Cb (1) and Cr (2) planes 16 bits per channel
|
||||
*/
|
||||
WL_SHM_FORMAT_S016 = 0x36313053,
|
||||
/**
|
||||
* 2x1 subsampled Cb (1) and Cr (2) planes 16 bits per channel
|
||||
*/
|
||||
WL_SHM_FORMAT_S216 = 0x36313253,
|
||||
/**
|
||||
* non-subsampled Cb (1) and Cr (2) planes 16 bits per channel
|
||||
*/
|
||||
WL_SHM_FORMAT_S416 = 0x36313453,
|
||||
};
|
||||
#endif /* WL_SHM_FORMAT_ENUM */
|
||||
|
||||
@@ -1991,6 +2079,11 @@ struct wl_shm_listener {
|
||||
*
|
||||
* Informs the client about a valid pixel format that can be used
|
||||
* for buffers. Known formats include argb8888 and xrgb8888.
|
||||
*
|
||||
* Extensions to drm_fourcc.h (or the format enum) do not require
|
||||
* increasing the wl_shm version; as a result, clients may receive
|
||||
* format codes which were not in the list at the time the client
|
||||
* was made.
|
||||
* @param format buffer pixel format
|
||||
*/
|
||||
void (*format)(void *data,
|
||||
@@ -3056,6 +3149,7 @@ enum wl_data_device_manager_dnd_action {
|
||||
|
||||
#define WL_DATA_DEVICE_MANAGER_CREATE_DATA_SOURCE 0
|
||||
#define WL_DATA_DEVICE_MANAGER_GET_DATA_DEVICE 1
|
||||
#define WL_DATA_DEVICE_MANAGER_RELEASE 2
|
||||
|
||||
|
||||
/**
|
||||
@@ -3066,6 +3160,10 @@ enum wl_data_device_manager_dnd_action {
|
||||
* @ingroup iface_wl_data_device_manager
|
||||
*/
|
||||
#define WL_DATA_DEVICE_MANAGER_GET_DATA_DEVICE_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_wl_data_device_manager
|
||||
*/
|
||||
#define WL_DATA_DEVICE_MANAGER_RELEASE_SINCE_VERSION 4
|
||||
|
||||
/** @ingroup iface_wl_data_device_manager */
|
||||
static inline void
|
||||
@@ -3126,6 +3224,19 @@ wl_data_device_manager_get_data_device(struct wl_data_device_manager *wl_data_de
|
||||
return (struct wl_data_device *) id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_data_device_manager
|
||||
*
|
||||
* This request destroys the wl_data_device_manager. This has no effect on any other
|
||||
* objects.
|
||||
*/
|
||||
static inline void
|
||||
wl_data_device_manager_release(struct wl_data_device_manager *wl_data_device_manager)
|
||||
{
|
||||
wl_proxy_marshal_flags((struct wl_proxy *) wl_data_device_manager,
|
||||
WL_DATA_DEVICE_MANAGER_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_device_manager), WL_MARSHAL_FLAG_DESTROY);
|
||||
}
|
||||
|
||||
#ifndef WL_SHELL_ERROR_ENUM
|
||||
#define WL_SHELL_ERROR_ENUM
|
||||
enum wl_shell_error {
|
||||
@@ -3691,6 +3802,10 @@ enum wl_surface_error {
|
||||
* surface was destroyed before its role object
|
||||
*/
|
||||
WL_SURFACE_ERROR_DEFUNCT_ROLE_OBJECT = 4,
|
||||
/**
|
||||
* no buffer was attached
|
||||
*/
|
||||
WL_SURFACE_ERROR_NO_BUFFER = 5,
|
||||
};
|
||||
#endif /* WL_SURFACE_ERROR_ENUM */
|
||||
|
||||
@@ -3795,6 +3910,7 @@ wl_surface_add_listener(struct wl_surface *wl_surface,
|
||||
#define WL_SURFACE_SET_BUFFER_SCALE 8
|
||||
#define WL_SURFACE_DAMAGE_BUFFER 9
|
||||
#define WL_SURFACE_OFFSET 10
|
||||
#define WL_SURFACE_GET_RELEASE 11
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_surface
|
||||
@@ -3857,6 +3973,10 @@ wl_surface_add_listener(struct wl_surface *wl_surface,
|
||||
* @ingroup iface_wl_surface
|
||||
*/
|
||||
#define WL_SURFACE_OFFSET_SINCE_VERSION 5
|
||||
/**
|
||||
* @ingroup iface_wl_surface
|
||||
*/
|
||||
#define WL_SURFACE_GET_RELEASE_SINCE_VERSION 7
|
||||
|
||||
/** @ingroup iface_wl_surface */
|
||||
static inline void
|
||||
@@ -3937,9 +4057,11 @@ wl_surface_destroy(struct wl_surface *wl_surface)
|
||||
* If a pending wl_buffer has been committed to more than one wl_surface,
|
||||
* the delivery of wl_buffer.release events becomes undefined. A well
|
||||
* behaved client should not rely on wl_buffer.release events in this
|
||||
* case. Alternatively, a client could create multiple wl_buffer objects
|
||||
* from the same backing storage or use a protocol extension providing
|
||||
* per-commit release notifications.
|
||||
* case. Instead, clients hitting this case should use
|
||||
* wl_surface.get_release or use a protocol extension providing per-commit
|
||||
* release notifications (if none of these options are available, a
|
||||
* fallback can be implemented by creating multiple wl_buffer objects from
|
||||
* the same backing storage).
|
||||
*
|
||||
* Destroying the wl_buffer after wl_buffer.release does not change
|
||||
* the surface contents. Destroying the wl_buffer before wl_buffer.release
|
||||
@@ -4120,21 +4242,48 @@ wl_surface_set_input_region(struct wl_surface *wl_surface, struct wl_region *reg
|
||||
* etc.) is double-buffered. Protocol requests modify the pending state,
|
||||
* as opposed to the active state in use by the compositor.
|
||||
*
|
||||
* A commit request atomically creates a content update from the pending
|
||||
* state, even if the pending state has not been touched. The content
|
||||
* update is placed in a queue until it becomes active. After commit, the
|
||||
* new pending state is as documented for each related request.
|
||||
*
|
||||
* When the content update is applied, the wl_buffer is applied before all
|
||||
* other state. This means that all coordinates in double-buffered state
|
||||
* are relative to the newly attached wl_buffers, except for
|
||||
* wl_surface.attach itself. If there is no newly attached wl_buffer, the
|
||||
* coordinates are relative to the previous content update.
|
||||
*
|
||||
* All requests that need a commit to become effective are documented
|
||||
* to affect double-buffered state.
|
||||
*
|
||||
* Other interfaces may add further double-buffered surface state.
|
||||
*
|
||||
* A commit request atomically creates a Content Update (CU) from the
|
||||
* pending state, even if the pending state has not been touched. The
|
||||
* content update is placed at the end of a per-surface queue until it
|
||||
* becomes active. After commit, the new pending state is as documented for
|
||||
* each related request.
|
||||
*
|
||||
* A CU is either a Desync Content Update (DCU) or a Sync Content Update
|
||||
* (SCU). If the surface is effectively synchronized at the commit request,
|
||||
* it is a SCU, otherwise a DCU.
|
||||
*
|
||||
* When a surface transitions from effectively synchronized to effectively
|
||||
* desynchronized, all SCUs in its queue which are not reachable by any
|
||||
* DCU become DCUs and dependency edges from outside the queue to these CUs
|
||||
* are removed.
|
||||
*
|
||||
* See wl_subsurface for the definition of 'effectively synchronized' and
|
||||
* 'effectively desynchronized'.
|
||||
*
|
||||
* When a CU is placed in the queue, the CU has a dependency on the CU in
|
||||
* front of it and to the SCU at end of the queue of every direct child
|
||||
* surface if that SCU exists and does not have another dependent. This can
|
||||
* form a directed acyclic graph of CUs with dependencies as edges.
|
||||
*
|
||||
* In addition to surface state, the CU can have constraints that must be
|
||||
* satisfied before it can be applied. Other interfaces may add CU
|
||||
* constraints.
|
||||
*
|
||||
* All DCUs which do not have a SCU in front of themselves in their queue,
|
||||
* are candidates. If the graph that's reachable by a candidate does not
|
||||
* have any unsatisfied constraints, the entire graph must be applied
|
||||
* atomically.
|
||||
*
|
||||
* When a CU is applied, the wl_buffer is applied before all other state.
|
||||
* This means that all coordinates in double-buffered state are relative to
|
||||
* the newly attached wl_buffers, except for wl_surface.attach itself. If
|
||||
* there is no newly attached wl_buffer, the coordinates are relative to
|
||||
* the previous content update.
|
||||
*/
|
||||
static inline void
|
||||
wl_surface_commit(struct wl_surface *wl_surface)
|
||||
@@ -4288,6 +4437,39 @@ wl_surface_offset(struct wl_surface *wl_surface, int32_t x, int32_t y)
|
||||
WL_SURFACE_OFFSET, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup iface_wl_surface
|
||||
*
|
||||
* Create a callback for the release of the buffer attached by the client
|
||||
* with wl_surface.attach.
|
||||
*
|
||||
* The compositor will release the buffer when it has finished its usage of
|
||||
* the underlying storage for the relevant commit. Once the client receives
|
||||
* this event, and assuming the associated buffer is not pending release
|
||||
* from other wl_surface.commit requests, the client can safely re-use the
|
||||
* buffer.
|
||||
*
|
||||
* Release callbacks are double-buffered state, and will be associated
|
||||
* with the pending buffer at wl_surface.commit time.
|
||||
*
|
||||
* The callback_data passed in the wl_callback.done event is unused and
|
||||
* is always zero.
|
||||
*
|
||||
* Sending this request without attaching a non-null buffer in the same
|
||||
* content update is a protocol error. The compositor will send the
|
||||
* no_buffer error in this case.
|
||||
*/
|
||||
static inline struct wl_callback *
|
||||
wl_surface_get_release(struct wl_surface *wl_surface)
|
||||
{
|
||||
struct wl_proxy *callback;
|
||||
|
||||
callback = wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
|
||||
WL_SURFACE_GET_RELEASE, &wl_callback_interface, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, NULL);
|
||||
|
||||
return (struct wl_callback *) callback;
|
||||
}
|
||||
|
||||
#ifndef WL_SEAT_CAPABILITY_ENUM
|
||||
#define WL_SEAT_CAPABILITY_ENUM
|
||||
/**
|
||||
@@ -6344,20 +6526,18 @@ wl_subsurface_destroy(struct wl_subsurface *wl_subsurface)
|
||||
/**
|
||||
* @ingroup iface_wl_subsurface
|
||||
*
|
||||
* This schedules a sub-surface position change.
|
||||
* This sets the position of the sub-surface, relative to the parent
|
||||
* surface.
|
||||
*
|
||||
* The sub-surface will be moved so that its origin (top left
|
||||
* corner pixel) will be at the location x, y of the parent surface
|
||||
* coordinate system. The coordinates are not restricted to the parent
|
||||
* surface area. Negative values are allowed.
|
||||
*
|
||||
* The scheduled coordinates will take effect whenever the state of the
|
||||
* parent surface is applied.
|
||||
*
|
||||
* If more than one set_position request is invoked by the client before
|
||||
* the commit of the parent surface, the position of a new request always
|
||||
* replaces the scheduled position from any previous request.
|
||||
*
|
||||
* The initial position is 0, 0.
|
||||
*
|
||||
* Position is double-buffered state on the parent surface, see
|
||||
* wl_subsurface and wl_surface.commit for more information.
|
||||
*/
|
||||
static inline void
|
||||
wl_subsurface_set_position(struct wl_subsurface *wl_subsurface, int32_t x, int32_t y)
|
||||
@@ -6375,13 +6555,11 @@ wl_subsurface_set_position(struct wl_subsurface *wl_subsurface, int32_t x, int32
|
||||
* parent surface. Using any other surface, including this sub-surface,
|
||||
* will cause a protocol error.
|
||||
*
|
||||
* The z-order is double-buffered. Requests are handled in order and
|
||||
* applied immediately to a pending state. The final pending state is
|
||||
* copied to the active state the next time the state of the parent
|
||||
* surface is applied.
|
||||
*
|
||||
* A new sub-surface is initially added as the top-most in the stack
|
||||
* of its siblings and parent.
|
||||
*
|
||||
* Z-order is double-buffered state on the parent surface, see
|
||||
* wl_subsurface and wl_surface.commit for more information.
|
||||
*/
|
||||
static inline void
|
||||
wl_subsurface_place_above(struct wl_subsurface *wl_subsurface, struct wl_surface *sibling)
|
||||
@@ -6394,6 +6572,7 @@ wl_subsurface_place_above(struct wl_subsurface *wl_subsurface, struct wl_surface
|
||||
* @ingroup iface_wl_subsurface
|
||||
*
|
||||
* The sub-surface is placed just below the reference surface.
|
||||
*
|
||||
* See wl_subsurface.place_above.
|
||||
*/
|
||||
static inline void
|
||||
@@ -6407,18 +6586,9 @@ wl_subsurface_place_below(struct wl_subsurface *wl_subsurface, struct wl_surface
|
||||
* @ingroup iface_wl_subsurface
|
||||
*
|
||||
* Change the commit behaviour of the sub-surface to synchronized
|
||||
* mode, also described as the parent dependent mode.
|
||||
* mode.
|
||||
*
|
||||
* In synchronized mode, wl_surface.commit on a sub-surface will
|
||||
* accumulate the committed state in a cache, but the state will
|
||||
* not be applied and hence will not change the compositor output.
|
||||
* The cached state is applied to the sub-surface immediately after
|
||||
* the parent surface's state is applied. This ensures atomic
|
||||
* updates of the parent and all its synchronized sub-surfaces.
|
||||
* Applying the cached state will invalidate the cache, so further
|
||||
* parent surface commits do not (re-)apply old state.
|
||||
*
|
||||
* See wl_subsurface for the recursive effect of this mode.
|
||||
* See wl_subsurface and wl_surface.commit for more information.
|
||||
*/
|
||||
static inline void
|
||||
wl_subsurface_set_sync(struct wl_subsurface *wl_subsurface)
|
||||
@@ -6431,24 +6601,9 @@ wl_subsurface_set_sync(struct wl_subsurface *wl_subsurface)
|
||||
* @ingroup iface_wl_subsurface
|
||||
*
|
||||
* Change the commit behaviour of the sub-surface to desynchronized
|
||||
* mode, also described as independent or freely running mode.
|
||||
* mode.
|
||||
*
|
||||
* In desynchronized mode, wl_surface.commit on a sub-surface will
|
||||
* apply the pending state directly, without caching, as happens
|
||||
* normally with a wl_surface. Calling wl_surface.commit on the
|
||||
* parent surface has no effect on the sub-surface's wl_surface
|
||||
* state. This mode allows a sub-surface to be updated on its own.
|
||||
*
|
||||
* If cached state exists when wl_surface.commit is called in
|
||||
* desynchronized mode, the pending state is added to the cached
|
||||
* state, and applied as a whole. This invalidates the cache.
|
||||
*
|
||||
* Note: even if a sub-surface is set to desynchronized, a parent
|
||||
* sub-surface may override it to behave as synchronized. For details,
|
||||
* see wl_subsurface.
|
||||
*
|
||||
* If a surface's parent surface behaves as desynchronized, then
|
||||
* the cached state is applied on set_desync.
|
||||
* See wl_subsurface and wl_surface.commit for more information.
|
||||
*/
|
||||
static inline void
|
||||
wl_subsurface_set_desync(struct wl_subsurface *wl_subsurface)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Generated by wayland-scanner 1.24.0 */
|
||||
/* Generated by wayland-scanner 1.25.0 */
|
||||
|
||||
#ifndef XDG_SHELL_CLIENT_PROTOCOL_H
|
||||
#define XDG_SHELL_CLIENT_PROTOCOL_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -81,7 +81,7 @@ public:
|
||||
|
||||
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
|
||||
bool connected() const override; //!< check if connected to wayland \returns \emph{true} if connected, \emph{false} otherwise
|
||||
|
||||
void dispatch() override; //!< dispatch the current context
|
||||
|
||||
|
||||
74
include/fennec/platform/linux/wayland/vulkan/context.h
Normal file
74
include/fennec/platform/linux/wayland/vulkan/context.h
Normal file
@@ -0,0 +1,74 @@
|
||||
// =====================================================================================================================
|
||||
// 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 context.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_PLATFORM_LINUX_WAYLAND_VULKAN_CONTEXT_H
|
||||
#define FENNEC_PLATFORM_LINUX_WAYLAND_VULKAN_CONTEXT_H
|
||||
|
||||
#include <fennec/renderers/vulkan/vkcontext.h>
|
||||
#include <fennec/platform/linux/wayland/server.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
class wayland_vkcontext : public vkcontext {
|
||||
|
||||
// Definitions & Constants =============================================================================================
|
||||
public:
|
||||
|
||||
///
|
||||
/// \brief Required Extensions
|
||||
inline static const dynarray<cstring> extensions = {
|
||||
VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME
|
||||
};
|
||||
|
||||
// Constructors & Destructor ===========================================================================================
|
||||
public:
|
||||
|
||||
explicit wayland_vkcontext(display_server* display);
|
||||
|
||||
~wayland_vkcontext();
|
||||
|
||||
// Operations ==========================================================================================================
|
||||
public:
|
||||
|
||||
gfxsurface* create_surface(window* window) override;
|
||||
|
||||
|
||||
// Private Member Variables ============================================================================================
|
||||
private:
|
||||
FENNEC_RTTI_CLASS_ENABLE(vkcontext) {
|
||||
wayland_server::ctx_registry::register_type<wayland_vkcontext>();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_PLATFORM_LINUX_WAYLAND_VULKAN_CONTEXT_H
|
||||
@@ -76,6 +76,8 @@ public:
|
||||
/// @}
|
||||
|
||||
|
||||
void set_size(const ivec2& size) override;
|
||||
|
||||
// Behaviour Flags =====================================================================================================
|
||||
public:
|
||||
|
||||
@@ -86,7 +88,7 @@ public:
|
||||
/// \brief sets a specific flag
|
||||
/// \param flag the flag from `window::flag_`
|
||||
/// \param val the value to set the flag to
|
||||
/// \returns \f$true\f$ on success, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} on success, \emph{false} otherwise
|
||||
bool set_flag(uint8_t flag, bool val) override;
|
||||
|
||||
/// @}
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
//
|
||||
|
||||
///
|
||||
/// \returns \f$true\f$ if the context is valid, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the context is valid, \emph{false} otherwise
|
||||
bool is_valid() override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
/// \brief convert egl error to a readable string
|
||||
/// \param err the error code
|
||||
/// \returns the error string corresponding to \f$err\f$
|
||||
/// \returns the error string corresponding to \emph{err}
|
||||
inline fennec::cstring eglErrorString(EGLint err) {
|
||||
switch (err) {
|
||||
case EGL_SUCCESS: return "None";
|
||||
|
||||
2176
include/fennec/platform/vulkan/volk/volk.h
Normal file
2176
include/fennec/platform/vulkan/volk/volk.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -104,12 +104,13 @@ public:
|
||||
/// \brief destructor
|
||||
~window_manager();
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
private:
|
||||
///
|
||||
/// \brief Copy Constructor
|
||||
/// \details Deleted, no semantics for copying a platform
|
||||
window_manager(const window_manager&) = delete;
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
// Initialization & Update =============================================================================================
|
||||
public:
|
||||
@@ -247,7 +248,7 @@ public:
|
||||
/// \brief tests if the window is visible
|
||||
///
|
||||
/// \param window The window.
|
||||
/// \returns \f$true\f$ if the window is visible, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the window is visible, \emph{false} otherwise
|
||||
bool is_visible(window_id window) const {
|
||||
lock_guard guard(_lock);
|
||||
return _check_state(window, window::state_visible);
|
||||
@@ -257,7 +258,7 @@ public:
|
||||
/// \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
|
||||
/// \returns \emph{true} if the window is a child, \emph{false} otherwise
|
||||
bool is_child(window_id window) const {
|
||||
lock_guard guard(_lock);
|
||||
return _check_state(window, window::state_child);
|
||||
@@ -267,7 +268,7 @@ public:
|
||||
/// \brief tests if the window is running
|
||||
///
|
||||
/// \param window The window.
|
||||
/// \returns \f$true\f$ if the window is running, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the window is running, \emph{false} otherwise
|
||||
bool is_running(window_id window) const {
|
||||
lock_guard guard(_lock);
|
||||
return _check_state(window, window::state_running);
|
||||
@@ -277,7 +278,7 @@ public:
|
||||
/// \brief tests if the window is suspended
|
||||
///
|
||||
/// \param window The window.
|
||||
/// \returns \f$true\f$ if the window is suspended, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the window is suspended, \emph{false} otherwise
|
||||
bool is_suspended(window_id window) const {
|
||||
lock_guard guard(_lock);
|
||||
return _check_state(window, window::state_suspended);
|
||||
@@ -297,7 +298,7 @@ public:
|
||||
///
|
||||
/// \param window The window.
|
||||
/// \param flag the flag from `window::flag_`
|
||||
/// \returns \f$true\f$ if the flag is set, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if the flag is set, \emph{false} otherwise
|
||||
bool get_flag(window_id window, uint8_t flag) {
|
||||
lock_guard guard(_lock);
|
||||
return _get_flag(window, flag);
|
||||
@@ -308,7 +309,7 @@ public:
|
||||
/// \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
|
||||
/// \returns \emph{true} if set, \emph{false} otherwise
|
||||
bool is_always_on_top(window_id window) {
|
||||
return get_flag(window, window::flag_always_on_top);
|
||||
}
|
||||
@@ -317,7 +318,7 @@ public:
|
||||
/// \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
|
||||
/// \returns \emph{true} if set, \emph{false} otherwise
|
||||
bool is_borderless(window_id window) {
|
||||
return get_flag(window, window::flag_borderless);
|
||||
}
|
||||
@@ -326,7 +327,7 @@ public:
|
||||
/// \brief check if the window is flagged to be modal
|
||||
///
|
||||
/// \param window The window.
|
||||
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if set, \emph{false} otherwise
|
||||
bool is_modal(window_id window) {
|
||||
return get_flag(window, window::flag_modal);
|
||||
}
|
||||
@@ -335,7 +336,7 @@ public:
|
||||
/// \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
|
||||
/// \returns \emph{true} if set, \emph{false} otherwise
|
||||
bool is_passing_mouse(window_id window) {
|
||||
return get_flag(window, window::flag_pass_mouse);
|
||||
}
|
||||
@@ -344,7 +345,7 @@ public:
|
||||
/// \brief check if the window is flagged as a popup
|
||||
///
|
||||
/// \param window The window.
|
||||
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if set, \emph{false} otherwise
|
||||
bool is_popup(window_id window) {
|
||||
return get_flag(window, window::flag_popup);
|
||||
}
|
||||
@@ -353,7 +354,7 @@ public:
|
||||
/// \brief check if the window is flagged to be resizable
|
||||
///
|
||||
/// \param window The window.
|
||||
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if set, \emph{false} otherwise
|
||||
bool is_resizable(window_id window) {
|
||||
return get_flag(window, window::flag_resizable);
|
||||
}
|
||||
@@ -362,7 +363,7 @@ public:
|
||||
/// \brief check if the window is flagged to be transparent
|
||||
///
|
||||
/// \param window The window.
|
||||
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if set, \emph{false} otherwise
|
||||
bool is_transparent(window_id window) {
|
||||
return get_flag(window, window::flag_transparent);
|
||||
}
|
||||
@@ -371,7 +372,7 @@ public:
|
||||
/// \brief check if the window is flagged to be unfocusable
|
||||
///
|
||||
/// \param window The window.
|
||||
/// \returns \f$true\f$ if set, \f$false\f$ otherwise
|
||||
/// \returns \emph{true} if set, \emph{false} otherwise
|
||||
bool is_no_focus(window_id window) {
|
||||
return get_flag(window, window::flag_no_focus);
|
||||
}
|
||||
@@ -398,7 +399,6 @@ public:
|
||||
///
|
||||
/// \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);
|
||||
}
|
||||
@@ -408,7 +408,6 @@ public:
|
||||
///
|
||||
/// \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);
|
||||
}
|
||||
@@ -418,7 +417,6 @@ public:
|
||||
///
|
||||
/// \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);
|
||||
}
|
||||
@@ -428,7 +426,6 @@ public:
|
||||
///
|
||||
/// \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);
|
||||
}
|
||||
@@ -438,7 +435,6 @@ public:
|
||||
///
|
||||
/// \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);
|
||||
}
|
||||
@@ -448,7 +444,6 @@ public:
|
||||
///
|
||||
/// \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);
|
||||
}
|
||||
@@ -458,7 +453,6 @@ public:
|
||||
///
|
||||
/// \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);
|
||||
}
|
||||
@@ -468,7 +462,6 @@ public:
|
||||
///
|
||||
/// \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);
|
||||
}
|
||||
|
||||
@@ -76,12 +76,15 @@ public:
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \returns \f$true\f$ if this
|
||||
/// \brief Context Validity
|
||||
/// \returns \emph{true} if the context is initialized and valid, \emph{false} otherwise.
|
||||
virtual bool is_valid() = 0;
|
||||
|
||||
///
|
||||
/// \returns A version struct containing the version of the graphics API.
|
||||
virtual const version& get_version() const { return version; }
|
||||
virtual const version& get_version() const {
|
||||
return version;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
@@ -108,12 +111,6 @@ protected:
|
||||
|
||||
FENNEC_RTTI_CLASS_ENABLE() {
|
||||
}
|
||||
|
||||
|
||||
// Assignment Operators ================================================================================================
|
||||
private:
|
||||
gfxcontext& operator=(const gfxcontext&) = delete;
|
||||
gfxcontext& operator=(gfxcontext&&) = delete;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,536 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 - 2026 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 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/forward.h>
|
||||
#include <fennec/renderers/opengl/lib/enum.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
namespace gl
|
||||
{
|
||||
|
||||
///
|
||||
/// \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 {
|
||||
|
||||
// Private Helpers =====================================================================================================
|
||||
private:
|
||||
static constexpr GLenum get_mutable_traits() {
|
||||
GLenum res;
|
||||
|
||||
// Set READ/DRAW/COPY
|
||||
if constexpr (map_read) {
|
||||
res = GL_STREAM_READ;
|
||||
} else if constexpr (map_write) {
|
||||
res = GL_STREAM_DRAW;
|
||||
} else {
|
||||
res = GL_STREAM_COPY;
|
||||
}
|
||||
|
||||
// Set STATIC/DYNAMIC/STREAM
|
||||
if constexpr (client or coherent) {
|
||||
// do nothing
|
||||
} else if constexpr (dynamic or persistent) {
|
||||
res += 6;
|
||||
} else {
|
||||
res += 3;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
// 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();
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
// Assertions ==========================================================================================================
|
||||
public:
|
||||
|
||||
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)
|
||||
, _data(nullptr)
|
||||
, _mapflags(0) {
|
||||
glGenBuffers(1, &_handle);
|
||||
use();
|
||||
if constexpr(immutable) {
|
||||
glBufferStorage(type, _size, data, flags);
|
||||
} else {
|
||||
glBufferData(type, _size, data, usage);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Buffer Move Constructor
|
||||
/// \param buff The buffer to take ownership of
|
||||
buffer(buffer&& buff) noexcept
|
||||
: _handle(buff)
|
||||
, _size(buff._size)
|
||||
, _data(nullptr)
|
||||
, _mapflags(0) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Buffer Destructor
|
||||
///
|
||||
/// \details Cleans up buffer data and object
|
||||
~buffer() {
|
||||
glDeleteBuffers(1, &_handle);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
private:
|
||||
buffer& operator=(const buffer&) = delete;
|
||||
|
||||
|
||||
// Use & Binding =======================================================================================================
|
||||
public:
|
||||
|
||||
/// \name Use & Binding
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \brief Use this buffer for buffer operations.
|
||||
void use() const {
|
||||
glBindBuffer(type, _handle);
|
||||
}
|
||||
|
||||
///
|
||||
/// \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);
|
||||
}
|
||||
|
||||
///
|
||||
/// \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);
|
||||
if (size <= 0) return;
|
||||
glBindBufferRange(type, i, _handle, offset, size);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
offset = max(offset, GLintptr(0));
|
||||
size = size < 0 ? _size : size;
|
||||
size = min(size, _size - offset);
|
||||
if (size <= 0) return nullptr;
|
||||
return _data = glMapBufferRange(type, offset, size, _mapflags = flags | access);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Release the mapping of the buffer.
|
||||
void unmap() {
|
||||
glUnmapBuffer(type);
|
||||
_data = nullptr;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
// 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, 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>
|
||||
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;
|
||||
size = fennec::min(size, cpy._size - read_offset);
|
||||
size = fennec::min(size, _size - write_offset);
|
||||
if (size <= 0) return;
|
||||
glBindBuffer(COPY_READ, cpy._handle);
|
||||
glBindBuffer(COPY_WRITE, _handle);
|
||||
glCopyBufferSubData(COPY_READ, COPY_WRITE, read_offset, write_offset, size);
|
||||
glBindBuffer(COPY_READ, NULL);
|
||||
glBindBuffer(COPY_WRITE, NULL);
|
||||
}
|
||||
|
||||
///
|
||||
/// \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);
|
||||
if (size <= 0) return;
|
||||
glGetBufferSubData(type, offset, size, data);
|
||||
}
|
||||
|
||||
///
|
||||
/// \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);
|
||||
if (size <= 0) return;
|
||||
glBufferSubData(type, offset, size, data);
|
||||
}
|
||||
|
||||
///
|
||||
/// \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;
|
||||
size = min(size, _size - offset);
|
||||
if (size <= 0) return;
|
||||
glFlushMappedBufferRange(type, offset, size);
|
||||
}
|
||||
|
||||
void invalidate(GLsizeiptr size, GLintptr offset = 0) {
|
||||
offset = max(offset, GLintptr(0));
|
||||
size = size < 0 ? _size : size;
|
||||
size = min(size, _size - offset);
|
||||
if (size <= 0) return;
|
||||
glInvalidateBufferSubData(type, offset, size);
|
||||
}
|
||||
|
||||
|
||||
// TYPED FUNCTIONS =====================================================================================================
|
||||
|
||||
template<typename TypeT>
|
||||
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* _data;
|
||||
GLbitfield _mapflags;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_RENDERERS_OPENGL_LIB_BUFFER_H
|
||||
@@ -107,6 +107,20 @@ enum texture_types : GLenum {
|
||||
};
|
||||
|
||||
|
||||
// Cubemap Faces =======================================================================================================
|
||||
|
||||
///
|
||||
/// \brief OpenGL Cubemap Faces
|
||||
enum cubemap_faces : GLenum {
|
||||
CUBEMAP_POSITIVE_X = GL_TEXTURE_CUBE_MAP_POSITIVE_X, //!< Cube Map +X Face
|
||||
CUBEMAP_NEGATIVE_X = GL_TEXTURE_CUBE_MAP_NEGATIVE_X, //!< Cube Map -X Face
|
||||
CUBEMAP_POSITIVE_Y = GL_TEXTURE_CUBE_MAP_POSITIVE_Y, //!< Cube Map +Y Face
|
||||
CUBEMAP_NEGATIVE_Y = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, //!< Cube Map -Y Face
|
||||
CUBEMAP_POSITIVE_Z = GL_TEXTURE_CUBE_MAP_POSITIVE_Z, //!< Cube Map +Z Face
|
||||
CUBEMAP_NEGATIVE_Z = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, //!< Cube Map -Z Face
|
||||
};
|
||||
|
||||
|
||||
// Built-In Types ======================================================================================================
|
||||
|
||||
///
|
||||
@@ -259,6 +273,9 @@ enum types : GLenum {
|
||||
UINT_ATOMIC_COUNTER = GL_UNSIGNED_INT_ATOMIC_COUNTER, //!< Atomic Counter
|
||||
};
|
||||
|
||||
|
||||
// Pixel Components ====================================================================================================
|
||||
|
||||
///
|
||||
/// \brief OpenGL Pixel Components
|
||||
enum pixel_components : GLenum {
|
||||
@@ -287,10 +304,13 @@ enum pixel_components : GLenum {
|
||||
DEPTH_STENCIL = GL_DEPTH_STENCIL, //!< Combined Depth-Stencil
|
||||
};
|
||||
|
||||
|
||||
// Pixel Formats =======================================================================================================
|
||||
|
||||
///
|
||||
/// \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$
|
||||
/// \brief OpenGL Pixel Formats
|
||||
/// \note UNORM formats are integers interpreted in the normalized range \math{[0.0, 1.0]}
|
||||
/// \note SNORM formats are integers interpreted in the normalized range \math{[-1.0, 1.0]}
|
||||
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
|
||||
@@ -378,6 +398,20 @@ enum pixel_formats : GLint {
|
||||
SRGBA_DXT5 = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, //!< Compressed sRGBA DXT5 Color
|
||||
};
|
||||
|
||||
|
||||
// Framebuffer Attachments =============================================================================================
|
||||
|
||||
|
||||
///
|
||||
/// \brief OpenGL Framebuffer Attachments
|
||||
enum framebuffer_attachments {
|
||||
NO_ATTACHMENT = GL_NONE, //!< No Attachment
|
||||
DEPTH_ATTACHMENT = GL_DEPTH_ATTACHMENT, //!< Depth Attachment
|
||||
STENCIL_ATTACHMENT = GL_STENCIL_ATTACHMENT, //!< Stencil Attachment
|
||||
DEPTH_STENCIL_ATTACHMENT = GL_DEPTH_STENCIL_ATTACHMENT, //!< Depth Stencil Attachment
|
||||
COLOR_ATTACHMENT = GL_COLOR_ATTACHMENT0, //!< Color Attachment
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,331 +0,0 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 - 2026 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 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
|
||||
|
||||
/* Because our implementation targets minimum OpenGL ES 3.2,
|
||||
* we are guaranteed to have the following relevant extensions (Starting from OpenGL ES 3.0):
|
||||
*
|
||||
* OES_texture_compression_astc
|
||||
* EXT_texture_border_clamp
|
||||
* OES_EGL_image_external_essl3
|
||||
* ARB_shader_image_load_store
|
||||
* ARB_stencil_texturing
|
||||
* ARG_shader_image_size
|
||||
* ARB_texture_multisample
|
||||
* ARB_texture_storage_multisample
|
||||
* ARB_sample_locations
|
||||
* OES_texture_view
|
||||
* NV_image_formats
|
||||
* EXT_render_snorm
|
||||
* EXT_render_norm16
|
||||
* EXT_color_buffer_float
|
||||
* OES_copy_image
|
||||
* OES_shader_image_atomic
|
||||
* OES_texture_border_clamp
|
||||
* OES_texture_buffer
|
||||
* OES_texture_cube_map_array
|
||||
* OES_texture_stencil8
|
||||
* OES_texture_storage_multisample_2d_array
|
||||
*/
|
||||
|
||||
|
||||
#include <fennec/math/common.h>
|
||||
#include <fennec/renderers/opengl/lib/fwd.h>
|
||||
#include <fennec/renderers/opengl/lib/enum.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
namespace gl
|
||||
{
|
||||
|
||||
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 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
|
||||
template<GLenum TypeV, GLint FormatV, GLboolean ImmutableV>
|
||||
class texture {
|
||||
|
||||
// Constants ===========================================================================================================
|
||||
|
||||
public:
|
||||
static constexpr GLenum type = TypeV;
|
||||
static constexpr GLint format = FormatV;
|
||||
static constexpr GLboolean immutable = ImmutableV;
|
||||
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;
|
||||
static constexpr GLboolean use_2d = ((is_2d and not is_array) or (is_1d and is_array)) and not sampled;
|
||||
static constexpr GLboolean use_3d = (is_3d or (is_2d and is_array)) and not (sampled or cubemap);
|
||||
|
||||
static constexpr GLint cubemap_faces = 6;
|
||||
static constexpr GLenum base_cubemap_face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||
|
||||
static constexpr GLboolean compressed = type == RGB_DXT1 or type == RGBA_DXT1 or type == RGBA_DXT3 or type == RGBA_DXT5
|
||||
or type == SRGB_DXT1 or type == SRGBA_DXT1 or type == SRGBA_DXT3 or type == SRGBA_DXT5;
|
||||
|
||||
|
||||
// Constructors ========================================================================================================
|
||||
|
||||
///
|
||||
/// \brief 1D Texture Constructor
|
||||
/// \param width The width of the texture
|
||||
/// \param mips The number of mipmap levels
|
||||
/// \param data A pointer to a buffer containing pixel values, used as an offset if a PIXEL_UNPACK_BUFFER is bound.
|
||||
/// \param component The type of each component
|
||||
/// \param layout The layout of components in each pixel
|
||||
/// \param size The size of the image data in bytes, for compressed pixel formats
|
||||
texture(GLsizei width, GLint mips,
|
||||
void* data = nullptr, GLenum component = BYTE, GLenum layout = R, GLsizei size = 0) requires use_1d
|
||||
: _handle(NULL)
|
||||
, _width(width), _height(1), _depth(1)
|
||||
, _samples(1), _mips(mips) {
|
||||
glGenTextures(1, &_handle);
|
||||
start();
|
||||
if constexpr(immutable) {
|
||||
glTexStorage1D(type, _mips, format, _width);
|
||||
glTexSubImage1D(type, 0, 0, _width, layout, component, data);
|
||||
} else if constexpr(compressed) {
|
||||
glCompressedTexImage1D(type, 0, format, _width, 0, size, data);
|
||||
} else {
|
||||
glTexImage1D(type, 0, format, _width, 0, layout, component, data);
|
||||
}
|
||||
genmips();
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief 2D Texture Constructor
|
||||
/// \param width The width of the texture
|
||||
/// \param height The height of the texture, or number of layers for arrays
|
||||
/// \param mips The number of mipmap levels
|
||||
/// \param data A pointer to a buffer containing pixel values, used as an offset if a PIXEL_UNPACK_BUFFER is bound.
|
||||
/// \param component The type of each component
|
||||
/// \param layout The layout of components in each pixel
|
||||
/// \param size The size of the image data in bytes, for compressed pixel formats
|
||||
texture(GLsizei width, GLsizei height, GLint mips,
|
||||
void* data = nullptr, GLenum component = BYTE, GLenum layout = R, GLsizei size = 0) requires use_2d and not cubemap
|
||||
: _handle(NULL)
|
||||
, _width(width), _height(height), _depth(1)
|
||||
, _samples(1), _mips(mips) {
|
||||
glGenTextures(1, &_handle);
|
||||
start();
|
||||
if constexpr(immutable) {
|
||||
glTexStorage2D(type, _mips, format, _width, _height);
|
||||
glTexSubImage2D(type, 0, 0, 0, _width, _height, layout, component, data);
|
||||
} else if constexpr(compressed) {
|
||||
glCompressedTexImage2D(type, 0, format, _width, _height, 0, size, data);
|
||||
} else {
|
||||
glTexImage2D(type, 0, format, _width, _height, 0, layout, component, data);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief 2D Texture Constructor
|
||||
/// \param width The width of the texture
|
||||
/// \param height The height of the texture
|
||||
/// \param depth The depth of the texture, or number of layers for arrays
|
||||
/// \param mips The number of mipmap levels
|
||||
/// \param data A pointer to a buffer containing pixel values, used as an offset if a PIXEL_UNPACK_BUFFER is bound.
|
||||
/// \param component The type of each component
|
||||
/// \param layout The layout of components in each pixel
|
||||
/// \param size The size of the image data in bytes, for compressed pixel formats
|
||||
texture(GLsizei width, GLsizei height, GLsizei depth, GLsizei mips,
|
||||
void* data = nullptr, GLenum component = BYTE, GLenum layout = R, GLsizei size = 0) requires use_3d and not cubemap
|
||||
: _handle(NULL)
|
||||
, _width(width), _height(height), _depth(depth)
|
||||
, _samples(1), _mips(mips) {
|
||||
glGenTextures(1, &_handle);
|
||||
start();
|
||||
if constexpr(immutable) {
|
||||
glTexStorage3D(type, _mips, format, _width, _height, _depth);
|
||||
glTexSubImage3D(type, 0, 0, 0, 0, _width, _height, _depth, layout, component, data);
|
||||
} else if constexpr(compressed) {
|
||||
glCompressedTexImage3D(type, 0, format, _width, _height, _depth, 0, size, data);
|
||||
} else {
|
||||
glTexImage3D(type, 0, format, _width, _height, _depth, 0, layout, component, data);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief 2D Multisample Texture Constructor
|
||||
/// \param width The width of the texture
|
||||
/// \param height The height of the texture
|
||||
/// \param samples The number of samples per pixel
|
||||
/// \param fixed When true, a fixed set of sample locations is used
|
||||
texture(GLsizei width, GLsizei height, GLsizei samples, GLboolean fixed = true) requires sampled and not is_array
|
||||
: _handle(NULL)
|
||||
, _width(width), _height(height), _depth(1)
|
||||
, _samples(samples), _mips(0) {
|
||||
glGenTextures(1, &_handle);
|
||||
start();
|
||||
if constexpr(immutable) {
|
||||
glTexStorage2DMultisample(type, _samples, format, _width, _height, fixed);
|
||||
} else {
|
||||
glTexImage2DMultisample(type, _samples, format, _width, _height, fixed);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief 2D Multisample Array Texture Constructor
|
||||
/// \param width The width of the texture
|
||||
/// \param height The height of the texture
|
||||
/// \param depth The number of layers in the array
|
||||
/// \param samples The number of samples per pixel
|
||||
/// \param fixed When true, a fixed set of sample locations is used
|
||||
texture(GLsizei width, GLsizei height, GLsizei depth, GLsizei samples, GLboolean fixed = true) requires sampled and is_array
|
||||
: _handle(NULL)
|
||||
, _width(width), _height(height), _depth(depth)
|
||||
, _samples(samples), _mips(0) {
|
||||
glGenTextures(1, &_handle);
|
||||
start();
|
||||
if constexpr(immutable) {
|
||||
glTexStorage3DMultisample(type, _samples, format, _width, _height, _depth, fixed);
|
||||
} else {
|
||||
glTexImage3DMultisample(type, _samples, format, _width, _height, _depth, fixed);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Cubemap Constructor
|
||||
/// \param size The size of each face texture
|
||||
/// \param mips The number of mipmap layers
|
||||
/// \param faces An array of pointers to textures containing pixel data for each face
|
||||
/// \param component The component type of the data
|
||||
/// \param layout The layout of the components in the pixel
|
||||
/// \param bytes The size of the image data in bytes, for compressed pixel formats
|
||||
texture(GLsizei size, GLsizei mips,
|
||||
const void* faces[6], GLenum component = BYTE, GLenum layout = R, GLsizei bytes = 0) requires is_2d and cubemap
|
||||
: _handle(NULL)
|
||||
, _width(size), _height(size), _depth(1)
|
||||
, _samples(1), _mips(mips) {
|
||||
glGenTextures(1, &_handle);
|
||||
start();
|
||||
if constexpr(immutable) {
|
||||
glTexStorage2D(type, _mips, format, _width, _height);
|
||||
for (int i = 0; i < cubemap_faces; ++i) {
|
||||
glTexSubImage2D(base_cubemap_face + i, 0, 0, 0, _width, _height, layout, component, faces[i]);
|
||||
}
|
||||
} else if constexpr(compressed) {
|
||||
for (int i = 0; i < cubemap_faces; ++i) {
|
||||
glCompressedTexImage2D(base_cubemap_face + i, 0, format, _width, _height, 0, bytes, faces[i]);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < cubemap_faces; ++i) {
|
||||
glTexImage2D(base_cubemap_face + i, 0, format, _width, _height, 0, layout, component, faces[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Cubemap Array Constructor
|
||||
/// \param size The size of each face texture
|
||||
/// \param depth The number of layers in the array
|
||||
/// \param mips The number of mipmap layers
|
||||
/// \param data A pointer to a buffer containing image data
|
||||
/// \param component The component type of the data
|
||||
/// \param layout The layout of the components in the pixel
|
||||
/// \param bytes The size of the image data in bytes, for compressed pixel formats
|
||||
///
|
||||
/// \details Requires OES_texture_cube_map_array
|
||||
texture(GLsizei size, GLsizei depth, GLsizei mips,
|
||||
const void* data, GLenum component = BYTE, GLenum layout = R, GLsizei bytes = 0) requires is_2d and cubemap
|
||||
: _handle(NULL)
|
||||
, _width(size), _height(size), _depth(depth)
|
||||
, _samples(1), _mips(mips) {
|
||||
glGenTextures(1, &_handle);
|
||||
start();
|
||||
if constexpr(immutable) {
|
||||
glTexStorage3D(type, _mips, format, _width, _height, _depth * 6);
|
||||
glTexSubImage3D(type, 0, 0, 0, 0, _width, _height, _depth * 6, layout, component, data);
|
||||
} else if constexpr(compressed) {
|
||||
for (int i = 0; i < cubemap_faces; ++i) {
|
||||
glCompressedTexImage3D(type, 0, format, _width, _height, _depth * 6, 0, bytes, data);
|
||||
}
|
||||
} else {
|
||||
glTexImage3D(type, 0, format, _width, _height, _depth * 6, 0, layout, component, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Basic Functions =====================================================================================================
|
||||
|
||||
void use() {
|
||||
glBindTexture(type, _handle);
|
||||
}
|
||||
|
||||
void bind(GLint i) {
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
use();
|
||||
}
|
||||
|
||||
void genmips() {
|
||||
glGenerateMipmap(type);
|
||||
}
|
||||
|
||||
private:
|
||||
GLuint _handle;
|
||||
GLsizei _width;
|
||||
GLsizei _height;
|
||||
GLsizei _depth;
|
||||
GLsizei _samples;
|
||||
GLint _mips;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_RENDERERS_OPENGL_LIB_TEXTURE_H
|
||||
@@ -32,7 +32,7 @@
|
||||
#ifndef FENNEC_RENDERERS_VULKAN_LIB_APP_INFO_H
|
||||
#define FENNEC_RENDERERS_VULKAN_LIB_APP_INFO_H
|
||||
|
||||
#include <volk.h>
|
||||
#include <fennec/renderers/vulkan/lib/forward.h>
|
||||
|
||||
#include <fennec/core/version.h>
|
||||
#include <fennec/string/cstring.h>
|
||||
@@ -44,6 +44,12 @@ namespace fennec::vk
|
||||
/// \brief Wrapper class for VkApplicationInfo
|
||||
struct app_info : private VkApplicationInfo {
|
||||
|
||||
// Definitions =========================================================================================================
|
||||
private:
|
||||
|
||||
|
||||
|
||||
|
||||
// Constructors & Destructor ===========================================================================================
|
||||
public:
|
||||
|
||||
@@ -52,30 +58,36 @@ public:
|
||||
|
||||
///
|
||||
/// \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
|
||||
/// until a structure of type fennec::vk::instance is constructed
|
||||
/// \param app_name the name of the application.
|
||||
/// \param app_version the internal version of the application
|
||||
/// \param engine_name the name of the engine, this cstring must exist for the lifetime of this object
|
||||
/// until a structure of type fennec::vk::instance is constructed
|
||||
/// \param engine_name the name of the engine.
|
||||
/// \param engine_version the internal version of the engine
|
||||
/// \param api_version the Vulkan API version to use, version::patch and version::str are ignored
|
||||
/// \param ext a pointer to an extension structure, the object next points to must exist for the lifetime of this
|
||||
/// object until a structure of type fennec::vk::instance is constructed
|
||||
/// TODO: DEFINE EXTENSION STRUCTURE WRAPPERS
|
||||
app_info(
|
||||
const cstring& app_name = {}, const version& app_version = {},
|
||||
const cstring& engine_name = {}, const version& engine_version = {},
|
||||
const version& api_version = {},
|
||||
void* ext = nullptr
|
||||
const cstring& engine_name = {}, const version& engine_version = {}
|
||||
) noexcept : VkApplicationInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||
.pNext = ext,
|
||||
.pApplicationName = app_name,
|
||||
.pNext = nullptr,
|
||||
.pApplicationName = nullptr,
|
||||
.applicationVersion = VK_MAKE_VERSION(app_version.major, app_version.minor, app_version.patch),
|
||||
.pEngineName = engine_name,
|
||||
.pEngineName = nullptr,
|
||||
.engineVersion = VK_MAKE_VERSION(engine_version.major, engine_version.minor, engine_version.patch),
|
||||
.apiVersion = VK_MAKE_API_VERSION(0, api_version.major, api_version.minor, 0),
|
||||
} {
|
||||
.apiVersion = VK_MAKE_API_VERSION(0, 1, 0, 0), // Default to 1.0
|
||||
}, _app_name(app_name)
|
||||
, _engine_name(engine_name) {
|
||||
|
||||
pApplicationName = _app_name.data();
|
||||
pEngineName = _engine_name.data();
|
||||
|
||||
// Attempt to acquire version supported by the driver
|
||||
if (vkEnumerateInstanceVersion) {
|
||||
uint32_t api_version;
|
||||
vkEnumerateInstanceVersion(&api_version);
|
||||
apiVersion = VK_MAKE_API_VERSION(0, VK_API_VERSION_MAJOR(api_version), VK_API_VERSION_MINOR(api_version), 0);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
@@ -102,13 +114,13 @@ public:
|
||||
///
|
||||
/// \brief Copy Assignment
|
||||
/// \param info The app_info object to move
|
||||
/// \returns A reference to self
|
||||
/// \returns A reference to \emph{this}
|
||||
app_info& operator=(const app_info& info) noexcept = default;
|
||||
|
||||
///
|
||||
/// \brief Move Assignment
|
||||
/// \param info The app_info object to move
|
||||
/// \returns A reference to self
|
||||
/// \returns A reference to \emph{this}
|
||||
app_info& operator=(app_info&& info) noexcept = default;
|
||||
|
||||
/// @}
|
||||
@@ -121,14 +133,14 @@ public:
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// \returns \f$this\f$ as if it were a pointer to the underlying type, \f$VkApplicationInfo\f$.
|
||||
/// \returns \emph{this} as if it were a pointer to the underlying type, \emph{VkApplicationInfo}.
|
||||
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$.
|
||||
/// \returns \emph{this} as if it were a pointer to the underlying type, \emph{VkApplicationInfo}.
|
||||
operator const VkApplicationInfo*() const noexcept {
|
||||
return this;
|
||||
}
|
||||
@@ -168,18 +180,22 @@ public:
|
||||
///
|
||||
/// \brief Set the engine version
|
||||
/// \param ver A version struct containing the new version
|
||||
void set_engine_version(const version& ver) {
|
||||
engineVersion = VK_MAKE_VERSION(ver.major, ver.minor, ver.patch);
|
||||
void set_app_version(const version& ver) {
|
||||
applicationVersion = VK_MAKE_VERSION(ver.major, ver.minor, ver.patch);
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns A cstring containing the engine name
|
||||
cstring get_engine_name() const { return cstring(pEngineName, strlen(pEngineName)); }
|
||||
cstring get_engine_name() const {
|
||||
return { pEngineName, strlen(pEngineName) };
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Set the engine name
|
||||
/// \param str A cstring containing the new name
|
||||
void set_engine_name(const cstring& str) { pEngineName = str; }
|
||||
void set_engine_name(const cstring& str) {
|
||||
pEngineName = str;
|
||||
}
|
||||
|
||||
///
|
||||
/// \returns A version struct containing the engine version
|
||||
@@ -203,7 +219,9 @@ public:
|
||||
version get_api_version() const {
|
||||
return version {
|
||||
.major = VK_API_VERSION_MAJOR(apiVersion),
|
||||
.minor = VK_API_VERSION_MINOR(apiVersion)
|
||||
.minor = VK_API_VERSION_MINOR(apiVersion),
|
||||
.patch = VK_API_VERSION_PATCH(apiVersion),
|
||||
.meta = VK_API_VERSION_VARIANT(apiVersion),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -222,7 +240,7 @@ public:
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Clear the extension structure with \f$nullptr\f$
|
||||
/// \brief Clear the extension structure with \emph{nullptr}
|
||||
void set_extension(nullptr_t) {
|
||||
pNext = nullptr;
|
||||
}
|
||||
@@ -232,6 +250,8 @@ public:
|
||||
|
||||
// Private Member Variables ============================================================================================
|
||||
private:
|
||||
string _app_name;
|
||||
string _engine_name;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
145
include/fennec/renderers/vulkan/lib/debug.h
Normal file
145
include/fennec/renderers/vulkan/lib/debug.h
Normal file
@@ -0,0 +1,145 @@
|
||||
// =====================================================================================================================
|
||||
// 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 debug.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_VULKAN_LIB_DEBUG_H
|
||||
#define FENNEC_RENDERERS_VULKAN_LIB_DEBUG_H
|
||||
|
||||
#include <fennec/containers/dynarray.h>
|
||||
#include <fennec/format/format.h>
|
||||
#include <fennec/lang/ranges.h>
|
||||
#include <fennec/renderers/vulkan/lib/forward.h>
|
||||
#include <fennec/renderers/vulkan/lib/enum.h>
|
||||
#include <fennec/string/string.h>
|
||||
|
||||
namespace fennec::vk
|
||||
{
|
||||
|
||||
///
|
||||
/// \brief Vulkan Debugger Interface
|
||||
class debugger {
|
||||
|
||||
// Definitions =========================================================================================================
|
||||
public:
|
||||
|
||||
///
|
||||
/// \brief Info for attaching a debugger to an instance.
|
||||
struct info
|
||||
: private VkDebugUtilsMessengerCreateInfoEXT
|
||||
{
|
||||
explicit info(const debugger& dbg)
|
||||
: VkDebugUtilsMessengerCreateInfoEXT {
|
||||
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.messageSeverity = debug_message_severity_all,
|
||||
.messageType = debug_message_type_all,
|
||||
.pfnUserCallback = _debug_message,
|
||||
.pUserData = const_cast<debugger*>(&dbg),
|
||||
} {
|
||||
}
|
||||
|
||||
operator const VkDebugUtilsMessengerCreateInfoEXT*() const {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Properties ==========================================================================================================
|
||||
public:
|
||||
|
||||
///
|
||||
/// \brief Instance Creation Info
|
||||
/// \returns An info object for attaching this debugger to an instance.
|
||||
info get_info() const {
|
||||
return info(*this);
|
||||
}
|
||||
|
||||
|
||||
// Debug Callbacks =====================================================================================================
|
||||
public:
|
||||
|
||||
///
|
||||
/// \brief
|
||||
/// \param severity The message severity
|
||||
/// \param type The message type
|
||||
/// \param id The message id
|
||||
/// \param message The message string
|
||||
/// \param queue The labels in the queue
|
||||
/// \param commands The labels in the command buffer
|
||||
/// \param objects The related objects
|
||||
virtual void message(uint32_t severity,
|
||||
uint32_t type,
|
||||
const cstring& id,
|
||||
const cstring& message,
|
||||
const dynarray<cstring>& queue,
|
||||
const dynarray<cstring>& commands,
|
||||
const dynarray<string>& objects) = 0;
|
||||
|
||||
|
||||
// Private Helper Functions ============================================================================================
|
||||
private:
|
||||
|
||||
static VkBool32 _debug_message(
|
||||
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
||||
VkDebugUtilsMessageTypeFlagsEXT messageType,
|
||||
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
|
||||
void* pUserData
|
||||
) {
|
||||
const cstring id = cstring(pCallbackData->pMessageIdName, strlen(pCallbackData->pMessageIdName));
|
||||
const cstring message = cstring(pCallbackData->pMessage, strlen(pCallbackData->pMessage));
|
||||
|
||||
dynarray<cstring> queue;
|
||||
dynarray<cstring> commands;
|
||||
dynarray<string> objects;
|
||||
|
||||
debugger* dbg = static_cast<debugger*>(pUserData);
|
||||
|
||||
for (const auto& label : range(pCallbackData->pQueueLabels, pCallbackData->pQueueLabels + pCallbackData->queueLabelCount)) {
|
||||
queue.emplace_back(label.pLabelName, strlen(label.pLabelName));
|
||||
}
|
||||
|
||||
for (const auto& label : range(pCallbackData->pCmdBufLabels, pCallbackData->pCmdBufLabels + pCallbackData->cmdBufLabelCount)) {
|
||||
commands.emplace_back(label.pLabelName, strlen(label.pLabelName));
|
||||
}
|
||||
|
||||
for (const auto& obj : range(pCallbackData->pObjects, pCallbackData->pObjects + pCallbackData->objectCount)) {
|
||||
objects.push_back(format("{:#016x} ({})", obj.objectHandle, object_string(obj.objectType)));
|
||||
}
|
||||
|
||||
dbg->message(messageSeverity, messageType, id, message, queue, commands, objects);
|
||||
|
||||
return VK_FALSE;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_RENDERERS_VULKAN_LIB_DEBUG_H
|
||||
359
include/fennec/renderers/vulkan/lib/enum.h
Normal file
359
include/fennec/renderers/vulkan/lib/enum.h
Normal file
@@ -0,0 +1,359 @@
|
||||
// =====================================================================================================================
|
||||
// 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 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_VULKAN_LIB_ENUM_H
|
||||
#define FENNEC_RENDERERS_VULKAN_LIB_ENUM_H
|
||||
|
||||
#include <fennec/renderers/vulkan/lib/forward.h>
|
||||
|
||||
namespace fennec::vk
|
||||
{
|
||||
|
||||
// Objects =============================================================================================================
|
||||
|
||||
///
|
||||
/// \brief An enum representing the Vulkan object types
|
||||
enum object_ : uint32_t {
|
||||
object_unknown = VK_OBJECT_TYPE_UNKNOWN, //!< Unknown type
|
||||
object_instance = VK_OBJECT_TYPE_INSTANCE, //!< Vulkan Instance
|
||||
object_physical_device = VK_OBJECT_TYPE_PHYSICAL_DEVICE, //!< Physical Device
|
||||
object_logical_device = VK_OBJECT_TYPE_DEVICE, //!< Logical Device
|
||||
object_queue = VK_OBJECT_TYPE_QUEUE, //!< Queue
|
||||
object_semaphore = VK_OBJECT_TYPE_SEMAPHORE, //!< Semaphore
|
||||
object_command_buffer = VK_OBJECT_TYPE_COMMAND_BUFFER, //!< Command Buffer
|
||||
object_fence = VK_OBJECT_TYPE_FENCE, //!< Fence
|
||||
object_device_memory = VK_OBJECT_TYPE_DEVICE_MEMORY, //!< Device Memory
|
||||
object_buffer = VK_OBJECT_TYPE_BUFFER, //!< Buffer
|
||||
object_image = VK_OBJECT_TYPE_IMAGE, //!< Image
|
||||
object_event = VK_OBJECT_TYPE_EVENT, //!< Event
|
||||
object_query_pool = VK_OBJECT_TYPE_QUERY_POOL, //!< Query Pool
|
||||
object_buffer_view = VK_OBJECT_TYPE_BUFFER_VIEW, //!< Buffer View
|
||||
object_image_view = VK_OBJECT_TYPE_IMAGE_VIEW, //!< Image View
|
||||
object_shader_module = VK_OBJECT_TYPE_SHADER_MODULE, //!< Shader Module
|
||||
object_pipeline_cache = VK_OBJECT_TYPE_PIPELINE_CACHE, //!< Pipeline Cache
|
||||
object_pipeline_layout = VK_OBJECT_TYPE_PIPELINE_LAYOUT, //!< Pipeline Layout
|
||||
object_render_pass = VK_OBJECT_TYPE_RENDER_PASS, //!< Render Pass
|
||||
object_pipeline = VK_OBJECT_TYPE_PIPELINE, //!< Pipeline
|
||||
object_descriptor_set_layout = VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, //!< Descriptor Set
|
||||
object_sampler = VK_OBJECT_TYPE_SAMPLER, //!< Sampler
|
||||
object_descriptor_pool = VK_OBJECT_TYPE_DESCRIPTOR_POOL, //!< Descriptor Pool
|
||||
object_descriptor_set = VK_OBJECT_TYPE_DESCRIPTOR_SET, //!< Descriptor Set
|
||||
object_framebuffer = VK_OBJECT_TYPE_FRAMEBUFFER, //!< Framebuffer
|
||||
object_command_pool = VK_OBJECT_TYPE_COMMAND_POOL, //!< Command Pool
|
||||
object_sampler_ycbcr_conversion = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION, //!< YCBCR Conversion Sampler
|
||||
object_descriptor_update_template = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, //!< Descriptor Update Template
|
||||
object_private_data_slot = VK_OBJECT_TYPE_PRIVATE_DATA_SLOT, //!< Private Data Slot
|
||||
object_debug_report_callback_ext = VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT, //!< Debug Report Callback
|
||||
object_debug_utils_messenger_ext = VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT, //!< Debug Utility Messenger
|
||||
object_validation_cache_ext = VK_OBJECT_TYPE_VALIDATION_CACHE_EXT, //!< Validation Cache
|
||||
object_micromap_ext = VK_OBJECT_TYPE_MICROMAP_EXT, //!< Micro-Map
|
||||
object_shader_ext = VK_OBJECT_TYPE_SHADER_EXT, //!< Shader
|
||||
object_indirect_commands_layout_ext = VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_EXT, //!< Indirect Commands Layout
|
||||
object_indirect_execution_set_ext = VK_OBJECT_TYPE_INDIRECT_EXECUTION_SET_EXT, //!< Indirect Execution Set
|
||||
|
||||
object_surface = VK_OBJECT_TYPE_SURFACE_KHR, //!< Surface
|
||||
object_swapchain = VK_OBJECT_TYPE_SWAPCHAIN_KHR, //!< Swap-chain
|
||||
object_display = VK_OBJECT_TYPE_DISPLAY_KHR, //!< Display
|
||||
object_display_mode = VK_OBJECT_TYPE_DISPLAY_MODE_KHR, //!< Display Mode
|
||||
object_video_session = VK_OBJECT_TYPE_VIDEO_SESSION_KHR, //!< Video Session
|
||||
object_video_session_parameters = VK_OBJECT_TYPE_VIDEO_SESSION_PARAMETERS_KHR, //!< Video Session Parameters
|
||||
object_acceleration_structure = VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR, //!< Acceleration Structure
|
||||
object_deferred_operation = VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR, //!< Deferred Operation
|
||||
object_pipeline_binary = VK_OBJECT_TYPE_PIPELINE_BINARY_KHR, //!< Pipeline Binary
|
||||
|
||||
object_acceleration_structure_NV = VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV, //!< NV Acceleration Structure
|
||||
object_indirect_commands_layout_NV = VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV, //!< NV Indirect Commands Layout
|
||||
object_optical_flow_session_NV = VK_OBJECT_TYPE_OPTICAL_FLOW_SESSION_NV, //!< NV Optical Flow Session
|
||||
object_external_compute_queue_NV = VK_OBJECT_TYPE_EXTERNAL_COMPUTE_QUEUE_NV, //!< NV External Compute Queue
|
||||
|
||||
object_cu_module_NVX = VK_OBJECT_TYPE_CU_MODULE_NVX, //!< NVX CU Module
|
||||
object_cu_function_NVX = VK_OBJECT_TYPE_CU_FUNCTION_NVX, //!< NVX CU Function
|
||||
|
||||
object_performance_configuration_INTEL = VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL, //!< Intel Performance Configuration
|
||||
|
||||
object_buffer_collection_FUCHSIA = VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA, //!< Fuchsia Buffer Collection
|
||||
|
||||
object_tensor_ARM = VK_OBJECT_TYPE_TENSOR_ARM, //!< ARM Tensor
|
||||
object_tensor_view_ARM = VK_OBJECT_TYPE_TENSOR_VIEW_ARM, //!< ARM Tensor View
|
||||
object_data_graph_pipeline_session_ARM = VK_OBJECT_TYPE_DATA_GRAPH_PIPELINE_SESSION_ARM, //!< ARM Data Graph Pipeline Session
|
||||
|
||||
// Beta Extensions
|
||||
#ifdef VK_ENABLE_BETA_EXTENSIONS
|
||||
object_cuda_module_NV = VK_OBJECT_TYPE_CUDA_MODULE_NV, //!< NV Cuda Module
|
||||
object_cuda_function_NV = VK_OBJECT_TYPE_CUDA_FUNCTION_NV, //!< NV Cuda Function
|
||||
#endif
|
||||
};
|
||||
|
||||
inline cstring object_string(uint32_t flag) {
|
||||
switch (flag) {
|
||||
default:
|
||||
case object_unknown: return "Unknown";
|
||||
case object_instance: return "Instance";
|
||||
case object_physical_device: return "Physical Device";
|
||||
case object_logical_device: return "Logical Device";
|
||||
case object_queue: return "Queue";
|
||||
case object_semaphore: return "Semaphore";
|
||||
case object_command_buffer: return "Command Buffer";
|
||||
case object_fence: return "Fence";
|
||||
case object_device_memory: return "Device Memory";
|
||||
case object_buffer: return "Buffer";
|
||||
case object_image: return "Image";
|
||||
case object_event: return "Event";
|
||||
case object_query_pool: return "Query Pool";
|
||||
case object_buffer_view: return "Buffer View";
|
||||
case object_image_view: return "Image View";
|
||||
case object_shader_module: return "Shader Module";
|
||||
case object_pipeline_cache: return "Pipeline Cache";
|
||||
case object_pipeline_layout: return "Pipeline Layout";
|
||||
case object_render_pass: return "Render Pass";
|
||||
case object_pipeline: return "Pipeline";
|
||||
case object_descriptor_set_layout: return "Descriptor Set Layout";
|
||||
case object_sampler: return "Sampler";
|
||||
case object_descriptor_pool: return "Descriptor Pool";
|
||||
case object_descriptor_set: return "Descriptor Set";
|
||||
case object_framebuffer: return "Framebuffer";
|
||||
case object_command_pool: return "Command Pool";
|
||||
case object_sampler_ycbcr_conversion: return "YCBCR Conversion Sampler";
|
||||
case object_descriptor_update_template: return "Descriptor Update Template";
|
||||
case object_private_data_slot: return "Private Data Slot";
|
||||
case object_debug_report_callback_ext: return "Report Callback";
|
||||
case object_debug_utils_messenger_ext: return "Debug Messenger";
|
||||
case object_validation_cache_ext: return "Validation Cache";
|
||||
case object_micromap_ext: return "Micro-Map";
|
||||
case object_shader_ext: return "Shader";
|
||||
case object_indirect_commands_layout_ext: return "Indirect Commands Layout";
|
||||
case object_indirect_execution_set_ext: return "Indirect Execution Set";
|
||||
|
||||
case object_surface: return "Surface";
|
||||
case object_swapchain: return "Swap-Chain";
|
||||
case object_display: return "Display";
|
||||
case object_display_mode: return "Display Mode";
|
||||
case object_video_session: return "Video Session";
|
||||
case object_video_session_parameters: return "Video Session Parameters";
|
||||
case object_acceleration_structure: return "Acceleration Structure";
|
||||
case object_deferred_operation: return "Deferred Operation";
|
||||
case object_pipeline_binary: return "Pipeline Binary";
|
||||
|
||||
case object_acceleration_structure_NV: return "NV Acceleration Structure";
|
||||
case object_indirect_commands_layout_NV: return "NV Indirect Commands Layout";
|
||||
case object_optical_flow_session_NV: return "NV Optical Flow Session";
|
||||
case object_external_compute_queue_NV: return "NV External Compute Queue";
|
||||
|
||||
case object_cu_module_NVX: return "NVX CU Module";
|
||||
case object_cu_function_NVX: return "NVX CU Function";
|
||||
|
||||
case object_performance_configuration_INTEL: return "Intel Performance Configuration";
|
||||
|
||||
case object_buffer_collection_FUCHSIA: return "Fuchsia Buffer Collection";
|
||||
|
||||
case object_tensor_ARM: return "ARM Tensor";
|
||||
case object_tensor_view_ARM: return "ARM Tensor View";
|
||||
case object_data_graph_pipeline_session_ARM: return "ARM Data Graph Pipeline Session";
|
||||
|
||||
// Beta Extensions
|
||||
#ifdef VK_ENABLE_BETA_EXTENSIONS
|
||||
case object_cuda_module_NV: return "NV CUDA Module",
|
||||
case object_cuda_function_NV: return "NV CUDA Function",
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Physical Devices ====================================================================================================
|
||||
|
||||
///
|
||||
/// \brief An enum representing the Vulkan physical device types
|
||||
enum device_ : uint32_t {
|
||||
device_other = VK_PHYSICAL_DEVICE_TYPE_OTHER, //!< Other Type
|
||||
device_integrated = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, //!< Integrated GPU
|
||||
device_discrete = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, //!< Discrete / Dedicated GPU
|
||||
device_virtual = VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU, //!< Virtualized / Software GPU
|
||||
device_cpu = VK_PHYSICAL_DEVICE_TYPE_CPU, //!< CPU
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Get a descriptor string for the provided device type.
|
||||
/// \param type The device type.
|
||||
/// \returns A cstring containing a short description.
|
||||
inline cstring device_string(uint32_t type) {
|
||||
switch (type) {
|
||||
default:
|
||||
case device_other: return "Other";
|
||||
case device_integrated: return "iGPU";
|
||||
case device_discrete: return "dGPU";
|
||||
case device_virtual: return "Virtual";
|
||||
case device_cpu: return "CPU";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Instances ===========================================================================================================
|
||||
|
||||
///
|
||||
/// \brief An enum representing the Vulkan instance creation flags
|
||||
enum instance_flag_ : uint32_t {
|
||||
instance_flag_portability = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR, //!< Portability, allow non-conformant devices
|
||||
|
||||
instance_flag_none = 0, //!< No flags
|
||||
instance_flag_all = instance_flag_portability, //!< All flags
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// \brief Get a descriptor string for the provided device type.
|
||||
/// \param flag The instance flag.
|
||||
/// \returns A cstring containing a short description.
|
||||
inline cstring instance_flag_string(uint32_t flag) {
|
||||
switch (flag) {
|
||||
default:
|
||||
case instance_flag_none: return "None";
|
||||
case instance_flag_portability: return "Portability";
|
||||
|
||||
// TODO: Multi-Flags
|
||||
|
||||
//case instance_flag_all: return cstring("All");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Debugging ===========================================================================================================
|
||||
|
||||
///
|
||||
/// \brief An enum representing the Vulkan debug message severity flags
|
||||
enum debug_message_severity_ : uint32_t {
|
||||
debug_message_severity_verbose = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT, //!< Verbose Message
|
||||
debug_message_severity_info = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, //!< Info Message
|
||||
debug_message_severity_warning = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, //!< Warning Message
|
||||
debug_message_severity_error = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, //!< Error Message
|
||||
|
||||
debug_message_severity_none = 0, //!< No flags
|
||||
|
||||
debug_message_severity_all = debug_message_severity_verbose
|
||||
| debug_message_severity_info
|
||||
| debug_message_severity_warning
|
||||
| debug_message_severity_error, //!< All flags
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Get a descriptor string for the provided message severity.
|
||||
/// \param flag The severity flag.
|
||||
/// \returns A cstring containing a short description.
|
||||
inline cstring message_severity_string(uint32_t flag) {
|
||||
switch (flag) {
|
||||
default:
|
||||
case debug_message_severity_none: return "None";
|
||||
case debug_message_severity_verbose: return "Verbose";
|
||||
case debug_message_severity_info: return "Info";
|
||||
case debug_message_severity_warning: return "Warning";
|
||||
case debug_message_severity_error: return "Error";
|
||||
|
||||
// TODO: Multi-Flags
|
||||
|
||||
case debug_message_severity_all: return "All";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// \brief An enum representing the Vulkan debug message type flags
|
||||
enum debug_message_type_ : uint32_t {
|
||||
debug_message_type_general = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, //!< General Message
|
||||
debug_message_type_validation = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT, //!< Validation Message
|
||||
debug_message_type_performance = VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, //!< Performance Message
|
||||
|
||||
debug_message_type_none = 0, //!< No flags
|
||||
|
||||
debug_message_type_all = debug_message_type_general
|
||||
| debug_message_type_validation
|
||||
| debug_message_type_performance, //!< All flags
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Get a descriptor string for the provided message type.
|
||||
/// \param flag The type flag.
|
||||
/// \returns A cstring containing a short description.
|
||||
inline cstring message_type_string(uint32_t flag) {
|
||||
switch (flag) {
|
||||
default:
|
||||
case debug_message_type_none: return "None";
|
||||
case debug_message_type_general: return "General";
|
||||
case debug_message_type_validation: return "Validation";
|
||||
case debug_message_type_performance: return "Performance";
|
||||
|
||||
// TODO: Multi-Flags
|
||||
|
||||
case debug_message_type_all: return "All";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// \brief An enum representing the Vulkan debug report flags
|
||||
enum debug_report_ : uint32_t {
|
||||
debug_report_information = VK_DEBUG_REPORT_INFORMATION_BIT_EXT, //!< Information Report
|
||||
debug_report_warning = VK_DEBUG_REPORT_WARNING_BIT_EXT, //!< Warning Report
|
||||
debug_report_performance = VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, //!< Performance Warning Report
|
||||
debug_report_error = VK_DEBUG_REPORT_ERROR_BIT_EXT, //!< Error Report
|
||||
debug_report_debug = VK_DEBUG_REPORT_DEBUG_BIT_EXT, //!< Debug Report
|
||||
|
||||
debug_report_none = 0, //!< No flags
|
||||
debug_report_all = debug_report_information
|
||||
| debug_report_warning
|
||||
| debug_report_performance
|
||||
| debug_report_error
|
||||
| debug_report_debug, //!< All flags
|
||||
};
|
||||
|
||||
///
|
||||
/// \brief Get a descriptor string for the provided report type.
|
||||
/// \param flag The type flag.
|
||||
/// \returns A cstring containing a short description.
|
||||
inline cstring report_string(uint32_t flag) {
|
||||
switch (flag) {
|
||||
default:
|
||||
case debug_report_none: return "None";
|
||||
case debug_report_information: return "Information";
|
||||
case debug_report_warning: return "Warning";
|
||||
case debug_report_performance: return "Performance";
|
||||
case debug_report_error: return "Error";
|
||||
case debug_report_debug: return "Debug";
|
||||
|
||||
// TODO: Multi-Flags
|
||||
|
||||
case debug_report_all: return "All";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_RENDERERS_VULKAN_LIB_ENUM_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user