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:
@@ -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;
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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() ) );
|
||||
}
|
||||
|
||||
|
||||
10
test/Jamfile
10
test/Jamfile
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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> >();
|
||||
}
|
||||
|
||||
78
test/get_integral_result_2.cpp
Normal file
78
test/get_integral_result_2.cpp
Normal 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();
|
||||
}
|
||||
50
test/get_integral_result_3.cpp
Normal file
50
test/get_integral_result_3.cpp
Normal 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();
|
||||
}
|
||||
119
test/get_integral_result_4.cpp
Normal file
119
test/get_integral_result_4.cpp
Normal 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();
|
||||
}
|
||||
74
test/get_integral_result_5.cpp
Normal file
74
test/get_integral_result_5.cpp
Normal 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();
|
||||
}
|
||||
Reference in New Issue
Block a user