mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-31 20:04:29 +02:00
Merge pull request #174 from boostorg/feature/pr165_refactor
feature/pr165 refactor
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
#include <boost/predef.h>
|
#include <boost/predef.h>
|
||||||
#include <boost/type_traits/has_trivial_copy.hpp>
|
#include <boost/type_traits/has_trivial_copy.hpp>
|
||||||
#include <boost/type_traits/is_nothrow_swappable.hpp>
|
#include <boost/type_traits/is_nothrow_swappable.hpp>
|
||||||
|
#include <boost/unordered/detail/narrow_cast.hpp>
|
||||||
#include <boost/unordered/detail/xmx.hpp>
|
#include <boost/unordered/detail/xmx.hpp>
|
||||||
#include <boost/unordered/hash_traits.hpp>
|
#include <boost/unordered/hash_traits.hpp>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
@@ -269,20 +270,12 @@ private:
|
|||||||
0xF8F8F8F8u,0xF9F9F9F9u,0xFAFAFAFAu,0xFBFBFBFBu,0xFCFCFCFCu,0xFDFDFDFDu,0xFEFEFEFEu,0xFFFFFFFFu,
|
0xF8F8F8F8u,0xF9F9F9F9u,0xFAFAFAFAu,0xFBFBFBFBu,0xFCFCFCFCu,0xFDFDFDFDu,0xFEFEFEFEu,0xFFFFFFFFu,
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(__MSVC_RUNTIME_CHECKS)
|
return (int)word[narrow_cast<unsigned char>(hash)];
|
||||||
return (int)word[hash&0xffu];
|
|
||||||
#else
|
|
||||||
return (int)word[(unsigned char)hash];
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static unsigned char reduced_hash(std::size_t hash)
|
inline static unsigned char reduced_hash(std::size_t hash)
|
||||||
{
|
{
|
||||||
#if defined(__MSVC_RUNTIME_CHECKS)
|
return narrow_cast<unsigned char>(match_word(hash));
|
||||||
return match_word(hash)&0xffu;
|
|
||||||
#else
|
|
||||||
return (unsigned char)match_word(hash);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned char& at(std::size_t pos)
|
inline unsigned char& at(std::size_t pos)
|
||||||
@@ -533,11 +526,7 @@ struct group15
|
|||||||
std::size_t pos=reinterpret_cast<uintptr_t>(pc)%sizeof(group15);
|
std::size_t pos=reinterpret_cast<uintptr_t>(pc)%sizeof(group15);
|
||||||
group15 *pg=reinterpret_cast<group15*>(pc-pos);
|
group15 *pg=reinterpret_cast<group15*>(pc-pos);
|
||||||
boost::uint64_t x=((pg->m[0])>>pos)&0x000100010001ull;
|
boost::uint64_t x=((pg->m[0])>>pos)&0x000100010001ull;
|
||||||
#if defined(__MSVC_RUNTIME_CHECKS)
|
boost::uint32_t y=narrow_cast<boost::uint32_t>(x|(x>>15)|(x>>30));
|
||||||
boost::uint32_t y=(x|(x>>15)|(x>>30))&0xffffffffu;
|
|
||||||
#else
|
|
||||||
boost::uint32_t y=static_cast<boost::uint32_t>(x|(x>>15)|(x>>30));
|
|
||||||
#endif
|
|
||||||
return !pg->is_not_overflowed(y);
|
return !pg->is_not_overflowed(y);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -552,11 +541,7 @@ struct group15
|
|||||||
inline int match_occupied()const
|
inline int match_occupied()const
|
||||||
{
|
{
|
||||||
boost::uint64_t x=m[0]|m[1];
|
boost::uint64_t x=m[0]|m[1];
|
||||||
#if defined(__MSVC_RUNTIME_CHECKS)
|
boost::uint32_t y=narrow_cast<boost::uint32_t>(x|(x>>32));
|
||||||
boost::uint32_t y=(x|(x>>32))&0xffffffffu;
|
|
||||||
#else
|
|
||||||
boost::uint32_t y=static_cast<boost::uint32_t>(x|(x>>32));
|
|
||||||
#endif
|
|
||||||
y|=y>>16;
|
y|=y>>16;
|
||||||
return y&0x7FFF;
|
return y&0x7FFF;
|
||||||
}
|
}
|
||||||
@@ -591,11 +576,7 @@ private:
|
|||||||
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
|
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(__MSVC_RUNTIME_CHECKS)
|
return table[narrow_cast<unsigned char>(hash)];
|
||||||
return table[hash&0xffu];
|
|
||||||
#else
|
|
||||||
return table[(unsigned char)hash];
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void set_impl(std::size_t pos,std::size_t n)
|
inline void set_impl(std::size_t pos,std::size_t n)
|
||||||
|
44
include/boost/unordered/detail/narrow_cast.hpp
Normal file
44
include/boost/unordered/detail/narrow_cast.hpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/* Copyright 2022 Joaquin M Lopez Munoz.
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* See https://www.boost.org/libs/unordered for library home page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BOOST_UNORDERED_DETAIL_NARROW_CAST_HPP
|
||||||
|
#define BOOST_UNORDERED_DETAIL_NARROW_CAST_HPP
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <boost/static_assert.hpp>
|
||||||
|
#include <boost/type_traits/is_integral.hpp>
|
||||||
|
#include <boost/type_traits/make_unsigned.hpp>
|
||||||
|
|
||||||
|
namespace boost{
|
||||||
|
namespace unordered{
|
||||||
|
namespace detail{
|
||||||
|
|
||||||
|
template<typename To,typename From>
|
||||||
|
BOOST_CONSTEXPR To narrow_cast(From x) BOOST_NOEXCEPT
|
||||||
|
{
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_integral<From>::value);
|
||||||
|
BOOST_STATIC_ASSERT(boost::is_integral<To>::value);
|
||||||
|
BOOST_STATIC_ASSERT(sizeof(From)>=sizeof(To));
|
||||||
|
|
||||||
|
return static_cast<To>(
|
||||||
|
x
|
||||||
|
|
||||||
|
#if defined(__MSVC_RUNTIME_CHECKS)
|
||||||
|
/* Avoids VS's "Run-Time Check Failure #1 - A cast to a smaller data type
|
||||||
|
* has caused a loss of data."
|
||||||
|
*/
|
||||||
|
&static_cast<typename boost::make_unsigned<To>::type>(~static_cast<To>(0))
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace detail */
|
||||||
|
} /* namespace unordered */
|
||||||
|
} /* namespace boost */
|
||||||
|
|
||||||
|
#endif
|
@@ -11,6 +11,7 @@
|
|||||||
#include <boost/preprocessor/seq/enum.hpp>
|
#include <boost/preprocessor/seq/enum.hpp>
|
||||||
#include <boost/preprocessor/seq/for_each.hpp>
|
#include <boost/preprocessor/seq/for_each.hpp>
|
||||||
#include <boost/preprocessor/seq/size.hpp>
|
#include <boost/preprocessor/seq/size.hpp>
|
||||||
|
#include <boost/unordered/detail/narrow_cast.hpp>
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
|
|
||||||
@@ -117,15 +118,9 @@ namespace boost {
|
|||||||
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
|
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
|
||||||
std::size_t sizes_under_32bit = inv_sizes32_len;
|
std::size_t sizes_under_32bit = inv_sizes32_len;
|
||||||
if (BOOST_LIKELY(size_index < sizes_under_32bit)) {
|
if (BOOST_LIKELY(size_index < sizes_under_32bit)) {
|
||||||
#if defined(__MSVC_RUNTIME_CHECKS)
|
|
||||||
return fast_modulo(
|
return fast_modulo(
|
||||||
boost::uint32_t(hash & 0xffffffffu) + boost::uint32_t(hash >> 32),
|
narrow_cast<boost::uint32_t>(hash) + narrow_cast<boost::uint32_t>(hash >> 32),
|
||||||
inv_sizes32[size_index], boost::uint32_t(sizes[size_index]));
|
inv_sizes32[size_index], boost::uint32_t(sizes[size_index]));
|
||||||
#else
|
|
||||||
return fast_modulo(
|
|
||||||
boost::uint32_t(hash) + boost::uint32_t(hash >> 32),
|
|
||||||
inv_sizes32[size_index], boost::uint32_t(sizes[size_index]));
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
return positions[size_index - sizes_under_32bit](hash);
|
return positions[size_index - sizes_under_32bit](hash);
|
||||||
}
|
}
|
||||||
|
@@ -95,6 +95,7 @@ run exception/rehash_exception_tests.cpp ;
|
|||||||
run exception/swap_exception_tests.cpp : : : <define>BOOST_UNORDERED_SWAP_METHOD=2 ;
|
run exception/swap_exception_tests.cpp : : : <define>BOOST_UNORDERED_SWAP_METHOD=2 ;
|
||||||
run exception/merge_exception_tests.cpp ;
|
run exception/merge_exception_tests.cpp ;
|
||||||
|
|
||||||
|
run unordered/narrow_cast_tests.cpp ;
|
||||||
run quick.cpp ;
|
run quick.cpp ;
|
||||||
|
|
||||||
import ../../config/checks/config : requires ;
|
import ../../config/checks/config : requires ;
|
||||||
|
107
test/unordered/narrow_cast_tests.cpp
Normal file
107
test/unordered/narrow_cast_tests.cpp
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
// Copyright 2022 Christian Mazakas
|
||||||
|
// Distributed under the Boost Software License, Version 1.0.
|
||||||
|
// https://www.boost.org/LICENSE_1_0.txt
|
||||||
|
|
||||||
|
#include <boost/unordered/detail/narrow_cast.hpp>
|
||||||
|
|
||||||
|
#include <boost/core/lightweight_test.hpp>
|
||||||
|
#include <boost/cstdint.hpp>
|
||||||
|
|
||||||
|
// want to prove that for the wider type, the higher bits of the value
|
||||||
|
// represenation don't affect the results of the narrowing, which in this case
|
||||||
|
// is masking out the high bits when comapred to the narrow type
|
||||||
|
|
||||||
|
static void signed_integral_narrowing()
|
||||||
|
{
|
||||||
|
// test positive range, fits
|
||||||
|
// [0, 127]
|
||||||
|
for (boost::int32_t i = 0x00; i < 0x80; ++i) {
|
||||||
|
boost::int8_t k = (boost::int8_t)i;
|
||||||
|
BOOST_TEST_GE(k, 0);
|
||||||
|
BOOST_TEST_EQ(boost::unordered::detail::narrow_cast<boost::int8_t>(i), k);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test positive range, doesn't fit
|
||||||
|
// [0xff00, 0xff7f]
|
||||||
|
for (boost::int32_t i = 0x00; i < 0x80; ++i) {
|
||||||
|
boost::int32_t j = i + 0xff00;
|
||||||
|
boost::int8_t k = (boost::int8_t)i;
|
||||||
|
BOOST_TEST_GE(k, 0);
|
||||||
|
BOOST_TEST_EQ(boost::unordered::detail::narrow_cast<boost::int8_t>(j), k);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test negative range, fits
|
||||||
|
// [-128, -1]
|
||||||
|
for (boost::int32_t i = 0x00; i < 0x80; ++i) {
|
||||||
|
boost::int32_t j = i + (boost::int32_t)0xffffff80;
|
||||||
|
boost::int8_t k = (boost::int8_t)j;
|
||||||
|
BOOST_TEST_LT(j, 0);
|
||||||
|
BOOST_TEST_LT(k, 0);
|
||||||
|
BOOST_TEST_EQ(boost::unordered::detail::narrow_cast<boost::int8_t>(j), k);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test negative range, doesn't fit
|
||||||
|
for (boost::int32_t i = 0x00; i < 0x80; ++i) {
|
||||||
|
boost::int32_t j = i + (boost::int32_t)0x80000000;
|
||||||
|
boost::int8_t k = (boost::int8_t)(i);
|
||||||
|
BOOST_TEST_LT(j, 0);
|
||||||
|
BOOST_TEST_EQ(boost::unordered::detail::narrow_cast<boost::int8_t>(j), k);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (boost::int32_t i = 0x00; i < 0x100; ++i) {
|
||||||
|
boost::int32_t j = (boost::int32_t)0x80ff0000 + i;
|
||||||
|
BOOST_TEST_LT(j, 0);
|
||||||
|
BOOST_TEST_EQ(boost::unordered::detail::narrow_cast<boost::int8_t>(j),
|
||||||
|
(boost::int8_t)i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test special values
|
||||||
|
{
|
||||||
|
boost::int32_t x = 0xff;
|
||||||
|
BOOST_TEST_EQ(boost::unordered::detail::narrow_cast<boost::int8_t>(x), -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::int32_t x = (boost::int32_t)0xffffff00;
|
||||||
|
BOOST_TEST_EQ(boost::unordered::detail::narrow_cast<boost::int8_t>(x),
|
||||||
|
(boost::int8_t)0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::int32_t x = (boost::int32_t)0xffffff7f;
|
||||||
|
BOOST_TEST_EQ(boost::unordered::detail::narrow_cast<boost::int8_t>(x),
|
||||||
|
(boost::int8_t)0x7f);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::int32_t x = (boost::int32_t)0xffffffff;
|
||||||
|
BOOST_TEST_EQ(boost::unordered::detail::narrow_cast<boost::int8_t>(x),
|
||||||
|
(boost::int8_t)-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unsigned_integral_narrowing()
|
||||||
|
{
|
||||||
|
// test range: [0x00, 0xff]
|
||||||
|
for (boost::uint32_t i = 0x00; i < 0x100; ++i) {
|
||||||
|
BOOST_TEST_EQ(boost::unordered::detail::narrow_cast<boost::uint8_t>(i),
|
||||||
|
(boost::uint8_t)(i & 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
// test range: [0xffffff00, 0xffffffff]
|
||||||
|
boost::uint32_t i = 0xffffff00;
|
||||||
|
for (; i < 0xffffffff; ++i) {
|
||||||
|
BOOST_TEST_EQ(boost::unordered::detail::narrow_cast<boost::uint8_t>(i),
|
||||||
|
(boost::uint8_t)(i & 0xff));
|
||||||
|
}
|
||||||
|
BOOST_TEST_EQ(boost::unordered::detail::narrow_cast<boost::uint8_t>(i),
|
||||||
|
(boost::uint8_t)(i & 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
signed_integral_narrowing();
|
||||||
|
unsigned_integral_narrowing();
|
||||||
|
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
Reference in New Issue
Block a user