Compare commits

...

57 Commits

Author SHA1 Message Date
016d255851 Rework as esp-idf component 2023-11-23 17:17:05 +01:00
6b87a43162 Update benchmarking diagrams based on new erase(iterator) implementation 2022-07-27 08:29:03 -07:00
a4c6bf90aa Merge pull request #138 from cmazakas/feature/erase-perf
erase(iterator) perf
2022-07-27 14:41:07 +03:00
a31e894411 Update implementation to use erase_node() where applicable 2022-07-25 11:35:38 -07:00
91e78fd746 Add erase_node() function to table, creating an optimizer-friendly function 2022-07-25 11:35:23 -07:00
3abe5de533 Switch from macos-10.15 (deprecated) to macos-11 2022-07-22 20:44:54 +03:00
dfa3c7311f Remove unnecessary RNG 2022-07-22 19:12:39 +03:00
2c5b8577aa Add tsl::robin_map to string.cpp 2022-07-22 19:10:50 +03:00
4e804a9d4d Add tsl::robin_map to uint64.cpp, string_view.cpp 2022-07-22 18:52:47 +03:00
0ca8c5f56f Add tsl::robin_map to uint32.cpp 2022-07-22 18:36:50 +03:00
912798e5cb Change uint64.cpp to use byteswapped indices instead of shifted indices 2022-07-22 18:22:34 +03:00
5bcdd7fdf0 Change uint32.cpp to use byteswapped indices instead of shifted indices 2022-07-22 18:18:35 +03:00
78ffc4c192 Fix tsl allocator 2022-07-01 19:32:19 +03:00
966b76182f Add tsl::hopscotch_map to string_view.cpp 2022-07-01 19:28:57 +03:00
b7101494f2 Add tsl::hopscotch_map to string.cpp 2022-07-01 19:15:28 +03:00
be467b3dc4 Add tsl::hopscotch_map to uint64.cpp 2022-07-01 19:03:52 +03:00
ee70d96c75 Add tsl::hopscotch_map to uint32.cpp 2022-07-01 18:48:10 +03:00
8fbd380879 Merge pull request #136 from cmazakas/feature/prime-fmod-cleanup
`prime_fmod_size` cleanup
2022-07-01 17:58:38 +03:00
7746518c0a Remove conditional usage of #pragma once from fca.hpp and prime_fmod.hpp, reorder config.hpp inclusion to come last 2022-06-30 13:07:11 -07:00
c8a98e27e0 Add boost:: namespace qualification to uint64_t and uint32_t for prime_fmod.hpp 2022-06-30 13:07:11 -07:00
3df902af23 Pull prime_fmod_size into its own dedicated header, update #include list for fca.hpp and prime_fmod_test.hpp 2022-06-30 13:07:11 -07:00
45542e26cb Update ci.yml 2022-06-30 12:29:47 +03:00
49f73b118c Update .appveyor.yml 2022-06-30 05:23:44 +03:00
6e3dcfddb0 Merge branch 'feature/gha' into develop 2022-06-28 14:19:00 +03:00
09088045ac Merge pull request #135 from boostorg/bugfix/gcc-4-6-is_nothrow_swappable
bypassed check in GCC<=4.6 (boost::is_nothrow_swappable not properly …
2022-06-28 10:09:02 +02:00
e466232757 bypassed check in GCC<=4.6 (boost::is_nothrow_swappable not properly supported) 2022-06-28 09:27:15 +02:00
2ccd6654c1 Update ci.yml 2022-06-28 03:29:35 +03:00
7d7a6b881e Merge pull request #134 from boostorg/bugfix/gcc-4-7
Bugfix/gcc 4 7
2022-06-27 21:48:25 +02:00
9661227d00 Merge remote-tracking branch 'remotes/origin/bugfix/gcc-4-7-scoped_allocator' into bugfix/gcc-4-7 2022-06-27 20:39:07 +02:00
5855c67d4d added Drone support to this branch 2022-06-27 20:35:59 +02:00
3edfe2b76f Merge branch 'develop' into bugfix/gcc-4-7-scoped_allocator 2022-06-27 20:35:27 +02:00
f36bfe24f6 added Drone support to this branch 2022-06-27 20:35:01 +02:00
9da4b3a45a Merge branch 'develop' into bugfix/gcc-4-7-ref-qualified_memfuns 2022-06-27 20:34:06 +02:00
95524a6af4 bypassed scoped_allocator test for GCC 4.7 and prior 2022-06-27 19:58:22 +02:00
d4b61541b5 used proper Boost.Config macro 2022-06-27 19:31:47 +02:00
143c378ba6 Update test/Jamfile 2022-06-27 20:24:25 +03:00
dfac93aebb workaround for lack of ref-qualified memfun support in GCC<=4.7 2022-06-27 19:21:34 +02:00
b6daca37d5 Update test/Jamfile 2022-06-27 19:56:22 +03:00
4937619ea0 Update .drone.jsonnet 2022-06-27 19:55:23 +03:00
6d34532301 Add Drone support 2022-06-27 18:53:36 +03:00
fb733483c6 made fast_modulo universally available in 64 bits and never used in 32 bits 2022-06-26 19:13:54 +02:00
2670bb149d added Peter Dimov's portable implementation of get_remainder 2022-06-25 17:35:43 +02:00
d49eda63f8 Merge branch 'feature/prime-fmod-tests' into develop 2022-06-25 04:21:20 +03:00
08e0fee141 Enable fastmod on clang-cl and other pretenders such as Intel 2022-06-25 01:44:14 +03:00
d204b9b408 Remove unnecessary include 2022-06-25 01:17:50 +03:00
c53e0228c5 Check BOOST_UNORDERED_FCA_HAS_64B_SIZE_T in the 32 bit case as well 2022-06-25 01:16:32 +03:00
31cffd8412 Fix reversed condition 2022-06-25 01:06:15 +03:00
0f71fe28a2 Fix typos; do not undefine macros needed for tests 2022-06-25 01:04:22 +03:00
f00a29d3df Add tests for the internal prime_fmod_size policy 2022-06-24 11:09:38 -07:00
e111389d6c Update .appveyor.yml 2022-06-24 01:03:53 +03:00
7079341416 Merge pull request #130 from cmazakas/bugfix/cmake-subdir-dependencies
Update the list of required dependencies for the subdir CML test
2022-06-23 03:53:02 +03:00
7fdbfc0c1a Update the list of required dependencies in for the CMake subdirectory test 2022-06-22 14:42:09 -07:00
e1dff1c931 Merge pull request #128 from cmazakas/feature/iterator-independence
Remove dependencies on Iterator, Detail
2022-06-21 21:45:12 +03:00
90b2536a99 Relace usage of BOOST_FORCEINLINE with plain inline to prevent warnings from certain versions of msvc 2022-06-21 08:42:52 -07:00
97f54318e3 Add Boost::concept_check to CMake test suite dependencies 2022-06-21 08:42:52 -07:00
f1481f0deb Remove dependency on Boost.Detail 2022-06-21 08:42:52 -07:00
b1a9cde690 Remove dependency on Boost.Iterator 2022-06-21 08:42:52 -07:00
68 changed files with 1307 additions and 483 deletions

View File

@ -40,52 +40,11 @@ environment:
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
B2_TOOLSET: msvc-12.0,msvc-14.0
- FLAVOR: Visual Studio 2017 C++14/17
- FLAVOR: Visual Studio 2017
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
B2_CXXSTD: 14,17
B2_CXXSTD: 14,17,latest
B2_TOOLSET: msvc-14.1
- FLAVOR: Visual Studio 2017 C++2a Strict
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
B2_CXXFLAGS: -permissive-
B2_CXXSTD: 2a
B2_TOOLSET: msvc-14.1
- FLAVOR: Visual Studio 2019
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
B2_CXXFLAGS: -permissive-
B2_CXXSTD: 14,17
B2_TOOLSET: msvc-14.2
- FLAVOR: Visual Studio 2022
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
B2_CXXFLAGS: -permissive-
B2_CXXSTD: 14,17
B2_TOOLSET: msvc-14.3
# C++20 Jobs split out from above due to build timeout
- FLAVOR: Visual Studio 2019 C++2a
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
B2_CXXFLAGS: -permissive-
B2_CXXSTD: 2a
B2_TOOLSET: msvc-14.2
- FLAVOR: Visual Studio 2022 C++20
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
B2_CXXFLAGS: -permissive-
B2_CXXSTD: 20
B2_TOOLSET: msvc-14.3
- FLAVOR: clang-cl C++11, C++14
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
B2_CXXSTD: 11,14
B2_TOOLSET: clang-win
# Extra job as compilation takes to long
- FLAVOR: clang-cl C++17, C++latest
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
B2_CXXSTD: 17,latest
B2_TOOLSET: clang-win
- FLAVOR: cygwin (32-bit)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
ADDPATH: C:\cygwin\bin;
@ -100,30 +59,35 @@ environment:
B2_CXXSTD: 03,11,14,1z
B2_TOOLSET: gcc
# (Currently) the images up to 2017 use an older Cygwin
# This tests that the library works with more recent versions
- FLAVOR: cygwin (64-bit, latest)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
ADDPATH: C:\cygwin64\bin;
B2_ADDRESS_MODEL: 64
B2_CXXSTD: 03,11,14,1z
B2_CXXSTD: 03,11
B2_TOOLSET: gcc
MAYFAIL: true
B2_FLAGS: "include=libs/unordered/test/unordered include=libs/unordered/test/exception"
- FLAVOR: mingw32
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
B2_ADDRESS_MODEL: 32
ADDPATH: C:\mingw\bin;
B2_CXXSTD: 03,11,14,1z
B2_TOOLSET: gcc
MAYFAIL: true
- FLAVOR: mingw64
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;
- FLAVOR: cygwin (64-bit, latest)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
ADDPATH: C:\cygwin64\bin;
B2_ADDRESS_MODEL: 64
B2_CXXSTD: 14,1z
B2_TOOLSET: gcc
B2_FLAGS: "include=libs/unordered/test/unordered include=libs/unordered/test/exception"
- FLAVOR: mingw-w64, 32 bit
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin;
B2_CXXSTD: 03,11,14,17,2a
B2_TOOLSET: gcc
B2_ADDRESS_MODEL: 32
- FLAVOR: mingw-w64, 64 bit
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;
B2_CXXSTD: 03,11,14,17,2a
B2_TOOLSET: gcc
B2_ADDRESS_MODEL: 64
#- FLAVOR: CodeCov (VS 2019)
# APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019

180
.drone.jsonnet Normal file
View File

@ -0,0 +1,180 @@
# Copyright 2022 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
local library = "unordered";
local triggers =
{
branch: [ "master", "develop", "feature/*", "bugfix/*" ]
};
local ubsan = { UBSAN: '1', UBSAN_OPTIONS: 'print_stacktrace=1' };
local asan = { ASAN: '1' };
local linux_pipeline(name, image, environment, packages = "", sources = [], arch = "amd64") =
{
name: name,
kind: "pipeline",
type: "docker",
trigger: triggers,
platform:
{
os: "linux",
arch: arch
},
steps:
[
{
name: "everything",
image: image,
environment: environment,
commands:
[
'set -e',
'wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -',
] +
(if sources != [] then [ ('apt-add-repository "' + source + '"') for source in sources ] else []) +
(if packages != "" then [ 'apt-get update', 'apt-get -y install ' + packages ] else []) +
[
'export LIBRARY=' + library,
'./.drone/drone.sh',
]
}
]
};
local macos_pipeline(name, environment, xcode_version = "12.2", osx_version = "catalina", arch = "amd64") =
{
name: name,
kind: "pipeline",
type: "exec",
trigger: triggers,
platform: {
"os": "darwin",
"arch": arch
},
node: {
"os": osx_version
},
steps: [
{
name: "everything",
environment: environment + { "DEVELOPER_DIR": "/Applications/Xcode-" + xcode_version + ".app/Contents/Developer" },
commands:
[
'export LIBRARY=' + library,
'./.drone/drone.sh',
]
}
]
};
local windows_pipeline(name, image, environment, arch = "amd64") =
{
name: name,
kind: "pipeline",
type: "docker",
trigger: triggers,
platform:
{
os: "windows",
arch: arch
},
"steps":
[
{
name: "everything",
image: image,
environment: environment,
commands:
[
'cmd /C .drone\\\\drone.bat ' + library,
]
}
]
};
[
linux_pipeline(
"Linux 14.04 GCC 4.4 32/64",
"cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-4.4', CXXSTD: '98,0x', ADDRMD: '32,64' },
"g++-4.4-multilib",
[ "ppa:ubuntu-toolchain-r/test" ],
),
linux_pipeline(
"Linux 14.04 GCC 4.6 32/64",
"cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-4.6', CXXSTD: '98,0x', ADDRMD: '32,64' },
"g++-4.6-multilib",
[ "ppa:ubuntu-toolchain-r/test" ],
),
linux_pipeline(
"Linux 14.04 GCC 4.7 32/64",
"cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-4.7', CXXSTD: '98,0x', ADDRMD: '32,64' },
"g++-4.7-multilib",
[ "ppa:ubuntu-toolchain-r/test" ],
),
linux_pipeline(
"Linux 14.04 GCC 4.8* 32/64",
"cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11', ADDRMD: '32,64' },
),
linux_pipeline(
"Linux 14.04 GCC 4.9 32/64",
"cppalliance/droneubuntu1404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-4.9', CXXSTD: '03,11', ADDRMD: '32,64' },
"g++-4.9-multilib",
[ "ppa:ubuntu-toolchain-r/test" ],
),
linux_pipeline(
"Linux 20.04 GCC 9* ARM64 32",
"cppalliance/droneubuntu2004:multiarch",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17,2a', ADDRMD: '32' },
arch="arm64",
),
linux_pipeline(
"Linux 20.04 GCC 9* ARM64 64",
"cppalliance/droneubuntu2004:multiarch",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17,2a', ADDRMD: '64' },
arch="arm64",
),
linux_pipeline(
"Linux 20.04 GCC 9* S390x 32",
"cppalliance/droneubuntu2004:multiarch",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17,2a', ADDRMD: '32' },
arch="s390x",
),
linux_pipeline(
"Linux 20.04 GCC 9* S390x 64",
"cppalliance/droneubuntu2004:multiarch",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '03,11,14,17,2a', ADDRMD: '64' },
arch="s390x",
),
macos_pipeline(
"MacOS 10.15 Xcode 12.2 UBSAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,1z' } + ubsan,
),
macos_pipeline(
"MacOS 10.15 Xcode 12.2 ASAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,1z' } + asan,
),
windows_pipeline(
"Windows VS2017 msvc-14.1",
"cppalliance/dronevs2017",
{ TOOLSET: 'msvc-14.1', CXXSTD: '14,17,latest' },
),
]

23
.drone/drone.bat Normal file
View File

@ -0,0 +1,23 @@
@REM Copyright 2022 Peter Dimov
@REM Distributed under the Boost Software License, Version 1.0.
@REM https://www.boost.org/LICENSE_1_0.txt
@ECHO ON
set LIBRARY=%1
set DRONE_BUILD_DIR=%CD%
set BOOST_BRANCH=develop
if "%DRONE_BRANCH%" == "master" set BOOST_BRANCH=master
cd ..
git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
git submodule update --init tools/boostdep
xcopy /s /e /q %DRONE_BUILD_DIR% libs\%LIBRARY%\
python tools/boostdep/depinst/depinst.py %LIBRARY%
cmd /c bootstrap
b2 -d0 headers
if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
b2 -j3 libs/%LIBRARY%/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release embed-manifest-via=linker

24
.drone/drone.sh Executable file
View File

@ -0,0 +1,24 @@
#!/bin/bash
# Copyright 2022 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
set -ex
DRONE_BUILD_DIR=$(pwd)
BOOST_BRANCH=develop
if [ "$DRONE_BRANCH" = "master" ]; then BOOST_BRANCH=master; fi
cd ..
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
git submodule update --init tools/boostdep
cp -r $DRONE_BUILD_DIR/* libs/$LIBRARY
python tools/boostdep/depinst/depinst.py $LIBRARY
./bootstrap.sh
./b2 -d0 headers
echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam
./b2 -j3 libs/$LIBRARY/test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release ${ADDRMD:+address-model=$ADDRMD} ${UBSAN:+undefined-sanitizer=norecover debug-symbols=on} ${ASAN:+address-sanitizer=norecover debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS}

View File

@ -42,16 +42,16 @@ jobs:
matrix:
include:
# Linux, gcc
- { compiler: gcc-4.8, cxxstd: '03,11', os: ubuntu-18.04 }
- { compiler: gcc-4.8, cxxstd: '03,11', os: ubuntu-18.04, install: 'g++-4.8-multilib', address-model: '32,64' }
- { compiler: gcc-4.9, cxxstd: '03,11', os: ubuntu-20.04, container: 'ubuntu:16.04' }
- { compiler: gcc-5, cxxstd: '03,11,14,1z', os: ubuntu-18.04 }
- { compiler: gcc-6, cxxstd: '03,11,14,17', os: ubuntu-18.04 }
- { compiler: gcc-7, cxxstd: '03,11,14,17', os: ubuntu-18.04 }
- { compiler: gcc-8, cxxstd: '03,11,14,17,2a', os: ubuntu-18.04 }
- { compiler: gcc-9, cxxstd: '03,11,14,17,2a', os: ubuntu-18.04 }
- { compiler: gcc-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 }
- { compiler: gcc-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 }
- { compiler: gcc-12, cxxstd: '03,11,14,17,20', os: ubuntu-22.04 }
- { compiler: gcc-5, cxxstd: '03,11,14,1z', os: ubuntu-18.04, install: 'g++-5-multilib', address-model: '32,64' }
- { compiler: gcc-6, cxxstd: '03,11,14,17', os: ubuntu-18.04, install: 'g++-6-multilib', address-model: '32,64' }
- { compiler: gcc-7, cxxstd: '03,11,14,17', os: ubuntu-18.04, install: 'g++-7-multilib', address-model: '32,64' }
- { compiler: gcc-8, cxxstd: '03,11,14,17,2a', os: ubuntu-18.04, install: 'g++-8-multilib', address-model: '32,64' }
- { compiler: gcc-9, cxxstd: '03,11,14,17,2a', os: ubuntu-18.04, install: 'g++-9-multilib', address-model: '32,64' }
- { compiler: gcc-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04, install: 'g++-10-multilib', address-model: '32,64' }
- { compiler: gcc-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04, install: 'g++-11-multilib', address-model: '32,64' }
- { compiler: gcc-12, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, install: 'g++-12-multilib', address-model: '32,64' }
- { name: GCC w/ sanitizers, sanitize: yes,
compiler: gcc-12, cxxstd: '03,11,14,17,20', os: ubuntu-22.04 }
- { name: Collect coverage, coverage: yes,
@ -65,8 +65,7 @@ jobs:
- { compiler: clang-5.0, cxxstd: '03,11,14,1z', os: ubuntu-18.04 }
- { compiler: clang-6.0, cxxstd: '03,11,14,17', os: ubuntu-18.04 }
- { compiler: clang-7, cxxstd: '03,11,14,17', os: ubuntu-18.04 }
# Note: clang-8 does not fully support C++20, so it is not compatible with some libstdc++ versions in this mode
- { compiler: clang-8, cxxstd: '03,11,14,17,2a', os: ubuntu-18.04, install: 'clang-8 g++-7', gcc_toolchain: 7 }
- { compiler: clang-8, cxxstd: '03,11,14,17', os: ubuntu-18.04 }
- { compiler: clang-9, cxxstd: '03,11,14,17,2a', os: ubuntu-20.04 }
- { compiler: clang-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 }
- { compiler: clang-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 }
@ -81,7 +80,7 @@ jobs:
compiler: clang-12, cxxstd: '03,11,14,17,20', os: ubuntu-20.04, stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev' }
# OSX, clang
- { compiler: clang, cxxstd: '03,11,14,17,2a', os: macos-10.15, sanitize: yes }
- { compiler: clang, cxxstd: '03,11,14,17,2a', os: macos-11, sanitize: yes }
timeout-minutes: 120
runs-on: ${{matrix.os}}
@ -226,11 +225,11 @@ jobs:
fail-fast: false
matrix:
include:
- { toolset: msvc-14.0, cxxstd: '14,latest', addrmd: '32,64', os: windows-2019 }
- { toolset: msvc-14.2, cxxstd: '14,17,20', addrmd: '32,64', os: windows-2019 }
- { toolset: msvc-14.3, cxxstd: '14,17,20,latest',addrmd: '32,64', os: windows-2022 }
- { toolset: clang-win, cxxstd: '14,17,latest', addrmd: '32,64', os: windows-2022 }
- { toolset: gcc, cxxstd: '03,11,14,17,2a', addrmd: '64', os: windows-2019 }
- { toolset: msvc-14.0, cxxstd: '14,latest', addrmd: '32,64', os: windows-2019 }
- { toolset: msvc-14.2, cxxstd: '14,17,20,latest', addrmd: '32,64', os: windows-2019 }
- { toolset: msvc-14.3, cxxstd: '14,17,20,latest', addrmd: '32,64', os: windows-2022 }
- { toolset: clang-win, cxxstd: '14,17,latest', addrmd: '32,64', os: windows-2022 }
- { toolset: gcc, cxxstd: '03,11,14,17,2a', addrmd: '64', os: windows-2019 }
runs-on: ${{matrix.os}}

View File

@ -3,6 +3,8 @@
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
if(NOT DEFINED IDF_TARGET)
cmake_minimum_required(VERSION 3.5...3.20)
project(boost_unordered VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
@ -18,7 +20,6 @@ target_link_libraries(boost_unordered
Boost::config
Boost::container_hash
Boost::core
Boost::iterator
Boost::move
Boost::mp11
Boost::predef
@ -33,3 +34,28 @@ if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
add_subdirectory(test)
endif()
else()
FILE(GLOB_RECURSE headers include/*.h include/*.hpp)
idf_component_register(
SRCS
${headers}
INCLUDE_DIRS
include
REQUIRES
boost_assert
boost_config
boost_container_hash
boost_core
boost_move
boost_mp11
boost_predef
boost_preprocessor
boost_throw_exception
boost_tuple
boost_type_traits
)
endif()

View File

@ -14,6 +14,12 @@
# include "absl/container/node_hash_map.h"
# include "absl/container/flat_hash_map.h"
#endif
#ifdef HAVE_TSL_HOPSCOTCH
# include "tsl/hopscotch_map.h"
#endif
#ifdef HAVE_TSL_ROBIN
# include "tsl/robin_map.h"
#endif
#include <unordered_map>
#include <vector>
#include <memory>
@ -137,7 +143,14 @@ template<class Map> BOOST_NOINLINE void test_iteration( Map& map, std::chrono::s
{
if( it->second & 1 )
{
map.erase( it++ );
if constexpr( std::is_void_v< decltype( map.erase( it ) ) > )
{
map.erase( it++ );
}
else
{
it = map.erase( it );
}
}
else
{
@ -159,13 +172,9 @@ template<class Map> BOOST_NOINLINE void test_erase( Map& map, std::chrono::stead
print_time( t1, "Consecutive erase", 0, map.size() );
for( unsigned i = 1; i <= N; ++i )
{
boost::detail::splitmix64 rng;
for( unsigned i = 1; i <= N; ++i )
{
map.erase( indices2[ i ] );
}
map.erase( indices2[ i ] );
}
print_time( t1, "Random erase", 0, map.size() );
@ -295,6 +304,26 @@ template<class K, class V> using absl_flat_hash_map =
#endif
#ifdef HAVE_TSL_HOPSCOTCH
template<class K, class V> using tsl_hopscotch_map =
tsl::hopscotch_map<K, V, std::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
template<class K, class V> using tsl_hopscotch_pg_map =
tsl::hopscotch_pg_map<K, V, std::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
#endif
#ifdef HAVE_TSL_ROBIN
template<class K, class V> using tsl_robin_map =
tsl::robin_map<K, V, std::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
template<class K, class V> using tsl_robin_pg_map =
tsl::robin_pg_map<K, V, std::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
#endif
// fnv1a_hash
template<int Bits> struct fnv1a_hash_impl;
@ -363,6 +392,26 @@ template<class K, class V> using absl_flat_hash_map_fnv1a =
#endif
#ifdef HAVE_TSL_HOPSCOTCH
template<class K, class V> using tsl_hopscotch_map_fnv1a =
tsl::hopscotch_map<K, V, fnv1a_hash, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
template<class K, class V> using tsl_hopscotch_pg_map_fnv1a =
tsl::hopscotch_pg_map<K, V, fnv1a_hash, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
#endif
#ifdef HAVE_TSL_ROBIN
template<class K, class V> using tsl_robin_map_fnv1a =
tsl::robin_map<K, V, fnv1a_hash, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
template<class K, class V> using tsl_robin_pg_map_fnv1a =
tsl::robin_pg_map<K, V, fnv1a_hash, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
#endif
//
int main()
@ -382,6 +431,20 @@ int main()
#endif
#ifdef HAVE_TSL_HOPSCOTCH
test<tsl_hopscotch_map>( "tsl::hopscotch_map" );
test<tsl_hopscotch_pg_map>( "tsl::hopscotch_pg_map" );
#endif
#ifdef HAVE_TSL_ROBIN
test<tsl_robin_map>( "tsl::robin_map" );
test<tsl_robin_pg_map>( "tsl::robin_pg_map" );
#endif
#endif
test<std_unordered_map_fnv1a>( "std::unordered_map, FNV-1a" );
@ -393,13 +456,27 @@ int main()
test<absl_node_hash_map_fnv1a>( "absl::node_hash_map, FNV-1a" );
test<absl_flat_hash_map_fnv1a>( "absl::flat_hash_map, FNV-1a" );
#endif
#ifdef HAVE_TSL_HOPSCOTCH
test<tsl_hopscotch_map_fnv1a>( "tsl::hopscotch_map, FNV-1a" );
test<tsl_hopscotch_pg_map_fnv1a>( "tsl::hopscotch_pg_map, FNV-1a" );
#endif
#ifdef HAVE_TSL_ROBIN
test<tsl_robin_map_fnv1a>( "tsl::robin_map, FNV-1a" );
test<tsl_robin_pg_map_fnv1a>( "tsl::robin_pg_map, FNV-1a" );
#endif
std::cout << "---\n\n";
for( auto const& x: times )
{
std::cout << std::setw( 30 ) << ( x.label_ + ": " ) << std::setw( 5 ) << x.time_ << " ms, " << std::setw( 9 ) << x.bytes_ << " bytes in " << x.count_ << " allocations\n";
std::cout << std::setw( 31 ) << ( x.label_ + ": " ) << std::setw( 5 ) << x.time_ << " ms, " << std::setw( 9 ) << x.bytes_ << " bytes in " << x.count_ << " allocations\n";
}
}

View File

@ -14,6 +14,12 @@
# include "absl/container/node_hash_map.h"
# include "absl/container/flat_hash_map.h"
#endif
#ifdef HAVE_TSL_HOPSCOTCH
# include "tsl/hopscotch_map.h"
#endif
#ifdef HAVE_TSL_ROBIN
# include "tsl/robin_map.h"
#endif
#include <unordered_map>
#include <string_view>
#include <vector>
@ -138,7 +144,14 @@ template<class Map> BOOST_NOINLINE void test_iteration( Map& map, std::chrono::s
{
if( it->second & 1 )
{
map.erase( it++ );
if constexpr( std::is_void_v< decltype( map.erase( it ) ) > )
{
map.erase( it++ );
}
else
{
it = map.erase( it );
}
}
else
{
@ -160,13 +173,9 @@ template<class Map> BOOST_NOINLINE void test_erase( Map& map, std::chrono::stead
print_time( t1, "Consecutive erase", 0, map.size() );
for( unsigned i = 1; i <= N; ++i )
{
boost::detail::splitmix64 rng;
for( unsigned i = 1; i <= N; ++i )
{
map.erase( indices2[ i ] );
}
map.erase( indices2[ i ] );
}
print_time( t1, "Random erase", 0, map.size() );
@ -296,6 +305,26 @@ template<class K, class V> using absl_flat_hash_map =
#endif
#ifdef HAVE_TSL_HOPSCOTCH
template<class K, class V> using tsl_hopscotch_map =
tsl::hopscotch_map<K, V, std::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
template<class K, class V> using tsl_hopscotch_pg_map =
tsl::hopscotch_pg_map<K, V, std::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
#endif
#ifdef HAVE_TSL_ROBIN
template<class K, class V> using tsl_robin_map =
tsl::robin_map<K, V, std::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
template<class K, class V> using tsl_robin_pg_map =
tsl::robin_pg_map<K, V, std::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
#endif
// fnv1a_hash
template<int Bits> struct fnv1a_hash_impl;
@ -364,6 +393,26 @@ template<class K, class V> using absl_flat_hash_map_fnv1a =
#endif
#ifdef HAVE_TSL_HOPSCOTCH
template<class K, class V> using tsl_hopscotch_map_fnv1a =
tsl::hopscotch_map<K, V, fnv1a_hash, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
template<class K, class V> using tsl_hopscotch_pg_map_fnv1a =
tsl::hopscotch_pg_map<K, V, fnv1a_hash, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
#endif
#ifdef HAVE_TSL_ROBIN
template<class K, class V> using tsl_robin_map_fnv1a =
tsl::robin_map<K, V, fnv1a_hash, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
template<class K, class V> using tsl_robin_pg_map_fnv1a =
tsl::robin_pg_map<K, V, fnv1a_hash, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
#endif
//
int main()
@ -383,6 +432,20 @@ int main()
#endif
#ifdef HAVE_TSL_HOPSCOTCH
test<tsl_hopscotch_map>( "tsl::hopscotch_map" );
test<tsl_hopscotch_pg_map>( "tsl::hopscotch_pg_map" );
#endif
#ifdef HAVE_TSL_ROBIN
test<tsl_robin_map>( "tsl::robin_map" );
test<tsl_robin_pg_map>( "tsl::robin_pg_map" );
#endif
#endif
test<std_unordered_map_fnv1a>( "std::unordered_map, FNV-1a" );
@ -394,13 +457,27 @@ int main()
test<absl_node_hash_map_fnv1a>( "absl::node_hash_map, FNV-1a" );
test<absl_flat_hash_map_fnv1a>( "absl::flat_hash_map, FNV-1a" );
#endif
#ifdef HAVE_TSL_HOPSCOTCH
test<tsl_hopscotch_map_fnv1a>( "tsl::hopscotch_map, FNV-1a" );
test<tsl_hopscotch_pg_map_fnv1a>( "tsl::hopscotch_pg_map, FNV-1a" );
#endif
#ifdef HAVE_TSL_ROBIN
test<tsl_robin_map_fnv1a>( "tsl::robin_map, FNV-1a" );
test<tsl_robin_pg_map_fnv1a>( "tsl::robin_pg_map, FNV-1a" );
#endif
std::cout << "---\n\n";
for( auto const& x: times )
{
std::cout << std::setw( 30 ) << ( x.label_ + ": " ) << std::setw( 5 ) << x.time_ << " ms, " << std::setw( 9 ) << x.bytes_ << " bytes in " << x.count_ << " allocations\n";
std::cout << std::setw( 31 ) << ( x.label_ + ": " ) << std::setw( 5 ) << x.time_ << " ms, " << std::setw( 9 ) << x.bytes_ << " bytes in " << x.count_ << " allocations\n";
}
}

View File

@ -8,12 +8,19 @@
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/endian/conversion.hpp>
#include <boost/core/detail/splitmix64.hpp>
#include <boost/config.hpp>
#ifdef HAVE_ABSEIL
# include "absl/container/node_hash_map.h"
# include "absl/container/flat_hash_map.h"
#endif
#ifdef HAVE_TSL_HOPSCOTCH
# include "tsl/hopscotch_map.h"
#endif
#ifdef HAVE_TSL_ROBIN
# include "tsl/robin_map.h"
#endif
#include <unordered_map>
#include <vector>
#include <memory>
@ -62,7 +69,7 @@ static void init_indices()
for( unsigned i = 1; i <= N*2; ++i )
{
indices3.push_back( (std::uint32_t)i << 11 );
indices3.push_back( boost::endian::endian_reverse( static_cast<std::uint32_t>( i ) ) );
}
}
@ -87,7 +94,7 @@ template<class Map> BOOST_NOINLINE void test_insert( Map& map, std::chrono::stea
map.insert( { indices3[ i ], i } );
}
print_time( t1, "Consecutive shifted insert", 0, map.size() );
print_time( t1, "Consecutive reversed insert", 0, map.size() );
std::cout << std::endl;
}
@ -133,7 +140,7 @@ template<class Map> BOOST_NOINLINE void test_lookup( Map& map, std::chrono::stea
}
}
print_time( t1, "Consecutive shifted lookup", s, map.size() );
print_time( t1, "Consecutive reversed lookup", s, map.size() );
std::cout << std::endl;
}
@ -146,7 +153,14 @@ template<class Map> BOOST_NOINLINE void test_iteration( Map& map, std::chrono::s
{
if( it->second & 1 )
{
map.erase( it++ );
if constexpr( std::is_void_v< decltype( map.erase( it ) ) > )
{
map.erase( it++ );
}
else
{
it = map.erase( it );
}
}
else
{
@ -168,13 +182,9 @@ template<class Map> BOOST_NOINLINE void test_erase( Map& map, std::chrono::stead
print_time( t1, "Consecutive erase", 0, map.size() );
for( unsigned i = 1; i <= N; ++i )
{
boost::detail::splitmix64 rng;
for( unsigned i = 1; i <= N; ++i )
{
map.erase( indices2[ i ] );
}
map.erase( indices2[ i ] );
}
print_time( t1, "Random erase", 0, map.size() );
@ -184,7 +194,7 @@ template<class Map> BOOST_NOINLINE void test_erase( Map& map, std::chrono::stead
map.erase( indices3[ i ] );
}
print_time( t1, "Consecutive shifted erase", 0, map.size() );
print_time( t1, "Consecutive reversed erase", 0, map.size() );
std::cout << std::endl;
}
@ -311,6 +321,26 @@ template<class K, class V> using absl_flat_hash_map =
#endif
#ifdef HAVE_TSL_HOPSCOTCH
template<class K, class V> using tsl_hopscotch_map =
tsl::hopscotch_map<K, V, std::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
template<class K, class V> using tsl_hopscotch_pg_map =
tsl::hopscotch_pg_map<K, V, std::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
#endif
#ifdef HAVE_TSL_ROBIN
template<class K, class V> using tsl_robin_map =
tsl::robin_map<K, V, std::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
template<class K, class V> using tsl_robin_pg_map =
tsl::robin_pg_map<K, V, std::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
#endif
int main()
{
init_indices();
@ -324,6 +354,20 @@ int main()
test<absl_node_hash_map>( "absl::node_hash_map" );
test<absl_flat_hash_map>( "absl::flat_hash_map" );
#endif
#ifdef HAVE_TSL_HOPSCOTCH
test<tsl_hopscotch_map>( "tsl::hopscotch_map" );
test<tsl_hopscotch_pg_map>( "tsl::hopscotch_pg_map" );
#endif
#ifdef HAVE_TSL_ROBIN
test<tsl_robin_map>( "tsl::robin_map" );
test<tsl_robin_pg_map>( "tsl::robin_pg_map" );
#endif
std::cout << "---\n\n";

View File

@ -8,12 +8,19 @@
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/endian/conversion.hpp>
#include <boost/core/detail/splitmix64.hpp>
#include <boost/config.hpp>
#ifdef HAVE_ABSEIL
# include "absl/container/node_hash_map.h"
# include "absl/container/flat_hash_map.h"
#endif
#ifdef HAVE_TSL_HOPSCOTCH
# include "tsl/hopscotch_map.h"
#endif
#ifdef HAVE_TSL_ROBIN
# include "tsl/robin_map.h"
#endif
#include <unordered_map>
#include <vector>
#include <memory>
@ -62,7 +69,7 @@ static void init_indices()
for( unsigned i = 1; i <= N*2; ++i )
{
indices3.push_back( (std::uint64_t)i << 40 );
indices3.push_back( boost::endian::endian_reverse( static_cast<std::uint64_t>( i ) ) );
}
}
@ -87,7 +94,7 @@ template<class Map> BOOST_NOINLINE void test_insert( Map& map, std::chrono::stea
map.insert( { indices3[ i ], i } );
}
print_time( t1, "Consecutive shifted insert", 0, map.size() );
print_time( t1, "Consecutive reversed insert", 0, map.size() );
std::cout << std::endl;
}
@ -133,7 +140,7 @@ template<class Map> BOOST_NOINLINE void test_lookup( Map& map, std::chrono::stea
}
}
print_time( t1, "Consecutive shifted lookup", s, map.size() );
print_time( t1, "Consecutive reversed lookup", s, map.size() );
std::cout << std::endl;
}
@ -146,7 +153,14 @@ template<class Map> BOOST_NOINLINE void test_iteration( Map& map, std::chrono::s
{
if( it->second & 1 )
{
map.erase( it++ );
if constexpr( std::is_void_v< decltype( map.erase( it ) ) > )
{
map.erase( it++ );
}
else
{
it = map.erase( it );
}
}
else
{
@ -168,13 +182,9 @@ template<class Map> BOOST_NOINLINE void test_erase( Map& map, std::chrono::stead
print_time( t1, "Consecutive erase", 0, map.size() );
for( unsigned i = 1; i <= N; ++i )
{
boost::detail::splitmix64 rng;
for( unsigned i = 1; i <= N; ++i )
{
map.erase( indices2[ i ] );
}
map.erase( indices2[ i ] );
}
print_time( t1, "Random erase", 0, map.size() );
@ -184,7 +194,7 @@ template<class Map> BOOST_NOINLINE void test_erase( Map& map, std::chrono::stead
map.erase( indices3[ i ] );
}
print_time( t1, "Consecutive shifted erase", 0, map.size() );
print_time( t1, "Consecutive reversed erase", 0, map.size() );
std::cout << std::endl;
}
@ -311,6 +321,26 @@ template<class K, class V> using absl_flat_hash_map =
#endif
#ifdef HAVE_TSL_HOPSCOTCH
template<class K, class V> using tsl_hopscotch_map =
tsl::hopscotch_map<K, V, std::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
template<class K, class V> using tsl_hopscotch_pg_map =
tsl::hopscotch_pg_map<K, V, std::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
#endif
#ifdef HAVE_TSL_ROBIN
template<class K, class V> using tsl_robin_map =
tsl::robin_map<K, V, std::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
template<class K, class V> using tsl_robin_pg_map =
tsl::robin_pg_map<K, V, std::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
#endif
int main()
{
init_indices();
@ -324,6 +354,20 @@ int main()
test<absl_node_hash_map>( "absl::node_hash_map" );
test<absl_flat_hash_map>( "absl::flat_hash_map" );
#endif
#ifdef HAVE_TSL_HOPSCOTCH
test<tsl_hopscotch_map>( "tsl::hopscotch_map" );
test<tsl_hopscotch_pg_map>( "tsl::hopscotch_pg_map" );
#endif
#ifdef HAVE_TSL_ROBIN
test<tsl_robin_map>( "tsl::robin_map" );
test<tsl_robin_pg_map>( "tsl::robin_pg_map" );
#endif
std::cout << "---\n\n";

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

@ -113,10 +113,7 @@ to normal separate chaining implementations.
*/
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/unordered/detail/prime_fmod.hpp>
#include <boost/core/addressof.hpp>
#include <boost/core/allocator_access.hpp>
@ -124,289 +121,20 @@ to normal separate chaining implementations.
#include <boost/core/empty_value.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include <boost/cstdint.hpp>
// `iterator_facade` has transitive dependencies on Boost.MPL; one of the
// headers is generating a `-Wsign-conversion` warning which has an open PR to
// address the issue but merging does not seem likely so for now create a rote
// workaround.
//
// TODO: eventually remove this once MPL is fixed or we decide to migrate off of
// the Boost.Iterator dependency.
//
#if defined(BOOST_GCC)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#pragma GCC diagnostic ignored "-Wconversion"
#include <boost/iterator/iterator_facade.hpp>
#pragma GCC diagnostic pop
#else
#include <boost/iterator/iterator_facade.hpp>
#endif
#include <boost/move/core.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/swap.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <climits>
#include <boost/config.hpp>
#include <iterator>
namespace boost {
namespace unordered {
namespace detail {
#if defined(SIZE_MAX)
#if ((((SIZE_MAX >> 16) >> 16) >> 16) >> 15) != 0
#define BOOST_UNORDERED_FCA_HAS_64B_SIZE_T
#endif
#elif defined(UINTPTR_MAX) /* used as proxy for std::size_t */
#if ((((UINTPTR_MAX >> 16) >> 16) >> 16) >> 15) != 0
#define BOOST_UNORDERED_FCA_HAS_64B_SIZE_T
#endif
#endif
#if !defined(BOOST_NO_INT64_T) && \
(defined(BOOST_HAS_INT128) || (defined(BOOST_MSVC) && defined(_WIN64)))
#define BOOST_UNORDERED_FCA_FASTMOD_SUPPORT
#endif
template <class = void> struct prime_fmod_size
{
// Because we compile for C++03, we don't have access to any inline
// initialization for array data members so the definitions must exist
// out-of-line. To keep the library header-only, we introduce a dummy
// template parameter which permits the definition to be included in
// multiple TUs without conflict.
//
static std::size_t sizes[];
static std::size_t const sizes_len;
static std::size_t (*positions[])(std::size_t);
#if defined(BOOST_UNORDERED_FCA_FASTMOD_SUPPORT)
static uint64_t inv_sizes32[];
static std::size_t const inv_sizes32_len;
#endif /* defined(BOOST_UNORDERED_FCA_FASTMOD_SUPPORT) */
static inline std::size_t size_index(std::size_t n)
{
std::size_t i = 0;
for (; i < (sizes_len - 1); ++i) {
if (sizes[i] >= n) {
break;
}
}
return i;
}
static inline std::size_t size(std::size_t size_index)
{
return sizes[size_index];
}
template <std::size_t Size> static std::size_t modulo(std::size_t hash)
{
return hash % Size;
}
#if defined(BOOST_UNORDERED_FCA_FASTMOD_SUPPORT)
// We emulate the techniques taken from:
// Faster Remainder by Direct Computation: Applications to Compilers and
// Software Libraries
// https://arxiv.org/abs/1902.01961
//
// In essence, use fancy math to directly calculate the remainder (aka
// modulo) exploiting how compilers transform division
//
#if defined(_MSC_VER)
static inline uint64_t get_remainder(uint64_t fractional, uint32_t d)
{
// use fancy msvc instrinsic when available instead of using `>> 64`
//
return __umulh(fractional, d);
}
#else
static inline uint64_t get_remainder(uint64_t fractional, uint32_t d)
{
__extension__ typedef unsigned __int128 uint128;
return static_cast<uint64_t>(((uint128)fractional * d) >> 64);
}
#endif /* defined(_MSC_VER) */
static inline uint32_t fast_modulo(uint32_t a, uint64_t M, uint32_t d)
{
uint64_t fractional = M * a;
return (uint32_t)(get_remainder(fractional, d));
}
#endif /* defined(BOOST_UNORDERED_FCA_FASTMOD_SUPPORT) */
static inline std::size_t position(
std::size_t hash, std::size_t size_index)
{
#if defined(BOOST_UNORDERED_FCA_FASTMOD_SUPPORT)
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
std::size_t sizes_under_32bit = inv_sizes32_len;
if (BOOST_LIKELY(size_index < sizes_under_32bit)) {
return fast_modulo(uint32_t(hash) + uint32_t(hash >> 32),
inv_sizes32[size_index], uint32_t(sizes[size_index]));
} else {
return positions[size_index - sizes_under_32bit](hash);
}
#else
return fast_modulo(
hash, inv_sizes32[size_index], uint32_t(sizes[size_index]));
#endif /* defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T) */
#else
return positions[size_index](hash);
#endif /* defined(BOOST_UNORDERED_FCA_FASTMOD_SUPPORT) */
}
}; // prime_fmod_size
#define BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT_INCOMPLETE \
(13ul)(29ul)(53ul)(97ul)(193ul)(389ul)(769ul)(1543ul)(3079ul)(6151ul)( \
12289ul)(24593ul)(49157ul)(98317ul)(196613ul)(393241ul)(786433ul)( \
1572869ul)(3145739ul)(6291469ul)(12582917ul)(25165843ul)(50331653ul)( \
100663319ul)(201326611ul)(402653189ul)(805306457ul)(1610612741ul)( \
3221225473ul)
#if !defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
#define BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT \
BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT_INCOMPLETE(4294967291ul)
#define BOOST_UNORDERED_PRIME_FMOD_SIZES_64BIT
#else
#define BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT \
BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT_INCOMPLETE
// The original sequence here is this:
// (6442450939ul)
// (12884901893ul)
// (25769803751ul)
// (51539607551ul)
// (103079215111ul)
// (206158430209ul)
// (412316860441ul)
// (824633720831ul)
// (1649267441651ul)
//
// but this causes problems on versions of mingw where the `long` type is 32
// bits, even for 64-bit targets. We work around this by replacing the literals
// with compile-time arithmetic, using bitshifts to reconstruct the number.
//
// clang-format off
#define BOOST_UNORDERED_PRIME_FMOD_SIZES_64BIT \
((boost::ulong_long_type(1ul) << 32) + boost::ulong_long_type(2147483643ul)) \
((boost::ulong_long_type(3ul) << 32) + boost::ulong_long_type(5ul)) \
((boost::ulong_long_type(5ul) << 32) + boost::ulong_long_type(4294967271ul)) \
((boost::ulong_long_type(11ul) << 32) + boost::ulong_long_type(4294967295ul)) \
((boost::ulong_long_type(24ul) << 32) + boost::ulong_long_type(7ul)) \
((boost::ulong_long_type(48ul) << 32) + boost::ulong_long_type(1ul)) \
((boost::ulong_long_type(96ul) << 32) + boost::ulong_long_type(25ul)) \
((boost::ulong_long_type(191ul) << 32) + boost::ulong_long_type(4294967295ul)) \
((boost::ulong_long_type(383ul) << 32) + boost::ulong_long_type(4294967283ul))
// clang-format on
#endif /* BOOST_UNORDERED_FCA_HAS_64B_SIZE_T */
#define BOOST_UNORDERED_PRIME_FMOD_SIZES \
BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT BOOST_UNORDERED_PRIME_FMOD_SIZES_64BIT
template <class T>
std::size_t prime_fmod_size<T>::sizes[] = {
BOOST_PP_SEQ_ENUM(BOOST_UNORDERED_PRIME_FMOD_SIZES)};
template <class T>
std::size_t const prime_fmod_size<T>::sizes_len = BOOST_PP_SEQ_SIZE(
BOOST_UNORDERED_PRIME_FMOD_SIZES);
// Similarly here, we have to re-express the integer initialization using
// arithmetic such that each literal can fit in a 32-bit value.
//
#if defined(BOOST_UNORDERED_FCA_FASTMOD_SUPPORT)
// clang-format off
template <class T>
uint64_t prime_fmod_size<T>::inv_sizes32[] = {
(boost::ulong_long_type(330382099ul) << 32) + boost::ulong_long_type(2973438898ul) /* = 1418980313362273202 */,
(boost::ulong_long_type(148102320ul) << 32) + boost::ulong_long_type(2369637129ul) /* = 636094623231363849 */,
(boost::ulong_long_type(81037118ul) << 32) + boost::ulong_long_type(3403558990ul) /* = 348051774975651918 */,
(boost::ulong_long_type(44278013ul) << 32) + boost::ulong_long_type(1549730468ul) /* = 190172619316593316 */,
(boost::ulong_long_type(22253716ul) << 32) + boost::ulong_long_type(2403401389ul) /* = 95578984837873325 */,
(boost::ulong_long_type(11041047ul) << 32) + boost::ulong_long_type(143533612ul) /* = 47420935922132524 */,
(boost::ulong_long_type(5585133ul) << 32) + boost::ulong_long_type(106117528ul) /* = 23987963684927896 */,
(boost::ulong_long_type(2783517ul) << 32) + boost::ulong_long_type(1572687312ul) /* = 11955116055547344 */,
(boost::ulong_long_type(1394922ul) << 32) + boost::ulong_long_type(3428720239ul) /* = 5991147799191151 */,
(boost::ulong_long_type(698255ul) << 32) + boost::ulong_long_type(552319807ul) /* = 2998982941588287 */,
(boost::ulong_long_type(349496ul) << 32) + boost::ulong_long_type(3827689953ul) /* = 1501077717772769 */,
(boost::ulong_long_type(174641ul) << 32) + boost::ulong_long_type(3699438549ul) /* = 750081082979285 */,
(boost::ulong_long_type(87372ul) << 32) + boost::ulong_long_type(1912757574ul) /* = 375261795343686 */,
(boost::ulong_long_type(43684ul) << 32) + boost::ulong_long_type(3821029929ul) /* = 187625172388393 */,
(boost::ulong_long_type(21844ul) << 32) + boost::ulong_long_type(3340590800ul) /* = 93822606204624 */,
(boost::ulong_long_type(10921ul) << 32) + boost::ulong_long_type(4175852267ul) /* = 46909513691883 */,
(boost::ulong_long_type(5461ul) << 32) + boost::ulong_long_type(1401829642ul) /* = 23456218233098 */,
(boost::ulong_long_type(2730ul) << 32) + boost::ulong_long_type(2826028947ul) /* = 11728086747027 */,
(boost::ulong_long_type(1365ul) << 32) + boost::ulong_long_type(1411150351ul) /* = 5864041509391 */,
(boost::ulong_long_type(682ul) << 32) + boost::ulong_long_type(2857253105ul) /* = 2932024948977 */,
(boost::ulong_long_type(341ul) << 32) + boost::ulong_long_type(1431073224ul) /* = 1466014921160 */,
(boost::ulong_long_type(170ul) << 32) + boost::ulong_long_type(2862758116ul) /* = 733007198436 */,
(boost::ulong_long_type(85ul) << 32) + boost::ulong_long_type(1431619357ul) /* = 366503839517 */,
(boost::ulong_long_type(42ul) << 32) + boost::ulong_long_type(2863269661ul) /* = 183251896093 */,
(boost::ulong_long_type(21ul) << 32) + boost::ulong_long_type(1431647119ul) /* = 91625960335 */,
(boost::ulong_long_type(10ul) << 32) + boost::ulong_long_type(2863310962ul) /* = 45812983922 */,
(boost::ulong_long_type(5ul) << 32) + boost::ulong_long_type(1431653234ul) /* = 22906489714 */,
(boost::ulong_long_type(2ul) << 32) + boost::ulong_long_type(2863311496ul) /* = 11453246088 */,
(boost::ulong_long_type(1ul) << 32) + boost::ulong_long_type(1431655764ul) /* = 5726623060 */,
#if !defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
};
#else
(boost::ulong_long_type(1ul) << 32) + boost::ulong_long_type(6ul) /* 4294967302 */
};
// clang-format on
#endif /* !defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T) */
template <class T>
std::size_t const
prime_fmod_size<T>::inv_sizes32_len = sizeof(inv_sizes32) /
sizeof(inv_sizes32[0]);
#endif /* defined(BOOST_UNORDERED_FCA_FASTMOD_SUPPORT) */
#define BOOST_UNORDERED_PRIME_FMOD_POSITIONS_ELEMENT(z, _, n) \
prime_fmod_size<T>::template modulo<n>,
template <class T>
std::size_t (*prime_fmod_size<T>::positions[])(std::size_t) = {
#if !defined(BOOST_UNORDERED_FCA_FASTMOD_SUPPORT)
BOOST_PP_SEQ_FOR_EACH(BOOST_UNORDERED_PRIME_FMOD_POSITIONS_ELEMENT, ~,
BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT)
#endif
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
BOOST_PP_SEQ_FOR_EACH(BOOST_UNORDERED_PRIME_FMOD_POSITIONS_ELEMENT, ~,
BOOST_UNORDERED_PRIME_FMOD_SIZES_64BIT)
#endif
};
#undef BOOST_UNORDERED_PRIME_FMOD_POSITIONS_ELEMENT
#undef BOOST_UNORDERED_PRIME_FMOD_SIZES
#undef BOOST_UNORDERED_PRIME_FMOD_SIZES_64BIT
#undef BOOST_UNORDERED_PRIME_FMOD_SIZES_34BIT
#undef BOOST_UNORDERED_PRIME_FMOD_SIZES_34BIT_INCOMPLETE
#ifdef BOOST_UNORDERED_FCA_FASTMOD_SUPPORT
#undef BOOST_UNORDERED_FCA_FASTMOD_SUPPORT
#endif
#ifdef BOOST_UNORDERED_FCA_HAS_64B_SIZE_T
#undef BOOST_UNORDERED_FCA_HAS_64B_SIZE_T
#endif
template <class ValueType, class VoidPtr> struct node
{
typedef ValueType value_type;
@ -472,10 +200,7 @@ namespace boost {
return ~(~(std::size_t(0)) >> (sizeof(std::size_t) * 8 - n));
}
template <class Bucket>
struct grouped_bucket_iterator
: public boost::iterator_facade<grouped_bucket_iterator<Bucket>,
Bucket, boost::forward_traversal_tag>
template <class Bucket> struct grouped_bucket_iterator
{
public:
typedef typename Bucket::bucket_pointer bucket_pointer;
@ -483,8 +208,12 @@ namespace boost {
typename boost::pointer_traits<bucket_pointer>::template rebind_to<
bucket_group<Bucket> >::type bucket_group_pointer;
typedef Bucket value_type;
typedef typename boost::pointer_traits<bucket_pointer>::difference_type
difference_type;
typedef Bucket& reference;
typedef Bucket* pointer;
typedef std::forward_iterator_tag iterator_category;
private:
bucket_pointer p;
@ -493,9 +222,38 @@ namespace boost {
public:
grouped_bucket_iterator() : p(), pbg() {}
private:
friend class boost::iterator_core_access;
reference operator*() const BOOST_NOEXCEPT { return dereference(); }
pointer operator->() const BOOST_NOEXCEPT
{
return boost::to_address(p);
}
grouped_bucket_iterator& operator++() BOOST_NOEXCEPT
{
increment();
return *this;
}
grouped_bucket_iterator operator++(int) BOOST_NOEXCEPT
{
grouped_bucket_iterator old = *this;
increment();
return old;
}
bool operator==(
grouped_bucket_iterator const& other) const BOOST_NOEXCEPT
{
return equal(other);
}
bool operator!=(
grouped_bucket_iterator const& other) const BOOST_NOEXCEPT
{
return !equal(other);
}
private:
template <typename, typename, typename>
friend class grouped_bucket_array;
@ -533,12 +291,8 @@ namespace boost {
template <class Node> struct const_grouped_local_bucket_iterator;
template <class Node>
struct grouped_local_bucket_iterator
: public boost::iterator_facade<grouped_local_bucket_iterator<Node>,
typename Node::value_type, boost::forward_traversal_tag>
template <class Node> struct grouped_local_bucket_iterator
{
typedef typename Node::node_pointer node_pointer;
public:
@ -551,9 +305,39 @@ namespace boost {
grouped_local_bucket_iterator() : p() {}
private:
friend class boost::iterator_core_access;
reference operator*() const BOOST_NOEXCEPT { return dereference(); }
pointer operator->() const BOOST_NOEXCEPT
{
return boost::to_address(p);
}
grouped_local_bucket_iterator& operator++() BOOST_NOEXCEPT
{
increment();
return *this;
}
grouped_local_bucket_iterator operator++(int) BOOST_NOEXCEPT
{
grouped_local_bucket_iterator old = *this;
increment();
return old;
}
bool operator==(
grouped_local_bucket_iterator const& other) const BOOST_NOEXCEPT
{
return equal(other);
}
bool operator!=(
grouped_local_bucket_iterator const& other) const BOOST_NOEXCEPT
{
return !equal(other);
}
private:
template <typename, typename, typename>
friend class grouped_bucket_array;
@ -573,11 +357,7 @@ namespace boost {
node_pointer p;
};
template <class Node>
struct const_grouped_local_bucket_iterator
: public boost::iterator_facade<
const_grouped_local_bucket_iterator<Node>,
typename Node::value_type const, boost::forward_traversal_tag>
template <class Node> struct const_grouped_local_bucket_iterator
{
typedef typename Node::node_pointer node_pointer;
@ -596,9 +376,39 @@ namespace boost {
{
}
private:
friend class boost::iterator_core_access;
reference operator*() const BOOST_NOEXCEPT { return dereference(); }
pointer operator->() const BOOST_NOEXCEPT
{
return boost::to_address(p);
}
const_grouped_local_bucket_iterator& operator++() BOOST_NOEXCEPT
{
increment();
return *this;
}
const_grouped_local_bucket_iterator operator++(int) BOOST_NOEXCEPT
{
const_grouped_local_bucket_iterator old = *this;
increment();
return old;
}
bool operator==(
const_grouped_local_bucket_iterator const& other) const BOOST_NOEXCEPT
{
return equal(other);
}
bool operator!=(
const_grouped_local_bucket_iterator const& other) const BOOST_NOEXCEPT
{
return !equal(other);
}
private:
template <typename, typename, typename>
friend class grouped_bucket_array;

View File

@ -1697,10 +1697,9 @@ namespace boost {
};
template <typename T>
struct rv_ref
: boost::detail::if_true<boost::is_class<T>::value>::
BOOST_NESTED_TEMPLATE then<boost::unordered::detail::rv_ref_impl<T>,
please_ignore_this_overload>::type
struct rv_ref : boost::conditional<boost::is_class<T>::value,
boost::unordered::detail::rv_ref_impl<T>,
please_ignore_this_overload>::type
{
};
@ -1730,10 +1729,7 @@ namespace boost {
namespace iterator_detail {
template <class Node, class Bucket> class c_iterator;
template <class Node, class Bucket>
class iterator
: public boost::iterator_facade<iterator<Node, Bucket>,
typename Node::value_type, boost::forward_traversal_tag>
template <class Node, class Bucket> class iterator
{
public:
typedef typename Node::value_type value_type;
@ -1745,6 +1741,50 @@ namespace boost {
iterator() : p(), itb(){};
reference operator*() const BOOST_NOEXCEPT { return dereference(); }
pointer operator->() const BOOST_NOEXCEPT
{
pointer x = boost::addressof(p->value());
return x;
}
iterator& operator++() BOOST_NOEXCEPT
{
increment();
return *this;
}
iterator operator++(int) BOOST_NOEXCEPT
{
iterator old = *this;
increment();
return old;
}
bool operator==(iterator const& other) const BOOST_NOEXCEPT
{
return equal(other);
}
bool operator!=(iterator const& other) const BOOST_NOEXCEPT
{
return !equal(other);
}
bool operator==(
boost::unordered::detail::iterator_detail::c_iterator<Node,
Bucket> const& other) const BOOST_NOEXCEPT
{
return equal(other);
}
bool operator!=(
boost::unordered::detail::iterator_detail::c_iterator<Node,
Bucket> const& other) const BOOST_NOEXCEPT
{
return !equal(other);
}
private:
typedef typename Node::node_pointer node_pointer;
typedef grouped_bucket_iterator<Bucket> bucket_iterator;
@ -1754,7 +1794,6 @@ namespace boost {
template <class Types> friend struct boost::unordered::detail::table;
template <class N, class B> friend class c_iterator;
friend class boost::iterator_core_access;
iterator(node_pointer p_, bucket_iterator itb_) : p(p_), itb(itb_) {}
@ -1765,6 +1804,13 @@ namespace boost {
return (p == x.p);
}
bool equal(
const boost::unordered::detail::iterator_detail::c_iterator<Node,
Bucket>& x) const BOOST_NOEXCEPT
{
return (p == x.p);
}
void increment() BOOST_NOEXCEPT
{
p = p->next;
@ -1774,10 +1820,7 @@ namespace boost {
}
};
template <class Node, class Bucket>
class c_iterator
: public boost::iterator_facade<c_iterator<Node, Bucket>,
typename Node::value_type const, boost::forward_traversal_tag>
template <class Node, class Bucket> class c_iterator
{
public:
typedef typename Node::value_type value_type;
@ -1788,7 +1831,51 @@ namespace boost {
typedef std::forward_iterator_tag iterator_category;
c_iterator() : p(), itb(){};
c_iterator(iterator<Node, Bucket> it) : p(it.p), itb(it.itb){};
c_iterator(iterator<Node, Bucket> it) : p(it.p), itb(it.itb) {}
reference operator*() const BOOST_NOEXCEPT { return dereference(); }
pointer operator->() const BOOST_NOEXCEPT
{
pointer x = boost::addressof(p->value());
return x;
}
c_iterator& operator++() BOOST_NOEXCEPT
{
increment();
return *this;
}
c_iterator operator++(int) BOOST_NOEXCEPT
{
c_iterator old = *this;
increment();
return old;
}
bool operator==(c_iterator const& other) const BOOST_NOEXCEPT
{
return equal(other);
}
bool operator!=(c_iterator const& other) const BOOST_NOEXCEPT
{
return !equal(other);
}
bool operator==(
boost::unordered::detail::iterator_detail::iterator<Node,
Bucket> const& other) const BOOST_NOEXCEPT
{
return equal(other);
}
bool operator!=(
boost::unordered::detail::iterator_detail::iterator<Node,
Bucket> const& other) const BOOST_NOEXCEPT
{
return !equal(other);
}
private:
typedef typename Node::node_pointer node_pointer;
@ -1798,7 +1885,7 @@ namespace boost {
bucket_iterator itb;
template <class Types> friend struct boost::unordered::detail::table;
friend class boost::iterator_core_access;
template <class, class> friend class iterator;
c_iterator(node_pointer p_, bucket_iterator itb_) : p(p_), itb(itb_)
{
@ -2362,13 +2449,8 @@ namespace boost {
k, this->hash_function(), this->key_eq());
}
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning( \
disable : 4714) // function 'function' marked as __forceinline not inlined
#endif
template <class Key, class Hash, class Pred>
BOOST_FORCEINLINE iterator transparent_find(
inline iterator transparent_find(
Key const& k, Hash const& h, Pred const& pred) const
{
std::size_t const key_hash = h(k);
@ -2382,10 +2464,6 @@ namespace boost {
return this->end();
}
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
template <class Key>
node_pointer* find_prev(Key const& key, bucket_iterator itb)
{
@ -2850,6 +2928,23 @@ namespace boost {
return 1;
}
iterator erase_node(c_iterator pos) {
c_iterator next = pos;
++next;
bucket_iterator itb = pos.itb;
node_pointer* pp = boost::addressof(itb->next);
while (*pp != pos.p) {
pp = boost::addressof((*pp)->next);
}
buckets_.extract_node_after(itb, pp);
this->delete_node(pos.p);
--size_;
return iterator(next.p, next.itb);
}
iterator erase_nodes_range(c_iterator first, c_iterator last)
{
if (first == last) {
@ -3418,8 +3513,8 @@ namespace boost {
sizeof(choice2::type)
};
typedef typename boost::detail::if_true<value>::BOOST_NESTED_TEMPLATE
then<Key const&, no_key>::type type;
typedef
typename boost::conditional<value, Key const&, no_key>::type type;
};
template <class ValueType> struct set_extractor

View File

@ -0,0 +1,262 @@
// Copyright (C) 2022 Joaquin M Lopez Munoz.
// Copyright (C) 2022 Christian Mazakas
//
// 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)
#ifndef BOOST_UNORDERED_DETAIL_PRIME_FMOD_HPP
#define BOOST_UNORDERED_DETAIL_PRIME_FMOD_HPP
#include <boost/cstdint.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/config.hpp>
#include <climits>
#include <cstddef>
#if defined(SIZE_MAX)
#if ((((SIZE_MAX >> 16) >> 16) >> 16) >> 15) != 0
#define BOOST_UNORDERED_FCA_HAS_64B_SIZE_T
#endif
#elif defined(UINTPTR_MAX) /* used as proxy for std::size_t */
#if ((((UINTPTR_MAX >> 16) >> 16) >> 16) >> 15) != 0
#define BOOST_UNORDERED_FCA_HAS_64B_SIZE_T
#endif
#endif
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T) && defined(_MSC_VER)
#include <intrin.h>
#endif
namespace boost {
namespace unordered {
namespace detail {
template <class = void> struct prime_fmod_size
{
// Because we compile for C++03, we don't have access to any inline
// initialization for array data members so the definitions must exist
// out-of-line. To keep the library header-only, we introduce a dummy
// template parameter which permits the definition to be included in
// multiple TUs without conflict.
//
static std::size_t sizes[];
static std::size_t const sizes_len;
static std::size_t (*positions[])(std::size_t);
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
static boost::uint64_t inv_sizes32[];
static std::size_t const inv_sizes32_len;
#endif /* defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T) */
static inline std::size_t size_index(std::size_t n)
{
std::size_t i = 0;
for (; i < (sizes_len - 1); ++i) {
if (sizes[i] >= n) {
break;
}
}
return i;
}
static inline std::size_t size(std::size_t size_index)
{
return sizes[size_index];
}
template <std::size_t Size> static std::size_t modulo(std::size_t hash)
{
return hash % Size;
}
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
// We emulate the techniques taken from:
// Faster Remainder by Direct Computation: Applications to Compilers and
// Software Libraries
// https://arxiv.org/abs/1902.01961
//
// In essence, use fancy math to directly calculate the remainder (aka
// modulo) exploiting how compilers transform division
//
static inline boost::uint64_t get_remainder(
boost::uint64_t fractional, boost::uint32_t d)
{
#if defined(_MSC_VER)
// use MSVC intrinsics when available to avoid promotion to 128 bits
return __umulh(fractional, d);
#elif defined(BOOST_HAS_INT128)
return static_cast<boost::uint64_t>(
((boost::uint128_type)fractional * d) >> 64);
#else
// portable implementation in the absence of boost::uint128_type on 64
// bits, which happens at least in GCC 4.5 and prior
boost::uint64_t r1 = (fractional & UINT32_MAX) * d;
boost::uint64_t r2 = (fractional >> 32) * d;
r2 += r1 >> 32;
return r2 >> 32;
#endif /* defined(_MSC_VER) */
}
static inline boost::uint32_t fast_modulo(
boost::uint32_t a, boost::uint64_t M, boost::uint32_t d)
{
boost::uint64_t fractional = M * a;
return (boost::uint32_t)(get_remainder(fractional, d));
}
#endif /* defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T) */
static inline std::size_t position(
std::size_t hash, std::size_t size_index)
{
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
std::size_t sizes_under_32bit = inv_sizes32_len;
if (BOOST_LIKELY(size_index < sizes_under_32bit)) {
return fast_modulo(
boost::uint32_t(hash) + boost::uint32_t(hash >> 32),
inv_sizes32[size_index], boost::uint32_t(sizes[size_index]));
} else {
return positions[size_index - sizes_under_32bit](hash);
}
#else
return positions[size_index](hash);
#endif /* defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T) */
}
}; // prime_fmod_size
#define BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT_INCOMPLETE \
(13ul)(29ul)(53ul)(97ul)(193ul)(389ul)(769ul)(1543ul)(3079ul)(6151ul)( \
12289ul)(24593ul)(49157ul)(98317ul)(196613ul)(393241ul)(786433ul)( \
1572869ul)(3145739ul)(6291469ul)(12582917ul)(25165843ul)(50331653ul)( \
100663319ul)(201326611ul)(402653189ul)(805306457ul)(1610612741ul)( \
3221225473ul)
#if !defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
#define BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT \
BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT_INCOMPLETE(4294967291ul)
#define BOOST_UNORDERED_PRIME_FMOD_SIZES_64BIT
#else
#define BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT \
BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT_INCOMPLETE
// The original sequence here is this:
// (6442450939ul)
// (12884901893ul)
// (25769803751ul)
// (51539607551ul)
// (103079215111ul)
// (206158430209ul)
// (412316860441ul)
// (824633720831ul)
// (1649267441651ul)
//
// but this causes problems on versions of mingw where the `long` type is 32
// bits, even for 64-bit targets. We work around this by replacing the literals
// with compile-time arithmetic, using bitshifts to reconstruct the number.
//
// clang-format off
#define BOOST_UNORDERED_PRIME_FMOD_SIZES_64BIT \
((boost::ulong_long_type(1ul) << 32) + boost::ulong_long_type(2147483643ul)) \
((boost::ulong_long_type(3ul) << 32) + boost::ulong_long_type(5ul)) \
((boost::ulong_long_type(5ul) << 32) + boost::ulong_long_type(4294967271ul)) \
((boost::ulong_long_type(11ul) << 32) + boost::ulong_long_type(4294967295ul)) \
((boost::ulong_long_type(24ul) << 32) + boost::ulong_long_type(7ul)) \
((boost::ulong_long_type(48ul) << 32) + boost::ulong_long_type(1ul)) \
((boost::ulong_long_type(96ul) << 32) + boost::ulong_long_type(25ul)) \
((boost::ulong_long_type(191ul) << 32) + boost::ulong_long_type(4294967295ul)) \
((boost::ulong_long_type(383ul) << 32) + boost::ulong_long_type(4294967283ul))
// clang-format on
#endif /* BOOST_UNORDERED_FCA_HAS_64B_SIZE_T */
#define BOOST_UNORDERED_PRIME_FMOD_SIZES \
BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT BOOST_UNORDERED_PRIME_FMOD_SIZES_64BIT
template <class T>
std::size_t prime_fmod_size<T>::sizes[] = {
BOOST_PP_SEQ_ENUM(BOOST_UNORDERED_PRIME_FMOD_SIZES)};
template <class T>
std::size_t const prime_fmod_size<T>::sizes_len = BOOST_PP_SEQ_SIZE(
BOOST_UNORDERED_PRIME_FMOD_SIZES);
// Similarly here, we have to re-express the integer initialization using
// arithmetic such that each literal can fit in a 32-bit value.
//
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
// clang-format off
template <class T>
boost::uint64_t prime_fmod_size<T>::inv_sizes32[] = {
(boost::ulong_long_type(330382099ul) << 32) + boost::ulong_long_type(2973438898ul) /* = 1418980313362273202 */,
(boost::ulong_long_type(148102320ul) << 32) + boost::ulong_long_type(2369637129ul) /* = 636094623231363849 */,
(boost::ulong_long_type(81037118ul) << 32) + boost::ulong_long_type(3403558990ul) /* = 348051774975651918 */,
(boost::ulong_long_type(44278013ul) << 32) + boost::ulong_long_type(1549730468ul) /* = 190172619316593316 */,
(boost::ulong_long_type(22253716ul) << 32) + boost::ulong_long_type(2403401389ul) /* = 95578984837873325 */,
(boost::ulong_long_type(11041047ul) << 32) + boost::ulong_long_type(143533612ul) /* = 47420935922132524 */,
(boost::ulong_long_type(5585133ul) << 32) + boost::ulong_long_type(106117528ul) /* = 23987963684927896 */,
(boost::ulong_long_type(2783517ul) << 32) + boost::ulong_long_type(1572687312ul) /* = 11955116055547344 */,
(boost::ulong_long_type(1394922ul) << 32) + boost::ulong_long_type(3428720239ul) /* = 5991147799191151 */,
(boost::ulong_long_type(698255ul) << 32) + boost::ulong_long_type(552319807ul) /* = 2998982941588287 */,
(boost::ulong_long_type(349496ul) << 32) + boost::ulong_long_type(3827689953ul) /* = 1501077717772769 */,
(boost::ulong_long_type(174641ul) << 32) + boost::ulong_long_type(3699438549ul) /* = 750081082979285 */,
(boost::ulong_long_type(87372ul) << 32) + boost::ulong_long_type(1912757574ul) /* = 375261795343686 */,
(boost::ulong_long_type(43684ul) << 32) + boost::ulong_long_type(3821029929ul) /* = 187625172388393 */,
(boost::ulong_long_type(21844ul) << 32) + boost::ulong_long_type(3340590800ul) /* = 93822606204624 */,
(boost::ulong_long_type(10921ul) << 32) + boost::ulong_long_type(4175852267ul) /* = 46909513691883 */,
(boost::ulong_long_type(5461ul) << 32) + boost::ulong_long_type(1401829642ul) /* = 23456218233098 */,
(boost::ulong_long_type(2730ul) << 32) + boost::ulong_long_type(2826028947ul) /* = 11728086747027 */,
(boost::ulong_long_type(1365ul) << 32) + boost::ulong_long_type(1411150351ul) /* = 5864041509391 */,
(boost::ulong_long_type(682ul) << 32) + boost::ulong_long_type(2857253105ul) /* = 2932024948977 */,
(boost::ulong_long_type(341ul) << 32) + boost::ulong_long_type(1431073224ul) /* = 1466014921160 */,
(boost::ulong_long_type(170ul) << 32) + boost::ulong_long_type(2862758116ul) /* = 733007198436 */,
(boost::ulong_long_type(85ul) << 32) + boost::ulong_long_type(1431619357ul) /* = 366503839517 */,
(boost::ulong_long_type(42ul) << 32) + boost::ulong_long_type(2863269661ul) /* = 183251896093 */,
(boost::ulong_long_type(21ul) << 32) + boost::ulong_long_type(1431647119ul) /* = 91625960335 */,
(boost::ulong_long_type(10ul) << 32) + boost::ulong_long_type(2863310962ul) /* = 45812983922 */,
(boost::ulong_long_type(5ul) << 32) + boost::ulong_long_type(1431653234ul) /* = 22906489714 */,
(boost::ulong_long_type(2ul) << 32) + boost::ulong_long_type(2863311496ul) /* = 11453246088 */,
(boost::ulong_long_type(1ul) << 32) + boost::ulong_long_type(1431655764ul) /* = 5726623060 */,
};
// clang-format on
template <class T>
std::size_t const
prime_fmod_size<T>::inv_sizes32_len = sizeof(inv_sizes32) /
sizeof(inv_sizes32[0]);
#endif /* defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T) */
#define BOOST_UNORDERED_PRIME_FMOD_POSITIONS_ELEMENT(z, _, n) \
prime_fmod_size<T>::template modulo<n>,
template <class T>
std::size_t (*prime_fmod_size<T>::positions[])(std::size_t) = {
#if !defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
BOOST_PP_SEQ_FOR_EACH(BOOST_UNORDERED_PRIME_FMOD_POSITIONS_ELEMENT, ~,
BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT)
#else
BOOST_PP_SEQ_FOR_EACH(BOOST_UNORDERED_PRIME_FMOD_POSITIONS_ELEMENT, ~,
BOOST_UNORDERED_PRIME_FMOD_SIZES_64BIT)
#endif
};
#undef BOOST_UNORDERED_PRIME_FMOD_POSITIONS_ELEMENT
#undef BOOST_UNORDERED_PRIME_FMOD_SIZES
#undef BOOST_UNORDERED_PRIME_FMOD_SIZES_64BIT
#undef BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT
#undef BOOST_UNORDERED_PRIME_FMOD_SIZES_32BIT_INCOMPLETE
} // namespace detail
} // namespace unordered
} // namespace boost
#endif // BOOST_UNORDERED_DETAIL_PRIME_FMOD_HPP

View File

@ -1856,18 +1856,14 @@ namespace boost {
typename unordered_map<K, T, H, P, A>::iterator
unordered_map<K, T, H, P, A>::erase(iterator position)
{
const_iterator last = position;
++last;
return table_.erase_nodes_range(position, last);
return table_.erase_node(position);
}
template <class K, class T, class H, class P, class A>
typename unordered_map<K, T, H, P, A>::iterator
unordered_map<K, T, H, P, A>::erase(const_iterator position)
{
const_iterator last = position;
++last;
return table_.erase_nodes_range(position, last);
return table_.erase_node(position);
}
template <class K, class T, class H, class P, class A>
@ -2340,9 +2336,7 @@ namespace boost {
unordered_multimap<K, T, H, P, A>::erase(iterator position)
{
BOOST_ASSERT(position != this->end());
iterator next = position;
++next;
return table_.erase_nodes_range(position, next);
return table_.erase_node(position);
}
template <class K, class T, class H, class P, class A>
@ -2350,9 +2344,7 @@ namespace boost {
unordered_multimap<K, T, H, P, A>::erase(const_iterator position)
{
BOOST_ASSERT(position != this->end());
const_iterator next = position;
++next;
return table_.erase_nodes_range(position, next);
return table_.erase_node(position);
}
template <class K, class T, class H, class P, class A>

View File

@ -1457,9 +1457,7 @@ namespace boost {
typename unordered_set<T, H, P, A>::iterator
unordered_set<T, H, P, A>::erase(const_iterator position)
{
const_iterator last = position;
++last;
return table_.erase_nodes_range(position, last);
return table_.erase_node(position);
}
template <class T, class H, class P, class A>
@ -1853,10 +1851,7 @@ namespace boost {
unordered_multiset<T, H, P, A>::erase(const_iterator position)
{
BOOST_ASSERT(position != this->end());
iterator next = position;
++next;
table_.erase_nodes_range(position, next);
return next;
return table_.erase_node(position);
}
template <class T, class H, class P, class A>

View File

@ -6,6 +6,12 @@ include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST)
if(HAVE_BOOST_TEST)
boost_test_jamfile(FILE Jamfile.v2 LINK_LIBRARIES Boost::unordered Boost::core)
boost_test_jamfile(
FILE Jamfile.v2
LINK_LIBRARIES
Boost::unordered
Boost::core
Boost::concept_check
)
endif()

View File

@ -24,11 +24,15 @@ project
<toolset>clang:<cxxflags>$(clang-flags)
<toolset>msvc:<cxxflags>$(msvc-flags)
<toolset>gcc-4.4:<cxxflags>-Wno-strict-aliasing
<toolset>gcc-4.4:<cxxflags>-fno-deduce-init-list
<toolset>gcc:<warnings-as-errors>on
<toolset>clang:<warnings-as-errors>on
<toolset>msvc:<warnings-as-errors>on
;
run unordered/prime_fmod_tests.cpp ;
run unordered/fwd_set_test.cpp ;
run unordered/fwd_map_test.cpp ;
run unordered/allocator_traits.cpp ;

View File

@ -18,7 +18,6 @@ assert
config
container_hash
core
iterator
move
mp11
predef
@ -29,24 +28,10 @@ type_traits
# Secondary dependencies
static_assert
concept_check
conversion
detail
function_types
fusion
mpl
optional
smart_ptr
utility
winapi
typeof
functional
io
function
bind
integer
type_index
static_assert
winapi
)
foreach(dep IN LISTS deps)

View File

@ -9,8 +9,8 @@
#include "./generators.hpp"
#include "./list.hpp"
#include "./metafunctions.hpp"
#include <boost/type_traits/conditional.hpp>
#include <algorithm>
#include <boost/detail/select_type.hpp>
namespace test {
template <class X> struct unordered_generator_set
@ -69,9 +69,8 @@ namespace test {
template <class X>
struct unordered_generator_base
: public boost::detail::if_true<test::is_set<X>::value>::
BOOST_NESTED_TEMPLATE then<test::unordered_generator_set<X>,
test::unordered_generator_map<X> >
: public boost::conditional<test::is_set<X>::value,
test::unordered_generator_set<X>, test::unordered_generator_map<X> >
{
};

View File

@ -1,4 +1,4 @@
// Copyright 2021 Christian Mazakas.
// Copyright 2021-2022 Christian Mazakas.
// 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)
@ -11,9 +11,10 @@
#include "../helpers/test.hpp"
#include <boost/config.hpp>
#include <string>
#if BOOST_CXX_VERSION >= 201103L
#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS)
#define UNORDERED_LVALUE_QUAL &
#else
#define UNORDERED_LVALUE_QUAL

View File

@ -189,7 +189,8 @@ namespace noexcept_tests {
#if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_NOEXCEPT) && \
!defined(BOOST_NO_CXX11_DECLTYPE) && \
!defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
!defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) && \
!BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40700)
BOOST_TEST(have_is_nothrow_swap);
#endif

View File

@ -0,0 +1,215 @@
// Copyright 2022 Christian Mazakas.
// 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 <boost/unordered/detail/prime_fmod.hpp>
#include <boost/core/detail/splitmix64.hpp>
#include <boost/core/lightweight_test.hpp>
#include <limits>
#if defined(BOOST_MSVC)
// conditional expression is constant
#pragma warning(disable : 4127)
#endif
void macros_test()
{
if (std::numeric_limits<std::size_t>::digits >= 64) {
#if !defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
BOOST_ERROR("std::numeric_limits<size_t>::digits >= 64, but "
"BOOST_UNORDERED_FCA_HAS_64B_SIZE_T is not defined");
#endif
}
else {
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
BOOST_ERROR("std::numeric_limits<size_t>::digits < 64, but "
"BOOST_UNORDERED_FCA_HAS_64B_SIZE_T is defined");
#endif
}
}
// Pretty inefficient, but the test is fast enough.
// Might be too slow if we had larger primes?
bool is_prime(std::size_t x)
{
if (x == 2) {
return true;
}
if (x == 1 || x % 2 == 0) {
return false;
}
// y*y <= x is susceptible to overflow, so instead make sure to use y <= (x/y)
for (std::size_t y = 3; y <= (x / y); y += 2) {
if (x % y == 0) {
return false;
}
}
return true;
}
void prime_sizes_test()
{
// just some basic sanity checks
//
BOOST_TEST(!is_prime(0));
BOOST_TEST(!is_prime(1));
BOOST_TEST(is_prime(2));
BOOST_TEST(is_prime(3));
BOOST_TEST(is_prime(13));
BOOST_TEST(!is_prime(4));
BOOST_TEST(!is_prime(100));
BOOST_TEST(!is_prime(49));
std::size_t* sizes = boost::unordered::detail::prime_fmod_size<>::sizes;
std::size_t sizes_len =
boost::unordered::detail::prime_fmod_size<>::sizes_len;
// prove every number in our sizes array is prime
//
BOOST_TEST_GT(sizes_len, 0u);
for (std::size_t i = 0; i < sizes_len; ++i) {
BOOST_TEST(is_prime(sizes[i]));
}
// prove that every subsequent number in the sequence is larger than the
// previous
//
for (std::size_t i = 1; i < sizes_len; ++i) {
BOOST_TEST_GT(sizes[i], sizes[i - 1]);
}
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
// now we wish to prove that if we do have the reciprocals stored, we have the
// correct amount of them, i.e. one for every entry in sizes[] that fits in 32
// bits
//
boost::uint64_t* inv_sizes32 =
boost::unordered::detail::prime_fmod_size<>::inv_sizes32;
std::size_t inv_sizes32_len =
boost::unordered::detail::prime_fmod_size<>::inv_sizes32_len;
std::size_t count = 0;
for (std::size_t i = 0; i < sizes_len; ++i) {
if (sizes[i] <= UINT32_MAX) {
++count;
}
}
BOOST_TEST_GT(inv_sizes32_len, 0u);
BOOST_TEST_EQ(inv_sizes32_len, count);
// these values should also be monotonically decreasing
//
for (std::size_t i = 1; i < inv_sizes32_len; ++i) {
BOOST_TEST_LT(inv_sizes32[i], inv_sizes32[i - 1]);
}
// now make sure the values in inv_sizes32 are what they should be as derived
// from the paper
//
for (std::size_t i = 0; i < inv_sizes32_len; ++i) {
std::size_t const size = sizes[i];
BOOST_TEST_LE(size, UINT_MAX);
boost::uint32_t d = static_cast<boost::uint32_t>(sizes[i]);
boost::uint64_t M = ((boost::ulong_long_type(0xffffffff) << 32) +
boost::ulong_long_type(0xffffffff)) /
d +
1;
BOOST_TEST_EQ(inv_sizes32[i], M);
}
#endif
}
void get_remainder_test()
{
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
struct
{
// boost::unordered::detail::prime_fmod_size<>::get_remainder
// uses several internal implementations depending on the availability of
// certain intrinsics or 128 bit integer support, defaulting to a slow,
// portable routine. The following is a transcription of the portable
// routine used here for verification purposes.
//
boost::uint64_t operator()(boost::uint64_t f, boost::uint32_t d)
{
boost::uint64_t r1 = (f & UINT32_MAX) * d;
boost::uint64_t r2 = (f >> 32) * d;
r2 += r1 >> 32;
return r2 >> 32;
}
} get_remainder;
boost::detail::splitmix64 rng;
for (std::size_t i = 0; i < 1000000u; ++i) {
boost::uint64_t f = rng();
boost::uint32_t d = static_cast<uint32_t>(rng());
boost::uint64_t r1 =
boost::unordered::detail::prime_fmod_size<>::get_remainder(f, d);
boost::uint64_t r2 = get_remainder(f, d);
if (!BOOST_TEST_EQ(r1, r2)) {
std::cerr << "f: " << f << ", d: " << d << std::endl;
return;
}
}
#endif
}
void modulo_test()
{
std::size_t* sizes = boost::unordered::detail::prime_fmod_size<>::sizes;
std::size_t const sizes_len =
boost::unordered::detail::prime_fmod_size<>::sizes_len;
boost::detail::splitmix64 rng;
for (std::size_t i = 0; i < 1000000u; ++i) {
std::size_t hash = static_cast<std::size_t>(rng());
for (std::size_t j = 0; j < sizes_len; ++j) {
std::size_t h = hash;
#if defined(BOOST_UNORDERED_FCA_HAS_64B_SIZE_T)
if (sizes[j] <= UINT_MAX) {
h = boost::uint32_t(h) + boost::uint32_t(h >> 32);
}
#endif
std::size_t p1 =
boost::unordered::detail::prime_fmod_size<>::position(hash, j);
std::size_t p2 = h % sizes[j];
if (!BOOST_TEST_EQ(p1, p2)) {
std::cerr << "hash: " << hash << ", j: " << j << ", h: " << h
<< ", sizes[" << j << "]: " << sizes[j] << std::endl;
return;
}
}
}
}
int main()
{
macros_test();
prime_sizes_test();
get_remainder_test();
modulo_test();
return boost::report_errors();
}

View File

@ -1,12 +1,13 @@
// Copyright 2021 Christian Mazakas.
// Copyright 2021-2022 Christian Mazakas.
// 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 <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
#include <boost/config/workaround.hpp>
#if BOOST_CXX_VERSION <= 199711L
#if BOOST_CXX_VERSION <= 199711L || BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
BOOST_PRAGMA_MESSAGE(
"scoped allocator adaptor tests only work under C++11 and above")