2
0
mirror of https://github.com/boostorg/hash2.git synced 2026-01-31 20:22:10 +00:00

Merge branch 'develop' into gh-pages

This commit is contained in:
Peter Dimov
2024-11-18 19:44:12 +02:00
12 changed files with 585 additions and 247 deletions

View File

@@ -35,3 +35,55 @@ struct hash_append_tag;
} // namespace boost
```
The header `boost/hash2/hash_append_fwd.hpp` declares the functions implemented in `boost/hash2/hash_append.hpp`.
It can be used when code wishes to implement `hash_append` support for a user-defined type without physically depending on the implementation of `hash_append`.
## Example
.X.hpp
[source]
----
#include <boost/hash2/hash_append_fwd.hpp>
#include <vector>
class X
{
private:
int a = -1;
std::vector<int> b{ 1, 2, 3 };
template<class Hash, class Flavor>
friend void tag_invoke(
boost::hash2::hash_append_tag const&, Hash& h, Flavor const& f, X const& v )
{
boost::hash2::hash_append( h, f, v.a );
boost::hash2::hash_append( h, f, v.b );
}
public:
X() = default;
};
----
.main.cpp
[source]
----
#include "X.hpp"
#include <boost/hash2/hash_append.hpp>
#include <boost/hash2/md5.hpp>
#include <iostream>
int main()
{
X x;
boost::hash2::md5_128 hash;
boost::hash2::hash_append( hash, {}, x );
std::cout << "MD5 digest of x: " << hash.result() << std::endl;
}
----

View File

@@ -1,105 +0,0 @@
#ifndef BOOST_HASH2_DETAIL_REVERSE_HPP_INCLUDED
#define BOOST_HASH2_DETAIL_REVERSE_HPP_INCLUDED
// Copyright 2024 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <cstdint>
#include <cstring>
#include <cstdlib>
namespace boost
{
namespace hash2
{
namespace detail
{
template<std::size_t N> void reverse( unsigned char (&d)[ N ], void const* s )
{
unsigned char const* s2 = static_cast<unsigned char const*>( s );
for( std::size_t i = 0; i < N; ++i )
{
d[ i ] = s2[ N-1-i ];
}
}
#if defined(__GNUC__) || defined(__clang__)
inline void reverse( unsigned char (&d)[ 2 ], void const* s )
{
std::uint16_t tmp;
std::memcpy( &tmp, s, 2 );
tmp = __builtin_bswap16( tmp );
std::memcpy( d, &tmp, 2 );
}
inline void reverse( unsigned char (&d)[ 4 ], void const* s )
{
std::uint32_t tmp;
std::memcpy( &tmp, s, 4 );
tmp = __builtin_bswap32( tmp );
std::memcpy( d, &tmp, 4 );
}
inline void reverse( unsigned char (&d)[ 8 ], void const* s )
{
std::uint64_t tmp;
std::memcpy( &tmp, s, 8 );
tmp = __builtin_bswap64( tmp );
std::memcpy( d, &tmp, 8 );
}
inline void reverse( unsigned char (&d)[ 16 ], void const* s )
{
std::uint64_t tmp[ 2 ];
std::memcpy( tmp, s, 16 );
std::uint64_t tmp2[ 2 ] = { __builtin_bswap64( tmp[1] ), __builtin_bswap64( tmp[0] ) };
std::memcpy( d, tmp2, 16 );
}
#elif defined(_MSC_VER)
inline void reverse( unsigned char (&d)[ 2 ], void const* s )
{
unsigned short tmp;
std::memcpy( &tmp, s, 2 );
tmp = _byteswap_ushort( tmp );
std::memcpy( d, &tmp, 2 );
}
inline void reverse( unsigned char (&d)[ 4 ], void const* s )
{
unsigned long tmp;
std::memcpy( &tmp, s, 4 );
tmp = _byteswap_ulong( tmp );
std::memcpy( d, &tmp, 4 );
}
inline void reverse( unsigned char (&d)[ 8 ], void const* s )
{
unsigned long long tmp;
std::memcpy( &tmp, s, 8 );
tmp = _byteswap_uint64( tmp );
std::memcpy( d, &tmp, 8 );
}
inline void reverse( unsigned char (&d)[ 16 ], void const* s )
{
unsigned long long tmp[ 2 ];
std::memcpy( tmp, s, 16 );
unsigned long long tmp2[ 2 ] = { _byteswap_uint64( tmp[1] ), _byteswap_uint64( tmp[0] ) };
std::memcpy( d, tmp2, 16 );
}
#endif
} // namespace detail
} // namespace hash2
} // namespace boost
#endif // #ifndef BOOST_HASH2_DETAIL_REVERSE_HPP_INCLUDED

View File

@@ -5,10 +5,9 @@
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/hash2/digest.hpp>
#include <boost/hash2/detail/read.hpp>
#include <array>
#include <type_traits>
#include <limits>
#include <cstddef>
namespace boost
@@ -16,33 +15,167 @@ namespace boost
namespace hash2
{
template<class T, class R>
typename std::enable_if<std::is_integral<R>::value && (sizeof(R) >= sizeof(T)), T>::type
get_integral_result( R const & r )
namespace detail
{
typedef typename std::make_unsigned<T>::type U;
return static_cast<T>( static_cast<U>( r ) );
// identity
template<class U, class R>
constexpr typename std::enable_if<sizeof(R) == sizeof(U), U>::type
get_result_multiplier()
{
return 1;
}
// contraction
// 2 -> 1
template<class U, class R>
constexpr typename std::enable_if<sizeof(R) == 2 && sizeof(U) == 1, R>::type
get_result_multiplier()
{
return 0xBF01;
}
// 4 -> 1
template<class U, class R>
constexpr typename std::enable_if<sizeof(R) == 4 && sizeof(U) == 1, R>::type
get_result_multiplier()
{
return 0x7F7F7F7Fu;
}
// 8 -> 1
template<class U, class R>
constexpr typename std::enable_if<sizeof(R) == 8 && sizeof(U) == 1, R>::type
get_result_multiplier()
{
return 0x7F7F7F7F7F7F7F7Full;
}
// 4 -> 2
template<class U, class R>
constexpr typename std::enable_if<sizeof(R) == 4 && sizeof(U) == 2, R>::type
get_result_multiplier()
{
return 0xBFFF0001u;
}
// 8 -> 2
template<class U, class R>
constexpr typename std::enable_if<sizeof(R) == 8 && sizeof(U) == 2, R>::type
get_result_multiplier()
{
return 0xBFFFBFFFBFFFBFFFull;
}
// 8 -> 4
template<class U, class R>
constexpr typename std::enable_if<sizeof(R) == 8 && sizeof(U) == 4, R>::type
get_result_multiplier()
{
return 0xBFFFFFFF00000001ull;
}
// expansion
// 1 -> 2
template<class U, class R>
constexpr typename std::enable_if<sizeof(R) == 1 && sizeof(U) == 2, U>::type
get_result_multiplier()
{
return 0x7F7F;
}
// 1 -> 4
template<class U, class R>
constexpr typename std::enable_if<sizeof(R) == 1 && sizeof(U) == 4, U>::type
get_result_multiplier()
{
return 0xBFBFBFBFu;
}
// 1 -> 8
template<class U, class R>
constexpr typename std::enable_if<sizeof(R) == 1 && sizeof(U) == 8, U>::type
get_result_multiplier()
{
return 0xDFDFDFDFDFDFDFDFull;
}
// 2 -> 4
template<class U, class R>
constexpr typename std::enable_if<sizeof(R) == 2 && sizeof(U) == 4, U>::type
get_result_multiplier()
{
return 0x7FFF7FFFu;
}
// 2 -> 8
template<class U, class R>
constexpr typename std::enable_if<sizeof(R) == 2 && sizeof(U) == 8, U>::type
get_result_multiplier()
{
return 0x7FFF7FFF7FFF7FFFull;
}
// 4 -> 8
template<class U, class R>
constexpr typename std::enable_if<sizeof(R) == 4 && sizeof(U) == 8, U>::type
get_result_multiplier()
{
return 0x7FFFFFFF7FFFFFFFull;
}
} // namespace detail
// contraction
template<class T, class R>
typename std::enable_if<std::is_integral<R>::value && sizeof(R) == 4 && sizeof(T) == 8, T>::type
typename std::enable_if<std::is_integral<R>::value && (sizeof(R) > sizeof(T)), T>::type
get_integral_result( R const & r )
{
static_assert( std::is_integral<T>::value, "T must be integral" );
static_assert( !std::is_same<typename std::remove_cv<T>::type, bool>::value, "T must not be bool" );
static_assert( std::is_unsigned<R>::value, "R must be unsigned" );
typedef typename std::make_unsigned<T>::type U;
return static_cast<T>( ( static_cast<U>( r ) << 32 ) + r );
constexpr auto m = detail::get_result_multiplier<U, R>();
return static_cast<T>( static_cast<U>( ( r * m ) >> ( std::numeric_limits<R>::digits - std::numeric_limits<U>::digits ) ) );
}
template<class T, std::size_t N>
T get_integral_result( std::array<unsigned char, N> const & r )
// identity or expansion
template<class T, class R>
typename std::enable_if<std::is_integral<R>::value && (sizeof(R) <= sizeof(T)), T>::type
get_integral_result( R const & r )
{
static_assert( N >= 8, "Array result type is too short" );
return static_cast<T>( detail::read64le( r.data() ) );
static_assert( std::is_integral<T>::value, "T must be integral" );
static_assert( !std::is_same<typename std::remove_cv<T>::type, bool>::value, "T must not be bool" );
static_assert( std::is_unsigned<R>::value, "R must be unsigned" );
typedef typename std::make_unsigned<T>::type U;
constexpr auto m = detail::get_result_multiplier<U, R>();
return static_cast<T>( static_cast<U>( r * m ) );
}
template<class T, std::size_t N>
T get_integral_result( digest<N> const & r )
// array-like R
template<class T, class R>
typename std::enable_if< !std::is_integral<R>::value, T >::type
get_integral_result( R const & r )
{
static_assert( N >= 8, "Digest result type is too short" );
static_assert( std::is_integral<T>::value, "T must be integral" );
static_assert( !std::is_same<typename std::remove_cv<T>::type, bool>::value, "T must not be bool" );
static_assert( R().size() >= 8, "Array-like result type is too short" );
return static_cast<T>( detail::read64le( r.data() ) );
}

View File

@@ -30,9 +30,16 @@ run is_trivially_equality_comparable.cpp ;
run is_endian_independent.cpp ;
run has_constant_size.cpp ;
# helpers
# get_integral_result
run get_integral_result.cpp ;
run get_integral_result_2.cpp ;
run get_integral_result_3.cpp ;
run get_integral_result_4.cpp ;
run get_integral_result_5.cpp ;
# digest
run digest.cpp ;
# detail
@@ -41,7 +48,6 @@ run detail_read.cpp ;
run detail_write.cpp ;
run detail_write_2.cpp ;
run detail_rot.cpp ;
run detail_reverse.cpp ;
run detail_has_tag_invoke.cpp ;
# hash_append

View File

@@ -71,10 +71,10 @@ int main()
test< fnv1a_32, little_endian_flavor, std::multimap<int, int> >( 1082144933ul );
test< fnv1a_64, little_endian_flavor, std::multimap<int, int> >( 12051529320333828229ull );
test< fnv1a_32, little_endian_flavor, std::unordered_map<int, int> >( 1094735330ul );
test< fnv1a_32, little_endian_flavor, std::unordered_map<int, int> >( 2445282413ul );
test< fnv1a_64, little_endian_flavor, std::unordered_map<int, int> >( 2617313294186790738ull );
test< fnv1a_32, little_endian_flavor, std::unordered_multimap<int, int> >( 1094735330ul );
test< fnv1a_32, little_endian_flavor, std::unordered_multimap<int, int> >( 2445282413ul );
test< fnv1a_64, little_endian_flavor, std::unordered_multimap<int, int> >( 2617313294186790738ull );
return boost::report_errors();

View File

@@ -69,10 +69,10 @@ int main()
test< fnv1a_32, little_endian_flavor, std::multiset<int> >( 3576652581ul );
test< fnv1a_64, little_endian_flavor, std::multiset<int> >( 17046016161958689285ull );
test< fnv1a_32, little_endian_flavor, std::unordered_set<int> >( 3782055292ul );
test< fnv1a_32, little_endian_flavor, std::unordered_set<int> >( 776982489ul );
test< fnv1a_64, little_endian_flavor, std::unordered_set<int> >( 3232503781718511241ull );
test< fnv1a_32, little_endian_flavor, std::unordered_multiset<int> >( 3782055292ul );
test< fnv1a_32, little_endian_flavor, std::unordered_multiset<int> >( 776982489ul );
test< fnv1a_64, little_endian_flavor, std::unordered_multiset<int> >( 3232503781718511241ull );
return boost::report_errors();

View File

@@ -1,40 +0,0 @@
// Copyright 2024 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/hash2/detail/reverse.hpp>
#include <boost/core/lightweight_test.hpp>
template<std::size_t N> void test()
{
unsigned char v[ N ] = {};
for( std::size_t i = 0; i < N; ++i ) v[ i ] = static_cast<unsigned char>( i + 1 );
unsigned char w[ N ] = {};
boost::hash2::detail::reverse( w, v );
for( std::size_t i = 0; i < N; ++i ) BOOST_TEST_EQ( w[ i ], v[ N - 1 - i ] );
}
int main()
{
test<1>();
test<2>();
test<3>();
test<4>();
test<5>();
test<6>();
test<7>();
test<8>();
test<9>();
test<10>();
test<11>();
test<12>();
test<13>();
test<14>();
test<15>();
test<16>();
test<17>();
return boost::report_errors();
}

View File

@@ -1,94 +1,65 @@
// Copyright 2017, 2018 Peter Dimov.
// Copyright 2017, 2018, 2024 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/hash2/get_integral_result.hpp>
#include <boost/core/lightweight_test.hpp>
#include <cstdint>
#include <boost/hash2/digest.hpp>
#include <boost/array.hpp>
#include <array>
#include <cstddef>
template<class R> void test()
{
using boost::hash2::get_integral_result;
R r = R();
get_integral_result<signed char>( r );
get_integral_result<unsigned char>( r );
get_integral_result<short>( r );
get_integral_result<unsigned short>( r );
get_integral_result<int>( r );
get_integral_result<unsigned int>( r );
get_integral_result<long>( r );
get_integral_result<unsigned long>( r );
get_integral_result<long long>( r );
get_integral_result<unsigned long long>( r );
get_integral_result<char>( r );
get_integral_result<char16_t>( r );
get_integral_result<char32_t>( r );
}
int main()
{
using boost::hash2::get_integral_result;
{
std::uint32_t u32 = 0x12345678;
test<unsigned char>();
test<unsigned short>();
test<unsigned int>();
test<unsigned long>();
test<unsigned long long>();
BOOST_TEST_EQ( get_integral_result<std::uint8_t>( u32 ), 0x78 );
BOOST_TEST_EQ( get_integral_result<std::int8_t>( u32 ), 0x78 );
BOOST_TEST_EQ( get_integral_result<std::uint16_t>( u32 ), 0x5678 );
BOOST_TEST_EQ( get_integral_result<std::int16_t>( u32 ), 0x5678 );
BOOST_TEST_EQ( get_integral_result<std::uint32_t>( u32 ), 0x12345678 );
BOOST_TEST_EQ( get_integral_result<std::int32_t>( u32 ), 0x12345678 );
BOOST_TEST_EQ( get_integral_result<std::uint64_t>( u32 ), 0x1234567812345678ull );
BOOST_TEST_EQ( get_integral_result<std::int64_t>( u32 ), 0x1234567812345678ull );
}
test< std::array<unsigned char, 8> >();
test< std::array<unsigned char, 16> >();
test< std::array<unsigned char, 20> >();
test< std::array<unsigned char, 28> >();
test< std::array<unsigned char, 32> >();
test< std::array<unsigned char, 48> >();
test< std::array<unsigned char, 64> >();
{
std::uint32_t s32 = 0xFFFFFFFFu;
test< boost::array<unsigned char, 8> >();
test< boost::array<unsigned char, 16> >();
test< boost::array<unsigned char, 20> >();
test< boost::array<unsigned char, 28> >();
test< boost::array<unsigned char, 32> >();
test< boost::array<unsigned char, 48> >();
test< boost::array<unsigned char, 64> >();
BOOST_TEST_EQ( get_integral_result<std::uint8_t>( s32 ), 0xFF );
BOOST_TEST_EQ( get_integral_result<std::int8_t>( s32 ), -1 );
BOOST_TEST_EQ( get_integral_result<std::uint16_t>( s32 ), 0xFFFF );
BOOST_TEST_EQ( get_integral_result<std::int16_t>( s32 ), -1 );
BOOST_TEST_EQ( get_integral_result<std::uint32_t>( s32 ), 0xFFFFFFFFu );
BOOST_TEST_EQ( get_integral_result<std::int32_t>( s32 ), -1 );
BOOST_TEST_EQ( get_integral_result<std::uint64_t>( s32 ), 0xFFFFFFFFFFFFFFFFull );
BOOST_TEST_EQ( get_integral_result<std::int64_t>( s32 ), -1 );
}
{
std::uint64_t u64 = 0x0123456789ABCDEFull;
BOOST_TEST_EQ( get_integral_result<std::uint8_t>( u64 ), 0xEF );
BOOST_TEST_EQ( get_integral_result<std::int8_t>( u64 ), -0x11 );
BOOST_TEST_EQ( get_integral_result<std::uint16_t>( u64 ), 0xCDEF );
BOOST_TEST_EQ( get_integral_result<std::int16_t>( u64 ), -0x3211 );
BOOST_TEST_EQ( get_integral_result<std::uint32_t>( u64 ), 0x89ABCDEF );
BOOST_TEST_EQ( get_integral_result<std::int32_t>( u64 ), 0x89ABCDEF );
BOOST_TEST_EQ( get_integral_result<std::uint64_t>( u64 ), 0x0123456789ABCDEFull );
BOOST_TEST_EQ( get_integral_result<std::int64_t>( u64 ), 0x0123456789ABCDEFull );
}
{
std::uint64_t s64 = 0xFFFFFFFFFFFFFFFFull;
BOOST_TEST_EQ( get_integral_result<std::uint8_t>( s64 ), 0xFF );
BOOST_TEST_EQ( get_integral_result<std::int8_t>( s64 ), -1 );
BOOST_TEST_EQ( get_integral_result<std::uint16_t>( s64 ), 0xFFFF );
BOOST_TEST_EQ( get_integral_result<std::int16_t>( s64 ), -1 );
BOOST_TEST_EQ( get_integral_result<std::uint32_t>( s64 ), 0xFFFFFFFFu );
BOOST_TEST_EQ( get_integral_result<std::int32_t>( s64 ), -1 );
BOOST_TEST_EQ( get_integral_result<std::uint64_t>( s64 ), 0xFFFFFFFFFFFFFFFFull );
BOOST_TEST_EQ( get_integral_result<std::int64_t>( s64 ), -1 );
}
{
std::array<unsigned char, 8> a64 = {{ 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01 }};
BOOST_TEST_EQ( get_integral_result<std::uint8_t>( a64 ), 0xEF );
BOOST_TEST_EQ( get_integral_result<std::int8_t>( a64 ), -0x11 );
BOOST_TEST_EQ( get_integral_result<std::uint16_t>( a64 ), 0xCDEF );
BOOST_TEST_EQ( get_integral_result<std::int16_t>( a64 ), -0x3211 );
BOOST_TEST_EQ( get_integral_result<std::uint32_t>( a64 ), 0x89ABCDEF );
BOOST_TEST_EQ( get_integral_result<std::int32_t>( a64 ), 0x89ABCDEF );
BOOST_TEST_EQ( get_integral_result<std::uint64_t>( a64 ), 0x0123456789ABCDEFull );
BOOST_TEST_EQ( get_integral_result<std::int64_t>( a64 ), 0x0123456789ABCDEFull );
}
{
std::array<unsigned char, 8> b64 = {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }};
BOOST_TEST_EQ( get_integral_result<std::uint8_t>( b64 ), 0xFF );
BOOST_TEST_EQ( get_integral_result<std::int8_t>( b64 ), -1 );
BOOST_TEST_EQ( get_integral_result<std::uint16_t>( b64 ), 0xFFFF );
BOOST_TEST_EQ( get_integral_result<std::int16_t>( b64 ), -1 );
BOOST_TEST_EQ( get_integral_result<std::uint32_t>( b64 ), 0xFFFFFFFFu );
BOOST_TEST_EQ( get_integral_result<std::int32_t>( b64 ), -1 );
BOOST_TEST_EQ( get_integral_result<std::uint64_t>( b64 ), 0xFFFFFFFFFFFFFFFFull );
BOOST_TEST_EQ( get_integral_result<std::int64_t>( b64 ), -1 );
}
return boost::report_errors();
test< boost::hash2::digest<8> >();
test< boost::hash2::digest<16> >();
test< boost::hash2::digest<20> >();
test< boost::hash2::digest<28> >();
test< boost::hash2::digest<32> >();
test< boost::hash2::digest<48> >();
test< boost::hash2::digest<64> >();
}

View File

@@ -0,0 +1,78 @@
// Copyright 2017, 2018, 2024 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/hash2/get_integral_result.hpp>
#include <boost/hash2/digest.hpp>
#include <boost/array.hpp>
#include <boost/core/lightweight_test.hpp>
#include <array>
#include <cstdint>
template<class R> void test( R const& r )
{
using boost::hash2::get_integral_result;
{
auto t1 = get_integral_result<signed char>( r );
auto t2 = get_integral_result<unsigned char>( r );
BOOST_TEST_EQ( static_cast<unsigned char>( t1 ), t2 );
}
{
auto t1 = get_integral_result<signed short>( r );
auto t2 = get_integral_result<unsigned short>( r );
BOOST_TEST_EQ( static_cast<unsigned short>( t1 ), t2 );
}
{
auto t1 = get_integral_result<signed int>( r );
auto t2 = get_integral_result<unsigned int>( r );
BOOST_TEST_EQ( static_cast<unsigned int>( t1 ), t2 );
}
{
auto t1 = get_integral_result<signed long>( r );
auto t2 = get_integral_result<unsigned long>( r );
BOOST_TEST_EQ( static_cast<unsigned long>( t1 ), t2 );
}
{
auto t1 = get_integral_result<signed long long>( r );
auto t2 = get_integral_result<unsigned long long>( r );
BOOST_TEST_EQ( static_cast<unsigned long long>( t1 ), t2 );
}
}
int main()
{
using boost::hash2::get_integral_result;
test<std::uint8_t>( 0x1E );
test<std::uint8_t>( 0xE1 );
test<std::uint16_t>( 0x1E1E );
test<std::uint16_t>( 0xE1E1 );
test<std::uint32_t>( 0x1E1E1E1Eu );
test<std::uint32_t>( 0xE1E1E1E1u );
test<std::uint64_t>( 0x1E1E1E1E1E1E1E1Eull );
test<std::uint64_t>( 0xE1E1E1E1E1E1E1E1ull );
test< std::array<unsigned char, 8> >( {{ 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E }} );
test< std::array<unsigned char, 8> >( {{ 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1 }} );
test< boost::array<unsigned char, 8> >( {{ 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E }} );
test< boost::array<unsigned char, 8> >( {{ 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1 }} );
test< boost::hash2::digest<8> >( {{ 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E }} );
test< boost::hash2::digest<8> >( {{ 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1 }} );
return boost::report_errors();
}

View File

@@ -0,0 +1,50 @@
// Copyright 2017, 2018, 2024 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/hash2/get_integral_result.hpp>
#include <boost/hash2/digest.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/array.hpp>
#include <cstdint>
#include <array>
template<class R> void test()
{
using boost::hash2::get_integral_result;
{
R a64 = {{ 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01 }};
BOOST_TEST_EQ( get_integral_result<std::uint8_t>( a64 ), 0xEF );
BOOST_TEST_EQ( get_integral_result<std::int8_t>( a64 ), -0x11 );
BOOST_TEST_EQ( get_integral_result<std::uint16_t>( a64 ), 0xCDEF );
BOOST_TEST_EQ( get_integral_result<std::int16_t>( a64 ), -0x3211 );
BOOST_TEST_EQ( get_integral_result<std::uint32_t>( a64 ), 0x89ABCDEF );
BOOST_TEST_EQ( get_integral_result<std::int32_t>( a64 ), 0x89ABCDEF );
BOOST_TEST_EQ( get_integral_result<std::uint64_t>( a64 ), 0x0123456789ABCDEFull );
BOOST_TEST_EQ( get_integral_result<std::int64_t>( a64 ), 0x0123456789ABCDEFull );
}
{
R b64 = {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }};
BOOST_TEST_EQ( get_integral_result<std::uint8_t>( b64 ), 0xFF );
BOOST_TEST_EQ( get_integral_result<std::int8_t>( b64 ), -1 );
BOOST_TEST_EQ( get_integral_result<std::uint16_t>( b64 ), 0xFFFF );
BOOST_TEST_EQ( get_integral_result<std::int16_t>( b64 ), -1 );
BOOST_TEST_EQ( get_integral_result<std::uint32_t>( b64 ), 0xFFFFFFFFu );
BOOST_TEST_EQ( get_integral_result<std::int32_t>( b64 ), -1 );
BOOST_TEST_EQ( get_integral_result<std::uint64_t>( b64 ), 0xFFFFFFFFFFFFFFFFull );
BOOST_TEST_EQ( get_integral_result<std::int64_t>( b64 ), -1 );
}
}
int main()
{
test< std::array<unsigned char, 8> >();
test< boost::array<unsigned char, 8> >();
test< boost::hash2::digest<8> >();
return boost::report_errors();
}

View File

@@ -0,0 +1,119 @@
// Copyright 2017, 2018, 2024 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/hash2/get_integral_result.hpp>
#include <boost/core/lightweight_test.hpp>
#include <set>
#include <limits>
#include <cstdint>
template<class T> void test_identity()
{
using boost::hash2::get_integral_result;
using R = T;
for( unsigned i = 0; i <= std::numeric_limits<T>::max(); ++i )
{
R r = static_cast<R>( i );
T t = get_integral_result<T>( r );
BOOST_TEST_EQ( t, r );
}
}
template<class T, class R> std::size_t test_permutation( int shift )
{
using boost::hash2::get_integral_result;
std::set<T> dist;
for( unsigned i = 0; i <= std::numeric_limits<T>::max(); ++i )
{
R r = static_cast<R>( i << shift );
T t = get_integral_result<T>( r );
dist.insert( t );
}
return dist.size();
}
template<class T, class R> std::size_t test_roundtrip()
{
using boost::hash2::get_integral_result;
std::set<T> dist;
for( unsigned i = 0; i <= std::numeric_limits<T>::max(); ++i )
{
T t1 = static_cast<T>( i );
R r = get_integral_result<R>( t1 );
T t2 = get_integral_result<T>( r );
dist.insert( t2 );
}
return dist.size();
}
int main()
{
// 1 -> 1
test_identity<std::uint8_t>();
// 1 -> 2
BOOST_TEST_EQ( (test_permutation<std::uint8_t, std::uint16_t>( 0 )), 256u );
BOOST_TEST_EQ( (test_permutation<std::uint8_t, std::uint16_t>( 8 )), 256u );
BOOST_TEST_GE( (test_roundtrip<std::uint8_t, std::uint16_t>()), 255u ); // !
// 1 -> 4
BOOST_TEST_EQ( (test_permutation<std::uint8_t, std::uint32_t>( 0 )), 256u );
BOOST_TEST_EQ( (test_permutation<std::uint8_t, std::uint32_t>( 8 )), 256u );
BOOST_TEST_GE( (test_permutation<std::uint8_t, std::uint32_t>( 16 )), 255u ); // !
BOOST_TEST_EQ( (test_permutation<std::uint8_t, std::uint32_t>( 24 )), 256u );
BOOST_TEST_EQ( (test_roundtrip<std::uint8_t, std::uint32_t>()), 256u );
// 1 -> 8
BOOST_TEST_EQ( (test_permutation<std::uint8_t, std::uint64_t>( 0 )), 256u );
BOOST_TEST_EQ( (test_permutation<std::uint8_t, std::uint64_t>( 8 )), 256u );
BOOST_TEST_EQ( (test_permutation<std::uint8_t, std::uint64_t>( 16 )), 256u );
BOOST_TEST_EQ( (test_permutation<std::uint8_t, std::uint64_t>( 24 )), 256u );
BOOST_TEST_EQ( (test_permutation<std::uint8_t, std::uint64_t>( 32 )), 256u );
BOOST_TEST_EQ( (test_permutation<std::uint8_t, std::uint64_t>( 40 )), 256u );
BOOST_TEST_EQ( (test_permutation<std::uint8_t, std::uint64_t>( 48 )), 256u );
BOOST_TEST_EQ( (test_permutation<std::uint8_t, std::uint64_t>( 56 )), 256u );
BOOST_TEST_EQ( (test_roundtrip<std::uint8_t, std::uint64_t>()), 256u );
// 2 -> 2
test_identity<std::uint16_t>();
// 2 -> 4
BOOST_TEST_EQ( (test_permutation<std::uint16_t, std::uint32_t>( 0 )), 65536u );
BOOST_TEST_EQ( (test_permutation<std::uint16_t, std::uint32_t>( 16 )), 65536u );
BOOST_TEST_GE( (test_roundtrip<std::uint16_t, std::uint32_t>()), 65535u ); // !
// 2 -> 8
BOOST_TEST_EQ( (test_permutation<std::uint16_t, std::uint64_t>( 0 )), 65536u );
BOOST_TEST_EQ( (test_permutation<std::uint16_t, std::uint64_t>( 16 )), 65536u );
BOOST_TEST_EQ( (test_permutation<std::uint16_t, std::uint64_t>( 32 )), 65536u );
BOOST_TEST_EQ( (test_permutation<std::uint16_t, std::uint64_t>( 48 )), 65536u );
BOOST_TEST_EQ( (test_roundtrip<std::uint16_t, std::uint64_t>()), 65536u );
//
return boost::report_errors();
}

View File

@@ -0,0 +1,74 @@
// Copyright 2017, 2018, 2024 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/hash2/get_integral_result.hpp>
#include <boost/core/lightweight_test.hpp>
#include <set>
#include <limits>
#include <cstdint>
using T = std::uint32_t;
void test_identity()
{
using boost::hash2::get_integral_result;
using R = T;
for( unsigned i = 0; i < 65536; ++i )
{
R r = static_cast<R>( i * 0x9E3779B9u );
T t = get_integral_result<T>( r );
BOOST_TEST_EQ( t, r );
}
}
template<class R> void test_permutation( R offset = 0, R scale = 1 )
{
using boost::hash2::get_integral_result;
std::set<T> dist;
for( unsigned i = 0; i < 65536; ++i )
{
R r = static_cast<R>( i * 0x9E3779B9u * scale + offset );
T t = get_integral_result<T>( r );
dist.insert( t );
}
BOOST_TEST_EQ( dist.size(), 65536u );
}
template<class R> void test_roundtrip()
{
using boost::hash2::get_integral_result;
std::set<T> dist;
for( unsigned i = 0; i < 65536; ++i )
{
T t1 = static_cast<T>( i * 0x9E3779B9u );
R r = get_integral_result<R>( t1 );
T t2 = get_integral_result<T>( r );
dist.insert( t2 );
}
BOOST_TEST_EQ( dist.size(), 65536u );
}
int main()
{
test_identity();
test_permutation<std::uint32_t>();
test_permutation<std::uint64_t>();
test_roundtrip<std::uint32_t>();
test_roundtrip<std::uint64_t>();
return boost::report_errors();
}