- 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

@@ -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;