2018-09-05 16:57:52 +00:00
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include "types.h"
|
|
|
|
|
|
|
|
|
|
namespace utils
|
|
|
|
|
{
|
|
|
|
|
// Rotate helpers
|
|
|
|
|
#if defined(__GNUG__)
|
|
|
|
|
|
2019-03-12 21:06:12 +00:00
|
|
|
|
constexpr u64 umulh64(u64 a, u64 b)
|
2018-09-05 16:57:52 +00:00
|
|
|
|
{
|
2019-03-12 21:06:12 +00:00
|
|
|
|
const __uint128_t x = a;
|
|
|
|
|
const __uint128_t y = b;
|
|
|
|
|
return (x * y) >> 64;
|
2018-09-05 16:57:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-12 21:06:12 +00:00
|
|
|
|
constexpr s64 mulh64(s64 a, s64 b)
|
2018-09-05 16:57:52 +00:00
|
|
|
|
{
|
2019-03-12 21:06:12 +00:00
|
|
|
|
const __int128_t x = a;
|
|
|
|
|
const __int128_t y = b;
|
|
|
|
|
return (x * y) >> 64;
|
2018-09-05 16:57:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-08-30 16:47:31 +00:00
|
|
|
|
constexpr s64 div128(s64 high, s64 low, s64 divisor, s64* remainder = nullptr)
|
|
|
|
|
{
|
|
|
|
|
const __int128_t x = (__uint128_t{u64(high)} << 64) | u64(low);
|
|
|
|
|
const __int128_t r = x / divisor;
|
|
|
|
|
|
|
|
|
|
if (remainder)
|
|
|
|
|
{
|
|
|
|
|
*remainder = x % divisor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
constexpr u64 udiv128(u64 high, u64 low, u64 divisor, u64* remainder = nullptr)
|
|
|
|
|
{
|
|
|
|
|
const __uint128_t x = (__uint128_t{high} << 64) | low;
|
|
|
|
|
const __uint128_t r = x / divisor;
|
|
|
|
|
|
|
|
|
|
if (remainder)
|
|
|
|
|
{
|
|
|
|
|
*remainder = x % divisor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-05 16:57:52 +00:00
|
|
|
|
#elif defined(_MSC_VER)
|
|
|
|
|
|
|
|
|
|
inline u64 umulh64(u64 x, u64 y)
|
|
|
|
|
{
|
|
|
|
|
return __umulh(x, y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline s64 mulh64(s64 x, s64 y)
|
|
|
|
|
{
|
|
|
|
|
return __mulh(x, y);
|
|
|
|
|
}
|
2019-08-30 16:47:31 +00:00
|
|
|
|
|
|
|
|
|
inline s64 div128(s64 high, s64 low, s64 divisor, s64* remainder = nullptr)
|
|
|
|
|
{
|
|
|
|
|
s64 rem;
|
|
|
|
|
s64 r = _div128(high, low, divisor, &rem);
|
|
|
|
|
|
|
|
|
|
if (remainder)
|
|
|
|
|
{
|
|
|
|
|
*remainder = rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline u64 udiv128(u64 high, u64 low, u64 divisor, u64* remainder = nullptr)
|
|
|
|
|
{
|
|
|
|
|
u64 rem;
|
|
|
|
|
u64 r = _udiv128(high, low, divisor, &rem);
|
|
|
|
|
|
|
|
|
|
if (remainder)
|
|
|
|
|
{
|
|
|
|
|
*remainder = rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
}
|
2018-09-05 16:57:52 +00:00
|
|
|
|
#endif
|
|
|
|
|
} // namespace utils
|