- Switched from Allman (BSD) to 1TBS (K&R)

Namespaces, Types, and Requires/Concepts still use Allman
This commit is contained in:
2025-07-08 12:07:44 -04:00
parent 2573de0904
commit 649e39c70e
32 changed files with 419048 additions and 877 deletions

View File

@@ -81,7 +81,7 @@ fennec Standards:
possible, prevent data loss, and get some debug information for it. fennec defines its own `assert` macro to 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 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 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 how to handle the impending crash. In Debug Mode there is nothing that can be done to stop the crash, as soon as the branch
finishes, `abort()` will be called. finishes, `abort()` will be called.

417774
conv/GLSLangSpec.4.60.pdf Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -104,17 +104,21 @@ struct array
/// ///
/// \brief /// \brief
friend constexpr bool_t operator==(const array& lhs, const array& rhs) friend constexpr bool_t operator==(const array& lhs, const array& rhs) {
{ return array::__compare(lhs, rhs, make_index_sequence<ElemV>{}); } return array::__compare(lhs, rhs, make_index_sequence<ElemV>{});
}
friend constexpr bool_t operator!=(const array& lhs, const array& rhs) friend constexpr bool_t operator!=(const array& lhs, const array& rhs) {
{ return not array::__compare(lhs, rhs, make_index_sequence<ElemV>{}); } return not array::__compare(lhs, rhs, make_index_sequence<ElemV>{});
}
/// @} /// @}
private: private:
template<size_t...i> template<size_t...i>
static bool __compare(const array& lhs, const array& rhs, index_sequence<i...>) { return ((lhs[i] == rhs[i]) && ...); } static bool __compare(const array& lhs, const array& rhs, index_sequence<i...>) {
return ((lhs[i] == rhs[i]) && ...);
}
}; };
} }

View File

@@ -50,20 +50,23 @@ public:
dynarray() : _alloc(8), _size(0) {} dynarray() : _alloc(8), _size(0) {}
/// ///
/// \breif Alloc Constructor, initalize empty allocation with allocator instance. /// \brief Alloc Constructor, initialize empty allocation with allocator instance.
/// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some data. /// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some data.
dynarray(const alloc_t& alloc) : _alloc(8, alloc), _size(0) {} dynarray(const alloc_t& alloc) : _alloc(8, alloc), _size(0) {}
/// ///
/// \brief Create an allocation with a size of `n` elements. All elements are initialized with the default constructor. /// \brief Sized Allocation, create an allocation with a size of `n` elements, initialized with the default constructor.
dynarray(size_t n) : _alloc(n), _size(n) dynarray(size_t n) : _alloc(n), _size(n)
{ {
element_t* addr = _alloc.data(); element_t* addr = _alloc.data();
for(; n > 0; --n, ++addr) { fennec::construct(addr); } for(; n > 0; --n, ++addr) { fennec::construct(addr); }
} }
dynarray(size_t n, const alloc_t& alloc) : _alloc(n, alloc), _size(n) ///
{ /// \brief
/// \param n
/// \param alloc
dynarray(size_t n, const alloc_t& alloc) : _alloc(n, alloc), _size(n) {
element_t* addr = _alloc.data(); element_t* addr = _alloc.data();
for(; n > 0; --n, ++addr) { fennec::construct(addr); } for(; n > 0; --n, ++addr) { fennec::construct(addr); }
} }
@@ -71,34 +74,40 @@ public:
/// ///
/// \brief Create an allocation of size `n`, with each element constructed using the copy constructor /// \brief Create an allocation of size `n`, with each element constructed using the copy constructor
/// \brief n the number of elements /// \brief n the number of elements
dynarray(size_t n, const TypeT& val) dynarray(size_t n, const TypeT& val) {
{
element_t* addr = _alloc.data(); element_t* addr = _alloc.data();
for(; n > 0; --n, ++addr) { fennec::construct(addr, val); } for(; n > 0; --n, ++addr) { fennec::construct(addr, val); }
} }
template<typename...ArgsT> template<typename...ArgsT>
dynarray(size_t n, ArgsT&&...args) dynarray(size_t n, ArgsT&&...args) {
{
element_t* addr = _alloc.data(); element_t* addr = _alloc.data();
for(; n > 0; --n, ++addr) { fennec::construct(addr, fennec::forward<ArgsT>(args)...); } for(; n > 0; --n, ++addr) { fennec::construct(addr, fennec::forward<ArgsT>(args)...); }
} }
~dynarray() ~dynarray() {
{
element_t* addr = _alloc.data(); element_t* addr = _alloc.data();
for(; n > 0; --n, ++addr) { fennec::destruct(addr); } for(; n > 0; --n, ++addr) { fennec::destruct(addr); }
} }
size_t size() const { return _size; } size_t size() const {
return _size;
}
size_t capacity() const { return _alloc.capacity(); } size_t capacity() const {
return _alloc.capacity();
}
TypeT& operator[](size_t i) { assertd(i < _size, "Array Out of Bounds"); return _alloc.data()[i]; } TypeT& operator[](size_t i) {
const TypeT& operator[](size_t i) const { assertd(i < _size, "Array Out of Bounds"); return _alloc.data()[i]; } assertd(i < _size, "Array Out of Bounds"); return _alloc.data()[i];
}
const TypeT& operator[](size_t i) const {
assertd(i < _size, "Array Out of Bounds"); return _alloc.data()[i];
}
void insert(size_t i, const TypeT& val) {
void insert(size_t i, const TypeT& val)
{
// Grow if the size has reached the capacity of the allocation // Grow if the size has reached the capacity of the allocation
if(_size == capacity()) _grow(); if(_size == capacity()) _grow();
@@ -114,8 +123,8 @@ public:
fennec::construct(_alloc.data() + i, val); fennec::construct(_alloc.data() + i, val);
} }
void insert(size_t i, TypeT&& val) void insert(size_t i, TypeT&& val) {
{
// Grow if the size has reached the capacity of the allocation // Grow if the size has reached the capacity of the allocation
if(_size == capacity()) _grow(); if(_size == capacity()) _grow();
@@ -132,8 +141,8 @@ public:
} }
template<typename...ArgsT> template<typename...ArgsT>
void emplace(size_t i, ArgsT&&...args) void emplace(size_t i, ArgsT&&...args) {
{
// Grow if the size has reached the capacity of the allocation // Grow if the size has reached the capacity of the allocation
if(_size == capacity()) _grow(); if(_size == capacity()) _grow();
@@ -149,10 +158,17 @@ public:
fennec::construct(_alloc.data() + i, fennec::forward<ArgsT>(args)...); fennec::construct(_alloc.data() + i, fennec::forward<ArgsT>(args)...);
} }
void push_back(const TypeT& val) { dynarray::insert(_size, val); } void push_back(const TypeT& val) {
void push_back(TypeT&& val) { dynarray::insert(_size, fennec::forward<TypeT>(val)); } dynarray::insert(_size, val);
}
template<typename...ArgsT> void emplace_back(ArgsT...args) { dynarray::emplace(_size, fennec::forward<ArgsT>(args)...); } void push_back(TypeT&& val) {
dynarray::insert(_size, fennec::forward<TypeT>(val));
}
template<typename...ArgsT> void emplace_back(ArgsT...args) {
dynarray::emplace(_size, fennec::forward<ArgsT>(args)...);
}
private: private:
void _grow() const { _alloc.reallocate(_alloc.capacity() * 2); } void _grow() const { _alloc.reallocate(_alloc.capacity() * 2); }

View File

@@ -18,13 +18,94 @@
#ifndef FENNEC_FPROC_FILESYSTEM_PATH_H #ifndef FENNEC_FPROC_FILESYSTEM_PATH_H
#define FENNEC_FPROC_FILESYSTEM_PATH_H #define FENNEC_FPROC_FILESYSTEM_PATH_H
#include <fennec/fproc/strings/string.h>
namespace fennec namespace fennec
{ {
struct path struct path
{ {
public:
using string_t = fennec::string;
///
/// \brief Helper function for getting the file separator for the current system
/// \returns A character containing the file separator
static constexpr char preferred_separator() {
#if defined(_WIN32) || defined(_WIN64)
return '\\';
#else
return '/';
#endif
}
///
/// \brief Default Constructor, initializes empty path
constexpr path()
: _str(), _file(0), _parent(0) {
}
///
/// \brief
/// \param str
constexpr path(const cstring& str)
: _str(str) {
_find_paths();
}
constexpr path(const string& str)
: _str(str) {
_find_paths();
}
constexpr path(string&& str)
: _str(fennec::forward<string_t>(str)) {
_find_paths();
}
constexpr path(const path& path)
: _str(path._str) {
_find_paths();
}
constexpr path(path&& path) noexcept
: _str(fennec::move(path._str)) {
_find_paths();
}
constexpr const string_t& string() const {
return _str;
}
constexpr path parent() const {
return _str.substring(0, _file);
}
constexpr path operator/(const cstring& file) const {
path res = _str + file;
return res;
}
constexpr path operator/(const string_t& file) const {
path res = _str + file;
return res;
}
constexpr path operator/(const path& file) const {
path res = _str + file._str;
return res;
}
private:
constexpr void _find_paths() {
_file = _str.rfind(preferred_separator());
_parent = _str.rfind(preferred_separator(), _file - 1);
}
string_t _str;
size_t _file
, _parent;
}; };
} }

View File

@@ -60,8 +60,8 @@ public:
/// ///
/// \brief Default Constructor, initializes with nullptr /// \brief Default Constructor, initializes with nullptr
constexpr cstring() constexpr cstring()
: _str(nullptr), _size(0), _const(true) : _str(nullptr), _size(0), _const(true) {
{ } }
/// ///
/// \brief Buffer Constructor, wraps the provided C-Style string /// \brief Buffer Constructor, wraps the provided C-Style string
@@ -70,8 +70,9 @@ public:
constexpr cstring(char* str, size_t n) constexpr cstring(char* str, size_t n)
: _str(str) : _str(str)
, _size(n - 1) , _size(n - 1)
, _const(false) , _const(false) {
{ assert(_str[n - 1] == '\0', "Invalid NTBS."); } assert(_str[n - 1] == '\0', "Invalid NTBS.");
}
/// ///
/// \brief Buffer Constructor, wraps the provided C-Style string /// \brief Buffer Constructor, wraps the provided C-Style string
@@ -81,8 +82,9 @@ public:
constexpr cstring(char(&str)[n]) constexpr cstring(char(&str)[n])
: _str(str) : _str(str)
, _size(n - 1) , _size(n - 1)
, _const(false) , _const(false) {
{ assert(_str[n - 1] == '\0', "Invalid NTBS."); } assert(_str[n - 1] == '\0', "Invalid NTBS.");
}
/// ///
/// \brief Const Buffer Constructor, wraps the provided C-Style string /// \brief Const Buffer Constructor, wraps the provided C-Style string
@@ -91,8 +93,9 @@ public:
constexpr cstring(const char* str, size_t n) constexpr cstring(const char* str, size_t n)
: _cstr(str) : _cstr(str)
, _size(n - 1) , _size(n - 1)
, _const(true) , _const(true) {
{ assert(_cstr[n - 1] == '\0', "Invalid NTBS."); } assert(_cstr[n - 1] == '\0', "Invalid NTBS.");
}
/// ///
/// \brief Buffer Constructor, wraps the provided C-Style string /// \brief Buffer Constructor, wraps the provided C-Style string
@@ -102,8 +105,9 @@ public:
constexpr cstring(const char(&str)[n]) constexpr cstring(const char(&str)[n])
: _cstr(str) : _cstr(str)
, _size(n - 1) , _size(n - 1)
, _const(true) , _const(true) {
{ assert(_cstr[n - 1] == '\0', "Invalid NTBS."); } assert(_cstr[n - 1] == '\0', "Invalid NTBS.");
}
/// ///
/// \brief Move Constructor /// \brief Move Constructor
@@ -111,8 +115,7 @@ public:
constexpr cstring(cstring&& str) noexcept constexpr cstring(cstring&& str) noexcept
: _cstr(str._cstr) : _cstr(str._cstr)
, _size(str._size) , _size(str._size)
, _const(str._const) , _const(str._const) {
{
str._cstr = nullptr; str._cstr = nullptr;
str._size = 0; str._size = 0;
str._const = true; str._const = true;
@@ -139,8 +142,7 @@ public:
} }
// TODO: Document // TODO: Document
constexpr cstring& operator=(cstring&& str) noexcept constexpr cstring& operator=(cstring&& str) noexcept {
{
_cstr = str._cstr; str._cstr = nullptr; _cstr = str._cstr; str._cstr = nullptr;
_size = str._size; str._size = 0; _size = str._size; str._size = 0;
_const = str._const; str._const = true; _const = str._const; str._const = true;
@@ -179,11 +181,15 @@ public:
/// ///
/// \brief Dereference Operator /// \brief Dereference Operator
/// \returns A const qualified pointer to the underlying allocation /// \returns A const qualified pointer to the underlying allocation
constexpr const char* operator*() const { return _cstr; } constexpr const char* operator*() const {
return _cstr;
}
/// ///
/// \brief Implicit Dereference Cast /// \brief Implicit Dereference Cast
constexpr operator const char*() const { return _cstr; } constexpr operator const char*() const {
return _cstr;
}
// Examination ========================================================================================================= // Examination =========================================================================================================
@@ -198,8 +204,7 @@ public:
/// \param ostr the string to compare against /// \param ostr the string to compare against
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the /// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
/// current locale, otherwise a positive value. /// current locale, otherwise a positive value.
constexpr int compare(const cstring& str, size_t i = 0) const constexpr int compare(const cstring& str, size_t i = 0) const {
{
if (i >= _size) return -1; if (i >= _size) return -1;
return ::strcoll(_cstr + i, str); return ::strcoll(_cstr + i, str);
} }
@@ -212,8 +217,7 @@ public:
/// \param c the character to find /// \param c the character to find
/// \param i the index to start at /// \param i the index to start at
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()` /// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
constexpr size_t find(char c, size_t i = 0) const constexpr size_t find(char c, size_t i = 0) const {
{
if (i >= _size) return _size; // bounds check if (i >= _size) return _size; // bounds check
const char* loc = ::strchr(_cstr + i, c); // get location using strchr const char* loc = ::strchr(_cstr + i, c); // get location using strchr
return loc ? loc - _cstr : _size; // return size if not found return loc ? loc - _cstr : _size; // return size if not found
@@ -224,8 +228,7 @@ public:
/// \param str the string to find /// \param str the string to find
/// \param i the index to start at /// \param i the index to start at
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()` /// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
constexpr size_t find(const cstring& str, size_t i = 0) const constexpr size_t find(const cstring& str, size_t i = 0) const {
{
if (i + str._size > _size) return _size; // bounds check if (i + str._size > _size) return _size; // bounds check
const char* loc = ::strstr(_cstr + i, str); // get location using strstr const char* loc = ::strstr(_cstr + i, str); // get location using strstr
return loc ? loc - _cstr : _size; // return size if not found return loc ? loc - _cstr : _size; // return size if not found
@@ -236,8 +239,7 @@ public:
/// \param c the string to find /// \param c the string to find
/// \param i the index to start at /// \param i the index to start at
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()` /// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
constexpr size_t rfind(char c, size_t i = 0) const constexpr size_t rfind(char c, size_t i = 0) const {
{
if (_size == 0) return _size; if (_size == 0) return _size;
i = min(i, _size - 1); // clamp i to bounds i = min(i, _size - 1); // clamp i to bounds
do { do {
@@ -251,8 +253,7 @@ public:
/// \param str the string to find /// \param str the string to find
/// \param i the index to start at /// \param i the index to start at
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()` /// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
constexpr size_t rfind(const cstring& str, size_t i = 0) const constexpr size_t rfind(const cstring& str, size_t i = 0) const {
{
const char first = str[0]; const char first = str[0];
i = min(i, _size - str._size); i = min(i, _size - str._size);
do { do {

View File

@@ -51,8 +51,8 @@ public:
/// ///
/// \brief Default Constructor, initializes empty string /// \brief Default Constructor, initializes empty string
constexpr _string() constexpr _string()
: _str() : _str() {
{ } }
/// ///
/// \brief Sized Constructor, initializes a null-terminated string of size `n` with null characters /// \brief Sized Constructor, initializes a null-terminated string of size `n` with null characters
@@ -60,8 +60,8 @@ public:
/// ///
/// \details adds additional character for null termination. /// \details adds additional character for null termination.
constexpr _string(size_t n) constexpr _string(size_t n)
: _string('\0', n) : _string('\0', n) {
{ } }
/// ///
/// \brief Sized Constructor, initializes a null-terminated string of size `n` filled with the character `c` /// \brief Sized Constructor, initializes a null-terminated string of size `n` filled with the character `c`
@@ -70,8 +70,9 @@ public:
/// ///
/// \details adds additional character for null termination. /// \details adds additional character for null termination.
constexpr _string(char c, size_t n) constexpr _string(char c, size_t n)
: _str(n + 1) : _str(n + 1) {
{ fennec::memset(_str, c, n); _str[n] = '\0'; } fennec::memset(_str, c, n); _str[n] = '\0';
}
/// ///
/// \brief Buffer Copy Constructor /// \brief Buffer Copy Constructor
@@ -81,19 +82,19 @@ public:
/// \details adds additional character for null termination. Ignores whether str is null-terminated. /// \details adds additional character for null termination. Ignores whether str is null-terminated.
/// This constructor makes the assumption that `len` is the intended number of characters. /// This constructor makes the assumption that `len` is the intended number of characters.
constexpr _string(const cstring& str) constexpr _string(const cstring& str)
: _str(str, str.size() + 1) : _str(str, str.size() + 1) {
{ _str[str.size()] = '\0'; } _str[str.size()] = '\0';
}
/// ///
/// \brief String Copy Constructor /// \brief String Copy Constructor
/// \param str the string to copy /// \param str the string to copy
constexpr _string(const string& str) constexpr _string(const string& str)
: _string(str, str.size() - 1) : _string(str, str.size() - 1) {
{ } }
constexpr _string(_string&& str) noexcept constexpr _string(_string&& str) noexcept
: _str(fennec::move(str._str)) : _str(fennec::move(str._str)) { }
{ }
/// ///
/// \brief String Destructor, cleans up the underlying allocation /// \brief String Destructor, cleans up the underlying allocation
@@ -103,7 +104,9 @@ public:
/// ///
/// \returns The size of the string excluding null terminator /// \returns The size of the string excluding null terminator
constexpr size_t size() const { return _str.capacity() - 1; } constexpr size_t size() const {
return _str.capacity() - 1;
}
// Access ============================================================================================================== // Access ==============================================================================================================
@@ -129,34 +132,38 @@ public:
/// ///
/// \brief Dereference Operator /// \brief Dereference Operator
/// \returns A const qualified pointer to the underlying allocation /// \returns A const qualified pointer to the underlying allocation
constexpr const char* operator*() const { return _str; } constexpr const char* operator*() const {
return _str;
}
/// ///
/// \brief Implicit Dereference Cast /// \brief Implicit Dereference Cast
constexpr operator const char*() const { return _str; } constexpr operator const char*() const {
return _str; }
// Examination ========================================================================================================= // Examination =========================================================================================================
/// ///
/// \returns The length of the string to the first null-terminator /// \returns The length of the string to the first null-terminator
constexpr size_t length() const constexpr size_t length() const {
{ return find('\0'); } return find('\0');
}
/// ///
/// \brief String Comparison /// \brief String Comparison
/// \param ostr the string to compare against /// \param ostr the string to compare against
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the /// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
/// current locale, otherwise a positive value. /// current locale, otherwise a positive value.
constexpr int compare(const string& ostr) const constexpr int compare(const string& ostr) const {
{ return ::strcoll(_str, ostr); } return ::strcoll(_str, ostr);
}
/// ///
/// \brief Finds the index of the first occurrence of `x` in the string /// \brief Finds the index of the first occurrence of `x` in the string
/// \param x the character to find /// \param x the character to find
/// \returns The index of `x` if it occurs in the string, otherwise returns `size()` /// \returns The index of `x` if it occurs in the string, otherwise returns `size()`
constexpr size_t find(char x) const constexpr size_t find(char x) const {
{
const char* loc = ::strchr(_str, x); const char* loc = ::strchr(_str, x);
return loc ? loc - _str : size(); return loc ? loc - _str : size();
} }
@@ -165,8 +172,7 @@ public:
/// \brief Finds the index of the first occurrence of `str` in the string. /// \brief Finds the index of the first occurrence of `str` in the string.
/// \param str the string to find /// \param str the string to find
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()` /// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
constexpr size_t find(const string& str) const constexpr size_t find(const string& str) const {
{
const char* loc = ::strstr(_str, str); const char* loc = ::strstr(_str, str);
return loc ? loc - _str : size(); return loc ? loc - _str : size();
} }
@@ -175,8 +181,7 @@ public:
/// \brief Finds the index of the first occurrence of `str` in the string. /// \brief Finds the index of the first occurrence of `str` in the string.
/// \param str the string to find /// \param str the string to find
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()` /// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
constexpr size_t find(const cstring& str) const constexpr size_t find(const cstring& str) const {
{
const char* loc = ::strstr(_str, str); const char* loc = ::strstr(_str, str);
return loc ? loc - _str : size(); return loc ? loc - _str : size();
} }
@@ -186,8 +191,7 @@ public:
/// \param c the string to find /// \param c the string to find
/// \param i the index to start at /// \param i the index to start at
/// \returns The index of `c` if it occurs in the string, otherwise returns `size()` /// \returns The index of `c` if it occurs in the string, otherwise returns `size()`
constexpr size_t rfind(char c, size_t i = 0) const constexpr size_t rfind(char c, size_t i = size()) const {
{
if (size() == 0) return size(); if (size() == 0) return size();
i = min(i, size() - 1); // clamp i to bounds i = min(i, size() - 1); // clamp i to bounds
do { do {
@@ -201,8 +205,7 @@ public:
/// \param str the string to find /// \param str the string to find
/// \param i the index to start at /// \param i the index to start at
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()` /// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
constexpr size_t rfind(const cstring& str, size_t i = 0) const constexpr size_t rfind(const cstring& str, size_t i = size()) const {
{
const char first = str[0]; const char first = str[0];
i = min(i, size() - str.size()); i = min(i, size() - str.size());
do { do {
@@ -217,8 +220,7 @@ public:
/// \param str the string to find /// \param str the string to find
/// \param i the index to start at /// \param i the index to start at
/// \returns The index of `str` if it occurs in the string, otherwise returns `size()` /// \returns The index of `str` if it occurs in the string, otherwise returns `size()`
constexpr size_t rfind(const string& str, size_t i = 0) const constexpr size_t rfind(const string& str, size_t i = size()) const {
{
const char first = str[0]; const char first = str[0];
i = min(i, size() - str.size()); i = min(i, size() - str.size());
do { do {
@@ -233,8 +235,7 @@ public:
/// ///
/// \brief Resize the string, filling additional bytes with `'\0'` /// \brief Resize the string, filling additional bytes with `'\0'`
/// \param n the new size of the string /// \param n the new size of the string
constexpr void resize(size_t n) constexpr void resize(size_t n) {
{
size_t i = size(); size_t i = size();
_str.reallocate(n + 1); _str.reallocate(n + 1);
if (n > i) fennec::memset(*_str + i, '\0', n - i); if (n > i) fennec::memset(*_str + i, '\0', n - i);
@@ -244,8 +245,7 @@ public:
/// \brief Copy Assignment Operator /// \brief Copy Assignment Operator
/// \param str the string to copy /// \param str the string to copy
/// \returns a reference to `this` /// \returns a reference to `this`
constexpr string& operator=(const string& str) constexpr string& operator=(const string& str) {
{
if (str.size() > size()) string::resize(str.size()); if (str.size() > size()) string::resize(str.size());
fennec::memcpy(_str, str, str.size()); fennec::memcpy(_str, str, str.size());
_str[str.size()] = '\0'; _str[str.size()] = '\0';
@@ -256,8 +256,7 @@ public:
/// \brief Move Assignment Operator /// \brief Move Assignment Operator
/// \param str the string to move /// \param str the string to move
/// \returns a reference to `this` /// \returns a reference to `this`
constexpr string& operator=(string&& str) noexcept constexpr string& operator=(string&& str) noexcept {
{
_str = fennec::move(str._str); _str = fennec::move(str._str);
return *this; return *this;
} }
@@ -267,8 +266,7 @@ public:
/// \param i the start index /// \param i the start index
/// \param n the number of characters /// \param n the number of characters
/// \return /// \return
constexpr string substring(size_t i, size_t n = size()) constexpr string substring(size_t i, size_t n = size()) const {
{
assert(i < size(), "Array Out of Bounds"); assert(i < size(), "Array Out of Bounds");
n = min(n, size() - i); n = min(n, size() - i);
return string(&_str[i], n); return string(&_str[i], n);
@@ -278,50 +276,44 @@ public:
/// \brief Returns a string with `c` appended to it /// \brief Returns a string with `c` appended to it
/// \param c /// \param c
/// \returns /// \returns
constexpr string operator+(char c) constexpr string operator+(char c) const {
{
// Copy contents with one additional byte. // Copy contents with one additional byte.
string res(_str, _str.size()); string res(_str, _str.size());
res[size()] = c; // Set the last character to c res[size()] = c; // Set the last character to c
return res; return res;
} }
constexpr string operator+(const string& str) constexpr string operator+(const cstring& str) const {
{
string res(size() + str.size()); // Make a new string with the size of this + str string res(size() + str.size()); // Make a new string with the size of this + str
fennec::memcpy(res, _str, size()); // Copy the contents of this fennec::memcpy(res, _str, size()); // Copy the contents of this
fennec::memcpy(&res[size()], str, str.size()); // Append the contents of str fennec::memcpy(&res[size()], str, str.size()); // Append the contents of str
return res; return res;
} }
constexpr string operator+(const cstring& str) constexpr string operator+(const string& str) const {
{
string res(size() + str.size()); // Make a new string with the size of this + str string res(size() + str.size()); // Make a new string with the size of this + str
fennec::memcpy(res, _str, size()); // Copy the contents of this fennec::memcpy(res, _str, size()); // Copy the contents of this
fennec::memcpy(&res[size()], str, str.size()); // Append the contents of str fennec::memcpy(&res[size()], str, str.size()); // Append the contents of str
return res; return res;
} }
constexpr string& operator+=(char c) constexpr string& operator+=(char c) {
{
size_t x = size(); size_t x = size();
resize(x + 1); resize(x + 1);
_str[x] = c; _str[x] = c;
return *this; return *this;
} }
constexpr string& operator+=(const string& str) constexpr string& operator+=(const cstring& str) {
{
size_t x = size(); size_t x = size();
string::resize(x + str.size()); resize(x + str.size());
fennec::memcpy(&_str[x], str, str.size()); fennec::memcpy(&_str[x], str, str.size());
return *this; return *this;
} }
constexpr string& operator+=(const cstring& str) constexpr string& operator+=(const string& str) {
{
size_t x = size(); size_t x = size();
resize(x + str.size()); string::resize(x + str.size());
fennec::memcpy(&_str[x], str, str.size()); fennec::memcpy(&_str[x], str, str.size());
return *this; return *this;
} }

View File

@@ -69,8 +69,9 @@ extern void __assert_impl(const char* expression, const char* file, int line, co
// flagged unlikely to optimize branch prediction // flagged unlikely to optimize branch prediction
#define assert(expression, description) \ #define assert(expression, description) \
if(not(expression)) [[unlikely]] \ if(not(expression)) [[unlikely]] { \
{ __assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description); } __assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description); \
}
#ifdef NDEBUG #ifdef NDEBUG
#define assertd(expression, description) (0) #define assertd(expression, description) (0)

View File

@@ -95,12 +95,10 @@ namespace fennec
/// \param from Value to bit cast /// \param from Value to bit cast
/// \returns A value containing a bitwise copy of the input /// \returns A value containing a bitwise copy of the input
template<typename ToT, typename FromT> requires(sizeof(ToT) == sizeof(FromT)) template<typename ToT, typename FromT> requires(sizeof(ToT) == sizeof(FromT))
constexpr ToT bit_cast(const FromT& from) constexpr ToT bit_cast(const FromT& from) {
{ if constexpr(FENNEC_HAS_BUILTIN_BIT_CAST) {
if constexpr(FENNEC_HAS_BUILTIN_BIT_CAST)
return FENNEC_BUILTIN_BIT_CAST(ToT, from); return FENNEC_BUILTIN_BIT_CAST(ToT, from);
else } else {
{
ToT to; ToT to;
fennec::memcpy(&to, &from, sizeof(ToT)); fennec::memcpy(&to, &from, sizeof(ToT));
return to; return to;
@@ -119,14 +117,15 @@ constexpr ToT bit_cast(const FromT& from)
/// \param mask the mask to and against arr /// \param mask the mask to and against arr
/// \param n the number of bytes /// \param n the number of bytes
/// \returns the pointer \f$arr\f$ /// \returns the pointer \f$arr\f$
constexpr void* bit_and(void* arr, const void* mask, size_t n) constexpr void* bit_and(void* arr, const void* mask, size_t n) {
{ if (arr == mask) {
if (arr == mask) return arr; return arr;
}
uint8_t* d = static_cast<uint8_t*>(arr); uint8_t* d = static_cast<uint8_t*>(arr);
const uint8_t* s = static_cast<const uint8_t*>(mask); const uint8_t* s = static_cast<const uint8_t*>(mask);
while (n > 0) while (n > 0) {
{
size_t step = detail::__bit_and(d, s, n); size_t step = detail::__bit_and(d, s, n);
d += step; s += step; n -= step; d += step; s += step; n -= step;
} }
@@ -143,8 +142,9 @@ constexpr void* bit_and(void* arr, const void* mask, size_t n)
/// \param mask the mask to and against arr /// \param mask the mask to and against arr
/// \param n1 the size of mask in bytes /// \param n1 the size of mask in bytes
/// \returns the pointer arr /// \returns the pointer arr
constexpr void* bit_and_s(void* arr, size_t n0, const void* mask, size_t n1) 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); } return bit_and(arr, mask, n0 < n1 ? n0 : n1);
}
@@ -158,12 +158,13 @@ constexpr void* bit_and_s(void* arr, size_t n0, const void* mask, size_t n1)
/// \param mask the mask to or against arr /// \param mask the mask to or against arr
/// \param n the number of bytes /// \param n the number of bytes
/// \returns the pointer arr /// \returns the pointer arr
constexpr void* bit_or(void* arr, const void* mask, size_t n) constexpr void* bit_or(void* arr, const void* mask, size_t n) {
{ if (arr == mask) {
if (arr == mask) return arr; return arr;
}
uint8_t* d = static_cast<uint8_t*>(arr); uint8_t* d = static_cast<uint8_t*>(arr);
const uint8_t* s = static_cast<const uint8_t*>(mask); const uint8_t* s = static_cast<const uint8_t*>(mask);
while (n > 0) while (n > 0)
{ {
size_t step = detail::__bit_or(d, s, n); size_t step = detail::__bit_or(d, s, n);
@@ -182,8 +183,9 @@ constexpr void* bit_or(void* arr, const void* mask, size_t n)
/// \param mask the mask to or against arr /// \param mask the mask to or against arr
/// \param n1 the size of mask in bytes /// \param n1 the size of mask in bytes
/// \returns the pointer arr /// \returns the pointer arr
constexpr void* bit_or_s(void* arr, size_t n0, const void* mask, size_t n1) 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); } return bit_or(arr, mask, n0 < n1 ? n0 : n1);
}
@@ -197,14 +199,14 @@ constexpr void* bit_or_s(void* arr, size_t n0, const void* mask, size_t n1)
/// \param mask the mask to or against arr /// \param mask the mask to or against arr
/// \param n the number of bytes /// \param n the number of bytes
/// \returns the pointer arr /// \returns the pointer arr
constexpr void* bit_xor(void* arr, const void* mask, size_t n) constexpr void* bit_xor(void* arr, const void* mask, size_t n) {
{ if (arr == mask) {
if (arr == mask) return arr; return arr;
}
uint8_t* d = static_cast<uint8_t*>(arr); uint8_t* d = static_cast<uint8_t*>(arr);
const uint8_t* s = static_cast<const uint8_t*>(mask); const uint8_t* s = static_cast<const uint8_t*>(mask);
while (n > 0) {
while (n > 0)
{
size_t step = detail::__bit_xor(d, s, n); size_t step = detail::__bit_xor(d, s, n);
d += step; s += step; n -= step; d += step; s += step; n -= step;
} }
@@ -221,8 +223,9 @@ constexpr void* bit_xor(void* arr, const void* mask, size_t n)
/// \param mask the mask to or against arr /// \param mask the mask to or against arr
/// \param n1 the size of mask in bytes /// \param n1 the size of mask in bytes
/// \returns the pointer arr /// \returns the pointer arr
constexpr void* bit_xor_s(void* arr, size_t n0, const void* mask, size_t n1) 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); } return bit_xor(arr, mask, n0 < n1 ? n0 : n1);
}
} }

View File

@@ -92,14 +92,12 @@ using conditional_t
// specialization of fennec::conditional for `true` case // specialization of fennec::conditional for `true` case
template<typename T, typename F> template<typename T, typename F>
struct conditional<true, T, F> struct conditional<true, T, F> : type_transform<T>{};
: type_transform<T>{};
// specialization of fennec::conditional for `false` case // specialization of fennec::conditional for `false` case
template<typename T, typename F> template<typename T, typename F>
struct conditional<false, T, F> struct conditional<false, T, F> : type_transform<F>{};
: type_transform<F>{};
// fennec::detect ====================================================================================================== // fennec::detect ======================================================================================================
@@ -122,8 +120,7 @@ struct detect
/// ///
/// \brief Shorthand for ```typename detect<DefaultT, DetectT, ArgsT...>::type``` /// \brief Shorthand for ```typename detect<DefaultT, DetectT, ArgsT...>::type```
template<typename DefaultT, template<typename...> typename DetectT, typename...ArgsT> template<typename DefaultT, template<typename...> typename DetectT, typename...ArgsT>
using detect_t using detect_t = typename detect<DefaultT, DetectT, ArgsT...>::type;
= typename detect<DefaultT, DetectT, ArgsT...>::type;
// true case // true case
@@ -133,7 +130,6 @@ struct detect<DefaultT, DetectT, ArgsT...>
{ {
using type = DetectT<ArgsT...>; using type = DetectT<ArgsT...>;
static constexpr bool is_detected = true; static constexpr bool is_detected = true;
}; };

View File

@@ -28,26 +28,28 @@ namespace detail
{ {
// helper for bitwise and for 1 byte // helper for bitwise and for 1 byte
constexpr size_t __bit_and_8(void* dst, const void* src) 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; } *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 // helper for bitwise and 2 bytes at once
constexpr size_t __bit_and_16(void* dst, const void* src) 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; } *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 // helper for bitwise and 4 bytes at once
constexpr size_t __bit_and_32(void* dst, const void* src) 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; } *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 // helper for bitwise and 8 bytes at once
constexpr size_t __bit_and_64(void* dst, const void* src) 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; } *static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) & *static_cast<const uint64_t*>(src); return 8;
}
// helper for selecting size // helper for selecting size
constexpr size_t __bit_and(void* dst, const void* src, size_t n) constexpr size_t __bit_and(void* dst, const void* src, size_t n) {
{ switch (n) {
switch (n)
{
case 0: case 0:
return 0; return 0;
case 1: case 1:
@@ -63,26 +65,28 @@ constexpr size_t __bit_and(void* dst, const void* src, size_t n)
// helper for bitwise or for 1 byte // helper for bitwise or for 1 byte
constexpr size_t __bit_or_8(void* dst, const void* src) 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; } *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 // helper for bitwise or 2 bytes at once
constexpr size_t __bit_or_16(void* dst, const void* src) 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; } *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 // helper for bitwise or 4 bytes at once
constexpr size_t __bit_or_32(void* dst, const void* src) 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; } *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 // helper for bitwise or 8 bytes at once
constexpr size_t __bit_or_64(void* dst, const void* src) 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; } *static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) | *static_cast<const uint64_t*>(src); return 8;
}
// helper for selecting size // helper for selecting size
constexpr size_t __bit_or(void* dst, const void* src, size_t n) constexpr size_t __bit_or(void* dst, const void* src, size_t n) {
{ switch (n) {
switch (n)
{
case 0: case 0:
return 0; return 0;
case 1: case 1:
@@ -98,26 +102,28 @@ constexpr size_t __bit_or(void* dst, const void* src, size_t n)
// helper for bitwise and 1 byte // helper for bitwise and 1 byte
constexpr size_t __bit_xor_8(void* dst, const void* src) 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; } *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 // helper for bitwise xor 2 bytes at once
constexpr size_t __bit_xor_16(void* dst, const void* src) 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; } *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 // helper for bitwise xor 4 bytes at once
constexpr size_t __bit_xor_32(void* dst, const void* src) 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; } *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 // helper for bitwise xor 8 bytes at once
constexpr size_t __bit_xor_64(void* dst, const void* src) 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; } *static_cast<uint64_t*>(dst) = *static_cast<uint64_t*>(dst) ^ *static_cast<const uint64_t*>(src); return 8;
}
// helper for selecting size // helper for selecting size
constexpr size_t __bit_xor(void* dst, const void* src, size_t n) constexpr size_t __bit_xor(void* dst, const void* src, size_t n) {
{ switch (n) {
switch (n)
{
case 0: case 0:
return 0; return 0;
case 1: case 1:

View File

@@ -103,7 +103,9 @@ template<typename ValueT, ValueT...Values> struct sequence
/// \brief returns the number of elements /// \brief returns the number of elements
/// ///
/// \return number of elements in the array /// \return number of elements in the array
inline static constexpr size_t size() noexcept { return sizeof...(Values); } inline static constexpr size_t size() noexcept {
return sizeof...(Values);
}
}; };
@@ -129,7 +131,9 @@ struct integer_sequence : sequence<IntT, Values...>
/// \brief returns the number of elements /// \brief returns the number of elements
/// ///
/// \return number of elements in the array /// \return number of elements in the array
inline static constexpr size_t size() noexcept { return sizeof...(Values); } inline static constexpr size_t size() noexcept {
return sizeof...(Values);
}
}; };
@@ -166,7 +170,9 @@ template<size_t...Indices> struct index_sequence : integer_sequence<size_t, Indi
/// \brief returns the number of elements /// \brief returns the number of elements
/// ///
/// \return number of elements in the array /// \return number of elements in the array
inline static constexpr size_t size() noexcept { return sizeof...(Indices); } inline static constexpr size_t size() noexcept {
return sizeof...(Indices);
}
}; };

View File

@@ -125,8 +125,7 @@ template<typename T> struct is_void
/// ///
/// \brief shorthand for ```is_void<T>::value``` /// \brief shorthand for ```is_void<T>::value```
/// \tparam T type to check /// \tparam T type to check
template<typename T> constexpr bool_t is_void_v template<typename T> constexpr bool_t is_void_v = is_void<T>::value;
= is_void<T>::value;
@@ -143,8 +142,7 @@ template<typename T> struct is_bool
/// ///
/// \brief shorthand for ```is_bool<T>::value``` /// \brief shorthand for ```is_bool<T>::value```
/// \tparam T type to check /// \tparam T type to check
template<typename T> constexpr bool_t is_bool_v template<typename T> constexpr bool_t is_bool_v = is_bool<T>::value;
= is_bool<T>::value;
@@ -161,8 +159,7 @@ template<typename T> struct is_null_pointer
/// ///
/// \brief shorthand for ```is_null_pointer<T>::value``` /// \brief shorthand for ```is_null_pointer<T>::value```
/// \tparam T type to check /// \tparam T type to check
template<typename T> constexpr bool_t is_null_pointer_v template<typename T> constexpr bool_t is_null_pointer_v = is_null_pointer<T>::value;
= is_null_pointer<T>::value;
@@ -197,8 +194,7 @@ template<typename T> struct is_array<T[]>
/// ///
/// \brief shorthand for ```is_array<T>::value``` /// \brief shorthand for ```is_array<T>::value```
/// \tparam T type to check /// \tparam T type to check
template<typename T> constexpr bool_t is_array_v template<typename T> constexpr bool_t is_array_v = is_array<T>::value;
= is_array<T>::value;
// fennec::is_class ==================================================================================================== // fennec::is_class ====================================================================================================
@@ -211,8 +207,7 @@ template<typename T> struct is_class
/// ///
/// \brief check if \p T is a class /// \brief check if \p T is a class
/// \tparam T type to check /// \tparam T type to check
template<typename T> constexpr size_t is_class_v template<typename T> constexpr size_t is_class_v = is_class<T>::value;
= is_class<T>::value;
@@ -229,8 +224,7 @@ template<typename T> struct is_integral
/// ///
/// \brief shorthand for ```is_integral<T>::value``` /// \brief shorthand for ```is_integral<T>::value```
/// \tparam T type to check /// \tparam T type to check
template<typename T> constexpr bool_t is_integral_v template<typename T> constexpr bool_t is_integral_v = is_integral<T>::value;
= is_integral<T>::value;
/// ///
@@ -244,8 +238,7 @@ template<typename T> struct is_signed
/// ///
/// \brief shorthand for ```is_signed<T>::value``` /// \brief shorthand for ```is_signed<T>::value```
/// \tparam T type to check /// \tparam T type to check
template<typename T> constexpr bool_t is_signed_v template<typename T> constexpr bool_t is_signed_v = is_signed<T>::value;
= is_signed<T>::value;
/// ///
@@ -259,8 +252,7 @@ template<typename T> struct is_unsigned
/// ///
/// \brief shorthand for ```is_unsigned<T>::value``` /// \brief shorthand for ```is_unsigned<T>::value```
/// \tparam T type to check /// \tparam T type to check
template<typename T> constexpr bool_t is_unsigned_v template<typename T> constexpr bool_t is_unsigned_v = is_unsigned<T>::value;
= is_unsigned<T>::value;
@@ -277,8 +269,7 @@ template<typename T> struct is_floating_point
/// ///
/// \brief shorthand for ```is_floating_point<T>::value``` /// \brief shorthand for ```is_floating_point<T>::value```
/// \tparam T type to check /// \tparam T type to check
template<typename T> constexpr bool_t is_floating_point_v template<typename T> constexpr bool_t is_floating_point_v = is_floating_point<T> {};
= is_floating_point<T> {};
@@ -295,8 +286,7 @@ template<typename T> struct is_arithmetic
/// ///
/// \brief shorthand for ```is_arithmetic<T>::value``` /// \brief shorthand for ```is_arithmetic<T>::value```
/// \tparam T type to check /// \tparam T type to check
template<typename T> constexpr bool_t is_arithmetic_v template<typename T> constexpr bool_t is_arithmetic_v = is_arithmetic<T>::value;
= is_arithmetic<T>::value;
// fennec::is_same ===================================================================================================== // fennec::is_same =====================================================================================================
@@ -306,18 +296,15 @@ template<typename T> constexpr bool_t is_arithmetic_v
/// \details Checks if `T0` and `T1` are identical and store it in `is_same::value` /// \details Checks if `T0` and `T1` are identical and store it in `is_same::value`
/// \tparam T0 first type to check /// \tparam T0 first type to check
/// \tparam T1 second type to check /// \tparam T1 second type to check
template<typename T0, typename T1> struct is_same template<typename T0, typename T1> struct is_same : false_type {};
: false_type {};
// true case // true case
template<typename T> struct is_same<T, T> template<typename T> struct is_same<T, T> : true_type {};
: true_type {};
/// ///
/// \brief shorthand for ```is_same<T0, T1>::value``` /// \brief shorthand for ```is_same<T0, T1>::value```
/// \tparam T type to check /// \tparam T type to check
template<typename T0, typename T1> constexpr bool_t is_same_v template<typename T0, typename T1> constexpr bool_t is_same_v = is_same<T0, T1> {};
= is_same<T0, T1> {};
// fennec::can_convert ================================================================================================= // fennec::can_convert =================================================================================================
@@ -334,8 +321,7 @@ template<typename FromT, typename ToT> struct is_convertible
/// \brief shorthand for `can_convert<TypeT0, TypeT1>::value` /// \brief shorthand for `can_convert<TypeT0, TypeT1>::value`
/// \param FromT First type /// \param FromT First type
/// \param ToT Second type /// \param ToT Second type
template<typename FromT, typename ToT> constexpr bool_t is_convertible_v template<typename FromT, typename ToT> constexpr bool_t is_convertible_v = is_convertible<FromT, ToT>{};
= is_convertible<FromT, ToT>{};
// fennec::is_constructible =============================================================================================== // fennec::is_constructible ===============================================================================================
@@ -350,8 +336,7 @@ template<typename ClassT, typename...ArgsT> struct is_constructible
/// ///
/// \brief Shorthand for `is_constructible<ClassT, ArgsT...>::value` /// \brief Shorthand for `is_constructible<ClassT, ArgsT...>::value`
template<typename ClassT, typename...ArgsT> constexpr bool_t is_constructible_v template<typename ClassT, typename...ArgsT> constexpr bool_t is_constructible_v = is_constructible<ClassT, ArgsT...>{};
= is_constructible<ClassT, ArgsT...>{};
// fennec:: // fennec::

View File

@@ -71,10 +71,14 @@ namespace fennec
/// \tparam T base type of the object /// \tparam T base type of the object
/// \param x reference to the object /// \param x reference to the object
/// \returns /// \returns
template<typename T> constexpr T&& forward(remove_reference_t<T>& x) noexcept { return static_cast<T&&>(x); } template<typename T> constexpr T&& forward(remove_reference_t<T>& x) noexcept {
return static_cast<T&&>(x);
}
// specialization for T&& // specialization for T&&
template<typename T> constexpr T&& forward(remove_reference_t<T>&& x) noexcept { return static_cast<T&&>(x); } template<typename T> constexpr T&& forward(remove_reference_t<T>&& x) noexcept {
return static_cast<T&&>(x);
}
/// ///
@@ -84,7 +88,9 @@ template<typename T> constexpr T&& forward(remove_reference_t<T>&& x) noexcept {
/// \tparam T base type of the object /// \tparam T base type of the object
/// \param x object to be moved /// \param x object to be moved
/// \returns `static_cast<remove_reference_t<T>&&>(x)` /// \returns `static_cast<remove_reference_t<T>&&>(x)`
template<typename T> constexpr remove_reference_t<T>&& move(T&& x) noexcept { return static_cast<remove_reference_t<T>&&>(x); } template<typename T> constexpr remove_reference_t<T>&& move(T&& x) noexcept {
return static_cast<remove_reference_t<T>&&>(x);
}
/// ///
@@ -94,7 +100,9 @@ template<typename T> constexpr remove_reference_t<T>&& move(T&& x) noexcept { re
/// \tparam T base type of the object /// \tparam T base type of the object
/// \param x object to be copied /// \param x object to be copied
/// \returns const r-value /// \returns const r-value
template<typename T> constexpr const remove_reference_t<T>& copy(T&& x) noexcept { return x; } template<typename T> constexpr const remove_reference_t<T>& copy(T&& x) noexcept {
return x;
}
} }

View File

@@ -301,15 +301,17 @@ namespace fennec
/// ///
/// \param x input value /// \param x input value
template<typename genType> template<typename genType>
constexpr genType sign(genType x) constexpr genType sign(genType x) {
{ return (x < genType(0) ? genType(-1) : genType(1)) * static_cast<genType>(x != 0); } // reduces to cmove return (x < genType(0) ? genType(-1) : genType(1)) * static_cast<genType>(x != 0); // reduces to cmove
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> sign(const vector<genType, i...>& x) constexpr vector<genType, i...> sign(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::sign(x[i]) ...); } return vector<genType, i...>(fennec::sign(x[i]) ...);
}
// Absolute Value ====================================================================================================== // Absolute Value ======================================================================================================
@@ -323,15 +325,17 @@ constexpr vector<genType, i...> sign(const vector<genType, i...>& x)
/// ///
/// \param x input value /// \param x input value
template<typename genType> template<typename genType>
constexpr genType abs(genType x) constexpr genType abs(genType x) {
{ return x * fennec::sign(x); } return x * fennec::sign(x);
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> abs(const vector<genType, i...>& x) constexpr vector<genType, i...> abs(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::abs(x[i]) ...); } return vector<genType, i...>(fennec::abs(x[i]) ...);
}
/// @} /// @}
@@ -355,15 +359,17 @@ constexpr vector<genType, i...> abs(const vector<genType, i...>& x)
/// ///
/// \param x input value /// \param x input value
template<typename genType> template<typename genType>
constexpr genType floor(genType x) constexpr genType floor(genType x) {
{ return ::floor(x); } return ::floor(x);
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> floor(const vector<genType, i...>& x) constexpr vector<genType, i...> floor(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::floor(x[i]) ...); } return vector<genType, i...>(fennec::floor(x[i]) ...);
}
@@ -378,15 +384,17 @@ constexpr vector<genType, i...> floor(const vector<genType, i...>& x)
/// ///
/// \param x input value /// \param x input value
template<typename genType> template<typename genType>
constexpr genType ceil(genType x) constexpr genType ceil(genType x) {
{ return ::ceil(x); } return ::ceil(x);
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> ceil(const vector<genType, i...>& x) constexpr vector<genType, i...> ceil(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::ceil(x[i]) ...); } return vector<genType, i...>(fennec::ceil(x[i]) ...);
}
@@ -401,15 +409,17 @@ constexpr vector<genType, i...> ceil(const vector<genType, i...>& x)
/// \f$\text{round}(x) = \text{sgn}(x) \cdot \lfloor \left| x \right| + 0.5 \rfloor\f$<br> <br> /// \f$\text{round}(x) = \text{sgn}(x) \cdot \lfloor \left| x \right| + 0.5 \rfloor\f$<br> <br>
/// ///
/// \param x input value /// \param x input value
template<typename genType> constexpr genType round(genType x) template<typename genType> constexpr genType round(genType x) {
{ return ::round(x); } return ::round(x);
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> round(const vector<genType, i...>& x) constexpr vector<genType, i...> round(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::round(x[i]) ...); } return vector<genType, i...>(fennec::round(x[i]) ...);
}
@@ -424,15 +434,17 @@ constexpr vector<genType, i...> round(const vector<genType, i...>& x)
/// ///
/// \param x input value /// \param x input value
template<typename genType> template<typename genType>
constexpr genType trunc(genType x) constexpr genType trunc(genType x) {
{ return ::trunc(x); } return ::trunc(x);
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> trunc(const vector<genType, i...>& x) constexpr vector<genType, i...> trunc(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::trunc(x[i]) ...); } return vector<genType, i...>(fennec::trunc(x[i]) ...);
}
@@ -449,17 +461,7 @@ constexpr vector<genType, i...> trunc(const vector<genType, i...>& x)
/// ///
/// \param x input value /// \param x input value
template<typename genType> template<typename genType>
constexpr genType roundEven(genType x) constexpr genType roundEven(genType x) {
{
//const genType e = numeric_limits<genType>::epsilon();
//genType f = x - fennec::floor(x);
//if (fennec::abs(f - genType(0.5)) > e)
// return fennec::round(x);
//
//genType i = fennec::floor(x);
//genType r = i / 2;
//bool up = r - fennec::floor(r) > e;
//return i + static_cast<genType>(up);
static const genType e = std::numeric_limits<genType>::epsilon(); static const genType e = std::numeric_limits<genType>::epsilon();
int I = static_cast<int>(x); int I = static_cast<int>(x);
genType i = static_cast<genType>(I); genType i = static_cast<genType>(I);
@@ -469,13 +471,25 @@ constexpr genType roundEven(genType x)
bool dir = (I % 2); bool dir = (I % 2);
return dir ? i + 1 : i; return dir ? i + 1 : i;
// Older version that generates significantly more branching and asm instructions
//const genType e = numeric_limits<genType>::epsilon();
//genType f = x - fennec::floor(x);
//if (fennec::abs(f - genType(0.5)) > e)
// return fennec::round(x);
//
//genType i = fennec::floor(x);
//genType r = i / 2;
//bool up = r - fennec::floor(r) > e; // This will cause a branch in most circumstances
//return i + static_cast<genType>(up);
} }
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> roundEven(const vector<genType, i...>& x) constexpr vector<genType, i...> roundEven(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::roundEven(x[i]) ...); } return vector<genType, i...>(fennec::roundEven(x[i]) ...);
}
/// @} /// @}
@@ -498,16 +512,17 @@ constexpr vector<genType, i...> roundEven(const vector<genType, i...>& x)
/// ///
/// \param x input value /// \param x input value
template<typename genType> template<typename genType>
constexpr genType fract(genType x) constexpr genType fract(genType x) {
{ return x - ::floor(x); } return x - ::floor(x);
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> fract(const vector<genType, i...>& x) constexpr vector<genType, i...> fract(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::fract(x[i]) ...); } return vector<genType, i...>(fennec::fract(x[i]) ...);
}
// Mod ================================================================================================================= // Mod =================================================================================================================
@@ -522,20 +537,22 @@ constexpr vector<genType, i...> fract(const vector<genType, i...>& x)
/// \param x dividend /// \param x dividend
/// \param y divisor /// \param y divisor
template<typename genType> template<typename genType>
constexpr genType mod(genType x, genType y) constexpr genType mod(genType x, genType y) {
{ return x - y * fennec::floor(x / y); } return x - y * fennec::floor(x / y);
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> mod(const vector<genType, i...>& x, genType y) constexpr vector<genType, i...> mod(const vector<genType, i...>& x, genType y) {
{ return x - y * fennec::floor(x / y); } return x - y * fennec::floor(x / y);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> mod(const vector<genType, i...>& x, const vector<genType, i...>& y) constexpr vector<genType, i...> mod(const vector<genType, i...>& x, const vector<genType, i...>& y) {
{ return x - y * fennec::floor(x / y); } return x - y * fennec::floor(x / y);
}
// ModF ================================================================================================================ // ModF ================================================================================================================
@@ -550,16 +567,17 @@ constexpr vector<genType, i...> mod(const vector<genType, i...>& x, const vector
/// \param x input value /// \param x input value
/// \param i integral out /// \param i integral out
template<typename genType> template<typename genType>
constexpr genType modf(genType x, genType& i) constexpr genType modf(genType x, genType& i) {
{ i = fennec::floor(x); return fennec::fract(x); } i = fennec::floor(x); return fennec::fract(x);
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> modf(const vector<genType, i...>& x, vector<genType, i...>& I) constexpr vector<genType, i...> modf(const vector<genType, i...>& x, vector<genType, i...>& I) {
{ I = fennec::floor(x); return fennec::fract(x); } I = fennec::floor(x); return fennec::fract(x);
}
// Is NaN ============================================================================================================== // Is NaN ==============================================================================================================
@@ -578,16 +596,17 @@ constexpr vector<genType, i...> modf(const vector<genType, i...>& x, vector<genT
/// ///
/// \param x input value /// \param x input value
template<typename genType, typename genBType = bool_t> requires(is_bool_v<genBType>) template<typename genType, typename genBType = bool_t> requires(is_bool_v<genBType>)
constexpr genBType isnan(genType x) constexpr genBType isnan(genType x) {
{ return ::isnanf(x); } return ::isnanf(x);
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, typename genBType = bool_t, size_t...i> requires(is_bool_v<genBType>) template<typename genType, typename genBType = bool_t, size_t...i> requires(is_bool_v<genBType>)
constexpr vector<genBType, i...> isnan(const vector<genType, i...>& x) constexpr vector<genBType, i...> isnan(const vector<genType, i...>& x) {
{ return vector<genBType, i...>(fennec::isnan(x[i]) ...); } return vector<genBType, i...>(fennec::isnan(x[i]) ...);
}
// Is Inf ============================================================================================================== // Is Inf ==============================================================================================================
@@ -601,15 +620,17 @@ constexpr vector<genBType, i...> isnan(const vector<genType, i...>& x)
/// ///
/// \param x input value /// \param x input value
template<typename genType, typename genBType = bool_t> requires(is_bool_v<genBType>) template<typename genType, typename genBType = bool_t> requires(is_bool_v<genBType>)
constexpr genBType isinf(genType x) constexpr genBType isinf(genType x) {
{ return ::isinff(x); } return ::isinff(x);
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, typename genBType = bool_t, size_t...i> requires(is_bool_v<genBType>) template<typename genType, typename genBType = bool_t, size_t...i> requires(is_bool_v<genBType>)
constexpr vector<genBType, i...> isinf(const vector<genType, i...>& x) constexpr vector<genBType, i...> isinf(const vector<genType, i...>& x) {
{ return vector<genBType, i...>(fennec::isinf(x[i]) ...); } return vector<genBType, i...>(fennec::isinf(x[i]) ...);
}
@@ -618,8 +639,10 @@ constexpr vector<genBType, i...> isinf(const vector<genType, i...>& x)
/// ///
/// \copydetails fennec::floatBitsToUint(fennec::genFType) /// \copydetails fennec::floatBitsToUint(fennec::genFType)
template<typename genType, typename genIType = int_t> requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and sizeof(genType) == sizeof(genIType)) template<typename genType, typename genIType = int_t> requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and sizeof(genType) == sizeof(genIType))
constexpr genIType floatBitsToInt(genType x) constexpr genIType floatBitsToInt(genType x) {
{ return fennec::bit_cast<genIType>(x); } return fennec::bit_cast<genIType>(x);
}
/// ///
/// \brief Returns a signed or unsigned integer value representing the encoding of a floating-point value. /// \brief Returns a signed or unsigned integer value representing the encoding of a floating-point value.
@@ -638,14 +661,17 @@ constexpr genIType floatBitsToInt(genType x)
/// ///
/// \param x value to convert /// \param x value to convert
template<typename genType, typename genUType = uint_t> requires(is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and sizeof(genType) == sizeof(genUType)) template<typename genType, typename genUType = uint_t> requires(is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and sizeof(genType) == sizeof(genUType))
constexpr genUType floatBitsToUint(genType x) constexpr genUType floatBitsToUint(genType x) {
{ return fennec::bit_cast<genUType>(x); } return fennec::bit_cast<genUType>(x);
}
/// ///
/// \copydetails fennec::uintBitsToFloat(fennec::genUType) /// \copydetails fennec::uintBitsToFloat(fennec::genUType)
template<typename genType = float_t, typename genIType = int_t> requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and sizeof(genType) == sizeof(genIType)) template<typename genType = float_t, typename genIType = int_t> requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and sizeof(genType) == sizeof(genIType))
constexpr genType intBitsToFloat(genIType x) constexpr genType intBitsToFloat(genIType x) {
{ return fennec::bit_cast<genType>(x); } return fennec::bit_cast<genType>(x);
}
/// ///
@@ -663,27 +689,32 @@ constexpr genType intBitsToFloat(genIType x)
/// ///
/// \param x value to convert /// \param x value to convert
template<typename genType = float_t, typename genUType = uint_t> requires(is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and sizeof(genType) == sizeof(genUType)) template<typename genType = float_t, typename genUType = uint_t> requires(is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and sizeof(genType) == sizeof(genUType))
constexpr genType uintBitsToFloat(genUType x) constexpr genType uintBitsToFloat(genUType x) {
{ return fennec::bit_cast<genType>(x); } return fennec::bit_cast<genType>(x);
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType = float_t, typename genIType = int_t, size_t...i> requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and sizeof(genType) == sizeof(genIType)) template<typename genType = float_t, typename genIType = int_t, size_t...i> requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and sizeof(genType) == sizeof(genIType))
constexpr vector<genIType, i...> floatBitsToInt(const vector<genType, i...>& x) constexpr vector<genIType, i...> floatBitsToInt(const vector<genType, i...>& x) {
{ return vector<genIType, i...>(fennec::bit_cast<genIType>(x[i])...); } return vector<genIType, i...>(fennec::bit_cast<genIType>(x[i])...);
}
template<typename genType = float_t, typename genUType = uint_t, size_t...i> requires(is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and sizeof(genType) == sizeof(genUType)) template<typename genType = float_t, typename genUType = uint_t, size_t...i> requires(is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and sizeof(genType) == sizeof(genUType))
constexpr vector<genUType, i...> floatBitsToUint(const vector<genType, i...>& x) constexpr vector<genUType, i...> floatBitsToUint(const vector<genType, i...>& x) {
{ return vector<genUType, i...>(fennec::bit_cast<genUType>(x[i])...); } return vector<genUType, i...>(fennec::bit_cast<genUType>(x[i])...);
}
template<typename genType = float_t, typename genIType = int_t, size_t...i> requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and sizeof(genType) == sizeof(genIType)) template<typename genType = float_t, typename genIType = int_t, size_t...i> requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and sizeof(genType) == sizeof(genIType))
constexpr vector<genType, i...> intBitsToFloat(const vector<genIType, i...>& x) constexpr vector<genType, i...> intBitsToFloat(const vector<genIType, i...>& x) {
{ return vector<genType, i...>(fennec::bit_cast<genType>(x[i]) ...); } return vector<genType, i...>(fennec::bit_cast<genType>(x[i]) ...);
}
template<typename genType = float_t, typename genUType = uint_t, size_t...i> requires(is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and sizeof(genType) == sizeof(genUType)) template<typename genType = float_t, typename genUType = uint_t, size_t...i> requires(is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and sizeof(genType) == sizeof(genUType))
constexpr vector<genType, i...> uintBitsToFloat(const vector<genUType, i...>& x) constexpr vector<genType, i...> uintBitsToFloat(const vector<genUType, i...>& x) {
{ return vector<genType, i...>(fennec::bit_cast<genType>(x[i]) ...); } return vector<genType, i...>(fennec::bit_cast<genType>(x[i]) ...);
}
@@ -700,15 +731,17 @@ constexpr vector<genType, i...> uintBitsToFloat(const vector<genUType, i...>& x)
/// \param b the multiplier /// \param b the multiplier
/// \param c the addend /// \param c the addend
template<typename genType> template<typename genType>
constexpr genType fma(genType a, genType b, genType c) constexpr genType fma(genType a, genType b, genType c) {
{ return genType(::fma(a, b, c)); } return genType(::fma(a, b, c));
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> fma(const vector<genType, i...>& a, const vector<genType, i...>& b, const vector<genType, i...>& c) constexpr vector<genType, i...> fma(const vector<genType, i...>& a, const vector<genType, i...>& b, const vector<genType, i...>& c) {
{ return vector<genType, i...>(fennec::fma(a[i], b[i], c[i]) ...); } return vector<genType, i...>(fennec::fma(a[i], b[i], c[i]) ...);
}
@@ -729,15 +762,17 @@ constexpr vector<genType, i...> fma(const vector<genType, i...>& a, const vector
/// \param x The floating-point value to split /// \param x The floating-point value to split
/// \param exp The variable to store the exponent in /// \param exp The variable to store the exponent in
template<typename genType, typename genIType = int_t> requires(is_integral_v<genIType>) template<typename genType, typename genIType = int_t> requires(is_integral_v<genIType>)
constexpr genType frexp(genType x, genIType& exp) constexpr genType frexp(genType x, genIType& exp) {
{ return ::frexp(x, &exp); } return ::frexp(x, &exp);
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, typename genIType = int_t, size_t...i> requires(is_integral_v<genIType>) template<typename genType, typename genIType = int_t, size_t...i> requires(is_integral_v<genIType>)
constexpr vector<genType, i...> frexp(const vector<genType, i...>& x, vector<genIType, i...>& exp) constexpr vector<genType, i...> frexp(const vector<genType, i...>& x, vector<genIType, i...>& exp) {
{ return vector<genType, i...>(fennec::frexp(x[i], exp[i])...); } return vector<genType, i...>(fennec::frexp(x[i], exp[i])...);
}
@@ -760,15 +795,17 @@ constexpr vector<genType, i...> frexp(const vector<genType, i...>& x, vector<gen
/// \param x The significand /// \param x The significand
/// \param exp The exponent /// \param exp The exponent
template<typename genType, typename genIType = int_t> requires(is_integral_v<genIType>) template<typename genType, typename genIType = int_t> requires(is_integral_v<genIType>)
constexpr genType ldexp(genType x, genIType exp) constexpr genType ldexp(genType x, genIType exp) {
{ return ::ldexp(x, exp); } return ::ldexp(x, exp);
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, typename genIType = int_t, size_t...i> requires(is_integral_v<genIType>) template<typename genType, typename genIType = int_t, size_t...i> requires(is_integral_v<genIType>)
constexpr vector<genType, i...> ldexp(const vector<genType, i...>& x, const vector<genType, i...>& exp) constexpr vector<genType, i...> ldexp(const vector<genType, i...>& x, const vector<genType, i...>& exp) {
{ return vector<genType, i...>(fennec::ldexp(x[i], exp[i])...); } return vector<genType, i...>(fennec::ldexp(x[i], exp[i])...);
}
/// @} /// @}
@@ -793,24 +830,27 @@ constexpr vector<genType, i...> ldexp(const vector<genType, i...>& x, const vect
/// \param x input value \f$x\f$ /// \param x input value \f$x\f$
/// \param y input value \f$y\f$ /// \param y input value \f$y\f$
template<typename genType> template<typename genType>
constexpr genType min(genType x, genType y) constexpr genType min(genType x, genType y) {
{ return (y < x) ? y : x; } return (y < x) ? y : x;
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> min(genType x, const vector<genType, i...>& y) constexpr vector<genType, i...> min(genType x, const vector<genType, i...>& y) {
{ return vector<genType, i...>(fennec::min(x, y[i]) ...); } return vector<genType, i...>(fennec::min(x, y[i]) ...);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> min(const vector<genType, i...>& x, genType y) constexpr vector<genType, i...> min(const vector<genType, i...>& x, genType y) {
{ return vector<genType, i...>(fennec::min(x[i], y) ...); } return vector<genType, i...>(fennec::min(x[i], y) ...);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> min(const vector<genType, i...>& x, const vector<genType, i...>& y) constexpr vector<genType, i...> min(const vector<genType, i...>& x, const vector<genType, i...>& y) {
{ return vector<genType, i...>(fennec::min(x[i], y[i]) ...); } return vector<genType, i...>(fennec::min(x[i], y[i]) ...);
}
// Max ================================================================================================================= // Max =================================================================================================================
@@ -825,23 +865,27 @@ constexpr vector<genType, i...> min(const vector<genType, i...>& x, const vector
/// \param x first input value /// \param x first input value
/// \param y second input value /// \param y second input value
template<typename genType> template<typename genType>
constexpr genType max(genType x, genType y) constexpr genType max(genType x, genType y) {
{ return (x < y) ? y : x; } return (x < y) ? y : x;
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> max(genType x, const vector<genType, i...>& y) constexpr vector<genType, i...> max(genType x, const vector<genType, i...>& y) {
{ return vector<genType, i...>(fennec::max(x, y[i]) ...); } return vector<genType, i...>(fennec::max(x, y[i]) ...);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> max(const vector<genType, i...>& x, genType y) constexpr vector<genType, i...> max(const vector<genType, i...>& x, genType y) {
{ return vector<genType, i...>(fennec::max(x[i], y) ...); } return vector<genType, i...>(fennec::max(x[i], y) ...);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> max(const vector<genType, i...>& x, const vector<genType, i...>& y) constexpr vector<genType, i...> max(const vector<genType, i...>& x, const vector<genType, i...>& y) {
{ return vector<genType, i...>(fennec::max(x[i], y[i]) ...); } return vector<genType, i...>(fennec::max(x[i], y[i]) ...);
}
// Clamp =============================================================================================================== // Clamp ===============================================================================================================
@@ -857,19 +901,22 @@ constexpr vector<genType, i...> max(const vector<genType, i...>& x, const vector
/// \param minVal minimum value /// \param minVal minimum value
/// \param maxVal maximum value /// \param maxVal maximum value
template<typename genType> template<typename genType>
constexpr genType clamp(genType x, genType minVal, genType maxVal) constexpr genType clamp(genType x, genType minVal, genType maxVal) {
{ return min(max(x, minVal), maxVal); } return min(max(x, minVal), maxVal);
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> clamp(const vector<genType, i...>& x, genType minVal, genType maxVal) constexpr vector<genType, i...> clamp(const vector<genType, i...>& x, genType minVal, genType maxVal) {
{ return vector<genType, i...>(fennec::min(fennec::max(x[i], minVal), maxVal)...); } return vector<genType, i...>(fennec::min(fennec::max(x[i], minVal), maxVal)...);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> clamp(const vector<genType, i...>& x, const vector<genType, i...>& minVal, const vector<genType, i...>& maxVal) constexpr vector<genType, i...> clamp(const vector<genType, i...>& x, const vector<genType, i...>& minVal, const vector<genType, i...>& maxVal) {
{ return vector<genType, i...>(fennec::min(fennec::max(x[i], minVal[i]), maxVal[i])...); } return vector<genType, i...>(fennec::min(fennec::max(x[i], minVal[i]), maxVal[i])...);
}
/// @} /// @}
@@ -894,19 +941,22 @@ constexpr vector<genType, i...> clamp(const vector<genType, i...>& x, const vect
/// \param edge The \f$x\f$ coordinate of the discontinuity /// \param edge The \f$x\f$ coordinate of the discontinuity
/// \param x The coordinate of the sample location /// \param x The coordinate of the sample location
template<typename genType> requires(is_floating_point_v<genType>) template<typename genType> requires(is_floating_point_v<genType>)
constexpr genType step(genType edge, genType x) constexpr genType step(genType edge, genType x) {
{ return static_cast<genType>(not(x < edge)); } return static_cast<genType>(not(x < edge));
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> requires(is_floating_point_v<genType>) template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
constexpr vector<genType, i...> step(genType edge, const vector<genType, i...>& x) constexpr vector<genType, i...> step(genType edge, const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::step(edge, x[i]) ...); } return vector<genType, i...>(fennec::step(edge, x[i]) ...);
}
template<typename genType, size_t...i> requires(is_floating_point_v<genType>) template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
constexpr vector<genType, i...> step(const vector<genType, i...>& edge, const vector<genType, i...>& x) constexpr vector<genType, i...> step(const vector<genType, i...>& edge, const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::step(edge[i], x[i]) ...); } return vector<genType, i...>(fennec::step(edge[i], x[i]) ...);
}
// Smoothstep ========================================================================================================== // Smoothstep ==========================================================================================================
@@ -932,19 +982,22 @@ constexpr vector<genType, i...> step(const vector<genType, i...>& edge, const ve
/// \param edge1 \f$x\f$ value where the function returns \f$1.0\f$ /// \param edge1 \f$x\f$ value where the function returns \f$1.0\f$
/// \param x \f$x\f$ coordinate input /// \param x \f$x\f$ coordinate input
template<typename genType> requires(is_floating_point_v<genType>) template<typename genType> requires(is_floating_point_v<genType>)
constexpr genType smoothstep(genType edge0, genType edge1, genType x) constexpr genType smoothstep(genType edge0, genType edge1, genType x) {
{ genType t = fennec::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f); return t * t * (3 - 2 * t); } genType t = fennec::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f); return t * t * (3 - 2 * t);
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> requires(is_floating_point_v<genType>) template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
constexpr vector<genType, i...> smoothstep(genType edge0, genType edge1, const vector<genType, i...>& x) constexpr vector<genType, i...> smoothstep(genType edge0, genType edge1, const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::smoothstep(edge0, edge1, x[i]) ...); } return vector<genType, i...>(fennec::smoothstep(edge0, edge1, x[i]) ...);
}
template<typename genType, size_t...i> requires(is_floating_point_v<genType>) template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
constexpr vector<genType, i...> smoothstep(const vector<genType, i...>& edge0, const vector<genType, i...>& edge1, const vector<genType, i...>& x) constexpr vector<genType, i...> smoothstep(const vector<genType, i...>& edge0, const vector<genType, i...>& edge1, const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::smoothstep(edge0[i], edge1[i], x[i]) ...); } return vector<genType, i...>(fennec::smoothstep(edge0[i], edge1[i], x[i]) ...);
}
// Mix ================================================================================================================= // Mix =================================================================================================================
@@ -963,18 +1016,21 @@ constexpr vector<genType, i...> smoothstep(const vector<genType, i...>& edge0, c
/// \param y Second value /// \param y Second value
/// \param a Interpolant /// \param a Interpolant
template<typename genType> requires(is_floating_point_v<genType>) template<typename genType> requires(is_floating_point_v<genType>)
constexpr genType mix(genType x, genType y, genType a) constexpr genType mix(genType x, genType y, genType a) {
{ return x * (genType(1.0) - a) + y * a; } return x * (genType(1.0) - a) + y * a;
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> requires(is_floating_point_v<genType>) template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
constexpr vector<genType, i...> mix(const vector<genType, i...>& x, const vector<genType, i...>& y, genType a) constexpr vector<genType, i...> mix(const vector<genType, i...>& x, const vector<genType, i...>& y, genType a) {
{ return x * (genType(1.0) - a) + y * a; } return x * (genType(1.0) - a) + y * a;
}
template<typename genType, size_t...i> requires(is_floating_point_v<genType>) template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
constexpr vector<genType, i...> mix(const vector<genType, i...>& x, const vector<genType, i...>& y, const vector<genType, i...>& a) constexpr vector<genType, i...> mix(const vector<genType, i...>& x, const vector<genType, i...>& y, const vector<genType, i...>& a) {
{ return x * (genType(1.0) - a) + y * a; } return x * (genType(1.0) - a) + y * a;
}
// Mix (Bool) ========================================================================================================== // Mix (Bool) ==========================================================================================================
@@ -995,24 +1051,28 @@ constexpr vector<genType, i...> mix(const vector<genType, i...>& x, const vector
/// \param y False Value /// \param y False Value
/// \param a Boolean Value /// \param a Boolean Value
template<typename genType, typename genBType = bool_t> requires(is_bool_v<genBType> and is_floating_point_v<genType>) template<typename genType, typename genBType = bool_t> requires(is_bool_v<genBType> and is_floating_point_v<genType>)
constexpr genType mix(genType x, genType y, genBType a) constexpr genType mix(genType x, genType y, genBType a) {
{ return a ? y : x; } return a ? y : x;
}
// Vector Specializations ---------------------------------------------------------------------------------------------- // Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, typename genBType = bool_t, size_t...i> requires(is_bool_v<genBType> and is_floating_point_v<genType>) template<typename genType, typename genBType = bool_t, size_t...i> requires(is_bool_v<genBType> and is_floating_point_v<genType>)
constexpr vector<genType, i...> mix(const vector<genType, i...>& x, const vector<genType, i...>& y, genBType a) constexpr vector<genType, i...> mix(const vector<genType, i...>& x, const vector<genType, i...>& y, genBType a) {
{ return genDType((a ? y[i] : x[i])...); } return genDType((a ? y[i] : x[i])...);
}
template<typename genBType = bool_t, size_t...i> requires(is_bool_v<genBType>) template<typename genBType = bool_t, size_t...i> requires(is_bool_v<genBType>)
constexpr vector<genBType, i...> mix(const vector<genBType, i...>& x, const vector<genBType, i...>& y, const vector<genBType, i...>& a) constexpr vector<genBType, i...> mix(const vector<genBType, i...>& x, const vector<genBType, i...>& y, const vector<genBType, i...>& a) {
{ return genBType((a[i] ? y[i] : x[i])...); } return genBType((a[i] ? y[i] : x[i])...);
}
template<typename genType, typename genBType = bool_t, size_t...i> requires(is_bool_v<genBType> and is_floating_point_v<genType>) template<typename genType, typename genBType = bool_t, size_t...i> requires(is_bool_v<genBType> and is_floating_point_v<genType>)
constexpr vector<genType, i...> mix(const vector<genType, i...>& x, const vector<genType, i...>& y, const vector<genBType, i...>& a) constexpr vector<genType, i...> mix(const vector<genType, i...>& x, const vector<genType, i...>& y, const vector<genBType, i...>& a) {
{ return genDType((a[i] ? y[i] : x[i])...); } return genDType((a[i] ? y[i] : x[i])...);
}
/// @} /// @}

View File

@@ -26,16 +26,14 @@ namespace fennec
// specialization for mat2 // specialization for mat2
template<typename scalar, size_t rows, size_t...cols> requires(rows == 2 && sizeof...(cols) == 2) template<typename scalar, size_t rows, size_t...cols> requires(rows == 2 && sizeof...(cols) == 2)
constexpr scalar determinant(const matrix<scalar, rows, cols...>& m) constexpr scalar determinant(const matrix<scalar, rows, cols...>& m) {
{
return m[0][0] * m[1][1] - m[1][0] * m[0][1]; return m[0][0] * m[1][1] - m[1][0] * m[0][1];
} }
// specialization for mat3 // specialization for mat3
template<typename scalar, size_t rows, size_t...cols> requires(rows == 3 && sizeof...(cols) == 3) template<typename scalar, size_t rows, size_t...cols> requires(rows == 3 && sizeof...(cols) == 3)
constexpr scalar determinant(const matrix<scalar, rows, cols...>& m) constexpr scalar determinant(const matrix<scalar, rows, cols...>& m) {
{ // Cofactor expansion over first column
// Cofactor expansion over first column, better for cache locality than the first row
return m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) return m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1])
- m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) - m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0])
+ m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); + m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
@@ -43,9 +41,8 @@ constexpr scalar determinant(const matrix<scalar, rows, cols...>& m)
// specialization for mat4 // specialization for mat4
template<typename scalar, size_t rows, size_t...cols> requires(rows == 4 && sizeof...(cols) == 4) template<typename scalar, size_t rows, size_t...cols> requires(rows == 4 && sizeof...(cols) == 4)
constexpr scalar determinant(const matrix<scalar, rows, cols...>& m) constexpr scalar determinant(const matrix<scalar, rows, cols...>& m) {
{ // Cofactor expansion over the first column
// Cofactor expansion over the first column, better for cache locality than the first row
scalar d00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; scalar d00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
scalar d01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; scalar d01 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
scalar d02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; scalar d02 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
@@ -64,8 +61,7 @@ constexpr scalar determinant(const matrix<scalar, rows, cols...>& m)
// specialization for mat2 // specialization for mat2
template<typename scalar, size_t rows, size_t...cols> requires(rows == 2 && sizeof...(cols) == 2) template<typename scalar, size_t rows, size_t...cols> requires(rows == 2 && sizeof...(cols) == 2)
constexpr matrix<scalar, rows, cols...> inverse(const matrix<scalar, rows, cols...>& m) constexpr matrix<scalar, rows, cols...> inverse(const matrix<scalar, rows, cols...>& m) {
{
scalar di = scalar(1) / fennec::determinant(m); scalar di = scalar(1) / fennec::determinant(m);
return matrix<scalar, rows, cols...>( return matrix<scalar, rows, cols...>(
m[1][1] * di, -m[0][1] * di, -m[1][0] * di, m[0][0] * di m[1][1] * di, -m[0][1] * di, -m[1][0] * di, m[0][0] * di
@@ -74,8 +70,7 @@ constexpr matrix<scalar, rows, cols...> inverse(const matrix<scalar, rows, cols.
// specialization for mat3 // specialization for mat3
template<typename scalar, size_t rows, size_t...cols> requires(rows == 3 && sizeof...(cols) == 3) template<typename scalar, size_t rows, size_t...cols> requires(rows == 3 && sizeof...(cols) == 3)
constexpr matrix<scalar, rows, cols...> inverse(const matrix<scalar, rows, cols...>& m) constexpr matrix<scalar, rows, cols...> inverse(const matrix<scalar, rows, cols...>& m) {
{
scalar di = scalar(1) / fennec::determinant(m); scalar di = scalar(1) / fennec::determinant(m);
matrix<scalar, rows, cols...> i( matrix<scalar, rows, cols...> i(
@@ -96,8 +91,7 @@ constexpr matrix<scalar, rows, cols...> inverse(const matrix<scalar, rows, cols.
} }
template<typename scalar, size_t rows, size_t...cols> requires(rows == 4 && sizeof...(cols) == 4) template<typename scalar, size_t rows, size_t...cols> requires(rows == 4 && sizeof...(cols) == 4)
constexpr matrix<scalar, rows, cols...> inverse(const matrix<scalar, rows, cols...>& m) constexpr matrix<scalar, rows, cols...> inverse(const matrix<scalar, rows, cols...>& m) {
{
scalar s0 = m[0][0] * m[1][1] - m[1][0] * m[0][1]; scalar s0 = m[0][0] * m[1][1] - m[1][0] * m[0][1];
scalar s1 = m[0][0] * m[1][2] - m[1][0] * m[0][2]; scalar s1 = m[0][0] * m[1][2] - m[1][0] * m[0][2];
scalar s2 = m[0][0] * m[1][3] - m[1][0] * m[0][3]; scalar s2 = m[0][0] * m[1][3] - m[1][0] * m[0][3];

View File

@@ -93,7 +93,7 @@ namespace fennec
{ {
// pow ----------------------------------------------------------------------------------------------------------------- // pow =================================================================================================================
/// ///
/// \brief Returns \f$x\f$ raised to the \f$y\f$ power, i.e., \f$x^y\f$. /// \brief Returns \f$x\f$ raised to the \f$y\f$ power, i.e., \f$x^y\f$.
@@ -104,15 +104,20 @@ namespace fennec
/// \param x the base /// \param x the base
/// \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 ::pow(x, y); } return ::pow(x, y);
}
// Vector Specialization -----------------------------------------------------------------------------------------------
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) {
{ return vector<genType, i...>(fennec::pow(x[i], y[i]) ...); } return vector<genType, i...>(fennec::pow(x[i], y[i]) ...);
}
// exp ----------------------------------------------------------------------------------------------------------------- // exp =================================================================================================================
/// ///
/// \brief Returns the natural exponentiation of \f$x\f$, i.e., \f$e^x\f$ /// \brief Returns the natural exponentiation of \f$x\f$, i.e., \f$e^x\f$
@@ -121,14 +126,19 @@ 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 ::exp(x); } return ::exp(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]) ...); }
// exp2 ---------------------------------------------------------------------------------------------------------------- // Vector Specialization -----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> constexpr vector<genType, i...> exp(const vector<genType, i...>& x) {
return vector<genType, i...>(fennec::exp(x[i]) ...);
}
// exp2 ================================================================================================================
/// ///
/// \brief Returns 2 raised to the \f$x\f$ power, i.e., \f$e^x\f$ /// \brief Returns 2 raised to the \f$x\f$ power, i.e., \f$e^x\f$
@@ -136,14 +146,19 @@ template<typename genType, size_t...i> constexpr vector<genType, i...> exp(const
/// \returns 2 raised to the \f$x\f$ power, i.e., \f$e^x\f$<br><br> /// \returns 2 raised to the \f$x\f$ power, i.e., \f$e^x\f$<br><br>
/// ///
/// \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 ::exp2(x); } return ::exp2(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]) ...); }
// log ----------------------------------------------------------------------------------------------------------------- // Vector Specialization -----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> constexpr vector<genType, i...> exp2(const vector<genType, i...>& x) {
return vector<genType, i...>(fennec::exp2(x[i]) ...);
}
// log =================================================================================================================
/// ///
/// \brief Returns the natural logarithm of \f$x\f$. /// \brief Returns the natural logarithm of \f$x\f$.
@@ -152,14 +167,19 @@ template<typename genType, size_t...i> constexpr vector<genType, i...> exp2(cons
/// \details Results are undefined if \f${x}\le{0}\f$.<br><br> /// \details Results are undefined if \f${x}\le{0}\f$.<br><br>
/// ///
/// \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 ::log(x); } return ::log(x);
}
template<typename genType, size_t...i> constexpr genType log(const vector<genType, i...>& x)
{ return vector<genType, i...>(log(x[i]) ...); }
// log2 ---------------------------------------------------------------------------------------------------------------- // Vector Specialization -----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> constexpr genType log(const vector<genType, i...>& x) {
return vector<genType, i...>(log(x[i]) ...);
}
// log2 ================================================================================================================
/// ///
/// \brief Returns the base 2 logarithm of \f$x\f$. /// \brief Returns the base 2 logarithm of \f$x\f$.
@@ -169,14 +189,19 @@ template<typename genType, size_t...i> constexpr genType log(const vector<genTyp
/// \details Results are undefined if \f${x}\le{0}\f$. <br><br> /// \details Results are undefined if \f${x}\le{0}\f$. <br><br>
/// ///
/// \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 ::log2(x); } return ::log2(x);
}
template<typename genType, size_t...i> constexpr genType log2(const vector<genType, i...>& x)
{ return vector<genType, i...>(log2(x[i]) ...); }
// sqrt ---------------------------------------------------------------------------------------------------------------- // Vector Specialization -----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> constexpr genType log2(const vector<genType, i...>& x) {
return vector<genType, i...>(log2(x[i]) ...);
}
// sqrt ================================================================================================================
/// ///
/// \brief Returns \f$\sqrt{x}\f$. /// \brief Returns \f$\sqrt{x}\f$.
@@ -185,14 +210,19 @@ template<typename genType, size_t...i> constexpr genType log2(const vector<genTy
/// \details Results are undefined if \f$x<0\f$<br><br> /// \details Results are undefined if \f$x<0\f$<br><br>
/// ///
/// \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 ::sqrt(x); } return ::sqrt(x);
}
template<typename genType, size_t...i> constexpr genType sqrt(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::sqrt(x[i]) ...); }
// inversesqrt --------------------------------------------------------------------------------------------------------- // Vector Specialization -----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> constexpr genType sqrt(const vector<genType, i...>& x) {
return vector<genType, i...>(fennec::sqrt(x[i]) ...);
}
// inversesqrt =========================================================================================================
/// ///
/// \brief Returns \f$\frac{1}{\sqrt{x}}\f$. /// \brief Returns \f$\frac{1}{\sqrt{x}}\f$.
@@ -201,12 +231,17 @@ template<typename genType, size_t...i> constexpr genType sqrt(const vector<genTy
/// \details Results are undefined if \f$x<0\f$.<br><br> /// \details Results are undefined if \f$x<0\f$.<br><br>
/// ///
/// \param x the input value /// \param x the input value
template<typename genType> constexpr genType inversesqrt(genType x) template<typename genType> constexpr genType inversesqrt(genType x) {
{ return 1.0f / ::sqrt(x); } return 1.0f / ::sqrt(x);
}
// Vector Specialization -----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> inversesqrt(const vector<genType, i...>& x) constexpr vector<genType, i...> inversesqrt(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::inversesqrt(x[i]) ...); } return vector<genType, i...>(fennec::inversesqrt(x[i]) ...);
}
} }

View File

@@ -538,8 +538,11 @@
namespace fennec namespace fennec
{ {
// http://numbers.computation.free.fr/Constants/Miscellaneous/digits.html
// 50 digits is sufficient for 128-bit floats // http://numbers.computation.free.fr/Constants/Miscellaneous/digits.html
// 50 digits is sufficient for 128-bit floats
// Break from 1TBS style for legibility
// Rational Constants ================================================================================================== // Rational Constants ==================================================================================================

View File

@@ -130,8 +130,9 @@ namespace fennec
/// \param x first vector /// \param x first vector
/// \param y second vector /// \param y second vector
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr genType dot(const vector<genType, i...>& x, const vector<genType, i...>& y) constexpr genType dot(const vector<genType, i...>& x, const vector<genType, i...>& y) {
{ return ((x[i] * y[i]) + ...); } return ((x[i] * y[i]) + ...);
}
// length2 ------------------------------------------------------------------------------------------------------------- // length2 -------------------------------------------------------------------------------------------------------------
@@ -147,8 +148,9 @@ constexpr genType dot(const vector<genType, i...>& x, const vector<genType, i...
/// ///
/// \param x the vector /// \param x the vector
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr genType length2(const vector<genType, i...>& x) constexpr genType length2(const vector<genType, i...>& x) {
{ return fennec::dot(x, x); } return fennec::dot(x, x);
}
// length -------------------------------------------------------------------------------------------------------------- // length --------------------------------------------------------------------------------------------------------------
@@ -164,7 +166,9 @@ constexpr genType length2(const vector<genType, i...>& x)
/// ///
/// \param x the vector /// \param x the vector
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr genType length(const vector<genType, i...>& x) { return fennec::sqrt(fennec::length2(x)); } constexpr genType length(const vector<genType, i...>& x) {
return fennec::sqrt(fennec::length2(x));
}
// distance ------------------------------------------------------------------------------------------------------------ // distance ------------------------------------------------------------------------------------------------------------
@@ -182,8 +186,9 @@ constexpr genType length(const vector<genType, i...>& x) { return fennec::sqrt(f
/// \param p0 first vector /// \param p0 first vector
/// \param p1 second vector /// \param p1 second vector
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr genType distance(const vector<genType, i...>& p0, const vector<genType, i...>& p1) constexpr genType distance(const vector<genType, i...>& p0, const vector<genType, i...>& p1) {
{ return fennec::length(p1 - p0); } return fennec::length(p1 - p0);
}
// cross --------------------------------------------------------------------------------------------------------------- // cross ---------------------------------------------------------------------------------------------------------------
@@ -203,8 +208,9 @@ constexpr genType distance(const vector<genType, i...>& p0, const vector<genType
/// \param x first vector /// \param x first vector
/// \param y second vector /// \param y second vector
template<typename genType, size_t...i> requires(sizeof...(i) == 3) template<typename genType, size_t...i> requires(sizeof...(i) == 3)
constexpr vector<genType, i...> cross(const vector<genType, i...>& x, const vector<genType, i...>& y) constexpr vector<genType, i...> cross(const vector<genType, i...>& x, const vector<genType, i...>& y) {
{ return vector<genType, i...>(x[1]*y[2]-y[1]*x[2], x[2]*y[0]-y[2]*x[0], x[0]*y[1]-y[0]*x[1]); } return vector<genType, i...>(x[1]*y[2]-y[1]*x[2], x[2]*y[0]-y[2]*x[0], x[0]*y[1]-y[0]*x[1]);
}
// normalize ----------------------------------------------------------------------------------------------------------- // normalize -----------------------------------------------------------------------------------------------------------
@@ -220,8 +226,9 @@ constexpr vector<genType, i...> cross(const vector<genType, i...>& x, const vect
/// ///
/// \param x /// \param x
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> normalize(const vector<genType, i...>& x) constexpr vector<genType, i...> normalize(const vector<genType, i...>& x) {
{ return x / fennec::length(x); } return x / fennec::length(x);
}
// faceforward --------------------------------------------------------------------------------------------------------- // faceforward ---------------------------------------------------------------------------------------------------------
@@ -235,8 +242,9 @@ constexpr vector<genType, i...> normalize(const vector<genType, i...>& x)
/// \param I the incident /// \param I the incident
/// \param Nref the reference /// \param Nref the reference
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> faceforward(const vector<genType, i...>& N, const vector<genType, i...>& I, const vector<genType, i...>& Nref) constexpr vector<genType, i...> faceforward(const vector<genType, i...>& N, const vector<genType, i...>& I, const vector<genType, i...>& Nref) {
{ return fennec::sign(fennec::dot(Nref, I)) * N; } return fennec::sign(fennec::dot(Nref, I)) * N;
}
// reflect ------------------------------------------------------------------------------------------------------------- // reflect -------------------------------------------------------------------------------------------------------------
@@ -251,8 +259,9 @@ constexpr vector<genType, i...> faceforward(const vector<genType, i...>& N, cons
/// \param I the incident /// \param I the incident
/// \param N the surface orientation /// \param N the surface orientation
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> reflect(const vector<genType, i...>& I, const vector<genType, i...>& N) constexpr vector<genType, i...> reflect(const vector<genType, i...>& I, const vector<genType, i...>& N) {
{ return I - genType(2.0) * fennec::dot(N, I) * N; } return I - genType(2.0) * fennec::dot(N, I) * N;
}
// refract ------------------------------------------------------------------------------------------------------------- // refract -------------------------------------------------------------------------------------------------------------
@@ -269,8 +278,7 @@ constexpr vector<genType, i...> reflect(const vector<genType, i...>& I, const ve
/// \param N the surface normal /// \param N the surface normal
/// \param eta the ratio of indices of refraction /// \param eta the ratio of indices of refraction
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> refract(const vector<genType, i...>& I, const vector<genType, i...>& N, genType eta) constexpr vector<genType, i...> refract(const vector<genType, i...>& I, const vector<genType, i...>& N, genType eta) {
{
genType ndi = fennec::dot(N, I); genType ndi = fennec::dot(N, I);
genType k = genType(1.0) - eta * eta * (genType(1.0) - ndi * ndi); genType k = genType(1.0) - eta * eta * (genType(1.0) - ndi * ndi);
if (k < 0) return vector<genType, i...>(0); if (k < 0) return vector<genType, i...>(0);

View File

@@ -112,14 +112,26 @@
/// ///
/// ///
// Base Scalar Types
#include <fennec/math/scalar.h>
// Vector Types
#include <fennec/math/vector.h> #include <fennec/math/vector.h>
#include <fennec/math/vector_traits.h> #include <fennec/math/vector_traits.h>
#include <fennec/math/swizzle.h> #include <fennec/math/swizzle.h>
// Matrix Types
#include <fennec/math/matrix.h> #include <fennec/math/matrix.h>
// Built-in Functions
#include <fennec/math/common.h> #include <fennec/math/common.h>
#include <fennec/math/exponential.h>
#include <fennec/math/geometric.h>
#include <fennec/math/relational.h>
#include <fennec/math/trigonometric.h> #include <fennec/math/trigonometric.h>
// Common Extensions
#include <fennec/math/ext/constants.h>
#endif // FENNEC_MATH_H #endif // FENNEC_MATH_H

View File

@@ -61,8 +61,9 @@ namespace fennec
/// \param i the index of the row /// \param i the index of the row
/// \returns a **copy** of the column at index \f$i\f$ /// \returns a **copy** of the column at index \f$i\f$
template<typename scalar, size_t rows, size_t...cols> template<typename scalar, size_t rows, size_t...cols>
constexpr vec<scalar, rows> column(const matrix<scalar, rows, cols...>& m, size_t i) noexcept constexpr vec<scalar, rows> column(const matrix<scalar, rows, cols...>& m, size_t i) noexcept {
{ return m[i]; } return m[i];
}
/// ///
@@ -71,8 +72,9 @@ constexpr vec<scalar, rows> column(const matrix<scalar, rows, cols...>& m, size_
/// \param i the index of the row /// \param i the index of the row
/// \returns a **copy** of the row at index \f$i\f$ /// \returns a **copy** of the row at index \f$i\f$
template<typename scalar, size_t rows, size_t...cols> template<typename scalar, size_t rows, size_t...cols>
constexpr vec<scalar, sizeof...(cols)> row(const matrix<scalar, rows, cols...>& m, size_t i) noexcept constexpr vec<scalar, sizeof...(cols)> row(const matrix<scalar, rows, cols...>& m, size_t i) noexcept {
{ return vec<scalar, sizeof...(cols)>(m[cols][i]...); } return vec<scalar, sizeof...(cols)>(m[cols][i]...);
}
template<typename ScalarT> template<typename ScalarT>
@@ -124,8 +126,9 @@ using dmat4x4 = tmat4x4<double_t>; ///< Specification for size glsl double matri
/// \param y the second matrix /// \param y the second matrix
/// \returns the resulting product in a matrix of the same size and base type /// \returns the resulting product in a matrix of the same size and base type
template<typename scalar, size_t rows, size_t...cols> template<typename scalar, size_t rows, size_t...cols>
constexpr matrix<scalar, rows, cols...> matrixCompMult(const matrix<scalar, rows, cols...>& x, const matrix<scalar, rows, cols...>& y) noexcept constexpr matrix<scalar, rows, cols...> matrixCompMult(const matrix<scalar, rows, cols...>& x, const matrix<scalar, rows, cols...>& y) noexcept {
{ return matrix<scalar, rows, cols...>(x[cols] * y[cols] ...); } return matrix<scalar, rows, cols...>(x[cols] * y[cols] ...);
}
/// ///
/// \brief Performs a linear algebraic multiply, multiplying \f$c\f$ by the components of \f$r\f$, producing a matrix. /// \brief Performs a linear algebraic multiply, multiplying \f$c\f$ by the components of \f$r\f$, producing a matrix.
@@ -140,8 +143,7 @@ constexpr matrix<scalar, rows, cols...> matrixCompMult(const matrix<scalar, rows
/// \param r the row vector /// \param r the row vector
/// \returns the resulting matrix produced by the linear algebraic product /// \returns the resulting matrix produced by the linear algebraic product
template<typename scalar, size_t...s0, size_t...s1> template<typename scalar, size_t...s0, size_t...s1>
constexpr matrix<scalar, sizeof...(s0), s1...> outerProduct(const vector<scalar, s0...>& c, const vector<scalar, s1...>& r) noexcept constexpr matrix<scalar, sizeof...(s0), s1...> outerProduct(const vector<scalar, s0...>& c, const vector<scalar, s1...>& r) noexcept {
{
return matrix<scalar, sizeof...(s0), s1...>( return matrix<scalar, sizeof...(s0), s1...>(
c * r[s1]... c * r[s1]...
); );
@@ -153,24 +155,23 @@ constexpr matrix<scalar, sizeof...(s0), s1...> outerProduct(const vector<scalar,
/// \returns a matrix that is the transpose of \f$m\f$ /// \returns a matrix that is the transpose of \f$m\f$
/// \details The input matrix m is not modified. /// \details The input matrix m is not modified.
template<typename scalar, size_t rows, size_t...cols> template<typename scalar, size_t rows, size_t...cols>
constexpr mat<scalar, rows, sizeof...(cols)> transpose(const matrix<scalar, rows, cols...>& m) noexcept constexpr mat<scalar, rows, sizeof...(cols)> transpose(const matrix<scalar, rows, cols...>& m) noexcept {
{ return mat<scalar, rows, sizeof...(cols)>::transpose(m); } return mat<scalar, rows, sizeof...(cols)>::transpose(m);
}
/// ///
/// \brief Returns the determinant of m. /// \brief Returns the determinant of m.
/// \param m the matrix /// \param m the matrix
/// \returns the determinant of m. /// \returns the determinant of m.
template<typename scalar, size_t rows, size_t...cols> template<typename scalar, size_t rows, size_t...cols>
constexpr scalar determinant(const matrix<scalar, rows, cols...>&) noexcept constexpr scalar determinant(const matrix<scalar, rows, cols...>&) noexcept {
{
// ReSharper disable once CppStaticAssertFailure // ReSharper disable once CppStaticAssertFailure
static_assert(false, "implementation undefined"); static_assert(false, "implementation undefined");
return 0; return 0;
} }
template<typename scalar, size_t rows, size_t...cols> template<typename scalar, size_t rows, size_t...cols>
constexpr matrix<scalar, rows, cols...> inverse(const matrix<scalar, rows, cols...>&) noexcept constexpr matrix<scalar, rows, cols...> inverse(const matrix<scalar, rows, cols...>&) noexcept {
{
// ReSharper disable once CppStaticAssertFailure // ReSharper disable once CppStaticAssertFailure
static_assert(false, "implementation undefined"); static_assert(false, "implementation undefined");
return 1; return 1;
@@ -249,7 +250,9 @@ struct matrix
/// \details /// \details
/// \param mat matrix to copy /// \param mat matrix to copy
constexpr matrix(const matrix_t& mat) constexpr matrix(const matrix_t& mat)
: data{ mat.data } {} : data{ mat.data } {
}
/// ///
/// \brief move constructor /// \brief move constructor
@@ -257,7 +260,9 @@ struct matrix
/// \details /// \details
/// \param mat matrix to move /// \param mat matrix to move
constexpr matrix(matrix_t&& mat) noexcept constexpr matrix(matrix_t&& mat) noexcept
: data{ mat.data } {} : data{ mat.data } {
}
/// ///
@@ -274,8 +279,9 @@ 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), ...);
}
/// ///
@@ -285,8 +291,9 @@ struct matrix
/// \tparam ArgsT /// \tparam ArgsT
/// \param args /// \param args
template<typename...ArgsT> requires(total_component_count_v<ArgsT...> == num_components) template<typename...ArgsT> requires(total_component_count_v<ArgsT...> == num_components)
constexpr matrix(ArgsT&&...args) constexpr matrix(ArgsT&&...args) {
{ matrix::__construct(fennec::forward<ArgsT>(args)...); } matrix::__construct(fennec::forward<ArgsT>(args)...);
}
/// @} /// @}
@@ -301,8 +308,9 @@ struct matrix
/// \details /// \details
/// \returns a reference to **this** after copying the contents of \p rhs /// \returns a reference to **this** after copying the contents of \p rhs
/// \param rhs the matrix to copy /// \param rhs the matrix to copy
constexpr matrix_t& operator=(const matrix_t& rhs) constexpr matrix_t& operator=(const matrix_t& rhs) {
{ data = rhs.data; return *this; } data = rhs.data; return *this;
}
/// ///
/// \brief move assignment operator /// \brief move assignment operator
@@ -310,8 +318,9 @@ struct matrix
/// \details /// \details
/// \returns a reference to **this** after moving the contents of \p rhs /// \returns a reference to **this** after moving the contents of \p rhs
/// \param rhs the matrix to move /// \param rhs the matrix to move
constexpr matrix_t& operator=(matrix_t&& rhs) noexcept constexpr matrix_t& operator=(matrix_t&& rhs) noexcept {
{ data = rhs.data; return *this; } data = rhs.data; return *this;
}
/// @} /// @}
@@ -323,8 +332,9 @@ struct matrix
/// ///
/// \copydetails matrix::operator[](size_t) const /// \copydetails matrix::operator[](size_t) const
constexpr column_t& operator[](size_t i) constexpr column_t& operator[](size_t i) {
{ return data[i]; } return data[i];
}
/// ///
/// \brief returns the column at index \f$i\f$ /// \brief returns the column at index \f$i\f$
@@ -332,21 +342,24 @@ struct matrix
/// \details /// \details
/// \param i the index /// \param i the index
/// \returns the column at index \f$i\f$ /// \returns the column at index \f$i\f$
constexpr const column_t& operator[](size_t i) const constexpr const column_t& operator[](size_t i) const {
{ return data[i]; } return data[i];
}
/// ///
/// \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) {
{ return data[i][j]; } return data[i][j];
}
/// ///
/// \brief returns the cell in row \p j column \p i /// \brief returns the cell in row \p j column \p i
/// \param i the column /// \param i the column
/// \param j the row /// \param j the row
/// \returns the cell at the specified index. /// \returns the cell at the specified index.
constexpr scalar_t operator[](size_t i, size_t j) const constexpr scalar_t operator[](size_t i, size_t j) const {
{ return data[i][j]; } return data[i][j];
}
/// @} /// @}
@@ -360,8 +373,7 @@ struct matrix
/// \param lhs the matrix /// \param lhs the matrix
/// \param rhs the scalar /// \param rhs the scalar
/// \returns a copy of the matrix with each component having been added by 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) constexpr friend matrix_t operator+(const matrix_t& lhs, scalar_t rhs) {
{
return matrix_t(lhs[ColIndicesV] + rhs ...); return matrix_t(lhs[ColIndicesV] + rhs ...);
} }
@@ -370,8 +382,7 @@ struct matrix
/// \param lhs the scalar /// \param lhs the scalar
/// \param rhs the matrix /// \param rhs the matrix
/// \returns a copy of the matrix with each component having been added by the scalar /// \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) constexpr friend matrix_t operator+(scalar_t lhs, const matrix_t& rhs) {
{
return matrix_t(lhs + rhs[ColIndicesV] ...); return matrix_t(lhs + rhs[ColIndicesV] ...);
} }
@@ -380,8 +391,7 @@ struct matrix
/// \param lhs the matrix /// \param lhs the matrix
/// \param rhs the scalar /// \param rhs the scalar
/// \returns a copy of the matrix with each component having been subtracted by 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) constexpr friend matrix_t operator-(const matrix_t& lhs, scalar_t rhs) {
{
return matrix_t(lhs[ColIndicesV] - rhs ...); return matrix_t(lhs[ColIndicesV] - rhs ...);
} }
@@ -390,8 +400,7 @@ struct matrix
/// \param lhs the scalar /// \param lhs the scalar
/// \param rhs the matrix /// \param rhs the matrix
/// \returns a copy of the matrix with each component having been subtracted by the scalar /// \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) constexpr friend matrix_t operator-(scalar_t lhs, const matrix_t& rhs) {
{
return matrix_t(lhs - rhs[ColIndicesV] ...); return matrix_t(lhs - rhs[ColIndicesV] ...);
} }
@@ -400,8 +409,7 @@ struct matrix
/// \param lhs the matrix /// \param lhs the matrix
/// \param rhs the scalar /// \param rhs the scalar
/// \returns a copy of the matrix with each component having been multiplied by 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) constexpr friend matrix_t operator*(const matrix_t& lhs, scalar_t rhs) {
{
return matrix_t(lhs[ColIndicesV] * rhs ...); return matrix_t(lhs[ColIndicesV] * rhs ...);
} }
@@ -410,8 +418,7 @@ struct matrix
/// \param lhs the scalar /// \param lhs the scalar
/// \param rhs the matrix /// \param rhs the matrix
/// \returns a copy of the matrix with each component having been multiplied by the scalar /// \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) constexpr friend matrix_t operator*(scalar_t lhs, const matrix_t& rhs) {
{
return matrix_t(lhs * rhs[ColIndicesV] ...); return matrix_t(lhs * rhs[ColIndicesV] ...);
} }
@@ -420,8 +427,7 @@ struct matrix
/// \param lhs the matrix /// \param lhs the matrix
/// \param rhs the scalar /// \param rhs the scalar
/// \returns a copy of the matrix with each component having been divided by 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) constexpr friend matrix_t operator/(const matrix_t& lhs, scalar_t rhs) {
{
return matrix_t(lhs[ColIndicesV] / rhs ...); return matrix_t(lhs[ColIndicesV] / rhs ...);
} }
@@ -430,8 +436,7 @@ struct matrix
/// \param lhs the scalar /// \param lhs the scalar
/// \param rhs the matrix /// \param rhs the matrix
/// \returns a copy of the matrix with each component having been divided by the scalar /// \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) constexpr friend matrix_t operator/(scalar_t lhs, const matrix_t& rhs) {
{
return matrix_t(lhs / rhs[ColIndicesV] ...); return matrix_t(lhs / rhs[ColIndicesV] ...);
} }
@@ -442,8 +447,7 @@ struct matrix
/// \param lhs the matrix /// \param lhs the matrix
/// \param rhs the scalar /// \param rhs the scalar
/// \returns the matrix after having each component added by the scalar /// \returns the matrix after having each component added by the scalar
constexpr friend matrix_t& operator+=(matrix_t& lhs, scalar_t rhs) constexpr friend matrix_t& operator+=(matrix_t& lhs, scalar_t rhs) {
{
((lhs[ColIndicesV] += rhs), ...); ((lhs[ColIndicesV] += rhs), ...);
return lhs; return lhs;
} }
@@ -453,8 +457,7 @@ struct matrix
/// \param lhs the scalar /// \param lhs the scalar
/// \param rhs the matrix /// \param rhs the matrix
/// \returns the matrix after having each component added by the scalar /// \returns the matrix after having each component added by the scalar
constexpr friend matrix_t& operator+=(scalar_t lhs, matrix_t& rhs) constexpr friend matrix_t& operator+=(scalar_t lhs, matrix_t& rhs) {
{
((rhs[ColIndicesV] += lhs), ...); ((rhs[ColIndicesV] += lhs), ...);
return rhs; return rhs;
} }
@@ -464,8 +467,7 @@ struct matrix
/// \param lhs the matrix /// \param lhs the matrix
/// \param rhs the scalar /// \param rhs the scalar
/// \returns the matrix after having each component subtracted by the scalar /// \returns the matrix after having each component subtracted by the scalar
constexpr friend matrix_t& operator-=(matrix_t& lhs, scalar_t rhs) constexpr friend matrix_t& operator-=(matrix_t& lhs, scalar_t rhs) {
{
((lhs[ColIndicesV] -= rhs), ...); ((lhs[ColIndicesV] -= rhs), ...);
return lhs; return lhs;
} }
@@ -475,8 +477,7 @@ struct matrix
/// \param lhs the scalar /// \param lhs the scalar
/// \param rhs the matrix /// \param rhs the matrix
/// \returns the matrix after having each component added by the scalar /// \returns the matrix after having each component added by the scalar
constexpr friend matrix_t& operator-=(scalar_t lhs, matrix_t& rhs) constexpr friend matrix_t& operator-=(scalar_t lhs, matrix_t& rhs) {
{
((rhs[ColIndicesV] -= lhs), ...); ((rhs[ColIndicesV] -= lhs), ...);
return rhs; return rhs;
} }
@@ -486,8 +487,7 @@ struct matrix
/// \param lhs the matrix /// \param lhs the matrix
/// \param rhs the scalar /// \param rhs the scalar
/// \returns the matrix after having each component multiplied by the scalar /// \returns the matrix after having each component multiplied by the scalar
constexpr friend matrix_t& operator*=(matrix_t& lhs, scalar_t rhs) constexpr friend matrix_t& operator*=(matrix_t& lhs, scalar_t rhs) {
{
((lhs[ColIndicesV] *= rhs), ...); ((lhs[ColIndicesV] *= rhs), ...);
return lhs; return lhs;
} }
@@ -497,8 +497,7 @@ struct matrix
/// \param lhs the scalar /// \param lhs the scalar
/// \param rhs the matrix /// \param rhs the matrix
/// \returns the matrix after having each component multiplied by the scalar /// \returns the matrix after having each component multiplied by the scalar
constexpr friend matrix_t& operator*=(scalar_t lhs, matrix_t& rhs) constexpr friend matrix_t& operator*=(scalar_t lhs, matrix_t& rhs) {
{
((rhs[ColIndicesV] *= lhs), ...); ((rhs[ColIndicesV] *= lhs), ...);
return rhs; return rhs;
} }
@@ -508,8 +507,7 @@ struct matrix
/// \param lhs the matrix /// \param lhs the matrix
/// \param rhs the scalar /// \param rhs the scalar
/// \returns the matrix after having each component divided by the scalar /// \returns the matrix after having each component divided by the scalar
constexpr friend matrix_t& operator/=(matrix_t& lhs, scalar_t rhs) constexpr friend matrix_t& operator/=(matrix_t& lhs, scalar_t rhs) {
{
((lhs[ColIndicesV] /= rhs), ...); ((lhs[ColIndicesV] /= rhs), ...);
return lhs; return lhs;
} }
@@ -519,8 +517,7 @@ struct matrix
/// \param lhs the scalar /// \param lhs the scalar
/// \param rhs the matrix /// \param rhs the matrix
/// \returns the matrix after having each component divided by the scalar /// \returns the matrix after having each component divided by the scalar
constexpr friend matrix_t& operator/=(scalar_t lhs, matrix_t& rhs) constexpr friend matrix_t& operator/=(scalar_t lhs, matrix_t& rhs) {
{
((rhs[ColIndicesV] /= lhs), ...); ((rhs[ColIndicesV] /= lhs), ...);
return rhs; return rhs;
} }
@@ -532,8 +529,7 @@ struct matrix
/// \param lhs the matrix /// \param lhs the matrix
/// \param rhs the scalar /// \param rhs the scalar
/// \returns a copy of the matrix with each component having been reduced modulo by 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> constexpr friend matrix_t operator%(const matrix_t& lhs, scalar_t rhs) requires is_integral_v<scalar_t> {
{
matrix_t retval = lhs; matrix_t retval = lhs;
((retval[ColIndicesV] %= rhs), ...); ((retval[ColIndicesV] %= rhs), ...);
return retval; return retval;
@@ -544,8 +540,7 @@ struct matrix
/// \param lhs the scalar /// \param lhs the scalar
/// \param rhs the matrix /// \param rhs the matrix
/// \returns a copy of the matrix with each component having been reduced modulo by the scalar /// \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> constexpr friend matrix_t operator%(scalar_t lhs, const matrix_t& rhs) requires is_integral_v<scalar_t> {
{
matrix_t retval = rhs; matrix_t retval = rhs;
((retval[ColIndicesV] %= lhs), ...); ((retval[ColIndicesV] %= lhs), ...);
return retval; return retval;
@@ -556,8 +551,7 @@ struct matrix
/// \param lhs the matrix /// \param lhs the matrix
/// \param rhs the scalar /// \param rhs the scalar
/// \returns the matrix after having each component reduced modulo by 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> constexpr friend matrix_t& operator%=(matrix_t& lhs, scalar_t rhs) requires is_integral_v<scalar_t> {
{
((lhs[ColIndicesV] %= rhs), ...); ((lhs[ColIndicesV] %= rhs), ...);
return lhs; return lhs;
} }
@@ -567,8 +561,7 @@ struct matrix
/// \param lhs the scalar /// \param lhs the scalar
/// \param rhs the matrix /// \param rhs the matrix
/// \returns the matrix after having each component reduced modulo by the scalar /// \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> constexpr friend matrix_t& operator%=(scalar_t lhs, matrix_t& rhs) requires is_integral_v<scalar_t> {
{
((rhs[ColIndicesV] %= lhs), ...); ((rhs[ColIndicesV] %= lhs), ...);
return rhs; return rhs;
} }
@@ -585,8 +578,7 @@ struct matrix
/// \param lhs the matrix /// \param lhs the matrix
/// \param rhs the vector /// \param rhs the vector
/// \returns a vector containing the dot products of \f$rhs\f$ with each row of \f$lhs\f$ /// \returns a vector containing the dot products of \f$rhs\f$ with each row of \f$lhs\f$
constexpr friend column_t operator*(const matrix_t& lhs, const row_t& rhs) constexpr friend column_t operator*(const matrix_t& lhs, const row_t& rhs) {
{
return __mul(lhs, rhs); return __mul(lhs, rhs);
} }
@@ -595,8 +587,9 @@ struct matrix
/// \param lhs the vector /// \param lhs the vector
/// \param rhs the matrix /// \param rhs the matrix
/// \returns a vector containing the dot products of \f$lhs\f$ with each column of \f$rhs\f$ /// \returns a vector containing the dot products of \f$lhs\f$ with each column of \f$rhs\f$
constexpr friend row_t operator*(const column_t& lhs, const matrix_t& rhs) constexpr friend row_t operator*(const column_t& lhs, const matrix_t& rhs) {
{ return row_t(fennec::dot(fennec::column(rhs, ColIndicesV), lhs) ...); } return row_t(fennec::dot(fennec::column(rhs, ColIndicesV), lhs) ...);
}
/// @} /// @}
@@ -612,24 +605,25 @@ struct matrix
/// \param lhs the first matrix /// \param lhs the first matrix
/// \param rhs the second 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 /// \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) constexpr friend bool operator==(const matrix_t& lhs, const matrix_t& rhs) {
{ return lhs.data == rhs.data; } return lhs.data == rhs.data;
}
/// ///
/// \brief matrix comparison operator /// \brief matrix comparison operator
/// \param lhs the first matrix /// \param lhs the first matrix
/// \param rhs the second 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 /// \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) constexpr friend bool operator!=(const matrix_t& lhs, const matrix_t& rhs) {
{ return lhs.data != rhs.data; } 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
/// \param rhs the columns to multiply with /// \param rhs the columns to multiply with
template<size_t ORowsV, size_t...OColIndicesV> requires(columns == ORowsV) template<size_t ORowsV, size_t...OColIndicesV> requires(columns == ORowsV)
constexpr friend matrix<scalar_t, RowsV, OColIndicesV...> operator*(const matrix_t& lhs, const matrix<scalar_t, ORowsV, OColIndicesV...>& rhs) constexpr friend matrix<scalar_t, RowsV, OColIndicesV...> operator*(const matrix_t& lhs, const matrix<scalar_t, ORowsV, OColIndicesV...>& rhs) {
{
return matrix<scalar_t, RowsV, OColIndicesV...>( return matrix<scalar_t, RowsV, OColIndicesV...>(
matrix::__mul(lhs, rhs[OColIndicesV])... matrix::__mul(lhs, rhs[OColIndicesV])...
); );
@@ -643,46 +637,51 @@ struct matrix
public: public:
static constexpr matrix_t transpose(const transpose_t& mat) static constexpr matrix_t transpose(const transpose_t& mat) {
{ return matrix_t(fennec::row(mat, ColIndicesV)...); } return matrix_t(fennec::row(mat, ColIndicesV)...);
}
private: private:
// ReSharper disable once CppMemberFunctionMayBeStatic // ReSharper disable once CppMemberFunctionMayBeStatic
template<size_t i0 = 0> template<size_t i0 = 0>
constexpr void __construct() { } // base case, does nothing, this will get optimized away constexpr void __construct() {
// base case, does nothing, this will get optimized away
}
// helper for parsing parameter packs // helper for parsing parameter packs
template<size_t i0 = 0, typename HeadT, typename...RestT> template<size_t i0 = 0, typename HeadT, typename...RestT>
constexpr void __construct(HeadT&& head, RestT&&...rest) constexpr void __construct(HeadT&& head, RestT&&...rest) {
{
matrix::__insert<i0>(head); // insert the head element matrix::__insert<i0>(head); // insert the head element
matrix::__construct<i0 + component_count_v<HeadT>>(std::forward<RestT>(rest)...); // propagate to the rest of the arguments matrix::__construct<i0 + component_count_v<HeadT>>(std::forward<RestT>(rest)...); // propagate to the rest of the arguments
} }
// helper for inserting a scalar value // helper for inserting a scalar value
template<size_t i0 = 0> template<size_t i0 = 0>
constexpr void __insert(scalar_t s) constexpr void __insert(scalar_t s) {
{ data[i0 / rows][i0 % rows] = s; } data[i0 / rows][i0 % rows] = s;
}
// helper for inserting a scalar value of differing type // helper for inserting a scalar value of differing type
template<size_t i0 = 0, typename OScalarT> requires(is_arithmetic_v<OScalarT>) template<size_t i0 = 0, typename OScalarT> requires(is_arithmetic_v<OScalarT>)
constexpr void __insert(OScalarT s) constexpr void __insert(OScalarT s) {
{ data[i0 / rows][i0 % rows] = scalar_t(s); } data[i0 / rows][i0 % rows] = scalar_t(s);
}
// helper for inserting a vector // helper for inserting a vector
template<size_t i0 = 0, size_t...i> template<size_t i0 = 0, size_t...i>
constexpr void __insert(const vector<scalar_t, i...>& v) constexpr void __insert(const vector<scalar_t, i...>& v) {
{ (matrix::__insert<i0 + i>(v[i]), ...); } (matrix::__insert<i0 + i>(v[i]), ...);
}
// helper for inserting a vector of differing type // helper for inserting a vector of differing type
template<size_t i0 = 0, typename OScalarT, size_t...i> template<size_t i0 = 0, typename OScalarT, size_t...i>
constexpr void __insert(const vector<OScalarT, i...>& v) constexpr void __insert(const vector<OScalarT, i...>& v) {
{ (matrix::__insert<i0 + i>(v[i]), ...); } (matrix::__insert<i0 + i>(v[i]), ...);
}
// helper for a linear algebraic multiply // helper for a linear algebraic multiply
static constexpr column_t __mul(const matrix_t& lhs, const row_t& rhs) static constexpr column_t __mul(const matrix_t& lhs, const row_t& rhs) {
{
// the compiler will optimize this better than writing out a specific definition // the compiler will optimize this better than writing out a specific definition
// when compared to glm or CxxSwizzle, this is faster by a significant margin // when compared to glm or CxxSwizzle, this is faster by a significant margin
// all implementations provide 7 decimal places of precision // all implementations provide 7 decimal places of precision

View File

@@ -123,8 +123,9 @@ namespace fennec
/// \param x lhs of the expression /// \param x lhs of the expression
/// \param y rhs of the expression /// \param y rhs of the expression
template<typename genType, typename genBType = bool_t, size_t...i> template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> lessThan(const vector<genType, i...>& x, const vector<genType, i...>& y) constexpr vector<genBType, i...> lessThan(const vector<genType, i...>& x, const vector<genType, i...>& y) {
{ return vector<genBType, i...>(x[i] < y[i]...); } return vector<genBType, i...>(x[i] < y[i]...);
}
/// ///
@@ -134,8 +135,9 @@ constexpr vector<genBType, i...> lessThan(const vector<genType, i...>& x, const
/// \param x lhs of the expression /// \param x lhs of the expression
/// \param y rhs of the expression /// \param y rhs of the expression
template<typename genType, typename genBType = bool_t, size_t...i> template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> lessThanEqual(const vector<genType, i...>& x, const vector<genType, i...>& y) constexpr vector<genBType, i...> lessThanEqual(const vector<genType, i...>& x, const vector<genType, i...>& y) {
{ return vector<genBType, i...>(x[i] <= y[i]...); } return vector<genBType, i...>(x[i] <= y[i]...);
}
/// ///
@@ -145,8 +147,9 @@ constexpr vector<genBType, i...> lessThanEqual(const vector<genType, i...>& x, c
/// \param x lhs of the expression /// \param x lhs of the expression
/// \param y rhs of the expression /// \param y rhs of the expression
template<typename genType, typename genBType = bool_t, size_t...i> template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> greaterThan(const vector<genType, i...>& x, const vector<genType, i...>& y) constexpr vector<genBType, i...> greaterThan(const vector<genType, i...>& x, const vector<genType, i...>& y) {
{ return vector<genBType, i...>(x[i] > y[i]...); } return vector<genBType, i...>(x[i] > y[i]...);
}
/// ///
@@ -156,8 +159,9 @@ constexpr vector<genBType, i...> greaterThan(const vector<genType, i...>& x, con
/// \param x lhs of the expression /// \param x lhs of the expression
/// \param y rhs of the expression /// \param y rhs of the expression
template<typename genType, typename genBType = bool_t, size_t...i> template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> greaterThanEqual(const vector<genType, i...>& x, const vector<genType, i...>& y) constexpr vector<genBType, i...> greaterThanEqual(const vector<genType, i...>& x, const vector<genType, i...>& y) {
{ return vector<genBType, i...>(x[i] >= y[i]...); } return vector<genBType, i...>(x[i] >= y[i]...);
}
/// ///
@@ -167,8 +171,9 @@ constexpr vector<genBType, i...> greaterThanEqual(const vector<genType, i...>& x
/// \param x lhs of the expression /// \param x lhs of the expression
/// \param y rhs of the expression /// \param y rhs of the expression
template<typename genType, typename genBType = bool_t, size_t...i> template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> equal(const vector<genType, i...>& x, const vector<genType, i...>& y) constexpr vector<genBType, i...> equal(const vector<genType, i...>& x, const vector<genType, i...>& y) {
{ return vector<genBType, i...>(x[i] == y[i]...); } return vector<genBType, i...>(x[i] == y[i]...);
}
/// ///
@@ -178,8 +183,9 @@ constexpr vector<genBType, i...> equal(const vector<genType, i...>& x, const vec
/// \param x lhs of the expression /// \param x lhs of the expression
/// \param y rhs of the expression /// \param y rhs of the expression
template<typename genType, typename genBType = bool_t, size_t...i> template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> notEqual(const vector<genType, i...>& x, const vector<genType, i...>& y) constexpr vector<genBType, i...> notEqual(const vector<genType, i...>& x, const vector<genType, i...>& y) {
{ return vector<genBType, i...>(x[i] != y[i]...); } return vector<genBType, i...>(x[i] != y[i]...);
}
/// ///
@@ -188,8 +194,9 @@ constexpr vector<genBType, i...> notEqual(const vector<genType, i...>& x, const
/// \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 /// \param x the boolean vector to test
template<typename genBType = bool_t, size_t...i> template<typename genBType = bool_t, size_t...i>
constexpr genBType any(const vector<genBType, i...>& x) constexpr genBType any(const vector<genBType, i...>& x) {
{ return (x[i] || ...); } return (x[i] || ...);
}
/// ///
/// \brief Returns \f$true\f$ if all components of \f$x\f$ are \f$true\f$ /// \brief Returns \f$true\f$ if all components of \f$x\f$ are \f$true\f$
@@ -197,8 +204,9 @@ constexpr genBType any(const vector<genBType, i...>& x)
/// \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 /// \param x the boolean vector to test
template<typename genBType = bool_t, size_t...i> template<typename genBType = bool_t, size_t...i>
constexpr genBType all(const vector<genBType, i...>& x) constexpr genBType all(const vector<genBType, i...>& x) {
{ return (x[i] && ...); } return (x[i] && ...);
}
/// ///
/// \anchor fennec_vector_not /// \anchor fennec_vector_not
@@ -208,8 +216,9 @@ constexpr genBType all(const vector<genBType, i...>& x)
/// \returns the component-wise logical complement of \f$x\f$. /// \returns the component-wise logical complement of \f$x\f$.
/// \param x the boolean vector to inverse /// \param x the boolean vector to inverse
template<typename genBType = bool_t, size_t...i> template<typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> operator not(const vector<genBType, i...>& x) constexpr vector<genBType, i...> operator not(const vector<genBType, i...>& x) {
{ return vector<genBType, i...>((!x[i]) ...); } return vector<genBType, i...>((!x[i]) ...);
}
} }

View File

@@ -77,18 +77,25 @@ public:
/// ///
/// \brief Decay the Swizzle into a Vector /// \brief Decay the Swizzle into a Vector
/// \return The Value of the Swizzle as a Vector /// \return The Value of the Swizzle as a Vector
constexpr VectorT decay() const { VectorT res; return decay_impl(res, make_index_sequence<size>{}); } constexpr VectorT decay() const {
VectorT res;
return decay_impl(res, make_index_sequence<size>{});
}
/// ///
/// \brief Vector Cast Operator /// \brief Vector Cast Operator
/// \returns The Value of the Swizzle as a Vector /// \returns The Value of the Swizzle as a Vector
constexpr explicit operator VectorT() const { return decay(); } constexpr explicit operator VectorT() const {
return decay();
}
swizzle() = default; swizzle() = default;
private: private:
template<size_t...VecIndicesV> template<size_t...VecIndicesV>
constexpr VectorT& decay_impl(VectorT& vec, index_sequence<VecIndicesV...>) { return ((vec[VecIndicesV] = this->data[IndicesV]), ..., vec); } constexpr VectorT& decay_impl(VectorT& vec, index_sequence<VecIndicesV...>) {
return ((vec[VecIndicesV] = this->data[IndicesV]), ..., vec);
}
}; };
} }

View File

@@ -46,7 +46,9 @@ struct swizzle_storage
/// \brief element access, returns a copy of the value at index \p i /// \brief element access, returns a copy of the value at index \p i
/// \param i the index /// \param i the index
/// \returns a copy of the scalar value at index \p i /// \returns a copy of the scalar value at index \p i
constexpr ScalarT operator[](size_t i) const noexcept { return data[indices[i]]; } constexpr ScalarT operator[](size_t i) const noexcept {
return data[indices[i]];
}
}; };
} }

View File

@@ -163,12 +163,14 @@ namespace fennec
/// \tparam genType floating point type /// \tparam genType floating point type
/// \param degrees the angle \f$\theta\f$ in \f$degrees\f$ /// \param degrees the angle \f$\theta\f$ in \f$degrees\f$
template<typename genType> template<typename genType>
constexpr genType radians(genType degrees) constexpr genType radians(genType degrees) {
{ return genType(degrees * 0.01745329251994329576923690768489); } return genType(degrees * 0.01745329251994329576923690768489);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> radians(const vector<genType, i...>& degrees) constexpr vector<genType, i...> radians(const vector<genType, i...>& degrees) {
{ return genType(degrees * 0.01745329251994329576923690768489); } return genType(degrees * 0.01745329251994329576923690768489);
}
/// ///
@@ -180,12 +182,14 @@ constexpr vector<genType, i...> radians(const vector<genType, i...>& degrees)
/// \tparam genType floating point type /// \tparam genType floating point type
/// \param radians the angle \f$\theta\f$ in \f$radians\f$ /// \param radians the angle \f$\theta\f$ in \f$radians\f$
template<typename genType> template<typename genType>
constexpr genType degrees(genType radians) constexpr genType degrees(genType radians) {
{ return genType(radians * 57.29577951308232087679815481410517); } return genType(radians * 57.29577951308232087679815481410517);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> degrees(const vector<genType, i...>& radians) constexpr vector<genType, i...> degrees(const vector<genType, i...>& radians) {
{ return genType(radians * 57.29577951308232087679815481410517); } return genType(radians * 57.29577951308232087679815481410517);
}
/// @} /// @}
@@ -205,12 +209,14 @@ constexpr vector<genType, i...> degrees(const vector<genType, i...>& radians)
/// \tparam genType floating point type /// \tparam genType floating point type
/// \param x the angle \f$\theta\f$ in \f$radians\f$ /// \param x the angle \f$\theta\f$ in \f$radians\f$
template<typename genType> template<typename genType>
constexpr genType sin(genType x) constexpr genType sin(genType x) {
{ return ::sin(x); } return ::sin(x);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> sin(const vector<genType, i...>& x) constexpr vector<genType, i...> sin(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::sin(x[i]) ...); } return vector<genType, i...>(fennec::sin(x[i]) ...);
}
/// ///
@@ -222,12 +228,14 @@ constexpr vector<genType, i...> sin(const vector<genType, i...>& x)
/// \tparam genType floating point type /// \tparam genType floating point type
/// \param x the angle \f$\theta\f$ in \f$radians\f$ /// \param x the angle \f$\theta\f$ in \f$radians\f$
template<typename genType> template<typename genType>
constexpr genType cos(genType x) constexpr genType cos(genType x) {
{ return ::cos(x); } return ::cos(x);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> cos(const vector<genType, i...>& x) constexpr vector<genType, i...> cos(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::cos(x[i]) ...); } return vector<genType, i...>(fennec::cos(x[i]) ...);
}
/// ///
@@ -239,12 +247,14 @@ constexpr vector<genType, i...> cos(const vector<genType, i...>& x)
/// \tparam genType floating point type /// \tparam genType floating point type
/// \param x The Angle \f$\theta\f$ in \f$radians\f$ /// \param x The Angle \f$\theta\f$ in \f$radians\f$
template<typename genType> template<typename genType>
constexpr genType tan(genType x) constexpr genType tan(genType x) {
{ return ::tan(x); } return ::tan(x);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> tan(const vector<genType, i...>& x) constexpr vector<genType, i...> tan(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::tan(x[i]) ...); } return vector<genType, i...>(fennec::tan(x[i]) ...);
}
/// @} /// @}
@@ -263,12 +273,14 @@ constexpr vector<genType, i...> tan(const vector<genType, i...>& x)
/// \tparam genType floating point type /// \tparam genType floating point type
/// \param x The Sine Value produced by \f$\theta\f$ /// \param x The Sine Value produced by \f$\theta\f$
template<typename genType> template<typename genType>
constexpr genType asin(genType x) constexpr genType asin(genType x) {
{ return ::asin(x); } return ::asin(x);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> asin(const vector<genType, i...>& x) constexpr vector<genType, i...> asin(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::asin(x[i]) ...); } return vector<genType, i...>(fennec::asin(x[i]) ...);
}
/// ///
@@ -281,12 +293,14 @@ constexpr vector<genType, i...> asin(const vector<genType, i...>& x)
/// \tparam genType floating point type /// \tparam genType floating point type
/// \param x The Cosine Value produced by \f$\theta\f$ /// \param x The Cosine Value produced by \f$\theta\f$
template<typename genType> template<typename genType>
constexpr genType acos(genType x) constexpr genType acos(genType x) {
{ return ::acos(x); } return ::acos(x);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> acos(const vector<genType, i...>& x) constexpr vector<genType, i...> acos(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::acos(x[i]) ...); } return vector<genType, i...>(fennec::acos(x[i]) ...);
}
/// ///
@@ -299,12 +313,14 @@ constexpr vector<genType, i...> acos(const vector<genType, i...>& x)
/// \tparam genType floating point type /// \tparam genType floating point type
/// \param y_over_x The Cosine Value produced by \f$\theta\f$ /// \param y_over_x The Cosine Value produced by \f$\theta\f$
template<typename genType> template<typename genType>
constexpr genType atan(genType y_over_x) constexpr genType atan(genType y_over_x) {
{ return ::atan(y_over_x); } return ::atan(y_over_x);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> atan(const vector<genType, i...>& y_over_x) constexpr vector<genType, i...> atan(const vector<genType, i...>& y_over_x) {
{ return vector<genType, i...>(fennec::atan(y_over_x[i]) ...); } return vector<genType, i...>(fennec::atan(y_over_x[i]) ...);
}
/// ///
@@ -318,12 +334,15 @@ constexpr vector<genType, i...> atan(const vector<genType, i...>& y_over_x)
/// \param y The Sine Value produced by \f$\theta\f$ /// \param y The Sine Value produced by \f$\theta\f$
/// \param x The Cosine Value produced by \f$\theta\f$ /// \param x The Cosine Value produced by \f$\theta\f$
template<typename genType> template<typename genType>
constexpr genType atan(genType y, genType x) constexpr genType atan(genType y, genType x) {
{ return ::atan2(y, x); } return ::atan2(y, x);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> atan(const vector<genType, i...>& y, const vector<genType, i...>& x) constexpr vector<genType, i...> atan(const vector<genType, i...>& y, const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::atan(y[i], x[i]) ...); } return vector<genType, i...>(fennec::atan(y[i], x[i]) ...);
}
/// @} /// @}
@@ -341,12 +360,14 @@ constexpr vector<genType, i...> atan(const vector<genType, i...>& y, const vecto
/// \tparam genType floating point type /// \tparam genType floating point type
/// \param x The Hyperbolic Angle \f$\alpha\f$ /// \param x The Hyperbolic Angle \f$\alpha\f$
template<typename genType> template<typename genType>
constexpr genType sinh(genType x) constexpr genType sinh(genType x) {
{ return ::sinh(x); } return ::sinh(x);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> sinh(const vector<genType, i...>& x) constexpr vector<genType, i...> sinh(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::sinh(x[i]) ...); } return vector<genType, i...>(fennec::sinh(x[i]) ...);
}
/// ///
@@ -356,12 +377,14 @@ constexpr vector<genType, i...> sinh(const vector<genType, i...>& x)
/// ///
/// \param x The Hyperbolic Angle \f$\alpha\f$ /// \param x The Hyperbolic Angle \f$\alpha\f$
template<typename genType> template<typename genType>
constexpr genType cosh(genType x) constexpr genType cosh(genType x) {
{ return ::cosh(x); } return ::cosh(x);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> cosh(const vector<genType, i...>& x) constexpr vector<genType, i...> cosh(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::cosh(x[i]) ...); } return vector<genType, i...>(fennec::cosh(x[i]) ...);
}
/// ///
@@ -371,12 +394,14 @@ constexpr vector<genType, i...> cosh(const vector<genType, i...>& x)
/// ///
/// \param x The Hyperbolic Angle \f$\alpha\f$ /// \param x The Hyperbolic Angle \f$\alpha\f$
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr genType tanh(genType x) constexpr genType tanh(genType x) {
{ return ::tanh(x); } return ::tanh(x);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> tanh(const vector<genType, i...>& x) constexpr vector<genType, i...> tanh(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::tanh(x[i]) ...); } return vector<genType, i...>(fennec::tanh(x[i]) ...);
}
/// @} /// @}
@@ -392,12 +417,14 @@ constexpr vector<genType, i...> tanh(const vector<genType, i...>& x)
/// ///
/// \param x the hyperbolic angle \f$\alpha\f$ /// \param x the hyperbolic angle \f$\alpha\f$
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr genType asinh(genType x) constexpr genType asinh(genType x) {
{ return ::asinh(x); } return ::asinh(x);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> asinh(const vector<genType, i...>& x) constexpr vector<genType, i...> asinh(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::asinh(x[i]) ...); } return vector<genType, i...>(fennec::asinh(x[i]) ...);
}
/// ///
@@ -408,12 +435,14 @@ constexpr vector<genType, i...> asinh(const vector<genType, i...>& x)
/// ///
/// \param x the hyperbolic angle \f$\alpha\f$ /// \param x the hyperbolic angle \f$\alpha\f$
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr genType acosh(genType x) constexpr genType acosh(genType x) {
{ return ::acosh(x); } return ::acosh(x);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> acosh(const vector<genType, i...>& x) constexpr vector<genType, i...> acosh(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::acosh(x[i]) ...); } return vector<genType, i...>(fennec::acosh(x[i]) ...);
}
/// ///
@@ -424,12 +453,14 @@ constexpr vector<genType, i...> acosh(const vector<genType, i...>& x)
/// ///
/// \param x The Hyperbolic Angle \f$\alpha\f$ /// \param x The Hyperbolic Angle \f$\alpha\f$
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr genType atanh(genType x) constexpr genType atanh(genType x) {
{ return ::atanh(x); } return ::atanh(x);
}
template<typename genType, size_t...i> template<typename genType, size_t...i>
constexpr vector<genType, i...> atanh(const vector<genType, i...>& x) constexpr vector<genType, i...> atanh(const vector<genType, i...>& x) {
{ return vector<genType, i...>(fennec::atanh(x[i]) ...); } return vector<genType, i...>(fennec::atanh(x[i]) ...);
}
/// @} /// @}

View File

@@ -115,33 +115,34 @@
namespace fennec namespace fennec
{ {
/// ///
/// \brief Main \ref fennec_math_vector "vector" template /// \brief Main \ref fennec_math_vector "vector" template
/// \tparam ScalarT The type of the Components /// \tparam ScalarT The type of the Components
/// \tparam SizeV The number of Components /// \tparam SizeV The number of Components
template<typename ScalarT, size_t SizeV> using vec = decltype(detail::__gen_vector<vector, ScalarT>(make_index_sequence<SizeV>{})); template<typename ScalarT, size_t SizeV>
using vec = decltype(detail::__gen_vector<vector, ScalarT>(make_index_sequence<SizeV>{}));
/// ///
/// \brief Shorthand for creating a 2-element \ref fennec::vector, ```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>``` /// \details Shorthand for creating a 2-element \ref fennec::vector, ```vec<ScalarT, 2>```
/// \tparam ScalarT The type of the Components /// \tparam ScalarT The type of the Components
template<typename ScalarT> using tvec2 = vec<ScalarT, 2>; template<typename ScalarT>
using tvec2 = vec<ScalarT, 2>;
/// ///
/// \brief Shorthand for creating a 3-element \ref fennec::vector, ```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>``` /// \details Shorthand for creating a 3-element \ref fennec::vector, ```vec<ScalarT, 3>```
/// \tparam ScalarT The type of the Components /// \tparam ScalarT The type of the Components
template<typename ScalarT> using tvec3 = vec<ScalarT, 3>; template<typename ScalarT>
using tvec3 = vec<ScalarT, 3>;
/// ///
/// \brief Shorthand for creating a 4-element \ref fennec::vector, ```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>``` /// \details Shorthand for creating a 4-element \ref fennec::vector, ```vec<ScalarT, 4>```
/// \tparam ScalarT The type of the Components /// \tparam ScalarT The type of the Components
template<typename ScalarT> using tvec4 = vec<ScalarT, 4>; template<typename ScalarT>
using tvec4 = vec<ScalarT, 4>;
using bvec2 = tvec2<bool_t>; ///< \brief A two-component boolean \ref fennec_math_vector "vector" using bvec2 = tvec2<bool_t>; ///< \brief A two-component boolean \ref fennec_math_vector "vector"
@@ -156,14 +157,19 @@ using uvec2 = tvec2<uint32_t>; ///< \brief A two-component unsigned integer \ref
using uvec3 = tvec3<uint32_t>; ///< \brief A three-component unsigned integer \ref fennec_math_vector "vector" using uvec3 = tvec3<uint32_t>; ///< \brief A three-component unsigned integer \ref fennec_math_vector "vector"
using uvec4 = tvec4<uint32_t>; ///< \brief A four-component unsigned integer \ref fennec_math_vector "vector" using uvec4 = tvec4<uint32_t>; ///< \brief A four-component unsigned integer \ref fennec_math_vector "vector"
using vec2 = tvec2<float_t>; ///< \brief A two-component single-precision floating-point \ref fennec_math_vector "vector" using vec2 = tvec2<float_t>;
using vec3 = tvec3<float_t>; ///< \brief A three-component single-precision floating-point \ref fennec_math_vector "vector" ///< \brief A two-component single-precision floating-point \ref fennec_math_vector "vector"
using vec4 = tvec4<float_t>; ///< \brief A four-component single-precision floating-point \ref fennec_math_vector "vector" using vec3 = tvec3<float_t>;
///< \brief A three-component single-precision floating-point \ref fennec_math_vector "vector"
using dvec2 = tvec2<double_t>; ///< \brief A two-component double-precision floating-point \ref fennec_math_vector "vector" using vec4 = tvec4<float_t>;
using dvec3 = tvec3<double_t>; ///< \brief A three-component double-precision floating-point \ref fennec_math_vector "vector" ///< \brief A four-component single-precision floating-point \ref fennec_math_vector "vector"
using dvec4 = tvec4<double_t>; ///< \brief A four-component double-precision floating-point \ref fennec_math_vector "vector"
using dvec2 = tvec2<double_t>;
///< \brief A two-component double-precision floating-point \ref fennec_math_vector "vector"
using dvec3 = tvec3<double_t>;
///< \brief A three-component double-precision floating-point \ref fennec_math_vector "vector"
using dvec4 = tvec4<double_t>;
///< \brief A four-component double-precision floating-point \ref fennec_math_vector "vector"
/// ///
@@ -171,7 +177,7 @@ using dvec4 = tvec4<double_t>; ///< \brief A four-component double-precision flo
/// \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
/// \nosubgrouping /// \nosubgrouping
template<typename ScalarT, size_t...IndicesV> template<typename ScalarT, size_t... IndicesV>
struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)> struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
{ {
// Assertions ========================================================================================================== // Assertions ==========================================================================================================
@@ -206,7 +212,8 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
static constexpr size_t size = sizeof...(IndicesV); ///< \brief size of the swizzle static constexpr size_t size = sizeof...(IndicesV); ///< \brief size of the swizzle
static constexpr size_t N = sizeof...(IndicesV); ///< \brief size of the swizzle static constexpr size_t N = sizeof...(IndicesV); ///< \brief size of the swizzle
using decay_t = conditional_t<N == 1, scalar_t, vector_t>; ///< Type that the \ref fennec_math_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
/// @} /// @}
@@ -220,7 +227,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \brief default constructor, initializes components with 0 /// \brief default constructor, initializes components with 0
/// ///
/// \details ** ** /// \details ** **
constexpr vector() { data = { 0 }; } constexpr vector() {
data = { 0 };
}
/// ///
@@ -228,7 +237,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// ///
/// \details /// \details
/// \param x object to copy /// \param x object to copy
constexpr vector(const vector_t& x) { data = x.data; } constexpr vector(const vector_t& x) {
data = x.data;
}
/// ///
@@ -236,7 +247,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// ///
/// \details /// \details
/// \param x object to move /// \param x object to move
constexpr vector(vector_t&& x) noexcept { data = std::move(x.data); } constexpr vector(vector_t&& x) noexcept {
data = fennec::move(x.data);
}
/// ///
@@ -244,7 +257,10 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// ///
/// \details /// \details
/// \param s scalar value to initialize with /// \param s scalar value to initialize with
explicit constexpr vector(scalar_t s) { ((data[IndicesV] = s), ...); } explicit constexpr vector(scalar_t s)
: vector() {
((data[IndicesV] = s), ...);
}
/// ///
@@ -252,8 +268,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// ///
/// \details /// \details
/// \param s scalar value to initialize with /// \param s scalar value to initialize with
explicit constexpr vector(int_t s) requires(not is_same_v<ScalarT, int_t>) { explicit constexpr vector(int_t s) requires(not is_same_v<ScalarT, int_t>)
if constexpr(N == 1) data[0] = ScalarT(s); : vector() {
if constexpr (N == 1) data[0] = ScalarT(s);
else ((data[IndicesV] = ScalarT(s)), ...); else ((data[IndicesV] = ScalarT(s)), ...);
} }
@@ -263,21 +280,25 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// ///
/// \details /// \details
/// \param s scalar value to initialize with /// \param s scalar value to initialize with
explicit constexpr vector(double_t s) requires(not is_same_v<ScalarT, double_t>) { explicit constexpr vector(double_t s) requires(not is_same_v<ScalarT, double_t>)
if constexpr(N == 1) data[0] = ScalarT(s); : vector() {
if constexpr (N == 1) data[0] = ScalarT(s);
else ((data[IndicesV] = ScalarT(s)), ...); else ((data[IndicesV] = ScalarT(s)), ...);
} }
/// // This is not in the GLSL spec, I don't remember writing it, and it's behaviour is strange.
/// \brief vector scalar conversion constructor /////
/// ///// \brief vector scalar conversion constructor
/// \details /////
/// \tparam OScalarT scalar Type of the \ref fennec_math_vector "vector" to Convert ///// \details
/// \param v \ref fennec_math_vector "vector" to Convert ///// \tparam OScalarT scalar Type of the \ref fennec_math_vector "vector" to Convert
template<typename OScalarT> ///// \param v \ref fennec_math_vector "vector" to Convert
explicit constexpr vector(const vector<OScalarT, IndicesV...>& v) //template<typename OScalarT>
{ ((data[IndicesV] = ScalarT(v[IndicesV])), ...); } //explicit constexpr vector(const vector<OScalarT, IndicesV...>& v)
//: data() {
// ((data[IndicesV] = ScalarT(v[IndicesV])), ...);
//}
/// ///
@@ -288,9 +309,10 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \tparam MoreIndicesStartV /// \tparam MoreIndicesStartV
/// \tparam MoreIndicesV /// \tparam MoreIndicesV
/// \param v /// \param v
template<typename OScalarT, size_t MoreIndicesStartV, size_t...MoreIndicesV> template<typename OScalarT, size_t MoreIndicesStartV, size_t... MoreIndicesV>
explicit constexpr vector(const vector<OScalarT, IndicesV..., MoreIndicesStartV, MoreIndicesV...>& v) explicit constexpr vector(const vector<OScalarT, IndicesV..., MoreIndicesStartV, MoreIndicesV...>& v) {
{ ((data[IndicesV] = ScalarT(v[IndicesV])), ...); } ((data[IndicesV] = ScalarT(v[IndicesV])), ...);
}
/// ///
@@ -301,9 +323,11 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \tparam SwizzleScalarT swizzle scalar Type /// \tparam SwizzleScalarT swizzle scalar Type
/// \tparam SwizzleIndicesV swizzle Indices /// \tparam SwizzleIndicesV swizzle Indices
/// \param swizzle swizzle object /// \param swizzle swizzle object
template<typename SwizzleDataT, typename SwizzleScalarT, size_t...SwizzleIndicesV> template<typename SwizzleDataT, typename SwizzleScalarT, size_t... SwizzleIndicesV>
explicit constexpr vector(const detail::swizzle_storage<SwizzleDataT, SwizzleScalarT, SwizzleIndicesV...>& swizzle) explicit constexpr vector(
{ ((data[IndicesV] = ScalarT(swizzle[IndicesV])), ...); } const detail::swizzle_storage<SwizzleDataT, SwizzleScalarT, SwizzleIndicesV...>& swizzle) {
((data[IndicesV] = ScalarT(swizzle[IndicesV])), ...);
}
/// ///
@@ -312,9 +336,10 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \details constructs a vector from a series of scalars, swizzles, and vectors /// \details constructs a vector from a series of scalars, swizzles, and vectors
/// \tparam ArgsT argument types /// \tparam ArgsT argument types
/// \param args arguments /// \param args arguments
template<typename...ArgsT> requires(total_component_count_v<ArgsT...> == N) template<typename... ArgsT> requires(total_component_count_v<ArgsT...> == N)
explicit constexpr vector(ArgsT&&...args) explicit constexpr vector(ArgsT&&... args) {
{ vector::__construct<0>(args...); } vector::__construct<0>(args...);
}
/// @} /// @}
@@ -329,8 +354,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// ///
/// \details /// \details
/// \returns scalar if \f$N==1\f$, otherwise, \ref fennec_math_vector "vector" /// \returns scalar if \f$N==1\f$, otherwise, \ref fennec_math_vector "vector"
decay_t decay() decay_t decay() {
{ return static_cast<const decay_t&>(*this); } return static_cast<const decay_t&>(*this);
}
/// @} /// @}
@@ -342,8 +368,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// ///
/// \copydetails vector::operator[](size_t) const /// \copydetails vector::operator[](size_t) const
constexpr scalar_t& operator[](size_t i) constexpr scalar_t& operator[](size_t i) {
{ return data[i]; } return data[i];
}
/// ///
/// \brief indexed access operator /// \brief indexed access operator
@@ -351,8 +378,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \details /// \details
/// \returns a copy of the component /// \returns a copy of the component
/// \param i the index of the component /// \param i the index of the component
constexpr scalar_t operator[](size_t i) const constexpr scalar_t operator[](size_t i) const {
{ return data[i]; } return data[i];
}
/// @} /// @}
@@ -368,8 +396,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \details /// \details
/// \returns A reference to \c this, after having set \p lhs, such that \f$lhs_i=rhs_i\f$ /// \returns A reference to \c this, after having set \p lhs, such that \f$lhs_i=rhs_i\f$
/// \param rhs vector to copy /// \param rhs vector to copy
constexpr vector_t& operator=(const vector_t& rhs) constexpr vector_t& operator=(const vector_t& rhs) {
{ return ((data[IndicesV] = rhs[IndicesV]), ..., *this); } return ((data[IndicesV] = rhs[IndicesV]), ..., *this);
}
/// ///
/// \brief move assignment /// \brief move assignment
@@ -377,8 +406,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \details /// \details
/// \returns A reference to \c this, after having set \p lhs, such that \f$lhs_i=rhs_i\f$ /// \returns A reference to \c this, after having set \p lhs, such that \f$lhs_i=rhs_i\f$
/// \param rhs vector to move /// \param rhs vector to move
constexpr vector_t& operator=(vector_t&& rhs) noexcept constexpr vector_t& operator=(vector_t&& rhs) noexcept {
{ return ((data[IndicesV] = fennec::move(rhs[IndicesV])), ..., *this); } return ((data[IndicesV] = fennec::move(rhs[IndicesV])), ..., *this);
}
/// @} /// @}
@@ -394,8 +424,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \details /// \details
/// \returns **true** if every respective component is equivalent, otherwise returns **false** /// \returns **true** if every respective component is equivalent, otherwise returns **false**
/// \param rhs vector to compare with /// \param rhs vector to compare with
constexpr bool_t operator==(const vector_t& rhs) const constexpr bool_t operator==(const vector_t& rhs) const {
{ return ((data[IndicesV] == rhs.data[IndicesV]) && ...); } return ((data[IndicesV] == rhs.data[IndicesV]) && ...);
}
/// ///
/// \brief vector inequality operator /// \brief vector inequality operator
@@ -403,8 +434,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \details /// \details
/// \returns **false** if every respective component is equivalent, otherwise returns **true** /// \returns **false** if every respective component is equivalent, otherwise returns **true**
/// \param rhs vector to compare with /// \param rhs vector to compare with
constexpr bool_t operator!=(const vector_t& rhs) const constexpr bool_t operator!=(const vector_t& rhs) const {
{ return ((data[IndicesV] != rhs.data[IndicesV]) || ...); } return ((data[IndicesV] != rhs.data[IndicesV]) || ...);
}
/// @} /// @}
@@ -421,8 +453,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
constexpr friend vector_t operator+(scalar_t lhs, const vector_t& rhs) constexpr friend vector_t operator+(scalar_t lhs, const vector_t& rhs) {
{ return vector_t((lhs + rhs[IndicesV]) ...); } return vector_t((lhs + rhs[IndicesV])...);
}
/// ///
/// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" subtraction operator /// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" subtraction operator
@@ -431,8 +464,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
constexpr friend vector_t operator-(scalar_t lhs, const vector_t& rhs) constexpr friend vector_t operator-(scalar_t lhs, const vector_t& rhs) {
{ return vector_t((lhs - rhs[IndicesV]) ...); } return vector_t((lhs - rhs[IndicesV])...);
}
/// ///
/// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" multiplication operator /// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" multiplication operator
@@ -441,8 +475,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i={lhs_i}\cdot{rhs_i}\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i={lhs_i}\cdot{rhs_i}\f$
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
constexpr friend vector_t operator*(scalar_t lhs, const vector_t& rhs) constexpr friend vector_t operator*(scalar_t lhs, const vector_t& rhs) {
{ return vector_t((lhs * rhs[IndicesV]) ...); } return vector_t((lhs * rhs[IndicesV])...);
}
/// ///
/// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" division operator /// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" division operator
@@ -451,8 +486,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=\frac{lhs_i}{rhs_i}\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=\frac{lhs_i}{rhs_i}\f$
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
constexpr friend vector_t operator/(scalar_t lhs, const vector_t& rhs) constexpr friend vector_t operator/(scalar_t lhs, const vector_t& rhs) {
{ return vector_t((lhs / rhs[IndicesV]) ...); } return vector_t((lhs / rhs[IndicesV])...);
}
/// ///
/// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" integer modulus operator /// \brief \ref fennec_math_scalar "scalar" - \ref fennec_math_vector "vector" integer modulus operator
@@ -461,8 +497,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
constexpr friend vector_t operator%(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator%(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
{ return vector_t((lhs % rhs[IndicesV]) ...); } return vector_t((lhs % rhs[IndicesV])...);
}
/// @} /// @}
@@ -478,8 +515,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
constexpr friend vector_t operator+(const vector_t& lhs, scalar_t rhs) constexpr friend vector_t operator+(const vector_t& lhs, scalar_t rhs) {
{ return vector_t((lhs[IndicesV] + rhs) ...); } return vector_t((lhs[IndicesV] + rhs)...);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" subtraction operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" subtraction operator
@@ -488,8 +526,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i-rhs_i\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i-rhs_i\f$
constexpr friend vector_t operator-(const vector_t& lhs, scalar_t rhs) constexpr friend vector_t operator-(const vector_t& lhs, scalar_t rhs) {
{ return vector_t((lhs[IndicesV] - rhs) ...); } return vector_t((lhs[IndicesV] - rhs)...);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" multiplication operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" multiplication operator
@@ -498,8 +537,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i={lhs_i}\cdot{rhs_i}\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i={lhs_i}\cdot{rhs_i}\f$
constexpr friend vector_t operator*(const vector_t& lhs, scalar_t rhs) constexpr friend vector_t operator*(const vector_t& lhs, scalar_t rhs) {
{ return vector_t((lhs[IndicesV] * rhs) ...); } return vector_t((lhs[IndicesV] * rhs)...);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" division operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" division operator
@@ -508,8 +548,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=\frac{lhs_i}{rhs_i}\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=\frac{lhs_i}{rhs_i}\f$
constexpr friend vector_t operator/(const vector_t& lhs, scalar_t rhs) constexpr friend vector_t operator/(const vector_t& lhs, scalar_t rhs) {
{ return vector((lhs[IndicesV] / rhs) ...); } return vector((lhs[IndicesV] / rhs)...);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" integer modulus operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" integer modulus operator
@@ -518,8 +559,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \param lhs left hand side /// \param lhs left hand side
/// \param rhs right hand side /// \param rhs right hand side
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\%rhs_i\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\%rhs_i\f$
constexpr friend vector_t operator%(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator%(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
{ return vector((lhs[IndicesV] % rhs) ...); } return vector((lhs[IndicesV] % rhs)...);
}
/// @} /// @}
@@ -535,8 +577,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t& operator+=(vector_t& lhs, scalar_t rhs) constexpr friend vector_t& operator+=(vector_t& lhs, scalar_t rhs) {
{ return ((lhs[IndicesV] += rhs), ..., lhs); } return ((lhs[IndicesV] += rhs), ..., lhs);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" Subtraction operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" Subtraction operator
@@ -545,8 +588,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t& operator-=(vector_t& lhs, scalar_t rhs) constexpr friend vector_t& operator-=(vector_t& lhs, scalar_t rhs) {
{ return ((lhs[IndicesV] -= rhs), ..., lhs); } return ((lhs[IndicesV] -= rhs), ..., lhs);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" multiplication operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" multiplication operator
@@ -555,8 +599,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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}\cdot{rhs_i}\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i={lhs_i}\cdot{rhs_i}\f$
constexpr friend vector_t& operator*=(vector_t& lhs, scalar_t rhs) constexpr friend vector_t& operator*=(vector_t& lhs, scalar_t rhs) {
{ return ((lhs[IndicesV] *= rhs), ..., lhs); } return ((lhs[IndicesV] *= rhs), ..., lhs);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" division operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" division operator
@@ -565,8 +610,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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=\frac{lhs_i}{rhs_i}\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=\frac{lhs_i}{rhs_i}\f$
constexpr friend vector_t& operator/=(vector_t& lhs, scalar_t rhs) constexpr friend vector_t& operator/=(vector_t& lhs, scalar_t rhs) {
{ return ((lhs[IndicesV] /= rhs), ..., lhs); } return ((lhs[IndicesV] /= rhs), ..., lhs);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" integer modulus operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" integer modulus operator
@@ -575,8 +621,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t& operator%=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t& operator%=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
{ return ((lhs[IndicesV] %= rhs), ..., lhs); } return ((lhs[IndicesV] %= rhs), ..., lhs);
}
/// @} /// @}
@@ -591,8 +638,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \details /// \details
/// \param x the vector /// \param x the vector
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=-x_i\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=-x_i\f$
constexpr friend vector_t operator-(const vector_t& x) constexpr friend vector_t operator-(const vector_t& x) {
{ return vector((-x[IndicesV]) ...); } return vector((-x[IndicesV])...);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" addition operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" addition operator
@@ -601,8 +649,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator+(const vector_t& lhs, const vector_t& rhs) constexpr friend vector_t operator+(const vector_t& lhs, const vector_t& rhs) {
{ return vector((lhs[IndicesV] + rhs[IndicesV]) ...); } return vector((lhs[IndicesV] + rhs[IndicesV])...);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" subtraction operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" subtraction operator
@@ -611,8 +660,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator-(const vector_t& lhs, const vector_t& rhs) constexpr friend vector_t operator-(const vector_t& lhs, const vector_t& rhs) {
{ return vector((lhs[IndicesV] - rhs[IndicesV]) ...); } return vector((lhs[IndicesV] - rhs[IndicesV])...);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" multiplication operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" multiplication operator
@@ -621,16 +671,18 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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}\cdot{rhs_i}\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i={lhs_i}\cdot{rhs_i}\f$
constexpr friend vector_t operator*(const vector_t& lhs, const vector_t& rhs) constexpr friend vector_t operator*(const vector_t& lhs, const vector_t& rhs) {
{ return vector((lhs[IndicesV] * rhs[IndicesV]) ...); } return vector((lhs[IndicesV] * rhs[IndicesV])...);
}
/// ///
/// \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
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=\frac{lhs_i}{rhs_i}\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=\frac{lhs_i}{rhs_i}\f$
constexpr friend vector_t operator/(const vector_t& lhs, const vector_t& rhs) constexpr friend vector_t operator/(const vector_t& lhs, const vector_t& rhs) {
{ return vector((lhs[IndicesV] / rhs[IndicesV]) ...); } return vector((lhs[IndicesV] / rhs[IndicesV])...);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" integer modulus operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" integer modulus operator
@@ -639,8 +691,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator%(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator%(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
{ return vector((lhs[IndicesV] % rhs[IndicesV]) ...); } return vector((lhs[IndicesV] % rhs[IndicesV])...);
}
/// @} /// @}
@@ -656,8 +709,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t& operator+=(vector_t& lhs, const vector_t& rhs) constexpr friend vector_t& operator+=(vector_t& lhs, const vector_t& rhs) {
{ return ((lhs[IndicesV] += rhs[IndicesV]), ..., lhs); } return ((lhs[IndicesV] += rhs[IndicesV]), ..., lhs);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" subtraction operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" subtraction operator
@@ -666,8 +720,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t& operator-=(vector_t& lhs, const vector_t& rhs) constexpr friend vector_t& operator-=(vector_t& lhs, const vector_t& rhs) {
{ return ((lhs[IndicesV] -= rhs[IndicesV]), ..., lhs); } return ((lhs[IndicesV] -= rhs[IndicesV]), ..., lhs);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" multiplication operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" multiplication operator
@@ -676,8 +731,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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}\cdot{rhs_i}\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i={lhs_i}\cdot{rhs_i}\f$
constexpr friend vector_t& operator*=(vector_t& lhs, const vector_t& rhs) constexpr friend vector_t& operator*=(vector_t& lhs, const vector_t& rhs) {
{ return ((lhs[IndicesV] *= rhs[IndicesV]), ..., lhs); } return ((lhs[IndicesV] *= rhs[IndicesV]), ..., lhs);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" division operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" division operator
@@ -686,8 +742,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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=\frac{lhs_i}{rhs_i}\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=\frac{lhs_i}{rhs_i}\f$
constexpr friend vector_t& operator/=(vector_t& lhs, const vector_t& rhs) constexpr friend vector_t& operator/=(vector_t& lhs, const vector_t& rhs) {
{ return ((lhs[IndicesV] /= rhs[IndicesV]), ..., lhs); } return ((lhs[IndicesV] /= rhs[IndicesV]), ..., lhs);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" integer modulus operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" integer modulus operator
@@ -696,8 +753,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t& operator%=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t& operator%=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
{ return ((lhs[IndicesV] %= rhs[IndicesV]), ..., lhs); } return ((lhs[IndicesV] %= rhs[IndicesV]), ..., lhs);
}
/// @} /// @}
@@ -712,8 +770,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \details /// \details
/// \param x the vector /// \param x the vector
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=!x_i\f$ /// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=!x_i\f$
constexpr friend vector_t operator!(const vector_t& x) constexpr friend vector_t operator!(const vector_t& x) {
{ return vector_t(!x[IndicesV] ...); } return vector_t(!x[IndicesV]...);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" logical and operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" logical and operator
@@ -722,16 +781,18 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator&&(const vector_t& lhs, scalar_t rhs) requires(is_bool_v<scalar_t>) constexpr friend vector_t operator&&(const vector_t& lhs, scalar_t rhs) requires(is_bool_v<scalar_t>) {
{ return vector_t((lhs[IndicesV] && rhs) ...); } return vector_t((lhs[IndicesV] && rhs)...);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" logical and operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" logical and operator
/// \param lhs Left Hand Side of the Expression /// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression /// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_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$
constexpr friend vector_t operator&&(const vector_t& lhs, const vector_t& rhs) requires(is_bool_v<scalar_t>) constexpr friend vector_t operator&&(const vector_t& lhs, const vector_t& rhs) requires(is_bool_v<scalar_t>) {
{ return vector_t((lhs[IndicesV] && rhs[IndicesV]) ...); } return vector_t((lhs[IndicesV] && rhs[IndicesV])...);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" logical or operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" logical or operator
@@ -740,8 +801,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator||(const vector_t& lhs, scalar_t rhs) requires(is_bool_v<scalar_t>) constexpr friend vector_t operator||(const vector_t& lhs, scalar_t rhs) requires(is_bool_v<scalar_t>) {
{ return vector_t((lhs[IndicesV] || rhs) ...); } return vector_t((lhs[IndicesV] || rhs)...);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" logical or operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" logical or operator
@@ -750,8 +812,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator||(const vector_t& lhs, const vector_t& rhs) requires(is_bool_v<scalar_t>) constexpr friend vector_t operator||(const vector_t& lhs, const vector_t& rhs) requires(is_bool_v<scalar_t>) {
{ return vector_t((lhs[IndicesV] || rhs[IndicesV]) ...); } return vector_t((lhs[IndicesV] || rhs[IndicesV])...);
}
/// @} /// @}
@@ -767,8 +830,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator&(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator&(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>) {
{ return vector_t((lhs[IndicesV] & rhs) ...); } return vector_t((lhs[IndicesV] & rhs)...);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise and operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise and operator
@@ -777,8 +841,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator&(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator&(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
{ return vector_t((lhs[IndicesV] & rhs) ...); } return vector_t((lhs[IndicesV] & rhs)...);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise and assignment operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise and assignment operator
@@ -787,8 +852,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator&=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator&=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
{ return ((lhs[IndicesV] &= rhs), ..., lhs); } return ((lhs[IndicesV] &= rhs), ..., lhs);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise and operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise and operator
@@ -797,8 +863,10 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator&(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator&(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<
{ return vector_t((lhs[IndicesV] & rhs[IndicesV]) ...); } scalar_t>) {
return vector_t((lhs[IndicesV] & rhs[IndicesV])...);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise and assignment operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise and assignment operator
@@ -807,9 +875,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator&=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator&=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
{ return ((lhs[IndicesV] &= rhs[IndicesV]), ..., lhs); } return ((lhs[IndicesV] &= rhs[IndicesV]), ..., lhs);
}
/// ///
@@ -819,8 +887,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator|(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator|(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>) {
{ return vector_t((lhs[IndicesV] | rhs) ...); } return vector_t((lhs[IndicesV] | rhs)...);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator
@@ -829,8 +898,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator|(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator|(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
{ return vector_t((lhs[IndicesV] | rhs) ...); } return vector_t((lhs[IndicesV] | rhs)...);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or assignment operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or assignment operator
@@ -839,8 +909,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator|=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator|=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
{ return ((lhs[IndicesV] |= rhs), ..., lhs); } return ((lhs[IndicesV] |= rhs), ..., lhs);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or operator
@@ -849,8 +920,10 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator|(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator|(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<
{ return vector_t((lhs[IndicesV] | rhs[IndicesV]) ...); } scalar_t>) {
return vector_t((lhs[IndicesV] | rhs[IndicesV])...);
}
/// ///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator /// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator
@@ -859,9 +932,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator|=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator|=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
{ return ((lhs[IndicesV] |= rhs[IndicesV]), ..., lhs); } return ((lhs[IndicesV] |= rhs[IndicesV]), ..., lhs);
}
/// ///
@@ -869,41 +942,46 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator^(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator^(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
{ return vector_t((lhs ^ rhs[IndicesV]) ...); } return vector_t((lhs ^ rhs[IndicesV])...);
}
/// ///
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise xor operator /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" 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$
constexpr friend vector_t operator^(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator^(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
{ return vector_t((lhs[IndicesV] ^ rhs) ...); } return vector_t((lhs[IndicesV] ^ rhs)...);
}
/// ///
/// \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 xor 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$
constexpr friend vector_t operator^=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator^=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
{ return ((lhs[IndicesV] ^= rhs), ..., lhs); } return ((lhs[IndicesV] ^= rhs), ..., lhs);
}
/// ///
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise xor operator /// \ref fennec_math_vector "vector" - \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$
constexpr friend vector_t operator^(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator^(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<
{ return vector_t((lhs[IndicesV] ^ rhs[IndicesV]) ...); } scalar_t>) {
return vector_t((lhs[IndicesV] ^ rhs[IndicesV])...);
}
/// ///
/// \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 xor 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$
constexpr friend vector_t operator^=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator^=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
{ return ((lhs[IndicesV] ^= rhs[IndicesV]), ..., lhs); } return ((lhs[IndicesV] ^= rhs[IndicesV]), ..., lhs);
}
/// ///
@@ -911,41 +989,45 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator<<(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator<<(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
{ return vector_t((lhs << rhs[IndicesV]) ...); } return vector_t((lhs << rhs[IndicesV])...);
}
/// ///
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift operator /// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift 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$
constexpr friend vector_t operator<<(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator<<(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
{ return vector_t((lhs[IndicesV] << rhs) ...); } return vector_t((lhs[IndicesV] << rhs)...);
}
/// ///
/// \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
/// \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$
constexpr friend vector_t operator<<=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator<<=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
{ return ((lhs[IndicesV] <<= rhs), ..., lhs); } return ((lhs[IndicesV] <<= rhs), ..., lhs);
}
/// ///
/// \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
/// \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$
constexpr friend vector_t operator<<(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator<<(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
{ return vector_t((lhs[IndicesV] << rhs[IndicesV]) ...); } return vector_t((lhs[IndicesV] << rhs[IndicesV])...);
}
/// ///
/// \ref 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
/// \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$
constexpr friend vector_t operator<<=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator<<=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
{ return ((lhs[IndicesV] <<= rhs[IndicesV]), ..., lhs); } return ((lhs[IndicesV] <<= rhs[IndicesV]), ..., lhs);
}
/// ///
@@ -953,40 +1035,45 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \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$
constexpr friend vector_t operator>>(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator>>(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
{ return vector_t((lhs >> rhs[IndicesV]) ...); } return vector_t((lhs >> rhs[IndicesV])...);
}
/// ///
/// \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
/// \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$
constexpr friend vector_t operator>>(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator>>(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
{ return vector_t((lhs[IndicesV] >> rhs) ...); } return vector_t((lhs[IndicesV] >> rhs)...);
}
/// ///
/// \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
/// \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$
constexpr friend vector_t operator>>=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator>>=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
{ return ((lhs[IndicesV] >>= rhs), ..., lhs); } return ((lhs[IndicesV] >>= rhs), ..., lhs);
}
/// ///
/// \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
/// \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$
constexpr friend vector_t operator>>(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator>>(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
{ return vector_t((lhs[IndicesV] >> rhs[IndicesV]) ...); } return vector_t((lhs[IndicesV] >> rhs[IndicesV])...);
}
/// ///
/// \ref 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
/// \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$
constexpr friend vector_t operator>>=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) constexpr friend vector_t operator>>=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
{ return ((lhs[IndicesV] >>= rhs[IndicesV]), ..., lhs); } return ((lhs[IndicesV] >>= rhs[IndicesV]), ..., lhs);
}
/// @} /// @}
@@ -994,30 +1081,34 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
// Helpers ============================================================================================================= // Helpers =============================================================================================================
private: private:
template<size_t IndexV = 0, typename HeadT, typename...TailT> template<size_t IndexV = 0, typename HeadT, typename... TailT>
constexpr void __construct(HeadT&& head, TailT&&...rest) constexpr void __construct(HeadT&& head, TailT&&... rest) {
{
vector::__insert<IndexV>(fennec::forward<HeadT>(head)); vector::__insert<IndexV>(fennec::forward<HeadT>(head));
if constexpr(sizeof...(TailT) > 0) if constexpr (sizeof...(TailT) > 0)
vector::__construct<IndexV + component_count_v<HeadT>>(fennec::forward<TailT>(rest)...); vector::__construct<IndexV + component_count_v<HeadT>>(fennec::forward<TailT>(rest)...);
} }
template<size_t OffsetV> template<size_t OffsetV>
constexpr void __insert(ScalarT& x) constexpr void __insert(ScalarT& x) {
{ data[OffsetV] = x; } data[OffsetV] = x;
}
template<size_t OffsetV, typename OScalarT> template<size_t OffsetV, typename OScalarT>
constexpr void __insert(OScalarT& x) constexpr void __insert(OScalarT& x) {
{ data[OffsetV] = ScalarT(x); } data[OffsetV] = ScalarT(x);
}
template<size_t OffsetV = 0, typename OScalarT, size_t...OIndicesV> template<size_t OffsetV = 0, typename OScalarT, size_t... OIndicesV>
constexpr void __insert(vector<OScalarT, OIndicesV...>& vec) constexpr void __insert(vector<OScalarT, OIndicesV...>& vec) {
{ ((data[OffsetV + OIndicesV] = fennec::forward<OScalarT>(vec[OIndicesV])), ...); } ((data[OffsetV + OIndicesV] = fennec::forward<OScalarT>(vec[OIndicesV])), ...);
}
template<size_t OffsetV = 0, typename OVectorT, typename ODataT, typename OScalarT, size_t...OIndicesV> template<size_t OffsetV = 0, typename OVectorT, typename ODataT, typename OScalarT, size_t... OIndicesV>
constexpr void __insert(swizzle<OVectorT, ODataT, OScalarT, OIndicesV...>& vec) constexpr void __insert(swizzle<OVectorT, ODataT, OScalarT, OIndicesV...>& vec) {
{ size_t i = 0; ((data[OffsetV + (i++)] = vec.data[OIndicesV]), ...); } size_t i = 0;
((data[OffsetV + (i++)] = vec.data[OIndicesV]), ...);
}
}; };
} }

View File

@@ -157,22 +157,34 @@ public:
/// \brief Equality operator /// \brief Equality operator
constexpr bool_t operator==(const allocator&) { return true; } constexpr bool_t operator==(const allocator&) {
return true;
}
/// \brief Inequality operator /// \brief Inequality operator
constexpr bool_t operator!=(const allocator&) { return false; } constexpr bool_t operator!=(const allocator&) {
return false;
}
/// \brief Equality operator for allocators of same type but with different data type /// \brief Equality operator for allocators of same type but with different data type
template<typename U> constexpr bool_t operator==(const allocator<U>&) { return true; } template<typename U> constexpr bool_t operator==(const allocator<U>&) {
return true;
}
/// \brief Inequality operator for allocators of same type but with different data type /// \brief Inequality operator for allocators of same type but with different data type
template<typename U> constexpr bool_t operator!=(const allocator<U>&) { return true; } template<typename U> constexpr bool_t operator!=(const allocator<U>&) {
return true;
}
/// \brief Allocate a block of memory large enough to hold `n` elements of type `T` /// \brief Allocate a block of memory large enough to hold `n` elements of type `T`
constexpr T* allocate(size_t n) { return ::operator new(n * sizeof(T)); } constexpr T* allocate(size_t n) {
return ::operator new(n * sizeof(T));
}
/// \brief Deallocate a block of memory with type `T` /// \brief Deallocate a block of memory with type `T`
constexpr void deallocate(T* ptr) { return ::operator delete(ptr); } constexpr void deallocate(T* ptr) {
return ::operator delete(ptr);
}
}; };
@@ -202,14 +214,16 @@ public:
/// ///
/// \brief Default Constructor, initializes internal data to `null` and the capacity to `0` /// \brief Default Constructor, initializes internal data to `null` and the capacity to `0`
constexpr allocation() noexcept constexpr allocation() noexcept
: _data(nullptr), _capacity(0) {} : _data(nullptr), _capacity(0) {
}
/// ///
/// \brief Sized Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes /// \brief Sized Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes
/// \param n The number of elements of type `T` to allocate for /// \param n The number of elements of type `T` to allocate for
constexpr allocation(size_t n) noexcept constexpr allocation(size_t n) noexcept
: _data(nullptr), _capacity(0) : _data(nullptr), _capacity(0) {
{ allocate(n); } allocate(n);
}
/// ///
/// \brief Buffer Copy Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes. /// \brief Buffer Copy Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes.
@@ -217,8 +231,9 @@ public:
/// \param data the buffer to copy /// \param data the buffer to copy
/// \param n the number of elements /// \param n the number of elements
constexpr allocation(const T* data, size_t n) constexpr allocation(const T* data, size_t n)
: allocation(n) : allocation(n) {
{ fennec::memcpy(_data, data, n); } fennec::memcpy(_data, data, n);
}
/// ///
/// \brief Allocator Constructor /// \brief Allocator Constructor
@@ -226,7 +241,8 @@ public:
/// ///
/// \details This constructor should be used when the type `AllocT` needs internal data. /// \details This constructor should be used when the type `AllocT` needs internal data.
constexpr allocation(const alloc_t& alloc) noexcept constexpr allocation(const alloc_t& alloc) noexcept
: _alloc(alloc), _data(nullptr), _capacity(0) {} : _alloc(alloc), _data(nullptr), _capacity(0) {
}
/// ///
/// \brief Sized Allocator Constructor /// \brief Sized Allocator Constructor
@@ -235,8 +251,9 @@ public:
/// ///
/// \details This constructor should be used when the type `AllocT` needs internal data. /// \details This constructor should be used when the type `AllocT` needs internal data.
constexpr allocation(size_t n, const alloc_t& alloc) noexcept constexpr allocation(size_t n, const alloc_t& alloc) noexcept
: _alloc(alloc), _data(nullptr), _capacity(0) : _alloc(alloc), _data(nullptr), _capacity(0) {
{ allocate(n); } allocate(n);
}
/// ///
/// \brief Buffer Copy Allocator Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes. /// \brief Buffer Copy Allocator Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes.
@@ -247,35 +264,39 @@ public:
/// ///
/// \details This constructor should be used when the type `AllocT` needs internal data. /// \details This constructor should be used when the type `AllocT` needs internal data.
constexpr allocation(const T* data, size_t n, const alloc_t& alloc) constexpr allocation(const T* data, size_t n, const alloc_t& alloc)
: allocation(n, alloc) : allocation(n, alloc) {
{ fennec::memcpy(_data, data, n); } fennec::memcpy(_data, data, n);
}
/// ///
/// \brief Copy Constructor, creates an allocation of equal size and performs a byte-wise copy /// \brief Copy Constructor, creates an allocation of equal size and performs a byte-wise copy
/// \param alloc The allocation to copy /// \param alloc The allocation to copy
constexpr allocation(const allocation& alloc) noexcept constexpr allocation(const allocation& alloc) noexcept
: _alloc(alloc._alloc), _data(_alloc.allocate(alloc._capacity)), _capacity(alloc._capacity) : _alloc(alloc._alloc), _data(_alloc.allocate(alloc._capacity)), _capacity(alloc._capacity) {
{ fennec::memcpy(_data, alloc._data, alloc._capacity * sizeof(T)); } fennec::memcpy(_data, alloc._data, alloc._capacity * sizeof(T));
}
/// ///
/// \brief Move Constructor, moves the data in `alloc` to the new object and cleans `alloc` so that it /// \brief Move Constructor, moves the data in `alloc` to the new object and cleans `alloc` so that it
/// can safely destruct /// can safely destruct
/// \param alloc The allocation to move /// \param alloc The allocation to move
constexpr allocation(allocation&& alloc) noexcept constexpr allocation(allocation&& alloc) noexcept
: _alloc(alloc._alloc), _data(alloc._data), _capacity(alloc._capacity) : _alloc(alloc._alloc), _data(alloc._data), _capacity(alloc._capacity) {
{ alloc._data = nullptr; alloc._capacity = 0; } alloc._data = nullptr; alloc._capacity = 0;
}
/// ///
/// \brief Default Destructor, releases the memory block if still present /// \brief Default Destructor, releases the memory block if still present
constexpr ~allocation() noexcept { if (_data) _alloc.deallocate(_data); } constexpr ~allocation() noexcept {
if (_data) _alloc.deallocate(_data);
}
/// ///
/// \brief Copy Assignment Operator /// \brief Copy Assignment Operator
/// \param alloc the allocation to copy /// \param alloc the allocation to copy
/// \returns a reference to `this` /// \returns a reference to `this`
constexpr allocation& operator=(const allocation& alloc) constexpr allocation& operator=(const allocation& alloc) {
{
allocation::allocate(alloc.capacity()); allocation::allocate(alloc.capacity());
fennec::memcpy(_data, alloc, size()); fennec::memcpy(_data, alloc, size());
return *this; return *this;
@@ -285,8 +306,7 @@ public:
/// \brief Move Assignment Operator /// \brief Move Assignment Operator
/// \param alloc the allocation to copy /// \param alloc the allocation to copy
/// \returns a reference to `this` /// \returns a reference to `this`
constexpr allocation& operator=(allocation&& alloc) noexcept constexpr allocation& operator=(allocation&& alloc) noexcept {
{
// Copy contents // Copy contents
_alloc = alloc._alloc; _alloc = alloc._alloc;
_data = alloc._data; _data = alloc._data;
@@ -303,10 +323,10 @@ public:
/// \brief Allocate a block of memory for the allocation. /// \brief Allocate a block of memory for the allocation.
/// If there is already an allocated block of memory, the previous allocation is released. /// If there is already an allocated block of memory, the previous allocation is released.
/// \param n The number of elements of type `T` to allocate for /// \param n The number of elements of type `T` to allocate for
constexpr void allocate(size_t n) noexcept constexpr void allocate(size_t n) noexcept {
{ if (_data) {
if (_data)
_alloc.deallocate(_data); _alloc.deallocate(_data);
}
_data = _alloc.allocate(_capacity = n); _data = _alloc.allocate(_capacity = n);
} }
@@ -315,8 +335,9 @@ public:
/// \brief Release the block of memory. /// \brief Release the block of memory.
constexpr void release() noexcept constexpr void release() noexcept
{ {
if (_data) if (_data) {
_alloc.deallocate(_data); _alloc.deallocate(_data);
}
_data = nullptr; _data = nullptr;
_capacity = 0; _capacity = 0;
@@ -327,8 +348,9 @@ public:
/// Contents are copied to the new allocation. /// Contents are copied to the new allocation.
constexpr void reallocate(size_t n) noexcept constexpr void reallocate(size_t n) noexcept
{ {
if (_data == nullptr) if (_data == nullptr) {
return _alloc.allocate(_capacity = n); return _alloc.allocate(_capacity = n);
}
value_t* old = _data; value_t* old = _data;
_data = _alloc.allocate(n); _data = _alloc.allocate(n);
@@ -339,25 +361,30 @@ public:
/// ///
/// \brief Clear the block of memory, setting all bytes to 0. /// \brief Clear the block of memory, setting all bytes to 0.
constexpr void clear() noexcept constexpr void clear() noexcept {
{
fennec::memset(_data, 0, _capacity * sizeof(T)); fennec::memset(_data, 0, _capacity * sizeof(T));
} }
/// ///
/// \brief Getter for the byte size of the allocation. /// \brief Getter for the byte size of the allocation.
/// \returns the size of the allocation in bytes /// \returns the size of the allocation in bytes
constexpr size_t size() const { return _capacity * sizeof(T); } constexpr size_t size() const {
return _capacity * sizeof(T);
}
/// ///
/// \brief Getter for the number of elements `n` of type `T` that the allocation can hold. /// \brief Getter for the number of elements `n` of type `T` that the allocation can hold.
/// \returns the size of the allocation in elements /// \returns the size of the allocation in elements
constexpr size_t capacity() const { return _capacity; } constexpr size_t capacity() const {
return _capacity;
}
/// ///
/// \brief Getter for the real pointer to the allocated block of memory /// \brief Getter for the real pointer to the allocated block of memory
/// \returns Pointer to the allocated memory. /// \returns Pointer to the allocated memory.
constexpr value_t* data() { return _data; } constexpr value_t* data() {
return _data;
}
private: private:
alloc_t _alloc; // Allocator object alloc_t _alloc; // Allocator object

View File

@@ -44,7 +44,9 @@ namespace fennec
/// \param obj The object to find the address of /// \param obj The object to find the address of
/// \return The true address of the /// \return The true address of the
template<typename TypeT> template<typename TypeT>
constexpr TypeT* addressof(TypeT& obj) { return FENNEC_BUILTIN_ADDRESSOF(obj); } constexpr TypeT* addressof(TypeT& obj) {
return FENNEC_BUILTIN_ADDRESSOF(obj);
}
/// ///
/// \brief Finds the first occurence of ```static_cast<uint8_t>(ch)``` in the first \f$n\f$ bytes /// \brief Finds the first occurence of ```static_cast<uint8_t>(ch)``` in the first \f$n\f$ bytes
@@ -70,8 +72,9 @@ using ::wmemcmp;
/// \copydoc fennec::memcmp /// \copydoc fennec::memcmp
/// \param n0 The size, in bytes, of lhs /// \param n0 The size, in bytes, of lhs
/// \param n1 The size, in bytes, of rhs /// \param n1 The size, in bytes, of rhs
constexpr int memcmp_s(const void* lhs, size_t n0, const void* rhs, size_t n1) constexpr int memcmp_s(const void* lhs, size_t n0, const void* rhs, size_t n1) {
{ return memcmp(lhs, rhs, n0 < n1 ? n0 : n1); } return memcmp(lhs, rhs, n0 < n1 ? n0 : n1);
}
/// ///
/// \brief Copies the first \f$n\f$ bytes of \f$src\f$ to \f$dst\f$. /// \brief Copies the first \f$n\f$ bytes of \f$src\f$ to \f$dst\f$.
@@ -93,8 +96,9 @@ using ::wmemcpy;
/// \copydoc fennec::memcpy /// \copydoc fennec::memcpy
/// \param n0 The size, in bytes, of dst /// \param n0 The size, in bytes, of dst
/// \param n1 The size, in bytes, of src /// \param n1 The size, in bytes, of src
constexpr void* memcpy_s(void* dst, size_t n0, const void* src, size_t n1) constexpr void* memcpy_s(void* dst, size_t n0, const void* src, size_t n1) {
{ return memcpy(dst, src, n0 < n1 ? n0 : n1); } return memcpy(dst, src, n0 < n1 ? n0 : n1);
}
/// ///
/// \brief Copies the first \f$n\f$ bytes of \f$src\f$ to \f$dst\f$, with overlap correction.. /// \brief Copies the first \f$n\f$ bytes of \f$src\f$ to \f$dst\f$, with overlap correction..
@@ -110,8 +114,9 @@ using ::wmemmove;
/// \copydoc fennec::memmove /// \copydoc fennec::memmove
/// \param n0 The size, in bytes, of dst /// \param n0 The size, in bytes, of dst
/// \param n1 The size, in bytes, of src /// \param n1 The size, in bytes, of src
constexpr void* memmove_s(void* dst, size_t n0, const void* src, size_t n1) constexpr void* memmove_s(void* dst, size_t n0, const void* src, size_t n1) {
{ return memmove(dst, src, n0 < n1 ? n0 : n1); } return memmove(dst, src, n0 < n1 ? n0 : n1);
}
/// ///
/// \brief Sets all bytes of \f$dst\f$ to \f$ch\f$, interpreted as an \f$uint8_t\f$ /// \brief Sets all bytes of \f$dst\f$ to \f$ch\f$, interpreted as an \f$uint8_t\f$

View File

@@ -45,8 +45,9 @@ struct __ptr_traits_ptr_to
using pointer_t = PtrT; using pointer_t = PtrT;
using element_t = ElemT; using element_t = ElemT;
static constexpr pointer_t pointer_to(element_t& obj) static constexpr pointer_t pointer_to(element_t& obj) {
{ return pointer_t::pointer_to(obj); } return pointer_t::pointer_to(obj);
}
}; };
// overload for C style pointers // overload for C style pointers
@@ -56,8 +57,9 @@ struct __ptr_traits_ptr_to<ElemT*, ElemT, false>
using pointer_t = ElemT*; using pointer_t = ElemT*;
using element_t = ElemT; using element_t = ElemT;
static constexpr pointer_t pointer_to(element_t& obj) static constexpr pointer_t pointer_to(element_t& obj) {
{ return addressof(obj); } return addressof(obj);
}
}; };
// underlying implementation for classes that behave like pointers // underlying implementation for classes that behave like pointers

View File

@@ -44,22 +44,30 @@ enum class align_t : size_t;
/// ///
/// \brief Type to handle explicit nothrow definitions /// \brief Type to handle explicit nothrow definitions
struct nothrow_t { explicit nothrow_t() noexcept { } }; struct nothrow_t
{
explicit nothrow_t() noexcept { }
};
template<typename TypeT> void construct(TypeT* ptr) template<typename TypeT> void construct(TypeT* ptr) {
{ ptr->TypeT(); } ptr->TypeT();
}
template<typename TypeT> void construct(TypeT* ptr, const TypeT& val) template<typename TypeT> void construct(TypeT* ptr, const TypeT& val) {
{ ptr->TypeT(val); } ptr->TypeT(val);
}
template<typename TypeT> void construct(TypeT* ptr, TypeT&& val) template<typename TypeT> void construct(TypeT* ptr, TypeT&& val) {
{ ptr->TypeT(fennec::forward<TypeT>(val)); } ptr->TypeT(fennec::forward<TypeT>(val));
}
template<typename TypeT, typename...ArgsT> void construct(TypeT* ptr, ArgsT...args) template<typename TypeT, typename...ArgsT> void construct(TypeT* ptr, ArgsT...args) {
{ ptr->TypeT(fennec::forward<TypeT>(args)...); } ptr->TypeT(fennec::forward<TypeT>(args)...);
}
template<typename TypeT> void destruct(TypeT* ptr) template<typename TypeT> void destruct(TypeT* ptr) {
{ ptr->~TypeT(); } ptr->~TypeT();
}
} }

View File

@@ -43,8 +43,7 @@ struct default_delete
/// ///
/// \brief Function Call Operator, calls `delete` on `ptr` /// \brief Function Call Operator, calls `delete` on `ptr`
/// \param ptr Memory resource to delete /// \param ptr Memory resource to delete
constexpr void operator()(TypeT* ptr) const noexcept constexpr void operator()(TypeT* ptr) const noexcept {
{
static_assert(not is_void_v<TypeT>, "cannot delete a pointer to an incomplete type"); static_assert(not is_void_v<TypeT>, "cannot delete a pointer to an incomplete type");
static_assert(not sizeof(TypeT) > 0, "cannot delete a pointer to an incomplete type"); static_assert(not sizeof(TypeT) > 0, "cannot delete a pointer to an incomplete type");
delete ptr; delete ptr;
@@ -69,8 +68,7 @@ struct default_delete<TypeT[]>
/// \brief Function Call Operator, calls `delete` on `ptr` /// \brief Function Call Operator, calls `delete` on `ptr`
/// \param ptr Memory resource to delete /// \param ptr Memory resource to delete
template<class ArrT> requires requires { is_convertible_v<ArrT(*)[], TypeT(*)[]> == true; } template<class ArrT> requires requires { is_convertible_v<ArrT(*)[], TypeT(*)[]> == true; }
constexpr void operator()(TypeT* ptr) const noexcept constexpr void operator()(TypeT* ptr) const noexcept {
{
static_assert(not is_void_v<TypeT>, "cannot delete a pointer to an incomplete type"); static_assert(not is_void_v<TypeT>, "cannot delete a pointer to an incomplete type");
static_assert(not sizeof(TypeT) > 0, "cannot delete a pointer to an incomplete type"); static_assert(not sizeof(TypeT) > 0, "cannot delete a pointer to an incomplete type");
delete[] ptr; delete[] ptr;
@@ -108,38 +106,45 @@ public:
/// \brief Pointer Constructor, creates a unique_ptr that owns `ptr` with deleter `del` /// \brief Pointer Constructor, creates a unique_ptr that owns `ptr` with deleter `del`
/// \param ptr The resource to own /// \param ptr The resource to own
/// \param del The deleter /// \param del The deleter
explicit constexpr unique_ptr(pointer_t ptr, const delete_t& del) : _delete(del), _handle(ptr) {} explicit constexpr unique_ptr(pointer_t ptr, const delete_t& del)
: _delete(del), _handle(ptr) {
}
/// ///
/// \brief Pointer Constructor, creates a unique_ptr that owns `ptr` with deleter `del` /// \brief Pointer Constructor, creates a unique_ptr that owns `ptr` with deleter `del`
/// \param ptr The resource to own /// \param ptr The resource to own
/// \param del The deleter /// \param del The deleter
explicit constexpr unique_ptr(pointer_t ptr, delete_t&& del) : _delete(del), _handle(ptr) {} explicit constexpr unique_ptr(pointer_t ptr, delete_t&& del)
: _delete(del), _handle(ptr) {
}
/// ///
/// \brief Move Constructor, transfers ownership from `other` /// \brief Move Constructor, transfers ownership from `other`
/// \param other The unique_ptr to take ownership from /// \param other The unique_ptr to take ownership from
constexpr unique_ptr(unique_ptr&& other) : _handle(other._handle) { other._handle = nullptr; } constexpr unique_ptr(unique_ptr&& other)
: _handle(other._handle) {
other._handle = nullptr;
}
// Delete copy constructor // Delete copy constructor
constexpr unique_ptr(const unique_ptr&) = delete; constexpr unique_ptr(const unique_ptr&) = delete;
/// ///
/// \brief Default Constructor, if it owns a resource, it deletes it using `delete_t` /// \brief Default Constructor, if it owns a resource, it deletes it using `delete_t`
constexpr ~unique_ptr() { if(_handle) _delete(_handle); } constexpr ~unique_ptr() {
if(_handle) _delete(_handle);
}
constexpr unique_ptr& operator=(const unique_ptr&) = delete; constexpr unique_ptr& operator=(const unique_ptr&) = delete;
constexpr unique_ptr& operator=(unique_ptr&& r) noexcept constexpr unique_ptr& operator=(unique_ptr&& r) noexcept {
{
_delete = r._delete; _delete = r._delete;
_handle = r._handle; _handle = r._handle;
r._handle = nullptr; r._handle = nullptr;
return *this; return *this;
} }
pointer_t release() pointer_t release() {
{
pointer_t retval = _handle; pointer_t retval = _handle;
_handle = nullptr; _handle = nullptr;
return retval; return retval;