#ifndef CORE_CONSTEXPR_HH #define CORE_CONSTEXPR_HH 1 #pragma once namespace cxpr { 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 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 cxpr template constexpr static inline const T cxpr::abs(const T x) { if(x < static_cast(0)) return -x; return x; } template constexpr static inline const std::size_t cxpr::array_size(const T(&)[L]) { return L; } template constexpr static inline const T cxpr::ceil(const F x) { static_assert(std::is_integral_v); static_assert(std::is_floating_point_v); const T ival = static_cast(x); if(ival < x) return ival + static_cast(1); return ival; } template constexpr static inline const T cxpr::degrees(const T x) { return x * static_cast(180.0) / static_cast(M_PI); } template constexpr static inline const T cxpr::floor(const F x) { static_assert(std::is_integral_v); static_assert(std::is_floating_point_v); const T ival = static_cast(x); if(ival > x) return ival - static_cast(1); return ival; } template constexpr static inline const T cxpr::clamp(const T x, const T min, const T max) { if(x < min) return min; if(x > max) return max; return x; } template constexpr static inline const T cxpr::lerp(const T x, const T y, const F a) { static_assert(std::is_arithmetic_v); static_assert(std::is_floating_point_v); return static_cast(static_cast(x) * (static_cast(1.0f) - a) + static_cast(y) * a); } template constexpr static inline const T cxpr::log2(const T x) { if(x < 2) return 0; return cxpr::log2((x + 1) >> 1) + 1; } template constexpr static inline const T cxpr::max(const T x, const T y) { if(x < y) return y; return x; } template constexpr static inline const T cxpr::min(const T x, const T y) { if(x > y) return y; return x; } template constexpr static inline const T cxpr::mod_signed(const T x, const T m) { static_assert(std::is_signed_v); static_assert(std::is_integral_v); const T result = static_cast(x % m); if(result < T(0)) return result + m; return result; } template constexpr static inline const T cxpr::pow2(const T x) { T value = static_cast(1); while(value < x) value *= static_cast(2); return value; } template constexpr static inline const T cxpr::radians(const T x) { return x * static_cast(M_PI) / static_cast(180.0); } template constexpr static inline const bool cxpr::range(const T x, const T min, const T max) { return ((x >= min) && (x <= max)); } template constexpr static inline const T cxpr::sign(const F x) { if(x < F(0)) return T(-1); if(x > F(0)) return T(+1); return T(0); } template constexpr static inline const T cxpr::smoothstep(const T x, const T y, const F a) { static_assert(std::is_arithmetic_v); static_assert(std::is_floating_point_v); const F t = cxpr::clamp((a - x) / (y - x), F(0), F(1)); return static_cast(t * t * (F(3) - F(2) * t)); } #endif /* CORE_CONSTEXPR_HH */