mirror of
https://github.com/boostorg/container_hash.git
synced 2026-03-07 06:24:04 +01:00
Compare commits
87 Commits
boost-1.79
...
feature/up
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
417180dd03 | ||
|
|
5ba74cd3a9 | ||
|
|
c14d3a1e2b | ||
|
|
a3cac265b1 | ||
|
|
c28d0b813b | ||
|
|
e39bf42dfc | ||
|
|
58502fddca | ||
|
|
5701dd3119 | ||
|
|
53c12550fa | ||
|
|
561cc5d010 | ||
|
|
bdf4bfe910 | ||
|
|
06e1b613f0 | ||
|
|
12be64b71e | ||
|
|
4e2811c4e1 | ||
|
|
2dc57b745f | ||
|
|
de618bf974 | ||
|
|
87c9eefe6e | ||
|
|
98bbd2ba56 | ||
|
|
08ea1677be | ||
|
|
3d3350646f | ||
|
|
884ce4b708 | ||
|
|
db1e23b611 | ||
|
|
5ddcd7c8e7 | ||
|
|
0e2e911df5 | ||
|
|
b3c9b35a13 | ||
|
|
c9c77cb104 | ||
|
|
873a60d009 | ||
|
|
b8d315fac5 | ||
|
|
e0e86a1413 | ||
|
|
866bd60dd3 | ||
|
|
6781cff622 | ||
|
|
dd605d0d1c | ||
|
|
dd172db079 | ||
|
|
e04ca1f442 | ||
|
|
0eada2ae93 | ||
|
|
943ef0ab82 | ||
|
|
14f8934bff | ||
|
|
f08204e29a | ||
|
|
7ad0365048 | ||
|
|
b3e424b650 | ||
|
|
d2986d9a64 | ||
|
|
000276988f | ||
|
|
9bdebb3df4 | ||
|
|
56f790d896 | ||
|
|
355c1cd7a4 | ||
|
|
c9b2d6fc90 | ||
|
|
2424ada9f9 | ||
|
|
faea988310 | ||
|
|
64c367734d | ||
|
|
6d84f9a41b | ||
|
|
aaa1f441ac | ||
|
|
3487450f62 | ||
|
|
8f163568f4 | ||
|
|
a4cbaa95b3 | ||
|
|
6ffc99adb7 | ||
|
|
bb99a2b1ae | ||
|
|
f05e8840d2 | ||
|
|
dff8843bb2 | ||
|
|
15ae39e176 | ||
|
|
39e4a4f184 | ||
|
|
88fbad7438 | ||
|
|
0737c56fec | ||
|
|
2b9251069f | ||
|
|
a63c85007f | ||
|
|
7a29dee42a | ||
|
|
a0a6fa0616 | ||
|
|
fe66085fbc | ||
|
|
24598bd45f | ||
|
|
7f2a43226e | ||
|
|
668f28660d | ||
|
|
9348a89fb4 | ||
|
|
3f2612d36e | ||
|
|
3cf502b34c | ||
|
|
b2e3beea3f | ||
|
|
d308495a67 | ||
|
|
00c837d523 | ||
|
|
415f2fafe2 | ||
|
|
9bbedce029 | ||
|
|
2fc970b6ae | ||
|
|
4e11c855cb | ||
|
|
bd379e1a46 | ||
|
|
b201ff97a8 | ||
|
|
e89fe04479 | ||
|
|
7ce3f759ec | ||
|
|
917ac6a88a | ||
|
|
9782883434 | ||
|
|
f0ef7b8e84 |
@@ -29,6 +29,10 @@ environment:
|
||||
TOOLSET: msvc-14.2
|
||||
CXXSTD: 14,17,latest
|
||||
ADDRMD: 32,64
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
TOOLSET: clang-win
|
||||
ADDRMD: 64
|
||||
CXXSTD: 14,17,latest
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
TOOLSET: clang-win
|
||||
CXXSTD: 14,17,latest
|
||||
|
||||
174
.github/workflows/ci.yml
vendored
174
.github/workflows/ci.yml
vendored
@@ -57,6 +57,11 @@ jobs:
|
||||
os: ubuntu-20.04
|
||||
install: g++-11-multilib
|
||||
address-model: 32,64
|
||||
- toolset: gcc-12
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-22.04
|
||||
install: g++-12-multilib
|
||||
address-model: 32,64
|
||||
- toolset: clang
|
||||
compiler: clang++-3.9
|
||||
cxxstd: "03,11,14"
|
||||
@@ -104,6 +109,16 @@ jobs:
|
||||
compiler: clang++-12
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-20.04
|
||||
- toolset: clang
|
||||
compiler: clang++-13
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-22.04
|
||||
install: clang-13
|
||||
- toolset: clang
|
||||
compiler: clang++-14
|
||||
cxxstd: "03,11,14,17,20"
|
||||
os: ubuntu-22.04
|
||||
install: clang-14
|
||||
- toolset: clang
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: macos-10.15
|
||||
@@ -210,3 +225,162 @@ jobs:
|
||||
cd ../boost-root
|
||||
b2 -j3 --verbose-test libs/%LIBRARY%/test//hash_info toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker
|
||||
b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker
|
||||
|
||||
posix-cmake-subdir:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-10.15
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
|
||||
LIBRARY=${GITHUB_REPOSITORY#*/}
|
||||
echo LIBRARY: $LIBRARY
|
||||
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
|
||||
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
|
||||
echo GITHUB_REF: $GITHUB_REF
|
||||
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
|
||||
REF=${REF#refs/heads/}
|
||||
echo REF: $REF
|
||||
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
|
||||
echo BOOST_BRANCH: $BOOST_BRANCH
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
|
||||
|
||||
- name: Use library with add_subdirectory
|
||||
run: |
|
||||
cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test
|
||||
mkdir __build__ && cd __build__
|
||||
cmake ..
|
||||
cmake --build .
|
||||
ctest --output-on-failure --no-tests=error
|
||||
|
||||
posix-cmake-install:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-10.15
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
|
||||
LIBRARY=${GITHUB_REPOSITORY#*/}
|
||||
echo LIBRARY: $LIBRARY
|
||||
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
|
||||
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
|
||||
echo GITHUB_REF: $GITHUB_REF
|
||||
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
|
||||
REF=${REF#refs/heads/}
|
||||
echo REF: $REF
|
||||
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
|
||||
echo BOOST_BRANCH: $BOOST_BRANCH
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
cd ../boost-root
|
||||
mkdir __build__ && cd __build__
|
||||
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local ..
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
cmake --build . --target install
|
||||
|
||||
- name: Use the installed library
|
||||
run: |
|
||||
cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__
|
||||
cmake -DCMAKE_INSTALL_PREFIX=~/.local ..
|
||||
cmake --build .
|
||||
ctest --output-on-failure --no-tests=error
|
||||
|
||||
posix-cmake-test:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-10.15
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
|
||||
LIBRARY=${GITHUB_REPOSITORY#*/}
|
||||
echo LIBRARY: $LIBRARY
|
||||
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
|
||||
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
|
||||
echo GITHUB_REF: $GITHUB_REF
|
||||
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
|
||||
REF=${REF#refs/heads/}
|
||||
echo REF: $REF
|
||||
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
|
||||
echo BOOST_BRANCH: $BOOST_BRANCH
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
cd ../boost-root
|
||||
mkdir __build__ && cd __build__
|
||||
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON ..
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
cmake --build . --target tests
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
ctest --output-on-failure --no-tests=error
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# Copyright 2018 Mike Dev
|
||||
# Generated by `boostdep --cmake container_hash`
|
||||
# Copyright 2020, 2021 Peter Dimov
|
||||
# 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
|
||||
# https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.20)
|
||||
|
||||
project(boost_container_hash VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
|
||||
|
||||
add_library(boost_container_hash INTERFACE)
|
||||
@@ -11,12 +13,13 @@ add_library(Boost::container_hash ALIAS boost_container_hash)
|
||||
target_include_directories(boost_container_hash INTERFACE include)
|
||||
|
||||
target_link_libraries(boost_container_hash
|
||||
INTERFACE
|
||||
Boost::assert
|
||||
Boost::config
|
||||
Boost::core
|
||||
Boost::detail
|
||||
Boost::integer
|
||||
Boost::static_assert
|
||||
Boost::type_traits
|
||||
INTERFACE
|
||||
Boost::config
|
||||
Boost::type_traits
|
||||
)
|
||||
|
||||
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
|
||||
|
||||
add_subdirectory(test)
|
||||
|
||||
endif()
|
||||
|
||||
101
benchmark/char_seq.cpp
Normal file
101
benchmark/char_seq.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright 2022 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/detail/splitmix64.hpp>
|
||||
#include <boost/core/type_name.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <chrono>
|
||||
|
||||
// test_hash_speed
|
||||
|
||||
template<class T, class V> void test_hash_speed( int N, V const& v )
|
||||
{
|
||||
std::vector<T> w;
|
||||
|
||||
w.reserve( N );
|
||||
|
||||
for( int i = 0; i < N; ++i )
|
||||
{
|
||||
w.emplace_back( v[i].begin(), v[i].end() );
|
||||
}
|
||||
|
||||
typedef std::chrono::steady_clock clock_type;
|
||||
|
||||
clock_type::time_point t1 = clock_type::now();
|
||||
|
||||
std::size_t q = 0;
|
||||
|
||||
boost::hash<T> const h;
|
||||
|
||||
for( int i = 0; i < N; ++i )
|
||||
{
|
||||
q += h( w[i] );
|
||||
}
|
||||
|
||||
clock_type::time_point t2 = clock_type::now();
|
||||
|
||||
long long ms1 = std::chrono::duration_cast<std::chrono::milliseconds>( t2 - t1 ).count();
|
||||
|
||||
std::string type = boost::core::type_name<T>();
|
||||
|
||||
#if defined( _MSC_VER )
|
||||
|
||||
std::printf( "%25s : q=%20Iu, %lld ms\n", type.c_str(), q, ms1 );
|
||||
|
||||
#else
|
||||
|
||||
std::printf( "%25s : q=%20zu, %lld ms\n", type.c_str(), q, ms1 );
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int const N = 1048576 * 8;
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
{
|
||||
v.reserve( N );
|
||||
|
||||
boost::detail::splitmix64 rnd;
|
||||
|
||||
for( int i = 0; i < N; ++i )
|
||||
{
|
||||
char buffer[ 64 ];
|
||||
|
||||
unsigned long long k = rnd();
|
||||
|
||||
if( k & 1 )
|
||||
{
|
||||
sprintf( buffer, "prefix_%llu_suffix", k );
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( buffer, "{%u}", static_cast<unsigned>( k ) );
|
||||
}
|
||||
|
||||
v.push_back( buffer );
|
||||
}
|
||||
}
|
||||
|
||||
std::puts( "Char sequence hashing test:\n" );
|
||||
|
||||
test_hash_speed< std::string >( N, v );
|
||||
test_hash_speed< std::vector<char> >( N, v );
|
||||
test_hash_speed< std::deque<char> >( N, v );
|
||||
test_hash_speed< std::list<char> >( N, v );
|
||||
|
||||
std::puts( "" );
|
||||
}
|
||||
389
benchmark/unordered.cpp
Normal file
389
benchmark/unordered.cpp
Normal file
@@ -0,0 +1,389 @@
|
||||
// Copyright 2022 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/core/detail/splitmix64.hpp>
|
||||
#include <boost/core/type_name.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
|
||||
// mul31_hash
|
||||
|
||||
class mul31_hash
|
||||
{
|
||||
public:
|
||||
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
char const * p = st.data();
|
||||
std::size_t n = st.size();
|
||||
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
std::size_t h = 0xCBF29CE484222325ull;
|
||||
#else
|
||||
std::size_t h = 0x811C9DC5u;
|
||||
#endif
|
||||
|
||||
for( std::size_t i = 0; i < n; ++i )
|
||||
{
|
||||
h = h * 31 + static_cast<unsigned char>( p[i] );
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
// mul31_unrolled_hash
|
||||
|
||||
template<int Bits> struct mul31_unrolled_hash_impl;
|
||||
|
||||
template<> struct mul31_unrolled_hash_impl<32>
|
||||
{
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
char const * p = st.data();
|
||||
std::size_t n = st.size();
|
||||
|
||||
std::size_t h = 0x811C9DC5u;
|
||||
|
||||
while( n >= 4 )
|
||||
{
|
||||
h = h * (31u * 31u * 31u * 31u)
|
||||
+ static_cast<unsigned char>( p[0] ) * (31u * 31u * 31u)
|
||||
+ static_cast<unsigned char>( p[1] ) * (31u * 31u)
|
||||
+ static_cast<unsigned char>( p[2] ) * 31u
|
||||
+ static_cast<unsigned char>( p[3] );
|
||||
|
||||
p += 4;
|
||||
n -= 4;
|
||||
}
|
||||
|
||||
while( n > 0 )
|
||||
{
|
||||
h = h * 31u + static_cast<unsigned char>( *p );
|
||||
|
||||
++p;
|
||||
--n;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct mul31_unrolled_hash_impl<64>
|
||||
{
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
char const * p = st.data();
|
||||
std::size_t n = st.size();
|
||||
|
||||
std::size_t h = 0xCBF29CE484222325ull;
|
||||
|
||||
while( n >= 8 )
|
||||
{
|
||||
h = h * (31ull * 31ull * 31ull * 31ull * 31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[0] ) * (31ull * 31ull * 31ull * 31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[1] ) * (31ull * 31ull * 31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[2] ) * (31ull * 31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[3] ) * (31ull * 31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[4] ) * (31ull * 31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[5] ) * (31ull * 31ull)
|
||||
+ static_cast<unsigned char>( p[6] ) * 31ull
|
||||
+ static_cast<unsigned char>( p[7] );
|
||||
|
||||
p += 8;
|
||||
n -= 8;
|
||||
}
|
||||
|
||||
while( n > 0 )
|
||||
{
|
||||
h = h * 31u + static_cast<unsigned char>( *p );
|
||||
|
||||
++p;
|
||||
--n;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
struct mul31_unrolled_hash: mul31_unrolled_hash_impl< std::numeric_limits<std::size_t>::digits > {};
|
||||
|
||||
// fnv1a_hash
|
||||
|
||||
template<int Bits> struct fnv1a_hash_impl;
|
||||
|
||||
template<> struct fnv1a_hash_impl<32>
|
||||
{
|
||||
std::size_t operator()( std::string const& s ) const
|
||||
{
|
||||
std::size_t h = 0x811C9DC5u;
|
||||
|
||||
char const * first = s.data();
|
||||
char const * last = first + s.size();
|
||||
|
||||
for( ; first != last; ++first )
|
||||
{
|
||||
h ^= static_cast<unsigned char>( *first );
|
||||
h *= 0x01000193ul;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct fnv1a_hash_impl<64>
|
||||
{
|
||||
std::size_t operator()( std::string const& s ) const
|
||||
{
|
||||
std::size_t h = 0xCBF29CE484222325ull;
|
||||
|
||||
char const * first = s.data();
|
||||
char const * last = first + s.size();
|
||||
|
||||
for( ; first != last; ++first )
|
||||
{
|
||||
h ^= static_cast<unsigned char>( *first );
|
||||
h *= 0x00000100000001B3ull;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
struct fnv1a_hash: fnv1a_hash_impl< std::numeric_limits<std::size_t>::digits > {};
|
||||
|
||||
// old_boost_hash
|
||||
|
||||
class old_boost_hash
|
||||
{
|
||||
public:
|
||||
|
||||
std::size_t operator()( std::string const& st ) const BOOST_NOEXCEPT
|
||||
{
|
||||
char const * p = st.data();
|
||||
std::size_t n = st.size();
|
||||
|
||||
std::size_t h = 0;
|
||||
|
||||
for( std::size_t i = 0; i < n; ++i )
|
||||
{
|
||||
h ^= static_cast<unsigned char>( p[i] ) + 0x9e3779b9 + ( h << 6 ) + ( h >> 2 );
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
// test_hash_speed
|
||||
|
||||
template<class H, class V> void test_hash_speed( int N, V const& v )
|
||||
{
|
||||
typedef std::chrono::steady_clock clock_type;
|
||||
|
||||
clock_type::time_point t1 = clock_type::now();
|
||||
|
||||
std::size_t q = 0;
|
||||
|
||||
H const h;
|
||||
|
||||
for( int i = 0; i < N; ++i )
|
||||
{
|
||||
q += h( v[i] );
|
||||
}
|
||||
|
||||
clock_type::time_point t2 = clock_type::now();
|
||||
|
||||
long long ms1 = std::chrono::duration_cast<std::chrono::milliseconds>( t2 - t1 ).count();
|
||||
|
||||
std::string hash = boost::core::type_name<H>();
|
||||
|
||||
#if defined( _MSC_VER )
|
||||
|
||||
std::printf( "%25s : q=%20Iu, %lld ms\n", hash.c_str(), q, ms1 );
|
||||
|
||||
#else
|
||||
|
||||
std::printf( "%25s : q=%20zu, %lld ms\n", hash.c_str(), q, ms1 );
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// test_hash_collision
|
||||
|
||||
template<class H, class V> void test_hash_collision( int N, V const& v, std::size_t n )
|
||||
{
|
||||
boost::unordered_set<std::size_t> s;
|
||||
H const h;
|
||||
|
||||
for( int i = 0; i < N; ++i )
|
||||
{
|
||||
s.insert( h( v[i] ) );
|
||||
}
|
||||
|
||||
std::string hash = boost::core::type_name<H>();
|
||||
|
||||
#if defined( _MSC_VER )
|
||||
|
||||
std::printf( "%25s : c=%Iu\n", hash.c_str(), n - s.size() );
|
||||
|
||||
#else
|
||||
|
||||
std::printf( "%25s : c=%zu\n", hash.c_str(), n - s.size() );
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// test_container_speed
|
||||
|
||||
template<class V, class S> void test4( int N, V const& v, char const * hash, S s )
|
||||
{
|
||||
typedef std::chrono::steady_clock clock_type;
|
||||
|
||||
clock_type::time_point t1 = clock_type::now();
|
||||
|
||||
for( int i = 0; i < N; ++i )
|
||||
{
|
||||
s.insert( v[ i * 16 ] );
|
||||
}
|
||||
|
||||
clock_type::time_point t2 = clock_type::now();
|
||||
|
||||
std::size_t q = 0;
|
||||
|
||||
for( int i = 0; i < 16 * N; ++i )
|
||||
{
|
||||
q += s.count( v[ i ] );
|
||||
}
|
||||
|
||||
clock_type::time_point t3 = clock_type::now();
|
||||
|
||||
long long ms1 = std::chrono::duration_cast<std::chrono::milliseconds>( t2 - t1 ).count();
|
||||
long long ms2 = std::chrono::duration_cast<std::chrono::milliseconds>( t3 - t2 ).count();
|
||||
|
||||
std::size_t n = s.bucket_count();
|
||||
std::size_t m = 0;
|
||||
std::size_t c = 0;
|
||||
|
||||
for( std::size_t i = 0; i < n; ++i )
|
||||
{
|
||||
std::size_t k = s.bucket_size( i );
|
||||
|
||||
if( k > 1 )
|
||||
{
|
||||
c += k - 1;
|
||||
}
|
||||
|
||||
if( k > m )
|
||||
{
|
||||
m = k;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined( _MSC_VER )
|
||||
|
||||
std::printf( "%25s : n=%Iu, m=%Iu, c=%Iu, q=%Iu, %lld + %lld ms\n", hash, n, m, c, q, ms1, ms2 );
|
||||
|
||||
#else
|
||||
|
||||
std::printf( "%25s : n=%zu, m=%zu, c=%zu, q=%zu, %lld + %lld ms\n", hash, n, m, c, q, ms1, ms2 );
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class K, class H, class V> void test_container_speed( int N, V const& v )
|
||||
{
|
||||
boost::unordered_set<K, H> s( 0 );
|
||||
test4( N, v, boost::core::type_name<H>().c_str(), s );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int const N = 1048576 / 2; // 1048576 is too much for 32 bit
|
||||
|
||||
std::vector<std::string> v;
|
||||
|
||||
{
|
||||
v.reserve( N * 16 );
|
||||
|
||||
boost::detail::splitmix64 rnd;
|
||||
|
||||
for( int i = 0; i < 16 * N; ++i )
|
||||
{
|
||||
char buffer[ 64 ];
|
||||
|
||||
unsigned long long k = rnd();
|
||||
|
||||
if( k & 1 )
|
||||
{
|
||||
sprintf( buffer, "prefix_%llu_suffix", k );
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( buffer, "{%u}", static_cast<unsigned>( k ) );
|
||||
}
|
||||
|
||||
v.push_back( buffer );
|
||||
}
|
||||
}
|
||||
|
||||
std::puts( "Hash speed test:\n" );
|
||||
|
||||
test_hash_speed<mul31_hash>( N * 16, v );
|
||||
test_hash_speed<mul31_unrolled_hash>( N * 16, v );
|
||||
test_hash_speed<fnv1a_hash>( N * 16, v );
|
||||
test_hash_speed<old_boost_hash>( N * 16, v );
|
||||
test_hash_speed<boost::hash<std::string> >( N * 16, v );
|
||||
test_hash_speed<std::hash<std::string> >( N * 16, v );
|
||||
|
||||
std::puts( "" );
|
||||
|
||||
std::puts( "Hash collision test:\n" );
|
||||
|
||||
{
|
||||
std::size_t n = 0;
|
||||
|
||||
{
|
||||
boost::unordered_set<std::string> s;
|
||||
|
||||
for( int i = 0; i < N * 16; ++i )
|
||||
{
|
||||
s.insert( v[i] );
|
||||
}
|
||||
|
||||
n = s.size();
|
||||
}
|
||||
|
||||
test_hash_collision<mul31_hash>( N * 16, v, n );
|
||||
test_hash_collision<mul31_unrolled_hash>( N * 16, v, n );
|
||||
test_hash_collision<fnv1a_hash>( N * 16, v, n );
|
||||
test_hash_collision<old_boost_hash>( N * 16, v, n );
|
||||
test_hash_collision<boost::hash<std::string> >( N * 16, v, n );
|
||||
test_hash_collision<std::hash<std::string> >( N * 16, v, n );
|
||||
}
|
||||
|
||||
std::puts( "" );
|
||||
|
||||
typedef std::string K;
|
||||
|
||||
std::puts( "Container speed test:\n" );
|
||||
|
||||
test_container_speed<K, mul31_hash>( N, v );
|
||||
test_container_speed<K, mul31_unrolled_hash>( N, v );
|
||||
test_container_speed<K, fnv1a_hash>( N, v );
|
||||
test_container_speed<K, old_boost_hash>( N, v );
|
||||
test_container_speed<K, boost::hash<std::string> >( N, v );
|
||||
test_container_speed<K, std::hash<std::string> >( N, v );
|
||||
|
||||
std::puts( "" );
|
||||
}
|
||||
@@ -6,4 +6,4 @@
|
||||
run books.cpp ;
|
||||
run point.cpp ;
|
||||
run portable.cpp ;
|
||||
run template.cpp ;
|
||||
run template.cpp : : : <toolset>msvc-8.0:<build>no ;
|
||||
|
||||
@@ -1,336 +0,0 @@
|
||||
|
||||
// Copyright 2005-2009 Daniel James.
|
||||
// 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)
|
||||
|
||||
#if !defined(BOOST_FUNCTIONAL_HASH_DETAIL_FLOAT_FUNCTIONS_HPP)
|
||||
#define BOOST_FUNCTIONAL_HASH_DETAIL_FLOAT_FUNCTIONS_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
|
||||
// Set BOOST_HASH_CONFORMANT_FLOATS to 1 for libraries known to have
|
||||
// sufficiently good floating point support to not require any
|
||||
// workarounds.
|
||||
//
|
||||
// When set to 0, the library tries to automatically
|
||||
// use the best available implementation. This normally works well, but
|
||||
// breaks when ambiguities are created by odd namespacing of the functions.
|
||||
//
|
||||
// Note that if this is set to 0, the library should still take full
|
||||
// advantage of the platform's floating point support.
|
||||
|
||||
#if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
|
||||
# define BOOST_HASH_CONFORMANT_FLOATS 0
|
||||
#elif defined(__LIBCOMO__)
|
||||
# define BOOST_HASH_CONFORMANT_FLOATS 0
|
||||
#elif defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER)
|
||||
// Rogue Wave library:
|
||||
# define BOOST_HASH_CONFORMANT_FLOATS 0
|
||||
#elif defined(_LIBCPP_VERSION)
|
||||
// libc++
|
||||
# define BOOST_HASH_CONFORMANT_FLOATS 1
|
||||
#elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
|
||||
// GNU libstdc++ 3
|
||||
# if defined(__GNUC__) && __GNUC__ >= 4
|
||||
# define BOOST_HASH_CONFORMANT_FLOATS 1
|
||||
# else
|
||||
# define BOOST_HASH_CONFORMANT_FLOATS 0
|
||||
# endif
|
||||
#elif defined(__STL_CONFIG_H)
|
||||
// generic SGI STL
|
||||
# define BOOST_HASH_CONFORMANT_FLOATS 0
|
||||
#elif defined(__MSL_CPP__)
|
||||
// MSL standard lib:
|
||||
# define BOOST_HASH_CONFORMANT_FLOATS 0
|
||||
#elif defined(__IBMCPP__)
|
||||
// VACPP std lib (probably conformant for much earlier version).
|
||||
# if __IBMCPP__ >= 1210
|
||||
# define BOOST_HASH_CONFORMANT_FLOATS 1
|
||||
# else
|
||||
# define BOOST_HASH_CONFORMANT_FLOATS 0
|
||||
# endif
|
||||
#elif defined(MSIPL_COMPILE_H)
|
||||
// Modena C++ standard library
|
||||
# define BOOST_HASH_CONFORMANT_FLOATS 0
|
||||
#elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)
|
||||
// Dinkumware Library (this has to appear after any possible replacement libraries):
|
||||
# if _CPPLIB_VER >= 405
|
||||
# define BOOST_HASH_CONFORMANT_FLOATS 1
|
||||
# else
|
||||
# define BOOST_HASH_CONFORMANT_FLOATS 0
|
||||
# endif
|
||||
#else
|
||||
# define BOOST_HASH_CONFORMANT_FLOATS 0
|
||||
#endif
|
||||
|
||||
#if BOOST_HASH_CONFORMANT_FLOATS
|
||||
|
||||
// The standard library is known to be compliant, so don't use the
|
||||
// configuration mechanism.
|
||||
|
||||
namespace boost {
|
||||
namespace hash_detail {
|
||||
template <typename Float>
|
||||
struct call_ldexp {
|
||||
typedef Float float_type;
|
||||
inline Float operator()(Float x, int y) const {
|
||||
return std::ldexp(x, y);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Float>
|
||||
struct call_frexp {
|
||||
typedef Float float_type;
|
||||
inline Float operator()(Float x, int* y) const {
|
||||
return std::frexp(x, y);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Float>
|
||||
struct select_hash_type
|
||||
{
|
||||
typedef Float type;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#else // BOOST_HASH_CONFORMANT_FLOATS == 0
|
||||
|
||||
// The C++ standard requires that the C float functions are overloarded
|
||||
// for float, double and long double in the std namespace, but some of the older
|
||||
// library implementations don't support this. On some that don't, the C99
|
||||
// float functions (frexpf, frexpl, etc.) are available.
|
||||
//
|
||||
// The following tries to automatically detect which are available.
|
||||
|
||||
namespace boost {
|
||||
namespace hash_detail {
|
||||
|
||||
// Returned by dummy versions of the float functions.
|
||||
|
||||
struct not_found {
|
||||
// Implicitly convertible to float and long double in order to avoid
|
||||
// a compile error when the dummy float functions are used.
|
||||
|
||||
inline operator float() const { return 0; }
|
||||
inline operator long double() const { return 0; }
|
||||
};
|
||||
|
||||
// A type for detecting the return type of functions.
|
||||
|
||||
template <typename T> struct is;
|
||||
template <> struct is<float> { char x[10]; };
|
||||
template <> struct is<double> { char x[20]; };
|
||||
template <> struct is<long double> { char x[30]; };
|
||||
template <> struct is<boost::hash_detail::not_found> { char x[40]; };
|
||||
|
||||
// Used to convert the return type of a function to a type for sizeof.
|
||||
|
||||
template <typename T> is<T> float_type(T);
|
||||
|
||||
// call_ldexp
|
||||
//
|
||||
// This will get specialized for float and long double
|
||||
|
||||
template <typename Float> struct call_ldexp
|
||||
{
|
||||
typedef double float_type;
|
||||
|
||||
inline double operator()(double a, int b) const
|
||||
{
|
||||
using namespace std;
|
||||
return ldexp(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
// call_frexp
|
||||
//
|
||||
// This will get specialized for float and long double
|
||||
|
||||
template <typename Float> struct call_frexp
|
||||
{
|
||||
typedef double float_type;
|
||||
|
||||
inline double operator()(double a, int* b) const
|
||||
{
|
||||
using namespace std;
|
||||
return frexp(a, b);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// A namespace for dummy functions to detect when the actual function we want
|
||||
// isn't available. ldexpl, ldexpf etc. might be added tby the macros below.
|
||||
//
|
||||
// AFAICT these have to be outside of the boost namespace, as if they're in
|
||||
// the boost namespace they'll always be preferable to any other function
|
||||
// (since the arguments are built in types, ADL can't be used).
|
||||
|
||||
namespace boost_hash_detect_float_functions {
|
||||
template <class Float> boost::hash_detail::not_found ldexp(Float, int);
|
||||
template <class Float> boost::hash_detail::not_found frexp(Float, int*);
|
||||
}
|
||||
|
||||
// Macros for generating specializations of call_ldexp and call_frexp.
|
||||
//
|
||||
// check_cpp and check_c99 check if the C++ or C99 functions are available.
|
||||
//
|
||||
// Then the call_* functions select an appropriate implementation.
|
||||
//
|
||||
// I used c99_func in a few places just to get a unique name.
|
||||
//
|
||||
// Important: when using 'using namespace' at namespace level, include as
|
||||
// little as possible in that namespace, as Visual C++ has an odd bug which
|
||||
// can cause the namespace to be imported at the global level. This seems to
|
||||
// happen mainly when there's a template in the same namesapce.
|
||||
|
||||
#define BOOST_HASH_CALL_FLOAT_FUNC(cpp_func, c99_func, type1, type2) \
|
||||
namespace boost_hash_detect_float_functions { \
|
||||
template <class Float> \
|
||||
boost::hash_detail::not_found c99_func(Float, type2); \
|
||||
} \
|
||||
\
|
||||
namespace boost { \
|
||||
namespace hash_detail { \
|
||||
namespace c99_func##_detect { \
|
||||
using namespace std; \
|
||||
using namespace boost_hash_detect_float_functions; \
|
||||
\
|
||||
struct check { \
|
||||
static type1 x; \
|
||||
static type2 y; \
|
||||
BOOST_STATIC_CONSTANT(bool, cpp = \
|
||||
sizeof(float_type(cpp_func(x,y))) \
|
||||
== sizeof(is<type1>)); \
|
||||
BOOST_STATIC_CONSTANT(bool, c99 = \
|
||||
sizeof(float_type(c99_func(x,y))) \
|
||||
== sizeof(is<type1>)); \
|
||||
}; \
|
||||
} \
|
||||
\
|
||||
template <bool x> \
|
||||
struct call_c99_##c99_func : \
|
||||
boost::hash_detail::call_##cpp_func<double> {}; \
|
||||
\
|
||||
template <> \
|
||||
struct call_c99_##c99_func<true> { \
|
||||
typedef type1 float_type; \
|
||||
\
|
||||
template <typename T> \
|
||||
inline type1 operator()(type1 a, T b) const \
|
||||
{ \
|
||||
using namespace std; \
|
||||
return c99_func(a, b); \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <bool x> \
|
||||
struct call_cpp_##c99_func : \
|
||||
call_c99_##c99_func< \
|
||||
::boost::hash_detail::c99_func##_detect::check::c99 \
|
||||
> {}; \
|
||||
\
|
||||
template <> \
|
||||
struct call_cpp_##c99_func<true> { \
|
||||
typedef type1 float_type; \
|
||||
\
|
||||
template <typename T> \
|
||||
inline type1 operator()(type1 a, T b) const \
|
||||
{ \
|
||||
using namespace std; \
|
||||
return cpp_func(a, b); \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <> \
|
||||
struct call_##cpp_func<type1> : \
|
||||
call_cpp_##c99_func< \
|
||||
::boost::hash_detail::c99_func##_detect::check::cpp \
|
||||
> {}; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define BOOST_HASH_CALL_FLOAT_MACRO(cpp_func, c99_func, type1, type2) \
|
||||
namespace boost { \
|
||||
namespace hash_detail { \
|
||||
\
|
||||
template <> \
|
||||
struct call_##cpp_func<type1> { \
|
||||
typedef type1 float_type; \
|
||||
inline type1 operator()(type1 x, type2 y) const { \
|
||||
return c99_func(x, y); \
|
||||
} \
|
||||
}; \
|
||||
} \
|
||||
}
|
||||
|
||||
#if defined(ldexpf)
|
||||
BOOST_HASH_CALL_FLOAT_MACRO(ldexp, ldexpf, float, int)
|
||||
#else
|
||||
BOOST_HASH_CALL_FLOAT_FUNC(ldexp, ldexpf, float, int)
|
||||
#endif
|
||||
|
||||
#if defined(ldexpl)
|
||||
BOOST_HASH_CALL_FLOAT_MACRO(ldexp, ldexpl, long double, int)
|
||||
#else
|
||||
BOOST_HASH_CALL_FLOAT_FUNC(ldexp, ldexpl, long double, int)
|
||||
#endif
|
||||
|
||||
#if defined(frexpf)
|
||||
BOOST_HASH_CALL_FLOAT_MACRO(frexp, frexpf, float, int*)
|
||||
#else
|
||||
BOOST_HASH_CALL_FLOAT_FUNC(frexp, frexpf, float, int*)
|
||||
#endif
|
||||
|
||||
#if defined(frexpl)
|
||||
BOOST_HASH_CALL_FLOAT_MACRO(frexp, frexpl, long double, int*)
|
||||
#else
|
||||
BOOST_HASH_CALL_FLOAT_FUNC(frexp, frexpl, long double, int*)
|
||||
#endif
|
||||
|
||||
#undef BOOST_HASH_CALL_FLOAT_MACRO
|
||||
#undef BOOST_HASH_CALL_FLOAT_FUNC
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
template <typename Float1, typename Float2>
|
||||
struct select_hash_type_impl {
|
||||
typedef double type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct select_hash_type_impl<float, float> {
|
||||
typedef float type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct select_hash_type_impl<long double, long double> {
|
||||
typedef long double type;
|
||||
};
|
||||
|
||||
|
||||
// select_hash_type
|
||||
//
|
||||
// If there is support for a particular floating point type, use that
|
||||
// otherwise use double (there's always support for double).
|
||||
|
||||
template <typename Float>
|
||||
struct select_hash_type : select_hash_type_impl<
|
||||
BOOST_DEDUCED_TYPENAME call_ldexp<Float>::float_type,
|
||||
BOOST_DEDUCED_TYPENAME call_frexp<Float>::float_type
|
||||
> {};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BOOST_HASH_CONFORMANT_FLOATS
|
||||
|
||||
#endif
|
||||
@@ -1,271 +0,0 @@
|
||||
|
||||
// Copyright 2005-2012 Daniel James.
|
||||
// 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)
|
||||
|
||||
#if !defined(BOOST_FUNCTIONAL_HASH_DETAIL_HASH_FLOAT_HEADER)
|
||||
#define BOOST_FUNCTIONAL_HASH_DETAIL_HASH_FLOAT_HEADER
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container_hash/detail/float_functions.hpp>
|
||||
#include <boost/container_hash/detail/limits.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
#include <boost/integer/static_log2.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <cstring>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#if BOOST_MSVC >= 1400
|
||||
#pragma warning(disable:6294) // Ill-defined for-loop: initial condition does
|
||||
// not satisfy test. Loop body not executed
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Can we use fpclassify?
|
||||
|
||||
// STLport
|
||||
#if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
|
||||
#define BOOST_HASH_USE_FPCLASSIFY 0
|
||||
|
||||
// GNU libstdc++ 3
|
||||
#elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
|
||||
# if (defined(__USE_ISOC99) || defined(_GLIBCXX_USE_C99_MATH)) && \
|
||||
!(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
|
||||
# define BOOST_HASH_USE_FPCLASSIFY 1
|
||||
# else
|
||||
# define BOOST_HASH_USE_FPCLASSIFY 0
|
||||
# endif
|
||||
|
||||
// Everything else
|
||||
#else
|
||||
# define BOOST_HASH_USE_FPCLASSIFY 0
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
inline void hash_float_combine(std::size_t& seed, std::size_t value)
|
||||
{
|
||||
seed ^= value + (seed<<6) + (seed>>2);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Binary hash function
|
||||
//
|
||||
// Only used for floats with known iec559 floats, and certain values in
|
||||
// numeric_limits
|
||||
|
||||
inline std::size_t hash_binary(char* ptr, std::size_t length)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
|
||||
if (length >= sizeof(std::size_t)) {
|
||||
std::memcpy(&seed, ptr, sizeof(std::size_t));
|
||||
length -= sizeof(std::size_t);
|
||||
ptr += sizeof(std::size_t);
|
||||
|
||||
while(length >= sizeof(std::size_t)) {
|
||||
std::size_t buffer = 0;
|
||||
std::memcpy(&buffer, ptr, sizeof(std::size_t));
|
||||
hash_float_combine(seed, buffer);
|
||||
length -= sizeof(std::size_t);
|
||||
ptr += sizeof(std::size_t);
|
||||
}
|
||||
}
|
||||
|
||||
if (length > 0) {
|
||||
std::size_t buffer = 0;
|
||||
std::memcpy(&buffer, ptr, length);
|
||||
hash_float_combine(seed, buffer);
|
||||
}
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
template <typename Float, unsigned digits, unsigned max_exponent>
|
||||
struct enable_binary_hash
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value =
|
||||
std::numeric_limits<Float>::is_iec559 &&
|
||||
std::numeric_limits<Float>::digits == digits &&
|
||||
std::numeric_limits<Float>::radix == 2 &&
|
||||
std::numeric_limits<Float>::max_exponent == max_exponent);
|
||||
};
|
||||
|
||||
template <typename Float>
|
||||
inline std::size_t float_hash_impl(Float v,
|
||||
BOOST_DEDUCED_TYPENAME boost::enable_if_c<
|
||||
enable_binary_hash<Float, 24, 128>::value,
|
||||
std::size_t>::type)
|
||||
{
|
||||
return hash_binary((char*) &v, 4);
|
||||
}
|
||||
|
||||
|
||||
template <typename Float>
|
||||
inline std::size_t float_hash_impl(Float v,
|
||||
BOOST_DEDUCED_TYPENAME boost::enable_if_c<
|
||||
enable_binary_hash<Float, 53, 1024>::value,
|
||||
std::size_t>::type)
|
||||
{
|
||||
return hash_binary((char*) &v, 8);
|
||||
}
|
||||
|
||||
template <typename Float>
|
||||
inline std::size_t float_hash_impl(Float v,
|
||||
BOOST_DEDUCED_TYPENAME boost::enable_if_c<
|
||||
enable_binary_hash<Float, 64, 16384>::value,
|
||||
std::size_t>::type)
|
||||
{
|
||||
return hash_binary((char*) &v, 10);
|
||||
}
|
||||
|
||||
template <typename Float>
|
||||
inline std::size_t float_hash_impl(Float v,
|
||||
BOOST_DEDUCED_TYPENAME boost::enable_if_c<
|
||||
enable_binary_hash<Float, 113, 16384>::value,
|
||||
std::size_t>::type)
|
||||
{
|
||||
return hash_binary((char*) &v, 16);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Portable hash function
|
||||
//
|
||||
// Used as a fallback when the binary hash function isn't supported.
|
||||
|
||||
template <class T>
|
||||
inline std::size_t float_hash_impl2(T v)
|
||||
{
|
||||
boost::hash_detail::call_frexp<T> frexp;
|
||||
boost::hash_detail::call_ldexp<T> ldexp;
|
||||
|
||||
int exp = 0;
|
||||
|
||||
v = frexp(v, &exp);
|
||||
|
||||
// A postive value is easier to hash, so combine the
|
||||
// sign with the exponent and use the absolute value.
|
||||
if(v < 0) {
|
||||
v = -v;
|
||||
exp += limits<T>::max_exponent -
|
||||
limits<T>::min_exponent;
|
||||
}
|
||||
|
||||
v = ldexp(v, limits<std::size_t>::digits);
|
||||
std::size_t seed = static_cast<std::size_t>(v);
|
||||
v -= static_cast<T>(seed);
|
||||
|
||||
// ceiling(digits(T) * log2(radix(T))/ digits(size_t)) - 1;
|
||||
std::size_t const length
|
||||
= (limits<T>::digits *
|
||||
boost::static_log2<limits<T>::radix>::value
|
||||
+ limits<std::size_t>::digits - 1)
|
||||
/ limits<std::size_t>::digits;
|
||||
|
||||
for(std::size_t i = 0; i != length; ++i)
|
||||
{
|
||||
v = ldexp(v, limits<std::size_t>::digits);
|
||||
std::size_t part = static_cast<std::size_t>(v);
|
||||
v -= static_cast<T>(part);
|
||||
hash_float_combine(seed, part);
|
||||
}
|
||||
|
||||
hash_float_combine(seed, static_cast<std::size_t>(exp));
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_HASH_DETAIL_TEST_WITHOUT_GENERIC)
|
||||
template <class T>
|
||||
inline std::size_t float_hash_impl(T v, ...)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME select_hash_type<T>::type type;
|
||||
return float_hash_impl2(static_cast<type>(v));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if BOOST_HASH_USE_FPCLASSIFY
|
||||
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
template <class T>
|
||||
inline std::size_t float_hash_value(T v)
|
||||
{
|
||||
#if defined(fpclassify)
|
||||
switch (fpclassify(v))
|
||||
#elif BOOST_HASH_CONFORMANT_FLOATS
|
||||
switch (std::fpclassify(v))
|
||||
#else
|
||||
using namespace std;
|
||||
switch (fpclassify(v))
|
||||
#endif
|
||||
{
|
||||
case FP_ZERO:
|
||||
return 0;
|
||||
case FP_INFINITE:
|
||||
return (std::size_t)(v > 0 ? -1 : -2);
|
||||
case FP_NAN:
|
||||
return (std::size_t)(-3);
|
||||
case FP_NORMAL:
|
||||
case FP_SUBNORMAL:
|
||||
return float_hash_impl(v, 0);
|
||||
default:
|
||||
BOOST_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else // !BOOST_HASH_USE_FPCLASSIFY
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
template <class T>
|
||||
inline bool is_zero(T v)
|
||||
{
|
||||
#if !defined(__GNUC__) && !defined(__clang__)
|
||||
return v == 0;
|
||||
#else
|
||||
// GCC's '-Wfloat-equal' will complain about comparing
|
||||
// v to 0, but because it disables warnings for system
|
||||
// headers it won't complain if you use std::equal_to to
|
||||
// compare with 0. Resulting in this silliness:
|
||||
return std::equal_to<T>()(v, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline std::size_t float_hash_value(T v)
|
||||
{
|
||||
return boost::hash_detail::is_zero(v) ? 0 : float_hash_impl(v, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BOOST_HASH_USE_FPCLASSIFY
|
||||
|
||||
#undef BOOST_HASH_USE_FPCLASSIFY
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
133
include/boost/container_hash/detail/hash_tuple.hpp
Normal file
133
include/boost/container_hash/detail/hash_tuple.hpp
Normal file
@@ -0,0 +1,133 @@
|
||||
// Copyright 2005-2009 Daniel James.
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP
|
||||
#define BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP
|
||||
|
||||
#include <boost/container_hash/hash_fwd.hpp>
|
||||
#include <boost/type_traits/enable_if.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
|
||||
// no support
|
||||
|
||||
#else
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
|
||||
template <std::size_t I, typename T>
|
||||
inline typename boost::enable_if_<(I == std::tuple_size<T>::value),
|
||||
void>::type
|
||||
hash_combine_tuple(std::size_t&, T const&)
|
||||
{
|
||||
}
|
||||
|
||||
template <std::size_t I, typename T>
|
||||
inline typename boost::enable_if_<(I < std::tuple_size<T>::value),
|
||||
void>::type
|
||||
hash_combine_tuple(std::size_t& seed, T const& v)
|
||||
{
|
||||
boost::hash_combine(seed, std::get<I>(v));
|
||||
boost::hash_detail::hash_combine_tuple<I + 1>(seed, v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::size_t hash_tuple(T const& v)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
boost::hash_detail::hash_combine_tuple<0>(seed, v);
|
||||
return seed;
|
||||
}
|
||||
|
||||
} // namespace hash_detail
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
template <typename... T>
|
||||
inline std::size_t hash_value(std::tuple<T...> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline std::size_t hash_value(std::tuple<> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0>
|
||||
inline std::size_t hash_value(std::tuple<A0> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7, A8> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7, A8, A9> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #if defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
|
||||
#endif // #ifndef BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP
|
||||
81
include/boost/container_hash/detail/is_contiguous_range.hpp
Normal file
81
include/boost/container_hash/detail/is_contiguous_range.hpp
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright 2017, 2018 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_HASH_DETAIL_IS_CONTIGUOUS_RANGE_HPP_INCLUDED
|
||||
#define BOOST_HASH_DETAIL_IS_CONTIGUOUS_RANGE_HPP_INCLUDED
|
||||
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC, < 40700)
|
||||
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/type_traits/declval.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
|
||||
template<class It, class T, class S>
|
||||
integral_constant< bool, is_same<typename std::iterator_traits<It>::value_type, T>::value && is_integral<S>::value >
|
||||
is_contiguous_range_check( It first, It last, T const*, T const*, S );
|
||||
|
||||
template<class T> decltype( is_contiguous_range_check( declval<T const&>().begin(), declval<T const&>().end(), declval<T const&>().data(), declval<T const&>().data() + declval<T const&>().size(), declval<T const&>().size() ) ) is_contiguous_range_( int );
|
||||
template<class T> false_type is_contiguous_range_( ... );
|
||||
|
||||
template<class T> struct is_contiguous_range: decltype( hash_detail::is_contiguous_range_<T>( 0 ) )
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace hash_detail
|
||||
} // namespace boost
|
||||
|
||||
#else // !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR)
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
#include <array>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
|
||||
template<class T> struct is_contiguous_range: false_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class E, class T, class A> struct is_contiguous_range< std::basic_string<E, T, A> >: true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class E, class T, class A> struct is_contiguous_range< std::basic_string<E, T, A> const >: true_type
|
||||
{
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
|
||||
template<class T, std::size_t N> struct is_contiguous_range< std::array<T, N> >: true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T, std::size_t N> struct is_contiguous_range< std::array<T, N> const >: true_type
|
||||
{
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace hash_detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR)
|
||||
|
||||
#endif // #ifndef BOOST_HASH_DETAIL_IS_CONTIGUOUS_RANGE_HPP_INCLUDED
|
||||
57
include/boost/container_hash/detail/is_range.hpp
Normal file
57
include/boost/container_hash/detail/is_range.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright 2017 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_HASH_DETAIL_IS_RANGE_HPP_INCLUDED
|
||||
#define BOOST_HASH_DETAIL_IS_RANGE_HPP_INCLUDED
|
||||
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/type_traits/declval.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC, < 40700)
|
||||
|
||||
template<class T, class It>
|
||||
integral_constant< bool, !is_same<typename remove_cv<T>::type, typename std::iterator_traits<It>::value_type>::value >
|
||||
is_range_check( It first, It last );
|
||||
|
||||
template<class T> decltype( is_range_check<T>( declval<T const&>().begin(), declval<T const&>().end() ) ) is_range_( int );
|
||||
template<class T> false_type is_range_( ... );
|
||||
|
||||
template<class T> struct is_range: decltype( is_range_<T>( 0 ) )
|
||||
{
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template<class T, class E = true_type> struct is_range_: false_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T> struct is_range_< T, integral_constant< bool,
|
||||
is_same<typename T::value_type, typename std::iterator_traits<typename T::const_iterator>::value_type>::value &&
|
||||
is_integral<typename T::size_type>::value
|
||||
> >: true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T> struct is_range: is_range_<T>
|
||||
{
|
||||
};
|
||||
|
||||
#endif // !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR)
|
||||
|
||||
} // namespace hash_detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_HASH_DETAIL_IS_RANGE_HPP_INCLUDED
|
||||
34
include/boost/container_hash/detail/is_unordered_range.hpp
Normal file
34
include/boost/container_hash/detail/is_unordered_range.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright 2017 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_HASH_DETAIL_IS_UNORDERED_RANGE_HPP_INCLUDED
|
||||
#define BOOST_HASH_DETAIL_IS_UNORDERED_RANGE_HPP_INCLUDED
|
||||
|
||||
#include <boost/container_hash/detail/is_range.hpp>
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
|
||||
template<class T, class E = true_type> struct has_hasher_: false_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T> struct has_hasher_< T, integral_constant< bool,
|
||||
is_same<typename T::hasher, typename T::hasher>::value
|
||||
> >: true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T> struct is_unordered_range: integral_constant< bool, is_range<T>::value && has_hasher_<T>::value >
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace hash_detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_HASH_DETAIL_IS_UNORDERED_RANGE_HPP_INCLUDED
|
||||
@@ -1,28 +1,11 @@
|
||||
|
||||
// Copyright 2005-2009 Daniel James.
|
||||
// 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)
|
||||
//
|
||||
// On some platforms std::limits gives incorrect values for long double.
|
||||
// This tries to work around them.
|
||||
|
||||
#if !defined(BOOST_FUNCTIONAL_HASH_DETAIL_LIMITS_HEADER)
|
||||
#ifndef BOOST_FUNCTIONAL_HASH_DETAIL_LIMITS_HEADER
|
||||
#define BOOST_FUNCTIONAL_HASH_DETAIL_LIMITS_HEADER
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/limits.hpp>
|
||||
|
||||
// On OpenBSD, numeric_limits is not reliable for long doubles, but
|
||||
// the macros defined in <float.h> are and support long double when STLport
|
||||
// doesn't.
|
||||
|
||||
#if defined(__OpenBSD__) || defined(_STLP_NO_LONG_DOUBLE)
|
||||
#include <float.h>
|
||||
#endif
|
||||
#include <limits>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
@@ -30,33 +13,7 @@ namespace boost
|
||||
{
|
||||
template <class T>
|
||||
struct limits : std::numeric_limits<T> {};
|
||||
|
||||
#if defined(__OpenBSD__) || defined(_STLP_NO_LONG_DOUBLE)
|
||||
template <>
|
||||
struct limits<long double>
|
||||
: std::numeric_limits<long double>
|
||||
{
|
||||
static long double epsilon() {
|
||||
return LDBL_EPSILON;
|
||||
}
|
||||
|
||||
static long double (max)() {
|
||||
return LDBL_MAX;
|
||||
}
|
||||
|
||||
static long double (min)() {
|
||||
return LDBL_MIN;
|
||||
}
|
||||
|
||||
BOOST_STATIC_CONSTANT(int, digits = LDBL_MANT_DIG);
|
||||
BOOST_STATIC_CONSTANT(int, max_exponent = LDBL_MAX_EXP);
|
||||
BOOST_STATIC_CONSTANT(int, min_exponent = LDBL_MIN_EXP);
|
||||
#if defined(_STLP_NO_LONG_DOUBLE)
|
||||
BOOST_STATIC_CONSTANT(int, radix = FLT_RADIX);
|
||||
#endif
|
||||
};
|
||||
#endif // __OpenBSD__
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // #ifndef BOOST_FUNCTIONAL_HASH_DETAIL_LIMITS_HEADER
|
||||
|
||||
@@ -1,361 +1,10 @@
|
||||
|
||||
// Copyright 2005-2009 Daniel James.
|
||||
// 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)
|
||||
|
||||
// Based on Peter Dimov's proposal
|
||||
// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
|
||||
// issue 6.18.
|
||||
|
||||
// This implements the extensions to the standard.
|
||||
// It's undocumented, so you shouldn't use it....
|
||||
|
||||
#if !defined(BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP)
|
||||
#ifndef BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP
|
||||
#define BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/detail/container_fwd.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
# include <array>
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
# include <tuple>
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
|
||||
#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||
#include <boost/type_traits/is_array.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <class A, class B>
|
||||
std::size_t hash_value(std::pair<A, B> const&);
|
||||
template <class T, class A>
|
||||
std::size_t hash_value(std::vector<T, A> const&);
|
||||
template <class T, class A>
|
||||
std::size_t hash_value(std::list<T, A> const& v);
|
||||
template <class T, class A>
|
||||
std::size_t hash_value(std::deque<T, A> const& v);
|
||||
template <class K, class C, class A>
|
||||
std::size_t hash_value(std::set<K, C, A> const& v);
|
||||
template <class K, class C, class A>
|
||||
std::size_t hash_value(std::multiset<K, C, A> const& v);
|
||||
template <class K, class T, class C, class A>
|
||||
std::size_t hash_value(std::map<K, T, C, A> const& v);
|
||||
template <class K, class T, class C, class A>
|
||||
std::size_t hash_value(std::multimap<K, T, C, A> const& v);
|
||||
|
||||
template <class T>
|
||||
std::size_t hash_value(std::complex<T> const&);
|
||||
|
||||
template <class A, class B>
|
||||
std::size_t hash_value(std::pair<A, B> const& v)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
boost::hash_combine(seed, v.first);
|
||||
boost::hash_combine(seed, v.second);
|
||||
return seed;
|
||||
}
|
||||
|
||||
template <class T, class A>
|
||||
std::size_t hash_value(std::vector<T, A> const& v)
|
||||
{
|
||||
return boost::hash_range(v.begin(), v.end());
|
||||
}
|
||||
|
||||
template <class T, class A>
|
||||
std::size_t hash_value(std::list<T, A> const& v)
|
||||
{
|
||||
return boost::hash_range(v.begin(), v.end());
|
||||
}
|
||||
|
||||
template <class T, class A>
|
||||
std::size_t hash_value(std::deque<T, A> const& v)
|
||||
{
|
||||
return boost::hash_range(v.begin(), v.end());
|
||||
}
|
||||
|
||||
template <class K, class C, class A>
|
||||
std::size_t hash_value(std::set<K, C, A> const& v)
|
||||
{
|
||||
return boost::hash_range(v.begin(), v.end());
|
||||
}
|
||||
|
||||
template <class K, class C, class A>
|
||||
std::size_t hash_value(std::multiset<K, C, A> const& v)
|
||||
{
|
||||
return boost::hash_range(v.begin(), v.end());
|
||||
}
|
||||
|
||||
template <class K, class T, class C, class A>
|
||||
std::size_t hash_value(std::map<K, T, C, A> const& v)
|
||||
{
|
||||
return boost::hash_range(v.begin(), v.end());
|
||||
}
|
||||
|
||||
template <class K, class T, class C, class A>
|
||||
std::size_t hash_value(std::multimap<K, T, C, A> const& v)
|
||||
{
|
||||
return boost::hash_range(v.begin(), v.end());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::size_t hash_value(std::complex<T> const& v)
|
||||
{
|
||||
boost::hash<T> hasher;
|
||||
std::size_t seed = hasher(v.imag());
|
||||
seed ^= hasher(v.real()) + (seed<<6) + (seed>>2);
|
||||
return seed;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
template <class T, std::size_t N>
|
||||
std::size_t hash_value(std::array<T, N> const& v)
|
||||
{
|
||||
return boost::hash_range(v.begin(), v.end());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
|
||||
namespace hash_detail {
|
||||
template <std::size_t I, typename T>
|
||||
inline typename boost::enable_if_c<(I == std::tuple_size<T>::value),
|
||||
void>::type
|
||||
hash_combine_tuple(std::size_t&, T const&)
|
||||
{
|
||||
}
|
||||
|
||||
template <std::size_t I, typename T>
|
||||
inline typename boost::enable_if_c<(I < std::tuple_size<T>::value),
|
||||
void>::type
|
||||
hash_combine_tuple(std::size_t& seed, T const& v)
|
||||
{
|
||||
boost::hash_combine(seed, std::get<I>(v));
|
||||
boost::hash_detail::hash_combine_tuple<I + 1>(seed, v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::size_t hash_tuple(T const& v)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
boost::hash_detail::hash_combine_tuple<0>(seed, v);
|
||||
return seed;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <typename... T>
|
||||
inline std::size_t hash_value(std::tuple<T...> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
#else
|
||||
|
||||
inline std::size_t hash_value(std::tuple<> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0>
|
||||
inline std::size_t hash_value(std::tuple<A0> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7, A8> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
template<typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
|
||||
inline std::size_t hash_value(std::tuple<A0, A1, A2, A3, A4, A5, A6, A7, A8, A9> const& v)
|
||||
{
|
||||
return boost::hash_detail::hash_tuple(v);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_SMART_PTR)
|
||||
template <typename T>
|
||||
inline std::size_t hash_value(std::shared_ptr<T> const& x) {
|
||||
return boost::hash_value(x.get());
|
||||
}
|
||||
|
||||
template <typename T, typename Deleter>
|
||||
inline std::size_t hash_value(std::unique_ptr<T, Deleter> const& x) {
|
||||
return boost::hash_value(x.get());
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// call_hash_impl
|
||||
//
|
||||
|
||||
// On compilers without function template ordering, this deals with arrays.
|
||||
|
||||
#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||
namespace hash_detail
|
||||
{
|
||||
template <bool IsArray>
|
||||
struct call_hash_impl
|
||||
{
|
||||
template <class T>
|
||||
struct inner
|
||||
{
|
||||
static std::size_t call(T const& v)
|
||||
{
|
||||
using namespace boost;
|
||||
return hash_value(v);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct call_hash_impl<true>
|
||||
{
|
||||
template <class Array>
|
||||
struct inner
|
||||
{
|
||||
static std::size_t call(Array const& v)
|
||||
{
|
||||
const int size = sizeof(v) / sizeof(*v);
|
||||
return boost::hash_range(v, v + size);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct call_hash
|
||||
: public call_hash_impl<boost::is_array<T>::value>
|
||||
::BOOST_NESTED_TEMPLATE inner<T>
|
||||
{
|
||||
};
|
||||
}
|
||||
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
|
||||
//
|
||||
// boost::hash
|
||||
//
|
||||
|
||||
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
|
||||
template <class T> struct hash
|
||||
: boost::hash_detail::hash_base<T>
|
||||
{
|
||||
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||
std::size_t operator()(T const& val) const
|
||||
{
|
||||
return hash_value(val);
|
||||
}
|
||||
#else
|
||||
std::size_t operator()(T const& val) const
|
||||
{
|
||||
return hash_detail::call_hash<T>::call(val);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#if BOOST_WORKAROUND(__DMC__, <= 0x848)
|
||||
template <class T, unsigned int n> struct hash<T[n]>
|
||||
: boost::hash_detail::hash_base<T[n]>
|
||||
{
|
||||
std::size_t operator()(const T* val) const
|
||||
{
|
||||
return boost::hash_range(val, val+n);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
// On compilers without partial specialization, boost::hash<T>
|
||||
// has already been declared to deal with pointers, so just
|
||||
// need to supply the non-pointer version of hash_impl.
|
||||
|
||||
namespace hash_detail
|
||||
{
|
||||
template <bool IsPointer>
|
||||
struct hash_impl;
|
||||
|
||||
template <>
|
||||
struct hash_impl<false>
|
||||
{
|
||||
template <class T>
|
||||
struct inner
|
||||
: boost::hash_detail::hash_base<T>
|
||||
{
|
||||
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||
std::size_t operator()(T const& val) const
|
||||
{
|
||||
return hash_value(val);
|
||||
}
|
||||
#else
|
||||
std::size_t operator()(T const& val) const
|
||||
{
|
||||
return hash_detail::call_hash<T>::call(val);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
};
|
||||
}
|
||||
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // #ifndef BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,23 +1,13 @@
|
||||
|
||||
// Copyright 2005-2009 Daniel James.
|
||||
// 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)
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
// Based on Peter Dimov's proposal
|
||||
// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
|
||||
// issue 6.18.
|
||||
|
||||
#if !defined(BOOST_FUNCTIONAL_HASH_FWD_HPP)
|
||||
#ifndef BOOST_FUNCTIONAL_HASH_FWD_HPP
|
||||
#define BOOST_FUNCTIONAL_HASH_FWD_HPP
|
||||
|
||||
#include <boost/config/workaround.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <class T> struct hash;
|
||||
@@ -27,10 +17,8 @@ namespace boost
|
||||
template <class It> std::size_t hash_range(It, It);
|
||||
template <class It> void hash_range(std::size_t&, It, It);
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551))
|
||||
template <class T> inline std::size_t hash_range(T*, T*);
|
||||
template <class T> inline void hash_range(std::size_t&, T*, T*);
|
||||
#endif
|
||||
template <class It> std::size_t hash_unordered_range(It, It);
|
||||
template <class It> void hash_unordered_range(std::size_t&, It, It);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // #ifndef BOOST_FUNCTIONAL_HASH_FWD_HPP
|
||||
|
||||
11
test/CMakeLists.txt
Normal file
11
test/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
# Copyright 2018, 2019, 2021 Peter Dimov
|
||||
# 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
|
||||
|
||||
include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST)
|
||||
|
||||
if(HAVE_BOOST_TEST)
|
||||
|
||||
boost_test_jamfile(FILE Jamfile.v2 LINK_LIBRARIES Boost::container_hash Boost::core Boost::utility)
|
||||
|
||||
endif()
|
||||
137
test/Jamfile.v2
137
test/Jamfile.v2
@@ -1,88 +1,83 @@
|
||||
|
||||
# Copyright 2005-2012 Daniel James.
|
||||
# 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)
|
||||
# Copyright 2022 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
import testing ;
|
||||
|
||||
local gcc-flags = -Wunused-parameter -Wconversion -Wsign-conversion -Wfloat-equal -Wshadow -Wno-variadic-macros ;
|
||||
local clang-flags = $(gcc-flags) -Wno-c99-extensions ;
|
||||
|
||||
project hash-tests
|
||||
: requirements
|
||||
<warnings>pedantic
|
||||
<toolset>intel:<warnings>on
|
||||
<toolset>gcc:<cxxflags>"-Wstrict-aliasing -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
|
||||
<toolset>darwin:<cxxflags>"-Wstrict-aliasing -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
|
||||
<toolset>clang:<cxxflags>"-Wstrict-aliasing -Wsign-promo -Wunused-parameter -Wsign-conversion -Wconversion -Wfloat-equal -Wshadow"
|
||||
<toolset>gcc:<cxxflags>$(gcc-flags)
|
||||
<toolset>darwin:<cxxflags>$(gcc-flags)
|
||||
<toolset>clang:<cxxflags>$(clang-flags)
|
||||
<toolset>msvc:<warnings-as-errors>on
|
||||
<toolset>gcc:<warnings-as-errors>on
|
||||
<toolset>clang:<warnings-as-errors>on
|
||||
;
|
||||
|
||||
test-suite container_hash/hash
|
||||
:
|
||||
[ run hash_info.cpp : : : <test-info>always_show_run_output ]
|
||||
[ compile check_float_funcs.cpp ]
|
||||
[ run hash_fwd_test_1.cpp ]
|
||||
[ run hash_fwd_test_2.cpp ]
|
||||
[ run hash_number_test.cpp ]
|
||||
[ run hash_enum_test.cpp ]
|
||||
[ run hash_pointer_test.cpp ]
|
||||
[ run hash_function_pointer_test.cpp ]
|
||||
[ run hash_float_test.cpp ]
|
||||
[ run hash_long_double_test.cpp ]
|
||||
[ run hash_string_test.cpp ]
|
||||
[ run hash_range_test.cpp ]
|
||||
[ run hash_custom_test.cpp ]
|
||||
[ run hash_global_namespace_test.cpp ]
|
||||
[ run hash_friend_test.cpp ]
|
||||
[ run hash_built_in_array_test.cpp ]
|
||||
[ run hash_value_array_test.cpp ]
|
||||
[ run hash_vector_test.cpp ]
|
||||
[ run hash_list_test.cpp ]
|
||||
[ run hash_deque_test.cpp ]
|
||||
[ run hash_set_test.cpp ]
|
||||
[ run hash_map_test.cpp ]
|
||||
[ run hash_complex_test.cpp ]
|
||||
[ run hash_optional_test.cpp ]
|
||||
[ run hash_variant_test.cpp ]
|
||||
[ run hash_type_index_test.cpp ]
|
||||
[ run hash_system_error_test.cpp ]
|
||||
[ run hash_std_array_test.cpp ]
|
||||
[ run hash_std_tuple_test.cpp ]
|
||||
[ run hash_std_smart_ptr_test.cpp ]
|
||||
[ run link_test.cpp link_test_2.cpp ]
|
||||
[ run link_ext_test.cpp link_no_ext_test.cpp ]
|
||||
[ run extensions_hpp_test.cpp ]
|
||||
[ compile-fail hash_no_ext_fail_test.cpp ]
|
||||
[ compile-fail namespace_fail_test.cpp ]
|
||||
[ run implicit_test.cpp ]
|
||||
[ run hash_no_ext_macro_1.cpp ]
|
||||
[ run hash_no_ext_macro_2.cpp ]
|
||||
;
|
||||
|
||||
test-suite container_hash/hash_no_ext
|
||||
:
|
||||
[ run hash_number_test.cpp : : : <define>BOOST_HASH_NO_EXTENSIONS : no_ext_number_test ]
|
||||
[ run hash_pointer_test.cpp : : : <define>BOOST_HASH_NO_EXTENSIONS : no_ext_pointer_test ]
|
||||
[ run hash_function_pointer_test.cpp : : : <define>BOOST_HASH_NO_EXTENSIONS : no_ext_function_pointer_test ]
|
||||
[ run hash_float_test.cpp : : : <define>BOOST_HASH_NO_EXTENSIONS : no_ext_float_test ]
|
||||
[ run hash_long_double_test.cpp : : : <define>BOOST_HASH_NO_EXTENSIONS : no_ext_long_double_test ]
|
||||
[ run hash_string_test.cpp : : : <define>BOOST_HASH_NO_EXTENSIONS : no_ext_string_test ]
|
||||
[ run link_test.cpp link_test_2.cpp : : : <define>BOOST_HASH_NO_EXTENSIONS : no_ext_link_test ]
|
||||
;
|
||||
|
||||
# Tests to see if the floating point hash is using the binary hash.
|
||||
# Not run normally because on some platforms these should fail.
|
||||
test-suite container_hash/hash_no_generic_float
|
||||
:
|
||||
[ run hash_float_test.cpp
|
||||
: : : <define>BOOST_HASH_DETAIL_TEST_WITHOUT_GENERIC
|
||||
: hash_float_test_no_generic ]
|
||||
[ run hash_long_double_test.cpp
|
||||
: : : <define>BOOST_HASH_DETAIL_TEST_WITHOUT_GENERIC
|
||||
: hash_long_double_test_no_generic ]
|
||||
;
|
||||
explicit container_hash/hash_no_generic_float ;
|
||||
run hash_info.cpp : : : <test-info>always_show_run_output ;
|
||||
compile check_float_funcs.cpp ;
|
||||
run hash_fwd_test_1.cpp ;
|
||||
run hash_fwd_test_2.cpp ;
|
||||
run hash_number_test.cpp ;
|
||||
run hash_enum_test.cpp ;
|
||||
run hash_pointer_test.cpp ;
|
||||
run hash_function_pointer_test.cpp ;
|
||||
run hash_float_test.cpp ;
|
||||
run hash_long_double_test.cpp ;
|
||||
run hash_string_test.cpp ;
|
||||
run hash_range_test.cpp ;
|
||||
run hash_custom_test.cpp ;
|
||||
run hash_global_namespace_test.cpp ;
|
||||
run hash_friend_test.cpp ;
|
||||
run hash_built_in_array_test.cpp ;
|
||||
run hash_value_array_test.cpp ;
|
||||
run hash_vector_test.cpp ;
|
||||
run hash_list_test.cpp ;
|
||||
run hash_deque_test.cpp ;
|
||||
run hash_set_test.cpp ;
|
||||
run hash_map_test.cpp ;
|
||||
run hash_complex_test.cpp ;
|
||||
run hash_optional_test.cpp ;
|
||||
run hash_variant_test.cpp ;
|
||||
run hash_type_index_test.cpp ;
|
||||
run hash_system_error_test.cpp ;
|
||||
run hash_std_array_test.cpp ;
|
||||
run hash_std_tuple_test.cpp ;
|
||||
run hash_std_smart_ptr_test.cpp ;
|
||||
run link_test.cpp link_test_2.cpp ;
|
||||
run link_ext_test.cpp link_no_ext_test.cpp ;
|
||||
run extensions_hpp_test.cpp ;
|
||||
compile-fail namespace_fail_test.cpp ;
|
||||
run implicit_test.cpp ;
|
||||
run hash_no_ext_macro_1.cpp ;
|
||||
run hash_no_ext_macro_2.cpp ;
|
||||
|
||||
build-project ../examples ;
|
||||
|
||||
run hash_reference_values.cpp ;
|
||||
|
||||
run detail_is_range_test.cpp ;
|
||||
run detail_is_contiguous_range_test.cpp ;
|
||||
run detail_is_unordered_range_test.cpp ;
|
||||
|
||||
run hash_forward_list_test.cpp ;
|
||||
|
||||
run quick.cpp ;
|
||||
|
||||
run hash_number_test2.cpp ;
|
||||
run hash_integral_test.cpp ;
|
||||
run hash_string_test2.cpp ;
|
||||
|
||||
# for gcc-4.8
|
||||
local fs-path-req = "-<toolset>gcc:<cxxflags>-Wshadow" "-<toolset>gcc:<cxxflags>-Wconversion" ;
|
||||
|
||||
run hash_fs_path_test.cpp /boost//filesystem/<warnings>off : : : $(fs-path-req) <toolset>msvc-14.0,<cxxstd>latest:<build>no ;
|
||||
run detail_is_range_test2.cpp : : : $(fs-path-req) ;
|
||||
|
||||
run hash_container_test.cpp ;
|
||||
|
||||
17
test/cmake_install_test/CMakeLists.txt
Normal file
17
test/cmake_install_test/CMakeLists.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
# Copyright 2018, 2019, 2021 Peter Dimov
|
||||
# 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
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.20)
|
||||
|
||||
project(cmake_install_test LANGUAGES CXX)
|
||||
|
||||
find_package(boost_container_hash REQUIRED)
|
||||
|
||||
add_executable(quick ../quick.cpp)
|
||||
target_link_libraries(quick Boost::container_hash)
|
||||
|
||||
enable_testing()
|
||||
add_test(quick quick)
|
||||
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $<CONFIG>)
|
||||
21
test/cmake_subdir_test/CMakeLists.txt
Normal file
21
test/cmake_subdir_test/CMakeLists.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
# Copyright 2018, 2019, 2021 Peter Dimov
|
||||
# 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
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.20)
|
||||
|
||||
project(cmake_subdir_test LANGUAGES CXX)
|
||||
|
||||
add_subdirectory(../.. boostorg/container_hash)
|
||||
|
||||
add_subdirectory(../../../config boostorg/config)
|
||||
add_subdirectory(../../../type_traits boostorg/type_traits)
|
||||
add_subdirectory(../../../static_assert boostorg/static_assert)
|
||||
|
||||
add_executable(quick ../quick.cpp)
|
||||
target_link_libraries(quick Boost::container_hash)
|
||||
|
||||
enable_testing()
|
||||
add_test(quick quick)
|
||||
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $<CONFIG>)
|
||||
101
test/detail_is_contiguous_range_test.cpp
Normal file
101
test/detail_is_contiguous_range_test.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright 2017, 2018 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/container_hash/detail/is_contiguous_range.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
# include <array>
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
# include <forward_list>
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
|
||||
# include <unordered_set>
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
|
||||
# include <unordered_map>
|
||||
#endif
|
||||
|
||||
struct X
|
||||
{
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
using boost::hash_detail::is_contiguous_range;
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<void>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<void const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<int>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<int const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<X>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<X const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<int[2]>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range<int const[2]>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_contiguous_range<std::string>));
|
||||
BOOST_TEST_TRAIT_TRUE((is_contiguous_range<std::string const>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_contiguous_range<std::wstring>));
|
||||
BOOST_TEST_TRAIT_TRUE((is_contiguous_range<std::wstring const>));
|
||||
|
||||
// std::vector doesn't have data() in C++03
|
||||
#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC, < 40700)
|
||||
BOOST_TEST_TRAIT_TRUE((is_contiguous_range< std::vector<X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_contiguous_range< std::vector<X> const >));
|
||||
#endif
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::deque<X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::deque<X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::set<int> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::set<int> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::multiset<int> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::multiset<int> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::map<int, X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::map<int, X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::multimap<int, X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::multimap<int, X> const >));
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
BOOST_TEST_TRAIT_TRUE((is_contiguous_range< std::array<X, 2> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_contiguous_range< std::array<X, 2> const >));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::forward_list<X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::forward_list<X> const >));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_set<int> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_set<int> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_multiset<int> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_multiset<int> const >));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_map<int, X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_map<int, X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_multimap<int, X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_contiguous_range< std::unordered_multimap<int, X> const >));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
98
test/detail_is_range_test.cpp
Normal file
98
test/detail_is_range_test.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright 2017 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/container_hash/detail/is_range.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
# include <array>
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
# include <forward_list>
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
|
||||
# include <unordered_set>
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
|
||||
# include <unordered_map>
|
||||
#endif
|
||||
|
||||
struct X
|
||||
{
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
using boost::hash_detail::is_range;
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_range<void>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_range<void const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_range<int>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_range<int const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_range<X>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_range<X const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_range<int[2]>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_range<int const[2]>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range<std::string>));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range<std::string const>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range<std::wstring>));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range<std::wstring const>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::vector<X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::vector<X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::deque<X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::deque<X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::set<int> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::set<int> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::multiset<int> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::multiset<int> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::map<int, X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::map<int, X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::multimap<int, X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::multimap<int, X> const >));
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::array<X, 2> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::array<X, 2> const >));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::forward_list<X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::forward_list<X> const >));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_set<int> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_set<int> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_multiset<int> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_multiset<int> const >));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_map<int, X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_map<int, X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_multimap<int, X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_range< std::unordered_multimap<int, X> const >));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
37
test/detail_is_range_test2.cpp
Normal file
37
test/detail_is_range_test2.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright 2022 Peter Dimov
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(disable: 4714) // forceinline not inlined
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
#include <boost/container_hash/detail/is_range.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_CXX17_HDR_FILESYSTEM) && !defined(__MINGW32__)
|
||||
# include <filesystem>
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
using boost::hash_detail::is_range;
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_range< boost::filesystem::path >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_range< boost::filesystem::path const >));
|
||||
|
||||
#if !defined(BOOST_NO_CXX17_HDR_FILESYSTEM) && !defined(__MINGW32__)
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_range< std::filesystem::path >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_range< std::filesystem::path const >));
|
||||
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
98
test/detail_is_unordered_range_test.cpp
Normal file
98
test/detail_is_unordered_range_test.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright 2017 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/container_hash/detail/is_unordered_range.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
# include <array>
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
# include <forward_list>
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
|
||||
# include <unordered_set>
|
||||
#endif
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
|
||||
# include <unordered_map>
|
||||
#endif
|
||||
|
||||
struct X
|
||||
{
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
using boost::hash_detail::is_unordered_range;
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<void>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<void const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<int>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<int const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<X>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<X const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<int[2]>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<int const[2]>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<std::string>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<std::string const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<std::wstring>));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range<std::wstring const>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::vector<X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::vector<X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::deque<X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::deque<X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::set<int> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::set<int> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::multiset<int> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::multiset<int> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::map<int, X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::map<int, X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::multimap<int, X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::multimap<int, X> const >));
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_ARRAY)
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::array<X, 2> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::array<X, 2> const >));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::forward_list<X> >));
|
||||
BOOST_TEST_TRAIT_FALSE((is_unordered_range< std::forward_list<X> const >));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
|
||||
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_set<int> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_set<int> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_multiset<int> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_multiset<int> const >));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP)
|
||||
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_map<int, X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_map<int, X> const >));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_multimap<int, X> >));
|
||||
BOOST_TEST_TRAIT_TRUE((is_unordered_range< std::unordered_multimap<int, X> const >));
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -29,6 +29,7 @@ int main() {}
|
||||
// 'const std::complex<float>::_Ty'
|
||||
#pragma warning(disable:4309) // truncation of constant value
|
||||
#pragma warning(disable:4512) // assignment operator could not be generated
|
||||
#pragma warning(disable:4996) // std::complex<Integer> is deprecated
|
||||
#if BOOST_MSVC < 1400
|
||||
#pragma warning(disable:4267) // conversion from 'size_t' to 'unsigned int',
|
||||
// possible loss of data
|
||||
@@ -39,9 +40,10 @@ int main() {}
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#endif
|
||||
|
||||
#include <boost/limits.hpp>
|
||||
#include <complex>
|
||||
#include <sstream>
|
||||
#include <boost/limits.hpp>
|
||||
#include <set>
|
||||
|
||||
template <class T>
|
||||
void generic_complex_tests(std::complex<T> v)
|
||||
@@ -88,6 +90,21 @@ void complex_integral_tests(Integer*)
|
||||
generic_complex_tests(complex(Integer(-543),Integer(763)));
|
||||
}
|
||||
|
||||
template<class T> void complex_grid_test( short N )
|
||||
{
|
||||
std::set<std::size_t> hashes;
|
||||
|
||||
for( short i = 0; i < N; ++i )
|
||||
{
|
||||
for( short j = 0; j < N; ++j )
|
||||
{
|
||||
hashes.insert( boost::hash< std::complex<T> >()( std::complex<T>( i, j ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_TEST_EQ( hashes.size(), static_cast<std::size_t>( N * N ) );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// I've comments out the short and unsigned short tests
|
||||
@@ -104,6 +121,11 @@ int main()
|
||||
complex_integral_tests((unsigned int*) 0);
|
||||
complex_integral_tests((unsigned long*) 0);
|
||||
|
||||
complex_grid_test<int>( 16 );
|
||||
complex_grid_test<float>( 7 );
|
||||
complex_grid_test<double>( 16 );
|
||||
complex_grid_test<long double>( 15 );
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
52
test/hash_container_test.cpp
Normal file
52
test/hash_container_test.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2022 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
# include <forward_list>
|
||||
#endif
|
||||
|
||||
template<class T> std::size_t hv( T const& t )
|
||||
{
|
||||
return boost::hash<T>()( t );
|
||||
}
|
||||
|
||||
template<class T> void test()
|
||||
{
|
||||
for( std::size_t i = 0; i < 8; ++i )
|
||||
{
|
||||
std::vector<T> v( i );
|
||||
std::size_t h0 = hv( v );
|
||||
|
||||
std::deque<T> d( v.begin(), v.end() );
|
||||
BOOST_TEST_EQ( h0, hv( d ) );
|
||||
|
||||
std::list<T> l( v.begin(), v.end() );
|
||||
BOOST_TEST_EQ( h0, hv( l ) );
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
|
||||
std::forward_list<T> f( v.begin(), v.end() );
|
||||
BOOST_TEST_EQ( h0, hv( f ) );
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test<char>();
|
||||
test<unsigned char>();
|
||||
test<signed char>();
|
||||
test<int>();
|
||||
test<float>();
|
||||
test<double>();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <boost/container_hash/detail/limits.hpp>
|
||||
#include <boost/container_hash/detail/float_functions.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
|
||||
#include <iostream>
|
||||
@@ -55,19 +54,6 @@ void float_tests(char const* name, T* = 0)
|
||||
<< boost::hash_detail::limits<std::size_t>::digits
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
<< "boost::hash_detail::call_ldexp<T>::float_type = "
|
||||
<< float_type(static_cast<BOOST_DEDUCED_TYPENAME
|
||||
boost::hash_detail::call_ldexp<T>::float_type*>(0))
|
||||
<< "\n"
|
||||
<< "boost::hash_detail::call_frexp<T>::float_type = "
|
||||
<< float_type(static_cast<BOOST_DEDUCED_TYPENAME
|
||||
boost::hash_detail::call_frexp<T>::float_type*>(0))
|
||||
<< "\n"
|
||||
<< "boost::hash_detail::select_hash_type<T>::type = "
|
||||
<< float_type(static_cast<BOOST_DEDUCED_TYPENAME
|
||||
boost::hash_detail::select_hash_type<T>::type*>(0))
|
||||
<< "\n"
|
||||
<< "\n"
|
||||
;
|
||||
|
||||
BOOST_HASH_TEST_NAMESPACE::hash<T> x1;
|
||||
|
||||
59
test/hash_forward_list_test.cpp
Normal file
59
test/hash_forward_list_test.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 8
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
|
||||
#if defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
|
||||
BOOST_PRAGMA_MESSAGE( "Test skipped, BOOST_NO_CXX11_HDR_FORWARD_LIST is defined" )
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
#include <forward_list>
|
||||
|
||||
template<class T> void test()
|
||||
{
|
||||
typedef std::forward_list<T> list;
|
||||
typedef boost::hash<list> hash;
|
||||
|
||||
int const N = 32;
|
||||
|
||||
std::size_t h[ N ];
|
||||
|
||||
list v;
|
||||
|
||||
for( int i = 0; i < N; ++i )
|
||||
{
|
||||
h[ i ] = hash()( v );
|
||||
|
||||
BOOST_TEST_EQ( h[ i ], hash()( v ) );
|
||||
|
||||
for( int j = 0; j < i; ++j )
|
||||
{
|
||||
BOOST_TEST_NE( h[ j ], h[ i ] );
|
||||
}
|
||||
|
||||
v.push_front( T() );
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test<int>();
|
||||
test<float>();
|
||||
test<double>();
|
||||
test< std::forward_list<int> >();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#endif
|
||||
30
test/hash_fs_path_test.cpp
Normal file
30
test/hash_fs_path_test.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright 2022 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(disable: 4714) // forceinline not inlined
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
template<class T> std::size_t hv( T const& t )
|
||||
{
|
||||
return boost::hash<T>()( t );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::filesystem::path p1( "/foo/bar" );
|
||||
boost::filesystem::path p2( "/foo/baz" );
|
||||
|
||||
BOOST_TEST_NE( hv( p1 ), hv( p2 ) );
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <climits>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
|
||||
@@ -37,10 +39,9 @@ void write_compiler_info() {
|
||||
{1700, "Visual C++ 11.0, VS2012"},
|
||||
{1800, "Visual C++ 12.0, VS2013"},
|
||||
{1900, "Visual C++ 14.00, VS2015"},
|
||||
{1910, "Visual C++ 14.10, VS2017 15.1/2"},
|
||||
{1911, "Visual C++ 14.11, VS2017 15.3/4"},
|
||||
{1912, "Visual C++ 14.12, VS2017 15.5"},
|
||||
{1913, "Visual C++ 14.13, VS2017 15.6"}
|
||||
{1910, "Visual C++ 14.1x, VS2017"},
|
||||
{1920, "Visual C++ 14.2x, VS2019"},
|
||||
{1930, "Visual C++ 14.3x, VS2022"},
|
||||
};
|
||||
|
||||
msvc_version msvc = { BOOST_MSVC, "" };
|
||||
@@ -62,41 +63,62 @@ void write_compiler_info() {
|
||||
|
||||
#endif
|
||||
|
||||
#define PRINT(x) std::cout << #x ": " << x << std::endl
|
||||
|
||||
int main() {
|
||||
write_compiler_info();
|
||||
std::cout << std::endl;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
std::cout << "__cplusplus: "
|
||||
<< __cplusplus
|
||||
<< std::endl;
|
||||
PRINT(__cplusplus);
|
||||
PRINT(BOOST_CXX_VERSION);
|
||||
std::cout << std::endl;
|
||||
|
||||
#if defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
|
||||
std::cout << "No <string_view>" << std::endl;
|
||||
#else
|
||||
std::cout << "Has <string_view>" << std::endl;
|
||||
#endif
|
||||
|
||||
std::cout << "BOOST_HASH_CXX17: "
|
||||
<< BOOST_HASH_CXX17
|
||||
<< std::endl;
|
||||
#if defined(BOOST_NO_CXX17_HDR_OPTIONAL)
|
||||
std::cout << "No <optional>" << std::endl;
|
||||
#else
|
||||
std::cout << "Has <optional>" << std::endl;
|
||||
#endif
|
||||
|
||||
std::cout << "BOOST_HASH_HAS_STRING_VIEW: "
|
||||
<< BOOST_HASH_HAS_STRING_VIEW
|
||||
<< std::endl;
|
||||
|
||||
std::cout << "BOOST_HASH_HAS_OPTIONAL: "
|
||||
<< BOOST_HASH_HAS_OPTIONAL
|
||||
<< std::endl;
|
||||
|
||||
std::cout << "BOOST_HASH_HAS_VARIANT: "
|
||||
<< BOOST_HASH_HAS_VARIANT
|
||||
<< std::endl;
|
||||
#if defined(BOOST_NO_CXX17_HDR_VARIANT)
|
||||
std::cout << "No <variant>" << std::endl;
|
||||
#else
|
||||
std::cout << "Has <variant>" << std::endl;
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
|
||||
std::cout << "No <typeindex>" << std::endl;
|
||||
#else
|
||||
std::cout << "<typeindex>" << std::endl;
|
||||
std::cout << "Has <typeindex>" << std::endl;
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR)
|
||||
std::cout << "No <system_error>" << std::endl;
|
||||
#else
|
||||
std::cout << "<system_error>" << std::endl;
|
||||
std::cout << "Has <system_error>" << std::endl;
|
||||
#endif
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
PRINT(CHAR_BIT);
|
||||
std::cout << std::endl;
|
||||
|
||||
PRINT(sizeof(std::size_t)*CHAR_BIT);
|
||||
std::cout << std::endl;
|
||||
|
||||
PRINT(sizeof(float)*CHAR_BIT);
|
||||
PRINT(std::numeric_limits<float>::digits);
|
||||
std::cout << std::endl;
|
||||
|
||||
PRINT(sizeof(double)*CHAR_BIT);
|
||||
PRINT(std::numeric_limits<double>::digits);
|
||||
std::cout << std::endl;
|
||||
|
||||
PRINT(sizeof(long double)*CHAR_BIT);
|
||||
PRINT(std::numeric_limits<long double>::digits);
|
||||
}
|
||||
|
||||
75
test/hash_integral_test.cpp
Normal file
75
test/hash_integral_test.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright 2005-2009 Daniel James.
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/type_name.hpp>
|
||||
#include <boost/type_traits/is_signed.hpp>
|
||||
#include <set>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(disable: 4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
// This test checks that small numbers hash to themselves even if
|
||||
// their type is wider than size_t
|
||||
|
||||
template<class T>
|
||||
void identity_test()
|
||||
{
|
||||
if( boost::is_signed<T>::value )
|
||||
{
|
||||
for( int i = -128; i <= 127; ++i )
|
||||
{
|
||||
BOOST_TEST_EQ( boost::hash<T>()( static_cast<T>( i ) ), static_cast<std::size_t>( i ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i <= 255; ++i )
|
||||
{
|
||||
BOOST_TEST_EQ( boost::hash<T>()( static_cast<T>( i ) ), static_cast<std::size_t>( i ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define TEST(type) std::cerr << "Testing: " #type " (" << boost::core::type_name<type>() << ")\n"; identity_test<type>();
|
||||
|
||||
int main()
|
||||
{
|
||||
TEST(char)
|
||||
TEST(signed char)
|
||||
TEST(unsigned char)
|
||||
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
|
||||
TEST(wchar_t)
|
||||
#endif
|
||||
#ifndef BOOST_NO_CXX11_CHAR16_T
|
||||
TEST(char16_t)
|
||||
#endif
|
||||
#ifndef BOOST_NO_CXX11_CHAR32_T
|
||||
TEST(char32_t)
|
||||
#endif
|
||||
TEST(short)
|
||||
TEST(unsigned short)
|
||||
TEST(int)
|
||||
TEST(unsigned int)
|
||||
TEST(long)
|
||||
TEST(unsigned long)
|
||||
|
||||
#if !defined(BOOST_NO_LONG_LONG)
|
||||
TEST(boost::long_long_type)
|
||||
TEST(boost::ulong_long_type)
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_INT128)
|
||||
TEST(boost::int128_type)
|
||||
TEST(boost::uint128_type)
|
||||
#endif
|
||||
|
||||
TEST(std::size_t)
|
||||
TEST(std::ptrdiff_t)
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -13,6 +13,11 @@
|
||||
#pragma warning(disable:4245) // signed/unsigned mismatch
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 8
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
namespace HASH_TEST_CAT(CONTAINER_TYPE, _tests)
|
||||
{
|
||||
template <class T>
|
||||
@@ -66,6 +71,10 @@ namespace HASH_TEST_CAT(CONTAINER_TYPE, _tests)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 8
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
|
||||
// Copyright 2006-2009 Daniel James.
|
||||
// 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)
|
||||
|
||||
#include "./config.hpp"
|
||||
|
||||
// Simple test to make sure BOOST_HASH_NO_EXTENSIONS does disable extensions
|
||||
// (or at least one of them).
|
||||
#if !defined(BOOST_HASH_NO_EXTENSIONS)
|
||||
# define BOOST_HASH_NO_EXTENSIONS
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HASH_TEST_STD_INCLUDES
|
||||
# include <functional>
|
||||
#else
|
||||
# include <boost/container_hash/hash.hpp>
|
||||
#endif
|
||||
|
||||
template <class T> void ignore(T const&) {}
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_HASH_TEST_NAMESPACE::hash< int[10] > hasher;
|
||||
ignore(hasher);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -103,10 +103,8 @@ void limits_test(T*)
|
||||
|
||||
if (limits::is_integer)
|
||||
{
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(min_value)
|
||||
== std::size_t(min_value));
|
||||
BOOST_TEST(BOOST_HASH_TEST_NAMESPACE::hash_value(max_value)
|
||||
== std::size_t(max_value));
|
||||
BOOST_TEST_EQ(BOOST_HASH_TEST_NAMESPACE::hash_value(min_value), std::size_t(min_value));
|
||||
BOOST_TEST_EQ(BOOST_HASH_TEST_NAMESPACE::hash_value(max_value), std::size_t(max_value));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
90
test/hash_number_test2.cpp
Normal file
90
test/hash_number_test2.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
// Copyright 2005-2009 Daniel James.
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/type_name.hpp>
|
||||
#include <set>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(disable: 4244) // conversion from int to float
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# pragma GCC diagnostic ignored "-Wconversion"
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
// This test checks for collisions in a small range of numbers
|
||||
|
||||
template<class T, int M>
|
||||
void collision_test_()
|
||||
{
|
||||
std::set<std::size_t> hashes;
|
||||
|
||||
for( int i = -128; i <= 127; ++i )
|
||||
{
|
||||
hashes.insert( boost::hash<T>()( i * M ) );
|
||||
}
|
||||
|
||||
BOOST_TEST_EQ( hashes.size(), 256u );
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void collision_test()
|
||||
{
|
||||
collision_test_<T, 1>();
|
||||
collision_test_<T, 2>();
|
||||
collision_test_<T, 3>();
|
||||
collision_test_<T, 4>();
|
||||
collision_test_<T, 5>();
|
||||
collision_test_<T, 8>();
|
||||
collision_test_<T, 10>();
|
||||
collision_test_<T, 16>();
|
||||
collision_test_<T, 32>();
|
||||
collision_test_<T, 64>();
|
||||
collision_test_<T, 100>();
|
||||
collision_test_<T, 128>();
|
||||
}
|
||||
|
||||
#define TEST(type) std::cerr << "Testing: " #type " (" << boost::core::type_name<type>() << ")\n"; collision_test<type>();
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
|
||||
TEST(wchar_t)
|
||||
#endif
|
||||
#ifndef BOOST_NO_CXX11_CHAR16_T
|
||||
TEST(char16_t)
|
||||
#endif
|
||||
#ifndef BOOST_NO_CXX11_CHAR32_T
|
||||
TEST(char32_t)
|
||||
#endif
|
||||
TEST(short)
|
||||
TEST(unsigned short)
|
||||
TEST(int)
|
||||
TEST(unsigned int)
|
||||
TEST(long)
|
||||
TEST(unsigned long)
|
||||
|
||||
#if !defined(BOOST_NO_LONG_LONG)
|
||||
TEST(boost::long_long_type)
|
||||
TEST(boost::ulong_long_type)
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_INT128)
|
||||
TEST(boost::int128_type)
|
||||
TEST(boost::uint128_type)
|
||||
#endif
|
||||
|
||||
TEST(float)
|
||||
TEST(double)
|
||||
TEST(long double)
|
||||
|
||||
TEST(std::size_t)
|
||||
TEST(std::ptrdiff_t)
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#if BOOST_HASH_HAS_OPTIONAL
|
||||
#if !defined(BOOST_NO_CXX17_HDR_OPTIONAL)
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
@@ -60,7 +60,7 @@ void test_optional_string()
|
||||
|
||||
int main()
|
||||
{
|
||||
#if BOOST_HASH_HAS_OPTIONAL
|
||||
#if !defined(BOOST_NO_CXX17_HDR_OPTIONAL)
|
||||
test_optional_int();
|
||||
test_optional_string();
|
||||
#else
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#define _SILENCE_NONFLOATING_COMPLEX_DEPRECATION_WARNING
|
||||
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__) && __cplusplus < 201100L
|
||||
@@ -15,6 +17,10 @@ int main() {}
|
||||
# pragma clang diagnostic ignored "-Wlong-long"
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <string>
|
||||
@@ -152,24 +158,9 @@ int main()
|
||||
BOOST_TEST_EQ( hv(-1e-38f), 2154619886U );
|
||||
BOOST_TEST_EQ( hv(1e+38f), 2123789977U );
|
||||
BOOST_TEST_EQ( hv(-1e+38f), 4271273625U );
|
||||
|
||||
#if !defined(__GLIBCXX__)
|
||||
|
||||
BOOST_TEST_EQ( hv(std::numeric_limits<float>::infinity()), 2139095040U );
|
||||
BOOST_TEST_EQ( hv(-std::numeric_limits<float>::infinity()), 4286578688U );
|
||||
|
||||
#elif SIZE_MAX == 4294967295U
|
||||
|
||||
BOOST_TEST_EQ( hv(std::numeric_limits<float>::infinity()), 4294967295U );
|
||||
BOOST_TEST_EQ( hv(-std::numeric_limits<float>::infinity()), 4294967294U );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(std::numeric_limits<float>::infinity()), 18446744073709551615ULL );
|
||||
BOOST_TEST_EQ( hv(-std::numeric_limits<float>::infinity()), 18446744073709551614ULL );
|
||||
|
||||
#endif
|
||||
|
||||
// double
|
||||
BOOST_TEST_EQ( hv(0.0), 0 );
|
||||
BOOST_TEST_EQ( hv(-0.0), 0 );
|
||||
@@ -184,19 +175,9 @@ int main()
|
||||
BOOST_TEST_EQ( hv(-1e-308), 3701356376U );
|
||||
BOOST_TEST_EQ( hv(1e+308), 2577739707U );
|
||||
BOOST_TEST_EQ( hv(-1e+308), 430256059U );
|
||||
|
||||
#if !defined(__GLIBCXX__)
|
||||
|
||||
BOOST_TEST_EQ( hv(std::numeric_limits<double>::infinity()), 2146435072U );
|
||||
BOOST_TEST_EQ( hv(-std::numeric_limits<double>::infinity()), 4293918720U );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(std::numeric_limits<double>::infinity()), 4294967295U );
|
||||
BOOST_TEST_EQ( hv(-std::numeric_limits<double>::infinity()), 4294967294U );
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(1.0), 4607182418800017408ULL );
|
||||
@@ -207,19 +188,9 @@ int main()
|
||||
BOOST_TEST_EQ( hv(-1e-308), 9225396059387848914ULL );
|
||||
BOOST_TEST_EQ( hv(1e+308), 9214871658872686752ULL );
|
||||
BOOST_TEST_EQ( hv(-1e+308), 18438243695727462560ULL );
|
||||
|
||||
#if !defined(__GLIBCXX__)
|
||||
|
||||
BOOST_TEST_EQ( hv(std::numeric_limits<double>::infinity()), 9218868437227405312ULL );
|
||||
BOOST_TEST_EQ( hv(-std::numeric_limits<double>::infinity()), 18442240474082181120ULL );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(std::numeric_limits<double>::infinity()), 18446744073709551615ULL );
|
||||
BOOST_TEST_EQ( hv(-std::numeric_limits<double>::infinity()), 18446744073709551614ULL );
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// long double
|
||||
@@ -256,38 +227,18 @@ int main()
|
||||
BOOST_TEST_EQ( hv(-1.0L), 2684403711U );
|
||||
BOOST_TEST_EQ( hv(3.14L), 83002659U );
|
||||
BOOST_TEST_EQ( hv(-3.14L), 82969891U );
|
||||
|
||||
#if !defined(__GLIBCXX__)
|
||||
|
||||
BOOST_TEST_EQ( hv(std::numeric_limits<long double>::infinity()), 0xA0007FFFu );
|
||||
BOOST_TEST_EQ( hv(-std::numeric_limits<long double>::infinity()), 0xA000FFFFu );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(std::numeric_limits<long double>::infinity()), 4294967295U );
|
||||
BOOST_TEST_EQ( hv(-std::numeric_limits<long double>::infinity()), 4294967294U );
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(1.0L), 11529215046068486143ULL );
|
||||
BOOST_TEST_EQ( hv(-1.0L), 11529215046068518911ULL );
|
||||
BOOST_TEST_EQ( hv(3.14L), 12059468778148142067ULL );
|
||||
BOOST_TEST_EQ( hv(-3.14L), 12059468778147191795ULL );
|
||||
|
||||
#if !defined(__GLIBCXX__)
|
||||
|
||||
BOOST_TEST_EQ( hv(std::numeric_limits<long double>::infinity()), 11529215046068502527ULL );
|
||||
BOOST_TEST_EQ( hv(-std::numeric_limits<long double>::infinity()), 11529215046068535295ULL );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_EQ( hv(std::numeric_limits<long double>::infinity()), 18446744073709551615ULL );
|
||||
BOOST_TEST_EQ( hv(-std::numeric_limits<long double>::infinity()), 18446744073709551614ULL );
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
#pragma warning(disable:4245) // signed/unsigned mismatch
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 8
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
namespace HASH_TEST_CAT(CONTAINER_TYPE, _tests)
|
||||
{
|
||||
template <class T>
|
||||
@@ -68,6 +73,10 @@ namespace HASH_TEST_CAT(CONTAINER_TYPE, _tests)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 8
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
#pragma warning(disable:4245) // signed/unsigned mismatch
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 8
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
namespace HASH_TEST_CAT(CONTAINER_TYPE, _tests)
|
||||
{
|
||||
template <class T>
|
||||
@@ -71,6 +76,10 @@ namespace HASH_TEST_CAT(CONTAINER_TYPE, _tests)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ == 8
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
@@ -176,7 +176,7 @@ int main()
|
||||
#endif
|
||||
|
||||
generic_string_tests((std::string*) 0);
|
||||
#if BOOST_HASH_HAS_STRING_VIEW
|
||||
#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
|
||||
generic_string_tests((std::string_view*) 0);
|
||||
#endif
|
||||
|
||||
|
||||
51
test/hash_string_test2.cpp
Normal file
51
test/hash_string_test2.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright 2022 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/utility/string_view.hpp>
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
|
||||
#include <string_view>
|
||||
#endif
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
# include <forward_list>
|
||||
#endif
|
||||
|
||||
// Test whether the hash values of a string and a
|
||||
// string_view that refers to it match. This is
|
||||
// important for unordered heterogeneous lookups.
|
||||
|
||||
template<class T> std::size_t hv( T const& t )
|
||||
{
|
||||
return boost::hash<T>()( t );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::string s( "Test." );
|
||||
std::size_t h0 = hv( s );
|
||||
|
||||
BOOST_TEST_EQ( h0, hv( boost::string_view( s ) ) );
|
||||
BOOST_TEST_EQ( h0, hv( boost::core::string_view( s ) ) );
|
||||
|
||||
#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
|
||||
BOOST_TEST_EQ( h0, hv( std::string_view( s ) ) );
|
||||
#endif
|
||||
|
||||
BOOST_TEST_EQ( h0, hv( std::vector<char>( s.begin(), s.end() ) ) );
|
||||
BOOST_TEST_EQ( h0, hv( std::deque<char>( s.begin(), s.end() ) ) );
|
||||
BOOST_TEST_EQ( h0, hv( std::list<char>( s.begin(), s.end() ) ) );
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
|
||||
BOOST_TEST_EQ( h0, hv( std::forward_list<char>( s.begin(), s.end() ) ) );
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
#if BOOST_HASH_HAS_VARIANT
|
||||
#if !defined(BOOST_NO_CXX17_HDR_VARIANT)
|
||||
|
||||
#include <variant>
|
||||
#include <string>
|
||||
@@ -90,7 +90,7 @@ void test_variant_unique_types()
|
||||
|
||||
int main()
|
||||
{
|
||||
#if BOOST_HASH_HAS_VARIANT
|
||||
#if !defined(BOOST_NO_CXX17_HDR_VARIANT)
|
||||
test_variant_int();
|
||||
test_variant_unique_types();
|
||||
#else
|
||||
|
||||
17
test/quick.cpp
Normal file
17
test/quick.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2006-2009 Daniel James.
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <deque>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::deque<int> x;
|
||||
|
||||
x.push_back( 1 );
|
||||
x.push_back( 2 );
|
||||
|
||||
return boost::hash< std::deque<int> >()( x ) == boost::hash_value( x )? 0: 1;
|
||||
}
|
||||
Reference in New Issue
Block a user