diff --git a/src/utility/rng.hpp b/src/utility/rng.hpp index f1d094b0..8f2d123c 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 GAPP_MAY_ALIAS range_len = detail::range_length(lbound, ubound); + const std::uint64_t GAPP_MAY_ALIAS range_len = detail::range_length(lbound, ubound); GAPP_ASSERT(ubound >= lbound); GAPP_ASSERT(range_len >= count); - const bool GAPP_MAY_ALIAS select_many = std::cmp_greater_equal(count, size_t(0.6 * range_len)); + const bool GAPP_MAY_ALIAS select_many = std::cmp_greater_equal(count, std::uint64_t(0.6 * range_len)); const bool GAPP_MAY_ALIAS huge_range = std::cmp_greater_equal(range_len, 65536); if (huge_range) return rng::sampleUniqueSet(lbound, ubound, count); diff --git a/src/utility/small_vector.hpp b/src/utility/small_vector.hpp index 11c1cf74..aecb4dda 100644 --- a/src/utility/small_vector.hpp +++ b/src/utility/small_vector.hpp @@ -167,7 +167,7 @@ namespace gapp::detail { if (!std::is_constant_evaluated()) { - std::fill((char*)first, (char*)last, 0); + std::fill((unsigned char*)first, (unsigned char*)last, 0); return; } } @@ -200,8 +200,8 @@ namespace gapp::detail { if (!std::is_constant_evaluated()) { - char* src = (char*)std::to_address(src_first); - std::copy(src, src + sizeof(T) * (last - first), (char*)first); + unsigned char* src = (unsigned char*)std::to_address(src_first); + std::copy(src, src + sizeof(T) * (last - first), (unsigned char*)first); return; } } @@ -221,7 +221,7 @@ namespace gapp::detail { if (!std::is_constant_evaluated()) { - std::copy((char*)first, (char*)last, (char*)dest); + std::copy((unsigned char*)first, (unsigned char*)last, (unsigned char*)dest); return; } } @@ -241,7 +241,7 @@ namespace gapp::detail { if (!std::is_constant_evaluated()) { - std::copy((char*)first, (char*)last, (char*)dest); + std::copy((unsigned char*)first, (unsigned char*)last, (unsigned char*)dest); return; } } diff --git a/src/utility/utility.hpp b/src/utility/utility.hpp index b7c2f223..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 @@ -75,13 +76,6 @@ #endif -#if defined(__GNUC__) || defined(__clang__) -# define GAPP_NON_NULL __attribute__((nonnull)) -#else -# define GAPP_NON_NULL -#endif - - #if defined(__GNUC__) || defined(__clang__) # define GAPP_MAY_ALIAS __attribute__((may_alias)) #else @@ -185,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 @@ -240,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/utility.cpp b/test/unit/utility.cpp new file mode 100644 index 00000000..81fc0b20 --- /dev/null +++ b/test/unit/utility.cpp @@ -0,0 +1,55 @@ +/* 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); +}