diff --git a/storm/big/Ops.cpp b/storm/big/Ops.cpp index 5b399ff..4a4fe20 100644 --- a/storm/big/Ops.cpp +++ b/storm/big/Ops.cpp @@ -68,6 +68,33 @@ void FromUnsigned(BigBuffer& buffer, uint32_t value) { buffer.SetCount(1); } +uint32_t HighBitPos(const BigBuffer& buffer) { + uint32_t index = buffer.Count(); + if (index == 0) { + return 0; + } + + while (buffer[--index] == 0) { + if (index == 0) { + return 0; + } + } + + uint32_t mask = 0x80000000; + uint32_t bitIndex = 32; + while (bitIndex > 0) { + bitIndex--; + + if (buffer[index] & mask) { + return (index * 32) + bitIndex; + } + + mask >>= 1; + } + + return 0; +} + uint64_t MakeLarge(uint32_t low, uint32_t high) { return low + (static_cast(high) << 32); } diff --git a/storm/big/Ops.hpp b/storm/big/Ops.hpp index 7eab1a9..bedf209 100644 --- a/storm/big/Ops.hpp +++ b/storm/big/Ops.hpp @@ -19,6 +19,8 @@ void FromBinary(BigBuffer& buffer, const void* value, uint32_t bytes); void FromUnsigned(BigBuffer& buffer, uint32_t value); +uint32_t HighBitPos(const BigBuffer& a); + uint64_t MakeLarge(uint32_t low, uint32_t high); void Mul(BigBuffer& a, const BigBuffer& b, uint64_t c); diff --git a/test/Big.cpp b/test/Big.cpp index fa55528..20112d7 100644 --- a/test/Big.cpp +++ b/test/Big.cpp @@ -200,6 +200,69 @@ TEST_CASE("ExtractLowPartSx", "[big]") { } } +TEST_CASE("HighBitPos", "[big]") { + SECTION("returns position of high bit for 0") { + BigData* num; + SBigNew(&num); + SBigFromUnsigned(num, 0); + + CHECK(HighBitPos(num->Primary()) == 0); + + SBigDel(num); + } + + SECTION("returns position of high bit for 0x1000") { + BigData* num; + SBigNew(&num); + SBigFromUnsigned(num, 0x1000); + + CHECK(HighBitPos(num->Primary()) == 12); + + SBigDel(num); + } + + SECTION("returns position of high bit for 0x1111") { + BigData* num; + SBigNew(&num); + SBigFromUnsigned(num, 0x1111); + + CHECK(HighBitPos(num->Primary()) == 12); + + SBigDel(num); + } + + SECTION("returns position of high bit for 0xFFFF") { + BigData* num; + SBigNew(&num); + SBigFromUnsigned(num, 0xFFFF); + + CHECK(HighBitPos(num->Primary()) == 15); + + SBigDel(num); + } + + SECTION("returns position of high bit for 0xFFFFFFFF") { + BigData* num; + SBigNew(&num); + SBigFromUnsigned(num, 0xFFFFFFFF); + + CHECK(HighBitPos(num->Primary()) == 31); + + SBigDel(num); + } + + SECTION("returns position of high bit for 0x123456789ABCDEF0") { + BigData* num; + SBigNew(&num); + uint64_t data = 0x123456789ABCDEF0; + SBigFromBinary(num, reinterpret_cast(&data), sizeof(data)); + + CHECK(HighBitPos(num->Primary()) == 60); + + SBigDel(num); + } +} + TEST_CASE("Mul", "[big]") { SECTION("multiplies 0 and 1") { BigData* a;