From f6f706d7081b8006cc6e8e815b95018234720a67 Mon Sep 17 00:00:00 2001 From: Oleksandr Kulkov Date: Fri, 15 Nov 2024 00:01:35 +0100 Subject: [PATCH] Use bmi2 target for kth_set_bit, improve compress_coords and radix sort --- cp-algo/util/bit.hpp | 2 +- cp-algo/util/compress_coords.hpp | 11 +++++++++-- cp-algo/util/sort.hpp | 8 ++++---- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/cp-algo/util/bit.hpp b/cp-algo/util/bit.hpp index 99ed132..0ad96e6 100644 --- a/cp-algo/util/bit.hpp +++ b/cp-algo/util/bit.hpp @@ -11,7 +11,7 @@ namespace cp_algo { size_t order_of_bit(auto x, size_t k) { return k ? std::popcount(x << (bit_width - k)) : 0; } - // Requires GCC target("popcnt,bmi2") + [[gnu::target("bmi2")]] size_t kth_set_bit(uint64_t x, size_t k) { return std::countr_zero(_pdep_u64(1ULL << k, x)); } diff --git a/cp-algo/util/compress_coords.hpp b/cp-algo/util/compress_coords.hpp index a9e36c2..39558d2 100644 --- a/cp-algo/util/compress_coords.hpp +++ b/cp-algo/util/compress_coords.hpp @@ -5,10 +5,17 @@ namespace cp_algo { // coords is a range of reference_wrapper auto compress_coords(auto &coords) { - std::vector original; + using T = std::decay_t + >>; + std::vector original; + if(empty(coords)) { + return original; + } original.reserve(size(coords)); radix_sort(coords); - int idx = -1, prev = -1; + size_t idx = -1; + T prev = ~coords.front(); for(auto &x: coords) { if(x != prev) { idx++; diff --git a/cp-algo/util/sort.hpp b/cp-algo/util/sort.hpp index 9466da9..af5466b 100644 --- a/cp-algo/util/sort.hpp +++ b/cp-algo/util/sort.hpp @@ -24,12 +24,12 @@ namespace cp_algo { if(empty(a)) { return; } - auto mx = std::ranges::max(a); - with_bit_floor(size(a), [&]() { + auto [mn, mx] = std::ranges::minmax(a); + with_bit_floor<1>(size(a), [&]() { constexpr int base = std::min(floor, 1 << 16); - for(int64_t i = 1; i <= mx; i *= base) { + for(int64_t i = 1; i <= mx - mn; i *= base) { count_sort(a, [&](auto x) { - return x / i % base; + return (x - mn) / i % base; }); } });