From c861c38ab1494e3595d3ae6f2358f57ca665b5f1 Mon Sep 17 00:00:00 2001 From: KRM7 <70973547+KRM7@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:13:54 +0200 Subject: [PATCH] use small_vector in more places --- .github/workflows/windows.yml | 5 +- CMakeLists.txt | 2 +- src/utility/dynamic_bitset.hpp | 2 +- src/utility/rng.hpp | 4 +- src/utility/small_vector.hpp | 12 +++-- src/utility/utility.hpp | 31 ++++------- test/unit/algorithm.cpp | 41 -------------- test/unit/small_vector.cpp | 1 - test/unit/utility.cpp | 97 ++++++++++++++++++++++++++++++++++ 9 files changed, 121 insertions(+), 74 deletions(-) create mode 100644 test/unit/utility.cpp diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 6f41a7e6..88035bdb 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -9,13 +9,16 @@ jobs: fail-fast: false matrix: build-type: [ Release, RelWithDebInfo ] - platform: [ x64 ] + platform: [ x64, Win32 ] generator: [ "Visual Studio 17 2022" ] compiler: [ { name: msvc, toolset: v143 }, { name: clang, toolset: ClangCL } ] build-shared: [ "ON", "OFF" ] + exclude: + - platform: Win32 + build-type: Release defaults: run: diff --git a/CMakeLists.txt b/CMakeLists.txt index ababc919..23f095fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,7 +101,7 @@ else() # GNU style compiler interface # gcc specific options if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") # -Warray-bounds, -Wstringop-overflow, -Wstringop-overread are regular false positives since g++-12 - set(GAPP_WARN_FLAGS "${GAPP_WARN_FLAGS} -Wlogical-op -Wno-array-bounds -Wno-stringop-overflow -Wno-stringop-overread -Wno-free-nonheap-object") + set(GAPP_WARN_FLAGS "${GAPP_WARN_FLAGS} -Wlogical-op -Wno-array-bounds -Wno-stringop-overflow -Wno-stringop-overread") endif() # clang specific options if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") diff --git a/src/utility/dynamic_bitset.hpp b/src/utility/dynamic_bitset.hpp index 4fbb2c29..a00c74db 100644 --- a/src/utility/dynamic_bitset.hpp +++ b/src/utility/dynamic_bitset.hpp @@ -205,7 +205,7 @@ namespace gapp::detail } private: - small_vector blocks_; + small_vector blocks_; size_type size_ = 0; constexpr size_type find_first_one() const noexcept diff --git a/src/utility/rng.hpp b/src/utility/rng.hpp index 7fa8a378..7ae23d42 100644 --- a/src/utility/rng.hpp +++ b/src/utility/rng.hpp @@ -475,12 +475,12 @@ namespace gapp::rng template small_vector sampleUnique(IntType lbound, IntType ubound, size_t count) { - const size_t range_len = detail::range_length(lbound, ubound); + const std::uint64_t range_len = detail::range_length(lbound, ubound); GAPP_ASSERT(ubound >= lbound); GAPP_ASSERT(range_len >= count); - const bool select_many = (count > 0.6 * range_len); + const bool select_many = (count >= std::uint64_t(0.6 * range_len)); const bool huge_range = (range_len >= 65536); if (huge_range) [[unlikely]] return rng::sampleUniqueSet(lbound, ubound, count); diff --git a/src/utility/small_vector.hpp b/src/utility/small_vector.hpp index 60decf5a..e46adb9d 100644 --- a/src/utility/small_vector.hpp +++ b/src/utility/small_vector.hpp @@ -890,10 +890,7 @@ namespace gapp } private: - static constexpr std::size_t alignment = std::max(alignof(T), detail::cache_line_size); - - alignas(alignment) - GAPP_NO_UNIQUE_ADDRESS detail::small_vector_buffer buffer_; + detail::small_vector_buffer buffer_; pointer first_ = nullptr; pointer last_ = nullptr; pointer last_alloc_ = nullptr; @@ -1007,7 +1004,12 @@ namespace gapp constexpr void deallocate() noexcept { - if (!is_small() && data()) detail::deallocate(alloc_, first_, capacity()); + if (!is_small() && data()) + { + GAPP_ASSUME(data_ != buffer_.begin()); + GAPP_ASSUME(size() <= inline_capacity()); + detail::deallocate(alloc_, first_, capacity()); + } } template diff --git a/src/utility/utility.hpp b/src/utility/utility.hpp index 86f825c4..2a2325a3 100644 --- a/src/utility/utility.hpp +++ b/src/utility/utility.hpp @@ -1,12 +1,13 @@ /* Copyright (c) 2022 Krisztián Rugási. Subject to the MIT License. */ -#ifndef GA_UTILITY_UTILITY_HPP -#define GA_UTILITY_UTILITY_HPP +#ifndef GAPP_UTILITY_UTILITY_HPP +#define GAPP_UTILITY_UTILITY_HPP #include #include #include #include +#include #include @@ -76,9 +77,9 @@ #if defined(__GNUC__) || defined(__clang__) -# define GAPP_NON_NULL __attribute__((nonnull)) +# define GAPP_MAY_ALIAS __attribute__((may_alias)) #else -# define GAPP_NON_NULL +# define GAPP_MAY_ALIAS #endif @@ -178,27 +179,13 @@ namespace gapp::detail temp.swap(vec); } - // returns true if the signs of the parameters are the same - template - constexpr bool same_sign(T left, T right) noexcept - { - return (left ^ right) >= 0; - } - - // returns the length of the range [low, high) without overflow + // returns the length of the range [low, high] without overflow template - constexpr size_t range_length(T low, T high) noexcept + constexpr std::uint64_t range_length(T low, T high) noexcept { GAPP_ASSERT(low <= high); - if constexpr (std::is_unsigned_v) - { - return high - low; - } - else - { - return same_sign(low, high) ? high - low : size_t(-(low + 1)) + high + 1; - } + return std::uint64_t(high) - std::uint64_t(low); } template @@ -233,4 +220,4 @@ namespace gapp::detail } // namespace gapp::detail -#endif // !GA_UTILITY_UTILITY_HPP \ No newline at end of file +#endif // !GAPP_UTILITY_UTILITY_HPP diff --git a/test/unit/algorithm.cpp b/test/unit/algorithm.cpp index c8bb77d2..390c3996 100644 --- a/test/unit/algorithm.cpp +++ b/test/unit/algorithm.cpp @@ -20,47 +20,6 @@ static constexpr auto always_false = [](auto) { return false; }; using namespace gapp; -TEST_CASE("next_mod", "[algorithm]") -{ - REQUIRE(detail::next_mod(0, 3) == 1); - REQUIRE(detail::next_mod(1, 3) == 2); - REQUIRE(detail::next_mod(2, 3) == 0); -} - -TEST_CASE("prev_mod", "[algorithm]") -{ - REQUIRE(detail::prev_mod(0, 3) == 2); - REQUIRE(detail::prev_mod(1, 3) == 0); - REQUIRE(detail::prev_mod(2, 3) == 1); -} - -TEST_CASE("increment_mod", "[algorithm]") -{ - int n = 0; - - detail::increment_mod(n, 3); - REQUIRE(n == 1); - - detail::increment_mod(n, 3); - REQUIRE(n == 2); - - detail::increment_mod(n, 3); - REQUIRE(n == 0); -} - -TEST_CASE("decrement_mod", "[algorithm]") -{ - int n = 0; - - detail::decrement_mod(n, 3); - REQUIRE(n == 2); - - detail::decrement_mod(n, 3); - REQUIRE(n == 1); - - detail::decrement_mod(n, 3); - REQUIRE(n == 0); -} TEST_CASE("index_vector", "[algorithm]") { diff --git a/test/unit/small_vector.cpp b/test/unit/small_vector.cpp index eac5e696..55210221 100644 --- a/test/unit/small_vector.cpp +++ b/test/unit/small_vector.cpp @@ -97,7 +97,6 @@ TEST_CASE("small_vector_size", "[object_layout][!mayfail]") // fails under clang STATIC_REQUIRE(std::is_standard_layout_v>); CHECK(sizeof(small_vector) == detail::cache_line_size); - CHECK(alignof(small_vector) == detail::cache_line_size); } diff --git a/test/unit/utility.cpp b/test/unit/utility.cpp new file mode 100644 index 00000000..472a95aa --- /dev/null +++ b/test/unit/utility.cpp @@ -0,0 +1,97 @@ +/* Copyright (c) 2024 Krisztián Rugási. Subject to the MIT License. */ + +#include +#include +#include "utility/utility.hpp" +#include +#include +#include + +using namespace gapp; +using namespace gapp::detail; + + +TEMPLATE_TEST_CASE("range_length_signed", "[utility]", std::int8_t, std::int16_t, std::int32_t, std::int64_t) +{ + using IntType = TestType; + using UIntType = std::make_unsigned_t; + + constexpr IntType small = std::numeric_limits::min(); + constexpr IntType large = std::numeric_limits::max(); + + STATIC_REQUIRE(range_length(IntType{ 0 }, IntType{ 0 }) == 0); + STATIC_REQUIRE(range_length(IntType{ -1 }, IntType{ -1 }) == 0); + STATIC_REQUIRE(range_length(IntType{ 1 }, IntType{ 1 }) == 0); + + STATIC_REQUIRE(range_length(IntType{ 0 }, IntType{ 1 }) == 1); + STATIC_REQUIRE(range_length(IntType{ -1 }, IntType{ 0 }) == 1); + + STATIC_REQUIRE(range_length(IntType{ -1 }, IntType{ 1 }) == 2); + + STATIC_REQUIRE(range_length(small, small) == 0); + STATIC_REQUIRE(range_length(large, large) == 0); + + STATIC_REQUIRE(range_length(small, IntType{ 0 }) == (UIntType(large) + 1)); + STATIC_REQUIRE(range_length(IntType{ 0 }, large) == UIntType(large)); + STATIC_REQUIRE(range_length(small, large) == std::numeric_limits::max()); +} + +TEMPLATE_TEST_CASE("range_length_unsigned", "[utility]", std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t) +{ + using IntType = TestType; + + constexpr IntType small = std::numeric_limits::min(); + constexpr IntType large = std::numeric_limits::max(); + + STATIC_REQUIRE(range_length(IntType{ 0 }, IntType{ 0 }) == 0); + STATIC_REQUIRE(range_length(IntType{ 1 }, IntType{ 1 }) == 0); + + STATIC_REQUIRE(range_length(IntType{ 0 }, IntType{ 1 }) == 1); + + STATIC_REQUIRE(range_length(small, small) == 0); + STATIC_REQUIRE(range_length(large, large) == 0); + + STATIC_REQUIRE(range_length(small, large) == large); +} + +TEST_CASE("next_mod", "[algorithm]") +{ + REQUIRE(detail::next_mod(0, 3) == 1); + REQUIRE(detail::next_mod(1, 3) == 2); + REQUIRE(detail::next_mod(2, 3) == 0); +} + +TEST_CASE("prev_mod", "[algorithm]") +{ + REQUIRE(detail::prev_mod(0, 3) == 2); + REQUIRE(detail::prev_mod(1, 3) == 0); + REQUIRE(detail::prev_mod(2, 3) == 1); +} + +TEST_CASE("increment_mod", "[algorithm]") +{ + int n = 0; + + detail::increment_mod(n, 3); + REQUIRE(n == 1); + + detail::increment_mod(n, 3); + REQUIRE(n == 2); + + detail::increment_mod(n, 3); + REQUIRE(n == 0); +} + +TEST_CASE("decrement_mod", "[algorithm]") +{ + int n = 0; + + detail::decrement_mod(n, 3); + REQUIRE(n == 2); + + detail::decrement_mod(n, 3); + REQUIRE(n == 1); + + detail::decrement_mod(n, 3); + REQUIRE(n == 0); +}