41 #ifndef __BASE_INTMATH_HH__
42 #define __BASE_INTMATH_HH__
46 #include <type_traits>
58 static constexpr std::enable_if_t<std::is_integral_v<T>,
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>
static constexpr int log2i(int value)
Calculate the log2 of a power of 2 integer.
static constexpr std::enable_if_t< sizeof(T)==sizeof(uint64_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 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(uint64_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 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 uint64_t mask(unsigned nbits)
Generate a 64-bit mask of 'nbits' 1s, right justified.
constexpr int ctz32(uint32_t value)
Count trailing zeros in a 32-bit value.
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
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)
void align(const scfx_rep &lhs, const scfx_rep &rhs, int &new_wp, int &len_mant, scfx_mant_ref &lhs_mant, scfx_mant_ref &rhs_mant)