├── index.html
├── doc
├── Jamfile.v2
├── index.html
├── img
│ ├── fpr_c.png
│ ├── fpr_n_k.png
│ ├── natvis.png
│ ├── stride.png
│ ├── bloom_lookup.png
│ ├── db_speedup.png
│ ├── fpr_n_k_bk.png
│ ├── block_insertion.png
│ ├── bloom_insertion.png
│ ├── block_multi_insertion.png
│ └── multiblock_insertion.png
├── bloom
│ ├── reference
│ │ ├── header_bloom.adoc
│ │ ├── header_block.adoc
│ │ ├── header_multiblock.adoc
│ │ ├── header_fast_multiblock32.adoc
│ │ ├── header_fast_multiblock64.adoc
│ │ ├── block.adoc
│ │ ├── multiblock.adoc
│ │ ├── header_filter.adoc
│ │ ├── fast_multiblock64.adoc
│ │ ├── fast_multiblock32.adoc
│ │ └── subfilters.adoc
│ ├── copyright.adoc
│ ├── release_notes.adoc
│ ├── reference.adoc
│ ├── acknowledgements.adoc
│ ├── future_work.adoc
│ ├── intro.adoc
│ ├── fpr_estimation.adoc
│ ├── implementation_notes.adoc
│ ├── configuration.adoc
│ ├── primer.adoc
│ └── tutorial.adoc
└── bloom.adoc
├── example
├── Jamfile.v2
├── basic.cpp
├── serialization.cpp
├── rolling_filter.cpp
└── genome.cpp
├── benchmark
├── Jamfile.v2
├── fpr_c.cpp
├── comparison_table.cpp
└── bulk_comparison_table.cpp
├── meta
└── libraries.json
├── test
├── CMakeLists.txt
├── test_boost_bloom_hpp.cpp
├── Jamfile.v2
├── test_visualization.cpp
├── test_types.hpp
├── test_bulk_operations.cpp
├── test_array.cpp
├── test_comparison.cpp
├── test_insertion.cpp
├── test_combination.cpp
├── test_fpr.cpp
├── test_capacity.cpp
└── test_utilities.hpp
├── include
└── boost
│ ├── bloom
│ ├── detail
│ │ ├── avx2.hpp
│ │ ├── neon.hpp
│ │ ├── sse2.hpp
│ │ ├── constexpr_bit_width.hpp
│ │ ├── block_fpr_base.hpp
│ │ ├── multiblock_fpr_base.hpp
│ │ ├── block_ops.hpp
│ │ ├── mulx64.hpp
│ │ ├── block_base.hpp
│ │ ├── fast_multiblock32_avx2.hpp
│ │ ├── fast_multiblock64_avx2.hpp
│ │ ├── fast_multiblock32_sse2.hpp
│ │ ├── fast_multiblock32_neon.hpp
│ │ ├── type_traits.hpp
│ │ └── bloom_printers.hpp
│ ├── fast_multiblock64.hpp
│ ├── fast_multiblock32.hpp
│ ├── multiblock.hpp
│ ├── block.hpp
│ └── filter.hpp
│ └── bloom.hpp
├── .codecov.yml
├── .drone
├── drone.bat
└── drone.sh
├── CMakeLists.txt
├── extra
├── boost_bloom.natvis
└── boost_bloom_printers.py
├── .gitattributes
└── README.md
/index.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boostorg/bloom/HEAD/index.html
--------------------------------------------------------------------------------
/doc/Jamfile.v2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boostorg/bloom/HEAD/doc/Jamfile.v2
--------------------------------------------------------------------------------
/doc/index.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boostorg/bloom/HEAD/doc/index.html
--------------------------------------------------------------------------------
/doc/img/fpr_c.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boostorg/bloom/HEAD/doc/img/fpr_c.png
--------------------------------------------------------------------------------
/doc/img/fpr_n_k.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boostorg/bloom/HEAD/doc/img/fpr_n_k.png
--------------------------------------------------------------------------------
/doc/img/natvis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boostorg/bloom/HEAD/doc/img/natvis.png
--------------------------------------------------------------------------------
/doc/img/stride.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boostorg/bloom/HEAD/doc/img/stride.png
--------------------------------------------------------------------------------
/example/Jamfile.v2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boostorg/bloom/HEAD/example/Jamfile.v2
--------------------------------------------------------------------------------
/benchmark/Jamfile.v2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boostorg/bloom/HEAD/benchmark/Jamfile.v2
--------------------------------------------------------------------------------
/doc/img/bloom_lookup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boostorg/bloom/HEAD/doc/img/bloom_lookup.png
--------------------------------------------------------------------------------
/doc/img/db_speedup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boostorg/bloom/HEAD/doc/img/db_speedup.png
--------------------------------------------------------------------------------
/doc/img/fpr_n_k_bk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boostorg/bloom/HEAD/doc/img/fpr_n_k_bk.png
--------------------------------------------------------------------------------
/doc/img/block_insertion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boostorg/bloom/HEAD/doc/img/block_insertion.png
--------------------------------------------------------------------------------
/doc/img/bloom_insertion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boostorg/bloom/HEAD/doc/img/bloom_insertion.png
--------------------------------------------------------------------------------
/doc/img/block_multi_insertion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boostorg/bloom/HEAD/doc/img/block_multi_insertion.png
--------------------------------------------------------------------------------
/doc/img/multiblock_insertion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boostorg/bloom/HEAD/doc/img/multiblock_insertion.png
--------------------------------------------------------------------------------
/doc/bloom/reference/header_bloom.adoc:
--------------------------------------------------------------------------------
1 | [#header_bloom]
2 | == ``
3 |
4 | :idprefix: header_bloom_
5 |
6 | Convenience header including all the other headers listed in this
7 | reference.
8 |
9 | '''
--------------------------------------------------------------------------------
/doc/bloom/copyright.adoc:
--------------------------------------------------------------------------------
1 | [#copyright]
2 | = Copyright and License
3 |
4 | :idprefix: copyright_
5 |
6 | Of this documentation:
7 |
8 | * Copyright © 2025 Joaquín M López Muñoz
9 |
10 | Distributed under the http://www.boost.org/LICENSE_1_0.txt[Boost Software License, Version 1.0^].
11 |
--------------------------------------------------------------------------------
/doc/bloom/reference/header_block.adoc:
--------------------------------------------------------------------------------
1 | [#header_block]
2 | == ``
3 |
4 | :idprefix: header_block_
5 |
6 | [listing,subs="+macros,+quotes"]
7 | -----
8 | namespace boost{
9 | namespace bloom{
10 |
11 | template
12 | struct xref:block[block];
13 |
14 | } // namespace bloom
15 | } // namespace boost
16 | -----
17 |
18 |
--------------------------------------------------------------------------------
/meta/libraries.json:
--------------------------------------------------------------------------------
1 | {
2 | "key": "bloom",
3 | "name": "Bloom",
4 | "authors": [
5 | "Joaqu\u00edn M L\u00f3pez Mu\u00f1oz"
6 | ],
7 | "description": "Bloom filters.",
8 | "cxxstd": "11",
9 | "category": [
10 | "Containers"
11 | ],
12 | "maintainers": [
13 | "Joaquin M Lopez Munoz "
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/doc/bloom/reference/header_multiblock.adoc:
--------------------------------------------------------------------------------
1 | [#header_multiblock]
2 | == ``
3 |
4 | :idprefix: header_multiblock_
5 |
6 | [listing,subs="+macros,+quotes"]
7 | -----
8 | namespace boost{
9 | namespace bloom{
10 |
11 | template
12 | struct xref:multiblock[multiblock];
13 |
14 | } // namespace bloom
15 | } // namespace boost
16 | -----
17 |
18 |
--------------------------------------------------------------------------------
/doc/bloom/reference/header_fast_multiblock32.adoc:
--------------------------------------------------------------------------------
1 | [#header_fast_multiblock32]
2 | == ``
3 |
4 | :idprefix: header_fast_multiblock32_
5 |
6 | [listing,subs="+macros,+quotes"]
7 | -----
8 | namespace boost{
9 | namespace bloom{
10 |
11 | template
12 | struct xref:fast_multiblock32[fast_multiblock32];
13 |
14 | } // namespace bloom
15 | } // namespace boost
16 | -----
17 |
18 |
--------------------------------------------------------------------------------
/doc/bloom/reference/header_fast_multiblock64.adoc:
--------------------------------------------------------------------------------
1 | [#header_fast_multiblock64]
2 | == ``
3 |
4 | :idprefix: header_fast_multiblock64_
5 |
6 | [listing,subs="+macros,+quotes"]
7 | -----
8 | namespace boost{
9 | namespace bloom{
10 |
11 | template
12 | struct xref:fast_multiblock64[fast_multiblock64];
13 |
14 | } // namespace bloom
15 | } // namespace boost
16 | -----
17 |
18 |
--------------------------------------------------------------------------------
/doc/bloom/release_notes.adoc:
--------------------------------------------------------------------------------
1 | [#release_notes]
2 | = Release Notes
3 |
4 | :idprefix: release_notes_
5 |
6 | == Boost 1.90
7 |
8 | * Added bulk-mode insertion and lookup for increased performance.
9 | * Made lookup implementation branchless for `block`, `fast_multiblock32`
10 | and `fast_multiblock64`, which results in some performance gains, particularly
11 | for mixed successful/unsuccessful queries.
12 |
13 | == Boost 1.89
14 |
15 | * Initial release.
16 |
17 |
--------------------------------------------------------------------------------
/test/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright 2018, 2019, 2021, 2022 Peter Dimov
2 | # Copyright 2025 Joaquin M Lopez Munoz
3 | # Distributed under the Boost Software License, Version 1.0.
4 | # See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
5 |
6 | include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST)
7 |
8 | if(HAVE_BOOST_TEST)
9 |
10 | boost_test_jamfile(FILE Jamfile.v2
11 | LINK_LIBRARIES Boost::bloom Boost::config Boost::core Boost::mp11)
12 |
13 | endif()
--------------------------------------------------------------------------------
/include/boost/bloom/detail/avx2.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #ifndef BOOST_BLOOM_DETAIL_AVX2_HPP
10 | #define BOOST_BLOOM_DETAIL_AVX2_HPP
11 |
12 | #if defined(__AVX2__)
13 | #define BOOST_BLOOM_AVX2
14 | #endif
15 |
16 | #if defined(BOOST_BLOOM_AVX2)
17 | #include
18 | #endif
19 |
20 | #endif
21 |
--------------------------------------------------------------------------------
/doc/bloom/reference.adoc:
--------------------------------------------------------------------------------
1 | [#reference]
2 | = Reference
3 |
4 | include::reference/header_bloom.adoc[]
5 | include::reference/header_filter.adoc[]
6 | include::reference/filter.adoc[]
7 | include::reference/subfilters.adoc[]
8 | include::reference/header_block.adoc[]
9 | include::reference/block.adoc[]
10 | include::reference/header_multiblock.adoc[]
11 | include::reference/multiblock.adoc[]
12 | include::reference/header_fast_multiblock32.adoc[]
13 | include::reference/fast_multiblock32.adoc[]
14 | include::reference/header_fast_multiblock64.adoc[]
15 | include::reference/fast_multiblock64.adoc[]
16 |
--------------------------------------------------------------------------------
/include/boost/bloom.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #ifndef BOOST_BLOOM_HPP
10 | #define BOOST_BLOOM_HPP
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | #endif
19 |
--------------------------------------------------------------------------------
/include/boost/bloom/detail/neon.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #ifndef BOOST_BLOOM_DETAIL_NEON_HPP
10 | #define BOOST_BLOOM_DETAIL_NEON_HPP
11 |
12 | #if defined(__ARM_NEON)&&!defined(__ARM_BIG_ENDIAN)
13 | #define BOOST_BLOOM_LITTLE_ENDIAN_NEON
14 | #endif
15 |
16 | #if defined(BOOST_BLOOM_LITTLE_ENDIAN_NEON)
17 | #include
18 | #endif
19 |
20 | #endif
21 |
--------------------------------------------------------------------------------
/include/boost/bloom/detail/sse2.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #ifndef BOOST_BLOOM_DETAIL_SSE2_HPP
10 | #define BOOST_BLOOM_DETAIL_SSE2_HPP
11 |
12 | #if defined(__SSE2__)|| \
13 | defined(_M_X64)||(defined(_M_IX86_FP)&&_M_IX86_FP>=2)
14 | #define BOOST_BLOOM_SSE2
15 | #endif
16 |
17 | #if defined(BOOST_BLOOM_SSE2)
18 | #include
19 | #endif
20 |
21 | #endif
22 |
--------------------------------------------------------------------------------
/.codecov.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2019 - 2021 Alexander Grund
2 | # Distributed under the Boost Software License, Version 1.0.
3 | # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
4 | #
5 | # Sample codecov configuration file. Edit as required
6 |
7 | codecov:
8 | max_report_age: off
9 | require_ci_to_pass: yes
10 | notify:
11 | # Increase this if you have multiple coverage collection jobs
12 | after_n_builds: 1
13 | wait_for_ci: yes
14 |
15 | # Change how pull request comments look
16 | comment:
17 | layout: "reach,diff,flags,files,footer"
18 |
19 | # Ignore specific files or folders. Glob patterns are supported.
20 | # See https://docs.codecov.com/docs/ignoring-paths
21 | ignore:
22 | - extra/**/*
23 | # - test/**/*
--------------------------------------------------------------------------------
/test/test_boost_bloom_hpp.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #include
10 | #include
11 |
12 | struct use_types
13 | {
14 | using type1=boost::bloom::filter;
15 | using type2=boost::bloom::block;
16 | using type3=boost::bloom::multiblock;
17 | using type4=boost::bloom::fast_multiblock32<1>;
18 | using type5=boost::bloom::fast_multiblock64<1>;
19 | };
20 |
21 | int main()
22 | {
23 | (void)use_types{};
24 | return boost::report_errors();
25 | }
26 |
--------------------------------------------------------------------------------
/include/boost/bloom/detail/constexpr_bit_width.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #ifndef BOOST_BLOOM_DETAIL_CONSTEXPR_BIT_WIDTH_HPP
10 | #define BOOST_BLOOM_DETAIL_CONSTEXPR_BIT_WIDTH_HPP
11 |
12 | #include
13 |
14 | namespace boost{
15 | namespace bloom{
16 | namespace detail{
17 |
18 | /* boost::core::bit_width is not always C++11 constexpr */
19 |
20 | constexpr std::size_t constexpr_bit_width(std::size_t x)
21 | {
22 | return x?1+constexpr_bit_width(x>>1):0;
23 | }
24 |
25 | } /* namespace detail */
26 | } /* namespace bloom */
27 | } /* namespace boost */
28 | #endif
29 |
--------------------------------------------------------------------------------
/include/boost/bloom/detail/block_fpr_base.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #ifndef BOOST_BLOOM_DETAIL_BLOCK_FPR_BASE_HPP
10 | #define BOOST_BLOOM_DETAIL_BLOCK_FPR_BASE_HPP
11 |
12 | #include
13 | #include
14 |
15 | namespace boost{
16 | namespace bloom{
17 | namespace detail{
18 |
19 | template
20 | struct block_fpr_base
21 | {
22 | static double fpr(std::size_t i,std::size_t w)
23 | {
24 | return std::pow(1.0-std::pow(1.0-1.0/w,(double)K*i),(double)K);
25 | }
26 | };
27 |
28 | } /* namespace detail */
29 | } /* namespace bloom */
30 | } /* namespace boost */
31 | #endif
32 |
--------------------------------------------------------------------------------
/include/boost/bloom/detail/multiblock_fpr_base.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #ifndef BOOST_BLOOM_DETAIL_MULTIBLOCK_FPR_BASE_HPP
10 | #define BOOST_BLOOM_DETAIL_MULTIBLOCK_FPR_BASE_HPP
11 |
12 | #include
13 | #include
14 |
15 | namespace boost{
16 | namespace bloom{
17 | namespace detail{
18 |
19 | template
20 | struct multiblock_fpr_base
21 | {
22 | static double fpr(std::size_t i,std::size_t w)
23 | {
24 | return std::pow(1.0-std::pow(1.0-(double)K/w,(double)i),(double)K);
25 | }
26 | };
27 |
28 | } /* namespace detail */
29 | } /* namespace bloom */
30 | } /* namespace boost */
31 | #endif
32 |
--------------------------------------------------------------------------------
/include/boost/bloom/fast_multiblock64.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #ifndef BOOST_BLOOM_FAST_MULTIBLOCK64_HPP
10 | #define BOOST_BLOOM_FAST_MULTIBLOCK64_HPP
11 |
12 | #include
13 |
14 | #if defined(BOOST_BLOOM_AVX2)
15 | #include
16 | #else /* fallback */
17 | #include
18 | #include
19 | #include
20 |
21 | namespace boost{
22 | namespace bloom{
23 |
24 | template
25 | using fast_multiblock64=multiblock;
26 |
27 | } /* namespace bloom */
28 | } /* namespace boost */
29 | #endif
30 |
31 | #endif
32 |
--------------------------------------------------------------------------------
/doc/bloom/reference/block.adoc:
--------------------------------------------------------------------------------
1 | [#block]
2 | == Class Template `block`
3 |
4 | :idprefix: block_
5 |
6 | `boost::bloom::block` -- A xref:subfilter[subfilter] over an integral type.
7 |
8 | === Synopsis
9 |
10 | [listing,subs="+macros,+quotes"]
11 | -----
12 | // #include
13 |
14 | namespace boost{
15 | namespace bloom{
16 |
17 | template
18 | struct block
19 | {
20 | static constexpr std::size_t k = K;
21 | using value_type = Block;
22 |
23 | // the rest of the interface is not public
24 |
25 | } // namespace bloom
26 | } // namespace boost
27 | -----
28 |
29 | === Description
30 |
31 | *Template Parameters*
32 |
33 | [cols="1,4"]
34 | |===
35 |
36 | |`Block`
37 | |An unsigned integral type or an array of 2^`N`^ elements of unsigned integral type.
38 |
39 | |`K`
40 | | Number of bits set/checked per operation. Must be greater than zero.
41 |
42 | |===
43 |
44 | '''
--------------------------------------------------------------------------------
/.drone/drone.bat:
--------------------------------------------------------------------------------
1 | @REM Copyright 2022 Peter Dimov
2 | @REM Distributed under the Boost Software License, Version 1.0.
3 | @REM https://www.boost.org/LICENSE_1_0.txt
4 |
5 | @ECHO ON
6 |
7 | set LIBRARY=%1
8 | set DRONE_BUILD_DIR=%CD%
9 |
10 | set BOOST_BRANCH=develop
11 | if "%DRONE_BRANCH%" == "master" set BOOST_BRANCH=master
12 | cd ..
13 | git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
14 | cd boost-root
15 | git submodule update --init tools/boostdep
16 | mkdir -p libs\%LIBRARY% & REM remove when/if the library makes it into Boost
17 | xcopy /s /e /q %DRONE_BUILD_DIR% libs\%LIBRARY%\
18 | python tools/boostdep/depinst/depinst.py -I examples %LIBRARY%
19 | cmd /c bootstrap
20 | b2 -d0 headers
21 |
22 | if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
23 | if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
24 | b2 -j3 libs/%LIBRARY%/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release embed-manifest-via=linker
25 |
--------------------------------------------------------------------------------
/doc/bloom/reference/multiblock.adoc:
--------------------------------------------------------------------------------
1 | [#multiblock]
2 | == Class Template `multiblock`
3 |
4 | :idprefix: multiblock_
5 |
6 | `boost::bloom::multiblock` -- A xref:subfilter[subfilter] over an array of an integral type.
7 |
8 | === Synopsis
9 |
10 | [listing,subs="+macros,+quotes"]
11 | -----
12 | // #include
13 |
14 | namespace boost{
15 | namespace bloom{
16 |
17 | template
18 | struct multiblock
19 | {
20 | static constexpr std::size_t k = K;
21 | using value_type = Block[k];
22 |
23 | // the rest of the interface is not public
24 |
25 | } // namespace bloom
26 | } // namespace boost
27 | -----
28 |
29 | === Description
30 |
31 | *Template Parameters*
32 |
33 | [cols="1,4"]
34 | |===
35 |
36 | |`Block`
37 | |An unsigned integral type or an array of 2^`N`^ elements of unsigned integral type.
38 |
39 | |`K`
40 | | Number of bits set/checked per operation. Must be greater than zero.
41 |
42 | |===
43 |
44 | Each of the `K` bits set/checked is located in a different element of the
45 | `Block[K]` array.
46 |
47 | '''
--------------------------------------------------------------------------------
/test/Jamfile.v2:
--------------------------------------------------------------------------------
1 | # Copyright 2025 Joaquín M López Muñoz.
2 | # Distributed under the Boost Software License, Version 1.0.
3 | # (See accompanying file LICENSE_1_0.txt or copy at
4 | # http://www.boost.org/LICENSE_1_0.txt)
5 | #
6 | # See http://www.boost.org/libs/bloom for library home page.
7 |
8 | require-b2 5.0.1 ;
9 | import-search /boost/config/checks ;
10 |
11 | import testing ;
12 | import config : requires ;
13 |
14 | project
15 | : requirements
16 | /boost/bloom//boost_bloom
17 | /boost/config//boost_config
18 | /boost/core//boost_core
19 | /boost/mp11//boost_mp11
20 | [ requires cxx11_noexcept ] # used as a proxy for C++11 support
21 | msvc:-D_SCL_SECURE_NO_WARNINGS
22 | ;
23 |
24 | run test_array.cpp ;
25 | run test_boost_bloom_hpp.cpp ;
26 | run test_bulk_operations.cpp ;
27 | run test_capacity.cpp ;
28 | run test_combination.cpp ;
29 | run test_comparison.cpp ;
30 | run test_construction.cpp ;
31 | run test_fpr.cpp ;
32 | run test_insertion.cpp ;
33 |
34 | compile test_visualization.cpp ;
35 |
--------------------------------------------------------------------------------
/test/test_visualization.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Braden Ganetsky.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | /* This is a file for testing of visualizations,
10 | * such as Visual Studio Natvis or GDB pretty printers.
11 | * Run this test and break at the label called `break_here`.
12 | * Inspect the variables to test correctness.
13 | */
14 |
15 | #include
16 |
17 | #include
18 |
19 | void break_here() {}
20 |
21 | // Prevent any "unused" errors
22 | template void use(Args&&...) {}
23 |
24 | int main()
25 | {
26 | boost::bloom::filter filter1{};
27 | boost::bloom::filter filter2{1};
28 | boost::bloom::filter filter3{{1,2,3,4,5}, 2000};
29 |
30 | use(filter1);
31 | use(filter2);
32 | use(filter3);
33 |
34 | break_here();
35 |
36 | return boost::report_errors();
37 | }
38 |
--------------------------------------------------------------------------------
/.drone/drone.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2022 Peter Dimov
4 | # Distributed under the Boost Software License, Version 1.0.
5 | # https://www.boost.org/LICENSE_1_0.txt
6 |
7 | set -ex
8 | export PATH=~/.local/bin:/usr/local/bin:$PATH
9 |
10 | DRONE_BUILD_DIR=$(pwd)
11 |
12 | BOOST_BRANCH=develop
13 | if [ "$DRONE_BRANCH" = "master" ]; then BOOST_BRANCH=master; fi
14 |
15 | cd ..
16 | git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
17 | cd boost-root
18 | mkdir -p libs/$LIBRARY # remove when/if the library makes it into Boost
19 | git submodule update --init tools/boostdep
20 | cp -r $DRONE_BUILD_DIR/* libs/$LIBRARY
21 | python tools/boostdep/depinst/depinst.py -I examples $LIBRARY
22 | ./bootstrap.sh
23 | ./b2 -d0 headers
24 |
25 | echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam
26 | ./b2 -j3 libs/$LIBRARY/test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release ${ADDRMD:+address-model=$ADDRMD} ${UBSAN:+undefined-sanitizer=norecover debug-symbols=on} ${ASAN:+address-sanitizer=norecover debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS} ${LINK:+link=$LINK}
27 |
--------------------------------------------------------------------------------
/doc/bloom/acknowledgements.adoc:
--------------------------------------------------------------------------------
1 | [#acknowledgements]
2 | = Acknowledgements
3 |
4 | :idprefix: acknowledgements_
5 |
6 | Peter Dimov and Christian Mazakas reviewed significant portions of the code
7 | and documentation during the development phase. Sam Darwin provided support
8 | for CI setup and documentation building. Braden Ganetsky contributed the
9 | GDB pretty-printer for `boost::bloom::filter`.
10 |
11 | The Boost acceptance review took place between the 13th and 22nd of May,
12 | 2025. Big thanks to Arnaud Becheler for his expert managing. The
13 | following people participated in the review:
14 | Dmitry Arkhipov,
15 | David Bien,
16 | Claudio DeSouza,
17 | Peter Dimov,
18 | Vinnie Falco,
19 | Alexander Grund,
20 | Seth Heeren,
21 | Andrzej Krzemieński,
22 | Ivan Matek,
23 | Christian Mazakas,
24 | Rubén Pérez,
25 | Kostas Savvidis,
26 | Peter Turcan,
27 | Tomer Vromen. Many thanks to all of them for their very helpful feedback.
28 |
29 | Boost.Bloom was designed and written in
30 | https://en.wikipedia.org/wiki/C%C3%A1ceres%2c_Spain[Cáceres^] and
31 | https://en.wikipedia.org/wiki/Oropesa,_Spain[Oropesa^],
32 | January-June 2025.
--------------------------------------------------------------------------------
/doc/bloom.adoc:
--------------------------------------------------------------------------------
1 | = Boost.Bloom
2 | :toc: left
3 | :toclevels: 3
4 | :idprefix:
5 | :docinfo: private-footer
6 | :source-highlighter: rouge
7 | :source-language: c++
8 | :nofooter:
9 | :sectlinks:
10 | :leveloffset: +1
11 | :imagesdir: ../img
12 | :stem: latexmath
13 | :small: pass:[]
14 | :small-end: pass:[]
15 | :cpp: C++
16 |
17 | ++++
18 |
39 | ++++
40 |
41 | include::bloom/intro.adoc[]
42 | include::bloom/primer.adoc[]
43 | include::bloom/tutorial.adoc[]
44 | include::bloom/configuration.adoc[]
45 | include::bloom/benchmarks.adoc[]
46 | include::bloom/reference.adoc[]
47 | include::bloom/future_work.adoc[]
48 | include::bloom/fpr_estimation.adoc[]
49 | include::bloom/implementation_notes.adoc[]
50 | include::bloom/release_notes.adoc[]
51 | include::bloom/acknowledgements.adoc[]
52 | include::bloom/copyright.adoc[]
53 |
--------------------------------------------------------------------------------
/include/boost/bloom/fast_multiblock32.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #ifndef BOOST_BLOOM_FAST_MULTIBLOCK32_HPP
10 | #define BOOST_BLOOM_FAST_MULTIBLOCK32_HPP
11 |
12 | #include
13 | #include
14 | #include
15 |
16 | #if defined(BOOST_BLOOM_AVX2)
17 | #include
18 | #elif defined(BOOST_BLOOM_SSE2) /* important that this comes after AVX2 */
19 | #include
20 | #elif defined(BOOST_BLOOM_LITTLE_ENDIAN_NEON)
21 | #include
22 | #else /* fallback */
23 | #include
24 | #include
25 | #include
26 |
27 | namespace boost{
28 | namespace bloom{
29 |
30 | template
31 | using fast_multiblock32=multiblock;
32 |
33 | } /* namespace bloom */
34 | } /* namespace boost */
35 | #endif
36 |
37 | #endif
38 |
--------------------------------------------------------------------------------
/doc/bloom/reference/header_filter.adoc:
--------------------------------------------------------------------------------
1 | [#header_filter]
2 | == ``
3 |
4 | :idprefix: header_filter_
5 |
6 | Defines `xref:filter[boost::bloom::filter]`
7 | and associated functions.
8 |
9 | [listing,subs="+macros,+quotes"]
10 | -----
11 | namespace boost{
12 | namespace bloom{
13 |
14 | template<
15 | typename T, std::size_t K,
16 | typename Subfilter = block, std::size_t Stride = 0,
17 | typename Hash = boost::hash,
18 | typename Allocator = std::allocator
19 | >
20 | class xref:filter[filter];
21 |
22 | template<
23 | typename T, std::size_t K, typename SF, std::size_t S, typename H, typename A
24 | >
25 | bool xref:filter_operator[operator+++==+++](
26 | const filter& x, const filter& y);
27 |
28 | template<
29 | typename T, std::size_t K, typename SF, std::size_t S, typename H, typename A
30 | >
31 | bool xref:filter_operator_2[operator!=](
32 | const filter& x, const filter& y);
33 |
34 | template<
35 | typename T, std::size_t K, typename SF, std::size_t S, typename H, typename A
36 | >
37 | void xref:filter_swap_2[swap](filter& x, filter& y)
38 | noexcept(noexcept(x.swap(y)));
39 |
40 | } // namespace bloom
41 | } // namespace boost
42 | -----
43 |
44 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Generated by `boostdep --cmake bloom`
2 | # Copyright 2020, 2021 Peter Dimov
3 | # Distributed under the Boost Software License, Version 1.0.
4 | # https://www.boost.org/LICENSE_1_0.txt
5 |
6 | cmake_minimum_required(VERSION 3.8...3.20)
7 |
8 | project(boost_bloom VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
9 |
10 | add_library(boost_bloom INTERFACE)
11 | add_library(Boost::bloom ALIAS boost_bloom)
12 |
13 | target_include_directories(boost_bloom INTERFACE include)
14 |
15 | target_link_libraries(boost_bloom
16 | INTERFACE
17 | Boost::assert
18 | Boost::config
19 | Boost::container_hash
20 | Boost::core
21 | Boost::throw_exception
22 | Boost::type_traits
23 | )
24 |
25 | target_compile_features(boost_bloom INTERFACE cxx_std_11)
26 |
27 | if(NOT CMAKE_VERSION VERSION_LESS 3.19 AND CMAKE_GENERATOR MATCHES "Visual Studio")
28 |
29 | file(GLOB_RECURSE boost_bloom_IDEFILES CONFIGURE_DEPENDS "include/*.hpp")
30 | source_group(TREE ${PROJECT_SOURCE_DIR}/include FILES ${boost_bloom_IDEFILES} PREFIX "Header Files")
31 | list(APPEND boost_bloom_IDEFILES extra/boost_bloom.natvis)
32 | target_sources(boost_bloom PRIVATE ${boost_bloom_IDEFILES})
33 |
34 | endif()
35 |
36 | if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
37 |
38 | add_subdirectory(test)
39 |
40 | endif()
41 |
--------------------------------------------------------------------------------
/example/basic.cpp:
--------------------------------------------------------------------------------
1 | /* Basic example of use of Boost.Bloom.
2 | *
3 | * Copyright 2025 Joaquin M Lopez Munoz.
4 | * Distributed under the Boost Software License, Version 1.0.
5 | * (See accompanying file LICENSE_1_0.txt or copy at
6 | * http://www.boost.org/LICENSE_1_0.txt)
7 | *
8 | * See https://www.boost.org/libs/bloom for library home page.
9 | */
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | int main()
17 | {
18 | /* Bloom filter of strings with 5 bits set per insertion */
19 |
20 | using filter = boost::bloom::filter;
21 |
22 | /* create filter with a capacity of 1,000,000 bits */
23 |
24 | filter f(1000000);
25 |
26 | /* insert elements in the set */
27 |
28 | f.insert("hello");
29 | f.insert("Boost");
30 |
31 | /* elements inserted are always correctly checked as such */
32 |
33 | assert(f.may_contain("hello") == true);
34 |
35 | /* Elements not inserted may incorrectly be identified as such with a
36 | * false probability rate (FPR) which is a function of the array capacity,
37 | * the number of bits set per element and generally how the
38 | * boost::bloom::filter was configured.
39 | */
40 |
41 | if(f.may_contain("bye")) { /* likely false */
42 | std::cout << "false positive\n";
43 | }
44 | else {
45 | std::cout << "everything worked as expected\n";
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/doc/bloom/reference/fast_multiblock64.adoc:
--------------------------------------------------------------------------------
1 | [#fast_multiblock64]
2 | == Class Template `fast_multiblock64`
3 |
4 | :idprefix: fast_multiblock64_
5 |
6 | `boost::bloom::fast_multiblock64` -- A faster replacement of
7 | `xref:multiblock[multiblock]`.
8 |
9 | === Synopsis
10 |
11 | [listing,subs="+macros,+quotes"]
12 | -----
13 | // #include
14 |
15 | namespace boost{
16 | namespace bloom{
17 |
18 | template
19 | struct fast_multiblock64
20 | {
21 | static constexpr std::size_t k = K;
22 | using value_type = _implementation-defined_;
23 |
24 | // might not be present
25 | static constexpr std::size_t used_value_size = _implementation-defined_;
26 |
27 | // the rest of the interface is not public
28 |
29 | } // namespace bloom
30 | } // namespace boost
31 | -----
32 |
33 | === Description
34 |
35 | *Template Parameters*
36 |
37 | [cols="1,4"]
38 | |===
39 |
40 | |`K`
41 | | Number of bits set/checked per operation. Must be greater than zero.
42 |
43 | |===
44 |
45 | `fast_multiblock64` is statistically equivalent to
46 | `xref:multiblock[multiblock]`, but takes advantage
47 | of selected SIMD technologies, when available at compile time, to perform faster.
48 | Currently supported: AVX2.
49 | The non-SIMD case falls back to regular `multiblock`.
50 |
51 | `xref:subfilters_used_value_size[_used-value-size_]>` is
52 | `8 * K`.
53 |
--------------------------------------------------------------------------------
/doc/bloom/reference/fast_multiblock32.adoc:
--------------------------------------------------------------------------------
1 | [#fast_multiblock32]
2 | == Class Template `fast_multiblock32`
3 |
4 | :idprefix: fast_multiblock32_
5 |
6 | `boost::bloom::fast_multiblock32` -- A faster replacement of
7 | `xref:multiblock[multiblock]`.
8 |
9 | === Synopsis
10 |
11 | [listing,subs="+macros,+quotes"]
12 | -----
13 | // #include
14 |
15 | namespace boost{
16 | namespace bloom{
17 |
18 | template
19 | struct fast_multiblock32
20 | {
21 | static constexpr std::size_t k = K;
22 | using value_type = _implementation-defined_;
23 |
24 | // might not be present
25 | static constexpr std::size_t used_value_size = _implementation-defined_;
26 |
27 | // the rest of the interface is not public
28 |
29 | } // namespace bloom
30 | } // namespace boost
31 | -----
32 |
33 | === Description
34 |
35 | *Template Parameters*
36 |
37 | [cols="1,4"]
38 | |===
39 |
40 | |`K`
41 | | Number of bits set/checked per operation. Must be greater than zero.
42 |
43 | |===
44 |
45 | `fast_multiblock32` is statistically equivalent to
46 | `xref:multiblock[multiblock]`, but takes advantage
47 | of selected SIMD technologies, when available at compile time, to perform faster.
48 | Currently supported: AVX2, little-endian Neon, SSE2.
49 | The non-SIMD case falls back to regular `multiblock`.
50 |
51 | `xref:subfilters_used_value_size[_used-value-size_]>` is
52 | `4 * K`.
53 |
54 | '''
--------------------------------------------------------------------------------
/test/test_types.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #ifndef BOOST_BLOOM_TEST_TEST_TYPES_HPP
10 | #define BOOST_BLOOM_TEST_TEST_TYPES_HPP
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 |
23 | using test_types=boost::mp11::mp_list<
24 | boost::bloom::filter<
25 | int,2
26 | >,
27 | boost::bloom::filter<
28 | std::string,1,boost::bloom::block,1
29 | >,
30 | boost::bloom::filter<
31 | int,1,boost::bloom::block
32 | >,
33 | boost::bloom::filter<
34 | std::size_t,1,boost::bloom::multiblock
35 | >,
36 | boost::bloom::filter<
37 | std::size_t,1,boost::bloom::multiblock,1
38 | >,
39 | boost::bloom::filter<
40 | unsigned char,1,boost::bloom::fast_multiblock32<5>,2
41 | >,
42 | boost::bloom::filter<
43 | int,1,boost::bloom::fast_multiblock64<11>
44 | >
45 | >;
46 |
47 | using identity_test_types=
48 | boost::mp11::mp_transform;
49 |
50 | #endif
51 |
--------------------------------------------------------------------------------
/extra/boost_bloom.natvis:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
23 |
24 |
25 | {{ capacity={capacity()} }}
26 |
27 | -
28 | *reinterpret_cast<hasher*>(static_cast<hash_base*>(this))
29 |
30 | -
31 | *reinterpret_cast<super::allocator_type*>(static_cast<super::allocator_base*>(this))
32 |
33 | -
34 | capacity()
35 |
36 |
37 | {{ data={(void*)data()} size={array_size()} }}
38 |
39 |
40 | array_size()
41 | data()
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/test/test_bulk_operations.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include "test_types.hpp"
14 | #include "test_utilities.hpp"
15 |
16 | using namespace test_utilities;
17 |
18 | template
19 | void test_bulk_operations()
20 | {
21 | using filter=Filter;
22 | using value_type=typename filter::value_type;
23 |
24 | ValueFactory fac;
25 | {
26 | filter f1(10000),f2(f1);
27 | std::array input;
28 | for(auto& x:input)x=fac();
29 | f1.insert(input.begin(),input.end());
30 | f2.insert(
31 | make_input_iterator(input.begin()),make_input_iterator(input.end()));
32 | BOOST_TEST(f1==f2);
33 | }
34 | {
35 | Filter f(10000);
36 | std::array input;
37 | for(auto& x:input)x=fac();
38 | for(std::size_t i=0;i
48 | void operator()(T)
49 | {
50 | using filter=typename T::type;
51 | using value_type=typename filter::value_type;
52 |
53 | test_bulk_operations>();
54 | }
55 | };
56 |
57 | int main()
58 | {
59 | boost::mp11::mp_for_each(lambda{});
60 | return boost::report_errors();
61 | }
62 |
--------------------------------------------------------------------------------
/test/test_array.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include "test_types.hpp"
14 | #include "test_utilities.hpp"
15 |
16 | using namespace test_utilities;
17 |
18 | template
19 | void test_array()
20 | {
21 | using filter=Filter;
22 |
23 | ValueFactory fac;
24 |
25 | {
26 | filter f;
27 | const filter& cf=f;
28 | BOOST_TEST_EQ(f.array().size(),0);
29 | BOOST_TEST_EQ(f.array().data(),cf.array().data());
30 | BOOST_TEST_EQ(f.array().size(),cf.array().size());
31 | }
32 | {
33 | filter f(1000);
34 | const filter& cf=f;
35 | BOOST_TEST_NE(f.array().data(),nullptr);
36 | BOOST_TEST_EQ(f.array().size(),f.capacity()/CHAR_BIT);
37 | BOOST_TEST_EQ(f.array().data(),cf.array().data());
38 | BOOST_TEST_EQ(f.array().size(),cf.array().size());
39 | }
40 | {
41 | filter f1(1000),f2(1000);
42 | for(int i=0;i<10;++i)f1.insert(fac());
43 | std::memcpy(f2.array().data(),f1.array().data(),f1.array().size());
44 | BOOST_TEST_NE(f1.array().data(),f2.array().data());
45 | BOOST_TEST(f1==f2);
46 | }
47 | }
48 |
49 | struct lambda
50 | {
51 | template
52 | void operator()(T)
53 | {
54 | using filter=typename T::type;
55 | using value_type=typename filter::value_type;
56 |
57 | test_array>();
58 | }
59 | };
60 |
61 | int main()
62 | {
63 | boost::mp11::mp_for_each(lambda{});
64 | return boost::report_errors();
65 | }
66 |
--------------------------------------------------------------------------------
/doc/bloom/future_work.adoc:
--------------------------------------------------------------------------------
1 | [#future_work]
2 | = Future Work
3 |
4 | :idprefix: future_work_
5 |
6 | A number of features asked by reviewers and users of Boost.Bloom are
7 | considered for inclusion into future versions of the library.
8 |
9 | == `try_insert`
10 |
11 | To avoid inserting an already present element, we now have to do:
12 |
13 | [source]
14 | -----
15 | if(!f.may_contain(x)) f.insert(x);
16 | -----
17 |
18 | These two calls can be combined in a potentially faster,
19 | single operation:
20 |
21 | [source]
22 | -----
23 | bool res = f.try_insert(x); // returns true if x was not present
24 | -----
25 |
26 | == Estimation of number of elements inserted
27 |
28 | For a classical Bloom filter, the number of elements actually inserted
29 | can be estimated from the number {small}stem:[B]{small-end} of bits set
30 | to one in the array as
31 |
32 | [.formula-center]
33 | {small}stem:[n\approx-\displaystyle\frac{m}{k}\ln\left(1-\displaystyle\frac{B}{m}\right),]{small-end}
34 |
35 | which can be used for the implementation of a member function
36 | `estimated_size`. As of this writing, we don't know how to extend the
37 | formula to the case of block and multiblock filters. Any help on this
38 | problem is much appreciated.
39 |
40 | == Run-time specification of _k_
41 |
42 | Currently, the number _k_ of bits set per operation is configured at compile time.
43 | A variation of (or extension to) `boost::bloom::filter` can be provided
44 | where the value of _k_ is specified at run-time, the tradeoff being that
45 | its performance will be worse than the static case (preliminary experiments
46 | show an increase in execution time of around 10-20%).
47 |
48 | == Alternative filters
49 |
50 | We can consider adding additional data structures such as
51 | https://en.wikipedia.org/wiki/Cuckoo_filter[cuckoo^] and
52 | https://arxiv.org/pdf/1912.08258[xor^] filters, which are more
53 | space efficient and potentially faster.
--------------------------------------------------------------------------------
/test/test_comparison.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #include
10 | #include
11 | #include "test_types.hpp"
12 | #include "test_utilities.hpp"
13 |
14 | using namespace test_utilities;
15 |
16 | template
17 | void test_comparison()
18 | {
19 | using filter=Filter;
20 |
21 | ValueFactory fac;
22 |
23 | {
24 | BOOST_TEST(filter{}==filter{});
25 | BOOST_TEST(!(filter{}!=filter{}));
26 | BOOST_TEST(!(filter{}==filter{1000}));
27 | BOOST_TEST(filter{1000}!=filter{});
28 | BOOST_TEST(!(filter{1000}==filter{{fac(),fac()},1000}));
29 | BOOST_TEST((filter{{fac(),fac()},1000}!=filter{1000}));
30 | }
31 | {
32 | filter f1{1000},f2{1000};
33 | for(int i=0;i<10;++i){
34 | auto x=fac();
35 | f1.insert(x);
36 | f2.insert(x);
37 | }
38 | BOOST_TEST(f1==f2);
39 | BOOST_TEST(!(f2!=f1));
40 |
41 | for(int i=0;i<10;++i){
42 | auto x=fac();
43 | f2.insert(x);
44 | }
45 | BOOST_TEST(!(f1==f2)); /* with high prob. */
46 | BOOST_TEST(f2!=f1);
47 |
48 | const filter f3=f2;
49 | BOOST_TEST(f2==f3);
50 | BOOST_TEST(!(f3!=f2));
51 |
52 | f2.clear();
53 | BOOST_TEST(!(f2==f3));
54 | BOOST_TEST(f3!=f2);
55 | }
56 | }
57 |
58 | struct lambda
59 | {
60 | template
61 | void operator()(T)
62 | {
63 | using filter=typename T::type;
64 | using value_type=typename filter::value_type;
65 |
66 | test_comparison>();
67 | }
68 | };
69 |
70 | int main()
71 | {
72 | boost::mp11::mp_for_each(lambda{});
73 | return boost::report_errors();
74 | }
75 |
--------------------------------------------------------------------------------
/include/boost/bloom/multiblock.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #ifndef BOOST_BLOOM_MULTIBLOCK_HPP
10 | #define BOOST_BLOOM_MULTIBLOCK_HPP
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 |
20 | namespace boost{
21 | namespace bloom{
22 |
23 | template
24 | struct multiblock:
25 | public detail::multiblock_fpr_base,
26 | private detail::block_base
27 | {
28 | static constexpr std::size_t k=K;
29 | using value_type=Block[k];
30 |
31 | /* NOLINTNEXTLINE(readability-redundant-inline-specifier) */
32 | static inline void mark(value_type& x,std::uint64_t hash)
33 | {
34 | std::size_t i=0;
35 | loop(hash,[&](std::uint64_t h){block_ops::set(x[i++],h&mask);});
36 | }
37 |
38 | #if BOOST_WORKAROUND(BOOST_MSVC,<=1900)
39 | /* 'int': forcing value to bool 'true' or 'false' */
40 | #pragma warning(push)
41 | #pragma warning(disable:4800)
42 | #endif
43 |
44 | /* NOLINTNEXTLINE(readability-redundant-inline-specifier) */
45 | static inline bool check(const value_type& x,std::uint64_t hash)
46 | {
47 | int res=1;
48 | std::size_t i=0;
49 | loop(hash,[&](std::uint64_t h){block_ops::reduce(res,x[i++],h&mask);});
50 | return res;
51 | }
52 |
53 | #if BOOST_WORKAROUND(BOOST_MSVC,<=1900)
54 | #pragma warning(pop) /* C4800 */
55 | #endif
56 |
57 | private:
58 | using super=detail::block_base;
59 | using super::mask;
60 | using super::loop;
61 | using block_ops=detail::block_ops;
62 | };
63 |
64 | } /* namespace bloom */
65 | } /* namespace boost */
66 | #endif
67 |
--------------------------------------------------------------------------------
/doc/bloom/reference/subfilters.adoc:
--------------------------------------------------------------------------------
1 | [#subfilter]
2 | == Subfilters
3 |
4 | :idprefix: subfilters_
5 |
6 | A _subfilter_ implements a specific algorithm for bit setting (insertion) and
7 | bit checking (lookup) for `boost::bloom::filter`. Subfilters operate
8 | on portions of the filter's internal array called _subarrays_. The
9 | exact width of these subarrays is statically dependent on the subfilter type.
10 |
11 | The full interface of a conforming subfilter is not exposed publicly, hence
12 | users can't provide their own subfilters and may only use those natively
13 | provided by the library. What follows is the publicly available interface.
14 |
15 | [listing,subs="+macros,+quotes"]
16 | -----
17 | Subfilter::k
18 | -----
19 |
20 | [horizontal]
21 | Result:;; A compile-time `std::size_t` value indicating
22 | the number of (not necessarily distinct) bits set/checked per operation.
23 |
24 | [listing,subs="+macros,+quotes"]
25 | -----
26 | typename Subfilter::value_type
27 | -----
28 |
29 | [horizontal]
30 | Result:;; A cv-unqualified,
31 | https://en.cppreference.com/w/cpp/named_req/TriviallyCopyable[TriviallyCopyable^]
32 | type to which the subfilter projects assigned subarrays.
33 |
34 | [listing,subs="+macros,+quotes"]
35 | -----
36 | Subfilter::used_value_size
37 | -----
38 |
39 | [horizontal]
40 | Result:;; A compile-time `std::size_t` value indicating
41 | the size of the effective portion of `Subfilter::value_type` used
42 | for bit setting/checking (assumed to begin at the lowest address in memory).
43 | Postconditions:;; Greater than zero and not greater than `sizeof(Subfilter::value_type)`.
44 | Notes:;; Optional.
45 |
46 | === _used-value-size_
47 |
48 | [listing,subs="+macros,+quotes"]
49 | -----
50 | template
51 | constexpr std::size_t _used-value-size_; // exposition only
52 | -----
53 |
54 | `_used-value-size_` is `Subfilter::used_value_size` if this nested
55 | constant exists, or `sizeof(Subfilter::value_type)` otherwise.
56 | The value is the effective size in bytes of the subarrays upon which a
57 | given subfilter operates.
58 |
59 | '''
--------------------------------------------------------------------------------
/include/boost/bloom/block.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #ifndef BOOST_BLOOM_BLOCK_HPP
10 | #define BOOST_BLOOM_BLOCK_HPP
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | namespace boost{
19 | namespace bloom{
20 |
21 | template
22 | struct block:
23 | public detail::block_fpr_base,
24 | private detail::block_base
25 | {
26 | static constexpr std::size_t k=K;
27 | using value_type=Block;
28 |
29 | /* NOLINTNEXTLINE(readability-redundant-inline-specifier) */
30 | static inline void mark(value_type& x,std::uint64_t hash)
31 | {
32 | loop(hash,[&](std::uint64_t h){block_ops::set(x,h&mask);});
33 | }
34 |
35 | /* NOLINTNEXTLINE(readability-redundant-inline-specifier) */
36 | static inline bool check(const value_type& x,std::uint64_t hash)
37 | {
38 | return check(x,hash,typename block_ops::is_extended_block{});
39 | }
40 |
41 | private:
42 | using super=detail::block_base;
43 | using super::mask;
44 | using super::loop;
45 | using super::loop_while;
46 | using block_ops=detail::block_ops;
47 |
48 | /* NOLINTNEXTLINE(readability-redundant-inline-specifier) */
49 | static inline bool check(
50 | const value_type& x,std::uint64_t hash,
51 | std::false_type /* non-extended block */)
52 | {
53 | Block fp;
54 | block_ops::zero(fp);
55 | mark(fp,hash);
56 | return block_ops::testc(x,fp);
57 | }
58 |
59 | /* NOLINTNEXTLINE(readability-redundant-inline-specifier) */
60 | static inline bool check(
61 | const value_type& x,std::uint64_t hash,
62 | std::true_type /* extended block */)
63 | {
64 | int res=1;
65 | loop(hash,[&](std::uint64_t h){
66 | res&=block_ops::get_at_lsb(x,h&mask);
67 | });
68 | return res;
69 | }
70 | };
71 |
72 | } /* namespace bloom */
73 | } /* namespace boost */
74 | #endif
75 |
--------------------------------------------------------------------------------
/include/boost/bloom/detail/block_ops.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #ifndef BOOST_BLOOM_DETAIL_BLOCK_OPS_HPP
10 | #define BOOST_BLOOM_DETAIL_BLOCK_OPS_HPP
11 |
12 | #include
13 | #include
14 | #include
15 |
16 | namespace boost{
17 | namespace bloom{
18 | namespace detail{
19 |
20 | #if defined(BOOST_MSVC)
21 | #pragma warning(push)
22 | #pragma warning(disable:4714) /* marked as __forceinline not inlined */
23 | #endif
24 |
25 | template
26 | struct block_ops
27 | {
28 | using is_extended_block=std::false_type;
29 | using value_type=Block;
30 |
31 | static BOOST_FORCEINLINE void zero(Block& x)
32 | {
33 | x=0;
34 | }
35 |
36 | static BOOST_FORCEINLINE void set(value_type& x,std::uint64_t n)
37 | {
38 | x|=Block(1)<(x>>n);
44 | }
45 |
46 | static BOOST_FORCEINLINE void reduce(
47 | int& res,const value_type& x,std::uint64_t n)
48 | {
49 | res&=get_at_lsb(x,n);
50 | }
51 |
52 | static BOOST_FORCEINLINE bool testc(const value_type& x,const value_type& y)
53 | {
54 | return (x&y)==y;
55 | }
56 | };
57 |
58 | template
59 | struct block_ops
60 | {
61 | using is_extended_block=std::true_type;
62 | using value_type=Block[N];
63 |
64 | static BOOST_FORCEINLINE void zero(value_type& x)
65 | {
66 | for(std::size_t i=0;i(x[n%N]>>(n/N));
77 | }
78 |
79 | static BOOST_FORCEINLINE void reduce(
80 | int& res,const value_type& x,std::uint64_t n)
81 | {
82 | res&=get_at_lsb(x,n);
83 | }
84 | };
85 |
86 | #if defined(BOOST_MSVC)
87 | #pragma warning(pop) /* C4714 */
88 | #endif
89 |
90 |
91 | } /* namespace detail */
92 | } /* namespace bloom */
93 | } /* namespace boost */
94 |
95 | #endif
96 |
--------------------------------------------------------------------------------
/doc/bloom/intro.adoc:
--------------------------------------------------------------------------------
1 | [#intro]
2 | = Introduction
3 |
4 | :idprefix: intro_
5 |
6 | Boost.Bloom provides the class template `xref:tutorial[boost::bloom::filter]`
7 | that can be configured to implement a classical Bloom filter as well as
8 | variations discussed in the literature such as block filters, multiblock filters,
9 | and more.
10 |
11 | [source,subs="+macros,+quotes"]
12 | -----
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | int main()
19 | {
20 | // Bloom filter of strings with 5 bits set per insertion
21 | using filter = boost::bloom::filter;
22 |
23 | // create filter with a capacity of 1'000'000 **bits**
24 | filter f(1'000'000);
25 |
26 | // insert elements (they can't be erased, Bloom filters are insert-only)
27 | f.insert("hello");
28 | f.insert("Boost");
29 |
30 | // elements inserted are always correctly checked as such
31 | assert(f.may_contain("hello") == true);
32 |
33 | // elements not inserted may incorrectly be identified as such with a
34 | // false positive rate (FPR) which is a function of the array capacity,
35 | // the number of bits set per element and generally how the boost::bloom::filter
36 | // was specified
37 | if(f.may_contain("bye")) { // likely false
38 | std::cout << "false positive\n";
39 | }
40 | else {
41 | std::cout << "everything worked as expected\n";
42 | }
43 | }
44 | -----
45 |
46 | The different filter variations supported are specified at compile time
47 | as part of the `boost::bloom::filter` instantiation definition.
48 | Boost.Bloom has been implemented with a focus on performance;
49 | SIMD technologies such as AVX2, Neon and SSE2 can be leveraged to speed up
50 | operations.
51 |
52 | == Getting Started
53 |
54 | Consult the website
55 | https://www.boost.org/doc/user-guide/getting-started.html[section^]
56 | on how to install the entire Boost project or only Boost.Bloom
57 | and its dependencies.
58 |
59 | Boost.Bloom is a header-only library, so no additional build phase is
60 | needed. C++11 or later required. The library has been verified to
61 | work with GCC 4.8, Clang 3.9 and Visual Studio 2015 (and later versions
62 | of those). You can check that your environment is correctly set up
63 | by compiling the
64 | link:../../example/basic.cpp[example program] shown above.
65 |
66 | If you are not familiar with Bloom filters in general, see the
67 | xref:primer[primer]; otherwise, you can jump directly to the
68 | xref:tutorial[tutorial].
--------------------------------------------------------------------------------
/example/serialization.cpp:
--------------------------------------------------------------------------------
1 | /* Serialization of boost::bloom::filter.
2 | *
3 | * Copyright 2025 Joaquin M Lopez Munoz.
4 | * Distributed under the Boost Software License, Version 1.0.
5 | * (See accompanying file LICENSE_1_0.txt or copy at
6 | * http://www.boost.org/LICENSE_1_0.txt)
7 | *
8 | * See https://www.boost.org/libs/bloom for library home page.
9 | */
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 |
20 | /* emits a deterministic pseudorandom sequence of UUIDs */
21 |
22 | struct uuid_generator
23 | {
24 | boost::uuids::uuid operator()()
25 | {
26 | std::uint8_t data[16];
27 | std::uint64_t x = rng();
28 | std::memcpy(&data[0], &x, sizeof(x));
29 | x = rng();
30 | std::memcpy(&data[8], &x, sizeof(x));
31 |
32 | return {data};
33 | }
34 |
35 | boost::detail::splitmix64 rng;
36 | };
37 |
38 | using filter = boost::bloom::filter<
39 | boost::uuids::uuid, 1, boost::bloom::multiblock >;
40 |
41 | static constexpr std::size_t num_elements = 10000;
42 |
43 | /* creates a filter with num_elements UUIDs */
44 |
45 | filter create_filter()
46 | {
47 | uuid_generator gen;
48 | filter f(num_elements, 0.005);
49 | for(std::size_t i = 0; i < num_elements; ++i) f.insert(gen());
50 | return f;
51 | }
52 |
53 | void save_filter(const filter& f, const char* filename)
54 | {
55 | std::ofstream out(filename, std::ios::binary | std::ios::trunc);
56 | std::size_t c=f.capacity();
57 | out.write(reinterpret_cast(&c), sizeof(c)); /* save capacity (bits) */
58 | auto s = f.array();
59 | out.write(reinterpret_cast(s.data()), s.size()); /* save array */
60 | }
61 |
62 | filter load_filter(const char* filename)
63 | {
64 | std::ifstream in(filename, std::ios::binary);
65 | std::size_t c;
66 | in.read(reinterpret_cast(&c), sizeof(c));
67 | filter f(c);
68 | auto s = f.array();
69 | in.read(reinterpret_cast(s.data()), s.size()); /* load array */
70 | return f;
71 | }
72 |
73 | int main()
74 | {
75 | static constexpr const char* filename = "filter.bin";
76 |
77 | auto f1 = create_filter();
78 | save_filter(f1, filename);
79 | auto f2 = load_filter(filename);
80 |
81 | if (f1 == f2) std::cout << "serialization correct\n";
82 | else std::cout << "something went wrong\n";
83 | }
84 |
--------------------------------------------------------------------------------
/include/boost/bloom/detail/mulx64.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2022 Peter Dimov.
2 | * Copyright 2025 Joaquin M Lopez Munoz.
3 | * Distributed under the Boost Software License, Version 1.0.
4 | * (See accompanying file LICENSE_1_0.txt or copy at
5 | * http://www.boost.org/LICENSE_1_0.txt)
6 | *
7 | * See https://www.boost.org/libs/bloom for library home page.
8 | */
9 |
10 | #ifndef BOOST_BLOOM_DETAIL_MULX64_HPP
11 | #define BOOST_BLOOM_DETAIL_MULX64_HPP
12 |
13 | #include
14 | #include
15 | #include
16 |
17 | #if defined(_MSC_VER)&&!defined(__clang__)
18 | #include
19 | #endif
20 |
21 | namespace boost{
22 | namespace bloom{
23 | namespace detail{
24 |
25 | #if defined(_MSC_VER)&&defined(_M_X64)&&!defined(__clang__)
26 |
27 | __forceinline std::uint64_t umul128(
28 | std::uint64_t x,std::uint64_t y,std::uint64_t& hi)
29 | {
30 | return _umul128(x,y,&hi);
31 | }
32 |
33 | #elif defined(_MSC_VER)&&defined(_M_ARM64)&&!defined(__clang__)
34 |
35 | __forceinline std::uint64_t umul128(
36 | std::uint64_t x,std::uint64_t y,std::uint64_t& hi)
37 | {
38 | hi=__umulh(x,y);
39 | return x*y;
40 | }
41 |
42 | #elif defined(__SIZEOF_INT128__)
43 |
44 | /* NOLINTNEXTLINE(readability-redundant-inline-specifier) */
45 | inline std::uint64_t umul128(
46 | std::uint64_t x,std::uint64_t y,std::uint64_t& hi)
47 | {
48 | __uint128_t r=(__uint128_t)x*y;
49 | hi=(std::uint64_t)(r>>64);
50 | return (std::uint64_t)r;
51 | }
52 |
53 | #else
54 |
55 | /* NOLINTNEXTLINE(readability-redundant-inline-specifier) */
56 | inline std::uint64_t umul128(
57 | std::uint64_t x,std::uint64_t y,std::uint64_t& hi)
58 | {
59 | std::uint64_t x1=(std::uint32_t)x;
60 | std::uint64_t x2=x >> 32;
61 |
62 | std::uint64_t y1=(std::uint32_t)y;
63 | std::uint64_t y2=y >> 32;
64 |
65 | std::uint64_t r3=x2*y2;
66 |
67 | std::uint64_t r2a=x1*y2;
68 |
69 | r3+=r2a>>32;
70 |
71 | std::uint64_t r2b=x2*y1;
72 |
73 | r3+=r2b>>32;
74 |
75 | std::uint64_t r1=x1*y1;
76 |
77 | std::uint64_t r2=(r1>>32)+(std::uint32_t)r2a+(std::uint32_t)r2b;
78 |
79 | r1=(r2<<32)+(std::uint32_t)r1;
80 | r3+=r2>>32;
81 |
82 | hi=r3;
83 | return r1;
84 | }
85 |
86 | #endif
87 |
88 | /* NOLINTNEXTLINE(readability-redundant-inline-specifier) */
89 | inline std::uint64_t mulx64(std::uint64_t x)noexcept
90 | {
91 | /* multiplier is 2^64/phi */
92 | std::uint64_t hi;
93 | std::uint64_t lo=umul128(x,0x9E3779B97F4A7C15ull,hi);
94 | return hi^lo;
95 | }
96 |
97 | } /* namespace detail */
98 | } /* namespace bloom */
99 | } /* namespace boost */
100 | #endif
101 |
--------------------------------------------------------------------------------
/include/boost/bloom/detail/block_base.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #ifndef BOOST_BLOOM_DETAIL_BLOCK_BASE_HPP
10 | #define BOOST_BLOOM_DETAIL_BLOCK_BASE_HPP
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 |
19 | namespace boost{
20 | namespace bloom{
21 | namespace detail{
22 |
23 | #if defined(BOOST_MSVC)
24 | #pragma warning(push)
25 | #pragma warning(disable:4714) /* marked as __forceinline not inlined */
26 | #endif
27 |
28 | /* Validates type Block and provides common looping facilities for block
29 | * and multiblock.
30 | */
31 |
32 | template
33 | struct block_base
34 | {
35 | static_assert(
36 | is_unsigned_integral_or_extended_unsigned_integral::value||
37 | (
38 | is_array_of<
39 | Block,is_unsigned_integral_or_extended_unsigned_integral>::value&&
40 | is_power_of_two::value>::value
41 | ),
42 | "Block must be an (extended) unsigned integral type or an array T[N] "
43 | "with T an (extended) unsigned integral type and N a power of two");
44 | static constexpr std::size_t k=K;
45 | static constexpr std::size_t hash_width=sizeof(std::uint64_t)*CHAR_BIT;
46 | static constexpr std::size_t block_width=sizeof(Block)*CHAR_BIT;
47 | static constexpr std::size_t mask=block_width-1;
48 | static constexpr std::size_t shift=constexpr_bit_width(mask);
49 | static constexpr std::size_t rehash_k=(hash_width-shift)/shift;
50 |
51 | template
52 | static BOOST_FORCEINLINE void loop(std::uint64_t hash,F f)
53 | {
54 | for(std::size_t i=0;i>=shift;
58 | f(h);
59 | }
60 | hash=detail::mulx64(hash);
61 | }
62 | auto h=hash;
63 | for(std::size_t i=0;i>=shift;
65 | f(h);
66 | }
67 | }
68 |
69 | template
70 | static BOOST_FORCEINLINE bool loop_while(std::uint64_t hash,F f)
71 | {
72 | for(std::size_t i=0;i>=shift;
76 | if(!f(h))return false;
77 | }
78 | hash=detail::mulx64(hash);
79 | }
80 | auto h=hash;
81 | for(std::size_t i=0;i>=shift;
83 | if(!f(h))return false;
84 | }
85 | return true;
86 | }
87 | };
88 |
89 | #if defined(BOOST_MSVC)
90 | #pragma warning(pop) /* C4714 */
91 | #endif
92 |
93 | } /* namespace detail */
94 | } /* namespace bloom */
95 | } /* namespace boost */
96 | #endif
97 |
--------------------------------------------------------------------------------
/test/test_insertion.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include "test_types.hpp"
14 | #include "test_utilities.hpp"
15 |
16 | using namespace test_utilities;
17 |
18 | template
19 | struct multiarg_constructed
20 | {
21 | multiarg_constructed()=default;
22 | template
23 | multiarg_constructed(Arg1&& arg,Arg2&&,Args&&...):
24 | x{std::forward(arg)}{}
25 | multiarg_constructed(const multiarg_constructed&)=delete;
26 | multiarg_constructed(multiarg_constructed&&)=delete;
27 | multiarg_constructed& operator=(const multiarg_constructed&)=default;
28 |
29 | operator const T&()const{return x;}
30 |
31 | T x;
32 | };
33 |
34 | template
35 | struct transparent:Functor
36 | {
37 | using is_transparent=void;
38 | using Functor::Functor;
39 | };
40 |
41 | template
42 | void test_insertion()
43 | {
44 | using filter=rehash_filter<
45 | revalue_filter>,
46 | transparent
47 | >;
48 | using value_type=typename filter::value_type;
49 |
50 | ValueFactory fac;
51 |
52 | {
53 | filter f(10000);
54 | value_type x{fac(),0};
55 | f.insert(const_cast(x));
56 | BOOST_TEST(f.may_contain(x));
57 | }
58 | {
59 | filter f(10000);
60 | value_type x{fac(),0};
61 | f.insert(std::move(x));
62 | BOOST_TEST(f.may_contain(x));
63 | }
64 | {
65 | filter f(10000);
66 | auto x=fac();
67 | f.insert(x); /* transparent insert */
68 | BOOST_TEST(f.may_contain(x));
69 | }
70 | {
71 | filter f(10000);
72 | std::array input;
73 | for(auto& x:input)x={fac(),0};
74 | f.insert(input.begin(),input.end());
75 | BOOST_TEST(may_contain(f,input));
76 | }
77 | {
78 | filter f(10000);
79 | std::array input;
80 | for(auto& x:input)x=fac();
81 | f.insert(input.begin(),input.end()); /* transparent insert */
82 | BOOST_TEST(may_contain(f,input));
83 | }
84 | {
85 | filter f(10000);
86 | std::initializer_list il={{fac(),0},{fac(),0},{fac(),0}};
87 | f.insert(il);
88 | BOOST_TEST(may_contain(f,il));
89 | }
90 | }
91 |
92 | struct lambda
93 | {
94 | template
95 | void operator()(T)
96 | {
97 | using filter=typename T::type;
98 | using value_type=typename filter::value_type;
99 |
100 | test_insertion>();
101 | }
102 | };
103 |
104 | int main()
105 | {
106 | boost::mp11::mp_for_each(lambda{});
107 | return boost::report_errors();
108 | }
109 |
--------------------------------------------------------------------------------
/test/test_combination.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #include
10 | #include
11 | #include
12 | #include "test_types.hpp"
13 | #include "test_utilities.hpp"
14 |
15 | using namespace test_utilities;
16 |
17 | template
18 | void test_combination()
19 | {
20 | using filter=Filter;
21 | using value_type=typename filter::value_type;
22 |
23 | std::vector input1,input2;
24 | ValueFactory fac;
25 | for(int i=0;i<10;++i){
26 | input1.push_back(fac());
27 | input2.push_back(fac());
28 | }
29 |
30 | #if defined(__clang__)&&defined(__has_warning)
31 | #if __has_warning("-Wself-assign-overloaded")
32 | #pragma clang diagnostic push
33 | #pragma clang diagnostic ignored "-Wself-assign-overloaded"
34 | #endif
35 | #endif
36 | {
37 | filter f{0};
38 | f&=f;
39 | f|=f;
40 | }
41 | {
42 | filter f{input1.begin(),input1.end(),1000},
43 | f_copy{f};
44 |
45 | f&=f;
46 | BOOST_TEST(f==f_copy);
47 | f|=f;
48 | BOOST_TEST(f==f_copy);
49 | }
50 | #if defined(__clang__)&&defined(__has_warning)
51 | #if __has_warning("-Wself-assign-overloaded")
52 | #pragma clang diagnostic pop
53 | #endif
54 | #endif
55 |
56 | {
57 | filter f1{input1.begin(),input1.end(),1000},
58 | f1_copy{f1},
59 | f2{input2.begin(),input2.end(),f1.capacity()+1};
60 |
61 | BOOST_TEST_THROWS(f1&=filter{},std::invalid_argument);
62 | BOOST_TEST(f1==f1_copy);
63 | BOOST_TEST_THROWS(f1&=f2,std::invalid_argument);
64 | BOOST_TEST(f1==f1_copy);
65 | BOOST_TEST_THROWS(f1|=filter{},std::invalid_argument);
66 | BOOST_TEST(f1==f1_copy);
67 | BOOST_TEST_THROWS(f1|=f2;,std::invalid_argument);
68 | BOOST_TEST(f1==f1_copy);
69 | }
70 | {
71 | filter f1{input1.begin(),input1.end(),1000},
72 | f1_copy{f1},
73 | empty{f1.capacity()};
74 |
75 | filter& rf1=(f1|=empty);
76 | BOOST_TEST_EQ(&rf1,&f1);
77 | BOOST_TEST(f1==f1_copy);
78 | filter& rf2=(f1&=empty);
79 | BOOST_TEST_EQ(&rf2,&f1);
80 | BOOST_TEST(f1==empty);
81 | }
82 | {
83 | filter f1{input1.begin(),input1.end(),1000};
84 | const filter f2{input2.begin(),input2.end(),f1.capacity()};
85 |
86 | f1.insert(input2.begin(),input2.end());
87 | f1&=f2;
88 | BOOST_TEST(may_contain(f1,input2));
89 | BOOST_TEST(may_not_contain(f1,input1));
90 | }
91 | {
92 | filter f1{input1.begin(),input1.end(),1000};
93 | const filter f2{input2.begin(),input2.end(),f1.capacity()};
94 |
95 | f1|=f2;
96 | BOOST_TEST(may_contain(f1,input1));
97 | BOOST_TEST(may_contain(f1,input2));
98 | }
99 | }
100 |
101 | struct lambda
102 | {
103 | template
104 | void operator()(T)
105 | {
106 | using filter=typename T::type;
107 | using value_type=typename filter::value_type;
108 |
109 | test_combination>();
110 | }
111 | };
112 |
113 | int main()
114 | {
115 | boost::mp11::mp_for_each(lambda{});
116 | return boost::report_errors();
117 | }
118 |
--------------------------------------------------------------------------------
/include/boost/bloom/detail/fast_multiblock32_avx2.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright 2025 Joaquin M Lopez Munoz.
2 | * Distributed under the Boost Software License, Version 1.0.
3 | * (See accompanying file LICENSE_1_0.txt or copy at
4 | * http://www.boost.org/LICENSE_1_0.txt)
5 | *
6 | * See https://www.boost.org/libs/bloom for library home page.
7 | */
8 |
9 | #ifndef BOOST_BLOOM_DETAIL_FAST_MULTIBLOCK32_AVX2_HPP
10 | #define BOOST_BLOOM_DETAIL_FAST_MULTIBLOCK32_AVX2_HPP
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 |
20 | namespace boost{
21 | namespace bloom{
22 |
23 | #if defined(BOOST_MSVC)
24 | #pragma warning(push)
25 | #pragma warning(disable:4714) /* marked as __forceinline not inlined */
26 | #endif
27 |
28 | template
29 | struct fast_multiblock32:detail::multiblock_fpr_base
30 | {
31 | static constexpr std::size_t k=K;
32 | using value_type=__m256i[(k+7)/8];
33 | static constexpr std::size_t used_value_size=sizeof(std::uint32_t)*k;
34 |
35 | static BOOST_FORCEINLINE void mark(value_type& x,std::uint64_t hash)
36 | {
37 | for(std::size_t i=0;i
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include "test_types.hpp"
16 | #include "test_utilities.hpp"
17 |
18 | using namespace test_utilities;
19 |
20 | template
21 | struct throwing_allocator
22 | {
23 | using value_type=T;
24 |
25 | throwing_allocator()=default;
26 | template
27 | throwing_allocator(const throwing_allocator&){}
28 |
29 | T* allocate(std::size_t n)
30 | {
31 | return static_cast(capped_new(n*sizeof(T)));
32 | }
33 |
34 | void deallocate(T* p,std::size_t){::operator delete(p);}
35 |
36 | bool operator==(const throwing_allocator& x)const{return true;}
37 | bool operator!=(const throwing_allocator& x)const{return false;}
38 | };
39 |
40 | template
41 | double measure_fpr(Filter&& f,std::size_t n)
42 | {
43 | using value_type=typename std::remove_reference::type::value_type;
44 |
45 | value_factory fac;
46 | std::size_t res=0;
47 | for(std::size_t i=0;i
54 | void test_fpr()
55 | {
56 | using filter=rehash_filter<
57 | revalue_filter<
58 | realloc_filter>,
59 | std::string
60 | >,
61 | boost::hash
62 | >;
63 |
64 | BOOST_TEST_GT(filter(0,0.0).capacity(),0u);
65 | BOOST_TEST_GT(filter(0,0.5).capacity(),0u);
66 | BOOST_TEST_EQ(filter(0,1.0).capacity(),0u);
67 | BOOST_TEST_THROWS((void)filter(1,0.0),std::bad_alloc);
68 | BOOST_TEST_EQ(filter(100,1.0).capacity(),0u);
69 |
70 | {
71 | static constexpr int max_fpr_exp=
72 | std::numeric_limits::digits>=64?5:3;
73 |
74 | for(int i=1;i<=max_fpr_exp;++i){
75 | std::size_t n=(std::size_t)std::pow(10.0,(double)(i+1));
76 | double target_fpr=std::pow(10,(double)-i);
77 | double measured_fpr=measure_fpr(filter(n,target_fpr),n);
78 | double err=measured_fpr/target_fpr;
79 | BOOST_TEST_LE(err,2.5);
80 | }
81 | }
82 |
83 | BOOST_TEST_EQ(filter::fpr_for(0,1),0.0);
84 | BOOST_TEST_EQ(filter::fpr_for(0,0),1.0);
85 | BOOST_TEST_EQ(filter::fpr_for(1,0),1.0);
86 |
87 | {
88 | for(int i=1;i<=5;++i){
89 | double fpr1=std::pow(10.0,(double)-i);
90 | double fpr2=filter::fpr_for(10000,filter::capacity_for(10000,fpr1));
91 | BOOST_TEST_LE(std::abs((double)fpr2-fpr1)/fpr1,0.2);
92 | }
93 | }
94 | {
95 | for(int i=1;i<=5;++i){
96 | std::size_t m1=(std::size_t)std::pow(10.0,(double)(i+4));
97 | std::size_t m2=filter::capacity_for(10000,filter::fpr_for(10000,m1));
98 | BOOST_TEST_LE(std::abs((double)m2-m1)/m1,0.05);
99 | }
100 | }
101 | }
102 |
103 | struct lambda
104 | {
105 | template
106 | void operator()(T)
107 | {
108 | using filter=typename T::type;
109 |
110 | test_fpr();
111 | }
112 | };
113 |
114 | int main()
115 | {
116 | boost::mp11::mp_for_each(lambda{});
117 | return boost::report_errors();
118 | }
119 |
--------------------------------------------------------------------------------
/benchmark/fpr_c.cpp:
--------------------------------------------------------------------------------
1 | /* For a given filter type, outputs FPR vs. c = m/n with optimum k.
2 | *
3 | * Copyright 2025 Joaquin M Lopez Munoz.
4 | * Distributed under the Boost Software License, Version 1.0.
5 | * (See accompanying file LICENSE_1_0.txt or copy at
6 | * http://www.boost.org/LICENSE_1_0.txt)
7 | *
8 | * See https://www.boost.org/libs/bloom for library home page.
9 | */
10 |
11 | #include