diff --git a/doc/diagrams/benchmarks-flat_map/clang-arm64/Running erasure.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/clang-arm64/Running erasure.xlsx.plot.png new file mode 100644 index 00000000..c71ce263 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/clang-arm64/Running erasure.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/clang-arm64/Running insertion.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/clang-arm64/Running insertion.xlsx.plot.png new file mode 100644 index 00000000..d0da34f6 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/clang-arm64/Running insertion.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/clang-arm64/Scattered successful looukp.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/clang-arm64/Scattered successful looukp.xlsx.plot.png new file mode 100644 index 00000000..1391cd2e Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/clang-arm64/Scattered successful looukp.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/clang-arm64/Scattered unsuccessful looukp.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/clang-arm64/Scattered unsuccessful looukp.xlsx.plot.png new file mode 100644 index 00000000..bfadd879 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/clang-arm64/Scattered unsuccessful looukp.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/clang-x64/Running erasure.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/clang-x64/Running erasure.xlsx.plot.png new file mode 100644 index 00000000..bccf8d52 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/clang-x64/Running erasure.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/clang-x64/Running insertion.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/clang-x64/Running insertion.xlsx.plot.png new file mode 100644 index 00000000..6399e6da Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/clang-x64/Running insertion.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/clang-x64/Scattered successful looukp.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/clang-x64/Scattered successful looukp.xlsx.plot.png new file mode 100644 index 00000000..c99cea4e Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/clang-x64/Scattered successful looukp.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/clang-x64/Scattered unsuccessful looukp.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/clang-x64/Scattered unsuccessful looukp.xlsx.plot.png new file mode 100644 index 00000000..11680c41 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/clang-x64/Scattered unsuccessful looukp.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/clang-x86/Running erasure.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/clang-x86/Running erasure.xlsx.plot.png new file mode 100644 index 00000000..6836cfbe Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/clang-x86/Running erasure.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/clang-x86/Running insertion.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/clang-x86/Running insertion.xlsx.plot.png new file mode 100644 index 00000000..5f5b4ba9 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/clang-x86/Running insertion.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/clang-x86/Scattered successful looukp.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/clang-x86/Scattered successful looukp.xlsx.plot.png new file mode 100644 index 00000000..67e9f266 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/clang-x86/Scattered successful looukp.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/clang-x86/Scattered unsuccessful looukp.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/clang-x86/Scattered unsuccessful looukp.xlsx.plot.png new file mode 100644 index 00000000..0e8d77f2 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/clang-x86/Scattered unsuccessful looukp.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/gcc-x64/Running erasure.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/gcc-x64/Running erasure.xlsx.plot.png new file mode 100644 index 00000000..a02a4cf2 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/gcc-x64/Running erasure.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/gcc-x64/Running insertion.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/gcc-x64/Running insertion.xlsx.plot.png new file mode 100644 index 00000000..806f2b21 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/gcc-x64/Running insertion.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/gcc-x64/Scattered successful looukp.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/gcc-x64/Scattered successful looukp.xlsx.plot.png new file mode 100644 index 00000000..4677a61b Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/gcc-x64/Scattered successful looukp.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/gcc-x64/Scattered unsuccessful looukp.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/gcc-x64/Scattered unsuccessful looukp.xlsx.plot.png new file mode 100644 index 00000000..e279bebb Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/gcc-x64/Scattered unsuccessful looukp.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/gcc-x86/Running erasure.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/gcc-x86/Running erasure.xlsx.plot.png new file mode 100644 index 00000000..8690ca94 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/gcc-x86/Running erasure.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/gcc-x86/Running insertion.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/gcc-x86/Running insertion.xlsx.plot.png new file mode 100644 index 00000000..7216a415 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/gcc-x86/Running insertion.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/gcc-x86/Scattered successful looukp.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/gcc-x86/Scattered successful looukp.xlsx.plot.png new file mode 100644 index 00000000..898d9557 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/gcc-x86/Scattered successful looukp.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/gcc-x86/Scattered unsuccessful looukp.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/gcc-x86/Scattered unsuccessful looukp.xlsx.plot.png new file mode 100644 index 00000000..53d4db83 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/gcc-x86/Scattered unsuccessful looukp.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/vs-x64/Running erasure.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/vs-x64/Running erasure.xlsx.plot.png new file mode 100644 index 00000000..3fb9474b Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/vs-x64/Running erasure.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/vs-x64/Running insertion.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/vs-x64/Running insertion.xlsx.plot.png new file mode 100644 index 00000000..2227cd65 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/vs-x64/Running insertion.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/vs-x64/Scattered successful looukp.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/vs-x64/Scattered successful looukp.xlsx.plot.png new file mode 100644 index 00000000..fe841c71 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/vs-x64/Scattered successful looukp.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/vs-x64/Scattered unsuccessful looukp.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/vs-x64/Scattered unsuccessful looukp.xlsx.plot.png new file mode 100644 index 00000000..cfabae47 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/vs-x64/Scattered unsuccessful looukp.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/vs-x86/Running erasure.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/vs-x86/Running erasure.xlsx.plot.png new file mode 100644 index 00000000..7920aaa6 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/vs-x86/Running erasure.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/vs-x86/Running insertion.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/vs-x86/Running insertion.xlsx.plot.png new file mode 100644 index 00000000..83f19d9c Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/vs-x86/Running insertion.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/vs-x86/Scattered successful looukp.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/vs-x86/Scattered successful looukp.xlsx.plot.png new file mode 100644 index 00000000..c3f60c76 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/vs-x86/Scattered successful looukp.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks-flat_map/vs-x86/Scattered unsuccessful looukp.xlsx.plot.png b/doc/diagrams/benchmarks-flat_map/vs-x86/Scattered unsuccessful looukp.xlsx.plot.png new file mode 100644 index 00000000..ed7ac1f2 Binary files /dev/null and b/doc/diagrams/benchmarks-flat_map/vs-x86/Scattered unsuccessful looukp.xlsx.plot.png differ diff --git a/doc/diagrams/benchmarks/clang_libcpp/running insertion.xlsx.practice non-unique 5.png b/doc/diagrams/benchmarks-set/clang_libcpp/running insertion.xlsx.practice non-unique 5.png similarity index 100% rename from doc/diagrams/benchmarks/clang_libcpp/running insertion.xlsx.practice non-unique 5.png rename to doc/diagrams/benchmarks-set/clang_libcpp/running insertion.xlsx.practice non-unique 5.png diff --git a/doc/diagrams/benchmarks/clang_libcpp/running insertion.xlsx.practice non-unique.png b/doc/diagrams/benchmarks-set/clang_libcpp/running insertion.xlsx.practice non-unique.png similarity index 100% rename from doc/diagrams/benchmarks/clang_libcpp/running insertion.xlsx.practice non-unique.png rename to doc/diagrams/benchmarks-set/clang_libcpp/running insertion.xlsx.practice non-unique.png diff --git a/doc/diagrams/benchmarks/clang_libcpp/running insertion.xlsx.practice norehash non-unique 5.png b/doc/diagrams/benchmarks-set/clang_libcpp/running insertion.xlsx.practice norehash non-unique 5.png similarity index 100% rename from doc/diagrams/benchmarks/clang_libcpp/running insertion.xlsx.practice norehash non-unique 5.png rename to doc/diagrams/benchmarks-set/clang_libcpp/running insertion.xlsx.practice norehash non-unique 5.png diff --git a/doc/diagrams/benchmarks/clang_libcpp/running insertion.xlsx.practice norehash non-unique.png b/doc/diagrams/benchmarks-set/clang_libcpp/running insertion.xlsx.practice norehash non-unique.png similarity index 100% rename from doc/diagrams/benchmarks/clang_libcpp/running insertion.xlsx.practice norehash non-unique.png rename to doc/diagrams/benchmarks-set/clang_libcpp/running insertion.xlsx.practice norehash non-unique.png diff --git a/doc/diagrams/benchmarks/clang_libcpp/running insertion.xlsx.practice norehash.png b/doc/diagrams/benchmarks-set/clang_libcpp/running insertion.xlsx.practice norehash.png similarity index 100% rename from doc/diagrams/benchmarks/clang_libcpp/running insertion.xlsx.practice norehash.png rename to doc/diagrams/benchmarks-set/clang_libcpp/running insertion.xlsx.practice norehash.png diff --git a/doc/diagrams/benchmarks/clang_libcpp/running insertion.xlsx.practice.png b/doc/diagrams/benchmarks-set/clang_libcpp/running insertion.xlsx.practice.png similarity index 100% rename from doc/diagrams/benchmarks/clang_libcpp/running insertion.xlsx.practice.png rename to doc/diagrams/benchmarks-set/clang_libcpp/running insertion.xlsx.practice.png diff --git a/doc/diagrams/benchmarks/clang_libcpp/scattered erasure.xlsx.practice non-unique 5.png b/doc/diagrams/benchmarks-set/clang_libcpp/scattered erasure.xlsx.practice non-unique 5.png similarity index 100% rename from doc/diagrams/benchmarks/clang_libcpp/scattered erasure.xlsx.practice non-unique 5.png rename to doc/diagrams/benchmarks-set/clang_libcpp/scattered erasure.xlsx.practice non-unique 5.png diff --git a/doc/diagrams/benchmarks/clang_libcpp/scattered erasure.xlsx.practice non-unique.png b/doc/diagrams/benchmarks-set/clang_libcpp/scattered erasure.xlsx.practice non-unique.png similarity index 100% rename from doc/diagrams/benchmarks/clang_libcpp/scattered erasure.xlsx.practice non-unique.png rename to doc/diagrams/benchmarks-set/clang_libcpp/scattered erasure.xlsx.practice non-unique.png diff --git a/doc/diagrams/benchmarks/clang_libcpp/scattered erasure.xlsx.practice.png b/doc/diagrams/benchmarks-set/clang_libcpp/scattered erasure.xlsx.practice.png similarity index 100% rename from doc/diagrams/benchmarks/clang_libcpp/scattered erasure.xlsx.practice.png rename to doc/diagrams/benchmarks-set/clang_libcpp/scattered erasure.xlsx.practice.png diff --git a/doc/diagrams/benchmarks/clang_libcpp/scattered successful looukp.xlsx.practice non-unique 5.png b/doc/diagrams/benchmarks-set/clang_libcpp/scattered successful looukp.xlsx.practice non-unique 5.png similarity index 100% rename from doc/diagrams/benchmarks/clang_libcpp/scattered successful looukp.xlsx.practice non-unique 5.png rename to doc/diagrams/benchmarks-set/clang_libcpp/scattered successful looukp.xlsx.practice non-unique 5.png diff --git a/doc/diagrams/benchmarks/clang_libcpp/scattered successful looukp.xlsx.practice non-unique.png b/doc/diagrams/benchmarks-set/clang_libcpp/scattered successful looukp.xlsx.practice non-unique.png similarity index 100% rename from doc/diagrams/benchmarks/clang_libcpp/scattered successful looukp.xlsx.practice non-unique.png rename to doc/diagrams/benchmarks-set/clang_libcpp/scattered successful looukp.xlsx.practice non-unique.png diff --git a/doc/diagrams/benchmarks/clang_libcpp/scattered successful looukp.xlsx.practice.png b/doc/diagrams/benchmarks-set/clang_libcpp/scattered successful looukp.xlsx.practice.png similarity index 100% rename from doc/diagrams/benchmarks/clang_libcpp/scattered successful looukp.xlsx.practice.png rename to doc/diagrams/benchmarks-set/clang_libcpp/scattered successful looukp.xlsx.practice.png diff --git a/doc/diagrams/benchmarks/clang_libcpp/scattered unsuccessful looukp.xlsx.practice non-unique 5.png b/doc/diagrams/benchmarks-set/clang_libcpp/scattered unsuccessful looukp.xlsx.practice non-unique 5.png similarity index 100% rename from doc/diagrams/benchmarks/clang_libcpp/scattered unsuccessful looukp.xlsx.practice non-unique 5.png rename to doc/diagrams/benchmarks-set/clang_libcpp/scattered unsuccessful looukp.xlsx.practice non-unique 5.png diff --git a/doc/diagrams/benchmarks/clang_libcpp/scattered unsuccessful looukp.xlsx.practice non-unique.png b/doc/diagrams/benchmarks-set/clang_libcpp/scattered unsuccessful looukp.xlsx.practice non-unique.png similarity index 100% rename from doc/diagrams/benchmarks/clang_libcpp/scattered unsuccessful looukp.xlsx.practice non-unique.png rename to doc/diagrams/benchmarks-set/clang_libcpp/scattered unsuccessful looukp.xlsx.practice non-unique.png diff --git a/doc/diagrams/benchmarks/clang_libcpp/scattered unsuccessful looukp.xlsx.practice.png b/doc/diagrams/benchmarks-set/clang_libcpp/scattered unsuccessful looukp.xlsx.practice.png similarity index 100% rename from doc/diagrams/benchmarks/clang_libcpp/scattered unsuccessful looukp.xlsx.practice.png rename to doc/diagrams/benchmarks-set/clang_libcpp/scattered unsuccessful looukp.xlsx.practice.png diff --git a/doc/diagrams/benchmarks/gcc/running insertion.xlsx.practice non-unique 5.png b/doc/diagrams/benchmarks-set/gcc/running insertion.xlsx.practice non-unique 5.png similarity index 100% rename from doc/diagrams/benchmarks/gcc/running insertion.xlsx.practice non-unique 5.png rename to doc/diagrams/benchmarks-set/gcc/running insertion.xlsx.practice non-unique 5.png diff --git a/doc/diagrams/benchmarks/gcc/running insertion.xlsx.practice non-unique.png b/doc/diagrams/benchmarks-set/gcc/running insertion.xlsx.practice non-unique.png similarity index 100% rename from doc/diagrams/benchmarks/gcc/running insertion.xlsx.practice non-unique.png rename to doc/diagrams/benchmarks-set/gcc/running insertion.xlsx.practice non-unique.png diff --git a/doc/diagrams/benchmarks/gcc/running insertion.xlsx.practice norehash non-unique 5.png b/doc/diagrams/benchmarks-set/gcc/running insertion.xlsx.practice norehash non-unique 5.png similarity index 100% rename from doc/diagrams/benchmarks/gcc/running insertion.xlsx.practice norehash non-unique 5.png rename to doc/diagrams/benchmarks-set/gcc/running insertion.xlsx.practice norehash non-unique 5.png diff --git a/doc/diagrams/benchmarks/gcc/running insertion.xlsx.practice norehash non-unique.png b/doc/diagrams/benchmarks-set/gcc/running insertion.xlsx.practice norehash non-unique.png similarity index 100% rename from doc/diagrams/benchmarks/gcc/running insertion.xlsx.practice norehash non-unique.png rename to doc/diagrams/benchmarks-set/gcc/running insertion.xlsx.practice norehash non-unique.png diff --git a/doc/diagrams/benchmarks/gcc/running insertion.xlsx.practice norehash.png b/doc/diagrams/benchmarks-set/gcc/running insertion.xlsx.practice norehash.png similarity index 100% rename from doc/diagrams/benchmarks/gcc/running insertion.xlsx.practice norehash.png rename to doc/diagrams/benchmarks-set/gcc/running insertion.xlsx.practice norehash.png diff --git a/doc/diagrams/benchmarks/gcc/running insertion.xlsx.practice.png b/doc/diagrams/benchmarks-set/gcc/running insertion.xlsx.practice.png similarity index 100% rename from doc/diagrams/benchmarks/gcc/running insertion.xlsx.practice.png rename to doc/diagrams/benchmarks-set/gcc/running insertion.xlsx.practice.png diff --git a/doc/diagrams/benchmarks/gcc/scattered erasure.xlsx.practice non-unique 5.png b/doc/diagrams/benchmarks-set/gcc/scattered erasure.xlsx.practice non-unique 5.png similarity index 100% rename from doc/diagrams/benchmarks/gcc/scattered erasure.xlsx.practice non-unique 5.png rename to doc/diagrams/benchmarks-set/gcc/scattered erasure.xlsx.practice non-unique 5.png diff --git a/doc/diagrams/benchmarks/gcc/scattered erasure.xlsx.practice non-unique.png b/doc/diagrams/benchmarks-set/gcc/scattered erasure.xlsx.practice non-unique.png similarity index 100% rename from doc/diagrams/benchmarks/gcc/scattered erasure.xlsx.practice non-unique.png rename to doc/diagrams/benchmarks-set/gcc/scattered erasure.xlsx.practice non-unique.png diff --git a/doc/diagrams/benchmarks/gcc/scattered erasure.xlsx.practice.png b/doc/diagrams/benchmarks-set/gcc/scattered erasure.xlsx.practice.png similarity index 100% rename from doc/diagrams/benchmarks/gcc/scattered erasure.xlsx.practice.png rename to doc/diagrams/benchmarks-set/gcc/scattered erasure.xlsx.practice.png diff --git a/doc/diagrams/benchmarks/gcc/scattered successful looukp.xlsx.practice non-unique 5.png b/doc/diagrams/benchmarks-set/gcc/scattered successful looukp.xlsx.practice non-unique 5.png similarity index 100% rename from doc/diagrams/benchmarks/gcc/scattered successful looukp.xlsx.practice non-unique 5.png rename to doc/diagrams/benchmarks-set/gcc/scattered successful looukp.xlsx.practice non-unique 5.png diff --git a/doc/diagrams/benchmarks/gcc/scattered successful looukp.xlsx.practice non-unique.png b/doc/diagrams/benchmarks-set/gcc/scattered successful looukp.xlsx.practice non-unique.png similarity index 100% rename from doc/diagrams/benchmarks/gcc/scattered successful looukp.xlsx.practice non-unique.png rename to doc/diagrams/benchmarks-set/gcc/scattered successful looukp.xlsx.practice non-unique.png diff --git a/doc/diagrams/benchmarks/gcc/scattered successful looukp.xlsx.practice.png b/doc/diagrams/benchmarks-set/gcc/scattered successful looukp.xlsx.practice.png similarity index 100% rename from doc/diagrams/benchmarks/gcc/scattered successful looukp.xlsx.practice.png rename to doc/diagrams/benchmarks-set/gcc/scattered successful looukp.xlsx.practice.png diff --git a/doc/diagrams/benchmarks/gcc/scattered unsuccessful looukp.xlsx.practice non-unique 5.png b/doc/diagrams/benchmarks-set/gcc/scattered unsuccessful looukp.xlsx.practice non-unique 5.png similarity index 100% rename from doc/diagrams/benchmarks/gcc/scattered unsuccessful looukp.xlsx.practice non-unique 5.png rename to doc/diagrams/benchmarks-set/gcc/scattered unsuccessful looukp.xlsx.practice non-unique 5.png diff --git a/doc/diagrams/benchmarks/gcc/scattered unsuccessful looukp.xlsx.practice non-unique.png b/doc/diagrams/benchmarks-set/gcc/scattered unsuccessful looukp.xlsx.practice non-unique.png similarity index 100% rename from doc/diagrams/benchmarks/gcc/scattered unsuccessful looukp.xlsx.practice non-unique.png rename to doc/diagrams/benchmarks-set/gcc/scattered unsuccessful looukp.xlsx.practice non-unique.png diff --git a/doc/diagrams/benchmarks/gcc/scattered unsuccessful looukp.xlsx.practice.png b/doc/diagrams/benchmarks-set/gcc/scattered unsuccessful looukp.xlsx.practice.png similarity index 100% rename from doc/diagrams/benchmarks/gcc/scattered unsuccessful looukp.xlsx.practice.png rename to doc/diagrams/benchmarks-set/gcc/scattered unsuccessful looukp.xlsx.practice.png diff --git a/doc/diagrams/benchmarks/vs/running insertion.xlsx.practice non-unique 5.png b/doc/diagrams/benchmarks-set/vs/running insertion.xlsx.practice non-unique 5.png similarity index 100% rename from doc/diagrams/benchmarks/vs/running insertion.xlsx.practice non-unique 5.png rename to doc/diagrams/benchmarks-set/vs/running insertion.xlsx.practice non-unique 5.png diff --git a/doc/diagrams/benchmarks/vs/running insertion.xlsx.practice non-unique.png b/doc/diagrams/benchmarks-set/vs/running insertion.xlsx.practice non-unique.png similarity index 100% rename from doc/diagrams/benchmarks/vs/running insertion.xlsx.practice non-unique.png rename to doc/diagrams/benchmarks-set/vs/running insertion.xlsx.practice non-unique.png diff --git a/doc/diagrams/benchmarks/vs/running insertion.xlsx.practice norehash non-unique 5.png b/doc/diagrams/benchmarks-set/vs/running insertion.xlsx.practice norehash non-unique 5.png similarity index 100% rename from doc/diagrams/benchmarks/vs/running insertion.xlsx.practice norehash non-unique 5.png rename to doc/diagrams/benchmarks-set/vs/running insertion.xlsx.practice norehash non-unique 5.png diff --git a/doc/diagrams/benchmarks/vs/running insertion.xlsx.practice norehash non-unique.png b/doc/diagrams/benchmarks-set/vs/running insertion.xlsx.practice norehash non-unique.png similarity index 100% rename from doc/diagrams/benchmarks/vs/running insertion.xlsx.practice norehash non-unique.png rename to doc/diagrams/benchmarks-set/vs/running insertion.xlsx.practice norehash non-unique.png diff --git a/doc/diagrams/benchmarks/vs/running insertion.xlsx.practice norehash.png b/doc/diagrams/benchmarks-set/vs/running insertion.xlsx.practice norehash.png similarity index 100% rename from doc/diagrams/benchmarks/vs/running insertion.xlsx.practice norehash.png rename to doc/diagrams/benchmarks-set/vs/running insertion.xlsx.practice norehash.png diff --git a/doc/diagrams/benchmarks/vs/running insertion.xlsx.practice.png b/doc/diagrams/benchmarks-set/vs/running insertion.xlsx.practice.png similarity index 100% rename from doc/diagrams/benchmarks/vs/running insertion.xlsx.practice.png rename to doc/diagrams/benchmarks-set/vs/running insertion.xlsx.practice.png diff --git a/doc/diagrams/benchmarks/vs/scattered erasure.xlsx.practice non-unique 5.png b/doc/diagrams/benchmarks-set/vs/scattered erasure.xlsx.practice non-unique 5.png similarity index 100% rename from doc/diagrams/benchmarks/vs/scattered erasure.xlsx.practice non-unique 5.png rename to doc/diagrams/benchmarks-set/vs/scattered erasure.xlsx.practice non-unique 5.png diff --git a/doc/diagrams/benchmarks/vs/scattered erasure.xlsx.practice non-unique.png b/doc/diagrams/benchmarks-set/vs/scattered erasure.xlsx.practice non-unique.png similarity index 100% rename from doc/diagrams/benchmarks/vs/scattered erasure.xlsx.practice non-unique.png rename to doc/diagrams/benchmarks-set/vs/scattered erasure.xlsx.practice non-unique.png diff --git a/doc/diagrams/benchmarks/vs/scattered erasure.xlsx.practice.png b/doc/diagrams/benchmarks-set/vs/scattered erasure.xlsx.practice.png similarity index 100% rename from doc/diagrams/benchmarks/vs/scattered erasure.xlsx.practice.png rename to doc/diagrams/benchmarks-set/vs/scattered erasure.xlsx.practice.png diff --git a/doc/diagrams/benchmarks/vs/scattered successful looukp.xlsx.practice non-unique 5.png b/doc/diagrams/benchmarks-set/vs/scattered successful looukp.xlsx.practice non-unique 5.png similarity index 100% rename from doc/diagrams/benchmarks/vs/scattered successful looukp.xlsx.practice non-unique 5.png rename to doc/diagrams/benchmarks-set/vs/scattered successful looukp.xlsx.practice non-unique 5.png diff --git a/doc/diagrams/benchmarks/vs/scattered successful looukp.xlsx.practice non-unique.png b/doc/diagrams/benchmarks-set/vs/scattered successful looukp.xlsx.practice non-unique.png similarity index 100% rename from doc/diagrams/benchmarks/vs/scattered successful looukp.xlsx.practice non-unique.png rename to doc/diagrams/benchmarks-set/vs/scattered successful looukp.xlsx.practice non-unique.png diff --git a/doc/diagrams/benchmarks/vs/scattered successful looukp.xlsx.practice.png b/doc/diagrams/benchmarks-set/vs/scattered successful looukp.xlsx.practice.png similarity index 100% rename from doc/diagrams/benchmarks/vs/scattered successful looukp.xlsx.practice.png rename to doc/diagrams/benchmarks-set/vs/scattered successful looukp.xlsx.practice.png diff --git a/doc/diagrams/benchmarks/vs/scattered unsuccessful looukp.xlsx.practice non-unique 5.png b/doc/diagrams/benchmarks-set/vs/scattered unsuccessful looukp.xlsx.practice non-unique 5.png similarity index 100% rename from doc/diagrams/benchmarks/vs/scattered unsuccessful looukp.xlsx.practice non-unique 5.png rename to doc/diagrams/benchmarks-set/vs/scattered unsuccessful looukp.xlsx.practice non-unique 5.png diff --git a/doc/diagrams/benchmarks/vs/scattered unsuccessful looukp.xlsx.practice non-unique.png b/doc/diagrams/benchmarks-set/vs/scattered unsuccessful looukp.xlsx.practice non-unique.png similarity index 100% rename from doc/diagrams/benchmarks/vs/scattered unsuccessful looukp.xlsx.practice non-unique.png rename to doc/diagrams/benchmarks-set/vs/scattered unsuccessful looukp.xlsx.practice non-unique.png diff --git a/doc/diagrams/benchmarks/vs/scattered unsuccessful looukp.xlsx.practice.png b/doc/diagrams/benchmarks-set/vs/scattered unsuccessful looukp.xlsx.practice.png similarity index 100% rename from doc/diagrams/benchmarks/vs/scattered unsuccessful looukp.xlsx.practice.png rename to doc/diagrams/benchmarks-set/vs/scattered unsuccessful looukp.xlsx.practice.png diff --git a/doc/diagrams/buckets-oa.png b/doc/diagrams/buckets-oa.png new file mode 100644 index 00000000..25fc6045 Binary files /dev/null and b/doc/diagrams/buckets-oa.png differ diff --git a/doc/unordered.adoc b/doc/unordered.adoc index deeff98e..07e09dbb 100644 --- a/doc/unordered.adoc +++ b/doc/unordered.adoc @@ -12,10 +12,10 @@ include::unordered/intro.adoc[] include::unordered/buckets.adoc[] -include::unordered/benchmarks.adoc[] include::unordered/hash_equality.adoc[] include::unordered/comparison.adoc[] include::unordered/compliance.adoc[] +include::unordered/benchmarks.adoc[] include::unordered/rationale.adoc[] include::unordered/ref.adoc[] include::unordered/changes.adoc[] diff --git a/doc/unordered/benchmarks.adoc b/doc/unordered/benchmarks.adoc index 23f2bc1d..e61cecb4 100644 --- a/doc/unordered/benchmarks.adoc +++ b/doc/unordered/benchmarks.adoc @@ -4,27 +4,29 @@ = Benchmarks -All benchmarks were created using `unordered_set` (non-duplicate) and `unordered_multiset` (duplicate). The source code can be https://github.com/joaquintides/boost_unordered_benchmark[found here]. +== boost::unordered_set + +All benchmarks were created using `unordered_set` (non-duplicate) and `unordered_multiset` (duplicate). The source code can be https://github.com/joaquintides/boost_unordered_benchmarks/tree/boost_unordered_set[found here^]. The insertion benchmarks insert `n` random values, where `n` is between 10,000 and 3 million. For the duplicated benchmarks, the same random values are repeated an average of 5 times. The erasure benchmarks erase all `n` elements randomly until the container is empty. -The successful lookup benchmarks are done by looking up all `n` values, in the their original insertion order. +The successful lookup benchmarks are done by looking up all `n` values, in their original insertion order. The unsuccessful lookup benchmarks use `n` randomly generated integers but using a different seed value. -== GCC 11 + libstdc++-v3 +=== GCC 11 + libstdc++-v3, x64 -=== Insertion +==== Insertion [caption=] [cols="3*^.^a", frame=all, grid=all] |=== -|image::benchmarks/gcc/running insertion.xlsx.practice.png[width=250,link=../diagrams/benchmarks/gcc/running insertion.xlsx.practice.png,window=_blank] -|image::benchmarks/gcc/running%20insertion.xlsx.practice non-unique.png[width=250,link=../diagrams/benchmarks/gcc/running%20insertion.xlsx.practice non-unique.png,window=_blank] -|image::benchmarks/gcc/running%20insertion.xlsx.practice non-unique 5.png[width=250,link=../diagrams/benchmarks/gcc/running%20insertion.xlsx.practice non-unique 5.png,window=_blank] +|image::benchmarks-set/gcc/running insertion.xlsx.practice.png[width=250,link=../diagrams/benchmarks-set/gcc/running insertion.xlsx.practice.png,window=_blank] +|image::benchmarks-set/gcc/running%20insertion.xlsx.practice non-unique.png[width=250,link=../diagrams/benchmarks-set/gcc/running%20insertion.xlsx.practice non-unique.png,window=_blank] +|image::benchmarks-set/gcc/running%20insertion.xlsx.practice non-unique 5.png[width=250,link=../diagrams/benchmarks-set/gcc/running%20insertion.xlsx.practice non-unique 5.png,window=_blank] h|non-duplicate elements h|duplicate elements @@ -36,9 +38,9 @@ max load factor 5 [cols="3*^.^a", frame=all, grid=all] |=== -|image::benchmarks/gcc/running%20insertion.xlsx.practice norehash.png[width=250,link=../diagrams/benchmarks/gcc/running%20insertion.xlsx.practice norehash.png,window=_blank] -|image::benchmarks/gcc/running%20insertion.xlsx.practice norehash non-unique.png[width=250,link=../diagrams/benchmarks/gcc/running%20insertion.xlsx.practice norehash non-unique.png,window=_blank] -|image::benchmarks/gcc/running%20insertion.xlsx.practice norehash non-unique 5.png[width=250,link=../diagrams/benchmarks/gcc/running%20insertion.xlsx.practice norehash non-unique 5.png,window=_blank] +|image::benchmarks-set/gcc/running%20insertion.xlsx.practice norehash.png[width=250,link=../diagrams/benchmarks-set/gcc/running%20insertion.xlsx.practice norehash.png,window=_blank] +|image::benchmarks-set/gcc/running%20insertion.xlsx.practice norehash non-unique.png[width=250,link=../diagrams/benchmarks-set/gcc/running%20insertion.xlsx.practice norehash non-unique.png,window=_blank] +|image::benchmarks-set/gcc/running%20insertion.xlsx.practice norehash non-unique 5.png[width=250,link=../diagrams/benchmarks-set/gcc/running%20insertion.xlsx.practice norehash non-unique 5.png,window=_blank] h|non-duplicate elements, + prior `reserve` @@ -50,15 +52,15 @@ prior `reserve` |=== -=== Erasure +==== Erasure [caption=] [cols="3*^.^a", frame=all, grid=all] |=== -|image::benchmarks/gcc/scattered%20erasure.xlsx.practice.png[width=250,link=../diagrams/benchmarks/gcc/scattered%20erasure.xlsx.practice.png,window=_blank] -|image::benchmarks/gcc/scattered%20erasure.xlsx.practice non-unique.png[width=250,link=../diagrams/benchmarks/gcc/scattered%20erasure.xlsx.practice non-unique.png,window=_blank] -|image::benchmarks/gcc/scattered%20erasure.xlsx.practice non-unique 5.png[width=250,link=../diagrams/benchmarks/gcc/scattered%20erasure.xlsx.practice non-unique 5.png,window=_blank] +|image::benchmarks-set/gcc/scattered%20erasure.xlsx.practice.png[width=250,link=../diagrams/benchmarks-set/gcc/scattered%20erasure.xlsx.practice.png,window=_blank] +|image::benchmarks-set/gcc/scattered%20erasure.xlsx.practice non-unique.png[width=250,link=../diagrams/benchmarks-set/gcc/scattered%20erasure.xlsx.practice non-unique.png,window=_blank] +|image::benchmarks-set/gcc/scattered%20erasure.xlsx.practice non-unique 5.png[width=250,link=../diagrams/benchmarks-set/gcc/scattered%20erasure.xlsx.practice non-unique 5.png,window=_blank] h|non-duplicate elements h|duplicate elements @@ -66,15 +68,15 @@ h|duplicate elements + max load factor 5 |=== -=== Successful Lookup +==== Successful Lookup [caption=] [cols="3*^.^a", frame=all, grid=all] |=== -|image::benchmarks/gcc/scattered%20successful%20looukp.xlsx.practice.png[width=250,window=_blank,link=../diagrams/benchmarks/gcc/scattered%20successful%20looukp.xlsx.practice.png] -|image::benchmarks/gcc/scattered%20successful%20looukp.xlsx.practice non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks/gcc/scattered%20successful%20looukp.xlsx.practice non-unique.png] -|image::benchmarks/gcc/scattered%20successful%20looukp.xlsx.practice non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks/gcc/scattered%20successful%20looukp.xlsx.practice non-unique 5.png] +|image::benchmarks-set/gcc/scattered%20successful%20looukp.xlsx.practice.png[width=250,window=_blank,link=../diagrams/benchmarks-set/gcc/scattered%20successful%20looukp.xlsx.practice.png] +|image::benchmarks-set/gcc/scattered%20successful%20looukp.xlsx.practice non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks-set/gcc/scattered%20successful%20looukp.xlsx.practice non-unique.png] +|image::benchmarks-set/gcc/scattered%20successful%20looukp.xlsx.practice non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks-set/gcc/scattered%20successful%20looukp.xlsx.practice non-unique 5.png] h|non-duplicate elements h|duplicate elements @@ -83,15 +85,15 @@ max load factor 5 |=== -=== Unsuccessful lookup +==== Unsuccessful lookup [caption=] [cols="3*^.^a", frame=all, grid=all] |=== -|image::benchmarks/gcc/scattered%20unsuccessful%20looukp.xlsx.practice.png[width=250,window=_blank,link=../diagrams/benchmarks/gcc/scattered%20unsuccessful%20looukp.xlsx.practice.png] -|image::benchmarks/gcc/scattered%20unsuccessful%20looukp.xlsx.practice non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks/gcc/scattered%20unsuccessful%20looukp.xlsx.practice non-unique.png] -|image::benchmarks/gcc/scattered%20unsuccessful%20looukp.xlsx.practice non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks/gcc/scattered%20unsuccessful%20looukp.xlsx.practice non-unique 5.png] +|image::benchmarks-set/gcc/scattered%20unsuccessful%20looukp.xlsx.practice.png[width=250,window=_blank,link=../diagrams/benchmarks-set/gcc/scattered%20unsuccessful%20looukp.xlsx.practice.png] +|image::benchmarks-set/gcc/scattered%20unsuccessful%20looukp.xlsx.practice non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks-set/gcc/scattered%20unsuccessful%20looukp.xlsx.practice non-unique.png] +|image::benchmarks-set/gcc/scattered%20unsuccessful%20looukp.xlsx.practice non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks-set/gcc/scattered%20unsuccessful%20looukp.xlsx.practice non-unique 5.png] h|non-duplicate elements h|duplicate elements @@ -100,17 +102,17 @@ max load factor 5 |=== -== Clang 12 + libc++ +=== Clang 12 + libc++, x64 -=== Insertion +==== Insertion [caption=] [cols="3*^.^a", frame=all, grid=all] |=== -|image::benchmarks/clang_libcpp/running%20insertion.xlsx.practice.png[width=250, window=_blank,link=../diagrams/benchmarks/clang_libcpp/running%20insertion.xlsx.practice.png] -|image::benchmarks/clang_libcpp/running%20insertion.xlsx.practice non-unique.png[width=250, window=_blank,link=../diagrams/benchmarks/clang_libcpp/running%20insertion.xlsx.practice non-unique.png] -|image::benchmarks/clang_libcpp/running%20insertion.xlsx.practice non-unique 5.png[width=250, window=_blank,link=../diagrams/benchmarks/clang_libcpp/running%20insertion.xlsx.practice non-unique 5.png] +|image::benchmarks-set/clang_libcpp/running%20insertion.xlsx.practice.png[width=250, window=_blank,link=../diagrams/benchmarks-set/clang_libcpp/running%20insertion.xlsx.practice.png] +|image::benchmarks-set/clang_libcpp/running%20insertion.xlsx.practice non-unique.png[width=250, window=_blank,link=../diagrams/benchmarks-set/clang_libcpp/running%20insertion.xlsx.practice non-unique.png] +|image::benchmarks-set/clang_libcpp/running%20insertion.xlsx.practice non-unique 5.png[width=250, window=_blank,link=../diagrams/benchmarks-set/clang_libcpp/running%20insertion.xlsx.practice non-unique 5.png] h|non-duplicate elements h|duplicate elements @@ -123,9 +125,9 @@ max load factor 5 [cols="3*^.^a", frame=all, grid=all] |=== -|image::benchmarks/clang_libcpp/running%20insertion.xlsx.practice norehash.png[width=250,window=_blank,link=../diagrams/benchmarks/clang_libcpp/running%20insertion.xlsx.practice norehash.png] -|image::benchmarks/clang_libcpp/running%20insertion.xlsx.practice norehash non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks/clang_libcpp/running%20insertion.xlsx.practice norehash non-unique.png] -|image::benchmarks/clang_libcpp/running%20insertion.xlsx.practice norehash non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks/clang_libcpp/running%20insertion.xlsx.practice norehash non-unique 5.png] +|image::benchmarks-set/clang_libcpp/running%20insertion.xlsx.practice norehash.png[width=250,window=_blank,link=../diagrams/benchmarks-set/clang_libcpp/running%20insertion.xlsx.practice norehash.png] +|image::benchmarks-set/clang_libcpp/running%20insertion.xlsx.practice norehash non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks-set/clang_libcpp/running%20insertion.xlsx.practice norehash non-unique.png] +|image::benchmarks-set/clang_libcpp/running%20insertion.xlsx.practice norehash non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks-set/clang_libcpp/running%20insertion.xlsx.practice norehash non-unique 5.png] h|non-duplicate elements, + prior `reserve` @@ -137,15 +139,15 @@ prior `reserve` |=== -=== Erasure +==== Erasure [caption=] [cols="3*^.^a", frame=all, grid=all] |=== -|image::benchmarks/clang_libcpp/scattered%20erasure.xlsx.practice.png[width=250,window=_blank,link=../diagrams/benchmarks/clang_libcpp/scattered%20erasure.xlsx.practice.png] -|image::benchmarks/clang_libcpp/scattered%20erasure.xlsx.practice non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks/clang_libcpp/scattered%20erasure.xlsx.practice non-unique.png] -|image::benchmarks/clang_libcpp/scattered%20erasure.xlsx.practice non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks/clang_libcpp/scattered%20erasure.xlsx.practice non-unique 5.png] +|image::benchmarks-set/clang_libcpp/scattered%20erasure.xlsx.practice.png[width=250,window=_blank,link=../diagrams/benchmarks-set/clang_libcpp/scattered%20erasure.xlsx.practice.png] +|image::benchmarks-set/clang_libcpp/scattered%20erasure.xlsx.practice non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks-set/clang_libcpp/scattered%20erasure.xlsx.practice non-unique.png] +|image::benchmarks-set/clang_libcpp/scattered%20erasure.xlsx.practice non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks-set/clang_libcpp/scattered%20erasure.xlsx.practice non-unique 5.png] h|non-duplicate elements h|duplicate elements @@ -154,15 +156,15 @@ max load factor 5 |=== -=== Successful lookup +==== Successful lookup [caption=] [cols="3*^.^a", frame=all, grid=all] |=== -|image::benchmarks/clang_libcpp/scattered%20successful%20looukp.xlsx.practice.png[width=250,window=_blank,link=../diagrams/benchmarks/clang_libcpp/scattered%20successful%20looukp.xlsx.practice.png] -|image::benchmarks/clang_libcpp/scattered%20successful%20looukp.xlsx.practice non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks/clang_libcpp/scattered%20successful%20looukp.xlsx.practice non-unique.png] -|image::benchmarks/clang_libcpp/scattered%20successful%20looukp.xlsx.practice non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks/clang_libcpp/scattered%20successful%20looukp.xlsx.practice non-unique 5.png] +|image::benchmarks-set/clang_libcpp/scattered%20successful%20looukp.xlsx.practice.png[width=250,window=_blank,link=../diagrams/benchmarks-set/clang_libcpp/scattered%20successful%20looukp.xlsx.practice.png] +|image::benchmarks-set/clang_libcpp/scattered%20successful%20looukp.xlsx.practice non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks-set/clang_libcpp/scattered%20successful%20looukp.xlsx.practice non-unique.png] +|image::benchmarks-set/clang_libcpp/scattered%20successful%20looukp.xlsx.practice non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks-set/clang_libcpp/scattered%20successful%20looukp.xlsx.practice non-unique 5.png] h|non-duplicate elements h|duplicate elements @@ -171,15 +173,15 @@ max load factor 5 |=== -=== Unsuccessful lookup +==== Unsuccessful lookup [caption=] [cols="3*^.^a", frame=all, grid=all] |=== -|image::benchmarks/clang_libcpp/scattered%20unsuccessful%20looukp.xlsx.practice.png[width=250,window=_blank,link=../diagrams/benchmarks/clang_libcpp/scattered%20unsuccessful%20looukp.xlsx.practice.png] -|image::benchmarks/clang_libcpp/scattered%20unsuccessful%20looukp.xlsx.practice non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks/clang_libcpp/scattered%20unsuccessful%20looukp.xlsx.practice non-unique.png] -|image::benchmarks/clang_libcpp/scattered%20unsuccessful%20looukp.xlsx.practice non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks/clang_libcpp/scattered%20unsuccessful%20looukp.xlsx.practice non-unique 5.png] +|image::benchmarks-set/clang_libcpp/scattered%20unsuccessful%20looukp.xlsx.practice.png[width=250,window=_blank,link=../diagrams/benchmarks-set/clang_libcpp/scattered%20unsuccessful%20looukp.xlsx.practice.png] +|image::benchmarks-set/clang_libcpp/scattered%20unsuccessful%20looukp.xlsx.practice non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks-set/clang_libcpp/scattered%20unsuccessful%20looukp.xlsx.practice non-unique.png] +|image::benchmarks-set/clang_libcpp/scattered%20unsuccessful%20looukp.xlsx.practice non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks-set/clang_libcpp/scattered%20unsuccessful%20looukp.xlsx.practice non-unique 5.png] h|non-duplicate elements h|duplicate elements @@ -188,17 +190,17 @@ max load factor 5 |=== -== Visual Studio 2019 + Dinkumware +=== Visual Studio 2019 + Dinkumware, x64 -=== Insertion +==== Insertion [caption=] [cols="3*^.^a", frame=all, grid=all] |=== -|image::benchmarks/vs/running%20insertion.xlsx.practice.png[width=250,window=_blank,link=../diagrams/benchmarks/vs/running%20insertion.xlsx.practice.png] -|image::benchmarks/vs/running%20insertion.xlsx.practice non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks/vs/running%20insertion.xlsx.practice non-unique.png] -|image::benchmarks/vs/running%20insertion.xlsx.practice non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks/vs/running%20insertion.xlsx.practice non-unique 5.png] +|image::benchmarks-set/vs/running%20insertion.xlsx.practice.png[width=250,window=_blank,link=../diagrams/benchmarks-set/vs/running%20insertion.xlsx.practice.png] +|image::benchmarks-set/vs/running%20insertion.xlsx.practice non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks-set/vs/running%20insertion.xlsx.practice non-unique.png] +|image::benchmarks-set/vs/running%20insertion.xlsx.practice non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks-set/vs/running%20insertion.xlsx.practice non-unique 5.png] h|non-duplicate elements h|duplicate elements @@ -211,9 +213,9 @@ max load factor 5 [cols="3*^.^a", frame=all, grid=all] |=== -|image::benchmarks/vs/running%20insertion.xlsx.practice norehash.png[width=250,window=_blank,link=../diagrams/benchmarks/vs/running%20insertion.xlsx.practice norehash.png] -|image::benchmarks/vs/running%20insertion.xlsx.practice norehash non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks/vs/running%20insertion.xlsx.practice norehash non-unique.png] -|image::benchmarks/vs/running%20insertion.xlsx.practice norehash non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks/vs/running%20insertion.xlsx.practice norehash non-unique 5.png] +|image::benchmarks-set/vs/running%20insertion.xlsx.practice norehash.png[width=250,window=_blank,link=../diagrams/benchmarks-set/vs/running%20insertion.xlsx.practice norehash.png] +|image::benchmarks-set/vs/running%20insertion.xlsx.practice norehash non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks-set/vs/running%20insertion.xlsx.practice norehash non-unique.png] +|image::benchmarks-set/vs/running%20insertion.xlsx.practice norehash non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks-set/vs/running%20insertion.xlsx.practice norehash non-unique 5.png] h|non-duplicate elements, + prior `reserve` @@ -225,15 +227,15 @@ prior `reserve` |=== -=== Erasure +==== Erasure [caption=] [cols="3*^.^a", frame=all, grid=all] |=== -|image::benchmarks/vs/scattered%20erasure.xlsx.practice.png[width=250,window=_blank,link=../diagrams/benchmarks/vs/scattered%20erasure.xlsx.practice.png] -|image::benchmarks/vs/scattered%20erasure.xlsx.practice non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks/vs/scattered%20erasure.xlsx.practice non-unique.png] -|image::benchmarks/vs/scattered%20erasure.xlsx.practice non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks/vs/scattered%20erasure.xlsx.practice non-unique 5.png] +|image::benchmarks-set/vs/scattered%20erasure.xlsx.practice.png[width=250,window=_blank,link=../diagrams/benchmarks-set/vs/scattered%20erasure.xlsx.practice.png] +|image::benchmarks-set/vs/scattered%20erasure.xlsx.practice non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks-set/vs/scattered%20erasure.xlsx.practice non-unique.png] +|image::benchmarks-set/vs/scattered%20erasure.xlsx.practice non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks-set/vs/scattered%20erasure.xlsx.practice non-unique 5.png] h|non-duplicate elements h|duplicate elements @@ -242,15 +244,15 @@ max load factor 5 |=== -=== Successful lookup +==== Successful lookup [caption=] [cols="3*^.^a", frame=all, grid=all] |=== -|image::benchmarks/vs/scattered%20successful%20looukp.xlsx.practice.png[width=250,window=_blank,link=../diagrams/benchmarks/vs/scattered%20successful%20looukp.xlsx.practice.png] -|image::benchmarks/vs/scattered%20successful%20looukp.xlsx.practice non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks/vs/scattered%20successful%20looukp.xlsx.practice non-unique.png] -|image::benchmarks/vs/scattered%20successful%20looukp.xlsx.practice non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks/vs/scattered%20successful%20looukp.xlsx.practice non-unique 5.png] +|image::benchmarks-set/vs/scattered%20successful%20looukp.xlsx.practice.png[width=250,window=_blank,link=../diagrams/benchmarks-set/vs/scattered%20successful%20looukp.xlsx.practice.png] +|image::benchmarks-set/vs/scattered%20successful%20looukp.xlsx.practice non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks-set/vs/scattered%20successful%20looukp.xlsx.practice non-unique.png] +|image::benchmarks-set/vs/scattered%20successful%20looukp.xlsx.practice non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks-set/vs/scattered%20successful%20looukp.xlsx.practice non-unique 5.png] h|non-duplicate elements h|duplicate elements @@ -259,15 +261,15 @@ max load factor 5 |=== -=== Unsuccessful lookup +==== Unsuccessful lookup [caption=] [cols="3*^.^a", frame=all, grid=all] |=== -|image::benchmarks/vs/scattered%20unsuccessful%20looukp.xlsx.practice.png[width=250,window=_blank,link=../diagrams/benchmarks/vs/scattered%20unsuccessful%20looukp.xlsx.practice.png] -|image::benchmarks/vs/scattered%20unsuccessful%20looukp.xlsx.practice non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks/vs/scattered%20unsuccessful%20looukp.xlsx.practice non-unique.png] -|image::benchmarks/vs/scattered%20unsuccessful%20looukp.xlsx.practice non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks/vs/scattered%20unsuccessful%20looukp.xlsx.practice non-unique 5.png] +|image::benchmarks-set/vs/scattered%20unsuccessful%20looukp.xlsx.practice.png[width=250,window=_blank,link=../diagrams/benchmarks-set/vs/scattered%20unsuccessful%20looukp.xlsx.practice.png] +|image::benchmarks-set/vs/scattered%20unsuccessful%20looukp.xlsx.practice non-unique.png[width=250,window=_blank,link=../diagrams/benchmarks-set/vs/scattered%20unsuccessful%20looukp.xlsx.practice non-unique.png] +|image::benchmarks-set/vs/scattered%20unsuccessful%20looukp.xlsx.practice non-unique 5.png[width=250,window=_blank,link=../diagrams/benchmarks-set/vs/scattered%20unsuccessful%20looukp.xlsx.practice non-unique 5.png] h|non-duplicate elements h|duplicate elements @@ -275,3 +277,156 @@ h|duplicate elements, + max load factor 5 |=== + +== boost::unordered_flat_map + +All benchmarks were created using: + +* `https://abseil.io/docs/cpp/guides/container[absl::flat_hash_map^]` +* `boost::unordered_flat_map` +* `boost::unordered_map` + +The source code can be https://github.com/joaquintides/boost_unordered_benchmarks/tree/boost_unordered_flat_map[found here^]. + +The insertion benchmarks insert `n` random values, where `n` is between 10,000 and 10 million. + +The erasure benchmarks erase traverse the `n` elements and erase those with odd key (50% on average). + +The successful lookup benchmarks are done by looking up all `n` values, in their original insertion order. + +The unsuccessful lookup benchmarks use `n` randomly generated integers but using a different seed value. + + +=== GCC 11, x64 + + +[caption=] +[cols="4*^.^a", frame=all, grid=all] +|=== + +|image::benchmarks-flat_map/gcc-x64/Running%20insertion.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/gcc-x64/Running%20insertion.xlsx.plot.png] +|image::benchmarks-flat_map/gcc-x64/Running%20erasure.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/gcc-x64/Running%20erasure.xlsx.plot.png] +|image::benchmarks-flat_map/gcc-x64/Scattered%20successful%20looukp.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/gcc-x64/Scattered%20successful%20looukp.xlsx.plot.png] +|image::benchmarks-flat_map/gcc-x64/Scattered%20unsuccessful%20looukp.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/gcc-x64/Scattered%20unsuccessful%20looukp.xlsx.plot.png] + +h|running insertion +h|running erasure +h|successful lookup +h|unsuccessful lookup + +|=== + +=== Clang 12, x64 + + +[caption=] +[cols="4*^.^a", frame=all, grid=all] +|=== + +|image::benchmarks-flat_map/clang-x64/Running%20insertion.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/clang-x64/Running%20insertion.xlsx.plot.png] +|image::benchmarks-flat_map/clang-x64/Running%20erasure.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/clang-x64/Running%20erasure.xlsx.plot.png] +|image::benchmarks-flat_map/clang-x64/Scattered%20successful%20looukp.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/clang-x64/Scattered%20successful%20looukp.xlsx.plot.png] +|image::benchmarks-flat_map/clang-x64/Scattered%20unsuccessful%20looukp.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/clang-x64/Scattered%20unsuccessful%20looukp.xlsx.plot.png] + +h|running insertion +h|running erasure +h|successful lookup +h|unsuccessful lookup + +|=== + +=== Visual Studio 2019, x64 + + +[caption=] +[cols="4*^.^a", frame=all, grid=all] +|=== + +|image::benchmarks-flat_map/vs-x64/Running%20insertion.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/vs-x64/Running%20insertion.xlsx.plot.png] +|image::benchmarks-flat_map/vs-x64/Running%20erasure.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/vs-x64/Running%20erasure.xlsx.plot.png] +|image::benchmarks-flat_map/vs-x64/Scattered%20successful%20looukp.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/vs-x64/Scattered%20successful%20looukp.xlsx.plot.png] +|image::benchmarks-flat_map/vs-x64/Scattered%20unsuccessful%20looukp.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/vs-x64/Scattered%20unsuccessful%20looukp.xlsx.plot.png] + +h|running insertion +h|running erasure +h|successful lookup +h|unsuccessful lookup + +|=== + +=== Clang 12, ARM64 + + +[caption=] +[cols="4*^.^a", frame=all, grid=all] +|=== + +|image::benchmarks-flat_map/clang-arm64/Running%20insertion.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/clang-arm64/Running%20insertion.xlsx.plot.png] +|image::benchmarks-flat_map/clang-arm64/Running%20erasure.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/clang-arm64/Running%20erasure.xlsx.plot.png] +|image::benchmarks-flat_map/clang-arm64/Scattered%20successful%20looukp.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/clang-arm64/Scattered%20successful%20looukp.xlsx.plot.png] +|image::benchmarks-flat_map/clang-arm64/Scattered%20unsuccessful%20looukp.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/clang-arm64/Scattered%20unsuccessful%20looukp.xlsx.plot.png] + +h|running insertion +h|running erasure +h|successful lookup +h|unsuccessful lookup + +|=== + +=== GCC 11, x86 + + +[caption=] +[cols="4*^.^a", frame=all, grid=all] +|=== + +|image::benchmarks-flat_map/gcc-x86/Running%20insertion.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/gcc-x86/Running%20insertion.xlsx.plot.png] +|image::benchmarks-flat_map/gcc-x86/Running%20erasure.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/gcc-x86/Running%20erasure.xlsx.plot.png] +|image::benchmarks-flat_map/gcc-x86/Scattered%20successful%20looukp.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/gcc-x86/Scattered%20successful%20looukp.xlsx.plot.png] +|image::benchmarks-flat_map/gcc-x86/Scattered%20unsuccessful%20looukp.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/gcc-x86/Scattered%20unsuccessful%20looukp.xlsx.plot.png] + +h|running insertion +h|running erasure +h|successful lookup +h|unsuccessful lookup + +|=== + +=== Clang 12, x64 + + +[caption=] +[cols="4*^.^a", frame=all, grid=all] +|=== + +|image::benchmarks-flat_map/clang-x86/Running%20insertion.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/clang-x86/Running%20insertion.xlsx.plot.png] +|image::benchmarks-flat_map/clang-x86/Running%20erasure.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/clang-x86/Running%20erasure.xlsx.plot.png] +|image::benchmarks-flat_map/clang-x86/Scattered%20successful%20looukp.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/clang-x86/Scattered%20successful%20looukp.xlsx.plot.png] +|image::benchmarks-flat_map/clang-x86/Scattered%20unsuccessful%20looukp.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/clang-x86/Scattered%20unsuccessful%20looukp.xlsx.plot.png] + +h|running insertion +h|running erasure +h|successful lookup +h|unsuccessful lookup + +|=== + +=== Visual Studio 2019, x86 + + +[caption=] +[cols="4*^.^a", frame=all, grid=all] +|=== + +|image::benchmarks-flat_map/vs-x86/Running%20insertion.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/vs-x86/Running%20insertion.xlsx.plot.png] +|image::benchmarks-flat_map/vs-x86/Running%20erasure.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/vs-x86/Running%20erasure.xlsx.plot.png] +|image::benchmarks-flat_map/vs-x86/Scattered%20successful%20looukp.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/vs-x86/Scattered%20successful%20looukp.xlsx.plot.png] +|image::benchmarks-flat_map/vs-x86/Scattered%20unsuccessful%20looukp.xlsx.plot.png[width=250,window=_blank,link=../diagrams/benchmarks-flat_map/vs-x86/Scattered%20unsuccessful%20looukp.xlsx.plot.png] + +h|running insertion +h|running erasure +h|successful lookup +h|unsuccessful lookup + +|=== + diff --git a/doc/unordered/bibliography.adoc b/doc/unordered/bibliography.adoc index 5a2e3f11..020d3c04 100644 --- a/doc/unordered/bibliography.adoc +++ b/doc/unordered/bibliography.adoc @@ -5,6 +5,8 @@ = Bibliography * _C/C++ Users Journal_. February, 2006. Pete Becker. http://www.ddj.com/cpp/184402066[STL and TR1: Part III - Unordered containers^]. + -An introducation to the standard unordered containers. - +An introduction to the standard unordered containers. +* _Wikipedia_. https://en.wikipedia.org/wiki/Hash_table[Hash table^]. + +An introduction to hash table implementations. Discusses the differences between closed-addressing and open-addressing approaches. +* Peter Dimov, 2022. https://pdimov.github.io/articles/unordered_dev_plan.html[Development Plan for Boost.Unordered^]. diff --git a/doc/unordered/buckets.adoc b/doc/unordered/buckets.adoc index e25b72fd..0844b81d 100644 --- a/doc/unordered/buckets.adoc +++ b/doc/unordered/buckets.adoc @@ -37,7 +37,7 @@ keep collisions to a minimum. If instead of `boost::unordered_set` we had used <>, the diagram would look as follows: -image::buckets oa.png[] +image::buckets-oa.png[] In open-addressing containers, buckets can hold at most one element; if a collision happens (like is the case of `D` in the example), the element uses some other available bucket in @@ -144,9 +144,9 @@ h|*Method* h|*Description* A note on `max_load` for open-addressing containers: the maximum load will naturally decrease when new insertions are performed, but _won't_ increase at the same rate when erasing: for instance, -adding 1,000 elements to a <> and then -erasing those 1,000 elements will typically reduce the maximum load by around 160 rather -than restoring it to its original value. This is done internally by Boost.Unordered in order +adding 1,000 elements to a <> under high load +conditions and then erasing 1,000 elements will typically reduce the maximum load by around +a few dozen elements rather than restoring it to its original value. This is done internally by Boost.Unordered in order to keep its performance stable, and must be taken into account when planning for rehash-free insertions. The maximum load will be reset to its theoretical maximum (`max_load_factor() * bucket_count()`) right after `rehash`. diff --git a/doc/unordered/compliance.adoc b/doc/unordered/compliance.adoc index 4e248614..f8e0b05d 100644 --- a/doc/unordered/compliance.adoc +++ b/doc/unordered/compliance.adoc @@ -7,9 +7,9 @@ == Closed-addressing containers: unordered_[multi]set, unordered_[multi]map -The intent of Boost.Unordered is to implement a close (but imperfect) -implementation of the {cpp}17 standard, that will work with {cpp}98 upwards. -The wide compatibility does mean some comprimises have to be made. +The intent of Boost.Unordered is to provide a conformant +implementation of the {cpp}20 standard that will work with {cpp}98 upwards. +This wide compatibility does mean some compromises have to be made. With a compiler and library that fully support {cpp}11, the differences should be minor. @@ -139,5 +139,5 @@ The main differences with C++ unordered associative containers are: * `erase(iterator)` returns `void` instead of an iterator to the following element. * There is no API for bucket handling (except `bucket_count`) or node extraction/insertion. * The maximum load factor of the container is managed internally and can't be set by the user. The maximum load, -exposed through the public function `max_load`, can not increase monotonically with the number of erasures. +exposed through the public function `max_load`, does not increase monotonically with the number of erasures. diff --git a/doc/unordered/rationale.adoc b/doc/unordered/rationale.adoc index a67eb9c0..5541cf52 100644 --- a/doc/unordered/rationale.adoc +++ b/doc/unordered/rationale.adoc @@ -17,7 +17,7 @@ has a good summary of the implementation issues for hash tables in general. === Data Structure By specifying an interface for accessing the buckets of the container the -standard pretty much requires that the hash table uses chained addressing. +standard pretty much requires that the hash table uses closed addressing. It would be conceivable to write a hash table that uses another method. For example, it could use open addressing, and use the lookup chain to act as a @@ -34,10 +34,10 @@ bucket but there are some serious problems with this: restrictions could prevent a rehash when it's really needed. The maximum load factor could be set to a fairly low value to work around this - but the standard requires that it is initially set to 1.0. -* And since the standard is written with a eye towards chained +* And since the standard is written with a eye towards closed addressing, users will be surprised if the performance doesn't reflect that. -So chained addressing is used. +So closed addressing is used. === Number of Buckets @@ -89,8 +89,8 @@ We discuss here the most relevant principles. Given its rich functionality and cross-platform interoperability, `boost::hash` remains the default hash function of `boost::unordered_flat_set` and `boost::unordered_flat_map`. -As it happens, `boost::hash` for integral and other basic types does not provide -the good statistical properties required by open addressing; to cope with this, +As it happens, `boost::hash` for integral and other basic types does not possess +the statistical properties required by open addressing; to cope with this, we implement a post-mixing stage: * 64-bit architectures: we use the `xmx` function defined in @@ -112,4 +112,4 @@ operations. Although the implementation internally uses SIMD technologies, such as https://en.wikipedia.org/wiki/SSE2[SSE2^] and https://en.wikipedia.org/wiki/ARM_architecture_family#Advanced_SIMD_(NEON)[Neon^], when available, this does not affect interoperatility. For instance, the behavior is the same -for Visual Studio on an Intel CPU with SSE2 in x64 and for GCC on an IBM s390x without any supported SIMD technology. +for Visual Studio on an x64-mode Intel CPU with SSE2 and for GCC on an IBM s390x without any supported SIMD technology. diff --git a/doc/unordered/ref.adoc b/doc/unordered/ref.adoc index bb4b83e9..f118ac05 100644 --- a/doc/unordered/ref.adoc +++ b/doc/unordered/ref.adoc @@ -7,3 +7,4 @@ include::unordered_set.adoc[] include::unordered_multiset.adoc[] include::hash_traits.adoc[] include::unordered_flat_map.adoc[] +include::unordered_flat_set.adoc[] diff --git a/doc/unordered/unordered_flat_map.adoc b/doc/unordered/unordered_flat_map.adoc index e3a41a96..311b8794 100644 --- a/doc/unordered/unordered_flat_map.adoc +++ b/doc/unordered/unordered_flat_map.adoc @@ -145,12 +145,6 @@ namespace boost { template iterator xref:#unordered_flat_map_insert_or_assign_with_hint[insert_or_assign](const_iterator hint, key_type&& k, M&& obj); - node_type xref:#unordered_flat_map_extract_by_iterator[extract](const_iterator position); - node_type xref:#unordered_flat_map_extract_by_key[extract](const key_type& k); - template node_type xref:#unordered_flat_map_transparent_extract_by_key[extract](K&& k); - insert_return_type xref:#unordered_flat_map_insert_with_node_handle[insert](node_type&& nh); - iterator xref:#unordered_flat_map_insert_with_hint_and_node_handle[insert](const_iterator hint, node_type&& nh); - void xref:#unordered_flat_map_erase_by_position[erase](iterator position); void xref:#unordered_flat_map_erase_by_position[erase](const_iterator position); size_type xref:#unordered_flat_map_erase_by_key[erase](const key_type& k); @@ -204,6 +198,7 @@ namespace boost { float xref:#unordered_flat_map_load_factor[load_factor]() const noexcept; float xref:#unordered_flat_map_max_load_factor[max_load_factor]() const noexcept; void xref:#unordered_flat_map_set_max_load_factor[max_load_factor](float z); + size_type xref:#unordered_flat_map_max_load[max_load]() const noexcept; void xref:#unordered_flat_map_rehash[rehash](size_type n); void xref:#unordered_flat_map_reserve[reserve](size_type n); }; @@ -250,7 +245,7 @@ https://en.cppreference.com/w/cpp/named_req/Erasable[Erasable^] from the contain |A unary function object type that acts a hash function for a `Key`. It takes a single argument of type `Key` and returns a value of type `std::size_t`. |_Pred_ -|A binary function object that implements an equivalence relation on values of type `Key`. A binary function object that induces an equivalence relation on values of type `Key`. It takes two arguments of type `Key` and returns a value of type `bool`. +|A binary function object that induces an equivalence relation on values of type `Key`. It takes two arguments of type `Key` and returns a value of type `bool`. |_Allocator_ |An allocator whose value type is the same as the container's value type. @@ -266,7 +261,7 @@ original position is used. The size of the bucket array can be automatically increased by a call to `insert`/`emplace`, or as a result of calling `rehash`/`reserve`. The _load factor_ of the container (number of elements divided by number of buckets) is never greater than `max_load_factor()`, except possibly for small sizes where the implementation may decide to -allow for higher load factors. +allow for higher loads. If `xref:hash_traits_hash_is_avalanching[hash_is_avalanching]::value` is `true`, the hash function is used as-is; otherwise, a bit-mixing post-processing stage is added to increase the quality of hashing @@ -317,9 +312,9 @@ Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` ==== Bucket Count Constructor ```c++ explicit unordered_flat_map(size_type n, - const hasher& hf = hasher(), - const key_equal& eql = key_equal(), - const allocator_type& a = allocator_type()); + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); ``` Constructs an empty container with at least `n` buckets, using `hf` as the hash @@ -563,7 +558,7 @@ const_iterator begin() const noexcept; [horizontal] Returns:;; An iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container. -Complexity:;; Linear +Complexity:;; O(`bucket_count()`) --- @@ -585,7 +580,7 @@ const_iterator cbegin() const noexcept; [horizontal] Returns:;; A `const_iterator` referring to the first element of the container, or if the container is empty the past-the-end value for the container. -Complexity:;; Linear +Complexity:;; O(`bucket_count()`) --- @@ -649,7 +644,7 @@ Returns:;; The `bool` component of the return type is `true` if an insert took p + If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect. -Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load factor to be greater than the maximum load factor. + +Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load. + --- @@ -668,7 +663,7 @@ Returns:;; The `bool` component of the return type is `true` if an insert took p + If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect. -Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load factor to be greater than the maximum load factor. + +Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load. + --- @@ -686,7 +681,7 @@ Returns:;; The `bool` component of the return type is `true` if an insert took p + If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect. -Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load factor to be greater than the maximum load factor. + +Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load. + + A call of the form `insert(x)`, where `x` is equally convertible to both `const value_type&` and `const init_type&`, is not ambiguous and selects the `init_type` overload. @@ -706,7 +701,7 @@ Returns:;; The `bool` component of the return type is `true` if an insert took p + If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect. -Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load factor to be greater than the maximum load factor. + +Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load. + + A call of the form `insert(x)`, where `x` is equally convertible to both `value_type&&` and `init_type&&`, is not ambiguous and selects the `init_type` overload. @@ -727,7 +722,7 @@ Returns:;; The `bool` component of the return type is `true` if an insert took p + If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect. -Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load factor to be greater than the maximum load factor. + +Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load. + + A call of the form `insert(hint, x)`, where `x` is equally convertible to both `const value_type&` and `const init_type&`, is not ambiguous and selects the `init_type` overload. @@ -749,7 +744,7 @@ Returns:;; The `bool` component of the return type is `true` if an insert took p + If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect. -Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load factor to be greater than the maximum load factor. + +Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load. + + A call of the form `insert(hint, x)`, where `x` is equally convertible to both `value_type&&` and `init_type&&`, is not ambiguous and selects the `init_type` overload. @@ -765,7 +760,7 @@ Inserts a range of elements into the container. Elements are inserted if and onl [horizontal] Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into the container from `*first`. Throws:;; When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect. -Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load factor to be greater than the maximum load factor. +Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load. --- @@ -779,7 +774,7 @@ Inserts a range of elements into the container. Elements are inserted if and onl [horizontal] Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into the container from `*first`. Throws:;; When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect. -Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load factor to be greater than the maximum load factor. +Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load. --- @@ -812,7 +807,7 @@ value_type(std::piecewise_construct, unlike xref:#unordered_flat_map_emplace[emplace], which simply forwards all arguments to ``value_type``'s constructor. -Can invalidate iterators pointers and references, but only if the insert causes the load factor to be greater than the maximum load factor. +Can invalidate iterators pointers and references, but only if the insert causes the load to be greater than the maximum load. -- @@ -847,7 +842,7 @@ value_type(std::piecewise_construct, unlike xref:#unordered_flat_map_emplace_hint[emplace_hint], which simply forwards all arguments to ``value_type``'s constructor. -Can invalidate iterators pointers and references, but only if the insert causes the load factor to be greater than the maximum load factor. +Can invalidate iterators pointers and references, but only if the insert causes the load to be greater than the maximum load. -- @@ -877,7 +872,7 @@ Returns:;; The `bool` component of the return type is `true` if an insert took p + If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect. -Notes:;; Can invalidate iterators pointers and references, but only if the insert causes the load factor to be greater than the maximum load factor. + +Notes:;; Can invalidate iterators pointers and references, but only if the insert causes the load to be greater than the maximum load. + --- @@ -905,7 +900,7 @@ value_type(std::piecewise_construct, [horizontal] Returns:;; If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect. -Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load factor to be greater than the maximum load factor. +Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load. --- @@ -991,7 +986,7 @@ void clear() noexcept; Erases all elements in the container. [horizontal] -Postconditions:;; `size() == 0` +Postconditions:;; `size() == 0`, `max_load() >= max_load_factor() * bucket_count()` --- @@ -1108,7 +1103,7 @@ mapped_type& operator[](key_type&& k); Effects:;; If the container does not already contain an element with a key equivalent to `k`, inserts the value `std::pair(k, mapped_type())`. Returns:;; A reference to `x.second` where `x` is the element already in the container, or the newly inserted element with a key equivalent to `k`. Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect. -Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load factor to be greater than the maximum load factor. +Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load. --- @@ -1170,6 +1165,19 @@ Effects:;; Does nothing, as the user is not allowed to change this parameter. Ke --- +==== max_load + +```c++ +size_type max_load() const noexcept; +``` + +[horizontal] +Returns:;; The maximum number of elements the container can hold without rehashing, assuming that no further elements will be erased. +Note:;; After construction, rehash or clearance, the container's maximum load is at least `max_load_factor() * bucket_count()`. This load will decrease by the number of elements inserted, +but won't increase at the same rate on erasure. + +--- + ==== rehash ```c++ void rehash(size_type n); diff --git a/doc/unordered/unordered_flat_set.adoc b/doc/unordered/unordered_flat_set.adoc new file mode 100644 index 00000000..7a122f09 --- /dev/null +++ b/doc/unordered/unordered_flat_set.adoc @@ -0,0 +1,1081 @@ +[#unordered_flat_set] +== Class template unordered_flat_set + +:idprefix: unordered_flat_set_ + +`boost::unordered_flat_set` — An open-addressing unordered associative container that stores unique values. + +The performance of `boost::unordered_flat_set` is much better than that of `boost::unordered_set` +or other implementations of `std::unordered_set`. Unlike standard unordered associative containers, +which are node-based, the elements of a `boost::unordered_flat_set` are held directly in the bucket +array, and insertions into an already occupied bucket are diverted to available buckets in the +vicinity of the original position. This type of data layout is known as _open addressing_. + +As a result of its using open addressing, the interface of `boost::unordered_flat_set` deviates in +a number of aspects from that of `boost::unordered_flat_set`/`std::unordered_flat_set`: + + - `value_type` must be move-constructible. + - Pointer stability is not kept under rehashing. + - `begin()` is not constant-time. + - `erase(iterator)` returns `void`. + - There is no API for bucket handling (except `bucket_count`) or node extraction/insertion. + - The maximum load factor of the container is managed internally and can't be set by the user. + +Other than this, `boost::unordered_flat_set` is mostly a drop-in replacement of node-based standard +unordered associative containers. + +=== Synopsis + +[listing,subs="+macros,+quotes"] +----- +// #include + +namespace boost { + template, + class Pred = std::equal_to, + class Allocator = std::allocator> + class unordered_flat_set { + public: + // types + using key_type = Key; + using value_type = Key; + using init_type = Key; + using hasher = Hash; + using key_equal = Pred; + using allocator_type = Allocator; + using pointer = typename std::allocator_traits::pointer; + using const_pointer = typename std::allocator_traits::const_pointer; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + + using iterator = _implementation-defined_; + using const_iterator = _implementation-defined_; + + // construct/copy/destroy + xref:#unordered_flat_set_default_constructor[unordered_flat_set](); + explicit xref:#unordered_flat_set_bucket_count_constructor[unordered_flat_set](size_type n, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); + template + xref:#unordered_flat_set_iterator_range_constructor[unordered_flat_set](InputIterator f, InputIterator l, + size_type n = _implementation-defined_, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); + xref:#unordered_flat_set_copy_constructor[unordered_flat_set](const unordered_flat_set& other); + xref:#unordered_flat_set_move_constructor[unordered_flat_set](unordered_flat_set&& other); + explicit xref:#unordered_flat_set_allocator_constructor[unordered_flat_set](const Allocator& a); + xref:#unordered_flat_set_copy_constructor_with_allocator[unordered_flat_set](const unordered_flat_set& other, const Allocator& a); + xref:#unordered_flat_set_move_constructor_with_allocator[unordered_flat_set](unordered_flat_set&& other, const Allocator& a); + xref:#unordered_flat_set_initializer_list_constructor[unordered_flat_set](std::initializer_list il, + size_type n = _implementation-defined_ + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); + xref:#unordered_flat_set_bucket_count_constructor_with_allocator[unordered_flat_set](size_type n, const allocator_type& a); + xref:#unordered_flat_set_bucket_count_constructor_with_hasher_and_allocator[unordered_flat_set](size_type n, const hasher& hf, const allocator_type& a); + template + xref:#unordered_flat_set_iterator_range_constructor_with_bucket_count_and_allocator[unordered_flat_set](InputIterator f, InputIterator l, size_type n, const allocator_type& a); + template + xref:#unordered_flat_set_iterator_range_constructor_with_bucket_count_and_hasher[unordered_flat_set](InputIterator f, InputIterator l, size_type n, const hasher& hf, + const allocator_type& a); + xref:#unordered_flat_set_initializer_list_constructor_with_bucket_count_and_allocator[unordered_flat_set](std::initializer_list il, size_type n, + const allocator_type& a); + xref:#unordered_flat_set_initializer_list_constructor_with_bucket_count_and_hasher_and_allocator[unordered_flat_set](std::initializer_list il, size_type n, const hasher& hf, + const allocator_type& a); + xref:#unordered_flat_set_destructor[~unordered_flat_set](); + unordered_flat_set& xref:#unordered_flat_set_copy_assignment[operator++=++](const unordered_flat_set& other); + unordered_flat_set& xref:#unordered_flat_set_move_assignment[operator++=++](unordered_flat_set&& other) + noexcept(boost::allocator_traits::is_always_equal::value && + boost::is_nothrow_move_assignable_v && + boost::is_nothrow_move_assignable_v); + unordered_flat_set& xref:#unordered_flat_set_initializer_list_assignment[operator++=++](std::initializer_list); + allocator_type xref:#unordered_flat_set_get_allocator[get_allocator]() const noexcept; + + // iterators + iterator xref:#unordered_flat_set_begin[begin]() noexcept; + const_iterator xref:#unordered_flat_set_begin[begin]() const noexcept; + iterator xref:#unordered_flat_set_end[end]() noexcept; + const_iterator xref:#unordered_flat_set_end[end]() const noexcept; + const_iterator xref:#unordered_flat_set_cbegin[cbegin]() const noexcept; + const_iterator xref:#unordered_flat_set_cend[cend]() const noexcept; + + // capacity + ++[[nodiscard]]++ bool xref:#unordered_flat_set_empty[empty]() const noexcept; + size_type xref:#unordered_flat_set_size[size]() const noexcept; + size_type xref:#unordered_flat_set_max_size[max_size]() const noexcept; + + // modifiers + template std::pair xref:#unordered_flat_set_emplace[emplace](Args&&... args); + template iterator xref:#unordered_flat_set_emplace_hint[emplace_hint](const_iterator position, Args&&... args); + std::pair xref:#unordered_flat_set_copy_insert[insert](const value_type& obj); + std::pair xref:#unordered_flat_set_move_insert[insert](value_type&& obj); + iterator xref:#unordered_flat_set_copy_insert_with_hint[insert](const_iterator hint, const value_type& obj); + iterator xref:#unordered_flat_set_move_insert_with_hint[insert](const_iterator hint, value_type&& obj); + template void xref:#unordered_flat_set_insert_iterator_range[insert](InputIterator first, InputIterator last); + void xref:#unordered_flat_set_insert_initializer_list[insert](std::initializer_list); + + void xref:#unordered_flat_set_erase_by_position[erase](iterator position); + void xref:#unordered_flat_set_erase_by_position[erase](const_iterator position); + size_type xref:#unordered_flat_set_erase_by_key[erase](const key_type& k); + template size_type xref:#unordered_flat_set_transparent_erase_by_key[erase](K&& k); + iterator xref:#unordered_flat_set_erase_range[erase](const_iterator first, const_iterator last); + void xref:#unordered_flat_set_swap[swap](unordered_flat_set& other) + noexcept(boost::allocator_traits::is_always_equal::value && + boost::is_nothrow_swappable_v && + boost::is_nothrow_swappable_v); + void xref:#unordered_flat_set_clear[clear]() noexcept; + + template + void xref:#unordered_flat_set_merge[merge](unordered_flat_set& source); + template + void xref:#unordered_flat_set_merge[merge](unordered_flat_set&& source); + + // observers + hasher xref:#unordered_flat_set_hash_function[hash_function]() const; + key_equal xref:#unordered_flat_set_key_eq[key_eq]() const; + + // set operations + iterator xref:#unordered_flat_set_find[find](const key_type& k); + const_iterator xref:#unordered_flat_set_find[find](const key_type& k) const; + template + iterator xref:#unordered_flat_set_find[find](const K& k); + template + const_iterator xref:#unordered_flat_set_find[find](const K& k) const; + size_type xref:#unordered_flat_set_count[count](const key_type& k) const; + template + size_type xref:#unordered_flat_set_count[count](const K& k) const; + bool xref:#unordered_flat_set_contains[contains](const key_type& k) const; + template + bool xref:#unordered_flat_set_contains[contains](const K& k) const; + std::pair xref:#unordered_flat_set_equal_range[equal_range](const key_type& k); + std::pair xref:#unordered_flat_set_equal_range[equal_range](const key_type& k) const; + template + std::pair xref:#unordered_flat_set_equal_range[equal_range](const K& k); + template + std::pair xref:#unordered_flat_set_equal_range[equal_range](const K& k) const; + + // bucket interface + size_type xref:#unordered_flat_set_bucket_count[bucket_count]() const noexcept; + + // hash policy + float xref:#unordered_flat_set_load_factor[load_factor]() const noexcept; + float xref:#unordered_flat_set_max_load_factor[max_load_factor]() const noexcept; + void xref:#unordered_flat_set_set_max_load_factor[max_load_factor](float z); + size_type xref:#unordered_flat_set_max_load[max_load]() const noexcept; + void xref:#unordered_flat_set_rehash[rehash](size_type n); + void xref:#unordered_flat_set_reserve[reserve](size_type n); + }; +} + +// Equality Comparisons +template + bool xref:#unordered_flat_set_operator_2[operator==](const unordered_flat_set& x, + const unordered_flat_set& y); + +template + bool xref:#unordered_flat_set_operator_3[operator!=](const unordered_flat_set& x, + const unordered_flat_set& y); + +// swap +template + void xref:#unordered_flat_set_swap_2[swap](unordered_flat_set& x, + unordered_flat_set& y) + noexcept(noexcept(x.swap(y))); + +template + typename unordered_flat_set::size_type + xref:#unordered_flat_set_erase_if[erase_if](unordered_flat_set& c, Predicate pred); +----- + +--- + +=== Description + +*Template Parameters* + +[cols="1,1"] +|=== + +|_Key_ +|`Key` must be https://en.cppreference.com/w/cpp/named_req/MoveInsertable[MoveInsertable^] into the container +and https://en.cppreference.com/w/cpp/named_req/Erasable[Erasable^] from the container. + +|_Hash_ +|A unary function object type that acts a hash function for a `Key`. It takes a single argument of type `Key` and returns a value of type `std::size_t`. + +|_Pred_ +|A binary function object that induces an equivalence relation on values of type `Key`. It takes two arguments of type `Key` and returns a value of type `bool`. + +|_Allocator_ +|An allocator whose value type is the same as the container's value type. +`std::allocator_traits::pointer` and `std::allocator_traits::const_pointer` +must be convertible to/from `value_type*` and `const value_type*`, respectively. + +|=== + +The elements of the container are held into an internal _bucket array_. An element is inserted into a bucket determined by its +hash code, but if the bucket is already occupied (a _collision_), an available one in the vicinity of the +original position is used. + +The size of the bucket array can be automatically increased by a call to `insert`/`emplace`, or as a result of calling +`rehash`/`reserve`. The _load factor_ of the container (number of elements divided by number of buckets) is never +greater than `max_load_factor()`, except possibly for small sizes where the implementation may decide to +allow for higher loads. + +If `xref:hash_traits_hash_is_avalanching[hash_is_avalanching]::value` is `true`, the hash function +is used as-is; otherwise, a bit-mixing post-processing stage is added to increase the quality of hashing +at the expense of extra computational cost. + +--- + +=== Typedefs + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ iterator; +---- + +A constant iterator whose value type is `value_type`. + +The iterator category is at least a forward iterator. + +Convertible to `const_iterator`. + +--- + +[source,c++,subs=+quotes] +---- +typedef _implementation-defined_ const_iterator; +---- + +A constant iterator whose value type is `value_type`. + +The iterator category is at least a forward iterator. + +=== Constructors + +==== Default Constructor +```c++ +unordered_flat_set(); +``` + +Constructs an empty container using `hasher()` as the hash function, +`key_equal()` as the key equality predicate and `allocator_type()` as the allocator. + +[horizontal] +Postconditions:;; `size() == 0` +Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Bucket Count Constructor +```c++ +explicit unordered_flat_set(size_type n, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); +``` + +Constructs an empty container with at least `n` buckets, using `hf` as the hash +function, `eql` as the key equality predicate, and `a` as the allocator. + +[horizontal] +Postconditions:;; `size() == 0` +Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Iterator Range Constructor +[source,c++,subs="+quotes"] +---- +template + unordered_flat_set(InputIterator f, InputIterator l, + size_type n = _implementation-defined_, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); +---- + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate and `a` as the allocator, and inserts the elements from `[f, l)` into it. + +[horizontal] +Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Copy Constructor +```c++ +unordered_flat_set(unordered_flat_set const& other); +``` + +The copy constructor. Copies the contained elements, hash function, predicate and allocator. + +If `Allocator::select_on_container_copy_construction` exists and has the right signature, the allocator will be constructed from its result. + +[horizontal] +Requires:;; `value_type` is copy constructible + +--- + +==== Move Constructor +```c++ +unordered_flat_set(unordered_flat_set&& other); +``` + +The move constructor. The internal bucket array of `other` is transferred directly to the new container. +The hash function, predicate and allocator are moved-constructed from `other`. + +--- + +==== Allocator Constructor +```c++ +explicit unordered_flat_set(Allocator const& a); +``` + +Constructs an empty container, using allocator `a`. + +--- + +==== Copy Constructor with Allocator +```c++ +unordered_flat_set(unordered_flat_set const& other, Allocator const& a); +``` + +Constructs a container, copying ``other``'s contained elements, hash function, and predicate, but using allocator `a`. + +--- + +==== Move Constructor with Allocator +```c++ +unordered_flat_set(unordered_flat_set&& other, Allocator const& a); +``` + +If `a == other.get_allocator()`, the elements of `other` are transferred directly to the new container; +otherwise, elements are moved-constructed from those of `other`. The hash function and predicate are moved-constructed +from `other`, and the allocator is copy-constructed from `a`. + +--- + +==== Initializer List Constructor +[source,c++,subs="+quotes"] +---- +unordered_flat_set(std::initializer_list il, + size_type n = _implementation-defined_ + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); +---- + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `eql` as the key equality predicate and `a`, and inserts the elements from `il` into it. + +[horizontal] +Requires:;; If the defaults are used, `hasher`, `key_equal` and `allocator_type` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Bucket Count Constructor with Allocator +```c++ +unordered_flat_set(size_type n, allocator_type const& a); +``` + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, the default hash function and key equality predicate and `a` as the allocator. + +[horizontal] +Postconditions:;; `size() == 0` +Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Bucket Count Constructor with Hasher and Allocator +```c++ +unordered_flat_set(size_type n, hasher const& hf, allocator_type const& a); +``` + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, the default key equality predicate and `a` as the allocator. + +[horizontal] +Postconditions:;; `size() == 0` +Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Iterator Range Constructor with Bucket Count and Allocator +[source,c++,subs="+quotes"] +---- +template + unordered_flat_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a); +---- + +Constructs an empty container with at least `n` buckets, using `a` as the allocator and default hash function and key equality predicate, and inserts the elements from `[f, l)` into it. + +[horizontal] +Requires:;; `hasher`, `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== Iterator Range Constructor with Bucket Count and Hasher +[source,c++,subs="+quotes"] +---- + template + unordered_flat_set(InputIterator f, InputIterator l, size_type n, const hasher& hf, + const allocator_type& a); +---- + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `a` as the allocator, with the default key equality predicate, and inserts the elements from `[f, l)` into it. + +[horizontal] +Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== initializer_list Constructor with Bucket Count and Allocator + +```c++ +unordered_flat_set(std::initializer_list il, size_type n, const allocator_type& a); +``` + +Constructs an empty container with at least `n` buckets, using `a` and default hash function and key equality predicate, and inserts the elements from `il` into it. + +[horizontal] +Requires:;; `hasher` and `key_equal` need to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +==== initializer_list Constructor with Bucket Count and Hasher and Allocator + +```c++ +unordered_flat_set(std::initializer_list il, size_type n, const hasher& hf, + const allocator_type& a); +``` + +Constructs an empty container with at least `n` buckets, using `hf` as the hash function, `a` as the allocator and default key equality predicate,and inserts the elements from `il` into it. + +[horizontal] +Requires:;; `key_equal` needs to be https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[DefaultConstructible^]. + +--- + +=== Destructor + +```c++ +~unordered_flat_set(); +``` + +[horizontal] +Note:;; The destructor is applied to every element, and all memory is deallocated + +--- + +=== Assignment + +==== Copy Assignment + +```c++ +unordered_flat_set& operator=(unordered_flat_set const& other); +``` + +The assignment operator. Destroys previously existing elements, copy-assigns the hash function and predicate from `other`, +copy-assigns the allocator from `other` if `Alloc::propagate_on_container_copy_assignment` exists and `Alloc::propagate_on_container_copy_assignment::value` is `true`, +and finally inserts copies of the elements of `other`. + +[horizontal] +Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/CopyInsertable[CopyInsertable^] + +--- + +==== Move Assignment +```c++ +unordered_flat_set& operator=(unordered_flat_set&& other) + noexcept(boost::allocator_traits::is_always_equal::value && + boost::is_nothrow_move_assignable_v && + boost::is_nothrow_move_assignable_v); +``` +The move assignment operator. Destroys previously existing elements, move-assigns the hash function and predicate from `other`, +and move-assigns the allocator from `other` if `Alloc::propagate_on_container_move_assignment` exists and `Alloc::propagate_on_container_move_assignment::value` is `true`. +If at this point the allocator is equal to `other.get_allocator()`, the internal bucket array of `other` is transferred directly to the new container; +otherwise, inserts move-constructed copies of the elements of `other`. + +--- + +==== Initializer List Assignment +```c++ +unordered_flat_set& operator=(std::initializer_list il); +``` + +Assign from values in initializer list. All previously existing elements are destroyed. + +[horizontal] +Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/CopyInsertable[CopyInsertable^] + +=== Iterators + +==== begin +```c++ +iterator begin() noexcept; +const_iterator begin() const noexcept; +``` + +[horizontal] +Returns:;; An iterator referring to the first element of the container, or if the container is empty the past-the-end value for the container. +Complexity:;; O(`bucket_count()`) + +--- + +==== end +```c++ +iterator end() noexcept; +const_iterator end() const noexcept; +``` + +[horizontal] +Returns:;; An iterator which refers to the past-the-end value for the container. + +--- + +==== cbegin +```c++ +const_iterator cbegin() const noexcept; +``` + +[horizontal] +Returns:;; A `const_iterator` referring to the first element of the container, or if the container is empty the past-the-end value for the container. +Complexity:;; O(`bucket_count()`) + +--- + +==== cend +```c++ +const_iterator cend() const noexcept; +``` + +[horizontal] +Returns:;; A `const_iterator` which refers to the past-the-end value for the container. + +--- + +=== Size and Capacity + +==== empty + +```c++ +[[nodiscard]] bool empty() const noexcept; +``` + +[horizontal] +Returns:;; `size() == 0` + +--- + +==== size + +```c++ +size_type size() const noexcept; +``` + +[horizontal] +Returns:;; `std::distance(begin(), end())` + +--- + +==== max_size + +```c++ +size_type max_size() const noexcept; +``` + +[horizontal] +Returns:;; `size()` of the largest possible container. + +--- + +=== Modifiers + +==== emplace +```c++ +template std::pair emplace(Args&&... args); +``` + +Inserts an object, constructed with the arguments `args`, in the container if and only if there is no element in the container with an equivalent key. + +[horizontal] +Requires:;; `value_type` is constructible from `args`. +Returns:;; The `bool` component of the return type is `true` if an insert took place. + ++ +If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. +Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect. +Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load. + + +--- + +==== emplace_hint +```c++ + template iterator emplace_hint(const_iterator position, Args&&... args); +``` + +Inserts an object, constructed with the arguments `args`, in the container if and only if there is no element in the container with an equivalent key. + +`position` is a suggestion to where the element should be inserted. This implementation ignores it. + +[horizontal] +Requires:;; `value_type` is constructible from `args`. +Returns:;; The `bool` component of the return type is `true` if an insert took place. + ++ +If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. +Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect. +Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load. + + +--- + +==== Copy Insert +```c++ +std::pair insert(const value_type& obj); +``` + +Inserts `obj` in the container if and only if there is no element in the container with an equivalent key. + +[horizontal] +Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/CopyInsertable[CopyInsertable^]. +Returns:;; The `bool` component of the return type is `true` if an insert took place. + ++ +If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. +Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect. +Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load. + +--- + +==== Move Insert +```c++ +std::pair insert(value_type&& obj); +``` + +Inserts `obj` in the container if and only if there is no element in the container with an equivalent key. + +[horizontal] +Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/MoveInsertable[MoveInsertable^]. +Returns:;; The `bool` component of the return type is `true` if an insert took place. + ++ +If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. +Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect. +Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load. + +--- + +==== Copy Insert with Hint +```c++ +iterator insert(const_iterator hint, const value_type& obj); +``` +Inserts `obj` in the container if and only if there is no element in the container with an equivalent key. + +`hint` is a suggestion to where the element should be inserted. This implementation ignores it. + +[horizontal] +Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/CopyInsertable[CopyInsertable^]. +Returns:;; The `bool` component of the return type is `true` if an insert took place. + ++ +If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. +Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect. +Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load. + +--- + +==== Move Insert with Hint +```c++ +iterator insert(const_iterator hint, value_type&& obj); +``` + +Inserts `obj` in the container if and only if there is no element in the container with an equivalent key. + +`hint` is a suggestion to where the element should be inserted. This implementation ignores it. + +[horizontal] +Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/MoveInsertable[MoveInsertable^]. +Returns:;; The `bool` component of the return type is `true` if an insert took place. + ++ +If an insert took place, then the iterator points to the newly inserted element. Otherwise, it points to the element with equivalent key. +Throws:;; If an exception is thrown by an operation other than a call to `hasher` the function has no effect. +Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load. + +--- + +==== Insert Iterator Range +```c++ +template void insert(InputIterator first, InputIterator last); +``` + +Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key. + +[horizontal] +Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into the container from `*first`. +Throws:;; When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect. +Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load. + +--- + +==== Insert Initializer List +```c++ +void insert(std::initializer_list); +``` + +Inserts a range of elements into the container. Elements are inserted if and only if there is no element in the container with an equivalent key. + +[horizontal] +Requires:;; `value_type` is https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] into the container from `*first`. +Throws:;; When inserting a single element, if an exception is thrown by an operation other than a call to `hasher` the function has no effect. +Notes:;; Can invalidate iterators, pointers and references, but only if the insert causes the load to be greater than the maximum load. + +--- + +==== Erase by Position + +```c++ +void erase(iterator position); +void erase(const_iterator position); +``` + +Erase the element pointed to by `position`. + +[horizontal] +Throws:;; Nothing. + +--- + +==== Erase by Key +```c++ +size_type erase(const key_type& k); +``` + +Erase all elements with key equivalent to `k`. + +[horizontal] +Returns:;; The number of elements erased. +Throws:;; Only throws an exception if it is thrown by `hasher` or `key_equal`. + +--- + +==== Transparent Erase by Key +```c++ +template size_type erase(K&& k); +``` + +Erase all elements with key equivalent to `k`. + +This overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs and neither `iterator` nor `const_iterator` are implicitly convertible from `K`. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. + +[horizontal] +Returns:;; The number of elements erased. +Throws:;; Only throws an exception if it is thrown by `hasher` or `key_equal`. + +--- + +==== Erase Range + +```c++ +iterator erase(const_iterator first, const_iterator last); +``` + +Erases the elements in the range from `first` to `last`. + +[horizontal] +Returns:;; The iterator following the erased elements - i.e. `last`. +Throws:;; Nothing in this implementation (neither the `hasher` nor the `key_equal` objects are called). + +--- + +==== swap +```c++ +void swap(unordered_flat_set& other) + noexcept(boost::allocator_traits::is_always_equal::value && + boost::is_nothrow_swappable_v && + boost::is_nothrow_swappable_v); +``` + +Swaps the contents of the container with the parameter. + +If `Allocator::propagate_on_container_swap` is declared and `Allocator::propagate_on_container_swap::value` is `true` then the containers' allocators are swapped. Otherwise, swapping with unequal allocators results in undefined behavior. + +[horizontal] +Throws:;; Nothing unless `key_equal` or `hasher` throw on swapping. + +--- + +==== clear +```c++ +void clear() noexcept; +``` + +Erases all elements in the container. + +[horizontal] +Postconditions:;; `size() == 0`, `max_load() >= max_load_factor() * bucket_count()` + +--- + +==== merge +```c++ +template + void merge(unordered_flat_set& source); +template + void merge(unordered_flat_set&& source); +``` + +Move-inserts all the elements from `source` whose key is not already present in `*this`, and erases them from `source`. + +--- + +=== Observers + +==== get_allocator +``` +allocator_type get_allocator() const noexcept; +``` + +[horizontal] +Returns:;; The container's allocator. + +--- + +==== hash_function +``` +hasher hash_function() const; +``` + +[horizontal] +Returns:;; The container's hash function. + +--- + +==== key_eq +``` +key_equal key_eq() const; +``` + +[horizontal] +Returns:;; The container's key equality predicate + +--- + +=== Lookup + +==== find +```c++ +iterator find(const key_type& k); +const_iterator find(const key_type& k) const; +template + iterator find(const K& k); + +``` + +[horizontal] +Returns:;; An iterator pointing to an element with key equivalent to `k`, or `end()` if no such element exists. +Notes:;; The `template ` overloads only participate in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. + +--- + +==== count +```c++ +size_type count(const key_type& k) const; +template + size_type count(const K& k) const; +``` + +[horizontal] +Returns:;; The number of elements with key equivalent to `k`. +Notes:;; The `template ` overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. + +--- + +==== contains +```c++ +bool contains(const key_type& k) const; +template + bool contains(const K& k) const; +``` + +[horizontal] +Returns:;; A boolean indicating whether or not there is an element with key equal to `key` in the container +Notes:;; The `template ` overload only participates in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. + +--- + +==== equal_range +```c++ +std::pair equal_range(const key_type& k); +std::pair equal_range(const key_type& k) const; +template + std::pair equal_range(const K& k); +template + std::pair equal_range(const K& k) const; +``` + +[horizontal] +Returns:;; A range containing all elements with key equivalent to `k`. If the container doesn't contain any such elements, returns `std::make_pair(b.end(), b.end())`. +Notes:;; The `template ` overloads only participate in overload resolution if `Hash::is_transparent` and `Pred::is_transparent` are valid member typedefs. The library assumes that `Hash` is callable with both `K` and `Key` and that `Pred` is transparent. This enables heterogeneous lookup which avoids the cost of instantiating an instance of the `Key` type. + +--- + +=== Bucket Interface + +==== bucket_count +```c++ +size_type bucket_count() const noexcept; +``` + +[horizontal] +Returns:;; The size of the bucket array. + +--- + +=== Hash Policy + +==== load_factor +```c++ +float load_factor() const noexcept; +``` + +[horizontal] +Returns:;; `static_cast(size())/static_cast(bucket_count())`, or `0` if `bucket_count() == 0`. + +--- + +==== max_load_factor + +```c++ +float max_load_factor() const noexcept; +``` + +[horizontal] +Returns:;; Returns the container's maximum load factor. + +--- + +==== Set max_load_factor +```c++ +void max_load_factor(float z); +``` + +[horizontal] +Effects:;; Does nothing, as the user is not allowed to change this parameter. Kept for compatibility with `boost::unordered_set`. + +--- + + +==== max_load + +```c++ +size_type max_load() const noexcept; +``` + +[horizontal] +Returns:;; The maximum number of elements the container can hold without rehashing, assuming that no further elements will be erased. +Note:;; After construction, rehash or clearance, the container's maximum load is at least `max_load_factor() * bucket_count()`. This load will decrease by the number of elements inserted, +but won't increase at the same rate on erasure. + +--- + +==== rehash +```c++ +void rehash(size_type n); +``` + +Changes if necessary the size of the bucket array so that there are at least `n` buckets, and so that the load factor is less than or equal to the maximum load factor. When applicable, this will either grow or shrink the `bucket_count()` associated with the container. + +When `size() == 0`, `rehash(0)` will deallocate the underlying buckets array. + +Invalidates iterators, pointers and references, and changes the order of elements. + +[horizontal] +Throws:;; The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + +--- + +==== reserve +```c++ +void reserve(size_type n); +``` + +Equivalent to `a.rehash(ceil(n / a.max_load_factor()))`. + +Similar to `rehash`, this function can be used to grow or shrink the number of buckets in the container. + +Invalidates iterators, pointers and references, and changes the order of elements. + +[horizontal] +Throws:;; The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function. + +=== Equality Comparisons + +==== operator== +```c++ +template + bool operator==(const unordered_flat_set& x, + const unordered_flat_set& y); +``` + +Return `true` if `x.size() == y.size()` and for every element in `x`, there is an element in `y` with the same key, with an equal value (using `operator==` to compare the value types). + +[horizontal] +Notes:;; Behavior is undefined if the two containers don't have equivalent equality predicates. + +--- + +==== operator!= +```c++ +template + bool operator!=(const unordered_flat_set& x, + const unordered_flat_set& y); +``` + +Return `false` if `x.size() == y.size()` and for every element in `x`, there is an element in `y` with the same key, with an equal value (using `operator==` to compare the value types). + +[horizontal] +Notes:;;Behavior is undefined if the two containers don't have equivalent equality predicates. + +=== Swap +```c++ +template + void swap(unordered_flat_set& x, + unordered_flat_set& y) + noexcept(noexcept(x.swap(y))); +``` + +Swaps the contents of `x` and `y`. + +If `Allocator::propagate_on_container_swap` is declared and `Allocator::propagate_on_container_swap::value` is `true` then the containers' allocators are swapped. Otherwise, swapping with unequal allocators results in undefined behavior. + +[horizontal] +Effects:;; `x.swap(y)` +Throws:;; Nothing unless `key_equal` or `hasher` throw on swapping. + +--- + +=== erase_if +```c++ +template + typename unordered_flat_set::size_type + erase_if(unordered_flat_set& c, Predicate pred); +``` + +Traverses the container `c` and removes all elements for which the supplied predicate returns `true`. + +[horizontal] +Returns:;; The number of erased elements. +Notes:;; Equivalent to: + ++ +```c++ +auto original_size = c.size(); +for (auto i = c.begin(), last = c.end(); i != last; ) { + if (pred(*i)) { + i = c.erase(i); + } else { + ++i; + } +} +return original_size - c.size(); +``` + +--- diff --git a/doc/unordered/unordered_map.adoc b/doc/unordered/unordered_map.adoc index a174a580..5b8f1f92 100644 --- a/doc/unordered/unordered_map.adoc +++ b/doc/unordered/unordered_map.adoc @@ -9,7 +9,7 @@ [listing,subs="+macros,+quotes"] ----- -// #include +// #include namespace boost { template +// #include namespace boost { template +// #include namespace boost { template +// #include namespace boost { template