Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions include/CppCore.Test/Math/Util.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,17 @@ namespace CppCore { namespace Test { namespace Math
CppCore::getbits32(0x00000011U, 0x000000FFU) == 0x00000011U &&
CppCore::getbits32(0x0000FF00U, 0x000000FFU) == 0x00000000U &&
CppCore::getbits32(0xFFFFFFFFU, 0xFFFFFFFFU) == 0xFFFFFFFFU;
return a && b;
if (!a || !b)
return false;
uint32_t r[2];
r[1] = 0x00000000U; r[0] = 0x00000000U; if (CppCore::getbits32(r, 0, 32) != 0x00000000U) return false;
r[1] = 0x00000001U; r[0] = 0x80000000U; if (CppCore::getbits32(r, 31, 2) != 0x00000003U) return false;
r[1] = 0x0000FF01U; r[0] = 0x80FF0000U; if (CppCore::getbits32(r, 31, 2) != 0x00000003U) return false;
r[1] = 0x80000000U; r[0] = 0x00000000U; if (CppCore::getbits32(r, 63, 1) != 0x00000001U) return false;
r[1] = 0xFFFFFFFFU; r[0] = 0xFFFFFFFFU; if (CppCore::getbits32(r, 16, 32) != 0xFFFFFFFFU) return false;
r[1] = 0x00000000U; r[0] = 0xFFFFFFFFU; if (CppCore::getbits32(r, 0, 32) != 0xFFFFFFFFU) return false;
r[1] = 0xFFFFFFFFU; r[0] = 0x00000000U; if (CppCore::getbits32(r, 32, 32) != 0xFFFFFFFFU) return false;
return true;
}

INLINE static bool getbits64()
Expand All @@ -41,7 +51,17 @@ namespace CppCore { namespace Test { namespace Math
CppCore::getbits64(0x0000000000000011ULL, 0x00000000000000FFULL) == 0x0000000000000011ULL &&
CppCore::getbits64(0x000000000000FF00ULL, 0x00000000000000FFULL) == 0x0000000000000000ULL &&
CppCore::getbits64(0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL) == 0xFFFFFFFFFFFFFFFFULL;
return a && b;
if (!a || !b)
return false;
uint64_t r[2];
r[1]=0x0000000000000000ULL; r[0]= 0x0000000000000000ULL; if (CppCore::getbits64(r, 0, 64) != 0x0000000000000000ULL) return false;
r[1]=0x0000000000000001ULL; r[0]= 0x8000000000000000ULL; if (CppCore::getbits64(r, 63, 2) != 0x0000000000000003ULL) return false;
r[1]=0x000000000000FF01ULL; r[0]= 0x80FF000000000000ULL; if (CppCore::getbits64(r, 63, 2) != 0x0000000000000003ULL) return false;
r[1]=0x8000000000000000ULL; r[0]= 0x0000000000000000ULL; if (CppCore::getbits64(r, 127, 1) != 0x0000000000000001ULL) return false;
r[1]=0x00000000FFFFFFFFULL; r[0]= 0xFFFFFFFF00000000ULL; if (CppCore::getbits64(r, 32, 64) != 0xFFFFFFFFFFFFFFFFULL) return false;
r[1]=0x0000000000000000ULL; r[0]= 0xFFFFFFFFFFFFFFFFULL; if (CppCore::getbits64(r, 0, 64) != 0xFFFFFFFFFFFFFFFFULL) return false;
r[1]=0xFFFFFFFFFFFFFFFFULL; r[0]= 0x0000000000000000ULL; if (CppCore::getbits64(r, 64, 64) != 0xFFFFFFFFFFFFFFFFULL) return false;
return true;
}

INLINE static bool setbit32()
Expand Down
42 changes: 42 additions & 0 deletions include/CppCore/Math/Util.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,27 @@ namespace CppCore
#endif
}

/// <summary>
/// Extracts up to 32 bits from an integer that's a multiple of 32 bit.
/// </summary>
template<typename UINT>
static INLINE uint32_t getbits32(const UINT& v, const uint32_t i, const uint32_t n)
{
static_assert(sizeof(UINT) % 4 == 0);
assert(i+n <= sizeof(UINT) * 8);
assert(n <= 32);
static constexpr size_t N32 = sizeof(UINT) / 4;
const uint32_t* p = (uint32_t*)&v;
const uint32_t idx = i >> 5;
const uint32_t off = i & 0x1F;
uint32_t r = p[idx];
if (off)
r = (idx+1 < N32) ? CppCore::shrd32(r, p[idx+1], off) : r >> off;
if (n < 32)
r &= (1U << n) - 1U;
return r;
}

/// <summary>
/// Returns in lowbits the n bits starting at index i from 64-bit integer v.
/// Undefined return for i >= 64 (use i AND 0x3F to map cyclic).
Expand Down Expand Up @@ -132,6 +153,27 @@ namespace CppCore
#endif
}

/// <summary>
/// Extracts up to 64 bits from an integer that's a multiple of 64 bit.
/// </summary>
template<typename UINT>
static INLINE uint64_t getbits64(const UINT& v, const uint32_t i, const uint32_t n)
{
static_assert(sizeof(UINT) % 8 == 0);
assert(i+n <= sizeof(UINT) * 8);
assert(n <= 64);
static constexpr size_t N64 = sizeof(UINT) / 8;
const uint64_t* p = (uint64_t*)&v;
const uint32_t idx = i >> 6;
const uint32_t off = i & 0x3F;
uint64_t r = p[idx];
if (off)
r = (idx+1 < N64) ? CppCore::shrd64(r, p[idx+1], off) : r >> off;
if (n < 64)
r &= (1ULL << n) - 1ULL;
return r;
}

/// <summary>
/// Sets bits that are 1 in mask to 0 in 32-bit integer v and returns it.
/// Uses BMI1 if enabled.
Expand Down