#pragma once #include #include #include namespace BAN::Math { template inline constexpr T min(T a, T b) { return a < b ? a : b; } template inline constexpr T max(T a, T b) { return a > b ? a : b; } template inline constexpr T clamp(T x, T min, T max) { return x < min ? min : x > max ? max : x; } template inline constexpr T gcd(T a, T b) { T t; while (b) { t = b; b = a % b; a = t; } return a; } template inline constexpr T lcm(T a, T b) { return a / gcd(a, b) * b; } template inline constexpr T div_round_up(T a, T b) { return (a + b - 1) / b; } template inline constexpr bool is_power_of_two(T value) { if (value == 0) return false; return (value & (value - 1)) == 0; } template requires is_same_v || is_same_v || is_same_v inline constexpr T ilog2(T value) { if constexpr(is_same_v) return sizeof(T) * 8 - __builtin_clz(value) - 1; if constexpr(is_same_v) return sizeof(T) * 8 - __builtin_clzl(value) - 1; return sizeof(T) * 8 - __builtin_clzll(value) - 1; } template inline constexpr T log2(T value) { T result; asm volatile("fyl2x" : "=t"(result) : "0"(value), "u"((T)1.0) : "st(1)"); return result; } template inline constexpr T log10(T value) { constexpr T INV_LOG_2_10 = 0.3010299956639811952137388947244930267681898814621085413104274611; T result; asm volatile("fyl2x" : "=t"(result) : "0"(value), "u"(INV_LOG_2_10) : "st(1)"); return result; } template inline constexpr T log(T value, T base) { return log2(value) / log2(base); } template inline constexpr T pow(T base, T exp) { T result; asm volatile( "fyl2x;" "fld1;" "fld %%st(1);" "fprem;" "f2xm1;" "faddp;" "fscale;" "fxch %%st(1);" "fstp %%st;" : "=t"(result) : "0"(base), "u"(exp) ); return result; } }