Compare commits

..

3 Commits

Author SHA1 Message Date
1c67c13a27 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	PLANNING.md
2025-06-16 01:55:59 -04:00
db7d52c86c - Fixed Documentation for Consistency
- Added more documentation, predominantly in the Math Library
2025-06-16 01:48:31 -04:00
096e82f47a - Created Layout for Textures
- Separated Build and Output directories
2025-06-14 22:17:46 -04:00
34 changed files with 1201 additions and 689 deletions

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
/build/ /build/
/docs/ /docs/
/bin/
/lib/

View File

@ -13,6 +13,14 @@ include_directories(include)
# Metaprogramming is a dependency for generating various type info before compilation of the engine. # Metaprogramming is a dependency for generating various type info before compilation of the engine.
add_subdirectory(metaprogramming) add_subdirectory(metaprogramming)
string(TOLOWER ${CMAKE_BUILD_TYPE} FENNEC_BUILD_NAME)
set(CMAKE_BINARY_DIR ${PROJECT_SOURCE_DIR}/build/${CMAKE_PLATFORM_NO_VERSIONED_SONAME})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib/${FENNEC_BUILD_NAME})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib/${FENNEC_BUILD_NAME})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin/${FENNEC_BUILD_NAME})
add_library(fennec STATIC add_library(fennec STATIC
# CORE ================================================================================================================= # CORE =================================================================================================================
@ -24,7 +32,8 @@ add_library(fennec STATIC
include/fennec/containers/dynarray.h include/fennec/containers/dynarray.h
# LANG ================================================================================================================= # LANG =================================================================================================================h
include/fennec/lang/bits.h
include/fennec/lang/constants.h include/fennec/lang/constants.h
include/fennec/lang/conditional_types.h include/fennec/lang/conditional_types.h
include/fennec/lang/intrinsics.h include/fennec/lang/intrinsics.h
@ -43,10 +52,10 @@ add_library(fennec STATIC
# MEMORY =============================================================================================================== # MEMORY ===============================================================================================================
include/fennec/memory/allocator.h
include/fennec/lang/bits.h
include/fennec/memory/memory.h
include/fennec/memory/new.h source/memory/new.cpp include/fennec/memory/new.h source/memory/new.cpp
include/fennec/memory/allocator.h
include/fennec/memory/memory.h
include/fennec/memory/pointers.h include/fennec/memory/pointers.h
include/fennec/memory/ptr_traits.h include/fennec/memory/ptr_traits.h
@ -78,6 +87,7 @@ add_library(fennec STATIC
include/fennec/math/detail/__types.h include/fennec/math/detail/__types.h
include/fennec/math/detail/__vector_traits.h include/fennec/math/detail/__vector_traits.h
include/fennec/lang/lang.h include/fennec/lang/lang.h
include/fennec/lang/detail/__bits.h
) )
# add metaprogramming templates as a dependency and also force documentation to be generated when fennec is compiled # add metaprogramming templates as a dependency and also force documentation to be generated when fennec is compiled

View File

@ -10,15 +10,18 @@
4. [Math Library](#math-library-math) 4. [Math Library](#math-library-math)
5. [Memory Library](#memory-library-memory) 5. [Memory Library](#memory-library-memory)
6. [Containers Library](#containers-containers) 6. [Containers Library](#containers-containers)
7. [Language Processing](#language-processing-proclang) 7. [Format Processing](#format-processing-fproc)
8. [Core](#core-core) 8. [Core](#core-core)
1. [Tick](#tick) 1. [Tick](#tick)
2. [Frame](#frame) 2. [Frame](#frame)
9. [Scene](#scene-scene) 9. [Application Layer](#application-layer-app)
10. [3D Graphics](#3d-graphics-gfx3d) 10. [Scene](#scene-scene)
11. 11. [2D Graphics](#2d-graphics-gfx2d)
12. [3D Physics](#3d-physics-physics3d) 12. [3D Graphics](#3d-graphics-gfx3d)
13. [Artificial Intelligence](#artificial-intelligence-ai) 1. [Structures](#structures-gfx3d)
2. [Stages](#stages-gfx3d)
13. [3D Physics](#3d-physics-physics3d)
14. [Artificial Intelligence](#artificial-intelligence-ai)
@ -78,12 +81,17 @@ as-needed basis.
Implement headers related to memory allocation in C++. Implement headers related to memory allocation in C++.
* Smart Pointers * Smart Pointers
* Unique Pointer
* Shared Pointer
- Memory Allocation - Memory Allocation
- Allocation
-
## Containers (`containers`) ## Containers Library (`containers`)
All containers of the [C++ Standard Library](https://cppreference.com/w/cpp/container.html) should be implemented. All containers of the [C++ Standard Library](https://cppreference.com/w/cpp/container.html) should be implemented.
@ -97,20 +105,18 @@ Here are essential data-structures not specified in the C++ stdlib:
## Language Processing (`proclang`) ## Format Processing (`fproc`)
Pronounced [ˈɒkh,læŋ](https://itinerarium.github.io/phoneme-synthesis/?w=pɹˈɒkh,læŋ)
No, this won't include Machine Learning, it will mostly include tools for processing human-readable files. No, this won't include Machine Learning, it will mostly include tools for processing human-readable files.
fennec should be able to use Doxygen and LaTeX externally. Consider including binaries with releases. fennec should be able to use Doxygen and LaTeX externally. Consider including binaries with releases.
* String Analysis (`proclang/strings`) * String Analysis (`fproc/strings`)
* Search * Search
* Manipulation * Manipulation
* Delimiting * Delimiting
* Regex * Regex
- File Formats (`proclang/formats`) - File Formats (`fproc/formats`)
- Serialization - Serialization
- JSON - JSON
- HTML - HTML
@ -127,16 +133,22 @@ fennec should be able to use Doxygen and LaTeX externally. Consider including bi
- ODS - ODS
- CSV - CSV
- Graphics Formats - Graphics Formats
- Textures
- BMP - BMP
- DDS
- JPG - JPG
- PNG - PNG
- TIFF - TIFF
- DDS - Vectors
- Wavefront OBJ - OTF
- SVG
- TTF
- Models
- FBX - FBX
- Wavefront OBJ
**MAYBE** **MAYBE**
* Compilation (`proclang/code`) * Compilation (`fproc/code`)
* Lexical Analysis * Lexical Analysis
* Syntax Analysis * Syntax Analysis
* Semantic Analysis * Semantic Analysis
@ -160,6 +172,9 @@ This will be the core of the engine.
The following systems are not essential to the core engine, but are instead major systems that should be defined The following systems are not essential to the core engine, but are instead major systems that should be defined
in their operation order: in their operation order:
**3D Systems will apply *before* their 2D Variants**
### Tick ### Tick
- **Update** - **Update**
- Events - Events
@ -179,8 +194,9 @@ in their operation order:
### Frame ### Frame
- **Graphics** - **Physics**
- Physics Interpolation - Physics Interpolation
- **Graphics**
- [2D Graphics](#2d-graphics-gfx2d) - [2D Graphics](#2d-graphics-gfx2d)
- Generate 3D Mask - Generate 3D Mask
- [3D Graphics](#3d-graphics-gfx3d) - [3D Graphics](#3d-graphics-gfx3d)
@ -213,8 +229,54 @@ implementations than I could write.
## 2D Graphics (`gfx2d`) ## 2D Graphics (`gfx2d`)
Links:
- https://en.wikipedia.org/wiki/Quadtree
- https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-25-rendering-vector-art-gpu
Object Structure. The mesh is implicit data.
### Structures (`gfx2d`)
For the 2d rendering framework, Materials need to be rendered independently because we have
no size constraints for images. This disallows us from using a meta-shader like in
the 3d rendering framework.
```c++
struct Object
{
vec2 location, scale; // A matrix would be 36 bytes, this is instead 20 bytes
float rotation;
}
```
- BVH - BVH
- Quadtree - Quadtree
- Leaf Size and Tree Depth should be calculated by the scene, constraints are as follows:
- Min Object Size
- Max Object Size
- Scene Center
- Scene Edge
- Insertions and Updates are done on the CPU
- Nodes
- Start Index 32-bits
- Object Count 32-bits
- Objects
- Buffer of Object IDs grouped by Octree Node
- Culling
- Starting at each Octree Leaf, traverse upwards.
- Insert Visible Leaf IDs
- Track using atomic buffer
- Generate the Command Buffer for Culled Meshes from the Visible Leaf Buffer
- Count Materials
- Count Meshes per Material
- Generate the Culled Object Buffer by copying objects from the Object Buffer
- Adjust Buffer Size using the counts
- Insert using another atomic buffer
- Translucent objects will be sorted. We can cheat by using a z-index instead of a z-coordinate.
This will allow us to sort objects as they are created. We can still bulk render each z-index,
with meshes and objects being grouped by material.
@ -237,7 +299,10 @@ If you would like to make a fork, have at it, but know that I will hold a deep d
The graphics pipeline will have a buffer with a list of objects and their rendering data. The graphics pipeline will have a buffer with a list of objects and their rendering data.
This will be referred to as the Object Buffer. There will be two, for both the Deferred and Forward Passes. This will be referred to as the Object Buffer. There will be two, for both the Deferred and Forward Passes.
The buffers will be optimized by scene prediction. This involves tracking the meshes directly and indirectly used by a scene. The buffers will be optimized by scene prediction.
This involves tracking the meshes and textures directly and indirectly used by a scene.
A callback function in the graphics system for scene loading can do this.
Materials and Lighting models will be run via a shader metaprogram to make the pipeline independent of this aspect. Materials and Lighting models will be run via a shader metaprogram to make the pipeline independent of this aspect.
This allows the GPU to draw every single deferred rendered mesh in a single draw call for each stage of the renderer. This allows the GPU to draw every single deferred rendered mesh in a single draw call for each stage of the renderer.
@ -245,12 +310,64 @@ This allows the GPU to draw every single deferred rendered mesh in a single draw
Specifications for debugging views via early breaks are included in the stages. Specifications for debugging views via early breaks are included in the stages.
### Structures (`gfx3d`)
Object Structure. The mesh is implicit data.
```c++
struct Object
{
vec3 location, scale; // A matrix would be 64 bytes, this is instead 28 bytes
quat rotation;
int material;
}
```
Textures for 3D rendering are stored in various buffers with sizes of powers of 2.
Ratios of `1:1` and `2:1` are allowed. The `2:1` ratio is specifically for spherical and cylindrical projection.
UVs may be transformed to use a `2:1` as if it were `1:2`.
Cubemaps may only be `1:1`, I would be concerned if you are using any other ratio.
- 8-Bit R Texture `4096, 2048, 1024, 512` (8)
- 8-Bit RG Texture `4096, 2048, 1024, 512` (8)
- 8-Bit RGB Texture `4096, 2048, 1024, 512` (8)
- 8-Bit RGBA Texture `4096, 2048, 1024, 512` (8)
- 8-Bit RGB Cubemap `1024, 512, 256, 128` (4)
* 16-Bit HDR RGB Texture `4096, 2048, 1024, 512` (8)
* 16-Bit HDR RGBA Texture `4096, 2048, 1024, 512` (8)
* 16-Bit HDR RGB Cubemap `1024, 512, 256, 128` (4)
- 16-Bit Shadow Texture `4096, 2048, 1024, 512` (8)
- 16-Bit Shadow Cubemap `2048, 1024, 512, 256` (4)
Documentation should provide guidelines on categories of Art Assets and the resolution of textures to use.
Textures are identified by an 8-bit integer and 16-bit integer.
- `int8` → the texture buffer
- `int16` → the layer in the buffer
Artists should be informed on the texture structure of the engine and its limitations.
However, these principles should be followed in other game engines as these are
guided by what is most efficient for typical GPU hardware.
Materials are, for the most part, user-defined. Documentation should make the user aware of this.
Material buffers will be a sequence of the Material Struct instances.
They will at the very least contain the id of their shader.
### Stages (`gfx3d`) ### Stages (`gfx3d`)
This is the set of stages for the graphics pipeline that runs every frame: This is the set of stages for the graphics pipeline that runs every frame:
Unless otherwise specified, each stage will be run on the GPU.
- BVH - BVH
- Octree - Octree `(8 Bpn, 64 bpn) [6-Layers ≈ 2.1MB]`
- Leaf Size and Tree Depth should be calculated by the scene, constraints are as follows: - Leaf Size and Tree Depth should be calculated by the scene, constraints are as follows:
- Min Object Size - Min Object Size
- Max Object Size - Max Object Size
@ -259,61 +376,61 @@ This is the set of stages for the graphics pipeline that runs every frame:
- Buffer has implicit locations due to the tree having 8 children. - Buffer has implicit locations due to the tree having 8 children.
- Insertions and Updates are done on the CPU - Insertions and Updates are done on the CPU
- Nodes - Nodes
- ID 16-bits - Start Index `int32`
- Start Index 32-bits - Object Count `int32`
- Object Count 16-bits
- Objects - Objects
- Buffer of Object IDs grouped by Octree Node - Buffer of Object IDs grouped by Octree Node
- Culling - Leaf Culling
- Starting at each Octree Leaf, traverse upwards. - Starting at each Octree Leaf, traverse upwards.
- Insert Visible Leaf IDs - Insert Visible Leaf IDs
- Track using atomic buffer - Track using atomic buffer
- At the second level, if a node is an edge, add the sister nodes to the visible buffer. - Generate the Command Buffer for Culled Mesh LODs from the Visible Leaf Buffer
- Output: Buffer of Visible Leaves - Track counts using atomic buffers
- To avoid double counting due to the construction of the Octree output, we have some options
* LOD Selection - Ignore Leaf Instances based on occurrences of the mesh in the surrounding 8 Quadtree Leaves. This would require
* Generate the Command Buffer for Culled Mesh LODs from the Visible Leaf Buffer
* Track counts using atomic buffers
* To avoid double counting due to the structure of the Octree output, we have some options
* Ignore Leaf Instances based on occurrences of the mesh in the surrounding 26 Octree Leaves. This would require
a bias towards a specific corner of the filter. a bias towards a specific corner of the filter.
* Perform a preprocessing step on the CPU to erase duplicate elements and fix the buffer continuity. - Perform a preprocessing step on the CPU to erase duplicate elements and fix the buffer continuity.
* Let the duplicates be rendered. - Let the duplicates be rendered.
* Generate the Culled Object Buffer by copying objects from the Object Buffer - Generate the Culled Object Buffer with the respective object IDs
* Adjust Buffer Size using the counts - Adjust Buffer Size using the counts
* Insert using another atomic buffer - Insert by reusing the count buffer, clipped to only contain used meshes
Debug View: Object ID, Mesh ID, LOD Debug View: Object ID, Mesh ID, LOD
- Visibility - Visibility
- Buffer - RGB32I w/ Depth24 - Buffer `(15 Bpp, 120 bpp) [1920x1080] ≈ 39.4MB`
- G = Object ID - Depth Buffer → `D24`
- B = Mesh ID - Visibility Info → `RGB32I`
- R = Object ID
- G = Mesh ID
- B = Material ID
- Regenerate the Command Buffer for Visible Mesh LODs - Regenerate the Command Buffer for Visible Mesh LODs
- Regenerate the Culled Object Buffer - Regenerate the Culled Object Buffer
Debug View: Visibility Buffer Debug View: Visibility Buffer
* G-Buffer Pass * G-Buffer Pass `(17 Bpp, 136 bpp) [1920x1080] ≈ 35.3MB`
* Depth - Stencil * Depth - Stencil → `D24_S8`
* 24-Bit Depth Buffer * S → used to represent the lighting model.
* 8-Bit Stencil Buffer, used to represent the lighting model. * Diffuse → `RGBA8`
* Diffuse - RGB8 * A → Ambient Occlusion
* Emission - RGB8 * Emission → `RGB8`
* Normal - RGB8 * Normal → `RGB8`
* Specular - RGB8 * Specular → `RGB8`
* R → Roughness * R → Roughness
* G → Specularity (sometimes called metallicism) * G → Specularity (sometimes called the Metallicness)
* B → Index of Refraction (IOR) * B → Index of Refraction (IOR)
Debug View: Depth, Stencil, Diffuse, Emission, Normal, Specularity Debug View: Depth, Stencil, Diffuse, Emission, Normal, Specularity
- Lighting Pass - Deferred Lighting Pass `(10 Bpp, 80 bpp) [1920x1080] ≈ 2 x 16.3MB + 8.3MB ≈ 24.6MB`
- Depth Buffer → `D24`
- Lighting Buffer → `RGB16` (w/ Mipmapping when Bloom or DoF are enabled)
- Stencil Buffer $rarr; `S8`
- Generate Dynamic Shadows - Generate Dynamic Shadows
- Generate Dynamic Reflections (Optional) - Generate Dynamic Reflections (Optional)
- SSAO (Optional) - SSAO (Optional)
- Apply Lighting Model - Apply Lighting Model
- Output → RGB16
Debug View: Shadows, Reflections, SSAO, Deferred Lighting Debug View: Shadows, Reflections, SSAO, Deferred Lighting
@ -323,11 +440,13 @@ Debug View: Shadows, Reflections, SSAO, Deferred Lighting
* Translucent Materials * Translucent Materials
* Dual Depth Peeling * Dual Depth Peeling
Debug View: Deferred and Forward Mask Debug View: Forward Mask
- Post Processing - Post Processing
- Depth of Field (Optional) → Poisson Sampling - Depth of Field (Optional)
- Bloom (Optional) → Mipmap Blurring - When enabled, the Visiblity Buffer, G-Buffer, and Deferred Lighting Pass will be double layered.
- At this point the Lighting Buffers will be Flattened
- Bloom (Optional) → Mipmap Blurring `(6Bpp, 48bpp) [1920x1080] ≈ 16.3MB`
- Tonemapping (Optional) - Tonemapping (Optional)
- HDR Correction - HDR Correction
@ -358,7 +477,7 @@ Systems
* Cloth → Position-Based Dynamics * Cloth → Position-Based Dynamics
* Water * Water
* Oceans → iWave * Oceans → iWave
* Reasoning: iWave provides interactive lightweight fluid dynamics suitable for flat planes of water. Simulat * Reasoning: iWave provides interactive lightweight fluid dynamics suitable for flat planes of water.
<br><br> <br><br>
* 3D Fluid Dynamics &rarr; Smoothed-Particle Hydrodynamics * 3D Fluid Dynamics &rarr; Smoothed-Particle Hydrodynamics

View File

@ -18,6 +18,7 @@
3. [Running the Test Suite](#running-the-test-suite) 3. [Running the Test Suite](#running-the-test-suite)
4. [Usage](#usage) 4. [Usage](#usage)
5. [Contribution](#contribution) 5. [Contribution](#contribution)
6. [Documentation](./fennec_documentation.html)
<br> <br>
<br> <br>

View File

@ -784,7 +784,7 @@ SHOW_USED_FILES = YES
# (if specified). # (if specified).
# The default value is: YES. # The default value is: YES.
SHOW_FILES = NO SHOW_FILES = YES
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
# page. This will remove the Namespaces entry from the Quick Index and from the # page. This will remove the Namespaces entry from the Quick Index and from the
@ -1306,7 +1306,7 @@ CLANG_DATABASE_PATH =
# classes, structs, unions or interfaces. # classes, structs, unions or interfaces.
# The default value is: YES. # The default value is: YES.
ALPHABETICAL_INDEX = NO ALPHABETICAL_INDEX = YES
# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes) # The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes)
# that should be ignored while generating the index headers. The IGNORE_PREFIX # that should be ignored while generating the index headers. The IGNORE_PREFIX

View File

@ -784,7 +784,7 @@ SHOW_USED_FILES = YES
# (if specified). # (if specified).
# The default value is: YES. # The default value is: YES.
SHOW_FILES = NO SHOW_FILES = YES
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
# page. This will remove the Namespaces entry from the Quick Index and from the # page. This will remove the Namespaces entry from the Quick Index and from the
@ -1306,7 +1306,7 @@ CLANG_DATABASE_PATH =
# classes, structs, unions or interfaces. # classes, structs, unions or interfaces.
# The default value is: YES. # The default value is: YES.
ALPHABETICAL_INDEX = NO ALPHABETICAL_INDEX = YES
# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes) # The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes)
# that should be ignored while generating the index headers. The IGNORE_PREFIX # that should be ignored while generating the index headers. The IGNORE_PREFIX

View File

@ -11,7 +11,7 @@
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/> <link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
<!--BEGIN DISABLE_INDEX--> <!--BEGIN DISABLE_INDEX-->
<!--BEGIN FULL_SIDEBAR--> <!--BEGIN FULL_SIDEBAR-->
<script type="text/javascript">var page_layout=1;</script> <script type="text/javascript">var layout=1;</script>
<!--END FULL_SIDEBAR--> <!--END FULL_SIDEBAR-->
<!--END DISABLE_INDEX--> <!--END DISABLE_INDEX-->
<script type="text/javascript" src="$relpath^jquery.js"></script> <script type="text/javascript" src="$relpath^jquery.js"></script>

View File

@ -29,9 +29,8 @@
/// ///
/// ///
/// \page page_fennec_documentation Documentation /// \page documentation Documentation
/// ///
/// \section page_fennec_documentation_pages Pages
/// 1. \ref introduction "Introduction" /// 1. \ref introduction "Introduction"
/// 1. \ref coding-standards "Coding Standards" /// 1. \ref coding-standards "Coding Standards"
/// 2. \ref building-from-source "Building from Source" /// 2. \ref building-from-source "Building from Source"
@ -40,20 +39,20 @@
/// 3. \ref running-the-test-suite "Running the Test Suite" /// 3. \ref running-the-test-suite "Running the Test Suite"
/// 4. \ref usage "Usage" /// 4. \ref usage "Usage"
/// 5. \ref contribution "Contribution" /// 5. \ref contribution "Contribution"
/// 6. \subpage page_fennec_libraries /// 6. \subpage libraries
/// 1. \ref page_fennec_lang "C++ Language Library" /// 1. \ref fennec_lang "C++ Language Library"
/// 2. \ref page_fennec_math "Math Library" /// 2. \ref fennec_math "Math Library"
/// ///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html)) /// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
/// ///
/// ///
/// \page page_fennec_libraries Libraries /// \page libraries Libraries
/// ///
/// | Library | Brief | /// | Library | Brief |
/// | :------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | /// | :------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
/// | \subpage page_fennec_lang | Implementation for functions and classes related to the C++ Language, including base types, common utility functions, and metaprogramming templates | /// | \subpage fennec_lang | Implementation for functions and classes related to the C++ Language, including base types, common utility functions, and metaprogramming templates |
/// | \subpage page_fennec_math | Implementation of math functions according to the [OpenGL 4.6 Shading Language Specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf). Additional extensions are provided for other common math functions. | /// | \subpage fennec_math | Implementation of math functions according to the [OpenGL 4.6 Shading Language Specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf). Additional extensions are provided for other common math functions. |
#ifndef FENNEC_CORE_ENGINE_H #ifndef FENNEC_CORE_ENGINE_H
#define FENNEC_CORE_ENGINE_H #define FENNEC_CORE_ENGINE_H

View File

@ -16,19 +16,31 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
// ===================================================================================================================== // =====================================================================================================================
///
/// \file bits.h
/// \brief bit-wise operations
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_LANG_BITS_H #ifndef FENNEC_LANG_BITS_H
#define FENNEC_LANG_BITS_H #define FENNEC_LANG_BITS_H
#include <fennec/lang/intrinsics.h> #include <fennec/lang/intrinsics.h>
#include <fennec/memory/memory.h> #include <fennec/memory/memory.h>
#include <fennec/lang/detail/__bits.h>
namespace fennec namespace fennec
{ {
/// ///
/// \fn fennec::bit_cast(const FromT&) /// \brief perform a bitcast of FromT to ToT
/// \brief
/// \tparam ToT Type to cast to /// \tparam ToT Type to cast to
/// \tparam FromT Type of the value /// \tparam FromT Type of the value
/// \param from Value to bit cast /// \param from Value to bit cast
@ -41,11 +53,110 @@ constexpr ToT bit_cast(const FromT& from)
else else
{ {
ToT to; ToT to;
memcpy(&to, &from, sizeof(ToT)); fennec::memcpy(&to, &from, sizeof(ToT));
return to; return to;
} }
} }
///
/// \brief perform a bit-wise and over an array of bytes
/// \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 arr
constexpr void* bit_and(void* arr, const void* mask, size_t n)
{
if (arr == mask) return arr;
uint8_t* d = static_cast<uint8_t*>(arr);
const uint8_t* s = static_cast<const uint8_t*>(mask);
while (n > 0)
{
size_t step = detail::__bit_and(d, s, n);
d += step; s += step; n -= step;
}
return arr;
}
///
/// \brief safe version of fennec::bit_and
/// \copydoc fennec::bit_and
/// \param n0 the size of arr in bytes
/// \param n1 the size of mask in bytes
constexpr void* bit_and_s(void* arr, size_t n0, const void* mask, size_t n1)
{ return bit_and(arr, mask, n0 < n1 ? n0 : n1); }
///
/// \brief perform a bit-wise or over an array of bytes
/// \param arr the array of bytes to modify
/// \param mask the mask to or against arr
/// \param n the number of bytes
/// \returns the pointer arr
constexpr void* bit_or(void* arr, const void* mask, size_t n)
{
if (arr == mask) return arr;
uint8_t* d = static_cast<uint8_t*>(arr);
const uint8_t* s = static_cast<const uint8_t*>(mask);
while (n > 0)
{
size_t step = detail::__bit_or(d, s, n);
d += step; s += step; n -= step;
}
return arr;
}
///
/// \brief safe version of fennec::bit_or
/// \copydoc fennec::bit_or
/// \param n0 the size of arr in bytes
/// \param n1 the size of mask in bytes
constexpr void* bit_or_s(void* arr, size_t n0, const void* mask, size_t n1)
{ return bit_or(arr, mask, n0 < n1 ? n0 : n1); }
///
/// \brief perform a bit-wise or over an array of bytes
/// \param arr the array of bytes to modify
/// \param mask the mask to or against arr
/// \param n the number of bytes
/// \returns the pointer arr
constexpr void* bit_xor(void* arr, const void* mask, size_t n)
{
if (arr == mask) return arr;
uint8_t* d = static_cast<uint8_t*>(arr);
const uint8_t* s = static_cast<const uint8_t*>(mask);
while (n > 0)
{
size_t step = detail::__bit_xor(d, s, n);
d += step; s += step; n -= step;
}
return arr;
}
///
/// \brief safe version of fennec::bit_xor
/// \copydoc fennec::bit_xor
/// \param n0 the size of arr in bytes
/// \param n1 the size of mask in bytes
constexpr void* bit_xor_s(void* arr, size_t n0, const void* mask, size_t n1)
{ return bit_xor(arr, mask, n0 < n1 ? n0 : n1); }
} }
#endif // FENNEC_LANG_BITS_H #endif // FENNEC_LANG_BITS_H

View File

@ -88,6 +88,13 @@ struct detect
static constexpr bool is_detected = false; static constexpr bool is_detected = false;
}; };
///
/// \brief Shorthand for ```typename detect<DefaultT, DetectT, ArgsT...>::type```
template<typename DefaultT, template<typename...> typename DetectT, typename...ArgsT>
using detect_t
= typename detect<DefaultT, DetectT, ArgsT...>::type;
// true case // true case
template<typename DefaultT, template<typename...> typename DetectT, typename...ArgsT> template<typename DefaultT, template<typename...> typename DetectT, typename...ArgsT>
requires requires { typename DetectT<ArgsT...>; } requires requires { typename DetectT<ArgsT...>; }
@ -97,13 +104,6 @@ struct detect<DefaultT, DetectT, ArgsT...>
static constexpr bool is_detected = true; static constexpr bool is_detected = true;
}; };
///
/// \brief Shorthand for ```typename detect<DefaultT, DetectT, ArgsT...>::type```
template<typename DefaultT, template<typename...> typename DetectT, typename...ArgsT>
using detect_t
= typename detect<DefaultT, DetectT, ArgsT...>::type;
} }
#endif // FENNEC_LANG_CONDITIONAL_TYPES_H #endif // FENNEC_LANG_CONDITIONAL_TYPES_H

View File

@ -48,7 +48,6 @@ template<typename T, T V> struct integral_constant
/// \brief value of the constant /// \brief value of the constant
inline static constexpr T value = V; inline static constexpr T value = V;
///
/// ///
/// \brief cast operator to allow for braced initialization /// \brief cast operator to allow for braced initialization
/// \returns the value of the constant /// \returns the value of the constant
@ -56,7 +55,6 @@ template<typename T, T V> struct integral_constant
}; };
///
/// ///
/// \brief metaprogramming boolean constant /// \brief metaprogramming boolean constant
/// ///
@ -67,14 +65,12 @@ struct bool_constant
: integral_constant<bool_t, V> {}; : integral_constant<bool_t, V> {};
///
/// ///
/// \brief metaprogramming true constant /// \brief metaprogramming true constant
struct true_type struct true_type
: bool_constant<true> {}; : bool_constant<true> {};
///
/// ///
/// \brief metaprogramming false constant /// \brief metaprogramming false constant
struct false_type struct false_type

View File

@ -0,0 +1,138 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_LANG_DETAIL_BITS_H
#define FENNEC_LANG_DETAIL_BITS_H
#include <fennec/lang/types.h>
namespace fennec
{
namespace detail
{
// helper for bitwise and for 1 byte
constexpr size_t __bit_and_8(void* dst, const void* src)
{ *static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) & *static_cast<const uint8_t*>(src); return 1; }
// helper for bitwise and 2 bytes at once
constexpr size_t __bit_and_16(void* dst, const void* src)
{ *static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) & *static_cast<const uint16_t*>(src); return 2; }
// helper for bitwise and 4 bytes at once
constexpr size_t __bit_and_32(void* dst, const void* src)
{ *static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) & *static_cast<const uint32_t*>(src); return 4; }
// helper for bitwise and 8 bytes at once
constexpr size_t __bit_and_64(void* dst, const void* src)
{ *static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) & *static_cast<const uint64_t*>(src); return 8; }
// helper for selecting size
constexpr size_t __bit_and(void* dst, const void* src, size_t n)
{
switch (n)
{
case 0:
return 0;
case 1:
return __bit_and_8(dst, src);
case 2: case 3:
return __bit_and_16(dst, src);
case 4: case 5: case 6: case 7:
return __bit_and_32(dst, src);
default:
return __bit_and_64(dst, src);
}
}
// helper for bitwise or for 1 byte
constexpr size_t __bit_or_8(void* dst, const void* src)
{ *static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) | *static_cast<const uint8_t*>(src); return 1; }
// helper for bitwise or 2 bytes at once
constexpr size_t __bit_or_16(void* dst, const void* src)
{ *static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) | *static_cast<const uint16_t*>(src); return 2; }
// helper for bitwise or 4 bytes at once
constexpr size_t __bit_or_32(void* dst, const void* src)
{ *static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) | *static_cast<const uint32_t*>(src); return 4; }
// helper for bitwise or 8 bytes at once
constexpr size_t __bit_or_64(void* dst, const void* src)
{ *static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) | *static_cast<const uint64_t*>(src); return 8; }
// helper for selecting size
constexpr size_t __bit_or(void* dst, const void* src, size_t n)
{
switch (n)
{
case 0:
return 0;
case 1:
return __bit_or_8(dst, src);
case 2: case 3:
return __bit_or_16(dst, src);
case 4: case 5: case 6: case 7:
return __bit_or_32(dst, src);
default:
return __bit_or_64(dst, src);
}
}
// helper for bitwise and 1 byte
constexpr size_t __bit_xor_8(void* dst, const void* src)
{ *static_cast<uint8_t*>(dst) = *static_cast<uint8_t*>(dst) ^ *static_cast<const uint8_t*>(src); return 1; }
// helper for bitwise xor 2 bytes at once
constexpr size_t __bit_xor_16(void* dst, const void* src)
{ *static_cast<uint16_t*>(dst) = *static_cast<uint16_t*>(dst) ^ *static_cast<const uint16_t*>(src); return 2; }
// helper for bitwise xor 4 bytes at once
constexpr size_t __bit_xor_32(void* dst, const void* src)
{ *static_cast<uint32_t*>(dst) = *static_cast<uint32_t*>(dst) ^ *static_cast<const uint32_t*>(src); return 4; }
// helper for bitwise xor 8 bytes at once
constexpr size_t __bit_xor_64(void* dst, const void* src)
{ *static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) ^ *static_cast<const uint64_t*>(src); return 8; }
// helper for selecting size
constexpr size_t __bit_xor(void* dst, const void* src, size_t n)
{
switch (n)
{
case 0:
return 0;
case 1:
return __bit_xor_8(dst, src);
case 2: case 3:
return __bit_xor_16(dst, src);
case 4: case 5: case 6: case 7:
return __bit_xor_32(dst, src);
default:
return __bit_xor_64(dst, src);
}
}
}
}
#endif // FENNEC_LANG_DETAIL_BITS_H

View File

@ -30,7 +30,7 @@
#ifndef FENNEC_LANG_FLOAT_H #ifndef FENNEC_LANG_FLOAT_H
#define FENNEC_LANG_FLOAT_H #define FENNEC_LANG_FLOAT_H
#include <fennec/memory/bits.h> #include <fennec/lang/bits.h>
#define FLT_HAS_INFINITY 1 #define FLT_HAS_INFINITY 1
#define FLT_HAS_QUIET_NAN 1 #define FLT_HAS_QUIET_NAN 1

View File

@ -32,10 +32,12 @@
#define FENNEC_LANG_H #define FENNEC_LANG_H
/// ///
/// \page page_fennec_lang C++ Language Library /// \page fennec_lang C++ Language Library
/// ///
/// This library implements the parts of the C++ stdlib that relate to built-in types and metaprogramming. /// This library implements the parts of the C++ stdlib that relate to built-in types and metaprogramming.
/// ///
/// \subpage
///
/// ///
#endif // FENNEC_LANG_H #endif // FENNEC_LANG_H

View File

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

View File

@ -33,12 +33,18 @@
#include <fennec/lang/type_transforms.h> #include <fennec/lang/type_transforms.h>
#include <fennec/lang/detail/__numeric_transforms.h> #include <fennec/lang/detail/__numeric_transforms.h>
// TODO: Document
namespace fennec namespace fennec
{ {
///
/// \brief Get the corresponding signed integral type of TypeT
/// \tparam TypeT the integral type to transform
template<typename TypeT> struct make_signed : detail::__make_signed<remove_cv_t<TypeT>> {}; template<typename TypeT> struct make_signed : detail::__make_signed<remove_cv_t<TypeT>> {};
///
/// \brief Get the corresponding unsigned integral type of TypeT
/// \tparam TypeT the integral type to transform
template<typename TypeT> struct make_unsigned : detail::__make_unsigned<remove_cv_t<TypeT>> {}; template<typename TypeT> struct make_unsigned : detail::__make_unsigned<remove_cv_t<TypeT>> {};
} }

View File

@ -47,7 +47,6 @@ template<typename...TypesT> using first_element_t = typename first_element<Types
///
/// ///
/// \brief Take a Template with a Pack `ClassT<ArgsT...>` and replace the first `ArgT` of `ArgsT...` with `SubT` /// \brief Take a Template with a Pack `ClassT<ArgsT...>` and replace the first `ArgT` of `ArgsT...` with `SubT`
template<typename ClassT, typename SubT> struct replace_first_element { }; template<typename ClassT, typename SubT> struct replace_first_element { };

View File

@ -18,7 +18,7 @@
/// ///
/// \file common.h /// \file common.h
/// \brief \ref page_fennec_math_common /// \brief \ref fennec_math_common
/// ///
/// ///
/// \details /// \details
@ -36,7 +36,7 @@
/// ///
/// ///
/// ///
/// \page page_fennec_math_common Common /// \page fennec_math_common Common
/// ///
/// \brief The Common Functions defined in the [OpenGL 4.6 Shading Language Specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf). /// \brief The Common Functions defined in the [OpenGL 4.6 Shading Language Specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf).
/// ///
@ -49,17 +49,17 @@
/// <th style="vertical-align: top">Description /// <th style="vertical-align: top">Description
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::abs(fennec::genType) "genIType abs(genIType)" <br> /// \ref fennec::abs(fennec::genType) "genIType abs(genIType x)" <br>
/// \ref fennec::abs(fennec::genType) "genFType abs(genFType)" <br> /// \ref fennec::abs(fennec::genType) "genFType abs(genFType x)" <br>
/// \ref fennec::abs(fennec::genType) "genDType abs(genDType)" /// \ref fennec::abs(fennec::genType) "genDType abs(genDType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::abs(fennec::genType) /// \copydetails fennec::abs(fennec::genType)
/// ///
/// ///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br> /// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::sign(fennec::genType) "genIType sign(genIType)" <br> /// \ref fennec::sign(fennec::genType) "genIType sign(genIType x)" <br>
/// \ref fennec::sign(fennec::genType) "genFType sign(genFType)" <br> /// \ref fennec::sign(fennec::genType) "genFType sign(genFType x)" <br>
/// \ref fennec::sign(fennec::genType) "genDType sign(genDType)" /// \ref fennec::sign(fennec::genType) "genDType sign(genDType x)"
/// <td width="50%" style="vertical-align: top" class="odd_c"> /// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydetails fennec::sign(fennec::genType) /// \copydetails fennec::sign(fennec::genType)
/// ///
@ -73,36 +73,36 @@
/// <th style="vertical-align: top">Description /// <th style="vertical-align: top">Description
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::floor(fennec::genType) "genFType floor(genFType)" <br> /// \ref fennec::floor(fennec::genType) "genFType floor(genFType x)" <br>
/// \ref fennec::floor(fennec::genType) "genDType floor(genDType)" /// \ref fennec::floor(fennec::genType) "genDType floor(genDType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::floor(fennec::genType) /// \copydetails fennec::floor(fennec::genType)
/// ///
/// ///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br> /// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::ceil(fennec::genType) "genFType ceil(genFType)" <br> /// \ref fennec::ceil(fennec::genType) "genFType ceil(genFType x)" <br>
/// \ref fennec::ceil(fennec::genType) "genDType ceil(genDType)" /// \ref fennec::ceil(fennec::genType) "genDType ceil(genDType x)"
/// <td width="50%" style="vertical-align: top" class="odd_c"> /// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydetails fennec::ceil(fennec::genType) /// \copydetails fennec::ceil(fennec::genType)
/// ///
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::round(fennec::genType) "genFType round(genFType)" <br> /// \ref fennec::round(fennec::genType) "genFType round(genFType x)" <br>
/// \ref fennec::round(fennec::genType) "genDType round(genDType)" /// \ref fennec::round(fennec::genType) "genDType round(genDType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::round(fennec::genType) /// \copydetails fennec::round(fennec::genType)
/// ///
/// ///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br> /// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::roundEven(fennec::genType) "genFType roundEven(genFType)" <br> /// \ref fennec::roundEven(fennec::genType) "genFType roundEven(genFType x)" <br>
/// \ref fennec::roundEven(fennec::genType) "genDType roundEven(genDType)" /// \ref fennec::roundEven(fennec::genType) "genDType roundEven(genDType x)"
/// <td width="50%" style="vertical-align: top" class="odd_c"> /// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydetails fennec::roundEven(fennec::genType) /// \copydetails fennec::roundEven(fennec::genType)
/// ///
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::trunc(fennec::genType) "genFType trunc(genFType)" <br> /// \ref fennec::trunc(fennec::genType) "genFType trunc(genFType x)" <br>
/// \ref fennec::trunc(fennec::genType) "genDType trunc(genDType)" /// \ref fennec::trunc(fennec::genType) "genDType trunc(genDType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::trunc(fennec::genType) /// \copydetails fennec::trunc(fennec::genType)
/// ///
@ -116,46 +116,46 @@
/// <th style="vertical-align: top">Description /// <th style="vertical-align: top">Description
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::fract(fennec::genType) "genFType fract(genFType)" <br> /// \ref fennec::fract(fennec::genType) "genFType fract(genFType x)" <br>
/// \ref fennec::fract(fennec::genType) "genDType fract(genDType)" /// \ref fennec::fract(fennec::genType) "genDType fract(genDType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::fract(fennec::genType) /// \copydetails fennec::fract(fennec::genType)
/// ///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br> /// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::mod(fennec::genType, fennec::genType) "genFType mod(genFType, float)" <br> /// \ref fennec::mod "genFType mod(genFType x, float y)" <br>
/// \ref fennec::mod(fennec::genType, fennec::genType) "genFType mod(genFType, genFType)" <br> /// \ref fennec::mod "genFType mod(genFType x, genFType y)" <br>
/// \ref fennec::mod(fennec::genType, fennec::genType) "genDType mod(genDType, double)" <br> /// \ref fennec::mod "genDType mod(genDType x, double y)" <br>
/// \ref fennec::mod(fennec::genType, fennec::genType) "genDType mod(genDType, genDType)" /// \ref fennec::mod "genDType mod(genDType x, genDType y)"
/// <td width="50%" style="vertical-align: top" class="odd_c"> /// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydetails fennec::mod(fennec::genType, fennec::genType) /// \copydetails fennec::mod
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::modf(fennec::genType, fennec::genType&) "genFType modf(genFType, out genFType)" <br> /// \ref fennec::modf(fennec::genType, fennec::genType&) "genFType modf(genFType x, out genFType i)" <br>
/// \ref fennec::modf(fennec::genType, fennec::genType&) "genDType modf(genDType, out genDType)" /// \ref fennec::modf(fennec::genType, fennec::genType&) "genDType modf(genDType x, out genDType i)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::modf(fennec::genType, fennec::genType&) /// \copydetails fennec::modf(fennec::genType, fennec::genType&)
/// ///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br> /// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::isnan(fennec::genType) "genBType isnan(genFType)" <br> /// \ref fennec::isnan(fennec::genType) "genBType isnan(genFType x)" <br>
/// \ref fennec::isnan(fennec::genType) "genBType isnan(genDType)" /// \ref fennec::isnan(fennec::genType) "genBType isnan(genDType x)"
/// <td width="50%" style="vertical-align: top" class="odd_c"> /// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydetails fennec::isnan(fennec::genType) /// \copydetails fennec::isnan(fennec::genType)
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::isinf(fennec::genType) "genBType isinf(genFType)" <br> /// \ref fennec::isinf(fennec::genType) "genBType isinf(genFType x)" <br>
/// \ref fennec::isinf(fennec::genType) "genBType isinf(genDType)" /// \ref fennec::isinf(fennec::genType) "genBType isinf(genDType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::isinf(fennec::genType) /// \copydetails fennec::isinf(fennec::genType)
/// ///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br> /// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::frexp(fennec::genType, fennec::genIType&) "genFType frexp(genFType, out genIType)" <br> /// \ref fennec::frexp(fennec::genType, fennec::genIType&) "genFType frexp(genFType x, out genIType exp)" <br>
/// \ref fennec::frexp(fennec::genType, fennec::genIType&) "genDType frexp(genDType, out genIType)" /// \ref fennec::frexp(fennec::genType, fennec::genIType&) "genDType frexp(genDType x, out genIType exp)"
/// <td width="50%" style="vertical-align: top" class="odd_c"> /// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydetails fennec::frexp(fennec::genType, fennec::genIType&) /// \copydetails fennec::frexp(fennec::genType, fennec::genIType&)
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::ldexp(fennec::genType, fennec::genIType) "genFType ldexp(genFType, genIType)" <br> /// \ref fennec::ldexp(fennec::genType, fennec::genIType) "genFType ldexp(genFType x, genIType exp)" <br>
/// \ref fennec::ldexp(fennec::genType, fennec::genIType) "genDType ldexp(genDType, genIType)" /// \ref fennec::ldexp(fennec::genType, fennec::genIType) "genDType ldexp(genDType x, genIType exp)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::ldexp(fennec::genType, fennec::genIType) /// \copydetails fennec::ldexp(fennec::genType, fennec::genIType)
/// ///
@ -169,14 +169,14 @@
/// <th style="vertical-align: top">Description /// <th style="vertical-align: top">Description
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::floatBitsToInt(fennec::genType) "genIType floatBitsToInt(genType)" <br> /// \ref fennec::floatBitsToInt(fennec::genType) "genIType floatBitsToInt(genType value)" <br>
/// \ref fennec::floatBitsToUint(fennec::genType) "genUType floatBitsToUint(genType)" /// \ref fennec::floatBitsToUint(fennec::genType) "genUType floatBitsToUint(genType value)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::floatBitsToUint(fennec::genType) /// \copydetails fennec::floatBitsToUint(fennec::genType)
/// ///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br> /// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::intBitsToFloat(fennec::genIType) "genFType intBitsToFloat(genIType)" <br> /// \ref fennec::intBitsToFloat(fennec::genIType) "genFType intBitsToFloat(genIType value)" <br>
/// \ref fennec::uintBitsToFloat(fennec::genUType) "genFType uintBitsToFloat(genUType)" /// \ref fennec::uintBitsToFloat(fennec::genUType) "genFType uintBitsToFloat(genUType value)"
/// <td width="50%" style="vertical-align: top" class="odd_c"> /// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydetails fennec::uintBitsToFloat(fennec::genType) /// \copydetails fennec::uintBitsToFloat(fennec::genType)
/// ///
@ -190,40 +190,40 @@
/// <th style="vertical-align: top">Description /// <th style="vertical-align: top">Description
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::min(fennec::genType, fennec::genType) "genFType min(genFType, float)" <br> /// \ref fennec::min "genFType min(genFType x, float y)" <br>
/// \ref fennec::min(fennec::genType, fennec::genType) "genFType min(genFType, genFType)" <br> /// \ref fennec::min "genFType min(genFType x, genFType y)" <br>
/// \ref fennec::min(fennec::genType, fennec::genType) "genDType min(genDType, double)" <br> /// \ref fennec::min "genDType min(genDType x, double y)" <br>
/// \ref fennec::min(fennec::genType, fennec::genType) "genDType min(genDType, genDType)" <br> /// \ref fennec::min "genDType min(genDType x, genDType y)" <br>
/// \ref fennec::min(fennec::genType, fennec::genType) "genIType min(genDType, int)" <br> /// \ref fennec::min "genIType min(genDType x, int y)" <br>
/// \ref fennec::min(fennec::genType, fennec::genType) "genIType min(genIType, genIType)" <br> /// \ref fennec::min "genIType min(genIType x, genIType y)" <br>
/// \ref fennec::min(fennec::genType, fennec::genType) "genUType min(genUType, uint)" <br> /// \ref fennec::min "genUType min(genUType x, uint y)" <br>
/// \ref fennec::min(fennec::genType, fennec::genType) "genUType min(genUType, genUType)" /// \ref fennec::min "genUType min(genUType x, genUType y)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::min(fennec::genType, fennec::genType) /// \copydetails fennec::min
/// ///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br> /// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::max(fennec::genType, fennec::genType) "genFType max(genFType, float)" <br> /// \ref fennec::max "genFType max(genFType x, float y)" <br>
/// \ref fennec::max(fennec::genType, fennec::genType) "genFType max(genFType, genFType)" <br> /// \ref fennec::max "genFType max(genFType x, genFType y)" <br>
/// \ref fennec::max(fennec::genType, fennec::genType) "genDType max(genDType, double)" <br> /// \ref fennec::max "genDType max(genDType x, double y)" <br>
/// \ref fennec::max(fennec::genType, fennec::genType) "genDType max(genDType, genDType)" <br> /// \ref fennec::max "genDType max(genDType x, genDType y)" <br>
/// \ref fennec::max(fennec::genType, fennec::genType) "genIType max(genDType, int)" <br> /// \ref fennec::max "genIType max(genDType x, int y)" <br>
/// \ref fennec::max(fennec::genType, fennec::genType) "genIType max(genIType, genIType)" <br> /// \ref fennec::max "genIType max(genIType x, genIType y)" <br>
/// \ref fennec::max(fennec::genType, fennec::genType) "genUType max(genUType, uint)" <br> /// \ref fennec::max "genUType max(genUType x, uint y)" <br>
/// \ref fennec::max(fennec::genType, fennec::genType) "genUType max(genUType, genUType)" /// \ref fennec::max "genUType max(genUType x, genUType y)"
/// <td width="50%" style="vertical-align: top" class="odd_c"> /// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydetails fennec::max(fennec::genType, fennec::genType) /// \copydetails fennec::max
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::clamp(fennec::genType, fennec::genType, fennec::genType) "genFType clamp(genFType, float, float)" <br> /// \ref fennec::clamp "genFType clamp(genFType x, float minVal, float maxVal)" <br>
/// \ref fennec::clamp(fennec::genType, fennec::genType, fennec::genType) "genFType clamp(genFType, genFType, genFType)" <br> /// \ref fennec::clamp "genFType clamp(genFType x, genFType minVal, genFType maxVal)" <br>
/// \ref fennec::clamp(fennec::genType, fennec::genType, fennec::genType) "genDType clamp(genDType, double, double)" <br> /// \ref fennec::clamp "genDType clamp(genDType x, double minVal, double maxVal)" <br>
/// \ref fennec::clamp(fennec::genType, fennec::genType, fennec::genType) "genDType clamp(genDType, genDType, genDType)" <br> /// \ref fennec::clamp "genDType clamp(genDType x, genDType minVal, genDType maxVal)" <br>
/// \ref fennec::clamp(fennec::genType, fennec::genType, fennec::genType) "genIType clamp(genDType, int, int)" <br> /// \ref fennec::clamp "genIType clamp(genDType x, int minVal, int maxVal)" <br>
/// \ref fennec::clamp(fennec::genType, fennec::genType, fennec::genType) "genIType clamp(genIType, genIType, genIType)" <br> /// \ref fennec::clamp "genIType clamp(genIType x, genIType minVal, genIType maxVal)" <br>
/// \ref fennec::clamp(fennec::genType, fennec::genType, fennec::genType) "genUType clamp(genUType(genUType, uint)" <br> /// \ref fennec::clamp "genUType clamp(genUType x, genUType minVal, uint maxVal)" <br>
/// \ref fennec::clamp(fennec::genType, fennec::genType, fennec::genType) "genUType clamp(genUType, genUType, genUType)" /// \ref fennec::clamp "genUType clamp(genUType x, genUType minVal, genUType maxVal)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::clamp(fennec::genType, fennec::genType, fennec::genType) /// \copydetails fennec::clamp
/// ///
/// </table> /// </table>
/// ///
@ -235,37 +235,37 @@
/// <th style="vertical-align: top">Description /// <th style="vertical-align: top">Description
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::step(fennec::genType, fennec::genType) "step(float, genFType)" <br> /// \ref fennec::step "step(float edge, genFType x)" <br>
/// \ref fennec::step(fennec::genType, fennec::genType) "step(genFType, genFType)" <br> /// \ref fennec::step "step(genFType edge, genFType x)" <br>
/// \ref fennec::step(fennec::genType, fennec::genType) "step(double, genDType)" <br> /// \ref fennec::step "step(double edge, genDType x)" <br>
/// \ref fennec::step(fennec::genType, fennec::genType) "step(genFType, genDType)" /// \ref fennec::step "step(genFType edge, genDType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::step(fennec::genType, fennec::genType) /// \copydetails fennec::step
/// ///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br> /// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::smoothstep(fennec::genType, fennec::genType, fennec::genType) "smoothstep(float, float, genFType)" <br> /// \ref fennec::smoothstep "smoothstep(float edge0, float edge1, genFType x)" <br>
/// \ref fennec::smoothstep(fennec::genType, fennec::genType, fennec::genType) "smoothstep(genFType, genFType, genFType)" <br> /// \ref fennec::smoothstep "smoothstep(genFType edge0, genFType edge1, genFType x)" <br>
/// \ref fennec::smoothstep(fennec::genType, fennec::genType, fennec::genType) "smoothstep(double, double, genDType)" <br> /// \ref fennec::smoothstep "smoothstep(double edge0, double edge1, genDType x)" <br>
/// \ref fennec::smoothstep(fennec::genType, fennec::genType, fennec::genType) "smoothstep(genFType, genFType, genDType)" /// \ref fennec::smoothstep "smoothstep(genFType edge0, genFType edge1, genDType x)"
/// <td width="50%" style="vertical-align: top" class="odd_c"> /// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydetails fennec::smoothstep(fennec::genType, fennec::genType, fennec::genType) /// \copydetails fennec::smoothstep
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::mix(fennec::genType, fennec::genType, fennec::genType) "mix(genFType, genFType, float)" <br> /// \ref fennec::mix "mix(genFType x, genFType y, float a)" <br>
/// \ref fennec::mix(fennec::genType, fennec::genType, fennec::genType) "mix(genFType, genFType, genFType)" <br> /// \ref fennec::mix "mix(genFType x, genFType y, genFType a)" <br>
/// \ref fennec::mix(fennec::genType, fennec::genType, fennec::genType) "mix(genDType, genDType, double)" <br> /// \ref fennec::mix "mix(genDType x, genDType y, double a)" <br>
/// \ref fennec::mix(fennec::genType, fennec::genType, fennec::genType) "mix(genDType, genDType, genDType)" /// \ref fennec::mix "mix(genDType x, genDType y, genDType a)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydetails fennec::mix(fennec::genType, fennec::genType, fennec::genType) /// \copydetails fennec::mix
/// ///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br> /// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::mix(fennec::genBType, fennec::genBType, fennec::genBType) "mix(genBType, genBType, genBType)" <br> /// \ref fennec::mix(fennec::genBType, fennec::genBType, fennec::genBType) "mix(genBType x, genBType y, genBType a)" <br>
/// \ref fennec::mix(fennec::genType, fennec::genType, fennec::genBType) "mix(genIType, genIType, genBType)" <br> /// \ref fennec::mix(fennec::genType, fennec::genType, fennec::genBType) "mix(genIType x, genIType y, genBType a)" <br>
/// \ref fennec::mix(fennec::genType, fennec::genType, fennec::genBType) "mix(genUType, genUType, genBType)" <br> /// \ref fennec::mix(fennec::genType, fennec::genType, fennec::genBType) "mix(genUType x, genUType y, genBType a)" <br>
/// \ref fennec::mix(fennec::genType, fennec::genType, fennec::genBType) "mix(genFType, genFType, genBType)" <br> /// \ref fennec::mix(fennec::genType, fennec::genType, fennec::genBType) "mix(genFType x, genFType y, genBType a)" <br>
/// \ref fennec::mix(fennec::genType, fennec::genType, fennec::genBType) "mix(genDType, genDType, genBType)" /// \ref fennec::mix(fennec::genType, fennec::genType, fennec::genBType) "mix(genDType x, genDType y, genBType a)"
/// <td width="50%" style="vertical-align: top" class="odd_c"> /// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydetails fennec::mix(fennec::genType, fennec::genType, fennec::genType) /// \copydetails fennec::mix
/// ///
/// </table> /// </table>
/// ///
@ -276,7 +276,6 @@
#include <cmath> #include <cmath>
#include <fennec/math/vector.h> #include <fennec/math/vector.h>
#include <../lang/bits.h>
namespace fennec namespace fennec
{ {
@ -333,7 +332,7 @@ template<typename genType, size_t...i>
constexpr vector<genType, i...> sign(const vector<genType, i...>& x) constexpr vector<genType, i...> sign(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::sign(x[i]) ...); } { return vector<genType, i...>(fennec::sign(x[i]) ...); }
// @} /// @}

View File

@ -18,7 +18,7 @@
/// ///
/// \file exponential.h /// \file exponential.h
/// \brief \ref page_fennec_math_exponential /// \brief \ref fennec_math_exponential
/// ///
/// ///
/// \details /// \details
@ -37,7 +37,7 @@
/// ///
/// ///
/// ///
/// \page page_fennec_math_exponential Exponential /// \page fennec_math_exponential Exponential
/// ///
/// \brief The Exponential Functions defined in the [OpenGL 4.6 Shading Language Specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf). /// \brief The Exponential Functions defined in the [OpenGL 4.6 Shading Language Specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf).
/// ///
@ -49,37 +49,37 @@
/// <th style="vertical-align: top">Description /// <th style="vertical-align: top">Description
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::pow(fennec::genType, fennec::genType) "genFType pow(genFType, genFType)" /// \ref fennec::pow(fennec::genType, fennec::genType) "genFType pow(genFType x, genFType y)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::pow(fennec::genType, fennec::genType) /// \copydoc fennec::pow(fennec::genType, fennec::genType)
/// ///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br> /// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::exp(fennec::genType)"genFType exp(genFType)" /// \ref fennec::exp(fennec::genType)"genFType exp(genFType x)"
/// <td width="50%" style="vertical-align: top" class="odd_c"> /// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydoc fennec::exp(fennec::genType) /// \copydoc fennec::exp(fennec::genType)
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::exp2(fennec::genType) "genFType exp2(genFType)" /// \ref fennec::exp2(fennec::genType) "genFType exp2(genFType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::exp2(fennec::genType) /// \copydoc fennec::exp2(fennec::genType)
/// ///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br> /// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::log(fennec::genType) "genFType log(genFType)" /// \ref fennec::log(fennec::genType) "genFType log(genFType x)"
/// <td width="50%" style="vertical-align: top" class="odd_c"> /// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydoc fennec::log(fennec::genType) /// \copydoc fennec::log(fennec::genType)
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::log2(fennec::genType) "genFType log2(genFType)" /// \ref fennec::log2(fennec::genType) "genFType log2(genFType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::log2(fennec::genType) /// \copydoc fennec::log2(fennec::genType)
/// ///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br> /// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::sqrt(fennec::genType) "genFType sqrt(genFType)" /// \ref fennec::sqrt(fennec::genType) "genFType sqrt(genFType x)"
/// <td width="50%" style="vertical-align: top" class="odd_c"> /// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydoc fennec::sqrt(fennec::genType) /// \copydoc fennec::sqrt(fennec::genType)
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::inversesqrt(fennec::genType) "genFType inversesqrt(genFType)" /// \ref fennec::inversesqrt(fennec::genType) "genFType inversesqrt(genFType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::inversesqrt(fennec::genType) /// \copydoc fennec::inversesqrt(fennec::genType)
/// ///

View File

@ -18,7 +18,7 @@
/// ///
/// \file geometric.h /// \file geometric.h
/// \brief \ref page_fennec_math_geometric /// \brief \ref fennec_math_geometric
/// ///
/// ///
/// \details /// \details
@ -39,7 +39,7 @@
/// ///
/// ///
/// ///
/// \page page_fennec_math_geometric Geometric /// \page fennec_math_geometric Geometric
/// ///
/// \brief The Geometric Functions defined in the [OpenGL 4.6 Shading Language Specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf). /// \brief The Geometric Functions defined in the [OpenGL 4.6 Shading Language Specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf).
/// ///
@ -51,58 +51,58 @@
/// <th style="vertical-align: top">Description /// <th style="vertical-align: top">Description
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::dot(const genFType&, const genFType&) "float dot(genFType x, genFType y)" <br> /// \ref fennec::dot "float dot(genFType x, genFType y)" <br>
/// \ref fennec::dot(const genDType&, const genDType&) "double dot(genDType x, genDType x)" /// \ref fennec::dot "double dot(genDType x, genDType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::dot(const genFType&, const genFType&) /// \copydoc fennec::dot
/// ///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br> /// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::length2(const genFType&) "float length2(genFType x)" <br> /// \ref fennec::length2 "float length2(genFType x)" <br>
/// \ref fennec::length2(const genDType&) "double length2(genDType x)" /// \ref fennec::length2 "double length2(genDType x)"
/// <td width="50%" style="vertical-align: top" class="odd_c"> /// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydoc fennec::length2(const genFType&) /// \copydoc fennec::length2
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::length(const genFType&) "float length(genFType x)" <br> /// \ref fennec::length "float length(genFType x)" <br>
/// \ref fennec::length(const genDType&) "double length(genDType x)" /// \ref fennec::length "double length(genDType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::length(const genFType&) /// \copydoc fennec::length
/// ///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br> /// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::distance(const genFType&, const genFType&) "float distance(genFType x, genFType y)" <br> /// \ref fennec::distance "float distance(genFType x, genFType y)" <br>
/// \ref fennec::distance(const genDType&, const genDType&) "double distance(genDType x, genDType x)" /// \ref fennec::distance "double distance(genDType x, genDType x)"
/// <td width="50%" style="vertical-align: top" class="odd_c"> /// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydoc fennec::distance(const genFType&, const genFType&) /// \copydoc fennec::distance
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::normalize(const genFType&) "float normalize(genFType x)" <br> /// \ref fennec::normalize "float normalize(genFType x)" <br>
/// \ref fennec::normalize(const genDType&) "double normalize(genDType x)" /// \ref fennec::normalize "double normalize(genDType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::normalize(const genFType&) /// \copydoc fennec::normalize
/// ///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br> /// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::cross(const fennec::vec3&, const fennec::vec3&) "vec3 cross(vec3 x, vec3 y)" <br> /// \ref fennec::cross "vec3 cross(vec3 x, vec3 y)" <br>
/// \ref fennec::cross(const fennec::dvec3&, const fennec::dvec3&) "dvec3 cross(dvec3 x, dvec3 x)" /// \ref fennec::cross "dvec3 cross(dvec3 x, dvec3 x)"
/// <td width="50%" style="vertical-align: top" class="odd_c"> /// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydoc fennec::cross(const fennec::vec3&, const fennec::vec3&) /// \copydoc fennec::cross
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::faceforward(const genFType&, const genFType&, const genFType&) "genFType faceforward(genFType N, genFType I, genFType Nref)" <br> /// \ref fennec::faceforward "genFType faceforward(genFType N, genFType I, genFType Nref)" <br>
/// \ref fennec::faceforward(const genDType&, const genDType&, const genDType&) "genDType faceforward(genDType N, genDType I, genDType Nref)" /// \ref fennec::faceforward "genDType faceforward(genDType N, genDType I, genDType Nref)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::faceforward(const genFType&, const genFType&, const genFType&) /// \copydoc fennec::faceforward
/// ///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br> /// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::reflect(const genFType&, const genFType&) "genFType reflect(genFType I, genFType N)" <br> /// \ref fennec::reflect "genFType reflect(genFType I, genFType N)" <br>
/// \ref fennec::reflect(const genDType&, const genDType&) "genDType reflect(genDType I, genDType N)" /// \ref fennec::reflect "genDType reflect(genDType I, genDType N)"
/// <td width="50%" style="vertical-align: top" class="odd_c"> /// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydoc fennec::reflect(const genFType&, const genFType&) /// \copydoc fennec::reflect
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::refract(const genFType&, const genFType&, float) "genFType refract(genFType N, genFType I, float eta)" <br> /// \ref fennec::refract "genFType refract(genFType N, genFType I, float eta)" <br>
/// \ref fennec::refract(const genDType&, const genDType&, double) "genDType refract(genDType N, genDType I, double eta)" /// \ref fennec::refract "genDType refract(genDType N, genDType I, double eta)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::refract(const genFType&, const genFType&, float) /// \copydoc fennec::refract
/// ///
/// </table> /// </table>
/// ///
@ -115,7 +115,6 @@ namespace fennec
// dot ----------------------------------------------------------------------------------------------------------------- // dot -----------------------------------------------------------------------------------------------------------------
///
/// ///
/// \brief 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$ /// \brief 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$
/// ///
@ -135,7 +134,6 @@ constexpr genType dot(const vector<genType, i...>& x, const vector<genType, i...
// length2 ------------------------------------------------------------------------------------------------------------- // 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 \f$x\f$, i.e., \f$x_0^2 + x_1^2 + \ldots\f$
/// ///
@ -153,7 +151,6 @@ constexpr genType length2(const vector<genType, i...>& x)
// length -------------------------------------------------------------------------------------------------------------- // 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 \f$x\f$, i.e., \f$\sqrt{x_0^2 + x_1^2 + \ldots}\f$
/// ///
@ -170,7 +167,6 @@ constexpr genType length(const vector<genType, i...>& x) { return fennec::sqrt(f
// distance ------------------------------------------------------------------------------------------------------------ // 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 \f$x\f$, i.e., \f$\sqrt{x_0^2 + x_1^2 + \ldots}\f$
/// ///
@ -190,7 +186,6 @@ constexpr genType distance(const vector<genType, i...>& p0, const vector<genType
// cross --------------------------------------------------------------------------------------------------------------- // cross ---------------------------------------------------------------------------------------------------------------
///
/// ///
/// \brief Returns the cross product of \f$x\f$ and \f$y\f$, i.e., /// \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$ /// \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$
@ -212,11 +207,10 @@ constexpr vector<genType, i...> cross(const vector<genType, i...>& x, const vect
// normalize ----------------------------------------------------------------------------------------------------------- // 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 \f$x\f$, but with a length of \f$1\f$, 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||}<br><br> /// \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>
/// \details we can represent this in linear algebra as the following, <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 \f$X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]\f$ <br><br>
/// ///
@ -230,7 +224,6 @@ constexpr vector<genType, i...> normalize(const vector<genType, i...>& x)
// faceforward --------------------------------------------------------------------------------------------------------- // faceforward ---------------------------------------------------------------------------------------------------------
///
/// ///
/// \brief If \f$\text{dot}(Nref, I)<0\f$ return \f$N\f$, otherwise return \f$-N\f$. /// \brief If \f$\text{dot}(Nref, I)<0\f$ return \f$N\f$, otherwise return \f$-N\f$.
/// ///
@ -246,7 +239,6 @@ constexpr vector<genType, i...> faceforward(const vector<genType, i...>& N, cons
// reflect ------------------------------------------------------------------------------------------------------------- // reflect -------------------------------------------------------------------------------------------------------------
///
/// ///
/// \brief For the incident vector \f$I\f$ and surface orientation \f$N\f$, returns the reflection direction. /// \brief For the incident vector \f$I\f$ and surface orientation \f$N\f$, returns the reflection direction.
/// ///
@ -263,8 +255,7 @@ constexpr vector<genType, i...> reflect(const vector<genType, i...>& I, const ve
// refract ------------------------------------------------------------------------------------------------------------- // 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 or the incident vector \f$I\f$ and surface normal \f$N\f$, and the ratio of indices of refraction \f$eta\f$,
/// return the refraction vector. /// 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 \f$I\f$, surface normal \f$N\f$, and ratio \f$eta\f$.<br><br>
@ -279,7 +270,8 @@ template<typename genType, size_t...i>
constexpr vector<genType, i...> refract(const vector<genType, i...>& I, const vector<genType, i...>& N, genType eta) constexpr vector<genType, i...> refract(const vector<genType, i...>& I, const vector<genType, i...>& N, genType eta)
{ genType ndi = fennec::dot(N, I); { genType ndi = fennec::dot(N, I);
genType k = 1.0 - eta * eta * (1.0 - ndi * ndi); genType k = 1.0 - eta * eta * (1.0 - ndi * ndi);
return (k < 0.0) ? 0.0 : eta * I - N * (eta * ndi + fennec::sqrt(k)); } return fennec::max(0.0, eta * I - N * (eta * ndi + fennec::sqrt(k))); }
} }
#endif // FENNEC_MATH_GEOMETRIC_H #endif // FENNEC_MATH_GEOMETRIC_H

View File

@ -21,10 +21,10 @@
/// \brief main math header which includes the main modules /// \brief main math header which includes the main modules
/// ///
/// ///
/// \details This header includes the following modules of \ref page_fennec_math : /// \details This header includes the following modules of \ref fennec_math :
/// - \ref page_fennec_math_scalar /// - \ref fennec_math_scalar
/// - \ref page_fennec_math_vector /// - \ref fennec_math_vector
/// - \ref page_fennec_math_trigonometric /// - \ref fennec_math_trigonometric
/// ///
/// \author Medusa Slockbower /// \author Medusa Slockbower
/// ///
@ -39,27 +39,29 @@
/// ///
/// ///
/// ///
/// \page page_fennec_math Math Library /// \page fennec_math Math Library
/// ///
/// The \ref fennec Math Library is composed of the modules listed in below. /// The \ref fennec Math Library is composed of the modules listed in below.
/// The overarching goal of this math library is to implement the math types and functions of the /// The overarching goal of this math library is to implement the math types and functions of the
/// [OpenGL 4.6 Shading Language Specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf). /// [OpenGL 4.6 Shading Language Specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf).
/// ///
/// \section page_fennec_math_topics Topics /// \section fennec_math_topics Topics
/// - \subpage page_fennec_math_set_theory /// - \subpage fennec_math_set_theory
/// ///
/// \section page_fennec_math_data_types Data Types /// \section fennec_math_data_types Data Types
/// ///
/// - \subpage page_fennec_math_scalar /// - \subpage fennec_math_scalar
/// - \subpage page_fennec_math_vector /// - \subpage fennec_math_vector
/// - \subpage page_fennec_math_matrix /// - \subpage fennec_math_matrix
/// ///
/// \section page_fennec_math_functions Functions /// \section fennec_math_functions Functions
///
/// - \subpage fennec_math_common
/// - \subpage fennec_math_exponential
/// - \subpage fennec_math_geometric
/// - \subpage fennec_math_relational
/// - \subpage fennec_math_trigonometric
/// ///
/// - \subpage page_fennec_math_common
/// - \subpage page_fennec_math_exponential
/// - \subpage page_fennec_math_geometric
/// - \subpage page_fennec_math_trigonometric
/// ///
/// ///
@ -68,13 +70,13 @@
/// ///
/// ///
/// ///
/// \page page_fennec_math_set_theory Set Theory /// \page fennec_math_set_theory Set Theory
/// ///
/// Binary Mathematics, like most branches of Mathematics, is built, foundationally, upon Set Theory. Set Theory is /// Binary Mathematics, like most branches of Mathematics, is built, foundationally, upon Set Theory. Set Theory is
/// the branch of Mathematics that studies Sets. Sets contain a collection of elements which may be numbers, or other /// the branch of Mathematics that studies Sets. Sets contain a collection of elements which may be numbers, or other
/// mathematical values and structures. /// mathematical values and structures.
/// ///
/// Set definitions for all mathematical structures in the \ref page_fennec_math "Fennec Math Library" are present in /// Set definitions for all mathematical structures in the \ref fennec_math "Fennec Math Library" are present in
/// their respective pages. /// their respective pages.
/// ///
/// ///

View File

@ -18,7 +18,7 @@
/// ///
/// \file matrix.h /// \file matrix.h
/// \brief the \ref page_fennec_math_matrix /// \brief the \ref fennec_math_matrix
/// ///
/// ///
/// \details /// \details
@ -31,7 +31,7 @@
/// ///
/// ///
/// ///
/// \page page_fennec_math_matrix Matrices /// \page fennec_math_matrix Matrices
/// ///
/// ///
/// ///
@ -357,7 +357,10 @@ private:
template<size_t i0 = 0, typename HeadT, typename...ArgsT> template<size_t i0 = 0, typename HeadT, typename...ArgsT>
constexpr void __construct(HeadT&& head, ArgsT&&...args) constexpr void __construct(HeadT&& head, ArgsT&&...args)
{ matrix::__insert(head); matrix::__construct<i0 + component_count_v<HeadT>>(std::forward<ArgsT>(args)...); } {
matrix::__insert(head);
matrix::__construct<i0 + component_count_v<HeadT>>(std::forward<ArgsT>(args)...);
}
template<size_t i0 = 0> template<size_t i0 = 0>
constexpr void __insert(scalar_t s) constexpr void __insert(scalar_t s)

View File

@ -18,7 +18,7 @@
/// ///
/// \file relational.h /// \file relational.h
/// \brief \ref page_fennec_math_relational /// \brief \ref fennec_math_relational
/// ///
/// ///
/// \details /// \details
@ -33,67 +33,181 @@
#include <fennec/lang/types.h> #include <fennec/lang/types.h>
///
/// \page fennec_math_relational Relational
///
/// \brief The Relational Functions defined in the [OpenGL 4.6 Shading Language Specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf).
///
/// <table width="100%" class="fieldtable" id="table_fennec_math_curve_functions">
/// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::lessThan "bvec lessThan(vec x, vec y)"<br>
/// \ref fennec::lessThan "bvec lessThan(dvec x, dvec y)"<br>
/// \ref fennec::lessThan "bvec lessThan(ivec x, ivec y)"<br>
/// \ref fennec::lessThan "bvec lessThan(uvec x, uvec y)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::lessThan
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::lessThanEqual "bvec lessThanEqual(vec x, vec y)"<br>
/// \ref fennec::lessThanEqual "bvec lessThanEqual(dvec x, dvec y)"<br>
/// \ref fennec::lessThanEqual "bvec lessThanEqual(ivec x, ivec y)"<br>
/// \ref fennec::lessThanEqual "bvec lessThanEqual(uvec x, uvec y)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::lessThanEqual
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::greaterThan "bvec greaterThan(vec x, vec y)"<br>
/// \ref fennec::greaterThan "bvec greaterThan(dvec x, dvec y)"<br>
/// \ref fennec::greaterThan "bvec greaterThan(ivec x, ivec y)"<br>
/// \ref fennec::greaterThan "bvec greaterThan(uvec x, uvec y)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::greaterThan
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::greaterThanEqual "bvec greaterThanEqual(vec x, vec y)"<br>
/// \ref fennec::greaterThanEqual "bvec greaterThanEqual(dvec x, dvec y)"<br>
/// \ref fennec::greaterThanEqual "bvec greaterThanEqual(ivec x, ivec y)"<br>
/// \ref fennec::greaterThanEqual "bvec greaterThanEqual(uvec x, uvec y)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::greaterThanEqual
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::equal "bvec equal(vec x, vec y)"<br>
/// \ref fennec::equal "bvec equal(dvec x, dvec y)"<br>
/// \ref fennec::equal "bvec equal(ivec x, ivec y)"<br>
/// \ref fennec::equal "bvec equal(uvec x, uvec y)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::equal
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::notEqual "bvec notEqual(vec x, vec y)"<br>
/// \ref fennec::notEqual "bvec notEqual(dvec x, dvec y)"<br>
/// \ref fennec::notEqual "bvec notEqual(ivec x, ivec y)"<br>
/// \ref fennec::notEqual "bvec notEqual(uvec x, uvec y)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::notEqual
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::any "bool any(bvec x)"<br>
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::any
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::all "bool all(bvec x)"<br>
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::all
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::operator! "bool not(bvec x)"<br>
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::operator!
/// </table>
///
///
///
// TODO: Document // TODO: Document
namespace fennec namespace fennec
{ {
template<typename genType, typename genBType = bool_t> ///
constexpr genBType lessThan(genType x, genType y) /// \brief Returns the component-wise compare of x < y.
{ return x < y; } ///
/// \returns the component-wise compare of x < y.
/// \param x lhs of the expression
/// \param y rhs of the expression
template<typename genType, typename genBType = bool_t, size_t...i> template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> lessThan(const vector<genType, i...>& x, const vector<genType, i...>& y) constexpr vector<genBType, i...> lessThan(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genBType, i...>(x[i] < y[i]...); } { return vector<genBType, i...>(x[i] < y[i]...); }
template<typename genType, typename genBType = bool_t>
constexpr genBType lessThanEqual(genType x, genType y)
{ return x <= y; }
///
/// \brief Returns the component-wise compare of x <= y.
///
/// \returns the component-wise compare of x <= y.
/// \param x lhs of the expression
/// \param y rhs of the expression
template<typename genType, typename genBType = bool_t, size_t...i> template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> lessThanEqual(const vector<genType, i...>& x, const vector<genType, i...>& y) constexpr vector<genBType, i...> lessThanEqual(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genBType, i...>(x[i] <= y[i]...); } { return vector<genBType, i...>(x[i] <= y[i]...); }
template<typename genType, typename genBType = bool_t>
constexpr genBType greaterThan(genType x, genType y)
{ return x > y; }
///
/// \brief Returns the component-wise compare of x > y.
///
/// \returns the component-wise compare of x > y.
/// \param x lhs of the expression
/// \param y rhs of the expression
template<typename genType, typename genBType = bool_t, size_t...i> template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> greaterThan(const vector<genType, i...>& x, const vector<genType, i...>& y) constexpr vector<genBType, i...> greaterThan(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genBType, i...>(x[i] > y[i]...); } { return vector<genBType, i...>(x[i] > y[i]...); }
template<typename genType, typename genBType = bool_t>
constexpr genBType greaterThanEqual(genType x, genType y)
{ return x >= y; }
///
/// \brief Returns the component-wise compare of x >= y.
///
/// \returns the component-wise compare of x >= y.
/// \param x lhs of the expression
/// \param y rhs of the expression
template<typename genType, typename genBType = bool_t, size_t...i> template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> greaterThanEqual(const vector<genType, i...>& x, const vector<genType, i...>& y) constexpr vector<genBType, i...> greaterThanEqual(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genBType, i...>(x[i] >= y[i]...); } { return vector<genBType, i...>(x[i] >= y[i]...); }
template<typename genType, typename genBType = bool_t>
constexpr genBType equal(genType x, genType y)
{ return x == y; }
///
/// \brief Returns the component-wise compare of x == y.
///
/// \returns the component-wise compare of x == y.
/// \param x lhs of the expression
/// \param y rhs of the expression
template<typename genType, typename genBType = bool_t, size_t...i> template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> equal(const vector<genType, i...>& x, const vector<genType, i...>& y) constexpr vector<genBType, i...> equal(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genBType, i...>(x[i] == y[i]...); } { return vector<genBType, i...>(x[i] == y[i]...); }
template<typename genType, typename genBType = bool_t>
constexpr genBType notEqual(genType x, genType y)
{ return x != y; }
///
/// \brief Returns the component-wise compare of x != y.
///
/// \returns the component-wise compare of x != y.
/// \param x lhs of the expression
/// \param y rhs of the expression
template<typename genType, typename genBType = bool_t, size_t...i> template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> notEqual(const vector<genType, i...>& x, const vector<genType, i...>& y) constexpr vector<genBType, i...> notEqual(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genBType, i...>(x[i] != y[i]...); } { return vector<genBType, i...>(x[i] != y[i]...); }
///
/// \brief Returns \f$true\f$ if any component of \f$x\f$ is \f$true\f$
///
/// \returns \f$true\f$ if any component of \f$x\f$ is \f$true\f$
/// \param x the boolean vector to test
template<typename genBType = bool_t, size_t...i> template<typename genBType = bool_t, size_t...i>
constexpr genBType any(const vector<genBType, i...>& x) constexpr genBType any(const vector<genBType, i...>& x)
{ return (x[i] || ...); } { return (x[i] || ...); }
///
/// \brief Returns \f$true\f$ if all components of \f$x\f$ are \f$true\f$
///
/// \returns \f$true\f$ if all components of \f$x\f$ are \f$true\f$
/// \param x the boolean vector to test
template<typename genBType = bool_t, size_t...i> template<typename genBType = bool_t, size_t...i>
constexpr genBType all(const vector<genBType, i...>& x) constexpr genBType all(const vector<genBType, i...>& x)
{ return (x[i] && ...); } { return (x[i] && ...); }
///
/// \brief Returns the component-wise logical complement of \f$x\f$.
///
/// \details
/// \returns the component-wise logical complement of \f$x\f$.
/// \param x the boolean vector to inverse
template<typename genBType = bool_t, size_t...i>
constexpr genBType operator!(const vector<genBType, i...>& x)
{ return vector<genBType, i...>((!x[i]) ...); }
} }

View File

@ -18,7 +18,7 @@
/// ///
/// \file scalar.h /// \file scalar.h
/// \brief the \ref page_fennec_math_scalar /// \brief the \ref fennec_math_scalar
/// ///
/// ///
/// \details /// \details
@ -36,7 +36,7 @@
/// ///
/// ///
/// ///
/// \page page_fennec_math_scalar Scalars /// \page fennec_math_scalar Scalars
/// \anchor scalar /// \anchor scalar
/// ///
/// The \ref fennec Library considers any type that passes ```is_arithmetic<T>``` to be a \ref scalar "Scalar." Bools are /// The \ref fennec Library considers any type that passes ```is_arithmetic<T>``` to be a \ref scalar "Scalar." Bools are
@ -44,13 +44,13 @@
/// ///
/// The GLSL Specification, and \ref fennec respectively, defines the following scalar types: /// The GLSL Specification, and \ref fennec respectively, defines the following scalar types:
/// ///
/// | Type | Meaning | /// | Type | Corresponding Type | Meaning |
/// |----------|------------------------------| /// |----------|-----------------------|------------------------------|
/// |\c bool | \copybrief fennec::bool_t | /// |\c bool | \ref fennec::bool_t | \copybrief fennec::bool_t |
/// |\c int | \copybrief fennec::int_t | /// |\c int | \ref fennec::int_t | \copybrief fennec::int_t |
/// |\c uint | \copybrief fennec::uint_t | /// |\c uint | \ref fennec::uint_t | \copybrief fennec::uint_t |
/// |\c float | \copybrief fennec::float_t | /// |\c float | \ref fennec::float_t | \copybrief fennec::float_t |
/// |\c double | \copybrief fennec::double_t | /// |\c double | \ref fennec::double_t | \copybrief fennec::double_t |
/// ///
/// ///
/// ///

View File

@ -18,7 +18,7 @@
/// ///
/// \file swizzle.h /// \file swizzle.h
/// \brief part of the \ref page_fennec_math_vector, /// \brief part of the \ref fennec_math_vector,
/// ///
/// ///
/// \details /// \details

View File

@ -18,7 +18,7 @@
/// ///
/// \file trigonometric.h /// \file trigonometric.h
/// \brief the \ref page_fennec_math_trigonometric /// \brief the \ref fennec_math_trigonometric
/// ///
/// ///
/// \details /// \details
@ -34,7 +34,7 @@
/// ///
/// ///
/// ///
/// \page page_fennec_math_trigonometric Trigonometry /// \page fennec_math_trigonometric Trigonometry
/// ///
/// \brief The fennec Trigonometry Module /// \brief The fennec Trigonometry Module
/// ///
@ -47,96 +47,96 @@
/// <th style="vertical-align: top">Description /// <th style="vertical-align: top">Description
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::degrees(genType) "genFType degrees(genFType)" /// \ref fennec::degrees "genFType degrees(genFType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::degrees(fennec::genType) /// \copydoc fennec::degrees
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::radians(genType) "genFType radians(genFType)" /// \ref fennec::radians "genFType radians(genFType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::radians(fennec::genType) /// \copydoc fennec::radians
/// ///
/// </table> /// </table>
/// ///
/// ///
/// ///
/// \section section_fennec_trigonometric_functions Trigonometry /// \section section_fennec_trigonometric_functions Trigonometric Functions
/// ///
/// <table width="100%" class="fieldtable" id="table_fennec_math_trigonometry_angle_conversions"> /// <table width="100%" class="fieldtable" id="table_fennec_math_trigonometry_angle_conversions">
/// <tr><th style="vertical-align: top">Syntax /// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description /// <th style="vertical-align: top">Description
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::sin(genType) "genFType sin(genFType)" /// \ref fennec::sin "genFType sin(genFType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::sin(fennec::genType) /// \copydoc fennec::sin
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::cos(genType) "genFType cos(genFType)" /// \ref fennec::cos "genFType cos(genFType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::cos(fennec::genType) /// \copydoc fennec::cos
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::tan(genType) "genFType tan(genFType)" /// \ref fennec::tan "genFType tan(genFType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::tan(fennec::genType) /// \copydoc fennec::tan
/// ///
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::asin(genType) "genFType asin(genFType)" /// \ref fennec::asin "genFType asin(genFType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::asin(fennec::genType) /// \copydoc fennec::asin
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::acos(genType) "genFType acos(genFType)" /// \ref fennec::acos "genFType acos(genFType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::acos(fennec::genType) /// \copydoc fennec::acos
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::atan(genType) "genFType atan(genFType)" /// \ref fennec::atan "genFType atan(genFType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::atan(fennec::genType) /// \copydoc fennec::atan
/// ///
/// </table> /// </table>
/// ///
/// ///
/// ///
/// \section section_fennec_hyperbolic_functions Trigonometry /// \section section_fennec_hyperbolic_functions Hyperbolic Functions
/// ///
/// <table width="100%" class="fieldtable" id="table_fennec_math_trigonometry_angle_conversions"> /// <table width="100%" class="fieldtable" id="table_fennec_math_trigonometry_angle_conversions">
/// <tr><th style="vertical-align: top">Syntax /// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description /// <th style="vertical-align: top">Description
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::sinh(genType) "genFType sinh(genFType)" /// \ref fennec::sinh "genFType sinh(genFType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::sinh(fennec::genType) /// \copydoc fennec::sinh
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::cosh(genType) "genFType cosh(genFType)" /// \ref fennec::cosh "genFType cosh(genFType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::cosh(fennec::genType) /// \copydoc fennec::cosh
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::tanh(genType) "genFType tanh(genFType)" /// \ref fennec::tanh "genFType tanh(genFType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::tanh(fennec::genType) /// \copydoc fennec::tanh
/// ///
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::asinh(genFType) "genFType asinh(genFType)" /// \ref fennec::asinh "genFType asinh(genFType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::asinh(fennec::genType) /// \copydoc fennec::asinh
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::acosh(genFType) "genFType acosh(genFType)" /// \ref fennec::acosh "genFType acosh(genFType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::acosh(fennec::genType) /// \copydoc fennec::acosh
/// ///
/// <tr><td width="50%" style="vertical-align: top"> <br> /// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::atanh(genFType) "genFType atanh(genFType)" /// \ref fennec::atanh "genFType atanh(genFType x)"
/// <td width="50%" style="vertical-align: top"> /// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::atanh(fennec::genType) /// \copydoc fennec::atanh
/// ///
/// </table> /// </table>
/// ///
@ -198,7 +198,6 @@ constexpr vector<genType, i...> degrees(const vector<genType, i...>& radians)
/// @{ /// @{
/// ///
/// \fn fennec::sin(fennec::genType)
/// \brief The standard trigonometric sine /// \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 \f$\theta\f$ in the range \f$\left[-1,\,1\right]\f$ <br><br>
@ -216,7 +215,6 @@ constexpr vector<genType, i...> sin(const vector<genType, i...>& x)
/// ///
/// \fn fennec::cos(fennec::genType)
/// \brief The Standard Trigonometric Cosine /// \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 \f$\theta\f$ in the range \f$\left[-1,\,1\right]\f$ <br><br>
@ -234,7 +232,6 @@ constexpr vector<genType, i...> cos(const vector<genType, i...>& x)
/// ///
/// \fn fennec::tan(fennec::genType)
/// \brief The Standard Trigonometric Tangent /// \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 \f$\theta\f$ in the Range \f$\left[-\inf,\,\inf\right]\f$<br><br>
@ -258,7 +255,6 @@ constexpr vector<genType, i...> tan(const vector<genType, i...>& x)
/// @{ /// @{
/// ///
/// \fn fennec::asin(fennec::genType)
/// \brief Arc Sine. Returns an angle \f$\theta\f$ whose sine is /a x. /// \brief Arc Sine. Returns an angle \f$\theta\f$ whose sine is /a x.
/// ///
/// \returns an angle \f$\theta\f$ whose sine is /a x. <br><br> /// \returns an angle \f$\theta\f$ whose sine is /a x. <br><br>
@ -277,7 +273,6 @@ constexpr vector<genType, i...> asin(const vector<genType, i...>& x)
/// ///
/// \fn fennec::acos(fennec::genType)
/// \brief Arc Cosine. Returns an angle \f$\theta\f$ whose cosine is /a x. /// \brief Arc Cosine. Returns an angle \f$\theta\f$ whose cosine is /a x.
/// ///
/// \returns an angle \f$\theta\f$ whose cosine is /a x. /// \returns an angle \f$\theta\f$ whose cosine is /a x.
@ -296,7 +291,6 @@ constexpr vector<genType, i...> acos(const vector<genType, i...>& x)
/// ///
/// \fn fennec::atan(fennec::genType)
/// \brief Arc Tangent. Returns an angle \f$\theta\f$ whose tangent is /a y_over_x. /// \brief Arc Tangent. Returns an angle \f$\theta\f$ whose tangent is /a y_over_x.
/// ///
/// \returns an angle \f$\theta\f$ whose tangent is /a y_over_x. /// \returns an angle \f$\theta\f$ whose tangent is /a y_over_x.
@ -315,7 +309,6 @@ constexpr vector<genType, i...> atan(const vector<genType, i...>& y_over_x)
/// ///
/// \fn fennec::tan(fennec::genType, fennec::genType)
/// \brief Arc Tangent. Returns an angle whose tangent is \f$\frac{y}{x}\f$. /// \brief Arc Tangent. Returns an angle whose tangent is \f$\frac{y}{x}\f$.
/// ///
/// \returns an angle whose tangent is \f$\frac{y}{x}\f$. <br><br> /// \returns an angle whose tangent is \f$\frac{y}{x}\f$. <br><br>
@ -342,7 +335,6 @@ constexpr vector<genType, i...> atan(const vector<genType, i...>& y, const vecto
/// @{ /// @{
/// ///
/// \fn fennec::sinh(fennec::genType)
/// \brief Returns the Hyperbolic Sine Function, \f$\frac{{e}^{x}-{e}^{-x}}{2}\f$ /// \brief Returns the Hyperbolic Sine Function, \f$\frac{{e}^{x}-{e}^{-x}}{2}\f$
/// ///
/// \returns The Hyperbolic Sine of \f$x\f$, \f$\frac{{e}^{x}-{e}^{-x}}{2}\f$ <br><br> /// \returns The Hyperbolic Sine of \f$x\f$, \f$\frac{{e}^{x}-{e}^{-x}}{2}\f$ <br><br>
@ -359,7 +351,6 @@ constexpr vector<genType, i...> sinh(const vector<genType, i...>& x)
/// ///
/// \fn fennec::cosh(fennec::genType)
/// \brief Returns the Hyperbolic Cosine Function, \f$\frac{{e}^{x}+{e}^{-x}}{2}\f$ /// \brief Returns the Hyperbolic Cosine Function, \f$\frac{{e}^{x}+{e}^{-x}}{2}\f$
/// ///
/// \returns The Hyperbolic Cosine of \f$x\f$, \f$\frac{{e}^{x}+{e}^{-x}}{2}\f$ <br><br> /// \returns The Hyperbolic Cosine of \f$x\f$, \f$\frac{{e}^{x}+{e}^{-x}}{2}\f$ <br><br>
@ -375,7 +366,6 @@ constexpr vector<genType, i...> cosh(const vector<genType, i...>& x)
/// ///
/// \fn fennec::tanh(fennec::genType)
/// \brief Returns the Hyperbolic Tangent Function, \f$\frac{\text{sinh}(x)}{\text{cosh}(x)}\f$ /// \brief Returns the Hyperbolic Tangent Function, \f$\frac{\text{sinh}(x)}{\text{cosh}(x)}\f$
/// ///
/// \returns The Hyperbolic Tangent of \f$x\f$, \f$\frac{{e}^{x}+{e}^{-x}}{2}\f$ <br><br> /// \returns The Hyperbolic Tangent of \f$x\f$, \f$\frac{{e}^{x}+{e}^{-x}}{2}\f$ <br><br>
@ -396,7 +386,6 @@ constexpr vector<genType, i...> tanh(const vector<genType, i...>& x)
/// @{ /// @{
/// ///
/// \fn fennec::asinh(fennec::genType)
/// \brief The Inverse Hyperbolic Sine Function /// \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 \f$y\f$ that fulfills \f$x=\text{sinh}(y)\f$ <br><br>
@ -413,7 +402,6 @@ constexpr vector<genType, i...> asinh(const vector<genType, i...>& x)
/// ///
/// \fn fennec::cosh(fennec::genType)
/// \brief The Inverse Hyperbolic Cosine Function /// \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 \f$y\f$ that fulfills \f$x=\text{cosh}(y)\f$ <br><br>
@ -430,7 +418,6 @@ constexpr vector<genType, i...> acosh(const vector<genType, i...>& x)
/// ///
/// \fn fennec::atan(fennec::genType)
/// \brief The Inverse Hyperbolic Tangent Function /// \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 \f$y\f$ that fulfills \f$x=\text{atanh}(y)\f$ <br><br>
@ -444,6 +431,7 @@ constexpr genType atanh(genType x)
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> atanh(const vector<genType, i...>& x) constexpr vector<genType, i...> atanh(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::atanh(x[i]) ...); } { return vector<genType, i...>(fennec::atanh(x[i]) ...); }
/// @} /// @}

View File

@ -18,7 +18,7 @@
/// ///
/// \file vector.h /// \file vector.h
/// \brief the \ref page_fennec_math_vector /// \brief the \ref fennec_math_vector
/// ///
/// ///
/// \details /// \details
@ -34,7 +34,7 @@
/// ///
/// ///
/// ///
/// \page page_fennec_math_vector Vectors /// \page fennec_math_vector Vectors
/// ///
/// \brief The fennec Vector Math Module /// \brief The fennec Vector Math Module
/// ///
@ -43,27 +43,27 @@
/// ///
/// <table> /// <table>
/// <caption id="table_fennec_math_vector_types"></caption> /// <caption id="table_fennec_math_vector_types"></caption>
/// <tr><th>Type <th>Brief /// <tr><th>Type <th>Corresponding Type <th>Brief
/// <tr><td colspan=2 style="text-align: center;">Floats /// <tr><th colspan=3 style="text-align: center;">Floats
/// <tr><td>```vec2``` <td>\copybrief fennec::vec2 /// <tr><td>```vec2``` <td>\ref fennec::vec2 <td>\copybrief fennec::vec2
/// <tr><td>```vec3``` <td>\copybrief fennec::vec3 /// <tr><td>```vec3``` <td>\ref fennec::vec3 <td>\copybrief fennec::vec3
/// <tr><td>```vec4``` <td>\copybrief fennec::vec4 /// <tr><td>```vec4``` <td>\ref fennec::vec4 <td>\copybrief fennec::vec4
/// <tr><td colspan=2 style="text-align: center;">Doubles /// <tr><th colspan=3 style="text-align: center;">Doubles
/// <tr><td>```dvec2```<td>\copybrief fennec::dvec2 /// <tr><td>```dvec2```<td>\ref fennec::dvec2 <td>\copybrief fennec::dvec2
/// <tr><td>```dvec3```<td>\copybrief fennec::dvec3 /// <tr><td>```dvec3```<td>\ref fennec::dvec3 <td>\copybrief fennec::dvec3
/// <tr><td>```dvec4```<td>\copybrief fennec::dvec4 /// <tr><td>```dvec4```<td>\ref fennec::dvec4 <td>\copybrief fennec::dvec4
/// <tr><td colspan=2 style="text-align: center;">Booleans /// <tr><th colspan=3 style="text-align: center;">Booleans
/// <tr><td>```bvec2```<td>\copybrief fennec::bvec2 /// <tr><td>```bvec2``` <td>\ref fennec::bvec2 <td>\copybrief fennec::bvec2
/// <tr><td>```bvec3```<td>\copybrief fennec::bvec3 /// <tr><td>```bvec3``` <td>\ref fennec::bvec3 <td>\copybrief fennec::bvec3
/// <tr><td>```bvec4```<td>\copybrief fennec::bvec4 /// <tr><td>```bvec4``` <td>\ref fennec::bvec4 <td>\copybrief fennec::bvec4
/// <tr><td colspan=2 style="text-align: center;">Integers /// <tr><th colspan=3 style="text-align: center;">Integers
/// <tr><td>```ivec2```<td>\copybrief fennec::ivec2 /// <tr><td>```ivec2``` <td>\ref fennec::ivec2 <td>\copybrief fennec::ivec2
/// <tr><td>```ivec3```<td>\copybrief fennec::ivec3 /// <tr><td>```ivec3``` <td>\ref fennec::ivec3 <td>\copybrief fennec::ivec3
/// <tr><td>```ivec4```<td>\copybrief fennec::ivec4 /// <tr><td>```ivec4``` <td>\ref fennec::ivec4 <td>\copybrief fennec::ivec4
/// <tr><td colspan=2 style="text-align: center;">Unsigned Integers /// <tr><th colspan=3 style="text-align: center;">Unsigned Integers
/// <tr><td>```uvec2```<td>\copybrief fennec::uvec2 /// <tr><td>```uvec2``` <td>\ref fennec::uvec2 <td>\copybrief fennec::uvec2
/// <tr><td>```uvec3```<td>\copybrief fennec::uvec3 /// <tr><td>```uvec3``` <td>\ref fennec::uvec3 <td>\copybrief fennec::uvec3
/// <tr><td>```uvec4```<td>\copybrief fennec::uvec4 /// <tr><td>```uvec4``` <td>\ref fennec::uvec4 <td>\copybrief fennec::uvec4
/// </table> /// </table>
/// ///
/// ///
@ -89,7 +89,7 @@
/// ///
/// \section vector_swizzling Swizzling /// \section vector_swizzling Swizzling
/// ///
/// The fennec \ref page_fennec_math_vector allows for the "swizzling" of vectors. Each component in the vector can be /// 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> /// used in any combination, with up to 4 components, to create another vector. For example, <br><br>
/// ///
/// let \f$V = (0, 1, 2)\f$ /// let \f$V = (0, 1, 2)\f$
@ -113,9 +113,7 @@ namespace fennec
/// ///
/// \typedef vec /// \brief Main \ref fennec_math_vector "vector" template
/// \anchor vec
/// \brief Main \ref fennec::vector "vector" template
/// \tparam ScalarT The type of the Components /// \tparam ScalarT The type of the Components
/// \tparam SizeV The number of Components /// \tparam SizeV The number of Components
template<typename ScalarT, size_t SizeV> using vec = decltype(detail::__gen_vector<vector, ScalarT>(make_index_sequence<SizeV>{})); template<typename ScalarT, size_t SizeV> using vec = decltype(detail::__gen_vector<vector, ScalarT>(make_index_sequence<SizeV>{}));
@ -123,122 +121,92 @@ template<typename ScalarT, size_t SizeV> using vec = decltype(detail::__gen_vect
/// ///
/// \typedef tvec2 /// \brief Shorthand for creating a 2-element \ref fennec::vector, ```vec<ScalarT, 2>```
/// \anchor tvec2 /// \details Shorthand for creating a 2-element \ref fennec::vector, ```vec<ScalarT, 2>```
/// \brief Shorthand for ```vec<ScalarT, 2>```
/// \tparam ScalarT The type of the Components /// \tparam ScalarT The type of the Components
template<typename ScalarT> using tvec2 = vec<ScalarT, 2>; template<typename ScalarT> using tvec2 = vec<ScalarT, 2>;
/// ///
/// \typedef tvec3 /// \brief Shorthand for creating a 3-element \ref fennec::vector, ```vec<ScalarT, 3>```
/// \anchor tvec3 /// \details Shorthand for creating a 3-element \ref fennec::vector, ```vec<ScalarT, 3>```
/// \brief Shorthand for ```vec<ScalarT, 3>```
/// \tparam ScalarT The type of the Components /// \tparam ScalarT The type of the Components
template<typename ScalarT> using tvec3 = vec<ScalarT, 3>; template<typename ScalarT> using tvec3 = vec<ScalarT, 3>;
/// ///
/// \typedef tvec4 /// \brief Shorthand for creating a 4-element \ref fennec::vector, ```vec<ScalarT, 4>```
/// \anchor tvec4 /// \details Shorthand for creating a 4-element \ref fennec::vector, ```vec<ScalarT, 4>```
/// \brief Shorthand for ```vec<ScalarT, 4>```
/// \tparam ScalarT The type of the Components /// \tparam ScalarT The type of the Components
template<typename ScalarT> using tvec4 = vec<ScalarT, 4>; template<typename ScalarT> using tvec4 = vec<ScalarT, 4>;
/// ///
/// \typedef bvec2 /// \brief A two-component boolean \ref fennec_math_vector "vector"
/// \anchor bvec2
/// \brief A two-component boolean \ref fennec::vector "vector"
using bvec2 = tvec2<bool_t>; using bvec2 = tvec2<bool_t>;
/// ///
/// \typedef bvec3 /// \brief A three-component boolean \ref fennec_math_vector "vector"
/// \anchor bvec3
/// \brief A three-component boolean \ref fennec::vector "vector"
using bvec3 = tvec3<bool_t>; using bvec3 = tvec3<bool_t>;
/// ///
/// \typedef bvec4 /// \brief A four-component boolean \ref fennec_math_vector "vector"
/// \anchor bvec4
/// \brief A four-component boolean \ref fennec::vector "vector"
using bvec4 = tvec4<bool_t>; using bvec4 = tvec4<bool_t>;
/// ///
/// \typedef ivec2 /// \brief A two-component signed integer \ref fennec_math_vector "vector"
/// \anchor ivec2
/// \brief A two-component signed integer \ref fennec::vector "vector"
using ivec2 = tvec2<int32_t>; using ivec2 = tvec2<int32_t>;
/// \typedef ivec3 ///
/// \anchor ivec3 /// \brief A three-component signed integer \ref fennec_math_vector "vector"
/// \brief A three-component signed integer \ref fennec::vector "vector"
using ivec3 = tvec3<int32_t>; using ivec3 = tvec3<int32_t>;
/// \typedef ivec4 /// \typedef ivec4
/// \anchor ivec4 /// \anchor ivec4
/// \brief A four-component signed integer \ref fennec::vector "vector" /// \brief A four-component signed integer \ref fennec_math_vector "vector"
using ivec4 = tvec4<int32_t>; using ivec4 = tvec4<int32_t>;
/// ///
/// \typedef uvec2 /// \brief A two-component unsigned integer \ref fennec_math_vector "vector"
/// \anchor uvec2
/// \brief A two-component unsigned integer \ref fennec::vector "vector"
using uvec2 = tvec2<uint32_t>; using uvec2 = tvec2<uint32_t>;
/// ///
/// \typedef uvec3 /// \brief A three-component unsigned integer \ref fennec_math_vector "vector"
/// \anchor uvec3
/// \brief A three-component unsigned integer \ref fennec::vector "vector"
using uvec3 = tvec3<uint32_t>; using uvec3 = tvec3<uint32_t>;
/// ///
/// \typedef uvec4 /// \brief A four-component unsigned integer \ref fennec_math_vector "vector"
/// \anchor uvec4
/// \brief A four-component unsigned integer \ref fennec::vector "vector"
using uvec4 = tvec4<uint32_t>; using uvec4 = tvec4<uint32_t>;
/// ///
/// \typedef vec2 /// \brief A two-component single-precision floating-point \ref fennec_math_vector "vector"
/// \anchor vec2
/// \brief A two-component single-precision floating-point \ref fennec::vector "vector"
using vec2 = tvec2<float32_t>; using vec2 = tvec2<float32_t>;
/// ///
/// \typedef vec3 /// \brief A three-component single-precision floating-point \ref fennec_math_vector "vector"
/// \anchor vec3
/// \brief A three-component single-precision floating-point \ref fennec::vector "vector"
using vec3 = tvec3<float32_t>; using vec3 = tvec3<float32_t>;
/// ///
/// \typedef vec4 /// \brief A four-component single-precision floating-point \ref fennec_math_vector "vector"
/// \anchor vec4
/// \brief A four-component single-precision floating-point \ref fennec::vector "vector"
using vec4 = tvec4<float32_t>; using vec4 = tvec4<float32_t>;
/// ///
/// \typedef dvec2 /// \brief A two-component double-precision floating-point \ref fennec_math_vector "vector"
/// \anchor dvec2
/// \brief A two-component double-precision floating-point \ref fennec::vector "vector"
using dvec2 = tvec2<float64_t>; using dvec2 = tvec2<float64_t>;
/// ///
/// \typedef dvec3 /// \brief A three-component double-precision floating-point \ref fennec_math_vector "vector"
/// \anchor dvec3
/// \brief A three-component double-precision floating-point \ref fennec::vector "vector"
using dvec3 = tvec3<float64_t>; using dvec3 = tvec3<float64_t>;
/// ///
/// \typedef dvec4 /// \brief A four-component double-precision floating-point \ref fennec_math_vector "vector"
/// \anchor dvec4
/// \brief A four-component double-precision floating-point \ref fennec::vector "vector"
using dvec4 = tvec4<float64_t>; using dvec4 = tvec4<float64_t>;
@ -288,7 +256,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
static constexpr size_t size = sizeof...(IndicesV); ///< \brief size of the swizzle static constexpr size_t size = sizeof...(IndicesV); ///< \brief size of the swizzle
static constexpr size_t N = sizeof...(IndicesV); ///< \brief size of the swizzle static constexpr size_t N = sizeof...(IndicesV); ///< \brief size of the swizzle
using decay_t = conditional_t<N == 1, scalar_t, vector_t>; ///< Type that the \ref fennec::vector "vector" should Decay into using decay_t = conditional_t<N == 1, scalar_t, vector_t>; ///< Type that the \ref fennec_math_vector "vector" should Decay into
/// @} /// @}
@ -355,8 +323,8 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \brief vector scalar conversion constructor /// \brief vector scalar conversion constructor
/// ///
/// \details /// \details
/// \tparam OScalarT scalar Type of the \ref fennec::vector "vector" to Convert /// \tparam OScalarT scalar Type of the \ref fennec_math_vector "vector" to Convert
/// \param v \ref fennec::vector "vector" to Convert /// \param v \ref fennec_math_vector "vector" to Convert
template<typename OScalarT> template<typename OScalarT>
explicit constexpr vector(const vector<OScalarT, IndicesV...>& v) explicit constexpr vector(const vector<OScalarT, IndicesV...>& v)
{ ((data[IndicesV] = ScalarT(v[IndicesV])), ...); } { ((data[IndicesV] = ScalarT(v[IndicesV])), ...); }
@ -366,7 +334,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \brief vector conversion constructor /// \brief vector conversion constructor
/// ///
/// \details /// \details
/// \tparam OScalarT scalar Type of the \ref fennec::vector "vector" to Convert /// \tparam OScalarT scalar Type of the \ref fennec_math_vector "vector" to Convert
/// \tparam MoreIndicesStartV /// \tparam MoreIndicesStartV
/// \tparam MoreIndicesV /// \tparam MoreIndicesV
/// \param v /// \param v
@ -410,7 +378,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \brief decay implementation /// \brief decay implementation
/// ///
/// \details /// \details
/// \returns scalar if \f$N==1\f$, otherwise, \ref fennec::vector "vector" /// \returns scalar if \f$N==1\f$, otherwise, \ref fennec_math_vector "vector"
decay_t decay() decay_t decay()
{ return static_cast<const decay_t&>(*this); } { return static_cast<const decay_t&>(*this); }
@ -493,54 +461,54 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
// Scalar-Vector Arithmetic operators ================================================================================== // Scalar-Vector Arithmetic operators ==================================================================================
/// \name \ref page_fennec_math_scalar "scalar" - \ref fennec::vector "vector" Arithmetic operators /// \name \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" Arithmetic operators
/// @{ /// @{
/// ///
/// \brief \ref page_fennec_math_scalar "scalar" - \ref fennec::vector "vector" addition operator /// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" addition operator
/// ///
/// \details /// \details
/// \returns A \ref fennec::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, \f$v_i=lhs_i+rhs_i\f$
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
constexpr friend vector_t operator+(scalar_t lhs, const vector_t& rhs) constexpr friend vector_t operator+(scalar_t lhs, const vector_t& rhs)
{ return vector_t((lhs[IndicesV] + rhs[IndicesV]) ...); } { return vector_t((lhs[IndicesV] + rhs[IndicesV]) ...); }
/// ///
/// \brief \ref page_fennec_math_scalar "scalar" - \ref fennec::vector "vector" subtraction operator /// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" subtraction operator
/// ///
/// \details /// \details
/// \returns A \ref fennec::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, \f$v_i=lhs_i-rhs_i\f$
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
constexpr friend vector_t operator-(scalar_t lhs, const vector_t& rhs) constexpr friend vector_t operator-(scalar_t lhs, const vector_t& rhs)
{ return vector_t((lhs[IndicesV] - rhs[IndicesV]) ...); } { return vector_t((lhs[IndicesV] - rhs[IndicesV]) ...); }
/// ///
/// \brief \ref page_fennec_math_scalar "scalar" - \ref fennec::vector "vector" multiplication operator /// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" multiplication operator
/// ///
/// \details /// \details
/// \returns A \ref fennec::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, \f$v_i={lhs_i}\cdot{rhs_i}\f$
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
constexpr friend vector_t operator*(scalar_t lhs, const vector_t& rhs) constexpr friend vector_t operator*(scalar_t lhs, const vector_t& rhs)
{ return vector_t((lhs * rhs[IndicesV]) ...); } { return vector_t((lhs * rhs[IndicesV]) ...); }
/// ///
/// \brief \ref page_fennec_math_scalar "scalar" - \ref fennec::vector "vector" division operator /// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" division operator
/// ///
/// \details /// \details
/// \returns A \ref fennec::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, \f$v_i=\frac{lhs_i}{rhs_i}\f$
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
constexpr friend vector_t operator/(scalar_t lhs, const vector_t& rhs) constexpr friend vector_t operator/(scalar_t lhs, const vector_t& rhs)
{ return vector_t((lhs / rhs[IndicesV]) ...); } { return vector_t((lhs / rhs[IndicesV]) ...); }
/// ///
/// \brief \ref page_fennec_math_scalar "scalar" - \ref fennec::vector "vector" integer modulus operator /// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" integer modulus operator
/// ///
/// \details /// \details
/// \returns A \ref fennec::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, \f$v_i=lhs_i\%rhs_i\f$
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right 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>) constexpr friend vector_t operator%(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
@ -550,56 +518,56 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
// Vector-Scalar Arithmetic operators ================================================================================== // Vector-Scalar Arithmetic operators ==================================================================================
/// \name \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" Arithmetic operators /// \name \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" Arithmetic operators
/// @{ /// @{
/// ///
/// \brief \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" addition operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" addition operator
/// ///
/// \details /// \details
/// \returns A \ref fennec::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, \f$v_i=lhs_i+rhs_i\f$
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
constexpr friend vector_t operator+(const vector_t& lhs, scalar_t rhs) constexpr friend vector_t operator+(const vector_t& lhs, scalar_t rhs)
{ return vector_t((lhs[IndicesV] + rhs) ...); } { return vector_t((lhs[IndicesV] + rhs) ...); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" subtraction operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" subtraction operator
/// ///
/// \details /// \details
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
/// \returns A \ref fennec::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, \f$v_i=lhs_i-rhs_i\f$
constexpr friend vector_t operator-(const vector_t& lhs, scalar_t rhs) constexpr friend vector_t operator-(const vector_t& lhs, scalar_t rhs)
{ return vector_t((lhs[IndicesV] - rhs) ...); } { return vector_t((lhs[IndicesV] - rhs) ...); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" multiplication operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" multiplication operator
/// ///
/// \details /// \details
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
/// \returns A \ref fennec::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, \f$v_i={lhs_i}\cdot{rhs_i}\f$
constexpr friend vector_t operator*(const vector_t& lhs, scalar_t rhs) constexpr friend vector_t operator*(const vector_t& lhs, scalar_t rhs)
{ return vector_t((lhs[IndicesV] * rhs) ...); } { return vector_t((lhs[IndicesV] * rhs) ...); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" division operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" division operator
/// ///
/// \details /// \details
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
/// \returns A \ref fennec::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, \f$v_i=\frac{lhs_i}{rhs_i}\f$
constexpr friend vector_t operator/(const vector_t& lhs, scalar_t rhs) constexpr friend vector_t operator/(const vector_t& lhs, scalar_t rhs)
{ return vector((lhs[IndicesV] / rhs) ...); } { return vector((lhs[IndicesV] / rhs) ...); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" integer modulus operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" integer modulus operator
/// ///
/// \details /// \details
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
/// \returns A \ref fennec::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, \f$v_i=lhs_i\%rhs_i\f$
constexpr friend vector_t operator%(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator%(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return vector((lhs[IndicesV] % rhs) ...); } { return vector((lhs[IndicesV] % rhs) ...); }
@ -607,56 +575,56 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
// Vector-Scalar Arithmetic Assignment operators ======================================================================= // Vector-Scalar Arithmetic Assignment operators =======================================================================
/// \name \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" Arithmetic Assignment operators /// \name \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" Arithmetic Assignment operators
/// @{ /// @{
/// ///
/// \brief \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" addition operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" addition operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i+rhs_i\f$
constexpr friend vector_t& operator+=(vector_t& lhs, scalar_t rhs) constexpr friend vector_t& operator+=(vector_t& lhs, scalar_t rhs)
{ return ((lhs[IndicesV] += rhs), ..., lhs); } { return ((lhs[IndicesV] += rhs), ..., lhs); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" Subtraction operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" Subtraction operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i-rhs_i\f$
constexpr friend vector_t& operator-=(vector_t& lhs, scalar_t rhs) constexpr friend vector_t& operator-=(vector_t& lhs, scalar_t rhs)
{ return ((lhs[IndicesV] -= rhs), ..., lhs); } { return ((lhs[IndicesV] -= rhs), ..., lhs); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" multiplication operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" multiplication operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i={lhs_i}\cdot{rhs_i}\f$
constexpr friend vector_t& operator*=(vector_t& lhs, scalar_t rhs) constexpr friend vector_t& operator*=(vector_t& lhs, scalar_t rhs)
{ return ((lhs[IndicesV] *= rhs), ..., lhs); } { return ((lhs[IndicesV] *= rhs), ..., lhs); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" division operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" division operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=\frac{lhs_i}{rhs_i}\f$
constexpr friend vector_t& operator/=(vector_t& lhs, scalar_t rhs) constexpr friend vector_t& operator/=(vector_t& lhs, scalar_t rhs)
{ return ((lhs[IndicesV] /= rhs), ..., lhs); } { return ((lhs[IndicesV] /= rhs), ..., lhs); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" integer modulus operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" integer modulus operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i\%rhs_i\f$
constexpr friend vector_t& operator%=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t& operator%=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] %= rhs), ..., lhs); } { return ((lhs[IndicesV] %= rhs), ..., lhs); }
@ -664,55 +632,55 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
// Vector-Vector Arithmetic operators ================================================================================== // Vector-Vector Arithmetic operators ==================================================================================
/// \name \ref fennec::vector "vector" - \ref fennec::vector "vector" Arithmetic operators /// \name \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" Arithmetic operators
/// @{ /// @{
/// ///
/// \brief \ref fennec::vector "vector" - \ref fennec::vector "vector" addition operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" addition operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i+rhs_i\f$
constexpr friend vector_t operator+(const vector_t& lhs, const vector_t& rhs) constexpr friend vector_t operator+(const vector_t& lhs, const vector_t& rhs)
{ return vector((lhs[IndicesV] + rhs[IndicesV]) ...); } { return vector((lhs[IndicesV] + rhs[IndicesV]) ...); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref fennec::vector "vector" subtraction operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" subtraction operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i-rhs_i\f$
constexpr friend vector_t operator-(const vector_t& lhs, const vector_t& rhs) constexpr friend vector_t operator-(const vector_t& lhs, const vector_t& rhs)
{ return vector((lhs[IndicesV] - rhs[IndicesV]) ...); } { return vector((lhs[IndicesV] - rhs[IndicesV]) ...); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref fennec::vector "vector" multiplication operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" multiplication operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i={lhs_i}\cdot{rhs_i}\f$
constexpr friend vector_t operator*(const vector_t& lhs, const vector_t& rhs) constexpr friend vector_t operator*(const vector_t& lhs, const vector_t& rhs)
{ return vector((lhs[IndicesV] * rhs[IndicesV]) ...); } { return vector((lhs[IndicesV] * rhs[IndicesV]) ...); }
/// ///
/// \fn vector::operator/(const vector_t&, const vector_t&) /// \fn vector::operator/(const vector_t&, const vector_t&)
/// \brief \ref fennec::vector "vector" - \ref fennec::vector "vector" division operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" division operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=\frac{lhs_i}{rhs_i}\f$
constexpr friend vector_t operator/(const vector_t& lhs, const vector_t& rhs) constexpr friend vector_t operator/(const vector_t& lhs, const vector_t& rhs)
{ return vector((lhs[IndicesV] / rhs[IndicesV]) ...); } { return vector((lhs[IndicesV] / rhs[IndicesV]) ...); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref fennec::vector "vector" integer modulus operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" integer modulus operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i\%rhs_i\f$
constexpr friend vector_t operator%(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) 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]) ...); } { return vector((lhs[IndicesV] % rhs[IndicesV]) ...); }
@ -720,56 +688,56 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
// Vector-Vector Arithmetic Assignment operators ======================================================================= // Vector-Vector Arithmetic Assignment operators =======================================================================
/// \name \ref fennec::vector "vector" - \ref fennec::vector "vector" Arithmetic Assignment operators /// \name \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" Arithmetic Assignment operators
/// @{ /// @{
/// ///
/// \brief \ref fennec::vector "vector" - \ref fennec::vector "vector" addition operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" addition operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i+rhs_i\f$
constexpr friend vector_t& operator+=(vector_t& lhs, const vector_t& rhs) constexpr friend vector_t& operator+=(vector_t& lhs, const vector_t& rhs)
{ return ((lhs[IndicesV] += rhs[IndicesV]), ..., lhs); } { return ((lhs[IndicesV] += rhs[IndicesV]), ..., lhs); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref fennec::vector "vector" subtraction operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" subtraction operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i-rhs_i\f$
constexpr friend vector_t& operator-=(vector_t& lhs, const vector_t& rhs) constexpr friend vector_t& operator-=(vector_t& lhs, const vector_t& rhs)
{ return ((lhs[IndicesV] -= rhs[IndicesV]), ..., lhs); } { return ((lhs[IndicesV] -= rhs[IndicesV]), ..., lhs); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref fennec::vector "vector" multiplication operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" multiplication operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i={lhs_i}\cdot{rhs_i}\f$
constexpr friend vector_t& operator*=(vector_t& lhs, const vector_t& rhs) constexpr friend vector_t& operator*=(vector_t& lhs, const vector_t& rhs)
{ return ((lhs[IndicesV] *= rhs[IndicesV]), ..., lhs); } { return ((lhs[IndicesV] *= rhs[IndicesV]), ..., lhs); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref fennec::vector "vector" division operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" division operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=\frac{lhs_i}{rhs_i}\f$
constexpr friend vector_t& operator/=(vector_t& lhs, const vector_t& rhs) constexpr friend vector_t& operator/=(vector_t& lhs, const vector_t& rhs)
{ return ((lhs[IndicesV] /= rhs[IndicesV]), ..., lhs); } { return ((lhs[IndicesV] /= rhs[IndicesV]), ..., lhs); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref fennec::vector "vector" integer modulus operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" integer modulus operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i\%rhs_i\f$
constexpr friend vector_t& operator%=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t& operator%=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] %= rhs[IndicesV]), ..., lhs); } { return ((lhs[IndicesV] %= rhs[IndicesV]), ..., lhs); }
@ -781,40 +749,40 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// @{ /// @{
/// ///
/// \brief \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" logical and operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" logical and operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i\&\&rhs_i\f$
constexpr friend vector_t operator&&(const vector_t& lhs, scalar_t rhs) requires(is_bool_v<scalar_t>) constexpr friend vector_t operator&&(const vector_t& lhs, scalar_t rhs) requires(is_bool_v<scalar_t>)
{ return vector_t((lhs[IndicesV] && rhs) ...); } { return vector_t((lhs[IndicesV] && rhs) ...); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref fennec::vector "vector" logical and operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" logical and operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i\&\&rhs_i\f$
constexpr friend vector_t operator&&(const vector_t& lhs, const vector_t& rhs) requires(is_bool_v<scalar_t>) 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]) ...); } { return vector_t((lhs[IndicesV] && rhs[IndicesV]) ...); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" logical or operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" logical or operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i\|\|rhs_i\f$
constexpr friend vector_t operator||(const vector_t& lhs, scalar_t rhs) requires(is_bool_v<scalar_t>) constexpr friend vector_t operator||(const vector_t& lhs, scalar_t rhs) requires(is_bool_v<scalar_t>)
{ return vector_t((lhs[IndicesV] || rhs) ...); } { return vector_t((lhs[IndicesV] || rhs) ...); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref fennec::vector "vector" logical or operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" logical or operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i\|\|rhs_i\f$
constexpr friend vector_t operator||(const vector_t& lhs, const vector_t& rhs) requires(is_bool_v<scalar_t>) 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]) ...); } { return vector_t((lhs[IndicesV] || rhs[IndicesV]) ...); }
@ -826,150 +794,150 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// @{ /// @{
/// ///
/// \brief \ref page_fennec_math_scalar "scalar" - \ref fennec::vector "vector" bitwise and operator /// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" bitwise and operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i\&rhs_i\f$
constexpr friend vector_t operator&(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator&(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs & rhs[IndicesV]) ...); } { return vector_t((lhs & rhs[IndicesV]) ...); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" bitwise and assignment operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise and assignment operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i\&rhs_i\f$
constexpr friend vector_t operator&=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator&=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] &= rhs), ..., lhs); } { return ((lhs[IndicesV] &= rhs), ..., lhs); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" bitwise and operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise and operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i\&rhs_i\f$
constexpr friend vector_t operator&(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator&(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs[IndicesV] & rhs) ...); } { return vector_t((lhs[IndicesV] & rhs) ...); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref fennec::vector "vector" bitwise and assignment operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise and assignment operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i\&rhs_i\f$
constexpr friend vector_t operator&=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator&=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] &= rhs), ..., lhs); } { return ((lhs[IndicesV] &= rhs), ..., lhs); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref fennec::vector "vector" bitwise and operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise and operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i\&rhs_i\f$
constexpr friend vector_t operator&(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) 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]) ...); } { return vector_t((lhs[IndicesV] & rhs[IndicesV]) ...); }
/// ///
/// \brief \ref page_fennec_math_scalar "scalar" - \ref fennec::vector "vector" bitwise or operator /// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" bitwise or operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i|rhs_i\f$
constexpr friend vector_t operator|(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator|(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs & rhs[IndicesV]) ...); } { return vector_t((lhs & rhs[IndicesV]) ...); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" bitwise or assignment operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or assignment operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i|rhs_i\f$
constexpr friend vector_t operator|=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator|=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] |= rhs), ..., lhs); } { return ((lhs[IndicesV] |= rhs), ..., lhs); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" bitwise or operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i|rhs_i\f$
constexpr friend vector_t operator|(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator|(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs[IndicesV] | rhs) ...); } { return vector_t((lhs[IndicesV] | rhs) ...); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref fennec::vector "vector" bitwise or assignment operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i|rhs_i\f$
constexpr friend vector_t operator|=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator|=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] |= rhs), ..., lhs); } { return ((lhs[IndicesV] |= rhs), ..., lhs); }
/// ///
/// \brief \ref fennec::vector "vector" - \ref fennec::vector "vector" bitwise or operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or operator
/// ///
/// \details /// \details
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i|rhs_i\f$
constexpr friend vector_t operator|(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) 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]) ...); } { return vector_t((lhs[IndicesV] | rhs[IndicesV]) ...); }
/// ///
/// \ref page_fennec_math_scalar "scalar" - \ref fennec::vector "vector" bitwise or operator /// \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" bitwise or operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i\^rhs_i\f$
constexpr friend vector_t operator^(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator^(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs ^ rhs[IndicesV]) ...); } { return vector_t((lhs ^ rhs[IndicesV]) ...); }
/// ///
/// \fn vector::operator^=(vector_t&, scalar_t) /// \fn vector::operator^=(vector_t&, scalar_t)
/// \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" bitwise or assignment operator /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or assignment operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i\^rhs_i\f$
constexpr friend vector_t operator^=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator^=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] ^= rhs), ..., lhs); } { return ((lhs[IndicesV] ^= rhs), ..., lhs); }
/// ///
/// \fn vector::operator^(const vector_t&, scalar_t) /// \fn vector::operator^(const vector_t&, scalar_t)
/// \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" bitwise or operator /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i\^rhs_i\f$
constexpr friend vector_t operator^(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator^(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs[IndicesV] ^ rhs) ...); } { return vector_t((lhs[IndicesV] ^ rhs) ...); }
/// ///
/// \fn vector::operator^=(vector_t&, const vector_t&) /// \fn vector::operator^=(vector_t&, const vector_t&)
/// \ref fennec::vector "vector" - \ref fennec::vector "vector" bitwise or assignment operator /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i\^rhs_i\f$
constexpr friend vector_t operator^=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator^=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] ^= rhs), ..., lhs); } { return ((lhs[IndicesV] ^= rhs), ..., lhs); }
/// ///
/// \fn vector::operator^(const vector_t&, const vector_t&) /// \fn vector::operator^(const vector_t&, const vector_t&)
/// \ref fennec::vector "vector" - \ref fennec::vector "vector" bitwise or operator /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i\^rhs_i\f$
constexpr friend vector_t operator^(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) 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]) ...); } { return vector_t((lhs[IndicesV] ^ rhs[IndicesV]) ...); }
@ -977,37 +945,37 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// ///
/// \fn vector::operator<<=(vector_t&, scalar_t) /// \fn vector::operator<<=(vector_t&, scalar_t)
/// \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" bitwise left-shift assignment operator /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift assignment operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i<<=rhs_i\f$
constexpr friend vector_t operator<<=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator<<=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] <<= rhs), ..., lhs); } { return ((lhs[IndicesV] <<= rhs), ..., lhs); }
/// ///
/// \fn vector::operator<<(const vector_t&, scalar_t) /// \fn vector::operator<<(const vector_t&, scalar_t)
/// \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" bitwise or operator /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i<<rhs_i\f$
constexpr friend vector_t operator<<(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator<<(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs[IndicesV] << rhs) ...); } { return vector_t((lhs[IndicesV] << rhs) ...); }
/// ///
/// \fn vector::operator<<=(vector_t&, const vector_t&) /// \fn vector::operator<<=(vector_t&, const vector_t&)
/// \ref fennec::vector "vector" - \ref fennec::vector "vector" bitwise or assignment operator /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i<<=rhs_i\f$
constexpr friend vector_t operator<<=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator<<=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] <<= rhs), ..., lhs); } { return ((lhs[IndicesV] <<= rhs), ..., lhs); }
/// ///
/// \fn vector::operator<<(const vector_t&, const vector_t&) /// \fn vector::operator<<(const vector_t&, const vector_t&)
/// \ref fennec::vector "vector" - \ref fennec::vector "vector" bitwise or operator /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i<<rhs_i\f$
constexpr friend vector_t operator<<(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) 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]) ...); } { return vector_t((lhs[IndicesV] << rhs[IndicesV]) ...); }
@ -1015,37 +983,37 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// ///
/// \fn vector::operator>>=(vector_t&, scalar_t) /// \fn vector::operator>>=(vector_t&, scalar_t)
/// \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" bitwise left-shift assignment operator /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift assignment operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i>>=rhs_i\f$
constexpr friend vector_t operator>>=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator>>=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] >>= rhs), ..., lhs); } { return ((lhs[IndicesV] >>= rhs), ..., lhs); }
/// ///
/// \fn vector::operator>>(const vector_t&, scalar_t) /// \fn vector::operator>>(const vector_t&, scalar_t)
/// \ref fennec::vector "vector" - \ref page_fennec_math_scalar "scalar" bitwise or operator /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i>>rhs_i\f$
constexpr friend vector_t operator>>(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator>>(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs[IndicesV] >> rhs) ...); } { return vector_t((lhs[IndicesV] >> rhs) ...); }
/// ///
/// \fn vector::operator>>=(vector_t&, const vector_t&) /// \fn vector::operator>>=(vector_t&, const vector_t&)
/// \ref fennec::vector "vector" - \ref fennec::vector "vector" bitwise or assignment operator /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i>>=rhs_i\f$
constexpr friend vector_t operator>>=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator>>=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] >>= rhs), ..., lhs); } { return ((lhs[IndicesV] >>= rhs), ..., lhs); }
/// ///
/// \fn vector::operator>>(const vector_t&, const vector_t&) /// \fn vector::operator>>(const vector_t&, const vector_t&)
/// \ref fennec::vector "vector" - \ref fennec::vector "vector" bitwise or operator /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec::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, \f$v_i=lhs_i>>rhs_i\f$
constexpr friend vector_t operator>>(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) 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]) ...); } { return vector_t((lhs[IndicesV] >> rhs[IndicesV]) ...); }

View File

@ -18,7 +18,7 @@
/// ///
/// \file vector_traits.h /// \file vector_traits.h
/// \brief part of the \ref page_fennec_math_vector /// \brief part of the \ref fennec_math_vector
/// ///
/// ///
/// \details this header implements functions to test vector types at compile time /// \details this header implements functions to test vector types at compile time

View File

@ -13,6 +13,9 @@ namespace fennec
namespace detail namespace detail
{ {
constexpr size_t __memcpy_8(void* dst, const void* src)
{ *static_cast<uint8_t*>(dst) = *static_cast<const uint8_t*>(src); return 1; }
// helper for copying 2 bytes at once // helper for copying 2 bytes at once
constexpr size_t __memcpy_16(void* dst, const void* src) constexpr size_t __memcpy_16(void* dst, const void* src)
{ *static_cast<uint16_t*>(dst) = *static_cast<const uint16_t*>(src); return 2; } { *static_cast<uint16_t*>(dst) = *static_cast<const uint16_t*>(src); return 2; }
@ -25,6 +28,23 @@ constexpr size_t __memcpy_32(void* dst, const void* src)
constexpr size_t __memcpy_64(void* dst, const void* src) constexpr size_t __memcpy_64(void* dst, const void* src)
{ *static_cast<uint64_t*>(dst) = *static_cast<const uint64_t*>(src); return 8; } { *static_cast<uint64_t*>(dst) = *static_cast<const uint64_t*>(src); return 8; }
constexpr size_t __memcpy(void* dst, const void* src, size_t n)
{
switch (n)
{
case 0:
return 0;
case 1:
return __memcpy_8(dst, src);
case 2: case 3:
return __memcpy_16(dst, src);
case 4: case 5: case 6: case 7:
return __memcpy_32(dst, src);
default:
return __memcpy_64(dst, src);
}
}
} }
} }

View File

@ -75,6 +75,14 @@ constexpr int memcmp(const void* lhs, const void* rhs, size_t n)
return 0; return 0;
} }
///
/// \brief Safe version of memcmp
/// \copydoc fennec::memcmp
/// \param n0 The size, in bytes, of lhs
/// \param n1 The size, in bytes, of rhs
constexpr int memcmp_s(const void* lhs, size_t n0, const void* rhs, size_t n1)
{ return memcmp(lhs, rhs, n0 < n1 ? n0 : n1); }
/// ///
/// \brief Copies the first \f$n\f$ bytes of \f$src\f$ to \f$dst\f$. /// \brief Copies the first \f$n\f$ bytes of \f$src\f$ to \f$dst\f$.
/// \param dst The destination object, interpreted as an array of bytes /// \param dst The destination object, interpreted as an array of bytes
@ -93,14 +101,23 @@ constexpr void* memcpy(void* dst, const void* src, size_t n)
uint8_t* d = static_cast<uint8_t*>(dst); uint8_t* d = static_cast<uint8_t*>(dst);
const uint8_t* s = static_cast<const uint8_t*>(src); const uint8_t* s = static_cast<const uint8_t*>(src);
while (n >= 8) { detail::__memcpy_64(d, s); d += 8; s += 8; n -= 8; } while (n > 0)
while (n >= 4) { detail::__memcpy_32(d, s); d += 4; s += 4; n -= 4; } {
while (n >= 2) { detail::__memcpy_16(d, s); d += 2; s += 2; n -= 2; } size_t step = detail::__memcpy(d, s, n);
while (n >= 1) { *d++ = *s++; --n; } d += step; s += step; n -= step;
}
return dst; return dst;
} }
///
/// \brief Safe version of memcpy
/// \copydoc fennec::memcpy
/// \param n0 The size, in bytes, of dst
/// \param n1 The size, in bytes, of src
constexpr void* memcpy_s(void* dst, size_t n0, const void* src, size_t n1)
{ return memcpy(dst, src, n0 < n1 ? n0 : n1); }
/// ///
/// \brief Copies the first \f$n\f$ bytes of \f$src\f$ to \f$dst\f$, with overlap correction.. /// \brief Copies the first \f$n\f$ bytes of \f$src\f$ to \f$dst\f$, with overlap correction..
/// \param dst The destination object, interpreted as an array of bytes /// \param dst The destination object, interpreted as an array of bytes
@ -115,22 +132,32 @@ constexpr void* memmove(void* dst, const void* src, size_t n)
if (d < s) if (d < s)
{ {
while (n >= 8) { detail::__memcpy_64(d, s); d += 8; s += 8; n -= 8; } while (n > 0)
while (n >= 4) { detail::__memcpy_32(d, s); d += 4; s += 4; n -= 4; } {
while (n >= 2) { detail::__memcpy_16(d, s); d += 2; s += 2; n -= 2; } size_t step = detail::__memcpy(d, s, n);
while (n >= 1) { *d++ = *s++; --n; } d += step; s += step; n -= step;
}
} }
else else
{ {
d += n - 1; s += n - 1; d += n - 1; s += n - 1;
while (n >= 8) { detail::__memcpy_64(d, s); d -= 8; s -= 8; n -= 8; } while (n > 0)
while (n >= 4) { detail::__memcpy_32(d, s); d -= 4; s -= 4; n -= 4; } {
while (n >= 2) { detail::__memcpy_16(d, s); d -= 2; s -= 2; n -= 2; } size_t step = detail::__memcpy(d, s, n);
while (n >= 1) { *d-- = *s--; --n; } d -= step; s -= step; n -= step;
}
} }
return dst; return dst;
} }
///
/// \brief Safe version of memmove
/// \copydoc fennec::memmove
/// \param n0 The size, in bytes, of dst
/// \param n1 The size, in bytes, of src
constexpr void* memmove_s(void* dst, size_t n0, const void* src, size_t n1)
{ return memmove(dst, src, n0 < n1 ? n0 : n1); }
/// ///
/// \brief Sets all bytes of \f$dst\f$ to \f$ch\f$, interpreted as an \f$uint8_t\f$ /// \brief Sets all bytes of \f$dst\f$ to \f$ch\f$, interpreted as an \f$uint8_t\f$
/// \param dst The destination object, interpreted as an array of bytes /// \param dst The destination object, interpreted as an array of bytes

View File

@ -3,7 +3,8 @@ project(fennec-metaprogramming)
set(CMAKE_CXX_STANDARD 26) set(CMAKE_CXX_STANDARD 26)
add_executable(fennec-metaprogramming main.cpp) add_executable(fennec-metaprogramming main.cpp
float.h)
add_custom_command( add_custom_command(
OUTPUT .metaprogramming OUTPUT .metaprogramming
COMMAND fennec-metaprogramming COMMAND fennec-metaprogramming

123
metaprogramming/float.h Normal file
View File

@ -0,0 +1,123 @@
//
// Created by medusa on 6/14/25.
//
#ifndef FENNEC_METAPROGRAMMING_FLOAT_H
#define FENNEC_METAPROGRAMMING_FLOAT_H
#include <iosfwd>
inline void float_h()
{
std::ofstream flt("float.h");
flt << "// =====================================================================================================================" << std::endl;
flt << "// fennec, a free and open source game engine" << std::endl;
flt << "// Copyright © 2025 Medusa Slockbower" << std::endl;
flt << "//" << std::endl;
flt << "// This program is free software: you can redistribute it and/or modify" << std::endl;
flt << "// it under the terms of the GNU General Public License as published by" << std::endl;
flt << "// the Free Software Foundation, either version 3 of the License, or" << std::endl;
flt << "// (at your option) any later version." << std::endl;
flt << "//" << std::endl;
flt << "// This program is distributed in the hope that it will be useful," << std::endl;
flt << "// but WITHOUT ANY WARRANTY; without even the implied warranty of" << std::endl;
flt << "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" << std::endl;
flt << "// GNU General Public License for more details." << std::endl;
flt << "//" << std::endl;
flt << "// You should have received a copy of the GNU General Public License" << std::endl;
flt << "// along with this program. If not, see <https://www.gnu.org/licenses/>." << std::endl;
flt << "// =====================================================================================================================" << std::endl;
flt << "" << std::endl;
flt << "///" << std::endl;
flt << "/// \\file float.h" << std::endl;
flt << "/// \\brief metaprogramming floating point type info" << std::endl;
flt << "///" << std::endl;
flt << "///" << std::endl;
flt << "/// \\details this file is automatically generated for the current build environment" << std::endl;
flt << "///" << std::endl;
flt << "/// \\copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))" << std::endl;
flt << "///" << std::endl;
flt << "///" << std::endl;
flt << "" << std::endl;
flt << "#ifndef FENNEC_LANG_FLOAT_H" << std::endl;
flt << "#define FENNEC_LANG_FLOAT_H" << std::endl;
flt << "" << std::endl;
flt << "#include <fennec/lang/bits.h>" << std::endl;
flt << "" << std::endl;
// TODO: Fix this to generate info without using the c++stdlib for platforms without this available.
flt << "#define FLT_HAS_INFINITY " << std::dec << std::numeric_limits<float>::has_infinity << std::endl;
flt << "#define FLT_HAS_QUIET_NAN " << std::dec << std::numeric_limits<float>::has_quiet_NaN << std::endl;
flt << "#define FLT_HAS_SIGNALING_NAN " << std::dec << std::numeric_limits<float>::has_signaling_NaN << std::endl;
flt << "#define FLT_HAS_DENORM " << std::dec << std::numeric_limits<float>::has_denorm << std::endl;
flt << "#define FLT_HAS_DENORM_LOSS " << std::dec << std::numeric_limits<float>::has_denorm_loss << std::endl;
flt << "#define FLT_ROUNDS " << std::dec << std::numeric_limits<float>::round_style << std::endl;
flt << "#define FLT_IS_IEC559 " << std::dec << std::numeric_limits<float>::is_iec559 << std::endl;
flt << "#define FLT_MANT_DIG " << std::dec << std::numeric_limits<float>::digits << std::endl;
flt << "#define FLT_DIG " << std::dec << std::numeric_limits<float>::digits10 << std::endl;
flt << "#define FLT_DECIMAL_DIG " << std::dec << std::numeric_limits<float>::max_digits10 << std::endl;
flt << "#define FLT_RADIX " << std::dec << std::numeric_limits<float>::radix << std::endl;
flt << "#define FLT_MIN_EXP " << std::dec << std::numeric_limits<float>::min_exponent << std::endl;
flt << "#define FLT_MAX_EXP " << std::dec << std::numeric_limits<float>::max_exponent << std::endl;
flt << "#define FLT_MIN_10_EXP " << std::dec << std::numeric_limits<float>::min_exponent10 << std::endl;
flt << "#define FLT_MAX_10_EXP " << std::dec << std::numeric_limits<float>::max_exponent10 << std::endl;
flt << "#define FLT_TRAPS " << std::dec << std::numeric_limits<float>::traps << std::endl;
flt << "#define FLT_TINYNESS_BEFORE " << std::dec << std::numeric_limits<float>::tinyness_before << std::endl;
flt << "#define FLT_MIN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::min() ) << ")" << std::endl;
flt << "#define FLT_MAX " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::max() ) << ")" << std::endl;
flt << "#define FLT_EPSILON " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::epsilon() ) << ")" << std::endl;
flt << "#define FLT_INF " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::infinity() ) << ")" << std::endl;
flt << "#define FLT_QUIET_NAN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::quiet_NaN() ) << ")" << std::endl;
flt << "#define FLT_SIGNALING_NAN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::signaling_NaN()) << ")" << std::endl;
flt << "#define FLT_DENORM_MIN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::denorm_min() ) << ")" << std::endl;
flt << "#define FLT_ROUND_ERR " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::round_error() ) << ")" << std::endl;
flt << "" << std::endl;
flt << "#define DBL_HAS_INFINITY " << std::dec << std::numeric_limits<double>::has_infinity << std::endl;
flt << "#define DBL_HAS_QUIET_NAN " << std::dec << std::numeric_limits<double>::has_quiet_NaN << std::endl;
flt << "#define DBL_HAS_SIGNALING_NAN " << std::dec << std::numeric_limits<double>::has_signaling_NaN << std::endl;
flt << "#define DBL_HAS_DENORM " << std::dec << std::numeric_limits<double>::has_denorm << std::endl;
flt << "#define DBL_HAS_DENORM_LOSS " << std::dec << std::numeric_limits<double>::has_denorm_loss << std::endl;
flt << "#define DBL_ROUNDS " << std::dec << std::numeric_limits<double>::round_style << std::endl;
flt << "#define DBL_IS_IEC559 " << std::dec << std::numeric_limits<double>::is_iec559 << std::endl;
flt << "#define DBL_MANT_DIG " << std::dec << std::numeric_limits<double>::digits << std::endl;
flt << "#define DBL_DIG " << std::dec << std::numeric_limits<double>::digits10 << std::endl;
flt << "#define DBL_DECIMAL_DIG " << std::dec << std::numeric_limits<double>::max_digits10 << std::endl;
flt << "#define DBL_RADIX " << std::dec << std::numeric_limits<double>::radix << std::endl;
flt << "#define DBL_MIN_EXP " << std::dec << std::numeric_limits<double>::min_exponent << std::endl;
flt << "#define DBL_MAX_EXP " << std::dec << std::numeric_limits<double>::max_exponent << std::endl;
flt << "#define DBL_MIN_10_EXP " << std::dec << std::numeric_limits<double>::min_exponent10 << std::endl;
flt << "#define DBL_MAX_10_EXP " << std::dec << std::numeric_limits<double>::max_exponent10 << std::endl;
flt << "#define DBL_TRAPS " << std::dec << std::numeric_limits<double>::traps << std::endl;
flt << "#define DBL_TINYNESS_BEFORE " << std::dec << std::numeric_limits<double>::tinyness_before << std::endl;
flt << "#define DBL_MIN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::min() ) << "l)" << std::endl;
flt << "#define DBL_MAX " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::max() ) << "l)" << std::endl;
flt << "#define DBL_EPSILON " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::epsilon() ) << "l)" << std::endl;
flt << "#define DBL_INF " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::infinity() ) << "l)" << std::endl;
flt << "#define DBL_QUIET_NAN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::quiet_NaN() ) << "l)" << std::endl;
flt << "#define DBL_SIGNALING_NAN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::signaling_NaN()) << "l)" << std::endl;
flt << "#define DBL_DENORM_MIN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::denorm_min() ) << "l)" << std::endl;
flt << "#define DBL_ROUND_ERR " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::round_error() ) << "l)" << std::endl;
flt << "" << std::endl;
flt << "#endif // FENNEC_LANG_FLOAT_H" << std::endl;
flt.close();
return 0;
}
#endif //FLOAT_H

View File

@ -21,113 +21,4 @@
int main(int, const char**) int main(int, const char**)
{ {
std::ofstream flt("float.h");
flt << "// =====================================================================================================================" << std::endl;
flt << "// fennec, a free and open source game engine" << std::endl;
flt << "// Copyright © 2025 Medusa Slockbower" << std::endl;
flt << "//" << std::endl;
flt << "// This program is free software: you can redistribute it and/or modify" << std::endl;
flt << "// it under the terms of the GNU General Public License as published by" << std::endl;
flt << "// the Free Software Foundation, either version 3 of the License, or" << std::endl;
flt << "// (at your option) any later version." << std::endl;
flt << "//" << std::endl;
flt << "// This program is distributed in the hope that it will be useful," << std::endl;
flt << "// but WITHOUT ANY WARRANTY; without even the implied warranty of" << std::endl;
flt << "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" << std::endl;
flt << "// GNU General Public License for more details." << std::endl;
flt << "//" << std::endl;
flt << "// You should have received a copy of the GNU General Public License" << std::endl;
flt << "// along with this program. If not, see <https://www.gnu.org/licenses/>." << std::endl;
flt << "// =====================================================================================================================" << std::endl;
flt << "" << std::endl;
flt << "///" << std::endl;
flt << "/// \\file float.h" << std::endl;
flt << "/// \\brief metaprogramming floating point type info" << std::endl;
flt << "///" << std::endl;
flt << "///" << std::endl;
flt << "/// \\details this file is automatically generated for the current build environment" << std::endl;
flt << "///" << std::endl;
flt << "/// \\copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))" << std::endl;
flt << "///" << std::endl;
flt << "///" << std::endl;
flt << "" << std::endl;
flt << "#ifndef FENNEC_LANG_FLOAT_H" << std::endl;
flt << "#define FENNEC_LANG_FLOAT_H" << std::endl;
flt << "" << std::endl;
flt << "#include <fennec/memory/bits.h>" << std::endl;
flt << "" << std::endl;
// TODO: Fix this to generate info without using the c++stdlib for platforms without this available.
flt << "#define FLT_HAS_INFINITY " << std::dec << std::numeric_limits<float>::has_infinity << std::endl;
flt << "#define FLT_HAS_QUIET_NAN " << std::dec << std::numeric_limits<float>::has_quiet_NaN << std::endl;
flt << "#define FLT_HAS_SIGNALING_NAN " << std::dec << std::numeric_limits<float>::has_signaling_NaN << std::endl;
flt << "#define FLT_HAS_DENORM " << std::dec << std::numeric_limits<float>::has_denorm << std::endl;
flt << "#define FLT_HAS_DENORM_LOSS " << std::dec << std::numeric_limits<float>::has_denorm_loss << std::endl;
flt << "#define FLT_ROUNDS " << std::dec << std::numeric_limits<float>::round_style << std::endl;
flt << "#define FLT_IS_IEC559 " << std::dec << std::numeric_limits<float>::is_iec559 << std::endl;
flt << "#define FLT_MANT_DIG " << std::dec << std::numeric_limits<float>::digits << std::endl;
flt << "#define FLT_DIG " << std::dec << std::numeric_limits<float>::digits10 << std::endl;
flt << "#define FLT_DECIMAL_DIG " << std::dec << std::numeric_limits<float>::max_digits10 << std::endl;
flt << "#define FLT_RADIX " << std::dec << std::numeric_limits<float>::radix << std::endl;
flt << "#define FLT_MIN_EXP " << std::dec << std::numeric_limits<float>::min_exponent << std::endl;
flt << "#define FLT_MAX_EXP " << std::dec << std::numeric_limits<float>::max_exponent << std::endl;
flt << "#define FLT_MIN_10_EXP " << std::dec << std::numeric_limits<float>::min_exponent10 << std::endl;
flt << "#define FLT_MAX_10_EXP " << std::dec << std::numeric_limits<float>::max_exponent10 << std::endl;
flt << "#define FLT_TRAPS " << std::dec << std::numeric_limits<float>::traps << std::endl;
flt << "#define FLT_TINYNESS_BEFORE " << std::dec << std::numeric_limits<float>::tinyness_before << std::endl;
flt << "#define FLT_MIN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::min() ) << ")" << std::endl;
flt << "#define FLT_MAX " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::max() ) << ")" << std::endl;
flt << "#define FLT_EPSILON " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::epsilon() ) << ")" << std::endl;
flt << "#define FLT_INF " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::infinity() ) << ")" << std::endl;
flt << "#define FLT_QUIET_NAN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::quiet_NaN() ) << ")" << std::endl;
flt << "#define FLT_SIGNALING_NAN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::signaling_NaN()) << ")" << std::endl;
flt << "#define FLT_DENORM_MIN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::denorm_min() ) << ")" << std::endl;
flt << "#define FLT_ROUND_ERR " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::round_error() ) << ")" << std::endl;
flt << "" << std::endl;
flt << "#define DBL_HAS_INFINITY " << std::dec << std::numeric_limits<double>::has_infinity << std::endl;
flt << "#define DBL_HAS_QUIET_NAN " << std::dec << std::numeric_limits<double>::has_quiet_NaN << std::endl;
flt << "#define DBL_HAS_SIGNALING_NAN " << std::dec << std::numeric_limits<double>::has_signaling_NaN << std::endl;
flt << "#define DBL_HAS_DENORM " << std::dec << std::numeric_limits<double>::has_denorm << std::endl;
flt << "#define DBL_HAS_DENORM_LOSS " << std::dec << std::numeric_limits<double>::has_denorm_loss << std::endl;
flt << "#define DBL_ROUNDS " << std::dec << std::numeric_limits<double>::round_style << std::endl;
flt << "#define DBL_IS_IEC559 " << std::dec << std::numeric_limits<double>::is_iec559 << std::endl;
flt << "#define DBL_MANT_DIG " << std::dec << std::numeric_limits<double>::digits << std::endl;
flt << "#define DBL_DIG " << std::dec << std::numeric_limits<double>::digits10 << std::endl;
flt << "#define DBL_DECIMAL_DIG " << std::dec << std::numeric_limits<double>::max_digits10 << std::endl;
flt << "#define DBL_RADIX " << std::dec << std::numeric_limits<double>::radix << std::endl;
flt << "#define DBL_MIN_EXP " << std::dec << std::numeric_limits<double>::min_exponent << std::endl;
flt << "#define DBL_MAX_EXP " << std::dec << std::numeric_limits<double>::max_exponent << std::endl;
flt << "#define DBL_MIN_10_EXP " << std::dec << std::numeric_limits<double>::min_exponent10 << std::endl;
flt << "#define DBL_MAX_10_EXP " << std::dec << std::numeric_limits<double>::max_exponent10 << std::endl;
flt << "#define DBL_TRAPS " << std::dec << std::numeric_limits<double>::traps << std::endl;
flt << "#define DBL_TINYNESS_BEFORE " << std::dec << std::numeric_limits<double>::tinyness_before << std::endl;
flt << "#define DBL_MIN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::min() ) << "l)" << std::endl;
flt << "#define DBL_MAX " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::max() ) << "l)" << std::endl;
flt << "#define DBL_EPSILON " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::epsilon() ) << "l)" << std::endl;
flt << "#define DBL_INF " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::infinity() ) << "l)" << std::endl;
flt << "#define DBL_QUIET_NAN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::quiet_NaN() ) << "l)" << std::endl;
flt << "#define DBL_SIGNALING_NAN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::signaling_NaN()) << "l)" << std::endl;
flt << "#define DBL_DENORM_MIN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::denorm_min() ) << "l)" << std::endl;
flt << "#define DBL_ROUND_ERR " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::round_error() ) << "l)" << std::endl;
flt << "" << std::endl;
flt << "#endif // FENNEC_LANG_FLOAT_H" << std::endl;
flt.close();
return 0;
} }

View File

@ -33,6 +33,7 @@ namespace test
inline void fennec_test_math_geometric() inline void fennec_test_math_geometric()
{ {
/*
fennec_test_spacer(1); fennec_test_spacer(1);
fennec_test_run(fennec::dot(vec2(1, 2), vec2(1, 2)), 5.0f); fennec_test_run(fennec::dot(vec2(1, 2), vec2(1, 2)), 5.0f);
@ -68,6 +69,7 @@ inline void fennec_test_math_geometric()
fennec_test_run(fennec::normalize(vec2(1, 1)), vec2(sqrt(2.0f) / 2.0f, sqrt(2.0f) / 2.0f)); fennec_test_run(fennec::normalize(vec2(1, 1)), vec2(sqrt(2.0f) / 2.0f, sqrt(2.0f) / 2.0f));
fennec_test_run(fennec::normalize(vec3(1, 1, 1)), vec3(sqrt(3.0f) / 3.0f, sqrt(3.0f) / 3.0f, sqrt(3.0f) / 3.0f)); fennec_test_run(fennec::normalize(vec3(1, 1, 1)), vec3(sqrt(3.0f) / 3.0f, sqrt(3.0f) / 3.0f, sqrt(3.0f) / 3.0f));
fennec_test_run(fennec::normalize(vec4(1, 1, 1, 1)), vec4(0.5f, 0.5f, 0.5f, 0.5f)); fennec_test_run(fennec::normalize(vec4(1, 1, 1, 1)), vec4(0.5f, 0.5f, 0.5f, 0.5f));
*/
} }
} }