41#ifndef __BASE_INTMATH_HH__
42#define __BASE_INTMATH_HH__
58static constexpr std::enable_if_t<std::is_integral_v<T>,
int>
64 uint64_t
ux = (
typename std::make_unsigned<T>::type)
x;
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));
108template <
class T,
class U>
112 return (
a +
b - 1) /
b;
119static constexpr std::enable_if_t<
sizeof(T) <=
sizeof(uint32_t)>
120mulUnsigned(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));
132static constexpr std::enable_if_t<
sizeof(T) <=
sizeof(uint32_t)>
133mulSigned(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));
155static constexpr std::enable_if_t<
sizeof(T) ==
sizeof(uint64_t)>
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;
183static constexpr std::enable_if_t<
sizeof(T) ==
sizeof(uint64_t)>
184mulUnsigned(std::make_unsigned_t<T> &high, std::make_unsigned_t<T> &low,
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;
197static 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;
217static constexpr std::enable_if_t<
sizeof(T) ==
sizeof(uint64_t)>
218mulSigned(std::make_signed_t<T> &high, std::make_signed_t<T> &low,
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;
232mulUnsigned(std::make_unsigned_t<T> val_a, std::make_unsigned_t<T> val_b)
234 std::make_unsigned_t<T> hi{}, low{};
241mulSigned(std::make_signed_t<T> val_a, std::make_signed_t<T> val_b)
243 std::make_signed_t<T> hi{}, low{};
258template <
class T,
class U>
263 T
mask = (T)align - 1;
277template <
class T,
class U>
282 T
mask = (T)align - 1;
static constexpr int log2i(int value)
Calculate the log2 of a power of 2 integer.
static constexpr std::enable_if_t< std::is_integral_v< T >, int > floorLog2(T x)
static constexpr int ceilLog2(const T &n)
static constexpr std::enable_if_t< sizeof(T)<=sizeof(uint32_t)> mulUnsigned(std::make_unsigned_t< T > &high, std::make_unsigned_t< T > &low, std::make_unsigned_t< T > val_a, std::make_unsigned_t< T > val_b)
static constexpr bool isPowerOf2(const T &n)
static constexpr T divCeil(const T &a, const U &b)
static constexpr std::enable_if_t< sizeof(T)<=sizeof(uint32_t)> mulSigned(std::make_signed_t< T > &high, std::make_signed_t< T > &low, std::make_signed_t< T > val_a, std::make_signed_t< T > val_b)
static constexpr T roundDown(const T &val, const U &align)
This function is used to align addresses in memory.
static constexpr T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
constexpr int ctz32(uint32_t value)
Count trailing zeros in a 32-bit value.
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
static constexpr std::enable_if_t< sizeof(T)==sizeof(uint64_t)> mulSignedManual(std::make_signed_t< T > &high, std::make_signed_t< T > &low, std::make_signed_t< T > val_a, std::make_signed_t< T > val_b)
static constexpr std::enable_if_t< sizeof(T)==sizeof(uint64_t)> mulUnsignedManual(std::make_unsigned_t< T > &high, std::make_unsigned_t< T > &low, std::make_unsigned_t< T > val_a, std::make_unsigned_t< T > val_b)
Multiply two values with place value p.