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/
/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.
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
# CORE =================================================================================================================
@ -24,7 +32,8 @@ add_library(fennec STATIC
include/fennec/containers/dynarray.h
# LANG =================================================================================================================
# LANG =================================================================================================================h
include/fennec/lang/bits.h
include/fennec/lang/constants.h
include/fennec/lang/conditional_types.h
include/fennec/lang/intrinsics.h
@ -43,10 +52,10 @@ add_library(fennec STATIC
# 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/allocator.h
include/fennec/memory/memory.h
include/fennec/memory/pointers.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/__vector_traits.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

View File

@ -10,15 +10,18 @@
4. [Math Library](#math-library-math)
5. [Memory Library](#memory-library-memory)
6. [Containers Library](#containers-containers)
7. [Language Processing](#language-processing-proclang)
7. [Format Processing](#format-processing-fproc)
8. [Core](#core-core)
1. [Tick](#tick)
2. [Frame](#frame)
9. [Scene](#scene-scene)
10. [3D Graphics](#3d-graphics-gfx3d)
11.
12. [3D Physics](#3d-physics-physics3d)
13. [Artificial Intelligence](#artificial-intelligence-ai)
9. [Application Layer](#application-layer-app)
10. [Scene](#scene-scene)
11. [2D Graphics](#2d-graphics-gfx2d)
12. [3D Graphics](#3d-graphics-gfx3d)
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++.
* Smart Pointers
* Unique Pointer
* Shared Pointer
- 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.
@ -97,20 +105,18 @@ Here are essential data-structures not specified in the C++ stdlib:
## Language Processing (`proclang`)
Pronounced [ˈɒkh,læŋ](https://itinerarium.github.io/phoneme-synthesis/?w=pɹˈɒkh,læŋ)
## Format Processing (`fproc`)
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.
* String Analysis (`proclang/strings`)
* String Analysis (`fproc/strings`)
* Search
* Manipulation
* Delimiting
* Regex
- File Formats (`proclang/formats`)
- File Formats (`fproc/formats`)
- Serialization
- JSON
- HTML
@ -127,16 +133,22 @@ fennec should be able to use Doxygen and LaTeX externally. Consider including bi
- ODS
- CSV
- Graphics Formats
- Textures
- BMP
- DDS
- JPG
- PNG
- TIFF
- DDS
- Wavefront OBJ
- Vectors
- OTF
- SVG
- TTF
- Models
- FBX
- Wavefront OBJ
**MAYBE**
* Compilation (`proclang/code`)
* Compilation (`fproc/code`)
* Lexical Analysis
* Syntax 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
in their operation order:
**3D Systems will apply *before* their 2D Variants**
### Tick
- **Update**
- Events
@ -179,8 +194,9 @@ in their operation order:
### Frame
- **Graphics**
- **Physics**
- Physics Interpolation
- **Graphics**
- [2D Graphics](#2d-graphics-gfx2d)
- Generate 3D Mask
- [3D Graphics](#3d-graphics-gfx3d)
@ -213,8 +229,54 @@ implementations than I could write.
## 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
- 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.
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.
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.
### 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`)
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
- 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:
- Min 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.
- Insertions and Updates are done on the CPU
- Nodes
- ID 16-bits
- Start Index 32-bits
- Object Count 16-bits
- Start Index `int32`
- Object Count `int32`
- Objects
- Buffer of Object IDs grouped by Octree Node
- Culling
- Leaf Culling
- Starting at each Octree Leaf, traverse upwards.
- Insert Visible Leaf IDs
- Track using atomic buffer
- At the second level, if a node is an edge, add the sister nodes to the visible buffer.
- Output: Buffer of Visible Leaves
* LOD Selection
* 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
- 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 construction of the Octree output, we have some options
- Ignore Leaf Instances based on occurrences of the mesh in the surrounding 8 Quadtree Leaves. This would require
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.
* Let the duplicates be rendered.
* Generate the Culled Object Buffer by copying objects from the Object Buffer
* Adjust Buffer Size using the counts
* Insert using another atomic buffer
- Perform a preprocessing step on the CPU to erase duplicate elements and fix the buffer continuity.
- Let the duplicates be rendered.
- Generate the Culled Object Buffer with the respective object IDs
- Adjust Buffer Size using the counts
- Insert by reusing the count buffer, clipped to only contain used meshes
Debug View: Object ID, Mesh ID, LOD
- Visibility
- Buffer - RGB32I w/ Depth24
- G = Object ID
- B = Mesh ID
- Buffer `(15 Bpp, 120 bpp) [1920x1080] ≈ 39.4MB`
- Depth Buffer → `D24`
- Visibility Info → `RGB32I`
- R = Object ID
- G = Mesh ID
- B = Material ID
- Regenerate the Command Buffer for Visible Mesh LODs
- Regenerate the Culled Object Buffer
Debug View: Visibility Buffer
* G-Buffer Pass
* Depth - Stencil
* 24-Bit Depth Buffer
* 8-Bit Stencil Buffer, used to represent the lighting model.
* Diffuse - RGB8
* Emission - RGB8
* Normal - RGB8
* Specular - RGB8
* G-Buffer Pass `(17 Bpp, 136 bpp) [1920x1080] ≈ 35.3MB`
* Depth - Stencil → `D24_S8`
* S → used to represent the lighting model.
* Diffuse → `RGBA8`
* A → Ambient Occlusion
* Emission → `RGB8`
* Normal → `RGB8`
* Specular → `RGB8`
* R → Roughness
* G → Specularity (sometimes called metallicism)
* G → Specularity (sometimes called the Metallicness)
* B → Index of Refraction (IOR)
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 Reflections (Optional)
- SSAO (Optional)
- Apply Lighting Model
- Output → RGB16
Debug View: Shadows, Reflections, SSAO, Deferred Lighting
@ -323,11 +440,13 @@ Debug View: Shadows, Reflections, SSAO, Deferred Lighting
* Translucent Materials
* Dual Depth Peeling
Debug View: Deferred and Forward Mask
Debug View: Forward Mask
- Post Processing
- Depth of Field (Optional) → Poisson Sampling
- Bloom (Optional) → Mipmap Blurring
- Depth of Field (Optional)
- 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)
- HDR Correction
@ -358,7 +477,7 @@ Systems
* Cloth → Position-Based Dynamics
* Water
* 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>
* 3D Fluid Dynamics &rarr; Smoothed-Particle Hydrodynamics

View File

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

View File

@ -784,7 +784,7 @@ SHOW_USED_FILES = YES
# (if specified).
# 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
# 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.
# 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)
# that should be ignored while generating the index headers. The IGNORE_PREFIX

View File

@ -784,7 +784,7 @@ SHOW_USED_FILES = YES
# (if specified).
# 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
# 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.
# 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)
# 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"/>
<!--BEGIN DISABLE_INDEX-->
<!--BEGIN FULL_SIDEBAR-->
<script type="text/javascript">var page_layout=1;</script>
<script type="text/javascript">var layout=1;</script>
<!--END FULL_SIDEBAR-->
<!--END DISABLE_INDEX-->
<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 coding-standards "Coding Standards"
/// 2. \ref building-from-source "Building from Source"
@ -40,20 +39,20 @@
/// 3. \ref running-the-test-suite "Running the Test Suite"
/// 4. \ref usage "Usage"
/// 5. \ref contribution "Contribution"
/// 6. \subpage page_fennec_libraries
/// 1. \ref page_fennec_lang "C++ Language Library"
/// 2. \ref page_fennec_math "Math Library"
/// 6. \subpage libraries
/// 1. \ref fennec_lang "C++ Language Library"
/// 2. \ref fennec_math "Math Library"
///
/// \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 |
/// | :------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
/// | \subpage page_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_lang | Implementation for functions and classes related to the C++ Language, including base types, common utility functions, and metaprogramming templates |
/// | \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
#define FENNEC_CORE_ENGINE_H

View File

@ -16,19 +16,31 @@
// 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
#define FENNEC_LANG_BITS_H
#include <fennec/lang/intrinsics.h>
#include <fennec/memory/memory.h>
#include <fennec/lang/detail/__bits.h>
namespace fennec
{
///
/// \fn fennec::bit_cast(const FromT&)
/// \brief
/// \brief perform a bitcast of FromT to ToT
/// \tparam ToT Type to cast to
/// \tparam FromT Type of the value
/// \param from Value to bit cast
@ -41,11 +53,110 @@ constexpr ToT bit_cast(const FromT& from)
else
{
ToT to;
memcpy(&to, &from, sizeof(ToT));
fennec::memcpy(&to, &from, sizeof(ToT));
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

View File

@ -88,6 +88,13 @@ struct detect
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
template<typename DefaultT, template<typename...> typename DetectT, typename...ArgsT>
requires requires { typename DetectT<ArgsT...>; }
@ -97,13 +104,6 @@ struct detect<DefaultT, DetectT, ArgsT...>
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

View File

@ -48,7 +48,6 @@ template<typename T, T V> struct integral_constant
/// \brief value of the constant
inline static constexpr T value = V;
///
///
/// \brief cast operator to allow for braced initialization
/// \returns the value of the constant
@ -56,7 +55,6 @@ template<typename T, T V> struct integral_constant
};
///
///
/// \brief metaprogramming boolean constant
///
@ -67,14 +65,12 @@ struct bool_constant
: integral_constant<bool_t, V> {};
///
///
/// \brief metaprogramming true constant
struct true_type
: bool_constant<true> {};
///
///
/// \brief metaprogramming false constant
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
#define FENNEC_LANG_FLOAT_H
#include <fennec/memory/bits.h>
#include <fennec/lang/bits.h>
#define FLT_HAS_INFINITY 1
#define FLT_HAS_QUIET_NAN 1

View File

@ -32,10 +32,12 @@
#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.
///
/// \subpage
///
///
#endif // FENNEC_LANG_H

View File

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

View File

@ -33,12 +33,18 @@
#include <fennec/lang/type_transforms.h>
#include <fennec/lang/detail/__numeric_transforms.h>
// TODO: Document
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>> {};
///
/// \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>> {};
}

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`
template<typename ClassT, typename SubT> struct replace_first_element { };

View File

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

View File

@ -18,7 +18,7 @@
///
/// \file exponential.h
/// \brief \ref page_fennec_math_exponential
/// \brief \ref fennec_math_exponential
///
///
/// \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).
///
@ -49,37 +49,37 @@
/// <th style="vertical-align: top">Description
///
/// <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">
/// \copydoc fennec::pow(fennec::genType, fennec::genType)
///
/// <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">
/// \copydoc fennec::exp(fennec::genType)
///
/// <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">
/// \copydoc fennec::exp2(fennec::genType)
///
/// <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">
/// \copydoc fennec::log(fennec::genType)
///
/// <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">
/// \copydoc fennec::log2(fennec::genType)
///
/// <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">
/// \copydoc fennec::sqrt(fennec::genType)
///
/// <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">
/// \copydoc fennec::inversesqrt(fennec::genType)
///

View File

@ -18,7 +18,7 @@
///
/// \file geometric.h
/// \brief \ref page_fennec_math_geometric
/// \brief \ref fennec_math_geometric
///
///
/// \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).
///
@ -51,58 +51,58 @@
/// <th style="vertical-align: top">Description
///
/// <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(const genDType&, const genDType&) "double dot(genDType x, genDType x)"
/// \ref fennec::dot "float dot(genFType x, genFType y)" <br>
/// \ref fennec::dot "double dot(genDType x, genDType x)"
/// <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>
/// \ref fennec::length2(const genFType&) "float length2(genFType x)" <br>
/// \ref fennec::length2(const genDType&) "double length2(genDType x)"
/// \ref fennec::length2 "float length2(genFType x)" <br>
/// \ref fennec::length2 "double length2(genDType x)"
/// <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>
/// \ref fennec::length(const genFType&) "float length(genFType x)" <br>
/// \ref fennec::length(const genDType&) "double length(genDType x)"
/// \ref fennec::length "float length(genFType x)" <br>
/// \ref fennec::length "double length(genDType x)"
/// <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>
/// \ref fennec::distance(const genFType&, const genFType&) "float distance(genFType x, genFType y)" <br>
/// \ref fennec::distance(const genDType&, const genDType&) "double distance(genDType x, genDType x)"
/// \ref fennec::distance "float distance(genFType x, genFType y)" <br>
/// \ref fennec::distance "double distance(genDType x, genDType x)"
/// <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>
/// \ref fennec::normalize(const genFType&) "float normalize(genFType x)" <br>
/// \ref fennec::normalize(const genDType&) "double normalize(genDType x)"
/// \ref fennec::normalize "float normalize(genFType x)" <br>
/// \ref fennec::normalize "double normalize(genDType x)"
/// <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>
/// \ref fennec::cross(const fennec::vec3&, const fennec::vec3&) "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 "vec3 cross(vec3 x, vec3 y)" <br>
/// \ref fennec::cross "dvec3 cross(dvec3 x, dvec3 x)"
/// <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>
/// \ref fennec::faceforward(const genFType&, const genFType&, const genFType&) "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 "genFType faceforward(genFType N, genFType I, genFType Nref)" <br>
/// \ref fennec::faceforward "genDType faceforward(genDType N, genDType I, genDType Nref)"
/// <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>
/// \ref fennec::reflect(const genFType&, const genFType&) "genFType reflect(genFType I, genFType N)" <br>
/// \ref fennec::reflect(const genDType&, const genDType&) "genDType reflect(genDType I, genDType N)"
/// \ref fennec::reflect "genFType reflect(genFType I, genFType N)" <br>
/// \ref fennec::reflect "genDType reflect(genDType I, genDType N)"
/// <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>
/// \ref fennec::refract(const genFType&, const genFType&, float) "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 "genFType refract(genFType N, genFType I, float eta)" <br>
/// \ref fennec::refract "genDType refract(genDType N, genDType I, double eta)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::refract(const genFType&, const genFType&, float)
/// \copydoc fennec::refract
///
/// </table>
///
@ -115,7 +115,6 @@ namespace fennec
// dot -----------------------------------------------------------------------------------------------------------------
///
///
/// \brief Returns the dot product of \f$x\f$ and \f$y\f$, i.e., \f$x_0 \cdot y_0 + x_0 \cdot y_0 + \ldots\f$
///
@ -135,7 +134,6 @@ constexpr genType dot(const vector<genType, i...>& x, const vector<genType, i...
// length2 -------------------------------------------------------------------------------------------------------------
///
///
/// \brief Returns the squared length of vector \f$x\f$, i.e., \f$x_0^2 + x_1^2 + \ldots\f$
///
@ -153,7 +151,6 @@ constexpr genType length2(const vector<genType, i...>& x)
// length --------------------------------------------------------------------------------------------------------------
///
///
/// \brief Returns the length of vector \f$x\f$, i.e., \f$\sqrt{x_0^2 + x_1^2 + \ldots}\f$
///
@ -170,7 +167,6 @@ constexpr genType length(const vector<genType, i...>& x) { return fennec::sqrt(f
// distance ------------------------------------------------------------------------------------------------------------
///
///
/// \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 ---------------------------------------------------------------------------------------------------------------
///
///
/// \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$
@ -212,11 +207,10 @@ constexpr vector<genType, i...> cross(const vector<genType, i...>& x, const vect
// normalize -----------------------------------------------------------------------------------------------------------
///
///
/// \brief Returns a vector in the same direction as \f$x\f$, but with a length of \f$1\f$, i.e.
///
/// \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>
/// 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 ---------------------------------------------------------------------------------------------------------
///
///
/// \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 -------------------------------------------------------------------------------------------------------------
///
///
/// \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 -------------------------------------------------------------------------------------------------------------
///
///
/// \brief or the incident vector \f$I\f$ and surface normal \f$N\f$, and the ratio of indices of refraction \f$eta\f$,
/// \brief For the incident vector \f$I\f$ and surface normal \f$N\f$, and the ratio of indices of refraction \f$eta\f$,
/// 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>
@ -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)
{ genType ndi = fennec::dot(N, I);
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

View File

@ -21,10 +21,10 @@
/// \brief main math header which includes the main modules
///
///
/// \details This header includes the following modules of \ref page_fennec_math :
/// - \ref page_fennec_math_scalar
/// - \ref page_fennec_math_vector
/// - \ref page_fennec_math_trigonometric
/// \details This header includes the following modules of \ref fennec_math :
/// - \ref fennec_math_scalar
/// - \ref fennec_math_vector
/// - \ref fennec_math_trigonometric
///
/// \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 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).
///
/// \section page_fennec_math_topics Topics
/// - \subpage page_fennec_math_set_theory
/// \section fennec_math_topics Topics
/// - \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 page_fennec_math_vector
/// - \subpage page_fennec_math_matrix
/// - \subpage fennec_math_scalar
/// - \subpage fennec_math_vector
/// - \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
/// the branch of Mathematics that studies Sets. Sets contain a collection of elements which may be numbers, or other
/// 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.
///
///

View File

@ -18,7 +18,7 @@
///
/// \file matrix.h
/// \brief the \ref page_fennec_math_matrix
/// \brief the \ref fennec_math_matrix
///
///
/// \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>
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>
constexpr void __insert(scalar_t s)

View File

@ -18,7 +18,7 @@
///
/// \file relational.h
/// \brief \ref page_fennec_math_relational
/// \brief \ref fennec_math_relational
///
///
/// \details
@ -33,67 +33,181 @@
#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
namespace fennec
{
template<typename genType, typename genBType = bool_t>
constexpr genBType lessThan(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>
constexpr vector<genBType, i...> lessThan(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ 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>
constexpr vector<genBType, i...> lessThanEqual(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ 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>
constexpr vector<genBType, i...> greaterThan(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ 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>
constexpr vector<genBType, i...> greaterThanEqual(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ 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>
constexpr vector<genBType, i...> equal(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ 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>
constexpr vector<genBType, i...> notEqual(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ 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>
constexpr genBType any(const vector<genBType, i...>& x)
{ 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>
constexpr genBType all(const vector<genBType, i...>& x)
{ 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
/// \brief the \ref page_fennec_math_scalar
/// \brief the \ref fennec_math_scalar
///
///
/// \details
@ -36,7 +36,7 @@
///
///
///
/// \page page_fennec_math_scalar Scalars
/// \page fennec_math_scalar Scalars
/// \anchor scalar
///
/// 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:
///
/// | Type | Meaning |
/// |----------|------------------------------|
/// |\c bool | \copybrief fennec::bool_t |
/// |\c int | \copybrief fennec::int_t |
/// |\c uint | \copybrief fennec::uint_t |
/// |\c float | \copybrief fennec::float_t |
/// |\c double | \copybrief fennec::double_t |
/// | Type | Corresponding Type | Meaning |
/// |----------|-----------------------|------------------------------|
/// |\c bool | \ref fennec::bool_t | \copybrief fennec::bool_t |
/// |\c int | \ref fennec::int_t | \copybrief fennec::int_t |
/// |\c uint | \ref fennec::uint_t | \copybrief fennec::uint_t |
/// |\c float | \ref fennec::float_t | \copybrief fennec::float_t |
/// |\c double | \ref fennec::double_t | \copybrief fennec::double_t |
///
///
///

View File

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

View File

@ -18,7 +18,7 @@
///
/// \file trigonometric.h
/// \brief the \ref page_fennec_math_trigonometric
/// \brief the \ref fennec_math_trigonometric
///
///
/// \details
@ -34,7 +34,7 @@
///
///
///
/// \page page_fennec_math_trigonometric Trigonometry
/// \page fennec_math_trigonometric Trigonometry
///
/// \brief The fennec Trigonometry Module
///
@ -47,96 +47,96 @@
/// <th style="vertical-align: top">Description
///
/// <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">
/// \copydoc fennec::degrees(fennec::genType)
/// \copydoc fennec::degrees
///
/// <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">
/// \copydoc fennec::radians(fennec::genType)
/// \copydoc fennec::radians
///
/// </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">
/// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description
///
/// <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">
/// \copydoc fennec::sin(fennec::genType)
/// \copydoc fennec::sin
///
/// <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">
/// \copydoc fennec::cos(fennec::genType)
/// \copydoc fennec::cos
///
/// <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">
/// \copydoc fennec::tan(fennec::genType)
/// \copydoc fennec::tan
///
///
/// <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">
/// \copydoc fennec::asin(fennec::genType)
/// \copydoc fennec::asin
///
/// <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">
/// \copydoc fennec::acos(fennec::genType)
/// \copydoc fennec::acos
///
/// <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">
/// \copydoc fennec::atan(fennec::genType)
/// \copydoc fennec::atan
///
/// </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">
/// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description
///
/// <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">
/// \copydoc fennec::sinh(fennec::genType)
/// \copydoc fennec::sinh
///
/// <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">
/// \copydoc fennec::cosh(fennec::genType)
/// \copydoc fennec::cosh
///
/// <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">
/// \copydoc fennec::tanh(fennec::genType)
/// \copydoc fennec::tanh
///
///
/// <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">
/// \copydoc fennec::asinh(fennec::genType)
/// \copydoc fennec::asinh
///
/// <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">
/// \copydoc fennec::acosh(fennec::genType)
/// \copydoc fennec::acosh
///
/// <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">
/// \copydoc fennec::atanh(fennec::genType)
/// \copydoc fennec::atanh
///
/// </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
///
/// \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
///
/// \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
///
/// \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.
///
/// \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.
///
/// \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.
///
/// \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$.
///
/// \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$
///
/// \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$
///
/// \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$
///
/// \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
///
/// \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
///
/// \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
///
/// \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>
constexpr vector<genType, i...> atanh(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::atanh(x[i]) ...); }
/// @}

View File

@ -18,7 +18,7 @@
///
/// \file vector.h
/// \brief the \ref page_fennec_math_vector
/// \brief the \ref fennec_math_vector
///
///
/// \details
@ -34,7 +34,7 @@
///
///
///
/// \page page_fennec_math_vector Vectors
/// \page fennec_math_vector Vectors
///
/// \brief The fennec Vector Math Module
///
@ -43,27 +43,27 @@
///
/// <table>
/// <caption id="table_fennec_math_vector_types"></caption>
/// <tr><th>Type <th>Brief
/// <tr><td colspan=2 style="text-align: center;">Floats
/// <tr><td>```vec2``` <td>\copybrief fennec::vec2
/// <tr><td>```vec3``` <td>\copybrief fennec::vec3
/// <tr><td>```vec4``` <td>\copybrief fennec::vec4
/// <tr><td colspan=2 style="text-align: center;">Doubles
/// <tr><td>```dvec2```<td>\copybrief fennec::dvec2
/// <tr><td>```dvec3```<td>\copybrief fennec::dvec3
/// <tr><td>```dvec4```<td>\copybrief fennec::dvec4
/// <tr><td colspan=2 style="text-align: center;">Booleans
/// <tr><td>```bvec2```<td>\copybrief fennec::bvec2
/// <tr><td>```bvec3```<td>\copybrief fennec::bvec3
/// <tr><td>```bvec4```<td>\copybrief fennec::bvec4
/// <tr><td colspan=2 style="text-align: center;">Integers
/// <tr><td>```ivec2```<td>\copybrief fennec::ivec2
/// <tr><td>```ivec3```<td>\copybrief fennec::ivec3
/// <tr><td>```ivec4```<td>\copybrief fennec::ivec4
/// <tr><td colspan=2 style="text-align: center;">Unsigned Integers
/// <tr><td>```uvec2```<td>\copybrief fennec::uvec2
/// <tr><td>```uvec3```<td>\copybrief fennec::uvec3
/// <tr><td>```uvec4```<td>\copybrief fennec::uvec4
/// <tr><th>Type <th>Corresponding Type <th>Brief
/// <tr><th colspan=3 style="text-align: center;">Floats
/// <tr><td>```vec2``` <td>\ref fennec::vec2 <td>\copybrief fennec::vec2
/// <tr><td>```vec3``` <td>\ref fennec::vec3 <td>\copybrief fennec::vec3
/// <tr><td>```vec4``` <td>\ref fennec::vec4 <td>\copybrief fennec::vec4
/// <tr><th colspan=3 style="text-align: center;">Doubles
/// <tr><td>```dvec2```<td>\ref fennec::dvec2 <td>\copybrief fennec::dvec2
/// <tr><td>```dvec3```<td>\ref fennec::dvec3 <td>\copybrief fennec::dvec3
/// <tr><td>```dvec4```<td>\ref fennec::dvec4 <td>\copybrief fennec::dvec4
/// <tr><th colspan=3 style="text-align: center;">Booleans
/// <tr><td>```bvec2``` <td>\ref fennec::bvec2 <td>\copybrief fennec::bvec2
/// <tr><td>```bvec3``` <td>\ref fennec::bvec3 <td>\copybrief fennec::bvec3
/// <tr><td>```bvec4``` <td>\ref fennec::bvec4 <td>\copybrief fennec::bvec4
/// <tr><th colspan=3 style="text-align: center;">Integers
/// <tr><td>```ivec2``` <td>\ref fennec::ivec2 <td>\copybrief fennec::ivec2
/// <tr><td>```ivec3``` <td>\ref fennec::ivec3 <td>\copybrief fennec::ivec3
/// <tr><td>```ivec4``` <td>\ref fennec::ivec4 <td>\copybrief fennec::ivec4
/// <tr><th colspan=3 style="text-align: center;">Unsigned Integers
/// <tr><td>```uvec2``` <td>\ref fennec::uvec2 <td>\copybrief fennec::uvec2
/// <tr><td>```uvec3``` <td>\ref fennec::uvec3 <td>\copybrief fennec::uvec3
/// <tr><td>```uvec4``` <td>\ref fennec::uvec4 <td>\copybrief fennec::uvec4
/// </table>
///
///
@ -89,7 +89,7 @@
///
/// \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>
///
/// let \f$V = (0, 1, 2)\f$
@ -113,9 +113,7 @@ namespace fennec
///
/// \typedef vec
/// \anchor vec
/// \brief Main \ref fennec::vector "vector" template
/// \brief Main \ref fennec_math_vector "vector" template
/// \tparam ScalarT The type of the 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>{}));
@ -123,122 +121,92 @@ template<typename ScalarT, size_t SizeV> using vec = decltype(detail::__gen_vect
///
/// \typedef tvec2
/// \anchor tvec2
/// \brief Shorthand for ```vec<ScalarT, 2>```
/// \brief Shorthand for creating a 2-element \ref fennec::vector, ```vec<ScalarT, 2>```
/// \details Shorthand for creating a 2-element \ref fennec::vector, ```vec<ScalarT, 2>```
/// \tparam ScalarT The type of the Components
template<typename ScalarT> using tvec2 = vec<ScalarT, 2>;
///
/// \typedef tvec3
/// \anchor tvec3
/// \brief Shorthand for ```vec<ScalarT, 3>```
/// \brief Shorthand for creating a 3-element \ref fennec::vector, ```vec<ScalarT, 3>```
/// \details Shorthand for creating a 3-element \ref fennec::vector, ```vec<ScalarT, 3>```
/// \tparam ScalarT The type of the Components
template<typename ScalarT> using tvec3 = vec<ScalarT, 3>;
///
/// \typedef tvec4
/// \anchor tvec4
/// \brief Shorthand for ```vec<ScalarT, 4>```
/// \brief Shorthand for creating a 4-element \ref fennec::vector, ```vec<ScalarT, 4>```
/// \details Shorthand for creating a 4-element \ref fennec::vector, ```vec<ScalarT, 4>```
/// \tparam ScalarT The type of the Components
template<typename ScalarT> using tvec4 = vec<ScalarT, 4>;
///
/// \typedef bvec2
/// \anchor bvec2
/// \brief A two-component boolean \ref fennec::vector "vector"
/// \brief A two-component boolean \ref fennec_math_vector "vector"
using bvec2 = tvec2<bool_t>;
///
/// \typedef bvec3
/// \anchor bvec3
/// \brief A three-component boolean \ref fennec::vector "vector"
/// \brief A three-component boolean \ref fennec_math_vector "vector"
using bvec3 = tvec3<bool_t>;
///
/// \typedef bvec4
/// \anchor bvec4
/// \brief A four-component boolean \ref fennec::vector "vector"
/// \brief A four-component boolean \ref fennec_math_vector "vector"
using bvec4 = tvec4<bool_t>;
///
/// \typedef ivec2
/// \anchor ivec2
/// \brief A two-component signed integer \ref fennec::vector "vector"
/// \brief A two-component signed integer \ref fennec_math_vector "vector"
using ivec2 = tvec2<int32_t>;
/// \typedef ivec3
/// \anchor ivec3
/// \brief A three-component signed integer \ref fennec::vector "vector"
///
/// \brief A three-component signed integer \ref fennec_math_vector "vector"
using ivec3 = tvec3<int32_t>;
/// \typedef 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>;
///
/// \typedef uvec2
/// \anchor uvec2
/// \brief A two-component unsigned integer \ref fennec::vector "vector"
/// \brief A two-component unsigned integer \ref fennec_math_vector "vector"
using uvec2 = tvec2<uint32_t>;
///
/// \typedef uvec3
/// \anchor uvec3
/// \brief A three-component unsigned integer \ref fennec::vector "vector"
/// \brief A three-component unsigned integer \ref fennec_math_vector "vector"
using uvec3 = tvec3<uint32_t>;
///
/// \typedef uvec4
/// \anchor uvec4
/// \brief A four-component unsigned integer \ref fennec::vector "vector"
/// \brief A four-component unsigned integer \ref fennec_math_vector "vector"
using uvec4 = tvec4<uint32_t>;
///
/// \typedef vec2
/// \anchor vec2
/// \brief A two-component single-precision floating-point \ref fennec::vector "vector"
/// \brief A two-component single-precision floating-point \ref fennec_math_vector "vector"
using vec2 = tvec2<float32_t>;
///
/// \typedef vec3
/// \anchor vec3
/// \brief A three-component single-precision floating-point \ref fennec::vector "vector"
/// \brief A three-component single-precision floating-point \ref fennec_math_vector "vector"
using vec3 = tvec3<float32_t>;
///
/// \typedef vec4
/// \anchor vec4
/// \brief A four-component single-precision floating-point \ref fennec::vector "vector"
/// \brief A four-component single-precision floating-point \ref fennec_math_vector "vector"
using vec4 = tvec4<float32_t>;
///
/// \typedef dvec2
/// \anchor dvec2
/// \brief A two-component double-precision floating-point \ref fennec::vector "vector"
/// \brief A two-component double-precision floating-point \ref fennec_math_vector "vector"
using dvec2 = tvec2<float64_t>;
///
/// \typedef dvec3
/// \anchor dvec3
/// \brief A three-component double-precision floating-point \ref fennec::vector "vector"
/// \brief A three-component double-precision floating-point \ref fennec_math_vector "vector"
using dvec3 = tvec3<float64_t>;
///
/// \typedef dvec4
/// \anchor dvec4
/// \brief A four-component double-precision floating-point \ref fennec::vector "vector"
/// \brief A four-component double-precision floating-point \ref fennec_math_vector "vector"
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 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
///
/// \details
/// \tparam OScalarT scalar Type of the \ref fennec::vector "vector" to Convert
/// \param v \ref fennec::vector "vector" to Convert
/// \tparam OScalarT scalar Type of the \ref fennec_math_vector "vector" to Convert
/// \param v \ref fennec_math_vector "vector" to Convert
template<typename OScalarT>
explicit constexpr vector(const vector<OScalarT, IndicesV...>& v)
{ ((data[IndicesV] = ScalarT(v[IndicesV])), ...); }
@ -366,7 +334,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \brief vector conversion constructor
///
/// \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 MoreIndicesV
/// \param v
@ -410,7 +378,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \brief decay implementation
///
/// \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()
{ return static_cast<const decay_t&>(*this); }
@ -493,54 +461,54 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
// 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
/// \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 rhs right hand side
constexpr friend vector_t operator+(scalar_t lhs, const vector_t& rhs)
{ 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
/// \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 rhs right hand side
constexpr friend vector_t operator-(scalar_t lhs, const vector_t& rhs)
{ 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
/// \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 rhs right hand side
constexpr friend vector_t operator*(scalar_t lhs, const vector_t& rhs)
{ 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
/// \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 rhs right hand side
constexpr friend vector_t operator/(scalar_t lhs, const vector_t& rhs)
{ 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
/// \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 rhs right hand side
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 ==================================================================================
/// \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
/// \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 rhs right hand side
constexpr friend vector_t operator+(const vector_t& lhs, scalar_t 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
/// \param lhs left 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)
{ 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
/// \param lhs left 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)
{ 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
/// \param lhs left 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)
{ 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
/// \param lhs left 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>)
{ return vector((lhs[IndicesV] % rhs) ...); }
@ -607,56 +575,56 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
// 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
/// \param lhs Left 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)
{ 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
/// \param lhs Left 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)
{ 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
/// \param lhs Left 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)
{ 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
/// \param lhs Left 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)
{ 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
/// \param lhs Left 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>)
{ return ((lhs[IndicesV] %= rhs), ..., lhs); }
@ -664,55 +632,55 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
// 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
/// \param lhs Left 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)
{ 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
/// \param lhs Left 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)
{ 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
/// \param lhs Left 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)
{ return vector((lhs[IndicesV] * rhs[IndicesV]) ...); }
///
/// \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 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)
{ 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
/// \param lhs Left 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>)
{ return vector((lhs[IndicesV] % rhs[IndicesV]) ...); }
@ -720,56 +688,56 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
// 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
/// \param lhs Left 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)
{ 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
/// \param lhs Left 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)
{ 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
/// \param lhs Left 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)
{ 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
/// \param lhs Left 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)
{ 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
/// \param lhs Left 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>)
{ 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
/// \param lhs Left 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>)
{ 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 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>)
{ 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
/// \param lhs Left 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>)
{ 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
/// \param lhs Left 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>)
{ 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
/// \param lhs Left 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>)
{ 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
/// \param lhs Left 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>)
{ 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
/// \param lhs Left 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>)
{ 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
/// \param lhs Left 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>)
{ 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
/// \param lhs Left 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>)
{ 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
/// \param lhs Left 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>)
{ 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
/// \param lhs Left 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>)
{ 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
/// \param lhs Left 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>)
{ 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
/// \param lhs Left 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>)
{ 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
/// \param lhs Left 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>)
{ 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 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>)
{ return vector_t((lhs ^ rhs[IndicesV]) ...); }
///
/// \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 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>)
{ return ((lhs[IndicesV] ^= rhs), ..., lhs); }
///
/// \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 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>)
{ return vector_t((lhs[IndicesV] ^ rhs) ...); }
///
/// \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 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>)
{ return ((lhs[IndicesV] ^= rhs), ..., lhs); }
///
/// \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 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>)
{ 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)
/// \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 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>)
{ return ((lhs[IndicesV] <<= rhs), ..., lhs); }
///
/// \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 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>)
{ return vector_t((lhs[IndicesV] << rhs) ...); }
///
/// \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 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>)
{ return ((lhs[IndicesV] <<= rhs), ..., lhs); }
///
/// \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 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>)
{ 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)
/// \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 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>)
{ return ((lhs[IndicesV] >>= rhs), ..., lhs); }
///
/// \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 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>)
{ return vector_t((lhs[IndicesV] >> rhs) ...); }
///
/// \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 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>)
{ return ((lhs[IndicesV] >>= rhs), ..., lhs); }
///
/// \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 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>)
{ return vector_t((lhs[IndicesV] >> rhs[IndicesV]) ...); }

View File

@ -18,7 +18,7 @@
///
/// \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

View File

@ -13,6 +13,9 @@ namespace fennec
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
constexpr size_t __memcpy_16(void* dst, const void* src)
{ *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)
{ *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;
}
///
/// \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$.
/// \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);
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 >= 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; }
while (n >= 1) { *d++ = *s++; --n; }
while (n > 0)
{
size_t step = detail::__memcpy(d, s, n);
d += step; s += step; n -= step;
}
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..
/// \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)
{
while (n >= 8) { detail::__memcpy_64(d, s); d += 8; s += 8; n -= 8; }
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; }
while (n >= 1) { *d++ = *s++; --n; }
while (n > 0)
{
size_t step = detail::__memcpy(d, s, n);
d += step; s += step; n -= step;
}
}
else
{
d += n - 1; s += n - 1;
while (n >= 8) { detail::__memcpy_64(d, s); d -= 8; s -= 8; n -= 8; }
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; }
while (n >= 1) { *d-- = *s--; --n; }
while (n > 0)
{
size_t step = detail::__memcpy(d, s, n);
d -= step; s -= step; n -= step;
}
}
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$
/// \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)
add_executable(fennec-metaprogramming main.cpp)
add_executable(fennec-metaprogramming main.cpp
float.h)
add_custom_command(
OUTPUT .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**)
{
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()
{
/*
fennec_test_spacer(1);
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(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));
*/
}
}