- Switched from Allman (BSD) to 1TBS (K&R)
Namespaces, Types, and Requires/Concepts still use Allman
This commit is contained in:
@@ -81,7 +81,7 @@ fennec Standards:
|
||||
possible, prevent data loss, and get some debug information for it. fennec defines its own `assert` macro to
|
||||
be used, defining a hook in the private version of the function. This hook is used to clean up any state information
|
||||
within the engine and may be used to send immediate events to listeners so that outside functionality may decide
|
||||
how to handle the impending crash. There is nothing that can be done to stop the crash, as soon as the branch
|
||||
how to handle the impending crash. In Debug Mode there is nothing that can be done to stop the crash, as soon as the branch
|
||||
finishes, `abort()` will be called.
|
||||
|
||||
|
||||
|
||||
417774
conv/GLSLangSpec.4.60.pdf
Normal file
417774
conv/GLSLangSpec.4.60.pdf
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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]) && ...);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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::
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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])...);
|
||||
}
|
||||
|
||||
|
||||
/// @}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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]) ...);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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 ==================================================================================================
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]) ...);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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]];
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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]) ...);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
@@ -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]), ...);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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$
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user