#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; } else { 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); } else { 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); } else { return ival; } } template constexpr static inline const T cxpr::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 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; } else { 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; } else { return x; } } template constexpr static inline const T cxpr::min(const T x, const T y) { if(x > y) { return y; } else { 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); auto result = static_cast(x % m); if(result < T(0)) { return result + m; } else { 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); } else if(x > F(0)) { return T(+1); } else { 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 */