From f0b305ce4327d0d6ac9be025817febad95df43fd Mon Sep 17 00:00:00 2001 From: sharkautarch <128002472+sharkautarch@users.noreply.github.com> Date: Wed, 11 Sep 2024 14:09:50 -0400 Subject: [PATCH] simd constexpr vec: fix some compile-time and run-time issues --- glm/detail/simd_constexpr/vec.hpp | 130 ++++++++++++++++-------- test/core/core_c++20_simd_constexpr.cpp | 2 +- 2 files changed, 89 insertions(+), 43 deletions(-) diff --git a/glm/detail/simd_constexpr/vec.hpp b/glm/detail/simd_constexpr/vec.hpp index 217d0069..093cb9bc 100644 --- a/glm/detail/simd_constexpr/vec.hpp +++ b/glm/detail/simd_constexpr/vec.hpp @@ -98,6 +98,9 @@ namespace glm #include "simd_helpers.inl" #include "../compute_vector_relational.hpp" #include "../compute_vector_decl.hpp" +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "../type_vec_simd.inl" +#endif namespace glm { template @@ -131,12 +134,55 @@ namespace glm default: case 0: return x; - case 1: - return y.t; - case 2: - return z.t; - case 3: - return w.t; + case 1: { + if constexpr (L>=2) + return y.t; + else + __builtin_unreachable(); + } + case 2:{ + if constexpr (L>=3) + return z.t; + else + __builtin_unreachable(); + } + case 3:{ + if constexpr (L>=4) + return w.t; + else + __builtin_unreachable(); + } + } + } + + inline GLM_CONSTEXPR T operator[](length_t i) const + { + if (!std::is_constant_evaluated()) { + GLM_ASSERT_LENGTH(i, L); + } + switch (std::max(i, length())) + { + default: + case 0: + return x; + case 1: { + if constexpr (L>=2) + return y.t; + else + __builtin_unreachable(); + } + case 2:{ + if constexpr (L>=3) + return z.t; + else + __builtin_unreachable(); + } + case 3:{ + if constexpr (L>=4) + return w.t; + else + __builtin_unreachable(); + } } } @@ -302,7 +348,7 @@ namespace glm } template - inline GLM_CONSTEXPR vec & operator+=(vec<1, Tx, Q> v) + inline GLM_CONSTEXPR vec & operator+=(vec<1, Tx, Q> v) requires (L != 1) { return (*this = detail::compute_vec_add::value>::call(*this, vec(v.x))); } @@ -319,7 +365,7 @@ namespace glm } template - inline GLM_CONSTEXPR vec & operator-=(vec<1, Tx, Q> v) + inline GLM_CONSTEXPR vec & operator-=(vec<1, Tx, Q> v) requires (L != 1) { return (*this = detail::compute_vec_sub::value>::call(*this, vec(v.x))); } @@ -336,7 +382,7 @@ namespace glm } template - inline GLM_CONSTEXPR vec & operator*=(vec<1, Tx, Q> v) + inline GLM_CONSTEXPR vec & operator*=(vec<1, Tx, Q> v) requires (L != 1) { return (*this = detail::compute_vec_mul::value>::call(*this, vec(v.x))); } @@ -353,7 +399,7 @@ namespace glm } template - inline GLM_CONSTEXPR vec & operator/=(vec<1, Tx, Q> v) + inline GLM_CONSTEXPR vec & operator/=(vec<1, Tx, Q> v) requires (L != 1) { return (*this = detail::compute_vec_div::value>::call(*this, vec(v.x))); } @@ -406,7 +452,7 @@ namespace glm } template - inline GLM_CONSTEXPR vec & operator%=(vec<1, Tx, Q> v) + inline GLM_CONSTEXPR vec & operator%=(vec<1, Tx, Q> v) requires (L != 1) { return (*this = detail::compute_vec_mod::value>::call(*this, vec(v))); } @@ -423,7 +469,7 @@ namespace glm } template - inline GLM_CONSTEXPR vec & operator&=(vec<1, Tx, Q> v) + inline GLM_CONSTEXPR vec & operator&=(vec<1, Tx, Q> v) requires (L != 1) { return (*this = detail::compute_vec_and::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec(v))); } @@ -440,7 +486,7 @@ namespace glm } template - inline GLM_CONSTEXPR vec & operator|=(vec<1, Tx, Q> const& v) + inline GLM_CONSTEXPR vec & operator|=(vec<1, Tx, Q> const& v) requires (L != 1) { return (*this = detail::compute_vec_or::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec(v))); } @@ -457,7 +503,7 @@ namespace glm } template - inline GLM_CONSTEXPR vec & operator^=(vec<1, Tx, Q> const& v) + inline GLM_CONSTEXPR vec & operator^=(vec<1, Tx, Q> const& v) requires (L != 1) { return (*this = detail::compute_vec_xor::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec(v))); } @@ -474,7 +520,7 @@ namespace glm } template - inline GLM_CONSTEXPR vec & operator<<=(vec<1, Tx, Q> const& v) + inline GLM_CONSTEXPR vec & operator<<=(vec<1, Tx, Q> const& v) requires (L != 1) { return (*this = detail::compute_vec_shift_left::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec(v))); } @@ -491,7 +537,7 @@ namespace glm } template - inline GLM_CONSTEXPR vec & operator>>=(vec<1, Tx, Q> const& v) + inline GLM_CONSTEXPR vec & operator>>=(vec<1, Tx, Q> const& v) requires (L != 1) { return (*this = detail::compute_vec_shift_right::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec(v))); } @@ -521,7 +567,7 @@ namespace glm return vec(*this) += scalar; } - inline GLM_CONSTEXPR vec operator+(vec<1, T, Q> const& v2) + inline GLM_CONSTEXPR vec operator+(vec<1, T, Q> const& v2) requires (L != 1) { return vec(*this) += v2; } @@ -531,7 +577,7 @@ namespace glm return vec(v) += scalar; } - friend inline GLM_CONSTEXPR vec operator+(vec<1, T, Q> const& v1, vec const& v2) + friend inline GLM_CONSTEXPR vec operator+(vec<1, T, Q> const& v1, vec const& v2) requires (L != 1) { return vec(v2) += v1; } @@ -546,7 +592,7 @@ namespace glm return vec(*this) -= scalar; } - inline GLM_CONSTEXPR vec operator-(vec<1, T, Q> const& v2) + inline GLM_CONSTEXPR vec operator-(vec<1, T, Q> const& v2) requires (L != 1) { return vec(*this) -= v2; } @@ -556,7 +602,7 @@ namespace glm return vec(scalar) -= v; } - friend inline GLM_CONSTEXPR vec operator-(vec<1, T, Q> const& v1, vec const& v2) + friend inline GLM_CONSTEXPR vec operator-(vec<1, T, Q> const& v1, vec const& v2) requires (L != 1) { return vec(v1.x) -= v2; } @@ -572,7 +618,7 @@ namespace glm } - inline GLM_CONSTEXPR vec operator*(vec<1, T, Q> const& v2) + inline GLM_CONSTEXPR vec operator*(vec<1, T, Q> const& v2) requires (L != 1) { return vec(*this) *= v2; } @@ -584,7 +630,7 @@ namespace glm } - friend inline GLM_CONSTEXPR vec operator*(vec<1, T, Q> const& v1, vec const& v2) + friend inline GLM_CONSTEXPR vec operator*(vec<1, T, Q> const& v1, vec const& v2) requires (L != 1) { return vec(v2) *= v1; } @@ -602,7 +648,7 @@ namespace glm } - inline GLM_CONSTEXPR vec operator/(vec<1, T, Q> const& v2) + inline GLM_CONSTEXPR vec operator/(vec<1, T, Q> const& v2) requires (L != 1) { return vec(*this) /= v2; } @@ -614,7 +660,7 @@ namespace glm } - friend inline GLM_CONSTEXPR vec operator/(vec<1, T, Q> const& v1, vec const& v2) + friend inline GLM_CONSTEXPR vec operator/(vec<1, T, Q> const& v1, vec const& v2) requires (L != 1) { return vec(v1.x) /= v2; } @@ -634,9 +680,9 @@ namespace glm } - friend inline GLM_CONSTEXPR vec operator%(vec const& v1, vec<1, T, Q> const& v2) + inline GLM_CONSTEXPR vec operator%(vec<1, T, Q> const& v2) requires (L != 1) { - return vec(v1) %= v2.x; + return vec(*this) %= v2.x; } @@ -646,7 +692,7 @@ namespace glm } - friend inline GLM_CONSTEXPR vec operator%(vec<1, T, Q> const& scalar, vec const& v) + friend inline GLM_CONSTEXPR vec operator%(vec<1, T, Q> const& scalar, vec const& v) requires (L != 1) { return vec(scalar.x) %= v; } @@ -664,9 +710,9 @@ namespace glm } - friend inline GLM_CONSTEXPR vec operator&(vec const& v, vec<1, T, Q> const& scalar) + inline GLM_CONSTEXPR vec operator&(vec<1, T, Q> const& scalar) requires (L != 1) { - return vec(v) &= scalar; + return vec(*this) &= scalar; } @@ -676,7 +722,7 @@ namespace glm } - friend inline GLM_CONSTEXPR vec operator&(vec<1, T, Q> const& v1, vec const& v2) + friend inline GLM_CONSTEXPR vec operator&(vec<1, T, Q> const& v1, vec const& v2) requires (L != 1) { return vec(v1.x) &= v2; } @@ -694,9 +740,9 @@ namespace glm } - friend inline GLM_CONSTEXPR vec operator|(vec const& v1, vec<1, T, Q> const& v2) + inline GLM_CONSTEXPR vec operator|(vec<1, T, Q> const& v2) requires (L != 1) { - return vec(v1) |= v2.x; + return vec(*this) |= v2.x; } @@ -706,7 +752,7 @@ namespace glm } - friend inline GLM_CONSTEXPR vec operator|(vec<1, T, Q> const& v1, vec const& v2) + friend inline GLM_CONSTEXPR vec operator|(vec<1, T, Q> const& v1, vec const& v2) requires (L != 1) { return vec(v1.x) |= v2; } @@ -724,9 +770,9 @@ namespace glm } - friend inline GLM_CONSTEXPR vec operator^(vec const& v1, vec<1, T, Q> const& v2) + inline GLM_CONSTEXPR vec operator^(vec<1, T, Q> const& v2) requires (L != 1) { - return vec(v1) ^= v2.x; + return vec(*this) ^= v2.x; } @@ -736,7 +782,7 @@ namespace glm } - friend inline GLM_CONSTEXPR vec operator^(vec<1, T, Q> const& v1, vec const& v2) + friend inline GLM_CONSTEXPR vec operator^(vec<1, T, Q> const& v1, vec const& v2) requires (L != 1) { return vec(v1.x) ^= v2; } @@ -754,9 +800,9 @@ namespace glm } - friend inline GLM_CONSTEXPR vec operator<<(vec const& v1, vec<1, T, Q> const& v2) + inline GLM_CONSTEXPR vec operator<<(vec<1, T, Q> const& v2) requires (L != 1) { - return vec(v1) <<= v2.x; + return vec(*this) <<= v2.x; } @@ -766,7 +812,7 @@ namespace glm } - friend inline GLM_CONSTEXPR vec operator<<(vec<1, T, Q> const& v1, vec const& v2) + friend inline GLM_CONSTEXPR vec operator<<(vec<1, T, Q> const& v1, vec const& v2) requires (L != 1) { return vec(v1.x) <<= v2; } @@ -784,9 +830,9 @@ namespace glm } - friend inline GLM_CONSTEXPR vec operator>>(vec const& v1, vec<1, T, Q> const& v2) + inline GLM_CONSTEXPR vec operator>>(vec<1, T, Q> const& v2) requires (L != 1) { - return vec(v1) >>= v2.x; + return vec(*this) >>= v2.x; } @@ -796,7 +842,7 @@ namespace glm } - friend inline GLM_CONSTEXPR vec operator>>(vec<1, T, Q> const& v1, vec const& v2) + friend inline GLM_CONSTEXPR vec operator>>(vec<1, T, Q> const& v1, vec const& v2) requires (L != 1) { return vec(v1.x) >>= v2; } diff --git a/test/core/core_c++20_simd_constexpr.cpp b/test/core/core_c++20_simd_constexpr.cpp index da9b8fb3..9d8ad8d3 100644 --- a/test/core/core_c++20_simd_constexpr.cpp +++ b/test/core/core_c++20_simd_constexpr.cpp @@ -32,6 +32,6 @@ int main() avec4 vfin = glm::max(v1, v2) + v3; static_assert(sizeof(vfin)>0); printf("vfin = %f %f %f %f\n", vfin[0], vfin[1], vfin[2], vfin[3]); - printf("v3 = %f %f %f %f\n", v3.x, v3.y, v3.z, v3.w); + printf("v3 = %f %f %f %f\n", v3[0], v3[1], v3[2], v3[3]); return 0; }