Make min, max, mix and clamp constexpr

These functions were already marked constexpr in the header, but their
implementations relied on non-constexpr functions. Mark those as
constexpr.
This commit is contained in:
0xf00ff00f
2025-12-21 18:55:33 -03:00
committed by Christophe
parent 2436fe7671
commit b1fed40786
2 changed files with 61 additions and 11 deletions

View File

@@ -47,12 +47,12 @@ namespace detail
{ {
template<typename T> template<typename T>
struct TMin { struct TMin {
GLM_FUNC_QUALIFIER T operator()(const T& a, const T& b) { return min(a, b); } GLM_FUNC_QUALIFIER GLM_CONSTEXPR T operator()(const T& a, const T& b) { return min(a, b); }
}; };
template<typename T> template<typename T>
struct TMax { struct TMax {
GLM_FUNC_QUALIFIER T operator()(const T& a, const T& b) { return max(a, b); } GLM_FUNC_QUALIFIER GLM_CONSTEXPR T operator()(const T& a, const T& b) { return max(a, b); }
}; };
template<typename T> template<typename T>
@@ -87,7 +87,7 @@ namespace detail
template<length_t L, typename T, typename U, qualifier Q, bool Aligned> template<length_t L, typename T, typename U, qualifier Q, bool Aligned>
struct compute_mix_vector struct compute_mix_vector
{ {
GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, U, Q> const& a) GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, U, Q> const& a)
{ {
static_assert(std::numeric_limits<U>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a"); static_assert(std::numeric_limits<U>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a");
@@ -98,7 +98,7 @@ namespace detail
template<length_t L, typename T, qualifier Q, bool Aligned> template<length_t L, typename T, qualifier Q, bool Aligned>
struct compute_mix_vector<L, T, bool, Q, Aligned> struct compute_mix_vector<L, T, bool, Q, Aligned>
{ {
GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, bool, Q> const& a) GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, bool, Q> const& a)
{ {
vec<L, T, Q> Result(0); vec<L, T, Q> Result(0);
for(length_t i = 0; i < x.length(); ++i) for(length_t i = 0; i < x.length(); ++i)
@@ -110,7 +110,7 @@ namespace detail
template<length_t L, typename T, typename U, qualifier Q, bool Aligned> template<length_t L, typename T, typename U, qualifier Q, bool Aligned>
struct compute_mix_scalar struct compute_mix_scalar
{ {
GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, U const& a) GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, U const& a)
{ {
static_assert(std::numeric_limits<U>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a"); static_assert(std::numeric_limits<U>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a");
@@ -121,7 +121,7 @@ namespace detail
template<length_t L, typename T, qualifier Q, bool Aligned> template<length_t L, typename T, qualifier Q, bool Aligned>
struct compute_mix_scalar<L, T, bool, Q, Aligned> struct compute_mix_scalar<L, T, bool, Q, Aligned>
{ {
GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, bool const& a) GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, bool const& a)
{ {
return a ? y : x; return a ? y : x;
} }
@@ -130,7 +130,7 @@ namespace detail
template<typename T, typename U> template<typename T, typename U>
struct compute_mix struct compute_mix
{ {
GLM_FUNC_QUALIFIER static T call(T const& x, T const& y, U const& a) GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(T const& x, T const& y, U const& a)
{ {
static_assert(std::numeric_limits<U>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a"); static_assert(std::numeric_limits<U>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a");
@@ -141,7 +141,7 @@ namespace detail
template<typename T> template<typename T>
struct compute_mix<T, bool> struct compute_mix<T, bool>
{ {
GLM_FUNC_QUALIFIER static T call(T const& x, T const& y, bool const& a) GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(T const& x, T const& y, bool const& a)
{ {
return a ? y : x; return a ? y : x;
} }
@@ -237,7 +237,7 @@ namespace detail
template<length_t L, typename T, qualifier Q, bool Aligned> template<length_t L, typename T, qualifier Q, bool Aligned>
struct compute_min_vector struct compute_min_vector
{ {
GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y) GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y)
{ {
return detail::functor2<vec, L, T, Q>::call(TMin<T>(), x, y); return detail::functor2<vec, L, T, Q>::call(TMin<T>(), x, y);
} }
@@ -246,7 +246,7 @@ namespace detail
template<length_t L, typename T, qualifier Q, bool Aligned> template<length_t L, typename T, qualifier Q, bool Aligned>
struct compute_max_vector struct compute_max_vector
{ {
GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y) GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y)
{ {
return detail::functor2<vec, L, T, Q>::call(TMax<T>(), x, y); return detail::functor2<vec, L, T, Q>::call(TMax<T>(), x, y);
} }
@@ -255,7 +255,7 @@ namespace detail
template<length_t L, typename T, qualifier Q, bool Aligned> template<length_t L, typename T, qualifier Q, bool Aligned>
struct compute_clamp_vector struct compute_clamp_vector
{ {
GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& minVal, vec<L, T, Q> const& maxVal) GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& minVal, vec<L, T, Q> const& maxVal)
{ {
return min(max(x, minVal), maxVal); return min(max(x, minVal), maxVal);
} }

View File

@@ -298,6 +298,28 @@ namespace min_
return Error; return Error;
} }
#if GLM_HAS_CONSTEXPR
static int test_constexpr()
{
constexpr glm::vec1 A0 = glm::min(glm::vec1(1), glm::vec1(1));
static_assert(glm::all(glm::equal(A0, glm::vec1(1), glm::epsilon<float>())), "GLM: Failed constexpr");
constexpr glm::vec2 B0 = glm::min(glm::vec2(1), glm::vec2(1));
constexpr glm::vec2 B1 = glm::min(glm::vec2(1), 1.0f);
static_assert(glm::all(glm::equal(B0, B1, glm::epsilon<float>())), "GLM: Failed constexpr");
constexpr glm::vec3 C0 = glm::min(glm::vec3(1), glm::vec3(1));
constexpr glm::vec3 C1 = glm::min(glm::vec3(1), 1.0f);
static_assert(glm::all(glm::equal(C0, C1, glm::epsilon<float>())), "GLM: Failed constexpr");
constexpr glm::vec4 D0 = glm::min(glm::vec4(1), glm::vec4(1));
constexpr glm::vec4 D1 = glm::min(glm::vec4(1), 1.0f);
static_assert(glm::all(glm::equal(D0, D1, glm::epsilon<float>())), "GLM: Failed constexpr");
return 0;
}
#endif
static int min_tern(int a, int b) static int min_tern(int a, int b)
{ {
return a < b ? a : b; return a < b ? a : b;
@@ -383,6 +405,28 @@ namespace max_
return Error; return Error;
} }
#if GLM_HAS_CONSTEXPR
static int test_constexpr()
{
constexpr glm::vec1 A0 = glm::max(glm::vec1(1), glm::vec1(1));
static_assert(glm::all(glm::equal(A0, glm::vec1(1), glm::epsilon<float>())), "GLM: Failed constexpr");
constexpr glm::vec2 B0 = glm::max(glm::vec2(1), glm::vec2(1));
constexpr glm::vec2 B1 = glm::max(glm::vec2(1), 1.0f);
static_assert(glm::all(glm::equal(B0, B1, glm::epsilon<float>())), "GLM: Failed constexpr");
constexpr glm::vec3 C0 = glm::max(glm::vec3(1), glm::vec3(1));
constexpr glm::vec3 C1 = glm::max(glm::vec3(1), 1.0f);
static_assert(glm::all(glm::equal(C0, C1, glm::epsilon<float>())), "GLM: Failed constexpr");
constexpr glm::vec4 D0 = glm::max(glm::vec4(1), glm::vec4(1));
constexpr glm::vec4 D1 = glm::max(glm::vec4(1), 1.0f);
static_assert(glm::all(glm::equal(D0, D1, glm::epsilon<float>())), "GLM: Failed constexpr");
return 0;
}
#endif
}//namespace max_ }//namespace max_
namespace clamp_ namespace clamp_
@@ -1386,7 +1430,13 @@ int main()
Error += step_::test(); Error += step_::test();
Error += smoothstep_::test(); Error += smoothstep_::test();
Error += max_::test(); Error += max_::test();
#if GLM_HAS_CONSTEXPR
Error += max_::test_constexpr();
#endif
Error += min_::test(); Error += min_::test();
#if GLM_HAS_CONSTEXPR
Error += min_::test_constexpr();
#endif
Error += clamp_::test(); Error += clamp_::test();
Error += round_::test(); Error += round_::test();
Error += roundEven::test(); Error += roundEven::test();