| @@ -39,6 +39,14 @@ static inline std::string getenv(std::string const &var) | |||||
| return std::string(); | return std::string(); | ||||
| } | } | ||||
| // A handy endianness test function | |||||
| static inline bool is_big_endian() | |||||
| { | |||||
| union { int i; char c; } u; | |||||
| u.i = 1; | |||||
| return u.c == 0; | |||||
| } | |||||
| } // namespace os | } // namespace os | ||||
| } // namespace lol | } // namespace lol | ||||
| @@ -17,6 +17,13 @@ | |||||
| // ————————————————— | // ————————————————— | ||||
| // | // | ||||
| // Ensure CreateFile2() is available on mingw | |||||
| #if defined _WIN32 && !defined _MSC_VER && \ | |||||
| (!defined _WIN32_WINNT || _WIN32_WINNT < 0x0602) | |||||
| # undef _WIN32_WINNT | |||||
| # define _WIN32_WINNT 0x0602 | |||||
| #endif | |||||
| //namespace lol | //namespace lol | ||||
| //{ | //{ | ||||
| @@ -19,16 +19,12 @@ | |||||
| // C++ compiler features detected through __has_cpp_attribute | // C++ compiler features detected through __has_cpp_attribute | ||||
| #if defined(__has_cpp_attribute) && __has_cpp_attribute(nodiscard) | |||||
| # define lol_attr_nodiscard [[nodiscard]] | |||||
| #else | |||||
| # define lol_attr_nodiscard /* */ | |||||
| #if defined(__has_cpp_attribute) && !__has_cpp_attribute(nodiscard) | |||||
| # error C++ compiler support for [[nodiscard]] is required (use -std=c++17?) | |||||
| #endif | #endif | ||||
| #if defined(__has_cpp_attribute) && __has_cpp_attribute(fallthrough) | |||||
| # define LOL_ATTR_FALLTHROUGH [[fallthrough]]; | |||||
| #else | |||||
| # define LOL_ATTR_FALLTHROUGH /* */ | |||||
| #if defined(__has_cpp_attribute) && !__has_cpp_attribute(fallthrough) | |||||
| # error C++ compiler support for [[fallthrough]] is required (use -std=c++17?) | |||||
| #endif | #endif | ||||
| // Define some attribute macros. | // Define some attribute macros. | ||||
| @@ -30,7 +30,7 @@ namespace lol | |||||
| { | { | ||||
| template<typename T> | template<typename T> | ||||
| struct lol_attr_nodiscard polynomial | |||||
| struct [[nodiscard]] polynomial | |||||
| { | { | ||||
| /* The zero polynomial */ | /* The zero polynomial */ | ||||
| explicit inline polynomial() {} | explicit inline polynomial() {} | ||||
| @@ -95,7 +95,7 @@ struct lol_attr_nodiscard polynomial | |||||
| /* Evaluate polynomial at a given value. This method can also | /* Evaluate polynomial at a given value. This method can also | ||||
| * be used to compose polynomials, i.e. using another polynomial | * be used to compose polynomials, i.e. using another polynomial | ||||
| * as the value instead of a scalar. */ | * as the value instead of a scalar. */ | ||||
| template<typename U> lol_attr_nodiscard U eval(U x) const | |||||
| template<typename U> [[nodiscard]] U eval(U x) const | |||||
| { | { | ||||
| U ret(leading()); | U ret(leading()); | ||||
| for (int i = degree() - 1; i >= 0; --i) | for (int i = degree() - 1; i >= 0; --i) | ||||
| @@ -264,7 +264,7 @@ struct lol_attr_nodiscard polynomial | |||||
| * copy because we cannot let the user mess with the integrity of | * copy because we cannot let the user mess with the integrity of | ||||
| * the structure (i.e. the guarantee that the leading coefficient | * the structure (i.e. the guarantee that the leading coefficient | ||||
| * remains non-zero). */ | * remains non-zero). */ | ||||
| lol_attr_nodiscard inline T operator[](ptrdiff_t n) const | |||||
| [[nodiscard]] inline T operator[](ptrdiff_t n) const | |||||
| { | { | ||||
| if (n < 0 || n > degree()) | if (n < 0 || n > degree()) | ||||
| return T(0); | return T(0); | ||||
| @@ -273,7 +273,7 @@ struct lol_attr_nodiscard polynomial | |||||
| } | } | ||||
| /* Return the leading coefficient */ | /* Return the leading coefficient */ | ||||
| lol_attr_nodiscard inline T leading() const | |||||
| [[nodiscard]] inline T leading() const | |||||
| { | { | ||||
| return (*this)[degree()]; | return (*this)[degree()]; | ||||
| } | } | ||||
| @@ -39,7 +39,7 @@ namespace lol | |||||
| */ | */ | ||||
| template<typename T, int COLS, int ROWS> | template<typename T, int COLS, int ROWS> | ||||
| struct lol_attr_nodiscard mat_t | |||||
| struct [[nodiscard]] mat_t | |||||
| : public linear_ops::base<vec_t<T,ROWS>> | : public linear_ops::base<vec_t<T,ROWS>> | ||||
| { | { | ||||
| static int const count = COLS; | static int const count = COLS; | ||||
| @@ -77,7 +77,7 @@ private: | |||||
| */ | */ | ||||
| template <typename T> | template <typename T> | ||||
| struct lol_attr_nodiscard mat_t<T, 2, 2> | |||||
| struct [[nodiscard]] mat_t<T, 2, 2> | |||||
| : public linear_ops::base<vec_t<T,2>> | : public linear_ops::base<vec_t<T,2>> | ||||
| { | { | ||||
| static int const count = 2; | static int const count = 2; | ||||
| @@ -129,7 +129,7 @@ static_assert(sizeof(dmat2) == 32, "sizeof(dmat2) == 32"); | |||||
| */ | */ | ||||
| template <typename T> | template <typename T> | ||||
| struct lol_attr_nodiscard mat_t<T, 3, 3> | |||||
| struct [[nodiscard]] mat_t<T, 3, 3> | |||||
| : public linear_ops::base<vec_t<T,3>> | : public linear_ops::base<vec_t<T,3>> | ||||
| { | { | ||||
| static int const count = 3; | static int const count = 3; | ||||
| @@ -220,7 +220,7 @@ static_assert(sizeof(dmat3) == 72, "sizeof(dmat3) == 72"); | |||||
| */ | */ | ||||
| template <typename T> | template <typename T> | ||||
| struct lol_attr_nodiscard mat_t<T, 4, 4> | |||||
| struct [[nodiscard]] mat_t<T, 4, 4> | |||||
| : public linear_ops::base<vec_t<T,4>> | : public linear_ops::base<vec_t<T,4>> | ||||
| { | { | ||||
| static int const count = 4; | static int const count = 4; | ||||
| @@ -402,7 +402,7 @@ mat_t<T, N - 1, N - 1> submatrix(mat_t<T, N, N> const &m, int i, int j) | |||||
| * Compute square matrix cofactor | * Compute square matrix cofactor | ||||
| */ | */ | ||||
| template<typename T, int N> lol_attr_nodiscard | |||||
| template<typename T, int N> [[nodiscard]] | |||||
| T cofactor(mat_t<T, N, N> const &m, int i, int j) | T cofactor(mat_t<T, N, N> const &m, int i, int j) | ||||
| { | { | ||||
| ASSERT(i >= 0); ASSERT(j >= 0); ASSERT(i < N); ASSERT(j < N); | ASSERT(i >= 0); ASSERT(j >= 0); ASSERT(i < N); ASSERT(j < N); | ||||
| @@ -410,7 +410,7 @@ T cofactor(mat_t<T, N, N> const &m, int i, int j) | |||||
| return ((i + j) & 1) ? -tmp : tmp; | return ((i + j) & 1) ? -tmp : tmp; | ||||
| } | } | ||||
| template<typename T> lol_attr_nodiscard | |||||
| template<typename T> [[nodiscard]] | |||||
| T cofactor(mat_t<T, 2, 2> const &m, int i, int j) | T cofactor(mat_t<T, 2, 2> const &m, int i, int j) | ||||
| { | { | ||||
| /* This specialisation shouldn't be needed, but Visual Studio. */ | /* This specialisation shouldn't be needed, but Visual Studio. */ | ||||
| @@ -420,7 +420,7 @@ T cofactor(mat_t<T, 2, 2> const &m, int i, int j) | |||||
| } | } | ||||
| // Lu decomposition with partial pivoting | // Lu decomposition with partial pivoting | ||||
| template<typename T, int N> lol_attr_nodiscard | |||||
| template<typename T, int N> [[nodiscard]] | |||||
| std::tuple<mat_t<T, N, N>, vec_t<int, N>, int> lu_decomposition(mat_t<T, N, N> const &m) | std::tuple<mat_t<T, N, N>, vec_t<int, N>, int> lu_decomposition(mat_t<T, N, N> const &m) | ||||
| { | { | ||||
| mat_t<T, N, N> lu = m; | mat_t<T, N, N> lu = m; | ||||
| @@ -463,7 +463,7 @@ std::tuple<mat_t<T, N, N>, vec_t<int, N>, int> lu_decomposition(mat_t<T, N, N> c | |||||
| * Compute square matrix determinant, with a specialisation for 1×1 matrices | * Compute square matrix determinant, with a specialisation for 1×1 matrices | ||||
| */ | */ | ||||
| template<typename T, int N> lol_attr_nodiscard | |||||
| template<typename T, int N> [[nodiscard]] | |||||
| T determinant(mat_t<T, N, N> const &m) | T determinant(mat_t<T, N, N> const &m) | ||||
| { | { | ||||
| auto lup = lu_decomposition(m); | auto lup = lu_decomposition(m); | ||||
| @@ -475,7 +475,7 @@ T determinant(mat_t<T, N, N> const &m) | |||||
| return det; | return det; | ||||
| } | } | ||||
| template<typename T> lol_attr_nodiscard | |||||
| template<typename T> [[nodiscard]] | |||||
| T const & determinant(mat_t<T, 1, 1> const &m) | T const & determinant(mat_t<T, 1, 1> const &m) | ||||
| { | { | ||||
| return m[0][0]; | return m[0][0]; | ||||
| @@ -71,14 +71,14 @@ namespace swizzle_ops | |||||
| namespace swizzle_ops | namespace swizzle_ops | ||||
| { | { | ||||
| template<typename T, int N, int SWIZZLE1, int SWIZZLE2> lol_attr_nodiscard | |||||
| template<typename T, int N, int SWIZZLE1, int SWIZZLE2> [[nodiscard]] | |||||
| static inline typename std::enable_if<SWIZZLE1 != FULL_SWIZZLE || SWIZZLE2 != FULL_SWIZZLE, bool>::type | static inline typename std::enable_if<SWIZZLE1 != FULL_SWIZZLE || SWIZZLE2 != FULL_SWIZZLE, bool>::type | ||||
| operator ==(vec_t<T,N,SWIZZLE1> const &a, vec_t<T,N,SWIZZLE2> const &b) | operator ==(vec_t<T,N,SWIZZLE1> const &a, vec_t<T,N,SWIZZLE2> const &b) | ||||
| { | { | ||||
| return vec_t<T,N>(a) == vec_t<T,N>(b); | return vec_t<T,N>(a) == vec_t<T,N>(b); | ||||
| } | } | ||||
| template<typename T, int N, int SWIZZLE1, int SWIZZLE2> lol_attr_nodiscard | |||||
| template<typename T, int N, int SWIZZLE1, int SWIZZLE2> [[nodiscard]] | |||||
| static inline typename std::enable_if<SWIZZLE1 != FULL_SWIZZLE || SWIZZLE2 != FULL_SWIZZLE, bool>::type | static inline typename std::enable_if<SWIZZLE1 != FULL_SWIZZLE || SWIZZLE2 != FULL_SWIZZLE, bool>::type | ||||
| operator !=(vec_t<T,N,SWIZZLE1> const &a, vec_t<T,N,SWIZZLE2> const &b) | operator !=(vec_t<T,N,SWIZZLE1> const &a, vec_t<T,N,SWIZZLE2> const &b) | ||||
| { | { | ||||
| @@ -136,7 +136,7 @@ namespace linear_ops | |||||
| * Comparisons | * Comparisons | ||||
| */ | */ | ||||
| template<typename V> lol_attr_nodiscard | |||||
| template<typename V> [[nodiscard]] | |||||
| static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, bool>::type | static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, bool>::type | ||||
| operator ==(V const &a, V const &b) | operator ==(V const &a, V const &b) | ||||
| { | { | ||||
| @@ -146,7 +146,7 @@ operator ==(V const &a, V const &b) | |||||
| return true; | return true; | ||||
| } | } | ||||
| template<typename V> lol_attr_nodiscard | |||||
| template<typename V> [[nodiscard]] | |||||
| static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, bool>::type | static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, bool>::type | ||||
| operator !=(V const &a, V const &b) | operator !=(V const &a, V const &b) | ||||
| { | { | ||||
| @@ -27,50 +27,50 @@ namespace lol | |||||
| { | { | ||||
| /* Random number generators */ | /* Random number generators */ | ||||
| template<typename T> lol_attr_nodiscard static inline T rand(); | |||||
| template<typename T> lol_attr_nodiscard static inline T rand(T a); | |||||
| template<typename T> lol_attr_nodiscard static inline T rand(T a, T b); | |||||
| template<typename T> [[nodiscard]] static inline T rand(); | |||||
| template<typename T> [[nodiscard]] static inline T rand(T a); | |||||
| template<typename T> [[nodiscard]] static inline T rand(T a, T b); | |||||
| /* One-value random number generators */ | /* One-value random number generators */ | ||||
| template<typename T> lol_attr_nodiscard static inline T rand(T a) | |||||
| template<typename T> [[nodiscard]] static inline T rand(T a) | |||||
| { | { | ||||
| return a ? rand<T>() % a : T(0); | return a ? rand<T>() % a : T(0); | ||||
| } | } | ||||
| #if 0 | #if 0 | ||||
| template<> lol_attr_nodiscard inline half rand<half>(half a) | |||||
| template<> [[nodiscard]] inline half rand<half>(half a) | |||||
| { | { | ||||
| float f = (float)std::rand() / (float)RAND_MAX; | float f = (float)std::rand() / (float)RAND_MAX; | ||||
| return (half)(a * f); | return (half)(a * f); | ||||
| } | } | ||||
| #endif | #endif | ||||
| template<> lol_attr_nodiscard inline float rand<float>(float a) | |||||
| template<> [[nodiscard]] inline float rand<float>(float a) | |||||
| { | { | ||||
| auto f = (float)std::rand() / (float)RAND_MAX; | auto f = (float)std::rand() / (float)RAND_MAX; | ||||
| return a * f; | return a * f; | ||||
| } | } | ||||
| template<> lol_attr_nodiscard inline double rand<double>(double a) | |||||
| template<> [[nodiscard]] inline double rand<double>(double a) | |||||
| { | { | ||||
| auto f = (double)std::rand() / (double)RAND_MAX; | auto f = (double)std::rand() / (double)RAND_MAX; | ||||
| return a * f; | return a * f; | ||||
| } | } | ||||
| template<> lol_attr_nodiscard inline long double rand<long double>(long double a) | |||||
| template<> [[nodiscard]] inline long double rand<long double>(long double a) | |||||
| { | { | ||||
| auto f = (long double)std::rand() / (long double)RAND_MAX; | auto f = (long double)std::rand() / (long double)RAND_MAX; | ||||
| return a * f; | return a * f; | ||||
| } | } | ||||
| /* Two-value random number generator -- no need for specialisation */ | /* Two-value random number generator -- no need for specialisation */ | ||||
| template<typename T> lol_attr_nodiscard static inline T rand(T a, T b) | |||||
| template<typename T> [[nodiscard]] static inline T rand(T a, T b) | |||||
| { | { | ||||
| return a + rand<T>(b - a); | return a + rand<T>(b - a); | ||||
| } | } | ||||
| /* Default random number generator */ | /* Default random number generator */ | ||||
| template<typename T> lol_attr_nodiscard static inline T rand() | |||||
| template<typename T> [[nodiscard]] static inline T rand() | |||||
| { | { | ||||
| switch (sizeof(T)) | switch (sizeof(T)) | ||||
| { | { | ||||
| @@ -124,11 +124,11 @@ template<typename T> lol_attr_nodiscard static inline T rand() | |||||
| } | } | ||||
| #if 0 | #if 0 | ||||
| template<> lol_attr_nodiscard inline half rand<half>() { return rand<half>(1.f); } | |||||
| template<> [[nodiscard]] inline half rand<half>() { return rand<half>(1.f); } | |||||
| #endif | #endif | ||||
| template<> lol_attr_nodiscard inline float rand<float>() { return rand<float>(1.f); } | |||||
| template<> lol_attr_nodiscard inline double rand<double>() { return rand<double>(1.0); } | |||||
| template<> lol_attr_nodiscard inline long double rand<long double>() { return rand<long double>(1.0); } | |||||
| template<> [[nodiscard]] inline float rand<float>() { return rand<float>(1.f); } | |||||
| template<> [[nodiscard]] inline double rand<double>() { return rand<double>(1.0); } | |||||
| template<> [[nodiscard]] inline long double rand<long double>() { return rand<long double>(1.0); } | |||||
| } /* namespace lol */ | } /* namespace lol */ | ||||
| @@ -41,7 +41,7 @@ namespace lol | |||||
| // call real::sqrt). | // call real::sqrt). | ||||
| // | // | ||||
| template<typename T> | template<typename T> | ||||
| class lol_attr_nodiscard real_t | |||||
| class [[nodiscard]] real_t | |||||
| { | { | ||||
| public: | public: | ||||
| typedef T bigit_t; | typedef T bigit_t; | ||||
| @@ -65,19 +65,19 @@ public: | |||||
| return n <= 0 ? count : (count = n); | return n <= 0 ? count : (count = n); | ||||
| } | } | ||||
| lol_attr_nodiscard bool is_zero() const { return m_mantissa.size() == 0; } | |||||
| lol_attr_nodiscard bool is_negative() const { return m_sign; } | |||||
| lol_attr_nodiscard bool is_nan() const { return m_nan; } | |||||
| lol_attr_nodiscard bool is_inf() const { return m_inf; } | |||||
| [[nodiscard]] bool is_zero() const { return m_mantissa.size() == 0; } | |||||
| [[nodiscard]] bool is_negative() const { return m_sign; } | |||||
| [[nodiscard]] bool is_nan() const { return m_nan; } | |||||
| [[nodiscard]] bool is_inf() const { return m_inf; } | |||||
| // Mark all these operators explicit to avoid surprises | // Mark all these operators explicit to avoid surprises | ||||
| lol_attr_nodiscard explicit operator float() const; | |||||
| lol_attr_nodiscard explicit operator double() const; | |||||
| lol_attr_nodiscard explicit operator long double() const; | |||||
| lol_attr_nodiscard explicit operator int32_t() const; | |||||
| lol_attr_nodiscard explicit operator uint32_t() const; | |||||
| lol_attr_nodiscard explicit operator int64_t() const; | |||||
| lol_attr_nodiscard explicit operator uint64_t() const; | |||||
| [[nodiscard]] explicit operator float() const; | |||||
| [[nodiscard]] explicit operator double() const; | |||||
| [[nodiscard]] explicit operator long double() const; | |||||
| [[nodiscard]] explicit operator int32_t() const; | |||||
| [[nodiscard]] explicit operator uint32_t() const; | |||||
| [[nodiscard]] explicit operator int64_t() const; | |||||
| [[nodiscard]] explicit operator uint64_t() const; | |||||
| real_t<T> operator +() const; | real_t<T> operator +() const; | ||||
| real_t<T> operator -() const; | real_t<T> operator -() const; | ||||
| @@ -90,15 +90,15 @@ public: | |||||
| real_t<T> const &operator *=(real_t<T> const &x); | real_t<T> const &operator *=(real_t<T> const &x); | ||||
| real_t<T> const &operator /=(real_t<T> const &x); | real_t<T> const &operator /=(real_t<T> const &x); | ||||
| lol_attr_nodiscard bool operator ==(real_t<T> const &x) const; | |||||
| lol_attr_nodiscard bool operator !=(real_t<T> const &x) const; | |||||
| lol_attr_nodiscard bool operator <(real_t<T> const &x) const; | |||||
| lol_attr_nodiscard bool operator >(real_t<T> const &x) const; | |||||
| lol_attr_nodiscard bool operator <=(real_t<T> const &x) const; | |||||
| lol_attr_nodiscard bool operator >=(real_t<T> const &x) const; | |||||
| [[nodiscard]] bool operator ==(real_t<T> const &x) const; | |||||
| [[nodiscard]] bool operator !=(real_t<T> const &x) const; | |||||
| [[nodiscard]] bool operator <(real_t<T> const &x) const; | |||||
| [[nodiscard]] bool operator >(real_t<T> const &x) const; | |||||
| [[nodiscard]] bool operator <=(real_t<T> const &x) const; | |||||
| [[nodiscard]] bool operator >=(real_t<T> const &x) const; | |||||
| lol_attr_nodiscard bool operator !() const; | |||||
| lol_attr_nodiscard explicit operator bool() const; | |||||
| [[nodiscard]] bool operator !() const; | |||||
| [[nodiscard]] explicit operator bool() const; | |||||
| // Comparison functions | // Comparison functions | ||||
| template<typename U> friend real_t<U> min(real_t<U> const &a, | template<typename U> friend real_t<U> min(real_t<U> const &a, | ||||
| @@ -32,7 +32,7 @@ namespace lol | |||||
| */ | */ | ||||
| template<typename T> | template<typename T> | ||||
| struct lol_attr_nodiscard cmplx_t : public linear_ops::base<T> | |||||
| struct [[nodiscard]] cmplx_t : public linear_ops::base<T> | |||||
| { | { | ||||
| static int const count = 2; | static int const count = 2; | ||||
| typedef T scalar_element; | typedef T scalar_element; | ||||
| @@ -80,7 +80,7 @@ static_assert(sizeof(dcmplx) == 16, "sizeof(dcmplx) == 16"); | |||||
| */ | */ | ||||
| template<typename T> | template<typename T> | ||||
| struct lol_attr_nodiscard quat_t : public linear_ops::base<T> | |||||
| struct [[nodiscard]] quat_t : public linear_ops::base<T> | |||||
| { | { | ||||
| static int const count = 4; | static int const count = 4; | ||||
| typedef T scalar_element; | typedef T scalar_element; | ||||
| @@ -234,7 +234,7 @@ struct lol_attr_nodiscard quat_t : public linear_ops::base<T> | |||||
| return normalize(v); | return normalize(v); | ||||
| } | } | ||||
| lol_attr_nodiscard inline T angle() | |||||
| [[nodiscard]] inline T angle() | |||||
| { | { | ||||
| vec_t<T,3> v(x, y, z); | vec_t<T,3> v(x, y, z); | ||||
| T n2 = sqlength(v); | T n2 = sqlength(v); | ||||
| @@ -259,7 +259,7 @@ static_assert(sizeof(dquat) == 32, "sizeof(dquat) == 32"); | |||||
| */ | */ | ||||
| template<typename T> | template<typename T> | ||||
| struct lol_attr_nodiscard sqt_t | |||||
| struct [[nodiscard]] sqt_t | |||||
| { | { | ||||
| /* Default constructor and copy constructor */ | /* Default constructor and copy constructor */ | ||||
| inline constexpr sqt_t() = default; | inline constexpr sqt_t() = default; | ||||
| @@ -343,7 +343,7 @@ std::ostream &operator<<(std::ostream &stream, quat_t<U> const &q) | |||||
| * Common operations on transforms | * Common operations on transforms | ||||
| */ | */ | ||||
| template<typename T> lol_attr_nodiscard | |||||
| template<typename T> [[nodiscard]] | |||||
| static inline T dot(cmplx_t<T> const &t1, cmplx_t<T> const &t2) | static inline T dot(cmplx_t<T> const &t1, cmplx_t<T> const &t2) | ||||
| { | { | ||||
| T ret(0); | T ret(0); | ||||
| @@ -352,20 +352,20 @@ static inline T dot(cmplx_t<T> const &t1, cmplx_t<T> const &t2) | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| template<typename T> lol_attr_nodiscard | |||||
| template<typename T> [[nodiscard]] | |||||
| static inline T sqlength(cmplx_t<T> const &t) | static inline T sqlength(cmplx_t<T> const &t) | ||||
| { | { | ||||
| return dot(t, t); | return dot(t, t); | ||||
| } | } | ||||
| template<typename T> lol_attr_nodiscard | |||||
| template<typename T> [[nodiscard]] | |||||
| static inline T length(cmplx_t<T> const &t) | static inline T length(cmplx_t<T> const &t) | ||||
| { | { | ||||
| /* FIXME: this is not very nice */ | /* FIXME: this is not very nice */ | ||||
| return (T)sqrt((double)sqlength(t)); | return (T)sqrt((double)sqlength(t)); | ||||
| } | } | ||||
| template<typename T> lol_attr_nodiscard | |||||
| template<typename T> [[nodiscard]] | |||||
| static inline T norm(cmplx_t<T> const &t) | static inline T norm(cmplx_t<T> const &t) | ||||
| { | { | ||||
| return length(t); | return length(t); | ||||
| @@ -380,7 +380,7 @@ static inline cmplx_t<T> normalize(cmplx_t<T> const &z) | |||||
| /* XXX: duplicate */ | /* XXX: duplicate */ | ||||
| template<typename T> lol_attr_nodiscard | |||||
| template<typename T> [[nodiscard]] | |||||
| static inline T dot(quat_t<T> const &t1, quat_t<T> const &t2) | static inline T dot(quat_t<T> const &t1, quat_t<T> const &t2) | ||||
| { | { | ||||
| T ret(0); | T ret(0); | ||||
| @@ -389,20 +389,20 @@ static inline T dot(quat_t<T> const &t1, quat_t<T> const &t2) | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| template<typename T> lol_attr_nodiscard | |||||
| template<typename T> [[nodiscard]] | |||||
| static inline T sqlength(quat_t<T> const &t) | static inline T sqlength(quat_t<T> const &t) | ||||
| { | { | ||||
| return dot(t, t); | return dot(t, t); | ||||
| } | } | ||||
| template<typename T> lol_attr_nodiscard | |||||
| template<typename T> [[nodiscard]] | |||||
| static inline T length(quat_t<T> const &t) | static inline T length(quat_t<T> const &t) | ||||
| { | { | ||||
| /* FIXME: this is not very nice */ | /* FIXME: this is not very nice */ | ||||
| return (T)sqrt((double)sqlength(t)); | return (T)sqrt((double)sqlength(t)); | ||||
| } | } | ||||
| template<typename T> lol_attr_nodiscard | |||||
| template<typename T> [[nodiscard]] | |||||
| static inline T norm(quat_t<T> const &t) | static inline T norm(quat_t<T> const &t) | ||||
| { | { | ||||
| return length(t); | return length(t); | ||||
| @@ -437,22 +437,22 @@ static inline cmplx_t<T> operator /(cmplx_t<T> a, cmplx_t<T> const &b) | |||||
| return a * inverse(b); | return a * inverse(b); | ||||
| } | } | ||||
| template<typename T> lol_attr_nodiscard | |||||
| template<typename T> [[nodiscard]] | |||||
| static inline bool operator ==(cmplx_t<T> const &a, T b) | static inline bool operator ==(cmplx_t<T> const &a, T b) | ||||
| { | { | ||||
| return (a.x == b) && !a.y; | return (a.x == b) && !a.y; | ||||
| } | } | ||||
| template<typename T> lol_attr_nodiscard | |||||
| template<typename T> [[nodiscard]] | |||||
| static inline bool operator !=(cmplx_t<T> const &a, T b) | static inline bool operator !=(cmplx_t<T> const &a, T b) | ||||
| { | { | ||||
| return (a.x != b) || a.y; | return (a.x != b) || a.y; | ||||
| } | } | ||||
| template<typename T> lol_attr_nodiscard | |||||
| template<typename T> [[nodiscard]] | |||||
| static inline bool operator ==(T a, cmplx_t<T> const &b) { return b == a; } | static inline bool operator ==(T a, cmplx_t<T> const &b) { return b == a; } | ||||
| template<typename T> lol_attr_nodiscard | |||||
| template<typename T> [[nodiscard]] | |||||
| static inline bool operator !=(T a, cmplx_t<T> const &b) { return b != a; } | static inline bool operator !=(T a, cmplx_t<T> const &b) { return b != a; } | ||||
| /* | /* | ||||
| @@ -44,7 +44,7 @@ namespace lol | |||||
| */ | */ | ||||
| template<typename T, int N, int SWIZZLE> | template<typename T, int N, int SWIZZLE> | ||||
| struct lol_attr_nodiscard vec_t | |||||
| struct [[nodiscard]] vec_t | |||||
| /* MUST have a different base than e.g. vec_t<T,2> otherwise the unions | /* MUST have a different base than e.g. vec_t<T,2> otherwise the unions | ||||
| * in vec_t<T,2> with the same base will cause empty base optimisation | * in vec_t<T,2> with the same base will cause empty base optimisation | ||||
| * failures. */ | * failures. */ | ||||
| @@ -114,7 +114,7 @@ private: | |||||
| /* The generic “vec_t” type, which is a fixed-size vector with no | /* The generic “vec_t” type, which is a fixed-size vector with no | ||||
| * swizzling. There's an override for N=2, N=3, N=4 that has swizzling. */ | * swizzling. There's an override for N=2, N=3, N=4 that has swizzling. */ | ||||
| template<typename T, int N> | template<typename T, int N> | ||||
| struct lol_attr_nodiscard vec_t<T, N, FULL_SWIZZLE> | |||||
| struct [[nodiscard]] vec_t<T, N, FULL_SWIZZLE> | |||||
| : public componentwise_ops::base<T> | : public componentwise_ops::base<T> | ||||
| { | { | ||||
| static int const count = N; | static int const count = N; | ||||
| @@ -131,13 +131,9 @@ struct lol_attr_nodiscard vec_t<T, N, FULL_SWIZZLE> | |||||
| /* Explicit constructor that takes exactly N arguments thanks to SFINAE. */ | /* Explicit constructor that takes exactly N arguments thanks to SFINAE. */ | ||||
| template<typename... ARGS> | template<typename... ARGS> | ||||
| #if LOL_FEATURE_CXX11_SFINAE_FOR_CTORS | |||||
| explicit inline vec_t(T const &X, | explicit inline vec_t(T const &X, | ||||
| typename std::enable_if<sizeof...(ARGS) + 2 == N, T>::type const &Y, | typename std::enable_if<sizeof...(ARGS) + 2 == N, T>::type const &Y, | ||||
| ARGS... args) | ARGS... args) | ||||
| #else | |||||
| explicit inline vec_t(T const &X, T const &Y, ARGS... args) | |||||
| #endif | |||||
| { | { | ||||
| static_assert(sizeof...(ARGS) + 2 == N, | static_assert(sizeof...(ARGS) + 2 == N, | ||||
| "wrong argument count in vec_t constructor"); | "wrong argument count in vec_t constructor"); | ||||
| @@ -203,7 +199,7 @@ private: | |||||
| */ | */ | ||||
| template <typename T> | template <typename T> | ||||
| struct lol_attr_nodiscard vec_t<T,2> | |||||
| struct [[nodiscard]] vec_t<T,2> | |||||
| : public swizzle_ops::base<T> | : public swizzle_ops::base<T> | ||||
| { | { | ||||
| static int const count = 2; | static int const count = 2; | ||||
| @@ -314,7 +310,7 @@ static_assert(sizeof(dvec2) == 16, "sizeof(dvec2) == 16"); | |||||
| */ | */ | ||||
| template <typename T> | template <typename T> | ||||
| struct lol_attr_nodiscard vec_t<T,3> | |||||
| struct [[nodiscard]] vec_t<T,3> | |||||
| : public swizzle_ops::base<T> | : public swizzle_ops::base<T> | ||||
| { | { | ||||
| static int const count = 3; | static int const count = 3; | ||||
| @@ -555,7 +551,7 @@ static_assert(sizeof(dvec3) == 24, "sizeof(dvec3) == 24"); | |||||
| */ | */ | ||||
| template <typename T> | template <typename T> | ||||
| struct lol_attr_nodiscard vec_t<T,4> | |||||
| struct [[nodiscard]] vec_t<T,4> | |||||
| : public swizzle_ops::base<T> | : public swizzle_ops::base<T> | ||||
| { | { | ||||
| static int const count = 4; | static int const count = 4; | ||||
| @@ -1117,7 +1113,7 @@ static inline vec_t<T,N> mix(vec_t<T,N,SWIZZLE1> const &x, | |||||
| * Some GLSL-like functions. | * Some GLSL-like functions. | ||||
| */ | */ | ||||
| template<typename T, int N, int SWIZZLE1, int SWIZZLE2> lol_attr_nodiscard | |||||
| template<typename T, int N, int SWIZZLE1, int SWIZZLE2> [[nodiscard]] | |||||
| static inline T dot(vec_t<T,N,SWIZZLE1> const &a, | static inline T dot(vec_t<T,N,SWIZZLE1> const &a, | ||||
| vec_t<T,N,SWIZZLE2> const &b) | vec_t<T,N,SWIZZLE2> const &b) | ||||
| { | { | ||||
| @@ -1127,13 +1123,13 @@ static inline T dot(vec_t<T,N,SWIZZLE1> const &a, | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| template<typename T, int N, int SWIZZLE> lol_attr_nodiscard | |||||
| template<typename T, int N, int SWIZZLE> [[nodiscard]] | |||||
| static inline T sqlength(vec_t<T,N,SWIZZLE> const &a) | static inline T sqlength(vec_t<T,N,SWIZZLE> const &a) | ||||
| { | { | ||||
| return dot(a, a); | return dot(a, a); | ||||
| } | } | ||||
| template<typename T, int N, int SWIZZLE> lol_attr_nodiscard | |||||
| template<typename T, int N, int SWIZZLE> [[nodiscard]] | |||||
| static inline T length(vec_t<T,N,SWIZZLE> const &a) | static inline T length(vec_t<T,N,SWIZZLE> const &a) | ||||
| { | { | ||||
| /* FIXME: this is not very nice */ | /* FIXME: this is not very nice */ | ||||
| @@ -1151,7 +1147,7 @@ static inline vec_t<T,N> lerp(vec_t<T,N,SWIZZLE1> const &a, | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| template<typename T, int N, int SWIZZLE1, int SWIZZLE2> lol_attr_nodiscard | |||||
| template<typename T, int N, int SWIZZLE1, int SWIZZLE2> [[nodiscard]] | |||||
| static inline T distance(vec_t<T,N,SWIZZLE1> const &a, | static inline T distance(vec_t<T,N,SWIZZLE1> const &a, | ||||
| vec_t<T,N,SWIZZLE2> const &b) | vec_t<T,N,SWIZZLE2> const &b) | ||||
| { | { | ||||
| @@ -96,7 +96,7 @@ private: | |||||
| template<int N, typename... T> | template<int N, typename... T> | ||||
| class lol_attr_nodiscard arraynd : protected array<T...> | |||||
| class [[nodiscard]] arraynd : protected array<T...> | |||||
| { | { | ||||
| public: | public: | ||||
| typedef array<T...> super; | typedef array<T...> super; | ||||
| @@ -37,7 +37,7 @@ namespace lol | |||||
| */ | */ | ||||
| template<unsigned int N = 16, typename T = uint32_t> | template<unsigned int N = 16, typename T = uint32_t> | ||||
| class lol_attr_nodiscard bigint | |||||
| class [[nodiscard]] bigint | |||||
| { | { | ||||
| static int const bits_per_digit = sizeof(T) * 8 - 1; | static int const bits_per_digit = sizeof(T) * 8 - 1; | ||||
| static T const digit_mask = ~((T)1 << bits_per_digit); | static T const digit_mask = ~((T)1 << bits_per_digit); | ||||
| @@ -44,15 +44,15 @@ namespace lol | |||||
| // Mechanism to import standard cmath functions | // Mechanism to import standard cmath functions | ||||
| #define LOL_FORWARD_FP_1_ARG(f) \ | #define LOL_FORWARD_FP_1_ARG(f) \ | ||||
| template<typename T, typename T2 = T, typename DUMMY = LOL_T_FLOATING_POINT> \ | template<typename T, typename T2 = T, typename DUMMY = LOL_T_FLOATING_POINT> \ | ||||
| lol_attr_nodiscard static inline T2 f(T x) { return std::f(x); } | |||||
| [[nodiscard]] static inline T2 f(T x) { return std::f(x); } | |||||
| #define LOL_FORWARD_ARITH_2_ARGS(f) \ | #define LOL_FORWARD_ARITH_2_ARGS(f) \ | ||||
| template<typename T, typename T2 = T, typename DUMMY = LOL_T_ARITHMETIC> \ | template<typename T, typename T2 = T, typename DUMMY = LOL_T_ARITHMETIC> \ | ||||
| lol_attr_nodiscard static inline T2 f(T x, T y) { return std::f(x, y); } | |||||
| [[nodiscard]] static inline T2 f(T x, T y) { return std::f(x, y); } | |||||
| #define LOL_FORWARD_FP_2_ARGS(f) \ | #define LOL_FORWARD_FP_2_ARGS(f) \ | ||||
| template<typename T, typename T2 = T, typename DUMMY = LOL_T_FLOATING_POINT> \ | template<typename T, typename T2 = T, typename DUMMY = LOL_T_FLOATING_POINT> \ | ||||
| lol_attr_nodiscard static inline T2 f(T x, T y) { return std::f(x, y); } | |||||
| [[nodiscard]] static inline T2 f(T x, T y) { return std::f(x, y); } | |||||
| LOL_FORWARD_FP_1_ARG(sqrt) | LOL_FORWARD_FP_1_ARG(sqrt) | ||||
| LOL_FORWARD_FP_1_ARG(cbrt) | LOL_FORWARD_FP_1_ARG(cbrt) | ||||
| @@ -78,72 +78,72 @@ LOL_FORWARD_FP_1_ARG(round) | |||||
| // Our extensions | // Our extensions | ||||
| template<typename T, typename T2 = LOL_T_FLOATING_POINT> | template<typename T, typename T2 = LOL_T_FLOATING_POINT> | ||||
| lol_attr_nodiscard static inline T2 sincos(T x, T *s, T *c) | |||||
| [[nodiscard]] static inline T2 sincos(T x, T *s, T *c) | |||||
| { | { | ||||
| *s = std::sin(x); | *s = std::sin(x); | ||||
| *c = std::cos(x); | *c = std::cos(x); | ||||
| } | } | ||||
| // Inherited from GLSL | // Inherited from GLSL | ||||
| lol_attr_nodiscard static inline float degrees(float radians) | |||||
| [[nodiscard]] static inline float degrees(float radians) | |||||
| { | { | ||||
| return radians * (180.0f / F_PI); | return radians * (180.0f / F_PI); | ||||
| } | } | ||||
| lol_attr_nodiscard static inline double degrees(double radians) | |||||
| [[nodiscard]] static inline double degrees(double radians) | |||||
| { | { | ||||
| return radians * (180.0 / D_PI); | return radians * (180.0 / D_PI); | ||||
| } | } | ||||
| lol_attr_nodiscard static inline ldouble degrees(ldouble radians) | |||||
| [[nodiscard]] static inline ldouble degrees(ldouble radians) | |||||
| { | { | ||||
| return radians * (180.0L / LD_PI); | return radians * (180.0L / LD_PI); | ||||
| } | } | ||||
| lol_attr_nodiscard static inline float radians(float degrees) | |||||
| [[nodiscard]] static inline float radians(float degrees) | |||||
| { | { | ||||
| return degrees * (F_PI / 180.0f); | return degrees * (F_PI / 180.0f); | ||||
| } | } | ||||
| lol_attr_nodiscard static inline double radians(double degrees) | |||||
| [[nodiscard]] static inline double radians(double degrees) | |||||
| { | { | ||||
| return degrees * (D_PI / 180.0); | return degrees * (D_PI / 180.0); | ||||
| } | } | ||||
| lol_attr_nodiscard static inline ldouble radians(ldouble degrees) | |||||
| [[nodiscard]] static inline ldouble radians(ldouble degrees) | |||||
| { | { | ||||
| return degrees * (LD_PI / 180.0L); | return degrees * (LD_PI / 180.0L); | ||||
| } | } | ||||
| // The integer versions return floating point values. This avoids nasty | // The integer versions return floating point values. This avoids nasty | ||||
| // surprises when calling radians(180) instead of radians(180.0). | // surprises when calling radians(180) instead of radians(180.0). | ||||
| lol_attr_nodiscard static inline float degrees(int8_t x) { return degrees(float(x)); } | |||||
| lol_attr_nodiscard static inline float degrees(uint8_t x) { return degrees(float(x)); } | |||||
| lol_attr_nodiscard static inline float degrees(int16_t x) { return degrees(float(x)); } | |||||
| lol_attr_nodiscard static inline float degrees(uint16_t x) { return degrees(float(x)); } | |||||
| lol_attr_nodiscard static inline double degrees(int32_t x) { return degrees(double(x)); } | |||||
| lol_attr_nodiscard static inline double degrees(uint32_t x) { return degrees(double(x)); } | |||||
| lol_attr_nodiscard static inline ldouble degrees(int64_t x) { return degrees(ldouble(x)); } | |||||
| lol_attr_nodiscard static inline ldouble degrees(uint64_t x) { return degrees(ldouble(x)); } | |||||
| lol_attr_nodiscard static inline float radians(int8_t x) { return radians(float(x)); } | |||||
| lol_attr_nodiscard static inline float radians(uint8_t x) { return radians(float(x)); } | |||||
| lol_attr_nodiscard static inline float radians(int16_t x) { return radians(float(x)); } | |||||
| lol_attr_nodiscard static inline float radians(uint16_t x) { return radians(float(x)); } | |||||
| lol_attr_nodiscard static inline double radians(int32_t x) { return radians(double(x)); } | |||||
| lol_attr_nodiscard static inline double radians(uint32_t x) { return radians(double(x)); } | |||||
| lol_attr_nodiscard static inline ldouble radians(int64_t x) { return radians(ldouble(x)); } | |||||
| lol_attr_nodiscard static inline ldouble radians(uint64_t x) { return radians(ldouble(x)); } | |||||
| [[nodiscard]] static inline float degrees(int8_t x) { return degrees(float(x)); } | |||||
| [[nodiscard]] static inline float degrees(uint8_t x) { return degrees(float(x)); } | |||||
| [[nodiscard]] static inline float degrees(int16_t x) { return degrees(float(x)); } | |||||
| [[nodiscard]] static inline float degrees(uint16_t x) { return degrees(float(x)); } | |||||
| [[nodiscard]] static inline double degrees(int32_t x) { return degrees(double(x)); } | |||||
| [[nodiscard]] static inline double degrees(uint32_t x) { return degrees(double(x)); } | |||||
| [[nodiscard]] static inline ldouble degrees(int64_t x) { return degrees(ldouble(x)); } | |||||
| [[nodiscard]] static inline ldouble degrees(uint64_t x) { return degrees(ldouble(x)); } | |||||
| [[nodiscard]] static inline float radians(int8_t x) { return radians(float(x)); } | |||||
| [[nodiscard]] static inline float radians(uint8_t x) { return radians(float(x)); } | |||||
| [[nodiscard]] static inline float radians(int16_t x) { return radians(float(x)); } | |||||
| [[nodiscard]] static inline float radians(uint16_t x) { return radians(float(x)); } | |||||
| [[nodiscard]] static inline double radians(int32_t x) { return radians(double(x)); } | |||||
| [[nodiscard]] static inline double radians(uint32_t x) { return radians(double(x)); } | |||||
| [[nodiscard]] static inline ldouble radians(int64_t x) { return radians(ldouble(x)); } | |||||
| [[nodiscard]] static inline ldouble radians(uint64_t x) { return radians(ldouble(x)); } | |||||
| template<typename T, typename T2 = LOL_T_FLOATING_POINT> | template<typename T, typename T2 = LOL_T_FLOATING_POINT> | ||||
| lol_attr_nodiscard static inline T2 mix(T a, T b, T x) | |||||
| [[nodiscard]] static inline T2 mix(T a, T b, T x) | |||||
| { | { | ||||
| return a + (b - a) * x; | return a + (b - a) * x; | ||||
| } | } | ||||
| // Inherited from HLSL | // Inherited from HLSL | ||||
| template<typename T, typename T2 = LOL_T_FLOATING_POINT> | template<typename T, typename T2 = LOL_T_FLOATING_POINT> | ||||
| lol_attr_nodiscard static inline T2 lerp(T a, T b, T x) | |||||
| [[nodiscard]] static inline T2 lerp(T a, T b, T x) | |||||
| { | { | ||||
| return mix(a, b, x); | return mix(a, b, x); | ||||
| } | } | ||||
| @@ -151,35 +151,35 @@ lol_attr_nodiscard static inline T2 lerp(T a, T b, T x) | |||||
| // C++ doesn't define abs() or fmod() for all types; we add these for | // C++ doesn't define abs() or fmod() for all types; we add these for | ||||
| // convenience to avoid adding complexity to vector.h. | // convenience to avoid adding complexity to vector.h. | ||||
| template<typename T, typename T2 = LOL_T_SIGNED> | template<typename T, typename T2 = LOL_T_SIGNED> | ||||
| lol_attr_nodiscard static inline T2 abs(T x) { return std::abs(x); } | |||||
| [[nodiscard]] static inline T2 abs(T x) { return std::abs(x); } | |||||
| template<typename T, typename T2 = T, typename DUMMY = LOL_T_UNSIGNED> | template<typename T, typename T2 = T, typename DUMMY = LOL_T_UNSIGNED> | ||||
| lol_attr_nodiscard static inline T2 abs(T x) { return x; } | |||||
| [[nodiscard]] static inline T2 abs(T x) { return x; } | |||||
| template<typename T, typename T2 = LOL_T_INTEGRAL> | template<typename T, typename T2 = LOL_T_INTEGRAL> | ||||
| lol_attr_nodiscard static inline T2 fmod(T x, T y) { return x % y; } | |||||
| [[nodiscard]] static inline T2 fmod(T x, T y) { return x % y; } | |||||
| template<typename T, typename T2 = LOL_T_INTEGRAL> | template<typename T, typename T2 = LOL_T_INTEGRAL> | ||||
| lol_attr_nodiscard static inline T2 floor(T x) { return x; } | |||||
| [[nodiscard]] static inline T2 floor(T x) { return x; } | |||||
| template<typename T, typename T2 = LOL_T_INTEGRAL> | template<typename T, typename T2 = LOL_T_INTEGRAL> | ||||
| lol_attr_nodiscard static inline T2 ceil(T x) { return x; } | |||||
| [[nodiscard]] static inline T2 ceil(T x) { return x; } | |||||
| template<typename T, typename T2 = LOL_T_INTEGRAL> | template<typename T, typename T2 = LOL_T_INTEGRAL> | ||||
| lol_attr_nodiscard static inline T2 round(T x) { return x; } | |||||
| [[nodiscard]] static inline T2 round(T x) { return x; } | |||||
| template<typename T, typename T2 = LOL_T_ARITHMETIC> | template<typename T, typename T2 = LOL_T_ARITHMETIC> | ||||
| lol_attr_nodiscard static inline T2 sq(T x) { return x * x; } | |||||
| [[nodiscard]] static inline T2 sq(T x) { return x * x; } | |||||
| template<typename T, typename T2 = LOL_T_ARITHMETIC> | template<typename T, typename T2 = LOL_T_ARITHMETIC> | ||||
| lol_attr_nodiscard static inline T2 fract(T x) { return x - lol::floor(x); } | |||||
| [[nodiscard]] static inline T2 fract(T x) { return x - lol::floor(x); } | |||||
| template<typename T, typename T2 = LOL_T_ARITHMETIC> | template<typename T, typename T2 = LOL_T_ARITHMETIC> | ||||
| lol_attr_nodiscard static inline T2 clamp(T x, T y, T z) { return min(max(x, y), z); } | |||||
| [[nodiscard]] static inline T2 clamp(T x, T y, T z) { return min(max(x, y), z); } | |||||
| template<typename T, typename T2 = LOL_T_ARITHMETIC> | template<typename T, typename T2 = LOL_T_ARITHMETIC> | ||||
| lol_attr_nodiscard static inline T2 saturate(T x) { return clamp(x, (T)0, (T)1); } | |||||
| [[nodiscard]] static inline T2 saturate(T x) { return clamp(x, (T)0, (T)1); } | |||||
| template<typename T, typename T2 = LOL_T_ARITHMETIC> | template<typename T, typename T2 = LOL_T_ARITHMETIC> | ||||
| lol_attr_nodiscard static inline T2 gcd(T x, T y) { return y == (T)0 ? lol::abs(x) : lol::gcd(y, lol::fmod(x, y)); } | |||||
| [[nodiscard]] static inline T2 gcd(T x, T y) { return y == (T)0 ? lol::abs(x) : lol::gcd(y, lol::fmod(x, y)); } | |||||
| template<typename T, typename T2 = LOL_T_SIGNED> | template<typename T, typename T2 = LOL_T_SIGNED> | ||||
| lol_attr_nodiscard static inline T2 sign(T x) { return (T)(((T)0 < x) - (x < (T)0)); } | |||||
| [[nodiscard]] static inline T2 sign(T x) { return (T)(((T)0 < x) - (x < (T)0)); } | |||||
| template<typename T, typename T2 = T, typename DUMMY = LOL_T_UNSIGNED> | template<typename T, typename T2 = T, typename DUMMY = LOL_T_UNSIGNED> | ||||
| lol_attr_nodiscard static inline T2 sign(T x) { return (T)((T)0 < x); } | |||||
| [[nodiscard]] static inline T2 sign(T x) { return (T)((T)0 < x); } | |||||
| } /* namespace lol */ | } /* namespace lol */ | ||||
| @@ -91,7 +91,7 @@ T_(box_t<, C_ 4>, box4) | |||||
| #undef T_ | #undef T_ | ||||
| template<typename T, int N> | template<typename T, int N> | ||||
| struct lol_attr_nodiscard box_t | |||||
| struct [[nodiscard]] box_t | |||||
| { | { | ||||
| inline box_t() | inline box_t() | ||||
| : aa(vec_t<T, N>(T(0))), | : aa(vec_t<T, N>(T(0))), | ||||
| @@ -154,12 +154,12 @@ struct lol_attr_nodiscard box_t | |||||
| return *this = *this * s; | return *this = *this * s; | ||||
| } | } | ||||
| lol_attr_nodiscard bool operator ==(box_t<T,N> const &box) const | |||||
| [[nodiscard]] bool operator ==(box_t<T,N> const &box) const | |||||
| { | { | ||||
| return aa == box.aa && bb == box.bb; | return aa == box.aa && bb == box.bb; | ||||
| } | } | ||||
| lol_attr_nodiscard bool operator !=(box_t<T,N> const &box) const | |||||
| [[nodiscard]] bool operator !=(box_t<T,N> const &box) const | |||||
| { | { | ||||
| return aa != box.aa || bb != box.bb; | return aa != box.aa || bb != box.bb; | ||||
| } | } | ||||
| @@ -193,19 +193,19 @@ private: | |||||
| float Minus() const; | float Minus() const; | ||||
| float Plus() const; | float Plus() const; | ||||
| public: | public: | ||||
| lol_attr_nodiscard bool operator==(float value) const; | |||||
| lol_attr_nodiscard bool operator!=(float value) const; | |||||
| lol_attr_nodiscard bool operator<(float value) const; | |||||
| lol_attr_nodiscard bool operator<=(float value) const; | |||||
| lol_attr_nodiscard bool operator>(float value) const; | |||||
| lol_attr_nodiscard bool operator>=(float value) const; | |||||
| [[nodiscard]] bool operator==(float value) const; | |||||
| [[nodiscard]] bool operator!=(float value) const; | |||||
| [[nodiscard]] bool operator<(float value) const; | |||||
| [[nodiscard]] bool operator<=(float value) const; | |||||
| [[nodiscard]] bool operator>(float value) const; | |||||
| [[nodiscard]] bool operator>=(float value) const; | |||||
| }; | }; | ||||
| lol_attr_nodiscard bool operator==(float value, const TestEpsilon& epsilon); | |||||
| lol_attr_nodiscard bool operator!=(float value, const TestEpsilon& epsilon); | |||||
| lol_attr_nodiscard bool operator<(float value, const TestEpsilon& epsilon); | |||||
| lol_attr_nodiscard bool operator<=(float value, const TestEpsilon& epsilon); | |||||
| lol_attr_nodiscard bool operator>(float value, const TestEpsilon& epsilon); | |||||
| lol_attr_nodiscard bool operator>=(float value, const TestEpsilon& epsilon); | |||||
| [[nodiscard]] bool operator==(float value, const TestEpsilon& epsilon); | |||||
| [[nodiscard]] bool operator!=(float value, const TestEpsilon& epsilon); | |||||
| [[nodiscard]] bool operator<(float value, const TestEpsilon& epsilon); | |||||
| [[nodiscard]] bool operator<=(float value, const TestEpsilon& epsilon); | |||||
| [[nodiscard]] bool operator>(float value, const TestEpsilon& epsilon); | |||||
| [[nodiscard]] bool operator>=(float value, const TestEpsilon& epsilon); | |||||
| //-- | //-- | ||||
| static inline bool TestAABBVsAABB(box2 const &b1, box2 const &b2) | static inline bool TestAABBVsAABB(box2 const &b1, box2 const &b2) | ||||
| @@ -32,7 +32,7 @@ namespace lol | |||||
| namespace half_ops { struct base {}; } | namespace half_ops { struct base {}; } | ||||
| class lol_attr_nodiscard half | |||||
| class [[nodiscard]] half | |||||
| : half_ops::base | : half_ops::base | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -44,22 +44,22 @@ public: | |||||
| inline half(double f) { *this = makefast((float)f); } | inline half(double f) { *this = makefast((float)f); } | ||||
| inline half(ldouble f) { *this = makefast((float)f); } | inline half(ldouble f) { *this = makefast((float)f); } | ||||
| lol_attr_nodiscard inline int is_nan() const | |||||
| [[nodiscard]] inline int is_nan() const | |||||
| { | { | ||||
| return ((bits & 0x7c00u) == 0x7c00u) && (bits & 0x03ffu); | return ((bits & 0x7c00u) == 0x7c00u) && (bits & 0x03ffu); | ||||
| } | } | ||||
| lol_attr_nodiscard inline int is_finite() const | |||||
| [[nodiscard]] inline int is_finite() const | |||||
| { | { | ||||
| return (bits & 0x7c00u) != 0x7c00u; | return (bits & 0x7c00u) != 0x7c00u; | ||||
| } | } | ||||
| lol_attr_nodiscard inline int is_inf() const | |||||
| [[nodiscard]] inline int is_inf() const | |||||
| { | { | ||||
| return (uint16_t)(bits << 1) == (0x7c00u << 1); | return (uint16_t)(bits << 1) == (0x7c00u << 1); | ||||
| } | } | ||||
| lol_attr_nodiscard inline int is_normal() const | |||||
| [[nodiscard]] inline int is_normal() const | |||||
| { | { | ||||
| return (is_finite() && (bits & 0x7c00u)) || ((bits & 0x7fffu) == 0); | return (is_finite() && (bits & 0x7c00u)) || ((bits & 0x7fffu) == 0); | ||||
| } | } | ||||
| @@ -69,33 +69,33 @@ public: | |||||
| inline half &operator =(float f) { return *this = makefast(f); } | inline half &operator =(float f) { return *this = makefast(f); } | ||||
| inline half &operator =(double f) { return *this = makefast((float)f); } | inline half &operator =(double f) { return *this = makefast((float)f); } | ||||
| inline half &operator =(ldouble f) { return *this = makefast((float)f); } | inline half &operator =(ldouble f) { return *this = makefast((float)f); } | ||||
| lol_attr_nodiscard inline operator int8_t() const { return (int8_t)(float)*this; } | |||||
| lol_attr_nodiscard inline operator uint8_t() const { return (uint8_t)(float)*this; } | |||||
| lol_attr_nodiscard inline operator int16_t() const { return (int16_t)(float)*this; } | |||||
| lol_attr_nodiscard inline operator uint16_t() const { return (uint16_t)(float)*this; } | |||||
| lol_attr_nodiscard inline operator int32_t() const { return (int32_t)(float)*this; } | |||||
| lol_attr_nodiscard inline operator uint32_t() const { return (uint32_t)(float)*this; } | |||||
| lol_attr_nodiscard inline operator int64_t() const { return (int64_t)(float)*this; } | |||||
| lol_attr_nodiscard inline operator uint64_t() const { return (uint64_t)(float)*this; } | |||||
| lol_attr_nodiscard operator float() const; | |||||
| lol_attr_nodiscard inline operator double() const { return (float)(*this); } | |||||
| lol_attr_nodiscard inline operator ldouble() const { return (float)(*this); } | |||||
| [[nodiscard]] inline operator int8_t() const { return (int8_t)(float)*this; } | |||||
| [[nodiscard]] inline operator uint8_t() const { return (uint8_t)(float)*this; } | |||||
| [[nodiscard]] inline operator int16_t() const { return (int16_t)(float)*this; } | |||||
| [[nodiscard]] inline operator uint16_t() const { return (uint16_t)(float)*this; } | |||||
| [[nodiscard]] inline operator int32_t() const { return (int32_t)(float)*this; } | |||||
| [[nodiscard]] inline operator uint32_t() const { return (uint32_t)(float)*this; } | |||||
| [[nodiscard]] inline operator int64_t() const { return (int64_t)(float)*this; } | |||||
| [[nodiscard]] inline operator uint64_t() const { return (uint64_t)(float)*this; } | |||||
| [[nodiscard]] operator float() const; | |||||
| [[nodiscard]] inline operator double() const { return (float)(*this); } | |||||
| [[nodiscard]] inline operator ldouble() const { return (float)(*this); } | |||||
| /* Array conversions */ | /* Array conversions */ | ||||
| static void convert(half *dst, float const *src, size_t nelem); | static void convert(half *dst, float const *src, size_t nelem); | ||||
| static void convert(float *dst, half const *src, size_t nelem); | static void convert(float *dst, half const *src, size_t nelem); | ||||
| /* Operations */ | /* Operations */ | ||||
| lol_attr_nodiscard bool operator ==(half x) const { return (float)*this == (float)x; } | |||||
| lol_attr_nodiscard bool operator !=(half x) const { return (float)*this != (float)x; } | |||||
| lol_attr_nodiscard bool operator <(half x) const { return (float)*this < (float)x; } | |||||
| lol_attr_nodiscard bool operator >(half x) const { return (float)*this > (float)x; } | |||||
| lol_attr_nodiscard bool operator <=(half x) const { return (float)*this <= (float)x; } | |||||
| lol_attr_nodiscard bool operator >=(half x) const { return (float)*this >= (float)x; } | |||||
| [[nodiscard]] bool operator ==(half x) const { return (float)*this == (float)x; } | |||||
| [[nodiscard]] bool operator !=(half x) const { return (float)*this != (float)x; } | |||||
| [[nodiscard]] bool operator <(half x) const { return (float)*this < (float)x; } | |||||
| [[nodiscard]] bool operator >(half x) const { return (float)*this > (float)x; } | |||||
| [[nodiscard]] bool operator <=(half x) const { return (float)*this <= (float)x; } | |||||
| [[nodiscard]] bool operator >=(half x) const { return (float)*this >= (float)x; } | |||||
| lol_attr_nodiscard bool operator !() const { return !(bits & 0x7fffu); } | |||||
| lol_attr_nodiscard operator bool() const { return !!*this; } | |||||
| [[nodiscard]] bool operator !() const { return !(bits & 0x7fffu); } | |||||
| [[nodiscard]] operator bool() const { return !!*this; } | |||||
| inline half operator -() const { return makebits(bits ^ 0x8000u); } | inline half operator -() const { return makebits(bits ^ 0x8000u); } | ||||
| inline half operator +() const { return *this; } | inline half operator +() const { return *this; } | ||||
| @@ -104,10 +104,10 @@ public: | |||||
| inline half &operator *=(half h) { return (*this = (half)(*this * h)); } | inline half &operator *=(half h) { return (*this = (half)(*this * h)); } | ||||
| inline half &operator /=(half h) { return (*this = (half)(*this / h)); } | inline half &operator /=(half h) { return (*this = (half)(*this / h)); } | ||||
| lol_attr_nodiscard inline float operator +(half h) const { return (float)*this + (float)h; } | |||||
| lol_attr_nodiscard inline float operator -(half h) const { return (float)*this - (float)h; } | |||||
| lol_attr_nodiscard inline float operator *(half h) const { return (float)*this * (float)h; } | |||||
| lol_attr_nodiscard inline float operator /(half h) const { return (float)*this / (float)h; } | |||||
| [[nodiscard]] inline float operator +(half h) const { return (float)*this + (float)h; } | |||||
| [[nodiscard]] inline float operator -(half h) const { return (float)*this - (float)h; } | |||||
| [[nodiscard]] inline float operator *(half h) const { return (float)*this * (float)h; } | |||||
| [[nodiscard]] inline float operator /(half h) const { return (float)*this / (float)h; } | |||||
| /* Factories */ | /* Factories */ | ||||
| static half makefast(float f); | static half makefast(float f); | ||||