diff --git a/include/hurchalla/util/BitpackedUintVector.h b/include/hurchalla/util/BitpackedUintVector.h index 87a3515..dbe045c 100644 --- a/include/hurchalla/util/BitpackedUintVector.h +++ b/include/hurchalla/util/BitpackedUintVector.h @@ -21,8 +21,8 @@ struct BitpackedUintVector static_assert(!std::numeric_limits::is_signed, ""); static_assert(element_bitlen <= std::numeric_limits::digits, ""); static_assert(0 < element_bitlen && element_bitlen <= 32, ""); - using size_type = - typename ImplBitpackedUintVector::size_type; + using size_type = typename + detail::ImplBitpackedUintVector::size_type; BitpackedUintVector(size_type count) : impl_buv(count) {} @@ -58,7 +58,8 @@ struct BitpackedUintVector // returns the maximum value that fits within element_bitlen bits. HURCHALLA_FORCE_INLINE static constexpr U max_allowed_value() { - return ImplBitpackedUintVector::max_allowed_value(); + return detail:: + ImplBitpackedUintVector::max_allowed_value(); } HURCHALLA_FORCE_INLINE std::size_t dataSizeBytes() const @@ -78,11 +79,11 @@ struct BitpackedUintVector // data (for the BitpackedUintVector constructor). HURCHALLA_FORCE_INLINE static constexpr uint64_t getFormatID() { - return ImplBitpackedUintVector::getFormatID(); + return detail::ImplBitpackedUintVector::getFormatID(); } private: - ImplBitpackedUintVector impl_buv; + detail::ImplBitpackedUintVector impl_buv; }; diff --git a/include/hurchalla/util/Unroll.h b/include/hurchalla/util/Unroll.h index e7f0f3d..0a47e3c 100644 --- a/include/hurchalla/util/Unroll.h +++ b/include/hurchalla/util/Unroll.h @@ -7,6 +7,7 @@ #include "hurchalla/util/compiler_macros.h" #include +#include namespace hurchalla { diff --git a/include/hurchalla/util/detail/ImplBitpackedUintVector.h b/include/hurchalla/util/detail/ImplBitpackedUintVector.h index a91fca8..373f964 100644 --- a/include/hurchalla/util/detail/ImplBitpackedUintVector.h +++ b/include/hurchalla/util/detail/ImplBitpackedUintVector.h @@ -13,7 +13,12 @@ #include #include -namespace hurchalla { +#if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable : 4127) +#endif + +namespace hurchalla { namespace detail { template @@ -24,7 +29,11 @@ struct ImplBitpackedUintVector static_assert(element_bitlen > 0, ""); static_assert(element_bitlen <= std::numeric_limits::digits, ""); - using size_type = std::uint64_t; + // if element_bitlen < 8, in theory we can hold an element count that is + // larger than max size_t. We presume(!) uint64_t will always be enough. + using size_type = typename std::conditional< + (element_bitlen < 8 && sizeof(std::uint64_t) > sizeof(std::size_t)), + std::uint64_t, std::size_t>::type; private: const size_type packed_count; const std::size_t vec8_bytes; @@ -47,7 +56,9 @@ struct ImplBitpackedUintVector vec8_bytes(data_bytes), vec8(std::move(data)) { - HPBC_PRECONDITION2(data_bytes >= getBytesFromCount(element_count)); + std::size_t bytes_needed = getBytesFromCount(element_count); + if (data_bytes != bytes_needed) + throw std::length_error("data_bytes doesn't match expected bytes needed for element_count"); } // returns the number of packed elements in this vector @@ -92,7 +103,7 @@ struct ImplBitpackedUintVector // each of size element_bitlen. static std::size_t getBytesFromCount(size_type count) { - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; bool overflowed; attemptGetLocationFromIndex(count, starting_byte, bit_offset, overflowed); if (overflowed) @@ -101,15 +112,16 @@ struct ImplBitpackedUintVector // Since attemptGetLocationFromIndex() returned without overflow, we // know that any value <= 'count' can be converted into 'starting_byte' // and 'bit_offset' correctly (i.e. without overflow). This lets us - // establish the class invariant that any index < count will be - // converted without overflow by attemptGetLocationFromIndex(). + // establish the class invariant that any index that satisfies + // (index < count) will be converted without overflow by + // attemptGetLocationFromIndex(). - constexpr size_type MAX_ST = std::numeric_limits::max(); + constexpr std::size_t MAXSIZET= std::numeric_limits::max(); - size_type bytes_needed = starting_byte; + std::size_t bytes_needed = starting_byte; if (bit_offset != 0) { HPBC_ASSERT2(bit_offset < 8); - if (bytes_needed == MAX_ST) + if (bytes_needed == MAXSIZET) throw std::length_error("BitpackedUintVector size too large, would overflow"); else ++bytes_needed; @@ -117,19 +129,12 @@ struct ImplBitpackedUintVector // We want to allocate one byte more than we strictly need, so that // setAt() can safely write one byte beyond where it strictly should. - if (bytes_needed == MAX_ST) + if (bytes_needed == MAXSIZET) throw std::length_error("BitpackedUintVector size too large, would overflow"); else ++bytes_needed; - // According to https://en.cppreference.com/w/cpp/types/size_t, - // "std::size_t can store the maximum size of a theoretically possible - // object of any type (including array)." - // Therefore bytes_needed must be able to fit within size_t. - if (bytes_needed >= std::numeric_limits::max()) - throw std::length_error("BitpackedUintVector size too large for std::size_t"); - - return static_cast(bytes_needed); + return bytes_needed; } @@ -137,8 +142,8 @@ struct ImplBitpackedUintVector // then it guarantees any value <= 'index' can be converted into // 'starting_byte' and 'bit_offset' correctly (i.e. without overflow). HURCHALLA_FORCE_INLINE static - void attemptGetLocationFromIndex(size_type index, size_type& starting_byte, - size_type& bit_offset, bool& overflowed) + void attemptGetLocationFromIndex(size_type index, + std::size_t& starting_byte, std::size_t& bit_offset, bool& overflowed) { constexpr size_type MAX_ST = std::numeric_limits::max(); static_assert(element_bitlen <= MAX_ST, ""); @@ -164,18 +169,26 @@ struct ImplBitpackedUintVector overflowed = true; size_type part1_bytes = (index/8) * ELEM_BITLEN; - // static assert that (index%8) *ELEM_BITLEN will not overflow. + // static assert that (index%8)*ELEM_BITLEN will not overflow. static_assert(ELEM_BITLEN <= MAX_ST / (8-1), ""); size_type part2_bytes = (index%8) * ELEM_BITLEN / 8; // if (part1_bytes + part2_bytes > MAX_ST) if (part1_bytes > MAX_ST - part2_bytes) overflowed = true; - starting_byte = part1_bytes + part2_bytes; + size_type sum = part1_bytes + part2_bytes; + + // According to https://en.cppreference.com/w/cpp/types/size_t, + // "std::size_t can store the maximum size of a theoretically possible + // object of any type (including array)." + // Therefore starting_byte must be able to fit within size_t. + if (sum > std::numeric_limits::max()) + overflowed = true; + starting_byte = static_cast(sum); using P = safely_promote_unsigned::type; // Below: (index*ELEM_BITLEN) might overflow, but since we use the // product mod 8, that's ok so long as we use unsigned arithmetic. - bit_offset = static_cast( + bit_offset = static_cast( (static_cast

(index) * ELEM_BITLEN) % 8); #endif HPBC_POSTCONDITION2(bit_offset < 8); @@ -188,7 +201,7 @@ struct ImplBitpackedUintVector template HURCHALLA_FORCE_INLINE typename std::enable_if<(BITS % 8 == 0), void>::type getLocationFromIndex(size_type index, - size_type& starting_byte, size_type& bit_offset) const + std::size_t& starting_byte, std::size_t& bit_offset) const { HPBC_PRECONDITION2(index < size()); @@ -197,11 +210,11 @@ struct ImplBitpackedUintVector // The constructor established a class invariant that any // index < size() will convert correctly by attemptGetLocationFromIndex(). // Thus we don't need to check for overflow of index * element_bytes - starting_byte = index * element_bytes; + starting_byte = static_cast(index * element_bytes); bit_offset = 0; if (HPBC_ASSERT2_MACRO_IS_ACTIVE) { - size_type start, offset; + std::size_t start, offset; bool overflowed; attemptGetLocationFromIndex(index, start, offset, overflowed); HPBC_ASSERT2(overflowed == false); @@ -219,14 +232,16 @@ struct ImplBitpackedUintVector { HPBC_PRECONDITION2(value <= max_allowed_value()); HPBC_PRECONDITION2(index < size()); - vec8[index] = static_cast(value); + std::size_t index_st = static_cast(index); + vec8[index_st] = static_cast(value); } template typename std::enable_if<(BITS == 8), U>::type getAt(size_type index) const { HPBC_PRECONDITION2(index < size()); - U value = vec8[index]; + std::size_t index_st = static_cast(index); + U value = vec8[index_st]; HPBC_POSTCONDITION2(value <= max_allowed_value()); return value; } @@ -239,7 +254,7 @@ struct ImplBitpackedUintVector HPBC_PRECONDITION2(value <= max_allowed_value()); HPBC_PRECONDITION2(index < size()); - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; getLocationFromIndex(index, starting_byte, bit_offset); static_assert(std::numeric_limits::digits >= 16, ""); @@ -252,7 +267,7 @@ struct ImplBitpackedUintVector { HPBC_PRECONDITION2(index < size()); - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; getLocationFromIndex(index, starting_byte, bit_offset); static_assert(std::numeric_limits::digits >= 16, ""); @@ -270,7 +285,7 @@ struct ImplBitpackedUintVector HPBC_PRECONDITION2(value <= max_allowed_value()); HPBC_PRECONDITION2(index < size()); - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; getLocationFromIndex(index, starting_byte, bit_offset); static_assert(std::numeric_limits::digits >= 24, ""); @@ -284,7 +299,7 @@ struct ImplBitpackedUintVector { HPBC_PRECONDITION2(index < size()); - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; getLocationFromIndex(index, starting_byte, bit_offset); static_assert(std::numeric_limits::digits >= 24, ""); @@ -303,7 +318,7 @@ struct ImplBitpackedUintVector HPBC_PRECONDITION2(value <= max_allowed_value()); HPBC_PRECONDITION2(index < size()); - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; getLocationFromIndex(index, starting_byte, bit_offset); static_assert(std::numeric_limits::digits >= 32, ""); @@ -318,7 +333,7 @@ struct ImplBitpackedUintVector { HPBC_PRECONDITION2(index < size()); - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; getLocationFromIndex(index, starting_byte, bit_offset); static_assert(std::numeric_limits::digits >= 32, ""); @@ -338,23 +353,23 @@ struct ImplBitpackedUintVector HURCHALLA_FORCE_INLINE typename std::enable_if<(BITS == 1)||(BITS == 2)||(BITS == 4), void>::type getLocationFromIndex(size_type index, - size_type& starting_byte, size_type& bit_offset) const + std::size_t& starting_byte, std::size_t& bit_offset) const { HPBC_PRECONDITION2(index < size()); static_assert(8 % element_bitlen == 0, ""); - constexpr decltype(element_bitlen) elements_per_byte= 8/element_bitlen; + constexpr decltype(element_bitlen) elements_per_byte = 8/element_bitlen; static_assert(elements_per_byte != 0, ""); - starting_byte = index / elements_per_byte; + starting_byte = static_cast(index / elements_per_byte); using P = safely_promote_unsigned::type; // Note: (index*element_bitlen) might overflow, but that's ok so long // as we use unsigned arithmetic, since we use the product mod 8. - bit_offset = static_cast( + bit_offset = static_cast( (static_cast

(index) * element_bitlen) % 8); if (HPBC_ASSERT2_MACRO_IS_ACTIVE) { - size_type start, offset; + std::size_t start, offset; bool overflowed; attemptGetLocationFromIndex(index, start, offset, overflowed); HPBC_ASSERT2(overflowed == false); @@ -385,7 +400,7 @@ struct ImplBitpackedUintVector HPBC_PRECONDITION2(value <= max_allowed_value()); HPBC_PRECONDITION2(index < size()); - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; getLocationFromIndex(index, starting_byte, bit_offset); // from getLocationFromIndex() we know HPBC_ASSERT2(element_bitlen + bit_offset <= 8); @@ -408,7 +423,7 @@ struct ImplBitpackedUintVector { HPBC_PRECONDITION2(index < size()); - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; getLocationFromIndex(index, starting_byte, bit_offset); // from getLocationFromIndex() we know HPBC_ASSERT2(element_bitlen + bit_offset <= 8); @@ -433,7 +448,7 @@ struct ImplBitpackedUintVector typename std::enable_if<(BITS == 3) || (BITS == 5) || (BITS == 6) || (BITS == 7), void>::type getLocationFromIndex(size_type index, - size_type& starting_byte, size_type& bit_offset) const + std::size_t& starting_byte, std::size_t& bit_offset) const { HPBC_PRECONDITION2(index < size()); // The constructor established a class invariant that any @@ -455,7 +470,7 @@ struct ImplBitpackedUintVector HPBC_PRECONDITION2(value <= max_allowed_value()); HPBC_PRECONDITION2(index < size()); - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; getLocationFromIndex(index, starting_byte, bit_offset); HPBC_ASSERT2(bit_offset < 8); @@ -483,7 +498,7 @@ struct ImplBitpackedUintVector { HPBC_PRECONDITION2(index < size()); - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; getLocationFromIndex(index, starting_byte, bit_offset); HPBC_ASSERT2(bit_offset < 8); @@ -508,7 +523,7 @@ struct ImplBitpackedUintVector HURCHALLA_FORCE_INLINE typename std::enable_if<(BITS == 9)||(BITS == 10)||(BITS == 12), void>::type getLocationFromIndex(size_type index, - size_type& starting_byte, size_type& bit_offset) const + std::size_t& starting_byte, std::size_t& bit_offset) const { HPBC_PRECONDITION2(index < size()); @@ -525,7 +540,7 @@ struct ImplBitpackedUintVector constexpr EBT spills_per_byte = 8 / spill; static_assert(spills_per_byte == 2 || spills_per_byte == 4 || spills_per_byte == 8, ""); - starting_byte = index + index / spills_per_byte; + starting_byte = static_cast(index + index/spills_per_byte); constexpr auto ST_MAX = std::numeric_limits::max(); // The constructor established a class invariant that any // index < size() can be converted correctly into starting_byte and @@ -537,11 +552,11 @@ struct ImplBitpackedUintVector using P = safely_promote_unsigned::type; // Below: (index*element_bitlen) might overflow, but since we use the // product mod 8, that's ok so long as we use unsigned arithmetic. - bit_offset = static_cast( + bit_offset = static_cast( (static_cast

(index) * element_bitlen) % 8); if (HPBC_ASSERT2_MACRO_IS_ACTIVE) { - size_type start, offset; + std::size_t start, offset; bool overflowed; attemptGetLocationFromIndex(index, start, offset, overflowed); HPBC_ASSERT2(overflowed == false); @@ -575,7 +590,7 @@ struct ImplBitpackedUintVector HPBC_PRECONDITION2(value <= max_allowed_value()); HPBC_PRECONDITION2(index < size()); - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; getLocationFromIndex(index, starting_byte, bit_offset); // from getLocationFromIndex() we know @@ -601,7 +616,7 @@ struct ImplBitpackedUintVector { HPBC_PRECONDITION2(index < size()); - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; getLocationFromIndex(index, starting_byte, bit_offset); // from getLocationFromIndex() we know @@ -629,7 +644,7 @@ struct ImplBitpackedUintVector typename std::enable_if<(BITS == 11) || (BITS == 13) || (BITS == 14) || (BITS == 15), void>::type getLocationFromIndex(size_type index, - size_type& starting_byte, size_type& bit_offset) const + std::size_t& starting_byte, std::size_t& bit_offset) const { HPBC_PRECONDITION2(index < size()); // The constructor established a class invariant that any @@ -651,7 +666,7 @@ struct ImplBitpackedUintVector HPBC_PRECONDITION2(value <= max_allowed_value()); HPBC_PRECONDITION2(index < size()); - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; getLocationFromIndex(index, starting_byte, bit_offset); HPBC_ASSERT2(bit_offset < 8); static_assert(element_bitlen < 16, ""); @@ -678,7 +693,7 @@ struct ImplBitpackedUintVector { HPBC_PRECONDITION2(index < size()); - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; getLocationFromIndex(index, starting_byte, bit_offset); HPBC_ASSERT2(bit_offset < 8); static_assert(element_bitlen < 16, ""); @@ -707,7 +722,7 @@ struct ImplBitpackedUintVector typename std::enable_if<((16 < BITS && BITS < 24) || (24 < BITS && BITS < 32)), void>::type getLocationFromIndex(size_type index, - size_type& starting_byte, size_type& bit_offset) const + std::size_t& starting_byte, std::size_t& bit_offset) const { HPBC_PRECONDITION2(index < size()); // The constructor established a class invariant that any @@ -728,7 +743,7 @@ struct ImplBitpackedUintVector HPBC_PRECONDITION2(value <= max_allowed_value()); HPBC_PRECONDITION2(index < size()); - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; getLocationFromIndex(index, starting_byte, bit_offset); HPBC_ASSERT2(bit_offset < 8); static_assert(element_bitlen < 24, ""); @@ -755,7 +770,7 @@ struct ImplBitpackedUintVector { HPBC_PRECONDITION2(index < size()); - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; getLocationFromIndex(index, starting_byte, bit_offset); HPBC_ASSERT2(bit_offset < 8); static_assert(element_bitlen < 24, ""); @@ -782,7 +797,7 @@ struct ImplBitpackedUintVector HPBC_PRECONDITION2(value <= max_allowed_value()); HPBC_PRECONDITION2(index < size()); - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; getLocationFromIndex(index, starting_byte, bit_offset); HPBC_ASSERT2(bit_offset < 8); static_assert(element_bitlen < 32, ""); @@ -812,7 +827,7 @@ struct ImplBitpackedUintVector { HPBC_PRECONDITION2(index < size()); - size_type starting_byte, bit_offset; + std::size_t starting_byte, bit_offset; getLocationFromIndex(index, starting_byte, bit_offset); HPBC_ASSERT2(bit_offset < 8); static_assert(element_bitlen < 32, ""); @@ -1069,6 +1084,11 @@ struct ImplBitpackedUintVector #endif -} // end namespace +}} // end namespace + + +#if defined(_MSC_VER) +# pragma warning(pop) +#endif #endif diff --git a/include/hurchalla/util/detail/impl_count_leading_zeros.h b/include/hurchalla/util/detail/impl_count_leading_zeros.h index 669e2d0..3bb5a0f 100644 --- a/include/hurchalla/util/detail/impl_count_leading_zeros.h +++ b/include/hurchalla/util/detail/impl_count_leading_zeros.h @@ -111,14 +111,13 @@ struct impl_count_leading_zeros { HPBC_PRECONDITION2(a != 0); using U = unsigned int; U x = static_cast(a); + constexpr int digitsT = ut_numeric_limits::digits; #ifndef _MSC_VER constexpr int digitsU = ut_numeric_limits::digits; - constexpr int digitsT = ut_numeric_limits::digits; return __builtin_clz(x) - (digitsU - digitsT); #else unsigned long index; _BitScanReverse(&index, x); - constexpr int digitsT = ut_numeric_limits::digits; return static_cast(digitsT) - 1 - static_cast(index); #endif } @@ -137,14 +136,13 @@ struct impl_count_leading_zeros { HPBC_PRECONDITION2(a != 0); using U = unsigned long; U x = static_cast(a); + constexpr int digitsT = ut_numeric_limits::digits; #ifndef _MSC_VER constexpr int digitsU = ut_numeric_limits::digits; - constexpr int digitsT = ut_numeric_limits::digits; return __builtin_clzl(x) - (digitsU - digitsT); #else unsigned long index; _BitScanReverse(&index, x); - constexpr int digitsT = ut_numeric_limits::digits; return static_cast(digitsT) - 1 - static_cast(index); #endif } @@ -164,16 +162,15 @@ struct impl_count_leading_zeros { HPBC_PRECONDITION2(a != 0); using U = unsigned long long; U x = static_cast(a); + constexpr int digitsT = ut_numeric_limits::digits; #ifndef _MSC_VER constexpr int digitsU = ut_numeric_limits::digits; - constexpr int digitsT = ut_numeric_limits::digits; return __builtin_clzll(x) - (digitsU - digitsT); #else # if HURCHALLA_TARGET_BIT_WIDTH >= 64 static_assert(sizeof(U) == sizeof(unsigned __int64), ""); unsigned long index; _BitScanReverse64(&index, x); - constexpr int digitsT = ut_numeric_limits::digits; return static_cast(digitsT) - 1 - static_cast(index); # else static_assert(ut_numeric_limits::digits == 64, ""); @@ -184,7 +181,6 @@ struct impl_count_leading_zeros { if (hi != 0) { unsigned long index; _BitScanReverse(&index, hi); - constexpr int digitsT = ut_numeric_limits::digits; return static_cast(digitsT) - 1 - (static_cast(index) + 32); } else { // given that hi == 0, the precondition of a != 0 means that lo != 0 @@ -257,6 +253,7 @@ struct impl_count_leading_zeros { if (word0 != 0) { _BitScanReverse(&index, word0); return static_cast(digitsT) - 1 - (static_cast(index) + 96); + } else if (word1 != 0) { _BitScanReverse(&index, word1); return static_cast(digitsT) - 1 - (static_cast(index) + 64); diff --git a/include/hurchalla/util/detail/impl_count_trailing_zeros.h b/include/hurchalla/util/detail/impl_count_trailing_zeros.h index c14ea4e..2cc552e 100644 --- a/include/hurchalla/util/detail/impl_count_trailing_zeros.h +++ b/include/hurchalla/util/detail/impl_count_trailing_zeros.h @@ -249,6 +249,7 @@ struct impl_count_trailing_zeros { if (word3 != 0) { _BitScanForward(&index, word3); return static_cast(index); + } else if (word2 != 0) { _BitScanForward(&index, word2); return static_cast(index + 32); diff --git a/test/test_BitpackedUintVector.cpp b/test/test_BitpackedUintVector.cpp index c540a2a..a7bab2e 100644 --- a/test/test_BitpackedUintVector.cpp +++ b/test/test_BitpackedUintVector.cpp @@ -34,12 +34,12 @@ void check_buv(std::vector& vec) (void)id; for (size_type i = 0; i < vec.size(); ++i) { - U val = static_cast(mask & vec[i]); + U val = static_cast(mask & vec[static_cast(i)]); buv.setAt(i, val); EXPECT_TRUE(val == buv.getAt(i)); } for (size_type i = 0; i < vec.size(); ++i) { - U val = static_cast(mask & vec[i]); + U val = static_cast(mask & vec[static_cast(i)]); EXPECT_TRUE(val == buv.getAt(i)); } @@ -61,7 +61,7 @@ void check_buv(std::vector& vec) EXPECT_TRUE(buv2.size() == vec.size()); for (size_type i = 0; i < buv2.size(); ++i) { - U val = static_cast(mask & vec[i]); + U val = static_cast(mask & vec[static_cast(i)]); EXPECT_TRUE(buv2.getAt(i) == val); EXPECT_TRUE(buv2.getAt(i) == buv.getAt(i)); } diff --git a/test/uint128.h b/test/uint128.h index 504ca47..ad416b7 100644 --- a/test/uint128.h +++ b/test/uint128.h @@ -22,6 +22,11 @@ struct uint128 { static_assert(hurchalla::ut_numeric_limits::digits == 64, ""); return lo; } + explicit operator unsigned long() const + { + static_assert(hurchalla::ut_numeric_limits::digits <= 64, ""); + return static_cast(lo); + } uint128& operator=(uint128 u) { hi = u.hi; @@ -34,7 +39,8 @@ struct uint128 { } #ifdef __GNUC__ #pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-overflow" +#pragma GCC diagnostic ignored "-Wstrict-overflow" +#endif uint128 operator<<(int shift) const { uint128 tmp = *this; @@ -67,6 +73,7 @@ struct uint128 { } return tmp; } +#ifdef __GNUC__ #pragma GCC diagnostic pop #endif uint128 operator+(uint128 x) const