- 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
be used, defining a hook in the private version of the function. This hook is used to clean up any state information
within the engine and may be used to send immediate events to listeners so that outside functionality may decide
how to handle the impending crash. There is nothing that can be done to stop the crash, as soon as the branch
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.

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
friend constexpr bool_t operator==(const array& lhs, const array& rhs)
{ return array::__compare(lhs, rhs, make_index_sequence<ElemV>{}); }
friend constexpr bool_t operator==(const array& lhs, const array& rhs) {
return array::__compare(lhs, rhs, make_index_sequence<ElemV>{});
}
friend constexpr bool_t operator!=(const array& lhs, const array& rhs)
{ return not array::__compare(lhs, rhs, make_index_sequence<ElemV>{}); }
friend constexpr bool_t operator!=(const array& lhs, const array& rhs) {
return not array::__compare(lhs, rhs, make_index_sequence<ElemV>{});
}
/// @}
private:
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) {}
///
/// \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.
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)
{
element_t* addr = _alloc.data();
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();
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 n the number of elements
dynarray(size_t n, const TypeT& val)
{
dynarray(size_t n, const TypeT& val) {
element_t* addr = _alloc.data();
for(; n > 0; --n, ++addr) { fennec::construct(addr, val); }
}
template<typename...ArgsT>
dynarray(size_t n, ArgsT&&...args)
{
dynarray(size_t n, ArgsT&&...args) {
element_t* addr = _alloc.data();
for(; n > 0; --n, ++addr) { fennec::construct(addr, fennec::forward<ArgsT>(args)...); }
}
~dynarray()
{
~dynarray() {
element_t* addr = _alloc.data();
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]; }
const TypeT& operator[](size_t i) const { assertd(i < _size, "Array Out of Bounds"); return _alloc.data()[i]; }
TypeT& operator[](size_t 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
if(_size == capacity()) _grow();
@@ -114,8 +123,8 @@ public:
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
if(_size == capacity()) _grow();
@@ -132,8 +141,8 @@ public:
}
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
if(_size == capacity()) _grow();
@@ -149,10 +158,17 @@ public:
fennec::construct(_alloc.data() + i, fennec::forward<ArgsT>(args)...);
}
void push_back(const TypeT& val) { dynarray::insert(_size, val); }
void push_back(TypeT&& val) { dynarray::insert(_size, fennec::forward<TypeT>(val)); }
void push_back(const 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:
void _grow() const { _alloc.reallocate(_alloc.capacity() * 2); }

View File

@@ -18,13 +18,94 @@
#ifndef FENNEC_FPROC_FILESYSTEM_PATH_H
#define FENNEC_FPROC_FILESYSTEM_PATH_H
#include <fennec/fproc/strings/string.h>
namespace fennec
{
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,18 +60,19 @@ public:
///
/// \brief Default Constructor, initializes with nullptr
constexpr cstring()
: _str(nullptr), _size(0), _const(true)
{ }
: _str(nullptr), _size(0), _const(true) {
}
///
/// \brief Buffer Constructor, wraps the provided C-Style string
/// \param str the buffer to wrap
/// \param n the number of characters in the buffer plus the null terminator
constexpr cstring(char* str, size_t n)
: _str(str)
, _size(n - 1)
, _const(false)
{ assert(_str[n - 1] == '\0', "Invalid NTBS."); }
: _str(str)
, _size(n - 1)
, _const(false) {
assert(_str[n - 1] == '\0', "Invalid NTBS.");
}
///
/// \brief Buffer Constructor, wraps the provided C-Style string
@@ -81,18 +82,20 @@ public:
constexpr cstring(char(&str)[n])
: _str(str)
, _size(n - 1)
, _const(false)
{ assert(_str[n - 1] == '\0', "Invalid NTBS."); }
, _const(false) {
assert(_str[n - 1] == '\0', "Invalid NTBS.");
}
///
/// \brief Const Buffer Constructor, wraps the provided C-Style string
/// \param str the buffer to wrap
/// \param n the number of characters in the buffer plus the null terminator
constexpr cstring(const char* str, size_t n)
: _cstr(str)
, _size(n - 1)
, _const(true)
{ assert(_cstr[n - 1] == '\0', "Invalid NTBS."); }
: _cstr(str)
, _size(n - 1)
, _const(true) {
assert(_cstr[n - 1] == '\0', "Invalid NTBS.");
}
///
/// \brief Buffer Constructor, wraps the provided C-Style string
@@ -100,19 +103,19 @@ public:
/// \tparam n the number of characters in the buffer plus the null terminator
template<size_t n>
constexpr cstring(const char(&str)[n])
: _cstr(str)
, _size(n - 1)
, _const(true)
{ assert(_cstr[n - 1] == '\0', "Invalid NTBS."); }
: _cstr(str)
, _size(n - 1)
, _const(true) {
assert(_cstr[n - 1] == '\0', "Invalid NTBS.");
}
///
/// \brief Move Constructor
/// \param str object to move
constexpr cstring(cstring&& str) noexcept
: _cstr(str._cstr)
, _size(str._size)
, _const(str._const)
{
: _cstr(str._cstr)
, _size(str._size)
, _const(str._const) {
str._cstr = nullptr;
str._size = 0;
str._const = true;
@@ -139,8 +142,7 @@ public:
}
// TODO: Document
constexpr cstring& operator=(cstring&& str) noexcept
{
constexpr cstring& operator=(cstring&& str) noexcept {
_cstr = str._cstr; str._cstr = nullptr;
_size = str._size; str._size = 0;
_const = str._const; str._const = true;
@@ -179,11 +181,15 @@ public:
///
/// \brief Dereference Operator
/// \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
constexpr operator const char*() const { return _cstr; }
constexpr operator const char*() const {
return _cstr;
}
// Examination =========================================================================================================
@@ -198,8 +204,7 @@ public:
/// \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
/// 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;
return ::strcoll(_cstr + i, str);
}
@@ -212,8 +217,7 @@ public:
/// \param c the character to find
/// \param i the index to start at
/// \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
const char* loc = ::strchr(_cstr + i, c); // get location using strchr
return loc ? loc - _cstr : _size; // return size if not found
@@ -224,8 +228,7 @@ public:
/// \param str the string to find
/// \param i the index to start at
/// \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
const char* loc = ::strstr(_cstr + i, str); // get location using strstr
return loc ? loc - _cstr : _size; // return size if not found
@@ -236,8 +239,7 @@ public:
/// \param c the string to find
/// \param i the index to start at
/// \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;
i = min(i, _size - 1); // clamp i to bounds
do {
@@ -251,8 +253,7 @@ public:
/// \param str the string to find
/// \param i the index to start at
/// \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];
i = min(i, _size - str._size);
do {

View File

@@ -51,8 +51,8 @@ public:
///
/// \brief Default Constructor, initializes empty string
constexpr _string()
: _str()
{ }
: _str() {
}
///
/// \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.
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`
@@ -70,8 +70,9 @@ public:
///
/// \details adds additional character for null termination.
constexpr _string(char c, size_t n)
: _str(n + 1)
{ fennec::memset(_str, c, n); _str[n] = '\0'; }
: _str(n + 1) {
fennec::memset(_str, c, n); _str[n] = '\0';
}
///
/// \brief Buffer Copy Constructor
@@ -81,19 +82,19 @@ public:
/// \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.
constexpr _string(const cstring& str)
: _str(str, str.size() + 1)
{ _str[str.size()] = '\0'; }
: _str(str, str.size() + 1) {
_str[str.size()] = '\0';
}
///
/// \brief String Copy Constructor
/// \param str the string to copy
constexpr _string(const string& str)
: _string(str, str.size() - 1)
{ }
: _string(str, str.size() - 1) {
}
constexpr _string(_string&& str) noexcept
: _str(fennec::move(str._str))
{ }
: _str(fennec::move(str._str)) { }
///
/// \brief String Destructor, cleans up the underlying allocation
@@ -103,7 +104,9 @@ public:
///
/// \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 ==============================================================================================================
@@ -129,34 +132,38 @@ public:
///
/// \brief Dereference Operator
/// \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
constexpr operator const char*() const { return _str; }
constexpr operator const char*() const {
return _str; }
// Examination =========================================================================================================
///
/// \returns The length of the string to the first null-terminator
constexpr size_t length() const
{ return find('\0'); }
constexpr size_t length() const {
return find('\0');
}
///
/// \brief String Comparison
/// \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
/// current locale, otherwise a positive value.
constexpr int compare(const string& ostr) const
{ return ::strcoll(_str, ostr); }
constexpr int compare(const string& ostr) const {
return ::strcoll(_str, ostr);
}
///
/// \brief Finds the index of the first occurrence of `x` in the string
/// \param x the character to find
/// \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);
return loc ? loc - _str : size();
}
@@ -165,8 +172,7 @@ public:
/// \brief Finds the index of the first occurrence of `str` in the string.
/// \param str the string to find
/// \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);
return loc ? loc - _str : size();
}
@@ -175,8 +181,7 @@ public:
/// \brief Finds the index of the first occurrence of `str` in the string.
/// \param str the string to find
/// \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);
return loc ? loc - _str : size();
}
@@ -186,8 +191,7 @@ public:
/// \param c the string to find
/// \param i the index to start at
/// \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();
i = min(i, size() - 1); // clamp i to bounds
do {
@@ -201,8 +205,7 @@ public:
/// \param str the string to find
/// \param i the index to start at
/// \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];
i = min(i, size() - str.size());
do {
@@ -217,8 +220,7 @@ public:
/// \param str the string to find
/// \param i the index to start at
/// \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];
i = min(i, size() - str.size());
do {
@@ -233,8 +235,7 @@ public:
///
/// \brief Resize the string, filling additional bytes with `'\0'`
/// \param n the new size of the string
constexpr void resize(size_t n)
{
constexpr void resize(size_t n) {
size_t i = size();
_str.reallocate(n + 1);
if (n > i) fennec::memset(*_str + i, '\0', n - i);
@@ -244,8 +245,7 @@ public:
/// \brief Copy Assignment Operator
/// \param str the string to copy
/// \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());
fennec::memcpy(_str, str, str.size());
_str[str.size()] = '\0';
@@ -256,8 +256,7 @@ public:
/// \brief Move Assignment Operator
/// \param str the string to move
/// \returns a reference to `this`
constexpr string& operator=(string&& str) noexcept
{
constexpr string& operator=(string&& str) noexcept {
_str = fennec::move(str._str);
return *this;
}
@@ -267,8 +266,7 @@ public:
/// \param i the start index
/// \param n the number of characters
/// \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");
n = min(n, size() - i);
return string(&_str[i], n);
@@ -278,50 +276,44 @@ public:
/// \brief Returns a string with `c` appended to it
/// \param c
/// \returns
constexpr string operator+(char c)
{
constexpr string operator+(char c) const {
// Copy contents with one additional byte.
string res(_str, _str.size());
res[size()] = c; // Set the last character to c
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
fennec::memcpy(res, _str, size()); // Copy the contents of this
fennec::memcpy(&res[size()], str, str.size()); // Append the contents of str
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
fennec::memcpy(res, _str, size()); // Copy the contents of this
fennec::memcpy(&res[size()], str, str.size()); // Append the contents of str
return res;
}
constexpr string& operator+=(char c)
{
constexpr string& operator+=(char c) {
size_t x = size();
resize(x + 1);
_str[x] = c;
return *this;
}
constexpr string& operator+=(const string& str)
{
constexpr string& operator+=(const cstring& str) {
size_t x = size();
string::resize(x + str.size());
resize(x + str.size());
fennec::memcpy(&_str[x], str, str.size());
return *this;
}
constexpr string& operator+=(const cstring& str)
{
constexpr string& operator+=(const string& str) {
size_t x = size();
resize(x + str.size());
string::resize(x + str.size());
fennec::memcpy(&_str[x], str, str.size());
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
#define assert(expression, description) \
if(not(expression)) [[unlikely]] \
{ __assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description); }
if(not(expression)) [[unlikely]] { \
__assert_impl(#expression, __FILE__, __LINE__, __PRETTY_FUNCTION__, description); \
}
#ifdef NDEBUG
#define assertd(expression, description) (0)

View File

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

View File

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

View File

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

View File

@@ -103,7 +103,9 @@ template<typename ValueT, ValueT...Values> struct sequence
/// \brief returns the number of elements
///
/// \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
///
/// \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
///
/// \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```
/// \tparam T type to check
template<typename T> constexpr bool_t is_void_v
= is_void<T>::value;
template<typename T> constexpr bool_t is_void_v = is_void<T>::value;
@@ -143,8 +142,7 @@ template<typename T> struct is_bool
///
/// \brief shorthand for ```is_bool<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_bool_v
= is_bool<T>::value;
template<typename T> constexpr bool_t is_bool_v = is_bool<T>::value;
@@ -161,8 +159,7 @@ template<typename T> struct is_null_pointer
///
/// \brief shorthand for ```is_null_pointer<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_null_pointer_v
= is_null_pointer<T>::value;
template<typename T> constexpr bool_t is_null_pointer_v = is_null_pointer<T>::value;
@@ -197,8 +194,7 @@ template<typename T> struct is_array<T[]>
///
/// \brief shorthand for ```is_array<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_array_v
= is_array<T>::value;
template<typename T> constexpr bool_t is_array_v = is_array<T>::value;
// fennec::is_class ====================================================================================================
@@ -211,8 +207,7 @@ template<typename T> struct is_class
///
/// \brief check if \p T is a class
/// \tparam T type to check
template<typename T> constexpr size_t is_class_v
= is_class<T>::value;
template<typename T> constexpr size_t is_class_v = is_class<T>::value;
@@ -229,8 +224,7 @@ template<typename T> struct is_integral
///
/// \brief shorthand for ```is_integral<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_integral_v
= is_integral<T>::value;
template<typename T> constexpr bool_t is_integral_v = is_integral<T>::value;
///
@@ -244,8 +238,7 @@ template<typename T> struct is_signed
///
/// \brief shorthand for ```is_signed<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_signed_v
= is_signed<T>::value;
template<typename T> constexpr bool_t is_signed_v = is_signed<T>::value;
///
@@ -259,8 +252,7 @@ template<typename T> struct is_unsigned
///
/// \brief shorthand for ```is_unsigned<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_unsigned_v
= is_unsigned<T>::value;
template<typename T> constexpr bool_t is_unsigned_v = is_unsigned<T>::value;
@@ -277,8 +269,7 @@ template<typename T> struct is_floating_point
///
/// \brief shorthand for ```is_floating_point<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_floating_point_v
= is_floating_point<T> {};
template<typename T> constexpr bool_t is_floating_point_v = is_floating_point<T> {};
@@ -295,8 +286,7 @@ template<typename T> struct is_arithmetic
///
/// \brief shorthand for ```is_arithmetic<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_arithmetic_v
= is_arithmetic<T>::value;
template<typename T> constexpr bool_t is_arithmetic_v = is_arithmetic<T>::value;
// 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`
/// \tparam T0 first type to check
/// \tparam T1 second type to check
template<typename T0, typename T1> struct is_same
: false_type {};
template<typename T0, typename T1> struct is_same : false_type {};
// true case
template<typename T> struct is_same<T, T>
: true_type {};
template<typename T> struct is_same<T, T> : true_type {};
///
/// \brief shorthand for ```is_same<T0, T1>::value```
/// \tparam T type to check
template<typename T0, typename T1> constexpr bool_t is_same_v
= is_same<T0, T1> {};
template<typename T0, typename T1> constexpr bool_t is_same_v = is_same<T0, T1> {};
// fennec::can_convert =================================================================================================
@@ -334,8 +321,7 @@ template<typename FromT, typename ToT> struct is_convertible
/// \brief shorthand for `can_convert<TypeT0, TypeT1>::value`
/// \param FromT First type
/// \param ToT Second type
template<typename FromT, typename ToT> constexpr bool_t is_convertible_v
= is_convertible<FromT, ToT>{};
template<typename FromT, typename ToT> constexpr bool_t is_convertible_v = is_convertible<FromT, ToT>{};
// fennec::is_constructible ===============================================================================================
@@ -350,8 +336,7 @@ template<typename ClassT, typename...ArgsT> struct is_constructible
///
/// \brief Shorthand for `is_constructible<ClassT, ArgsT...>::value`
template<typename ClassT, typename...ArgsT> constexpr bool_t is_constructible_v
= is_constructible<ClassT, ArgsT...>{};
template<typename ClassT, typename...ArgsT> constexpr bool_t is_constructible_v = is_constructible<ClassT, ArgsT...>{};
// fennec::

View File

@@ -71,10 +71,14 @@ namespace fennec
/// \tparam T base type of the object
/// \param x reference to the object
/// \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&&
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
/// \param x object to be moved
/// \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
/// \param x object to be copied
/// \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
template<typename genType>
constexpr genType sign(genType x)
{ return (x < genType(0) ? genType(-1) : genType(1)) * static_cast<genType>(x != 0); } // reduces to cmove
constexpr genType sign(genType x) {
return (x < genType(0) ? genType(-1) : genType(1)) * static_cast<genType>(x != 0); // reduces to cmove
}
// Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i>
constexpr vector<genType, i...> sign(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::sign(x[i]) ...); }
constexpr vector<genType, i...> sign(const vector<genType, i...>& x) {
return vector<genType, i...>(fennec::sign(x[i]) ...);
}
// Absolute Value ======================================================================================================
@@ -323,15 +325,17 @@ constexpr vector<genType, i...> sign(const vector<genType, i...>& x)
///
/// \param x input value
template<typename genType>
constexpr genType abs(genType x)
{ return x * fennec::sign(x); }
constexpr genType abs(genType x) {
return x * fennec::sign(x);
}
// Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i>
constexpr vector<genType, i...> abs(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::abs(x[i]) ...); }
constexpr vector<genType, i...> abs(const vector<genType, i...>& x) {
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
template<typename genType>
constexpr genType floor(genType x)
{ return ::floor(x); }
constexpr genType floor(genType x) {
return ::floor(x);
}
// Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i>
constexpr vector<genType, i...> floor(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::floor(x[i]) ...); }
constexpr vector<genType, i...> floor(const vector<genType, i...>& x) {
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
template<typename genType>
constexpr genType ceil(genType x)
{ return ::ceil(x); }
constexpr genType ceil(genType x) {
return ::ceil(x);
}
// Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i>
constexpr vector<genType, i...> ceil(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::ceil(x[i]) ...); }
constexpr vector<genType, i...> ceil(const vector<genType, i...>& x) {
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>
///
/// \param x input value
template<typename genType> constexpr genType round(genType x)
{ return ::round(x); }
template<typename genType> constexpr genType round(genType x) {
return ::round(x);
}
// Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i>
constexpr vector<genType, i...> round(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::round(x[i]) ...); }
constexpr vector<genType, i...> round(const vector<genType, i...>& x) {
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
template<typename genType>
constexpr genType trunc(genType x)
{ return ::trunc(x); }
constexpr genType trunc(genType x) {
return ::trunc(x);
}
// Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i>
constexpr vector<genType, i...> trunc(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::trunc(x[i]) ...); }
constexpr vector<genType, i...> trunc(const vector<genType, i...>& x) {
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
template<typename genType>
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);
constexpr genType roundEven(genType x) {
static const genType e = std::numeric_limits<genType>::epsilon();
int I = static_cast<int>(x);
genType i = static_cast<genType>(I);
@@ -469,13 +471,25 @@ constexpr genType roundEven(genType x)
bool dir = (I % 2);
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 ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i>
constexpr vector<genType, i...> roundEven(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::roundEven(x[i]) ...); }
constexpr vector<genType, i...> roundEven(const vector<genType, i...>& x) {
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
template<typename genType>
constexpr genType fract(genType x)
{ return x - ::floor(x); }
constexpr genType fract(genType x) {
return x - ::floor(x);
}
// Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i>
constexpr vector<genType, i...> fract(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::fract(x[i]) ...); }
constexpr vector<genType, i...> fract(const vector<genType, i...>& x) {
return vector<genType, i...>(fennec::fract(x[i]) ...);
}
// Mod =================================================================================================================
@@ -522,20 +537,22 @@ constexpr vector<genType, i...> fract(const vector<genType, i...>& x)
/// \param x dividend
/// \param y divisor
template<typename genType>
constexpr genType mod(genType x, genType y)
{ return x - y * fennec::floor(x / y); }
constexpr genType mod(genType x, genType y) {
return x - y * fennec::floor(x / y);
}
// Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i>
constexpr vector<genType, i...> mod(const vector<genType, i...>& x, genType y)
{ return x - y * fennec::floor(x / y); }
constexpr vector<genType, i...> mod(const vector<genType, i...>& x, genType y) {
return x - y * fennec::floor(x / y);
}
template<typename genType, size_t...i>
constexpr vector<genType, i...> mod(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return x - y * fennec::floor(x / y); }
constexpr vector<genType, i...> mod(const vector<genType, i...>& x, const vector<genType, i...>& y) {
return x - y * fennec::floor(x / y);
}
// ModF ================================================================================================================
@@ -550,16 +567,17 @@ constexpr vector<genType, i...> mod(const vector<genType, i...>& x, const vector
/// \param x input value
/// \param i integral out
template<typename genType>
constexpr genType modf(genType x, genType& i)
{ i = fennec::floor(x); return fennec::fract(x); }
constexpr genType modf(genType x, genType& i) {
i = fennec::floor(x); return fennec::fract(x);
}
// Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i>
constexpr vector<genType, i...> modf(const vector<genType, i...>& x, vector<genType, i...>& I)
{ I = fennec::floor(x); return fennec::fract(x); }
constexpr vector<genType, i...> modf(const vector<genType, i...>& x, vector<genType, i...>& I) {
I = fennec::floor(x); return fennec::fract(x);
}
// Is NaN ==============================================================================================================
@@ -578,16 +596,17 @@ constexpr vector<genType, i...> modf(const vector<genType, i...>& x, vector<genT
///
/// \param x input value
template<typename genType, typename genBType = bool_t> requires(is_bool_v<genBType>)
constexpr genBType isnan(genType x)
{ return ::isnanf(x); }
constexpr genBType isnan(genType x) {
return ::isnanf(x);
}
// Vector Specializations ----------------------------------------------------------------------------------------------
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)
{ return vector<genBType, i...>(fennec::isnan(x[i]) ...); }
constexpr vector<genBType, i...> isnan(const vector<genType, i...>& x) {
return vector<genBType, i...>(fennec::isnan(x[i]) ...);
}
// Is Inf ==============================================================================================================
@@ -601,15 +620,17 @@ constexpr vector<genBType, i...> isnan(const vector<genType, i...>& x)
///
/// \param x input value
template<typename genType, typename genBType = bool_t> requires(is_bool_v<genBType>)
constexpr genBType isinf(genType x)
{ return ::isinff(x); }
constexpr genBType isinf(genType x) {
return ::isinff(x);
}
// Vector Specializations ----------------------------------------------------------------------------------------------
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)
{ return vector<genBType, i...>(fennec::isinf(x[i]) ...); }
constexpr vector<genBType, i...> isinf(const vector<genType, i...>& x) {
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)
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)
{ return fennec::bit_cast<genIType>(x); }
constexpr genIType floatBitsToInt(genType x) {
return fennec::bit_cast<genIType>(x);
}
///
/// \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
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)
{ return fennec::bit_cast<genUType>(x); }
constexpr genUType floatBitsToUint(genType x) {
return fennec::bit_cast<genUType>(x);
}
///
/// \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))
constexpr genType intBitsToFloat(genIType x)
{ return fennec::bit_cast<genType>(x); }
constexpr genType intBitsToFloat(genIType x) {
return fennec::bit_cast<genType>(x);
}
///
@@ -663,27 +689,32 @@ constexpr genType intBitsToFloat(genIType x)
///
/// \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))
constexpr genType uintBitsToFloat(genUType x)
{ return fennec::bit_cast<genType>(x); }
constexpr genType uintBitsToFloat(genUType x) {
return fennec::bit_cast<genType>(x);
}
// 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))
constexpr vector<genIType, i...> floatBitsToInt(const vector<genType, i...>& x)
{ return vector<genIType, i...>(fennec::bit_cast<genIType>(x[i])...); }
constexpr vector<genIType, i...> floatBitsToInt(const vector<genType, i...>& x) {
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))
constexpr vector<genUType, i...> floatBitsToUint(const vector<genType, i...>& x)
{ return vector<genUType, i...>(fennec::bit_cast<genUType>(x[i])...); }
constexpr vector<genUType, i...> floatBitsToUint(const vector<genType, i...>& x) {
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))
constexpr vector<genType, i...> intBitsToFloat(const vector<genIType, i...>& x)
{ return vector<genType, i...>(fennec::bit_cast<genType>(x[i]) ...); }
constexpr vector<genType, i...> intBitsToFloat(const vector<genIType, i...>& x) {
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))
constexpr vector<genType, i...> uintBitsToFloat(const vector<genUType, i...>& x)
{ return vector<genType, i...>(fennec::bit_cast<genType>(x[i]) ...); }
constexpr vector<genType, i...> uintBitsToFloat(const vector<genUType, i...>& x) {
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 c the addend
template<typename genType>
constexpr genType fma(genType a, genType b, genType c)
{ return genType(::fma(a, b, c)); }
constexpr genType fma(genType a, genType b, genType c) {
return genType(::fma(a, b, c));
}
// Vector Specializations ----------------------------------------------------------------------------------------------
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)
{ return vector<genType, i...>(fennec::fma(a[i], b[i], c[i]) ...); }
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]) ...);
}
@@ -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 exp The variable to store the exponent in
template<typename genType, typename genIType = int_t> requires(is_integral_v<genIType>)
constexpr genType frexp(genType x, genIType& exp)
{ return ::frexp(x, &exp); }
constexpr genType frexp(genType x, genIType& exp) {
return ::frexp(x, &exp);
}
// Vector Specializations ----------------------------------------------------------------------------------------------
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)
{ return vector<genType, i...>(fennec::frexp(x[i], exp[i])...); }
constexpr vector<genType, i...> frexp(const vector<genType, i...>& x, vector<genIType, i...>& exp) {
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 exp The exponent
template<typename genType, typename genIType = int_t> requires(is_integral_v<genIType>)
constexpr genType ldexp(genType x, genIType exp)
{ return ::ldexp(x, exp); }
constexpr genType ldexp(genType x, genIType exp) {
return ::ldexp(x, exp);
}
// Vector Specializations ----------------------------------------------------------------------------------------------
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)
{ return vector<genType, i...>(fennec::ldexp(x[i], exp[i])...); }
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])...);
}
/// @}
@@ -793,24 +830,27 @@ constexpr vector<genType, i...> ldexp(const vector<genType, i...>& x, const vect
/// \param x input value \f$x\f$
/// \param y input value \f$y\f$
template<typename genType>
constexpr genType min(genType x, genType y)
{ return (y < x) ? y : x; }
constexpr genType min(genType x, genType y) {
return (y < x) ? y : x;
}
// Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i>
constexpr vector<genType, i...> min(genType x, const vector<genType, i...>& y)
{ return vector<genType, i...>(fennec::min(x, y[i]) ...); }
constexpr vector<genType, i...> min(genType x, const vector<genType, i...>& y) {
return vector<genType, i...>(fennec::min(x, y[i]) ...);
}
template<typename genType, size_t...i>
constexpr vector<genType, i...> min(const vector<genType, i...>& x, genType y)
{ return vector<genType, i...>(fennec::min(x[i], y) ...); }
constexpr vector<genType, i...> min(const vector<genType, i...>& x, genType y) {
return vector<genType, i...>(fennec::min(x[i], y) ...);
}
template<typename genType, size_t...i>
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]) ...); }
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]) ...);
}
// Max =================================================================================================================
@@ -825,23 +865,27 @@ constexpr vector<genType, i...> min(const vector<genType, i...>& x, const vector
/// \param x first input value
/// \param y second input value
template<typename genType>
constexpr genType max(genType x, genType y)
{ return (x < y) ? y : x; }
constexpr genType max(genType x, genType y) {
return (x < y) ? y : x;
}
// Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i>
constexpr vector<genType, i...> max(genType x, const vector<genType, i...>& y)
{ return vector<genType, i...>(fennec::max(x, y[i]) ...); }
constexpr vector<genType, i...> max(genType x, const vector<genType, i...>& y) {
return vector<genType, i...>(fennec::max(x, y[i]) ...);
}
template<typename genType, size_t...i>
constexpr vector<genType, i...> max(const vector<genType, i...>& x, genType y)
{ return vector<genType, i...>(fennec::max(x[i], y) ...); }
constexpr vector<genType, i...> max(const vector<genType, i...>& x, genType y) {
return vector<genType, i...>(fennec::max(x[i], y) ...);
}
template<typename genType, size_t...i>
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]) ...); }
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]) ...);
}
// Clamp ===============================================================================================================
@@ -857,19 +901,22 @@ constexpr vector<genType, i...> max(const vector<genType, i...>& x, const vector
/// \param minVal minimum value
/// \param maxVal maximum value
template<typename genType>
constexpr genType clamp(genType x, genType minVal, genType maxVal)
{ return min(max(x, minVal), maxVal); }
constexpr genType clamp(genType x, genType minVal, genType maxVal) {
return min(max(x, minVal), maxVal);
}
// Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i>
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)...); }
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)...);
}
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)
{ return vector<genType, i...>(fennec::min(fennec::max(x[i], minVal[i]), maxVal[i])...); }
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])...);
}
/// @}
@@ -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 x The coordinate of the sample location
template<typename genType> requires(is_floating_point_v<genType>)
constexpr genType step(genType edge, genType x)
{ return static_cast<genType>(not(x < edge)); }
constexpr genType step(genType edge, genType x) {
return static_cast<genType>(not(x < edge));
}
// Vector Specializations ----------------------------------------------------------------------------------------------
template<typename genType, size_t...i> requires(is_floating_point_v<genType>)
constexpr vector<genType, i...> step(genType edge, const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::step(edge, x[i]) ...); }
constexpr vector<genType, i...> step(genType edge, const vector<genType, i...>& x) {
return vector<genType, i...>(fennec::step(edge, x[i]) ...);
}
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)
{ return vector<genType, i...>(fennec::step(edge[i], x[i]) ...); }
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]) ...);
}
// 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 x \f$x\f$ coordinate input
template<typename genType> requires(is_floating_point_v<genType>)
constexpr genType smoothstep(genType edge0, genType edge1, genType x)
{ genType t = fennec::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f); return t * t * (3 - 2 * t); }
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);
}
// Vector Specializations ----------------------------------------------------------------------------------------------
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)
{ return vector<genType, i...>(fennec::smoothstep(edge0, edge1, x[i]) ...); }
constexpr vector<genType, i...> smoothstep(genType edge0, genType edge1, const vector<genType, i...>& x) {
return vector<genType, i...>(fennec::smoothstep(edge0, edge1, x[i]) ...);
}
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)
{ return vector<genType, i...>(fennec::smoothstep(edge0[i], edge1[i], x[i]) ...); }
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]) ...);
}
// Mix =================================================================================================================
@@ -963,18 +1016,21 @@ constexpr vector<genType, i...> smoothstep(const vector<genType, i...>& edge0, c
/// \param y Second value
/// \param a Interpolant
template<typename genType> requires(is_floating_point_v<genType>)
constexpr genType mix(genType x, genType y, genType a)
{ return x * (genType(1.0) - a) + y * a; }
constexpr genType mix(genType x, genType y, genType a) {
return x * (genType(1.0) - a) + y * a;
}
// Vector Specializations ----------------------------------------------------------------------------------------------
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)
{ return x * (genType(1.0) - a) + y * 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;
}
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)
{ return x * (genType(1.0) - a) + y * 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;
}
// Mix (Bool) ==========================================================================================================
@@ -995,24 +1051,28 @@ constexpr vector<genType, i...> mix(const vector<genType, i...>& x, const vector
/// \param y False Value
/// \param a Boolean Value
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)
{ return a ? y : x; }
constexpr genType mix(genType x, genType y, genBType a) {
return a ? y : x;
}
// Vector Specializations ----------------------------------------------------------------------------------------------
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)
{ return genDType((a ? y[i] : x[i])...); }
constexpr vector<genType, i...> mix(const vector<genType, i...>& x, const vector<genType, i...>& y, genBType a) {
return genDType((a ? y[i] : x[i])...);
}
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)
{ return genBType((a[i] ? y[i] : x[i])...); }
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])...);
}
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)
{ return genDType((a[i] ? y[i] : x[i])...); }
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])...);
}
/// @}

View File

@@ -28,7 +28,7 @@ template<typename ScalarT, size_t...IndicesV> struct vector; //
template<typename ScalarT, size_t RowsV, size_t...ColIndicesV> struct matrix; // Forward def for matrices
// Simplified interface for creating sized vectors or matrices
template<typename ScalarT, size_t SizeV> using vec
template<typename ScalarT, size_t SizeV> using vec
= decltype(detail::__gen_vector<vector, ScalarT>(make_index_sequence<SizeV>{})); // Gets the type returned by this function
template<typename ScalarT, size_t ColsV, size_t RowsV> using mat

View File

@@ -26,16 +26,14 @@ namespace fennec
// specialization for mat2
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];
}
// specialization for mat3
template<typename scalar, size_t rows, size_t...cols> requires(rows == 3 && sizeof...(cols) == 3)
constexpr scalar determinant(const matrix<scalar, rows, cols...>& m)
{
// Cofactor expansion over first column, better for cache locality than the first row
constexpr scalar determinant(const matrix<scalar, rows, cols...>& m) {
// Cofactor expansion over first column
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][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
template<typename scalar, size_t rows, size_t...cols> requires(rows == 4 && sizeof...(cols) == 4)
constexpr scalar determinant(const matrix<scalar, rows, cols...>& m)
{
// Cofactor expansion over the first column, better for cache locality than the first row
constexpr scalar determinant(const matrix<scalar, rows, cols...>& m) {
// Cofactor expansion over the first column
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 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
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);
return matrix<scalar, rows, cols...>(
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
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);
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)
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 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];

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$.
@@ -104,15 +104,20 @@ namespace fennec
/// \param x the base
/// \param y the exponent
template<typename genType>
constexpr genType pow(genType x, genType y)
{ return ::pow(x, y); }
constexpr genType pow(genType x, genType y) {
return ::pow(x, y);
}
// Vector Specialization -----------------------------------------------------------------------------------------------
template<typename genType, size_t...i>
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]) ...); }
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]) ...);
}
// exp -----------------------------------------------------------------------------------------------------------------
// exp =================================================================================================================
///
/// \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
template<typename genType>
constexpr genType exp(genType 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]) ...); }
constexpr genType exp(genType x) {
return ::exp(x);
}
// 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$
@@ -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>
///
/// \param x the exponent
template<typename genType> constexpr genType exp2(genType 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]) ...); }
template<typename genType> constexpr genType exp2(genType x) {
return ::exp2(x);
}
// 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$.
@@ -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>
///
/// \param x the input value
template<typename genType> constexpr genType log(genType 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]) ...); }
template<typename genType> constexpr genType log(genType x) {
return ::log(x);
}
// 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$.
@@ -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>
///
/// \param x the input value
template<typename genType> constexpr genType log2(genType 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]) ...); }
template<typename genType> constexpr genType log2(genType x) {
return ::log2(x);
}
// 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$.
@@ -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>
///
/// \param x the input value
template<typename genType> constexpr genType sqrt(genType 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]) ...); }
template<typename genType> constexpr genType sqrt(genType x) {
return ::sqrt(x);
}
// 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$.
@@ -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>
///
/// \param x the input value
template<typename genType> constexpr genType inversesqrt(genType x)
{ return 1.0f / ::sqrt(x); }
template<typename genType> constexpr genType inversesqrt(genType x) {
return 1.0f / ::sqrt(x);
}
// Vector Specialization -----------------------------------------------------------------------------------------------
template<typename genType, size_t...i>
constexpr vector<genType, i...> inversesqrt(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::inversesqrt(x[i]) ...); }
constexpr vector<genType, i...> inversesqrt(const vector<genType, i...>& x) {
return vector<genType, i...>(fennec::inversesqrt(x[i]) ...);
}
}

View File

@@ -538,8 +538,11 @@
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 ==================================================================================================

View File

@@ -130,8 +130,9 @@ namespace fennec
/// \param x first vector
/// \param y second vector
template<typename genType, size_t...i>
constexpr genType dot(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return ((x[i] * y[i]) + ...); }
constexpr genType dot(const vector<genType, i...>& x, const vector<genType, i...>& y) {
return ((x[i] * y[i]) + ...);
}
// length2 -------------------------------------------------------------------------------------------------------------
@@ -147,8 +148,9 @@ constexpr genType dot(const vector<genType, i...>& x, const vector<genType, i...
///
/// \param x the vector
template<typename genType, size_t...i>
constexpr genType length2(const vector<genType, i...>& x)
{ return fennec::dot(x, x); }
constexpr genType length2(const vector<genType, i...>& x) {
return fennec::dot(x, x);
}
// length --------------------------------------------------------------------------------------------------------------
@@ -164,7 +166,9 @@ constexpr genType length2(const vector<genType, i...>& x)
///
/// \param x the vector
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 ------------------------------------------------------------------------------------------------------------
@@ -182,8 +186,9 @@ constexpr genType length(const vector<genType, i...>& x) { return fennec::sqrt(f
/// \param p0 first vector
/// \param p1 second vector
template<typename genType, size_t...i>
constexpr genType distance(const vector<genType, i...>& p0, const vector<genType, i...>& p1)
{ return fennec::length(p1 - p0); }
constexpr genType distance(const vector<genType, i...>& p0, const vector<genType, i...>& p1) {
return fennec::length(p1 - p0);
}
// cross ---------------------------------------------------------------------------------------------------------------
@@ -203,8 +208,9 @@ constexpr genType distance(const vector<genType, i...>& p0, const vector<genType
/// \param x first vector
/// \param y second vector
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)
{ 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]); }
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]);
}
// normalize -----------------------------------------------------------------------------------------------------------
@@ -220,8 +226,9 @@ constexpr vector<genType, i...> cross(const vector<genType, i...>& x, const vect
///
/// \param x
template<typename genType, size_t...i>
constexpr vector<genType, i...> normalize(const vector<genType, i...>& x)
{ return x / fennec::length(x); }
constexpr vector<genType, i...> normalize(const vector<genType, i...>& x) {
return x / fennec::length(x);
}
// faceforward ---------------------------------------------------------------------------------------------------------
@@ -235,8 +242,9 @@ constexpr vector<genType, i...> normalize(const vector<genType, i...>& x)
/// \param I the incident
/// \param Nref the reference
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)
{ return fennec::sign(fennec::dot(Nref, I)) * N; }
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;
}
// reflect -------------------------------------------------------------------------------------------------------------
@@ -251,8 +259,9 @@ constexpr vector<genType, i...> faceforward(const vector<genType, i...>& N, cons
/// \param I the incident
/// \param N the surface orientation
template<typename genType, size_t...i>
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; }
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;
}
// refract -------------------------------------------------------------------------------------------------------------
@@ -269,8 +278,7 @@ constexpr vector<genType, i...> reflect(const vector<genType, i...>& I, const ve
/// \param N the surface normal
/// \param eta the ratio of indices of refraction
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 k = genType(1.0) - eta * eta * (genType(1.0) - ndi * ndi);
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_traits.h>
#include <fennec/math/swizzle.h>
// Matrix Types
#include <fennec/math/matrix.h>
// Built-in Functions
#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>
// Common Extensions
#include <fennec/math/ext/constants.h>
#endif // FENNEC_MATH_H

View File

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

View File

@@ -123,8 +123,9 @@ namespace fennec
/// \param x lhs of the expression
/// \param y rhs of the expression
template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> lessThan(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genBType, i...>(x[i] < y[i]...); }
constexpr vector<genBType, i...> lessThan(const vector<genType, i...>& x, const vector<genType, i...>& y) {
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 y rhs of the expression
template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> lessThanEqual(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genBType, i...>(x[i] <= y[i]...); }
constexpr vector<genBType, i...> lessThanEqual(const vector<genType, i...>& x, const vector<genType, i...>& y) {
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 y rhs of the expression
template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> greaterThan(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genBType, i...>(x[i] > y[i]...); }
constexpr vector<genBType, i...> greaterThan(const vector<genType, i...>& x, const vector<genType, i...>& y) {
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 y rhs of the expression
template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> greaterThanEqual(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genBType, i...>(x[i] >= y[i]...); }
constexpr vector<genBType, i...> greaterThanEqual(const vector<genType, i...>& x, const vector<genType, i...>& y) {
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 y rhs of the expression
template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> equal(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genBType, i...>(x[i] == y[i]...); }
constexpr vector<genBType, i...> equal(const vector<genType, i...>& x, const vector<genType, i...>& y) {
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 y rhs of the expression
template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> notEqual(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genBType, i...>(x[i] != y[i]...); }
constexpr vector<genBType, i...> notEqual(const vector<genType, i...>& x, const vector<genType, i...>& y) {
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$
/// \param x the boolean vector to test
template<typename genBType = bool_t, size_t...i>
constexpr genBType any(const vector<genBType, i...>& x)
{ return (x[i] || ...); }
constexpr genBType any(const vector<genBType, i...>& x) {
return (x[i] || ...);
}
///
/// \brief Returns \f$true\f$ if all components of \f$x\f$ are \f$true\f$
@@ -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$
/// \param x the boolean vector to test
template<typename genBType = bool_t, size_t...i>
constexpr genBType all(const vector<genBType, i...>& x)
{ return (x[i] && ...); }
constexpr genBType all(const vector<genBType, i...>& x) {
return (x[i] && ...);
}
///
/// \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$.
/// \param x the boolean vector to inverse
template<typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> operator not(const vector<genBType, i...>& x)
{ return vector<genBType, i...>((!x[i]) ...); }
constexpr vector<genBType, i...> operator not(const vector<genBType, i...>& x) {
return vector<genBType, i...>((!x[i]) ...);
}
}

View File

@@ -77,18 +77,25 @@ public:
///
/// \brief Decay the Swizzle into 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
/// \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;
private:
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
/// \param i the index
/// \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
/// \param degrees the angle \f$\theta\f$ in \f$degrees\f$
template<typename genType>
constexpr genType radians(genType degrees)
{ return genType(degrees * 0.01745329251994329576923690768489); }
constexpr genType radians(genType degrees) {
return genType(degrees * 0.01745329251994329576923690768489);
}
template<typename genType, size_t...i>
constexpr vector<genType, i...> radians(const vector<genType, i...>& degrees)
{ return genType(degrees * 0.01745329251994329576923690768489); }
constexpr vector<genType, i...> radians(const vector<genType, i...>& degrees) {
return genType(degrees * 0.01745329251994329576923690768489);
}
///
@@ -180,12 +182,14 @@ constexpr vector<genType, i...> radians(const vector<genType, i...>& degrees)
/// \tparam genType floating point type
/// \param radians the angle \f$\theta\f$ in \f$radians\f$
template<typename genType>
constexpr genType degrees(genType radians)
{ return genType(radians * 57.29577951308232087679815481410517); }
constexpr genType degrees(genType radians) {
return genType(radians * 57.29577951308232087679815481410517);
}
template<typename genType, size_t...i>
constexpr vector<genType, i...> degrees(const vector<genType, i...>& radians)
{ return genType(radians * 57.29577951308232087679815481410517); }
constexpr vector<genType, i...> degrees(const vector<genType, i...>& radians) {
return genType(radians * 57.29577951308232087679815481410517);
}
/// @}
@@ -205,12 +209,14 @@ constexpr vector<genType, i...> degrees(const vector<genType, i...>& radians)
/// \tparam genType floating point type
/// \param x the angle \f$\theta\f$ in \f$radians\f$
template<typename genType>
constexpr genType sin(genType x)
{ return ::sin(x); }
constexpr genType sin(genType x) {
return ::sin(x);
}
template<typename genType, size_t...i>
constexpr vector<genType, i...> sin(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::sin(x[i]) ...); }
constexpr vector<genType, i...> sin(const vector<genType, i...>& x) {
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
/// \param x the angle \f$\theta\f$ in \f$radians\f$
template<typename genType>
constexpr genType cos(genType x)
{ return ::cos(x); }
constexpr genType cos(genType x) {
return ::cos(x);
}
template<typename genType, size_t...i>
constexpr vector<genType, i...> cos(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::cos(x[i]) ...); }
constexpr vector<genType, i...> cos(const vector<genType, i...>& x) {
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
/// \param x The Angle \f$\theta\f$ in \f$radians\f$
template<typename genType>
constexpr genType tan(genType x)
{ return ::tan(x); }
constexpr genType tan(genType x) {
return ::tan(x);
}
template<typename genType, size_t...i>
constexpr vector<genType, i...> tan(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::tan(x[i]) ...); }
constexpr vector<genType, i...> tan(const vector<genType, i...>& x) {
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
/// \param x The Sine Value produced by \f$\theta\f$
template<typename genType>
constexpr genType asin(genType x)
{ return ::asin(x); }
constexpr genType asin(genType x) {
return ::asin(x);
}
template<typename genType, size_t...i>
constexpr vector<genType, i...> asin(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::asin(x[i]) ...); }
constexpr vector<genType, i...> asin(const vector<genType, i...>& x) {
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
/// \param x The Cosine Value produced by \f$\theta\f$
template<typename genType>
constexpr genType acos(genType x)
{ return ::acos(x); }
constexpr genType acos(genType x) {
return ::acos(x);
}
template<typename genType, size_t...i>
constexpr vector<genType, i...> acos(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::acos(x[i]) ...); }
constexpr vector<genType, i...> acos(const vector<genType, i...>& x) {
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
/// \param y_over_x The Cosine Value produced by \f$\theta\f$
template<typename genType>
constexpr genType atan(genType y_over_x)
{ return ::atan(y_over_x); }
constexpr genType atan(genType y_over_x) {
return ::atan(y_over_x);
}
template<typename genType, size_t...i>
constexpr vector<genType, i...> atan(const vector<genType, i...>& y_over_x)
{ return vector<genType, i...>(fennec::atan(y_over_x[i]) ...); }
constexpr vector<genType, i...> atan(const vector<genType, i...>& y_over_x) {
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 x The Cosine Value produced by \f$\theta\f$
template<typename genType>
constexpr genType atan(genType y, genType x)
{ return ::atan2(y, x); }
constexpr genType atan(genType y, genType x) {
return ::atan2(y, x);
}
template<typename genType, size_t...i>
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]) ...); }
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]) ...);
}
/// @}
@@ -341,12 +360,14 @@ constexpr vector<genType, i...> atan(const vector<genType, i...>& y, const vecto
/// \tparam genType floating point type
/// \param x The Hyperbolic Angle \f$\alpha\f$
template<typename genType>
constexpr genType sinh(genType x)
{ return ::sinh(x); }
constexpr genType sinh(genType x) {
return ::sinh(x);
}
template<typename genType, size_t...i>
constexpr vector<genType, i...> sinh(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::sinh(x[i]) ...); }
constexpr vector<genType, i...> sinh(const vector<genType, i...>& x) {
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$
template<typename genType>
constexpr genType cosh(genType x)
{ return ::cosh(x); }
constexpr genType cosh(genType x) {
return ::cosh(x);
}
template<typename genType, size_t...i>
constexpr vector<genType, i...> cosh(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::cosh(x[i]) ...); }
constexpr vector<genType, i...> cosh(const vector<genType, i...>& x) {
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$
template<typename genType, size_t...i>
constexpr genType tanh(genType x)
{ return ::tanh(x); }
constexpr genType tanh(genType x) {
return ::tanh(x);
}
template<typename genType, size_t...i>
constexpr vector<genType, i...> tanh(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::tanh(x[i]) ...); }
constexpr vector<genType, i...> tanh(const vector<genType, i...>& x) {
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$
template<typename genType, size_t...i>
constexpr genType asinh(genType x)
{ return ::asinh(x); }
constexpr genType asinh(genType x) {
return ::asinh(x);
}
template<typename genType, size_t...i>
constexpr vector<genType, i...> asinh(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::asinh(x[i]) ...); }
constexpr vector<genType, i...> asinh(const vector<genType, i...>& x) {
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$
template<typename genType, size_t...i>
constexpr genType acosh(genType x)
{ return ::acosh(x); }
constexpr genType acosh(genType x) {
return ::acosh(x);
}
template<typename genType, size_t...i>
constexpr vector<genType, i...> acosh(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::acosh(x[i]) ...); }
constexpr vector<genType, i...> acosh(const vector<genType, i...>& x) {
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$
template<typename genType, size_t...i>
constexpr genType atanh(genType x)
{ return ::atanh(x); }
constexpr genType atanh(genType x) {
return ::atanh(x);
}
template<typename genType, size_t...i>
constexpr vector<genType, i...> atanh(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::atanh(x[i]) ...); }
constexpr vector<genType, i...> atanh(const vector<genType, i...>& x) {
return vector<genType, i...>(fennec::atanh(x[i]) ...);
}
/// @}

View File

@@ -115,33 +115,34 @@
namespace fennec
{
///
/// \brief Main \ref fennec_math_vector "vector" template
/// \tparam ScalarT The type of the Components
/// \tparam SizeV The number of Components
template<typename ScalarT, size_t SizeV> using vec = decltype(detail::__gen_vector<vector, ScalarT>(make_index_sequence<SizeV>{}));
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>```
/// \details Shorthand for creating a 2-element \ref fennec::vector, ```vec<ScalarT, 2>```
/// \tparam ScalarT The type of the Components
template<typename ScalarT> using tvec2 = vec<ScalarT, 2>;
template<typename ScalarT>
using tvec2 = vec<ScalarT, 2>;
///
/// \brief Shorthand for creating a 3-element \ref fennec::vector, ```vec<ScalarT, 3>```
/// \details Shorthand for creating a 3-element \ref fennec::vector, ```vec<ScalarT, 3>```
/// \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>```
/// \details Shorthand for creating a 4-element \ref fennec::vector, ```vec<ScalarT, 4>```
/// \tparam ScalarT The type of the Components
template<typename ScalarT> using tvec4 = vec<ScalarT, 4>;
template<typename ScalarT>
using tvec4 = vec<ScalarT, 4>;
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 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 vec3 = tvec3<float_t>; ///< \brief A three-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 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"
using vec2 = tvec2<float_t>;
///< \brief A two-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 vec4 = tvec4<float_t>;
///< \brief A four-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 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 IndicesV index of each Component
/// \nosubgrouping
template<typename ScalarT, size_t...IndicesV>
template<typename ScalarT, size_t... IndicesV>
struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
{
// Assertions ==========================================================================================================
@@ -201,12 +207,13 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
using vector_t = vector;
// Size Aliases
static constexpr size_t dimension = sizeof...(IndicesV); ///< \brief dimension of the swizzle
static constexpr size_t dimension = sizeof...(IndicesV); ///< \brief dimension of the swizzle
static constexpr size_t num_components = sizeof...(IndicesV); ///< \brief number of components
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 size = sizeof...(IndicesV); ///< \brief size of the swizzle
static constexpr size_t N = sizeof...(IndicesV); ///< \brief size of the swizzle
using decay_t = conditional_t<N == 1, scalar_t, vector_t>; ///< Type that the \ref fennec_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
///
/// \details ** **
constexpr vector() { data = { 0 }; }
constexpr vector() {
data = { 0 };
}
///
@@ -228,7 +237,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
///
/// \details
/// \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
/// \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
/// \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,9 +268,10 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
///
/// \details
/// \param s scalar value to initialize with
explicit constexpr vector(int_t s) requires(not is_same_v<ScalarT, int_t>) {
if constexpr(N == 1) data[0] = ScalarT(s);
else ((data[IndicesV] = ScalarT(s)), ...);
explicit constexpr vector(int_t s) requires(not is_same_v<ScalarT, int_t>)
: vector() {
if constexpr (N == 1) data[0] = ScalarT(s);
else ((data[IndicesV] = ScalarT(s)), ...);
}
@@ -263,21 +280,25 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
///
/// \details
/// \param s scalar value to initialize with
explicit constexpr vector(double_t s) requires(not is_same_v<ScalarT, double_t>) {
if constexpr(N == 1) data[0] = ScalarT(s);
else ((data[IndicesV] = ScalarT(s)), ...);
explicit constexpr vector(double_t s) requires(not is_same_v<ScalarT, double_t>)
: vector() {
if constexpr (N == 1) data[0] = ScalarT(s);
else ((data[IndicesV] = ScalarT(s)), ...);
}
///
/// \brief vector scalar conversion constructor
///
/// \details
/// \tparam OScalarT scalar Type of the \ref fennec_math_vector "vector" to Convert
/// \param v \ref fennec_math_vector "vector" to Convert
template<typename OScalarT>
explicit constexpr vector(const vector<OScalarT, IndicesV...>& v)
{ ((data[IndicesV] = ScalarT(v[IndicesV])), ...); }
// This is not in the GLSL spec, I don't remember writing it, and it's behaviour is strange.
/////
///// \brief vector scalar conversion constructor
/////
///// \details
///// \tparam OScalarT scalar Type of the \ref fennec_math_vector "vector" to Convert
///// \param v \ref fennec_math_vector "vector" to Convert
//template<typename OScalarT>
//explicit constexpr vector(const vector<OScalarT, IndicesV...>& v)
//: data() {
// ((data[IndicesV] = ScalarT(v[IndicesV])), ...);
//}
///
@@ -288,9 +309,10 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \tparam MoreIndicesStartV
/// \tparam MoreIndicesV
/// \param v
template<typename OScalarT, size_t MoreIndicesStartV, size_t...MoreIndicesV>
explicit constexpr vector(const vector<OScalarT, IndicesV..., MoreIndicesStartV, MoreIndicesV...>& v)
{ ((data[IndicesV] = ScalarT(v[IndicesV])), ...); }
template<typename OScalarT, size_t MoreIndicesStartV, size_t... MoreIndicesV>
explicit constexpr vector(const vector<OScalarT, IndicesV..., MoreIndicesStartV, MoreIndicesV...>& v) {
((data[IndicesV] = ScalarT(v[IndicesV])), ...);
}
///
@@ -301,9 +323,11 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \tparam SwizzleScalarT swizzle scalar Type
/// \tparam SwizzleIndicesV swizzle Indices
/// \param swizzle swizzle object
template<typename SwizzleDataT, typename SwizzleScalarT, size_t...SwizzleIndicesV>
explicit constexpr vector(const detail::swizzle_storage<SwizzleDataT, SwizzleScalarT, SwizzleIndicesV...>& swizzle)
{ ((data[IndicesV] = ScalarT(swizzle[IndicesV])), ...); }
template<typename SwizzleDataT, typename SwizzleScalarT, size_t... SwizzleIndicesV>
explicit constexpr vector(
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
/// \tparam ArgsT argument types
/// \param args arguments
template<typename...ArgsT> requires(total_component_count_v<ArgsT...> == N)
explicit constexpr vector(ArgsT&&...args)
{ vector::__construct<0>(args...); }
template<typename... ArgsT> requires(total_component_count_v<ArgsT...> == N)
explicit constexpr vector(ArgsT&&... args) {
vector::__construct<0>(args...);
}
/// @}
@@ -329,8 +354,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
///
/// \details
/// \returns scalar if \f$N==1\f$, otherwise, \ref fennec_math_vector "vector"
decay_t decay()
{ return static_cast<const decay_t&>(*this); }
decay_t decay() {
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
constexpr scalar_t& operator[](size_t i)
{ return data[i]; }
constexpr scalar_t& operator[](size_t i) {
return data[i];
}
///
/// \brief indexed access operator
@@ -351,8 +378,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \details
/// \returns a copy of the component
/// \param i the index of the component
constexpr scalar_t operator[](size_t i) const
{ return data[i]; }
constexpr scalar_t operator[](size_t i) const {
return data[i];
}
/// @}
@@ -368,8 +396,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \details
/// \returns A reference to \c this, after having set \p lhs, such that \f$lhs_i=rhs_i\f$
/// \param rhs vector to copy
constexpr vector_t& operator=(const vector_t& rhs)
{ return ((data[IndicesV] = rhs[IndicesV]), ..., *this); }
constexpr vector_t& operator=(const vector_t& rhs) {
return ((data[IndicesV] = rhs[IndicesV]), ..., *this);
}
///
/// \brief move assignment
@@ -377,8 +406,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \details
/// \returns A reference to \c this, after having set \p lhs, such that \f$lhs_i=rhs_i\f$
/// \param rhs vector to move
constexpr vector_t& operator=(vector_t&& rhs) noexcept
{ return ((data[IndicesV] = fennec::move(rhs[IndicesV])), ..., *this); }
constexpr vector_t& operator=(vector_t&& rhs) noexcept {
return ((data[IndicesV] = fennec::move(rhs[IndicesV])), ..., *this);
}
/// @}
@@ -394,8 +424,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \details
/// \returns **true** if every respective component is equivalent, otherwise returns **false**
/// \param rhs vector to compare with
constexpr bool_t operator==(const vector_t& rhs) const
{ return ((data[IndicesV] == rhs.data[IndicesV]) && ...); }
constexpr bool_t operator==(const vector_t& rhs) const {
return ((data[IndicesV] == rhs.data[IndicesV]) && ...);
}
///
/// \brief vector inequality operator
@@ -403,8 +434,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \details
/// \returns **false** if every respective component is equivalent, otherwise returns **true**
/// \param rhs vector to compare with
constexpr bool_t operator!=(const vector_t& rhs) const
{ return ((data[IndicesV] != rhs.data[IndicesV]) || ...); }
constexpr bool_t operator!=(const vector_t& rhs) const {
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$
/// \param lhs left hand side
/// \param rhs right hand side
constexpr friend vector_t operator+(scalar_t lhs, const vector_t& rhs)
{ return vector_t((lhs + rhs[IndicesV]) ...); }
constexpr friend vector_t operator+(scalar_t lhs, const vector_t& rhs) {
return vector_t((lhs + rhs[IndicesV])...);
}
///
/// \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$
/// \param lhs left hand side
/// \param rhs right hand side
constexpr friend vector_t operator-(scalar_t lhs, const vector_t& rhs)
{ return vector_t((lhs - rhs[IndicesV]) ...); }
constexpr friend vector_t operator-(scalar_t lhs, const vector_t& rhs) {
return vector_t((lhs - rhs[IndicesV])...);
}
///
/// \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$
/// \param lhs left hand side
/// \param rhs right hand side
constexpr friend vector_t operator*(scalar_t lhs, const vector_t& rhs)
{ return vector_t((lhs * rhs[IndicesV]) ...); }
constexpr friend vector_t operator*(scalar_t lhs, const vector_t& rhs) {
return vector_t((lhs * rhs[IndicesV])...);
}
///
/// \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$
/// \param lhs left hand side
/// \param rhs right hand side
constexpr friend vector_t operator/(scalar_t lhs, const vector_t& rhs)
{ return vector_t((lhs / rhs[IndicesV]) ...); }
constexpr friend vector_t operator/(scalar_t lhs, const vector_t& rhs) {
return vector_t((lhs / rhs[IndicesV])...);
}
///
/// \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$
/// \param lhs left hand side
/// \param rhs right hand side
constexpr friend vector_t operator%(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs % rhs[IndicesV]) ...); }
constexpr friend vector_t operator%(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
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$
/// \param lhs left hand side
/// \param rhs right hand side
constexpr friend vector_t operator+(const vector_t& lhs, scalar_t rhs)
{ return vector_t((lhs[IndicesV] + rhs) ...); }
constexpr friend vector_t operator+(const vector_t& lhs, scalar_t rhs) {
return vector_t((lhs[IndicesV] + rhs)...);
}
///
/// \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 rhs right hand side
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i-rhs_i\f$
constexpr friend vector_t operator-(const vector_t& lhs, scalar_t rhs)
{ return vector_t((lhs[IndicesV] - rhs) ...); }
constexpr friend vector_t operator-(const vector_t& lhs, scalar_t rhs) {
return vector_t((lhs[IndicesV] - rhs)...);
}
///
/// \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 rhs right hand side
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i={lhs_i}\cdot{rhs_i}\f$
constexpr friend vector_t operator*(const vector_t& lhs, scalar_t rhs)
{ return vector_t((lhs[IndicesV] * rhs) ...); }
constexpr friend vector_t operator*(const vector_t& lhs, scalar_t rhs) {
return vector_t((lhs[IndicesV] * rhs)...);
}
///
/// \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 rhs right hand side
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=\frac{lhs_i}{rhs_i}\f$
constexpr friend vector_t operator/(const vector_t& lhs, scalar_t rhs)
{ return vector((lhs[IndicesV] / rhs) ...); }
constexpr friend vector_t operator/(const vector_t& lhs, scalar_t rhs) {
return vector((lhs[IndicesV] / rhs)...);
}
///
/// \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 rhs right hand side
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\%rhs_i\f$
constexpr friend vector_t operator%(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return vector((lhs[IndicesV] % rhs) ...); }
constexpr friend vector_t operator%(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
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 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$
constexpr friend vector_t& operator+=(vector_t& lhs, scalar_t rhs)
{ return ((lhs[IndicesV] += rhs), ..., lhs); }
constexpr friend vector_t& operator+=(vector_t& lhs, scalar_t rhs) {
return ((lhs[IndicesV] += rhs), ..., lhs);
}
///
/// \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 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$
constexpr friend vector_t& operator-=(vector_t& lhs, scalar_t rhs)
{ return ((lhs[IndicesV] -= rhs), ..., lhs); }
constexpr friend vector_t& operator-=(vector_t& lhs, scalar_t rhs) {
return ((lhs[IndicesV] -= rhs), ..., lhs);
}
///
/// \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 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$
constexpr friend vector_t& operator*=(vector_t& lhs, scalar_t rhs)
{ return ((lhs[IndicesV] *= rhs), ..., lhs); }
constexpr friend vector_t& operator*=(vector_t& lhs, scalar_t rhs) {
return ((lhs[IndicesV] *= rhs), ..., lhs);
}
///
/// \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 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$
constexpr friend vector_t& operator/=(vector_t& lhs, scalar_t rhs)
{ return ((lhs[IndicesV] /= rhs), ..., lhs); }
constexpr friend vector_t& operator/=(vector_t& lhs, scalar_t rhs) {
return ((lhs[IndicesV] /= rhs), ..., lhs);
}
///
/// \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 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$
constexpr friend vector_t& operator%=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] %= rhs), ..., lhs); }
constexpr friend vector_t& operator%=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
return ((lhs[IndicesV] %= rhs), ..., lhs);
}
/// @}
@@ -591,8 +638,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \details
/// \param x the vector
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=-x_i\f$
constexpr friend vector_t operator-(const vector_t& x)
{ return vector((-x[IndicesV]) ...); }
constexpr friend vector_t operator-(const vector_t& x) {
return vector((-x[IndicesV])...);
}
///
/// \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 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$
constexpr friend vector_t operator+(const vector_t& lhs, const vector_t& rhs)
{ return vector((lhs[IndicesV] + rhs[IndicesV]) ...); }
constexpr friend vector_t operator+(const vector_t& lhs, const vector_t& rhs) {
return vector((lhs[IndicesV] + rhs[IndicesV])...);
}
///
/// \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 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$
constexpr friend vector_t operator-(const vector_t& lhs, const vector_t& rhs)
{ return vector((lhs[IndicesV] - rhs[IndicesV]) ...); }
constexpr friend vector_t operator-(const vector_t& lhs, const vector_t& rhs) {
return vector((lhs[IndicesV] - rhs[IndicesV])...);
}
///
/// \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 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$
constexpr friend vector_t operator*(const vector_t& lhs, const vector_t& rhs)
{ return vector((lhs[IndicesV] * rhs[IndicesV]) ...); }
constexpr friend vector_t operator*(const vector_t& lhs, const vector_t& rhs) {
return vector((lhs[IndicesV] * rhs[IndicesV])...);
}
///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" division operator
/// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=\frac{lhs_i}{rhs_i}\f$
constexpr friend vector_t operator/(const vector_t& lhs, const vector_t& rhs)
{ return vector((lhs[IndicesV] / rhs[IndicesV]) ...); }
constexpr friend vector_t operator/(const vector_t& lhs, const vector_t& rhs) {
return vector((lhs[IndicesV] / rhs[IndicesV])...);
}
///
/// \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 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$
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]) ...); }
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])...);
}
/// @}
@@ -656,8 +709,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i+rhs_i\f$
constexpr friend vector_t& operator+=(vector_t& lhs, const vector_t& rhs)
{ return ((lhs[IndicesV] += rhs[IndicesV]), ..., lhs); }
constexpr friend vector_t& operator+=(vector_t& lhs, const vector_t& rhs) {
return ((lhs[IndicesV] += rhs[IndicesV]), ..., lhs);
}
///
/// \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 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$
constexpr friend vector_t& operator-=(vector_t& lhs, const vector_t& rhs)
{ return ((lhs[IndicesV] -= rhs[IndicesV]), ..., lhs); }
constexpr friend vector_t& operator-=(vector_t& lhs, const vector_t& rhs) {
return ((lhs[IndicesV] -= rhs[IndicesV]), ..., lhs);
}
///
/// \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 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$
constexpr friend vector_t& operator*=(vector_t& lhs, const vector_t& rhs)
{ return ((lhs[IndicesV] *= rhs[IndicesV]), ..., lhs); }
constexpr friend vector_t& operator*=(vector_t& lhs, const vector_t& rhs) {
return ((lhs[IndicesV] *= rhs[IndicesV]), ..., lhs);
}
///
/// \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 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$
constexpr friend vector_t& operator/=(vector_t& lhs, const vector_t& rhs)
{ return ((lhs[IndicesV] /= rhs[IndicesV]), ..., lhs); }
constexpr friend vector_t& operator/=(vector_t& lhs, const vector_t& rhs) {
return ((lhs[IndicesV] /= rhs[IndicesV]), ..., lhs);
}
///
/// \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 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$
constexpr friend vector_t& operator%=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] %= rhs[IndicesV]), ..., lhs); }
constexpr friend vector_t& operator%=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
return ((lhs[IndicesV] %= rhs[IndicesV]), ..., lhs);
}
/// @}
@@ -712,8 +770,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \details
/// \param x the vector
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=!x_i\f$
constexpr friend vector_t operator!(const vector_t& x)
{ return vector_t(!x[IndicesV] ...); }
constexpr friend vector_t operator!(const vector_t& x) {
return vector_t(!x[IndicesV]...);
}
///
/// \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 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$
constexpr friend vector_t operator&&(const vector_t& lhs, scalar_t rhs) requires(is_bool_v<scalar_t>)
{ return vector_t((lhs[IndicesV] && rhs) ...); }
constexpr friend vector_t operator&&(const vector_t& lhs, scalar_t rhs) requires(is_bool_v<scalar_t>) {
return vector_t((lhs[IndicesV] && rhs)...);
}
///
/// \brief \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" logical and operator
/// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\&\&rhs_i\f$
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]) ...); }
constexpr friend vector_t operator&&(const vector_t& lhs, const vector_t& rhs) requires(is_bool_v<scalar_t>) {
return vector_t((lhs[IndicesV] && rhs[IndicesV])...);
}
///
/// \brief \ref fennec_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 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$
constexpr friend vector_t operator||(const vector_t& lhs, scalar_t rhs) requires(is_bool_v<scalar_t>)
{ return vector_t((lhs[IndicesV] || rhs) ...); }
constexpr friend vector_t operator||(const vector_t& lhs, scalar_t rhs) requires(is_bool_v<scalar_t>) {
return vector_t((lhs[IndicesV] || rhs)...);
}
///
/// \brief \ref fennec_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 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$
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]) ...); }
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])...);
}
/// @}
@@ -767,8 +830,9 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
/// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\&rhs_i\f$
constexpr friend vector_t operator&(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs[IndicesV] & rhs) ...); }
constexpr friend vector_t operator&(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>) {
return vector_t((lhs[IndicesV] & rhs)...);
}
///
/// \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 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$
constexpr friend vector_t operator&(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs[IndicesV] & rhs) ...); }
constexpr friend vector_t operator&(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
return vector_t((lhs[IndicesV] & rhs)...);
}
///
/// \brief \ref fennec_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 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$
constexpr friend vector_t operator&=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] &= rhs), ..., lhs); }
constexpr friend vector_t operator&=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
return ((lhs[IndicesV] &= rhs), ..., lhs);
}
///
/// \brief \ref fennec_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 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$
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]) ...); }
constexpr friend vector_t operator&(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<
scalar_t>) {
return vector_t((lhs[IndicesV] & rhs[IndicesV])...);
}
///
/// \brief \ref 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 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$
constexpr friend vector_t operator&=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] &= rhs[IndicesV]), ..., lhs); }
constexpr friend vector_t operator&=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
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 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$
constexpr friend vector_t operator|(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs[IndicesV] | rhs) ...); }
constexpr friend vector_t operator|(scalar_t rhs, const vector_t& lhs) requires(is_integral_v<scalar_t>) {
return vector_t((lhs[IndicesV] | rhs)...);
}
///
/// \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 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$
constexpr friend vector_t operator|(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs[IndicesV] | rhs) ...); }
constexpr friend vector_t operator|(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
return vector_t((lhs[IndicesV] | rhs)...);
}
///
/// \brief \ref fennec_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 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$
constexpr friend vector_t operator|=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] |= rhs), ..., lhs); }
constexpr friend vector_t operator|=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
return ((lhs[IndicesV] |= rhs), ..., lhs);
}
///
/// \brief \ref fennec_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 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$
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]) ...); }
constexpr friend vector_t operator|(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<
scalar_t>) {
return vector_t((lhs[IndicesV] | rhs[IndicesV])...);
}
///
/// \brief \ref 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 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$
constexpr friend vector_t operator|=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] |= rhs[IndicesV]), ..., lhs); }
constexpr friend vector_t operator|=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
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 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$
constexpr friend vector_t operator^(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs ^ rhs[IndicesV]) ...); }
constexpr friend vector_t operator^(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
return vector_t((lhs ^ rhs[IndicesV])...);
}
///
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise xor operator
/// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$
constexpr friend vector_t operator^(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs[IndicesV] ^ rhs) ...); }
constexpr friend vector_t operator^(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
return vector_t((lhs[IndicesV] ^ rhs)...);
}
///
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise xor assignment operator
/// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$
constexpr friend vector_t operator^=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] ^= rhs), ..., lhs); }
constexpr friend vector_t operator^=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
return ((lhs[IndicesV] ^= rhs), ..., lhs);
}
///
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise xor operator
/// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$
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]) ...); }
constexpr friend vector_t operator^(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<
scalar_t>) {
return vector_t((lhs[IndicesV] ^ rhs[IndicesV])...);
}
///
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise xor assignment operator
/// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i\^rhs_i\f$
constexpr friend vector_t operator^=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] ^= rhs[IndicesV]), ..., lhs); }
constexpr friend vector_t operator^=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
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 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$
constexpr friend vector_t operator<<(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs << rhs[IndicesV]) ...); }
constexpr friend vector_t operator<<(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
return vector_t((lhs << rhs[IndicesV])...);
}
///
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift operator
/// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i<<rhs_i\f$
constexpr friend vector_t operator<<(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs[IndicesV] << rhs) ...); }
constexpr friend vector_t operator<<(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
return vector_t((lhs[IndicesV] << rhs)...);
}
///
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift assignment operator
/// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i<<=rhs_i\f$
constexpr friend vector_t operator<<=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] <<= rhs), ..., lhs); }
constexpr friend vector_t operator<<=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
return ((lhs[IndicesV] <<= rhs), ..., lhs);
}
///
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or operator
/// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i<<rhs_i\f$
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]) ...); }
constexpr friend vector_t operator<<(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
return vector_t((lhs[IndicesV] << rhs[IndicesV])...);
}
///
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator
/// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i<<=rhs_i\f$
constexpr friend vector_t operator<<=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] <<= rhs[IndicesV]), ..., lhs); }
constexpr friend vector_t operator<<=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
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 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$
constexpr friend vector_t operator>>(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs >> rhs[IndicesV]) ...); }
constexpr friend vector_t operator>>(scalar_t lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
return vector_t((lhs >> rhs[IndicesV])...);
}
///
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise or operator
/// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i>>rhs_i\f$
constexpr friend vector_t operator>>(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return vector_t((lhs[IndicesV] >> rhs) ...); }
constexpr friend vector_t operator>>(const vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
return vector_t((lhs[IndicesV] >> rhs)...);
}
///
/// \ref fennec_math_vector "vector" - \ref fennec_math_scalar "scalar" bitwise left-shift assignment operator
/// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i>>=rhs_i\f$
constexpr friend vector_t operator>>=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] >>= rhs), ..., lhs); }
constexpr friend vector_t operator>>=(vector_t& lhs, scalar_t rhs) requires(is_integral_v<scalar_t>) {
return ((lhs[IndicesV] >>= rhs), ..., lhs);
}
///
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or operator
/// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i>>rhs_i\f$
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]) ...); }
constexpr friend vector_t operator>>(const vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
return vector_t((lhs[IndicesV] >> rhs[IndicesV])...);
}
///
/// \ref fennec_math_vector "vector" - \ref fennec_math_vector "vector" bitwise or assignment operator
/// \param lhs Left Hand Side of the Expression
/// \param rhs Right Hand Side of the Expression
/// \returns A \ref fennec_math_vector "vector" \a v such that, \f$v_i=lhs_i>>=rhs_i\f$
constexpr friend vector_t operator>>=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>)
{ return ((lhs[IndicesV] >>= rhs[IndicesV]), ..., lhs); }
constexpr friend vector_t operator>>=(vector_t& lhs, const vector_t& rhs) requires(is_integral_v<scalar_t>) {
return ((lhs[IndicesV] >>= rhs[IndicesV]), ..., lhs);
}
/// @}
@@ -994,30 +1081,34 @@ struct vector : detail::vector_base_type<ScalarT, sizeof...(IndicesV)>
// Helpers =============================================================================================================
private:
template<size_t IndexV = 0, typename HeadT, typename...TailT>
constexpr void __construct(HeadT&& head, TailT&&...rest)
{
template<size_t IndexV = 0, typename HeadT, typename... TailT>
constexpr void __construct(HeadT&& head, TailT&&... rest) {
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)...);
}
template<size_t OffsetV>
constexpr void __insert(ScalarT& x)
{ data[OffsetV] = x; }
constexpr void __insert(ScalarT& x) {
data[OffsetV] = x;
}
template<size_t OffsetV, typename OScalarT>
constexpr void __insert(OScalarT& x)
{ data[OffsetV] = ScalarT(x); }
constexpr void __insert(OScalarT& x) {
data[OffsetV] = ScalarT(x);
}
template<size_t OffsetV = 0, typename OScalarT, size_t...OIndicesV>
constexpr void __insert(vector<OScalarT, OIndicesV...>& vec)
{ ((data[OffsetV + OIndicesV] = fennec::forward<OScalarT>(vec[OIndicesV])), ...); }
template<size_t OffsetV = 0, typename OScalarT, size_t... OIndicesV>
constexpr void __insert(vector<OScalarT, OIndicesV...>& vec) {
((data[OffsetV + OIndicesV] = fennec::forward<OScalarT>(vec[OIndicesV])), ...);
}
template<size_t OffsetV = 0, typename OVectorT, typename ODataT, typename OScalarT, size_t...OIndicesV>
constexpr void __insert(swizzle<OVectorT, ODataT, OScalarT, OIndicesV...>& vec)
{ size_t i = 0; ((data[OffsetV + (i++)] = vec.data[OIndicesV]), ...); }
template<size_t OffsetV = 0, typename OVectorT, typename ODataT, typename OScalarT, size_t... OIndicesV>
constexpr void __insert(swizzle<OVectorT, ODataT, OScalarT, OIndicesV...>& vec) {
size_t i = 0;
((data[OffsetV + (i++)] = vec.data[OIndicesV]), ...);
}
};
}

View File

@@ -157,22 +157,34 @@ public:
/// \brief Equality operator
constexpr bool_t operator==(const allocator&) { return true; }
constexpr bool_t operator==(const allocator&) {
return true;
}
/// \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
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
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`
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`
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`
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
/// \param n The number of elements of type `T` to allocate for
constexpr allocation(size_t n) noexcept
: _data(nullptr), _capacity(0)
{ allocate(n); }
: _data(nullptr), _capacity(0) {
allocate(n);
}
///
/// \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 n the number of elements
constexpr allocation(const T* data, size_t n)
: allocation(n)
{ fennec::memcpy(_data, data, n); }
: allocation(n) {
fennec::memcpy(_data, data, n);
}
///
/// \brief Allocator Constructor
@@ -226,7 +241,8 @@ public:
///
/// \details This constructor should be used when the type `AllocT` needs internal data.
constexpr allocation(const alloc_t& alloc) noexcept
: _alloc(alloc), _data(nullptr), _capacity(0) {}
: _alloc(alloc), _data(nullptr), _capacity(0) {
}
///
/// \brief Sized Allocator Constructor
@@ -235,8 +251,9 @@ public:
///
/// \details This constructor should be used when the type `AllocT` needs internal data.
constexpr allocation(size_t n, const alloc_t& alloc) noexcept
: _alloc(alloc), _data(nullptr), _capacity(0)
{ allocate(n); }
: _alloc(alloc), _data(nullptr), _capacity(0) {
allocate(n);
}
///
/// \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.
constexpr allocation(const T* data, size_t n, const alloc_t& alloc)
: allocation(n, alloc)
{ fennec::memcpy(_data, data, n); }
: allocation(n, alloc) {
fennec::memcpy(_data, data, n);
}
///
/// \brief Copy Constructor, creates an allocation of equal size and performs a byte-wise copy
/// \param alloc The allocation to copy
constexpr allocation(const allocation& alloc) noexcept
: _alloc(alloc._alloc), _data(_alloc.allocate(alloc._capacity)), _capacity(alloc._capacity)
{ fennec::memcpy(_data, alloc._data, alloc._capacity * sizeof(T)); }
: _alloc(alloc._alloc), _data(_alloc.allocate(alloc._capacity)), _capacity(alloc._capacity) {
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
/// can safely destruct
/// \param alloc The allocation to move
constexpr allocation(allocation&& alloc) noexcept
: _alloc(alloc._alloc), _data(alloc._data), _capacity(alloc._capacity)
{ alloc._data = nullptr; alloc._capacity = 0; }
: _alloc(alloc._alloc), _data(alloc._data), _capacity(alloc._capacity) {
alloc._data = nullptr; alloc._capacity = 0;
}
///
/// \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
/// \param alloc the allocation to copy
/// \returns a reference to `this`
constexpr allocation& operator=(const allocation& alloc)
{
constexpr allocation& operator=(const allocation& alloc) {
allocation::allocate(alloc.capacity());
fennec::memcpy(_data, alloc, size());
return *this;
@@ -285,8 +306,7 @@ public:
/// \brief Move Assignment Operator
/// \param alloc the allocation to copy
/// \returns a reference to `this`
constexpr allocation& operator=(allocation&& alloc) noexcept
{
constexpr allocation& operator=(allocation&& alloc) noexcept {
// Copy contents
_alloc = alloc._alloc;
_data = alloc._data;
@@ -303,10 +323,10 @@ public:
/// \brief Allocate a block of memory for the allocation.
/// 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
constexpr void allocate(size_t n) noexcept
{
if (_data)
constexpr void allocate(size_t n) noexcept {
if (_data) {
_alloc.deallocate(_data);
}
_data = _alloc.allocate(_capacity = n);
}
@@ -315,8 +335,9 @@ public:
/// \brief Release the block of memory.
constexpr void release() noexcept
{
if (_data)
if (_data) {
_alloc.deallocate(_data);
}
_data = nullptr;
_capacity = 0;
@@ -327,8 +348,9 @@ public:
/// Contents are copied to the new allocation.
constexpr void reallocate(size_t n) noexcept
{
if (_data == nullptr)
if (_data == nullptr) {
return _alloc.allocate(_capacity = n);
}
value_t* old = _data;
_data = _alloc.allocate(n);
@@ -339,25 +361,30 @@ public:
///
/// \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));
}
///
/// \brief Getter for the byte size of the allocation.
/// \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.
/// \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
/// \returns Pointer to the allocated memory.
constexpr value_t* data() { return _data; }
constexpr value_t* data() {
return _data;
}
private:
alloc_t _alloc; // Allocator object

View File

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

View File

@@ -45,8 +45,9 @@ struct __ptr_traits_ptr_to
using pointer_t = PtrT;
using element_t = ElemT;
static constexpr pointer_t pointer_to(element_t& obj)
{ return pointer_t::pointer_to(obj); }
static constexpr pointer_t pointer_to(element_t& obj) {
return pointer_t::pointer_to(obj);
}
};
// overload for C style pointers
@@ -56,8 +57,9 @@ struct __ptr_traits_ptr_to<ElemT*, ElemT, false>
using pointer_t = ElemT*;
using element_t = ElemT;
static constexpr pointer_t pointer_to(element_t& obj)
{ return addressof(obj); }
static constexpr pointer_t pointer_to(element_t& obj) {
return addressof(obj);
}
};
// 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
struct nothrow_t { explicit nothrow_t() noexcept { } };
struct nothrow_t
{
explicit nothrow_t() noexcept { }
};
template<typename TypeT> void construct(TypeT* ptr)
{ ptr->TypeT(); }
template<typename TypeT> void construct(TypeT* ptr) {
ptr->TypeT();
}
template<typename TypeT> void construct(TypeT* ptr, const TypeT& val)
{ ptr->TypeT(val); }
template<typename TypeT> void construct(TypeT* ptr, const TypeT& val) {
ptr->TypeT(val);
}
template<typename TypeT> void construct(TypeT* ptr, TypeT&& val)
{ ptr->TypeT(fennec::forward<TypeT>(val)); }
template<typename TypeT> void construct(TypeT* ptr, TypeT&& val) {
ptr->TypeT(fennec::forward<TypeT>(val));
}
template<typename TypeT, typename...ArgsT> void construct(TypeT* ptr, ArgsT...args)
{ ptr->TypeT(fennec::forward<TypeT>(args)...); }
template<typename TypeT, typename...ArgsT> void construct(TypeT* ptr, ArgsT...args) {
ptr->TypeT(fennec::forward<TypeT>(args)...);
}
template<typename TypeT> void destruct(TypeT* ptr)
{ ptr->~TypeT(); }
template<typename TypeT> void destruct(TypeT* ptr) {
ptr->~TypeT();
}
}

View File

@@ -43,8 +43,7 @@ struct default_delete
///
/// \brief Function Call Operator, calls `delete` on `ptr`
/// \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 sizeof(TypeT) > 0, "cannot delete a pointer to an incomplete type");
delete ptr;
@@ -69,8 +68,7 @@ struct default_delete<TypeT[]>
/// \brief Function Call Operator, calls `delete` on `ptr`
/// \param ptr Memory resource to delete
template<class ArrT> requires requires { is_convertible_v<ArrT(*)[], TypeT(*)[]> == true; }
constexpr void operator()(TypeT* ptr) const noexcept
{
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 sizeof(TypeT) > 0, "cannot delete a pointer to an incomplete type");
delete[] ptr;
@@ -108,38 +106,45 @@ public:
/// \brief Pointer Constructor, creates a unique_ptr that owns `ptr` with deleter `del`
/// \param ptr The resource to own
/// \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`
/// \param ptr The resource to own
/// \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`
/// \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
constexpr unique_ptr(const unique_ptr&) = delete;
///
/// \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=(unique_ptr&& r) noexcept
{
constexpr unique_ptr& operator=(unique_ptr&& r) noexcept {
_delete = r._delete;
_handle = r._handle;
r._handle = nullptr;
return *this;
}
pointer_t release()
{
pointer_t release() {
pointer_t retval = _handle;
_handle = nullptr;
return retval;