41 #ifndef __BASE_INTMATH_HH__
42 #define __BASE_INTMATH_HH__
46 #include <type_traits>
58 static constexpr std::enable_if_t<std::is_integral<T>::value,
int>
67 constexpr
auto ts =
sizeof(T);
69 if (
ts >= 8 && (
ux & 0xffffffff00000000ULL)) { y += 32;
ux >>= 32; }
70 if (
ts >= 4 && (
ux & 0x00000000ffff0000ULL)) { y += 16;
ux >>= 16; }
71 if (
ts >= 2 && (
ux & 0x000000000000ff00ULL)) { y += 8;
ux >>= 8; }
72 if (
ux & 0x00000000000000f0ULL) { y += 4;
ux >>= 4; }
73 if (
ux & 0x000000000000000cULL) { y += 2;
ux >>= 2; }
74 if (
ux & 0x0000000000000002ULL) { y += 1; }
102 return n && !(
n & (
n - 1));
108 template <
class T,
class U>
112 return (
a +
b - 1) /
b;
118 template <
typename T>
119 static constexpr std::enable_if_t<
sizeof(T) <=
sizeof(uint32_t)>
120 mulUnsigned(std::make_unsigned_t<T> &
high, std::make_unsigned_t<T> &low,
121 std::make_unsigned_t<T> val_a, std::make_unsigned_t<T> val_b)
123 uint64_t product = (uint64_t)val_a * (uint64_t)val_b;
125 high = (product >> (
sizeof(low) * 8));
131 template <
typename T>
132 static constexpr std::enable_if_t<
sizeof(T) <=
sizeof(uint32_t)>
133 mulSigned(std::make_signed_t<T> &
high, std::make_signed_t<T> &low,
134 std::make_signed_t<T> val_a, std::make_signed_t<T> val_b)
136 uint64_t product = (int64_t)val_a * (int64_t)val_b;
138 high = (product >> (
sizeof(low) * 8));
154 template <
typename T>
155 static constexpr std::enable_if_t<
sizeof(T) ==
sizeof(uint64_t)>
156 mulUnsignedManual(std::make_unsigned_t<T> &
high, std::make_unsigned_t<T> &low,
157 std::make_unsigned_t<T> val_a, std::make_unsigned_t<T> val_b)
161 uint64_t A = (uint32_t)(val_a >> 32);
162 uint64_t
a = (uint32_t)val_a;
163 uint64_t B = (uint32_t)(val_b >> 32);
164 uint64_t
b = (uint32_t)val_b;
166 uint64_t c1 = 0,
c2 = 0;
167 uint64_t ab =
a *
b, Ab = A *
b, aB =
a * B, AB = A * B;
169 c1 = (uint32_t)(ab >> 32);
172 c2 = (c1 >> 1) + (Ab >> 1) + (aB >> 1);
173 c2 += ((c1 & 0x1) + (Ab & 0x1) + (aB & 0x1)) >> 1;
182 template <
typename T>
183 static constexpr std::enable_if_t<
sizeof(T) ==
sizeof(uint64_t)>
185 std::make_unsigned_t<T> val_a, std::make_unsigned_t<T> val_b)
187 #ifdef __SIZEOF_INT128__
188 __uint128_t
val = (__uint128_t)val_a * (__uint128_t)val_b;
192 mulUnsignedManual<T>(
high, low, val_a, val_b);
196 template <
typename T>
197 static constexpr std::enable_if_t<
sizeof(T) ==
sizeof(uint64_t)>
199 std::make_signed_t<T> val_a, std::make_signed_t<T> val_b)
201 uint64_t u_high = 0, u_low = 0;
202 mulUnsigned<T>(u_high, u_low, val_a, val_b);
216 template <
typename T>
217 static constexpr std::enable_if_t<
sizeof(T) ==
sizeof(uint64_t)>
219 std::make_signed_t<T> val_a, std::make_signed_t<T> val_b)
221 #ifdef __SIZEOF_INT128__
222 __int128_t
val = (__int128_t)val_a * (__int128_t)val_b;
226 mulSignedManual<T>(
high, low, val_a, val_b);
230 template <
typename T>
232 mulUnsigned(std::make_unsigned_t<T> val_a, std::make_unsigned_t<T> val_b)
234 std::make_unsigned_t<T> hi{}, low{};
235 mulUnsigned<T>(hi, low, val_a, val_b);
239 template <
typename T>
241 mulSigned(std::make_signed_t<T> val_a, std::make_signed_t<T> val_b)
243 std::make_signed_t<T> hi{}, low{};
244 mulSigned<T>(hi, low, val_a, val_b);
258 template <
class T,
class U>
277 template <
class T,
class U>
303 #endif // __BASE_INTMATH_HH__