From fe9df24e02baa9af4c35274a560aad284dadeec0 Mon Sep 17 00:00:00 2001 From: Samuel Li Date: Tue, 30 Apr 2024 17:07:09 -0600 Subject: [PATCH] Use __cplusplus version check, and minor improve on the bitmask. (#239) * use __cplusplus version checking instead of feature macros * use bit operations for count_true * add lib implementation test * clang-format * minor --------- Co-authored-by: Samuel Li Co-authored-by: Samuel Li --- include/Bitmask.h | 2 +- src/Bitmask.cpp | 27 +++++++++++++++++++++------ src/SPECK1D_INT_DEC.cpp | 5 ++--- src/SPECK1D_INT_ENC.cpp | 5 ++--- src/SPECK2D_INT.cpp | 5 ++--- src/SPECK3D_INT.cpp | 5 ++--- src/SPECK_INT.cpp | 11 ++++------- test_scripts/bitstream_unit_test.cpp | 6 +++--- 8 files changed, 37 insertions(+), 29 deletions(-) diff --git a/include/Bitmask.h b/include/Bitmask.h index b45fca92..961d7de8 100644 --- a/include/Bitmask.h +++ b/include/Bitmask.h @@ -63,7 +63,7 @@ class Bitmask { auto view_buffer() const -> const std::vector&; void use_bitstream(const void* p); -#if defined __cpp_lib_three_way_comparison && defined __cpp_impl_three_way_comparison +#if __cplusplus >= 201907L && defined __cpp_lib_three_way_comparison auto operator<=>(const Bitmask& rhs) const noexcept; auto operator==(const Bitmask& rhs) const noexcept -> bool; #endif diff --git a/src/Bitmask.cpp b/src/Bitmask.cpp index 380af242..2a8e5f7b 100644 --- a/src/Bitmask.cpp +++ b/src/Bitmask.cpp @@ -4,6 +4,10 @@ #include #include +#if __cplusplus >= 201907L +#include +#endif + sperr::Bitmask::Bitmask(size_t nbits) { if (nbits > 0) { @@ -48,11 +52,13 @@ auto sperr::Bitmask::has_true(size_t start, size_t len) const -> int64_t { auto long_idx = start / 64; auto processed_bits = int64_t{0}; - - // Collect the remaining bits from the start long. auto word = m_buf[long_idx]; auto answer = uint64_t{0}; - for (auto i = start - long_idx * 64; i < 64 && processed_bits < len; i++) { + + // Collect the remaining bits from the start long. + auto begin_idx = start - long_idx * 64; + auto nbits = std::min(size_t{64}, begin_idx + len); + for (auto i = begin_idx; i < nbits; i++) { answer |= word & (uint64_t{1} << i); if constexpr (Position) { if (answer != 0) @@ -70,9 +76,14 @@ auto sperr::Bitmask::has_true(size_t start, size_t len) const -> int64_t word = m_buf[++long_idx]; if (word) { if constexpr (Position) { +#if __cplusplus >= 201907L + int64_t i = std::countr_zero(word); + return processed_bits + i; +#else for (int64_t i = 0; i < 64; i++) if (word & (uint64_t{1} << i)) return processed_bits + i; +#endif } else return 1; @@ -82,7 +93,7 @@ auto sperr::Bitmask::has_true(size_t start, size_t len) const -> int64_t // Examine the remaining bits if (processed_bits < len) { - auto nbits = len - processed_bits; + nbits = len - processed_bits; assert(nbits < 64); word = m_buf[++long_idx]; answer = 0; @@ -112,11 +123,15 @@ auto sperr::Bitmask::count_true() const -> size_t // Note that unused bits in the last long are not guaranteed to be all 0's. for (size_t i = 0; i < m_buf.size() - 1; i++) { - const auto val = m_buf[i]; + auto val = m_buf[i]; +#if __cplusplus >= 201907L + counter += std::popcount(val); +#else if (val != 0) { for (size_t j = 0; j < 64; j++) counter += ((val >> j) & uint64_t{1}); } +#endif } const auto val = m_buf.back(); if (val != 0) { @@ -186,7 +201,7 @@ void sperr::Bitmask::use_bitstream(const void* p) std::copy(pu64, pu64 + m_buf.size(), m_buf.begin()); } -#if defined __cpp_lib_three_way_comparison && defined __cpp_impl_three_way_comparison +#if __cplusplus >= 201907L && defined __cpp_lib_three_way_comparison auto sperr::Bitmask::operator<=>(const Bitmask& rhs) const noexcept { auto cmp = m_num_bits <=> rhs.m_num_bits; diff --git a/src/SPECK1D_INT_DEC.cpp b/src/SPECK1D_INT_DEC.cpp index 208bb64a..b7053ea5 100644 --- a/src/SPECK1D_INT_DEC.cpp +++ b/src/SPECK1D_INT_DEC.cpp @@ -5,7 +5,7 @@ #include // std::memcpy() #include -#if defined __cpp_lib_bitops +#if __cplusplus >= 201907L #include #endif @@ -19,11 +19,10 @@ void sperr::SPECK1D_INT_DEC::m_sorting_pass() for (size_t i = 0; i < bits_x64; i += 64) { auto value = m_LIP_mask.rlong(i); -#if defined __cpp_lib_bitops +#if __cplusplus >= 201907L while (value) { size_t j = std::countr_zero(value); m_process_P(i + j, j, true); - value &= value - 1; } #else diff --git a/src/SPECK1D_INT_ENC.cpp b/src/SPECK1D_INT_ENC.cpp index d9f0f725..68ab0a51 100644 --- a/src/SPECK1D_INT_ENC.cpp +++ b/src/SPECK1D_INT_ENC.cpp @@ -5,7 +5,7 @@ #include // std::memcpy() #include -#if defined __cpp_lib_bitops +#if __cplusplus >= 201907L #include #endif @@ -19,11 +19,10 @@ void sperr::SPECK1D_INT_ENC::m_sorting_pass() for (size_t i = 0; i < bits_x64; i += 64) { auto value = m_LIP_mask.rlong(i); -#if defined __cpp_lib_bitops +#if __cplusplus >= 201907L while (value) { size_t j = std::countr_zero(value); m_process_P(i + j, SigType::Dunno, j, true); - value &= value - 1; } #else diff --git a/src/SPECK2D_INT.cpp b/src/SPECK2D_INT.cpp index 3f84d78c..7cd9fecf 100644 --- a/src/SPECK2D_INT.cpp +++ b/src/SPECK2D_INT.cpp @@ -3,7 +3,7 @@ #include #include -#if defined __cpp_lib_bitops +#if __cplusplus >= 201907L #include #endif @@ -17,11 +17,10 @@ void sperr::SPECK2D_INT::m_sorting_pass() for (size_t i = 0; i < bits_x64; i += 64) { auto value = m_LIP_mask.rlong(i); -#if defined __cpp_lib_bitops +#if __cplusplus >= 201907L while (value) { size_t j = std::countr_zero(value); m_process_P(i + j, j, true); - value &= value - 1; } #else diff --git a/src/SPECK3D_INT.cpp b/src/SPECK3D_INT.cpp index 8c1d71be..c119cdab 100644 --- a/src/SPECK3D_INT.cpp +++ b/src/SPECK3D_INT.cpp @@ -5,7 +5,7 @@ #include #include -#if defined __cpp_lib_bitops +#if __cplusplus >= 201907L #include #endif @@ -106,11 +106,10 @@ void sperr::SPECK3D_INT::m_sorting_pass() for (size_t i = 0; i < bits_x64; i += 64) { auto value = m_LIP_mask.rlong(i); -#if defined __cpp_lib_bitops +#if __cplusplus >= 201907L while (value) { auto j = std::countr_zero(value); m_process_P_lite(i + j); - value &= value - 1; } #else diff --git a/src/SPECK_INT.cpp b/src/SPECK_INT.cpp index 18b44cd4..07e78bb5 100644 --- a/src/SPECK_INT.cpp +++ b/src/SPECK_INT.cpp @@ -5,7 +5,7 @@ #include #include -#if defined __cpp_lib_bitops +#if __cplusplus >= 201907L #include #endif @@ -317,13 +317,12 @@ void sperr::SPECK_INT::m_refinement_pass_encode() for (size_t i = 0; i < bits_x64; i += 64) { // Evaluate 64 bits at a time. auto value = m_LSP_mask.rlong(i); -#if defined __cpp_lib_bitops +#if __cplusplus >= 201907L while (value) { auto j = std::countr_zero(value); const bool o1 = m_coeff_buf[i + j] >= m_threshold; m_coeff_buf[i + j] -= tmp1[o1]; m_bit_buffer.wbit(o1); - value &= value - 1; } #else @@ -375,7 +374,7 @@ void sperr::SPECK_INT::m_refinement_pass_decode() for (size_t i = 0; i < bits_x64; i += 64) { // <-- Point 2 auto value = m_LSP_mask.rlong(i); -#if defined __cpp_lib_bitops +#if __cplusplus >= 201907L while (value) { auto j = std::countr_zero(value); if (m_bit_buffer.rbit()) @@ -384,7 +383,6 @@ void sperr::SPECK_INT::m_refinement_pass_decode() m_coeff_buf[i + j] -= half_t; if (++read_pos == m_avail_bits) // <-- Point 3 goto INITIALIZE_NEWLY_FOUND_POINTS_LABEL; // <-- Point 4 - value &= value - 1; } #else @@ -417,14 +415,13 @@ void sperr::SPECK_INT::m_refinement_pass_decode() for (size_t i = 0; i < bits_x64; i += 64) { auto value = m_LSP_mask.rlong(i); -#if defined __cpp_lib_bitops +#if __cplusplus >= 201907L while (value) { auto j = std::countr_zero(value); if (m_bit_buffer.rbit()) ++(m_coeff_buf[i + j]); if (++read_pos == m_avail_bits) goto INITIALIZE_NEWLY_FOUND_POINTS_LABEL; - value &= value - 1; } #else diff --git a/test_scripts/bitstream_unit_test.cpp b/test_scripts/bitstream_unit_test.cpp index fa982bca..a9cfdc17 100644 --- a/test_scripts/bitstream_unit_test.cpp +++ b/test_scripts/bitstream_unit_test.cpp @@ -362,7 +362,7 @@ TEST(Bitmask, BufferTransfer) TEST(Bitmask, has_true) { - const size_t mask_size = 130; + const size_t mask_size = 210; // Loop over all positions for (size_t idx = 0; idx < mask_size; idx++) { @@ -390,7 +390,7 @@ TEST(Bitmask, has_true) TEST(Bitmask, has_true_position) { - const size_t mask_size = 130; + const size_t mask_size = 210; // Loop over all positions for (size_t idx = 0; idx < mask_size; idx++) { @@ -421,7 +421,7 @@ TEST(Bitmask, has_true_position) {} } -#if defined __cpp_lib_three_way_comparison && defined __cpp_impl_three_way_comparison +#if __cplusplus >= 201907L && defined __cpp_lib_three_way_comparison TEST(Bitmask, spaceship) { auto src = Mask(60);