mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-30 11:27:15 +02:00
Add xmx3, mulx2 with multipliers from https://arxiv.org/abs/2001.05304
This commit is contained in:
@ -295,9 +295,15 @@ template<class K, class V> using boost_unordered_flat_map_xmx =
|
|||||||
template<class K, class V> using boost_unordered_flat_map_xmx2 =
|
template<class K, class V> using boost_unordered_flat_map_xmx2 =
|
||||||
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::xmx2_mix>;
|
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::xmx2_mix>;
|
||||||
|
|
||||||
|
template<class K, class V> using boost_unordered_flat_map_xmx3 =
|
||||||
|
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::xmx3_mix>;
|
||||||
|
|
||||||
template<class K, class V> using boost_unordered_flat_map_mulx =
|
template<class K, class V> using boost_unordered_flat_map_mulx =
|
||||||
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::mulx_mix>;
|
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::mulx_mix>;
|
||||||
|
|
||||||
|
template<class K, class V> using boost_unordered_flat_map_mulx2 =
|
||||||
|
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::mulx2_mix>;
|
||||||
|
|
||||||
#ifdef HAVE_ABSEIL
|
#ifdef HAVE_ABSEIL
|
||||||
|
|
||||||
template<class K, class V> using absl_node_hash_map =
|
template<class K, class V> using absl_node_hash_map =
|
||||||
@ -321,9 +327,12 @@ int main()
|
|||||||
|
|
||||||
test<std_unordered_map>( "std::unordered_map" );
|
test<std_unordered_map>( "std::unordered_map" );
|
||||||
test<boost_unordered_map>( "boost::unordered_map" );
|
test<boost_unordered_map>( "boost::unordered_map" );
|
||||||
|
|
||||||
test<boost_unordered_flat_map_xmx>( "boost::unordered_flat_map, xmx" );
|
test<boost_unordered_flat_map_xmx>( "boost::unordered_flat_map, xmx" );
|
||||||
test<boost_unordered_flat_map_xmx2>( "boost::unordered_flat_map, xmx2" );
|
test<boost_unordered_flat_map_xmx2>( "boost::unordered_flat_map, xmx2" );
|
||||||
|
test<boost_unordered_flat_map_xmx3>( "boost::unordered_flat_map, xmx3" );
|
||||||
test<boost_unordered_flat_map_mulx>( "boost::unordered_flat_map, mulx" );
|
test<boost_unordered_flat_map_mulx>( "boost::unordered_flat_map, mulx" );
|
||||||
|
test<boost_unordered_flat_map_mulx2>( "boost::unordered_flat_map, mulx2" );
|
||||||
|
|
||||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||||
|
|
||||||
|
@ -295,9 +295,15 @@ template<class K, class V> using boost_unordered_flat_map_xmx =
|
|||||||
template<class K, class V> using boost_unordered_flat_map_xmx2 =
|
template<class K, class V> using boost_unordered_flat_map_xmx2 =
|
||||||
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::xmx2_mix>;
|
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::xmx2_mix>;
|
||||||
|
|
||||||
|
template<class K, class V> using boost_unordered_flat_map_xmx3 =
|
||||||
|
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::xmx3_mix>;
|
||||||
|
|
||||||
template<class K, class V> using boost_unordered_flat_map_mulx =
|
template<class K, class V> using boost_unordered_flat_map_mulx =
|
||||||
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::mulx_mix>;
|
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::mulx_mix>;
|
||||||
|
|
||||||
|
template<class K, class V> using boost_unordered_flat_map_mulx2 =
|
||||||
|
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::mulx2_mix>;
|
||||||
|
|
||||||
#ifdef HAVE_ABSEIL
|
#ifdef HAVE_ABSEIL
|
||||||
|
|
||||||
template<class K, class V> using absl_node_hash_map =
|
template<class K, class V> using absl_node_hash_map =
|
||||||
@ -331,9 +337,12 @@ int main()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
test<boost_unordered_map>( "boost::unordered_map" );
|
test<boost_unordered_map>( "boost::unordered_map" );
|
||||||
|
|
||||||
test<boost_unordered_flat_map_xmx>( "boost::unordered_flat_map, xmx" );
|
test<boost_unordered_flat_map_xmx>( "boost::unordered_flat_map, xmx" );
|
||||||
test<boost_unordered_flat_map_xmx2>( "boost::unordered_flat_map, xmx2" );
|
test<boost_unordered_flat_map_xmx2>( "boost::unordered_flat_map, xmx2" );
|
||||||
|
test<boost_unordered_flat_map_xmx3>( "boost::unordered_flat_map, xmx3" );
|
||||||
test<boost_unordered_flat_map_mulx>( "boost::unordered_flat_map, mulx" );
|
test<boost_unordered_flat_map_mulx>( "boost::unordered_flat_map, mulx" );
|
||||||
|
test<boost_unordered_flat_map_mulx2>( "boost::unordered_flat_map, mulx2" );
|
||||||
|
|
||||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||||
|
|
||||||
|
@ -346,9 +346,15 @@ template<class K, class V> using boost_unordered_flat_map_xmx =
|
|||||||
template<class K, class V> using boost_unordered_flat_map_xmx2 =
|
template<class K, class V> using boost_unordered_flat_map_xmx2 =
|
||||||
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::xmx2_mix>;
|
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::xmx2_mix>;
|
||||||
|
|
||||||
|
template<class K, class V> using boost_unordered_flat_map_xmx3 =
|
||||||
|
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::xmx3_mix>;
|
||||||
|
|
||||||
template<class K, class V> using boost_unordered_flat_map_mulx =
|
template<class K, class V> using boost_unordered_flat_map_mulx =
|
||||||
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::mulx_mix>;
|
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::mulx_mix>;
|
||||||
|
|
||||||
|
template<class K, class V> using boost_unordered_flat_map_mulx2 =
|
||||||
|
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::mulx2_mix>;
|
||||||
|
|
||||||
#ifdef HAVE_ABSEIL
|
#ifdef HAVE_ABSEIL
|
||||||
|
|
||||||
template<class K, class V> using absl_node_hash_map =
|
template<class K, class V> using absl_node_hash_map =
|
||||||
@ -372,9 +378,12 @@ int main()
|
|||||||
|
|
||||||
test<std_unordered_map>( "std::unordered_map" );
|
test<std_unordered_map>( "std::unordered_map" );
|
||||||
test<boost_unordered_map>( "boost::unordered_map" );
|
test<boost_unordered_map>( "boost::unordered_map" );
|
||||||
|
|
||||||
test<boost_unordered_flat_map_xmx>( "boost::unordered_flat_map, xmx" );
|
test<boost_unordered_flat_map_xmx>( "boost::unordered_flat_map, xmx" );
|
||||||
test<boost_unordered_flat_map_xmx2>( "boost::unordered_flat_map, xmx2" );
|
test<boost_unordered_flat_map_xmx2>( "boost::unordered_flat_map, xmx2" );
|
||||||
|
test<boost_unordered_flat_map_xmx3>( "boost::unordered_flat_map, xmx3" );
|
||||||
test<boost_unordered_flat_map_mulx>( "boost::unordered_flat_map, mulx" );
|
test<boost_unordered_flat_map_mulx>( "boost::unordered_flat_map, mulx" );
|
||||||
|
test<boost_unordered_flat_map_mulx2>( "boost::unordered_flat_map, mulx2" );
|
||||||
|
|
||||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||||
|
|
||||||
|
@ -187,9 +187,15 @@ template<class K, class V> using boost_unordered_flat_map_xmx =
|
|||||||
template<class K, class V> using boost_unordered_flat_map_xmx2 =
|
template<class K, class V> using boost_unordered_flat_map_xmx2 =
|
||||||
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::xmx2_mix>;
|
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::xmx2_mix>;
|
||||||
|
|
||||||
|
template<class K, class V> using boost_unordered_flat_map_xmx3 =
|
||||||
|
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::xmx3_mix>;
|
||||||
|
|
||||||
template<class K, class V> using boost_unordered_flat_map_mulx =
|
template<class K, class V> using boost_unordered_flat_map_mulx =
|
||||||
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::mulx_mix>;
|
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::mulx_mix>;
|
||||||
|
|
||||||
|
template<class K, class V> using boost_unordered_flat_map_mulx2 =
|
||||||
|
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>, boost::unordered::detail::foa::mulx2_mix>;
|
||||||
|
|
||||||
#ifdef HAVE_ABSEIL
|
#ifdef HAVE_ABSEIL
|
||||||
|
|
||||||
template<class K, class V> using absl_node_hash_map =
|
template<class K, class V> using absl_node_hash_map =
|
||||||
@ -213,9 +219,12 @@ int main()
|
|||||||
|
|
||||||
test<std_unordered_map>( "std::unordered_map" );
|
test<std_unordered_map>( "std::unordered_map" );
|
||||||
test<boost_unordered_map>( "boost::unordered_map" );
|
test<boost_unordered_map>( "boost::unordered_map" );
|
||||||
|
|
||||||
test<boost_unordered_flat_map_xmx>( "boost::unordered_flat_map, xmx" );
|
test<boost_unordered_flat_map_xmx>( "boost::unordered_flat_map, xmx" );
|
||||||
test<boost_unordered_flat_map_xmx2>( "boost::unordered_flat_map, xmx2" );
|
test<boost_unordered_flat_map_xmx2>( "boost::unordered_flat_map, xmx2" );
|
||||||
|
test<boost_unordered_flat_map_xmx3>( "boost::unordered_flat_map, xmx3" );
|
||||||
test<boost_unordered_flat_map_mulx>( "boost::unordered_flat_map, mulx" );
|
test<boost_unordered_flat_map_mulx>( "boost::unordered_flat_map, mulx" );
|
||||||
|
test<boost_unordered_flat_map_mulx2>( "boost::unordered_flat_map, mulx2" );
|
||||||
|
|
||||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||||
|
|
||||||
|
@ -770,6 +770,15 @@ struct xmx2_mix
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct xmx3_mix
|
||||||
|
{
|
||||||
|
template<typename Hash,typename T>
|
||||||
|
static inline std::size_t mix(const Hash& h,const T& x)
|
||||||
|
{
|
||||||
|
return xmx3(h(x));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct mulx_mix
|
struct mulx_mix
|
||||||
{
|
{
|
||||||
template<typename Hash,typename T>
|
template<typename Hash,typename T>
|
||||||
@ -779,6 +788,15 @@ struct mulx_mix
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct mulx2_mix
|
||||||
|
{
|
||||||
|
template<typename Hash,typename T>
|
||||||
|
static inline std::size_t mix(const Hash& h,const T& x)
|
||||||
|
{
|
||||||
|
return mulx2(h(x));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/* boost::core::countr_zero has a potentially costly check for
|
/* boost::core::countr_zero has a potentially costly check for
|
||||||
* the case x==0.
|
* the case x==0.
|
||||||
*/
|
*/
|
||||||
|
@ -94,6 +94,8 @@ inline boost::uint32_t mulx32( boost::uint32_t x, boost::uint32_t y )
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// phi multipliers
|
||||||
|
|
||||||
inline std::size_t mulx( std::size_t x ) noexcept
|
inline std::size_t mulx( std::size_t x ) noexcept
|
||||||
{
|
{
|
||||||
#if defined(BOOST_UNORDERED_64B_ARCHITECTURE)
|
#if defined(BOOST_UNORDERED_64B_ARCHITECTURE)
|
||||||
@ -107,6 +109,21 @@ inline std::size_t mulx( std::size_t x ) noexcept
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// multipliers from https://arxiv.org/abs/2001.05304
|
||||||
|
|
||||||
|
inline std::size_t mulx2( std::size_t x ) noexcept
|
||||||
|
{
|
||||||
|
#if defined(BOOST_UNORDERED_64B_ARCHITECTURE)
|
||||||
|
|
||||||
|
return (std::size_t)mulx64( (boost::uint64_t)x, 0xDEFBA91144F2B375ull );
|
||||||
|
|
||||||
|
#else /* 32 bits assumed */
|
||||||
|
|
||||||
|
return mulx32( x, 0xE817FB2Du );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef BOOST_UNORDERED_64B_ARCHITECTURE
|
#ifdef BOOST_UNORDERED_64B_ARCHITECTURE
|
||||||
#undef BOOST_UNORDERED_64B_ARCHITECTURE
|
#undef BOOST_UNORDERED_64B_ARCHITECTURE
|
||||||
#endif
|
#endif
|
||||||
|
@ -64,7 +64,7 @@ static inline std::size_t xmx(std::size_t x)noexcept
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// alternative multipliers
|
// alternative multipliers (phi)
|
||||||
|
|
||||||
static inline std::size_t xmx2( std::size_t x ) noexcept
|
static inline std::size_t xmx2( std::size_t x ) noexcept
|
||||||
{
|
{
|
||||||
@ -89,6 +89,31 @@ static inline std::size_t xmx2( std::size_t x ) noexcept
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// alternative multipliers (https://arxiv.org/abs/2001.05304)
|
||||||
|
|
||||||
|
static inline std::size_t xmx3( std::size_t x ) noexcept
|
||||||
|
{
|
||||||
|
#if defined(BOOST_UNORDERED_64B_ARCHITECTURE)
|
||||||
|
|
||||||
|
boost::uint64_t z=(boost::uint64_t)x;
|
||||||
|
|
||||||
|
z ^= z >> 23;
|
||||||
|
z *= 0xF1357AEA2E62A9C5ull;
|
||||||
|
z ^= z >> 23;
|
||||||
|
|
||||||
|
return (std::size_t)z;
|
||||||
|
|
||||||
|
#else /* 32 bits assumed */
|
||||||
|
|
||||||
|
x ^= x >> 18;
|
||||||
|
x *= 0x93D765DDu;
|
||||||
|
x ^= x >> 16;
|
||||||
|
|
||||||
|
return x;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef BOOST_UNORDERED_64B_ARCHITECTURE
|
#ifdef BOOST_UNORDERED_64B_ARCHITECTURE
|
||||||
#undef BOOST_UNORDERED_64B_ARCHITECTURE
|
#undef BOOST_UNORDERED_64B_ARCHITECTURE
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user