- Touched up documentation for Math library

- finished matrix implementation
 - added custom assert implementation
This commit is contained in:
2025-06-22 16:28:49 -04:00
parent 4d8466851c
commit 31e3c26b66
14 changed files with 423 additions and 206 deletions

View File

@@ -62,6 +62,8 @@ add_library(fennec STATIC
include/fennec/lang/detail/__type_traits.h include/fennec/lang/detail/__type_traits.h
include/fennec/lang/detail/__type_sequences.h include/fennec/lang/detail/__type_sequences.h
include/fennec/lang/assert.h source/lang/assert.cpp
# MEMORY =============================================================================================================== # MEMORY ===============================================================================================================
include/fennec/memory/new.h source/memory/new.cpp include/fennec/memory/new.h source/memory/new.cpp
@@ -98,8 +100,8 @@ add_library(fennec STATIC
include/fennec/math/detail/__fwd.h include/fennec/math/detail/__fwd.h
include/fennec/math/detail/__types.h include/fennec/math/detail/__types.h
include/fennec/math/detail/__vector_traits.h include/fennec/math/detail/__vector_traits.h
include/fennec/lang/assert.h
source/lang/assert.cpp source/debug/assert_impl.cpp
) )
# add metaprogramming templates as a dependency and also force documentation to be generated when fennec is compiled # add metaprogramming templates as a dependency and also force documentation to be generated when fennec is compiled

View File

@@ -9,7 +9,7 @@
3. [C++ Language](#c-language-library-lang) 3. [C++ Language](#c-language-library-lang)
4. [Math Library](#math-library-math) 4. [Math Library](#math-library-math)
5. [Memory Library](#memory-library-memory) 5. [Memory Library](#memory-library-memory)
6. [Containers Library](#containers-containers) 6. [Containers Library](#containers-library-containers)
7. [Format Processing](#format-processing-fproc) 7. [Format Processing](#format-processing-fproc)
8. [Core](#core-core) 8. [Core](#core-core)
1. [Tick](#tick) 1. [Tick](#tick)
@@ -33,9 +33,11 @@ This file serves as a general planning document for engine structure, systems, p
Implementations of core engine systems should strive to be `O(1)` in implementations, Implementations of core engine systems should strive to be `O(1)` in implementations,
both in terms of runtime and memory performance. This is obviously not a realistic goal, both in terms of runtime and memory performance. This is obviously not a realistic goal,
so rather than the goal requiring the entire engine to be `O(1)`, we should more specifically look so rather than the goal requiring the entire engine to be `O(1)`, we should more specifically look
at achieving `O(1)` performance on hot paths. at achieving `O(1)` performance on hot paths. I distinctly use 'strive' and 'goal' as different concepts, where designs
should *strive* to accommodate function implementations for `O(1)`, however the specifics of the implementation might not always
be able to achieve that, so the end *goal* is that hot paths should be `O(1)`.
Functions should be highly verbose, and in debug mode any bugprone or erroneous behaviour should throw Functions should be highly verbose and any bugprone or erroneous behaviour should throw
assertions. **DO NOT USE EXCEPTIONS**. assertions. **DO NOT USE EXCEPTIONS**.
System implementations should be independent of architecture or platforms. i.e. the code of the graphics system should System implementations should be independent of architecture or platforms. i.e. the code of the graphics system should
@@ -48,7 +50,7 @@ This principle should extend to the submodules of the engine.
It is also best to avoid objects having behaviour that is not defined by the system they are in. There are some exceptions It is also best to avoid objects having behaviour that is not defined by the system they are in. There are some exceptions
in extensions or mods and should be given configurability and programmability within those systems and their stages. in extensions or mods and should be given configurability and programmability within those systems and their stages.
This however can be acheived using events at different stages of those engines that are on-demand. This however can be achieved using events at different stages of those engines that are on-demand.
@@ -81,8 +83,8 @@ Implement math functions according to the [OpenGL 4.6 Shading Language Specifica
the Specification. the Specification.
Additional extensions should be implemented to provide standard definitions for functions predominantly related Additional extensions should be implemented to provide standard definitions for functions predominantly related
to Linear Algebra, Mathematical Analysis, and Discrete Analysis. Additional extensions will be implemented on a to Linear Algebra, Mathematical Analysis, and more specifically Discrete Analysis. Additional extensions will be
as-needed basis. implemented on an as-needed basis.
@@ -219,9 +221,9 @@ in their operation order:
## Application Layer (`app`) ## Application Layer (`app`)
This is the core windowing system of fennec. The implementation will initially be an SDL3 wrapper. This is the core windowing system of fennec. The implementation will initially be an SDL3 wrapper.
Custom implementation may be further down the roadmap, however this is extremely complicated and there are better Custom implementation may be further down the roadmap, however this is extremely complicated and there are better
implementations than I could write. implementations than I could write alone.
@@ -249,8 +251,8 @@ Object Structure. The mesh is implicit data.
### Structures (`gfx2d`) ### Structures (`gfx2d`)
For the 2d rendering framework, Materials need to be rendered independently because we have 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 no size constraints for images. This disallows us from using a meta-shader like in
the 3d rendering framework. the 3d rendering framework.
```c++ ```c++
@@ -285,8 +287,8 @@ struct Object
- Adjust Buffer Size using the counts - Adjust Buffer Size using the counts
- Insert using another atomic buffer - Insert using another atomic buffer
- Translucent objects will be sorted. We can cheat by using a z-index instead of a z-coordinate. - 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, 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. with meshes and objects being grouped by material.
@@ -304,14 +306,14 @@ Links:
- https://pixelandpoly.com/ior.html - https://pixelandpoly.com/ior.html
- https://developer.download.nvidia.com/SDK/10/opengl/screenshots/samples/dual_depth_peeling.html - https://developer.download.nvidia.com/SDK/10/opengl/screenshots/samples/dual_depth_peeling.html
**DirectX will never have official support.** **DirectX will never have official support.**
If you would like to make a fork, have at it, but know that I will hold a deep disdain for you. If you would like to make a fork, have at it, but know that I will hold a deep disdain for you.
The graphics pipeline will have a buffer with a list of objects and their rendering data. The graphics pipeline will have a buffer with a list of objects and their rendering data.
This will be referred to as the Object Buffer. There will be two, for both the Deferred and Forward Passes. This will be referred to as the Object Buffer. There will be two, for both the Deferred and Forward Passes.
The buffers will be optimized by scene prediction. The buffers will be optimized by scene prediction.
This involves tracking the meshes and textures directly and indirectly used by a scene. 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. A callback function in the graphics system for scene loading can do this.

View File

@@ -18,7 +18,7 @@
3. [Running the Test Suite](#running-the-test-suite) 3. [Running the Test Suite](#running-the-test-suite)
4. [Usage](#usage) 4. [Usage](#usage)
5. [Contribution](#contribution) 5. [Contribution](#contribution)
6. [Documentation](./fennec_documentation.html) 6. [Documentation](./documentation.html)
<br> <br>
<br> <br>
@@ -27,16 +27,16 @@
<a id="introduction"></a> <a id="introduction"></a>
## Introduction ## Introduction
fennec is designed to be a general purpose, educational game engine. &ensp; fennec is designed to be a general purpose, educational game engine. fennec
fennec may be used through the provided editor application, or as a standalone may be used through the provided editor application, or as a standalone library to
library to link against your application. link against your application.
<br> <br>
<a id="coding-standards"></a> <a id="coding-standards"></a>
### Coding Standards ### Coding Standards
Interfacing with the API in C++ follows the [GNU Coding Standards](https://www.gnu.org/prep/standards/html_node/index.html). Interfacing with the API in C++ follows the [GNU Coding Standards](https://www.gnu.org/prep/standards/html_node/index.html).
Some main areas where the engine strays from the GNU standard includes the following: Some main areas where the engine strays from the GNU standard includes the following:
* [Section 4.7, Standards for Graphical Interfaces](https://www.gnu.org/prep/standards/html_node/Graphical-Interfaces.html). * [Section 4.7, Standards for Graphical Interfaces](https://www.gnu.org/prep/standards/html_node/Graphical-Interfaces.html).
@@ -44,25 +44,44 @@ Some main areas where the engine strays from the GNU standard includes the follo
- [Section 6.1, GNU Manuals](https://www.gnu.org/prep/standards/html_node/GNU-Manuals.html) - [Section 6.1, GNU Manuals](https://www.gnu.org/prep/standards/html_node/GNU-Manuals.html)
fennec does not use Texinfo and instead uses Doxygen. Otherwise, it follows the other standards of this section. fennec does not use Texinfo and instead uses Doxygen. Otherwise, it follows the other standards of this section.
* [Section 7, The Release Process](https://www.gnu.org/prep/standards/html_node/Managing-Releases.html) * [Section 7, The Release Process](https://www.gnu.org/prep/standards/html_node/Managing-Releases.html)
fennec follows most of the conventions in this section, however the build system used is CMake and not fennec follows most of the conventions in this section, however the build system used is CMake and not
Makefile. CMake, although overwhelming at first, is much more friendly to those who are learning build systems for the first time. Makefile. CMake, although overwhelming at first, is much more friendly to those who are learning build systems for the first time.
<br> <br>
fennec Standards: fennec Standards:
* As per the GNU standard, macros should be `SCREAMING_SNAKE_CASE`. Additionally, Macros should be preceded by `<APP_NAME>_`. * As per the GNU standard, macros should be `SCREAMING_SNAKE_CASE`. Additionally, Macros should be preceded by `<APP_NAME>_`.
Macros that wrap C-Style functions may use normal `snake_case`. Macros that wrap C-Style functions may use normal `snake_case`.
- Header Guards should be implemented using `#ifndef`, `#define`, and `#endif` for portability. - Header Guards should be implemented using `#ifndef`, `#define`, and `#endif` for portability.
The naming convention for Header Guards is as follows: `<APP_NAME>_<DIRECTORY_PATH>_<FILE_NAME>_H`. The naming convention for Header Guards is as follows: `<APP_NAME>_<DIRECTORY_PATH>_<FILE_NAME>_H`.
I.E. the engine file `fennec/lang/utility.h` has the Header Guard `FENNEC_LANG_UTILITY_H`. I.E. the engine file `fennec/lang/utility.h` has the Header Guard `FENNEC_LANG_UTILITY_H`.
* Helper Functions, in the case of classes, should be private. * Helper Functions, in the case of classes, should be private.
In the case of global functions, helpers should be placed in a similarly named file in a subdirectory and namespace called `detail`. In the case of global functions, helpers should be placed in a similarly named file in a subdirectory and namespace
Helper functions should be documented with C-Style comments, however it is not necessary to provide Doxygen documentation. called `detail`. Helper functions should be documented with C-Style comments, however it is not necessary to provide
Doxygen documentation.
- **DO NOT USE C++ EXCEPTIONS** they will not be supported because they are shit. No, I won't elaborate. - **DO NOT USE C++ EXCEPTIONS** they will not be supported because they are shit. No, I won't elaborate.[[1]](#f1)
* Most behaviours should be type independent. Specifically interactions with the core systems of the engine.
<br><br>
<a id="f1"></a>
[1] Okay, I will elaborate. If we were to use the exception paradigm for all erroneous behaviour, we couldn't
guarantee that the state will not be corrupted when an exception is thrown. The behaviour afterward is
undefined because of this, and we also don't really know when, how, or where that exception will be handled.
The assertion paradigm is better at handling this because you are defining erroneous behaviour in the code and how
it is handled. In a debug build we can immediately halt the program, we don't care about the state afterward, only
beforehand. Now for a release build, this is first and foremost a game engine, so we want to crash as gracefully as
possible, prevent data loss, and get some debug information for it. fennec defines its own `assert` macro to
be used, defining a hook in the private version of the function. This hook is used to clean up any state information
within the engine and may be used to send immediate events to listeners so that outside functionality may decide
how to handle the impending crash. There is nothing that can be done to stop the crash, as soon as the branch
finishes, `abort()` will be called.
<br> <br>
@@ -82,11 +101,11 @@ There are a few reasons for this:
<a id="building-from-source"></a> <a id="building-from-source"></a>
## Building from Source ## Building from Source
fennec uses the CMake build manager. The CMake build script provides several &ensp; fennec uses the CMake build manager. The CMake build script provides several
targets for building parts of the engine. targets for building parts of the engine.
Using an IDE will streamline the build process for you and add additional configuration &ensp; Using an IDE will streamline the build process for you and add additional configuration
options. Eclipse, Visual Studio, and CLion provide built-in support for CMake. VSCode options. Eclipse, Visual Studio, and CLion provide built-in support for CMake. VSCode
is also a viable IDE but involves some extra setup. is also a viable IDE but involves some extra setup.
| Target | Description | | Target | Description |
@@ -116,18 +135,17 @@ is also a viable IDE but involves some extra setup.
`build.sh` provides profiles for building the main engine. Run `./build.sh --help` `build.sh` provides profiles for building the main engine. Run `./build.sh --help`
for more info. for more info.
By default, the CMake generator &ensp; By default, the CMake generator used is Ninja, which requires Ninja to be installed. You can modify the
used is Ninja, which requires Ninja to be installed. build scripts to use another build manager, see the [CMake documentation for available generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html).
You can modify the build scripts to use another build manager, see the [CMake documentation for available generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html).
<br> <br>
<a id="building-on-windows"></a> <a id="building-on-windows"></a>
### Building on Windows ### Building on Windows
The bash script can be run natively on Windows when WSL is enabled. &ensp; The bash script can be run natively on Windows when WSL is enabled. You do not need to run the
You do not need to run the script in WSL, simply use the "bash" command in Command Prompt or PowerShell. script in WSL, simply use the "bash" command in Command Prompt or PowerShell. The script will require
The script will require the build [dependencies](#dependencies) installed and configured to be available on the `PATH` environment variable. the build [dependencies](#dependencies) installed and configured to be available on the `PATH` environment variable.
Fore more details, [see this blog post](https://blogs.windows.com/windows-insider/2016/04/06/announcing-windows-10-insider-preview-build-14316/) for Windows Build 14316. Fore more details, [see this blog post](https://blogs.windows.com/windows-insider/2016/04/06/announcing-windows-10-insider-preview-build-14316/) for Windows Build 14316.
@@ -152,10 +170,9 @@ The value of `<profile>` may be one of the following:
<br> <br>
If you would like to use Visual Studio without CMake, you can use the build &ensp; If you would like to use Visual Studio without CMake, you can use the build script to generate
script to generate a Visual Studio project for the source. For a list of available a Visual Studio project for the source. For a list of available Visual Studio generators, [see this section](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html)
Visual Studio generators, [see this section](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html). of the CMake docs. Running the following command will generate the Visual Studio project.
Running the following command will generate the Visual Studio project.
```commandline ```commandline
cmake -G "Visual Studio 17 2022" -A x64 cmake -G "Visual Studio 17 2022" -A x64
@@ -169,10 +186,10 @@ cmake -G "Visual Studio 17 2022" -A x64
`test.sh` provides profiles for building the test suite and executes them. `test.sh` provides profiles for building the test suite and executes them.
By default, it runs in debug mode and the first failed test will throw an assertion. &ensp; By default, the program runs in debug mode and the first failed test will throw an assertion.
Any tests that involve running as an application will spawn a subprocess with a window, Any tests that involve running as an application will spawn a subprocess with a window, and give
and give a short description of the behaviour in the terminal. It will then have you confirm a short description of the behaviour in the terminal. It will then have you confirm whether the
whether the information displayed is correct. information displayed is correct.
<br> <br>
<br> <br>

View File

@@ -21,8 +21,6 @@
using assert_handler = void (*)(const char *, const char *, int , const char *); using assert_handler = void (*)(const char *, const char *, int , const char *);
extern void set_assert_handler(assert_handler handler);
extern void __assert_impl(const char* expression, const char* file, int line, const char* function); extern void __assert_impl(const char* expression, const char* file, int line, const char* function);
#define assert(expression) if(not(expression)) { __assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__); } #define assert(expression) if(not(expression)) { __assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__); }

View File

@@ -131,7 +131,6 @@ namespace fennec
// fennec::type_transform ============================================================================================== // fennec::type_transform ==============================================================================================
/// ///
/// \struct fennec::type_transform
/// \brief Base Class for Type Transformations /// \brief Base Class for Type Transformations
/// ///
/// \details resembles a transformation from one type to T, the result is stored in the member type_transform::type /// \details resembles a transformation from one type to T, the result is stored in the member type_transform::type
@@ -139,7 +138,6 @@ namespace fennec
template<typename T> struct type_transform { template<typename T> struct type_transform {
/// ///
/// \typedef type_transform::type
/// \brief the type to transform into /// \brief the type to transform into
using type = T; using type = T;
}; };

View File

@@ -32,7 +32,10 @@
#ifndef FENNEC_MATH_EXPONENTIAL_H #ifndef FENNEC_MATH_EXPONENTIAL_H
#define FENNEC_MATH_EXPONENTIAL_H #define FENNEC_MATH_EXPONENTIAL_H
#include <cmath> #pragma push_macro("__cplusplus")
#undef __cplusplus
#include <math.h>
#pragma pop_macro("__cplusplus")
/// ///
/// ///
@@ -106,7 +109,7 @@ namespace fennec
/// \param y the exponent /// \param y the exponent
template<typename genType> template<typename genType>
constexpr genType pow(genType x, genType y) constexpr genType pow(genType x, genType y)
{ return std::pow(x, y); } { return ::pow(x, y); }
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> pow(const vector<genType, i...> & x, const vector<genType, i...> & y) constexpr vector<genType, i...> pow(const vector<genType, i...> & x, const vector<genType, i...> & y)
@@ -123,7 +126,7 @@ constexpr vector<genType, i...> pow(const vector<genType, i...> & x, const vecto
/// \param x the exponent /// \param x the exponent
template<typename genType> template<typename genType>
constexpr genType exp(genType x) constexpr genType exp(genType x)
{ return std::exp(x); } { return ::exp(x); }
template<typename genType, size_t...i> constexpr vector<genType, i...> exp(const vector<genType, i...>& x) template<typename genType, size_t...i> constexpr vector<genType, i...> exp(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::exp(x[i]) ...); } { return vector<genType, i...>(fennec::exp(x[i]) ...); }
@@ -138,7 +141,7 @@ template<typename genType, size_t...i> constexpr vector<genType, i...> exp(const
/// ///
/// \param x the exponent /// \param x the exponent
template<typename genType> constexpr genType exp2(genType x) template<typename genType> constexpr genType exp2(genType x)
{ return std::exp2(x); } { return ::exp2(x); }
template<typename genType, size_t...i> constexpr vector<genType, i...> exp2(const vector<genType, i...>& x) template<typename genType, size_t...i> constexpr vector<genType, i...> exp2(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::exp2(x[i]) ...); } { return vector<genType, i...>(fennec::exp2(x[i]) ...); }
@@ -154,7 +157,7 @@ template<typename genType, size_t...i> constexpr vector<genType, i...> exp2(cons
/// ///
/// \param x the input value /// \param x the input value
template<typename genType> constexpr genType log(genType x) template<typename genType> constexpr genType log(genType x)
{ return std::log(x); } { return ::log(x); }
template<typename genType, size_t...i> constexpr genType log(const vector<genType, i...>& x) template<typename genType, size_t...i> constexpr genType log(const vector<genType, i...>& x)
{ return vector<genType, i...>(log(x[i]) ...); } { return vector<genType, i...>(log(x[i]) ...); }
@@ -171,7 +174,7 @@ template<typename genType, size_t...i> constexpr genType log(const vector<genTyp
/// ///
/// \param x the input value /// \param x the input value
template<typename genType> constexpr genType log2(genType x) template<typename genType> constexpr genType log2(genType x)
{ return std::log2(x); } { return ::log2(x); }
template<typename genType, size_t...i> constexpr genType log2(const vector<genType, i...>& x) template<typename genType, size_t...i> constexpr genType log2(const vector<genType, i...>& x)
{ return vector<genType, i...>(log2(x[i]) ...); } { return vector<genType, i...>(log2(x[i]) ...); }
@@ -187,7 +190,7 @@ template<typename genType, size_t...i> constexpr genType log2(const vector<genTy
/// ///
/// \param x the input value /// \param x the input value
template<typename genType> constexpr genType sqrt(genType x) template<typename genType> constexpr genType sqrt(genType x)
{ return std::sqrt(x); } { return ::sqrt(x); }
template<typename genType, size_t...i> constexpr genType sqrt(const vector<genType, i...>& x) template<typename genType, size_t...i> constexpr genType sqrt(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::sqrt(x[i]) ...); } { return vector<genType, i...>(fennec::sqrt(x[i]) ...); }

View File

@@ -46,8 +46,8 @@
#include <fennec/math/detail/__fwd.h> #include <fennec/math/detail/__fwd.h>
#include <fennec/containers/array.h> #include <fennec/containers/array.h>
#include <fennec/math/geometric.h> #include <fennec/math/geometric.h>
#include <fennec/math/vector.h>
#include <fennec/math/vector_traits.h> #include <fennec/math/vector_traits.h>
namespace fennec namespace fennec
@@ -80,38 +80,43 @@ constexpr vec<scalar, sizeof...(cols)> row(const matrix<scalar, rows, cols...>&
{ return vec<scalar, sizeof...(cols)>(m[cols][i]...); } { return vec<scalar, sizeof...(cols)>(m[cols][i]...); }
template<typename ScalarT> using tmat2x2 = mat<ScalarT, 2, 2>; ///< helper for creating 2x2 matrices of the specified type.
template<typename ScalarT> using tmat2x3 = mat<ScalarT, 2, 3>; ///< helper for creating 2x3 matrices of the specified type.
template<typename ScalarT> using tmat2x4 = mat<ScalarT, 2, 4>; ///< helper for creating 2x4 matrices of the specified type.
template<typename ScalarT> using tmat3x2 = mat<ScalarT, 3, 2>; ///< helper for creating 3x2 matrices of the specified type.
template<typename ScalarT> using tmat3x3 = mat<ScalarT, 3, 3>; ///< helper for creating 3x3 matrices of the specified type.
template<typename ScalarT> using tmat3x4 = mat<ScalarT, 3, 4>; ///< helper for creating 3x4 matrices of the specified type.
template<typename ScalarT> using tmat4x2 = mat<ScalarT, 4, 2>; ///< helper for creating 4x2 matrices of the specified type.
template<typename ScalarT> using tmat4x3 = mat<ScalarT, 4, 3>; ///< helper for creating 4x3 matrices of the specified type.
template<typename ScalarT> using tmat4x4 = mat<ScalarT, 4, 4>; ///< helper for creating 4x4 matrices of the specified type.
template<size_t rows, size_t cols> using tmat = mat<float_t, rows, cols>; using mat2 = tmat2x2<float_t>; ///< Specification for glsl float matrices
using mat3 = tmat3x3<float_t>; ///< Specification for glsl float matrices
using mat4 = tmat3x3<float_t>; ///< Specification for glsl float matrices
using mat2 = tmat<2, 2>; using mat2x2 = tmat2x2<float_t>; ///< Specification for sized glsl float matrices
using mat3 = tmat<3, 3>; using mat2x3 = tmat2x3<float_t>; ///< Specification for sized glsl float matrices
using mat4 = tmat<4, 4>; using mat2x4 = tmat2x4<float_t>; ///< Specification for sized glsl float matrices
using mat3x2 = tmat3x2<float_t>; ///< Specification for sized glsl float matrices
using mat3x3 = tmat3x3<float_t>; ///< Specification for sized glsl float matrices
using mat3x4 = tmat3x4<float_t>; ///< Specification for sized glsl float matrices
using mat4x2 = tmat4x2<float_t>; ///< Specification for sized glsl float matrices
using mat4x3 = tmat4x3<float_t>; ///< Specification for sized glsl float matrices
using mat4x4 = tmat4x4<float_t>; ///< Specification for sized glsl float matrices
using mat2x2 = tmat<2, 2>; using dmat2 = tmat2x2<double_t>; ///< Specification for glsl double matrices
using mat2x3 = tmat<2, 3>; using dmat3 = tmat3x3<double_t>; ///< Specification for glsl double matrices
using mat2x4 = tmat<2, 4>; using dmat4 = tmat3x3<double_t>; ///< Specification for glsl double matrices
using mat3x2 = tmat<3, 2>;
using mat3x3 = tmat<3, 3>;
using mat3x4 = tmat<3, 4>;
using mat4x2 = tmat<4, 2>;
using mat4x3 = tmat<4, 3>;
using mat4x4 = tmat<4, 4>;
template<size_t rows, size_t cols> using tdmat = mat<float_t, rows, cols>; using dmat2x2 = tmat2x2<double_t>; ///< Specification for size glsl double matrices
using dmat2x3 = tmat2x3<double_t>; ///< Specification for size glsl double matrices
using dmat2 = tdmat<2, 2>; using dmat2x4 = tmat2x4<double_t>; ///< Specification for size glsl double matrices
using dmat3 = tdmat<3, 3>; using dmat3x2 = tmat3x2<double_t>; ///< Specification for size glsl double matrices
using dmat4 = tdmat<4, 4>; using dmat3x3 = tmat3x3<double_t>; ///< Specification for size glsl double matrices
using dmat3x4 = tmat3x4<double_t>; ///< Specification for size glsl double matrices
using dmat2x2 = tdmat<2, 2>; using dmat4x2 = tmat4x2<double_t>; ///< Specification for size glsl double matrices
using dmat2x3 = tdmat<2, 3>; using dmat4x3 = tmat4x3<double_t>; ///< Specification for size glsl double matrices
using dmat2x4 = tdmat<2, 4>; using dmat4x4 = tmat4x4<double_t>; ///< Specification for size glsl double matrices
using dmat3x2 = tdmat<3, 2>;
using dmat3x3 = tdmat<3, 3>;
using dmat3x4 = tdmat<3, 4>;
using dmat4x2 = tdmat<4, 2>;
using dmat4x3 = tdmat<4, 3>;
using dmat4x4 = tdmat<4, 4>;
/// ///
@@ -197,7 +202,7 @@ struct matrix
/// ///
/// \details /// \details
/// \param mat matrix to move /// \param mat matrix to move
constexpr matrix(matrix_t&& mat) constexpr matrix(matrix_t&& mat) noexcept
: data{ mat.data } {} : data{ mat.data } {}
@@ -215,7 +220,6 @@ struct matrix
/// </table><br><br> /// </table><br><br>
/// ///
/// \param s scalar value /// \param s scalar value
///
constexpr matrix(scalar_t s) constexpr matrix(scalar_t s)
{ (((ColIndicesV < rows) ? data[ColIndicesV][ColIndicesV] = s : 0), ...); } { (((ColIndicesV < rows) ? data[ColIndicesV][ColIndicesV] = s : 0), ...); }
@@ -278,7 +282,6 @@ struct matrix
{ assert(i < rows); return data[i]; } { assert(i < rows); return data[i]; }
/// ///
/// \fn matrix::operator()(size_t, size_t)
/// \copydetails matrix::operator()(size_t, size_t) const /// \copydetails matrix::operator()(size_t, size_t) const
constexpr scalar_t& operator()(size_t i, size_t j) constexpr scalar_t& operator()(size_t i, size_t j)
{ assert(i < rows && j < columns); return data[i][j]; } { assert(i < rows && j < columns); return data[i][j]; }
@@ -298,13 +301,245 @@ struct matrix
/// \name Scalar Operators /// \name Scalar Operators
/// @{ /// @{
///
/// \brief \ref fennec::matrix "matrix" - \ref scalar addition operator.
/// \param lhs the matrix
/// \param rhs the scalar
/// \returns a copy of the matrix with each component having been added by the scalar
constexpr friend matrix_t operator+(const matrix_t& lhs, scalar_t rhs)
{
matrix_t retval = lhs;
((retval[ColIndicesV] += rhs), ...);
return retval;
}
///
/// \brief \ref scalar - \ref fennec::matrix "matrix" addition operator.
/// \param lhs the scalar
/// \param rhs the matrix
/// \returns a copy of the matrix with each component having been added by the scalar
constexpr friend matrix_t operator+(scalar_t lhs, const matrix_t& rhs)
{
matrix_t retval = rhs;
((retval[ColIndicesV] += lhs), ...);
return retval;
}
///
/// \brief \ref fennec::matrix "matrix" - \ref scalar subtraction operator.
/// \param lhs the matrix
/// \param rhs the scalar
/// \returns a copy of the matrix with each component having been subtracted by the scalar
constexpr friend matrix_t operator-(const matrix_t& lhs, scalar_t rhs)
{
matrix_t retval = lhs;
((retval[ColIndicesV] -= rhs), ...);
return retval;
}
///
/// \brief \ref scalar - \ref fennec::matrix "matrix" subtraction operator.
/// \param lhs the scalar
/// \param rhs the matrix
/// \returns a copy of the matrix with each component having been subtracted by the scalar
constexpr friend matrix_t operator-(scalar_t lhs, const matrix_t& rhs)
{
matrix_t retval = rhs;
((retval[ColIndicesV] -= lhs), ...);
return retval;
}
///
/// \brief \ref fennec::matrix "matrix" - \ref scalar multiplication operator.
/// \param lhs the matrix
/// \param rhs the scalar
/// \returns a copy of the matrix with each component having been multiplied by the scalar
constexpr friend matrix_t operator*(const matrix_t& lhs, scalar_t rhs)
{
matrix_t retval = lhs;
((retval[ColIndicesV] *= rhs), ...);
return retval;
}
///
/// \brief \ref scalar - \ref fennec::matrix "matrix" multiplication operator.
/// \param lhs the scalar
/// \param rhs the matrix
/// \returns a copy of the matrix with each component having been multiplied by the scalar
constexpr friend matrix_t operator*(scalar_t lhs, const matrix_t& rhs)
{
matrix_t retval = rhs;
((retval[ColIndicesV] *= lhs), ...);
return retval;
}
///
/// \brief \ref fennec::matrix "matrix" - \ref scalar division operator.
/// \param lhs the matrix
/// \param rhs the scalar
/// \returns a copy of the matrix with each component having been divided by the scalar
constexpr friend matrix_t operator/(const matrix_t& lhs, scalar_t rhs)
{
matrix_t retval = lhs;
((retval[ColIndicesV] /= rhs), ...);
return retval;
}
///
/// \brief \ref scalar - \ref fennec::matrix "matrix" division operator.
/// \param lhs the scalar
/// \param rhs the matrix
/// \returns a copy of the matrix with each component having been divided by the scalar
constexpr friend matrix_t operator/(scalar_t lhs, const matrix_t& rhs)
{
matrix_t retval = rhs;
((retval[ColIndicesV] /= lhs), ...);
return retval;
}
///
/// \brief \ref fennec::matrix "matrix" - \ref scalar addition assignment operator.
/// \param lhs the matrix
/// \param rhs the scalar
/// \returns the matrix after having each component added by the scalar
constexpr friend matrix_t& operator+=(matrix_t& lhs, scalar_t rhs)
{
((lhs[ColIndicesV] += rhs), ...);
return lhs;
}
///
/// \brief \ref scalar - \ref fennec::matrix "matrix" addition assignment operator.
/// \param lhs the scalar
/// \param rhs the matrix
/// \returns the matrix after having each component added by the scalar
constexpr friend matrix_t& operator+=(scalar_t lhs, matrix_t& rhs)
{
((rhs[ColIndicesV] += lhs), ...);
return rhs;
}
///
/// \brief \ref fennec::matrix "matrix" - \ref scalar subtraction assignment operator.
/// \param lhs the matrix
/// \param rhs the scalar
/// \returns the matrix after having each component subtracted by the scalar
constexpr friend matrix_t& operator-=(matrix_t& lhs, scalar_t rhs)
{
((lhs[ColIndicesV] -= rhs), ...);
return lhs;
}
///
/// \brief \ref scalar - \ref fennec::matrix "matrix" addition assignment operator.
/// \param lhs the scalar
/// \param rhs the matrix
/// \returns the matrix after having each component added by the scalar
constexpr friend matrix_t& operator-=(scalar_t lhs, matrix_t& rhs)
{
((rhs[ColIndicesV] -= lhs), ...);
return rhs;
}
///
/// \brief \ref fennec::matrix "matrix" - \ref scalar multiplication assignment operator.
/// \param lhs the matrix
/// \param rhs the scalar
/// \returns the matrix after having each component multiplied by the scalar
constexpr friend matrix_t& operator*=(matrix_t& lhs, scalar_t rhs)
{
((lhs[ColIndicesV] *= rhs), ...);
return lhs;
}
///
/// \brief \ref scalar - \ref fennec::matrix "matrix" multiplication assignment operator.
/// \param lhs the scalar
/// \param rhs the matrix
/// \returns the matrix after having each component multiplied by the scalar
constexpr friend matrix_t& operator*=(scalar_t lhs, matrix_t& rhs)
{
((rhs[ColIndicesV] *= lhs), ...);
return rhs;
}
///
/// \brief \ref fennec::matrix "matrix" - \ref scalar division assignment operator.
/// \param lhs the matrix
/// \param rhs the scalar
/// \returns the matrix after having each component divided by the scalar
constexpr friend matrix_t& operator/=(matrix_t& lhs, scalar_t rhs)
{
((lhs[ColIndicesV] /= rhs), ...);
return lhs;
}
///
/// \brief \ref scalar - \ref fennec::matrix "matrix" division assignment operator.
/// \param lhs the scalar
/// \param rhs the matrix
/// \returns the matrix after having each component divided by the scalar
constexpr friend matrix_t& operator/=(scalar_t lhs, matrix_t& rhs)
{
((rhs[ColIndicesV] /= lhs), ...);
return rhs;
}
///
/// \brief \ref fennec::matrix "matrix" - \ref scalar modulo operator.
/// \param lhs the matrix
/// \param rhs the scalar
/// \returns a copy of the matrix with each component having been reduced modulo by the scalar
constexpr friend matrix_t operator%(const matrix_t& lhs, scalar_t rhs) requires is_integral_v<scalar_t>
{
matrix_t retval = lhs;
((retval[ColIndicesV] %= rhs), ...);
return retval;
}
///
/// \brief \ref scalar - \ref fennec::matrix "matrix" modulo operator.
/// \param lhs the scalar
/// \param rhs the matrix
/// \returns a copy of the matrix with each component having been reduced modulo by the scalar
constexpr friend matrix_t operator%(scalar_t lhs, const matrix_t& rhs) requires is_integral_v<scalar_t>
{
matrix_t retval = rhs;
((retval[ColIndicesV] %= lhs), ...);
return retval;
}
///
/// \brief \ref fennec::matrix "matrix" - \ref scalar modulo assignment operator.
/// \param lhs the matrix
/// \param rhs the scalar
/// \returns the matrix after having each component reduced modulo by the scalar
constexpr friend matrix_t& operator%=(matrix_t& lhs, scalar_t rhs) requires is_integral_v<scalar_t>
{
((lhs[ColIndicesV] %= rhs), ...);
return lhs;
}
///
/// \brief \ref scalar - \ref fennec::matrix "matrix" modulo assignment operator.
/// \param lhs the scalar
/// \param rhs the matrix
/// \returns the matrix after having each component reduced modulo by the scalar
constexpr friend matrix_t& operator%=(scalar_t lhs, matrix_t& rhs) requires is_integral_v<scalar_t>
{
((rhs[ColIndicesV] %= lhs), ...);
return rhs;
}
/// @} /// @}
// Vector Operators ==================================================================================================== // Vector Operators ====================================================================================================
/// \name \ref matrix_t "matrix" \ref fennec::vector "vector" Operators /// \name \ref fennec::matrix "matrix" - \ref fennec::vector "vector" Operators
/// @{ /// @{
/// ///
@@ -330,9 +565,25 @@ struct matrix
// Matrix Operators ==================================================================================================== // Matrix Operators ====================================================================================================
/// \name \ref matrix_t "matrix" \ref matrix_t "matrix" Operators /// \name \ref fennec::matrix "matrix" - \ref fennec::matrix "matrix" Operators
/// @{ /// @{
///
/// \brief matrix comparison operator
/// \param lhs the first matrix
/// \param rhs the second matrix
/// \returns a boolean value that contains \f$true\f$ when all components of `lhs` and `rhs` are equal and \f$false\f$ otherwise
constexpr friend bool operator==(const matrix_t& lhs, const matrix_t& rhs)
{ return lhs.data == rhs.data; }
///
/// \brief matrix comparison operator
/// \param lhs the first matrix
/// \param rhs the second matrix
/// \returns a boolean value that contains \f$true\f$ when all components of `lhs` and `rhs` are not equal and \f$false\f$ otherwise
constexpr friend bool operator!=(const matrix_t& lhs, const matrix_t& rhs)
{ return lhs.data != rhs.data; }
/// ///
/// \brief performs a linear algebraic matrix multiplication /// \brief performs a linear algebraic matrix multiplication
/// \param lhs the rows to multiply with /// \param lhs the rows to multiply with
@@ -341,12 +592,6 @@ struct matrix
{ return [lhs, rhs]<size_t...i>(index_sequence<i...>) -> matrix_t { return [lhs, rhs]<size_t...i>(index_sequence<i...>) -> matrix_t
{ return matrix_t(rhs * fennec::row(lhs, i)...); }(make_index_sequence<rows>{}); } { return matrix_t(rhs * fennec::row(lhs, i)...); }(make_index_sequence<rows>{}); }
constexpr friend bool operator==(const matrix_t& lhs, const matrix_t& rhs)
{ return lhs.data == rhs.data; }
constexpr friend bool operator!=(const matrix_t& lhs, const matrix_t& rhs)
{ return lhs.data != rhs.data; }
/// @} /// @}

View File

@@ -163,8 +163,7 @@ using ivec2 = tvec2<int32_t>;
/// \brief A three-component signed integer \ref fennec_math_vector "vector" /// \brief A three-component signed integer \ref fennec_math_vector "vector"
using ivec3 = tvec3<int32_t>; using ivec3 = tvec3<int32_t>;
/// \typedef ivec4 ///
/// \anchor ivec4
/// \brief A four-component signed integer \ref fennec_math_vector "vector" /// \brief A four-component signed integer \ref fennec_math_vector "vector"
using ivec4 = tvec4<int32_t>; using ivec4 = tvec4<int32_t>;
@@ -214,7 +213,6 @@ using dvec4 = tvec4<float64_t>;
/// ///
/// \struct fennec::vector
/// \brief Math Vector Type /// \brief Math Vector Type
/// \tparam ScalarT base \ref scalar type of each Component /// \tparam ScalarT base \ref scalar type of each Component
/// \tparam IndicesV index of each Component /// \tparam IndicesV index of each Component
@@ -233,7 +231,6 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// @{ /// @{
/// ///
/// \typedef vector::base_type
/// \brief vector base type /// \brief vector base type
using base_type = detail::vector_base_type<ScalarT, sizeof...(IndicesV)>; using base_type = detail::vector_base_type<ScalarT, sizeof...(IndicesV)>;
@@ -242,12 +239,10 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
using base_type::data; using base_type::data;
/// ///
/// \typedef scalar_t
/// \brief alias for ScalarT /// \brief alias for ScalarT
using scalar_t = ScalarT; using scalar_t = ScalarT;
/// ///
/// \typedef vector::vector_t
/// \brief alias for this type /// \brief alias for this type
using vector_t = vector; using vector_t = vector;
@@ -667,7 +662,6 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
{ return vector((lhs[IndicesV] * rhs[IndicesV]) ...); } { return vector((lhs[IndicesV] * rhs[IndicesV]) ...); }
/// ///
/// \fn vector::operator/(const vector_t&, const vector_t&)
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" division operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" division operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
@@ -899,7 +893,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// ///
/// \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" bitwise or operator /// \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" bitwise xor operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$
@@ -907,8 +901,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
{ return vector_t((lhs ^ rhs[IndicesV]) ...); } { return vector_t((lhs ^ rhs[IndicesV]) ...); }
/// ///
/// \fn vector::operator^=(vector_t&, scalar_t) /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise xor assignment operator
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or assignment operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$
@@ -916,8 +909,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
{ return ((lhs[IndicesV] ^= rhs), ..., lhs); } { return ((lhs[IndicesV] ^= rhs), ..., lhs); }
/// ///
/// \fn vector::operator^(const vector_t&, scalar_t) /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise xor operator
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$
@@ -925,8 +917,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
{ return vector_t((lhs[IndicesV] ^ rhs) ...); } { return vector_t((lhs[IndicesV] ^ rhs) ...); }
/// ///
/// \fn vector::operator^=(vector_t&, const vector_t&) /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise xor assignment operator
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$
@@ -934,8 +925,7 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
{ return ((lhs[IndicesV] ^= rhs), ..., lhs); } { return ((lhs[IndicesV] ^= rhs), ..., lhs); }
/// ///
/// \fn vector::operator^(const vector_t&, const vector_t&) /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise xor operator
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$
@@ -945,7 +935,6 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// ///
/// \fn vector::operator<<=(vector_t&, scalar_t)
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift assignment operator /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift assignment operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
@@ -954,7 +943,6 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
{ return ((lhs[IndicesV] <<= rhs), ..., lhs); } { return ((lhs[IndicesV] <<= rhs), ..., lhs); }
/// ///
/// \fn vector::operator<<(const vector_t&, scalar_t)
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
@@ -963,7 +951,6 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
{ return vector_t((lhs[IndicesV] << rhs) ...); } { return vector_t((lhs[IndicesV] << rhs) ...); }
/// ///
/// \fn vector::operator<<=(vector_t&, const vector_t&)
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
@@ -972,7 +959,6 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
{ return ((lhs[IndicesV] <<= rhs), ..., lhs); } { return ((lhs[IndicesV] <<= rhs), ..., lhs); }
/// ///
/// \fn vector::operator<<(const vector_t&, const vector_t&)
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or operator /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
@@ -983,7 +969,6 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// ///
/// \fn vector::operator>>=(vector_t&, scalar_t)
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift assignment operator /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift assignment operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
@@ -992,7 +977,6 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
{ return ((lhs[IndicesV] >>= rhs), ..., lhs); } { return ((lhs[IndicesV] >>= rhs), ..., lhs); }
/// ///
/// \fn vector::operator>>(const vector_t&, scalar_t)
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
@@ -1001,7 +985,6 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
{ return vector_t((lhs[IndicesV] >> rhs) ...); } { return vector_t((lhs[IndicesV] >> rhs) ...); }
/// ///
/// \fn vector::operator>>=(vector_t&, const vector_t&)
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
@@ -1010,7 +993,6 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
{ return ((lhs[IndicesV] >>= rhs), ..., lhs); } { return ((lhs[IndicesV] >>= rhs), ..., lhs); }
/// ///
/// \fn vector::operator>>(const vector_t&, const vector_t&)
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or operator /// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression

View File

@@ -34,7 +34,6 @@ namespace detail
{ {
/// ///
/// \struct vector_base_type_helper
/// \brief helper class for generating vectors /// \brief helper class for generating vectors
/// \tparam scalar base scalar type /// \tparam scalar base scalar type
/// \tparam size size of the vector type /// \tparam size size of the vector type
@@ -48,22 +47,18 @@ struct vector_base_type_helper
/// ///
/// \typedef ScalarT
/// \brief Base scalar type /// \brief Base scalar type
using ScalarT = scalar; using ScalarT = scalar;
/// ///
/// \typedef VectorT
/// \brief Base vector type /// \brief Base vector type
using VectorT = vec<ScalarT, SizeV>; using VectorT = vec<ScalarT, SizeV>;
/// ///
/// \typedef DataT
/// \brief Backing array holding the elements /// \brief Backing array holding the elements
using DataT = array<ScalarT, SizeV>; using DataT = array<ScalarT, SizeV>;
/// ///
/// \struct SwizzleGen
/// \brief Helper for generating a swizzle from a set of indices /// \brief Helper for generating a swizzle from a set of indices
/// \tparam IndicesV Indices of the vector to pull from /// \tparam IndicesV Indices of the vector to pull from
template<size_t...IndicesV> struct SwizzleGen template<size_t...IndicesV> struct SwizzleGen
@@ -72,10 +67,7 @@ struct vector_base_type_helper
using type = swizzle<VectorT, DataT, ScalarT, IndicesV...>; using type = swizzle<VectorT, DataT, ScalarT, IndicesV...>;
}; };
/// // Specialization for single component swizzles to decay into a scalar
/// \struct SwizzleGen<IndexV>
/// \brief Partial Specialization for single component swizzles to decay into a scalar
/// \tparam IndexV
template<size_t IndexV> struct SwizzleGen<IndexV> template<size_t IndexV> struct SwizzleGen<IndexV>
{ {
/// \brief decayed scalar type /// \brief decayed scalar type
@@ -83,11 +75,12 @@ struct vector_base_type_helper
}; };
/// ///
/// \typedef StorageT
/// \brief backing storage type /// \brief backing storage type
using StorageT = vector_storage<SizeV, SwizzleGen, DataT>; using StorageT = vector_storage<SizeV, SwizzleGen, DataT>;
}; };
///
/// \brief helper for getting the storage type of the vector constructed with the provided size and scalar type
template<typename ScalarT, size_t SizeV> template<typename ScalarT, size_t SizeV>
using vector_base_type = typename vector_base_type_helper<ScalarT, SizeV>::StorageT; using vector_base_type = typename vector_base_type_helper<ScalarT, SizeV>::StorageT;

View File

@@ -30,7 +30,6 @@ namespace detail
{ {
/// ///
/// \struct vector_storage
/// \brief backing storage type for vectors /// \brief backing storage type for vectors
/// \tparam SizeV size of the vector /// \tparam SizeV size of the vector
/// \tparam SwizzleGenT generator for swizzles /// \tparam SwizzleGenT generator for swizzles
@@ -38,17 +37,10 @@ namespace detail
template<size_t SizeV, template<size_t...> class SwizzleGenT, typename DataT> struct vector_storage; template<size_t SizeV, template<size_t...> class SwizzleGenT, typename DataT> struct vector_storage;
/// // specialization for single component vectors
/// \struct vector_storage<1, SwizzleGenT, DataT>
/// \brief specialization for single component vectors
/// \tparam SwizzleGenT generator for swizzles
/// \tparam DataT backing data type
template <template <size_t...> class SwizzleGenT, typename DataT> template <template <size_t...> class SwizzleGenT, typename DataT>
struct vector_storage<1, SwizzleGenT, DataT> struct vector_storage<1, SwizzleGenT, DataT>
{ {
///
/// \typedef swizzle
/// alias to allow for increased legibility
template<size_t...IndicesV> using swizzle = typename SwizzleGenT<IndicesV...>::type; template<size_t...IndicesV> using swizzle = typename SwizzleGenT<IndicesV...>::type;
vector_storage() = default; vector_storage() = default;
@@ -69,16 +61,11 @@ struct vector_storage<1, SwizzleGenT, DataT>
}; };
/// // specialization for two component vectors
/// \struct vector_storage<2, SwizzleGenT, DataT>
/// \brief specialization for two component vectors
/// \tparam SwizzleGenT generator for swizzles
/// \tparam DataT backing data type
template <template <size_t...> class SwizzleGenT, typename DataT> template <template <size_t...> class SwizzleGenT, typename DataT>
struct vector_storage<2, SwizzleGenT, DataT> struct vector_storage<2, SwizzleGenT, DataT>
{ {
/// ///
/// \typedef swizzle
/// alias to allow for increased legibility /// alias to allow for increased legibility
template<size_t...IndicesV> using swizzle = typename SwizzleGenT<IndicesV...>::type; template<size_t...IndicesV> using swizzle = typename SwizzleGenT<IndicesV...>::type;
@@ -123,17 +110,10 @@ struct vector_storage<2, SwizzleGenT, DataT>
}; };
/// // specialization for three component vectors
/// \struct vector_storage<3, SwizzleGenT, DataT>
/// \brief specialization for three component vectors
/// \tparam SwizzleGenT generator for swizzles
/// \tparam DataT backing data type
template <template <size_t...> class SwizzleGenT, typename DataT> template <template <size_t...> class SwizzleGenT, typename DataT>
struct vector_storage<3, SwizzleGenT, DataT> struct vector_storage<3, SwizzleGenT, DataT>
{ {
///
/// \typedef swizzle
/// alias to allow for increased legibility
template<size_t...IndicesV> using swizzle = typename SwizzleGenT<IndicesV...>::type; template<size_t...IndicesV> using swizzle = typename SwizzleGenT<IndicesV...>::type;
vector_storage() = default; vector_storage() = default;
@@ -266,17 +246,10 @@ struct vector_storage<3, SwizzleGenT, DataT>
}; };
/// // specialization for four component vectors
/// \struct vector_storage<4, SwizzleGenT, DataT>
/// \brief specialization for four component vectors
/// \tparam SwizzleGenT generator for swizzles
/// \tparam DataT backing data type
template <template <size_t...> class SwizzleGenT, typename DataT> template <template <size_t...> class SwizzleGenT, typename DataT>
struct vector_storage<4, SwizzleGenT, DataT> struct vector_storage<4, SwizzleGenT, DataT>
{ {
///
/// \typedef swizzle
/// alias to allow for increased legibility
template<size_t...IndicesV> using swizzle = typename SwizzleGenT<IndicesV...>::type; template<size_t...IndicesV> using swizzle = typename SwizzleGenT<IndicesV...>::type;
vector_storage() = default; vector_storage() = default;

View File

@@ -39,8 +39,8 @@ constexpr TypeT* addressof(TypeT& obj) { return FENNEC_BUILTIN_ADDRESSOF(obj); }
constexpr void* memchr(void* arr, int ch, size_t n) constexpr void* memchr(void* arr, int ch, size_t n)
{ {
uint8_t* a = static_cast<uint8_t*>(arr); uint8_t* a = static_cast<uint8_t*>(arr);
while (n--) if (*a++ == ch) return a - 1; while (n-- && *a++ != ch) {}
return nullptr; return n ? a : nullptr;
} }
/// ///
@@ -52,8 +52,8 @@ constexpr void* memchr(void* arr, int ch, size_t n)
constexpr const void* memchr(const void* arr, int ch, size_t n) constexpr const void* memchr(const void* arr, int ch, size_t n)
{ {
const uint8_t* a = static_cast<const uint8_t*>(arr); const uint8_t* a = static_cast<const uint8_t*>(arr);
while (n--) if (*a++ == ch) return a - 1; while (n-- && *a++ != ch) {}
return nullptr; return n ? a : nullptr;
} }
/// ///
@@ -67,12 +67,8 @@ constexpr int memcmp(const void* lhs, const void* rhs, size_t n)
{ {
const uint8_t* lhs_ = static_cast<const uint8_t*>(lhs); const uint8_t* lhs_ = static_cast<const uint8_t*>(lhs);
const uint8_t* rhs_ = static_cast<const uint8_t*>(rhs); const uint8_t* rhs_ = static_cast<const uint8_t*>(rhs);
while (n-- && *lhs_++ == *rhs_++) {}
while (n--) return n ? *lhs_ - *rhs_ : 0;
if (*lhs_++ != *rhs_++)
return lhs_[-1] - rhs_[-1];
return 0;
} }
/// ///
@@ -101,8 +97,7 @@ constexpr void* memcpy(void* dst, const void* src, size_t n)
uint8_t* d = static_cast<uint8_t*>(dst); uint8_t* d = static_cast<uint8_t*>(dst);
const uint8_t* s = static_cast<const uint8_t*>(src); const uint8_t* s = static_cast<const uint8_t*>(src);
while (n > 0) while (n > 0) {
{
size_t step = detail::__memcpy(d, s, n); size_t step = detail::__memcpy(d, s, n);
d += step; s += step; n -= step; d += step; s += step; n -= step;
} }
@@ -130,19 +125,15 @@ constexpr void* memmove(void* dst, const void* src, size_t n)
uint8_t* d = static_cast<uint8_t*>(dst); uint8_t* d = static_cast<uint8_t*>(dst);
const uint8_t* s = static_cast<const uint8_t*>(src); const uint8_t* s = static_cast<const uint8_t*>(src);
if (d < s) if (d < s) {
{ while (n > 0) {
while (n > 0)
{
size_t step = detail::__memcpy(d, s, n); size_t step = detail::__memcpy(d, s, n);
d += step; s += step; n -= step; d += step; s += step; n -= step;
} }
} }
else else {
{
d += n - 1; s += n - 1; d += n - 1; s += n - 1;
while (n > 0) while (n > 0) {
{
size_t step = detail::__memcpy(d, s, n); size_t step = detail::__memcpy(d, s, n);
d -= step; s -= step; n -= step; d -= step; s -= step; n -= step;
} }
@@ -167,15 +158,12 @@ constexpr void* memmove_s(void* dst, size_t n0, const void* src, size_t n1)
constexpr void* memset(void* dst, int ch, size_t n) constexpr void* memset(void* dst, int ch, size_t n)
{ {
uint8_t* d = static_cast<uint8_t*>(dst); uint8_t* d = static_cast<uint8_t*>(dst);
uint8_t val8 = ch; uint8_t val[8] = { static_cast<uint8_t>(ch) };
uint16_t val16 = (static_cast<uint16_t>(val8) << 8) | static_cast<int16_t>(val8);
uint32_t val32 = (static_cast<uint32_t>(val16) << 16) | static_cast<int32_t>(val16);
uint64_t val64 = (static_cast<uint64_t>(val32) << 32) | static_cast<int64_t>(val32);
while (n >= 8) { detail::__memcpy_64(d, &val64); d += 8; n -= 8; } while (n > 0) {
while (n >= 4) { detail::__memcpy_32(d, &val32); d += 4; n -= 4; } size_t step = detail::__memcpy(d, val, n);
while (n >= 2) { detail::__memcpy_16(d, &val16); d += 2; n -= 2; } d += step; n -= step;
while (n >= 1) { *d++ = val8; --n; } }
return dst; return dst;
} }

View File

@@ -0,0 +1,22 @@
// =====================================================================================================================
// 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/>.
// =====================================================================================================================
void __assert_callback(const char*, const char*, int, const char*)
{
}

View File

@@ -20,17 +20,11 @@
using assert_handler = void (*)(const char *, const char *, int , const char *); using assert_handler = void (*)(const char *, const char *, int , const char *);
static assert_handler __priv_handler = nullptr; extern void __assert_callback(const char* expression, const char* file, int line, const char* function);
void set_assert_handler(assert_handler handler)
{
__priv_handler = handler;
}
void __assert_impl(const char* expression, const char* file, int line, const char* function) void __assert_impl(const char* expression, const char* file, int line, const char* function)
{ {
if (__priv_handler) __assert_callback(expression, file, line, function);
__priv_handler(expression, file, line, function);
abort(); abort();
} }

View File

@@ -42,7 +42,7 @@ Debug()
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -S ../.. -B . cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -S ../.. -B .
cmake --build . --target fennec-test cmake --build . --target fennec-test
cd ../../bin/debug/ cd ../../bin/debug/
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind.txt fennec-test valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind.txt ./fennec-test
cd ../.. cd ../..
} }
@@ -53,7 +53,7 @@ Release()
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -S ../.. -B . cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -S ../.. -B .
cmake --build . --target fennec-test cmake --build . --target fennec-test
cd ../../bin/release/ cd ../../bin/release/
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind.txt fennec-test valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind.txt ./fennec-test
cd ../.. cd ../..
} }
@@ -64,7 +64,7 @@ RelWithDebInfo()
cmake -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -S ../.. -B . cmake -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -S ../.. -B .
cmake --build . --target fennec-test cmake --build . --target fennec-test
cd ../../bin/relwithdebinfo/ cd ../../bin/relwithdebinfo/
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind.txt fennec-test valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind.txt ./fennec-test
cd ../.. cd ../..
} }
@@ -75,7 +75,7 @@ MinSizeRel()
cmake -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel -S ../.. -B . cmake -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel -S ../.. -B .
cmake --build . --target fennec-test cmake --build . --target fennec-test
cd ../../bin/minsizerel/ cd ../../bin/minsizerel/
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind.txt fennec-test valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind.txt ./fennec-test
cd ../.. cd ../..
} }