19#ifndef MTCORE_MATH_CORE_HPP
20#define MTCORE_MATH_CORE_HPP
40 template<
typename T,
typename R =
double>
45 const T max =
static_cast<T
>(
static_cast<uint64_t
>(1) <<
static_cast<uint64_t
>(std::numeric_limits<T>::digits - 1));
46 if (num >= max || num <= -max) {
47 return static_cast<R
>(num);
49 const auto a =
static_cast<T
>(
static_cast<int64_t
>(num));
50 return (num < 0 && num != a) ?
static_cast<R
>(a - 1) :
static_cast<R
>(a);
61 template<
typename T,
typename R =
double>
66 const T max =
static_cast<T
>(
static_cast<uint64_t
>(1) <<
static_cast<uint64_t
>(std::numeric_limits<T>::digits - 1));
67 if (num >= max || num <= -max) {
70 const auto a =
static_cast<T
>(
static_cast<int64_t
>(num));
71 return (num > 0 && num != a) ?
static_cast<R
>(a + 1) :
static_cast<R
>(a);
81 template<
typename T,
typename R = T>
82 constexpr R
floor(T num)
noexcept {
83 if constexpr (std::is_integral<T>::value) {
84 return static_cast<R
>(num);
86 else if (std::is_constant_evaluated()) {
90 return static_cast<R
>(std::floor(num));
102 template<
typename T,
typename R = T>
103 constexpr R
ceil(T v)
noexcept {
104 if constexpr (std::is_integral_v<T>) {
105 return static_cast<R
>(v);
107 else if (std::is_constant_evaluated()) {
111 return static_cast<R
>(std::ceil(v));
127 template<
typename L,
typename R,
typename Res = L>
128 constexpr Res
mod(L left, R right)
noexcept {
129 if (std::is_integral_v<L> || std::is_integral_v<R>) {
130 return static_cast<Res
>(
mod(
static_cast<long double>(left),
static_cast<long double>(right)));
133 return static_cast<Res
>(left - right *
math::floor(left / right));
143 return a == b ? x : a +
mod(x - a, b - a);
150 template<
typename L,
typename R,
typename Res = L>
151 constexpr auto amod(L x, R y)
noexcept -> Res {
152 return static_cast<Res
>(y +
mod(x, -y));
160 template<
typename T,
typename R = T>
161 constexpr auto approx_eq(T x, R y, T epsilon = T{0.000001})
noexcept ->
bool {
162 return (x <= y + epsilon) & (x >= y - epsilon);
171 constexpr int sign(
const T &v) {
189 return l *
static_cast<L
>(
sign(l));
207 else if ((exp & 1) == 0) {
208 return int_pow(val * val, exp / 2);
211 return val *
int_pow(val * val, (exp - 1) / 2);
222 template<std::
integral T>
223 constexpr T
gcd(T a, T b) {
237 template<std::
integral T>
238 constexpr T
lcm(T a, T b) {
constexpr auto approx_eq(T x, R y, T epsilon=T{0.000001}) noexcept -> bool
Checks if two numbers are approximately equal (within epsilon distance)
constexpr R floor(T num) noexcept
Floors a number with support for constexpr and fast runtime compilation.
constexpr R ceil_constexpr(T num) noexcept
Constexpr ceil function.
constexpr R ceil(T v) noexcept
Ceils a number with support for constexpr and fast runtime compilation.
constexpr Res mod(L left, R right) noexcept
Calculates the mathematical mod of two numbers.
constexpr auto amod(L x, R y) noexcept -> Res
x mod [1..y]
constexpr auto mod_range(T x, i64 a, i64 b) noexcept -> T
x mod [a..b)
constexpr R floor_constexpr(T num) noexcept
Constexpr floor function.
constexpr T lcm(T a, T b)
Calculates the LCM (Least Common Multiple) of two integer numbers.
constexpr int sign(const T &v)
Gets the sign (1 for positive, -1 for negative, 0 for zero)
constexpr L abs(L l)
Gets absolute value of a number.
constexpr T int_pow(T val, int exp)
Raises to an integer power (positive or negative)
constexpr T gcd(T a, T b)
Calculates the GCD (Greatest Common Divisor) of two integer numbers.
int64_t i64
Alias for 64-bit ints.
Math utilities, often with constexpr support.