#ifndef CORE_CONSTEXPR_HH #define CORE_CONSTEXPR_HH 1 #pragma once #include "core/concepts.hh" namespace vx { template constexpr static inline const T abs(const T x); template constexpr static inline const std::size_t array_size(const T (&)[L]); template constexpr static inline const T ceil(const F x); template constexpr static inline const T degrees(const T x); template constexpr static inline const T floor(const F x); template constexpr static inline const T clamp(const T x, const T min, const T max); template constexpr static inline const T lerp(const T x, const T y, const F a); template constexpr static inline const T log2(const T x); template constexpr static inline const T max(const T x, const T y); template constexpr static inline const T min(const T x, const T y); template requires std::is_signed_v constexpr static inline const T mod_signed(const T x, const T m); template constexpr static inline const T pow2(const T x); template constexpr static inline const T radians(const T x); template constexpr static inline const bool range(const T x, const T min, const T max); template constexpr static inline const T sign(const F x); template constexpr static inline const T smoothstep(const T x, const T y, const F a); } // namespace vx template constexpr static inline const T vx::abs(const T x) { if(x < static_cast(0)) { return -x; } else { return x; } } template constexpr static inline const std::size_t vx::array_size(const T (&)[L]) { return L; } template constexpr static inline const T vx::ceil(const F x) { const T ival = static_cast(x); if(ival < x) { return ival + static_cast(1); } else { return ival; } } template constexpr static inline const T vx::degrees(const T x) { return x * static_cast(180.0) / static_cast(M_PI); } template constexpr static inline const T vx::floor(const F x) { const T ival = static_cast(x); if(ival > x) { return ival - static_cast(1); } else { return ival; } } template constexpr static inline const T vx::clamp(const T x, const T min, const T max) { if(x < min) { return min; } else if(x > max) { return max; } else { return x; } } template constexpr static inline const T vx::lerp(const T x, const T y, const F a) { return static_cast(static_cast(x) * (static_cast(1.0f) - a) + static_cast(y) * a); } template constexpr static inline const T vx::log2(const T x) { if(x < 2) { return 0; } else { return vx::log2((x + 1) >> 1) + 1; } } template constexpr static inline const T vx::max(const T x, const T y) { if(x < y) { return y; } else { return x; } } template constexpr static inline const T vx::min(const T x, const T y) { if(x > y) { return y; } else { return x; } } template requires std::is_signed_v constexpr static inline const T vx::mod_signed(const T x, const T m) { auto result = static_cast(x % m); if(result < T(0)) { return result + m; } else { return result; } } template constexpr static inline const T vx::pow2(const T x) { T value = static_cast(1); while(value < x) value *= static_cast(2); return value; } template constexpr static inline const T vx::radians(const T x) { return x * static_cast(M_PI) / static_cast(180.0); } template constexpr static inline const bool vx::range(const T x, const T min, const T max) { return ((x >= min) && (x <= max)); } template constexpr static inline const T vx::sign(const F x) { if(x < F(0)) { return T(-1); } else if(x > F(0)) { return T(+1); } else { return T(0); } } template constexpr static inline const T vx::smoothstep(const T x, const T y, const F a) { const F t = vx::clamp((a - x) / (y - x), F(0), F(1)); return static_cast(t * t * (F(3) - F(2) * t)); } #endif // CORE_CONSTEXPR_HH